@fountain-ui/lab 2.0.0-beta.12 → 2.0.0-beta.15

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 (154) hide show
  1. package/build/commonjs/Carousel/Carousel.js +39 -37
  2. package/build/commonjs/Carousel/Carousel.js.map +1 -1
  3. package/build/commonjs/Carousel/CarouselProps.js.map +1 -1
  4. package/build/commonjs/Carousel/animation/createDefaultScrollAnimation.js +2 -2
  5. package/build/commonjs/Carousel/animation/createDefaultScrollAnimation.js.map +1 -1
  6. package/build/commonjs/Carousel/animation/parallaxItemStyleFactory.js +15 -15
  7. package/build/commonjs/Carousel/animation/parallaxItemStyleFactory.js.map +1 -1
  8. package/build/commonjs/Carousel/components/InternalContext.js.map +1 -1
  9. package/build/commonjs/Carousel/components/ItemView.js +6 -4
  10. package/build/commonjs/Carousel/components/ItemView.js.map +1 -1
  11. package/build/commonjs/Carousel/components/RootView.js +21 -3
  12. package/build/commonjs/Carousel/components/RootView.js.map +1 -1
  13. package/build/commonjs/Carousel/components/ScrollViewGesture.js +18 -13
  14. package/build/commonjs/Carousel/components/ScrollViewGesture.js.map +1 -1
  15. package/build/commonjs/Carousel/{hooks → components}/useItemInterpolation.js +6 -4
  16. package/build/commonjs/Carousel/components/useItemInterpolation.js.map +1 -0
  17. package/build/commonjs/Carousel/hooks/index.js +0 -16
  18. package/build/commonjs/Carousel/hooks/index.js.map +1 -1
  19. package/build/commonjs/Carousel/hooks/useAutoplayController.js +4 -1
  20. package/build/commonjs/Carousel/hooks/useAutoplayController.js.map +1 -1
  21. package/build/commonjs/Carousel/hooks/useIndexController.js +15 -46
  22. package/build/commonjs/Carousel/hooks/useIndexController.js.map +1 -1
  23. package/build/commonjs/Carousel/hooks/useItemVisibilityStore.js +12 -12
  24. package/build/commonjs/Carousel/hooks/useItemVisibilityStore.js.map +1 -1
  25. package/build/commonjs/Carousel/hooks/usePagingAnimation.js +121 -69
  26. package/build/commonjs/Carousel/hooks/usePagingAnimation.js.map +1 -1
  27. package/build/commonjs/Carousel/tick.js +16 -0
  28. package/build/commonjs/Carousel/tick.js.map +1 -0
  29. package/build/commonjs/Carousel/types.js.map +1 -1
  30. package/build/commonjs/ViewPager/ChildrenMemoizedPage.js +53 -47
  31. package/build/commonjs/ViewPager/ChildrenMemoizedPage.js.map +1 -1
  32. package/build/commonjs/ViewPager/InternalContext.js +17 -0
  33. package/build/commonjs/ViewPager/InternalContext.js.map +1 -0
  34. package/build/commonjs/ViewPager/ViewPagerNative.js +74 -23
  35. package/build/commonjs/ViewPager/ViewPagerNative.js.map +1 -1
  36. package/build/commonjs/ViewPager/ViewPagerProps.js.map +1 -1
  37. package/build/commonjs/ViewPager/ViewPagerWeb.js +23 -12
  38. package/build/commonjs/ViewPager/ViewPagerWeb.js.map +1 -1
  39. package/build/commonjs/ViewPager/index.js.map +1 -1
  40. package/build/commonjs/ViewPager/types.js +6 -0
  41. package/build/commonjs/ViewPager/types.js.map +1 -0
  42. package/build/commonjs/ViewPager/usePageStore.js +35 -0
  43. package/build/commonjs/ViewPager/usePageStore.js.map +1 -0
  44. package/build/commonjs/ViewPager/utils.js.map +1 -1
  45. package/build/commonjs/ViewabilityTrackerView/measureViewability.js +6 -6
  46. package/build/commonjs/ViewabilityTrackerView/measureViewability.js.map +1 -1
  47. package/build/commonjs/hooks/useUnstableCollapsibleAppBar.js +1 -1
  48. package/build/commonjs/hooks/useUnstableCollapsibleAppBar.js.map +1 -1
  49. package/build/module/Carousel/Carousel.js +39 -39
  50. package/build/module/Carousel/Carousel.js.map +1 -1
  51. package/build/module/Carousel/CarouselProps.js.map +1 -1
  52. package/build/module/Carousel/animation/createDefaultScrollAnimation.js +2 -2
  53. package/build/module/Carousel/animation/createDefaultScrollAnimation.js.map +1 -1
  54. package/build/module/Carousel/animation/parallaxItemStyleFactory.js +15 -15
  55. package/build/module/Carousel/animation/parallaxItemStyleFactory.js.map +1 -1
  56. package/build/module/Carousel/components/InternalContext.js.map +1 -1
  57. package/build/module/Carousel/components/ItemView.js +5 -3
  58. package/build/module/Carousel/components/ItemView.js.map +1 -1
  59. package/build/module/Carousel/components/RootView.js +22 -4
  60. package/build/module/Carousel/components/RootView.js.map +1 -1
  61. package/build/module/Carousel/components/ScrollViewGesture.js +18 -13
  62. package/build/module/Carousel/components/ScrollViewGesture.js.map +1 -1
  63. package/build/module/Carousel/{hooks → components}/useItemInterpolation.js +3 -3
  64. package/build/module/Carousel/components/useItemInterpolation.js.map +1 -0
  65. package/build/module/Carousel/hooks/index.js +0 -2
  66. package/build/module/Carousel/hooks/index.js.map +1 -1
  67. package/build/module/Carousel/hooks/useAutoplayController.js +4 -1
  68. package/build/module/Carousel/hooks/useAutoplayController.js.map +1 -1
  69. package/build/module/Carousel/hooks/useIndexController.js +14 -39
  70. package/build/module/Carousel/hooks/useIndexController.js.map +1 -1
  71. package/build/module/Carousel/hooks/useItemVisibilityStore.js +10 -11
  72. package/build/module/Carousel/hooks/useItemVisibilityStore.js.map +1 -1
  73. package/build/module/Carousel/hooks/usePagingAnimation.js +122 -69
  74. package/build/module/Carousel/hooks/usePagingAnimation.js.map +1 -1
  75. package/build/module/Carousel/tick.js +6 -0
  76. package/build/module/Carousel/tick.js.map +1 -0
  77. package/build/module/Carousel/types.js.map +1 -1
  78. package/build/module/ViewPager/ChildrenMemoizedPage.js +53 -47
  79. package/build/module/ViewPager/ChildrenMemoizedPage.js.map +1 -1
  80. package/build/module/ViewPager/InternalContext.js +7 -0
  81. package/build/module/ViewPager/InternalContext.js.map +1 -0
  82. package/build/module/ViewPager/ViewPagerNative.js +72 -23
  83. package/build/module/ViewPager/ViewPagerNative.js.map +1 -1
  84. package/build/module/ViewPager/ViewPagerProps.js.map +1 -1
  85. package/build/module/ViewPager/ViewPagerWeb.js +21 -13
  86. package/build/module/ViewPager/ViewPagerWeb.js.map +1 -1
  87. package/build/module/ViewPager/index.js.map +1 -1
  88. package/build/module/ViewPager/types.js +2 -0
  89. package/build/module/ViewPager/types.js.map +1 -0
  90. package/build/module/ViewPager/usePageStore.js +25 -0
  91. package/build/module/ViewPager/usePageStore.js.map +1 -0
  92. package/build/module/ViewPager/utils.js.map +1 -1
  93. package/build/module/ViewabilityTrackerView/measureViewability.js +2 -2
  94. package/build/module/ViewabilityTrackerView/measureViewability.js.map +1 -1
  95. package/build/module/hooks/useUnstableCollapsibleAppBar.js +1 -1
  96. package/build/module/hooks/useUnstableCollapsibleAppBar.js.map +1 -1
  97. package/build/typescript/Carousel/CarouselProps.d.ts +4 -3
  98. package/build/typescript/Carousel/animation/parallaxItemStyleFactory.d.ts +5 -5
  99. package/build/typescript/Carousel/components/InternalContext.d.ts +2 -2
  100. package/build/typescript/Carousel/components/ItemView.d.ts +2 -0
  101. package/build/typescript/Carousel/components/RootView.d.ts +4 -4
  102. package/build/typescript/Carousel/components/ScrollViewGesture.d.ts +3 -3
  103. package/build/typescript/Carousel/{hooks → components}/useItemInterpolation.d.ts +0 -0
  104. package/build/typescript/Carousel/hooks/index.d.ts +0 -2
  105. package/build/typescript/Carousel/hooks/useIndexController.d.ts +0 -2
  106. package/build/typescript/Carousel/hooks/useItemVisibilityStore.d.ts +5 -2
  107. package/build/typescript/Carousel/hooks/usePagingAnimation.d.ts +8 -10
  108. package/build/typescript/Carousel/tick.d.ts +2 -0
  109. package/build/typescript/Carousel/types.d.ts +26 -5
  110. package/build/typescript/ViewPager/ChildrenMemoizedPage.d.ts +1 -1
  111. package/build/typescript/ViewPager/InternalContext.d.ts +7 -0
  112. package/build/typescript/ViewPager/ViewPagerNative.d.ts +2 -2
  113. package/build/typescript/ViewPager/ViewPagerProps.d.ts +4 -22
  114. package/build/typescript/ViewPager/ViewPagerWeb.d.ts +2 -2
  115. package/build/typescript/ViewPager/index.d.ts +2 -1
  116. package/build/typescript/ViewPager/types.d.ts +19 -0
  117. package/build/typescript/ViewPager/usePageStore.d.ts +2 -0
  118. package/build/typescript/ViewPager/utils.d.ts +1 -1
  119. package/package.json +3 -3
  120. package/src/Carousel/Carousel.tsx +32 -40
  121. package/src/Carousel/CarouselProps.ts +4 -3
  122. package/src/Carousel/animation/createDefaultScrollAnimation.ts +2 -2
  123. package/src/Carousel/animation/parallaxItemStyleFactory.ts +24 -24
  124. package/src/Carousel/components/InternalContext.ts +2 -2
  125. package/src/Carousel/components/ItemView.tsx +13 -3
  126. package/src/Carousel/components/RootView.tsx +19 -6
  127. package/src/Carousel/components/ScrollViewGesture.tsx +23 -15
  128. package/src/Carousel/{hooks → components}/useItemInterpolation.ts +3 -3
  129. package/src/Carousel/hooks/index.ts +0 -2
  130. package/src/Carousel/hooks/useAutoplayController.ts +4 -1
  131. package/src/Carousel/hooks/useIndexController.tsx +14 -44
  132. package/src/Carousel/hooks/useItemVisibilityStore.ts +17 -13
  133. package/src/Carousel/hooks/usePagingAnimation.ts +161 -83
  134. package/src/Carousel/tick.ts +6 -0
  135. package/src/Carousel/types.ts +34 -5
  136. package/src/ViewPager/ChildrenMemoizedPage.tsx +53 -50
  137. package/src/ViewPager/InternalContext.ts +13 -0
  138. package/src/ViewPager/ViewPagerNative.tsx +91 -44
  139. package/src/ViewPager/ViewPagerProps.ts +4 -27
  140. package/src/ViewPager/ViewPagerWeb.tsx +28 -23
  141. package/src/ViewPager/index.ts +2 -1
  142. package/src/ViewPager/types.ts +24 -0
  143. package/src/ViewPager/usePageStore.ts +30 -0
  144. package/src/ViewPager/utils.tsx +1 -1
  145. package/src/ViewabilityTrackerView/measureViewability.ts +1 -3
  146. package/src/hooks/useUnstableCollapsibleAppBar.ts +1 -1
  147. package/build/commonjs/Carousel/hooks/useDimensionChangeReaction.js +0 -23
  148. package/build/commonjs/Carousel/hooks/useDimensionChangeReaction.js.map +0 -1
  149. package/build/commonjs/Carousel/hooks/useItemInterpolation.js.map +0 -1
  150. package/build/module/Carousel/hooks/useDimensionChangeReaction.js +0 -14
  151. package/build/module/Carousel/hooks/useDimensionChangeReaction.js.map +0 -1
  152. package/build/module/Carousel/hooks/useItemInterpolation.js.map +0 -1
  153. package/build/typescript/Carousel/hooks/useDimensionChangeReaction.d.ts +0 -7
  154. package/src/Carousel/hooks/useDimensionChangeReaction.ts +0 -25
