@fountain-ui/lab 2.0.0-beta.13 → 2.0.0-beta.16

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 (135) hide show
  1. package/build/commonjs/Carousel/Carousel.js +27 -30
  2. package/build/commonjs/Carousel/Carousel.js.map +1 -1
  3. package/build/commonjs/Carousel/animation/createDefaultScrollAnimation.js +2 -2
  4. package/build/commonjs/Carousel/animation/createDefaultScrollAnimation.js.map +1 -1
  5. package/build/commonjs/Carousel/animation/parallaxItemStyleFactory.js +2 -2
  6. package/build/commonjs/Carousel/animation/parallaxItemStyleFactory.js.map +1 -1
  7. package/build/commonjs/Carousel/components/ItemView.js +2 -2
  8. package/build/commonjs/Carousel/components/ItemView.js.map +1 -1
  9. package/build/commonjs/Carousel/components/ScrollViewGesture.js +6 -6
  10. package/build/commonjs/Carousel/components/ScrollViewGesture.js.map +1 -1
  11. package/build/commonjs/Carousel/{hooks → components}/useItemInterpolation.js +6 -4
  12. package/build/commonjs/Carousel/components/useItemInterpolation.js.map +1 -0
  13. package/build/commonjs/Carousel/hooks/index.js +0 -16
  14. package/build/commonjs/Carousel/hooks/index.js.map +1 -1
  15. package/build/commonjs/Carousel/hooks/useIndexController.js +23 -45
  16. package/build/commonjs/Carousel/hooks/useIndexController.js.map +1 -1
  17. package/build/commonjs/Carousel/hooks/useItemVisibilityStore.js +12 -12
  18. package/build/commonjs/Carousel/hooks/useItemVisibilityStore.js.map +1 -1
  19. package/build/commonjs/Carousel/hooks/usePagingAnimation.js +72 -56
  20. package/build/commonjs/Carousel/hooks/usePagingAnimation.js.map +1 -1
  21. package/build/commonjs/Carousel/tick.js +16 -0
  22. package/build/commonjs/Carousel/tick.js.map +1 -0
  23. package/build/commonjs/Carousel/types.js +1 -0
  24. package/build/commonjs/Carousel/types.js.map +1 -1
  25. package/build/commonjs/ViewPager/ChildrenMemoizedPage.js +53 -47
  26. package/build/commonjs/ViewPager/ChildrenMemoizedPage.js.map +1 -1
  27. package/build/commonjs/ViewPager/InternalContext.js +17 -0
  28. package/build/commonjs/ViewPager/InternalContext.js.map +1 -0
  29. package/build/commonjs/ViewPager/ViewPagerNative.js +40 -17
  30. package/build/commonjs/ViewPager/ViewPagerNative.js.map +1 -1
  31. package/build/commonjs/ViewPager/ViewPagerProps.js.map +1 -1
  32. package/build/commonjs/ViewPager/ViewPagerWeb.js +19 -8
  33. package/build/commonjs/ViewPager/ViewPagerWeb.js.map +1 -1
  34. package/build/commonjs/ViewPager/index.js.map +1 -1
  35. package/build/commonjs/ViewPager/types.js +6 -0
  36. package/build/commonjs/ViewPager/types.js.map +1 -0
  37. package/build/commonjs/ViewPager/usePageStore.js +35 -0
  38. package/build/commonjs/ViewPager/usePageStore.js.map +1 -0
  39. package/build/commonjs/ViewPager/utils.js.map +1 -1
  40. package/build/commonjs/ViewabilityTrackerView/measureViewability.js +6 -6
  41. package/build/commonjs/ViewabilityTrackerView/measureViewability.js.map +1 -1
  42. package/build/commonjs/hooks/useUnstableCollapsibleAppBar.js +1 -1
  43. package/build/commonjs/hooks/useUnstableCollapsibleAppBar.js.map +1 -1
  44. package/build/module/Carousel/Carousel.js +27 -32
  45. package/build/module/Carousel/Carousel.js.map +1 -1
  46. package/build/module/Carousel/animation/createDefaultScrollAnimation.js +2 -2
  47. package/build/module/Carousel/animation/createDefaultScrollAnimation.js.map +1 -1
  48. package/build/module/Carousel/animation/parallaxItemStyleFactory.js +2 -2
  49. package/build/module/Carousel/animation/parallaxItemStyleFactory.js.map +1 -1
  50. package/build/module/Carousel/components/ItemView.js +1 -1
  51. package/build/module/Carousel/components/ItemView.js.map +1 -1
  52. package/build/module/Carousel/components/ScrollViewGesture.js +6 -6
  53. package/build/module/Carousel/components/ScrollViewGesture.js.map +1 -1
  54. package/build/module/Carousel/{hooks → components}/useItemInterpolation.js +3 -3
  55. package/build/module/Carousel/components/useItemInterpolation.js.map +1 -0
  56. package/build/module/Carousel/hooks/index.js +0 -2
  57. package/build/module/Carousel/hooks/index.js.map +1 -1
  58. package/build/module/Carousel/hooks/useIndexController.js +23 -39
  59. package/build/module/Carousel/hooks/useIndexController.js.map +1 -1
  60. package/build/module/Carousel/hooks/useItemVisibilityStore.js +10 -11
  61. package/build/module/Carousel/hooks/useItemVisibilityStore.js.map +1 -1
  62. package/build/module/Carousel/hooks/usePagingAnimation.js +73 -56
  63. package/build/module/Carousel/hooks/usePagingAnimation.js.map +1 -1
  64. package/build/module/Carousel/tick.js +6 -0
  65. package/build/module/Carousel/tick.js.map +1 -0
  66. package/build/module/Carousel/types.js +1 -0
  67. package/build/module/Carousel/types.js.map +1 -1
  68. package/build/module/ViewPager/ChildrenMemoizedPage.js +53 -47
  69. package/build/module/ViewPager/ChildrenMemoizedPage.js.map +1 -1
  70. package/build/module/ViewPager/InternalContext.js +7 -0
  71. package/build/module/ViewPager/InternalContext.js.map +1 -0
  72. package/build/module/ViewPager/ViewPagerNative.js +38 -17
  73. package/build/module/ViewPager/ViewPagerNative.js.map +1 -1
  74. package/build/module/ViewPager/ViewPagerProps.js.map +1 -1
  75. package/build/module/ViewPager/ViewPagerWeb.js +16 -8
  76. package/build/module/ViewPager/ViewPagerWeb.js.map +1 -1
  77. package/build/module/ViewPager/index.js.map +1 -1
  78. package/build/module/ViewPager/types.js +2 -0
  79. package/build/module/ViewPager/types.js.map +1 -0
  80. package/build/module/ViewPager/usePageStore.js +25 -0
  81. package/build/module/ViewPager/usePageStore.js.map +1 -0
  82. package/build/module/ViewPager/utils.js.map +1 -1
  83. package/build/module/ViewabilityTrackerView/measureViewability.js +2 -2
  84. package/build/module/ViewabilityTrackerView/measureViewability.js.map +1 -1
  85. package/build/module/hooks/useUnstableCollapsibleAppBar.js +1 -1
  86. package/build/module/hooks/useUnstableCollapsibleAppBar.js.map +1 -1
  87. package/build/typescript/Carousel/components/ScrollViewGesture.d.ts +2 -2
  88. package/build/typescript/Carousel/{hooks → components}/useItemInterpolation.d.ts +0 -0
  89. package/build/typescript/Carousel/hooks/index.d.ts +0 -2
  90. package/build/typescript/Carousel/hooks/useIndexController.d.ts +0 -2
  91. package/build/typescript/Carousel/hooks/useItemVisibilityStore.d.ts +5 -2
  92. package/build/typescript/Carousel/hooks/usePagingAnimation.d.ts +5 -7
  93. package/build/typescript/Carousel/tick.d.ts +2 -0
  94. package/build/typescript/Carousel/types.d.ts +4 -2
  95. package/build/typescript/ViewPager/ChildrenMemoizedPage.d.ts +1 -1
  96. package/build/typescript/ViewPager/InternalContext.d.ts +7 -0
  97. package/build/typescript/ViewPager/ViewPagerNative.d.ts +2 -2
  98. package/build/typescript/ViewPager/ViewPagerProps.d.ts +4 -22
  99. package/build/typescript/ViewPager/ViewPagerWeb.d.ts +2 -2
  100. package/build/typescript/ViewPager/index.d.ts +2 -1
  101. package/build/typescript/ViewPager/types.d.ts +19 -0
  102. package/build/typescript/ViewPager/usePageStore.d.ts +2 -0
  103. package/build/typescript/ViewPager/utils.d.ts +1 -1
  104. package/package.json +3 -3
  105. package/src/Carousel/Carousel.tsx +25 -34
  106. package/src/Carousel/animation/createDefaultScrollAnimation.ts +2 -2
  107. package/src/Carousel/animation/parallaxItemStyleFactory.ts +1 -1
  108. package/src/Carousel/components/ItemView.tsx +1 -1
  109. package/src/Carousel/components/ScrollViewGesture.tsx +8 -7
  110. package/src/Carousel/{hooks → components}/useItemInterpolation.ts +3 -3
  111. package/src/Carousel/hooks/index.ts +0 -2
  112. package/src/Carousel/hooks/useIndexController.tsx +25 -47
  113. package/src/Carousel/hooks/useItemVisibilityStore.ts +17 -13
  114. package/src/Carousel/hooks/usePagingAnimation.ts +104 -64
  115. package/src/Carousel/tick.ts +6 -0
  116. package/src/Carousel/types.ts +6 -2
  117. package/src/ViewPager/ChildrenMemoizedPage.tsx +53 -50
  118. package/src/ViewPager/InternalContext.ts +13 -0
  119. package/src/ViewPager/ViewPagerNative.tsx +53 -39
  120. package/src/ViewPager/ViewPagerProps.ts +4 -27
  121. package/src/ViewPager/ViewPagerWeb.tsx +23 -18
  122. package/src/ViewPager/index.ts +2 -1
  123. package/src/ViewPager/types.ts +24 -0
  124. package/src/ViewPager/usePageStore.ts +30 -0
  125. package/src/ViewPager/utils.tsx +1 -1
  126. package/src/ViewabilityTrackerView/measureViewability.ts +1 -3
  127. package/src/hooks/useUnstableCollapsibleAppBar.ts +1 -1
  128. package/build/commonjs/Carousel/hooks/useDimensionChangeReaction.js +0 -23
  129. package/build/commonjs/Carousel/hooks/useDimensionChangeReaction.js.map +0 -1
  130. package/build/commonjs/Carousel/hooks/useItemInterpolation.js.map +0 -1
  131. package/build/module/Carousel/hooks/useDimensionChangeReaction.js +0 -14
  132. package/build/module/Carousel/hooks/useDimensionChangeReaction.js.map +0 -1
  133. package/build/module/Carousel/hooks/useItemInterpolation.js.map +0 -1
  134. package/build/typescript/Carousel/hooks/useDimensionChangeReaction.d.ts +0 -7
  135. package/src/Carousel/hooks/useDimensionChangeReaction.ts +0 -25
