react-native-reorderable-list 0.8.0 → 0.10.0

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 (66) hide show
  1. package/README.md +104 -32
  2. package/lib/commonjs/components/ReorderableListCell.js +19 -14
  3. package/lib/commonjs/components/ReorderableListCell.js.map +1 -1
  4. package/lib/commonjs/components/ReorderableListCore/ReorderableListCore.js +11 -11
  5. package/lib/commonjs/components/ReorderableListCore/ReorderableListCore.js.map +1 -1
  6. package/lib/commonjs/components/ReorderableListCore/useReorderableListCore.js +50 -22
  7. package/lib/commonjs/components/ReorderableListCore/useReorderableListCore.js.map +1 -1
  8. package/lib/commonjs/components/helpers.js +32 -0
  9. package/lib/commonjs/components/helpers.js.map +1 -0
  10. package/lib/commonjs/contexts/ReorderableCellContext.js.map +1 -1
  11. package/lib/commonjs/contexts/ReorderableListContext.js.map +1 -1
  12. package/lib/commonjs/hooks/index.js +11 -0
  13. package/lib/commonjs/hooks/index.js.map +1 -1
  14. package/lib/commonjs/hooks/useIsActive.js +16 -0
  15. package/lib/commonjs/hooks/useIsActive.js.map +1 -0
  16. package/lib/commonjs/index.js +6 -0
  17. package/lib/commonjs/index.js.map +1 -1
  18. package/lib/commonjs/types/misc.js.map +1 -1
  19. package/lib/module/components/ReorderableListCell.js +19 -14
  20. package/lib/module/components/ReorderableListCell.js.map +1 -1
  21. package/lib/module/components/ReorderableListCore/ReorderableListCore.js +11 -11
  22. package/lib/module/components/ReorderableListCore/ReorderableListCore.js.map +1 -1
  23. package/lib/module/components/ReorderableListCore/useReorderableListCore.js +51 -23
  24. package/lib/module/components/ReorderableListCore/useReorderableListCore.js.map +1 -1
  25. package/lib/module/components/helpers.js +25 -0
  26. package/lib/module/components/helpers.js.map +1 -0
  27. package/lib/module/contexts/ReorderableCellContext.js.map +1 -1
  28. package/lib/module/contexts/ReorderableListContext.js.map +1 -1
  29. package/lib/module/hooks/index.js +1 -0
  30. package/lib/module/hooks/index.js.map +1 -1
  31. package/lib/module/hooks/useIsActive.js +9 -0
  32. package/lib/module/hooks/useIsActive.js.map +1 -0
  33. package/lib/module/index.js +2 -2
  34. package/lib/module/index.js.map +1 -1
  35. package/lib/module/types/misc.js.map +1 -1
  36. package/lib/typescript/components/ReorderableListCell.d.ts.map +1 -1
  37. package/lib/typescript/components/ReorderableListCore/useReorderableListCore.d.ts +138 -3
  38. package/lib/typescript/components/ReorderableListCore/useReorderableListCore.d.ts.map +1 -1
  39. package/lib/typescript/components/helpers.d.ts +11 -0
  40. package/lib/typescript/components/helpers.d.ts.map +1 -0
  41. package/lib/typescript/contexts/ReorderableCellContext.d.ts +1 -0
  42. package/lib/typescript/contexts/ReorderableCellContext.d.ts.map +1 -1
  43. package/lib/typescript/contexts/ReorderableListContext.d.ts +3 -2
  44. package/lib/typescript/contexts/ReorderableListContext.d.ts.map +1 -1
  45. package/lib/typescript/hooks/index.d.ts +1 -0
  46. package/lib/typescript/hooks/index.d.ts.map +1 -1
  47. package/lib/typescript/hooks/useIsActive.d.ts +2 -0
  48. package/lib/typescript/hooks/useIsActive.d.ts.map +1 -0
  49. package/lib/typescript/index.d.ts +2 -2
  50. package/lib/typescript/index.d.ts.map +1 -1
  51. package/lib/typescript/types/misc.d.ts +9 -0
  52. package/lib/typescript/types/misc.d.ts.map +1 -1
  53. package/lib/typescript/types/props.d.ts +35 -8
  54. package/lib/typescript/types/props.d.ts.map +1 -1
  55. package/package.json +3 -1
  56. package/src/components/ReorderableListCell.tsx +24 -11
  57. package/src/components/ReorderableListCore/ReorderableListCore.tsx +9 -9
  58. package/src/components/ReorderableListCore/useReorderableListCore.ts +68 -20
  59. package/src/components/helpers.ts +36 -0
  60. package/src/contexts/ReorderableCellContext.ts +1 -0
  61. package/src/contexts/ReorderableListContext.ts +4 -2
  62. package/src/hooks/index.ts +1 -0
  63. package/src/hooks/useIsActive.ts +7 -0
  64. package/src/index.ts +2 -0
  65. package/src/types/misc.ts +10 -0
  66. package/src/types/props.ts +71 -8