@@ -1,24 +1,26 @@
1
1
  import React, { useCallback } from 'react';
2
2
  import { Animated } from 'react-native';
3
3
  import { PanGestureHandler, State as GestureHandlerState } from 'react-native-gesture-handler';
4
- const SCROLL_TO_ADJACENT_TX_THRESHOLD = 60;
5
- const SCROLL_TO_ADJACENT_VX_THRESHOLD = 500;
4
+ const SCROLL_TO_ADJACENT_TX_THRESHOLD = 80;
5
+ const SCROLL_TO_ADJACENT_VX_THRESHOLD = 1000;
6
6
  const ACTIVE_OFFSET_ABS_X = 5;
7
7
  const activeOffsetX = [-ACTIVE_OFFSET_ABS_X, ACTIVE_OFFSET_ABS_X];
8
- const endAnimationStates = [GestureHandlerState.CANCELLED, GestureHandlerState.END];
8
+ const endAnimationStates = [GestureHandlerState.CANCELLED, GestureHandlerState.END, GestureHandlerState.FAILED];
9
9
 
10
10
  function shouldScrollToAdjacent(translationX, velocityX) {
11
- return Math.abs(translationX) >= SCROLL_TO_ADJACENT_TX_THRESHOLD || Math.abs(velocityX) >= SCROLL_TO_ADJACENT_VX_THRESHOLD;
11
+ const isSameDirection = translationX * velocityX > 0;
12
+ const isEnoughMovement = Math.abs(translationX) >= SCROLL_TO_ADJACENT_TX_THRESHOLD || Math.abs(velocityX) >= SCROLL_TO_ADJACENT_VX_THRESHOLD;
13
+ return isSameDirection && isEnoughMovement;
12
14
  }
13
15
 
