@legendapp/list 1.0.0-beta.21 → 1.0.0-beta.23

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.
package/animated.d.mts CHANGED
@@ -3,7 +3,7 @@ import * as _legendapp_list from '@legendapp/list';
3
3
  import * as react_native from 'react-native';
4
4
  import { Animated } from 'react-native';
5
5
 
6
- declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<react_native.ScrollViewProps, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
6
+ declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<react_native.ScrollViewProps, "maintainVisibleContentPosition" | "stickyHeaderIndices" | "contentInset" | "contentOffset"> & {
7
7
  data: readonly T[];
8
8
  initialScrollOffset?: number;
9
9
  initialScrollIndex?: number;
package/animated.d.ts CHANGED
@@ -3,7 +3,7 @@ import * as _legendapp_list from '@legendapp/list';
3
3
  import * as react_native from 'react-native';
4
4
  import { Animated } from 'react-native';
5
5
 
6
- declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<react_native.ScrollViewProps, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
6
+ declare const AnimatedLegendList: Animated.AnimatedComponent<(<T>(props: Omit<react_native.ScrollViewProps, "maintainVisibleContentPosition" | "stickyHeaderIndices" | "contentInset" | "contentOffset"> & {
7
7
  data: readonly T[];
8
8
  initialScrollOffset?: number;
9
9
  initialScrollIndex?: number;
package/index.d.mts CHANGED
@@ -100,7 +100,7 @@ interface InternalState {
100
100
  isAtBottom: boolean;
101
101
  isAtTop: boolean;
102
102
  data: readonly any[];
103
- hasScrolled: boolean;
103
+ hasScrolled?: boolean;
104
104
  scrollLength: number;
105
105
  startBuffered: number;
106
106
  startBufferedId?: string;
@@ -135,6 +135,9 @@ interface InternalState {
135
135
  enableScrollForNextCalculateItemsInView: boolean;
136
136
  minIndexSizeChanged: number | undefined;
137
137
  numPendingInitialLayout: number;
138
+ queuedCalculateItemsInView: number | undefined;
139
+ lastBatchingAction: number;
140
+ ignoreScrollFromCalcTotal?: boolean;
138
141
  }
139
142
  interface ViewableRange<T> {
140
143
  startBuffered: number;
@@ -253,7 +256,7 @@ type TypedMemo = <T extends React.ComponentType<any>>(Component: T, propsAreEqua
253
256
  };
254
257
  declare const typedMemo: TypedMemo;
255
258
 
256
- declare const LegendList: <T>(props: Omit<react_native.ScrollViewProps, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
259
+ declare const LegendList: <T>(props: Omit<react_native.ScrollViewProps, "maintainVisibleContentPosition" | "stickyHeaderIndices" | "contentInset" | "contentOffset"> & {
257
260
  data: readonly T[];
258
261
  initialScrollOffset?: number;
259
262
  initialScrollIndex?: number;
package/index.d.ts CHANGED
@@ -100,7 +100,7 @@ interface InternalState {
100
100
  isAtBottom: boolean;
101
101
  isAtTop: boolean;
102
102
  data: readonly any[];
103
- hasScrolled: boolean;
103
+ hasScrolled?: boolean;
104
104
  scrollLength: number;
105
105
  startBuffered: number;
106
106
  startBufferedId?: string;
@@ -135,6 +135,9 @@ interface InternalState {
135
135
  enableScrollForNextCalculateItemsInView: boolean;
136
136
  minIndexSizeChanged: number | undefined;
137
137
  numPendingInitialLayout: number;
138
+ queuedCalculateItemsInView: number | undefined;
139
+ lastBatchingAction: number;
140
+ ignoreScrollFromCalcTotal?: boolean;
138
141
  }
139
142
  interface ViewableRange<T> {
140
143
  startBuffered: number;
@@ -253,7 +256,7 @@ type TypedMemo = <T extends React.ComponentType<any>>(Component: T, propsAreEqua
253
256
  };
254
257
  declare const typedMemo: TypedMemo;
255
258
 
256
- declare const LegendList: <T>(props: Omit<react_native.ScrollViewProps, "contentOffset" | "contentInset" | "maintainVisibleContentPosition" | "stickyHeaderIndices"> & {
259
+ declare const LegendList: <T>(props: Omit<react_native.ScrollViewProps, "maintainVisibleContentPosition" | "stickyHeaderIndices" | "contentInset" | "contentOffset"> & {
257
260
  data: readonly T[];
258
261
  initialScrollOffset?: number;
259
262
  initialScrollIndex?: number;
package/index.js CHANGED
@@ -239,6 +239,7 @@ var Container = ({
239
239
  const itemKey = use$(`containerItemKey${id}`);
240
240
  const data = use$(`containerItemData${id}`);
241
241
  const extraData = use$("extraData");
242
+ const refLastSize = React6.useRef();
242
243
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
243
244
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
244
245
  let verticalPaddingStyles;
@@ -246,9 +247,7 @@ var Container = ({
246
247
  const { columnGap, rowGap, gap } = columnWrapperStyle;
247
248
  verticalPaddingStyles = {
248
249
  paddingBottom: !lastItemKeys.has(itemKey) ? rowGap || gap || void 0 : void 0,
249
- // Apply horizontal padding based on column position (first, middle, or last)
250
- paddingLeft: column > 1 ? (columnGap || gap || 0) / 2 : void 0,
251
- paddingRight: column < numColumns ? (columnGap || gap || 0) / 2 : void 0
250
+ paddingHorizontal: (columnGap || gap || 0) / 2
252
251
  };
253
252
  }
254
253
  const style = horizontal ? {
@@ -286,7 +285,8 @@ var Container = ({
286
285
  }
287
286
  return;
288
287
  }
289
- updateItemSize(id, itemKey, size);
288
+ refLastSize.current = size;
289
+ updateItemSize(itemKey, size);
290
290
  }
291
291
  };
292
292
  const ref = React6.useRef(null);
@@ -298,11 +298,24 @@ var Container = ({
298
298
  if (measured) {
299
299
  const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
300
300
  if (size) {
301
- updateItemSize(id, itemKey, size);
301
+ updateItemSize(itemKey, size);
302
302
  }
303
303
  }
304
304
  }
305
305
  }, [itemKey]);
306
+ } else {
307
+ React6.useEffect(() => {
308
+ if (itemKey) {
309
+ const timeout = setTimeout(() => {
310
+ if (refLastSize.current) {
311
+ updateItemSize(itemKey, refLastSize.current);
312
+ }
313
+ }, 16);
314
+ return () => {
315
+ clearTimeout(timeout);
316
+ };
317
+ }
318
+ }, [itemKey]);
306
319
  }
307
320
  const contextValue = React6.useMemo(
308
321
  () => ({ containerId: id, itemKey, index, value: data }),
@@ -357,6 +370,9 @@ var Containers = typedMemo(function Containers2({
357
370
  updateItemSize,
358
371
  getRenderedItem
359
372
  }) {
373
+ const ctx = useStateContext();
374
+ const columnWrapperStyle = ctx.columnWrapperStyle;
375
+ const numColumns = use$("numColumns");
360
376
  const numContainers = use$("numContainersPooled");
361
377
  const animSize = useValue$(
362
378
  "totalSizeWithScrollAdjust",
@@ -383,6 +399,13 @@ var Containers = typedMemo(function Containers2({
383
399
  );
384
400
  }
385
401
  const style = horizontal ? { width: animSize, opacity: animOpacity } : { height: animSize, opacity: animOpacity };
402
+ if (columnWrapperStyle && !horizontal && numColumns > 1) {
403
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
404
+ const mx = (columnGap || gap || 0) / 2;
405
+ if (mx) {
406
+ style.marginHorizontal = -mx;
407
+ }
408
+ }
386
409
  return /* @__PURE__ */ React6__namespace.createElement(reactNative.Animated.View, { style }, containers);
387
410
  });
388
411
 
@@ -687,11 +710,13 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
687
710
  }
688
711
  }
689
712
  function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index) {
690
- const { sizes, positions, scroll } = state;
713
+ const { sizes, positions, scroll: scrollState, scrollAdjustHandler } = state;
691
714
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
692
715
  const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
693
716
  const viewAreaMode = viewAreaCoveragePercentThreshold != null;
694
717
  const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
718
+ const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
719
+ const scroll = scrollState - previousScrollAdjust - topPad;
695
720
  const top = positions.get(key) - scroll + topPad;
696
721
  const size = sizes.get(key) || 0;
697
722
  const bottom = top + size;
@@ -848,7 +873,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
848
873
  isAtBottom: false,
849
874
  isAtTop: false,
850
875
  data: dataProp,
851
- hasScrolled: false,
852
876
  scrollLength: initialScrollLength,
853
877
  startBuffered: 0,
854
878
  startNoBuffer: 0,
@@ -878,7 +902,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
878
902
  scrollForNextCalculateItemsInView: void 0,
879
903
  enableScrollForNextCalculateItemsInView: true,
880
904
  minIndexSizeChanged: 0,
881
- numPendingInitialLayout: 0
905
+ numPendingInitialLayout: 0,
906
+ queuedCalculateItemsInView: 0,
907
+ lastBatchingAction: Date.now()
882
908
  };
883
909
  if (maintainVisibleContentPosition) {
884
910
  if (initialScrollIndex) {
@@ -1001,7 +1027,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1001
1027
  }
1002
1028
  return res;
1003
1029
  };
1004
- const calculateItemsInView = React6.useCallback((speed) => {
1030
+ const calculateItemsInView = React6.useCallback(() => {
1005
1031
  var _a2;
1006
1032
  const state = refState.current;
1007
1033
  const {
@@ -1011,7 +1037,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1011
1037
  startBufferedId: startBufferedIdOrig,
1012
1038
  positions,
1013
1039
  columns,
1014
- scrollAdjustHandler
1040
+ scrollAdjustHandler,
1041
+ scrollVelocity: speed
1015
1042
  } = state;
1016
1043
  if (!data || scrollLength === 0) {
1017
1044
  return;
@@ -1370,7 +1397,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1370
1397
  if (!keyExtractorProp) {
1371
1398
  state.positions.clear();
1372
1399
  }
1373
- calculateItemsInView(state.scrollVelocity);
1400
+ calculateItemsInView();
1374
1401
  const didMaintainScrollAtEnd = doMaintainScrollAtEnd(false);
1375
1402
  if (!didMaintainScrollAtEnd && dataProp.length > state.data.length) {
1376
1403
  state.isEndReached = false;
@@ -1419,7 +1446,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1419
1446
  (_a2 = refState.current.belowAnchorElementPositions) == null ? void 0 : _a2.clear();
1420
1447
  (_b2 = refScroller.current) == null ? void 0 : _b2.scrollTo({ x: 0, y: 0, animated: false });
1421
1448
  setTimeout(() => {
1422
- calculateItemsInView(0);
1449
+ calculateItemsInView();
1423
1450
  }, 0);
1424
1451
  } else {
1425
1452
  refState.current.startBufferedId = void 0;
@@ -1434,7 +1461,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1434
1461
  }
1435
1462
  (_c2 = refScroller.current) == null ? void 0 : _c2.scrollTo({ x: 0, y: 0, animated: false });
1436
1463
  setTimeout(() => {
1437
- calculateItemsInView(0);
1464
+ calculateItemsInView();
1438
1465
  }, 0);
1439
1466
  }
1440
1467
  }
@@ -1457,10 +1484,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1457
1484
  if (maxSizeInRow > 0) {
1458
1485
  totalSize += maxSizeInRow;
1459
1486
  }
1487
+ const state = refState.current;
1488
+ state.ignoreScrollFromCalcTotal = true;
1489
+ requestAnimationFrame(() => {
1490
+ state.ignoreScrollFromCalcTotal = false;
1491
+ });
1460
1492
  addTotalSize(null, totalSize, totalSizeBelowIndex);
1461
1493
  };
1462
1494
  const isFirst = !refState.current.renderItem;
1463
1495
  if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
1496
+ refState.current.lastBatchingAction = Date.now();
1464
1497
  if (!keyExtractorProp && !isFirst && didDataChange) {
1465
1498
  refState.current.sizes.clear();
1466
1499
  refState.current.positions.clear();
@@ -1541,10 +1574,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1541
1574
  set$(ctx, "numContainersPooled", numContainers * 2);
1542
1575
  if (initialScrollIndex) {
1543
1576
  requestAnimationFrame(() => {
1544
- calculateItemsInView(state.scrollVelocity);
1577
+ calculateItemsInView();
1545
1578
  });
1546
1579
  } else {
1547
- calculateItemsInView(state.scrollVelocity);
1580
+ calculateItemsInView();
1548
1581
  }
1549
1582
  }
1550
1583
  };
@@ -1555,7 +1588,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1555
1588
  state.enableScrollForNextCalculateItemsInView = !viewability;
1556
1589
  doInitialAllocateContainers();
1557
1590
  });
1558
- const updateItemSize = React6.useCallback((containerId, itemKey, size) => {
1591
+ const updateItemSize = React6.useCallback((itemKey, size) => {
1559
1592
  const state = refState.current;
1560
1593
  const { sizes, indexByKey, sizesLaidOut, data, rowHeights } = state;
1561
1594
  if (!data) {
@@ -1625,27 +1658,30 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1625
1658
  if (needsCalculate) {
1626
1659
  const scrollVelocity = state.scrollVelocity;
1627
1660
  if ((Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1) && (!waitForInitialLayout || state.numPendingInitialLayout < 0)) {
1628
- calculateItemsInView(state.scrollVelocity);
1661
+ if (Date.now() - state.lastBatchingAction < 500) {
1662
+ state.queuedCalculateItemsInView = requestAnimationFrame(() => {
1663
+ state.queuedCalculateItemsInView = void 0;
1664
+ calculateItemsInView();
1665
+ });
1666
+ } else {
1667
+ calculateItemsInView();
1668
+ }
1629
1669
  }
1630
1670
  }
1631
1671
  }, []);
1632
- const handleScrollDebounced = React6.useCallback((velocity) => {
1633
- calculateItemsInView(velocity);
1634
- checkAtBottom();
1635
- checkAtTop();
1636
- }, []);
1637
1672
  const onLayout = React6.useCallback((event) => {
1673
+ const state = refState.current;
1638
1674
  const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
1639
- const didChange = scrollLength !== refState.current.scrollLength;
1640
- refState.current.scrollLength;
1641
- refState.current.scrollLength = scrollLength;
1675
+ const didChange = scrollLength !== state.scrollLength;
1676
+ state.scrollLength = scrollLength;
1677
+ state.lastBatchingAction = Date.now();
1642
1678
  doInitialAllocateContainers();
1643
1679
  doMaintainScrollAtEnd(false);
1644
1680
  doUpdatePaddingTop();
1645
1681
  checkAtBottom();
1646
1682
  checkAtTop();
1647
1683
  if (didChange) {
1648
- calculateItemsInView(0);
1684
+ calculateItemsInView();
1649
1685
  }
1650
1686
  if (__DEV__) {
1651
1687
  const isWidthZero = event.nativeEvent.layout.width === 0;
@@ -1667,7 +1703,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1667
1703
  return;
1668
1704
  }
1669
1705
  const state = refState.current;
1706
+ if (state.ignoreScrollFromCalcTotal) {
1707
+ return;
1708
+ }
1670
1709
  state.hasScrolled = true;
1710
+ state.lastBatchingAction = Date.now();
1671
1711
  const currentTime = performance.now();
1672
1712
  const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
1673
1713
  if (!(state.scrollHistory.length === 0 && newScroll === initialContentOffset)) {
@@ -1695,7 +1735,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1695
1735
  state.scroll = newScroll;
1696
1736
  state.scrollTime = currentTime;
1697
1737
  state.scrollVelocity = velocity;
1698
- handleScrollDebounced(velocity);
1738
+ calculateItemsInView();
1739
+ checkAtBottom();
1740
+ checkAtTop();
1699
1741
  if (!fromSelf) {
1700
1742
  onScrollProp == null ? void 0 : onScrollProp(event);
1701
1743
  }
@@ -1734,7 +1776,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1734
1776
  if (wasAdjusted) {
1735
1777
  refState.current.scrollVelocity = 0;
1736
1778
  refState.current.scrollHistory = [];
1737
- calculateItemsInView(0);
1779
+ calculateItemsInView();
1738
1780
  }
1739
1781
  },
1740
1782
  animated ? 1e3 : 50
@@ -1785,7 +1827,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1785
1827
  if (wasPaused) {
1786
1828
  refState.current.scrollVelocity = 0;
1787
1829
  refState.current.scrollHistory = [];
1788
- calculateItemsInView(0);
1830
+ calculateItemsInView();
1789
1831
  }
1790
1832
  if (onMomentumScrollEnd) {
1791
1833
  onMomentumScrollEnd(event);
package/index.mjs CHANGED
@@ -218,6 +218,7 @@ var Container = ({
218
218
  const itemKey = use$(`containerItemKey${id}`);
219
219
  const data = use$(`containerItemData${id}`);
220
220
  const extraData = use$("extraData");
221
+ const refLastSize = useRef();
221
222
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
222
223
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
223
224
  let verticalPaddingStyles;
@@ -225,9 +226,7 @@ var Container = ({
225
226
  const { columnGap, rowGap, gap } = columnWrapperStyle;
226
227
  verticalPaddingStyles = {
227
228
  paddingBottom: !lastItemKeys.has(itemKey) ? rowGap || gap || void 0 : void 0,
228
- // Apply horizontal padding based on column position (first, middle, or last)
229
- paddingLeft: column > 1 ? (columnGap || gap || 0) / 2 : void 0,
230
- paddingRight: column < numColumns ? (columnGap || gap || 0) / 2 : void 0
229
+ paddingHorizontal: (columnGap || gap || 0) / 2
231
230
  };
232
231
  }
233
232
  const style = horizontal ? {
@@ -265,7 +264,8 @@ var Container = ({
265
264
  }
266
265
  return;
267
266
  }
268
- updateItemSize(id, itemKey, size);
267
+ refLastSize.current = size;
268
+ updateItemSize(itemKey, size);
269
269
  }
270
270
  };
271
271
  const ref = useRef(null);
@@ -277,11 +277,24 @@ var Container = ({
277
277
  if (measured) {
278
278
  const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
279
279
  if (size) {
280
- updateItemSize(id, itemKey, size);
280
+ updateItemSize(itemKey, size);
281
281
  }
282
282
  }
283
283
  }
284
284
  }, [itemKey]);
285
+ } else {
286
+ useEffect(() => {
287
+ if (itemKey) {
288
+ const timeout = setTimeout(() => {
289
+ if (refLastSize.current) {
290
+ updateItemSize(itemKey, refLastSize.current);
291
+ }
292
+ }, 16);
293
+ return () => {
294
+ clearTimeout(timeout);
295
+ };
296
+ }
297
+ }, [itemKey]);
285
298
  }
286
299
  const contextValue = useMemo(
287
300
  () => ({ containerId: id, itemKey, index, value: data }),
@@ -336,6 +349,9 @@ var Containers = typedMemo(function Containers2({
336
349
  updateItemSize,
337
350
  getRenderedItem
338
351
  }) {
352
+ const ctx = useStateContext();
353
+ const columnWrapperStyle = ctx.columnWrapperStyle;
354
+ const numColumns = use$("numColumns");
339
355
  const numContainers = use$("numContainersPooled");
340
356
  const animSize = useValue$(
341
357
  "totalSizeWithScrollAdjust",
@@ -362,6 +378,13 @@ var Containers = typedMemo(function Containers2({
362
378
  );
363
379
  }
364
380
  const style = horizontal ? { width: animSize, opacity: animOpacity } : { height: animSize, opacity: animOpacity };
381
+ if (columnWrapperStyle && !horizontal && numColumns > 1) {
382
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
383
+ const mx = (columnGap || gap || 0) / 2;
384
+ if (mx) {
385
+ style.marginHorizontal = -mx;
386
+ }
387
+ }
365
388
  return /* @__PURE__ */ React6.createElement(Animated.View, { style }, containers);
366
389
  });
367
390
 
@@ -666,11 +689,13 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
666
689
  }
667
690
  }
668
691
  function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index) {
669
- const { sizes, positions, scroll } = state;
692
+ const { sizes, positions, scroll: scrollState, scrollAdjustHandler } = state;
670
693
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
671
694
  const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
672
695
  const viewAreaMode = viewAreaCoveragePercentThreshold != null;
673
696
  const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
697
+ const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
698
+ const scroll = scrollState - previousScrollAdjust - topPad;
674
699
  const top = positions.get(key) - scroll + topPad;
675
700
  const size = sizes.get(key) || 0;
676
701
  const bottom = top + size;
@@ -827,7 +852,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
827
852
  isAtBottom: false,
828
853
  isAtTop: false,
829
854
  data: dataProp,
830
- hasScrolled: false,
831
855
  scrollLength: initialScrollLength,
832
856
  startBuffered: 0,
833
857
  startNoBuffer: 0,
@@ -857,7 +881,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
857
881
  scrollForNextCalculateItemsInView: void 0,
858
882
  enableScrollForNextCalculateItemsInView: true,
859
883
  minIndexSizeChanged: 0,
860
- numPendingInitialLayout: 0
884
+ numPendingInitialLayout: 0,
885
+ queuedCalculateItemsInView: 0,
886
+ lastBatchingAction: Date.now()
861
887
  };
862
888
  if (maintainVisibleContentPosition) {
863
889
  if (initialScrollIndex) {
@@ -980,7 +1006,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
980
1006
  }
981
1007
  return res;
982
1008
  };
983
- const calculateItemsInView = useCallback((speed) => {
1009
+ const calculateItemsInView = useCallback(() => {
984
1010
  var _a2;
985
1011
  const state = refState.current;
986
1012
  const {
@@ -990,7 +1016,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
990
1016
  startBufferedId: startBufferedIdOrig,
991
1017
  positions,
992
1018
  columns,
993
- scrollAdjustHandler
1019
+ scrollAdjustHandler,
1020
+ scrollVelocity: speed
994
1021
  } = state;
995
1022
  if (!data || scrollLength === 0) {
996
1023
  return;
@@ -1349,7 +1376,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1349
1376
  if (!keyExtractorProp) {
1350
1377
  state.positions.clear();
1351
1378
  }
1352
- calculateItemsInView(state.scrollVelocity);
1379
+ calculateItemsInView();
1353
1380
  const didMaintainScrollAtEnd = doMaintainScrollAtEnd(false);
1354
1381
  if (!didMaintainScrollAtEnd && dataProp.length > state.data.length) {
1355
1382
  state.isEndReached = false;
@@ -1398,7 +1425,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1398
1425
  (_a2 = refState.current.belowAnchorElementPositions) == null ? void 0 : _a2.clear();
1399
1426
  (_b2 = refScroller.current) == null ? void 0 : _b2.scrollTo({ x: 0, y: 0, animated: false });
1400
1427
  setTimeout(() => {
1401
- calculateItemsInView(0);
1428
+ calculateItemsInView();
1402
1429
  }, 0);
1403
1430
  } else {
1404
1431
  refState.current.startBufferedId = void 0;
@@ -1413,7 +1440,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1413
1440
  }
1414
1441
  (_c2 = refScroller.current) == null ? void 0 : _c2.scrollTo({ x: 0, y: 0, animated: false });
1415
1442
  setTimeout(() => {
1416
- calculateItemsInView(0);
1443
+ calculateItemsInView();
1417
1444
  }, 0);
1418
1445
  }
1419
1446
  }
@@ -1436,10 +1463,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1436
1463
  if (maxSizeInRow > 0) {
1437
1464
  totalSize += maxSizeInRow;
1438
1465
  }
1466
+ const state = refState.current;
1467
+ state.ignoreScrollFromCalcTotal = true;
1468
+ requestAnimationFrame(() => {
1469
+ state.ignoreScrollFromCalcTotal = false;
1470
+ });
1439
1471
  addTotalSize(null, totalSize, totalSizeBelowIndex);
1440
1472
  };
1441
1473
  const isFirst = !refState.current.renderItem;
1442
1474
  if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
1475
+ refState.current.lastBatchingAction = Date.now();
1443
1476
  if (!keyExtractorProp && !isFirst && didDataChange) {
1444
1477
  refState.current.sizes.clear();
1445
1478
  refState.current.positions.clear();
@@ -1520,10 +1553,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1520
1553
  set$(ctx, "numContainersPooled", numContainers * 2);
1521
1554
  if (initialScrollIndex) {
1522
1555
  requestAnimationFrame(() => {
1523
- calculateItemsInView(state.scrollVelocity);
1556
+ calculateItemsInView();
1524
1557
  });
1525
1558
  } else {
1526
- calculateItemsInView(state.scrollVelocity);
1559
+ calculateItemsInView();
1527
1560
  }
1528
1561
  }
1529
1562
  };
@@ -1534,7 +1567,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1534
1567
  state.enableScrollForNextCalculateItemsInView = !viewability;
1535
1568
  doInitialAllocateContainers();
1536
1569
  });
1537
- const updateItemSize = useCallback((containerId, itemKey, size) => {
1570
+ const updateItemSize = useCallback((itemKey, size) => {
1538
1571
  const state = refState.current;
1539
1572
  const { sizes, indexByKey, sizesLaidOut, data, rowHeights } = state;
1540
1573
  if (!data) {
@@ -1604,27 +1637,30 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1604
1637
  if (needsCalculate) {
1605
1638
  const scrollVelocity = state.scrollVelocity;
1606
1639
  if ((Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1) && (!waitForInitialLayout || state.numPendingInitialLayout < 0)) {
1607
- calculateItemsInView(state.scrollVelocity);
1640
+ if (Date.now() - state.lastBatchingAction < 500) {
1641
+ state.queuedCalculateItemsInView = requestAnimationFrame(() => {
1642
+ state.queuedCalculateItemsInView = void 0;
1643
+ calculateItemsInView();
1644
+ });
1645
+ } else {
1646
+ calculateItemsInView();
1647
+ }
1608
1648
  }
1609
1649
  }
1610
1650
  }, []);
1611
- const handleScrollDebounced = useCallback((velocity) => {
1612
- calculateItemsInView(velocity);
1613
- checkAtBottom();
1614
- checkAtTop();
1615
- }, []);
1616
1651
  const onLayout = useCallback((event) => {
1652
+ const state = refState.current;
1617
1653
  const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
1618
- const didChange = scrollLength !== refState.current.scrollLength;
1619
- refState.current.scrollLength;
1620
- refState.current.scrollLength = scrollLength;
1654
+ const didChange = scrollLength !== state.scrollLength;
1655
+ state.scrollLength = scrollLength;
1656
+ state.lastBatchingAction = Date.now();
1621
1657
  doInitialAllocateContainers();
1622
1658
  doMaintainScrollAtEnd(false);
1623
1659
  doUpdatePaddingTop();
1624
1660
  checkAtBottom();
1625
1661
  checkAtTop();
1626
1662
  if (didChange) {
1627
- calculateItemsInView(0);
1663
+ calculateItemsInView();
1628
1664
  }
1629
1665
  if (__DEV__) {
1630
1666
  const isWidthZero = event.nativeEvent.layout.width === 0;
@@ -1646,7 +1682,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1646
1682
  return;
1647
1683
  }
1648
1684
  const state = refState.current;
1685
+ if (state.ignoreScrollFromCalcTotal) {
1686
+ return;
1687
+ }
1649
1688
  state.hasScrolled = true;
1689
+ state.lastBatchingAction = Date.now();
1650
1690
  const currentTime = performance.now();
1651
1691
  const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
1652
1692
  if (!(state.scrollHistory.length === 0 && newScroll === initialContentOffset)) {
@@ -1674,7 +1714,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1674
1714
  state.scroll = newScroll;
1675
1715
  state.scrollTime = currentTime;
1676
1716
  state.scrollVelocity = velocity;
1677
- handleScrollDebounced(velocity);
1717
+ calculateItemsInView();
1718
+ checkAtBottom();
1719
+ checkAtTop();
1678
1720
  if (!fromSelf) {
1679
1721
  onScrollProp == null ? void 0 : onScrollProp(event);
1680
1722
  }
@@ -1713,7 +1755,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1713
1755
  if (wasAdjusted) {
1714
1756
  refState.current.scrollVelocity = 0;
1715
1757
  refState.current.scrollHistory = [];
1716
- calculateItemsInView(0);
1758
+ calculateItemsInView();
1717
1759
  }
1718
1760
  },
1719
1761
  animated ? 1e3 : 50
@@ -1764,7 +1806,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1764
1806
  if (wasPaused) {
1765
1807
  refState.current.scrollVelocity = 0;
1766
1808
  refState.current.scrollHistory = [];
1767
- calculateItemsInView(0);
1809
+ calculateItemsInView();
1768
1810
  }
1769
1811
  if (onMomentumScrollEnd) {
1770
1812
  onMomentumScrollEnd(event);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "1.0.0-beta.21",
3
+ "version": "1.0.0-beta.23",
4
4
  "description": "Legend List aims to be a drop-in replacement for FlatList with much better performance and supporting dynamically sized items.",
5
5
  "sideEffects": false,
6
6
  "private": false,