@@ -1 +1 @@
1
- {"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../../src/types/props.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAE,eAAe,EAAC,MAAM,cAAc,CAAC;AAEjE,OAAO,EAAC,WAAW,EAAE,wBAAwB,EAAC,MAAM,yBAAyB,CAAC;AAE9E,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,6BAA6B;IAC5C;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,KAAK,YAAY,GACb,YAAY,GACZ,UAAU,GACV,qBAAqB,GACrB,uBAAuB,GACvB,uBAAuB,GACvB,YAAY,CAAC;AAEjB,MAAM,WAAW,oBAAoB,CAAC,CAAC,CACrC,SAAQ,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC;IAC5C,IAAI,EAAE,CAAC,EAAE,CAAC;IACV;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;OAEG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,cAAc,CAAC,EAAE,6BAA6B,CAAC;IAC/C;;OAEG;IACH,SAAS,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,CAAC;IACxD;;OAEG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;IACvD;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,6BAA6B,KAAK,IAAI,CAAC;IAC7D;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,2BAA2B,KAAK,IAAI,CAAC;CAC1D;AAED,MAAM,WAAW,6BAA6B;IAC5C;;OAEG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;IACtC;;OAEG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;CACrC;AAED,MAAM,WAAW,wBACf,SAAQ,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC;IACzC;;OAEG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,0BAA0B,CAAC,CAAC,CAAE,SAAQ,oBAAoB,CAAC,CAAC,CAAC;IAC5E;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB"}
1
+ {"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../../src/types/props.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-reorderable-list",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "Reorderable list for React Native applications, powered by Reanimated",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -146,6 +146,8 @@
146
146
  "import"
147
147
  ],
