@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.mjs CHANGED
@@ -1,23 +1,25 @@
1
1
  import * as React3 from 'react';
2
- import React3__default, { useReducer, useEffect, createContext, useMemo, useState, useRef, useLayoutEffect, useCallback, useImperativeHandle, useContext, forwardRef, memo } from 'react';
3
- import { View, Text, Platform, Animated, ScrollView, StyleSheet, Dimensions, RefreshControl } from 'react-native';
2
+ import React3__default, { useReducer, useEffect, createContext, useRef, useState, useMemo, useLayoutEffect, useCallback, useImperativeHandle, useContext, forwardRef, memo } from 'react';
3
+ import { View, Text, Platform, Animated, ScrollView, StyleSheet, Dimensions, RefreshControl, unstable_batchedUpdates } from 'react-native';
4
4
  import { useSyncExternalStore } from 'use-sync-external-store/shim';
5
5
 
6
- // src/LegendList.tsx
6
+ // src/components/LazyLegendList.tsx
7
7
  var ContextState = React3.createContext(null);
8
8
  function StateProvider({ children }) {
9
9
  const [value] = React3.useState(() => ({
10
+ columnWrapperStyle: void 0,
10
11
  listeners: /* @__PURE__ */ new Map(),
12
+ mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
13
+ mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
14
+ mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
15
+ mapViewabilityValues: /* @__PURE__ */ new Map(),
11
16
  values: /* @__PURE__ */ new Map([
12
17
  ["alignItemsPaddingTop", 0],
13
18
  ["stylePaddingTop", 0],
14
- ["headerSize", 0]
19
+ ["headerSize", 0],
20
+ ["numContainers", 0],
21
+ ["totalSize", 0]
15
22
  ]),
16
- mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
17
- mapViewabilityValues: /* @__PURE__ */ new Map(),
18
- mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
19
- mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
20
- columnWrapperStyle: void 0,
21
23
  viewRefs: /* @__PURE__ */ new Map()
22
24
  }));
23
25
  return /* @__PURE__ */ React3.createElement(ContextState.Provider, { value }, children);
@@ -29,17 +31,6 @@ function createSelectorFunctionsArr(ctx, signalNames) {
29
31
  let lastValues = [];
30
32
  let lastSignalValues = [];
31
33
  return {
32
- subscribe: (cb) => {
33
- const listeners = [];
34
- for (const signalName of signalNames) {
35
- listeners.push(listen$(ctx, signalName, cb));
36
- }
37
- return () => {
38
- for (const listener of listeners) {
39
- listener();
40
- }
41
- };
42
- },
43
34
  get: () => {
44
35
  const currentValues = [];
45
36
  let hasChanged = false;
@@ -55,6 +46,17 @@ function createSelectorFunctionsArr(ctx, signalNames) {
55
46
  lastValues = currentValues;
56
47
  }
57
48
  return lastValues;
49
+ },
50
+ subscribe: (cb) => {
51
+ const listeners = [];
52
+ for (const signalName of signalNames) {
53
+ listeners.push(listen$(ctx, signalName, cb));
54
+ }
55
+ return () => {
56
+ for (const listener of listeners) {
57
+ listener();
58
+ }
59
+ };
58
60
  }
59
61
  };
60
62
  }
@@ -89,7 +91,7 @@ function getContentSize(ctx) {
89
91
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
90
92
  const headerSize = values.get("headerSize") || 0;
91
93
  const footerSize = values.get("footerSize") || 0;
92
- const totalSize = values.get("totalSize") || 0;
94
+ const totalSize = values.get("totalSize");
93
95
  return headerSize + footerSize + totalSize + stylePaddingTop;
94
96
  }
95
97
  function useArr$(signalNames) {
@@ -105,13 +107,13 @@ function useSelector$(signalName, selector) {
105
107
  return value;
106
108
  }
107
109
 
108
- // src/DebugView.tsx
110
+ // src/components/DebugView.tsx
109
111
  var DebugRow = ({ children }) => {
110
- return /* @__PURE__ */ React3.createElement(View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" } }, children);
112
+ return /* @__PURE__ */ React3.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
111
113
  };
112
114
  var DebugView = React3.memo(function DebugView2({ state }) {
113
115
  const ctx = useStateContext();
114
- const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, numContainers = 0, numContainersPooled = 0] = useArr$([
116
+ const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
115
117
  "totalSize",
116
118
  "scrollAdjust",
117
119
  "debugRawScroll",
@@ -127,18 +129,18 @@ var DebugView = React3.memo(function DebugView2({ state }) {
127
129
  return /* @__PURE__ */ React3.createElement(
128
130
  View,
129
131
  {
132
+ pointerEvents: "none",
130
133
  style: {
131
- position: "absolute",
132
- top: 0,
133
- right: 0,
134
- paddingLeft: 4,
135
- paddingBottom: 4,
136
134
  // height: 100,
137
135
  backgroundColor: "#FFFFFFCC",
136
+ borderRadius: 4,
138
137
  padding: 4,
139
- borderRadius: 4
140
- },
141
- pointerEvents: "none"
138
+ paddingBottom: 4,
139
+ paddingLeft: 4,
140
+ position: "absolute",
141
+ right: 0,
142
+ top: 0
143
+ }
142
144
  },
143
145
  /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React3.createElement(Text, null, totalSize.toFixed(2))),
144
146
  /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React3.createElement(Text, null, contentSize.toFixed(2))),
@@ -156,8 +158,34 @@ function useInterval(callback, delay) {
156
158
  return () => clearInterval(interval);
157
159
  }, [delay]);
158
160
  }
161
+ var LeanViewComponent = React3.forwardRef((props, ref) => {
162
+ return React3.createElement("RCTView", { ...props, ref });
163
+ });
164
+ LeanViewComponent.displayName = "RCTView";
165
+ var LeanView = Platform.OS === "android" || Platform.OS === "ios" ? LeanViewComponent : View;
166
+
167
+ // src/components/Separator.tsx
168
+ function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
169
+ const [lastItemKeys] = useArr$(["lastItemKeys"]);
170
+ const isALastItem = lastItemKeys.includes(itemKey);
171
+ return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
172
+ }
173
+
174
+ // src/constants.ts
175
+ var POSITION_OUT_OF_VIEW = -1e7;
176
+ var ENABLE_DEVMODE = __DEV__ && false;
177
+ var ENABLE_DEBUG_VIEW = __DEV__ && false;
178
+ var IsNewArchitecture = global.nativeFabricUIManager != null;
179
+ var symbolFirst = Symbol();
180
+ function useInit(cb) {
181
+ const refValue = useRef(symbolFirst);
182
+ if (refValue.current === symbolFirst) {
183
+ refValue.current = cb();
184
+ }
185
+ return refValue.current;
186
+ }
159
187
 
160
- // src/helpers.ts
188
+ // src/utils/helpers.ts
161
189
  function isFunction(obj) {
162
190
  return typeof obj === "function";
163
191
  }
@@ -187,16 +215,8 @@ function getPadding(s, type) {
187
215
  function extractPadding(style, contentContainerStyle, type) {
188
216
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
189
217
  }
190
- var symbolFirst = Symbol();
191
- function useInit(cb) {
192
- const refValue = useRef(symbolFirst);
193
- if (refValue.current === symbolFirst) {
194
- refValue.current = cb();
195
- }
196
- return refValue.current;
197
- }
198
218
 
199
- // src/ContextContainer.ts
219
+ // src/state/ContextContainer.ts
200
220
  var ContextContainer = createContext(null);
201
221
  function useViewability(callback, configId) {
202
222
  const ctx = useStateContext();
@@ -240,7 +260,7 @@ function useRecyclingEffect(effect) {
240
260
  prevItem: void 0
241
261
  });
242
262
  useEffect(() => {
243
- let ret = void 0;
263
+ let ret;
244
264
  if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
245
265
  ret = effect({
246
266
  index,
@@ -254,7 +274,7 @@ function useRecyclingEffect(effect) {
254
274
  prevItem: value
255
275
  };
256
276
  return ret;
257
- }, [index, value]);
277
+ }, [index, value, effect]);
258
278
  }
259
279
  function useRecyclingState(valueOrFun) {
260
280
  const { index, value, itemKey, triggerLayout } = useContext(ContextContainer);
@@ -292,34 +312,18 @@ function useListScrollSize() {
292
312
  const [scrollSize] = useArr$(["scrollSize"]);
293
313
  return scrollSize;
294
314
  }
295
- var LeanViewComponent = React3.forwardRef((props, ref) => {
296
- return React3.createElement("RCTView", { ...props, ref });
297
- });
298
- LeanViewComponent.displayName = "RCTView";
299
- var LeanView = Platform.OS === "android" || Platform.OS === "ios" ? LeanViewComponent : View;
300
-
301
- // src/Separator.tsx
302
- function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
303
- const [lastItemKeys] = useArr$(["lastItemKeys"]);
304
- const isALastItem = lastItemKeys.includes(itemKey);
305
- return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
306
- }
307
-
308
- // src/constants.ts
309
- var POSITION_OUT_OF_VIEW = -1e7;
310
- var ENABLE_DEVMODE = __DEV__ && false;
311
- var ENABLE_DEBUG_VIEW = __DEV__ && false;
312
- var IsNewArchitecture = global.nativeFabricUIManager != null;
315
+ var typedForwardRef = forwardRef;
316
+ var typedMemo = memo;
313
317
 
314
- // src/Container.tsx
315
- var Container = ({
318
+ // src/components/Container.tsx
319
+ var Container = typedMemo(function Container2({
316
320
  id,
317
321
  recycleItems,
318
322
  horizontal,
319
323
  getRenderedItem: getRenderedItem2,
320
324
  updateItemSize: updateItemSize2,
321
325
  ItemSeparatorComponent
322
- }) => {
326
+ }) {
323
327
  const ctx = useStateContext();
324
328
  const columnWrapperStyle = ctx.columnWrapperStyle;
325
329
  const [column = 0, data, itemKey, position = POSITION_OUT_OF_VIEW, numColumns, extraData] = useArr$([
@@ -353,17 +357,17 @@ var Container = ({
353
357
  }
354
358
  const style = horizontal ? {
355
359
  flexDirection: ItemSeparatorComponent ? "row" : void 0,
356
- position: "absolute",
357
- top: otherAxisPos,
358
360
  height: otherAxisSize,
359
361
  left: position,
362
+ position: "absolute",
363
+ top: otherAxisPos,
360
364
  ...paddingStyles || {}
361
365
  } : {
362
- position: "absolute",
363
366
  left: otherAxisPos,
367
+ position: "absolute",
364
368
  right: numColumns > 1 ? null : 0,
365
- width: otherAxisSize,
366
369
  top: position,
370
+ width: otherAxisSize,
367
371
  ...paddingStyles || {}
368
372
  };
369
373
  const renderedItemInfo = useMemo(
@@ -371,12 +375,17 @@ var Container = ({
371
375
  [itemKey, data, extraData]
372
376
  );
373
377
  const { index, renderedItem } = renderedItemInfo || {};
374
- const triggerLayout = useCallback(() => {
375
- forceLayoutRender((v) => v + 1);
376
- }, []);
377
378
  const contextValue = useMemo(() => {
378
379
  ctx.viewRefs.set(id, ref);
379
- return { containerId: id, itemKey, index, value: data, triggerLayout };
380
+ return {
381
+ containerId: id,
382
+ index,
383
+ itemKey,
384
+ triggerLayout: () => {
385
+ forceLayoutRender((v) => v + 1);
386
+ },
387
+ value: data
388
+ };
380
389
  }, [id, itemKey, index, data]);
381
390
  const onLayout = (event) => {
382
391
  var _a, _b;
@@ -385,14 +394,14 @@ var Container = ({
385
394
  let layout = event.nativeEvent.layout;
386
395
  const size = layout[horizontal ? "width" : "height"];
387
396
  const doUpdate = () => {
388
- refLastSize.current = { width: layout.width, height: layout.height };
397
+ refLastSize.current = { height: layout.height, width: layout.width };
389
398
  updateItemSize2(itemKey, layout);
390
399
  };
391
400
  if (IsNewArchitecture || size > 0) {
392
401
  doUpdate();
393
402
  } else {
394
- (_b = (_a = ref.current) == null ? void 0 : _a.measure) == null ? void 0 : _b.call(_a, (x, y, width, height) => {
395
- layout = { width, height };
403
+ (_b = (_a = ref.current) == null ? void 0 : _a.measure) == null ? void 0 : _b.call(_a, (_x, _y, width, height) => {
404
+ layout = { height, width };
396
405
  doUpdate();
397
406
  });
398
407
  }
@@ -425,30 +434,28 @@ var Container = ({
425
434
  }
426
435
  }, [itemKey]);
427
436
  }
428
- return /* @__PURE__ */ React3.createElement(LeanView, { style, onLayout, ref, key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React3.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3.createElement(
437
+ return /* @__PURE__ */ React3.createElement(LeanView, { key: recycleItems ? void 0 : itemKey, onLayout, ref, style }, /* @__PURE__ */ React3.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3.createElement(
429
438
  Separator,
430
439
  {
431
- itemKey,
432
440
  ItemSeparatorComponent,
441
+ itemKey,
433
442
  leadingItem: renderedItemInfo.item
434
443
  }
435
444
  )));
436
- };
437
- var typedForwardRef = forwardRef;
438
- var typedMemo = memo;
445
+ });
439
446
  var useAnimatedValue = (initialValue) => {
440
447
  return useRef(new Animated.Value(initialValue)).current;
441
448
  };
442
449
 
443
- // src/useValue$.ts
450
+ // src/hooks/useValue$.ts
444
451
  function useValue$(key, params) {
445
452
  var _a;
446
453
  const { getValue, delay } = params || {};
447
454
  const ctx = useStateContext();
448
455
  const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
449
456
  useMemo(() => {
450
- let newValue = void 0;
451
- let prevValue = void 0;
457
+ let newValue;
458
+ let prevValue;
452
459
  let didQueueTask = false;
453
460
  listen$(ctx, key, (v) => {
454
461
  newValue = getValue ? getValue(v) : v;
@@ -477,7 +484,7 @@ function useValue$(key, params) {
477
484
  return animValue;
478
485
  }
479
486
 
480
- // src/Containers.tsx
487
+ // src/components/Containers.tsx
481
488
  var Containers = typedMemo(function Containers2({
482
489
  horizontal,
483
490
  recycleItems,
@@ -501,18 +508,18 @@ var Containers = typedMemo(function Containers2({
501
508
  /* @__PURE__ */ React3.createElement(
502
509
  Container,
503
510
  {
511
+ getRenderedItem: getRenderedItem2,
512
+ horizontal,
513
+ ItemSeparatorComponent,
504
514
  id: i,
505
515
  key: i,
506
516
  recycleItems,
507
- horizontal,
508
- getRenderedItem: getRenderedItem2,
509
- updateItemSize: updateItemSize2,
510
- ItemSeparatorComponent
517
+ updateItemSize: updateItemSize2
511
518
  }
512
519
  )
513
520
  );
514
521
  }
515
- const style = horizontal ? { width: animSize, opacity: animOpacity, minHeight: otherAxisSize } : { height: animSize, opacity: animOpacity, minWidth: otherAxisSize };
522
+ const style = horizontal ? { minHeight: otherAxisSize, opacity: animOpacity, width: animSize } : { height: animSize, minWidth: otherAxisSize, opacity: animOpacity };
516
523
  if (columnWrapperStyle && numColumns > 1) {
517
524
  const { columnGap, rowGap, gap } = columnWrapperStyle;
518
525
  const gapX = columnGap || gap || 0;
@@ -543,15 +550,21 @@ function ScrollAdjust() {
543
550
  View,
544
551
  {
545
552
  style: {
546
- position: "absolute",
547
553
  height: 0,
548
- width: 0,
554
+ left: 0,
555
+ position: "absolute",
549
556
  top: scrollOffset,
550
- left: 0
557
+ width: 0
551
558
  }
552
559
  }
553
560
  );
554
561
  }
562
+
563
+ // src/components/SnapWrapper.tsx
564
+ function SnapWrapper({ ScrollComponent, ...props }) {
565
+ const [snapToOffsets] = useArr$(["snapToOffsets"]);
566
+ return /* @__PURE__ */ React.createElement(ScrollComponent, { ...props, snapToOffsets });
567
+ }
555
568
  function useSyncLayout({
556
569
  onChange
557
570
  }) {
@@ -562,17 +575,19 @@ function useSyncLayout({
562
575
  },
563
576
  [onChange]
564
577
  );
565
- useLayoutEffect(() => {
566
- if (ref.current) {
567
- ref.current.measure((x, y, width, height) => {
568
- onChange({ x, y, width, height }, true);
569
- });
570
- }
571
- }, []);
578
+ if (IsNewArchitecture) {
579
+ useLayoutEffect(() => {
580
+ if (ref.current) {
581
+ ref.current.measure((x, y, width, height) => {
582
+ onChange({ height, width, x, y }, true);
583
+ });
584
+ }
585
+ }, []);
586
+ }
572
587
  return { onLayout, ref };
573
588
  }
574
589
 
575
- // src/ListComponent.tsx
590
+ // src/components/ListComponent.tsx
576
591
  var getComponent = (Component) => {
577
592
  if (React3.isValidElement(Component)) {
578
593
  return Component;
@@ -592,12 +607,12 @@ var PaddingDevMode = () => {
592
607
  Animated.View,
593
608
  {
594
609
  style: {
595
- position: "absolute",
596
- top: 0,
610
+ backgroundColor: "green",
597
611
  height: animPaddingTop,
598
612
  left: 0,
613
+ position: "absolute",
599
614
  right: 0,
600
- backgroundColor: "green"
615
+ top: 0
601
616
  }
602
617
  }
603
618
  ));
@@ -626,6 +641,7 @@ var ListComponent = typedMemo(function ListComponent2({
626
641
  renderScrollComponent,
627
642
  scrollAdjustHandler,
628
643
  onLayoutHeader,
644
+ snapToIndices,
629
645
  ...rest
630
646
  }) {
631
647
  const ctx = useStateContext();
@@ -643,76 +659,56 @@ var ListComponent = typedMemo(function ListComponent2({
643
659
  }, 0);
644
660
  }
645
661
  }, [canRender]);
662
+ const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
646
663
  return /* @__PURE__ */ React3.createElement(
647
- ScrollComponent,
664
+ SnapOrScroll,
648
665
  {
649
666
  ...rest,
650
- style,
651
- maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
652
667
  contentContainerStyle: [
653
668
  contentContainerStyle,
654
669
  horizontal ? {
655
670
  height: "100%"
656
671
  } : {}
657
672
  ],
658
- onScroll: onScroll2,
659
- onLayout,
660
- horizontal,
661
673
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
662
- ref: refScrollView
674
+ horizontal,
675
+ maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
676
+ onLayout,
677
+ onScroll: onScroll2,
678
+ ref: refScrollView,
679
+ ScrollComponent: snapToIndices ? ScrollComponent : void 0,
680
+ style
663
681
  },
664
682
  maintainVisibleContentPosition && /* @__PURE__ */ React3.createElement(ScrollAdjust, null),
665
683
  ENABLE_DEVMODE ? /* @__PURE__ */ React3.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3.createElement(Padding, null),
666
- ListHeaderComponent && /* @__PURE__ */ React3.createElement(View, { style: ListHeaderComponentStyle, onLayout: onLayoutHeaderSync, ref: refHeader }, getComponent(ListHeaderComponent)),
684
+ ListHeaderComponent && /* @__PURE__ */ React3.createElement(View, { onLayout: onLayoutHeaderSync, ref: refHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
667
685
  ListEmptyComponent && getComponent(ListEmptyComponent),
668
686
  canRender && /* @__PURE__ */ React3.createElement(
669
687
  Containers,
670
688
  {
671
- horizontal,
672
- recycleItems,
673
- waitForInitialLayout,
674
689
  getRenderedItem: getRenderedItem2,
690
+ horizontal,
675
691
  ItemSeparatorComponent,
676
- updateItemSize: updateItemSize2
692
+ recycleItems,
693
+ updateItemSize: updateItemSize2,
694
+ waitForInitialLayout
677
695
  }
678
696
  ),
679
697
  ListFooterComponent && /* @__PURE__ */ React3.createElement(
680
698
  View,
681
699
  {
682
- style: ListFooterComponentStyle,
683
700
  onLayout: (event) => {
684
701
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
685
702
  set$(ctx, "footerSize", size);
686
- }
703
+ },
704
+ style: ListFooterComponentStyle
687
705
  },
688
706
  getComponent(ListFooterComponent)
689
707
  )
690
708
  );
691
709
  });
692
710
 
693
- // src/ScrollAdjustHandler.ts
694
- var ScrollAdjustHandler = class {
695
- constructor(ctx) {
696
- this.appliedAdjust = 0;
697
- this.mounted = false;
698
- this.context = ctx;
699
- }
700
- requestAdjust(add) {
701
- const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
702
- this.appliedAdjust = add + oldAdjustTop;
703
- const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
704
- if (this.mounted) {
705
- set();
706
- } else {
707
- requestAnimationFrame(set);
708
- }
709
- }
710
- setMounted() {
711
- this.mounted = true;
712
- }
713
- };
714
-
715
- // src/getId.ts
711
+ // src/utils/getId.ts
716
712
  function getId(state, index) {
717
713
  const { data, keyExtractor } = state.props;
718
714
  if (!data) {
@@ -724,7 +720,7 @@ function getId(state, index) {
724
720
  return id;
725
721
  }
726
722
 
727
- // src/calculateOffsetForIndex.ts
723
+ // src/core/calculateOffsetForIndex.ts
728
724
  function calculateOffsetForIndex(ctx, state, index) {
729
725
  let position = 0;
730
726
  if (index !== void 0) {
@@ -741,7 +737,7 @@ function calculateOffsetForIndex(ctx, state, index) {
741
737
  return position;
742
738
  }
743
739
 
744
- // src/getItemSize.ts
740
+ // src/utils/getItemSize.ts
745
741
  function getItemSize(state, key, index, data, useAverageSize) {
746
742
  const {
747
743
  sizesKnown,
@@ -754,7 +750,7 @@ function getItemSize(state, key, index, data, useAverageSize) {
754
750
  return sizeKnown;
755
751
  }
756
752
  let size;
757
- if (IsNewArchitecture && useAverageSize !== void 0 && sizeKnown === void 0 && !getEstimatedItemSize && !scrollingTo) {
753
+ if (useAverageSize !== void 0 && sizeKnown === void 0 && !getEstimatedItemSize && !scrollingTo) {
758
754
  size = useAverageSize;
759
755
  }
760
756
  if (size === void 0) {
@@ -770,7 +766,7 @@ function getItemSize(state, key, index, data, useAverageSize) {
770
766
  return size;
771
767
  }
772
768
 
773
- // src/calculateOffsetWithOffsetPosition.ts
769
+ // src/core/calculateOffsetWithOffsetPosition.ts
774
770
  function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
775
771
  const { index, viewOffset, viewPosition } = params;
776
772
  let offset = offsetParam;
@@ -783,330 +779,85 @@ function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
783
779
  return offset;
784
780
  }
785
781
 
786
- // src/checkAllSizesKnown.ts
787
- function checkAllSizesKnown(state) {
788
- const { startBuffered, endBuffered, sizesKnown } = state;
789
- if (endBuffered !== null) {
790
- let areAllKnown = true;
791
- for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
792
- const key = getId(state, i);
793
- areAllKnown && (areAllKnown = sizesKnown.has(key));
782
+ // src/utils/requestAdjust.ts
783
+ function requestAdjust(ctx, state, positionDiff) {
784
+ if (Math.abs(positionDiff) > 0.1) {
785
+ const doit = () => {
786
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
787
+ };
788
+ state.scroll += positionDiff;
789
+ state.scrollForNextCalculateItemsInView = void 0;
790
+ const didLayout = peek$(ctx, "containersDidLayout");
791
+ if (didLayout) {
792
+ doit();
793
+ const threshold = state.scroll - positionDiff / 2;
794
+ if (!state.ignoreScrollFromMVCP) {
795
+ state.ignoreScrollFromMVCP = {};
796
+ }
797
+ if (positionDiff > 0) {
798
+ state.ignoreScrollFromMVCP.lt = threshold;
799
+ } else {
800
+ state.ignoreScrollFromMVCP.gt = threshold;
801
+ }
802
+ if (state.ignoreScrollFromMVCPTimeout) {
803
+ clearTimeout(state.ignoreScrollFromMVCPTimeout);
804
+ }
805
+ state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
806
+ state.ignoreScrollFromMVCP = void 0;
807
+ }, 100);
808
+ } else {
809
+ requestAnimationFrame(doit);
794
810
  }
795
- return areAllKnown;
796
811
  }
797
- return false;
798
812
  }
799
813
 
800
- // src/findAvailableContainers.ts
801
- function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
802
- const numContainers = peek$(ctx, "numContainers");
803
- const result = [];
804
- const availableContainers = [];
805
- for (let u = 0; u < numContainers; u++) {
806
- const key = peek$(ctx, `containerItemKey${u}`);
807
- let isOk = key === void 0;
808
- if (!isOk) {
809
- const index = pendingRemoval.indexOf(u);
810
- if (index !== -1) {
811
- pendingRemoval.splice(index, 1);
812
- isOk = true;
813
- }
814
- }
815
- if (isOk) {
816
- result.push(u);
817
- if (result.length >= numNeeded) {
818
- return result;
819
- }
814
+ // src/core/prepareMVCP.ts
815
+ function prepareMVCP(ctx, state) {
816
+ const {
817
+ positions,
818
+ scrollingTo,
819
+ props: { maintainVisibleContentPosition }
820
+ } = state;
821
+ let prevPosition;
822
+ let targetId;
823
+ let targetIndex;
824
+ const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
825
+ if (maintainVisibleContentPosition) {
826
+ const indexByKey = state.indexByKey;
827
+ if (scrollTarget !== void 0) {
828
+ targetId = getId(state, scrollTarget);
829
+ targetIndex = scrollTarget;
830
+ } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
831
+ targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
832
+ targetIndex = indexByKey.get(targetId);
820
833
  }
821
- }
822
- for (let u = 0; u < numContainers; u++) {
823
- const key = peek$(ctx, `containerItemKey${u}`);
824
- if (key === void 0) continue;
825
- const index = state.indexByKey.get(key);
826
- if (index < startBuffered) {
827
- availableContainers.push({ index: u, distance: startBuffered - index });
828
- } else if (index > endBuffered) {
829
- availableContainers.push({ index: u, distance: index - endBuffered });
834
+ if (targetId !== void 0 && targetIndex !== void 0) {
835
+ prevPosition = positions.get(targetId);
830
836
  }
831
837
  }
832
- const remaining = numNeeded - result.length;
833
- if (remaining > 0) {
834
- if (availableContainers.length > 0) {
835
- if (availableContainers.length > remaining) {
836
- availableContainers.sort(comparatorByDistance);
837
- availableContainers.length = remaining;
838
- }
839
- for (const container of availableContainers) {
840
- result.push(container.index);
841
- }
842
- }
843
- const stillNeeded = numNeeded - result.length;
844
- if (stillNeeded > 0) {
845
- for (let i = 0; i < stillNeeded; i++) {
846
- result.push(numContainers + i);
847
- }
848
- if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
849
- console.warn(
850
- "[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.",
851
- {
852
- debugInfo: {
853
- numContainers,
854
- numNeeded,
855
- stillNeeded,
856
- numContainersPooled: peek$(ctx, "numContainersPooled")
857
- }
858
- }
859
- );
860
- }
861
- }
862
- }
863
- return result.sort(comparatorDefault);
864
- }
865
- function comparatorByDistance(a, b) {
866
- return b.distance - a.distance;
867
- }
868
-
869
- // src/getScrollVelocity.ts
870
- var getScrollVelocity = (state) => {
871
- const { scrollHistory } = state;
872
- let velocity = 0;
873
- if (scrollHistory.length >= 1) {
874
- const newest = scrollHistory[scrollHistory.length - 1];
875
- let oldest;
876
- let start = 0;
877
- for (let i = 0; i < scrollHistory.length - 1; i++) {
878
- const entry = scrollHistory[i];
879
- const nextEntry = scrollHistory[i + 1];
880
- if (i > 0) {
881
- const prevEntry = scrollHistory[i - 1];
882
- const prevDirection = entry.scroll - prevEntry.scroll;
883
- const currentDirection = nextEntry.scroll - entry.scroll;
884
- if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
885
- start = i;
886
- break;
887
- }
888
- }
889
- }
890
- for (let i = start; i < scrollHistory.length - 1; i++) {
891
- const entry = scrollHistory[i];
892
- if (newest.time - entry.time <= 1e3) {
893
- oldest = entry;
894
- break;
895
- }
896
- }
897
- if (oldest) {
898
- const scrollDiff = newest.scroll - oldest.scroll;
899
- const timeDiff = newest.time - oldest.time;
900
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
901
- }
902
- }
903
- return velocity;
904
- };
905
-
906
- // src/requestAdjust.ts
907
- function requestAdjust(ctx, state, positionDiff) {
908
- if (Math.abs(positionDiff) > 0.1) {
909
- const doit = () => {
910
- state.scrollAdjustHandler.requestAdjust(positionDiff);
911
- };
912
- state.scroll += positionDiff;
913
- state.scrollForNextCalculateItemsInView = void 0;
914
- if (peek$(ctx, "containersDidLayout")) {
915
- doit();
916
- } else {
917
- requestAnimationFrame(doit);
918
- }
919
- const threshold = state.scroll - positionDiff / 2;
920
- if (!state.ignoreScrollFromMVCP) {
921
- state.ignoreScrollFromMVCP = {};
922
- }
923
- if (positionDiff > 0) {
924
- state.ignoreScrollFromMVCP.lt = threshold;
925
- } else {
926
- state.ignoreScrollFromMVCP.gt = threshold;
927
- }
928
- if (state.ignoreScrollFromMVCPTimeout) {
929
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
930
- }
931
- state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
932
- state.ignoreScrollFromMVCP = void 0;
933
- }, 100);
934
- }
935
- }
936
-
937
- // src/prepareMVCP.ts
938
- function prepareMVCP(ctx, state) {
939
- const {
940
- positions,
941
- scrollingTo,
942
- props: { maintainVisibleContentPosition }
943
- } = state;
944
- let prevPosition;
945
- let targetId;
946
- let targetIndex;
947
- const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
948
- if (maintainVisibleContentPosition) {
949
- const indexByKey = state.indexByKey;
950
- if (scrollTarget !== void 0) {
951
- targetId = getId(state, scrollTarget);
952
- targetIndex = scrollTarget;
953
- } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
954
- targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
955
- targetIndex = indexByKey.get(targetId);
956
- }
957
- if (targetId !== void 0 && targetIndex !== void 0) {
958
- prevPosition = positions.get(targetId);
959
- }
960
- }
961
- return () => {
962
- if (targetId !== void 0 && prevPosition !== void 0) {
963
- const newPosition = positions.get(targetId);
964
- if (newPosition !== void 0) {
965
- const positionDiff = newPosition - prevPosition;
966
- if (Math.abs(positionDiff) > 0.1) {
967
- requestAdjust(ctx, state, positionDiff);
968
- }
838
+ return () => {
839
+ if (targetId !== void 0 && prevPosition !== void 0) {
840
+ const newPosition = positions.get(targetId);
841
+ if (newPosition !== void 0) {
842
+ const positionDiff = newPosition - prevPosition;
843
+ if (Math.abs(positionDiff) > 0.1) {
844
+ requestAdjust(ctx, state, positionDiff);
845
+ }
969
846
  }
970
847
  }
971
848
  };
972
849
  }
973
850
 
974
- // src/checkThreshold.ts
975
- var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
976
- const distanceAbs = Math.abs(distance);
977
- const isAtThreshold = atThreshold || distanceAbs < threshold;
978
- if (!isReached && !isBlockedByTimer) {
979
- if (isAtThreshold) {
980
- onReached == null ? void 0 : onReached(distance);
981
- blockTimer == null ? void 0 : blockTimer(true);
982
- setTimeout(() => {
983
- blockTimer == null ? void 0 : blockTimer(false);
984
- }, 700);
985
- return true;
986
- }
987
- } else {
988
- if (distance >= 1.3 * threshold) {
989
- return false;
990
- }
991
- }
992
- return isReached;
993
- };
994
-
995
- // src/checkAtBottom.ts
996
- function checkAtBottom(ctx, state) {
997
- if (!state) {
998
- return;
999
- }
1000
- const {
1001
- queuedInitialLayout,
1002
- scrollLength,
1003
- scroll,
1004
- maintainingScrollAtEnd,
1005
- props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1006
- } = state;
1007
- const contentSize = getContentSize(ctx);
1008
- if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1009
- const distanceFromEnd = contentSize - scroll - scrollLength;
1010
- const isContentLess = contentSize < scrollLength;
1011
- state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1012
- state.isEndReached = checkThreshold(
1013
- distanceFromEnd,
1014
- isContentLess,
1015
- onEndReachedThreshold * scrollLength,
1016
- state.isEndReached,
1017
- state.endReachedBlockedByTimer,
1018
- (distance) => {
1019
- var _a, _b;
1020
- return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1021
- },
1022
- (block) => {
1023
- state.endReachedBlockedByTimer = block;
1024
- }
1025
- );
1026
- }
1027
- }
1028
-
1029
- // src/finishScrollTo.ts
1030
- var finishScrollTo = (state) => {
1031
- if (state) {
1032
- state.scrollingTo = void 0;
1033
- state.scrollHistory.length = 0;
1034
- }
1035
- };
1036
-
1037
- // src/scrollTo.ts
1038
- function scrollTo(state, params = {}) {
1039
- var _a;
1040
- const { animated } = params;
1041
- const {
1042
- refScroller,
1043
- props: { horizontal }
1044
- } = state;
1045
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1046
- state.scrollHistory.length = 0;
1047
- state.scrollingTo = params;
1048
- state.scrollPending = offset;
1049
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1050
- x: horizontal ? offset : 0,
1051
- y: horizontal ? 0 : offset,
1052
- animated: !!animated
1053
- });
1054
- if (!animated) {
1055
- state.scroll = offset;
1056
- setTimeout(() => finishScrollTo(state), 100);
1057
- }
1058
- }
1059
-
1060
- // src/scrollToIndex.ts
1061
- function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1062
- if (index >= state.props.data.length) {
1063
- index = state.props.data.length - 1;
1064
- } else if (index < 0) {
1065
- index = 0;
1066
- }
1067
- const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
1068
- const isLast = index === state.props.data.length - 1;
1069
- if (isLast && viewPosition === void 0) {
1070
- viewPosition = 1;
1071
- }
1072
- const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1073
- state.scrollForNextCalculateItemsInView = void 0;
1074
- scrollTo(state, {
1075
- offset: firstIndexScrollPostion,
1076
- animated,
1077
- index,
1078
- viewPosition: viewPosition != null ? viewPosition : 0,
1079
- viewOffset
1080
- });
1081
- }
1082
-
1083
- // src/setDidLayout.ts
1084
- function setDidLayout(ctx, state) {
1085
- const {
1086
- loadStartTime,
1087
- initialScroll,
1088
- props: { onLoad }
1089
- } = state;
1090
- state.queuedInitialLayout = true;
1091
- checkAtBottom(ctx, state);
1092
- if (!IsNewArchitecture && initialScroll) {
1093
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1094
- }
1095
- set$(ctx, "containersDidLayout", true);
1096
- if (onLoad) {
1097
- onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1098
- }
1099
- }
1100
-
1101
- // src/setPaddingTop.ts
1102
- function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
851
+ // src/utils/setPaddingTop.ts
852
+ function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1103
853
  if (stylePaddingTop !== void 0) {
1104
854
  const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1105
855
  if (stylePaddingTop < prevStylePaddingTop) {
1106
- const prevTotalSize = peek$(ctx, "totalSize") || 0;
856
+ let prevTotalSize = peek$(ctx, "totalSize");
1107
857
  set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
1108
- setTimeout(() => {
1109
- set$(ctx, "totalSize", prevTotalSize);
858
+ state.timeoutSetPaddingTop = setTimeout(() => {
859
+ prevTotalSize = peek$(ctx, "totalSize");
860
+ set$(ctx, "totalSize", prevTotalSize - prevStylePaddingTop);
1110
861
  }, 16);
1111
862
  }
1112
863
  set$(ctx, "stylePaddingTop", stylePaddingTop);
@@ -1116,7 +867,7 @@ function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
1116
867
  }
1117
868
  }
1118
869
 
1119
- // src/updateAlignItemsPaddingTop.ts
870
+ // src/utils/updateAlignItemsPaddingTop.ts
1120
871
  function updateAlignItemsPaddingTop(ctx, state) {
1121
872
  const {
1122
873
  scrollLength,
@@ -1128,11 +879,11 @@ function updateAlignItemsPaddingTop(ctx, state) {
1128
879
  const contentSize = getContentSize(ctx);
1129
880
  alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1130
881
  }
1131
- setPaddingTop(ctx, { alignItemsPaddingTop });
882
+ setPaddingTop(ctx, state, { alignItemsPaddingTop });
1132
883
  }
1133
884
  }
1134
885
 
1135
- // src/updateTotalSize.ts
886
+ // src/core/updateTotalSize.ts
1136
887
  function updateTotalSize(ctx, state) {
1137
888
  const {
1138
889
  positions,
@@ -1158,6 +909,10 @@ function addTotalSize(ctx, state, key, add) {
1158
909
  const { alignItemsAtEnd } = state.props;
1159
910
  {
1160
911
  state.totalSize = add;
912
+ if (state.timeoutSetPaddingTop) {
913
+ clearTimeout(state.timeoutSetPaddingTop);
914
+ state.timeoutSetPaddingTop = void 0;
915
+ }
1161
916
  }
1162
917
  set$(ctx, "totalSize", state.totalSize);
1163
918
  if (alignItemsAtEnd) {
@@ -1165,32 +920,93 @@ function addTotalSize(ctx, state, key, add) {
1165
920
  }
1166
921
  }
1167
922
 
1168
- // src/updateAllPositions.ts
1169
- function updateAllPositions(ctx, state, dataChanged) {
1170
- var _a, _b, _c, _d, _e;
1171
- const { averageSizes, columns, indexByKey, positions, firstFullyOnScreenIndex, idCache, sizesKnown } = state;
1172
- const data = state.props.data;
1173
- const numColumns = peek$(ctx, "numColumns");
1174
- const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1175
- const scrollVelocity = getScrollVelocity(state);
1176
- if (dataChanged) {
1177
- indexByKey.clear();
1178
- idCache.clear();
1179
- }
1180
- const itemType = "";
1181
- let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
1182
- if (averageSize !== void 0) {
1183
- averageSize = roundSize(averageSize);
1184
- }
1185
- const shouldUseBackwards = !dataChanged && scrollVelocity < 0 && firstFullyOnScreenIndex > 5 && firstFullyOnScreenIndex < data.length;
1186
- if (shouldUseBackwards && firstFullyOnScreenIndex !== void 0) {
1187
- const anchorId = getId(state, firstFullyOnScreenIndex);
1188
- const anchorPosition = positions.get(anchorId);
1189
- if (anchorPosition !== void 0) {
1190
- let currentRowTop2 = anchorPosition;
1191
- let maxSizeInRow2 = 0;
1192
- let bailout = false;
1193
- for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
923
+ // src/utils/getScrollVelocity.ts
924
+ var getScrollVelocity = (state) => {
925
+ const { scrollHistory } = state;
926
+ let velocity = 0;
927
+ if (scrollHistory.length >= 1) {
928
+ const newest = scrollHistory[scrollHistory.length - 1];
929
+ let oldest;
930
+ let start = 0;
931
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
932
+ const entry = scrollHistory[i];
933
+ const nextEntry = scrollHistory[i + 1];
934
+ if (i > 0) {
935
+ const prevEntry = scrollHistory[i - 1];
936
+ const prevDirection = entry.scroll - prevEntry.scroll;
937
+ const currentDirection = nextEntry.scroll - entry.scroll;
938
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
939
+ start = i;
940
+ break;
941
+ }
942
+ }
943
+ }
944
+ for (let i = start; i < scrollHistory.length - 1; i++) {
945
+ const entry = scrollHistory[i];
946
+ if (newest.time - entry.time <= 1e3) {
947
+ oldest = entry;
948
+ break;
949
+ }
950
+ }
951
+ if (oldest) {
952
+ const scrollDiff = newest.scroll - oldest.scroll;
953
+ const timeDiff = newest.time - oldest.time;
954
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
955
+ }
956
+ }
957
+ return velocity;
958
+ };
959
+
960
+ // src/utils/updateSnapToOffsets.ts
961
+ function updateSnapToOffsets(ctx, state) {
962
+ const {
963
+ positions,
964
+ props: { snapToIndices }
965
+ } = state;
966
+ const snapToOffsets = Array(snapToIndices.length);
967
+ for (let i = 0; i < snapToIndices.length; i++) {
968
+ const idx = snapToIndices[i];
969
+ const key = getId(state, idx);
970
+ snapToOffsets[i] = positions.get(key);
971
+ }
972
+ set$(ctx, "snapToOffsets", snapToOffsets);
973
+ }
974
+
975
+ // src/core/updateAllPositions.ts
976
+ function updateAllPositions(ctx, state, dataChanged) {
977
+ var _a, _b, _c, _d, _e;
978
+ const {
979
+ averageSizes,
980
+ columns,
981
+ indexByKey,
982
+ positions,
983
+ firstFullyOnScreenIndex,
984
+ idCache,
985
+ sizesKnown,
986
+ props: { snapToIndices }
987
+ } = state;
988
+ const data = state.props.data;
989
+ const numColumns = peek$(ctx, "numColumns");
990
+ const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
991
+ const scrollVelocity = getScrollVelocity(state);
992
+ if (dataChanged) {
993
+ indexByKey.clear();
994
+ idCache.clear();
995
+ }
996
+ const itemType = "";
997
+ let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
998
+ if (averageSize !== void 0) {
999
+ averageSize = roundSize(averageSize);
1000
+ }
1001
+ const shouldUseBackwards = !dataChanged && scrollVelocity < 0 && firstFullyOnScreenIndex > 5 && firstFullyOnScreenIndex < data.length;
1002
+ if (shouldUseBackwards && firstFullyOnScreenIndex !== void 0) {
1003
+ const anchorId = getId(state, firstFullyOnScreenIndex);
1004
+ const anchorPosition = positions.get(anchorId);
1005
+ if (anchorPosition !== void 0) {
1006
+ let currentRowTop2 = anchorPosition;
1007
+ let maxSizeInRow2 = 0;
1008
+ let bailout = false;
1009
+ for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
1194
1010
  const id = (_b = idCache.get(i)) != null ? _b : getId(state, i);
1195
1011
  const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(state, id, i, data[i], averageSize);
1196
1012
  const itemColumn = columns.get(id);
@@ -1248,9 +1064,12 @@ function updateAllPositions(ctx, state, dataChanged) {
1248
1064
  }
1249
1065
  }
1250
1066
  updateTotalSize(ctx, state);
1067
+ if (snapToIndices) {
1068
+ updateSnapToOffsets(ctx, state);
1069
+ }
1251
1070
  }
1252
1071
 
1253
- // src/viewability.ts
1072
+ // src/core/viewability.ts
1254
1073
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
1255
1074
  function setupViewability(props) {
1256
1075
  let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
@@ -1258,27 +1077,31 @@ function setupViewability(props) {
1258
1077
  viewabilityConfigCallbackPairs = [
1259
1078
  ...viewabilityConfigCallbackPairs || [],
1260
1079
  {
1080
+ onViewableItemsChanged,
1261
1081
  viewabilityConfig: viewabilityConfig || {
1262
1082
  viewAreaCoveragePercentThreshold: 0
1263
- },
1264
- onViewableItemsChanged
1083
+ }
1265
1084
  }
1266
1085
  ];
1267
1086
  }
1268
1087
  if (viewabilityConfigCallbackPairs) {
1269
1088
  for (const pair of viewabilityConfigCallbackPairs) {
1270
1089
  mapViewabilityConfigCallbackPairs.set(pair.viewabilityConfig.id, {
1271
- viewableItems: [],
1272
- start: -1,
1273
1090
  end: -1,
1091
+ previousEnd: -1,
1274
1092
  previousStart: -1,
1275
- previousEnd: -1
1093
+ start: -1,
1094
+ viewableItems: []
1276
1095
  });
1277
1096
  }
1278
1097
  }
1279
1098
  return viewabilityConfigCallbackPairs;
1280
1099
  }
1281
1100
  function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
1101
+ const {
1102
+ timeouts,
1103
+ props: { data }
1104
+ } = state;
1282
1105
  for (const viewabilityConfigCallbackPair of viewabilityConfigCallbackPairs) {
1283
1106
  const viewabilityState = mapViewabilityConfigCallbackPairs.get(
1284
1107
  viewabilityConfigCallbackPair.viewabilityConfig.id
@@ -1287,12 +1110,12 @@ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollS
1287
1110
  viewabilityState.end = end;
1288
1111
  if (viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime) {
1289
1112
  const timer = setTimeout(() => {
1290
- state.timeouts.delete(timer);
1291
- updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1113
+ timeouts.delete(timer);
1114
+ updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1292
1115
  }, viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime);
1293
- state.timeouts.add(timer);
1116
+ timeouts.add(timer);
1294
1117
  } else {
1295
- updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1118
+ updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
1296
1119
  }
1297
1120
  }
1298
1121
  }
@@ -1344,11 +1167,11 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1344
1167
  const containerId = findContainerId(ctx, key);
1345
1168
  if (isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
1346
1169
  const viewToken = {
1347
- item,
1348
- key,
1170
+ containerId,
1349
1171
  index: i,
1350
1172
  isViewable: true,
1351
- containerId
1173
+ item,
1174
+ key
1352
1175
  };
1353
1176
  viewableItems.push(viewToken);
1354
1177
  if (!(previousViewableItems == null ? void 0 : previousViewableItems.find((v) => v.key === viewToken.key))) {
@@ -1358,9 +1181,9 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1358
1181
  }
1359
1182
  }
1360
1183
  Object.assign(viewabilityState, {
1361
- viewableItems,
1184
+ previousEnd: end,
1362
1185
  previousStart: start,
1363
- previousEnd: end
1186
+ viewableItems
1364
1187
  });
1365
1188
  if (changed.length > 0) {
1366
1189
  viewabilityState.viewableItems = viewableItems;
@@ -1369,7 +1192,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1369
1192
  maybeUpdateViewabilityCallback(ctx, configId, change.containerId, change);
1370
1193
  }
1371
1194
  if (onViewableItemsChanged) {
1372
- onViewableItemsChanged({ viewableItems, changed });
1195
+ onViewableItemsChanged({ changed, viewableItems });
1373
1196
  }
1374
1197
  }
1375
1198
  for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
@@ -1395,16 +1218,16 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
1395
1218
  const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
1396
1219
  const isViewable2 = percent >= viewablePercentThreshold;
1397
1220
  const value = {
1221
+ containerId,
1398
1222
  index,
1399
1223
  isViewable: isViewable2,
1400
1224
  item,
1401
1225
  key,
1402
- percentVisible,
1403
1226
  percentOfScroller,
1404
- sizeVisible,
1405
- size,
1227
+ percentVisible,
1406
1228
  scrollSize,
1407
- containerId
1229
+ size,
1230
+ sizeVisible
1408
1231
  };
1409
1232
  if (JSON.stringify(value) !== JSON.stringify(ctx.mapViewabilityAmountValues.get(containerId))) {
1410
1233
  ctx.mapViewabilityAmountValues.set(containerId, value);
@@ -1436,314 +1259,482 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1436
1259
  cb == null ? void 0 : cb(viewToken);
1437
1260
  }
1438
1261
 
1439
- // src/calculateItemsInView.ts
1440
- function calculateItemsInView(ctx, state, params = {}) {
1441
- var _a, _b, _c, _d, _e, _f, _g, _h;
1442
- const {
1443
- scrollLength,
1444
- startBufferedId: startBufferedIdOrig,
1445
- positions,
1446
- columns,
1447
- containerItemKeys,
1448
- idCache,
1449
- sizes,
1450
- indexByKey,
1451
- scrollForNextCalculateItemsInView,
1452
- enableScrollForNextCalculateItemsInView,
1453
- minIndexSizeChanged
1454
- } = state;
1455
- const data = state.props.data;
1456
- if (!data || scrollLength === 0) {
1457
- return;
1458
- }
1459
- const totalSize = peek$(ctx, "totalSize");
1460
- const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
1461
- const numColumns = peek$(ctx, "numColumns");
1462
- const previousScrollAdjust = 0;
1463
- const { dataChanged, doMVCP } = params;
1464
- const speed = getScrollVelocity(state);
1465
- if (doMVCP || dataChanged) {
1466
- const checkMVCP = doMVCP ? prepareMVCP(ctx, state) : void 0;
1467
- updateAllPositions(ctx, state, dataChanged);
1468
- checkMVCP == null ? void 0 : checkMVCP();
1469
- }
1470
- const scrollExtra = 0;
1471
- const { queuedInitialLayout } = state;
1472
- let { scroll: scrollState } = state;
1473
- const initialScroll = state.props.initialScroll;
1474
- if (!queuedInitialLayout && initialScroll) {
1475
- const updatedOffset = calculateOffsetWithOffsetPosition(
1476
- state,
1477
- calculateOffsetForIndex(ctx, state, initialScroll.index),
1478
- initialScroll
1479
- );
1480
- scrollState = updatedOffset;
1481
- }
1482
- const scrollAdjustPad = -previousScrollAdjust - topPad;
1483
- let scroll = scrollState + scrollExtra + scrollAdjustPad;
1484
- if (scroll + scrollLength > totalSize) {
1485
- scroll = totalSize - scrollLength;
1486
- }
1487
- if (ENABLE_DEBUG_VIEW) {
1488
- set$(ctx, "debugRawScroll", scrollState);
1489
- set$(ctx, "debugComputedScroll", scroll);
1490
- }
1491
- const scrollBuffer = state.props.scrollBuffer;
1492
- let scrollBufferTop = scrollBuffer;
1493
- let scrollBufferBottom = scrollBuffer;
1494
- if (speed > 0) {
1495
- scrollBufferTop = scrollBuffer * 0.5;
1496
- scrollBufferBottom = scrollBuffer * 1.5;
1497
- } else {
1498
- scrollBufferTop = scrollBuffer * 1.5;
1499
- scrollBufferBottom = scrollBuffer * 0.5;
1500
- }
1501
- const scrollTopBuffered = scroll - scrollBufferTop;
1502
- const scrollBottom = scroll + scrollLength;
1503
- const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1504
- if (scrollForNextCalculateItemsInView) {
1505
- const { top, bottom } = scrollForNextCalculateItemsInView;
1506
- if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
1507
- return;
1262
+ // src/utils/checkAllSizesKnown.ts
1263
+ function checkAllSizesKnown(state) {
1264
+ const { startBuffered, endBuffered, sizesKnown } = state;
1265
+ if (endBuffered !== null) {
1266
+ let areAllKnown = true;
1267
+ for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1268
+ const key = getId(state, i);
1269
+ areAllKnown && (areAllKnown = sizesKnown.has(key));
1508
1270
  }
1271
+ return areAllKnown;
1509
1272
  }
1510
- let startNoBuffer = null;
1511
- let startBuffered = null;
1512
- let startBufferedId = null;
1513
- let endNoBuffer = null;
1514
- let endBuffered = null;
1515
- let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1516
- if (minIndexSizeChanged !== void 0) {
1517
- loopStart = Math.min(minIndexSizeChanged, loopStart);
1518
- state.minIndexSizeChanged = void 0;
1519
- }
1520
- for (let i = loopStart; i >= 0; i--) {
1521
- const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
1522
- const top = positions.get(id);
1523
- const size = (_b = sizes.get(id)) != null ? _b : getItemSize(state, id, i, data[i]);
1524
- const bottom = top + size;
1525
- if (bottom > scroll - scrollBuffer) {
1526
- loopStart = i;
1527
- } else {
1528
- break;
1273
+ return false;
1274
+ }
1275
+
1276
+ // src/utils/findAvailableContainers.ts
1277
+ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
1278
+ const numContainers = peek$(ctx, "numContainers");
1279
+ const result = [];
1280
+ const availableContainers = [];
1281
+ for (let u = 0; u < numContainers; u++) {
1282
+ const key = peek$(ctx, `containerItemKey${u}`);
1283
+ let isOk = key === void 0;
1284
+ if (!isOk) {
1285
+ const index = pendingRemoval.indexOf(u);
1286
+ if (index !== -1) {
1287
+ pendingRemoval.splice(index, 1);
1288
+ isOk = true;
1289
+ }
1290
+ }
1291
+ if (isOk) {
1292
+ result.push(u);
1293
+ if (result.length >= numNeeded) {
1294
+ return result;
1295
+ }
1529
1296
  }
1530
1297
  }
1531
- const loopStartMod = loopStart % numColumns;
1532
- if (loopStartMod > 0) {
1533
- loopStart -= loopStartMod;
1534
- }
1535
- let foundEnd = false;
1536
- let nextTop;
1537
- let nextBottom;
1538
- const prevNumContainers = ctx.values.get("numContainers");
1539
- let maxIndexRendered = 0;
1540
- for (let i = 0; i < prevNumContainers; i++) {
1541
- const key = peek$(ctx, `containerItemKey${i}`);
1542
- if (key !== void 0) {
1543
- const index = indexByKey.get(key);
1544
- maxIndexRendered = Math.max(maxIndexRendered, index);
1298
+ for (let u = 0; u < numContainers; u++) {
1299
+ const key = peek$(ctx, `containerItemKey${u}`);
1300
+ if (key === void 0) continue;
1301
+ const index = state.indexByKey.get(key);
1302
+ if (index < startBuffered) {
1303
+ availableContainers.push({ distance: startBuffered - index, index: u });
1304
+ } else if (index > endBuffered) {
1305
+ availableContainers.push({ distance: index - endBuffered, index: u });
1545
1306
  }
1546
1307
  }
1547
- let firstFullyOnScreenIndex;
1548
- const dataLength = data.length;
1549
- for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
1550
- const id = (_c = idCache.get(i)) != null ? _c : getId(state, i);
1551
- const size = (_d = sizes.get(id)) != null ? _d : getItemSize(state, id, i, data[i]);
1552
- const top = positions.get(id);
1553
- if (!foundEnd) {
1554
- if (startNoBuffer === null && top + size > scroll) {
1555
- startNoBuffer = i;
1308
+ const remaining = numNeeded - result.length;
1309
+ if (remaining > 0) {
1310
+ if (availableContainers.length > 0) {
1311
+ if (availableContainers.length > remaining) {
1312
+ availableContainers.sort(comparatorByDistance);
1313
+ availableContainers.length = remaining;
1556
1314
  }
1557
- if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10) {
1558
- firstFullyOnScreenIndex = i;
1315
+ for (const container of availableContainers) {
1316
+ result.push(container.index);
1559
1317
  }
1560
- if (startBuffered === null && top + size > scrollTopBuffered) {
1561
- startBuffered = i;
1562
- startBufferedId = id;
1563
- nextTop = top;
1318
+ }
1319
+ const stillNeeded = numNeeded - result.length;
1320
+ if (stillNeeded > 0) {
1321
+ for (let i = 0; i < stillNeeded; i++) {
1322
+ result.push(numContainers + i);
1564
1323
  }
1565
- if (startNoBuffer !== null) {
1566
- if (top <= scrollBottom) {
1567
- endNoBuffer = i;
1568
- }
1569
- if (top <= scrollBottomBuffered) {
1570
- endBuffered = i;
1571
- nextBottom = top + size;
1572
- } else {
1573
- foundEnd = true;
1574
- }
1324
+ if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
1325
+ console.warn(
1326
+ "[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.",
1327
+ {
1328
+ debugInfo: {
1329
+ numContainers,
1330
+ numContainersPooled: peek$(ctx, "numContainersPooled"),
1331
+ numNeeded,
1332
+ stillNeeded
1333
+ }
1334
+ }
1335
+ );
1575
1336
  }
1576
1337
  }
1577
1338
  }
1578
- const idsInView = [];
1579
- for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
1580
- const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1581
- idsInView.push(id);
1339
+ return result.sort(comparatorDefault);
1340
+ }
1341
+ function comparatorByDistance(a, b) {
1342
+ return b.distance - a.distance;
1343
+ }
1344
+
1345
+ // src/core/finishScrollTo.ts
1346
+ var finishScrollTo = (state) => {
1347
+ if (state) {
1348
+ state.scrollingTo = void 0;
1349
+ state.scrollHistory.length = 0;
1582
1350
  }
1583
- Object.assign(state, {
1584
- startBuffered,
1585
- startBufferedId,
1586
- startNoBuffer,
1587
- endBuffered,
1588
- endNoBuffer,
1589
- idsInView,
1590
- firstFullyOnScreenIndex
1351
+ };
1352
+
1353
+ // src/core/scrollTo.ts
1354
+ function scrollTo(state, params = {}) {
1355
+ var _a;
1356
+ const { animated } = params;
1357
+ const {
1358
+ refScroller,
1359
+ props: { horizontal }
1360
+ } = state;
1361
+ const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1362
+ state.scrollHistory.length = 0;
1363
+ state.scrollingTo = params;
1364
+ state.scrollPending = offset;
1365
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1366
+ animated: !!animated,
1367
+ x: horizontal ? offset : 0,
1368
+ y: horizontal ? 0 : offset
1591
1369
  });
1592
- if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
1593
- state.scrollForNextCalculateItemsInView = nextTop !== void 0 && nextBottom !== void 0 ? {
1594
- top: nextTop,
1595
- bottom: nextBottom
1596
- } : void 0;
1370
+ if (!animated) {
1371
+ state.scroll = offset;
1372
+ setTimeout(() => finishScrollTo(state), 100);
1597
1373
  }
1598
- const numContainers = peek$(ctx, "numContainers");
1599
- const pendingRemoval = [];
1600
- if (dataChanged) {
1601
- for (let i = 0; i < numContainers; i++) {
1602
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1603
- if (!state.props.keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1604
- pendingRemoval.push(i);
1605
- }
1374
+ }
1375
+
1376
+ // src/core/scrollToIndex.ts
1377
+ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1378
+ if (index >= state.props.data.length) {
1379
+ index = state.props.data.length - 1;
1380
+ } else if (index < 0) {
1381
+ index = 0;
1382
+ }
1383
+ const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
1384
+ const isLast = index === state.props.data.length - 1;
1385
+ if (isLast && viewPosition === void 0) {
1386
+ viewPosition = 1;
1387
+ }
1388
+ const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1389
+ state.scrollForNextCalculateItemsInView = void 0;
1390
+ scrollTo(state, {
1391
+ animated,
1392
+ index,
1393
+ offset: firstIndexScrollPostion,
1394
+ viewOffset,
1395
+ viewPosition: viewPosition != null ? viewPosition : 0
1396
+ });
1397
+ }
1398
+
1399
+ // src/utils/checkThreshold.ts
1400
+ var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
1401
+ const distanceAbs = Math.abs(distance);
1402
+ const isAtThreshold = atThreshold || distanceAbs < threshold;
1403
+ if (!isReached && !isBlockedByTimer) {
1404
+ if (isAtThreshold) {
1405
+ onReached == null ? void 0 : onReached(distance);
1406
+ blockTimer == null ? void 0 : blockTimer(true);
1407
+ setTimeout(() => {
1408
+ blockTimer == null ? void 0 : blockTimer(false);
1409
+ }, 700);
1410
+ return true;
1606
1411
  }
1412
+ } else {
1413
+ if (distance >= 1.3 * threshold) {
1414
+ return false;
1415
+ }
1416
+ }
1417
+ return isReached;
1418
+ };
1419
+
1420
+ // src/utils/checkAtBottom.ts
1421
+ function checkAtBottom(ctx, state) {
1422
+ if (!state) {
1423
+ return;
1607
1424
  }
1608
- if (startBuffered !== null && endBuffered !== null) {
1609
- let numContainers2 = prevNumContainers;
1610
- const needNewContainers = [];
1611
- for (let i = startBuffered; i <= endBuffered; i++) {
1612
- const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
1613
- if (!containerItemKeys.has(id)) {
1614
- needNewContainers.push(i);
1425
+ const {
1426
+ queuedInitialLayout,
1427
+ scrollLength,
1428
+ scroll,
1429
+ maintainingScrollAtEnd,
1430
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1431
+ } = state;
1432
+ const contentSize = getContentSize(ctx);
1433
+ if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1434
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1435
+ const isContentLess = contentSize < scrollLength;
1436
+ state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1437
+ state.isEndReached = checkThreshold(
1438
+ distanceFromEnd,
1439
+ isContentLess,
1440
+ onEndReachedThreshold * scrollLength,
1441
+ state.isEndReached,
1442
+ state.endReachedBlockedByTimer,
1443
+ (distance) => {
1444
+ var _a, _b;
1445
+ return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1446
+ },
1447
+ (block) => {
1448
+ state.endReachedBlockedByTimer = block;
1615
1449
  }
1450
+ );
1451
+ }
1452
+ }
1453
+
1454
+ // src/utils/setDidLayout.ts
1455
+ function setDidLayout(ctx, state) {
1456
+ const {
1457
+ loadStartTime,
1458
+ initialScroll,
1459
+ props: { onLoad }
1460
+ } = state;
1461
+ state.queuedInitialLayout = true;
1462
+ checkAtBottom(ctx, state);
1463
+ if (!IsNewArchitecture && initialScroll) {
1464
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1465
+ }
1466
+ set$(ctx, "containersDidLayout", true);
1467
+ if (onLoad) {
1468
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1469
+ }
1470
+ }
1471
+
1472
+ // src/core/calculateItemsInView.ts
1473
+ function calculateItemsInView(ctx, state, params = {}) {
1474
+ unstable_batchedUpdates(() => {
1475
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1476
+ const {
1477
+ scrollLength,
1478
+ startBufferedId: startBufferedIdOrig,
1479
+ positions,
1480
+ columns,
1481
+ containerItemKeys,
1482
+ idCache,
1483
+ sizes,
1484
+ indexByKey,
1485
+ scrollForNextCalculateItemsInView,
1486
+ enableScrollForNextCalculateItemsInView,
1487
+ minIndexSizeChanged
1488
+ } = state;
1489
+ const data = state.props.data;
1490
+ const prevNumContainers = peek$(ctx, "numContainers");
1491
+ if (!data || scrollLength === 0 || !prevNumContainers) {
1492
+ return;
1616
1493
  }
1617
- if (needNewContainers.length > 0) {
1618
- const availableContainers = findAvailableContainers(
1619
- ctx,
1494
+ const totalSize = peek$(ctx, "totalSize");
1495
+ const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
1496
+ const numColumns = peek$(ctx, "numColumns");
1497
+ const previousScrollAdjust = 0;
1498
+ const { dataChanged, doMVCP } = params;
1499
+ const speed = getScrollVelocity(state);
1500
+ if (doMVCP || dataChanged) {
1501
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state) : void 0;
1502
+ updateAllPositions(ctx, state, dataChanged);
1503
+ checkMVCP == null ? void 0 : checkMVCP();
1504
+ }
1505
+ const scrollExtra = 0;
1506
+ const { queuedInitialLayout } = state;
1507
+ let { scroll: scrollState } = state;
1508
+ const initialScroll = state.props.initialScroll;
1509
+ if (!queuedInitialLayout && initialScroll) {
1510
+ const updatedOffset = calculateOffsetWithOffsetPosition(
1620
1511
  state,
1621
- needNewContainers.length,
1622
- startBuffered,
1623
- endBuffered,
1624
- pendingRemoval
1512
+ calculateOffsetForIndex(ctx, state, initialScroll.index),
1513
+ initialScroll
1625
1514
  );
1626
- for (let idx = 0; idx < needNewContainers.length; idx++) {
1627
- const i = needNewContainers[idx];
1628
- const containerIndex = availableContainers[idx];
1629
- const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
1630
- const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
1631
- if (oldKey && oldKey !== id) {
1632
- containerItemKeys.delete(oldKey);
1515
+ scrollState = updatedOffset;
1516
+ }
1517
+ const scrollAdjustPad = -previousScrollAdjust - topPad;
1518
+ let scroll = scrollState + scrollExtra + scrollAdjustPad;
1519
+ if (scroll + scrollLength > totalSize) {
1520
+ scroll = totalSize - scrollLength;
1521
+ }
1522
+ if (ENABLE_DEBUG_VIEW) {
1523
+ set$(ctx, "debugRawScroll", scrollState);
1524
+ set$(ctx, "debugComputedScroll", scroll);
1525
+ }
1526
+ const scrollBuffer = state.props.scrollBuffer;
1527
+ let scrollBufferTop = scrollBuffer;
1528
+ let scrollBufferBottom = scrollBuffer;
1529
+ if (speed > 0) {
1530
+ scrollBufferTop = scrollBuffer * 0.5;
1531
+ scrollBufferBottom = scrollBuffer * 1.5;
1532
+ } else {
1533
+ scrollBufferTop = scrollBuffer * 1.5;
1534
+ scrollBufferBottom = scrollBuffer * 0.5;
1535
+ }
1536
+ const scrollTopBuffered = scroll - scrollBufferTop;
1537
+ const scrollBottom = scroll + scrollLength;
1538
+ const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1539
+ if (scrollForNextCalculateItemsInView) {
1540
+ const { top, bottom } = scrollForNextCalculateItemsInView;
1541
+ if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
1542
+ return;
1543
+ }
1544
+ }
1545
+ let startNoBuffer = null;
1546
+ let startBuffered = null;
1547
+ let startBufferedId = null;
1548
+ let endNoBuffer = null;
1549
+ let endBuffered = null;
1550
+ let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1551
+ if (minIndexSizeChanged !== void 0) {
1552
+ loopStart = Math.min(minIndexSizeChanged, loopStart);
1553
+ state.minIndexSizeChanged = void 0;
1554
+ }
1555
+ for (let i = loopStart; i >= 0; i--) {
1556
+ const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
1557
+ const top = positions.get(id);
1558
+ const size = (_b = sizes.get(id)) != null ? _b : getItemSize(state, id, i, data[i]);
1559
+ const bottom = top + size;
1560
+ if (bottom > scroll - scrollBuffer) {
1561
+ loopStart = i;
1562
+ } else {
1563
+ break;
1564
+ }
1565
+ }
1566
+ const loopStartMod = loopStart % numColumns;
1567
+ if (loopStartMod > 0) {
1568
+ loopStart -= loopStartMod;
1569
+ }
1570
+ let foundEnd = false;
1571
+ let nextTop;
1572
+ let nextBottom;
1573
+ let maxIndexRendered = 0;
1574
+ for (let i = 0; i < prevNumContainers; i++) {
1575
+ const key = peek$(ctx, `containerItemKey${i}`);
1576
+ if (key !== void 0) {
1577
+ const index = indexByKey.get(key);
1578
+ maxIndexRendered = Math.max(maxIndexRendered, index);
1579
+ }
1580
+ }
1581
+ let firstFullyOnScreenIndex;
1582
+ const dataLength = data.length;
1583
+ for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
1584
+ const id = (_c = idCache.get(i)) != null ? _c : getId(state, i);
1585
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(state, id, i, data[i]);
1586
+ const top = positions.get(id);
1587
+ if (!foundEnd) {
1588
+ if (startNoBuffer === null && top + size > scroll) {
1589
+ startNoBuffer = i;
1590
+ }
1591
+ if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10) {
1592
+ firstFullyOnScreenIndex = i;
1633
1593
  }
1634
- set$(ctx, `containerItemKey${containerIndex}`, id);
1635
- set$(ctx, `containerItemData${containerIndex}`, data[i]);
1636
- containerItemKeys.add(id);
1637
- if (containerIndex >= numContainers2) {
1638
- numContainers2 = containerIndex + 1;
1594
+ if (startBuffered === null && top + size > scrollTopBuffered) {
1595
+ startBuffered = i;
1596
+ startBufferedId = id;
1597
+ nextTop = top;
1598
+ }
1599
+ if (startNoBuffer !== null) {
1600
+ if (top <= scrollBottom) {
1601
+ endNoBuffer = i;
1602
+ }
1603
+ if (top <= scrollBottomBuffered) {
1604
+ endBuffered = i;
1605
+ nextBottom = top + size;
1606
+ } else {
1607
+ foundEnd = true;
1608
+ }
1639
1609
  }
1640
1610
  }
1641
- if (numContainers2 !== prevNumContainers) {
1642
- set$(ctx, "numContainers", numContainers2);
1643
- if (numContainers2 > peek$(ctx, "numContainersPooled")) {
1644
- set$(ctx, "numContainersPooled", Math.ceil(numContainers2 * 1.5));
1611
+ }
1612
+ const idsInView = [];
1613
+ for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
1614
+ const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1615
+ idsInView.push(id);
1616
+ }
1617
+ Object.assign(state, {
1618
+ endBuffered,
1619
+ endNoBuffer,
1620
+ firstFullyOnScreenIndex,
1621
+ idsInView,
1622
+ startBuffered,
1623
+ startBufferedId,
1624
+ startNoBuffer
1625
+ });
1626
+ if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
1627
+ state.scrollForNextCalculateItemsInView = nextTop !== void 0 && nextBottom !== void 0 ? {
1628
+ bottom: nextBottom,
1629
+ top: nextTop
1630
+ } : void 0;
1631
+ }
1632
+ const numContainers = peek$(ctx, "numContainers");
1633
+ const pendingRemoval = [];
1634
+ if (dataChanged) {
1635
+ for (let i = 0; i < numContainers; i++) {
1636
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
1637
+ if (!state.props.keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1638
+ pendingRemoval.push(i);
1645
1639
  }
1646
1640
  }
1647
1641
  }
1648
- }
1649
- for (let i = 0; i < numContainers; i++) {
1650
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1651
- if (pendingRemoval.includes(i)) {
1652
- if (itemKey) {
1653
- containerItemKeys.delete(itemKey);
1642
+ if (startBuffered !== null && endBuffered !== null) {
1643
+ let numContainers2 = prevNumContainers;
1644
+ const needNewContainers = [];
1645
+ for (let i = startBuffered; i <= endBuffered; i++) {
1646
+ const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
1647
+ if (!containerItemKeys.has(id)) {
1648
+ needNewContainers.push(i);
1649
+ }
1654
1650
  }
1655
- set$(ctx, `containerItemKey${i}`, void 0);
1656
- set$(ctx, `containerItemData${i}`, void 0);
1657
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1658
- set$(ctx, `containerColumn${i}`, -1);
1659
- } else {
1660
- const itemIndex = indexByKey.get(itemKey);
1661
- const item = data[itemIndex];
1662
- if (item !== void 0) {
1663
- const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
1664
- const position = positions.get(id);
1665
- if (position === void 0) {
1666
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1667
- } else {
1668
- const pos = positions.get(id);
1669
- const column = columns.get(id) || 1;
1670
- const prevPos = peek$(ctx, `containerPosition${i}`);
1671
- const prevColumn = peek$(ctx, `containerColumn${i}`);
1672
- const prevData = peek$(ctx, `containerItemData${i}`);
1673
- if (!prevPos || pos > POSITION_OUT_OF_VIEW && pos !== prevPos) {
1674
- set$(ctx, `containerPosition${i}`, pos);
1651
+ if (needNewContainers.length > 0) {
1652
+ const availableContainers = findAvailableContainers(
1653
+ ctx,
1654
+ state,
1655
+ needNewContainers.length,
1656
+ startBuffered,
1657
+ endBuffered,
1658
+ pendingRemoval
1659
+ );
1660
+ for (let idx = 0; idx < needNewContainers.length; idx++) {
1661
+ const i = needNewContainers[idx];
1662
+ const containerIndex = availableContainers[idx];
1663
+ const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
1664
+ const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
1665
+ if (oldKey && oldKey !== id) {
1666
+ containerItemKeys.delete(oldKey);
1675
1667
  }
1676
- if (column >= 0 && column !== prevColumn) {
1677
- set$(ctx, `containerColumn${i}`, column);
1668
+ set$(ctx, `containerItemKey${containerIndex}`, id);
1669
+ set$(ctx, `containerItemData${containerIndex}`, data[i]);
1670
+ containerItemKeys.add(id);
1671
+ if (containerIndex >= numContainers2) {
1672
+ numContainers2 = containerIndex + 1;
1678
1673
  }
1679
- if (prevData !== item) {
1680
- set$(ctx, `containerItemData${i}`, data[itemIndex]);
1674
+ }
1675
+ if (numContainers2 !== prevNumContainers) {
1676
+ set$(ctx, "numContainers", numContainers2);
1677
+ if (numContainers2 > peek$(ctx, "numContainersPooled")) {
1678
+ set$(ctx, "numContainersPooled", Math.ceil(numContainers2 * 1.5));
1681
1679
  }
1682
1680
  }
1683
1681
  }
1684
1682
  }
1685
- }
1686
- if (!queuedInitialLayout && endBuffered !== null) {
1687
- if (checkAllSizesKnown(state)) {
1688
- setDidLayout(ctx, state);
1689
- }
1690
- }
1691
- if (state.props.viewabilityConfigCallbackPairs) {
1692
- updateViewableItems(
1693
- state,
1694
- ctx,
1695
- state.props.viewabilityConfigCallbackPairs,
1696
- scrollLength,
1697
- startNoBuffer,
1698
- endNoBuffer
1699
- );
1700
- }
1701
- }
1702
-
1703
- // src/checkAtTop.ts
1704
- function checkAtTop(state) {
1705
- if (!state) {
1706
- return;
1707
- }
1708
- const {
1709
- scrollLength,
1710
- scroll,
1711
- props: { onStartReachedThreshold }
1712
- } = state;
1713
- const distanceFromTop = scroll;
1714
- state.isAtStart = distanceFromTop <= 0;
1715
- state.isStartReached = checkThreshold(
1716
- distanceFromTop,
1717
- false,
1718
- onStartReachedThreshold * scrollLength,
1719
- state.isStartReached,
1720
- state.startReachedBlockedByTimer,
1721
- (distance) => {
1722
- var _a, _b;
1723
- return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
1724
- },
1725
- (block) => {
1726
- state.startReachedBlockedByTimer = block;
1683
+ for (let i = 0; i < numContainers; i++) {
1684
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
1685
+ if (pendingRemoval.includes(i)) {
1686
+ if (itemKey) {
1687
+ containerItemKeys.delete(itemKey);
1688
+ }
1689
+ set$(ctx, `containerItemKey${i}`, void 0);
1690
+ set$(ctx, `containerItemData${i}`, void 0);
1691
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1692
+ set$(ctx, `containerColumn${i}`, -1);
1693
+ } else {
1694
+ const itemIndex = indexByKey.get(itemKey);
1695
+ const item = data[itemIndex];
1696
+ if (item !== void 0) {
1697
+ const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
1698
+ const position = positions.get(id);
1699
+ if (position === void 0) {
1700
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1701
+ } else {
1702
+ const column = columns.get(id) || 1;
1703
+ const prevPos = peek$(ctx, `containerPosition${i}`);
1704
+ const prevColumn = peek$(ctx, `containerColumn${i}`);
1705
+ const prevData = peek$(ctx, `containerItemData${i}`);
1706
+ if (position > POSITION_OUT_OF_VIEW && position !== prevPos) {
1707
+ set$(ctx, `containerPosition${i}`, position);
1708
+ }
1709
+ if (column >= 0 && column !== prevColumn) {
1710
+ set$(ctx, `containerColumn${i}`, column);
1711
+ }
1712
+ if (prevData !== item) {
1713
+ set$(ctx, `containerItemData${i}`, data[itemIndex]);
1714
+ }
1715
+ }
1716
+ }
1717
+ }
1727
1718
  }
1728
- );
1729
- }
1730
-
1731
- // src/createColumnWrapperStyle.ts
1732
- function createColumnWrapperStyle(contentContainerStyle) {
1733
- const { gap, columnGap, rowGap } = contentContainerStyle;
1734
- if (gap || columnGap || rowGap) {
1735
- contentContainerStyle.gap = void 0;
1736
- contentContainerStyle.columnGap = void 0;
1737
- contentContainerStyle.rowGap = void 0;
1738
- return {
1739
- gap,
1740
- columnGap,
1741
- rowGap
1742
- };
1743
- }
1719
+ if (!queuedInitialLayout && endBuffered !== null) {
1720
+ if (checkAllSizesKnown(state)) {
1721
+ setDidLayout(ctx, state);
1722
+ }
1723
+ }
1724
+ if (state.viewabilityConfigCallbackPairs) {
1725
+ updateViewableItems(
1726
+ state,
1727
+ ctx,
1728
+ state.viewabilityConfigCallbackPairs,
1729
+ scrollLength,
1730
+ startNoBuffer,
1731
+ endNoBuffer
1732
+ );
1733
+ }
1734
+ });
1744
1735
  }
1745
1736
 
1746
- // src/doInitialAllocateContainers.ts
1737
+ // src/core/doInitialAllocateContainers.ts
1747
1738
  function doInitialAllocateContainers(ctx, state) {
1748
1739
  const { scrollLength } = state;
1749
1740
  const data = state.props.data;
@@ -1772,7 +1763,7 @@ function doInitialAllocateContainers(ctx, state) {
1772
1763
  }
1773
1764
  }
1774
1765
 
1775
- // src/doMaintainScrollAtEnd.ts
1766
+ // src/core/doMaintainScrollAtEnd.ts
1776
1767
  function doMaintainScrollAtEnd(ctx, state, animated) {
1777
1768
  const {
1778
1769
  refScroller,
@@ -1799,34 +1790,42 @@ function doMaintainScrollAtEnd(ctx, state, animated) {
1799
1790
  return true;
1800
1791
  }
1801
1792
  }
1802
- function getRenderedItem(ctx, state, key) {
1793
+
1794
+ // src/utils/checkAtTop.ts
1795
+ function checkAtTop(state) {
1803
1796
  if (!state) {
1804
- return null;
1797
+ return;
1805
1798
  }
1806
1799
  const {
1807
- indexByKey,
1808
- props: { data, renderItem: renderItem2 }
1800
+ scrollLength,
1801
+ scroll,
1802
+ props: { onStartReachedThreshold }
1809
1803
  } = state;
1810
- const index = indexByKey.get(key);
1811
- if (index === void 0) {
1812
- return null;
1813
- }
1814
- let renderedItem = null;
1815
- if (renderItem2) {
1816
- const itemProps = {
1817
- item: data[index],
1818
- index,
1819
- extraData: peek$(ctx, "extraData")
1820
- };
1821
- renderedItem = React3__default.createElement(renderItem2, itemProps);
1822
- }
1823
- return { index, item: data[index], renderedItem };
1804
+ const distanceFromTop = scroll;
1805
+ state.isAtStart = distanceFromTop <= 0;
1806
+ state.isStartReached = checkThreshold(
1807
+ distanceFromTop,
1808
+ false,
1809
+ onStartReachedThreshold * scrollLength,
1810
+ state.isStartReached,
1811
+ state.startReachedBlockedByTimer,
1812
+ (distance) => {
1813
+ var _a, _b;
1814
+ return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
1815
+ },
1816
+ (block) => {
1817
+ state.startReachedBlockedByTimer = block;
1818
+ }
1819
+ );
1824
1820
  }
1825
1821
 
1826
- // src/handleLayout.ts
1827
- function handleLayout(ctx, state, size, setCanRender) {
1828
- const scrollLength = size[state.props.horizontal ? "width" : "height"];
1829
- const otherAxisSize = size[state.props.horizontal ? "height" : "width"];
1822
+ // src/core/handleLayout.ts
1823
+ function handleLayout(ctx, state, layout, setCanRender) {
1824
+ const { maintainScrollAtEnd } = state.props;
1825
+ const scrollLength = layout[state.props.horizontal ? "width" : "height"];
1826
+ const otherAxisSize = layout[state.props.horizontal ? "height" : "width"];
1827
+ const needsCalculate = !state.lastLayout || scrollLength > state.scrollLength || state.lastLayout.x !== layout.x || state.lastLayout.y !== layout.y;
1828
+ state.lastLayout = layout;
1830
1829
  const didChange = scrollLength !== state.scrollLength;
1831
1830
  const prevOtherAxisSize = state.otherAxisSize;
1832
1831
  state.scrollLength = scrollLength;
@@ -1834,13 +1833,15 @@ function handleLayout(ctx, state, size, setCanRender) {
1834
1833
  state.lastBatchingAction = Date.now();
1835
1834
  state.scrollForNextCalculateItemsInView = void 0;
1836
1835
  doInitialAllocateContainers(ctx, state);
1837
- if (didChange) {
1836
+ if (needsCalculate) {
1838
1837
  calculateItemsInView(ctx, state, { doMVCP: true });
1839
1838
  }
1840
1839
  if (didChange || otherAxisSize !== prevOtherAxisSize) {
1841
- set$(ctx, "scrollSize", { width: size.width, height: size.height });
1840
+ set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
1841
+ }
1842
+ if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
1843
+ doMaintainScrollAtEnd(ctx, state, false);
1842
1844
  }
1843
- doMaintainScrollAtEnd(ctx, state, false);
1844
1845
  updateAlignItemsPaddingTop(ctx, state);
1845
1846
  checkAtBottom(ctx, state);
1846
1847
  checkAtTop(state);
@@ -1853,11 +1854,10 @@ function handleLayout(ctx, state, size, setCanRender) {
1853
1854
  `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.`
1854
1855
  );
1855
1856
  }
1856
- calculateItemsInView(ctx, state, { doMVCP: true });
1857
1857
  setCanRender(true);
1858
1858
  }
1859
1859
 
1860
- // src/onScroll.ts
1860
+ // src/core/onScroll.ts
1861
1861
  function onScroll(ctx, state, event) {
1862
1862
  var _a, _b, _c, _d, _e;
1863
1863
  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) {
@@ -1895,14 +1895,44 @@ function updateScroll(ctx, state, newScroll) {
1895
1895
  checkAtTop(state);
1896
1896
  }
1897
1897
 
1898
- // src/updateItemSize.ts
1898
+ // src/core/ScrollAdjustHandler.ts
1899
+ var ScrollAdjustHandler = class {
1900
+ constructor(ctx) {
1901
+ this.appliedAdjust = 0;
1902
+ this.mounted = false;
1903
+ this.context = ctx;
1904
+ }
1905
+ requestAdjust(add) {
1906
+ const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
1907
+ this.appliedAdjust = add + oldAdjustTop;
1908
+ const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
1909
+ if (this.mounted) {
1910
+ set();
1911
+ } else {
1912
+ requestAnimationFrame(set);
1913
+ }
1914
+ }
1915
+ setMounted() {
1916
+ this.mounted = true;
1917
+ }
1918
+ };
1919
+
1920
+ // src/core/updateItemSize.ts
1899
1921
  function updateItemSizes(ctx, state, itemUpdates) {
1900
1922
  var _a;
1901
1923
  const {
1902
- props: { horizontal, maintainVisibleContentPosition, suggestEstimatedItemSize, onItemSizeChanged, data }
1924
+ props: {
1925
+ horizontal,
1926
+ maintainVisibleContentPosition,
1927
+ suggestEstimatedItemSize,
1928
+ onItemSizeChanged,
1929
+ data,
1930
+ maintainScrollAtEnd
1931
+ }
1903
1932
  } = state;
1904
1933
  if (!data) return;
1905
- let needsRecalculate = false;
1934
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
1935
+ let needsRecalculate = !containersDidLayout;
1906
1936
  let shouldMaintainScrollAtEnd = false;
1907
1937
  let minIndexSizeChanged;
1908
1938
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
@@ -1913,7 +1943,7 @@ function updateItemSizes(ctx, state, itemUpdates) {
1913
1943
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
1914
1944
  if (diff !== 0) {
1915
1945
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
1916
- if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index) {
1946
+ if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
1917
1947
  requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
1918
1948
  }
1919
1949
  const { startBuffered, endBuffered } = state;
@@ -1935,11 +1965,11 @@ function updateItemSizes(ctx, state, itemUpdates) {
1935
1965
  shouldMaintainScrollAtEnd = true;
1936
1966
  }
1937
1967
  onItemSizeChanged == null ? void 0 : onItemSizeChanged({
1938
- size,
1939
- previous: size - diff,
1940
1968
  index,
1969
+ itemData: state.props.data[index],
1941
1970
  itemKey,
1942
- itemData: state.props.data[index]
1971
+ previous: size - diff,
1972
+ size
1943
1973
  });
1944
1974
  }
1945
1975
  }
@@ -1962,42 +1992,33 @@ function updateItemSizes(ctx, state, itemUpdates) {
1962
1992
  if (!cur || maxOtherAxisSize > cur) {
1963
1993
  set$(ctx, "otherAxisSize", maxOtherAxisSize);
1964
1994
  }
1965
- const containersDidLayout = peek$(ctx, "containersDidLayout");
1966
1995
  if (containersDidLayout || checkAllSizesKnown(state)) {
1967
1996
  if (needsRecalculate) {
1968
1997
  state.scrollForNextCalculateItemsInView = void 0;
1969
1998
  calculateItemsInView(ctx, state, { doMVCP: true });
1970
1999
  }
1971
2000
  if (shouldMaintainScrollAtEnd) {
1972
- doMaintainScrollAtEnd(ctx, state, false);
2001
+ if (maintainScrollAtEnd === true || maintainScrollAtEnd.onItemLayout) {
2002
+ doMaintainScrollAtEnd(ctx, state, false);
2003
+ }
1973
2004
  }
1974
2005
  }
1975
2006
  }
1976
2007
  function updateItemSize(ctx, state, itemKey, sizeObj) {
1977
- var _a, _b;
1978
- if (IsNewArchitecture) {
1979
- const { sizesKnown } = state;
1980
- const numContainers = ctx.values.get("numContainers");
1981
- const changes = [];
1982
- for (let i = 0; i < numContainers; i++) {
1983
- const containerItemKey = peek$(ctx, `containerItemKey${i}`);
1984
- if (itemKey === containerItemKey) {
1985
- changes.push({ itemKey, sizeObj });
1986
- } else if (!sizesKnown.has(containerItemKey) && containerItemKey !== void 0) {
1987
- const containerRef = ctx.viewRefs.get(i);
1988
- if (containerRef) {
1989
- const measured = (_b = (_a = containerRef.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
1990
- if (measured) {
1991
- changes.push({ itemKey: containerItemKey, sizeObj: measured });
1992
- }
1993
- }
1994
- }
1995
- }
1996
- if (changes.length > 0) {
1997
- updateItemSizes(ctx, state, changes);
2008
+ const { queuedItemSizeUpdates, queuedItemSizeUpdatesWaiting } = state;
2009
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
2010
+ if (!containersDidLayout || !queuedItemSizeUpdatesWaiting) {
2011
+ updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
2012
+ if (containersDidLayout) {
2013
+ state.queuedItemSizeUpdatesWaiting = true;
2014
+ requestAnimationFrame(() => {
2015
+ state.queuedItemSizeUpdatesWaiting = false;
2016
+ updateItemSizes(ctx, state, queuedItemSizeUpdates);
2017
+ queuedItemSizeUpdates.length = 0;
2018
+ });
1998
2019
  }
1999
2020
  } else {
2000
- updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
2021
+ queuedItemSizeUpdates.push({ itemKey, sizeObj });
2001
2022
  }
2002
2023
  }
2003
2024
  function updateOneItemSize(state, itemKey, sizeObj) {
@@ -2016,7 +2037,7 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2016
2037
  const itemType = "";
2017
2038
  let averages = averageSizes[itemType];
2018
2039
  if (!averages) {
2019
- averages = averageSizes[itemType] = { num: 0, avg: 0 };
2040
+ averages = averageSizes[itemType] = { avg: 0, num: 0 };
2020
2041
  }
2021
2042
  averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2022
2043
  averages.num++;
@@ -2042,7 +2063,45 @@ var useCombinedRef = (...refs) => {
2042
2063
  return callback;
2043
2064
  };
2044
2065
 
2045
- // src/LegendList.tsx
2066
+ // src/utils/createColumnWrapperStyle.ts
2067
+ function createColumnWrapperStyle(contentContainerStyle) {
2068
+ const { gap, columnGap, rowGap } = contentContainerStyle;
2069
+ if (gap || columnGap || rowGap) {
2070
+ contentContainerStyle.gap = void 0;
2071
+ contentContainerStyle.columnGap = void 0;
2072
+ contentContainerStyle.rowGap = void 0;
2073
+ return {
2074
+ columnGap,
2075
+ gap,
2076
+ rowGap
2077
+ };
2078
+ }
2079
+ }
2080
+ function getRenderedItem(ctx, state, key) {
2081
+ if (!state) {
2082
+ return null;
2083
+ }
2084
+ const {
2085
+ indexByKey,
2086
+ props: { data, renderItem: renderItem2 }
2087
+ } = state;
2088
+ const index = indexByKey.get(key);
2089
+ if (index === void 0) {
2090
+ return null;
2091
+ }
2092
+ let renderedItem = null;
2093
+ if (renderItem2) {
2094
+ const itemProps = {
2095
+ extraData: peek$(ctx, "extraData"),
2096
+ index,
2097
+ item: data[index]
2098
+ };
2099
+ renderedItem = React3__default.createElement(renderItem2, itemProps);
2100
+ }
2101
+ return { index, item: data[index], renderedItem };
2102
+ }
2103
+
2104
+ // src/components/LegendList.tsx
2046
2105
  var DEFAULT_DRAW_DISTANCE = 250;
2047
2106
  var DEFAULT_ITEM_SIZE = 100;
2048
2107
  var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
@@ -2089,6 +2148,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2089
2148
  initialContainerPoolRatio = 2,
2090
2149
  viewabilityConfig,
2091
2150
  viewabilityConfigCallbackPairs,
2151
+ snapToIndices,
2092
2152
  onViewableItemsChanged,
2093
2153
  onStartReached,
2094
2154
  onEndReached,
@@ -2109,54 +2169,56 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2109
2169
  const combinedRef = useCombinedRef(refScroller, refScrollView);
2110
2170
  const estimatedItemSize = estimatedItemSizeProp != null ? estimatedItemSizeProp : DEFAULT_ITEM_SIZE;
2111
2171
  const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
2112
- const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
2172
+ const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
2113
2173
  const refState = useRef();
2114
2174
  if (!refState.current) {
2115
- const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { width: 0, height: 0 } : Dimensions.get("window"))[horizontal ? "width" : "height"];
2175
+ const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : Dimensions.get("window"))[horizontal ? "width" : "height"];
2116
2176
  refState.current = {
2117
- sizes: /* @__PURE__ */ new Map(),
2118
- positions: /* @__PURE__ */ new Map(),
2177
+ averageSizes: {},
2119
2178
  columns: /* @__PURE__ */ new Map(),
2120
- pendingAdjust: 0,
2121
- isStartReached: false,
2122
- isEndReached: false,
2123
- isAtEnd: false,
2124
- isAtStart: false,
2125
- scrollLength: initialScrollLength,
2126
- startBuffered: -1,
2127
- startNoBuffer: -1,
2179
+ containerItemKeys: /* @__PURE__ */ new Set(),
2180
+ enableScrollForNextCalculateItemsInView: true,
2128
2181
  endBuffered: -1,
2129
2182
  endNoBuffer: -1,
2183
+ endReachedBlockedByTimer: false,
2130
2184
  firstFullyOnScreenIndex: -1,
2185
+ idCache: /* @__PURE__ */ new Map(),
2186
+ idsInView: [],
2187
+ indexByKey: /* @__PURE__ */ new Map(),
2188
+ initialScroll,
2189
+ isAtEnd: false,
2190
+ isAtStart: false,
2191
+ isEndReached: false,
2192
+ isStartReached: false,
2193
+ lastBatchingAction: Date.now(),
2194
+ lastLayout: void 0,
2195
+ loadStartTime: Date.now(),
2196
+ minIndexSizeChanged: 0,
2197
+ nativeMarginTop: 0,
2198
+ pendingAdjust: 0,
2199
+ positions: /* @__PURE__ */ new Map(),
2200
+ props: {},
2201
+ queuedCalculateItemsInView: 0,
2202
+ queuedItemSizeUpdates: [],
2203
+ refScroller: void 0,
2131
2204
  scroll: 0,
2132
- totalSize: 0,
2133
- timeouts: /* @__PURE__ */ new Set(),
2134
- viewabilityConfigCallbackPairs: void 0,
2135
2205
  scrollAdjustHandler: new ScrollAdjustHandler(ctx),
2136
- nativeMarginTop: 0,
2206
+ scrollForNextCalculateItemsInView: void 0,
2207
+ scrollHistory: [],
2208
+ scrollLength: initialScrollLength,
2209
+ scrollPending: 0,
2137
2210
  scrollPrev: 0,
2138
2211
  scrollPrevTime: 0,
2139
2212
  scrollTime: 0,
2140
- scrollPending: 0,
2141
- indexByKey: /* @__PURE__ */ new Map(),
2142
- scrollHistory: [],
2213
+ sizes: /* @__PURE__ */ new Map(),
2143
2214
  sizesKnown: /* @__PURE__ */ new Map(),
2144
- timeoutSizeMessage: 0,
2215
+ startBuffered: -1,
2216
+ startNoBuffer: -1,
2145
2217
  startReachedBlockedByTimer: false,
2146
- endReachedBlockedByTimer: false,
2147
- scrollForNextCalculateItemsInView: void 0,
2148
- enableScrollForNextCalculateItemsInView: true,
2149
- minIndexSizeChanged: 0,
2150
- queuedCalculateItemsInView: 0,
2151
- lastBatchingAction: Date.now(),
2152
- averageSizes: {},
2153
- idsInView: [],
2154
- containerItemKeys: /* @__PURE__ */ new Set(),
2155
- idCache: /* @__PURE__ */ new Map(),
2156
- props: {},
2157
- refScroller: void 0,
2158
- loadStartTime: Date.now(),
2159
- initialScroll
2218
+ timeoutSizeMessage: 0,
2219
+ timeouts: /* @__PURE__ */ new Set(),
2220
+ totalSize: 0,
2221
+ viewabilityConfigCallbackPairs: void 0
2160
2222
  };
2161
2223
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2162
2224
  set$(ctx, "extraData", extraData);
@@ -2168,28 +2230,28 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2168
2230
  alignItemsAtEnd,
2169
2231
  data: dataProp,
2170
2232
  estimatedItemSize,
2233
+ getEstimatedItemSize,
2234
+ horizontal: !!horizontal,
2235
+ initialContainerPoolRatio,
2236
+ initialScroll,
2237
+ keyExtractor,
2171
2238
  maintainScrollAtEnd,
2172
2239
  maintainScrollAtEndThreshold,
2173
- onEndReachedThreshold,
2174
- onStartReachedThreshold,
2175
- stylePaddingBottom: stylePaddingBottomState,
2176
- horizontal: !!horizontal,
2177
2240
  maintainVisibleContentPosition,
2241
+ numColumns: numColumnsProp,
2242
+ onEndReached,
2243
+ onEndReachedThreshold,
2178
2244
  onItemSizeChanged,
2179
- suggestEstimatedItemSize: !!suggestEstimatedItemSize,
2180
- keyExtractor,
2245
+ onLoad,
2181
2246
  onScroll: onScrollProp,
2182
- getEstimatedItemSize,
2183
2247
  onStartReached,
2184
- onEndReached,
2185
- onLoad,
2248
+ onStartReachedThreshold,
2186
2249
  renderItem: renderItem2,
2187
- initialScroll,
2188
2250
  scrollBuffer,
2189
- viewabilityConfigCallbackPairs: void 0,
2190
- numColumns: numColumnsProp,
2191
- initialContainerPoolRatio,
2192
- stylePaddingTop: stylePaddingTopState
2251
+ snapToIndices,
2252
+ stylePaddingBottom: stylePaddingBottomState,
2253
+ stylePaddingTop: stylePaddingTopState,
2254
+ suggestEstimatedItemSize: !!suggestEstimatedItemSize
2193
2255
  };
2194
2256
  state.refScroller = refScroller;
2195
2257
  const checkResetContainers = (isFirst2) => {
@@ -2198,7 +2260,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2198
2260
  state2.props.data = dataProp;
2199
2261
  if (!isFirst2) {
2200
2262
  calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
2201
- const didMaintainScrollAtEnd = doMaintainScrollAtEnd(ctx, state2, false);
2263
+ const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
2264
+ const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state2, false);
2202
2265
  if (!didMaintainScrollAtEnd && dataProp.length > state2.props.data.length) {
2203
2266
  state2.isEndReached = false;
2204
2267
  }
@@ -2216,27 +2279,29 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2216
2279
  (_, i) => getId(state, dataProp.length - 1 - i)
2217
2280
  );
2218
2281
  }, [dataProp, numColumnsProp]);
2219
- const initalizeStateVars = () => {
2282
+ const initializeStateVars = () => {
2220
2283
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
2221
2284
  set$(ctx, "numColumns", numColumnsProp);
2222
2285
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
2223
- setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
2286
+ setPaddingTop(ctx, state, { stylePaddingTop: stylePaddingTopState });
2224
2287
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
2225
- const paddingDiff = stylePaddingTopState - prevPaddingTop;
2226
- if (paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") {
2227
- calculateItemsInView(ctx, state, { doMVCP: true });
2288
+ let paddingDiff = stylePaddingTopState - prevPaddingTop;
2289
+ if (maintainVisibleContentPosition && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") {
2290
+ if (state.scroll < 0) {
2291
+ paddingDiff += state.scroll;
2292
+ }
2228
2293
  requestAdjust(ctx, state, paddingDiff);
2229
2294
  }
2230
2295
  };
2231
2296
  if (isFirst) {
2232
- initalizeStateVars();
2297
+ initializeStateVars();
2233
2298
  updateAllPositions(ctx, state);
2234
2299
  }
2235
2300
  const initialContentOffset = useMemo(() => {
2236
2301
  const initialContentOffset2 = initialScrollOffset || calculateOffsetForIndex(ctx, state, initialScrollIndex);
2237
2302
  refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
2238
2303
  if (initialContentOffset2 > 0) {
2239
- scrollTo(state, { offset: initialContentOffset2, animated: false, index: initialScrollIndex });
2304
+ scrollTo(state, { animated: false, index: initialScrollIndex, offset: initialContentOffset2 });
2240
2305
  }
2241
2306
  return initialContentOffset2;
2242
2307
  }, [renderNum]);
@@ -2252,9 +2317,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2252
2317
  }
2253
2318
  }
2254
2319
  useLayoutEffect(() => {
2255
- var _a2, _b;
2256
2320
  if (IsNewArchitecture) {
2257
- const measured = (_b = (_a2 = refScroller.current) == null ? void 0 : _a2.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a2);
2321
+ let measured;
2322
+ refScroller.current.measure((x, y, width, height) => {
2323
+ measured = { height, width, x, y };
2324
+ });
2258
2325
  if (measured) {
2259
2326
  const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
2260
2327
  if (size) {
@@ -2281,6 +2348,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2281
2348
  }
2282
2349
  }
2283
2350
  }, []);
2351
+ useLayoutEffect(() => {
2352
+ if (snapToIndices) {
2353
+ updateSnapToOffsets(ctx, state);
2354
+ }
2355
+ }, [snapToIndices]);
2284
2356
  useLayoutEffect(() => {
2285
2357
  const didAllocateContainers = doInitialAllocateContainersCallback();
2286
2358
  if (!didAllocateContainers) {
@@ -2293,7 +2365,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2293
2365
  useLayoutEffect(() => {
2294
2366
  set$(ctx, "extraData", extraData);
2295
2367
  }, [extraData]);
2296
- useLayoutEffect(initalizeStateVars, [
2368
+ useLayoutEffect(initializeStateVars, [
2297
2369
  memoizedLastItemKeys.join(","),
2298
2370
  numColumnsProp,
2299
2371
  stylePaddingTopState,
@@ -2304,12 +2376,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2304
2376
  };
2305
2377
  useEffect(() => {
2306
2378
  const viewability = setupViewability({
2379
+ onViewableItemsChanged,
2307
2380
  viewabilityConfig,
2308
- viewabilityConfigCallbackPairs,
2309
- onViewableItemsChanged
2381
+ viewabilityConfigCallbackPairs
2310
2382
  });
2311
2383
  state.viewabilityConfigCallbackPairs = viewability;
2312
- state.props.viewabilityConfigCallbackPairs = viewability;
2313
2384
  state.enableScrollForNextCalculateItemsInView = !viewability;
2314
2385
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
2315
2386
  if (!IsNewArchitecture) {
@@ -2324,97 +2395,94 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2324
2395
  onLayoutProp(event);
2325
2396
  }
2326
2397
  }, []);
2327
- useImperativeHandle(
2328
- forwardedRef,
2329
- () => {
2330
- const scrollIndexIntoView = (options) => {
2398
+ useImperativeHandle(forwardedRef, () => {
2399
+ const scrollIndexIntoView = (options) => {
2400
+ const state2 = refState.current;
2401
+ if (state2) {
2402
+ const { index, ...rest2 } = options;
2403
+ const { startNoBuffer, endNoBuffer } = state2;
2404
+ if (index < startNoBuffer || index > endNoBuffer) {
2405
+ const viewPosition = index < startNoBuffer ? 0 : 1;
2406
+ scrollToIndex(ctx, state2, {
2407
+ ...rest2,
2408
+ index,
2409
+ viewPosition
2410
+ });
2411
+ }
2412
+ }
2413
+ };
2414
+ return {
2415
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
2416
+ getNativeScrollRef: () => refScroller.current,
2417
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
2418
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
2419
+ getState: () => {
2331
2420
  const state2 = refState.current;
2332
- if (state2) {
2333
- const { index, ...rest2 } = options;
2334
- const { startNoBuffer, endNoBuffer } = state2;
2335
- if (index < startNoBuffer || index > endNoBuffer) {
2336
- const viewPosition = index < startNoBuffer ? 0 : 1;
2337
- scrollToIndex(ctx, state2, {
2338
- ...rest2,
2339
- viewPosition,
2340
- index
2341
- });
2342
- }
2421
+ return state2 ? {
2422
+ contentLength: state2.totalSize,
2423
+ end: state2.endNoBuffer,
2424
+ endBuffered: state2.endBuffered,
2425
+ isAtEnd: state2.isAtEnd,
2426
+ isAtStart: state2.isAtStart,
2427
+ positions: state2.positions,
2428
+ scroll: state2.scroll,
2429
+ scrollLength: state2.scrollLength,
2430
+ sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index)),
2431
+ sizes: state2.sizesKnown,
2432
+ start: state2.startNoBuffer,
2433
+ startBuffered: state2.startBuffered
2434
+ } : {};
2435
+ },
2436
+ scrollIndexIntoView,
2437
+ scrollItemIntoView: ({ item, ...props2 }) => {
2438
+ const data = refState.current.props.data;
2439
+ const index = data.indexOf(item);
2440
+ if (index !== -1) {
2441
+ scrollIndexIntoView({ index, ...props2 });
2343
2442
  }
2344
- };
2345
- return {
2346
- flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
2347
- getNativeScrollRef: () => refScroller.current,
2348
- getScrollableNode: () => refScroller.current.getScrollableNode(),
2349
- getScrollResponder: () => refScroller.current.getScrollResponder(),
2350
- getState: () => {
2351
- const state2 = refState.current;
2352
- return state2 ? {
2353
- contentLength: state2.totalSize,
2354
- end: state2.endNoBuffer,
2355
- endBuffered: state2.endBuffered,
2356
- isAtEnd: state2.isAtEnd,
2357
- isAtStart: state2.isAtStart,
2358
- scroll: state2.scroll,
2359
- scrollLength: state2.scrollLength,
2360
- start: state2.startNoBuffer,
2361
- startBuffered: state2.startBuffered,
2362
- sizes: state2.sizesKnown,
2363
- sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index))
2364
- } : {};
2365
- },
2366
- scrollIndexIntoView,
2367
- scrollItemIntoView: ({ item, ...props2 }) => {
2368
- const data = refState.current.props.data;
2369
- const index = data.indexOf(item);
2370
- if (index !== -1) {
2371
- scrollIndexIntoView({ index, ...props2 });
2372
- }
2373
- },
2374
- scrollToIndex: (params) => scrollToIndex(ctx, state, params),
2375
- scrollToItem: ({ item, ...props2 }) => {
2376
- const data = refState.current.props.data;
2377
- const index = data.indexOf(item);
2378
- if (index !== -1) {
2379
- scrollToIndex(ctx, state, { index, ...props2 });
2380
- }
2381
- },
2382
- scrollToOffset: (params) => scrollTo(state, params),
2383
- scrollToEnd: (options) => {
2384
- const data = refState.current.props.data;
2385
- const stylePaddingBottom = refState.current.props.stylePaddingBottom;
2386
- const index = data.length - 1;
2387
- if (index !== -1) {
2388
- const paddingBottom = stylePaddingBottom || 0;
2389
- const footerSize = peek$(ctx, "footerSize") || 0;
2390
- scrollToIndex(ctx, state, {
2391
- index,
2392
- viewPosition: 1,
2393
- viewOffset: -paddingBottom - footerSize,
2394
- ...options
2395
- });
2396
- }
2397
- },
2398
- setVisibleContentAnchorOffset: (value) => {
2399
- const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2400
- set$(ctx, "scrollAdjustUserOffset", val);
2443
+ },
2444
+ scrollToEnd: (options) => {
2445
+ const data = refState.current.props.data;
2446
+ const stylePaddingBottom = refState.current.props.stylePaddingBottom;
2447
+ const index = data.length - 1;
2448
+ if (index !== -1) {
2449
+ const paddingBottom = stylePaddingBottom || 0;
2450
+ const footerSize = peek$(ctx, "footerSize") || 0;
2451
+ scrollToIndex(ctx, state, {
2452
+ index,
2453
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
2454
+ viewPosition: 1,
2455
+ ...options
2456
+ });
2401
2457
  }
2402
- };
2403
- },
2404
- []
2405
- );
2458
+ },
2459
+ scrollToIndex: (params) => scrollToIndex(ctx, state, params),
2460
+ scrollToItem: ({ item, ...props2 }) => {
2461
+ const data = refState.current.props.data;
2462
+ const index = data.indexOf(item);
2463
+ if (index !== -1) {
2464
+ scrollToIndex(ctx, state, { index, ...props2 });
2465
+ }
2466
+ },
2467
+ scrollToOffset: (params) => scrollTo(state, params),
2468
+ setVisibleContentAnchorOffset: (value) => {
2469
+ const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2470
+ set$(ctx, "scrollAdjustUserOffset", val);
2471
+ }
2472
+ };
2473
+ }, []);
2406
2474
  if (Platform.OS === "web") {
2407
2475
  useEffect(() => {
2408
2476
  if (initialContentOffset) {
2409
- scrollTo(state, { offset: initialContentOffset, animated: false });
2477
+ scrollTo(state, { animated: false, offset: initialContentOffset });
2410
2478
  }
2411
2479
  }, []);
2412
2480
  }
2413
2481
  const fns = useMemo(
2414
2482
  () => ({
2415
- updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj),
2416
2483
  getRenderedItem: (key) => getRenderedItem(ctx, state, key),
2417
- onScroll: (event) => onScroll(ctx, state, event)
2484
+ onScroll: (event) => onScroll(ctx, state, event),
2485
+ updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj)
2418
2486
  }),
2419
2487
  []
2420
2488
  );
@@ -2422,13 +2490,17 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2422
2490
  ListComponent,
2423
2491
  {
2424
2492
  ...rest,
2493
+ alignItemsAtEnd,
2425
2494
  canRender,
2495
+ contentContainerStyle,
2496
+ getRenderedItem: fns.getRenderedItem,
2426
2497
  horizontal,
2427
- refScrollView: combinedRef,
2428
2498
  initialContentOffset,
2429
- getRenderedItem: fns.getRenderedItem,
2430
- updateItemSize: fns.updateItemSize,
2431
- onScroll: fns.onScroll,
2499
+ ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
2500
+ ListHeaderComponent,
2501
+ maintainVisibleContentPosition,
2502
+ onLayout,
2503
+ onLayoutHeader,
2432
2504
  onMomentumScrollEnd: (event) => {
2433
2505
  requestAnimationFrame(() => {
2434
2506
  finishScrollTo(refState.current);
@@ -2437,31 +2509,30 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2437
2509
  onMomentumScrollEnd(event);
2438
2510
  }
2439
2511
  },
2440
- onLayout,
2512
+ onScroll: fns.onScroll,
2441
2513
  recycleItems,
2442
- alignItemsAtEnd,
2443
- ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
2444
- ListHeaderComponent,
2445
- maintainVisibleContentPosition,
2446
- scrollEventThrottle: Platform.OS === "web" ? 16 : void 0,
2447
- waitForInitialLayout,
2448
2514
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControl, {
2449
2515
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
2450
2516
  }) : refreshControl : onRefresh && /* @__PURE__ */ React3.createElement(
2451
2517
  RefreshControl,
2452
2518
  {
2453
- refreshing: !!refreshing,
2454
2519
  onRefresh,
2455
- progressViewOffset: (progressViewOffset || 0) + stylePaddingTopState
2520
+ progressViewOffset: (progressViewOffset || 0) + stylePaddingTopState,
2521
+ refreshing: !!refreshing
2456
2522
  }
2457
2523
  ),
2458
- style,
2459
- contentContainerStyle,
2524
+ refScrollView: combinedRef,
2460
2525
  scrollAdjustHandler: (_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler,
2461
- onLayoutHeader
2526
+ scrollEventThrottle: Platform.OS === "web" ? 16 : void 0,
2527
+ snapToIndices,
2528
+ style,
2529
+ updateItemSize: fns.updateItemSize,
2530
+ waitForInitialLayout
2462
2531
  }
2463
2532
  ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3.createElement(DebugView, { state: refState.current }));
2464
2533
  });
2534
+
2535
+ // src/components/LazyLegendList.tsx
2465
2536
  var typedForwardRef2 = forwardRef;
2466
2537
  var renderItem = ({ item }) => item;
2467
2538
  var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedRef) {
@@ -2470,7 +2541,7 @@ var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedR
2470
2541
  const data = (isArray(children) ? children : React3.Children.toArray(children)).flat(1);
2471
2542
  return (
2472
2543
  // @ts-expect-error TODO: Fix this type
2473
- /* @__PURE__ */ React3.createElement(LegendListComponent, { ...rest, data, renderItem, ref: forwardedRef })
2544
+ /* @__PURE__ */ React3.createElement(LegendListComponent, { ...rest, data, ref: forwardedRef, renderItem })
2474
2545
  );
2475
2546
  });
2476
2547