react-native-reorderable-list 0.7.1 → 0.9.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 (104) hide show
  1. package/README.md +131 -47
  2. package/lib/commonjs/components/ReorderableList.js +11 -13
  3. package/lib/commonjs/components/ReorderableList.js.map +1 -1
  4. package/lib/commonjs/components/ReorderableListCell.js +44 -31
  5. package/lib/commonjs/components/ReorderableListCell.js.map +1 -1
  6. package/lib/commonjs/components/ReorderableListCore/ReorderableListCore.js +18 -17
  7. package/lib/commonjs/components/ReorderableListCore/ReorderableListCore.js.map +1 -1
  8. package/lib/commonjs/components/ReorderableListCore/animationDefaults.js +34 -0
  9. package/lib/commonjs/components/ReorderableListCore/animationDefaults.js.map +1 -0
  10. package/lib/commonjs/components/ReorderableListCore/{constants.js → autoscrollConfig.js} +1 -1
  11. package/lib/commonjs/components/ReorderableListCore/autoscrollConfig.js.map +1 -0
  12. package/lib/commonjs/components/ReorderableListCore/useReorderableListCore.js +82 -33
  13. package/lib/commonjs/components/ReorderableListCore/useReorderableListCore.js.map +1 -1
  14. package/lib/commonjs/components/ScrollViewContainer.js +2 -2
  15. package/lib/commonjs/components/ScrollViewContainer.js.map +1 -1
  16. package/lib/commonjs/components/index.js +0 -11
  17. package/lib/commonjs/components/index.js.map +1 -1
  18. package/lib/commonjs/contexts/ReorderableCellContext.js.map +1 -1
  19. package/lib/commonjs/contexts/ReorderableListContext.js.map +1 -1
  20. package/lib/commonjs/hooks/index.js +11 -0
  21. package/lib/commonjs/hooks/index.js.map +1 -1
  22. package/lib/commonjs/hooks/useIsActive.js +16 -0
  23. package/lib/commonjs/hooks/useIsActive.js.map +1 -0
  24. package/lib/commonjs/index.js +6 -6
  25. package/lib/commonjs/index.js.map +1 -1
  26. package/lib/commonjs/types/misc.js +3 -3
  27. package/lib/module/components/ReorderableList.js +11 -13
  28. package/lib/module/components/ReorderableList.js.map +1 -1
  29. package/lib/module/components/ReorderableListCell.js +45 -32
  30. package/lib/module/components/ReorderableListCell.js.map +1 -1
  31. package/lib/module/components/ReorderableListCore/ReorderableListCore.js +17 -15
  32. package/lib/module/components/ReorderableListCore/ReorderableListCore.js.map +1 -1
  33. package/lib/module/components/ReorderableListCore/animationDefaults.js +28 -0
  34. package/lib/module/components/ReorderableListCore/animationDefaults.js.map +1 -0
  35. package/lib/module/components/ReorderableListCore/{constants.js → autoscrollConfig.js} +1 -1
  36. package/lib/module/components/ReorderableListCore/autoscrollConfig.js.map +1 -0
  37. package/lib/module/components/ReorderableListCore/useReorderableListCore.js +82 -33
  38. package/lib/module/components/ReorderableListCore/useReorderableListCore.js.map +1 -1
  39. package/lib/module/components/ScrollViewContainer.js +3 -3
  40. package/lib/module/components/ScrollViewContainer.js.map +1 -1
  41. package/lib/module/components/index.js +0 -1
  42. package/lib/module/components/index.js.map +1 -1
  43. package/lib/module/contexts/ReorderableCellContext.js.map +1 -1
  44. package/lib/module/contexts/ReorderableListContext.js.map +1 -1
  45. package/lib/module/hooks/index.js +1 -0
  46. package/lib/module/hooks/index.js.map +1 -1
  47. package/lib/module/hooks/useIsActive.js +9 -0
  48. package/lib/module/hooks/useIsActive.js.map +1 -0
  49. package/lib/module/index.js +3 -3
  50. package/lib/module/index.js.map +1 -1
  51. package/lib/module/types/misc.js +3 -3
  52. package/lib/typescript/components/ReorderableList.d.ts.map +1 -1
  53. package/lib/typescript/components/ReorderableListCell.d.ts +1 -1
  54. package/lib/typescript/components/ReorderableListCell.d.ts.map +1 -1
  55. package/lib/typescript/components/ReorderableListCore/ReorderableListCore.d.ts.map +1 -1
  56. package/lib/typescript/components/ReorderableListCore/animationDefaults.d.ts +13 -0
  57. package/lib/typescript/components/ReorderableListCore/animationDefaults.d.ts.map +1 -0
  58. package/lib/typescript/components/ReorderableListCore/{constants.d.ts → autoscrollConfig.d.ts} +1 -1
  59. package/lib/typescript/components/ReorderableListCore/autoscrollConfig.d.ts.map +1 -0
  60. package/lib/typescript/components/ReorderableListCore/useReorderableListCore.d.ts +11 -4
  61. package/lib/typescript/components/ReorderableListCore/useReorderableListCore.d.ts.map +1 -1
  62. package/lib/typescript/components/ScrollViewContainer.d.ts.map +1 -1
  63. package/lib/typescript/components/index.d.ts +0 -1
  64. package/lib/typescript/components/index.d.ts.map +1 -1
  65. package/lib/typescript/contexts/ReorderableCellContext.d.ts +1 -0
  66. package/lib/typescript/contexts/ReorderableCellContext.d.ts.map +1 -1
  67. package/lib/typescript/contexts/ReorderableListContext.d.ts +3 -0
  68. package/lib/typescript/contexts/ReorderableListContext.d.ts.map +1 -1
  69. package/lib/typescript/hooks/index.d.ts +1 -0
  70. package/lib/typescript/hooks/index.d.ts.map +1 -1
  71. package/lib/typescript/hooks/useIsActive.d.ts +2 -0
  72. package/lib/typescript/hooks/useIsActive.d.ts.map +1 -0
  73. package/lib/typescript/index.d.ts +4 -4
  74. package/lib/typescript/index.d.ts.map +1 -1
  75. package/lib/typescript/types/misc.d.ts +3 -3
  76. package/lib/typescript/types/misc.d.ts.map +1 -1
  77. package/lib/typescript/types/props.d.ts +31 -31
  78. package/lib/typescript/types/props.d.ts.map +1 -1
  79. package/package.json +5 -5
  80. package/src/components/ReorderableList.tsx +14 -16
  81. package/src/components/ReorderableListCell.tsx +38 -33
  82. package/src/components/ReorderableListCore/ReorderableListCore.tsx +22 -13
  83. package/src/components/ReorderableListCore/animationDefaults.ts +35 -0
  84. package/src/components/ReorderableListCore/useReorderableListCore.ts +117 -40
  85. package/src/components/ScrollViewContainer.tsx +7 -3
  86. package/src/components/index.ts +0 -1
  87. package/src/contexts/ReorderableCellContext.ts +1 -0
  88. package/src/contexts/ReorderableListContext.ts +3 -0
  89. package/src/hooks/index.ts +1 -0
  90. package/src/hooks/useIsActive.ts +7 -0
  91. package/src/index.ts +6 -6
  92. package/src/types/misc.ts +3 -3
  93. package/src/types/props.ts +32 -37
  94. package/lib/commonjs/components/ReorderableListCore/constants.js.map +0 -1
  95. package/lib/commonjs/components/ReorderableListItem.js +0 -87
  96. package/lib/commonjs/components/ReorderableListItem.js.map +0 -1
  97. package/lib/module/components/ReorderableListCore/constants.js.map +0 -1
  98. package/lib/module/components/ReorderableListItem.js +0 -78
  99. package/lib/module/components/ReorderableListItem.js.map +0 -1
  100. package/lib/typescript/components/ReorderableListCore/constants.d.ts.map +0 -1
  101. package/lib/typescript/components/ReorderableListItem.d.ts +0 -4
  102. package/lib/typescript/components/ReorderableListItem.d.ts.map +0 -1
  103. package/src/components/ReorderableListItem.tsx +0 -108
  104. /package/src/components/ReorderableListCore/{constants.ts → autoscrollConfig.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-reorderable-list",
3
- "version": "0.7.1",
3
+ "version": "0.9.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",
@@ -81,8 +81,8 @@
81
81
  "react": "18.3.1",
82
82
  "react-native": "0.76.5",
83
83
  "react-native-builder-bob": "^0.20.0",
84
- "react-native-gesture-handler": "^2.12.0",
85
- "react-native-reanimated": "^3.15.3",
84
+ "react-native-gesture-handler": "2.12.0",
85
+ "react-native-reanimated": "3.12.0",
86
86
  "release-it": "^17.6.0",
87
87
  "tsc": "^2.0.4",
88
88
  "typescript": "5.0.4"
@@ -90,8 +90,8 @@
90
90
  "peerDependencies": {
91
91
  "react": "*",
92
92
  "react-native": "*",
93
- "react-native-gesture-handler": ">=2.0.0",
94
- "react-native-reanimated": ">=3.6.0"
93
+ "react-native-gesture-handler": ">=2.12.0",
94
+ "react-native-reanimated": ">=3.12.0"
95
95
  },
96
96
  "engines": {
97
97
  "node": ">= 18.0.0"
@@ -7,22 +7,20 @@ import type {ReorderableListProps} from '../types';
7
7
  const ReorderableListWithRef = <T,>(
8
8
  {scrollEnabled = true, ...rest}: ReorderableListProps<T>,
9
9
  ref: React.Ref<FlatList<T>>,
10
- ) => {
11
- return (
12
- <ReorderableListCore
13
- {...rest}
14
- ref={ref}
15
- scrollEnabled={scrollEnabled}
16
- initialScrollViewScrollEnabled={true}
17
- scrollable={true}
18
- scrollViewContainerRef={undefined}
19
- scrollViewScrollOffsetY={undefined}
20
- scrollViewHeightY={undefined}
21
- outerScrollGesture={undefined}
22
- scrollViewScrollEnabled={undefined}
23
- />
24
- );
25
- };
10
+ ) => (
11
+ <ReorderableListCore
12
+ {...rest}
13
+ ref={ref}
14
+ scrollEnabled={scrollEnabled}
15
+ initialScrollViewScrollEnabled={true}
16
+ scrollable={true}
17
+ scrollViewContainerRef={undefined}
18
+ scrollViewScrollOffsetY={undefined}
19
+ scrollViewHeightY={undefined}
20
+ outerScrollGesture={undefined}
21
+ scrollViewScrollEnabled={undefined}
22
+ />
23
+ );
26
24
 
27
25
  export const ReorderableList = forwardRef(ReorderableListWithRef) as <T>(
28
26
  props: ReorderableListProps<T> & React.RefAttributes<FlatList<T>>,
@@ -1,5 +1,5 @@
1
1
  import React, {memo, useCallback, useMemo} from 'react';
2
- import type {CellRendererProps, LayoutChangeEvent} from 'react-native';
2
+ import {CellRendererProps, LayoutChangeEvent} from 'react-native';
3
3
 
4
4
  import Animated, {
5
5
  Easing,
@@ -7,6 +7,7 @@ import Animated, {
7
7
  runOnUI,
8
8
  useAnimatedReaction,
9
9
  useAnimatedStyle,
10
+ useDerivedValue,
10
11
  useSharedValue,
11
12
  withTiming,
12
13
  } from 'react-native-reanimated';
@@ -21,7 +22,6 @@ interface ReorderableListCellProps<T>
21
22
  itemHeight: SharedValue<number[]>;
22
23
  dragY: SharedValue<number>;
23
24
  draggedIndex: SharedValue<number>;
24
- // animation duration as a shared value allows to avoid re-renders on value change
25
25
  animationDuration: SharedValue<number>;
26
26
  }
27
27
 
@@ -37,36 +37,39 @@ export const ReorderableListCell = memo(
37
37
  draggedIndex,
38
38
  animationDuration,
39
39
  }: ReorderableListCellProps<T>) => {
40
- const dragHandler = useCallback(() => {
41
- 'worklet';
42
-
43
- startDrag(index);
44
- }, [startDrag, index]);
40
+ const {currentIndex, draggedHeight, scale, opacity, activeIndex} =
41
+ useContext(ReorderableListContext);
42
+ const dragHandler = useCallback(
43
+ () => runOnUI(startDrag)(index),
44
+ [startDrag, index],
45
+ );
45
46
 
47
+ const isActive = activeIndex === index;
46
48
  const contextValue = useMemo(
47
49
  () => ({
48
50
  index,
49
51
  dragHandler,
50
52
  draggedIndex,
53
+ isActive,
51
54
  }),
52
- [index, dragHandler, draggedIndex],
55
+ [index, dragHandler, draggedIndex, isActive],
53
56
  );
54
- const {currentIndex, draggedHeight} = useContext(ReorderableListContext);
55
57
 
56
- const itemZIndex = useSharedValue(0);
57
- const itemPositionY = useSharedValue(0);
58
- const itemDragY = useSharedValue(0);
59
- const itemIndex = useSharedValue(index);
58
+ // Keep separate animated reactions that update itemTranslateY
59
+ // otherwise animations might stutter if multiple are triggered
60
+ // (even in other cells, e.g. released item and reordering cells)
61
+ const itemTranslateY = useSharedValue(0);
62
+ const isActiveCell = useDerivedValue(() => draggedIndex.value === index);
60
63
 
61
64
  useAnimatedReaction(
62
65
  () => dragY.value,
63
66
  () => {
64
67
  if (
65
- itemIndex.value === draggedIndex.value &&
68
+ index === draggedIndex.value &&
66
69
  currentIndex.value >= 0 &&
67
70
  draggedIndex.value >= 0
68
71
  ) {
69
- itemDragY.value = dragY.value;
72
+ itemTranslateY.value = dragY.value;
70
73
  }
71
74
  },
72
75
  );
@@ -75,7 +78,7 @@ export const ReorderableListCell = memo(
75
78
  () => currentIndex.value,
76
79
  () => {
77
80
  if (
78
- itemIndex.value !== draggedIndex.value &&
81
+ index !== draggedIndex.value &&
79
82
  currentIndex.value >= 0 &&
80
83
  draggedIndex.value >= 0
81
84
  ) {
@@ -84,12 +87,12 @@ export const ReorderableListCell = memo(
84
87
  const endMove = Math.max(draggedIndex.value, currentIndex.value);
85
88
  let newValue = 0;
86
89
 
87
- if (itemIndex.value >= startMove && itemIndex.value <= endMove) {
90
+ if (index >= startMove && index <= endMove) {
88
91
  newValue = moveDown ? -draggedHeight.value : draggedHeight.value;
89
92
  }
90
93
 
91
- if (newValue !== itemPositionY.value) {
92
- itemPositionY.value = withTiming(newValue, {
94
+ if (newValue !== itemTranslateY.value) {
95
+ itemTranslateY.value = withTiming(newValue, {
93
96
  duration: animationDuration.value,
94
97
  easing: Easing.out(Easing.ease),
95
98
  });
@@ -98,20 +101,22 @@ export const ReorderableListCell = memo(
98
101
  },
99
102
  );
100
103
 
101
- useAnimatedReaction(
102
- () => draggedIndex.value === index,
103
- newValue => {
104
- itemZIndex.value = newValue ? 999 : 0;
105
- },
106
- );
107
-
108
- const animatedStyle = useAnimatedStyle(() => ({
109
- zIndex: itemZIndex.value,
110
- transform: [
111
- {translateY: itemDragY.value},
112
- {translateY: itemPositionY.value},
113
- ],
114
- }));
104
+ const animatedStyle = useAnimatedStyle(() => {
105
+ if (isActiveCell.value) {
106
+ return {
107
+ transform: [{translateY: itemTranslateY.value}, {scale: scale.value}],
108
+ opacity: opacity.value,
109
+ zIndex: 999,
110
+ };
111
+ }
112
+
113
+ return {
114
+ transform: [{translateY: itemTranslateY.value}],
115
+ // TODO: move to stylesheet when this is fixed
116
+ // https://github.com/software-mansion/react-native-reanimated/issues/6681#issuecomment-2514228447
117
+ zIndex: 0,
118
+ };
119
+ });
115
120
 
116
121
  const handleLayout = (e: LayoutChangeEvent) => {
117
122
  runOnUI((y: number, height: number) => {
@@ -12,9 +12,12 @@ import {
12
12
  GestureDetector,
13
13
  NativeGesture,
14
14
  } from 'react-native-gesture-handler';
15
- import Animated, {SharedValue} from 'react-native-reanimated';
15
+ import Animated, {
16
+ SharedValue,
17
+ useComposedEventHandler,
18
+ } from 'react-native-reanimated';
16
19
 
17
- import {AUTOSCROLL_CONFIG} from './constants';
20
+ import {AUTOSCROLL_CONFIG} from './autoscrollConfig';
18
21
  import {useReorderableListCore} from './useReorderableListCore';
19
22
  import {ReorderableListContext} from '../../contexts';
20
23
  import type {ReorderableListProps} from '../../types';
@@ -40,7 +43,6 @@ interface ReorderableListCoreProps<T> extends ReorderableListProps<T> {
40
43
 
41
44
  const ReorderableListCore = <T,>(
42
45
  {
43
- data,
44
46
  autoscrollThreshold = 0.1,
45
47
  autoscrollSpeedScale = 1,
46
48
  autoscrollDelay = AUTOSCROLL_CONFIG.delay,
@@ -49,17 +51,19 @@ const ReorderableListCore = <T,>(
49
51
  onLayout,
50
52
  onReorder,
51
53
  onScroll,
54
+ onDragStart,
52
55
  onDragEnd,
53
- keyExtractor,
54
- extraData,
55
56
  scrollViewContainerRef,
56
57
  scrollViewHeightY,
57
58
  scrollViewScrollOffsetY,
58
59
  scrollViewScrollEnabled,
59
- scrollEnabled,
60
60
  initialScrollViewScrollEnabled,
61
61
  scrollable,
62
62
  outerScrollGesture,
63
+ cellAnimations,
64
+ shouldUpdateActiveItem,
65
+ panEnabled = true,
66
+ panActivateAfterLongPress,
63
67
  ...rest
64
68
  }: ReorderableListCoreProps<T>,
65
69
  ref: React.ForwardedRef<FlatList<T>>,
@@ -85,7 +89,7 @@ const ReorderableListCore = <T,>(
85
89
  dragReorderThreshold,
86
90
  onLayout,
87
91
  onReorder,
88
- onScroll,
92
+ onDragStart,
89
93
  onDragEnd,
90
94
  scrollViewContainerRef,
91
95
  scrollViewHeightY,
@@ -94,12 +98,16 @@ const ReorderableListCore = <T,>(
94
98
  // flatlist will default to true if we pass explicitly undefined,
95
99
  // but internally we would treat it as false, so we force true
96
100
  initialScrollEnabled:
97
- typeof scrollEnabled === 'undefined' ? true : scrollEnabled,
101
+ typeof rest.scrollEnabled === 'undefined' ? true : rest.scrollEnabled,
98
102
  initialScrollViewScrollEnabled:
99
103
  typeof initialScrollViewScrollEnabled === 'undefined'
100
104
  ? true
101
105
  : initialScrollViewScrollEnabled,
102
106
  nestedScrollable: scrollable,
107
+ cellAnimations,
108
+ shouldUpdateActiveItem,
109
+ panEnabled,
110
+ panActivateAfterLongPress,
103
111
  });
104
112
 
105
113
  const combinedGesture = useMemo(() => {
@@ -111,6 +119,11 @@ const ReorderableListCore = <T,>(
111
119
  return gestureHandler;
112
120
  }, [scrollable, outerScrollGesture, gestureHandler]);
113
121
 
122
+ const composedScrollHandler = useComposedEventHandler([
123
+ handleScroll,
124
+ onScroll || null,
125
+ ]);
126
+
114
127
  const renderAnimatedCell = useCallback(
115
128
  ({cellKey, ...props}: CellRendererProps<T>) => (
116
129
  <ReorderableListCell
@@ -134,17 +147,13 @@ const ReorderableListCore = <T,>(
134
147
  <AnimatedFlatList
135
148
  {...rest}
136
149
  ref={handleRef}
137
- data={data}
138
150
  CellRendererComponent={renderAnimatedCell}
139
151
  onLayout={handleFlatListLayout}
140
- onScroll={handleScroll}
152
+ onScroll={composedScrollHandler}
141
153
  scrollEventThrottle={1}
142
154
  horizontal={false}
143
155
  removeClippedSubviews={false}
144
- keyExtractor={keyExtractor}
145
- extraData={extraData}
146
156
  numColumns={1}
147
- scrollEnabled={scrollEnabled}
148
157
  />
149
158
  </GestureDetector>
150
159
  </ReorderableListContext.Provider>
@@ -0,0 +1,35 @@
1
+ import {Easing, WithTimingConfig} from 'react-native-reanimated';
2
+
3
+ const DURATION_START = 150;
4
+ const DURATION_END = 200;
5
+
6
+ interface AnimationConfig {
7
+ start: WithTimingConfig & {toValue: number};
8
+ end: WithTimingConfig & {toValue: number};
9
+ }
10
+
11
+ export const SCALE_ANIMATION_CONFIG_DEFAULT: AnimationConfig = {
12
+ start: {
13
+ toValue: 1.025,
14
+ easing: Easing.in(Easing.ease),
15
+ duration: DURATION_START,
16
+ },
17
+ end: {
18
+ toValue: 1,
19
+ easing: Easing.out(Easing.ease),
20
+ duration: DURATION_END,
21
+ },
22
+ };
23
+
24
+ export const OPACITY_ANIMATION_CONFIG_DEFAULT: AnimationConfig = {
25
+ start: {
26
+ toValue: 0.75,
27
+ easing: Easing.in(Easing.ease),
28
+ duration: DURATION_START,
29
+ },
30
+ end: {
31
+ toValue: 1,
32
+ easing: Easing.out(Easing.ease),
33
+ duration: DURATION_END,
34
+ },
35
+ };