react-native-reanimated-carousel 4.0.0-alpha.7 → 4.0.0-alpha.9

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 (56) hide show
  1. package/README.md +2 -3
  2. package/lib/commonjs/components/BaseLayout.js +2 -20
  3. package/lib/commonjs/components/BaseLayout.js.map +1 -1
  4. package/lib/commonjs/components/Carousel.js +21 -45
  5. package/lib/commonjs/components/Carousel.js.map +1 -1
  6. package/lib/commonjs/components/ItemRenderer.js +80 -0
  7. package/lib/commonjs/components/ItemRenderer.js.map +1 -0
  8. package/lib/commonjs/components/ScrollViewGesture.js +5 -5
  9. package/lib/commonjs/components/ScrollViewGesture.js.map +1 -1
  10. package/lib/commonjs/hooks/useCarouselController.js +9 -9
  11. package/lib/commonjs/hooks/useCarouselController.js.map +1 -1
  12. package/lib/commonjs/hooks/useOffsetX.test.js.map +1 -1
  13. package/lib/commonjs/hooks/usePanGestureProxy.js +12 -12
  14. package/lib/commonjs/hooks/usePanGestureProxy.js.map +1 -1
  15. package/lib/commonjs/hooks/usePanGestureProxy.test.js +8 -8
  16. package/lib/commonjs/hooks/usePanGestureProxy.test.js.map +1 -1
  17. package/lib/commonjs/hooks/useVisibleRanges.js +33 -16
  18. package/lib/commonjs/hooks/useVisibleRanges.js.map +1 -1
  19. package/lib/commonjs/index.js.map +1 -1
  20. package/lib/module/components/BaseLayout.js +3 -15
  21. package/lib/module/components/BaseLayout.js.map +1 -1
  22. package/lib/module/components/Carousel.js +21 -42
  23. package/lib/module/components/Carousel.js.map +1 -1
  24. package/lib/module/components/ItemRenderer.js +62 -0
  25. package/lib/module/components/ItemRenderer.js.map +1 -0
  26. package/lib/module/components/ScrollViewGesture.js +5 -5
  27. package/lib/module/components/ScrollViewGesture.js.map +1 -1
  28. package/lib/module/hooks/useCarouselController.js +9 -9
  29. package/lib/module/hooks/useCarouselController.js.map +1 -1
  30. package/lib/module/hooks/useOffsetX.test.js.map +1 -1
  31. package/lib/module/hooks/usePanGestureProxy.js +12 -12
  32. package/lib/module/hooks/usePanGestureProxy.js.map +1 -1
  33. package/lib/module/hooks/usePanGestureProxy.test.js +8 -8
  34. package/lib/module/hooks/usePanGestureProxy.test.js.map +1 -1
  35. package/lib/module/hooks/useVisibleRanges.js +32 -16
  36. package/lib/module/hooks/useVisibleRanges.js.map +1 -1
  37. package/lib/module/index.js.map +1 -1
  38. package/lib/typescript/components/ItemRenderer.d.ts +22 -0
  39. package/lib/typescript/components/ScrollViewGesture.d.ts +1 -1
  40. package/lib/typescript/hooks/useCarouselController.d.ts +1 -1
  41. package/lib/typescript/hooks/usePanGestureProxy.d.ts +1 -1
  42. package/lib/typescript/hooks/useVisibleRanges.d.ts +7 -4
  43. package/lib/typescript/index.d.ts +1 -0
  44. package/lib/typescript/types.d.ts +2 -2
  45. package/package.json +1 -1
  46. package/src/components/BaseLayout.tsx +3 -33
  47. package/src/components/Carousel.tsx +21 -58
  48. package/src/components/ItemRenderer.tsx +105 -0
  49. package/src/components/ScrollViewGesture.tsx +6 -6
  50. package/src/hooks/useCarouselController.tsx +9 -9
  51. package/src/hooks/useOffsetX.test.ts +1 -1
  52. package/src/hooks/usePanGestureProxy.test.tsx +6 -7
  53. package/src/hooks/usePanGestureProxy.ts +15 -15
  54. package/src/hooks/useVisibleRanges.tsx +54 -22
  55. package/src/index.tsx +2 -0
  56. package/src/types.ts +2 -2
