@legendapp/list 2.0.0-next.1 → 2.0.0-next.10

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/index.js CHANGED
@@ -24,21 +24,23 @@ function _interopNamespace(e) {
24
24
 
25
25
  var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
26
26
 
27
- // src/LegendList.tsx
27
+ // src/components/LazyLegendList.tsx
28
28
  var ContextState = React3__namespace.createContext(null);
29
29
  function StateProvider({ children }) {
30
30
  const [value] = React3__namespace.useState(() => ({
31
+ columnWrapperStyle: void 0,
31
32
  listeners: /* @__PURE__ */ new Map(),
33
+ mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
34
+ mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
35
+ mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
36
+ mapViewabilityValues: /* @__PURE__ */ new Map(),
32
37
  values: /* @__PURE__ */ new Map([
33
38
  ["alignItemsPaddingTop", 0],
34
39
  ["stylePaddingTop", 0],
35
- ["headerSize", 0]
40
+ ["headerSize", 0],
41
+ ["numContainers", 0],
42
+ ["totalSize", 0]
36
43
  ]),
37
- mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
38
- mapViewabilityValues: /* @__PURE__ */ new Map(),
39
- mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
40
- mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
41
- columnWrapperStyle: void 0,
42
44
  viewRefs: /* @__PURE__ */ new Map()
43
45
  }));
44
46
  return /* @__PURE__ */ React3__namespace.createElement(ContextState.Provider, { value }, children);
@@ -50,17 +52,6 @@ function createSelectorFunctionsArr(ctx, signalNames) {
50
52
  let lastValues = [];
51
53
  let lastSignalValues = [];
52
54
  return {
53
- subscribe: (cb) => {
54
- const listeners = [];
55
- for (const signalName of signalNames) {
56
- listeners.push(listen$(ctx, signalName, cb));
57
- }
58
- return () => {
59
- for (const listener of listeners) {
60
- listener();
61
- }
62
- };
63
- },
64
55
  get: () => {
65
56
  const currentValues = [];
66
57
  let hasChanged = false;
@@ -76,6 +67,17 @@ function createSelectorFunctionsArr(ctx, signalNames) {
76
67
  lastValues = currentValues;
77
68
  }
78
69
  return lastValues;
70
+ },
71
+ subscribe: (cb) => {
72
+ const listeners = [];
73
+ for (const signalName of signalNames) {
74
+ listeners.push(listen$(ctx, signalName, cb));
75
+ }
76
+ return () => {
77
+ for (const listener of listeners) {
78
+ listener();
79
+ }
80
+ };
79
81
  }
80
82
  };
81
83
  }
@@ -110,7 +112,7 @@ function getContentSize(ctx) {
110
112
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
111
113
  const headerSize = values.get("headerSize") || 0;
112
114
  const footerSize = values.get("footerSize") || 0;
113
- const totalSize = values.get("totalSize") || 0;
115
+ const totalSize = values.get("totalSize");
114
116
  return headerSize + footerSize + totalSize + stylePaddingTop;
115
117
  }
116
118
  function useArr$(signalNames) {
@@ -126,13 +128,13 @@ function useSelector$(signalName, selector) {
126
128
  return value;
127
129
  }
128
130
 
129
- // src/DebugView.tsx
131
+ // src/components/DebugView.tsx
130
132
  var DebugRow = ({ children }) => {
131
- return /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" } }, children);
133
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
132
134
  };
133
135
  var DebugView = React3__namespace.memo(function DebugView2({ state }) {
134
136
  const ctx = useStateContext();
135
- const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, numContainers = 0, numContainersPooled = 0] = useArr$([
137
+ const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
136
138
  "totalSize",
137
139
  "scrollAdjust",
138
140
  "debugRawScroll",
@@ -148,18 +150,18 @@ var DebugView = React3__namespace.memo(function DebugView2({ state }) {
148
150
  return /* @__PURE__ */ React3__namespace.createElement(
149
151
  reactNative.View,
150
152
  {
153
+ pointerEvents: "none",
151
154
  style: {
152
- position: "absolute",
153
- top: 0,
154
- right: 0,
155
- paddingLeft: 4,
156
- paddingBottom: 4,
157
155
  // height: 100,
158
156
  backgroundColor: "#FFFFFFCC",
157
+ borderRadius: 4,
159
158
  padding: 4,
160
- borderRadius: 4
161
- },
162
- pointerEvents: "none"
159
+ paddingBottom: 4,
160
+ paddingLeft: 4,
161
+ position: "absolute",
162
+ right: 0,
163
+ top: 0
164
+ }
163
165
  },
164
166
  /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "TotalSize:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, totalSize.toFixed(2))),
165
167
  /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "ContentSize:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, contentSize.toFixed(2))),
@@ -177,8 +179,34 @@ function useInterval(callback, delay) {
177
179
  return () => clearInterval(interval);
178
180
  }, [delay]);
179
181
  }
182
+ var LeanViewComponent = React3__namespace.forwardRef((props, ref) => {
183
+ return React3__namespace.createElement("RCTView", { ...props, ref });
184
+ });
185
+ LeanViewComponent.displayName = "RCTView";
186
+ var LeanView = reactNative.Platform.OS === "android" || reactNative.Platform.OS === "ios" ? LeanViewComponent : reactNative.View;
187
+
188
+ // src/components/Separator.tsx
189
+ function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
190
+ const [lastItemKeys] = useArr$(["lastItemKeys"]);
191
+ const isALastItem = lastItemKeys.includes(itemKey);
192
+ return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
193
+ }
194
+
195
+ // src/constants.ts
196
+ var POSITION_OUT_OF_VIEW = -1e7;
197
+ var ENABLE_DEVMODE = __DEV__ && false;
198
+ var ENABLE_DEBUG_VIEW = __DEV__ && false;
199
+ var IsNewArchitecture = global.nativeFabricUIManager != null;
200
+ var symbolFirst = Symbol();
201
+ function useInit(cb) {
202
+ const refValue = React3.useRef(symbolFirst);
203
+ if (refValue.current === symbolFirst) {
204
+ refValue.current = cb();
205
+ }
206
+ return refValue.current;
207
+ }
180
208
 
181
- // src/helpers.ts
209
+ // src/utils/helpers.ts
182
210
  function isFunction(obj) {
183
211
  return typeof obj === "function";
184
212
  }
@@ -208,16 +236,8 @@ function getPadding(s, type) {
208
236
  function extractPadding(style, contentContainerStyle, type) {
209
237
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
210
238
  }
211
- var symbolFirst = Symbol();
212
- function useInit(cb) {
213
- const refValue = React3.useRef(symbolFirst);
214
- if (refValue.current === symbolFirst) {
215
- refValue.current = cb();
216
- }
217
- return refValue.current;
218
- }
219
239
 
220
- // src/ContextContainer.ts
240
+ // src/state/ContextContainer.ts
221
241
  var ContextContainer = React3.createContext(null);
222
242
  function useViewability(callback, configId) {
223
243
  const ctx = useStateContext();
@@ -261,7 +281,7 @@ function useRecyclingEffect(effect) {
261
281
  prevItem: void 0
262
282
  });
263
283
  React3.useEffect(() => {
264
- let ret = void 0;
284
+ let ret;
265
285
  if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
266
286
  ret = effect({
267
287
  index,
@@ -275,7 +295,7 @@ function useRecyclingEffect(effect) {
275
295
  prevItem: value
276
296
  };
277
297
  return ret;
278
- }, [index, value]);
298
+ }, [index, value, effect]);
279
299
  }
280
300
  function useRecyclingState(valueOrFun) {
281
301
  const { index, value, itemKey, triggerLayout } = React3.useContext(ContextContainer);
@@ -313,34 +333,18 @@ function useListScrollSize() {
313
333
  const [scrollSize] = useArr$(["scrollSize"]);
314
334
  return scrollSize;
315
335
  }
316
- var LeanViewComponent = React3__namespace.forwardRef((props, ref) => {
317
- return React3__namespace.createElement("RCTView", { ...props, ref });
318
- });
319
- LeanViewComponent.displayName = "RCTView";
320
- var LeanView = reactNative.Platform.OS === "android" || reactNative.Platform.OS === "ios" ? LeanViewComponent : reactNative.View;
321
-
322
- // src/Separator.tsx
323
- function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
324
- const [lastItemKeys] = useArr$(["lastItemKeys"]);
325
- const isALastItem = lastItemKeys.includes(itemKey);
326
- return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
327
- }
328
-
329
- // src/constants.ts
330
- var POSITION_OUT_OF_VIEW = -1e7;
331
- var ENABLE_DEVMODE = __DEV__ && false;
332
- var ENABLE_DEBUG_VIEW = __DEV__ && false;
333
- var IsNewArchitecture = global.nativeFabricUIManager != null;
336
+ var typedForwardRef = React3.forwardRef;
337
+ var typedMemo = React3.memo;
334
338
 
335
- // src/Container.tsx
336
- var Container = ({
339
+ // src/components/Container.tsx
340
+ var Container = typedMemo(function Container2({
337
341
  id,
338
342
  recycleItems,
339
343
  horizontal,
340
344
  getRenderedItem: getRenderedItem2,
341
345
  updateItemSize: updateItemSize2,
342
346
  ItemSeparatorComponent
343
- }) => {
347
+ }) {
344
348
  const ctx = useStateContext();
345
349
  const columnWrapperStyle = ctx.columnWrapperStyle;
346
350
  const [column = 0, data, itemKey, position = POSITION_OUT_OF_VIEW, numColumns, extraData] = useArr$([
@@ -374,17 +378,17 @@ var Container = ({
374
378
  }
375
379
  const style = horizontal ? {
376
380
  flexDirection: ItemSeparatorComponent ? "row" : void 0,
377
- position: "absolute",
378
- top: otherAxisPos,
379
381
  height: otherAxisSize,
380
382
  left: position,
383
+ position: "absolute",
384
+ top: otherAxisPos,
381
385
  ...paddingStyles || {}
382
386
  } : {
383
- position: "absolute",
384
387
  left: otherAxisPos,
388
+ position: "absolute",
385
389
  right: numColumns > 1 ? null : 0,
386
- width: otherAxisSize,
387
390
  top: position,
391
+ width: otherAxisSize,
388
392
  ...paddingStyles || {}
389
393
  };
390
394
  const renderedItemInfo = React3.useMemo(
@@ -392,12 +396,17 @@ var Container = ({
392
396
  [itemKey, data, extraData]
393
397
  );
394
398
  const { index, renderedItem } = renderedItemInfo || {};
395
- const triggerLayout = React3.useCallback(() => {
396
- forceLayoutRender((v) => v + 1);
397
- }, []);
398
399
  const contextValue = React3.useMemo(() => {
399
400
  ctx.viewRefs.set(id, ref);
400
- return { containerId: id, itemKey, index, value: data, triggerLayout };
401
+ return {
402
+ containerId: id,
403
+ index,
404
+ itemKey,
405
+ triggerLayout: () => {
406
+ forceLayoutRender((v) => v + 1);
407
+ },
408
+ value: data
409
+ };
401
410
  }, [id, itemKey, index, data]);
402
411
  const onLayout = (event) => {
403
412
  var _a, _b;
@@ -406,14 +415,14 @@ var Container = ({
406
415
  let layout = event.nativeEvent.layout;
407
416
  const size = layout[horizontal ? "width" : "height"];
408
417
  const doUpdate = () => {
409
- refLastSize.current = { width: layout.width, height: layout.height };
418
+ refLastSize.current = { height: layout.height, width: layout.width };
410
419
  updateItemSize2(itemKey, layout);
411
420
  };
412
421
  if (IsNewArchitecture || size > 0) {
413
422
  doUpdate();
414
423
  } else {
415
- (_b = (_a = ref.current) == null ? void 0 : _a.measure) == null ? void 0 : _b.call(_a, (x, y, width, height) => {
416
- layout = { width, height };
424
+ (_b = (_a = ref.current) == null ? void 0 : _a.measure) == null ? void 0 : _b.call(_a, (_x, _y, width, height) => {
425
+ layout = { height, width };
417
426
  doUpdate();
418
427
  });
419
428
  }
@@ -446,30 +455,28 @@ var Container = ({
446
455
  }
447
456
  }, [itemKey]);
448
457
  }
449
- return /* @__PURE__ */ React3__namespace.createElement(LeanView, { style, onLayout, ref, key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(
458
+ return /* @__PURE__ */ React3__namespace.createElement(LeanView, { key: recycleItems ? void 0 : itemKey, onLayout, ref, style }, /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(
450
459
  Separator,
451
460
  {
452
- itemKey,
453
461
  ItemSeparatorComponent,
462
+ itemKey,
454
463
  leadingItem: renderedItemInfo.item
455
464
  }
456
465
  )));
457
- };
458
- var typedForwardRef = React3.forwardRef;
459
- var typedMemo = React3.memo;
466
+ });
460
467
  var useAnimatedValue = (initialValue) => {
461
468
  return React3.useRef(new reactNative.Animated.Value(initialValue)).current;
462
469
  };
463
470
 
464
- // src/useValue$.ts
471
+ // src/hooks/useValue$.ts
465
472
  function useValue$(key, params) {
466
473
  var _a;
467
474
  const { getValue, delay } = params || {};
468
475
  const ctx = useStateContext();
469
476
  const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
470
477
  React3.useMemo(() => {
471
- let newValue = void 0;
472
- let prevValue = void 0;
478
+ let newValue;
479
+ let prevValue;
473
480
  let didQueueTask = false;
474
481
  listen$(ctx, key, (v) => {
475
482
  newValue = getValue ? getValue(v) : v;
@@ -498,7 +505,7 @@ function useValue$(key, params) {
498
505
  return animValue;
499
506
  }
500
507
 
501
- // src/Containers.tsx
508
+ // src/components/Containers.tsx
502
509
  var Containers = typedMemo(function Containers2({
503
510
  horizontal,
504
511
  recycleItems,
@@ -522,18 +529,18 @@ var Containers = typedMemo(function Containers2({
522
529
  /* @__PURE__ */ React3__namespace.createElement(
523
530
  Container,
524
531
  {
532
+ getRenderedItem: getRenderedItem2,
533
+ horizontal,
534
+ ItemSeparatorComponent,
525
535
  id: i,
526
536
  key: i,
527
537
  recycleItems,
528
- horizontal,
529
- getRenderedItem: getRenderedItem2,
530
- updateItemSize: updateItemSize2,
531
- ItemSeparatorComponent
538
+ updateItemSize: updateItemSize2
532
539
  }
533
540
  )
534
541
  );
535
542
  }
536
- const style = horizontal ? { width: animSize, opacity: animOpacity, minHeight: otherAxisSize } : { height: animSize, opacity: animOpacity, minWidth: otherAxisSize };
543
+ const style = horizontal ? { minHeight: otherAxisSize, opacity: animOpacity, width: animSize } : { height: animSize, minWidth: otherAxisSize, opacity: animOpacity };
537
544
  if (columnWrapperStyle && numColumns > 1) {
538
545
  const { columnGap, rowGap, gap } = columnWrapperStyle;
539
546
  const gapX = columnGap || gap || 0;
@@ -564,15 +571,21 @@ function ScrollAdjust() {
564
571
  reactNative.View,
565
572
  {
566
573
  style: {
567
- position: "absolute",
568
574
  height: 0,
569
- width: 0,
575
+ left: 0,
576
+ position: "absolute",
570
577
  top: scrollOffset,
571
- left: 0
578
+ width: 0
572
579
  }
573
580
  }
574
581
  );
575
582
  }
583
+
584
+ // src/components/SnapWrapper.tsx
585
+ function SnapWrapper({ ScrollComponent, ...props }) {
586
+ const [snapToOffsets] = useArr$(["snapToOffsets"]);
587
+ return /* @__PURE__ */ React.createElement(ScrollComponent, { ...props, snapToOffsets });
588
+ }
576
589
  function useSyncLayout({
577
590
  onChange
578
591
  }) {
@@ -583,17 +596,19 @@ function useSyncLayout({
583
596
  },
584
597
  [onChange]
585
598
  );
586
- React3.useLayoutEffect(() => {
587
- if (ref.current) {
588
- ref.current.measure((x, y, width, height) => {
589
- onChange({ x, y, width, height }, true);
590
- });
591
- }
592
- }, []);
599
+ if (IsNewArchitecture) {
600
+ React3.useLayoutEffect(() => {
601
+ if (ref.current) {
602
+ ref.current.measure((x, y, width, height) => {
603
+ onChange({ height, width, x, y }, true);
604
+ });
605
+ }
606
+ }, []);
607
+ }
593
608
  return { onLayout, ref };
594
609
  }
595
610
 
596
- // src/ListComponent.tsx
611
+ // src/components/ListComponent.tsx
597
612
  var getComponent = (Component) => {
598
613
  if (React3__namespace.isValidElement(Component)) {
599
614
  return Component;
@@ -613,12 +628,12 @@ var PaddingDevMode = () => {
613
628
  reactNative.Animated.View,
614
629
  {
615
630
  style: {
616
- position: "absolute",
617
- top: 0,
631
+ backgroundColor: "green",
618
632
  height: animPaddingTop,
619
633
  left: 0,
634
+ position: "absolute",
620
635
  right: 0,
621
- backgroundColor: "green"
636
+ top: 0
622
637
  }
623
638
  }
624
639
  ));
@@ -647,6 +662,7 @@ var ListComponent = typedMemo(function ListComponent2({
647
662
  renderScrollComponent,
648
663
  scrollAdjustHandler,
649
664
  onLayoutHeader,
665
+ snapToIndices,
650
666
  ...rest
651
667
  }) {
652
668
  const ctx = useStateContext();
@@ -664,76 +680,56 @@ var ListComponent = typedMemo(function ListComponent2({
664
680
  }, 0);
665
681
  }
666
682
  }, [canRender]);
683
+ const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
667
684
  return /* @__PURE__ */ React3__namespace.createElement(
668
- ScrollComponent,
685
+ SnapOrScroll,
669
686
  {
670
687
  ...rest,
671
- style,
672
- maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
673
688
  contentContainerStyle: [
674
689
  contentContainerStyle,
675
690
  horizontal ? {
676
691
  height: "100%"
677
692
  } : {}
678
693
  ],
679
- onScroll: onScroll2,
680
- onLayout,
681
- horizontal,
682
694
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
683
- ref: refScrollView
695
+ horizontal,
696
+ maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
697
+ onLayout,
698
+ onScroll: onScroll2,
699
+ ref: refScrollView,
700
+ ScrollComponent: snapToIndices ? ScrollComponent : void 0,
701
+ style
684
702
  },
685
703
  maintainVisibleContentPosition && /* @__PURE__ */ React3__namespace.createElement(ScrollAdjust, null),
686
704
  ENABLE_DEVMODE ? /* @__PURE__ */ React3__namespace.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3__namespace.createElement(Padding, null),
687
- ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { style: ListHeaderComponentStyle, onLayout: onLayoutHeaderSync, ref: refHeader }, getComponent(ListHeaderComponent)),
705
+ ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { onLayout: onLayoutHeaderSync, ref: refHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
688
706
  ListEmptyComponent && getComponent(ListEmptyComponent),
689
707
  canRender && /* @__PURE__ */ React3__namespace.createElement(
690
708
  Containers,
691
709
  {
692
- horizontal,
693
- recycleItems,
694
- waitForInitialLayout,
695
710
  getRenderedItem: getRenderedItem2,
711
+ horizontal,
696
712
  ItemSeparatorComponent,
697
- updateItemSize: updateItemSize2
713
+ recycleItems,
714
+ updateItemSize: updateItemSize2,
715
+ waitForInitialLayout
698
716
  }
699
717
  ),
700
718
  ListFooterComponent && /* @__PURE__ */ React3__namespace.createElement(
701
719
  reactNative.View,
702
720
  {
703
- style: ListFooterComponentStyle,
704
721
  onLayout: (event) => {
705
722
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
706
723
  set$(ctx, "footerSize", size);
707
- }
724
+ },
725
+ style: ListFooterComponentStyle
708
726
  },
709
727
  getComponent(ListFooterComponent)
710
728
  )
711
729
  );
712
730
  });
713
731
 
714
- // src/ScrollAdjustHandler.ts
715
- var ScrollAdjustHandler = class {
716
- constructor(ctx) {
717
- this.appliedAdjust = 0;
718
- this.mounted = false;
719
- this.context = ctx;
720
- }
721
- requestAdjust(add) {
722
- const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
723
- this.appliedAdjust = add + oldAdjustTop;
724
- const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
725
- if (this.mounted) {
726
- set();
727
- } else {
728
- requestAnimationFrame(set);
729
- }
730
- }
731
- setMounted() {
732
- this.mounted = true;
733
- }
734
- };
735
-
736
- // src/getId.ts
732
+ // src/utils/getId.ts
737
733
  function getId(state, index) {
738
734
  const { data, keyExtractor } = state.props;
739
735
  if (!data) {
@@ -745,7 +741,7 @@ function getId(state, index) {
745
741
  return id;
746
742
  }
747
743
 
748
- // src/calculateOffsetForIndex.ts
744
+ // src/core/calculateOffsetForIndex.ts
749
745
  function calculateOffsetForIndex(ctx, state, index) {
750
746
  let position = 0;
751
747
  if (index !== void 0) {
@@ -762,7 +758,7 @@ function calculateOffsetForIndex(ctx, state, index) {
762
758
  return position;
763
759
  }
764
760
 
765
- // src/getItemSize.ts
761
+ // src/utils/getItemSize.ts
766
762
  function getItemSize(state, key, index, data, useAverageSize) {
767
763
  const {
768
764
  sizesKnown,
@@ -775,7 +771,7 @@ function getItemSize(state, key, index, data, useAverageSize) {
775
771
  return sizeKnown;
776
772
  }
777
773
  let size;
778
- if (IsNewArchitecture && useAverageSize !== void 0 && sizeKnown === void 0 && !getEstimatedItemSize && !scrollingTo) {
774
+ if (useAverageSize !== void 0 && sizeKnown === void 0 && !getEstimatedItemSize && !scrollingTo) {
779
775
  size = useAverageSize;
780
776
  }
781
777
  if (size === void 0) {
@@ -791,7 +787,7 @@ function getItemSize(state, key, index, data, useAverageSize) {
791
787
  return size;
792
788
  }
793
789
 
794
- // src/calculateOffsetWithOffsetPosition.ts
790
+ // src/core/calculateOffsetWithOffsetPosition.ts
795
791
  function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
796
792
  const { index, viewOffset, viewPosition } = params;
797
793
  let offset = offsetParam;
@@ -804,330 +800,85 @@ function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
804
800
  return offset;
805
801
  }
806
802
 
807
- // src/checkAllSizesKnown.ts
808
- function checkAllSizesKnown(state) {
809
- const { startBuffered, endBuffered, sizesKnown } = state;
810
- if (endBuffered !== null) {
811
- let areAllKnown = true;
812
- for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
813
- const key = getId(state, i);
814
- areAllKnown && (areAllKnown = sizesKnown.has(key));
803
+ // src/utils/requestAdjust.ts
804
+ function requestAdjust(ctx, state, positionDiff) {
805
+ if (Math.abs(positionDiff) > 0.1) {
806
+ const doit = () => {
807
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
808
+ };
809
+ state.scroll += positionDiff;
810
+ state.scrollForNextCalculateItemsInView = void 0;
811
+ const didLayout = peek$(ctx, "containersDidLayout");
812
+ if (didLayout) {
813
+ doit();
814
+ const threshold = state.scroll - positionDiff / 2;
815
+ if (!state.ignoreScrollFromMVCP) {
816
+ state.ignoreScrollFromMVCP = {};
817
+ }
818
+ if (positionDiff > 0) {
819
+ state.ignoreScrollFromMVCP.lt = threshold;
820
+ } else {
821
+ state.ignoreScrollFromMVCP.gt = threshold;
822
+ }
823
+ if (state.ignoreScrollFromMVCPTimeout) {
824
+ clearTimeout(state.ignoreScrollFromMVCPTimeout);
825
+ }
826
+ state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
827
+ state.ignoreScrollFromMVCP = void 0;
828
+ }, 100);
829
+ } else {
830
+ requestAnimationFrame(doit);
815
831
  }
816
- return areAllKnown;
817
832
  }
818
- return false;
819
833
  }
820
834
 
821
- // src/findAvailableContainers.ts
822
- function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
823
- const numContainers = peek$(ctx, "numContainers");
824
- const result = [];
825
- const availableContainers = [];
826
- for (let u = 0; u < numContainers; u++) {
827
- const key = peek$(ctx, `containerItemKey${u}`);
828
- let isOk = key === void 0;
829
- if (!isOk) {
830
- const index = pendingRemoval.indexOf(u);
831
- if (index !== -1) {
832
- pendingRemoval.splice(index, 1);
833
- isOk = true;
834
- }
835
- }
836
- if (isOk) {
837
- result.push(u);
838
- if (result.length >= numNeeded) {
839
- return result;
840
- }
835
+ // src/core/prepareMVCP.ts
836
+ function prepareMVCP(ctx, state) {
837
+ const {
838
+ positions,
839
+ scrollingTo,
840
+ props: { maintainVisibleContentPosition }
841
+ } = state;
842
+ let prevPosition;
843
+ let targetId;
844
+ let targetIndex;
845
+ const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
846
+ if (maintainVisibleContentPosition) {
847
+ const indexByKey = state.indexByKey;
848
+ if (scrollTarget !== void 0) {
849
+ targetId = getId(state, scrollTarget);
850
+ targetIndex = scrollTarget;
851
+ } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
852
+ targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
853
+ targetIndex = indexByKey.get(targetId);
841
854
  }
842
- }
843
- for (let u = 0; u < numContainers; u++) {
844
- const key = peek$(ctx, `containerItemKey${u}`);
845
- if (key === void 0) continue;
846
- const index = state.indexByKey.get(key);
847
- if (index < startBuffered) {
848
- availableContainers.push({ index: u, distance: startBuffered - index });
849
- } else if (index > endBuffered) {
850
- availableContainers.push({ index: u, distance: index - endBuffered });
855
+ if (targetId !== void 0 && targetIndex !== void 0) {
856
+ prevPosition = positions.get(targetId);
851
857
  }
852
858
  }
853
- const remaining = numNeeded - result.length;
854
- if (remaining > 0) {
855
- if (availableContainers.length > 0) {
856
- if (availableContainers.length > remaining) {
857
- availableContainers.sort(comparatorByDistance);
858
- availableContainers.length = remaining;
859
- }
860
- for (const container of availableContainers) {
861
- result.push(container.index);
862
- }
863
- }
864
- const stillNeeded = numNeeded - result.length;
865
- if (stillNeeded > 0) {
866
- for (let i = 0; i < stillNeeded; i++) {
867
- result.push(numContainers + i);
868
- }
869
- if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
870
- console.warn(
871
- "[legend-list] No unused container available, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize or increasing initialContainerPoolRatio.",
872
- {
873
- debugInfo: {
874
- numContainers,
875
- numNeeded,
876
- stillNeeded,
877
- numContainersPooled: peek$(ctx, "numContainersPooled")
878
- }
879
- }
880
- );
881
- }
882
- }
883
- }
884
- return result.sort(comparatorDefault);
885
- }
886
- function comparatorByDistance(a, b) {
887
- return b.distance - a.distance;
888
- }
889
-
890
- // src/getScrollVelocity.ts
891
- var getScrollVelocity = (state) => {
892
- const { scrollHistory } = state;
893
- let velocity = 0;
894
- if (scrollHistory.length >= 1) {
895
- const newest = scrollHistory[scrollHistory.length - 1];
896
- let oldest;
897
- let start = 0;
898
- for (let i = 0; i < scrollHistory.length - 1; i++) {
899
- const entry = scrollHistory[i];
900
- const nextEntry = scrollHistory[i + 1];
901
- if (i > 0) {
902
- const prevEntry = scrollHistory[i - 1];
903
- const prevDirection = entry.scroll - prevEntry.scroll;
904
- const currentDirection = nextEntry.scroll - entry.scroll;
905
- if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
906
- start = i;
907
- break;
908
- }
909
- }
910
- }
911
- for (let i = start; i < scrollHistory.length - 1; i++) {
912
- const entry = scrollHistory[i];
913
- if (newest.time - entry.time <= 1e3) {
914
- oldest = entry;
915
- break;
916
- }
917
- }
918
- if (oldest) {
919
- const scrollDiff = newest.scroll - oldest.scroll;
920
- const timeDiff = newest.time - oldest.time;
921
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
922
- }
923
- }
924
- return velocity;
925
- };
926
-
927
- // src/requestAdjust.ts
928
- function requestAdjust(ctx, state, positionDiff) {
929
- if (Math.abs(positionDiff) > 0.1) {
930
- const doit = () => {
931
- state.scrollAdjustHandler.requestAdjust(positionDiff);
932
- };
933
- state.scroll += positionDiff;
934
- state.scrollForNextCalculateItemsInView = void 0;
935
- if (peek$(ctx, "containersDidLayout")) {
936
- doit();
937
- } else {
938
- requestAnimationFrame(doit);
939
- }
940
- const threshold = state.scroll - positionDiff / 2;
941
- if (!state.ignoreScrollFromMVCP) {
942
- state.ignoreScrollFromMVCP = {};
943
- }
944
- if (positionDiff > 0) {
945
- state.ignoreScrollFromMVCP.lt = threshold;
946
- } else {
947
- state.ignoreScrollFromMVCP.gt = threshold;
948
- }
949
- if (state.ignoreScrollFromMVCPTimeout) {
950
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
951
- }
952
- state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
953
- state.ignoreScrollFromMVCP = void 0;
954
- }, 100);
955
- }
956
- }
957
-
958
- // src/prepareMVCP.ts
959
- function prepareMVCP(ctx, state) {
960
- const {
961
- positions,
962
- scrollingTo,
963
- props: { maintainVisibleContentPosition }
964
- } = state;
965
- let prevPosition;
966
- let targetId;
967
- let targetIndex;
968
- const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
969
- if (maintainVisibleContentPosition) {
970
- const indexByKey = state.indexByKey;
971
- if (scrollTarget !== void 0) {
972
- targetId = getId(state, scrollTarget);
973
- targetIndex = scrollTarget;
974
- } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
975
- targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
976
- targetIndex = indexByKey.get(targetId);
977
- }
978
- if (targetId !== void 0 && targetIndex !== void 0) {
979
- prevPosition = positions.get(targetId);
980
- }
981
- }
982
- return () => {
983
- if (targetId !== void 0 && prevPosition !== void 0) {
984
- const newPosition = positions.get(targetId);
985
- if (newPosition !== void 0) {
986
- const positionDiff = newPosition - prevPosition;
987
- if (Math.abs(positionDiff) > 0.1) {
988
- requestAdjust(ctx, state, positionDiff);
989
- }
859
+ return () => {
860
+ if (targetId !== void 0 && prevPosition !== void 0) {
861
+ const newPosition = positions.get(targetId);
862
+ if (newPosition !== void 0) {
863
+ const positionDiff = newPosition - prevPosition;
864
+ if (Math.abs(positionDiff) > 0.1) {
865
+ requestAdjust(ctx, state, positionDiff);
866
+ }
990
867
  }
991
868
  }
992
869
  };
993
870
  }
994
871
 
995
- // src/checkThreshold.ts
996
- var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
997
- const distanceAbs = Math.abs(distance);
998
- const isAtThreshold = atThreshold || distanceAbs < threshold;
999
- if (!isReached && !isBlockedByTimer) {
1000
- if (isAtThreshold) {
1001
- onReached == null ? void 0 : onReached(distance);
1002
- blockTimer == null ? void 0 : blockTimer(true);
1003
- setTimeout(() => {
1004
- blockTimer == null ? void 0 : blockTimer(false);
1005
- }, 700);
1006
- return true;
1007
- }
1008
- } else {
1009
- if (distance >= 1.3 * threshold) {
1010
- return false;
1011
- }
1012
- }
1013
- return isReached;
1014
- };
1015
-
1016
- // src/checkAtBottom.ts
1017
- function checkAtBottom(ctx, state) {
1018
- if (!state) {
1019
- return;
1020
- }
1021
- const {
1022
- queuedInitialLayout,
1023
- scrollLength,
1024
- scroll,
1025
- maintainingScrollAtEnd,
1026
- props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1027
- } = state;
1028
- const contentSize = getContentSize(ctx);
1029
- if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1030
- const distanceFromEnd = contentSize - scroll - scrollLength;
1031
- const isContentLess = contentSize < scrollLength;
1032
- state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1033
- state.isEndReached = checkThreshold(
1034
- distanceFromEnd,
1035
- isContentLess,
1036
- onEndReachedThreshold * scrollLength,
1037
- state.isEndReached,
1038
- state.endReachedBlockedByTimer,
1039
- (distance) => {
1040
- var _a, _b;
1041
- return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1042
- },
1043
- (block) => {
1044
- state.endReachedBlockedByTimer = block;
1045
- }
1046
- );
1047
- }
1048
- }
1049
-
1050
- // src/finishScrollTo.ts
1051
- var finishScrollTo = (state) => {
1052
- if (state) {
1053
- state.scrollingTo = void 0;
1054
- state.scrollHistory.length = 0;
1055
- }
1056
- };
1057
-
1058
- // src/scrollTo.ts
1059
- function scrollTo(state, params = {}) {
1060
- var _a;
1061
- const { animated } = params;
1062
- const {
1063
- refScroller,
1064
- props: { horizontal }
1065
- } = state;
1066
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1067
- state.scrollHistory.length = 0;
1068
- state.scrollingTo = params;
1069
- state.scrollPending = offset;
1070
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1071
- x: horizontal ? offset : 0,
1072
- y: horizontal ? 0 : offset,
1073
- animated: !!animated
1074
- });
1075
- if (!animated) {
1076
- state.scroll = offset;
1077
- setTimeout(() => finishScrollTo(state), 100);
1078
- }
1079
- }
1080
-
1081
- // src/scrollToIndex.ts
1082
- function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1083
- if (index >= state.props.data.length) {
1084
- index = state.props.data.length - 1;
1085
- } else if (index < 0) {
1086
- index = 0;
1087
- }
1088
- const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
1089
- const isLast = index === state.props.data.length - 1;
1090
- if (isLast && viewPosition === void 0) {
1091
- viewPosition = 1;
1092
- }
1093
- const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1094
- state.scrollForNextCalculateItemsInView = void 0;
1095
- scrollTo(state, {
1096
- offset: firstIndexScrollPostion,
1097
- animated,
1098
- index,
1099
- viewPosition: viewPosition != null ? viewPosition : 0,
1100
- viewOffset
1101
- });
1102
- }
1103
-
1104
- // src/setDidLayout.ts
1105
- function setDidLayout(ctx, state) {
1106
- const {
1107
- loadStartTime,
1108
- initialScroll,
1109
- props: { onLoad }
1110
- } = state;
1111
- state.queuedInitialLayout = true;
1112
- checkAtBottom(ctx, state);
1113
- if (!IsNewArchitecture && initialScroll) {
1114
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1115
- }
1116
- set$(ctx, "containersDidLayout", true);
1117
- if (onLoad) {
1118
- onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1119
- }
1120
- }
1121
-
1122
- // src/setPaddingTop.ts
1123
- function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
872
+ // src/utils/setPaddingTop.ts
873
+ function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1124
874
  if (stylePaddingTop !== void 0) {
1125
875
  const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1126
876
  if (stylePaddingTop < prevStylePaddingTop) {
1127
- const prevTotalSize = peek$(ctx, "totalSize") || 0;
877
+ let prevTotalSize = peek$(ctx, "totalSize");
1128
878
  set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
1129
- setTimeout(() => {
1130
- set$(ctx, "totalSize", prevTotalSize);
879
+ state.timeoutSetPaddingTop = setTimeout(() => {
880
+ prevTotalSize = peek$(ctx, "totalSize");
881
+ set$(ctx, "totalSize", prevTotalSize - prevStylePaddingTop);
1131
882
  }, 16);
1132
883
  }
1133
884
  set$(ctx, "stylePaddingTop", stylePaddingTop);
@@ -1137,7 +888,7 @@ function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
1137
888
  }
1138
889
  }
1139
890
 
1140
- // src/updateAlignItemsPaddingTop.ts
891
+ // src/utils/updateAlignItemsPaddingTop.ts
1141
892
  function updateAlignItemsPaddingTop(ctx, state) {
1142
893
  const {
1143
894
  scrollLength,
@@ -1149,11 +900,11 @@ function updateAlignItemsPaddingTop(ctx, state) {
1149
900
  const contentSize = getContentSize(ctx);
1150
901
  alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1151
902
  }
1152
- setPaddingTop(ctx, { alignItemsPaddingTop });
903
+ setPaddingTop(ctx, state, { alignItemsPaddingTop });
1153
904
  }
1154
905
  }
1155
906
 
1156
- // src/updateTotalSize.ts
907
+ // src/core/updateTotalSize.ts
1157
908
  function updateTotalSize(ctx, state) {
1158
909
  const {
1159
910
  positions,
@@ -1179,6 +930,10 @@ function addTotalSize(ctx, state, key, add) {
1179
930
  const { alignItemsAtEnd } = state.props;
1180
931
  {
1181
932
  state.totalSize = add;
933
+ if (state.timeoutSetPaddingTop) {
934
+ clearTimeout(state.timeoutSetPaddingTop);
935
+ state.timeoutSetPaddingTop = void 0;
936
+ }
1182
937
  }
1183
938
  set$(ctx, "totalSize", state.totalSize);
1184
939
  if (alignItemsAtEnd) {
@@ -1186,32 +941,93 @@ function addTotalSize(ctx, state, key, add) {
1186
941
  }
1187
942
  }
1188
943
 
1189
- // src/updateAllPositions.ts
1190
- function updateAllPositions(ctx, state, dataChanged) {
1191
- var _a, _b, _c, _d, _e;
1192
- const { averageSizes, columns, indexByKey, positions, firstFullyOnScreenIndex, idCache, sizesKnown } = state;
1193
- const data = state.props.data;
1194
- const numColumns = peek$(ctx, "numColumns");
1195
- const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1196
- const scrollVelocity = getScrollVelocity(state);
1197
- if (dataChanged) {
1198
- indexByKey.clear();
1199
- idCache.clear();
1200
- }
1201
- const itemType = "";
1202
- let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
1203
- if (averageSize !== void 0) {
1204
- averageSize = roundSize(averageSize);
1205
- }
1206
- const shouldUseBackwards = !dataChanged && scrollVelocity < 0 && firstFullyOnScreenIndex > 5 && firstFullyOnScreenIndex < data.length;
1207
- if (shouldUseBackwards && firstFullyOnScreenIndex !== void 0) {
1208
- const anchorId = getId(state, firstFullyOnScreenIndex);
1209
- const anchorPosition = positions.get(anchorId);
1210
- if (anchorPosition !== void 0) {
1211
- let currentRowTop2 = anchorPosition;
1212
- let maxSizeInRow2 = 0;
1213
- let bailout = false;
1214
- for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
944
+ // src/utils/getScrollVelocity.ts
945
+ var getScrollVelocity = (state) => {
946
+ const { scrollHistory } = state;
947
+ let velocity = 0;
948
+ if (scrollHistory.length >= 1) {
949
+ const newest = scrollHistory[scrollHistory.length - 1];
950
+ let oldest;
951
+ let start = 0;
952
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
953
+ const entry = scrollHistory[i];
954
+ const nextEntry = scrollHistory[i + 1];
955
+ if (i > 0) {
956
+ const prevEntry = scrollHistory[i - 1];
957
+ const prevDirection = entry.scroll - prevEntry.scroll;
958
+ const currentDirection = nextEntry.scroll - entry.scroll;
959
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
960
+ start = i;
961
+ break;
962
+ }
963
+ }
964
+ }
965
+ for (let i = start; i < scrollHistory.length - 1; i++) {
966
+ const entry = scrollHistory[i];
967
+ if (newest.time - entry.time <= 1e3) {
968
+ oldest = entry;
969
+ break;
970
+ }
971
+ }
972
+ if (oldest) {
973
+ const scrollDiff = newest.scroll - oldest.scroll;
974
+ const timeDiff = newest.time - oldest.time;
975
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
976
+ }
977
+ }
978
+ return velocity;
979
+ };
980
+
981
+ // src/utils/updateSnapToOffsets.ts
982
+ function updateSnapToOffsets(ctx, state) {
983
+ const {
984
+ positions,
985
+ props: { snapToIndices }
986
+ } = state;
987
+ const snapToOffsets = Array(snapToIndices.length);
988
+ for (let i = 0; i < snapToIndices.length; i++) {
989
+ const idx = snapToIndices[i];
990
+ const key = getId(state, idx);
991
+ snapToOffsets[i] = positions.get(key);
992
+ }
993
+ set$(ctx, "snapToOffsets", snapToOffsets);
994
+ }
995
+
996
+ // src/core/updateAllPositions.ts
997
+ function updateAllPositions(ctx, state, dataChanged) {
998
+ var _a, _b, _c, _d, _e;
999
+ const {
1000
+ averageSizes,
1001
+ columns,
1002
+ indexByKey,
1003
+ positions,
1004
+ firstFullyOnScreenIndex,
1005
+ idCache,
1006
+ sizesKnown,
1007
+ props: { snapToIndices }
1008
+ } = state;
1009
+ const data = state.props.data;
1010
+ const numColumns = peek$(ctx, "numColumns");
1011
+ const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1012
+ const scrollVelocity = getScrollVelocity(state);
1013
+ if (dataChanged) {
1014
+ indexByKey.clear();
1015
+ idCache.clear();
1016
+ }
1017
+ const itemType = "";
1018
+ let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
1019
+ if (averageSize !== void 0) {
1020
+ averageSize = roundSize(averageSize);
1021
+ }
1022
+ const shouldUseBackwards = !dataChanged && scrollVelocity < 0 && firstFullyOnScreenIndex > 5 && firstFullyOnScreenIndex < data.length;
1023
+ if (shouldUseBackwards && firstFullyOnScreenIndex !== void 0) {
1024
+ const anchorId = getId(state, firstFullyOnScreenIndex);
1025
+ const anchorPosition = positions.get(anchorId);
1026
+ if (anchorPosition !== void 0) {
1027
+ let currentRowTop2 = anchorPosition;
1028
+ let maxSizeInRow2 = 0;
1029
+ let bailout = false;
1030
+ for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
1215
1031
  const id = (_b = idCache.get(i)) != null ? _b : getId(state, i);
1216
1032
  const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(state, id, i, data[i], averageSize);
1217
1033
  const itemColumn = columns.get(id);
@@ -1269,9 +1085,12 @@ function updateAllPositions(ctx, state, dataChanged) {
1269
1085
  }
1270
1086
  }
1271
1087
  updateTotalSize(ctx, state);
1088
+ if (snapToIndices) {
1089
+ updateSnapToOffsets(ctx, state);
1090
+ }
1272
1091
  }
1273
1092
 
1274
- // src/viewability.ts
1093
+ // src/core/viewability.ts
1275
1094
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
1276
1095
  function setupViewability(props) {
1277
1096
  let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
@@ -1279,27 +1098,31 @@ function setupViewability(props) {
1279
1098
  viewabilityConfigCallbackPairs = [
1280
1099
  ...viewabilityConfigCallbackPairs || [],
1281
1100
  {
1101
+ onViewableItemsChanged,
1282
1102
  viewabilityConfig: viewabilityConfig || {
1283
1103
  viewAreaCoveragePercentThreshold: 0
1284
- },
1285
- onViewableItemsChanged
1104
+ }
1286
1105
  }
1287
1106
  ];
1288
1107
  }
1289
1108
  if (viewabilityConfigCallbackPairs) {
1290
1109
  for (const pair of viewabilityConfigCallbackPairs) {
1291
1110
  mapViewabilityConfigCallbackPairs.set(pair.viewabilityConfig.id, {
1292
- viewableItems: [],
1293
- start: -1,
1294
1111
  end: -1,
1112
+ previousEnd: -1,
1295
1113
  previousStart: -1,
1296
- previousEnd: -1
1114
+ start: -1,
1115
+ viewableItems: []
1297
1116
  });
1298
1117
  }
1299
1118
  }
1300
1119
  return viewabilityConfigCallbackPairs;
1301
1120
  }
1302
1121
  function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
1122
+ const {
1123
+ timeouts,
1124
+ props: { data }
1125
+ } = state;
1303
1126
  for (const viewabilityConfigCallbackPair of viewabilityConfigCallbackPairs) {
1304
1127
  const viewabilityState = mapViewabilityConfigCallbackPairs.get(
1305
1128
  viewabilityConfigCallbackPair.viewabilityConfig.id
@@ -1308,12 +1131,12 @@ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollS
1308
1131
  viewabilityState.end = end;
1309
1132
  if (viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime) {
1310
1133
  const timer = setTimeout(() => {
1311
- state.timeouts.delete(timer);
1312
- updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1134
+ timeouts.delete(timer);
1135
+ updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1313
1136
  }, viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime);
1314
- state.timeouts.add(timer);
1137
+ timeouts.add(timer);
1315
1138
  } else {
1316
- updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1139
+ updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1317
1140
  }
1318
1141
  }
1319
1142
  }
@@ -1365,11 +1188,11 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1365
1188
  const containerId = findContainerId(ctx, key);
1366
1189
  if (isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
1367
1190
  const viewToken = {
1368
- item,
1369
- key,
1191
+ containerId,
1370
1192
  index: i,
1371
1193
  isViewable: true,
1372
- containerId
1194
+ item,
1195
+ key
1373
1196
  };
1374
1197
  viewableItems.push(viewToken);
1375
1198
  if (!(previousViewableItems == null ? void 0 : previousViewableItems.find((v) => v.key === viewToken.key))) {
@@ -1379,9 +1202,9 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1379
1202
  }
1380
1203
  }
1381
1204
  Object.assign(viewabilityState, {
1382
- viewableItems,
1205
+ previousEnd: end,
1383
1206
  previousStart: start,
1384
- previousEnd: end
1207
+ viewableItems
1385
1208
  });
1386
1209
  if (changed.length > 0) {
1387
1210
  viewabilityState.viewableItems = viewableItems;
@@ -1390,7 +1213,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1390
1213
  maybeUpdateViewabilityCallback(ctx, configId, change.containerId, change);
1391
1214
  }
1392
1215
  if (onViewableItemsChanged) {
1393
- onViewableItemsChanged({ viewableItems, changed });
1216
+ onViewableItemsChanged({ changed, viewableItems });
1394
1217
  }
1395
1218
  }
1396
1219
  for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
@@ -1416,16 +1239,16 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
1416
1239
  const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
1417
1240
  const isViewable2 = percent >= viewablePercentThreshold;
1418
1241
  const value = {
1242
+ containerId,
1419
1243
  index,
1420
1244
  isViewable: isViewable2,
1421
1245
  item,
1422
1246
  key,
1423
- percentVisible,
1424
1247
  percentOfScroller,
1425
- sizeVisible,
1426
- size,
1248
+ percentVisible,
1427
1249
  scrollSize,
1428
- containerId
1250
+ size,
1251
+ sizeVisible
1429
1252
  };
1430
1253
  if (JSON.stringify(value) !== JSON.stringify(ctx.mapViewabilityAmountValues.get(containerId))) {
1431
1254
  ctx.mapViewabilityAmountValues.set(containerId, value);
@@ -1457,314 +1280,482 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1457
1280
  cb == null ? void 0 : cb(viewToken);
1458
1281
  }
1459
1282
 
1460
- // src/calculateItemsInView.ts
1461
- function calculateItemsInView(ctx, state, params = {}) {
1462
- var _a, _b, _c, _d, _e, _f, _g, _h;
1463
- const {
1464
- scrollLength,
1465
- startBufferedId: startBufferedIdOrig,
1466
- positions,
1467
- columns,
1468
- containerItemKeys,
1469
- idCache,
1470
- sizes,
1471
- indexByKey,
1472
- scrollForNextCalculateItemsInView,
1473
- enableScrollForNextCalculateItemsInView,
1474
- minIndexSizeChanged
1475
- } = state;
1476
- const data = state.props.data;
1477
- if (!data || scrollLength === 0) {
1478
- return;
1479
- }
1480
- const totalSize = peek$(ctx, "totalSize");
1481
- const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
1482
- const numColumns = peek$(ctx, "numColumns");
1483
- const previousScrollAdjust = 0;
1484
- const { dataChanged, doMVCP } = params;
1485
- const speed = getScrollVelocity(state);
1486
- if (doMVCP || dataChanged) {
1487
- const checkMVCP = doMVCP ? prepareMVCP(ctx, state) : void 0;
1488
- updateAllPositions(ctx, state, dataChanged);
1489
- checkMVCP == null ? void 0 : checkMVCP();
1490
- }
1491
- const scrollExtra = 0;
1492
- const { queuedInitialLayout } = state;
1493
- let { scroll: scrollState } = state;
1494
- const initialScroll = state.props.initialScroll;
1495
- if (!queuedInitialLayout && initialScroll) {
1496
- const updatedOffset = calculateOffsetWithOffsetPosition(
1497
- state,
1498
- calculateOffsetForIndex(ctx, state, initialScroll.index),
1499
- initialScroll
1500
- );
1501
- scrollState = updatedOffset;
1502
- }
1503
- const scrollAdjustPad = -previousScrollAdjust - topPad;
1504
- let scroll = scrollState + scrollExtra + scrollAdjustPad;
1505
- if (scroll + scrollLength > totalSize) {
1506
- scroll = totalSize - scrollLength;
1507
- }
1508
- if (ENABLE_DEBUG_VIEW) {
1509
- set$(ctx, "debugRawScroll", scrollState);
1510
- set$(ctx, "debugComputedScroll", scroll);
1511
- }
1512
- const scrollBuffer = state.props.scrollBuffer;
1513
- let scrollBufferTop = scrollBuffer;
1514
- let scrollBufferBottom = scrollBuffer;
1515
- if (speed > 0) {
1516
- scrollBufferTop = scrollBuffer * 0.5;
1517
- scrollBufferBottom = scrollBuffer * 1.5;
1518
- } else {
1519
- scrollBufferTop = scrollBuffer * 1.5;
1520
- scrollBufferBottom = scrollBuffer * 0.5;
1521
- }
1522
- const scrollTopBuffered = scroll - scrollBufferTop;
1523
- const scrollBottom = scroll + scrollLength;
1524
- const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1525
- if (scrollForNextCalculateItemsInView) {
1526
- const { top, bottom } = scrollForNextCalculateItemsInView;
1527
- if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
1528
- return;
1283
+ // src/utils/checkAllSizesKnown.ts
1284
+ function checkAllSizesKnown(state) {
1285
+ const { startBuffered, endBuffered, sizesKnown } = state;
1286
+ if (endBuffered !== null) {
1287
+ let areAllKnown = true;
1288
+ for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1289
+ const key = getId(state, i);
1290
+ areAllKnown && (areAllKnown = sizesKnown.has(key));
1529
1291
  }
1292
+ return areAllKnown;
1530
1293
  }
1531
- let startNoBuffer = null;
1532
- let startBuffered = null;
1533
- let startBufferedId = null;
1534
- let endNoBuffer = null;
1535
- let endBuffered = null;
1536
- let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1537
- if (minIndexSizeChanged !== void 0) {
1538
- loopStart = Math.min(minIndexSizeChanged, loopStart);
1539
- state.minIndexSizeChanged = void 0;
1540
- }
1541
- for (let i = loopStart; i >= 0; i--) {
1542
- const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
1543
- const top = positions.get(id);
1544
- const size = (_b = sizes.get(id)) != null ? _b : getItemSize(state, id, i, data[i]);
1545
- const bottom = top + size;
1546
- if (bottom > scroll - scrollBuffer) {
1547
- loopStart = i;
1548
- } else {
1549
- break;
1294
+ return false;
1295
+ }
1296
+
1297
+ // src/utils/findAvailableContainers.ts
1298
+ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
1299
+ const numContainers = peek$(ctx, "numContainers");
1300
+ const result = [];
1301
+ const availableContainers = [];
1302
+ for (let u = 0; u < numContainers; u++) {
1303
+ const key = peek$(ctx, `containerItemKey${u}`);
1304
+ let isOk = key === void 0;
1305
+ if (!isOk) {
1306
+ const index = pendingRemoval.indexOf(u);
1307
+ if (index !== -1) {
1308
+ pendingRemoval.splice(index, 1);
1309
+ isOk = true;
1310
+ }
1311
+ }
1312
+ if (isOk) {
1313
+ result.push(u);
1314
+ if (result.length >= numNeeded) {
1315
+ return result;
1316
+ }
1550
1317
  }
1551
1318
  }
1552
- const loopStartMod = loopStart % numColumns;
1553
- if (loopStartMod > 0) {
1554
- loopStart -= loopStartMod;
1555
- }
1556
- let foundEnd = false;
1557
- let nextTop;
1558
- let nextBottom;
1559
- const prevNumContainers = ctx.values.get("numContainers");
1560
- let maxIndexRendered = 0;
1561
- for (let i = 0; i < prevNumContainers; i++) {
1562
- const key = peek$(ctx, `containerItemKey${i}`);
1563
- if (key !== void 0) {
1564
- const index = indexByKey.get(key);
1565
- maxIndexRendered = Math.max(maxIndexRendered, index);
1319
+ for (let u = 0; u < numContainers; u++) {
1320
+ const key = peek$(ctx, `containerItemKey${u}`);
1321
+ if (key === void 0) continue;
1322
+ const index = state.indexByKey.get(key);
1323
+ if (index < startBuffered) {
1324
+ availableContainers.push({ distance: startBuffered - index, index: u });
1325
+ } else if (index > endBuffered) {
1326
+ availableContainers.push({ distance: index - endBuffered, index: u });
1566
1327
  }
1567
1328
  }
1568
- let firstFullyOnScreenIndex;
1569
- const dataLength = data.length;
1570
- for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
1571
- const id = (_c = idCache.get(i)) != null ? _c : getId(state, i);
1572
- const size = (_d = sizes.get(id)) != null ? _d : getItemSize(state, id, i, data[i]);
1573
- const top = positions.get(id);
1574
- if (!foundEnd) {
1575
- if (startNoBuffer === null && top + size > scroll) {
1576
- startNoBuffer = i;
1577
- }
1578
- if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10) {
1579
- firstFullyOnScreenIndex = i;
1580
- }
1581
- if (startBuffered === null && top + size > scrollTopBuffered) {
1582
- startBuffered = i;
1583
- startBufferedId = id;
1584
- nextTop = top;
1585
- }
1586
- if (startNoBuffer !== null) {
1587
- if (top <= scrollBottom) {
1588
- endNoBuffer = i;
1589
- }
1590
- if (top <= scrollBottomBuffered) {
1591
- endBuffered = i;
1592
- nextBottom = top + size;
1593
- } else {
1594
- foundEnd = true;
1595
- }
1329
+ const remaining = numNeeded - result.length;
1330
+ if (remaining > 0) {
1331
+ if (availableContainers.length > 0) {
1332
+ if (availableContainers.length > remaining) {
1333
+ availableContainers.sort(comparatorByDistance);
1334
+ availableContainers.length = remaining;
1335
+ }
1336
+ for (const container of availableContainers) {
1337
+ result.push(container.index);
1338
+ }
1339
+ }
1340
+ const stillNeeded = numNeeded - result.length;
1341
+ if (stillNeeded > 0) {
1342
+ for (let i = 0; i < stillNeeded; i++) {
1343
+ result.push(numContainers + i);
1344
+ }
1345
+ if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
1346
+ console.warn(
1347
+ "[legend-list] No unused container available, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize or increasing initialContainerPoolRatio.",
1348
+ {
1349
+ debugInfo: {
1350
+ numContainers,
1351
+ numContainersPooled: peek$(ctx, "numContainersPooled"),
1352
+ numNeeded,
1353
+ stillNeeded
1354
+ }
1355
+ }
1356
+ );
1596
1357
  }
1597
1358
  }
1598
1359
  }
1599
- const idsInView = [];
1600
- for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
1601
- const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1602
- idsInView.push(id);
1360
+ return result.sort(comparatorDefault);
1361
+ }
1362
+ function comparatorByDistance(a, b) {
1363
+ return b.distance - a.distance;
1364
+ }
1365
+
1366
+ // src/core/finishScrollTo.ts
1367
+ var finishScrollTo = (state) => {
1368
+ if (state) {
1369
+ state.scrollingTo = void 0;
1370
+ state.scrollHistory.length = 0;
1603
1371
  }
1604
- Object.assign(state, {
1605
- startBuffered,
1606
- startBufferedId,
1607
- startNoBuffer,
1608
- endBuffered,
1609
- endNoBuffer,
1610
- idsInView,
1611
- firstFullyOnScreenIndex
1372
+ };
1373
+
1374
+ // src/core/scrollTo.ts
1375
+ function scrollTo(state, params = {}) {
1376
+ var _a;
1377
+ const { animated } = params;
1378
+ const {
1379
+ refScroller,
1380
+ props: { horizontal }
1381
+ } = state;
1382
+ const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1383
+ state.scrollHistory.length = 0;
1384
+ state.scrollingTo = params;
1385
+ state.scrollPending = offset;
1386
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1387
+ animated: !!animated,
1388
+ x: horizontal ? offset : 0,
1389
+ y: horizontal ? 0 : offset
1612
1390
  });
1613
- if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
1614
- state.scrollForNextCalculateItemsInView = nextTop !== void 0 && nextBottom !== void 0 ? {
1615
- top: nextTop,
1616
- bottom: nextBottom
1617
- } : void 0;
1391
+ if (!animated) {
1392
+ state.scroll = offset;
1393
+ setTimeout(() => finishScrollTo(state), 100);
1618
1394
  }
1619
- const numContainers = peek$(ctx, "numContainers");
1620
- const pendingRemoval = [];
1621
- if (dataChanged) {
1622
- for (let i = 0; i < numContainers; i++) {
1623
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1624
- if (!state.props.keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1625
- pendingRemoval.push(i);
1626
- }
1395
+ }
1396
+
1397
+ // src/core/scrollToIndex.ts
1398
+ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1399
+ if (index >= state.props.data.length) {
1400
+ index = state.props.data.length - 1;
1401
+ } else if (index < 0) {
1402
+ index = 0;
1403
+ }
1404
+ const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
1405
+ const isLast = index === state.props.data.length - 1;
1406
+ if (isLast && viewPosition === void 0) {
1407
+ viewPosition = 1;
1408
+ }
1409
+ const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1410
+ state.scrollForNextCalculateItemsInView = void 0;
1411
+ scrollTo(state, {
1412
+ animated,
1413
+ index,
1414
+ offset: firstIndexScrollPostion,
1415
+ viewOffset,
1416
+ viewPosition: viewPosition != null ? viewPosition : 0
1417
+ });
1418
+ }
1419
+
1420
+ // src/utils/checkThreshold.ts
1421
+ var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
1422
+ const distanceAbs = Math.abs(distance);
1423
+ const isAtThreshold = atThreshold || distanceAbs < threshold;
1424
+ if (!isReached && !isBlockedByTimer) {
1425
+ if (isAtThreshold) {
1426
+ onReached == null ? void 0 : onReached(distance);
1427
+ blockTimer == null ? void 0 : blockTimer(true);
1428
+ setTimeout(() => {
1429
+ blockTimer == null ? void 0 : blockTimer(false);
1430
+ }, 700);
1431
+ return true;
1432
+ }
1433
+ } else {
1434
+ if (distance >= 1.3 * threshold) {
1435
+ return false;
1627
1436
  }
1628
1437
  }
1629
- if (startBuffered !== null && endBuffered !== null) {
1630
- let numContainers2 = prevNumContainers;
1631
- const needNewContainers = [];
1632
- for (let i = startBuffered; i <= endBuffered; i++) {
1633
- const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
1634
- if (!containerItemKeys.has(id)) {
1635
- needNewContainers.push(i);
1438
+ return isReached;
1439
+ };
1440
+
1441
+ // src/utils/checkAtBottom.ts
1442
+ function checkAtBottom(ctx, state) {
1443
+ if (!state) {
1444
+ return;
1445
+ }
1446
+ const {
1447
+ queuedInitialLayout,
1448
+ scrollLength,
1449
+ scroll,
1450
+ maintainingScrollAtEnd,
1451
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1452
+ } = state;
1453
+ const contentSize = getContentSize(ctx);
1454
+ if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1455
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1456
+ const isContentLess = contentSize < scrollLength;
1457
+ state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1458
+ state.isEndReached = checkThreshold(
1459
+ distanceFromEnd,
1460
+ isContentLess,
1461
+ onEndReachedThreshold * scrollLength,
1462
+ state.isEndReached,
1463
+ state.endReachedBlockedByTimer,
1464
+ (distance) => {
1465
+ var _a, _b;
1466
+ return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1467
+ },
1468
+ (block) => {
1469
+ state.endReachedBlockedByTimer = block;
1636
1470
  }
1471
+ );
1472
+ }
1473
+ }
1474
+
1475
+ // src/utils/setDidLayout.ts
1476
+ function setDidLayout(ctx, state) {
1477
+ const {
1478
+ loadStartTime,
1479
+ initialScroll,
1480
+ props: { onLoad }
1481
+ } = state;
1482
+ state.queuedInitialLayout = true;
1483
+ checkAtBottom(ctx, state);
1484
+ if (!IsNewArchitecture && initialScroll) {
1485
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1486
+ }
1487
+ set$(ctx, "containersDidLayout", true);
1488
+ if (onLoad) {
1489
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1490
+ }
1491
+ }
1492
+
1493
+ // src/core/calculateItemsInView.ts
1494
+ function calculateItemsInView(ctx, state, params = {}) {
1495
+ reactNative.unstable_batchedUpdates(() => {
1496
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1497
+ const {
1498
+ scrollLength,
1499
+ startBufferedId: startBufferedIdOrig,
1500
+ positions,
1501
+ columns,
1502
+ containerItemKeys,
1503
+ idCache,
1504
+ sizes,
1505
+ indexByKey,
1506
+ scrollForNextCalculateItemsInView,
1507
+ enableScrollForNextCalculateItemsInView,
1508
+ minIndexSizeChanged
1509
+ } = state;
1510
+ const data = state.props.data;
1511
+ const prevNumContainers = peek$(ctx, "numContainers");
1512
+ if (!data || scrollLength === 0 || !prevNumContainers) {
1513
+ return;
1637
1514
  }
1638
- if (needNewContainers.length > 0) {
1639
- const availableContainers = findAvailableContainers(
1640
- ctx,
1515
+ const totalSize = peek$(ctx, "totalSize");
1516
+ const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
1517
+ const numColumns = peek$(ctx, "numColumns");
1518
+ const previousScrollAdjust = 0;
1519
+ const { dataChanged, doMVCP } = params;
1520
+ const speed = getScrollVelocity(state);
1521
+ if (doMVCP || dataChanged) {
1522
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state) : void 0;
1523
+ updateAllPositions(ctx, state, dataChanged);
1524
+ checkMVCP == null ? void 0 : checkMVCP();
1525
+ }
1526
+ const scrollExtra = 0;
1527
+ const { queuedInitialLayout } = state;
1528
+ let { scroll: scrollState } = state;
1529
+ const initialScroll = state.props.initialScroll;
1530
+ if (!queuedInitialLayout && initialScroll) {
1531
+ const updatedOffset = calculateOffsetWithOffsetPosition(
1641
1532
  state,
1642
- needNewContainers.length,
1643
- startBuffered,
1644
- endBuffered,
1645
- pendingRemoval
1533
+ calculateOffsetForIndex(ctx, state, initialScroll.index),
1534
+ initialScroll
1646
1535
  );
1647
- for (let idx = 0; idx < needNewContainers.length; idx++) {
1648
- const i = needNewContainers[idx];
1649
- const containerIndex = availableContainers[idx];
1650
- const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
1651
- const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
1652
- if (oldKey && oldKey !== id) {
1653
- containerItemKeys.delete(oldKey);
1536
+ scrollState = updatedOffset;
1537
+ }
1538
+ const scrollAdjustPad = -previousScrollAdjust - topPad;
1539
+ let scroll = scrollState + scrollExtra + scrollAdjustPad;
1540
+ if (scroll + scrollLength > totalSize) {
1541
+ scroll = totalSize - scrollLength;
1542
+ }
1543
+ if (ENABLE_DEBUG_VIEW) {
1544
+ set$(ctx, "debugRawScroll", scrollState);
1545
+ set$(ctx, "debugComputedScroll", scroll);
1546
+ }
1547
+ const scrollBuffer = state.props.scrollBuffer;
1548
+ let scrollBufferTop = scrollBuffer;
1549
+ let scrollBufferBottom = scrollBuffer;
1550
+ if (speed > 0) {
1551
+ scrollBufferTop = scrollBuffer * 0.5;
1552
+ scrollBufferBottom = scrollBuffer * 1.5;
1553
+ } else {
1554
+ scrollBufferTop = scrollBuffer * 1.5;
1555
+ scrollBufferBottom = scrollBuffer * 0.5;
1556
+ }
1557
+ const scrollTopBuffered = scroll - scrollBufferTop;
1558
+ const scrollBottom = scroll + scrollLength;
1559
+ const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1560
+ if (scrollForNextCalculateItemsInView) {
1561
+ const { top, bottom } = scrollForNextCalculateItemsInView;
1562
+ if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
1563
+ return;
1564
+ }
1565
+ }
1566
+ let startNoBuffer = null;
1567
+ let startBuffered = null;
1568
+ let startBufferedId = null;
1569
+ let endNoBuffer = null;
1570
+ let endBuffered = null;
1571
+ let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1572
+ if (minIndexSizeChanged !== void 0) {
1573
+ loopStart = Math.min(minIndexSizeChanged, loopStart);
1574
+ state.minIndexSizeChanged = void 0;
1575
+ }
1576
+ for (let i = loopStart; i >= 0; i--) {
1577
+ const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
1578
+ const top = positions.get(id);
1579
+ const size = (_b = sizes.get(id)) != null ? _b : getItemSize(state, id, i, data[i]);
1580
+ const bottom = top + size;
1581
+ if (bottom > scroll - scrollBuffer) {
1582
+ loopStart = i;
1583
+ } else {
1584
+ break;
1585
+ }
1586
+ }
1587
+ const loopStartMod = loopStart % numColumns;
1588
+ if (loopStartMod > 0) {
1589
+ loopStart -= loopStartMod;
1590
+ }
1591
+ let foundEnd = false;
1592
+ let nextTop;
1593
+ let nextBottom;
1594
+ let maxIndexRendered = 0;
1595
+ for (let i = 0; i < prevNumContainers; i++) {
1596
+ const key = peek$(ctx, `containerItemKey${i}`);
1597
+ if (key !== void 0) {
1598
+ const index = indexByKey.get(key);
1599
+ maxIndexRendered = Math.max(maxIndexRendered, index);
1600
+ }
1601
+ }
1602
+ let firstFullyOnScreenIndex;
1603
+ const dataLength = data.length;
1604
+ for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
1605
+ const id = (_c = idCache.get(i)) != null ? _c : getId(state, i);
1606
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(state, id, i, data[i]);
1607
+ const top = positions.get(id);
1608
+ if (!foundEnd) {
1609
+ if (startNoBuffer === null && top + size > scroll) {
1610
+ startNoBuffer = i;
1654
1611
  }
1655
- set$(ctx, `containerItemKey${containerIndex}`, id);
1656
- set$(ctx, `containerItemData${containerIndex}`, data[i]);
1657
- containerItemKeys.add(id);
1658
- if (containerIndex >= numContainers2) {
1659
- numContainers2 = containerIndex + 1;
1612
+ if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10) {
1613
+ firstFullyOnScreenIndex = i;
1614
+ }
1615
+ if (startBuffered === null && top + size > scrollTopBuffered) {
1616
+ startBuffered = i;
1617
+ startBufferedId = id;
1618
+ nextTop = top;
1619
+ }
1620
+ if (startNoBuffer !== null) {
1621
+ if (top <= scrollBottom) {
1622
+ endNoBuffer = i;
1623
+ }
1624
+ if (top <= scrollBottomBuffered) {
1625
+ endBuffered = i;
1626
+ nextBottom = top + size;
1627
+ } else {
1628
+ foundEnd = true;
1629
+ }
1660
1630
  }
1661
1631
  }
1662
- if (numContainers2 !== prevNumContainers) {
1663
- set$(ctx, "numContainers", numContainers2);
1664
- if (numContainers2 > peek$(ctx, "numContainersPooled")) {
1665
- set$(ctx, "numContainersPooled", Math.ceil(numContainers2 * 1.5));
1632
+ }
1633
+ const idsInView = [];
1634
+ for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
1635
+ const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1636
+ idsInView.push(id);
1637
+ }
1638
+ Object.assign(state, {
1639
+ endBuffered,
1640
+ endNoBuffer,
1641
+ firstFullyOnScreenIndex,
1642
+ idsInView,
1643
+ startBuffered,
1644
+ startBufferedId,
1645
+ startNoBuffer
1646
+ });
1647
+ if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
1648
+ state.scrollForNextCalculateItemsInView = nextTop !== void 0 && nextBottom !== void 0 ? {
1649
+ bottom: nextBottom,
1650
+ top: nextTop
1651
+ } : void 0;
1652
+ }
1653
+ const numContainers = peek$(ctx, "numContainers");
1654
+ const pendingRemoval = [];
1655
+ if (dataChanged) {
1656
+ for (let i = 0; i < numContainers; i++) {
1657
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
1658
+ if (!state.props.keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1659
+ pendingRemoval.push(i);
1666
1660
  }
1667
1661
  }
1668
1662
  }
1669
- }
1670
- for (let i = 0; i < numContainers; i++) {
1671
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1672
- if (pendingRemoval.includes(i)) {
1673
- if (itemKey) {
1674
- containerItemKeys.delete(itemKey);
1663
+ if (startBuffered !== null && endBuffered !== null) {
1664
+ let numContainers2 = prevNumContainers;
1665
+ const needNewContainers = [];
1666
+ for (let i = startBuffered; i <= endBuffered; i++) {
1667
+ const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
1668
+ if (!containerItemKeys.has(id)) {
1669
+ needNewContainers.push(i);
1670
+ }
1675
1671
  }
1676
- set$(ctx, `containerItemKey${i}`, void 0);
1677
- set$(ctx, `containerItemData${i}`, void 0);
1678
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1679
- set$(ctx, `containerColumn${i}`, -1);
1680
- } else {
1681
- const itemIndex = indexByKey.get(itemKey);
1682
- const item = data[itemIndex];
1683
- if (item !== void 0) {
1684
- const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
1685
- const position = positions.get(id);
1686
- if (position === void 0) {
1687
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1688
- } else {
1689
- const pos = positions.get(id);
1690
- const column = columns.get(id) || 1;
1691
- const prevPos = peek$(ctx, `containerPosition${i}`);
1692
- const prevColumn = peek$(ctx, `containerColumn${i}`);
1693
- const prevData = peek$(ctx, `containerItemData${i}`);
1694
- if (!prevPos || pos > POSITION_OUT_OF_VIEW && pos !== prevPos) {
1695
- set$(ctx, `containerPosition${i}`, pos);
1672
+ if (needNewContainers.length > 0) {
1673
+ const availableContainers = findAvailableContainers(
1674
+ ctx,
1675
+ state,
1676
+ needNewContainers.length,
1677
+ startBuffered,
1678
+ endBuffered,
1679
+ pendingRemoval
1680
+ );
1681
+ for (let idx = 0; idx < needNewContainers.length; idx++) {
1682
+ const i = needNewContainers[idx];
1683
+ const containerIndex = availableContainers[idx];
1684
+ const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
1685
+ const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
1686
+ if (oldKey && oldKey !== id) {
1687
+ containerItemKeys.delete(oldKey);
1696
1688
  }
1697
- if (column >= 0 && column !== prevColumn) {
1698
- set$(ctx, `containerColumn${i}`, column);
1689
+ set$(ctx, `containerItemKey${containerIndex}`, id);
1690
+ set$(ctx, `containerItemData${containerIndex}`, data[i]);
1691
+ containerItemKeys.add(id);
1692
+ if (containerIndex >= numContainers2) {
1693
+ numContainers2 = containerIndex + 1;
1699
1694
  }
1700
- if (prevData !== item) {
1701
- set$(ctx, `containerItemData${i}`, data[itemIndex]);
1695
+ }
1696
+ if (numContainers2 !== prevNumContainers) {
1697
+ set$(ctx, "numContainers", numContainers2);
1698
+ if (numContainers2 > peek$(ctx, "numContainersPooled")) {
1699
+ set$(ctx, "numContainersPooled", Math.ceil(numContainers2 * 1.5));
1702
1700
  }
1703
1701
  }
1704
1702
  }
1705
1703
  }
1706
- }
1707
- if (!queuedInitialLayout && endBuffered !== null) {
1708
- if (checkAllSizesKnown(state)) {
1709
- setDidLayout(ctx, state);
1710
- }
1711
- }
1712
- if (state.props.viewabilityConfigCallbackPairs) {
1713
- updateViewableItems(
1714
- state,
1715
- ctx,
1716
- state.props.viewabilityConfigCallbackPairs,
1717
- scrollLength,
1718
- startNoBuffer,
1719
- endNoBuffer
1720
- );
1721
- }
1722
- }
1723
-
1724
- // src/checkAtTop.ts
1725
- function checkAtTop(state) {
1726
- if (!state) {
1727
- return;
1728
- }
1729
- const {
1730
- scrollLength,
1731
- scroll,
1732
- props: { onStartReachedThreshold }
1733
- } = state;
1734
- const distanceFromTop = scroll;
1735
- state.isAtStart = distanceFromTop <= 0;
1736
- state.isStartReached = checkThreshold(
1737
- distanceFromTop,
1738
- false,
1739
- onStartReachedThreshold * scrollLength,
1740
- state.isStartReached,
1741
- state.startReachedBlockedByTimer,
1742
- (distance) => {
1743
- var _a, _b;
1744
- return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
1745
- },
1746
- (block) => {
1747
- state.startReachedBlockedByTimer = block;
1704
+ for (let i = 0; i < numContainers; i++) {
1705
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
1706
+ if (pendingRemoval.includes(i)) {
1707
+ if (itemKey) {
1708
+ containerItemKeys.delete(itemKey);
1709
+ }
1710
+ set$(ctx, `containerItemKey${i}`, void 0);
1711
+ set$(ctx, `containerItemData${i}`, void 0);
1712
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1713
+ set$(ctx, `containerColumn${i}`, -1);
1714
+ } else {
1715
+ const itemIndex = indexByKey.get(itemKey);
1716
+ const item = data[itemIndex];
1717
+ if (item !== void 0) {
1718
+ const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
1719
+ const position = positions.get(id);
1720
+ if (position === void 0) {
1721
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1722
+ } else {
1723
+ const column = columns.get(id) || 1;
1724
+ const prevPos = peek$(ctx, `containerPosition${i}`);
1725
+ const prevColumn = peek$(ctx, `containerColumn${i}`);
1726
+ const prevData = peek$(ctx, `containerItemData${i}`);
1727
+ if (position > POSITION_OUT_OF_VIEW && position !== prevPos) {
1728
+ set$(ctx, `containerPosition${i}`, position);
1729
+ }
1730
+ if (column >= 0 && column !== prevColumn) {
1731
+ set$(ctx, `containerColumn${i}`, column);
1732
+ }
1733
+ if (prevData !== item) {
1734
+ set$(ctx, `containerItemData${i}`, data[itemIndex]);
1735
+ }
1736
+ }
1737
+ }
1738
+ }
1748
1739
  }
1749
- );
1750
- }
1751
-
1752
- // src/createColumnWrapperStyle.ts
1753
- function createColumnWrapperStyle(contentContainerStyle) {
1754
- const { gap, columnGap, rowGap } = contentContainerStyle;
1755
- if (gap || columnGap || rowGap) {
1756
- contentContainerStyle.gap = void 0;
1757
- contentContainerStyle.columnGap = void 0;
1758
- contentContainerStyle.rowGap = void 0;
1759
- return {
1760
- gap,
1761
- columnGap,
1762
- rowGap
1763
- };
1764
- }
1740
+ if (!queuedInitialLayout && endBuffered !== null) {
1741
+ if (checkAllSizesKnown(state)) {
1742
+ setDidLayout(ctx, state);
1743
+ }
1744
+ }
1745
+ if (state.viewabilityConfigCallbackPairs) {
1746
+ updateViewableItems(
1747
+ state,
1748
+ ctx,
1749
+ state.viewabilityConfigCallbackPairs,
1750
+ scrollLength,
1751
+ startNoBuffer,
1752
+ endNoBuffer
1753
+ );
1754
+ }
1755
+ });
1765
1756
  }
1766
1757
 
1767
- // src/doInitialAllocateContainers.ts
1758
+ // src/core/doInitialAllocateContainers.ts
1768
1759
  function doInitialAllocateContainers(ctx, state) {
1769
1760
  const { scrollLength } = state;
1770
1761
  const data = state.props.data;
@@ -1793,7 +1784,7 @@ function doInitialAllocateContainers(ctx, state) {
1793
1784
  }
1794
1785
  }
1795
1786
 
1796
- // src/doMaintainScrollAtEnd.ts
1787
+ // src/core/doMaintainScrollAtEnd.ts
1797
1788
  function doMaintainScrollAtEnd(ctx, state, animated) {
1798
1789
  const {
1799
1790
  refScroller,
@@ -1820,34 +1811,42 @@ function doMaintainScrollAtEnd(ctx, state, animated) {
1820
1811
  return true;
1821
1812
  }
1822
1813
  }
1823
- function getRenderedItem(ctx, state, key) {
1814
+
1815
+ // src/utils/checkAtTop.ts
1816
+ function checkAtTop(state) {
1824
1817
  if (!state) {
1825
- return null;
1818
+ return;
1826
1819
  }
1827
1820
  const {
1828
- indexByKey,
1829
- props: { data, renderItem: renderItem2 }
1821
+ scrollLength,
1822
+ scroll,
1823
+ props: { onStartReachedThreshold }
1830
1824
  } = state;
1831
- const index = indexByKey.get(key);
1832
- if (index === void 0) {
1833
- return null;
1834
- }
1835
- let renderedItem = null;
1836
- if (renderItem2) {
1837
- const itemProps = {
1838
- item: data[index],
1839
- index,
1840
- extraData: peek$(ctx, "extraData")
1841
- };
1842
- renderedItem = React3__namespace.default.createElement(renderItem2, itemProps);
1843
- }
1844
- return { index, item: data[index], renderedItem };
1825
+ const distanceFromTop = scroll;
1826
+ state.isAtStart = distanceFromTop <= 0;
1827
+ state.isStartReached = checkThreshold(
1828
+ distanceFromTop,
1829
+ false,
1830
+ onStartReachedThreshold * scrollLength,
1831
+ state.isStartReached,
1832
+ state.startReachedBlockedByTimer,
1833
+ (distance) => {
1834
+ var _a, _b;
1835
+ return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
1836
+ },
1837
+ (block) => {
1838
+ state.startReachedBlockedByTimer = block;
1839
+ }
1840
+ );
1845
1841
  }
1846
1842
 
1847
- // src/handleLayout.ts
1848
- function handleLayout(ctx, state, size, setCanRender) {
1849
- const scrollLength = size[state.props.horizontal ? "width" : "height"];
1850
- const otherAxisSize = size[state.props.horizontal ? "height" : "width"];
1843
+ // src/core/handleLayout.ts
1844
+ function handleLayout(ctx, state, layout, setCanRender) {
1845
+ const { maintainScrollAtEnd } = state.props;
1846
+ const scrollLength = layout[state.props.horizontal ? "width" : "height"];
1847
+ const otherAxisSize = layout[state.props.horizontal ? "height" : "width"];
1848
+ const needsCalculate = !state.lastLayout || scrollLength > state.scrollLength || state.lastLayout.x !== layout.x || state.lastLayout.y !== layout.y;
1849
+ state.lastLayout = layout;
1851
1850
  const didChange = scrollLength !== state.scrollLength;
1852
1851
  const prevOtherAxisSize = state.otherAxisSize;
1853
1852
  state.scrollLength = scrollLength;
@@ -1855,13 +1854,15 @@ function handleLayout(ctx, state, size, setCanRender) {
1855
1854
  state.lastBatchingAction = Date.now();
1856
1855
  state.scrollForNextCalculateItemsInView = void 0;
1857
1856
  doInitialAllocateContainers(ctx, state);
1858
- if (didChange) {
1857
+ if (needsCalculate) {
1859
1858
  calculateItemsInView(ctx, state, { doMVCP: true });
1860
1859
  }
1861
1860
  if (didChange || otherAxisSize !== prevOtherAxisSize) {
1862
- set$(ctx, "scrollSize", { width: size.width, height: size.height });
1861
+ set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
1862
+ }
1863
+ if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
1864
+ doMaintainScrollAtEnd(ctx, state, false);
1863
1865
  }
1864
- doMaintainScrollAtEnd(ctx, state, false);
1865
1866
  updateAlignItemsPaddingTop(ctx, state);
1866
1867
  checkAtBottom(ctx, state);
1867
1868
  checkAtTop(state);
@@ -1874,11 +1875,10 @@ function handleLayout(ctx, state, size, setCanRender) {
1874
1875
  `List ${state.props.horizontal ? "width" : "height"} is 0. You may need to set a style or \`flex: \` for the list, because children are absolutely positioned.`
1875
1876
  );
1876
1877
  }
1877
- calculateItemsInView(ctx, state, { doMVCP: true });
1878
1878
  setCanRender(true);
1879
1879
  }
1880
1880
 
1881
- // src/onScroll.ts
1881
+ // src/core/onScroll.ts
1882
1882
  function onScroll(ctx, state, event) {
1883
1883
  var _a, _b, _c, _d, _e;
1884
1884
  if (((_b = (_a = event.nativeEvent) == null ? void 0 : _a.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
@@ -1916,14 +1916,44 @@ function updateScroll(ctx, state, newScroll) {
1916
1916
  checkAtTop(state);
1917
1917
  }
1918
1918
 
1919
- // src/updateItemSize.ts
1919
+ // src/core/ScrollAdjustHandler.ts
1920
+ var ScrollAdjustHandler = class {
1921
+ constructor(ctx) {
1922
+ this.appliedAdjust = 0;
1923
+ this.mounted = false;
1924
+ this.context = ctx;
1925
+ }
1926
+ requestAdjust(add) {
1927
+ const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
1928
+ this.appliedAdjust = add + oldAdjustTop;
1929
+ const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
1930
+ if (this.mounted) {
1931
+ set();
1932
+ } else {
1933
+ requestAnimationFrame(set);
1934
+ }
1935
+ }
1936
+ setMounted() {
1937
+ this.mounted = true;
1938
+ }
1939
+ };
1940
+
1941
+ // src/core/updateItemSize.ts
1920
1942
  function updateItemSizes(ctx, state, itemUpdates) {
1921
1943
  var _a;
1922
1944
  const {
1923
- props: { horizontal, maintainVisibleContentPosition, suggestEstimatedItemSize, onItemSizeChanged, data }
1945
+ props: {
1946
+ horizontal,
1947
+ maintainVisibleContentPosition,
1948
+ suggestEstimatedItemSize,
1949
+ onItemSizeChanged,
1950
+ data,
1951
+ maintainScrollAtEnd
1952
+ }
1924
1953
  } = state;
1925
1954
  if (!data) return;
1926
- let needsRecalculate = false;
1955
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
1956
+ let needsRecalculate = !containersDidLayout;
1927
1957
  let shouldMaintainScrollAtEnd = false;
1928
1958
  let minIndexSizeChanged;
1929
1959
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
@@ -1934,7 +1964,7 @@ function updateItemSizes(ctx, state, itemUpdates) {
1934
1964
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
1935
1965
  if (diff !== 0) {
1936
1966
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
1937
- if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index) {
1967
+ if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
1938
1968
  requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
1939
1969
  }
1940
1970
  const { startBuffered, endBuffered } = state;
@@ -1956,11 +1986,11 @@ function updateItemSizes(ctx, state, itemUpdates) {
1956
1986
  shouldMaintainScrollAtEnd = true;
1957
1987
  }
1958
1988
  onItemSizeChanged == null ? void 0 : onItemSizeChanged({
1959
- size,
1960
- previous: size - diff,
1961
1989
  index,
1990
+ itemData: state.props.data[index],
1962
1991
  itemKey,
1963
- itemData: state.props.data[index]
1992
+ previous: size - diff,
1993
+ size
1964
1994
  });
1965
1995
  }
1966
1996
  }
@@ -1983,42 +2013,33 @@ function updateItemSizes(ctx, state, itemUpdates) {
1983
2013
  if (!cur || maxOtherAxisSize > cur) {
1984
2014
  set$(ctx, "otherAxisSize", maxOtherAxisSize);
1985
2015
  }
1986
- const containersDidLayout = peek$(ctx, "containersDidLayout");
1987
2016
  if (containersDidLayout || checkAllSizesKnown(state)) {
1988
2017
  if (needsRecalculate) {
1989
2018
  state.scrollForNextCalculateItemsInView = void 0;
1990
2019
  calculateItemsInView(ctx, state, { doMVCP: true });
1991
2020
  }
1992
2021
  if (shouldMaintainScrollAtEnd) {
1993
- doMaintainScrollAtEnd(ctx, state, false);
2022
+ if (maintainScrollAtEnd === true || maintainScrollAtEnd.onItemLayout) {
2023
+ doMaintainScrollAtEnd(ctx, state, false);
2024
+ }
1994
2025
  }
1995
2026
  }
1996
2027
  }
1997
2028
  function updateItemSize(ctx, state, itemKey, sizeObj) {
1998
- var _a, _b;
1999
- if (IsNewArchitecture) {
2000
- const { sizesKnown } = state;
2001
- const numContainers = ctx.values.get("numContainers");
2002
- const changes = [];
2003
- for (let i = 0; i < numContainers; i++) {
2004
- const containerItemKey = peek$(ctx, `containerItemKey${i}`);
2005
- if (itemKey === containerItemKey) {
2006
- changes.push({ itemKey, sizeObj });
2007
- } else if (!sizesKnown.has(containerItemKey) && containerItemKey !== void 0) {
2008
- const containerRef = ctx.viewRefs.get(i);
2009
- if (containerRef) {
2010
- const measured = (_b = (_a = containerRef.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
2011
- if (measured) {
2012
- changes.push({ itemKey: containerItemKey, sizeObj: measured });
2013
- }
2014
- }
2015
- }
2016
- }
2017
- if (changes.length > 0) {
2018
- updateItemSizes(ctx, state, changes);
2029
+ const { queuedItemSizeUpdates, queuedItemSizeUpdatesWaiting } = state;
2030
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
2031
+ if (!containersDidLayout || !queuedItemSizeUpdatesWaiting) {
2032
+ updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
2033
+ if (containersDidLayout) {
2034
+ state.queuedItemSizeUpdatesWaiting = true;
2035
+ requestAnimationFrame(() => {
2036
+ state.queuedItemSizeUpdatesWaiting = false;
2037
+ updateItemSizes(ctx, state, queuedItemSizeUpdates);
2038
+ queuedItemSizeUpdates.length = 0;
2039
+ });
2019
2040
  }
2020
2041
  } else {
2021
- updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
2042
+ queuedItemSizeUpdates.push({ itemKey, sizeObj });
2022
2043
  }
2023
2044
  }
2024
2045
  function updateOneItemSize(state, itemKey, sizeObj) {
@@ -2037,7 +2058,7 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2037
2058
  const itemType = "";
2038
2059
  let averages = averageSizes[itemType];
2039
2060
  if (!averages) {
2040
- averages = averageSizes[itemType] = { num: 0, avg: 0 };
2061
+ averages = averageSizes[itemType] = { avg: 0, num: 0 };
2041
2062
  }
2042
2063
  averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2043
2064
  averages.num++;
@@ -2063,7 +2084,45 @@ var useCombinedRef = (...refs) => {
2063
2084
  return callback;
2064
2085
  };
2065
2086
 
2066
- // src/LegendList.tsx
2087
+ // src/utils/createColumnWrapperStyle.ts
2088
+ function createColumnWrapperStyle(contentContainerStyle) {
2089
+ const { gap, columnGap, rowGap } = contentContainerStyle;
2090
+ if (gap || columnGap || rowGap) {
2091
+ contentContainerStyle.gap = void 0;
2092
+ contentContainerStyle.columnGap = void 0;
2093
+ contentContainerStyle.rowGap = void 0;
2094
+ return {
2095
+ columnGap,
2096
+ gap,
2097
+ rowGap
2098
+ };
2099
+ }
2100
+ }
2101
+ function getRenderedItem(ctx, state, key) {
2102
+ if (!state) {
2103
+ return null;
2104
+ }
2105
+ const {
2106
+ indexByKey,
2107
+ props: { data, renderItem: renderItem2 }
2108
+ } = state;
2109
+ const index = indexByKey.get(key);
2110
+ if (index === void 0) {
2111
+ return null;
2112
+ }
2113
+ let renderedItem = null;
2114
+ if (renderItem2) {
2115
+ const itemProps = {
2116
+ extraData: peek$(ctx, "extraData"),
2117
+ index,
2118
+ item: data[index]
2119
+ };
2120
+ renderedItem = React3__namespace.default.createElement(renderItem2, itemProps);
2121
+ }
2122
+ return { index, item: data[index], renderedItem };
2123
+ }
2124
+
2125
+ // src/components/LegendList.tsx
2067
2126
  var DEFAULT_DRAW_DISTANCE = 250;
2068
2127
  var DEFAULT_ITEM_SIZE = 100;
2069
2128
  var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
@@ -2110,6 +2169,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2110
2169
  initialContainerPoolRatio = 2,
2111
2170
  viewabilityConfig,
2112
2171
  viewabilityConfigCallbackPairs,
2172
+ snapToIndices,
2113
2173
  onViewableItemsChanged,
2114
2174
  onStartReached,
2115
2175
  onEndReached,
@@ -2130,54 +2190,56 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2130
2190
  const combinedRef = useCombinedRef(refScroller, refScrollView);
2131
2191
  const estimatedItemSize = estimatedItemSizeProp != null ? estimatedItemSizeProp : DEFAULT_ITEM_SIZE;
2132
2192
  const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
2133
- const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
2193
+ const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
2134
2194
  const refState = React3.useRef();
2135
2195
  if (!refState.current) {
2136
- const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { width: 0, height: 0 } : reactNative.Dimensions.get("window"))[horizontal ? "width" : "height"];
2196
+ const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : reactNative.Dimensions.get("window"))[horizontal ? "width" : "height"];
2137
2197
  refState.current = {
2138
- sizes: /* @__PURE__ */ new Map(),
2139
- positions: /* @__PURE__ */ new Map(),
2198
+ averageSizes: {},
2140
2199
  columns: /* @__PURE__ */ new Map(),
2141
- pendingAdjust: 0,
2142
- isStartReached: false,
2143
- isEndReached: false,
2144
- isAtEnd: false,
2145
- isAtStart: false,
2146
- scrollLength: initialScrollLength,
2147
- startBuffered: -1,
2148
- startNoBuffer: -1,
2200
+ containerItemKeys: /* @__PURE__ */ new Set(),
2201
+ enableScrollForNextCalculateItemsInView: true,
2149
2202
  endBuffered: -1,
2150
2203
  endNoBuffer: -1,
2204
+ endReachedBlockedByTimer: false,
2151
2205
  firstFullyOnScreenIndex: -1,
2206
+ idCache: /* @__PURE__ */ new Map(),
2207
+ idsInView: [],
2208
+ indexByKey: /* @__PURE__ */ new Map(),
2209
+ initialScroll,
2210
+ isAtEnd: false,
2211
+ isAtStart: false,
2212
+ isEndReached: false,
2213
+ isStartReached: false,
2214
+ lastBatchingAction: Date.now(),
2215
+ lastLayout: void 0,
2216
+ loadStartTime: Date.now(),
2217
+ minIndexSizeChanged: 0,
2218
+ nativeMarginTop: 0,
2219
+ pendingAdjust: 0,
2220
+ positions: /* @__PURE__ */ new Map(),
2221
+ props: {},
2222
+ queuedCalculateItemsInView: 0,
2223
+ queuedItemSizeUpdates: [],
2224
+ refScroller: void 0,
2152
2225
  scroll: 0,
2153
- totalSize: 0,
2154
- timeouts: /* @__PURE__ */ new Set(),
2155
- viewabilityConfigCallbackPairs: void 0,
2156
2226
  scrollAdjustHandler: new ScrollAdjustHandler(ctx),
2157
- nativeMarginTop: 0,
2227
+ scrollForNextCalculateItemsInView: void 0,
2228
+ scrollHistory: [],
2229
+ scrollLength: initialScrollLength,
2230
+ scrollPending: 0,
2158
2231
  scrollPrev: 0,
2159
2232
  scrollPrevTime: 0,
2160
2233
  scrollTime: 0,
2161
- scrollPending: 0,
2162
- indexByKey: /* @__PURE__ */ new Map(),
2163
- scrollHistory: [],
2234
+ sizes: /* @__PURE__ */ new Map(),
2164
2235
  sizesKnown: /* @__PURE__ */ new Map(),
2165
- timeoutSizeMessage: 0,
2236
+ startBuffered: -1,
2237
+ startNoBuffer: -1,
2166
2238
  startReachedBlockedByTimer: false,
2167
- endReachedBlockedByTimer: false,
2168
- scrollForNextCalculateItemsInView: void 0,
2169
- enableScrollForNextCalculateItemsInView: true,
2170
- minIndexSizeChanged: 0,
2171
- queuedCalculateItemsInView: 0,
2172
- lastBatchingAction: Date.now(),
2173
- averageSizes: {},
2174
- idsInView: [],
2175
- containerItemKeys: /* @__PURE__ */ new Set(),
2176
- idCache: /* @__PURE__ */ new Map(),
2177
- props: {},
2178
- refScroller: void 0,
2179
- loadStartTime: Date.now(),
2180
- initialScroll
2239
+ timeoutSizeMessage: 0,
2240
+ timeouts: /* @__PURE__ */ new Set(),
2241
+ totalSize: 0,
2242
+ viewabilityConfigCallbackPairs: void 0
2181
2243
  };
2182
2244
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2183
2245
  set$(ctx, "extraData", extraData);
@@ -2189,28 +2251,28 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2189
2251
  alignItemsAtEnd,
2190
2252
  data: dataProp,
2191
2253
  estimatedItemSize,
2254
+ getEstimatedItemSize,
2255
+ horizontal: !!horizontal,
2256
+ initialContainerPoolRatio,
2257
+ initialScroll,
2258
+ keyExtractor,
2192
2259
  maintainScrollAtEnd,
2193
2260
  maintainScrollAtEndThreshold,
2194
- onEndReachedThreshold,
2195
- onStartReachedThreshold,
2196
- stylePaddingBottom: stylePaddingBottomState,
2197
- horizontal: !!horizontal,
2198
2261
  maintainVisibleContentPosition,
2262
+ numColumns: numColumnsProp,
2263
+ onEndReached,
2264
+ onEndReachedThreshold,
2199
2265
  onItemSizeChanged,
2200
- suggestEstimatedItemSize: !!suggestEstimatedItemSize,
2201
- keyExtractor,
2266
+ onLoad,
2202
2267
  onScroll: onScrollProp,
2203
- getEstimatedItemSize,
2204
2268
  onStartReached,
2205
- onEndReached,
2206
- onLoad,
2269
+ onStartReachedThreshold,
2207
2270
  renderItem: renderItem2,
2208
- initialScroll,
2209
2271
  scrollBuffer,
2210
- viewabilityConfigCallbackPairs: void 0,
2211
- numColumns: numColumnsProp,
2212
- initialContainerPoolRatio,
2213
- stylePaddingTop: stylePaddingTopState
2272
+ snapToIndices,
2273
+ stylePaddingBottom: stylePaddingBottomState,
2274
+ stylePaddingTop: stylePaddingTopState,
2275
+ suggestEstimatedItemSize: !!suggestEstimatedItemSize
2214
2276
  };
2215
2277
  state.refScroller = refScroller;
2216
2278
  const checkResetContainers = (isFirst2) => {
@@ -2219,7 +2281,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2219
2281
  state2.props.data = dataProp;
2220
2282
  if (!isFirst2) {
2221
2283
  calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
2222
- const didMaintainScrollAtEnd = doMaintainScrollAtEnd(ctx, state2, false);
2284
+ const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
2285
+ const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state2, false);
2223
2286
  if (!didMaintainScrollAtEnd && dataProp.length > state2.props.data.length) {
2224
2287
  state2.isEndReached = false;
2225
2288
  }
@@ -2237,27 +2300,29 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2237
2300
  (_, i) => getId(state, dataProp.length - 1 - i)
2238
2301
  );
2239
2302
  }, [dataProp, numColumnsProp]);
2240
- const initalizeStateVars = () => {
2303
+ const initializeStateVars = () => {
2241
2304
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
2242
2305
  set$(ctx, "numColumns", numColumnsProp);
2243
2306
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
2244
- setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
2307
+ setPaddingTop(ctx, state, { stylePaddingTop: stylePaddingTopState });
2245
2308
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
2246
- const paddingDiff = stylePaddingTopState - prevPaddingTop;
2247
- if (paddingDiff && prevPaddingTop !== void 0 && reactNative.Platform.OS === "ios") {
2248
- calculateItemsInView(ctx, state, { doMVCP: true });
2309
+ let paddingDiff = stylePaddingTopState - prevPaddingTop;
2310
+ if (maintainVisibleContentPosition && paddingDiff && prevPaddingTop !== void 0 && reactNative.Platform.OS === "ios") {
2311
+ if (state.scroll < 0) {
2312
+ paddingDiff += state.scroll;
2313
+ }
2249
2314
  requestAdjust(ctx, state, paddingDiff);
2250
2315
  }
2251
2316
  };
2252
2317
  if (isFirst) {
2253
- initalizeStateVars();
2318
+ initializeStateVars();
2254
2319
  updateAllPositions(ctx, state);
2255
2320
  }
2256
2321
  const initialContentOffset = React3.useMemo(() => {
2257
2322
  const initialContentOffset2 = initialScrollOffset || calculateOffsetForIndex(ctx, state, initialScrollIndex);
2258
2323
  refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
2259
2324
  if (initialContentOffset2 > 0) {
2260
- scrollTo(state, { offset: initialContentOffset2, animated: false, index: initialScrollIndex });
2325
+ scrollTo(state, { animated: false, index: initialScrollIndex, offset: initialContentOffset2 });
2261
2326
  }
2262
2327
  return initialContentOffset2;
2263
2328
  }, [renderNum]);
@@ -2273,9 +2338,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2273
2338
  }
2274
2339
  }
2275
2340
  React3.useLayoutEffect(() => {
2276
- var _a2, _b;
2277
2341
  if (IsNewArchitecture) {
2278
- const measured = (_b = (_a2 = refScroller.current) == null ? void 0 : _a2.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a2);
2342
+ let measured;
2343
+ refScroller.current.measure((x, y, width, height) => {
2344
+ measured = { height, width, x, y };
2345
+ });
2279
2346
  if (measured) {
2280
2347
  const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
2281
2348
  if (size) {
@@ -2302,6 +2369,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2302
2369
  }
2303
2370
  }
2304
2371
  }, []);
2372
+ React3.useLayoutEffect(() => {
2373
+ if (snapToIndices) {
2374
+ updateSnapToOffsets(ctx, state);
2375
+ }
2376
+ }, [snapToIndices]);
2305
2377
  React3.useLayoutEffect(() => {
2306
2378
  const didAllocateContainers = doInitialAllocateContainersCallback();
2307
2379
  if (!didAllocateContainers) {
@@ -2314,7 +2386,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2314
2386
  React3.useLayoutEffect(() => {
2315
2387
  set$(ctx, "extraData", extraData);
2316
2388
  }, [extraData]);
2317
- React3.useLayoutEffect(initalizeStateVars, [
2389
+ React3.useLayoutEffect(initializeStateVars, [
2318
2390
  memoizedLastItemKeys.join(","),
2319
2391
  numColumnsProp,
2320
2392
  stylePaddingTopState,
@@ -2325,12 +2397,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2325
2397
  };
2326
2398
  React3.useEffect(() => {
2327
2399
  const viewability = setupViewability({
2400
+ onViewableItemsChanged,
2328
2401
  viewabilityConfig,
2329
- viewabilityConfigCallbackPairs,
2330
- onViewableItemsChanged
2402
+ viewabilityConfigCallbackPairs
2331
2403
  });
2332
2404
  state.viewabilityConfigCallbackPairs = viewability;
2333
- state.props.viewabilityConfigCallbackPairs = viewability;
2334
2405
  state.enableScrollForNextCalculateItemsInView = !viewability;
2335
2406
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
2336
2407
  if (!IsNewArchitecture) {
@@ -2345,97 +2416,94 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2345
2416
  onLayoutProp(event);
2346
2417
  }
2347
2418
  }, []);
2348
- React3.useImperativeHandle(
2349
- forwardedRef,
2350
- () => {
2351
- const scrollIndexIntoView = (options) => {
2419
+ React3.useImperativeHandle(forwardedRef, () => {
2420
+ const scrollIndexIntoView = (options) => {
2421
+ const state2 = refState.current;
2422
+ if (state2) {
2423
+ const { index, ...rest2 } = options;
2424
+ const { startNoBuffer, endNoBuffer } = state2;
2425
+ if (index < startNoBuffer || index > endNoBuffer) {
2426
+ const viewPosition = index < startNoBuffer ? 0 : 1;
2427
+ scrollToIndex(ctx, state2, {
2428
+ ...rest2,
2429
+ index,
2430
+ viewPosition
2431
+ });
2432
+ }
2433
+ }
2434
+ };
2435
+ return {
2436
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
2437
+ getNativeScrollRef: () => refScroller.current,
2438
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
2439
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
2440
+ getState: () => {
2352
2441
  const state2 = refState.current;
2353
- if (state2) {
2354
- const { index, ...rest2 } = options;
2355
- const { startNoBuffer, endNoBuffer } = state2;
2356
- if (index < startNoBuffer || index > endNoBuffer) {
2357
- const viewPosition = index < startNoBuffer ? 0 : 1;
2358
- scrollToIndex(ctx, state2, {
2359
- ...rest2,
2360
- viewPosition,
2361
- index
2362
- });
2363
- }
2442
+ return state2 ? {
2443
+ contentLength: state2.totalSize,
2444
+ end: state2.endNoBuffer,
2445
+ endBuffered: state2.endBuffered,
2446
+ isAtEnd: state2.isAtEnd,
2447
+ isAtStart: state2.isAtStart,
2448
+ positions: state2.positions,
2449
+ scroll: state2.scroll,
2450
+ scrollLength: state2.scrollLength,
2451
+ sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index)),
2452
+ sizes: state2.sizesKnown,
2453
+ start: state2.startNoBuffer,
2454
+ startBuffered: state2.startBuffered
2455
+ } : {};
2456
+ },
2457
+ scrollIndexIntoView,
2458
+ scrollItemIntoView: ({ item, ...props2 }) => {
2459
+ const data = refState.current.props.data;
2460
+ const index = data.indexOf(item);
2461
+ if (index !== -1) {
2462
+ scrollIndexIntoView({ index, ...props2 });
2364
2463
  }
2365
- };
2366
- return {
2367
- flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
2368
- getNativeScrollRef: () => refScroller.current,
2369
- getScrollableNode: () => refScroller.current.getScrollableNode(),
2370
- getScrollResponder: () => refScroller.current.getScrollResponder(),
2371
- getState: () => {
2372
- const state2 = refState.current;
2373
- return state2 ? {
2374
- contentLength: state2.totalSize,
2375
- end: state2.endNoBuffer,
2376
- endBuffered: state2.endBuffered,
2377
- isAtEnd: state2.isAtEnd,
2378
- isAtStart: state2.isAtStart,
2379
- scroll: state2.scroll,
2380
- scrollLength: state2.scrollLength,
2381
- start: state2.startNoBuffer,
2382
- startBuffered: state2.startBuffered,
2383
- sizes: state2.sizesKnown,
2384
- sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index))
2385
- } : {};
2386
- },
2387
- scrollIndexIntoView,
2388
- scrollItemIntoView: ({ item, ...props2 }) => {
2389
- const data = refState.current.props.data;
2390
- const index = data.indexOf(item);
2391
- if (index !== -1) {
2392
- scrollIndexIntoView({ index, ...props2 });
2393
- }
2394
- },
2395
- scrollToIndex: (params) => scrollToIndex(ctx, state, params),
2396
- scrollToItem: ({ item, ...props2 }) => {
2397
- const data = refState.current.props.data;
2398
- const index = data.indexOf(item);
2399
- if (index !== -1) {
2400
- scrollToIndex(ctx, state, { index, ...props2 });
2401
- }
2402
- },
2403
- scrollToOffset: (params) => scrollTo(state, params),
2404
- scrollToEnd: (options) => {
2405
- const data = refState.current.props.data;
2406
- const stylePaddingBottom = refState.current.props.stylePaddingBottom;
2407
- const index = data.length - 1;
2408
- if (index !== -1) {
2409
- const paddingBottom = stylePaddingBottom || 0;
2410
- const footerSize = peek$(ctx, "footerSize") || 0;
2411
- scrollToIndex(ctx, state, {
2412
- index,
2413
- viewPosition: 1,
2414
- viewOffset: -paddingBottom - footerSize,
2415
- ...options
2416
- });
2417
- }
2418
- },
2419
- setVisibleContentAnchorOffset: (value) => {
2420
- const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2421
- set$(ctx, "scrollAdjustUserOffset", val);
2464
+ },
2465
+ scrollToEnd: (options) => {
2466
+ const data = refState.current.props.data;
2467
+ const stylePaddingBottom = refState.current.props.stylePaddingBottom;
2468
+ const index = data.length - 1;
2469
+ if (index !== -1) {
2470
+ const paddingBottom = stylePaddingBottom || 0;
2471
+ const footerSize = peek$(ctx, "footerSize") || 0;
2472
+ scrollToIndex(ctx, state, {
2473
+ index,
2474
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
2475
+ viewPosition: 1,
2476
+ ...options
2477
+ });
2422
2478
  }
2423
- };
2424
- },
2425
- []
2426
- );
2479
+ },
2480
+ scrollToIndex: (params) => scrollToIndex(ctx, state, params),
2481
+ scrollToItem: ({ item, ...props2 }) => {
2482
+ const data = refState.current.props.data;
2483
+ const index = data.indexOf(item);
2484
+ if (index !== -1) {
2485
+ scrollToIndex(ctx, state, { index, ...props2 });
2486
+ }
2487
+ },
2488
+ scrollToOffset: (params) => scrollTo(state, params),
2489
+ setVisibleContentAnchorOffset: (value) => {
2490
+ const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2491
+ set$(ctx, "scrollAdjustUserOffset", val);
2492
+ }
2493
+ };
2494
+ }, []);
2427
2495
  if (reactNative.Platform.OS === "web") {
2428
2496
  React3.useEffect(() => {
2429
2497
  if (initialContentOffset) {
2430
- scrollTo(state, { offset: initialContentOffset, animated: false });
2498
+ scrollTo(state, { animated: false, offset: initialContentOffset });
2431
2499
  }
2432
2500
  }, []);
2433
2501
  }
2434
2502
  const fns = React3.useMemo(
2435
2503
  () => ({
2436
- updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj),
2437
2504
  getRenderedItem: (key) => getRenderedItem(ctx, state, key),
2438
- onScroll: (event) => onScroll(ctx, state, event)
2505
+ onScroll: (event) => onScroll(ctx, state, event),
2506
+ updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj)
2439
2507
  }),
2440
2508
  []
2441
2509
  );
@@ -2443,13 +2511,17 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2443
2511
  ListComponent,
2444
2512
  {
2445
2513
  ...rest,
2514
+ alignItemsAtEnd,
2446
2515
  canRender,
2516
+ contentContainerStyle,
2517
+ getRenderedItem: fns.getRenderedItem,
2447
2518
  horizontal,
2448
- refScrollView: combinedRef,
2449
2519
  initialContentOffset,
2450
- getRenderedItem: fns.getRenderedItem,
2451
- updateItemSize: fns.updateItemSize,
2452
- onScroll: fns.onScroll,
2520
+ ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
2521
+ ListHeaderComponent,
2522
+ maintainVisibleContentPosition,
2523
+ onLayout,
2524
+ onLayoutHeader,
2453
2525
  onMomentumScrollEnd: (event) => {
2454
2526
  requestAnimationFrame(() => {
2455
2527
  finishScrollTo(refState.current);
@@ -2458,31 +2530,30 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2458
2530
  onMomentumScrollEnd(event);
2459
2531
  }
2460
2532
  },
2461
- onLayout,
2533
+ onScroll: fns.onScroll,
2462
2534
  recycleItems,
2463
- alignItemsAtEnd,
2464
- ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
2465
- ListHeaderComponent,
2466
- maintainVisibleContentPosition,
2467
- scrollEventThrottle: reactNative.Platform.OS === "web" ? 16 : void 0,
2468
- waitForInitialLayout,
2469
2535
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
2470
2536
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
2471
2537
  }) : refreshControl : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
2472
2538
  reactNative.RefreshControl,
2473
2539
  {
2474
- refreshing: !!refreshing,
2475
2540
  onRefresh,
2476
- progressViewOffset: (progressViewOffset || 0) + stylePaddingTopState
2541
+ progressViewOffset: (progressViewOffset || 0) + stylePaddingTopState,
2542
+ refreshing: !!refreshing
2477
2543
  }
2478
2544
  ),
2479
- style,
2480
- contentContainerStyle,
2545
+ refScrollView: combinedRef,
2481
2546
  scrollAdjustHandler: (_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler,
2482
- onLayoutHeader
2547
+ scrollEventThrottle: reactNative.Platform.OS === "web" ? 16 : void 0,
2548
+ snapToIndices,
2549
+ style,
2550
+ updateItemSize: fns.updateItemSize,
2551
+ waitForInitialLayout
2483
2552
  }
2484
2553
  ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3__namespace.createElement(DebugView, { state: refState.current }));
2485
2554
  });
2555
+
2556
+ // src/components/LazyLegendList.tsx
2486
2557
  var typedForwardRef2 = React3.forwardRef;
2487
2558
  var renderItem = ({ item }) => item;
2488
2559
  var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedRef) {
@@ -2491,7 +2562,7 @@ var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedR
2491
2562
  const data = (isArray(children) ? children : React3__namespace.Children.toArray(children)).flat(1);
2492
2563
  return (
2493
2564
  // @ts-expect-error TODO: Fix this type
2494
- /* @__PURE__ */ React3__namespace.createElement(LegendListComponent, { ...rest, data, renderItem, ref: forwardedRef })
2565
+ /* @__PURE__ */ React3__namespace.createElement(LegendListComponent, { ...rest, data, ref: forwardedRef, renderItem })
2495
2566
  );
2496
2567
  });
2497
2568