@@ -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,73 +15,89 @@ function directionToValue(itemWidth) {
16
15
  };
17
16
  }
18
17
 
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
+
19
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
35
+ offsetX,
36
+ translateX
29
37
  } = params;
30
- const animationRef = useRef(null);
38
+ const {
39
+ getCurrentIndex,
40
+ lastIndex,
41
+ notifyAnimationState,
42
+ notifyOffsetHasChanged
43
+ } = indexController;
31
44
  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
45
+ const currentOffsetRef = useRef(0);
46
+ const isAnimatingRef = useRef(false);
47
+ const maxWidth = Math.abs(numberOfData * itemWidth);
48
+ const ensureOffsetBoundary = useCallback(offset => {
49
+ if (loop) {
50
+ const isCloseToEnd = Math.abs(offset) >= maxWidth - itemWidth;
51
+
52
+ if (isCloseToEnd) {
53
+ const signOfOffset = offset > 0 ? 1 : -1;
54
+ return offset + -signOfOffset * maxWidth;
55
+ }
56
+ }
36
57
 
37
- if (currentTx !== 0) {
38
- const maxWidth = numberOfData * itemWidth;
58
+ return offset % maxWidth;
59
+ }, [itemWidth, loop, maxWidth]);
60
+ const requireNewOffset = useCallback(newOffset => {
61
+ const nextOffset = ensureOffsetBoundary(newOffset);
62
+ currentOffsetRef.current = nextOffset;
63
+ offsetX.setValue(nextOffset);
64
+ toValueRef.current = 0;
65
+ translateX.setValue(0);
66
+ }, [ensureOffsetBoundary, offsetX, translateX]);
67
+ const interruptAnimation = useCallback(() => {
68
+ if (!isAnimatingRef.current) {
69
+ return;
70
+ }
39
71
 
40
- if (Math.abs(Math.round(currentTx)) === Math.round(maxWidth)) {
41
- // reset position
42
- controlledTx.setValue(0);
43
- }
44
- }
72
+ translateX.stopAnimation(lastValue => {
73
+ isAnimatingRef.current = false;
74
+ const prevOffset = currentOffsetRef.current;
75
+ const totalOffset = prevOffset + lastValue;
76
+ notifyOffsetHasChanged(totalOffset);
77
+ notifyAnimationState('interrupted');
78
+ requireNewOffset(totalOffset);
45
79
  });
46
- return () => {
47
- controlledTx.removeListener(subscriptionId);
48
- };
49
- }, [numberOfData, itemWidth]);
80
+ }, [requireNewOffset, translateX]);
50
81
  const finalizeAnimation = useCallback(() => {
51
- const stopUnfinishedSnapAnimation = () => {
52
- if (animationRef.current) {
53
- var _animationRef$current;
54
-
55
- (_animationRef$current = animationRef.current) === null || _animationRef$current === void 0 ? void 0 : _animationRef$current.stop();
56
- animationRef.current = null;
57
- }
58
- };
59
-
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.
66
-
67
- if (Platform.OS === 'web') {
68
- // @ts-ignore
69
- controlledTx.setValue(controlledTx._value);
70
- }
71
-
72
- offsetTx.setValue(0);
73
- toValueRef.current = 0;
74
- };
75
-
76
- stopUnfinishedSnapAnimation();
77
- resetBoundary();
78
- }, [controlledTx]);
82
+ notifyAnimationState('finished');
83
+ isAnimatingRef.current = false;
84
+ const prevOffset = currentOffsetRef.current;
85
+ const toValue = toValueRef.current;
86
+ const totalOffset = prevOffset + toValue;
87
+ requireNewOffset(totalOffset);
88
+ }, [notifyAnimationState, requireNewOffset]);
79
89
  const startPagingAnimation = useCallback((type, config) => {
90
+ if (isAnimatingRef.current) {
91
+ return;
92
+ }
93
+
80
94
  const configWithDefaults = {
81
95
  animated: true,
82
96
  ...config
83
97
  };
84
98
  const currentIndex = getCurrentIndex();
85
99
  const getValueByDirectionOnAllAdjacentItemsVisible = directionToValue(itemWidth);
100
+ const compensateToValue = toValueCompensator(itemWidth);
86
101
 
87
102
  const getValueByDirectionalPagingOnLoopDisabled = _config => {
88
103
  const {
@@ -122,14 +137,16 @@ export default function usePagingAnimation(params) {
122
137
  return distance * direction;
123
138
  };
124
139
 
125
- const toValue = type === 'directional' // @ts-ignore
140
+ const wantedToValue = type === 'directional' // @ts-ignore
126
141
  ? getValueByDirectionalPaging(configWithDefaults) // @ts-ignore
127
142
  : getValueByIndexPaging(configWithDefaults);
143
+ const toValue = compensateToValue(wantedToValue, currentOffsetRef.current);
128
144
  toValueRef.current = toValue;
145
+ isAnimatingRef.current = true;
146
+ notifyOffsetHasChanged(currentOffsetRef.current + toValue);
129
147
 
130
148
  if (configWithDefaults.animated) {
131
- const animation = createScrollAnimation(offsetTx, toValue);
132
- animationRef.current = animation;
149
+ const animation = createScrollAnimation(translateX, toValue);
133
150
  animation.start(_ref2 => {
134
151
  let {
135
152
  finished
@@ -139,13 +156,13 @@ export default function usePagingAnimation(params) {
139
156
  finalizeAnimation();
140
157
  }
141
158
  });
159
+ notifyAnimationState('started');
142
160
  } else {
143
161
  finalizeAnimation();
144
162
  }
145
- }, [createScrollAnimation, getCurrentIndex, finalizeAnimation, itemWidth, lastIndex, loop]);
163
+ }, [createScrollAnimation, getCurrentIndex, finalizeAnimation, itemWidth, lastIndex, loop, notifyAnimationState, notifyOffsetHasChanged]);
146
164
  return {
147
- globalInterpolation,
148
- finalizeAnimation,
165
+ interruptAnimation,
149
166
  startPagingAnimation
150
167
  };
151
168
  }