14
16
  export default function ScrollViewGesture(props) {
15
17
  const {
16
18
  autoplayController,
17
19
  children,
18
- finalizeAnimation,
19
- offsetTx,
20
+ interruptAnimation,
21
+ translateX,
20
22
  scrollEnabled,
21
- startAnimation
23
+ startPagingAnimation
22
24
  } = props;
23
25
  const {
24
26
  pause: pauseAutoplay,
@@ -26,11 +28,11 @@ export default function ScrollViewGesture(props) {
26
28
  } = autoplayController;
27
29
  const handleGestureBegin = useCallback(() => {
28
30
  pauseAutoplay();
29
- finalizeAnimation();
30
- }, [finalizeAnimation, pauseAutoplay]);
31
+ interruptAnimation();
32
+ }, [interruptAnimation, pauseAutoplay]);
31
33
  const handleGestureEvent = useCallback(Animated.event([{
32
34
  nativeEvent: {
33
- translationX: offsetTx
35
+ translationX: translateX
34
36
  }
35
37
  }], {
36
38
  useNativeDriver: true
@@ -45,11 +47,14 @@ export default function ScrollViewGesture(props) {
45
47
  } = event;
46
48
 
47
49
  if (endAnimationStates.includes(state)) {
48
- const userDirection = shouldScrollToAdjacent(translationX, velocityX) ? translationX < 0 ? 'next' : 'prev' : 'stay';
49
- startAnimation(userDirection, true);
50
+ const direction = shouldScrollToAdjacent(translationX, velocityX) ? translationX < 0 ? 'next' : 'prev' : 'stay';
51
+ startPagingAnimation('directional', {
52
+ direction: direction,
53
+ isOriginatedFromGesture: true
54
+ });
50
55
  resumeAutoplay();
51
56
  }
52
- }, [startAnimation, resumeAutoplay]);
57
+ }, [startPagingAnimation, resumeAutoplay]);
53
58
  return /*#__PURE__*/React.createElement(PanGestureHandler, {
54
59
  activeOffsetX: activeOffsetX,
55
60
  children: children,
@@ -1 +1 @@
1
- {"version":3,"names":["React","useCallback","Animated","PanGestureHandler","State","GestureHandlerState","SCROLL_TO_ADJACENT_TX_THRESHOLD","SCROLL_TO_ADJACENT_VX_THRESHOLD","ACTIVE_OFFSET_ABS_X","activeOffsetX","endAnimationStates","CANCELLED","END","shouldScrollToAdjacent","translationX","velocityX","Math","abs","ScrollViewGesture","props","autoplayController","children","finalizeAnimation","offsetTx","scrollEnabled","startAnimation","pause","pauseAutoplay","resume","resumeAutoplay","handleGestureBegin","handleGestureEvent","event","nativeEvent","useNativeDriver","handleHandlerStateChange","state","includes","userDirection"],"sources":["ScrollViewGesture.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport React, { useCallback } from 'react';\nimport { Animated } from 'react-native';\nimport type { PanGestureHandlerStateChangeEvent } from 'react-native-gesture-handler';\nimport { PanGestureHandler, State as GestureHandlerState } from 'react-native-gesture-handler';\nimport type { AutoplayController, PagingDirection, StartPagingAnimation } from '../types';\n\nexport interface ScrollViewGestureProps {\n autoplayController: AutoplayController;\n children: ReactNode;\n finalizeAnimation: () => void;\n offsetTx: Animated.Value,\n scrollEnabled: boolean;\n startAnimation: StartPagingAnimation;\n}\n\nconst SCROLL_TO_ADJACENT_TX_THRESHOLD = 60;\nconst SCROLL_TO_ADJACENT_VX_THRESHOLD = 500;\n\nconst ACTIVE_OFFSET_ABS_X = 5;\nconst activeOffsetX: number[] = [-ACTIVE_OFFSET_ABS_X, ACTIVE_OFFSET_ABS_X];\n\nconst endAnimationStates: Readonly<GestureHandlerState[]> = [\n GestureHandlerState.CANCELLED,\n GestureHandlerState.END,\n];\n\nfunction shouldScrollToAdjacent(translationX: number, velocityX: number): boolean {\n return Math.abs(translationX) >= SCROLL_TO_ADJACENT_TX_THRESHOLD\n || Math.abs(velocityX) >= SCROLL_TO_ADJACENT_VX_THRESHOLD;\n}\n\nexport default function ScrollViewGesture(props: ScrollViewGestureProps) {\n const {\n autoplayController,\n children,\n finalizeAnimation,\n offsetTx,\n scrollEnabled,\n startAnimation,\n } = props;\n\n const { pause: pauseAutoplay, resume: resumeAutoplay } = autoplayController;\n\n const handleGestureBegin = useCallback(() => {\n pauseAutoplay();\n\n finalizeAnimation();\n }, [finalizeAnimation, pauseAutoplay]);\n\n const handleGestureEvent = useCallback(Animated.event(\n [{ nativeEvent: { translationX: offsetTx } }],\n { useNativeDriver: true },\n ), []);\n\n const handleHandlerStateChange = useCallback((event: PanGestureHandlerStateChangeEvent) => {\n const { nativeEvent: { translationX, velocityX, state } } = event;\n\n if (endAnimationStates.includes(state)) {\n const userDirection: PagingDirection = shouldScrollToAdjacent(translationX, velocityX)\n ? (translationX < 0 ? 'next' : 'prev')\n : 'stay';\n\n startAnimation(userDirection, true);\n\n resumeAutoplay();\n }\n }, [startAnimation, resumeAutoplay]);\n\n return (\n <PanGestureHandler\n activeOffsetX={activeOffsetX}\n children={children}\n enabled={scrollEnabled}\n onBegan={handleGestureBegin}\n onGestureEvent={handleGestureEvent}\n onHandlerStateChange={handleHandlerStateChange}\n />\n );\n}\n"],"mappings":"AACA,OAAOA,KAAP,IAAgBC,WAAhB,QAAmC,OAAnC;AACA,SAASC,QAAT,QAAyB,cAAzB;AAEA,SAASC,iBAAT,EAA4BC,KAAK,IAAIC,mBAArC,QAAgE,8BAAhE;AAYA,MAAMC,+BAA+B,GAAG,EAAxC;AACA,MAAMC,+BAA+B,GAAG,GAAxC;AAEA,MAAMC,mBAAmB,GAAG,CAA5B;AACA,MAAMC,aAAuB,GAAG,CAAC,CAACD,mBAAF,EAAuBA,mBAAvB,CAAhC;AAEA,MAAME,kBAAmD,GAAG,CACxDL,mBAAmB,CAACM,SADoC,EAExDN,mBAAmB,CAACO,GAFoC,CAA5D;;AAKA,SAASC,sBAAT,CAAgCC,YAAhC,EAAsDC,SAAtD,EAAkF;EAC9E,OAAOC,IAAI,CAACC,GAAL,CAASH,YAAT,KAA0BR,+BAA1B,IACAU,IAAI,CAACC,GAAL,CAASF,SAAT,KAAuBR,+BAD9B;AAEH;;AAED,eAAe,SAASW,iBAAT,CAA2BC,KAA3B,EAA0D;EACrE,MAAM;IACFC,kBADE;IAEFC,QAFE;IAGFC,iBAHE;IAIFC,QAJE;IAKFC,aALE;IAMFC;EANE,IAOFN,KAPJ;EASA,MAAM;IAAEO,KAAK,EAAEC,aAAT;IAAwBC,MAAM,EAAEC;EAAhC,IAAmDT,kBAAzD;EAEA,MAAMU,kBAAkB,GAAG7B,WAAW,CAAC,MAAM;IACzC0B,aAAa;IAEbL,iBAAiB;EACpB,CAJqC,EAInC,CAACA,iBAAD,EAAoBK,aAApB,CAJmC,CAAtC;EAMA,MAAMI,kBAAkB,GAAG9B,WAAW,CAACC,QAAQ,CAAC8B,KAAT,CACnC,CAAC;IAAEC,WAAW,EAAE;MAAEnB,YAAY,EAAES;IAAhB;EAAf,CAAD,CADmC,EAEnC;IAAEW,eAAe,EAAE;EAAnB,CAFmC,CAAD,EAGnC,EAHmC,CAAtC;EAKA,MAAMC,wBAAwB,GAAGlC,WAAW,CAAE+B,KAAD,IAA8C;IACvF,MAAM;MAAEC,WAAW,EAAE;QAAEnB,YAAF;QAAgBC,SAAhB;QAA2BqB;MAA3B;IAAf,IAAsDJ,KAA5D;;IAEA,IAAItB,kBAAkB,CAAC2B,QAAnB,CAA4BD,KAA5B,CAAJ,EAAwC;MACpC,MAAME,aAA8B,GAAGzB,sBAAsB,CAACC,YAAD,EAAeC,SAAf,CAAtB,GAChCD,YAAY,GAAG,CAAf,GAAmB,MAAnB,GAA4B,MADI,GAEjC,MAFN;MAIAW,cAAc,CAACa,aAAD,EAAgB,IAAhB,CAAd;MAEAT,cAAc;IACjB;EACJ,CAZ2C,EAYzC,CAACJ,cAAD,EAAiBI,cAAjB,CAZyC,CAA5C;EAcA,oBACI,oBAAC,iBAAD;IACI,aAAa,EAAEpB,aADnB;IAEI,QAAQ,EAAEY,QAFd;IAGI,OAAO,EAAEG,aAHb;IAII,OAAO,EAAEM,kBAJb;IAKI,cAAc,EAAEC,kBALpB;IAMI,oBAAoB,EAAEI;EAN1B,EADJ;AAUH"}
1
+ {"version":3,"names":["React","useCallback","Animated","PanGestureHandler","State","GestureHandlerState","SCROLL_TO_ADJACENT_TX_THRESHOLD","SCROLL_TO_ADJACENT_VX_THRESHOLD","ACTIVE_OFFSET_ABS_X","activeOffsetX","endAnimationStates","CANCELLED","END","FAILED","shouldScrollToAdjacent","translationX","velocityX","isSameDirection","isEnoughMovement","Math","abs","ScrollViewGesture","props","autoplayController","children","interruptAnimation","translateX","scrollEnabled","startPagingAnimation","pause","pauseAutoplay","resume","resumeAutoplay","handleGestureBegin","handleGestureEvent","event","nativeEvent","useNativeDriver","handleHandlerStateChange","state","includes","direction","isOriginatedFromGesture"],"sources":["ScrollViewGesture.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport React, { useCallback } from 'react';\nimport { Animated } from 'react-native';\nimport type { PanGestureHandlerStateChangeEvent } from 'react-native-gesture-handler';\nimport { PanGestureHandler, State as GestureHandlerState } from 'react-native-gesture-handler';\nimport type { AutoplayController, PagingDirection, StartPagingAnimation } from '../types';\n\nexport interface ScrollViewGestureProps {\n autoplayController: AutoplayController;\n children: ReactNode;\n interruptAnimation: () => void;\n translateX: Animated.Value,\n scrollEnabled: boolean;\n startPagingAnimation: StartPagingAnimation;\n}\n\nconst SCROLL_TO_ADJACENT_TX_THRESHOLD = 80;\nconst SCROLL_TO_ADJACENT_VX_THRESHOLD = 1000;\n\nconst ACTIVE_OFFSET_ABS_X = 5;\nconst activeOffsetX: number[] = [-ACTIVE_OFFSET_ABS_X, ACTIVE_OFFSET_ABS_X];\n\nconst endAnimationStates: Readonly<GestureHandlerState[]> = [\n GestureHandlerState.CANCELLED,\n GestureHandlerState.END,\n GestureHandlerState.FAILED,\n];\n\nfunction shouldScrollToAdjacent(translationX: number, velocityX: number): boolean {\n const isSameDirection = translationX * velocityX > 0;\n const isEnoughMovement =\n Math.abs(translationX) >= SCROLL_TO_ADJACENT_TX_THRESHOLD\n || Math.abs(velocityX) >= SCROLL_TO_ADJACENT_VX_THRESHOLD;\n\n return isSameDirection && isEnoughMovement;\n}\n\nexport default function ScrollViewGesture(props: ScrollViewGestureProps) {\n const {\n autoplayController,\n children,\n interruptAnimation,\n translateX,\n scrollEnabled,\n startPagingAnimation,\n } = props;\n\n const { pause: pauseAutoplay, resume: resumeAutoplay } = autoplayController;\n\n const handleGestureBegin = useCallback(() => {\n pauseAutoplay();\n\n interruptAnimation();\n }, [interruptAnimation, pauseAutoplay]);\n\n const handleGestureEvent = useCallback(Animated.event(\n [{ nativeEvent: { translationX: translateX } }],\n { useNativeDriver: true },\n ), []);\n\n const handleHandlerStateChange = useCallback((event: PanGestureHandlerStateChangeEvent) => {\n const { nativeEvent: { translationX, velocityX, state } } = event;\n\n if (endAnimationStates.includes(state)) {\n const direction: PagingDirection = shouldScrollToAdjacent(translationX, velocityX)\n ? (translationX < 0 ? 'next' : 'prev')\n : 'stay';\n\n startPagingAnimation(\n 'directional',\n { direction: direction, isOriginatedFromGesture: true },\n );\n\n resumeAutoplay();\n }\n }, [startPagingAnimation, resumeAutoplay]);\n\n return (\n <PanGestureHandler\n activeOffsetX={activeOffsetX}\n children={children}\n enabled={scrollEnabled}\n onBegan={handleGestureBegin}\n onGestureEvent={handleGestureEvent}\n onHandlerStateChange={handleHandlerStateChange}\n />\n );\n}\n"],"mappings":"AACA,OAAOA,KAAP,IAAgBC,WAAhB,QAAmC,OAAnC;AACA,SAASC,QAAT,QAAyB,cAAzB;AAEA,SAASC,iBAAT,EAA4BC,KAAK,IAAIC,mBAArC,QAAgE,8BAAhE;AAYA,MAAMC,+BAA+B,GAAG,EAAxC;AACA,MAAMC,+BAA+B,GAAG,IAAxC;AAEA,MAAMC,mBAAmB,GAAG,CAA5B;AACA,MAAMC,aAAuB,GAAG,CAAC,CAACD,mBAAF,EAAuBA,mBAAvB,CAAhC;AAEA,MAAME,kBAAmD,GAAG,CACxDL,mBAAmB,CAACM,SADoC,EAExDN,mBAAmB,CAACO,GAFoC,EAGxDP,mBAAmB,CAACQ,MAHoC,CAA5D;;AAMA,SAASC,sBAAT,CAAgCC,YAAhC,EAAsDC,SAAtD,EAAkF;EAC9E,MAAMC,eAAe,GAAGF,YAAY,GAAGC,SAAf,GAA2B,CAAnD;EACA,MAAME,gBAAgB,GAClBC,IAAI,CAACC,GAAL,CAASL,YAAT,KAA0BT,+BAA1B,IACGa,IAAI,CAACC,GAAL,CAASJ,SAAT,KAAuBT,+BAF9B;EAIA,OAAOU,eAAe,IAAIC,gBAA1B;AACH;;AAED,eAAe,SAASG,iBAAT,CAA2BC,KAA3B,EAA0D;EACrE,MAAM;IACFC,kBADE;IAEFC,QAFE;IAGFC,kBAHE;IAIFC,UAJE;IAKFC,aALE;IAMFC;EANE,IAOFN,KAPJ;EASA,MAAM;IAAEO,KAAK,EAAEC,aAAT;IAAwBC,MAAM,EAAEC;EAAhC,IAAmDT,kBAAzD;EAEA,MAAMU,kBAAkB,GAAGhC,WAAW,CAAC,MAAM;IACzC6B,aAAa;IAEbL,kBAAkB;EACrB,CAJqC,EAInC,CAACA,kBAAD,EAAqBK,aAArB,CAJmC,CAAtC;EAMA,MAAMI,kBAAkB,GAAGjC,WAAW,CAACC,QAAQ,CAACiC,KAAT,CACnC,CAAC;IAAEC,WAAW,EAAE;MAAErB,YAAY,EAAEW;IAAhB;EAAf,CAAD,CADmC,EAEnC;IAAEW,eAAe,EAAE;EAAnB,CAFmC,CAAD,EAGnC,EAHmC,CAAtC;EAKA,MAAMC,wBAAwB,GAAGrC,WAAW,CAAEkC,KAAD,IAA8C;IACvF,MAAM;MAAEC,WAAW,EAAE;QAAErB,YAAF;QAAgBC,SAAhB;QAA2BuB;MAA3B;IAAf,IAAsDJ,KAA5D;;IAEA,IAAIzB,kBAAkB,CAAC8B,QAAnB,CAA4BD,KAA5B,CAAJ,EAAwC;MACpC,MAAME,SAA0B,GAAG3B,sBAAsB,CAACC,YAAD,EAAeC,SAAf,CAAtB,GAC5BD,YAAY,GAAG,CAAf,GAAmB,MAAnB,GAA4B,MADA,GAE7B,MAFN;MAIAa,oBAAoB,CAChB,aADgB,EAEhB;QAAEa,SAAS,EAAEA,SAAb;QAAwBC,uBAAuB,EAAE;MAAjD,CAFgB,CAApB;MAKAV,cAAc;IACjB;EACJ,CAf2C,EAezC,CAACJ,oBAAD,EAAuBI,cAAvB,CAfyC,CAA5C;EAiBA,oBACI,oBAAC,iBAAD;IACI,aAAa,EAAEvB,aADnB;IAEI,QAAQ,EAAEe,QAFd;IAGI,OAAO,EAAEG,aAHb;IAII,OAAO,EAAEM,kBAJb;IAKI,cAAc,EAAEC,kBALpB;IAMI,oBAAoB,EAAEI;EAN1B,EADJ;AAUH"}
@@ -1,6 +1,6 @@
1
1
  import { useContext, useMemo } from 'react';
2
2
  import { Animated } from 'react-native';
3
- import { InternalContext } from '../components';
3
+ import InternalContext from './InternalContext';
4
4
  const OVERSCROLL_FRICTION_FACTOR = 4;
5
5
  export default function useItemInterpolation(index) {
6
6
  const {
@@ -43,8 +43,8 @@ export default function useItemInterpolation(index) {
43
43
  }, [index, itemWidth, numberOfData]);
44
44
  return useMemo(() => {
45
45
  const interpolationConfig = loop ? interpolationConfigOnLoop : interpolationConfigOnNoLoop;
46
- const offsetX = globalInterpolation.interpolate(interpolationConfig);
47
- return Animated.divide(offsetX, itemWidth);
46
+ const localOffsetX = globalInterpolation.interpolate(interpolationConfig);
47
+ return Animated.divide(localOffsetX, itemWidth);
48
48
  }, [globalInterpolation, interpolationConfigOnLoop, interpolationConfigOnNoLoop, itemWidth, loop]);
49
49
  }
50
50
  ;
@@ -0,0 +1 @@
1
+ {"version":3,"names":["useContext","useMemo","Animated","InternalContext","OVERSCROLL_FRICTION_FACTOR","useItemInterpolation","index","itemWidth","data","globalInterpolation","loop","numberOfData","length","interpolationConfigOnLoop","lastIndex","maxWidth","Math","abs","halfOfItemWidth","positiveCount","round","startPosition","max","min","inputRange","Number","MIN_VALUE","outputRange","extrapolate","interpolationConfigOnNoLoop","friction","interpolationConfig","localOffsetX","interpolate","divide"],"sources":["useItemInterpolation.ts"],"sourcesContent":["import { useContext, useMemo } from 'react';\nimport { Animated } from 'react-native';\nimport InternalContext from './InternalContext';\n\nconst OVERSCROLL_FRICTION_FACTOR = 4;\n\nexport default function useItemInterpolation(index: number): Animated.AnimatedInterpolation {\n const {\n itemWidth,\n data,\n globalInterpolation,\n loop,\n } = useContext(InternalContext);\n\n const numberOfData = data.length;\n\n const interpolationConfigOnLoop = useMemo<Animated.InterpolationConfigType>(() => {\n const lastIndex = numberOfData - 1;\n const maxWidth = Math.abs(itemWidth * numberOfData);\n const halfOfItemWidth = 0.5 * itemWidth;\n\n const positiveCount = Math.round(lastIndex / 2);\n const startPosition = index > positiveCount\n ? (index - numberOfData) * itemWidth\n : itemWidth * index;\n\n const max = positiveCount * itemWidth;\n const min = -((lastIndex - positiveCount) * itemWidth);\n\n const inputRange = [\n -maxWidth,\n min - halfOfItemWidth - startPosition - Number.MIN_VALUE,\n min - halfOfItemWidth - startPosition,\n 0,\n max + halfOfItemWidth - startPosition,\n max + halfOfItemWidth - startPosition + Number.MIN_VALUE,\n maxWidth,\n ];\n\n const outputRange = [\n startPosition,\n max + halfOfItemWidth - Number.MIN_VALUE,\n min - halfOfItemWidth,\n startPosition,\n max + halfOfItemWidth,\n min - halfOfItemWidth + Number.MIN_VALUE,\n startPosition,\n ];\n\n return {\n inputRange,\n outputRange,\n extrapolate: 'clamp',\n };\n }, [\n index,\n itemWidth,\n numberOfData,\n ]);\n\n const interpolationConfigOnNoLoop = useMemo<Animated.InterpolationConfigType>(() => {\n const lastIndex = numberOfData - 1;\n const maxWidth = itemWidth * lastIndex;\n const startPosition = itemWidth * index;\n const friction = itemWidth / OVERSCROLL_FRICTION_FACTOR;\n\n const inputRange = [\n -(maxWidth + itemWidth), // overscroll\n -maxWidth,\n 0,\n itemWidth, // overscroll\n ];\n\n const outputRange = [\n -maxWidth + startPosition - friction,\n -maxWidth + startPosition,\n startPosition,\n startPosition + friction,\n ];\n\n return {\n inputRange,\n outputRange,\n extrapolate: 'clamp',\n };\n }, [\n index,\n itemWidth,\n numberOfData,\n ]);\n\n return useMemo(() => {\n const interpolationConfig = loop\n ? interpolationConfigOnLoop\n : interpolationConfigOnNoLoop;\n\n const localOffsetX = globalInterpolation.interpolate(interpolationConfig);\n\n return Animated.divide(localOffsetX, itemWidth);\n }, [\n globalInterpolation,\n interpolationConfigOnLoop,\n interpolationConfigOnNoLoop,\n itemWidth,\n loop,\n ]);\n};\n"],"mappings":"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"}
@@ -1,7 +1,5 @@
1
1
  export { default as useAutoplayController } from './useAutoplayController';
2
- export { default as useDimensionChangeReaction } from './useDimensionChangeReaction';
3
2
  export { default as useIndexController } from './useIndexController';
4
- export { default as useItemInterpolation } from './useItemInterpolation';
5
3
  export { default as useLoopedData } from './useLoopedData';
6
4
  export { default as usePagingAnimation } from './usePagingAnimation';
7
5
  export { default as useItemVisibilityStore } from './useItemVisibilityStore';
@@ -1 +1 @@
1
- {"version":3,"names":["default","useAutoplayController","useDimensionChangeReaction","useIndexController","useItemInterpolation","useLoopedData","usePagingAnimation","useItemVisibilityStore"],"sources":["index.ts"],"sourcesContent":["export { default as useAutoplayController } from './useAutoplayController';\nexport { default as useDimensionChangeReaction } from './useDimensionChangeReaction';\nexport { default as useIndexController } from './useIndexController';\nexport { default as useItemInterpolation } from './useItemInterpolation';\nexport { default as useLoopedData } from './useLoopedData';\nexport { default as usePagingAnimation } from './usePagingAnimation';\nexport { default as useItemVisibilityStore } from './useItemVisibilityStore';\n"],"mappings":"AAAA,SAASA,OAAO,IAAIC,qBAApB,QAAiD,yBAAjD;AACA,SAASD,OAAO,IAAIE,0BAApB,QAAsD,8BAAtD;AACA,SAASF,OAAO,IAAIG,kBAApB,QAA8C,sBAA9C;AACA,SAASH,OAAO,IAAII,oBAApB,QAAgD,wBAAhD;AACA,SAASJ,OAAO,IAAIK,aAApB,QAAyC,iBAAzC;AACA,SAASL,OAAO,IAAIM,kBAApB,QAA8C,sBAA9C;AACA,SAASN,OAAO,IAAIO,sBAApB,QAAkD,0BAAlD"}
1
+ {"version":3,"names":["default","useAutoplayController","useIndexController","useLoopedData","usePagingAnimation","useItemVisibilityStore"],"sources":["index.ts"],"sourcesContent":["export { default as useAutoplayController } from './useAutoplayController';\nexport { default as useIndexController } from './useIndexController';\nexport { default as useLoopedData } from './useLoopedData';\nexport { default as usePagingAnimation } from './usePagingAnimation';\nexport { default as useItemVisibilityStore } from './useItemVisibilityStore';\n"],"mappings":"AAAA,SAASA,OAAO,IAAIC,qBAApB,QAAiD,yBAAjD;AACA,SAASD,OAAO,IAAIE,kBAApB,QAA8C,sBAA9C;AACA,SAASF,OAAO,IAAIG,aAApB,QAAyC,iBAAzC;AACA,SAASH,OAAO,IAAII,kBAApB,QAA8C,sBAA9C;AACA,SAASJ,OAAO,IAAIK,sBAApB,QAAkD,0BAAlD"}
@@ -14,7 +14,10 @@ export default function useAutoplayController(config) {
14
14
  }
15
15
 
16
16
  executor.execute(() => {
17
- startPagingAnimation('next', false);
17
+ startPagingAnimation('directional', {
18
+ direction: 'next',
19
+ isOriginatedFromGesture: false
20
+ });
18
21
  play();
19
22
  }, intervalMillis);
20
23
  }, [intervalMillis, startPagingAnimation]);
