@fountain-ui/lab 2.0.0-beta.11 → 2.0.0-beta.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/build/commonjs/Carousel/Carousel.js +142 -0
  2. package/build/commonjs/Carousel/Carousel.js.map +1 -0
  3. package/build/commonjs/Carousel/CarouselProps.js.map +1 -1
  4. package/build/commonjs/Carousel/animation/animationUtils.js +9 -0
  5. package/build/commonjs/Carousel/animation/animationUtils.js.map +1 -0
  6. package/build/commonjs/Carousel/animation/createDefaultItemStyle.js +15 -0
  7. package/build/commonjs/Carousel/animation/createDefaultItemStyle.js.map +1 -0
  8. package/build/commonjs/Carousel/animation/createDefaultScrollAnimation.js +20 -0
  9. package/build/commonjs/Carousel/animation/createDefaultScrollAnimation.js.map +1 -0
  10. package/build/commonjs/Carousel/animation/index.js +40 -0
  11. package/build/commonjs/Carousel/animation/index.js.map +1 -0
  12. package/build/commonjs/Carousel/animation/normalItemStyleFactory.js +27 -0
  13. package/build/commonjs/Carousel/animation/normalItemStyleFactory.js.map +1 -0
  14. package/build/commonjs/Carousel/animation/parallaxItemStyleFactory.js +65 -0
  15. package/build/commonjs/Carousel/animation/parallaxItemStyleFactory.js.map +1 -0
  16. package/build/commonjs/Carousel/components/InternalContext.js +29 -0
  17. package/build/commonjs/Carousel/components/InternalContext.js.map +1 -0
  18. package/build/commonjs/Carousel/components/ItemView.js +66 -0
  19. package/build/commonjs/Carousel/components/ItemView.js.map +1 -0
  20. package/build/commonjs/Carousel/components/RootView.js +86 -0
  21. package/build/commonjs/Carousel/components/RootView.js.map +1 -0
  22. package/build/commonjs/Carousel/components/ScrollViewGesture.js +81 -0
  23. package/build/commonjs/Carousel/components/ScrollViewGesture.js.map +1 -0
  24. package/build/commonjs/Carousel/components/index.js +40 -0
  25. package/build/commonjs/Carousel/components/index.js.map +1 -0
  26. package/build/commonjs/Carousel/hooks/index.js +64 -0
  27. package/build/commonjs/Carousel/hooks/index.js.map +1 -0
  28. package/build/commonjs/Carousel/hooks/useAutoplayController.js +58 -0
  29. package/build/commonjs/Carousel/hooks/useAutoplayController.js.map +1 -0
  30. package/build/commonjs/Carousel/hooks/useDimensionChangeReaction.js +23 -0
  31. package/build/commonjs/Carousel/hooks/useDimensionChangeReaction.js.map +1 -0
  32. package/build/commonjs/Carousel/hooks/useIndexController.js +70 -0
  33. package/build/commonjs/Carousel/hooks/useIndexController.js.map +1 -0
  34. package/build/commonjs/Carousel/hooks/useItemInterpolation.js +63 -0
  35. package/build/commonjs/Carousel/hooks/useItemInterpolation.js.map +1 -0
  36. package/build/commonjs/Carousel/hooks/useItemVisibilityStore.js +95 -0
  37. package/build/commonjs/Carousel/hooks/useItemVisibilityStore.js.map +1 -0
  38. package/build/commonjs/Carousel/hooks/useLoopedData.js +33 -0
  39. package/build/commonjs/Carousel/hooks/useLoopedData.js.map +1 -0
  40. package/build/commonjs/Carousel/hooks/usePagingAnimation.js +162 -0
  41. package/build/commonjs/Carousel/hooks/usePagingAnimation.js.map +1 -0
  42. package/build/commonjs/Carousel/index.js +16 -2
  43. package/build/commonjs/Carousel/index.js.map +1 -1
  44. package/build/commonjs/Carousel/types.js +7 -0
  45. package/build/commonjs/Carousel/types.js.map +1 -0
  46. package/build/commonjs/ViewPager/ChildrenMemoizedPage.js +53 -59
  47. package/build/commonjs/ViewPager/ChildrenMemoizedPage.js.map +1 -1
  48. package/build/commonjs/ViewPager/InternalContext.js +17 -0
  49. package/build/commonjs/ViewPager/InternalContext.js.map +1 -0
  50. package/build/commonjs/ViewPager/PageStateContext.js +22 -0
  51. package/build/commonjs/ViewPager/PageStateContext.js.map +1 -0
  52. package/build/commonjs/ViewPager/ViewPagerNative.js +90 -25
  53. package/build/commonjs/ViewPager/ViewPagerNative.js.map +1 -1
  54. package/build/commonjs/ViewPager/ViewPagerProps.js.map +1 -1
  55. package/build/commonjs/ViewPager/ViewPagerWeb.js +27 -14
  56. package/build/commonjs/ViewPager/ViewPagerWeb.js.map +1 -1
  57. package/build/commonjs/ViewPager/index.js +8 -0
  58. package/build/commonjs/ViewPager/index.js.map +1 -1
  59. package/build/commonjs/ViewPager/index.native.js +8 -0
  60. package/build/commonjs/ViewPager/index.native.js.map +1 -1
  61. package/build/commonjs/ViewPager/types.js +6 -0
  62. package/build/commonjs/ViewPager/types.js.map +1 -0
  63. package/build/commonjs/ViewPager/usePageStore.js +30 -0
  64. package/build/commonjs/ViewPager/usePageStore.js.map +1 -0
  65. package/build/commonjs/ViewPager/utils.js +3 -1
  66. package/build/commonjs/ViewPager/utils.js.map +1 -1
  67. package/build/commonjs/ViewabilityTrackerView/Viewability.js +2 -0
  68. package/build/commonjs/ViewabilityTrackerView/Viewability.js.map +1 -0
  69. package/build/commonjs/ViewabilityTrackerView/ViewabilityTrackerView.js +45 -0
  70. package/build/commonjs/ViewabilityTrackerView/ViewabilityTrackerView.js.map +1 -0
  71. package/build/commonjs/ViewabilityTrackerView/ViewabilityTrackerViewProps.js +2 -0
  72. package/build/commonjs/ViewabilityTrackerView/ViewabilityTrackerViewProps.js.map +1 -0
  73. package/build/commonjs/{Carousel/index.native.js → ViewabilityTrackerView/index.js} +3 -3
  74. package/build/commonjs/ViewabilityTrackerView/index.js.map +1 -0
  75. package/build/commonjs/ViewabilityTrackerView/measureViewability.js +42 -0
  76. package/build/commonjs/ViewabilityTrackerView/measureViewability.js.map +1 -0
  77. package/build/commonjs/ViewabilityTrackerView/useViewabilityTracker.js +88 -0
  78. package/build/commonjs/ViewabilityTrackerView/useViewabilityTracker.js.map +1 -0
  79. package/build/commonjs/hooks/index.js +16 -0
  80. package/build/commonjs/hooks/index.js.map +1 -1
  81. package/build/commonjs/hooks/useDeferredExecutor.js +45 -0
  82. package/build/commonjs/hooks/useDeferredExecutor.js.map +1 -0
  83. package/build/commonjs/hooks/useIsMounted.js +22 -0
  84. package/build/commonjs/hooks/useIsMounted.js.map +1 -0
  85. package/build/commonjs/hooks/useUnstableCollapsibleAppBar.js +1 -1
  86. package/build/commonjs/hooks/useUnstableCollapsibleAppBar.js.map +1 -1
  87. package/build/commonjs/index.js +22 -1
  88. package/build/commonjs/index.js.map +1 -1
  89. package/build/module/Carousel/Carousel.js +120 -0
  90. package/build/module/Carousel/Carousel.js.map +1 -0
  91. package/build/module/Carousel/CarouselProps.js.map +1 -1
  92. package/build/module/Carousel/animation/animationUtils.js +2 -0
  93. package/build/module/Carousel/animation/animationUtils.js.map +1 -0
  94. package/build/module/Carousel/animation/createDefaultItemStyle.js +3 -0
  95. package/build/module/Carousel/animation/createDefaultItemStyle.js.map +1 -0
  96. package/build/module/Carousel/animation/createDefaultScrollAnimation.js +11 -0
  97. package/build/module/Carousel/animation/createDefaultScrollAnimation.js.map +1 -0
  98. package/build/module/Carousel/animation/index.js +5 -0
  99. package/build/module/Carousel/animation/index.js.map +1 -0
  100. package/build/module/Carousel/animation/normalItemStyleFactory.js +18 -0
  101. package/build/module/Carousel/animation/normalItemStyleFactory.js.map +1 -0
  102. package/build/module/Carousel/animation/parallaxItemStyleFactory.js +55 -0
  103. package/build/module/Carousel/animation/parallaxItemStyleFactory.js.map +1 -0
  104. package/build/module/Carousel/components/InternalContext.js +19 -0
  105. package/build/module/Carousel/components/InternalContext.js.map +1 -0
  106. package/build/module/Carousel/components/ItemView.js +46 -0
  107. package/build/module/Carousel/components/ItemView.js.map +1 -0
  108. package/build/module/Carousel/components/RootView.js +65 -0
  109. package/build/module/Carousel/components/RootView.js.map +1 -0
  110. package/build/module/Carousel/components/ScrollViewGesture.js +67 -0
  111. package/build/module/Carousel/components/ScrollViewGesture.js.map +1 -0
  112. package/build/module/Carousel/components/index.js +5 -0
  113. package/build/module/Carousel/components/index.js.map +1 -0
  114. package/build/module/Carousel/hooks/index.js +8 -0
  115. package/build/module/Carousel/hooks/index.js.map +1 -0
  116. package/build/module/Carousel/hooks/useAutoplayController.js +48 -0
  117. package/build/module/Carousel/hooks/useAutoplayController.js.map +1 -0
  118. package/build/module/Carousel/hooks/useDimensionChangeReaction.js +14 -0
  119. package/build/module/Carousel/hooks/useDimensionChangeReaction.js.map +1 -0
  120. package/build/module/Carousel/hooks/useIndexController.js +54 -0
  121. package/build/module/Carousel/hooks/useIndexController.js.map +1 -0
  122. package/build/module/Carousel/hooks/useItemInterpolation.js +51 -0
  123. package/build/module/Carousel/hooks/useItemInterpolation.js.map +1 -0
  124. package/build/module/Carousel/hooks/useItemVisibilityStore.js +87 -0
  125. package/build/module/Carousel/hooks/useItemVisibilityStore.js.map +1 -0
  126. package/build/module/Carousel/hooks/useLoopedData.js +24 -0
  127. package/build/module/Carousel/hooks/useLoopedData.js.map +1 -0
  128. package/build/module/Carousel/hooks/usePagingAnimation.js +153 -0
  129. package/build/module/Carousel/hooks/usePagingAnimation.js.map +1 -0
  130. package/build/module/Carousel/index.js +2 -1
  131. package/build/module/Carousel/index.js.map +1 -1
  132. package/build/module/Carousel/types.js +3 -0
  133. package/build/module/Carousel/types.js.map +1 -0
  134. package/build/module/ViewPager/ChildrenMemoizedPage.js +48 -56
  135. package/build/module/ViewPager/ChildrenMemoizedPage.js.map +1 -1
  136. package/build/module/ViewPager/InternalContext.js +7 -0
  137. package/build/module/ViewPager/InternalContext.js.map +1 -0
  138. package/build/module/ViewPager/PageStateContext.js +10 -0
  139. package/build/module/ViewPager/PageStateContext.js.map +1 -0
  140. package/build/module/ViewPager/ViewPagerNative.js +90 -27
  141. package/build/module/ViewPager/ViewPagerNative.js.map +1 -1
  142. package/build/module/ViewPager/ViewPagerProps.js.map +1 -1
  143. package/build/module/ViewPager/ViewPagerWeb.js +25 -15
  144. package/build/module/ViewPager/ViewPagerWeb.js.map +1 -1
  145. package/build/module/ViewPager/index.js +1 -0
  146. package/build/module/ViewPager/index.js.map +1 -1
  147. package/build/module/ViewPager/index.native.js +1 -0
  148. package/build/module/ViewPager/index.native.js.map +1 -1
  149. package/build/module/ViewPager/types.js +2 -0
  150. package/build/module/ViewPager/types.js.map +1 -0
  151. package/build/module/ViewPager/usePageStore.js +20 -0
  152. package/build/module/ViewPager/usePageStore.js.map +1 -0
  153. package/build/module/ViewPager/utils.js +1 -0
  154. package/build/module/ViewPager/utils.js.map +1 -1
  155. package/build/module/ViewabilityTrackerView/Viewability.js +2 -0
  156. package/build/module/ViewabilityTrackerView/Viewability.js.map +1 -0
  157. package/build/module/ViewabilityTrackerView/ViewabilityTrackerView.js +28 -0
  158. package/build/module/ViewabilityTrackerView/ViewabilityTrackerView.js.map +1 -0
  159. package/build/module/ViewabilityTrackerView/ViewabilityTrackerViewProps.js +2 -0
  160. package/build/module/ViewabilityTrackerView/ViewabilityTrackerViewProps.js.map +1 -0
  161. package/build/module/ViewabilityTrackerView/index.js +2 -0
  162. package/build/module/ViewabilityTrackerView/index.js.map +1 -0
  163. package/build/module/ViewabilityTrackerView/measureViewability.js +34 -0
  164. package/build/module/ViewabilityTrackerView/measureViewability.js.map +1 -0
  165. package/build/module/ViewabilityTrackerView/useViewabilityTracker.js +73 -0
  166. package/build/module/ViewabilityTrackerView/useViewabilityTracker.js.map +1 -0
  167. package/build/module/hooks/index.js +2 -0
  168. package/build/module/hooks/index.js.map +1 -1
  169. package/build/module/hooks/useDeferredExecutor.js +33 -0
  170. package/build/module/hooks/useDeferredExecutor.js.map +1 -0
  171. package/build/module/hooks/useIsMounted.js +13 -0
  172. package/build/module/hooks/useIsMounted.js.map +1 -0
  173. package/build/module/hooks/useUnstableCollapsibleAppBar.js +1 -1
  174. package/build/module/hooks/useUnstableCollapsibleAppBar.js.map +1 -1
  175. package/build/module/index.js +2 -0
  176. package/build/module/index.js.map +1 -1
  177. package/build/typescript/Carousel/Carousel.d.ts +5 -0
  178. package/build/typescript/Carousel/CarouselProps.d.ts +33 -48
  179. package/build/typescript/Carousel/animation/animationUtils.d.ts +1 -0
  180. package/build/typescript/Carousel/animation/createDefaultItemStyle.d.ts +2 -0
  181. package/build/typescript/Carousel/animation/createDefaultScrollAnimation.d.ts +2 -0
  182. package/build/typescript/Carousel/animation/index.d.ts +4 -0
  183. package/build/typescript/Carousel/animation/normalItemStyleFactory.d.ts +2 -0
  184. package/build/typescript/Carousel/animation/parallaxItemStyleFactory.d.ts +9 -0
  185. package/build/typescript/Carousel/components/InternalContext.d.ts +14 -0
  186. package/build/typescript/Carousel/components/ItemView.d.ts +9 -0
  187. package/build/typescript/Carousel/components/RootView.d.ts +16 -0
  188. package/build/typescript/Carousel/components/ScrollViewGesture.d.ts +12 -0
  189. package/build/typescript/Carousel/components/index.d.ts +4 -0
  190. package/build/typescript/Carousel/hooks/index.d.ts +7 -0
  191. package/build/typescript/Carousel/hooks/useAutoplayController.d.ts +7 -0
  192. package/build/typescript/Carousel/hooks/useDimensionChangeReaction.d.ts +7 -0
  193. package/build/typescript/Carousel/hooks/useIndexController.d.ts +10 -0
  194. package/build/typescript/Carousel/hooks/useItemInterpolation.d.ts +2 -0
  195. package/build/typescript/Carousel/hooks/useItemVisibilityStore.d.ts +7 -0
  196. package/build/typescript/Carousel/hooks/useLoopedData.d.ts +1 -0
  197. package/build/typescript/Carousel/hooks/usePagingAnimation.d.ts +18 -0
  198. package/build/typescript/Carousel/index.d.ts +3 -1
  199. package/build/typescript/Carousel/types.d.ts +79 -0
  200. package/build/typescript/ViewPager/ChildrenMemoizedPage.d.ts +1 -1
  201. package/build/typescript/ViewPager/InternalContext.d.ts +7 -0
  202. package/build/typescript/ViewPager/PageStateContext.d.ts +7 -0
  203. package/build/typescript/ViewPager/ViewPagerNative.d.ts +2 -2
  204. package/build/typescript/ViewPager/ViewPagerProps.d.ts +13 -20
  205. package/build/typescript/ViewPager/ViewPagerWeb.d.ts +2 -2
  206. package/build/typescript/ViewPager/index.d.ts +3 -1
  207. package/build/typescript/ViewPager/index.native.d.ts +1 -0
  208. package/build/typescript/ViewPager/types.d.ts +19 -0
  209. package/build/typescript/ViewPager/usePageStore.d.ts +2 -0
  210. package/build/typescript/ViewPager/utils.d.ts +2 -1
  211. package/build/typescript/ViewabilityTrackerView/Viewability.d.ts +3 -0
  212. package/build/typescript/ViewabilityTrackerView/ViewabilityTrackerView.d.ts +2 -0
  213. package/build/typescript/ViewabilityTrackerView/ViewabilityTrackerViewProps.d.ts +22 -0
  214. package/build/typescript/ViewabilityTrackerView/index.d.ts +2 -0
  215. package/build/typescript/ViewabilityTrackerView/measureViewability.d.ts +11 -0
  216. package/build/typescript/ViewabilityTrackerView/useViewabilityTracker.d.ts +11 -0
  217. package/build/typescript/hooks/index.d.ts +2 -0
  218. package/build/typescript/hooks/useDeferredExecutor.d.ts +11 -0
  219. package/build/typescript/hooks/useIsMounted.d.ts +4 -0
  220. package/build/typescript/index.d.ts +2 -0
  221. package/package.json +4 -19
  222. package/src/Carousel/Carousel.tsx +152 -0
  223. package/src/Carousel/CarouselProps.ts +35 -53
  224. package/src/Carousel/animation/animationUtils.ts +1 -0
  225. package/src/Carousel/animation/createDefaultItemStyle.ts +3 -0
  226. package/src/Carousel/animation/createDefaultScrollAnimation.ts +13 -0
  227. package/src/Carousel/animation/index.ts +4 -0
  228. package/src/Carousel/animation/normalItemStyleFactory.ts +19 -0
  229. package/src/Carousel/animation/parallaxItemStyleFactory.ts +79 -0
  230. package/src/Carousel/components/InternalContext.ts +33 -0
  231. package/src/Carousel/components/ItemView.tsx +66 -0
  232. package/src/Carousel/components/RootView.tsx +79 -0
  233. package/src/Carousel/components/ScrollViewGesture.tsx +87 -0
  234. package/src/Carousel/components/index.ts +4 -0
  235. package/src/Carousel/hooks/index.ts +7 -0
  236. package/src/Carousel/hooks/useAutoplayController.ts +57 -0
  237. package/src/Carousel/hooks/useDimensionChangeReaction.ts +25 -0
  238. package/src/Carousel/hooks/useIndexController.tsx +76 -0
  239. package/src/Carousel/hooks/useItemInterpolation.ts +107 -0
  240. package/src/Carousel/hooks/useItemVisibilityStore.ts +107 -0
  241. package/src/Carousel/hooks/useLoopedData.ts +26 -0
  242. package/src/Carousel/hooks/usePagingAnimation.ts +195 -0
  243. package/src/Carousel/index.ts +4 -2
  244. package/src/Carousel/types.ts +97 -0
  245. package/src/ViewPager/ChildrenMemoizedPage.tsx +55 -54
  246. package/src/ViewPager/InternalContext.ts +13 -0
  247. package/src/ViewPager/PageStateContext.ts +15 -0
  248. package/src/ViewPager/ViewPagerNative.tsx +114 -43
  249. package/src/ViewPager/ViewPagerProps.ts +15 -25
  250. package/src/ViewPager/ViewPagerWeb.tsx +30 -21
  251. package/src/ViewPager/index.native.ts +1 -0
  252. package/src/ViewPager/index.ts +3 -1
  253. package/src/ViewPager/types.ts +24 -0
  254. package/src/ViewPager/usePageStore.ts +24 -0
  255. package/src/ViewPager/utils.tsx +3 -2
  256. package/src/ViewabilityTrackerView/Viewability.ts +3 -0
  257. package/src/ViewabilityTrackerView/ViewabilityTrackerView.tsx +33 -0
  258. package/src/ViewabilityTrackerView/ViewabilityTrackerViewProps.ts +25 -0
  259. package/src/ViewabilityTrackerView/index.ts +2 -0
  260. package/src/ViewabilityTrackerView/measureViewability.ts +56 -0
  261. package/src/ViewabilityTrackerView/useViewabilityTracker.ts +85 -0
  262. package/src/hooks/index.ts +2 -0
  263. package/src/hooks/useDeferredExecutor.ts +46 -0
  264. package/src/hooks/useIsMounted.ts +19 -0
  265. package/src/hooks/useUnstableCollapsibleAppBar.ts +1 -1
  266. package/src/index.ts +3 -0
  267. package/build/commonjs/Carousel/CarouselNative.js +0 -72
  268. package/build/commonjs/Carousel/CarouselNative.js.map +0 -1
  269. package/build/commonjs/Carousel/CarouselWeb.js +0 -237
  270. package/build/commonjs/Carousel/CarouselWeb.js.map +0 -1
  271. package/build/commonjs/Carousel/index.native.js.map +0 -1
  272. package/build/commonjs/Carousel/utils.js +0 -19
  273. package/build/commonjs/Carousel/utils.js.map +0 -1
  274. package/build/module/Carousel/CarouselNative.js +0 -54
  275. package/build/module/Carousel/CarouselNative.js.map +0 -1
  276. package/build/module/Carousel/CarouselWeb.js +0 -215
  277. package/build/module/Carousel/CarouselWeb.js.map +0 -1
  278. package/build/module/Carousel/index.native.js +0 -2
  279. package/build/module/Carousel/index.native.js.map +0 -1
  280. package/build/module/Carousel/utils.js +0 -7
  281. package/build/module/Carousel/utils.js.map +0 -1
  282. package/build/typescript/Carousel/CarouselNative.d.ts +0 -2
  283. package/build/typescript/Carousel/CarouselWeb.d.ts +0 -4
  284. package/build/typescript/Carousel/index.native.d.ts +0 -1
  285. package/build/typescript/Carousel/utils.d.ts +0 -6
  286. package/src/Carousel/CarouselNative.tsx +0 -67
  287. package/src/Carousel/CarouselWeb.tsx +0 -222
  288. package/src/Carousel/index.native.ts +0 -1
  289. package/src/Carousel/utils.ts +0 -11