@@ -1 +1 @@
1
- {"version":3,"names":["useCallback","useEffect","useMemo","useRef","Animated","Platform","directionToValue","itemWidth","direction","usePagingAnimation","params","controlledTx","createScrollAnimation","getCurrentIndex","lastIndex","loop","numberOfData","offsetTx","animationRef","toValueRef","globalInterpolation","add","subscriptionId","addListener","value","currentTx","maxWidth","Math","abs","round","setValue","removeListener","finalizeAnimation","stopUnfinishedSnapAnimation","current","stop","resetBoundary","setOffset","flattenOffset","OS","_value","startPagingAnimation","type","config","configWithDefaults","animated","currentIndex","getValueByDirectionOnAllAdjacentItemsVisible","getValueByDirectionalPagingOnLoopDisabled","_config","isOriginatedFromGesture","getValueByDirectionalPaging","_configWithDefaults","getValueByIndexPaging","index","distance","toValue","animation","start","finished"],"sources":["usePagingAnimation.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { Animated, Platform } from 'react-native';\nimport type {\n CreateScrollAnimation,\n DirectionalPagingAnimationConfig,\n GetCurrentIndex,\n IndexPagingAnimationConfig,\n PagingAnimationConfig,\n PagingAnimationType,\n PagingDirection,\n StartPagingAnimation,\n} from '../types';\n\nexport interface PagingAnimationParameters {\n controlledTx: Animated.Value;\n createScrollAnimation: CreateScrollAnimation;\n getCurrentIndex: GetCurrentIndex;\n itemWidth: number;\n lastIndex: number;\n loop: boolean;\n numberOfData: number;\n offsetTx: Animated.Value;\n}\n\nexport interface UsePagingAnimation {\n finalizeAnimation: () => void;\n globalInterpolation: Animated.AnimatedInterpolation;\n startPagingAnimation: StartPagingAnimation;\n}\n\nfunction directionToValue(itemWidth: number) {\n return function (direction: PagingDirection): number {\n switch (direction) {\n case 'next':\n return -itemWidth;\n case 'prev':\n return itemWidth;\n case 'stay':\n return 0;\n }\n };\n}\n\nexport default function usePagingAnimation(params: PagingAnimationParameters): UsePagingAnimation {\n const {\n controlledTx,\n createScrollAnimation,\n getCurrentIndex,\n itemWidth,\n lastIndex,\n loop,\n numberOfData,\n offsetTx,\n } = params;\n\n const animationRef = useRef<Animated.CompositeAnimation | null>(null);\n const toValueRef = useRef<number>(0);\n\n const globalInterpolation = useMemo(\n () => Animated.add(controlledTx, offsetTx),\n [controlledTx, offsetTx],\n );\n\n useEffect(() => {\n const subscriptionId = controlledTx.addListener((value) => {\n const currentTx = value.value;\n\n // Prevent infinite loop\n if (currentTx !== 0) {\n const maxWidth = numberOfData * itemWidth;\n\n if (Math.abs(Math.round(currentTx)) === Math.round(maxWidth)) {\n // reset position\n controlledTx.setValue(0);\n }\n }\n });\n\n return () => {\n controlledTx.removeListener(subscriptionId);\n };\n }, [numberOfData, itemWidth]);\n\n const finalizeAnimation = useCallback(() => {\n const stopUnfinishedSnapAnimation = () => {\n if (animationRef.current) {\n animationRef.current?.stop();\n animationRef.current = null;\n }\n };\n\n const resetBoundary = () => {\n controlledTx.setOffset(toValueRef.current);\n controlledTx.flattenOffset();\n\n // FIXME: react-native-web bug maybe?\n // `AnimatedValue.flattenOffset()` does not trigger any event listener.\n // Accessing value directly via `_value` is dangerous but working on web (`useNativeDriver` always false).\n // So setting same value with `value.setValue(value._value)` will trigger event listener.\n if (Platform.OS === 'web') {\n // @ts-ignore\n controlledTx.setValue(controlledTx._value);\n }\n\n offsetTx.setValue(0);\n toValueRef.current = 0;\n };\n\n stopUnfinishedSnapAnimation();\n\n resetBoundary();\n }, [controlledTx]);\n\n const startPagingAnimation = useCallback((type: PagingAnimationType, config: PagingAnimationConfig) => {\n const configWithDefaults: PagingAnimationConfig = {\n animated: true,\n ...config,\n };\n\n const currentIndex = getCurrentIndex();\n\n const getValueByDirectionOnAllAdjacentItemsVisible = directionToValue(itemWidth);\n\n const getValueByDirectionalPagingOnLoopDisabled = (_config: DirectionalPagingAnimationConfig): number => {\n const { direction, isOriginatedFromGesture } = _config;\n\n if (currentIndex === 0 && direction === 'prev') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : -lastIndex * itemWidth; // last position\n } else if (currentIndex === lastIndex && direction === 'next') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : lastIndex * itemWidth; // first position\n }\n return getValueByDirectionOnAllAdjacentItemsVisible(direction);\n };\n\n const getValueByDirectionalPaging = (_config: DirectionalPagingAnimationConfig): number => {\n const _configWithDefaults: DirectionalPagingAnimationConfig = {\n isOriginatedFromGesture: false,\n ..._config,\n };\n\n return loop\n ? getValueByDirectionOnAllAdjacentItemsVisible(_configWithDefaults.direction)\n : getValueByDirectionalPagingOnLoopDisabled(_configWithDefaults);\n };\n\n const getValueByIndexPaging = ({ index }: IndexPagingAnimationConfig): number => {\n if (index < 0 || index > lastIndex || index === currentIndex) {\n // no animation if index is invalid or equals to current index\n return 0;\n }\n\n const distance = Math.abs(currentIndex - index) * itemWidth;\n const direction = index > currentIndex ? -1 : 1;\n\n return distance * direction;\n };\n\n const toValue = type === 'directional'\n // @ts-ignore\n ? getValueByDirectionalPaging(configWithDefaults)\n // @ts-ignore\n : getValueByIndexPaging(configWithDefaults);\n\n toValueRef.current = toValue;\n\n if (configWithDefaults.animated) {\n const animation = createScrollAnimation(offsetTx, toValue);\n animationRef.current = animation;\n animation.start(({ finished }) => {\n if (finished) {\n finalizeAnimation();\n }\n });\n } else {\n finalizeAnimation();\n }\n }, [\n createScrollAnimation,\n getCurrentIndex,\n finalizeAnimation,\n itemWidth,\n lastIndex,\n loop,\n ]);\n\n return {\n globalInterpolation,\n finalizeAnimation,\n startPagingAnimation,\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"names":["useCallback","useRef","directionToValue","itemWidth","direction","toValueCompensator","toValue","currentOffset","remainder","Math","abs","halfOfItemWidth","compensateVector","usePagingAnimation","params","createScrollAnimation","indexController","loop","numberOfData","offsetX","translateX","getCurrentIndex","lastIndex","notifyAnimationState","notifyOffsetHasChanged","toValueRef","currentOffsetRef","isAnimatingRef","maxWidth","ensureOffsetBoundary","offset","isCloseToEnd","signOfOffset","requireNewOffset","newOffset","nextOffset","current","setValue","interruptAnimation","stopAnimation","lastValue","prevOffset","totalOffset","finalizeAnimation","startPagingAnimation","type","config","configWithDefaults","animated","currentIndex","getValueByDirectionOnAllAdjacentItemsVisible","compensateToValue","getValueByDirectionalPagingOnLoopDisabled","_config","isOriginatedFromGesture","getValueByDirectionalPaging","_configWithDefaults","getValueByIndexPaging","index","distance","wantedToValue","animation","start","finished"],"sources":["usePagingAnimation.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\nimport { Animated } from 'react-native';\nimport type {\n CreateScrollAnimation,\n DirectionalPagingAnimationConfig,\n IndexController,\n IndexPagingAnimationConfig,\n PagingAnimationConfig,\n PagingAnimationType,\n PagingDirection,\n StartPagingAnimation,\n} from '../types';\n\nexport interface PagingAnimationParameters {\n createScrollAnimation: CreateScrollAnimation;\n itemWidth: number;\n indexController: IndexController;\n loop: boolean;\n numberOfData: number;\n offsetX: Animated.Value;\n translateX: Animated.Value;\n}\n\nexport interface UsePagingAnimation {\n interruptAnimation: () => void;\n startPagingAnimation: StartPagingAnimation;\n}\n\nfunction directionToValue(itemWidth: number) {\n return function (direction: PagingDirection): number {\n switch (direction) {\n case 'next':\n return -itemWidth;\n case 'prev':\n return itemWidth;\n case 'stay':\n return 0;\n }\n };\n}\n\nfunction toValueCompensator(itemWidth: number) {\n return function (toValue: number, currentOffset: number): number {\n const remainder = Math.abs(currentOffset % itemWidth);\n\n const halfOfItemWidth = Math.abs(itemWidth / 2);\n const compensateVector = remainder > halfOfItemWidth\n ? remainder - itemWidth\n : remainder;\n\n const direction = currentOffset > 0 ? -1 : 1;\n\n return toValue + (direction * compensateVector);\n };\n}\n\nexport default function usePagingAnimation(params: PagingAnimationParameters): UsePagingAnimation {\n const {\n createScrollAnimation,\n itemWidth,\n indexController,\n loop,\n numberOfData,\n offsetX,\n translateX,\n } = params;\n\n const {\n getCurrentIndex,\n lastIndex,\n notifyAnimationState,\n notifyOffsetHasChanged,\n } = indexController;\n\n const toValueRef = useRef<number>(0);\n const currentOffsetRef = useRef<number>(0);\n\n const isAnimatingRef = useRef<boolean>(false);\n\n const maxWidth = Math.abs(numberOfData * itemWidth);\n\n const ensureOffsetBoundary: (offset: number) => number = useCallback((offset: number) => {\n if (loop) {\n const isCloseToEnd = Math.abs(offset) >= (maxWidth - itemWidth);\n if (isCloseToEnd) {\n const signOfOffset = offset > 0 ? 1 : -1;\n return offset + (-signOfOffset * maxWidth);\n }\n }\n\n return offset % maxWidth;\n }, [itemWidth, loop, maxWidth]);\n\n const requireNewOffset = useCallback((newOffset: number) => {\n const nextOffset = ensureOffsetBoundary(newOffset);\n\n currentOffsetRef.current = nextOffset;\n offsetX.setValue(nextOffset);\n\n toValueRef.current = 0;\n translateX.setValue(0);\n }, [\n ensureOffsetBoundary,\n offsetX,\n translateX,\n ]);\n\n const interruptAnimation = useCallback(() => {\n if (!isAnimatingRef.current) {\n return;\n }\n\n translateX.stopAnimation(lastValue => {\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const totalOffset = prevOffset + lastValue;\n\n notifyOffsetHasChanged(totalOffset);\n notifyAnimationState('interrupted');\n\n requireNewOffset(totalOffset);\n });\n }, [requireNewOffset, translateX]);\n\n const finalizeAnimation = useCallback(() => {\n notifyAnimationState('finished');\n\n isAnimatingRef.current = false;\n\n const prevOffset = currentOffsetRef.current;\n const toValue = toValueRef.current;\n const totalOffset = prevOffset + toValue;\n\n requireNewOffset(totalOffset);\n }, [\n notifyAnimationState,\n requireNewOffset,\n ]);\n\n const startPagingAnimation = useCallback((type: PagingAnimationType, config: PagingAnimationConfig) => {\n if (isAnimatingRef.current) {\n return;\n }\n\n const configWithDefaults: PagingAnimationConfig = {\n animated: true,\n ...config,\n };\n\n const currentIndex = getCurrentIndex();\n\n const getValueByDirectionOnAllAdjacentItemsVisible = directionToValue(itemWidth);\n const compensateToValue = toValueCompensator(itemWidth);\n\n const getValueByDirectionalPagingOnLoopDisabled = (_config: DirectionalPagingAnimationConfig): number => {\n const { direction, isOriginatedFromGesture } = _config;\n\n if (currentIndex === 0 && direction === 'prev') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : -lastIndex * itemWidth; // last position\n } else if (currentIndex === lastIndex && direction === 'next') {\n return isOriginatedFromGesture\n ? getValueByDirectionOnAllAdjacentItemsVisible('stay')\n : lastIndex * itemWidth; // first position\n }\n return getValueByDirectionOnAllAdjacentItemsVisible(direction);\n };\n\n const getValueByDirectionalPaging = (_config: DirectionalPagingAnimationConfig): number => {\n const _configWithDefaults: DirectionalPagingAnimationConfig = {\n isOriginatedFromGesture: false,\n ..._config,\n };\n\n return loop\n ? getValueByDirectionOnAllAdjacentItemsVisible(_configWithDefaults.direction)\n : getValueByDirectionalPagingOnLoopDisabled(_configWithDefaults);\n };\n\n const getValueByIndexPaging = ({ index }: IndexPagingAnimationConfig): number => {\n if (index < 0 || index > lastIndex || index === currentIndex) {\n // no animation if index is invalid or equals to current index\n return 0;\n }\n\n const distance = Math.abs(currentIndex - index) * itemWidth;\n const direction = index > currentIndex ? -1 : 1;\n\n return distance * direction;\n };\n\n const wantedToValue = type === 'directional'\n // @ts-ignore\n ? getValueByDirectionalPaging(configWithDefaults)\n // @ts-ignore\n : getValueByIndexPaging(configWithDefaults);\n\n const toValue = compensateToValue(wantedToValue, currentOffsetRef.current);\n\n toValueRef.current = toValue;\n isAnimatingRef.current = true;\n\n notifyOffsetHasChanged(currentOffsetRef.current + toValue);\n\n if (configWithDefaults.animated) {\n const animation = createScrollAnimation(translateX, toValue);\n\n animation.start(({ finished }) => {\n if (finished) {\n finalizeAnimation();\n }\n });\n\n notifyAnimationState('started');\n } else {\n finalizeAnimation();\n }\n }, [\n createScrollAnimation,\n getCurrentIndex,\n finalizeAnimation,\n itemWidth,\n lastIndex,\n loop,\n notifyAnimationState,\n notifyOffsetHasChanged,\n ]);\n\n return {\n interruptAnimation,\n startPagingAnimation,\n };\n};\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { logger } from '@fountain-ui/utils';
2
+ export default logger('Carousel', {
3
+ enabled: __DEV__,
4
+ format: 'diff'
5
+ });
6
+ //# sourceMappingURL=tick.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["logger","enabled","__DEV__","format"],"sources":["tick.ts"],"sourcesContent":["import { logger } from '@fountain-ui/utils';\n\nexport default logger('Carousel', {\n enabled: __DEV__,\n format: 'diff',\n});\n"],"mappings":"AAAA,SAASA,MAAT,QAAuB,oBAAvB;AAEA,eAAeA,MAAM,CAAC,UAAD,EAAa;EAC9BC,OAAO,EAAEC,OADqB;EAE9BC,MAAM,EAAE;AAFsB,CAAb,CAArB"}
@@ -1,3 +1,4 @@
1
1
  const directions = ['next', 'prev', 'stay'];
2
+ const animationStates = ['started', 'finished', 'interrupted'];
2
3
  export {};
3
4
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["directions"],"sources":["types.ts"],"sourcesContent":["import type { ReactElement } from 'react';\nimport type { Animated, ViewProps } from 'react-native';\n\nconst directions = ['next', 'prev', 'stay'] as const;\n\nexport type PagingDirection = (typeof directions)[number];\n\nexport type ItemHeight = number | 'auto';\n\nexport interface RenderItem<T> {\n (info: { item: T, index: number, interpolation: Animated.AnimatedInterpolation }): ReactElement | null;\n}\n\nexport interface CreateScrollAnimation {\n (aValue: Animated.AnimatedValue, toValue: number): Animated.CompositeAnimation;\n}\n\nexport interface CreateItemStyle {\n (itemInterpolation: Animated.AnimatedInterpolation, itemWidth: number): Animated.AnimatedProps<ViewProps['style']>;\n}\n\nexport interface GetCurrentIndex {\n (): number;\n}\n\nexport interface IndexController {\n currentIndex: number;\n getCurrentIndex: GetCurrentIndex;\n lastIndex: number;\n monitorElement: ReactElement;\n}\n\nexport type PagingAnimationType = 'directional' | 'index';\n\nexport interface BasePagingAnimationConfig {\n animated?: boolean;\n}\n\nexport interface DirectionalPagingAnimationConfig extends BasePagingAnimationConfig {\n direction: PagingDirection;\n isOriginatedFromGesture?: boolean;\n}\n\nexport interface IndexPagingAnimationConfig extends BasePagingAnimationConfig {\n index: number;\n}\n\nexport type PagingAnimationConfig = DirectionalPagingAnimationConfig | IndexPagingAnimationConfig;\n\nexport interface StartPagingAnimation {\n (type: PagingAnimationType, config: PagingAnimationConfig): void;\n}\n\nexport type VisibleIndexRanges = Array<[number, number]>;\n\nexport interface StoreSubscription {\n (): void;\n}\n\nexport interface ItemVisibilityStore {\n dispatch: (ranges: VisibleIndexRanges) => void;\n subscribe: (listener: (ranges: VisibleIndexRanges) => void) => StoreSubscription;\n removeAllListeners: () => void;\n}\n\nexport interface AutoplayController {\n pause: () => void;\n resume: () => void;\n}\n\nexport interface ScrollToOption {\n index: number;\n animated?: boolean;\n}\n\nexport interface CarouselInstance {\n /**\n * Get current visible item index.\n */\n getCurrentIndex: GetCurrentIndex;\n\n /**\n * Scroll to next visible item.\n */\n next: () => void;\n\n /**\n * Scroll to previous visible item.\n */\n prev: () => void;\n\n /**\n * Scroll to desired indexed item.\n * Invalid index is ignored.\n */\n scrollTo: (option: ScrollToOption) => void;\n}\n"],"mappings":"AAGA,MAAMA,UAAU,GAAG,CAAC,MAAD,EAAS,MAAT,EAAiB,MAAjB,CAAnB"}
1
+ {"version":3,"names":["directions","animationStates"],"sources":["types.ts"],"sourcesContent":["import type { ReactElement } from 'react';\nimport type { Animated, ViewProps } from 'react-native';\n\nconst directions = ['next', 'prev', 'stay'] as const;\n\nexport type PagingDirection = (typeof directions)[number];\n\nconst animationStates = ['started', 'finished', 'interrupted'] as const;\n\nexport type AnimationState = (typeof animationStates)[number];\n\nexport type ItemHeight = number | 'auto';\n\nexport interface RenderItem<T> {\n (info: { item: T, index: number, interpolation: Animated.AnimatedInterpolation }): ReactElement | null;\n}\n\nexport interface CreateScrollAnimation {\n (aValue: Animated.AnimatedValue, toValue: number): Animated.CompositeAnimation;\n}\n\nexport interface CreateItemStyle {\n (itemInterpolation: Animated.AnimatedInterpolation, itemWidth: number): Animated.AnimatedProps<ViewProps['style']>;\n}\n\nexport interface GetCurrentIndex {\n (): number;\n}\n\nexport interface IndexController {\n getCurrentIndex: GetCurrentIndex;\n lastIndex: number;\n notifyAnimationState: (state: AnimationState) => void;\n notifyOffsetHasChanged: (offset: number) => void;\n}\n\nexport type PagingAnimationType = 'directional' | 'index';\n\nexport interface BasePagingAnimationConfig {\n animated?: boolean;\n}\n\nexport interface DirectionalPagingAnimationConfig extends BasePagingAnimationConfig {\n direction: PagingDirection;\n isOriginatedFromGesture?: boolean;\n}\n\nexport interface IndexPagingAnimationConfig extends BasePagingAnimationConfig {\n index: number;\n}\n\nexport type PagingAnimationConfig = DirectionalPagingAnimationConfig | IndexPagingAnimationConfig;\n\nexport interface StartPagingAnimation {\n (type: PagingAnimationType, config: PagingAnimationConfig): void;\n}\n\nexport type VisibleIndexRanges = Array<[number, number]>;\n\nexport interface StoreSubscription {\n (): void;\n}\n\nexport interface ItemVisibilityStore {\n dispatch: (ranges: VisibleIndexRanges) => void;\n subscribe: (listener: (ranges: VisibleIndexRanges) => void) => StoreSubscription;\n removeAllListeners: () => void;\n}\n\nexport interface AutoplayController {\n pause: () => void;\n resume: () => void;\n}\n\nexport interface ScrollToOption {\n index: number;\n animated?: boolean;\n}\n\nexport interface CarouselInstance {\n /**\n * Get current visible item index.\n */\n getCurrentIndex: GetCurrentIndex;\n\n /**\n * Scroll to next visible item.\n */\n next: () => void;\n\n /**\n * Scroll to previous visible item.\n */\n prev: () => void;\n\n /**\n * Scroll to desired indexed item.\n * Invalid index is ignored.\n */\n scrollTo: (option: ScrollToOption) => void;\n}\n"],"mappings":"AAGA,MAAMA,UAAU,GAAG,CAAC,MAAD,EAAS,MAAT,EAAiB,MAAjB,CAAnB;AAIA,MAAMC,eAAe,GAAG,CAAC,SAAD,EAAY,UAAZ,EAAwB,aAAxB,CAAxB"}
@@ -1,8 +1,8 @@
1
- import React, { memo, useMemo, useState } from 'react';
1
+ import React, { memo, useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState } from 'react';
2
2
  import { Platform, View } from 'react-native';
3
- import { runOnJS, useAnimatedReaction } from 'react-native-reanimated';
4
3
  import { StyleSheet } from '@fountain-ui/core';
5
4
  import PageStateContext from './PageStateContext';
5
+ import InternalContext from './InternalContext';
6
6
  const styles = StyleSheet.create({
7
7
  fill: {
8
8
  width: '100%',
@@ -16,66 +16,72 @@ const styles = StyleSheet.create({
16
16
  function Page(props) {
17
17
  const {
18
18
  index,
19
+ initialPage,
19
20
  children,
20
21
  loading,
21
- offscreenPageRerenderLimit,
22
- sharedIndex
22
+ offscreenPageRerenderLimit
23
23
  } = props;
24
-
25
- const assumeInitialPageState = () => {
26
- const activeIndex = sharedIndex.value;
24
+ const {
25
+ pageStore
26
+ } = useContext(InternalContext);
27
+ const computePageDescription = useCallback(page => {
28
+ const activeIndex = page;
27
29
  const isActive = index === activeIndex;
30
+ const shouldRerender = index >= activeIndex - offscreenPageRerenderLimit && index <= activeIndex + offscreenPageRerenderLimit;
31
+ const becomeNeighbor = shouldRerender && !isActive;
32
+ return {
33
+ isActive,
34
+ becomeNeighbor
35
+ };
36
+ }, [index]);
37
+ const [initialState] = useState(() => {
38
+ const {
39
+ isActive,
40
+ becomeNeighbor
41
+ } = computePageDescription(initialPage);
28
42
 
29
43
  if (loading === 'eager') {
30
44
  return {
31
- isActive,
32
- isLoaded: true
45
+ active: isActive,
46
+ loaded: true
33
47
  };
34
48
  }
35
49
 
36
- const isLoaded = index >= activeIndex - offscreenPageRerenderLimit && index <= activeIndex + offscreenPageRerenderLimit;
37
50
  return {
38
- isActive,
39
- isLoaded
51
+ active: isActive,
52
+ loaded: isActive || becomeNeighbor
40
53
  };
41
- };
42
-
43
- const [pageState, setPageState] = useState(assumeInitialPageState);
44
- const content = pageState.isLoaded ? children : null;
54
+ }); // `Bailing out of a state update` is not working as expected.
45
55
 
46
- const onActiveStateChange = isActive => {
47
- setPageState(prevState => ({ ...prevState,
48
- isActive,
49
- isLoaded: isActive || prevState.isLoaded
50
- }));
51
- };
52
-
53
- const onBecomeNeighbor = () => {
54
- setPageState(prevState => ({ ...prevState,
55
- isLoaded: true
56
- }));
57
- };
56
+ const pageStateRef = useRef(initialState);
57
+ const [, forceRender] = useReducer(s => s + 1, 0);
58
+ const {
59
+ active,
60
+ loaded
61
+ } = pageStateRef.current;
62
+ const content = loaded ? children : null;
63
+ useEffect(() => {
64
+ return pageStore.subscribe(newPage => {
65
+ const {
66
+ isActive,
67
+ becomeNeighbor
68
+ } = computePageDescription(newPage);
69
+ const currentState = pageStateRef.current;
70
+ const newState = {
71
+ active: isActive,
72
+ loaded: isActive || becomeNeighbor ? true : currentState.loaded
73
+ };
58
74
 
59
- useAnimatedReaction(() => {
60
- const activeIndex = sharedIndex.value;
61
- const isActive = index === activeIndex;
62
- const shouldRerender = index >= activeIndex - offscreenPageRerenderLimit && index <= activeIndex + offscreenPageRerenderLimit;
63
- const becomeNeighbor = shouldRerender && !isActive;
64
- return {
65
- isActive,
66
- becomeNeighbor
67
- };
68
- }, (nextState, prevState) => {
69
- if (nextState.isActive !== (prevState === null || prevState === void 0 ? void 0 : prevState.isActive)) {
70
- runOnJS(onActiveStateChange)(nextState.isActive);
71
- } else if (nextState.becomeNeighbor) {
72
- runOnJS(onBecomeNeighbor)();
73
- }
74
- }, [index]);
75
+ if (currentState.active !== newState.active || currentState.loaded !== newState.loaded) {
76
+ pageStateRef.current = newState;
77
+ forceRender();
78
+ }
79
+ });
80
+ }, [pageStore, computePageDescription]);
75
81
  const contextValue = useMemo(() => ({
76
- isActive: pageState.isActive
77
- }), [pageState.isActive]);
78
- const style = Platform.OS === 'web' ? pageState.isActive ? StyleSheet.absoluteFill : styles.none : styles.fill;
82
+ isActive: active
83
+ }), [active]);
84
+ const style = Platform.OS === 'web' ? active ? StyleSheet.absoluteFill : styles.none : styles.fill;
79
85
  return /*#__PURE__*/React.createElement(View, {
80
86
  collapsable: false,
81
87
  style: style
@@ -1 +1 @@
1
- {"version":3,"names":["React","memo","useMemo","useState","Platform","View","runOnJS","useAnimatedReaction","StyleSheet","PageStateContext","styles","create","fill","width","height","none","display","Page","props","index","children","loading","offscreenPageRerenderLimit","sharedIndex","assumeInitialPageState","activeIndex","value","isActive","isLoaded","pageState","setPageState","content","onActiveStateChange","prevState","onBecomeNeighbor","shouldRerender","becomeNeighbor","nextState","contextValue","style","OS","absoluteFill","prevProps","nextProps","rerenderKey"],"sources":["ChildrenMemoizedPage.tsx"],"sourcesContent":["import React, { memo, useMemo, useState } from 'react';\nimport { Platform, View } from 'react-native';\nimport { runOnJS, useAnimatedReaction } from 'react-native-reanimated';\nimport { StyleSheet } from '@fountain-ui/core';\nimport type { PageProps } from './ViewPagerProps';\nimport PageStateContext from './PageStateContext';\n\nconst styles = StyleSheet.create({\n fill: { width: '100%', height: '100%' },\n none: { display: 'none' },\n});\n\ninterface InternalPageState {\n isActive: boolean;\n isLoaded: boolean;\n}\n\nfunction Page(props: PageProps) {\n const {\n index,\n children,\n loading,\n offscreenPageRerenderLimit,\n sharedIndex,\n } = props;\n\n const assumeInitialPageState = (): InternalPageState => {\n const activeIndex = sharedIndex.value;\n\n const isActive = index === activeIndex;\n\n if (loading === 'eager') {\n return { isActive, isLoaded: true };\n }\n\n const isLoaded = index >= activeIndex - offscreenPageRerenderLimit\n && index <= activeIndex + offscreenPageRerenderLimit;\n\n return { isActive, isLoaded };\n };\n\n const [pageState, setPageState] = useState<InternalPageState>(assumeInitialPageState);\n\n const content = pageState.isLoaded ? children : null;\n\n const onActiveStateChange = (isActive: boolean) => {\n setPageState(prevState => ({\n ...prevState,\n isActive,\n isLoaded: isActive || prevState.isLoaded,\n }));\n };\n\n const onBecomeNeighbor = () => {\n setPageState(prevState => ({\n ...prevState,\n isLoaded: true,\n }));\n };\n\n useAnimatedReaction(\n () => {\n const activeIndex = sharedIndex.value;\n\n const isActive = index === activeIndex;\n\n const shouldRerender = index >= activeIndex - offscreenPageRerenderLimit\n && index <= activeIndex + offscreenPageRerenderLimit;\n\n const becomeNeighbor = shouldRerender && !isActive;\n\n return { isActive, becomeNeighbor };\n },\n (nextState, prevState) => {\n if (nextState.isActive !== prevState?.isActive) {\n runOnJS(onActiveStateChange)(nextState.isActive);\n } else if (nextState.becomeNeighbor) {\n runOnJS(onBecomeNeighbor)();\n }\n },\n [index],\n );\n\n const contextValue = useMemo(() => ({\n isActive: pageState.isActive,\n }), [pageState.isActive]);\n\n const style = Platform.OS === 'web'\n ? (pageState.isActive ? StyleSheet.absoluteFill : styles.none)\n : styles.fill;\n\n return (\n <View\n collapsable={false}\n style={style}\n >\n <PageStateContext.Provider value={contextValue}>\n {content}\n </PageStateContext.Provider>\n </View>\n );\n}\n\nexport default memo(Page, (prevProps, nextProps) => {\n if (prevProps.rerenderKey !== nextProps.rerenderKey) {\n return false;\n }\n\n return prevProps.index !== nextProps.index;\n});\n"],"mappings":"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"}
1
+ {"version":3,"names":["React","memo","useCallback","useContext","useEffect","useMemo","useReducer","useRef","useState","Platform","View","StyleSheet","PageStateContext","InternalContext","styles","create","fill","width","height","none","display","Page","props","index","initialPage","children","loading","offscreenPageRerenderLimit","pageStore","computePageDescription","page","activeIndex","isActive","shouldRerender","becomeNeighbor","initialState","active","loaded","pageStateRef","forceRender","s","current","content","subscribe","newPage","currentState","newState","contextValue","style","OS","absoluteFill","prevProps","nextProps","rerenderKey"],"sources":["ChildrenMemoizedPage.tsx"],"sourcesContent":["import React, { memo, useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState } from 'react';\nimport { Platform, View } from 'react-native';\nimport { StyleSheet } from '@fountain-ui/core';\nimport type { PageProps } from './types';\nimport PageStateContext from './PageStateContext';\nimport InternalContext from './InternalContext';\n\nconst styles = StyleSheet.create({\n fill: { width: '100%', height: '100%' },\n none: { display: 'none' },\n});\n\ninterface InternalPageDescription {\n isActive: boolean;\n becomeNeighbor: boolean;\n}\n\ninterface InternalPageState {\n active: boolean;\n loaded: boolean;\n}\n\nfunction Page(props: PageProps) {\n const {\n index,\n initialPage,\n children,\n loading,\n offscreenPageRerenderLimit,\n } = props;\n\n const { pageStore } = useContext(InternalContext);\n\n const computePageDescription: (page: number) => InternalPageDescription = useCallback((page: number) => {\n const activeIndex = page;\n\n const isActive = index === activeIndex;\n\n const shouldRerender = index >= activeIndex - offscreenPageRerenderLimit\n && index <= activeIndex + offscreenPageRerenderLimit;\n\n const becomeNeighbor = shouldRerender && !isActive;\n\n return { isActive, becomeNeighbor };\n }, [index]);\n\n const [initialState] = useState<InternalPageState>(() => {\n const { isActive, becomeNeighbor } = computePageDescription(initialPage);\n\n if (loading === 'eager') {\n return { active: isActive, loaded: true };\n }\n\n return { active: isActive, loaded: isActive || becomeNeighbor };\n });\n\n // `Bailing out of a state update` is not working as expected.\n const pageStateRef = useRef<InternalPageState>(initialState);\n const [, forceRender] = useReducer((s) => s + 1, 0);\n\n const { active, loaded } = pageStateRef.current;\n\n const content = loaded ? children : null;\n\n useEffect(() => {\n return pageStore.subscribe(newPage => {\n const { isActive, becomeNeighbor } = computePageDescription(newPage);\n\n const currentState = pageStateRef.current;\n\n const newState: InternalPageState = {\n active: isActive,\n loaded: isActive || becomeNeighbor ? true : currentState.loaded,\n };\n\n if (\n currentState.active !== newState.active\n || currentState.loaded !== newState.loaded\n ) {\n pageStateRef.current = newState;\n\n forceRender();\n }\n });\n }, [pageStore, computePageDescription]);\n\n const contextValue = useMemo(() => ({\n isActive: active,\n }), [active]);\n\n const style = Platform.OS === 'web'\n ? (active ? StyleSheet.absoluteFill : styles.none)\n : styles.fill;\n\n return (\n <View\n collapsable={false}\n style={style}\n >\n <PageStateContext.Provider value={contextValue}>\n {content}\n </PageStateContext.Provider>\n </View>\n );\n}\n\nexport default memo(Page, (prevProps, nextProps) => {\n if (prevProps.rerenderKey !== nextProps.rerenderKey) {\n return false;\n }\n\n return prevProps.index !== nextProps.index;\n});\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { createContext } from 'react';
2
+ import { MockStore } from '@fountain-ui/core';
3
+ const InternalContext = /*#__PURE__*/createContext({
4
+ pageStore: new MockStore()
5
+ });
6
+ export default InternalContext;
7
+ //# sourceMappingURL=InternalContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createContext","MockStore","InternalContext","pageStore"],"sources":["InternalContext.ts"],"sourcesContent":["import { createContext } from 'react';\nimport type { MonoStore } from '@fountain-ui/core';\nimport { MockStore } from '@fountain-ui/core';\n\nexport interface InternalContextValue {\n pageStore: MonoStore<number>;\n}\n\nconst InternalContext = createContext<InternalContextValue>({\n pageStore: new MockStore(),\n});\n\nexport default InternalContext;\n"],"mappings":"AAAA,SAASA,aAAT,QAA8B,OAA9B;AAEA,SAASC,SAAT,QAA0B,mBAA1B;AAMA,MAAMC,eAAe,gBAAGF,aAAa,CAAuB;EACxDG,SAAS,EAAE,IAAIF,SAAJ;AAD6C,CAAvB,CAArC;AAIA,eAAeC,eAAf"}
@@ -1,7 +1,9 @@
1
1
  import React, { Children, forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from 'react';
2
2
  import RNViewPager from 'react-native-pager-view';
3
- import { runOnJS, useAnimatedReaction, useSharedValue } from 'react-native-reanimated';
3
+ import { useSyncAnimatedValue } from '@fountain-ui/core';
4
4
  import { defaultInitialPage, defaultLoading, defaultOffscreenPageRerenderLimit, defaultPageComponent } from './utils';
5
+ import usePageStore from './usePageStore';
6
+ import InternalContext from './InternalContext';
5
7
  const ViewPager = /*#__PURE__*/forwardRef(function ViewPager(props, ref) {
6
8
  const {
7
9
  children,
@@ -16,8 +18,11 @@ const ViewPager = /*#__PURE__*/forwardRef(function ViewPager(props, ref) {
16
18
  style,
17
19
  UNSTABLE_sharedPage
18
20
  } = props;
19
- const fallbackSharedPage = useSharedValue(initialPage);
21
+ const fallbackSharedPage = useSyncAnimatedValue({
22
+ initialValue: initialPage
23
+ });
20
24
  const sharedPage = UNSTABLE_sharedPage ?? fallbackSharedPage;
25
+ const pageRef = useRef(sharedPage.initialValue);
21
26
  const desiredPageRef = useRef(NaN);
22
27
  const pagerRef = useRef(null);
23
28
  const animationFrameRef = useRef(NaN);
@@ -30,7 +35,7 @@ const ViewPager = /*#__PURE__*/forwardRef(function ViewPager(props, ref) {
30
35
  var _pagerRef$current;
31
36
 
32
37
  if (Number.isFinite(desiredPageRef.current)) {
33
- if (sharedPage.value === desiredPageRef.current) {
38
+ if (pageRef.current === desiredPageRef.current) {
34
39
  // end of state machine. clear desired page.
35
40
  desiredPageRef.current = NaN;
36
41
  return;
@@ -52,9 +57,17 @@ const ViewPager = /*#__PURE__*/forwardRef(function ViewPager(props, ref) {
52
57
  }
53
58
  };
54
59
  }, []);
55
- useAnimatedReaction(() => sharedPage.value, result => {
56
- runOnJS(setPage)(result);
57
- }, [setPage]);
60
+ useEffect(() => {
61
+ const animatedValue = sharedPage.animatedValue;
62
+ const id = animatedValue.addListener(newValue => {
63
+ const newPage = newValue.value;
64
+ pageRef.current = newPage;
65
+ setPage(newPage);
66
+ });
67
+ return () => {
68
+ animatedValue.removeListener(id);
69
+ };
70
+ }, [sharedPage, setPage]);
58
71
  const handlePageSelected = useCallback(e => {
59
72
  if (Number.isFinite(desiredPageRef.current)) {
60
73
  // onPageSelected is called from outer controlling mechanism
@@ -64,28 +77,36 @@ const ViewPager = /*#__PURE__*/forwardRef(function ViewPager(props, ref) {
64
77
  // other than that trust the value from desiredPageRef.
65
78
  const desiredPage = desiredPageRef.current;
66
79
 
67
- if (sharedPage.value === desiredPage) {
80
+ if (pageRef.current === desiredPage) {
68
81
  // end of state machine. clear desired page.
69
82
  desiredPageRef.current = NaN;
70
83
  } else {
71
- sharedPage.value = desiredPage;
84
+ sharedPage.animatedValue.setValue(desiredPage);
72
85
  }
73
86
 
74
87
  onChange === null || onChange === void 0 ? void 0 : onChange(desiredPage);
75
88
  } else {
76
89
  const trustfulNextPage = e.nativeEvent.position;
77
- desiredPageRef.current = trustfulNextPage;
78
- sharedPage.value = trustfulNextPage;
79
- onChange === null || onChange === void 0 ? void 0 : onChange(trustfulNextPage);
90
+
91
+ if (trustfulNextPage !== pageRef.current) {
92
+ desiredPageRef.current = trustfulNextPage;
93
+ sharedPage.animatedValue.setValue(trustfulNextPage);
94
+ onChange === null || onChange === void 0 ? void 0 : onChange(trustfulNextPage);
95
+ }
80
96
  }
81
- }, [onChange]);
97
+ }, [onChange, sharedPage]);
82
98
  useImperativeHandle(ref, () => ({
83
99
  setPage
84
100
  }), [setPage]);
101
+ const pageStore = usePageStore(sharedPage);
85
102
  const PageComponent = pageComponent;
86
- return /*#__PURE__*/React.createElement(RNViewPager, {
103
+ return /*#__PURE__*/React.createElement(InternalContext.Provider, {
104
+ value: {
105
+ pageStore
106
+ }
107
+ }, /*#__PURE__*/React.createElement(RNViewPager, {
87
108
  ref: pagerRef,
88
- initialPage: sharedPage.value,
109
+ initialPage: sharedPage.initialValue,
89
110
  keyboardDismissMode: keyboardDismissMode,
90
111
  onPageSelected: handlePageSelected,
91
112
  pageMargin: 8,
@@ -95,11 +116,11 @@ const ViewPager = /*#__PURE__*/forwardRef(function ViewPager(props, ref) {
95
116
  key: index,
96
117
  children: child,
97
118
  index: index,
119
+ initialPage: sharedPage.initialValue,
98
120
  loading: loading,
99
121
  offscreenPageRerenderLimit: offscreenPageRerenderLimit,
100
- rerenderKey: pageForceRerenderKey,
101
- sharedIndex: sharedPage
102
- })));
122
+ rerenderKey: pageForceRerenderKey
123
+ }))));
103
124
  });
104
125
  export default ViewPager;
105
126
  //# sourceMappingURL=ViewPagerNative.js.map