@@ -1 +1 @@
1
- {"version":3,"names":["useCallback","useEffect","useRef","useDeferredExecutor","useAutoplayController","config","enabled","intervalMillis","startPagingAnimation","paused","executor","play","current","execute","pause","cancel","resume"],"sources":["useAutoplayController.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport type { AutoplayController, StartPagingAnimation } from '../types';\nimport { useDeferredExecutor } from '../../hooks';\n\nexport interface AutoplayConfig {\n enabled: boolean;\n intervalMillis: number;\n startPagingAnimation: StartPagingAnimation;\n}\n\nexport default function useAutoplayController(config: AutoplayConfig): AutoplayController {\n const {\n enabled,\n intervalMillis,\n startPagingAnimation,\n } = config;\n\n const paused = useRef<boolean>(false);\n\n const executor = useDeferredExecutor();\n\n const play = useCallback(() => {\n if (paused.current) {\n return;\n }\n\n executor.execute(() => {\n startPagingAnimation('next', false);\n play();\n }, intervalMillis);\n }, [intervalMillis, startPagingAnimation]);\n\n const pause = useCallback(() => {\n executor.cancel();\n paused.current = true;\n }, []);\n\n const resume = useCallback(() => {\n paused.current = false;\n if (enabled) {\n play();\n }\n }, [play, enabled]);\n\n useEffect(() => {\n if (enabled) {\n resume();\n } else {\n pause();\n }\n }, [enabled]);\n\n return { pause, resume };\n};\n"],"mappings":"AAAA,SAASA,WAAT,EAAsBC,SAAtB,EAAiCC,MAAjC,QAA+C,OAA/C;AAEA,SAASC,mBAAT,QAAoC,aAApC;AAQA,eAAe,SAASC,qBAAT,CAA+BC,MAA/B,EAA2E;EACtF,MAAM;IACFC,OADE;IAEFC,cAFE;IAGFC;EAHE,IAIFH,MAJJ;EAMA,MAAMI,MAAM,GAAGP,MAAM,CAAU,KAAV,CAArB;EAEA,MAAMQ,QAAQ,GAAGP,mBAAmB,EAApC;EAEA,MAAMQ,IAAI,GAAGX,WAAW,CAAC,MAAM;IAC3B,IAAIS,MAAM,CAACG,OAAX,EAAoB;MAChB;IACH;;IAEDF,QAAQ,CAACG,OAAT,CAAiB,MAAM;MACnBL,oBAAoB,CAAC,MAAD,EAAS,KAAT,CAApB;MACAG,IAAI;IACP,CAHD,EAGGJ,cAHH;EAIH,CATuB,EASrB,CAACA,cAAD,EAAiBC,oBAAjB,CATqB,CAAxB;EAWA,MAAMM,KAAK,GAAGd,WAAW,CAAC,MAAM;IAC5BU,QAAQ,CAACK,MAAT;IACAN,MAAM,CAACG,OAAP,GAAiB,IAAjB;EACH,CAHwB,EAGtB,EAHsB,CAAzB;EAKA,MAAMI,MAAM,GAAGhB,WAAW,CAAC,MAAM;IAC7BS,MAAM,CAACG,OAAP,GAAiB,KAAjB;;IACA,IAAIN,OAAJ,EAAa;MACTK,IAAI;IACP;EACJ,CALyB,EAKvB,CAACA,IAAD,EAAOL,OAAP,CALuB,CAA1B;EAOAL,SAAS,CAAC,MAAM;IACZ,IAAIK,OAAJ,EAAa;MACTU,MAAM;IACT,CAFD,MAEO;MACHF,KAAK;IACR;EACJ,CANQ,EAMN,CAACR,OAAD,CANM,CAAT;EAQA,OAAO;IAAEQ,KAAF;IAASE;EAAT,CAAP;AACH;AAAA"}
1
+ {"version":3,"names":["useCallback","useEffect","useRef","useDeferredExecutor","useAutoplayController","config","enabled","intervalMillis","startPagingAnimation","paused","executor","play","current","execute","direction","isOriginatedFromGesture","pause","cancel","resume"],"sources":["useAutoplayController.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport type { AutoplayController, StartPagingAnimation } from '../types';\nimport { useDeferredExecutor } from '../../hooks';\n\nexport interface AutoplayConfig {\n enabled: boolean;\n intervalMillis: number;\n startPagingAnimation: StartPagingAnimation;\n}\n\nexport default function useAutoplayController(config: AutoplayConfig): AutoplayController {\n const {\n enabled,\n intervalMillis,\n startPagingAnimation,\n } = config;\n\n const paused = useRef<boolean>(false);\n\n const executor = useDeferredExecutor();\n\n const play = useCallback(() => {\n if (paused.current) {\n return;\n }\n\n executor.execute(() => {\n startPagingAnimation(\n 'directional',\n { direction: 'next', isOriginatedFromGesture: false },\n );\n play();\n }, intervalMillis);\n }, [intervalMillis, startPagingAnimation]);\n\n const pause = useCallback(() => {\n executor.cancel();\n paused.current = true;\n }, []);\n\n const resume = useCallback(() => {\n paused.current = false;\n if (enabled) {\n play();\n }\n }, [play, enabled]);\n\n useEffect(() => {\n if (enabled) {\n resume();\n } else {\n pause();\n }\n }, [enabled]);\n\n return { pause, resume };\n};\n"],"mappings":"AAAA,SAASA,WAAT,EAAsBC,SAAtB,EAAiCC,MAAjC,QAA+C,OAA/C;AAEA,SAASC,mBAAT,QAAoC,aAApC;AAQA,eAAe,SAASC,qBAAT,CAA+BC,MAA/B,EAA2E;EACtF,MAAM;IACFC,OADE;IAEFC,cAFE;IAGFC;EAHE,IAIFH,MAJJ;EAMA,MAAMI,MAAM,GAAGP,MAAM,CAAU,KAAV,CAArB;EAEA,MAAMQ,QAAQ,GAAGP,mBAAmB,EAApC;EAEA,MAAMQ,IAAI,GAAGX,WAAW,CAAC,MAAM;IAC3B,IAAIS,MAAM,CAACG,OAAX,EAAoB;MAChB;IACH;;IAEDF,QAAQ,CAACG,OAAT,CAAiB,MAAM;MACnBL,oBAAoB,CAChB,aADgB,EAEhB;QAAEM,SAAS,EAAE,MAAb;QAAqBC,uBAAuB,EAAE;MAA9C,CAFgB,CAApB;MAIAJ,IAAI;IACP,CAND,EAMGJ,cANH;EAOH,CAZuB,EAYrB,CAACA,cAAD,EAAiBC,oBAAjB,CAZqB,CAAxB;EAcA,MAAMQ,KAAK,GAAGhB,WAAW,CAAC,MAAM;IAC5BU,QAAQ,CAACO,MAAT;IACAR,MAAM,CAACG,OAAP,GAAiB,IAAjB;EACH,CAHwB,EAGtB,EAHsB,CAAzB;EAKA,MAAMM,MAAM,GAAGlB,WAAW,CAAC,MAAM;IAC7BS,MAAM,CAACG,OAAP,GAAiB,KAAjB;;IACA,IAAIN,OAAJ,EAAa;MACTK,IAAI;IACP;EACJ,CALyB,EAKvB,CAACA,IAAD,EAAOL,OAAP,CALuB,CAA1B;EAOAL,SAAS,CAAC,MAAM;IACZ,IAAIK,OAAJ,EAAa;MACTY,MAAM;IACT,CAFD,MAEO;MACHF,KAAK;IACR;EACJ,CANQ,EAMN,CAACV,OAAD,CANM,CAAT;EAQA,OAAO;IAAEU,KAAF;IAASE;EAAT,CAAP;AACH;AAAA"}
@@ -1,53 +1,28 @@
1
- import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
- import { Animated } from 'react-native';
3
-
4
- const normalizeIndex = (maybeIndex, numberOfData) => Math.abs(Math.floor(maybeIndex)) % numberOfData;
5
-
1
+ import { useCallback, useRef } from 'react';
2
+ import { mod } from '@fountain-ui/utils';
6
3
  export default function useIndexController(params) {
7
4
  const {
8
- controlledTx,
9
5
  initialIndex,
10
6
  itemWidth,
11
7
  numberOfOriginalData,
12
8
  onIndexChange
13
9
  } = params;
14
- const indexRef = useRef(initialIndex);
15
- const [index, setIndex] = useState(indexRef.current);
16
- const maybeIndex = useMemo(() => {
17
- const negative = new Animated.Value(-1);
18
- const reversedTx = Animated.multiply(controlledTx, negative);
19
- const normalized = Animated.divide(reversedTx, itemWidth);
20
- return Animated.modulo(normalized, numberOfOriginalData);
21
- }, [controlledTx, itemWidth, numberOfOriginalData]);
22
- useEffect(() => {
23
- const subscriptionId = maybeIndex.addListener(observedValue => {
24
- const newIndex = normalizeIndex(observedValue.value, numberOfOriginalData);
10
+ const currentIndexRef = useRef(initialIndex);
11
+ const getCurrentIndex = useCallback(() => currentIndexRef.current, []);
12
+ const notifyOffsetHasChanged = useCallback(offset => {
13
+ const roundedOffset = Math.round(offset / itemWidth) * itemWidth; // To prevent floating point problem, make sure index is integer type.
14
+
15
+ const nextIndex = Math.floor(mod(-roundedOffset / itemWidth, numberOfOriginalData));
25
16
 
26
- if (indexRef.current !== newIndex) {
27
- indexRef.current = newIndex;
28
- setIndex(newIndex);
29
- onIndexChange === null || onIndexChange === void 0 ? void 0 : onIndexChange(newIndex);
30
- }
31
- });
32
- return () => {
33
- maybeIndex.removeListener(subscriptionId);
34
- };
35
- }, [maybeIndex, numberOfOriginalData, onIndexChange]);
36
- const getCurrentIndex = useCallback(() => indexRef.current, []);
17
+ if (nextIndex !== currentIndexRef.current) {
18
+ currentIndexRef.current = nextIndex;
19
+ onIndexChange === null || onIndexChange === void 0 ? void 0 : onIndexChange(nextIndex);
20
+ }
21
+ }, [itemWidth, numberOfOriginalData, onIndexChange]);
37
22
  return {
38
- currentIndex: index,
39
23
  getCurrentIndex,
40
24
  lastIndex: numberOfOriginalData - 1,
41
- monitorElement: /*#__PURE__*/React.createElement(Animated.View, {
42
- collapsable: false,
43
- style: [{
44
- zIndex: maybeIndex
45
- }, {
46
- width: 1,
47
- height: 1,
48
- position: 'absolute'
49
- }]
50
- })
25
+ notifyOffsetHasChanged
51
26
  };
52
27
  }
