react-native-reorderable-list 0.16.2 → 0.17.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 (48) hide show
  1. package/README.md +12 -5
  2. package/lib/commonjs/components/NestedReorderableList.js +6 -6
  3. package/lib/commonjs/components/NestedReorderableList.js.map +1 -1
  4. package/lib/commonjs/components/ReorderableList.js +3 -3
  5. package/lib/commonjs/components/ReorderableList.js.map +1 -1
  6. package/lib/commonjs/components/ReorderableListCell.js +20 -18
  7. package/lib/commonjs/components/ReorderableListCell.js.map +1 -1
  8. package/lib/commonjs/components/ReorderableListCore.js +168 -158
  9. package/lib/commonjs/components/ReorderableListCore.js.map +1 -1
  10. package/lib/commonjs/components/ScrollViewContainer.js +13 -12
  11. package/lib/commonjs/components/ScrollViewContainer.js.map +1 -1
  12. package/lib/commonjs/contexts/ReorderableListContext.js.map +1 -1
  13. package/lib/commonjs/index.js.map +1 -1
  14. package/lib/module/components/NestedReorderableList.js +6 -6
  15. package/lib/module/components/NestedReorderableList.js.map +1 -1
  16. package/lib/module/components/ReorderableList.js +3 -3
  17. package/lib/module/components/ReorderableList.js.map +1 -1
  18. package/lib/module/components/ReorderableListCell.js +20 -18
  19. package/lib/module/components/ReorderableListCell.js.map +1 -1
  20. package/lib/module/components/ReorderableListCore.js +168 -158
  21. package/lib/module/components/ReorderableListCore.js.map +1 -1
  22. package/lib/module/components/ScrollViewContainer.js +13 -12
  23. package/lib/module/components/ScrollViewContainer.js.map +1 -1
  24. package/lib/module/contexts/ReorderableListContext.js.map +1 -1
  25. package/lib/module/index.js.map +1 -1
  26. package/lib/typescript/components/ReorderableListCell.d.ts +3 -3
  27. package/lib/typescript/components/ReorderableListCell.d.ts.map +1 -1
  28. package/lib/typescript/components/ReorderableListCore.d.ts +3 -3
  29. package/lib/typescript/components/ReorderableListCore.d.ts.map +1 -1
  30. package/lib/typescript/components/ScrollViewContainer.d.ts.map +1 -1
  31. package/lib/typescript/contexts/ReorderableListContext.d.ts +2 -1
  32. package/lib/typescript/contexts/ReorderableListContext.d.ts.map +1 -1
  33. package/lib/typescript/contexts/ScrollViewContainerContext.d.ts +3 -3
  34. package/lib/typescript/contexts/ScrollViewContainerContext.d.ts.map +1 -1
  35. package/lib/typescript/index.d.ts +2 -2
  36. package/lib/typescript/index.d.ts.map +1 -1
  37. package/lib/typescript/types/props.d.ts +18 -4
  38. package/lib/typescript/types/props.d.ts.map +1 -1
  39. package/package.json +1 -1
  40. package/src/components/NestedReorderableList.tsx +6 -6
  41. package/src/components/ReorderableList.tsx +3 -3
  42. package/src/components/ReorderableListCell.tsx +27 -19
  43. package/src/components/ReorderableListCore.tsx +277 -217
  44. package/src/components/ScrollViewContainer.tsx +27 -14
  45. package/src/contexts/ReorderableListContext.ts +2 -1
  46. package/src/contexts/ScrollViewContainerContext.ts +3 -3
  47. package/src/index.ts +2 -0
  48. package/src/types/props.ts +24 -5