@@ -0,0 +1,76 @@
1
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { Animated } from 'react-native';
3
+ import type { IndexController } from '../types';
4
+
5
+ export interface UseIndexControllerParameters {
6
+ controlledTx: Animated.AnimatedValue;
7
+ initialIndex: number;
8
+ itemWidth: number;
9
+ numberOfOriginalData: number;
10
+ onIndexChange?: (newIndex: number) => void;
11
+ }
12
+
13
+ const normalizeIndex = (maybeIndex: number, numberOfData: number): number =>
14
+ Math.abs(Math.floor(maybeIndex)) % numberOfData;
15
+
16
+ export default function useIndexController(params: UseIndexControllerParameters): IndexController {
17
+ const {
18
+ controlledTx,
19
+ initialIndex,
20
+ itemWidth,
21
+ numberOfOriginalData,
22
+ onIndexChange,
23
+ } = params;
24
+
25
+ const indexRef = useRef<number>(initialIndex);
26
+ const [index, setIndex] = useState<number>(indexRef.current);
27
+
28
+ const maybeIndex = useMemo(() => {
29
+ const negative = new Animated.Value(-1);
30
+ const reversedTx = Animated.multiply(controlledTx, negative);
31
+ const normalized = Animated.divide(reversedTx, itemWidth);
32
+ return Animated.modulo(normalized, numberOfOriginalData);
33
+ }, [
34
+ controlledTx,
35
+ itemWidth,
36
+ numberOfOriginalData,
37
+ ]);
38
+
39
+ useEffect(() => {
40
+ const subscriptionId = maybeIndex.addListener((observedValue) => {
41
+ const newIndex = normalizeIndex(observedValue.value, numberOfOriginalData);
42
+
43
+ if (indexRef.current !== newIndex) {
44
+ indexRef.current = newIndex;
45
+ setIndex(newIndex);
46
+
47
+ onIndexChange?.(newIndex);
48
+ }
49
+ });
50
+
51
+ return () => {
52
+ maybeIndex.removeListener(subscriptionId);
53
+ };
54
+ }, [
55
+ maybeIndex,
56
+ numberOfOriginalData,
57
+ onIndexChange,
58
+ ]);
59
+
60
+ const getCurrentIndex = useCallback(() => indexRef.current, []);
61
+
62
+ return {
63
+ currentIndex: index,
64
+ getCurrentIndex,
65
+ lastIndex: numberOfOriginalData - 1,
66
+ monitorElement: (
67
+ <Animated.View
68
+ collapsable={false}
69
+ style={[
70
+ { zIndex: maybeIndex },
71
+ { width: 1, height: 1, position: 'absolute' },
72
+ ]}
73
+ />
74
+ ),
75
+ };
76
+ };
@@ -0,0 +1,107 @@
1
+ import { useContext, useMemo } from 'react';
2
+ import { Animated } from 'react-native';
3
+ import { InternalContext } from '../components';
4
+
5
+ const OVERSCROLL_FRICTION_FACTOR = 4;
6
+
7
+ export default function useItemInterpolation(index: number): Animated.AnimatedInterpolation {
8
+ const {
9
+ itemWidth,
10
+ data,
11
+ globalInterpolation,
12
+ loop,
13
+ } = useContext(InternalContext);
14
+
15
+ const numberOfData = data.length;
16
+
17
+ const interpolationConfigOnLoop = useMemo<Animated.InterpolationConfigType>(() => {
18
+ const lastIndex = numberOfData - 1;
19
+ const maxWidth = Math.abs(itemWidth * numberOfData);
20
+ const halfOfItemWidth = 0.5 * itemWidth;
21
+
22
+ const positiveCount = Math.round(lastIndex / 2);
23
+ const startPosition = index > positiveCount
24
+ ? (index - numberOfData) * itemWidth
25
+ : itemWidth * index;
26
+
27
+ const max = positiveCount * itemWidth;
28
+ const min = -((lastIndex - positiveCount) * itemWidth);
29
+
30
+ const inputRange = [
31
+ -maxWidth,
32
+ min - halfOfItemWidth - startPosition - Number.MIN_VALUE,
33
+ min - halfOfItemWidth - startPosition,
34
+ 0,
35
+ max + halfOfItemWidth - startPosition,
36
+ max + halfOfItemWidth - startPosition + Number.MIN_VALUE,
37
+ maxWidth,
38
+ ];
39
+
40
+ const outputRange = [
41
+ startPosition,
42
+ max + halfOfItemWidth - Number.MIN_VALUE,
43
+ min - halfOfItemWidth,
44
+ startPosition,
45
+ max + halfOfItemWidth,
46
+ min - halfOfItemWidth + Number.MIN_VALUE,
47
+ startPosition,
48
+ ];
49
+
50
+ return {
51
+ inputRange,
52
+ outputRange,
53
+ extrapolate: 'clamp',
54
+ };
55
+ }, [
56
+ index,
57
+ itemWidth,
58
+ numberOfData,
59
+ ]);
60
+
61
+ const interpolationConfigOnNoLoop = useMemo<Animated.InterpolationConfigType>(() => {
62
+ const lastIndex = numberOfData - 1;
63
+ const maxWidth = itemWidth * lastIndex;
64
+ const startPosition = itemWidth * index;
65
+ const friction = itemWidth / OVERSCROLL_FRICTION_FACTOR;
66
+
67
+ const inputRange = [
68
+ -(maxWidth + itemWidth), // overscroll
69
+ -maxWidth,
70
+ 0,
71
+ itemWidth, // overscroll
72
+ ];
73
+
74
+ const outputRange = [
75
+ -maxWidth + startPosition - friction,
76
+ -maxWidth + startPosition,
77
+ startPosition,
78
+ startPosition + friction,
79
+ ];
80
+
81
+ return {
82
+ inputRange,
83
+ outputRange,
84
+ extrapolate: 'clamp',
85
+ };
86
+ }, [
87
+ index,
88
+ itemWidth,
89
+ numberOfData,
90
+ ]);
91
+
92
+ return useMemo(() => {
93
+ const interpolationConfig = loop
94
+ ? interpolationConfigOnLoop
95
+ : interpolationConfigOnNoLoop;
96
+
97
+ const offsetX = globalInterpolation.interpolate(interpolationConfig);
98
+
99
+ return Animated.divide(offsetX, itemWidth);
100
+ }, [
101
+ globalInterpolation,
102
+ interpolationConfigOnLoop,
103
+ interpolationConfigOnNoLoop,
104
+ itemWidth,
105
+ loop,
106
+ ]);
107
+ };
@@ -0,0 +1,107 @@
1
+ import { useEffect, useRef, useState } from 'react';
2
+ import type { ItemVisibilityStore, VisibleIndexRanges } from '../types';
3
+
4
+ export interface Parameters {
5
+ currentIndex: number;
6
+ numberOfData: number;
7
+ windowSize: number;
8
+ }
9
+
10
+ class SimpleItemVisibilityStore implements ItemVisibilityStore {
11
+
12
+ private store: VisibleIndexRanges;
13
+
14
+ constructor(initialValue: VisibleIndexRanges) {
15
+ this.store = initialValue;
16
+ }
17
+
18
+ private listeners: Array<(ranges: VisibleIndexRanges) => void> = [];
19
+
20
+ subscribe(listener: (ranges: VisibleIndexRanges) => void) {
21
+ this.listeners.push(listener);
22
+
23
+ listener(this.store);
24
+
25
+ return () => {
26
+ const index = this.listeners.indexOf(listener);
27
+ this.listeners.splice(index, 1);
28
+ };
29
+ }
30
+
31
+ dispatch(ranges: VisibleIndexRanges): void {
32
+ this.store = ranges;
33
+ for (const id in this.listeners) {
34
+ const listener = this.listeners[id];
35
+ listener?.(ranges);
36
+ }
37
+ }
38
+
39
+ removeAllListeners(): void {
40
+ this.listeners.splice(0, this.listeners.length);
41
+ }
42
+
43
+ }
44
+
45
+ function normalize(windowSize: number, numberOfData: number): number {
46
+ if (windowSize <= 0) {
47
+ return numberOfData;
48
+ }
49
+ if (windowSize > 0 && windowSize % 2 === 0) {
50
+ return windowSize + 1;
51
+ }
52
+ return windowSize;
53
+ }
54
+
55
+ function mod(value: number, modulo: number): number {
56
+ return ((value % modulo) + modulo) % modulo;
57
+ }
58
+
59
+ function makeVisibleIndexRanges(numberOfData: number, windowSize: number, index: number): VisibleIndexRanges {
60
+ const ws = normalize(windowSize, numberOfData);
61
+
62
+ const firstIndex = 0;
63
+ const lastIndex = numberOfData - 1;
64
+ const halfNumberOfAdjacent = Math.floor(ws / 2);
65
+
66
+ const leftSide = index - halfNumberOfAdjacent;
67
+ const rightSide = index + halfNumberOfAdjacent;
68
+
69
+ const leftRanges = leftSide >= 0
70
+ ? [[leftSide, index]]
71
+ : [[firstIndex, index], [mod(leftSide, numberOfData), lastIndex]];
72
+
73
+ const rightRanges = rightSide < numberOfData
74
+ ? [[index, rightSide]]
75
+ : [[index, lastIndex], [firstIndex, mod(rightSide, numberOfData)]];
76
+
77
+ // @ts-ignore
78
+ return [
79
+ ...leftRanges,
80
+ ...rightRanges,
81
+ ];
82
+ }
83
+
84
+ export default function useItemVisibilityStore(params: Parameters): ItemVisibilityStore {
85
+ const {
86
+ currentIndex,
87
+ numberOfData,
88
+ windowSize,
89
+ } = params;
90
+
91
+ const [initialRange] = useState(() => makeVisibleIndexRanges(numberOfData, windowSize, currentIndex));
92
+ const store = useRef(new SimpleItemVisibilityStore(initialRange)).current;
93
+
94
+ useEffect(() => {
95
+ const newRanges = makeVisibleIndexRanges(numberOfData, windowSize, currentIndex);
96
+
97
+ store.dispatch(newRanges);
98
+ }, [currentIndex, numberOfData, windowSize]);
99
+
100
+ useEffect(() => {
101
+ return () => {
102
+ store.removeAllListeners();
103
+ };
104
+ }, []);
105
+
106
+ return store;
107
+ };
@@ -0,0 +1,26 @@
1
+ import { useMemo } from 'react';
2
+
3
+ export default function useLoopedData<ItemT>(
4
+ originalData: ReadonlyArray<ItemT>,
5
+ loop: boolean,
6
+ ): ReadonlyArray<ItemT> {
7
+ return useMemo(() => {
8
+ if (!loop) {
9
+ return originalData;
10
+ }
11
+
12
+ const numberOfData = originalData.length;
13
+
14
+ if (numberOfData === 1) {
15
+ const [first] = originalData;
16
+ return [first, first, first];
17
+ }
18
+
19
+ if (numberOfData === 2) {
20
+ const [first, second] = originalData;
21
+ return [first, second, first, second];
22
+ }
23
+
24
+ return originalData;
25
+ }, [originalData, loop]);
26
+ };
@@ -0,0 +1,195 @@
1
+ import { useCallback, useEffect, useMemo, useRef } from 'react';
2
+ import { Animated, Platform } from 'react-native';
3
+ import type {
4
+ CreateScrollAnimation,
5
+ DirectionalPagingAnimationConfig,
6
+ GetCurrentIndex,
7
+ IndexPagingAnimationConfig,
8
+ PagingAnimationConfig,
9
+ PagingAnimationType,
10
+ PagingDirection,
11
+ StartPagingAnimation,
12
+ } from '../types';
13
+
14
+ export interface PagingAnimationParameters {
15
+ controlledTx: Animated.Value;
16
+ createScrollAnimation: CreateScrollAnimation;
17
+ getCurrentIndex: GetCurrentIndex;
18
+ itemWidth: number;
19
+ lastIndex: number;
20
+ loop: boolean;
21
+ numberOfData: number;
22
+ offsetTx: Animated.Value;
23
+ }
24
+
25
+ export interface UsePagingAnimation {
26
+ finalizeAnimation: () => void;
27
+ globalInterpolation: Animated.AnimatedInterpolation;
28
+ startPagingAnimation: StartPagingAnimation;
29
+ }
30
+
31
+ function directionToValue(itemWidth: number) {
32
+ return function (direction: PagingDirection): number {
33
+ switch (direction) {
34
+ case 'next':
35
+ return -itemWidth;
36
+ case 'prev':
37
+ return itemWidth;
38
+ case 'stay':
39
+ return 0;
40
+ }
41
+ };
42
+ }
43
+
44
+ export default function usePagingAnimation(params: PagingAnimationParameters): UsePagingAnimation {
45
+ const {
46
+ controlledTx,
47
+ createScrollAnimation,
48
+ getCurrentIndex,
49
+ itemWidth,
50
+ lastIndex,
51
+ loop,
52
+ numberOfData,
53
+ offsetTx,
54
+ } = params;
55
+
56
+ const animationRef = useRef<Animated.CompositeAnimation | null>(null);
57
+ const toValueRef = useRef<number>(0);
58
+
59
+ const globalInterpolation = useMemo(
60
+ () => Animated.add(controlledTx, offsetTx),
61
+ [controlledTx, offsetTx],
62
+ );
63
+
64
+ useEffect(() => {
65
+ const subscriptionId = controlledTx.addListener((value) => {
66
+ const currentTx = value.value;
67
+
68
+ // Prevent infinite loop
69
+ if (currentTx !== 0) {
70
+ const maxWidth = numberOfData * itemWidth;
71
+
72
+ if (Math.abs(Math.round(currentTx)) === Math.round(maxWidth)) {
73
+ // reset position
74
+ controlledTx.setValue(0);
75
+ }
76
+ }
77
+ });
78
+
79
+ return () => {
80
+ controlledTx.removeListener(subscriptionId);
81
+ };
82
+ }, [numberOfData, itemWidth]);
83
+
84
+ const finalizeAnimation = useCallback(() => {
85
+ const stopUnfinishedSnapAnimation = () => {
86
+ if (animationRef.current) {
87
+ animationRef.current?.stop();
88
+ animationRef.current = null;
89
+ }
90
+ };
91
+
92
+ const resetBoundary = () => {
93
+ controlledTx.setOffset(toValueRef.current);
94
+ controlledTx.flattenOffset();
95
+
96
+ // FIXME: react-native-web bug maybe?
97
+ // `AnimatedValue.flattenOffset()` does not trigger any event listener.
98
+ // Accessing value directly via `_value` is dangerous but working on web (`useNativeDriver` always false).
99
+ // So setting same value with `value.setValue(value._value)` will trigger event listener.
100
+ if (Platform.OS === 'web') {
101
+ // @ts-ignore
102
+ controlledTx.setValue(controlledTx._value);
103
+ }
104
+
105
+ offsetTx.setValue(0);
106
+ toValueRef.current = 0;
107
+ };
108
+
109
+ stopUnfinishedSnapAnimation();
110
+
111
+ resetBoundary();
112
+ }, [controlledTx]);
113
+
114
+ const startPagingAnimation = useCallback((type: PagingAnimationType, config: PagingAnimationConfig) => {
115
+ const configWithDefaults: PagingAnimationConfig = {
116
+ animated: true,
117
+ ...config,
118
+ };
119
+
120
+ const currentIndex = getCurrentIndex();
121
+
122
+ const getValueByDirectionOnAllAdjacentItemsVisible = directionToValue(itemWidth);
123
+
124
+ const getValueByDirectionalPagingOnLoopDisabled = (_config: DirectionalPagingAnimationConfig): number => {
125
+ const { direction, isOriginatedFromGesture } = _config;
126
+
127
+ if (currentIndex === 0 && direction === 'prev') {
128
+ return isOriginatedFromGesture
129
+ ? getValueByDirectionOnAllAdjacentItemsVisible('stay')
130
+ : -lastIndex * itemWidth; // last position
131
+ } else if (currentIndex === lastIndex && direction === 'next') {
132
+ return isOriginatedFromGesture
133
+ ? getValueByDirectionOnAllAdjacentItemsVisible('stay')
134
+ : lastIndex * itemWidth; // first position
135
+ }
136
+ return getValueByDirectionOnAllAdjacentItemsVisible(direction);
137
+ };
138
+
139
+ const getValueByDirectionalPaging = (_config: DirectionalPagingAnimationConfig): number => {
140
+ const _configWithDefaults: DirectionalPagingAnimationConfig = {
141
+ isOriginatedFromGesture: false,
142
+ ..._config,
143
+ };
144
+
145
+ return loop
146
+ ? getValueByDirectionOnAllAdjacentItemsVisible(_configWithDefaults.direction)
147
+ : getValueByDirectionalPagingOnLoopDisabled(_configWithDefaults);
148
+ };
149
+
150
+ const getValueByIndexPaging = ({ index }: IndexPagingAnimationConfig): number => {
151
+ if (index < 0 || index > lastIndex || index === currentIndex) {
152
+ // no animation if index is invalid or equals to current index
153
+ return 0;
154
+ }
155
+
156
+ const distance = Math.abs(currentIndex - index) * itemWidth;
157
+ const direction = index > currentIndex ? -1 : 1;
158
+
159
+ return distance * direction;
160
+ };
161
+
162
+ const toValue = type === 'directional'
163
+ // @ts-ignore
164
+ ? getValueByDirectionalPaging(configWithDefaults)
165
+ // @ts-ignore
166
+ : getValueByIndexPaging(configWithDefaults);
167
+
168
+ toValueRef.current = toValue;
169
+
170
+ if (configWithDefaults.animated) {
171
+ const animation = createScrollAnimation(offsetTx, toValue);
172
+ animationRef.current = animation;
173
+ animation.start(({ finished }) => {
174
+ if (finished) {
175
+ finalizeAnimation();
176
+ }
177
+ });
178
+ } else {
179
+ finalizeAnimation();
180
+ }
181
+ }, [
182
+ createScrollAnimation,
183
+ getCurrentIndex,
184
+ finalizeAnimation,
185
+ itemWidth,
186
+ lastIndex,
187
+ loop,
188
+ ]);
189
+
190
+ return {
191
+ globalInterpolation,
192
+ finalizeAnimation,
193
+ startPagingAnimation,
194
+ };
195
+ };
@@ -1,2 +1,4 @@
1
- export { default } from './CarouselWeb';
2
- export type { default as CarouselProps } from './CarouselProps';
1
+ export { default } from './Carousel';
2
+ export type { default as CarouselProps } from './CarouselProps';
3
+ export type { CarouselInstance } from './types';
4
+ export { normalItemStyleFactory, parallaxItemStyleFactory } from './animation';
@@ -0,0 +1,97 @@
1
+ import type { ReactElement } from 'react';
2
+ import type { Animated, ViewProps } from 'react-native';
3
+
4
+ const directions = ['next', 'prev', 'stay'] as const;
5
+
6
+ export type PagingDirection = (typeof directions)[number];
7
+
8
+ export type ItemHeight = number | 'auto';
9
+
10
+ export interface RenderItem<T> {
11
+ (info: { item: T, index: number, interpolation: Animated.AnimatedInterpolation }): ReactElement | null;
12
+ }
13
+
14
+ export interface CreateScrollAnimation {
15
+ (aValue: Animated.AnimatedValue, toValue: number): Animated.CompositeAnimation;
16
+ }
17
+
18
+ export interface CreateItemStyle {
19
+ (itemInterpolation: Animated.AnimatedInterpolation, itemWidth: number): Animated.AnimatedProps<ViewProps['style']>;
20
+ }
21
+
22
+ export interface GetCurrentIndex {
23
+ (): number;
24
+ }
25
+
26
+ export interface IndexController {
27
+ currentIndex: number;
28
+ getCurrentIndex: GetCurrentIndex;
29
+ lastIndex: number;
30
+ monitorElement: ReactElement;
31
+ }
32
+
33
+ export type PagingAnimationType = 'directional' | 'index';
34
+
35
+ export interface BasePagingAnimationConfig {
36
+ animated?: boolean;
37
+ }
38
+
39
+ export interface DirectionalPagingAnimationConfig extends BasePagingAnimationConfig {
40
+ direction: PagingDirection;
41
+ isOriginatedFromGesture?: boolean;
42
+ }
43
+
44
+ export interface IndexPagingAnimationConfig extends BasePagingAnimationConfig {
45
+ index: number;
46
+ }
47
+
48
+ export type PagingAnimationConfig = DirectionalPagingAnimationConfig | IndexPagingAnimationConfig;
49
+
50
+ export interface StartPagingAnimation {
51
+ (type: PagingAnimationType, config: PagingAnimationConfig): void;
52
+ }
53
+
54
+ export type VisibleIndexRanges = Array<[number, number]>;
55
+
56
+ export interface StoreSubscription {
57
+ (): void;
58
+ }
59
+
60
+ export interface ItemVisibilityStore {
61
+ dispatch: (ranges: VisibleIndexRanges) => void;
62
+ subscribe: (listener: (ranges: VisibleIndexRanges) => void) => StoreSubscription;
63
+ removeAllListeners: () => void;
64
+ }
65
+
66
+ export interface AutoplayController {
67
+ pause: () => void;
68
+ resume: () => void;
69
+ }
70
+
71
+ export interface ScrollToOption {
72
+ index: number;
73
+ animated?: boolean;
74
+ }
75
+
76
+ export interface CarouselInstance {
77
+ /**
78
+ * Get current visible item index.
79
+ */
80
+ getCurrentIndex: GetCurrentIndex;
81
+
82
+ /**
83
+ * Scroll to next visible item.
84
+ */
85
+ next: () => void;
86
+
87
+ /**
88
+ * Scroll to previous visible item.
89
+ */
90
+ prev: () => void;
91
+
92
+ /**
93
+ * Scroll to desired indexed item.
94
+ * Invalid index is ignored.
95
+ */
96
+ scrollTo: (option: ScrollToOption) => void;
97
+ }