53
28
  ;
@@ -1 +1 @@
1
- {"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","Animated","normalizeIndex","maybeIndex","numberOfData","Math","abs","floor","useIndexController","params","controlledTx","initialIndex","itemWidth","numberOfOriginalData","onIndexChange","indexRef","index","setIndex","current","negative","Value","reversedTx","multiply","normalized","divide","modulo","subscriptionId","addListener","observedValue","newIndex","value","removeListener","getCurrentIndex","currentIndex","lastIndex","monitorElement","zIndex","width","height","position"],"sources":["useIndexController.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Animated } from 'react-native';\nimport type { IndexController } from '../types';\n\nexport interface UseIndexControllerParameters {\n controlledTx: Animated.AnimatedValue;\n initialIndex: number;\n itemWidth: number;\n numberOfOriginalData: number;\n onIndexChange?: (newIndex: number) => void;\n}\n\nconst normalizeIndex = (maybeIndex: number, numberOfData: number): number =>\n Math.abs(Math.floor(maybeIndex)) % numberOfData;\n\nexport default function useIndexController(params: UseIndexControllerParameters): IndexController {\n const {\n controlledTx,\n initialIndex,\n itemWidth,\n numberOfOriginalData,\n onIndexChange,\n } = params;\n\n const indexRef = useRef<number>(initialIndex);\n const [index, setIndex] = useState<number>(indexRef.current);\n\n const maybeIndex = useMemo(() => {\n const negative = new Animated.Value(-1);\n const reversedTx = Animated.multiply(controlledTx, negative);\n const normalized = Animated.divide(reversedTx, itemWidth);\n return Animated.modulo(normalized, numberOfOriginalData);\n }, [\n controlledTx,\n itemWidth,\n numberOfOriginalData,\n ]);\n\n useEffect(() => {\n const subscriptionId = maybeIndex.addListener((observedValue) => {\n const newIndex = normalizeIndex(observedValue.value, numberOfOriginalData);\n\n if (indexRef.current !== newIndex) {\n indexRef.current = newIndex;\n setIndex(newIndex);\n\n onIndexChange?.(newIndex);\n }\n });\n\n return () => {\n maybeIndex.removeListener(subscriptionId);\n };\n }, [\n maybeIndex,\n numberOfOriginalData,\n onIndexChange,\n ]);\n\n const getCurrentIndex = useCallback(() => indexRef.current, []);\n\n return {\n currentIndex: index,\n getCurrentIndex,\n lastIndex: numberOfOriginalData - 1,\n monitorElement: (\n <Animated.View\n collapsable={false}\n style={[\n { zIndex: maybeIndex },\n { width: 1, height: 1, position: 'absolute' },\n ]}\n />\n ),\n };\n};\n"],"mappings":"AAAA,OAAOA,KAAP,IAAgBC,WAAhB,EAA6BC,SAA7B,EAAwCC,OAAxC,EAAiDC,MAAjD,EAAyDC,QAAzD,QAAyE,OAAzE;AACA,SAASC,QAAT,QAAyB,cAAzB;;AAWA,MAAMC,cAAc,GAAG,CAACC,UAAD,EAAqBC,YAArB,KACnBC,IAAI,CAACC,GAAL,CAASD,IAAI,CAACE,KAAL,CAAWJ,UAAX,CAAT,IAAmCC,YADvC;;AAGA,eAAe,SAASI,kBAAT,CAA4BC,MAA5B,EAAmF;EAC9F,MAAM;IACFC,YADE;IAEFC,YAFE;IAGFC,SAHE;IAIFC,oBAJE;IAKFC;EALE,IAMFL,MANJ;EAQA,MAAMM,QAAQ,GAAGhB,MAAM,CAASY,YAAT,CAAvB;EACA,MAAM,CAACK,KAAD,EAAQC,QAAR,IAAoBjB,QAAQ,CAASe,QAAQ,CAACG,OAAlB,CAAlC;EAEA,MAAMf,UAAU,GAAGL,OAAO,CAAC,MAAM;IAC7B,MAAMqB,QAAQ,GAAG,IAAIlB,QAAQ,CAACmB,KAAb,CAAmB,CAAC,CAApB,CAAjB;IACA,MAAMC,UAAU,GAAGpB,QAAQ,CAACqB,QAAT,CAAkBZ,YAAlB,EAAgCS,QAAhC,CAAnB;IACA,MAAMI,UAAU,GAAGtB,QAAQ,CAACuB,MAAT,CAAgBH,UAAhB,EAA4BT,SAA5B,CAAnB;IACA,OAAOX,QAAQ,CAACwB,MAAT,CAAgBF,UAAhB,EAA4BV,oBAA5B,CAAP;EACH,CALyB,EAKvB,CACCH,YADD,EAECE,SAFD,EAGCC,oBAHD,CALuB,CAA1B;EAWAhB,SAAS,CAAC,MAAM;IACZ,MAAM6B,cAAc,GAAGvB,UAAU,CAACwB,WAAX,CAAwBC,aAAD,IAAmB;MAC7D,MAAMC,QAAQ,GAAG3B,cAAc,CAAC0B,aAAa,CAACE,KAAf,EAAsBjB,oBAAtB,CAA/B;;MAEA,IAAIE,QAAQ,CAACG,OAAT,KAAqBW,QAAzB,EAAmC;QAC/Bd,QAAQ,CAACG,OAAT,GAAmBW,QAAnB;QACAZ,QAAQ,CAACY,QAAD,CAAR;QAEAf,aAAa,SAAb,IAAAA,aAAa,WAAb,YAAAA,aAAa,CAAGe,QAAH,CAAb;MACH;IACJ,CATsB,CAAvB;IAWA,OAAO,MAAM;MACT1B,UAAU,CAAC4B,cAAX,CAA0BL,cAA1B;IACH,CAFD;EAGH,CAfQ,EAeN,CACCvB,UADD,EAECU,oBAFD,EAGCC,aAHD,CAfM,CAAT;EAqBA,MAAMkB,eAAe,GAAGpC,WAAW,CAAC,MAAMmB,QAAQ,CAACG,OAAhB,EAAyB,EAAzB,CAAnC;EAEA,OAAO;IACHe,YAAY,EAAEjB,KADX;IAEHgB,eAFG;IAGHE,SAAS,EAAErB,oBAAoB,GAAG,CAH/B;IAIHsB,cAAc,eACV,oBAAC,QAAD,CAAU,IAAV;MACI,WAAW,EAAE,KADjB;MAEI,KAAK,EAAE,CACH;QAAEC,MAAM,EAAEjC;MAAV,CADG,EAEH;QAAEkC,KAAK,EAAE,CAAT;QAAYC,MAAM,EAAE,CAApB;QAAuBC,QAAQ,EAAE;MAAjC,CAFG;IAFX;EALD,CAAP;AAcH;AAAA"}
1
+ {"version":3,"names":["useCallback","useRef","mod","useIndexController","params","initialIndex","itemWidth","numberOfOriginalData","onIndexChange","currentIndexRef","getCurrentIndex","current","notifyOffsetHasChanged","offset","roundedOffset","Math","round","nextIndex","floor","lastIndex"],"sources":["useIndexController.tsx"],"sourcesContent":["import React, { useCallback, useRef } from 'react';\nimport { mod } from '@fountain-ui/utils';\nimport type { IndexController } from '../types';\n\nexport interface UseIndexControllerParameters {\n initialIndex: number;\n itemWidth: number;\n numberOfOriginalData: number;\n onIndexChange?: (newIndex: number) => void;\n}\n\nexport default function useIndexController(params: UseIndexControllerParameters): IndexController {\n const {\n initialIndex,\n itemWidth,\n numberOfOriginalData,\n onIndexChange,\n } = params;\n\n const currentIndexRef = useRef<number>(initialIndex);\n\n const getCurrentIndex = useCallback(() => currentIndexRef.current, []);\n\n const notifyOffsetHasChanged = useCallback((offset: number) => {\n const roundedOffset = Math.round(offset / itemWidth) * itemWidth;\n\n // To prevent floating point problem, make sure index is integer type.\n const nextIndex = Math.floor(mod((-roundedOffset / itemWidth), numberOfOriginalData));\n\n if (nextIndex !== currentIndexRef.current) {\n currentIndexRef.current = nextIndex;\n\n onIndexChange?.(nextIndex);\n }\n }, [\n itemWidth,\n numberOfOriginalData,\n onIndexChange,\n ]);\n\n return {\n getCurrentIndex,\n lastIndex: numberOfOriginalData - 1,\n notifyOffsetHasChanged,\n };\n};\n"],"mappings":"AAAA,SAAgBA,WAAhB,EAA6BC,MAA7B,QAA2C,OAA3C;AACA,SAASC,GAAT,QAAoB,oBAApB;AAUA,eAAe,SAASC,kBAAT,CAA4BC,MAA5B,EAAmF;EAC9F,MAAM;IACFC,YADE;IAEFC,SAFE;IAGFC,oBAHE;IAIFC;EAJE,IAKFJ,MALJ;EAOA,MAAMK,eAAe,GAAGR,MAAM,CAASI,YAAT,CAA9B;EAEA,MAAMK,eAAe,GAAGV,WAAW,CAAC,MAAMS,eAAe,CAACE,OAAvB,EAAgC,EAAhC,CAAnC;EAEA,MAAMC,sBAAsB,GAAGZ,WAAW,CAAEa,MAAD,IAAoB;IAC3D,MAAMC,aAAa,GAAGC,IAAI,CAACC,KAAL,CAAWH,MAAM,GAAGP,SAApB,IAAiCA,SAAvD,CAD2D,CAG3D;;IACA,MAAMW,SAAS,GAAGF,IAAI,CAACG,KAAL,CAAWhB,GAAG,CAAE,CAACY,aAAD,GAAiBR,SAAnB,EAA+BC,oBAA/B,CAAd,CAAlB;;IAEA,IAAIU,SAAS,KAAKR,eAAe,CAACE,OAAlC,EAA2C;MACvCF,eAAe,CAACE,OAAhB,GAA0BM,SAA1B;MAEAT,aAAa,SAAb,IAAAA,aAAa,WAAb,YAAAA,aAAa,CAAGS,SAAH,CAAb;IACH;EACJ,CAXyC,EAWvC,CACCX,SADD,EAECC,oBAFD,EAGCC,aAHD,CAXuC,CAA1C;EAiBA,OAAO;IACHE,eADG;IAEHS,SAAS,EAAEZ,oBAAoB,GAAG,CAF/B;IAGHK;EAHG,CAAP;AAKH;AAAA"}
@@ -1,6 +1,7 @@
1
1
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
2
2
 