@@ -23,9 +23,9 @@ const ReorderableListCore = ({
23
23
  onDragEnd,
24
24
  onIndexChange,
25
25
  scrollViewContainerRef,
26
- scrollViewPageY,
27
- scrollViewHeightY,
28
- scrollViewScrollOffsetY,
26
+ scrollViewPageXY,
27
+ scrollViewSize,
28
+ scrollViewScrollOffsetXY,
29
29
  scrollViewScrollEnabledProp,
30
30
  setScrollViewForceDisableScroll,
31
31
  scrollable,
@@ -50,35 +50,35 @@ const ReorderableListCore = ({
50
50
  const scrollEnabledProp = usePropAsSharedValue(scrollEnabled);
51
51
  const currentScrollEnabled = useSharedValue(scrollEnabled);
52
52
  const gestureState = useSharedValue(State.UNDETERMINED);
53
- const currentY = useSharedValue(0);
54
- const currentTranslationY = useSharedValue(0);
55
- const currentItemDragCenterY = useSharedValue(null);
56
- const startItemDragCenterY = useSharedValue(0);
57
- const flatListScrollOffsetY = useSharedValue(0);
58
- const flatListHeightY = useSharedValue(0);
59
- const flatListPageY = useSharedValue(0);
60
- // The scroll y translation of the list since drag start
61
- const dragScrollTranslationY = useSharedValue(0);
62
- // The initial scroll offset y of the list on drag start
63
- const dragInitialScrollOffsetY = useSharedValue(0);
64
- // The scroll y translation of the ScrollViewContainer since drag start
65
- const scrollViewDragScrollTranslationY = useSharedValue(0);
66
- // The initial scroll offset y of the ScrollViewContainer on drag start
67
- const scrollViewDragInitialScrollOffsetY = useSharedValue(0);
68
- const draggedHeight = useSharedValue(0);
53
+ const currentXY = useSharedValue(0);
54
+ const currentTranslationXY = useSharedValue(0);
55
+ const currentItemDragCenterXY = useSharedValue(null);
56
+ const startItemDragCenterXY = useSharedValue(0);
57
+ const flatListScrollOffsetXY = useSharedValue(0);
58
+ const flatListSize = useSharedValue(0);
59
+ const flatListPageXY = useSharedValue(0);
60
+ // The scroll x or y translation of the list since drag start
61
+ const dragScrollTranslationXY = useSharedValue(0);
62
+ // The initial scroll offset x or y of the list on drag start
63
+ const dragInitialScrollOffsetXY = useSharedValue(0);
64
+ // The scroll x or y translation of the ScrollViewContainer since drag start
65
+ const scrollViewDragScrollTranslationXY = useSharedValue(0);
66
+ // The initial scroll offset x or y of the ScrollViewContainer on drag start
67
+ const scrollViewDragInitialScrollOffsetXY = useSharedValue(0);
68
+ const draggedSize = useSharedValue(0);
69
69
  const itemOffset = useSharedValue([]);
70
- const itemHeight = useSharedValue([]);
71
- // We need to track data length since itemOffset and itemHeight might contain more data than we need.
70
+ const itemSize = useSharedValue([]);
71
+ // We need to track data length since itemOffset and itemSize might contain more data than we need.
72
72
  // e.g. items are removed from the list, in which case layout data for those items is set to 0.
73
73
  const itemCount = useSharedValue(data.length);
74
74
  const autoscrollTrigger = useSharedValue(-1);
75
75
  const lastAutoscrollTrigger = useSharedValue(-1);
76
- const dragY = useSharedValue(0);
76
+ const dragXY = useSharedValue(0);
77
77
  const currentIndex = useSharedValue(-1);
78
78
  const draggedIndex = useSharedValue(-1);
79
79
  const state = useSharedValue(ReorderableListState.IDLE);
80
80
  const dragEndHandlers = useSharedValue([]);
81
- const startY = useSharedValue(0);
81
+ const startXY = useSharedValue(0);
82
82
  const scaleDefault = useSharedValue(1);
83
83
  const opacityDefault = useSharedValue(1);
84
84
  const dragDirection = useSharedValue(0);
@@ -90,9 +90,10 @@ const ReorderableListCore = ({
90
90
  const animationDurationProp = usePropAsSharedValue(animationDuration);
91
91
  const autoscrollActivationDeltaProp = usePropAsSharedValue(autoscrollActivationDelta);
92
92
  const dragEnabledProp = usePropAsSharedValue(dragEnabled ?? true);
93
+ const horizontalProp = usePropAsSharedValue(!!rest.horizontal);
93
94
 
94
95
  // Position of the list relative to the scroll container
95
- const nestedFlatListPositionY = useDerivedValue(() => flatListPageY.value - ((scrollViewPageY === null || scrollViewPageY === void 0 ? void 0 : scrollViewPageY.value) || 0));
96
+ const nestedFlatListPositionXY = useDerivedValue(() => flatListPageXY.value - ((scrollViewPageXY === null || scrollViewPageXY === void 0 ? void 0 : scrollViewPageXY.value) || 0));
96
97
  useEffect(() => {
97
98
  itemCount.value = data.length;
98
99
 
@@ -102,13 +103,13 @@ const ReorderableListCore = ({
102
103
  if (data.length < prevItemCount.current) {
103
104
  for (let i = data.length; i < prevItemCount.current; i++) {
104
105
  runOnUI(() => {
105
- itemHeight.value[i] = 0;
106
+ itemSize.value[i] = 0;
106
107
  itemOffset.value[i] = 0;
107
108
  })();
108
109
  }
109
110
  }
110
111
  prevItemCount.current = data.length;
111
- }, [data.length, itemHeight, itemOffset, itemCount]);
112
+ }, [data.length, itemSize, itemOffset, itemCount]);
112
113
  useEffect(() => {
113
114
  if (!markedCellsRef.current ||
114
115
  // Clean keys once they surpass by 10% the size of the list itself.
@@ -141,12 +142,13 @@ const ReorderableListCore = ({
141
142
  return `${cellKey}#${mark}`;
142
143
  }, []);
143
144
  const listContextValue = useMemo(() => ({
144
- draggedHeight,
145
+ draggedSize,
145
146
  currentIndex,
146
147
  draggedIndex,
147
148
  dragEndHandlers,
148
149
  activeIndex,
149
150
  itemLayoutAnimation: itemLayoutAnimationPropRef,
151
+ horizontal: horizontalProp,
150
152
  cellAnimations: {
151
153
  ...cellAnimations,
152
154
  transform: cellAnimations && 'transform' in cellAnimations ? cellAnimations.transform : [{
@@ -154,7 +156,7 @@ const ReorderableListCore = ({
154
156
  }],
155
157
  opacity: cellAnimations && 'opacity' in cellAnimations ? cellAnimations.opacity : opacityDefault
156
158
  }
157
- }), [draggedHeight, currentIndex, draggedIndex, dragEndHandlers, activeIndex, cellAnimations, itemLayoutAnimationPropRef, scaleDefault, opacityDefault]);
159
+ }), [draggedSize, currentIndex, draggedIndex, dragEndHandlers, activeIndex, cellAnimations, itemLayoutAnimationPropRef, scaleDefault, opacityDefault, horizontalProp]);
158
160
 
159
161
  /**
160
162
  * Decides the intended drag direction of the user.
@@ -166,41 +168,46 @@ const ReorderableListCore = ({
166
168
  const setDragDirection = useCallback(e => {
167
169
  'worklet';
168
170
 
169
- const direction = e.velocityY > 0 ? 1 : -1;
171
+ const absoluteXY = horizontalProp.value ? e.absoluteX : e.absoluteY;
172
+ const velocityXY = horizontalProp.value ? e.velocityX : e.velocityY;
173
+ const direction = velocityXY > 0 ? 1 : -1;
170
174
  if (direction !== dragDirection.value) {
171
175
  if (lastDragDirectionPivot.value === null) {
172
- lastDragDirectionPivot.value = e.absoluteY;
173
- } else if (Math.abs(e.absoluteY - lastDragDirectionPivot.value) >= autoscrollActivationDeltaProp.value) {
176
+ lastDragDirectionPivot.value = absoluteXY;
177
+ } else if (Math.abs(absoluteXY - lastDragDirectionPivot.value) >= autoscrollActivationDeltaProp.value) {
174
178
  dragDirection.value = direction;
175
- lastDragDirectionPivot.value = e.absoluteY;
179
+ lastDragDirectionPivot.value = absoluteXY;
176
180
  }
177
181
  }
178
- }, [dragDirection, lastDragDirectionPivot, autoscrollActivationDeltaProp]);
179
- const setCurrentItemDragCenterY = useCallback(e => {
182
+ }, [dragDirection, lastDragDirectionPivot, autoscrollActivationDeltaProp, horizontalProp]);
183
+ const setCurrentItemDragCenterXY = useCallback(e => {
180
184
  'worklet';
181
185
 
182
- if (currentItemDragCenterY.value === null) {
186
+ const translationXY = horizontalProp.value ? e.translationX : e.translationY;
187
+ if (currentItemDragCenterXY.value === null) {
183
188
  if (currentIndex.value >= 0) {
184
- const itemCenter = itemHeight.value[currentIndex.value] * 0.5;
185
- // the y coordinate of the item relative to the list
186
- const itemY = itemOffset.value[currentIndex.value] - (flatListScrollOffsetY.value + scrollViewDragScrollTranslationY.value);
187
- const value = itemY + itemCenter + e.translationY;
188
- startItemDragCenterY.value = value;
189
- currentItemDragCenterY.value = value;
189
+ const itemCenter = itemSize.value[currentIndex.value] * 0.5;
190
+ // the x or y coordinate of the item relative to the list
191
+ const itemXY = itemOffset.value[currentIndex.value] - (flatListScrollOffsetXY.value + scrollViewDragScrollTranslationXY.value);
192
+ const value = itemXY + itemCenter + translationXY;
193
+ startItemDragCenterXY.value = value;
194
+ currentItemDragCenterXY.value = value;
190
195
  }
191
196
  } else {
192
- currentItemDragCenterY.value = startItemDragCenterY.value + e.translationY;
197
+ currentItemDragCenterXY.value = startItemDragCenterXY.value + translationXY;
193
198
  }
194
- }, [currentItemDragCenterY, currentIndex, startItemDragCenterY, itemOffset, itemHeight, flatListScrollOffsetY, scrollViewDragScrollTranslationY]);
199
+ }, [horizontalProp, currentItemDragCenterXY, currentIndex, startItemDragCenterXY, itemOffset, itemSize, flatListScrollOffsetXY, scrollViewDragScrollTranslationXY]);
195
200
  const panGestureHandler = useMemo(() => (panGesture || Gesture.Pan()).onBegin(e => {
196
201
  'worklet';
197
202
 
198
203
  // prevent new dragging until item is completely released
199
204
  if (state.value === ReorderableListState.IDLE) {
200
- startY.value = e.y;
201
- currentY.value = e.y;
202
- currentTranslationY.value = e.translationY;
203
- dragY.value = e.translationY;
205
+ const xy = horizontalProp.value ? e.x : e.y;
206
+ const translationXY = horizontalProp.value ? e.translationX : e.translationY;
207
+ startXY.value = xy;
208
+ currentXY.value = xy;
209
+ currentTranslationXY.value = translationXY;
210
+ dragXY.value = translationXY;
204
211
  gestureState.value = e.state;
205
212
  }
206
213
  }).onUpdate(e => {
@@ -210,10 +217,11 @@ const ReorderableListCore = ({
210
217
  setDragDirection(e);
211
218
  }
212
219
  if (state.value !== ReorderableListState.RELEASED) {
213
- setCurrentItemDragCenterY(e);
214
- currentY.value = startY.value + e.translationY;
215
- currentTranslationY.value = e.translationY;
216
- dragY.value = e.translationY + dragScrollTranslationY.value + scrollViewDragScrollTranslationY.value;
220
+ setCurrentItemDragCenterXY(e);
221
+ const translationXY = horizontalProp.value ? e.translationX : e.translationY;
222
+ currentXY.value = startXY.value + translationXY;
223
+ currentTranslationXY.value = translationXY;
224
+ dragXY.value = translationXY + dragScrollTranslationXY.value + scrollViewDragScrollTranslationXY.value;
217
225
  gestureState.value = e.state;
218
226
  }
219
227
  }).onEnd(e => {
@@ -224,7 +232,7 @@ const ReorderableListCore = ({
224
232
  'worklet';
225
233
 
226
234
  gestureState.value = e.state;
227
- }), [panGesture, state, startY, currentY, currentTranslationY, dragY, gestureState, dragScrollTranslationY, scrollViewDragScrollTranslationY, setDragDirection, setCurrentItemDragCenterY]);
235
+ }), [panGesture, state, startXY, currentXY, currentTranslationXY, dragXY, gestureState, dragScrollTranslationXY, scrollViewDragScrollTranslationXY, setDragDirection, setCurrentItemDragCenterXY, horizontalProp]);
228
236
  const panGestureHandlerWithPropOptions = useMemo(() => {
229
237
  if (typeof panActivateAfterLongPress === 'number') {
230
238
  panGestureHandler.activateAfterLongPress(panActivateAfterLongPress);
@@ -268,13 +276,13 @@ const ReorderableListCore = ({
268
276
 
269
277
  state.value = ReorderableListState.IDLE;
270
278
  draggedIndex.value = -1;
271
- dragY.value = 0;
272
- dragScrollTranslationY.value = 0;
273
- scrollViewDragScrollTranslationY.value = 0;
279
+ dragXY.value = 0;
280
+ dragScrollTranslationXY.value = 0;
281
+ scrollViewDragScrollTranslationXY.value = 0;
274
282
  dragDirection.value = 0;
275
283
  lastDragDirectionPivot.value = null;
276
- currentItemDragCenterY.value = null;
277
- }, [state, draggedIndex, dragY, dragScrollTranslationY, scrollViewDragScrollTranslationY, dragDirection, lastDragDirectionPivot, currentItemDragCenterY]);
284
+ currentItemDragCenterXY.value = null;
285
+ }, [state, draggedIndex, dragXY, dragScrollTranslationXY, scrollViewDragScrollTranslationXY, dragDirection, lastDragDirectionPivot, currentItemDragCenterXY]);
278
286
  const resetSharedValuesAfterAnimations = useCallback(() => {
279
287
  setTimeout(runOnUI(resetSharedValues), animationDurationProp.value);
280
288
  }, [resetSharedValues, animationDurationProp]);
@@ -311,14 +319,14 @@ const ReorderableListCore = ({
311
319
  const index1 = itemDirection ? from : to;
312
320
  const index2 = itemDirection ? to : from;
313
321
  const newOffset1 = itemOffset.value[index1];
314
- const newHeight1 = itemHeight.value[index2];
315
- const newOffset2 = itemOffset.value[index2] + itemHeight.value[index2] - itemHeight.value[index1];
316
- const newHeight2 = itemHeight.value[index1];
322
+ const newSize1 = itemSize.value[index2];
323
+ const newOffset2 = itemOffset.value[index2] + itemSize.value[index2] - itemSize.value[index1];
324
+ const newSize2 = itemSize.value[index1];
317
325
  itemOffset.value[index1] = newOffset1;
318
- itemHeight.value[index1] = newHeight1;
326
+ itemSize.value[index1] = newSize1;
319
327
  itemOffset.value[index2] = newOffset2;
320
- itemHeight.value[index2] = newHeight2;
321
- }, [itemOffset, itemHeight]);
328
+ itemSize.value[index2] = newSize2;
329
+ }, [itemOffset, itemSize]);
322
330
 
323
331
  /**
324
332
  * Computes a potential new drop container for the current dragged item and evaluates
@@ -330,29 +338,29 @@ const ReorderableListCore = ({
330
338
  const computeCurrentIndex = useCallback(() => {
331
339
  'worklet';
332
340
 
333
- if (currentItemDragCenterY.value === null) {
341
+ if (currentItemDragCenterXY.value === null) {
334
342
  return currentIndex.value;
335
343
  }
336
344
 
337
- // apply scroll offset and scroll container translation
338
- const relativeDragCenterY = flatListScrollOffsetY.value + scrollViewDragScrollTranslationY.value + currentItemDragCenterY.value;
345
+ // Apply scroll offset and scroll container translation.
346
+ const relativeDragCenterXY = flatListScrollOffsetXY.value + scrollViewDragScrollTranslationXY.value + currentItemDragCenterXY.value;
339
347
  const currentOffset = itemOffset.value[currentIndex.value];
340
- const currentHeight = itemHeight.value[currentIndex.value];
341
- const currentCenter = currentOffset + currentHeight * 0.5;
348
+ const currentSize = itemSize.value[currentIndex.value];
349
+ const currentCenter = currentOffset + currentSize * 0.5;
342
350
  const max = itemCount.value;
343
- const possibleIndex = relativeDragCenterY < currentCenter ? Math.max(0, currentIndex.value - 1) : Math.min(max - 1, currentIndex.value + 1);
351
+ const possibleIndex = relativeDragCenterXY < currentCenter ? Math.max(0, currentIndex.value - 1) : Math.min(max - 1, currentIndex.value + 1);
344
352
  if (currentIndex.value !== possibleIndex) {
345
353
  let possibleOffset = itemOffset.value[possibleIndex];
346
354
  if (possibleIndex > currentIndex.value) {
347
- possibleOffset += itemHeight.value[possibleIndex] - currentHeight;
355
+ possibleOffset += itemSize.value[possibleIndex] - currentSize;
348
356
  }
349
- const possibleCenter = possibleOffset + currentHeight * 0.5;
350
- const distanceFromCurrent = Math.abs(relativeDragCenterY - currentCenter);
351
- const distanceFromPossible = Math.abs(relativeDragCenterY - possibleCenter);
357
+ const possibleCenter = possibleOffset + currentSize * 0.5;
358
+ const distanceFromCurrent = Math.abs(relativeDragCenterXY - currentCenter);
359
+ const distanceFromPossible = Math.abs(relativeDragCenterXY - possibleCenter);
352
360
  return distanceFromCurrent <= distanceFromPossible ? currentIndex.value : possibleIndex;
353
361
  }
354
362
  return currentIndex.value;
355
- }, [currentIndex, currentItemDragCenterY, itemCount, itemOffset, itemHeight, flatListScrollOffsetY, scrollViewDragScrollTranslationY]);
363
+ }, [currentIndex, currentItemDragCenterXY, itemCount, itemOffset, itemSize, flatListScrollOffsetXY, scrollViewDragScrollTranslationXY]);
356
364
  const setCurrentIndex = useCallback(() => {
357
365
  'worklet';
358
366
 
@@ -374,7 +382,7 @@ const ReorderableListCore = ({
374
382
  scaleDefault.value = withTiming(scaleConfig.toValue, scaleConfig);
375
383
  }
376
384
 
377
- // if no custom opacity run the default
385
+ // If no custom opacity run the default.
378
386
  if (!(cellAnimations && 'opacity' in cellAnimations)) {
379
387
  const opacityConfig = OPACITY_ANIMATION_CONFIG_DEFAULT[type];
380
388
  opacityDefault.value = withTiming(opacityConfig.toValue, opacityConfig);
@@ -390,7 +398,7 @@ const ReorderableListCore = ({
390
398
  runOnJS(setActiveIndex)(-1);
391
399
  }
392
400
 
393
- // trigger onDragEnd event
401
+ // Trigger onDragEnd event.
394
402
  let e = {
395
403
  from: draggedIndex.value,
396
404
  to: currentIndex.value
@@ -403,23 +411,23 @@ const ReorderableListCore = ({
403
411
 
404
412
  // they are actually swapped on drag translation
405
413
  const currentItemOffset = itemOffset.value[draggedIndex.value];
406
- const currentItemHeight = itemHeight.value[draggedIndex.value];
414
+ const currentItemSize = itemSize.value[draggedIndex.value];
407
415
  const draggedItemOffset = itemOffset.value[currentIndex.value];
408
- const draggedItemHeight = itemHeight.value[currentIndex.value];
409
- const newTopPosition = currentIndex.value > draggedIndex.value ? draggedItemOffset - currentItemOffset : draggedItemOffset - currentItemOffset + (draggedItemHeight - currentItemHeight);
416
+ const draggedItemSize = itemSize.value[currentIndex.value];
417
+ const newPositionXY = currentIndex.value > draggedIndex.value ? draggedItemOffset - currentItemOffset : draggedItemOffset - currentItemOffset + (draggedItemSize - currentItemSize);
410
418
  runDefaultDragAnimations('end');
411
- if (dragY.value !== newTopPosition) {
412
- // animate dragged item to its new position on release
413
- dragY.value = withTiming(newTopPosition, {
419
+ if (dragXY.value !== newPositionXY) {
420
+ // Animate dragged item to its new position on release.
421
+ dragXY.value = withTiming(newPositionXY, {
414
422
  duration: animationDurationProp.value,
415
423
  easing: Easing.out(Easing.ease)
416
424
  }, () => {
417
425
  runOnJS(reorder)(draggedIndex.value, currentIndex.value);
418
426
  });
419
427
  } else {
420
- // user might drag and release the item without moving it so,
428
+ // User might drag and release the item without moving it so,
421
429
  // since the animation end callback is not executed in that case
422
- // we need to reset values as the reorder function would do
430
+ // we need to reset values as the reorder function would do.
423
431
  runOnJS(resetSharedValuesAfterAnimations)();
424
432
  }
425
433
  }
@@ -427,58 +435,58 @@ const ReorderableListCore = ({
427
435
  const computeHiddenArea = useCallback(() => {
428
436
  'worklet';
429
437
 
430
- if (!scrollViewScrollOffsetY || !scrollViewHeightY) {
438
+ if (!scrollViewScrollOffsetXY || !scrollViewSize) {
431
439
  return {
432
- top: 0,
433
- bottom: 0
440
+ start: 0,
441
+ end: 0
434
442
  };
435
443
  }
436
444
 
437
445
  // hidden area cannot be negative
438
- const top = Math.max(0, scrollViewScrollOffsetY.value - nestedFlatListPositionY.value);
439
- const bottom = Math.max(0, nestedFlatListPositionY.value + flatListHeightY.value - (scrollViewScrollOffsetY.value + scrollViewHeightY.value));
446
+ const start = Math.max(0, scrollViewScrollOffsetXY.value - nestedFlatListPositionXY.value);
447
+ const end = Math.max(0, nestedFlatListPositionXY.value + flatListSize.value - (scrollViewScrollOffsetXY.value + scrollViewSize.value));
440
448
  return {
441
- top,
442
- bottom
449
+ start,
450
+ end
443
451
  };
444
- }, [scrollViewScrollOffsetY, scrollViewHeightY, nestedFlatListPositionY, flatListHeightY]);
452
+ }, [scrollViewScrollOffsetXY, scrollViewSize, nestedFlatListPositionXY, flatListSize]);
445
453
  const computeThresholdArea = useCallback(() => {
446
454
  'worklet';
447
455
 
448
456
  const hiddenArea = computeHiddenArea();
449
- const offsetTop = Math.max(0, (autoscrollThresholdOffset === null || autoscrollThresholdOffset === void 0 ? void 0 : autoscrollThresholdOffset.top) || 0);
450
- const offsetBottom = Math.max(0, (autoscrollThresholdOffset === null || autoscrollThresholdOffset === void 0 ? void 0 : autoscrollThresholdOffset.bottom) || 0);
457
+ const offsetStart = Math.max(0, (autoscrollThresholdOffset === null || autoscrollThresholdOffset === void 0 ? void 0 : autoscrollThresholdOffset.start) || (autoscrollThresholdOffset === null || autoscrollThresholdOffset === void 0 ? void 0 : autoscrollThresholdOffset.top) || 0);
458
+ const offsetEnd = Math.max(0, (autoscrollThresholdOffset === null || autoscrollThresholdOffset === void 0 ? void 0 : autoscrollThresholdOffset.end) || (autoscrollThresholdOffset === null || autoscrollThresholdOffset === void 0 ? void 0 : autoscrollThresholdOffset.bottom) || 0);
451
459
  const threshold = Math.max(0, Math.min(autoscrollThreshold, 0.4));
452
- const visibleHeight = flatListHeightY.value - (hiddenArea.top + hiddenArea.bottom) - (offsetTop + offsetBottom);
453
- const area = visibleHeight * threshold;
454
- const top = area + offsetTop;
455
- const bottom = flatListHeightY.value - area - offsetBottom;
460
+ const visibleSize = flatListSize.value - (hiddenArea.start + hiddenArea.end) - (offsetStart + offsetEnd);
461
+ const area = visibleSize * threshold;
462
+ const start = area + offsetStart;
463
+ const end = flatListSize.value - area - offsetEnd;
456
464
  return {
457
- top,
458
- bottom
465
+ start,
466
+ end
459
467
  };
460
- }, [computeHiddenArea, autoscrollThreshold, autoscrollThresholdOffset, flatListHeightY]);
468
+ }, [computeHiddenArea, autoscrollThreshold, autoscrollThresholdOffset, flatListSize]);
461
469
  const computeContainerThresholdArea = useCallback(() => {
462
470
  'worklet';
463
471
 
464
- if (!scrollViewHeightY) {
472
+ if (!scrollViewSize) {
465
473
  return {
466
- top: -Infinity,
467
- bottom: Infinity
474
+ start: -Infinity,
475
+ end: Infinity
468
476
  };
469
477
  }
470
- const offsetTop = Math.max(0, (autoscrollThresholdOffset === null || autoscrollThresholdOffset === void 0 ? void 0 : autoscrollThresholdOffset.top) || 0);
471
- const offsetBottom = Math.max(0, (autoscrollThresholdOffset === null || autoscrollThresholdOffset === void 0 ? void 0 : autoscrollThresholdOffset.bottom) || 0);
478
+ const offsetStart = Math.max(0, (autoscrollThresholdOffset === null || autoscrollThresholdOffset === void 0 ? void 0 : autoscrollThresholdOffset.start) || (autoscrollThresholdOffset === null || autoscrollThresholdOffset === void 0 ? void 0 : autoscrollThresholdOffset.top) || 0);
479
+ const offsetEnd = Math.max(0, (autoscrollThresholdOffset === null || autoscrollThresholdOffset === void 0 ? void 0 : autoscrollThresholdOffset.end) || (autoscrollThresholdOffset === null || autoscrollThresholdOffset === void 0 ? void 0 : autoscrollThresholdOffset.bottom) || 0);
472
480
  const threshold = Math.max(0, Math.min(autoscrollThreshold, 0.4));
473
- const visibleHeight = scrollViewHeightY.value - (offsetTop + offsetBottom);
474
- const area = visibleHeight * threshold;
475
- const top = area + offsetTop;
476
- const bottom = visibleHeight - area - offsetBottom;
481
+ const visibleSize = scrollViewSize.value - (offsetStart + offsetEnd);
482
+ const area = visibleSize * threshold;
483
+ const start = area + offsetStart;
484
+ const end = visibleSize - area - offsetEnd;
477
485
  return {
478
- top,
479
- bottom
486
+ start,
487
+ end
480
488
  };
481
- }, [autoscrollThreshold, autoscrollThresholdOffset, scrollViewHeightY]);
489
+ }, [autoscrollThreshold, autoscrollThresholdOffset, scrollViewSize]);
482
490
  const shouldScrollContainer = useCallback(y => {
483
491
  'worklet';
484
492
 
@@ -487,52 +495,53 @@ const ReorderableListCore = ({
487
495
 
488
496
  // We should scroll the container if there's a hidden part of the nested list.
489
497
  // We might have floating errors like 0.0001 which we should ignore.
490
- return nestedListHiddenArea.top > 0.01 && y <= containerThresholdArea.top || nestedListHiddenArea.bottom > 0.01 && y >= containerThresholdArea.bottom;
498
+ return nestedListHiddenArea.start > 0.01 && y <= containerThresholdArea.start || nestedListHiddenArea.end > 0.01 && y >= containerThresholdArea.end;
491
499
  }, [computeHiddenArea, computeContainerThresholdArea]);
492
- const getRelativeContainerY = useCallback(() => {
500
+ const getRelativeContainerXY = useCallback(() => {
493
501
  'worklet';
494
502
 
495
- return currentY.value + nestedFlatListPositionY.value - scrollViewDragInitialScrollOffsetY.value;
496
- }, [currentY, nestedFlatListPositionY, scrollViewDragInitialScrollOffsetY]);
497
- const getRelativeListY = useCallback(() => {
503
+ return currentXY.value + nestedFlatListPositionXY.value - scrollViewDragInitialScrollOffsetXY.value;
504
+ }, [currentXY, nestedFlatListPositionXY, scrollViewDragInitialScrollOffsetXY]);
505
+ const getRelativeListXY = useCallback(() => {
498
506
  'worklet';
499
507
 
500
- return currentY.value + scrollViewDragScrollTranslationY.value;
501
- }, [currentY, scrollViewDragScrollTranslationY]);
508
+ return currentXY.value + scrollViewDragScrollTranslationXY.value;
509
+ }, [currentXY, scrollViewDragScrollTranslationXY]);
502
510
  const scrollDirection = useCallback(() => {
503
511
  'worklet';
504
512
 
505
- const relativeContainerY = getRelativeContainerY();
506
- if (shouldScrollContainer(relativeContainerY)) {
513
+ const relativeContainerXY = getRelativeContainerXY();
514
+ if (shouldScrollContainer(relativeContainerXY)) {
507
515
  const containerThresholdArea = computeContainerThresholdArea();
508
- if (relativeContainerY <= containerThresholdArea.top) {
516
+ if (relativeContainerXY <= containerThresholdArea.start) {
509
517
  return -1;
510
518
  }
511
- if (relativeContainerY >= containerThresholdArea.bottom) {
519
+ if (relativeContainerXY >= containerThresholdArea.end) {
512
520
  return 1;
513
521
  }
514
522
  } else if (scrollable) {
515
- const relativeListY = getRelativeListY();
523
+ const relativeListXY = getRelativeListXY();
516
524
  const thresholdArea = computeThresholdArea();
517
- if (relativeListY <= thresholdArea.top) {
525
+ if (relativeListXY <= thresholdArea.start) {
518
526
  return -1;
519
527
  }
520
- if (relativeListY >= thresholdArea.bottom) {
528
+ if (relativeListXY >= thresholdArea.end) {
521
529
  return 1;
522
530
  }
523
531
  }
524
532
  return 0;
525
- }, [shouldScrollContainer, computeThresholdArea, computeContainerThresholdArea, getRelativeContainerY, getRelativeListY, scrollable]);
526
- useAnimatedReaction(() => currentY.value, () => {
533
+ }, [shouldScrollContainer, computeThresholdArea, computeContainerThresholdArea, getRelativeContainerXY, getRelativeListXY, scrollable]);
534
+ useAnimatedReaction(() => currentXY.value, () => {
527
535
  if (state.value === ReorderableListState.DRAGGED || state.value === ReorderableListState.AUTOSCROLL) {
528
536
  setCurrentIndex();
529
537
 
530
538
  // Trigger autoscroll when:
531
- // 1. Within the threshold area (top or bottom of list)
539
+ // 1. Within the threshold area (start or end of list)
532
540
  // 2. Have dragged in the same direction as the scroll
533
541
  // 3. Not already in autoscroll mode
534
542
  if (dragDirection.value === scrollDirection()) {
535
- // When the first two conditions are met and it's already in autoscroll mode, we let it continue (no-op)
543
+ // When the first two conditions are met and it's already in autoscroll mode,
544
+ // we let it continue (no-op).
536
545
  if (state.value !== ReorderableListState.AUTOSCROLL) {
537
546
  state.value = ReorderableListState.AUTOSCROLL;
538
547
  lastAutoscrollTrigger.value = autoscrollTrigger.value;
@@ -547,17 +556,18 @@ const ReorderableListCore = ({
547
556
  if (autoscrollTrigger.value !== lastAutoscrollTrigger.value && state.value === ReorderableListState.AUTOSCROLL) {
548
557
  const autoscrollIncrement = dragDirection.value * AUTOSCROLL_CONFIG.increment * autoscrollSpeedScale;
549
558
  if (autoscrollIncrement !== 0) {
550
- let scrollOffset = flatListScrollOffsetY.value;
559
+ let scrollOffset = flatListScrollOffsetXY.value;
551
560
  let listRef = flatListRef;
552
561
 
553
562
  // Checking on every autoscroll whether to scroll the container,
554
563
  // this allows to smoothly pass the scroll from the container to the nested list
555
564
  // without any gesture input.
556
- if (scrollViewScrollOffsetY && shouldScrollContainer(getRelativeContainerY())) {
557
- scrollOffset = scrollViewScrollOffsetY.value;
565
+ if (scrollViewScrollOffsetXY && shouldScrollContainer(getRelativeContainerXY())) {
566
+ scrollOffset = scrollViewScrollOffsetXY.value;
558
567
  listRef = scrollViewContainerRef;
559
568
  }
560
- scrollTo(listRef, 0, scrollOffset + autoscrollIncrement, true);
569
+ const scrollToValue = scrollOffset + autoscrollIncrement;
570
+ scrollTo(listRef, horizontalProp.value ? scrollToValue : 0, horizontalProp.value ? 0 : scrollToValue, true);
561
571
  }
562
572
 
563
573
  // when autoscrolling user may not be moving his finger so we need
@@ -568,16 +578,16 @@ const ReorderableListCore = ({
568
578
 
569
579
  // flatlist scroll handler
570
580
  const handleScroll = useAnimatedScrollHandler(e => {
571
- flatListScrollOffsetY.value = e.contentOffset.y;
581
+ flatListScrollOffsetXY.value = horizontalProp.value ? e.contentOffset.x : e.contentOffset.y;
572
582
 
573
583
  // Checking if the list is not scrollable instead of the scrolling state.
574
584
  // Fixes a bug on iOS where the item is shifted after autoscrolling and then
575
585
  // moving away from the area.
576
586
  if (!currentScrollEnabled.value) {
577
- dragScrollTranslationY.value = flatListScrollOffsetY.value - dragInitialScrollOffsetY.value;
587
+ dragScrollTranslationXY.value = flatListScrollOffsetXY.value - dragInitialScrollOffsetXY.value;
578
588
  }
579
589
  if (state.value === ReorderableListState.AUTOSCROLL) {
580
- dragY.value = currentTranslationY.value + dragScrollTranslationY.value + scrollViewDragScrollTranslationY.value;
590
+ dragXY.value = currentTranslationXY.value + dragScrollTranslationXY.value + scrollViewDragScrollTranslationXY.value;
581
591
  lastAutoscrollTrigger.value = autoscrollTrigger.value;
582
592
  autoscrollTrigger.value = withDelay(autoscrollDelay, withTiming(autoscrollTrigger.value * -1, {
583
593
  duration: 0
@@ -586,16 +596,16 @@ const ReorderableListCore = ({
586
596
  });
587
597
 
588
598
  // container scroll handler
589
- useAnimatedReaction(() => scrollViewScrollOffsetY === null || scrollViewScrollOffsetY === void 0 ? void 0 : scrollViewScrollOffsetY.value, value => {
599
+ useAnimatedReaction(() => scrollViewScrollOffsetXY === null || scrollViewScrollOffsetXY === void 0 ? void 0 : scrollViewScrollOffsetXY.value, value => {
590
600
  if (value) {
591
601
  // Checking if the list is not scrollable instead of the scrolling state.
592
- // Fixes a bug on iOS where the item is shifted after autoscrolling and then
602
+ // Fixes a bug on iOS where the item is shifted, after autoscrolling and then
593
603
  // moving away from the area.
594
604
  if (!currentScrollEnabled.value) {
595
- scrollViewDragScrollTranslationY.value = value - scrollViewDragInitialScrollOffsetY.value;
605
+ scrollViewDragScrollTranslationXY.value = value - scrollViewDragInitialScrollOffsetXY.value;
596
606
  }
597
607
  if (state.value === ReorderableListState.AUTOSCROLL) {
598
- dragY.value = currentTranslationY.value + scrollViewDragScrollTranslationY.value;
608
+ dragXY.value = currentTranslationXY.value + scrollViewDragScrollTranslationXY.value;
599
609
  lastAutoscrollTrigger.value = autoscrollTrigger.value;
600
610
  autoscrollTrigger.value = withDelay(autoscrollDelay, withTiming(autoscrollTrigger.value * -1, {
601
611
  duration: 0
@@ -610,17 +620,17 @@ const ReorderableListCore = ({
610
620
  return;
611
621
  }
612
622
 
613
- // allow new drag when item is completely released
623
+ // Allow new drag when item is completely released.
614
624
  if (state.value === ReorderableListState.IDLE) {
615
- // resetting shared values again fixes a flickeing bug in nested lists where
616
- // after scrolling the parent list it would offset the new dragged item in another nested list
625
+ // Resetting shared values again fixes a flickeing bug in nested lists where
626
+ // after scrolling the parent list it would offset the new dragged item in another nested list.
617
627
  resetSharedValues();
618
628
  if (shouldUpdateActiveItem) {
619
629
  runOnJS(setActiveIndex)(index);
620
630
  }
621
- dragInitialScrollOffsetY.value = flatListScrollOffsetY.value;
622
- scrollViewDragInitialScrollOffsetY.value = (scrollViewScrollOffsetY === null || scrollViewScrollOffsetY === void 0 ? void 0 : scrollViewScrollOffsetY.value) || 0;
623
- draggedHeight.value = itemHeight.value[index];
631
+ dragInitialScrollOffsetXY.value = flatListScrollOffsetXY.value;
632
+ scrollViewDragInitialScrollOffsetXY.value = (scrollViewScrollOffsetXY === null || scrollViewScrollOffsetXY === void 0 ? void 0 : scrollViewScrollOffsetXY.value) || 0;
633
+ draggedSize.value = itemSize.value[index];
624
634
  draggedIndex.value = index;
625
635
  currentIndex.value = index;
626
636
  state.value = ReorderableListState.DRAGGED;
@@ -632,29 +642,30 @@ const ReorderableListCore = ({
632
642
  index
633
643
  });
634
644
  }
635
- }, [dragEnabledProp, resetSharedValues, shouldUpdateActiveItem, dragInitialScrollOffsetY, scrollViewScrollOffsetY, scrollViewDragInitialScrollOffsetY, setScrollEnabled, currentIndex, draggedHeight, draggedIndex, state, flatListScrollOffsetY, itemHeight, onDragStart, runDefaultDragAnimations]);
645
+ }, [dragEnabledProp, resetSharedValues, shouldUpdateActiveItem, dragInitialScrollOffsetXY, scrollViewScrollOffsetXY, scrollViewDragInitialScrollOffsetXY, setScrollEnabled, currentIndex, draggedSize, draggedIndex, state, flatListScrollOffsetXY, itemSize, onDragStart, runDefaultDragAnimations]);
636
646
  const handleFlatListLayout = useCallback(e => {
637
- flatListHeightY.value = e.nativeEvent.layout.height;
647
+ flatListSize.value = horizontalProp.value ? e.nativeEvent.layout.width : e.nativeEvent.layout.height;
638
648
 
639
649
  // If nested in a scroll container.
640
- if (scrollViewScrollOffsetY) {
641
- // Timeout fixes a bug where measure returns height 0.
650
+ if (scrollViewScrollOffsetXY) {
651
+ // Timeout fixes a bug where measure returns width or height 0.
642
652
  setTimeout(() => {
643
653
  runOnUI(() => {
644
654
  const measurement = measure(flatListRef);
645
655
  if (!measurement) {
646
656
  return;
647
657
  }
658
+ const pageXY = horizontalProp.value ? measurement.pageX : measurement.pageY;
648
659
 
649
660
  // We need to use pageY because the list might be nested into other views,
650
661
  // It's important that we take the measurement of the list without any scroll offset
651
662
  // from the scroll container.
652
- flatListPageY.value = measurement.pageY + ((scrollViewScrollOffsetY === null || scrollViewScrollOffsetY === void 0 ? void 0 : scrollViewScrollOffsetY.value) || 0);
663
+ flatListPageXY.value = pageXY + ((scrollViewScrollOffsetXY === null || scrollViewScrollOffsetXY === void 0 ? void 0 : scrollViewScrollOffsetXY.value) || 0);
653
664
  })();
654
665
  }, 100);
655
666
  }
656
667
  onLayout === null || onLayout === void 0 || onLayout(e);
657
- }, [flatListRef, flatListPageY, flatListHeightY, scrollViewScrollOffsetY, onLayout]);
668
+ }, [flatListRef, flatListPageXY, flatListSize, horizontalProp, scrollViewScrollOffsetXY, onLayout]);
658
669
  const handleRef = useCallback(value => {
659
670
  flatListRef(value);
660
671
  if (typeof ref === 'function') {
@@ -664,7 +675,7 @@ const ReorderableListCore = ({
664
675
  }
665
676
  }, [flatListRef, ref]);
666
677
  const combinedGesture = useMemo(() => {
667
- // android is able to handle nested scroll view, but not the full height ones like iOS
678
+ // Android is able to handle nested scroll view, but not the full size ones like iOS.
668
679
  if (outerScrollGesture && !(Platform.OS === 'android' && scrollable)) {
669
680
  return Gesture.Simultaneous(outerScrollGesture, gestureHandler);
670
681
  }
@@ -678,8 +689,8 @@ const ReorderableListCore = ({
678
689
  // forces remount with key change on reorder
679
690
  key: createCellKey(cellKey),
680
691
  itemOffset: itemOffset,
681
- itemHeight: itemHeight,
682
- dragY: dragY,
692
+ itemSize: itemSize,
693
+ dragXY: dragXY,
683
694
  draggedIndex: draggedIndex,
684
695
  animationDuration: animationDurationProp,
685
696
  startDrag: startDrag
@@ -696,7 +707,6 @@ const ReorderableListCore = ({
696
707
  onLayout: handleFlatListLayout,
697
708
  onScroll: composedScrollHandler,
698
709
  scrollEventThrottle: 1,
699
- horizontal: false,
700
710
  removeClippedSubviews: false,
701
711
  numColumns: 1
702
712
  // We force disable scroll or let the component prop control it.