@souscheflabs/reanimated-flashlist 0.3.2 → 0.3.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"AnimatedFlashList.d.ts","sourceRoot":"","sources":["../src/AnimatedFlashList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAaf,OAAO,KAAK,EACV,gBAAgB,EAChB,sBAAsB,EACtB,oBAAoB,EAErB,MAAM,SAAS,CAAC;AA0YjB,eAAO,MAAM,iBAAiB,EAAyC,CACrE,CAAC,SAAS,gBAAgB,EAE1B,KAAK,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,oBAAoB,CAAC,CAAA;CAAE,KAClF,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC"}
1
+ {"version":3,"file":"AnimatedFlashList.d.ts","sourceRoot":"","sources":["../src/AnimatedFlashList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAaf,OAAO,KAAK,EACV,gBAAgB,EAChB,sBAAsB,EACtB,oBAAoB,EAErB,MAAM,SAAS,CAAC;AAyYjB,eAAO,MAAM,iBAAiB,EAAyC,CACrE,CAAC,SAAS,gBAAgB,EAE1B,KAAK,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,oBAAoB,CAAC,CAAA;CAAE,KAClF,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC"}
@@ -46,13 +46,17 @@ const ItemWrapper = react_1.default.memo(function ItemWrapper({ item, index, tot
46
46
  });
47
47
  function InnerFlashList({ data, totalItemsRef, flashListRef, renderItem, keyExtractor, canDrag, dragEnabled, onReorderByDelta, onHapticFeedback, itemHeight, ListFooterComponent, onEndReached, onEndReachedThreshold, onRefresh, refreshing, refreshTintColor, contentContainerStyle, drawDistance = 500, showsVerticalScrollIndicator = true, }) {
48
48
  // Get drag state context for scroll tracking
49
- const { scrollOffset, contentHeight, visibleHeight, listTopY, setListRef } = (0, contexts_1.useDragState)();
49
+ const { scrollOffset, contentHeight, visibleHeight, listTopY, setListRef, totalItems } = (0, contexts_1.useDragState)();
50
50
  // Register FlashList ref with drag context for autoscroll
51
51
  (0, react_1.useEffect)(() => {
52
52
  // Cast to unknown to satisfy the generic constraint
53
53
  setListRef(flashListRef.current);
54
54
  return () => setListRef(null);
55
55
  }, [setListRef, flashListRef]);
56
+ // Sync totalItems SharedValue with data.length for worklet access
57
+ (0, react_1.useEffect)(() => {
58
+ totalItems.value = data.length;
59
+ }, [data.length, totalItems]);
56
60
  // Update scroll offset on scroll
57
61
  const handleScroll = (0, react_1.useCallback)((event) => {
58
62
  scrollOffset.value = event.nativeEvent.contentOffset.y;
@@ -127,17 +131,11 @@ function AnimatedFlashListInner(props, ref) {
127
131
  const { data, keyExtractor, renderItem, dragEnabled = false, onReorder, onReorderByNeighbors, canDrag, onHapticFeedback, config, onPrepareLayoutAnimation, ListFooterComponent, onRefresh, refreshing = false, onEndReached, onEndReachedThreshold = 0.5, contentContainerStyle, estimatedItemSize, ...flashListProps } = props;
128
132
  // Merge config with defaults
129
133
  // Use estimatedItemSize as default itemHeight if not explicitly configured
130
- const dragConfig = (0, react_1.useMemo)(() => {
131
- const mergedConfig = {
132
- ...constants_1.DEFAULT_DRAG_CONFIG,
133
- ...config?.drag,
134
- itemHeight: config?.drag?.itemHeight ?? estimatedItemSize ?? constants_1.DEFAULT_DRAG_CONFIG.itemHeight,
135
- };
136
- if (__DEV__) {
137
- console.log(`[AnimatedFlashList] dragConfig.itemHeight=${mergedConfig.itemHeight}, estimatedItemSize=${estimatedItemSize}, config.drag?.itemHeight=${config?.drag?.itemHeight}`);
138
- }
139
- return mergedConfig;
140
- }, [config?.drag, estimatedItemSize]);
134
+ const dragConfig = (0, react_1.useMemo)(() => ({
135
+ ...constants_1.DEFAULT_DRAG_CONFIG,
136
+ ...config?.drag,
137
+ itemHeight: config?.drag?.itemHeight ?? estimatedItemSize ?? constants_1.DEFAULT_DRAG_CONFIG.itemHeight,
138
+ }), [config?.drag, estimatedItemSize]);
141
139
  // Ref to FlashList
142
140
  const flashListRef = (0, react_1.useRef)(null);
143
141
  // Expose methods to parent via ref
@@ -1 +1 @@
1
- {"version":3,"file":"AnimatedFlashListItem.d.ts","sourceRoot":"","sources":["../src/AnimatedFlashListItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAwD,MAAM,OAAO,CAAC;AAY7E,OAAO,KAAK,EACV,gBAAgB,EAChB,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB,UAAU,0BAA0B,CAAC,CAAC,SAAS,gBAAgB;IAC7D,oBAAoB;IACpB,IAAI,EAAE,CAAC,CAAC;IACR,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,aAAa,EAAE,OAAO,CAAC;IACvB,kCAAkC;IAClC,UAAU,EAAE,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,YAAY,CAAC;IACpE,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACvD;AAED;;;;;;;;;;GAUG;AACH,iBAAS,0BAA0B,CAAC,CAAC,SAAS,gBAAgB,EAAE,EAC9D,IAAI,EACJ,KAAK,EACL,UAAU,EACV,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,gBAAgB,GACjB,EAAE,0BAA0B,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAmK3D;AAGD,eAAO,MAAM,qBAAqB,EAE7B,OAAO,0BAA0B,CAAC"}
1
+ {"version":3,"file":"AnimatedFlashListItem.d.ts","sourceRoot":"","sources":["../src/AnimatedFlashListItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAwD,MAAM,OAAO,CAAC;AAY7E,OAAO,KAAK,EACV,gBAAgB,EAChB,sBAAsB,EACtB,kBAAkB,EACnB,MAAM,SAAS,CAAC;AAEjB,UAAU,0BAA0B,CAAC,CAAC,SAAS,gBAAgB;IAC7D,oBAAoB;IACpB,IAAI,EAAE,CAAC,CAAC;IACR,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,aAAa,EAAE,OAAO,CAAC;IACvB,kCAAkC;IAClC,UAAU,EAAE,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,YAAY,CAAC;IACpE,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;CACvD;AAED;;;;;;;;;;GAUG;AACH,iBAAS,0BAA0B,CAAC,CAAC,SAAS,gBAAgB,EAAE,EAC9D,IAAI,EACJ,KAAK,EACL,UAAU,EACV,aAAa,EACb,UAAU,EACV,gBAAgB,EAChB,gBAAgB,GACjB,EAAE,0BAA0B,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CA8J3D;AAGD,eAAO,MAAM,qBAAqB,EAE7B,OAAO,0BAA0B,CAAC"}
@@ -50,10 +50,6 @@ const contexts_1 = require("./contexts");
50
50
  * @internal
51
51
  */
52
52
  function AnimatedFlashListItemInner({ item, index, totalItems, isDragEnabled, renderItem, onReorderByDelta, onHapticFeedback, }) {
53
- // DEBUG: Log renders
54
- if (__DEV__) {
55
- console.log(`[AnimatedFlashListItem] RENDER ${item.id} at index=${index}`);
56
- }
57
53
  // Register this item's index in the central registry
58
54
  // This handles FlashList's recycling behavior where components may not re-render
59
55
  // after data changes, leaving their index props stale
@@ -72,10 +68,10 @@ function AnimatedFlashListItemInner({ item, index, totalItems, isDragEnabled, re
72
68
  const animationContext = (0, contexts_1.useListAnimationOptional)();
73
69
  // === DRAG HOOKS ===
74
70
  // Pan gesture for drag-to-reorder
71
+ // Note: totalItems is now accessed via SharedValue from DragStateContext
75
72
  const { panGesture, isDragging, translateY } = (0, hooks_1.useDragGesture)({
76
73
  itemId: item.id,
77
74
  index,
78
- totalItems,
79
75
  enabled: isDragEnabled,
80
76
  containerRef,
81
77
  }, {
@@ -80,6 +80,8 @@ export interface DragStateContextValue {
80
80
  * Call this from handleDragEnd after onEnd updates the registry.
81
81
  */
82
82
  markRegistryUpdated: () => void;
83
+ /** Total number of items in the list (synced from data.length) */
84
+ totalItems: SharedValue<number>;
83
85
  }
84
86
  /**
85
87
  * Hook to access shared drag state from context.
@@ -1 +1 @@
1
- {"version":3,"file":"DragStateContext.d.ts","sourceRoot":"","sources":["../../src/contexts/DragStateContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAMZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAgC3C;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC,2CAA2C;IAC3C,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,oEAAoE;IACpE,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,oFAAoF;IACpF,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,iFAAiF;IACjF,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,sEAAsE;IACtE,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,+DAA+D;IAC/D,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,uFAAuF;IACvF,qBAAqB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,yEAAyE;IACzE,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,qDAAqD;IACrD,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,mFAAmF;IACnF,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9B,4EAA4E;IAC5E,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACxC,yDAAyD;IACzD,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,gFAAgF;IAChF,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,2DAA2D;IAC3D,UAAU,EAAE,CAAC,GAAG,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;IACxD,wEAAwE;IACxE,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7D,6EAA6E;IAC7E,+BAA+B,EAAE,MAAM,IAAI,CAAC;IAC5C,sDAAsD;IACtD,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,iCAAiC;IACjC,MAAM,EAAE,UAAU,CAAC;IACnB;;;;OAIG;IACH,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,mEAAmE;IACnE,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,4CAA4C;IAC5C,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACrD;;;;OAIG;IACH,sBAAsB,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5D;;;OAGG;IACH,uBAAuB,EAAE,MAAM,IAAI,CAAC;IACpC;;;OAGG;IACH,sBAAsB,EAAE,CACtB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,KACZ,IAAI,CAAC;IACV;;;OAGG;IACH,mBAAmB,EAAE,MAAM,IAAI,CAAC;CACjC;AAID;;;GAGG;AACH,eAAO,MAAM,YAAY,QAAO,qBAM/B,CAAC;AAEF,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,SAAS,CAAC;IACpB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;CAC9B;AAmDD,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAyO9D,CAAC"}
1
+ {"version":3,"file":"DragStateContext.d.ts","sourceRoot":"","sources":["../../src/contexts/DragStateContext.tsx"],"names":[],"mappings":"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"}
@@ -136,6 +136,8 @@ const DragStateProvider = ({ children, config: configOverrides, }) => {
136
136
  const itemIndexRegistry = (0, react_native_reanimated_1.useSharedValue)({});
137
137
  // Snapshot of registry taken at drag start for consistent index lookup during drag
138
138
  const dragStartIndexSnapshot = (0, react_native_reanimated_1.useSharedValue)({});
139
+ // Total number of items in the list (synced from data.length by InnerFlashList)
140
+ const totalItems = (0, react_native_reanimated_1.useSharedValue)(0);
139
141
  // Timestamp when registry was last updated by onEnd (for protecting against stale overwrites)
140
142
  const registryUpdateTimestamp = (0, react_1.useRef)(0);
141
143
  // Ref to FlashList for autoscroll operations
@@ -258,6 +260,7 @@ const DragStateProvider = ({ children, config: configOverrides, }) => {
258
260
  snapshotRegistryForDrag,
259
261
  applyReorderToRegistry,
260
262
  markRegistryUpdated,
263
+ totalItems,
261
264
  }), [
262
265
  isDragging,
263
266
  draggedIndex,
@@ -283,6 +286,7 @@ const DragStateProvider = ({ children, config: configOverrides, }) => {
283
286
  snapshotRegistryForDrag,
284
287
  applyReorderToRegistry,
285
288
  markRegistryUpdated,
289
+ totalItems,
286
290
  ]);
287
291
  return (<DragStateContext.Provider value={value}>
288
292
  {children}
@@ -1 +1 @@
1
- {"version":3,"file":"useDragGesture.d.ts","sourceRoot":"","sources":["../../../src/hooks/drag/useDragGesture.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,oBAAoB,EAC5B,SAAS,EAAE,uBAAuB,GACjC,oBAAoB,CAybtB"}
1
+ {"version":3,"file":"useDragGesture.d.ts","sourceRoot":"","sources":["../../../src/hooks/drag/useDragGesture.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,oBAAoB,EAC5B,SAAS,EAAE,uBAAuB,GACjC,oBAAoB,CA2btB"}
@@ -35,7 +35,7 @@ const DragStateContext_1 = require("../../contexts/DragStateContext");
35
35
  * ```
36
36
  */
37
37
  function useDragGesture(config, callbacks) {
38
- const { itemId, index, totalItems, enabled, containerRef } = config;
38
+ const { itemId, index, enabled, containerRef } = config;
39
39
  const { onReorderByDelta, onHapticFeedback } = callbacks;
40
40
  // Dev-only guard to warn once if measurement is missing
41
41
  const hasWarnedMissingHeight = (0, react_1.useRef)(false);
@@ -43,7 +43,7 @@ function useDragGesture(config, callbacks) {
43
43
  const isDragging = (0, react_native_reanimated_1.useSharedValue)(false);
44
44
  const translateY = (0, react_native_reanimated_1.useSharedValue)(0);
45
45
  // Global drag state for coordinating animations across all items
46
- const { isDragging: globalIsDragging, draggedIndex, draggedItemId, currentTranslateY, draggedScale, scrollOffset, dragStartScrollOffset, contentHeight, visibleHeight, listTopY, measuredItemHeight, isDropping, scrollToOffset, prepareForLayoutAnimationRender, config: dragConfig, itemIndexRegistry, dragStartIndexSnapshot, dragSequence, markRegistryUpdated, } = (0, DragStateContext_1.useDragState)();
46
+ const { isDragging: globalIsDragging, draggedIndex, draggedItemId, currentTranslateY, draggedScale, scrollOffset, dragStartScrollOffset, contentHeight, visibleHeight, listTopY, measuredItemHeight, isDropping, scrollToOffset, prepareForLayoutAnimationRender, config: dragConfig, itemIndexRegistry, dragStartIndexSnapshot, dragSequence, markRegistryUpdated, totalItems, } = (0, DragStateContext_1.useDragState)();
47
47
  // Performance optimization: Track last significant Y position and scroll time
48
48
  // to avoid updating on every pixel movement
49
49
  const lastSignificantY = (0, react_native_reanimated_1.useSharedValue)(0);
@@ -82,20 +82,20 @@ function useDragGesture(config, callbacks) {
82
82
  currentIndex.value = index;
83
83
  }, [index, currentIndex]);
84
84
  // Store current values in refs for stable gesture callbacks
85
+ // Note: totalItems is now a SharedValue from context, accessed directly in worklets
85
86
  const dragContextRef = (0, react_1.useRef)({
86
- totalItems,
87
87
  itemId,
88
88
  onReorderByDelta,
89
89
  });
90
90
  // Keep ref in sync with current values
91
91
  dragContextRef.current = {
92
- totalItems,
93
92
  itemId,
94
93
  onReorderByDelta,
95
94
  };
96
95
  // Calculate new position and call reorder callback
97
96
  const handleDragEnd = (0, react_1.useCallback)((finalTranslateY) => {
98
- const { totalItems: total, itemId: currentItemId, onReorderByDelta: reorder, } = dragContextRef.current;
97
+ const { itemId: currentItemId, onReorderByDelta: reorder, } = dragContextRef.current;
98
+ const total = totalItems.value;
99
99
  // Use draggedIndex from context, which was set in onStart using the registry
100
100
  // This handles FlashList's recycling where closure-captured index may be stale
101
101
  const currentIndex = draggedIndex.value;
@@ -184,6 +184,7 @@ function useDragGesture(config, callbacks) {
184
184
  onHapticFeedback,
185
185
  dragSequence,
186
186
  markRegistryUpdated,
187
+ totalItems,
187
188
  ]);
188
189
  // Stable haptic callback for drag start
189
190
  const triggerLightHaptic = (0, react_1.useCallback)(() => {
@@ -301,7 +302,7 @@ function useDragGesture(config, callbacks) {
301
302
  // runs on the JS thread, which would cause the new drag's snapshot to have
302
303
  // stale indices.
303
304
  const currentIdx = draggedIndex.value;
304
- const total = dragContextRef.current.totalItems;
305
+ const total = totalItems.value;
305
306
  // Use measured item height for accurate position calculations
306
307
  // Fall back to config height if measurement failed or not yet available
307
308
  const itemHeight = measuredItemHeight.value > 0
@@ -371,6 +372,7 @@ function useDragGesture(config, callbacks) {
371
372
  itemId,
372
373
  dragStartIndexSnapshot,
373
374
  itemIndexRegistry,
375
+ totalItems,
374
376
  ]);
375
377
  return { panGesture, isDragging, translateY };
376
378
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useDropCompensation.d.ts","sourceRoot":"","sources":["../../../src/hooks/drag/useDropCompensation.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,yBAAyB,GAAG,IAAI,CA+I3E"}
1
+ {"version":3,"file":"useDropCompensation.d.ts","sourceRoot":"","sources":["../../../src/hooks/drag/useDropCompensation.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,yBAAyB,GAAG,IAAI,CA0I3E"}
@@ -84,9 +84,6 @@ function useDropCompensation(config) {
84
84
  }
85
85
  else {
86
86
  // Normal index change (not during drop): apply compensation
87
- if (__DEV__) {
88
- console.log("[DROP-COMP] Non-dragged normal index change - compensating");
89
- }
90
87
  translateY.value = (0, react_native_reanimated_1.withTiming)(compensatedY, {
91
88
  duration: constants_1.ANIMATION_TIMING.COMPENSATION_DURATION,
92
89
  easing: react_native_reanimated_1.Easing.out(react_native_reanimated_1.Easing.ease),
@@ -28,8 +28,6 @@ export interface UseDragGestureConfig {
28
28
  itemId: string;
29
29
  /** Current index in list */
30
30
  index: number;
31
- /** Total number of items in the list */
32
- totalItems: number;
33
31
  /** Whether drag is enabled for this item */
34
32
  enabled: boolean;
35
33
  /** Ref to measure item container */
@@ -1 +1 @@
1
- {"version":3,"file":"drag.d.ts","sourceRoot":"","sources":["../../src/types/drag.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,+BAA+B;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,aAAa,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,oCAAoC;IACpC,YAAY,EAAE,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,KAAK,IAAI,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,UAAU,EAAE,WAAW,CAAC;IACxB,mDAAmD;IACnD,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,sCAAsC;IACtC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,yDAAyD;IACzD,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,sEAAsE;IACtE,iBAAiB,EAAE,UAAU,CAAC,cAAc,yBAAyB,EAAE,gBAAgB,CAAC,CAAC;CAC1F"}
1
+ {"version":3,"file":"drag.d.ts","sourceRoot":"","sources":["../../src/types/drag.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,+BAA+B;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,aAAa,EAAE,MAAM,CAAC;IACtB,+CAA+C;IAC/C,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,oCAAoC;IACpC,YAAY,EAAE,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,KAAK,IAAI,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,UAAU,EAAE,WAAW,CAAC;IACxB,mDAAmD;IACnD,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,sCAAsC;IACtC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC,yDAAyD;IACzD,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,sEAAsE;IACtE,iBAAiB,EAAE,UAAU,CAAC,cAAc,yBAAyB,EAAE,gBAAgB,CAAC,CAAC;CAC1F"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@souscheflabs/reanimated-flashlist",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "A high-performance animated FlashList with drag-to-reorder and entry/exit animations (New Architecture)",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/index.js",
@@ -112,7 +112,7 @@ function InnerFlashList<T extends AnimatedListItem>({
112
112
  showsVerticalScrollIndicator = true,
113
113
  }: InnerFlashListProps<T>): React.ReactElement {
114
114
  // Get drag state context for scroll tracking
115
- const { scrollOffset, contentHeight, visibleHeight, listTopY, setListRef } =
115
+ const { scrollOffset, contentHeight, visibleHeight, listTopY, setListRef, totalItems } =
116
116
  useDragState();
117
117
 
118
118
  // Register FlashList ref with drag context for autoscroll
@@ -122,6 +122,11 @@ function InnerFlashList<T extends AnimatedListItem>({
122
122
  return () => setListRef(null);
123
123
  }, [setListRef, flashListRef]);
124
124
 
125
+ // Sync totalItems SharedValue with data.length for worklet access
126
+ useEffect(() => {
127
+ totalItems.value = data.length;
128
+ }, [data.length, totalItems]);
129
+
125
130
  // Update scroll offset on scroll
126
131
  const handleScroll = useCallback(
127
132
  (event: NativeSyntheticEvent<NativeScrollEvent>) => {
@@ -285,17 +290,11 @@ function AnimatedFlashListInner<T extends AnimatedListItem>(
285
290
  // Merge config with defaults
286
291
  // Use estimatedItemSize as default itemHeight if not explicitly configured
287
292
  const dragConfig = useMemo(
288
- () => {
289
- const mergedConfig = {
290
- ...DEFAULT_DRAG_CONFIG,
291
- ...config?.drag,
292
- itemHeight: config?.drag?.itemHeight ?? estimatedItemSize ?? DEFAULT_DRAG_CONFIG.itemHeight,
293
- };
294
- if (__DEV__) {
295
- console.log(`[AnimatedFlashList] dragConfig.itemHeight=${mergedConfig.itemHeight}, estimatedItemSize=${estimatedItemSize}, config.drag?.itemHeight=${config?.drag?.itemHeight}`);
296
- }
297
- return mergedConfig;
298
- },
293
+ () => ({
294
+ ...DEFAULT_DRAG_CONFIG,
295
+ ...config?.drag,
296
+ itemHeight: config?.drag?.itemHeight ?? estimatedItemSize ?? DEFAULT_DRAG_CONFIG.itemHeight,
297
+ }),
299
298
  [config?.drag, estimatedItemSize],
300
299
  );
301
300
 
@@ -53,11 +53,6 @@ function AnimatedFlashListItemInner<T extends AnimatedListItem>({
53
53
  onReorderByDelta,
54
54
  onHapticFeedback,
55
55
  }: AnimatedFlashListItemProps<T>): React.ReactElement | null {
56
- // DEBUG: Log renders
57
- if (__DEV__) {
58
- console.log(`[AnimatedFlashListItem] RENDER ${item.id} at index=${index}`);
59
- }
60
-
61
56
  // Register this item's index in the central registry
62
57
  // This handles FlashList's recycling behavior where components may not re-render
63
58
  // after data changes, leaving their index props stale
@@ -82,11 +77,11 @@ function AnimatedFlashListItemInner<T extends AnimatedListItem>({
82
77
  // === DRAG HOOKS ===
83
78
 
84
79
  // Pan gesture for drag-to-reorder
80
+ // Note: totalItems is now accessed via SharedValue from DragStateContext
85
81
  const { panGesture, isDragging, translateY } = useDragGesture(
86
82
  {
87
83
  itemId: item.id,
88
84
  index,
89
- totalItems,
90
85
  enabled: isDragEnabled,
91
86
  containerRef,
92
87
  },
@@ -123,6 +123,8 @@ export interface DragStateContextValue {
123
123
  * Call this from handleDragEnd after onEnd updates the registry.
124
124
  */
125
125
  markRegistryUpdated: () => void;
126
+ /** Total number of items in the list (synced from data.length) */
127
+ totalItems: SharedValue<number>;
126
128
  }
127
129
 
128
130
  const DragStateContext = createContext<DragStateContextValue | null>(null);
@@ -236,6 +238,9 @@ export const DragStateProvider: React.FC<DragStateProviderProps> = ({
236
238
  // Snapshot of registry taken at drag start for consistent index lookup during drag
237
239
  const dragStartIndexSnapshot = useSharedValue<Record<string, number>>({});
238
240
 
241
+ // Total number of items in the list (synced from data.length by InnerFlashList)
242
+ const totalItems = useSharedValue(0);
243
+
239
244
  // Timestamp when registry was last updated by onEnd (for protecting against stale overwrites)
240
245
  const registryUpdateTimestamp = useRef<number>(0);
241
246
 
@@ -393,6 +398,7 @@ export const DragStateProvider: React.FC<DragStateProviderProps> = ({
393
398
  snapshotRegistryForDrag,
394
399
  applyReorderToRegistry,
395
400
  markRegistryUpdated,
401
+ totalItems,
396
402
  }),
397
403
  [
398
404
  isDragging,
@@ -419,6 +425,7 @@ export const DragStateProvider: React.FC<DragStateProviderProps> = ({
419
425
  snapshotRegistryForDrag,
420
426
  applyReorderToRegistry,
421
427
  markRegistryUpdated,
428
+ totalItems,
422
429
  ],
423
430
  );
424
431
 
@@ -55,7 +55,7 @@ export function useDragGesture(
55
55
  config: UseDragGestureConfig,
56
56
  callbacks: UseDragGestureCallbacks,
57
57
  ): UseDragGestureResult {
58
- const { itemId, index, totalItems, enabled, containerRef } = config;
58
+ const { itemId, index, enabled, containerRef } = config;
59
59
  const { onReorderByDelta, onHapticFeedback } = callbacks;
60
60
 
61
61
  // Dev-only guard to warn once if measurement is missing
@@ -86,6 +86,7 @@ export function useDragGesture(
86
86
  dragStartIndexSnapshot,
87
87
  dragSequence,
88
88
  markRegistryUpdated,
89
+ totalItems,
89
90
  } = useDragState();
90
91
 
91
92
  // Performance optimization: Track last significant Y position and scroll time
@@ -131,15 +132,14 @@ export function useDragGesture(
131
132
  }, [index, currentIndex]);
132
133
 
133
134
  // Store current values in refs for stable gesture callbacks
135
+ // Note: totalItems is now a SharedValue from context, accessed directly in worklets
134
136
  const dragContextRef = useRef({
135
- totalItems,
136
137
  itemId,
137
138
  onReorderByDelta,
138
139
  });
139
140
 
140
141
  // Keep ref in sync with current values
141
142
  dragContextRef.current = {
142
- totalItems,
143
143
  itemId,
144
144
  onReorderByDelta,
145
145
  };
@@ -148,10 +148,10 @@ export function useDragGesture(
148
148
  const handleDragEnd = useCallback(
149
149
  (finalTranslateY: number) => {
150
150
  const {
151
- totalItems: total,
152
151
  itemId: currentItemId,
153
152
  onReorderByDelta: reorder,
154
153
  } = dragContextRef.current;
154
+ const total = totalItems.value;
155
155
 
156
156
  // Use draggedIndex from context, which was set in onStart using the registry
157
157
  // This handles FlashList's recycling where closure-captured index may be stale
@@ -266,6 +266,7 @@ export function useDragGesture(
266
266
  onHapticFeedback,
267
267
  dragSequence,
268
268
  markRegistryUpdated,
269
+ totalItems,
269
270
  ],
270
271
  );
271
272
 
@@ -416,7 +417,7 @@ export function useDragGesture(
416
417
  // runs on the JS thread, which would cause the new drag's snapshot to have
417
418
  // stale indices.
418
419
  const currentIdx = draggedIndex.value;
419
- const total = dragContextRef.current.totalItems;
420
+ const total = totalItems.value;
420
421
  // Use measured item height for accurate position calculations
421
422
  // Fall back to config height if measurement failed or not yet available
422
423
  const itemHeight =
@@ -491,6 +492,7 @@ export function useDragGesture(
491
492
  itemId,
492
493
  dragStartIndexSnapshot,
493
494
  itemIndexRegistry,
495
+ totalItems,
494
496
  ],
495
497
  );
496
498
 
@@ -110,11 +110,6 @@ export function useDropCompensation(config: UseDropCompensationConfig): void {
110
110
  translateY.value = 0;
111
111
  } else {
112
112
  // Normal index change (not during drop): apply compensation
113
- if (__DEV__) {
114
- console.log(
115
- "[DROP-COMP] Non-dragged normal index change - compensating",
116
- );
117
- }
118
113
  translateY.value = withTiming(compensatedY, {
119
114
  duration: ANIMATION_TIMING.COMPENSATION_DURATION,
120
115
  easing: Easing.out(Easing.ease),
package/src/types/drag.ts CHANGED
@@ -30,8 +30,6 @@ export interface UseDragGestureConfig {
30
30
  itemId: string;
31
31
  /** Current index in list */
32
32
  index: number;
33
- /** Total number of items in the list */
34
- totalItems: number;
35
33
  /** Whether drag is enabled for this item */
36
34
  enabled: boolean;
37
35
  /** Ref to measure item container */