3
- import { useEffect, useRef, useState } from 'react';
3
+ import { useCallback, useEffect, useRef, useState } from 'react';
4
+ import { mod } from '@fountain-ui/utils';
4
5
 
5
6
  class SimpleItemVisibilityStore {
6
7
  constructor(initialValue) {
@@ -47,10 +48,6 @@ function normalize(windowSize, numberOfData) {
47
48
  return windowSize;
48
49
  }
49
50
 
50
- function mod(value, modulo) {
51
- return (value % modulo + modulo) % modulo;
52
- }
53
-
54
51
  function makeVisibleIndexRanges(numberOfData, windowSize, index) {
55
52
  const ws = normalize(windowSize, numberOfData);
56
53
  const firstIndex = 0;
@@ -66,22 +63,24 @@ function makeVisibleIndexRanges(numberOfData, windowSize, index) {
66
63
 
67
64
  export default function useItemVisibilityStore(params) {
68
65
  const {
69
- currentIndex,
66
+ initialIndex,
70
67
  numberOfData,
71
68
  windowSize
72
69
  } = params;
73
- const [initialRange] = useState(() => makeVisibleIndexRanges(numberOfData, windowSize, currentIndex));
70
+ const [initialRange] = useState(() => {
71
+ return makeVisibleIndexRanges(numberOfData, windowSize, initialIndex);
72
+ });
74
73
  const store = useRef(new SimpleItemVisibilityStore(initialRange)).current;
75
- useEffect(() => {
76
- const newRanges = makeVisibleIndexRanges(numberOfData, windowSize, currentIndex);
74
+ const onIndexChange = useCallback(newIndex => {
75
+ const newRanges = makeVisibleIndexRanges(numberOfData, windowSize, newIndex);
77
76
  store.dispatch(newRanges);
78
- }, [currentIndex, numberOfData, windowSize]);
77
+ }, [numberOfData, windowSize]);
79
78
  useEffect(() => {
80
79
  return () => {
81
80
  store.removeAllListeners();
82
81
  };
83
82
  }, []);
84
- return store;
83
+ return [store, onIndexChange];
85
84
  }
86
85
  ;
87
86
  //# sourceMappingURL=useItemVisibilityStore.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["useEffect","useRef","useState","SimpleItemVisibilityStore","constructor","initialValue","store","subscribe","listener","listeners","push","index","indexOf","splice","dispatch","ranges","id","removeAllListeners","length","normalize","windowSize","numberOfData","mod","value","modulo","makeVisibleIndexRanges","ws","firstIndex","lastIndex","halfNumberOfAdjacent","Math","floor","leftSide","rightSide","leftRanges","rightRanges","useItemVisibilityStore","params","currentIndex","initialRange","current","newRanges"],"sources":["useItemVisibilityStore.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport type { ItemVisibilityStore, VisibleIndexRanges } from '../types';\n\nexport interface Parameters {\n currentIndex: number;\n numberOfData: number;\n windowSize: number;\n}\n\nclass SimpleItemVisibilityStore implements ItemVisibilityStore {\n\n private store: VisibleIndexRanges;\n\n constructor(initialValue: VisibleIndexRanges) {\n this.store = initialValue;\n }\n\n private listeners: Array<(ranges: VisibleIndexRanges) => void> = [];\n\n subscribe(listener: (ranges: VisibleIndexRanges) => void) {\n this.listeners.push(listener);\n\n listener(this.store);\n\n return () => {\n const index = this.listeners.indexOf(listener);\n this.listeners.splice(index, 1);\n };\n }\n\n dispatch(ranges: VisibleIndexRanges): void {\n this.store = ranges;\n for (const id in this.listeners) {\n const listener = this.listeners[id];\n listener?.(ranges);\n }\n }\n\n removeAllListeners(): void {\n this.listeners.splice(0, this.listeners.length);\n }\n\n}\n\nfunction normalize(windowSize: number, numberOfData: number): number {\n if (windowSize <= 0) {\n return numberOfData;\n }\n if (windowSize > 0 && windowSize % 2 === 0) {\n return windowSize + 1;\n }\n return windowSize;\n}\n\nfunction mod(value: number, modulo: number): number {\n return ((value % modulo) + modulo) % modulo;\n}\n\nfunction makeVisibleIndexRanges(numberOfData: number, windowSize: number, index: number): VisibleIndexRanges {\n const ws = normalize(windowSize, numberOfData);\n\n const firstIndex = 0;\n const lastIndex = numberOfData - 1;\n const halfNumberOfAdjacent = Math.floor(ws / 2);\n\n const leftSide = index - halfNumberOfAdjacent;\n const rightSide = index + halfNumberOfAdjacent;\n\n const leftRanges = leftSide >= 0\n ? [[leftSide, index]]\n : [[firstIndex, index], [mod(leftSide, numberOfData), lastIndex]];\n\n const rightRanges = rightSide < numberOfData\n ? [[index, rightSide]]\n : [[index, lastIndex], [firstIndex, mod(rightSide, numberOfData)]];\n\n // @ts-ignore\n return [\n ...leftRanges,\n ...rightRanges,\n ];\n}\n\nexport default function useItemVisibilityStore(params: Parameters): ItemVisibilityStore {\n const {\n currentIndex,\n numberOfData,\n windowSize,\n } = params;\n\n const [initialRange] = useState(() => makeVisibleIndexRanges(numberOfData, windowSize, currentIndex));\n const store = useRef(new SimpleItemVisibilityStore(initialRange)).current;\n\n useEffect(() => {\n const newRanges = makeVisibleIndexRanges(numberOfData, windowSize, currentIndex);\n\n store.dispatch(newRanges);\n }, [currentIndex, numberOfData, windowSize]);\n\n useEffect(() => {\n return () => {\n store.removeAllListeners();\n };\n }, []);\n\n return store;\n};\n"],"mappings":"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"}
1
+ {"version":3,"names":["useCallback","useEffect","useRef","useState","mod","SimpleItemVisibilityStore","constructor","initialValue","store","subscribe","listener","listeners","push","index","indexOf","splice","dispatch","ranges","id","removeAllListeners","length","normalize","windowSize","numberOfData","makeVisibleIndexRanges","ws","firstIndex","lastIndex","halfNumberOfAdjacent","Math","floor","leftSide","rightSide","leftRanges","rightRanges","useItemVisibilityStore","params","initialIndex","initialRange","current","onIndexChange","newIndex","newRanges"],"sources":["useItemVisibilityStore.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { mod } from '@fountain-ui/utils';\nimport type { ItemVisibilityStore, VisibleIndexRanges } from '../types';\n\nexport interface Parameters {\n initialIndex: number;\n numberOfData: number;\n windowSize: number;\n}\n\nexport interface OnIndexChange {\n (newIndex: number): void;\n}\n\nclass SimpleItemVisibilityStore implements ItemVisibilityStore {\n\n private store: VisibleIndexRanges;\n\n constructor(initialValue: VisibleIndexRanges) {\n this.store = initialValue;\n }\n\n private listeners: Array<(ranges: VisibleIndexRanges) => void> = [];\n\n subscribe(listener: (ranges: VisibleIndexRanges) => void) {\n this.listeners.push(listener);\n\n listener(this.store);\n\n return () => {\n const index = this.listeners.indexOf(listener);\n this.listeners.splice(index, 1);\n };\n }\n\n dispatch(ranges: VisibleIndexRanges): void {\n this.store = ranges;\n for (const id in this.listeners) {\n const listener = this.listeners[id];\n listener?.(ranges);\n }\n }\n\n removeAllListeners(): void {\n this.listeners.splice(0, this.listeners.length);\n }\n\n}\n\nfunction normalize(windowSize: number, numberOfData: number): number {\n if (windowSize <= 0) {\n return numberOfData;\n }\n if (windowSize > 0 && windowSize % 2 === 0) {\n return windowSize + 1;\n }\n return windowSize;\n}\n\nfunction makeVisibleIndexRanges(numberOfData: number, windowSize: number, index: number): VisibleIndexRanges {\n const ws = normalize(windowSize, numberOfData);\n\n const firstIndex = 0;\n const lastIndex = numberOfData - 1;\n const halfNumberOfAdjacent = Math.floor(ws / 2);\n\n const leftSide = index - halfNumberOfAdjacent;\n const rightSide = index + halfNumberOfAdjacent;\n\n const leftRanges = leftSide >= 0\n ? [[leftSide, index]]\n : [[firstIndex, index], [mod(leftSide, numberOfData), lastIndex]];\n\n const rightRanges = rightSide < numberOfData\n ? [[index, rightSide]]\n : [[index, lastIndex], [firstIndex, mod(rightSide, numberOfData)]];\n\n // @ts-ignore\n return [\n ...leftRanges,\n ...rightRanges,\n ];\n}\n\nexport default function useItemVisibilityStore(params: Parameters): [ItemVisibilityStore, OnIndexChange] {\n const {\n initialIndex,\n numberOfData,\n windowSize,\n } = params;\n\n const [initialRange] = useState(() => {\n return makeVisibleIndexRanges(numberOfData, windowSize, initialIndex);\n });\n\n const store = useRef(new SimpleItemVisibilityStore(initialRange)).current;\n\n const onIndexChange: OnIndexChange = useCallback((newIndex) => {\n const newRanges = makeVisibleIndexRanges(numberOfData, windowSize, newIndex);\n\n store.dispatch(newRanges);\n }, [numberOfData, windowSize]);\n\n useEffect(() => {\n return () => {\n store.removeAllListeners();\n };\n }, []);\n\n return [store, onIndexChange];\n};\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
- import { useCallback, useEffect, useMemo, useRef } from 'react';
2
- import { Animated, Platform } from 'react-native';
1
+ import { useCallback, useRef } from 'react';
3
2
 
4
3
  function directionToValue(itemWidth) {
5
4
  return function (direction) {
@@ -16,99 +15,153 @@ function directionToValue(itemWidth) {
16
15
  };
17
16
  }
18
17
 
19
- export default function usePagingAnimation(config) {
18
+ function toValueCompensator(itemWidth) {
19
+ return function (toValue, currentOffset) {
20
+ const remainder = Math.abs(currentOffset % itemWidth);
21
+ const halfOfItemWidth = Math.abs(itemWidth / 2);
22
+ const compensateVector = remainder > halfOfItemWidth ? remainder - itemWidth : remainder;
23
+ const direction = currentOffset > 0 ? -1 : 1;
24
+ return toValue + direction * compensateVector;
25
+ };
26
+ }
27
+
28
+ export default function usePagingAnimation(params) {
20
29
  const {
21
- controlledTx,
22
30
  createScrollAnimation,
23
- getCurrentIndex,
24
31
  itemWidth,
25
- lastIndex,
32
+ indexController,
26
33
  loop,
27
34
  numberOfData,
28
- offsetTx
29
- } = config;
30
- const animationRef = useRef(null);
35
+ offsetX,
36
+ translateX
37
+ } = params;
38
+ const {
39
+ getCurrentIndex,
40
+ lastIndex,
41
+ notifyOffsetHasChanged
42
+ } = indexController;
31
43
  const toValueRef = useRef(0);
32
- const globalInterpolation = useMemo(() => Animated.add(controlledTx, offsetTx), [controlledTx, offsetTx]);
33
- useEffect(() => {
34
- const subscriptionId = controlledTx.addListener(value => {
35
- const currentTx = value.value; // Prevent infinite loop
36
-
37
- if (currentTx !== 0) {
38
- const maxWidth = numberOfData * itemWidth;
44
+ const currentOffsetRef = useRef(0);
45
+ const isAnimatingRef = useRef(false);
46
+ const maxWidth = Math.abs(numberOfData * itemWidth);
47
+ const ensureOffsetBoundary = useCallback(offset => {
48
+ if (loop) {
49
+ const isCloseToEnd = Math.abs(offset) >= maxWidth - itemWidth;
39
50
 
40
- if (Math.abs(Math.round(currentTx)) === Math.round(maxWidth)) {
41
- // reset position
42
- controlledTx.setValue(0);
43
- }
51
+ if (isCloseToEnd) {
52
+ const signOfOffset = offset > 0 ? 1 : -1;
53
+ return offset + -signOfOffset * maxWidth;
44
54
  }
55
+ }
56
+
57
+ return offset % maxWidth;
58
+ }, [itemWidth, loop, maxWidth]);
59
+ const requireNewOffset = useCallback(newOffset => {
60
+ const nextOffset = ensureOffsetBoundary(newOffset);
61
+ currentOffsetRef.current = nextOffset;
62
+ offsetX.setValue(nextOffset);
63
+ toValueRef.current = 0;
64
+ translateX.setValue(0);
65
+ }, [ensureOffsetBoundary, offsetX, translateX]);
66
+ const interruptAnimation = useCallback(() => {
67
+ if (toValueRef.current === 0) {
68
+ // Performance optimization
69
+ return;
70
+ }
71
+
72
+ translateX.stopAnimation(lastValue => {
73
+ isAnimatingRef.current = false;
74
+ const prevOffset = currentOffsetRef.current;
75
+ const totalOffset = prevOffset + lastValue;
76
+ notifyOffsetHasChanged(totalOffset);
77
+ requireNewOffset(totalOffset);
45
78
  });
46
- return () => {
47
- controlledTx.removeListener(subscriptionId);
48
- };
49
- }, [numberOfData, itemWidth]);
79
+ }, [requireNewOffset, translateX]);
50
80
  const finalizeAnimation = useCallback(() => {
51
- const stopUnfinishedSnapAnimation = () => {
52
- if (animationRef.current) {
53
- var _animationRef$current;
81
+ isAnimatingRef.current = false;
82
+ const prevOffset = currentOffsetRef.current;
83
+ const toValue = toValueRef.current;
84
+ const totalOffset = prevOffset + toValue;
85
+ requireNewOffset(totalOffset);
86
+ }, [requireNewOffset]);
87
+ const startPagingAnimation = useCallback((type, config) => {
88
+ if (isAnimatingRef.current) {
89
+ return;
90
+ }
54
91
 
55
- (_animationRef$current = animationRef.current) === null || _animationRef$current === void 0 ? void 0 : _animationRef$current.stop();
56
- animationRef.current = null;
57
- }
92
+ const configWithDefaults = {
93
+ animated: true,
94
+ ...config
58
95
  };
96
+ const currentIndex = getCurrentIndex();
97
+ const getValueByDirectionOnAllAdjacentItemsVisible = directionToValue(itemWidth);
98
+ const compensateToValue = toValueCompensator(itemWidth);
59
99
 
60
- const resetBoundary = () => {
61
- controlledTx.setOffset(toValueRef.current);
62
- controlledTx.flattenOffset(); // FIXME: react-native-web bug maybe?
63
- // `AnimatedValue.flattenOffset()` does not trigger any event listener.
64
- // Accessing value directly via `_value` is dangerous but working on web (`useNativeDriver` always false).
65
- // So setting same value with `value.setValue(value._value)` will trigger event listener.
100
+ const getValueByDirectionalPagingOnLoopDisabled = _config => {
101
+ const {
102
+ direction,
103
+ isOriginatedFromGesture
104
+ } = _config;
66
105
 
67
- if (Platform.OS === 'web') {
68
- // @ts-ignore
69
- controlledTx.setValue(controlledTx._value);
106
+ if (currentIndex === 0 && direction === 'prev') {
107
+ return isOriginatedFromGesture ? getValueByDirectionOnAllAdjacentItemsVisible('stay') : -lastIndex * itemWidth; // last position
108
+ } else if (currentIndex === lastIndex && direction === 'next') {
109
+ return isOriginatedFromGesture ? getValueByDirectionOnAllAdjacentItemsVisible('stay') : lastIndex * itemWidth; // first position
70
110
  }
71
111
 
72
- offsetTx.setValue(0);
73
- toValueRef.current = 0;
112
+ return getValueByDirectionOnAllAdjacentItemsVisible(direction);
74
113
  };
75
114
 
76
- stopUnfinishedSnapAnimation();
77
- resetBoundary();
78
- }, [controlledTx]);
79
- const startAnimation = useCallback(function (direction) {
80
- let isGesture = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
81
- const getToValueByDirection = directionToValue(itemWidth);
82
- const currentIndex = getCurrentIndex();
115
+ const getValueByDirectionalPaging = _config => {
116
+ const _configWithDefaults = {
117
+ isOriginatedFromGesture: false,
118
+ ..._config
119
+ };
120
+ return loop ? getValueByDirectionOnAllAdjacentItemsVisible(_configWithDefaults.direction) : getValueByDirectionalPagingOnLoopDisabled(_configWithDefaults);
121
+ };
83
122
 
84
- const computeToValueOnNoLoop = () => {
85
- if (currentIndex === 0 && direction === 'prev') {
86
- return isGesture ? getToValueByDirection('stay') : -lastIndex * itemWidth; // last position
87
- } else if (currentIndex === lastIndex && direction === 'next') {
88
- return isGesture ? getToValueByDirection('stay') : lastIndex * itemWidth; // first position
123
+ const getValueByIndexPaging = _ref => {
124
+ let {
125
+ index
126
+ } = _ref;
127
+
128
+ if (index < 0 || index > lastIndex || index === currentIndex) {
129
+ // no animation if index is invalid or equals to current index
130
+ return 0;
89
131
  }
90
132
 
91
- return getToValueByDirection(direction);
133
+ const distance = Math.abs(currentIndex - index) * itemWidth;
134
+ const direction = index > currentIndex ? -1 : 1;
135
+ return distance * direction;
92
136
  };
93
137
 
94
- const toValue = loop ? getToValueByDirection(direction) : computeToValueOnNoLoop();
95
- const animation = createScrollAnimation(offsetTx, toValue);
96
- animationRef.current = animation;
138
+ const wantedToValue = type === 'directional' // @ts-ignore
139
+ ? getValueByDirectionalPaging(configWithDefaults) // @ts-ignore
140
+ : getValueByIndexPaging(configWithDefaults);
141
+ const toValue = compensateToValue(wantedToValue, currentOffsetRef.current);
97
142
  toValueRef.current = toValue;
98
- animation.start(_ref => {
99
- let {
100
- finished
101
- } = _ref;
143
+ isAnimatingRef.current = true;
102
144
 
103
- if (finished) {
104
- finalizeAnimation();
105
- }
106
- });
107
- }, [createScrollAnimation, getCurrentIndex, finalizeAnimation, itemWidth, lastIndex, loop]);
145
+ if (configWithDefaults.animated) {
146
+ const animation = createScrollAnimation(translateX, toValue);
147
+ animation.start(_ref2 => {
148
+ let {
149
+ finished
150
+ } = _ref2;
151
+
152
+ if (finished) {
153
+ finalizeAnimation();
154
+ }
155
+ });
156
+ } else {
157
+ finalizeAnimation();
158
+ }
159
+
160
+ notifyOffsetHasChanged(currentOffsetRef.current + toValue);
161
+ }, [createScrollAnimation, getCurrentIndex, finalizeAnimation, itemWidth, lastIndex, loop, notifyOffsetHasChanged]);
108
162
  return {
109
- globalInterpolation,
110
- finalizeAnimation,
111
- startAnimation
163
+ interruptAnimation,
164
+ startPagingAnimation
112
165
  };
113
166
  }
114
167
  ;