@@ -3,7 +3,7 @@ import { StyleSheet } from "react-native";
3
3
  import { GestureHandlerRootView } from "react-native-gesture-handler";
4
4
  import { runOnJS, useDerivedValue } from "react-native-reanimated";
5
5
 
6
- import { BaseLayout } from "./BaseLayout";
6
+ import { ItemRenderer } from "./ItemRenderer";
7
7
  import { ScrollViewGesture } from "./ScrollViewGesture";
8
8
 
9
9
  import { useAutoPlay } from "../hooks/useAutoPlay";
@@ -13,7 +13,6 @@ import { useInitProps } from "../hooks/useInitProps";
13
13
  import { useLayoutConfig } from "../hooks/useLayoutConfig";
14
14
  import { useOnProgressChange } from "../hooks/useOnProgressChange";
15
15
  import { usePropsErrorBoundary } from "../hooks/usePropsErrorBoundary";
16
- import { useVisibleRanges } from "../hooks/useVisibleRanges";
17
16
  import { CTX } from "../store";
18
17
  import type { ICarouselInstance, TCarouselProps } from "../types";
19
18
  import { computedRealIndexWithAutoFillData } from "../utils/computed-with-auto-fill-data";
@@ -30,8 +29,6 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
30
29
  data,
31
30
  // Length of fill data
32
31
  dataLength,
33
- // Raw data that has not been processed
34
- rawData,
35
32
  // Length of raw data
36
33
  rawDataLength,
37
34
  mode,
@@ -49,7 +46,7 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
49
46
  renderItem,
50
47
  onScrollEnd,
51
48
  onSnapToItem,
52
- onScrollBegin,
49
+ onScrollStart,
53
50
  onProgressChange,
54
51
  customAnimation,
55
52
  defaultIndex,
@@ -89,7 +86,7 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
89
86
  fixedDirection,
90
87
  duration: scrollAnimationDuration,
91
88
  onScrollEnd: () => runOnJS(_onScrollEnd)(),
92
- onScrollBegin: () => !!onScrollBegin && runOnJS(onScrollBegin)(),
89
+ onScrollStart: () => !!onScrollStart && runOnJS(onScrollStart)(),
93
90
  });
94
91
 
95
92
  const { next, prev, scrollTo, getSharedIndex, getCurrentIndex }
@@ -126,10 +123,10 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
126
123
  onScrollEnd,
127
124
  ]);
128
125
 
129
- const scrollViewGestureOnScrollBegin = React.useCallback(() => {
126
+ const scrollViewGestureOnScrollStart = React.useCallback(() => {
130
127
  pauseAutoPlay();
131
- onScrollBegin?.();
132
- }, [onScrollBegin, pauseAutoPlay]);
128
+ onScrollStart?.();
129
+ }, [onScrollStart, pauseAutoPlay]);
133
130
 