148
148
  "rules": {
149
+ "@typescript-eslint/no-explicit-any": "error",
150
+ "no-console": "error",
149
151
  "prettier/prettier": [
150
152
  "error",
151
153
  {
@@ -14,6 +14,7 @@ import Animated, {
14
14
 
15
15
  import {ReorderableCellContext, ReorderableListContext} from '../contexts';
16
16
  import {useContext} from '../hooks';
17
+ import {applyAnimatedStyles} from './helpers';
17
18
 
18
19
  interface ReorderableListCellProps<T>
19
20
  extends Omit<CellRendererProps<T>, 'cellKey'> {
@@ -37,28 +38,29 @@ export const ReorderableListCell = memo(
37
38
  draggedIndex,
38
39
  animationDuration,
39
40
  }: ReorderableListCellProps<T>) => {
40
- const {currentIndex, draggedHeight, scale, opacity} = useContext(
41
- ReorderableListContext,
42
- );
41
+ const {currentIndex, draggedHeight, activeIndex, cellAnimations} =
42
+ useContext(ReorderableListContext);
43
43
  const dragHandler = useCallback(
44
44
  () => runOnUI(startDrag)(index),
45
45
  [startDrag, index],
46
46
  );
47
47
 
48
+ const isActive = activeIndex === index;
48
49
  const contextValue = useMemo(
49
50
  () => ({
50
51
  index,
51
52
  dragHandler,
52
53
  draggedIndex,
54
+ isActive,
53
55
  }),
54
- [index, dragHandler, draggedIndex],
56
+ [index, dragHandler, draggedIndex, isActive],
55
57
  );
56
58
 
57
59
  // Keep separate animated reactions that update itemTranslateY
58
60
  // otherwise animations might stutter if multiple are triggered
59
61
  // (even in other cells, e.g. released item and reordering cells)
60
62
  const itemTranslateY = useSharedValue(0);
61
- const isActive = useDerivedValue(() => draggedIndex.value === index);
63
+ const isActiveCell = useDerivedValue(() => draggedIndex.value === index);
62
64
 
63
65
  useAnimatedReaction(
64
66
  () => dragY.value,
@@ -101,12 +103,23 @@ export const ReorderableListCell = memo(
101
103
  );
102
104
 
103
105
  const animatedStyle = useAnimatedStyle(() => {
104
- if (isActive.value) {
105
- return {
106
- transform: [{translateY: itemTranslateY.value}, {scale: scale.value}],
107
- opacity: opacity.value,
108
- zIndex: 999,
109
- };
106
+ if (isActiveCell.value) {
107
+ const transform = [{translateY: itemTranslateY.value}];
108
+ if (Array.isArray(cellAnimations.transform)) {
109
+ const customTransform = cellAnimations.transform.map(x =>
110
+ applyAnimatedStyles({}, x),
111
+ ) as [];
112
+ transform.push(...customTransform);
113
+ }
114
+
115
+ return applyAnimatedStyles(
116
+ {
117
+ transform,
118
+ zIndex: 999,
119
+ },
120
+ cellAnimations,
121
+ ['transform'],
122
+ );
110
123
  }
111
124
 
112
125
  return {
@@ -43,8 +43,8 @@ interface ReorderableListCoreProps<T> extends ReorderableListProps<T> {
43
43
 
44
44
  const ReorderableListCore = <T,>(
45
45
  {
46
- data,
47
46
  autoscrollThreshold = 0.1,
47
+ autoscrollThresholdOffset,
48
48
  autoscrollSpeedScale = 1,
49
49
  autoscrollDelay = AUTOSCROLL_CONFIG.delay,
50
50
  animationDuration = 200,
@@ -54,17 +54,17 @@ const ReorderableListCore = <T,>(
54
54
  onScroll,
55
55
  onDragStart,
56
56
  onDragEnd,
57
- keyExtractor,
58
- extraData,
59
57
  scrollViewContainerRef,
60
58
  scrollViewHeightY,
61
59
  scrollViewScrollOffsetY,
62
60
  scrollViewScrollEnabled,
63
- scrollEnabled,
64
61
  initialScrollViewScrollEnabled,
65
62
  scrollable,
66
63
  outerScrollGesture,
67
64
  cellAnimations,
65
+ shouldUpdateActiveItem,
66
+ panEnabled = true,
67
+ panActivateAfterLongPress,
68
68
  ...rest
69
69
  }: ReorderableListCoreProps<T>,
70
70
  ref: React.ForwardedRef<FlatList<T>>,
@@ -84,6 +84,7 @@ const ReorderableListCore = <T,>(
84
84
  } = useReorderableListCore({
85
85
  ref,
86
86
  autoscrollThreshold,
87
+ autoscrollThresholdOffset,
87
88
  autoscrollSpeedScale,
88
89
  autoscrollDelay,
89
90
  animationDuration,
@@ -99,13 +100,16 @@ const ReorderableListCore = <T,>(
99
100
  // flatlist will default to true if we pass explicitly undefined,
100
101
  // but internally we would treat it as false, so we force true
101
102
  initialScrollEnabled:
102
- typeof scrollEnabled === 'undefined' ? true : scrollEnabled,
103
+ typeof rest.scrollEnabled === 'undefined' ? true : rest.scrollEnabled,
103
104
  initialScrollViewScrollEnabled:
104
105
  typeof initialScrollViewScrollEnabled === 'undefined'
105
106
  ? true
106
107
  : initialScrollViewScrollEnabled,
107
108
  nestedScrollable: scrollable,
108
109
  cellAnimations,
110
+ shouldUpdateActiveItem,
111
+ panEnabled,
112
+ panActivateAfterLongPress,
109
113
  });
110
114
 
111
115
  const combinedGesture = useMemo(() => {
@@ -145,17 +149,13 @@ const ReorderableListCore = <T,>(
145
149
  <AnimatedFlatList
146
150
  {...rest}
147
151
  ref={handleRef}
148
- data={data}
149
152
  CellRendererComponent={renderAnimatedCell}
150
153
  onLayout={handleFlatListLayout}
151
154
  onScroll={composedScrollHandler}
152
155
  scrollEventThrottle={1}
153
156
  horizontal={false}
154
157
  removeClippedSubviews={false}
155
- keyExtractor={keyExtractor}
156
- extraData={extraData}
157
158
  numColumns={1}
158
- scrollEnabled={scrollEnabled}
159
159
  />
160
160
  </GestureDetector>
161
161
  </ReorderableListContext.Provider>
@@ -1,4 +1,4 @@
1
- import React, {useCallback, useEffect, useMemo} from 'react';
1
+ import React, {useCallback, useEffect, useMemo, useState} from 'react';
2
2
  import {
3
3
  FlatList,
4
4
  LayoutChangeEvent,
@@ -43,6 +43,7 @@ const hasAutomaticBatching = version.length
43
43
  interface UseReorderableListCoreArgs<T> {
44
44
  ref: React.ForwardedRef<FlatList<T>>;
45
45
  autoscrollThreshold: number;
46
+ autoscrollThresholdOffset: {top?: number; bottom?: number} | undefined;
46
47
  autoscrollSpeedScale: number;
47
48
  autoscrollDelay: number;
48
49
  animationDuration: number;
@@ -59,11 +60,15 @@ interface UseReorderableListCoreArgs<T> {
59
60
  initialScrollViewScrollEnabled: boolean | undefined;
60
61
  nestedScrollable: boolean | undefined;
61
62
  cellAnimations: ReorderableListCellAnimations | undefined;
63
+ shouldUpdateActiveItem: boolean | undefined;
64
+ panEnabled: boolean;
65
+ panActivateAfterLongPress: number | undefined;
62
66
  }
63
67
 
64
68
  export const useReorderableListCore = <T>({
65
69
  ref,
66
70
  autoscrollThreshold,
71
+ autoscrollThresholdOffset,
67
72
  autoscrollSpeedScale,
68
73
  autoscrollDelay,
69
74
  animationDuration,
@@ -80,8 +85,12 @@ export const useReorderableListCore = <T>({
80
85
  initialScrollViewScrollEnabled,
81
86
  nestedScrollable,
82
87
  cellAnimations,
88
+ shouldUpdateActiveItem,
89
+ panActivateAfterLongPress,
90
+ panEnabled,
83
91
  }: UseReorderableListCoreArgs<T>) => {
84
92
  const flatListRef = useAnimatedRef<FlatList>();
93
+ const [activeIndex, setActiveIndex] = useState(-1);
85
94
  const scrollEnabled = useSharedValue(initialScrollEnabled);
86
95
  const gestureState = useSharedValue<State>(State.UNDETERMINED);
87
96
  const currentY = useSharedValue(0);
@@ -112,7 +121,6 @@ export const useReorderableListCore = <T>({
112
121
  const duration = useSharedValue(animationDuration);
113
122
  const scaleDefault = useSharedValue(1);
114
123
  const opacityDefault = useSharedValue(1);
115
- const {scale, opacity} = cellAnimations || {};
116
124
 
117
125
  useEffect(() => {
118
126
  duration.value = animationDuration;
@@ -124,17 +132,27 @@ export const useReorderableListCore = <T>({
124
132
  currentIndex,
125
133
  draggedIndex,
126
134
  dragEndHandlers,
127
- scale: scale || scaleDefault,
128
- opacity: opacity || opacityDefault,
135
+ activeIndex,
136
+ cellAnimations: {
137
+ ...cellAnimations,
138
+ transform:
139
+ cellAnimations && 'transform' in cellAnimations
140
+ ? cellAnimations.transform
141
+ : [{scale: scaleDefault}],
142
+ opacity:
143
+ cellAnimations && 'opacity' in cellAnimations
144
+ ? cellAnimations.opacity
145
+ : opacityDefault,
146
+ },
129
147
  }),
130
148
  [
131
149
  draggedHeight,
132
150
  currentIndex,
133
151
  draggedIndex,
134
152
  dragEndHandlers,
135
- scale,
153
+ activeIndex,
154
+ cellAnimations,
136
155
  scaleDefault,
137
- opacity,
138
156
  opacityDefault,
139
157
  ],
140
158
  );
@@ -177,9 +195,21 @@ export const useReorderableListCore = <T>({
177
195
  ],
178
196
  );
179
197
 
198
+ const panGestureHandlerWithOptions = useMemo(() => {
199
+ if (typeof panActivateAfterLongPress === 'number') {
200
+ panGestureHandler.activateAfterLongPress(panActivateAfterLongPress);
201
+ }
202
+
203
+ if (!panEnabled) {
204
+ panGestureHandler.enabled(panEnabled);
205
+ }
206
+
207
+ return panGestureHandler;
208
+ }, [panActivateAfterLongPress, panEnabled, panGestureHandler]);
209
+
180
210
  const gestureHandler = useMemo(
181
- () => Gesture.Simultaneous(Gesture.Native(), panGestureHandler),
182
- [panGestureHandler],
211
+ () => Gesture.Simultaneous(Gesture.Native(), panGestureHandlerWithOptions),
212
+ [panGestureHandlerWithOptions],
183
213
  );
184
214
 
185
215
  const setScrollEnabled = useCallback(
@@ -338,19 +368,19 @@ export const useReorderableListCore = <T>({
338
368
  (type: 'start' | 'end') => {
339
369
  'worklet';
340
370
 
341
- // if animation is not disabled and not custom run the default
342
- if (scale !== false && !scale) {
371
+ // if no custom scale run default
372
+ if (!(cellAnimations && 'transformtra' in cellAnimations)) {
343
373
  const scaleConfig = SCALE_ANIMATION_CONFIG_DEFAULT[type];
344
374
  scaleDefault.value = withTiming(scaleConfig.toValue, scaleConfig);
345
375
  }
346
376
 
347
- // if animation is not disabled and not custom run the default
348
- if (opacity !== false && !opacity) {
377
+ // if no custom opacity run the default
378
+ if (!(cellAnimations && 'opacity' in cellAnimations)) {
349
379
  const opacityConfig = OPACITY_ANIMATION_CONFIG_DEFAULT[type];
350
380
  opacityDefault.value = withTiming(opacityConfig.toValue, opacityConfig);
351
381
  }
352
382
  },
353
- [scale, scaleDefault, opacity, opacityDefault],
383
+ [cellAnimations, scaleDefault, opacityDefault],
354
384
  );
355
385
 
356
386
  useAnimatedReaction(
@@ -367,6 +397,10 @@ export const useReorderableListCore = <T>({
367
397
  // enable back scroll on releasing
368
398
  runOnJS(setScrollEnabled)(true);
369
399
 
400
+ if (shouldUpdateActiveItem) {
401
+ runOnJS(setActiveIndex)(-1);
402
+ }
403
+
370
404
  // trigger onDragEnd event
371
405
  let e = {from: draggedIndex.value, to: currentIndex.value};
372
406
  onDragEnd?.(e);
@@ -442,24 +476,33 @@ export const useReorderableListCore = <T>({
442
476
  const calculateThresholdArea = useCallback(
443
477
  (hiddenArea: {top: number; bottom: number}) => {
444
478
  'worklet';
479
+ const offsetTop = Math.max(0, autoscrollThresholdOffset?.top || 0);
480
+ const offsetBottom = Math.max(0, autoscrollThresholdOffset?.bottom || 0);
445
481
  const threshold = Math.max(0, Math.min(autoscrollThreshold, 0.4));
446
482
  const visibleHeight =
447
- flatListHeightY.value - (hiddenArea.top + hiddenArea.bottom);
483
+ flatListHeightY.value -
484
+ (hiddenArea.top + hiddenArea.bottom) -
485
+ (offsetTop + offsetBottom);
448
486
 
449
- const top = visibleHeight * threshold;
450
- const bottom = flatListHeightY.value - top;
487
+ const area = visibleHeight * threshold;
488
+ const top = area + offsetTop;
489
+ const bottom = flatListHeightY.value - area - offsetBottom;
451
490
 
452
491
  return {top, bottom};
453
492
  },
454
- [autoscrollThreshold, flatListHeightY],
493
+ [autoscrollThreshold, autoscrollThresholdOffset, flatListHeightY],
455
494
  );
456
495
 
457
496
  const calculateThresholdAreaParent = useCallback(
458
497
  (hiddenArea: {top: number; bottom: number}) => {
459
498
  'worklet';
499
+ const offsetTop = Math.max(0, autoscrollThresholdOffset?.top || 0);
500
+ const offsetBottom = Math.max(0, autoscrollThresholdOffset?.bottom || 0);
460
501
  const threshold = Math.max(0, Math.min(autoscrollThreshold, 0.4));
461
- const top = flatListHeightY.value * threshold;
462
- const bottom = flatListHeightY.value - top;
502
+
503
+ const area = flatListHeightY.value * threshold;
504
+ const top = area + offsetTop;
505
+ const bottom = flatListHeightY.value - area - offsetBottom;
463
506
 
464
507
  // if the hidden area is 0 then we don't have a threshold area
465
508
  // we might have floating errors like 0.0001 which we should ignore
@@ -468,7 +511,7 @@ export const useReorderableListCore = <T>({
468
511
  bottom: hiddenArea.bottom > 0.1 ? bottom - hiddenArea.bottom : 0,
469
512
  };
470
513
  },
471
- [autoscrollThreshold, flatListHeightY],
514
+ [autoscrollThreshold, autoscrollThresholdOffset, flatListHeightY],
472
515
  );
473
516
 
474
517
  const shouldScrollParent = useCallback(
@@ -644,6 +687,10 @@ export const useReorderableListCore = <T>({
644
687
  // after scrolling the parent list it would offset the new dragged item in another nested list
645
688
  resetSharedValues();
646
689
 
690
+ if (shouldUpdateActiveItem) {
691
+ runOnJS(setActiveIndex)(index);
692
+ }
693
+
647
694
  dragInitialScrollOffsetY.value = flatListScrollOffsetY.value;
648
695
  scrollViewDragInitialScrollOffsetY.value = scrollViewScrollOffsetY
649
696
  ? scrollViewScrollOffsetY.value
@@ -664,6 +711,7 @@ export const useReorderableListCore = <T>({
664
711
  },
665
712
  [
666
713
  resetSharedValues,
714
+ shouldUpdateActiveItem,
667
715
  dragInitialScrollOffsetY,
668
716
  scrollViewScrollOffsetY,
669
717
  scrollViewDragInitialScrollOffsetY,
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Flattens an object containing `SharedValue`s by extracting their underlying values.
3
+ *
4
+ * @param target - An object to which the flattened shared values and every other field will be mapped to.
5
+ * @param source - The object containing, possibly among others, the shared values.
6
+ * @param excludedKeys - The keys to exclude from flattening and mapping.
7
+ *
8
+ * @returns The object to which the fields where flattened and mapped to.
9
+ */
10
+ export const applyAnimatedStyles = (
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ target: Record<string, any>,
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ source: Record<string, any>,
15
+ excludedKeys: string[] = [],
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ ): Record<string, any> => {
18
+ 'worklet';
19
+
20
+ let keys = Object.keys(source);
21
+
22
+ for (let key of keys) {
23
+ if (excludedKeys.includes(key)) {
24
+ continue;
25
+ }
26
+
27
+ let value = source[key];
28
+
29
+ target[key] =
30
+ value !== null && typeof value === 'object' && 'value' in value
31
+ ? value.value
32
+ : value;
33
+ }
34
+
35
+ return target;
36
+ };
@@ -6,6 +6,7 @@ interface ReorderableCellContextData {
6
6
  index: number;
7
7
  dragHandler: () => void;
8
8
  draggedIndex: SharedValue<number>;
9
+ isActive: boolean;
9
10
  }
10
11
 
11
12
  export const ReorderableCellContext = React.createContext<
@@ -2,12 +2,14 @@ import React from 'react';
2
2
 
3
3
  import type {SharedValue} from 'react-native-reanimated';
4
4
 
5
+ import {ReorderableListCellAnimations} from '../types';
6
+
5
7
  interface ReorderableListContextData {
6
8
  currentIndex: SharedValue<number>;
7
9
  draggedHeight: SharedValue<number>;
8
10
  dragEndHandlers: SharedValue<((from: number, to: number) => void)[][]>;
9
- scale: SharedValue<number>;
10
- opacity: SharedValue<number>;
11
+ activeIndex: number;
12
+ cellAnimations: ReorderableListCellAnimations;
11
13
  }
12
14
 
13
15
  export const ReorderableListContext = React.createContext<
@@ -1,3 +1,4 @@
1
+ export * from './useIsActive';
1
2
  export * from './useReorderableDrag';
2
3
  export * from './useReorderableDragStart';
3
4
  export * from './useReorderableDragEnd';
@@ -0,0 +1,7 @@
1
+ import {useContext} from './useContext';
2
+ import {ReorderableCellContext} from '../contexts';
3
+
4
+ export const useIsActive = () => {
5
+ const {isActive} = useContext(ReorderableCellContext);
6
+ return isActive;
7
+ };
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  ScrollViewContainer,
5
5
  } from './components';
6
6
  import {
7
+ useIsActive,
7
8
  useReorderableDrag,
8
9
  useReorderableDragEnd,
9
10
  useReorderableDragStart,
@@ -19,6 +20,7 @@ import type {
19
20
  import {reorderItems} from './utils';
20
21
 
21
22
  export {
23
+ useIsActive,
22
24
  useReorderableDrag,
23
25
  useReorderableDragStart,
24
26
  useReorderableDragEnd,
package/src/types/misc.ts CHANGED
@@ -1,6 +1,16 @@
1
+ import {SharedValue} from 'react-native-reanimated';
2
+
1
3
  export enum ReorderableListState {
2
4
  IDLE = 0,
3
5
  DRAGGED,
4
6
  RELEASED,
5
7
  AUTOSCROLL,
6
8
  }
9
+
10
+ export type SharedValueOrType<T> = {
11
+ [TKey in keyof T]?: SharedValue<T[TKey]> | T[TKey];
12
+ };
13
+
14
+ export type MaximumOneOf<T, K extends keyof T = keyof T> = K extends keyof T
15
+ ? {[P in K]: T[K]} & {[P in Exclude<keyof T, K>]?: never}
16
+ : never;
@@ -1,7 +1,26 @@
1
- import type {FlatListProps, ScrollViewProps} from 'react-native';
1
+ import type {
2
+ FlatListProps,
3
+ MatrixTransform,
4
+ PerspectiveTransform,
5
+ RotateTransform,
6
+ RotateXTransform,
7
+ RotateYTransform,
8
+ RotateZTransform,
9
+ ScaleTransform,
10
+ ScaleXTransform,
11
+ ScaleYTransform,
12
+ ScrollViewProps,
13
+ SkewXTransform,
14
+ SkewYTransform,
15
+ TranslateXTransform,
16
+ TranslateYTransform,
17
+ ViewStyle,
18
+ } from 'react-native';
2
19
 
3
20
  import {SharedValue, useAnimatedScrollHandler} from 'react-native-reanimated';
4
21
 
22
+ import {MaximumOneOf, SharedValueOrType} from './misc';
23
+
5
24
  export interface ReorderableListReorderEvent {
6
25
  /**
7
26
  * Index of the dragged item.
@@ -43,11 +62,16 @@ export interface ReorderableListProps<T>
43
62
  extends Omit<FlatListProps<T>, OmittedProps> {
44
63
  data: T[];
45
64
  /**
46
- * Threshold at the extremety of the list which triggers autoscroll when an item is dragged to it.
65
+ * Threshold at the extremety of the list which triggers autoscroll when an item is dragged to it.
47
66
  * A value of 0.1 means that 10% of the area at the top and 10% at the bottom of the list will trigger autoscroll
48
67
  * when an item is dragged to it. Min value: `0`. Max value: `0.4`. Default: `0.1`.
49
68
  */
50
69
  autoscrollThreshold?: number;
70
+ /**
71
+ * Amount by which the threshold is offset at the extremety of the list.
72
+ * For example, setting `{top: 50}` will make the autoscroll trigger 50 pixels earlier at the top.
73
+ */
74
+ autoscrollThresholdOffset?: {top?: number; bottom?: number};
51
75
  /**
52
76
  * Scales the autoscroll spreed at which the list scrolls when an item is dragged to the scroll areas. Default: `1`.
53
77
  */
@@ -71,9 +95,21 @@ export interface ReorderableListProps<T>
71
95
  */
72
96
  animationDuration?: number;
73
97
  /**
74
- * Allows passing an object with shared values that can animate a cell by using the `onDragStart` and `onDragEnd` events.
98
+ * Allows passing an object with values and/or shared values that can animate a cell, for example by using the `onDragStart` and `onDragEnd` events. Supports view style properties. Override opacity and/or transform to disable the default animation, e.g. `{opacity: 1, transform: []}`.
75
99
  */
76
100
  cellAnimations?: ReorderableListCellAnimations;
101
+ /**
102
+ * Whether the active item should be updated. Enables usage of `useIsActive` hook. Default: `false`.
103
+ */
104
+ shouldUpdateActiveItem?: boolean;
105
+ /**
106
+ * Wether the pan gestures necessary for dragging are enabled. Default: `true`.
107
+ */
108
+ panEnabled?: boolean;
109
+ /**
110
+ * Duration in milliseconds of a long press on the list before pan gestures, necessary for dragging, are allowed to activate.
111
+ */
112
+ panActivateAfterLongPress?: number;
77
113
  /**
78
114
  * Event fired after an item is released and the list is reordered.
79
115
  */
@@ -92,15 +128,42 @@ export interface ReorderableListProps<T>
92
128
  onDragEnd?: (event: ReorderableListDragEndEvent) => void;
93
129
  }
94
130
 
95
- export interface ReorderableListCellAnimations {
131
+ export type Transforms = PerspectiveTransform &
132
+ RotateTransform &
133
+ RotateXTransform &
134
+ RotateYTransform &
135
+ RotateZTransform &
136
+ ScaleTransform &
137
+ ScaleXTransform &
138
+ ScaleYTransform &
139
+ TranslateXTransform &
140
+ TranslateYTransform &
141
+ SkewXTransform &
142
+ SkewYTransform &
143
+ MatrixTransform;
144
+
145
+ export type ReorderableListCellAnimatedStyles = Omit<
146
+ {
147
+ [StyleKey in keyof ViewStyle]?:
148
+ | SharedValue<ViewStyle[StyleKey]>
149
+ | ViewStyle[StyleKey];
150
+ },
151
+ // omit custom type and type with JSDoc
152
+ 'transform' | 'opacity'
153
+ >;
154
+
155
+ export interface ReorderableListCellAnimations
156
+ extends ReorderableListCellAnimatedStyles {
96
157
  /**
97
- * Shared value to animate the opacity of a dragged item. Set to false to disable default opacity animations.
158
+ * Transform animations for a dragged item.
159
+ * Disable default animation by overriding transform, e.g. `[]` or `[{ scale: customSharedValue }]`.
98
160
  */
99
- opacity?: SharedValue<number> | false;
161
+ transform?: Readonly<MaximumOneOf<SharedValueOrType<Transforms>>[]>;
100
162
  /**
101
- * Shared value to animate the scale of a dragged item. Set to false to disable default scale animations.
163
+ * Shared value to animate the opacity of a dragged item.
164
+ * Disable default animation by overriding opacity, e.g `1`.
102
165
  */
103
- scale?: SharedValue<number> | false;
166
+ opacity?: SharedValue<number> | number;
104
167
  }
105
168
 
106
169
  export interface ScrollViewContainerProps