134
131
  const scrollViewGestureOnScrollEnd = React.useCallback(() => {
135
132
  startAutoPlay();
@@ -155,55 +152,8 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
155
152
  [getCurrentIndex, next, prev, scrollTo],
156
153
  );
157
154
 
158
- const visibleRanges = useVisibleRanges({
159
- total: dataLength,
160
- viewSize: size,
161
- translation: handlerOffset,
162
- windowSize,
163
- loop,
164
- });
165
-
166
155
  const layoutConfig = useLayoutConfig({ ...props, size });
167
156
 
168
- const renderLayout = React.useCallback(
169
- (item: any, i: number) => {
170
- const realIndex = computedRealIndexWithAutoFillData({
171
- index: i,
172
- dataLength: rawDataLength,
173
- loop,
174
- autoFillData,
175
- });
176
-
177
- return (
178
- <BaseLayout
179
- key={i}
180
- index={i}
181
- handlerOffset={offsetX}
182
- visibleRanges={visibleRanges}
183
- animationStyle={customAnimation || layoutConfig}
184
- >
185
- {({ animationValue }) =>
186
- renderItem({
187
- item,
188
- index: realIndex,
189
- animationValue,
190
- })
191
- }
192
- </BaseLayout>
193
- );
194
- },
195
- [
196
- loop,
197
- rawData,
198
- offsetX,
199
- visibleRanges,
200
- autoFillData,
201
- renderItem,
202
- layoutConfig,
203
- customAnimation,
204
- ],
205
- );
206
-
207
157
  return (
208
158
  <GestureHandlerRootView>
209
159
  <CTX.Provider value={{ props, common: commonVariables }}>
@@ -223,12 +173,25 @@ const Carousel = React.forwardRef<ICarouselInstance, TCarouselProps<any>>(
223
173
  : styles.itemsHorizontal,
224
174
  ]}
225
175
  testID={testID}
226
- onScrollBegin={scrollViewGestureOnScrollBegin}
176
+ onScrollStart={scrollViewGestureOnScrollStart}
227
177
  onScrollEnd={scrollViewGestureOnScrollEnd}
228
178
  onTouchBegin={scrollViewGestureOnTouchBegin}
229
179
  onTouchEnd={scrollViewGestureOnTouchEnd}
230
180
  >
231
- {data.map(renderLayout)}
181
+ <ItemRenderer
182
+ data={data}
183
+ dataLength={dataLength}
184
+ rawDataLength={rawDataLength}
185
+ loop={loop}
186
+ size={size}
187
+ windowSize={windowSize}
188
+ autoFillData={autoFillData}
189
+ offsetX={offsetX}
190
+ handlerOffset={handlerOffset}
191
+ layoutConfig={layoutConfig}
192
+ renderItem={renderItem}
193
+ customAnimation={customAnimation}
194
+ />
232
195
  </ScrollViewGesture>
233
196
  </CTX.Provider>
234
197
  </GestureHandlerRootView>
@@ -0,0 +1,105 @@
1
+ import React from "react";
2
+ import type { FC } from "react";
3
+ import type { ViewStyle } from "react-native";
4
+ import type Animated from "react-native-reanimated";
5
+ import { useAnimatedReaction, type AnimatedStyleProp, runOnJS } from "react-native-reanimated";
6
+
7
+ import type { TAnimationStyle } from "./BaseLayout";
8
+ import { BaseLayout } from "./BaseLayout";
9
+
10
+ import type { VisibleRanges } from "../hooks/useVisibleRanges";
11
+ import { useVisibleRanges } from "../hooks/useVisibleRanges";
12
+ import type { CarouselRenderItem } from "../types";
13
+ import { computedRealIndexWithAutoFillData } from "../utils/computed-with-auto-fill-data";
14
+
15
+ interface Props {
16
+ data: any[]
17
+ dataLength: number
18
+ rawDataLength: number
19
+ loop: boolean
20
+ size: number
21
+ windowSize?: number
22
+ autoFillData: boolean
23
+ offsetX: Animated.SharedValue<number>
24
+ handlerOffset: Animated.SharedValue<number>
25
+ layoutConfig: TAnimationStyle
26
+ renderItem: CarouselRenderItem<any>
27
+ customAnimation?: ((value: number) => AnimatedStyleProp<ViewStyle>)
28
+ }
29
+
30
+ export const ItemRenderer: FC<Props> = (props) => {
31
+ const {
32
+ data,
33
+ size,
34
+ windowSize,
35
+ handlerOffset,
36
+ offsetX,
37
+ dataLength,
38
+ rawDataLength,
39
+ loop,
40
+ autoFillData,
41
+ layoutConfig,
42
+ renderItem,
43
+ customAnimation,
44
+ } = props;
45
+
46
+ const visibleRanges = useVisibleRanges({
47
+ total: dataLength,
48
+ viewSize: size,
49
+ translation: handlerOffset,
50
+ windowSize,
51
+ loop,
52
+ });
53
+
54
+ const [displayedItems, setDisplayedItems] = React.useState<VisibleRanges>(null!);
55
+
56
+ useAnimatedReaction(
57
+ () => visibleRanges.value,
58
+ ranges => runOnJS(setDisplayedItems)(ranges),
59
+ [visibleRanges],
60
+ );
61
+
62
+ if (!displayedItems)
63
+ return null;
64
+
65
+ return (
66
+ <>
67
+ {
68
+ data.map((item, index) => {
69
+ const realIndex = computedRealIndexWithAutoFillData({
70
+ index,
71
+ dataLength: rawDataLength,
72
+ loop,
73
+ autoFillData,
74
+ });
75
+
76
+ const { negativeRange, positiveRange } = displayedItems;
77
+
78
+ const shouldRender = (index >= negativeRange[0] && index <= negativeRange[1])
79
+ || (index >= positiveRange[0] && index <= positiveRange[1]);
80
+
81
+ if (!shouldRender)
82
+ return null;
83
+
84
+ return (
85
+ <BaseLayout
86
+ key={index}
87
+ index={index}
88
+ handlerOffset={offsetX}
89
+ visibleRanges={visibleRanges}
90
+ animationStyle={customAnimation || layoutConfig}
91
+ >
92
+ {({ animationValue }) =>
93
+ renderItem({
94
+ item,
95
+ index: realIndex,
96
+ animationValue,
97
+ })
98
+ }
99
+ </BaseLayout>
100
+ );
101
+ })
102
+ }
103
+ </>
104
+ );
105
+ };
@@ -25,7 +25,7 @@ interface Props {
25
25
  infinite?: boolean
26
26
  testID?: string
27
27
  style?: StyleProp<ViewStyle>
28
- onScrollBegin?: () => void
28
+ onScrollStart?: () => void
29
29
  onScrollEnd?: () => void
30
30
  onTouchBegin?: () => void
31
31
  onTouchEnd?: () => void
@@ -55,7 +55,7 @@ const IScrollViewGesture: React.FC<PropsWithChildren<Props>> = (props) => {
55
55
  translation,
56
56
  testID,
57
57
  style = {},
58
- onScrollBegin,
58
+ onScrollStart,
59
59
  onScrollEnd,
60
60
  onTouchBegin,
61
61
  onTouchEnd,
@@ -259,12 +259,12 @@ const IScrollViewGesture: React.FC<PropsWithChildren<Props>> = (props) => {
259
259
  return translation;
260
260
  }
261
261
 
262
- const onGestureBegin = useCallback((_: PanGestureHandlerEventPayload) => {
262
+ const onGestureStart = useCallback((_: PanGestureHandlerEventPayload) => {
263
263
  "worklet";
264
264
 
265
265
  touching.value = true;
266
266
  validStart.value = true;
267
- onScrollBegin && runOnJS(onScrollBegin)();
267
+ onScrollStart && runOnJS(onScrollStart)();
268
268
 
269
269
  max.value = (maxPage - 1) * size;
270
270
  if (!loop && !overscrollEnabled)
@@ -282,7 +282,7 @@ const IScrollViewGesture: React.FC<PropsWithChildren<Props>> = (props) => {
282
282
  translation,
283
283
  overscrollEnabled,
284
284
  getLimit,
285
- onScrollBegin,
285
+ onScrollStart,
286
286
  ]);
287
287
 
288
288
  const onGestureUpdate = useCallback((e: PanGestureHandlerEventPayload) => {
@@ -380,7 +380,7 @@ const IScrollViewGesture: React.FC<PropsWithChildren<Props>> = (props) => {
380
380
 
381
381
  const gesture = usePanGestureProxy({
382
382
  onConfigurePanGesture,
383
- onGestureBegin,
383
+ onGestureStart,
384
384
  onGestureUpdate,
385
385
  onGestureEnd,
386
386
  options: { enabled },
@@ -27,7 +27,7 @@ interface IOpts {
27
27
  fixedDirection?: TCarouselProps["fixedDirection"]
28
28
  duration?: number
29
29
  defaultIndex?: number
30
- onScrollBegin?: () => void
30
+ onScrollStart?: () => void
31
31
  onScrollEnd?: () => void
32
32
  }
33
33
 
@@ -138,8 +138,8 @@ export function useCarouselController(options: IOpts): ICarouselController {
138
138
  options.onScrollEnd?.();
139
139
  }, [options]);
140
140
 
141
- const onScrollBegin = React.useCallback(() => {
142
- options.onScrollBegin?.();
141
+ const onScrollStart = React.useCallback(() => {
142
+ options.onScrollStart?.();
143
143
  }, [options]);
144
144
 
145
145
  const scrollWithTiming = React.useCallback(
@@ -173,7 +173,7 @@ export function useCarouselController(options: IOpts): ICarouselController {
173
173
  if (!canSliding() || (!loop && index.value >= dataInfo.length - 1))
174
174
  return;
175
175
 
176
- onScrollBegin?.();
176
+ onScrollStart?.();
177
177
 
178
178
  const nextPage = currentFixedPage() + count;
179
179
  index.value = nextPage;
@@ -194,7 +194,7 @@ export function useCarouselController(options: IOpts): ICarouselController {
194
194
  loop,
195
195
  index,
196
196
  dataInfo,
197
- onScrollBegin,
197
+ onScrollStart,
198
198
  handlerOffset,
199
199
  size,
200
200
  scrollWithTiming,
@@ -207,7 +207,7 @@ export function useCarouselController(options: IOpts): ICarouselController {
207
207
  const { count = 1, animated = true, onFinished } = opts;
208
208
  if (!canSliding() || (!loop && index.value <= 0)) return;
209
209
 
210
- onScrollBegin?.();
210
+ onScrollStart?.();
211
211
 
212
212
  const prevPage = currentFixedPage() - count;
213
213
  index.value = prevPage;
@@ -227,7 +227,7 @@ export function useCarouselController(options: IOpts): ICarouselController {
227
227
  canSliding,
228
228
  loop,
229
229
  index,
230
- onScrollBegin,
230
+ onScrollStart,
231
231
  handlerOffset,
232
232
  size,
233
233
  scrollWithTiming,
@@ -241,7 +241,7 @@ export function useCarouselController(options: IOpts): ICarouselController {
241
241
  if (i === index.value) return;
242
242
  if (!canSliding()) return;
243
243
 
244
- onScrollBegin?.();
244
+ onScrollStart?.();
245
245
  // direction -> 1 | -1
246
246
  const direction = handlerOffsetDirection(handlerOffset, fixedDirection);
247
247
 
@@ -283,7 +283,7 @@ export function useCarouselController(options: IOpts): ICarouselController {
283
283
  handlerOffset,
284
284
  dataInfo.length,
285
285
  canSliding,
286
- onScrollBegin,
286
+ onScrollStart,
287
287
  scrollWithTiming,
288
288
  ],
289
289
  );
@@ -12,7 +12,7 @@ describe("useSharedValue", () => {
12
12
  const range = useSharedValue({
13
13
  negativeRange: [7, 9],
14
14
  positiveRange: [0, 3],
15
- });
15
+ }) as IVisibleRanges;
16
16
  const inputs: Array<{
17
17
  config: IOpts
18
18
  range: IVisibleRanges
@@ -46,14 +46,13 @@ describe("Using RNGH v2 gesture API", () => {
46
46
  onConfigurePanGesture: (gesture: PanGesture) => {
47
47
  // This is user's customizations
48
48
  gesture
49
- .onStart(treatStartAsUpdate ? handlers.active : handlers.start)
50
49
  .onBegin(handlersFromUser.begin)
51
50
  .onUpdate(handlersFromUser.active)
52
51
  .onEnd(handlersFromUser.end)
53
52
  .onFinalize(handlers.finish)
54
53
  .withTestId("pan");
55
54
  },
56
- onGestureBegin: handlers.begin,
55
+ onGestureStart: treatStartAsUpdate ? handlers.active : handlers.start,
57
56
  onGestureUpdate: handlers.active,
58
57
  onGestureEnd: handlers.end,
59
58
  options: { enabled: true },
@@ -82,10 +81,11 @@ describe("Using RNGH v2 gesture API", () => {
82
81
  const pan = usePanGestureProxy({
83
82
  onConfigurePanGesture: (_: PanGesture) => {
84
83
  _
84
+ .onBegin(panHandlers.begin)
85
85
  .onFinalize(panHandlers.finish)
86
86
  .withTestId("pan");
87
87
  },
88
- onGestureBegin: panHandlers.begin,
88
+ onGestureStart: panHandlers.start,
89
89
  onGestureUpdate: panHandlers.active,
90
90
  onGestureEnd: panHandlers.end,
91
91
  options: { enabled: true },
@@ -153,14 +153,13 @@ describe("Event list validation", () => {
153
153
  const pan = usePanGestureProxy({
154
154
  onConfigurePanGesture: (_: PanGesture) => {
155
155
  _
156
- .onStart(treatStartAsUpdate ? handlers.active : handlers.start)
157
156
  .onBegin(handlersFromUser.begin)
158
157
  .onUpdate(handlersFromUser.active)
159
158
  .onEnd(handlersFromUser.end)
160
159
  .onFinalize(handlers.finish)
161
160
  .withTestId("pan");
162
161
  },
163
- onGestureBegin: handlers.begin,
162
+ onGestureStart: treatStartAsUpdate ? handlers.active : handlers.start,
164
163
  onGestureUpdate: handlers.active,
165
164
  onGestureEnd: handlers.end,
166
165
  options: { enabled: true },
@@ -233,11 +232,11 @@ describe("Filling event list with defaults", () => {
233
232
  const pan = usePanGestureProxy({
234
233
  onConfigurePanGesture: (_: PanGesture) => {
235
234
  _
236
- .onStart(treatStartAsUpdate ? handlers.active : handlers.start)
235
+ .onBegin(handlers.begin)
237
236
  .onFinalize(handlers.finish)
238
237
  .withTestId("pan");
239
238
  },
240
- onGestureBegin: handlers.begin,
239
+ onGestureStart: treatStartAsUpdate ? handlers.active : handlers.start,
241
240
  onGestureUpdate: handlers.active,
242
241
  onGestureEnd: handlers.end,
243
242
  options: { enabled: true },
@@ -8,7 +8,7 @@ import { useUpdateGestureConfig } from "./useUpdateGestureConfig";
8
8
  export const usePanGestureProxy = (
9
9
  customization: {
10
10
  onConfigurePanGesture?: (gesture: PanGesture) => void
11
- onGestureBegin: (event: GestureStateChangeEvent<PanGestureHandlerEventPayload>) => void
11
+ onGestureStart: (event: GestureStateChangeEvent<PanGestureHandlerEventPayload>) => void
12
12
  onGestureUpdate: (event: GestureUpdateEvent<PanGestureHandlerEventPayload>) => void
13
13
  onGestureEnd: (event: GestureStateChangeEvent<PanGestureHandlerEventPayload>, success: boolean) => void
14
14
  options?: GestureConfig
@@ -16,7 +16,7 @@ export const usePanGestureProxy = (
16
16
  ) => {
17
17
  const {
18
18
  onConfigurePanGesture,
19
- onGestureBegin,
19
+ onGestureStart,
20
20
  onGestureUpdate,
21
21
  onGestureEnd,
22
22
  options = {},
@@ -27,25 +27,25 @@ export const usePanGestureProxy = (
27
27
 
28
28
  // Save the original gesture callbacks
29
29
  const originalGestures = {
30
- onBegin: gesture.onBegin,
30
+ onStart: gesture.onStart,
31
31
  onUpdate: gesture.onUpdate,
32
32
  onEnd: gesture.onEnd,
33
33
  };
34
34
 
35
35
  // Save the user defined gesture callbacks
36
36
  const userDefinedConflictGestures: {
37
- onBegin?: Parameters<(typeof gesture)["onBegin"]>[0]
37
+ onStart?: Parameters<(typeof gesture)["onStart"]>[0]
38
38
  onUpdate?: Parameters<(typeof gesture)["onUpdate"]>[0]
39
39
  onEnd?: Parameters<(typeof gesture)["onEnd"]>[0]
40
40
  } = {
41
- onBegin: undefined,
41
+ onStart: undefined,
42
42
  onUpdate: undefined,
43
43
  onEnd: undefined,
44
44
  };
45
45
 
46
- const fakeOnBegin: typeof gesture.onBegin = (cb) => {
47
- // Using fakeOnBegin to save the user defined callback
48
- userDefinedConflictGestures.onBegin = cb;
46
+ const fakeOnStart: typeof gesture.onStart = (cb) => {
47
+ // Using fakeOnStart to save the user defined callback
48
+ userDefinedConflictGestures.onStart = cb;
49
49
  return gesture;
50
50
  };
51
51
 
@@ -62,7 +62,7 @@ export const usePanGestureProxy = (
62
62
  };
63
63
 
64
64
  // Setup the fake callbacks
65
- gesture.onBegin = fakeOnBegin;
65
+ gesture.onStart = fakeOnStart;
66
66
  gesture.onUpdate = fakeOnUpdate;
67
67
  gesture.onEnd = fakeOnEnd;
68
68
 
@@ -71,17 +71,17 @@ export const usePanGestureProxy = (
71
71
  onConfigurePanGesture(gesture);
72
72
 
73
73
  // Restore the original callbacks
74
- gesture.onBegin = originalGestures.onBegin;
74
+ gesture.onStart = originalGestures.onStart;
75
75
  gesture.onUpdate = originalGestures.onUpdate;
76
76
  gesture.onEnd = originalGestures.onEnd;
77
77
 
78
78
  // Setup the original callbacks with the user defined callbacks
79
79
  gesture
80
- .onBegin((e) => {
81
- onGestureBegin(e);
80
+ .onStart((e) => {
81
+ onGestureStart(e);
82
82
 
83
- if (userDefinedConflictGestures.onBegin)
84
- userDefinedConflictGestures.onBegin(e);
83
+ if (userDefinedConflictGestures.onStart)
84
+ userDefinedConflictGestures.onStart(e);
85
85
  })
86
86
  .onUpdate((e) => {
87
87
  onGestureUpdate(e);
@@ -98,7 +98,7 @@ export const usePanGestureProxy = (
98
98
 
99
99
  return gesture;
100
100
  }, [
101
- onGestureBegin,
101
+ onGestureStart,
102
102
  onGestureUpdate,
103
103
  onGestureEnd,
104
104
  onConfigurePanGesture,
@@ -1,10 +1,15 @@
1
+ import { useRef } from "react";
1
2
  import type Animated from "react-native-reanimated";
2
3
  import { useDerivedValue } from "react-native-reanimated";
3
4
 
4
- export type IVisibleRanges = Animated.SharedValue<{
5
- negativeRange: number[]
6
- positiveRange: number[]
7
- }>;
5
+ type Range = [number, number];
6
+
7
+ export interface VisibleRanges {
8
+ negativeRange: Range
9
+ positiveRange: Range
10
+ }
11
+
12
+ export type IVisibleRanges = Animated.SharedValue<VisibleRanges>;
8
13
 
9
14
  export function useVisibleRanges(options: {
10
15
  total: number
@@ -22,6 +27,7 @@ export function useVisibleRanges(options: {
22
27
  } = options;
23
28
 
24
29
  const windowSize = _windowSize ?? total;
30
+ const cachedRanges = useRef<VisibleRanges>(null!);
25
31
 
26
32
  const ranges = useDerivedValue(() => {
27
33
  const positiveCount = Math.round(windowSize / 2);
@@ -30,36 +36,62 @@ export function useVisibleRanges(options: {
30
36
  let currentIndex = Math.round(-translation.value / viewSize);
31
37
  currentIndex = currentIndex < 0 ? (currentIndex % total) + total : currentIndex;
32
38
 
39
+ let newRanges: VisibleRanges;
40
+
33
41
  if (!loop) {
34
42
  // Adjusting negative range if the carousel is not loopable.
35
43
  // So, It will be only displayed the positive items.
36
- return {
44
+ newRanges = {
37
45
  negativeRange: [0 + currentIndex - (windowSize - 1), 0 + currentIndex],
38
46
  positiveRange: [0 + currentIndex, currentIndex + (windowSize - 1)],
39
47
  };
40
48
  }
49
+ else {
50
+ const negativeRange: Range = [
51
+ (currentIndex - negativeCount + total) % total,
52
+ (currentIndex - 1 + total) % total,
53
+ ];
41
54
 
42
- const negativeRange = [
43
- (currentIndex - negativeCount + total) % total,
44
- (currentIndex - 1 + total) % total,
45
- ];
55
+ const positiveRange: Range = [
56
+ (currentIndex + total) % total,
57
+ (currentIndex + positiveCount + total) % total,
58
+ ];
46
59
 
47
- const positiveRange = [
48
- (currentIndex + total) % total,
49
- (currentIndex + positiveCount + total) % total,
50
- ];
60
+ if (negativeRange[0] < total && negativeRange[0] > negativeRange[1]) {
61
+ negativeRange[1] = total - 1;
62
+ positiveRange[0] = 0;
63
+ }
64
+ if (positiveRange[0] > positiveRange[1]) {
65
+ negativeRange[1] = total - 1;
66
+ positiveRange[0] = 0;
67
+ }
51
68
 
52
- if (negativeRange[0] < total && negativeRange[0] > negativeRange[1]) {
53
- negativeRange[1] = total - 1;
54
- positiveRange[0] = 0;
55
- }
56
- if (positiveRange[0] > positiveRange[1]) {
57
- negativeRange[1] = total - 1;
58
- positiveRange[0] = 0;
69
+ // console.log({ negativeRange, positiveRange ,total,windowSize,a:total <= _windowSize})
70
+ newRanges = { negativeRange, positiveRange };
59
71
  }
60
- // console.log({ negativeRange, positiveRange ,total,windowSize,a:total <= _windowSize})
61
- return { negativeRange, positiveRange };
72
+
73
+ if (
74
+ isArraysEqual(
75
+ cachedRanges.current?.negativeRange ?? [],
76
+ newRanges.negativeRange,
77
+ )
78
+ && isArraysEqual(
79
+ cachedRanges.current?.positiveRange ?? [],
80
+ newRanges.positiveRange,
81
+ )
82
+ )
83
+ return cachedRanges.current;
84
+
85
+ cachedRanges.current = newRanges;
86
+ return cachedRanges.current;
62
87
  }, [loop, total, windowSize, translation]);
63
88
 
64
89
  return ranges;
65
90
  }
91
+
92
+ function isArraysEqual(a: number[], b: number[]): boolean {
93
+ "worklet";
94
+ if (a.length !== b.length) return false;
95
+
96
+ return a.every((value, index) => value === b[index]);
97
+ }
package/src/index.tsx CHANGED
@@ -1,10 +1,12 @@
1
1
  import Carousel from "./components/Carousel";
2
+
2
3
  export type {
3
4
  TCarouselProps,
4
5
  ICarouselInstance,
5
6
  IComputedDirectionTypes,
6
7
  CarouselRenderItem,
7
8
  } from "./types";
9
+ export type { TAnimationStyle } from "./components/BaseLayout";
8
10
  export type { ILayoutConfig } from "./layouts/stack";
9
11
 
10
12
  export default Carousel;
package/src/types.ts CHANGED
@@ -180,9 +180,9 @@ export type TCarouselProps<T = any> = {
180
180
  */
181
181
  onSnapToItem?: (index: number) => void
182
182
  /**
183
- * On scroll begin
183
+ * On scroll start
184
184
  */
185
- onScrollBegin?: () => void
185
+ onScrollStart?: () => void
186
186
  /**
187
187
  * On scroll end
188
188
  */