@legendapp/list 2.0.8 → 2.0.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,14 +1,15 @@
1
- import * as React2 from 'react';
2
- import React2__default, { useReducer, useEffect, createContext, useRef, useState, useMemo, useLayoutEffect, useCallback, useImperativeHandle, forwardRef, memo, useContext } from 'react';
1
+ import * as React3 from 'react';
2
+ import React3__default, { useReducer, useEffect, createContext, useRef, useState, useMemo, useCallback, useLayoutEffect, useImperativeHandle, forwardRef, memo, useContext } from 'react';
3
3
  import { View, Text, Platform, Animated, StyleSheet, Dimensions, RefreshControl, unstable_batchedUpdates } from 'react-native';
4
4
  import { useSyncExternalStore } from 'use-sync-external-store/shim';
5
5
 
6
6
  // src/components/LegendList.tsx
7
- var ContextState = React2.createContext(null);
7
+ var ContextState = React3.createContext(null);
8
8
  function StateProvider({ children }) {
9
- const [value] = React2.useState(() => ({
9
+ const [value] = React3.useState(() => ({
10
10
  animatedScrollY: new Animated.Value(0),
11
11
  columnWrapperStyle: void 0,
12
+ internalState: void 0,
12
13
  listeners: /* @__PURE__ */ new Map(),
13
14
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
14
15
  mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
@@ -24,10 +25,10 @@ function StateProvider({ children }) {
24
25
  ]),
25
26
  viewRefs: /* @__PURE__ */ new Map()
26
27
  }));
27
- return /* @__PURE__ */ React2.createElement(ContextState.Provider, { value }, children);
28
+ return /* @__PURE__ */ React3.createElement(ContextState.Provider, { value }, children);
28
29
  }
29
30
  function useStateContext() {
30
- return React2.useContext(ContextState);
31
+ return React3.useContext(ContextState);
31
32
  }
32
33
  function createSelectorFunctionsArr(ctx, signalNames) {
33
34
  let lastValues = [];
@@ -97,23 +98,23 @@ function getContentSize(ctx) {
97
98
  return headerSize + footerSize + totalSize + stylePaddingTop;
98
99
  }
99
100
  function useArr$(signalNames) {
100
- const ctx = React2.useContext(ContextState);
101
- const { subscribe, get } = React2.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
101
+ const ctx = React3.useContext(ContextState);
102
+ const { subscribe, get } = React3.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
102
103
  const value = useSyncExternalStore(subscribe, get);
103
104
  return value;
104
105
  }
105
106
  function useSelector$(signalName, selector) {
106
- const ctx = React2.useContext(ContextState);
107
- const { subscribe, get } = React2.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
107
+ const ctx = React3.useContext(ContextState);
108
+ const { subscribe, get } = React3.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
108
109
  const value = useSyncExternalStore(subscribe, () => selector(get()[0]));
109
110
  return value;
110
111
  }
111
112
 
112
113
  // src/components/DebugView.tsx
113
114
  var DebugRow = ({ children }) => {
114
- return /* @__PURE__ */ React2.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
115
+ return /* @__PURE__ */ React3.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
115
116
  };
116
- var DebugView = React2.memo(function DebugView2({ state }) {
117
+ var DebugView = React3.memo(function DebugView2({ state }) {
117
118
  const ctx = useStateContext();
118
119
  const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
119
120
  "totalSize",
@@ -128,7 +129,7 @@ var DebugView = React2.memo(function DebugView2({ state }) {
128
129
  useInterval(() => {
129
130
  forceUpdate();
130
131
  }, 100);
131
- return /* @__PURE__ */ React2.createElement(
132
+ return /* @__PURE__ */ React3.createElement(
132
133
  View,
133
134
  {
134
135
  pointerEvents: "none",
@@ -144,14 +145,14 @@ var DebugView = React2.memo(function DebugView2({ state }) {
144
145
  top: 0
145
146
  }
146
147
  },
147
- /* @__PURE__ */ React2.createElement(DebugRow, null, /* @__PURE__ */ React2.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React2.createElement(Text, null, totalSize.toFixed(2))),
148
- /* @__PURE__ */ React2.createElement(DebugRow, null, /* @__PURE__ */ React2.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React2.createElement(Text, null, contentSize.toFixed(2))),
149
- /* @__PURE__ */ React2.createElement(DebugRow, null, /* @__PURE__ */ React2.createElement(Text, null, "At end:"), /* @__PURE__ */ React2.createElement(Text, null, String(state.isAtEnd))),
150
- /* @__PURE__ */ React2.createElement(Text, null),
151
- /* @__PURE__ */ React2.createElement(DebugRow, null, /* @__PURE__ */ React2.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React2.createElement(Text, null, scrollAdjust.toFixed(2))),
152
- /* @__PURE__ */ React2.createElement(Text, null),
153
- /* @__PURE__ */ React2.createElement(DebugRow, null, /* @__PURE__ */ React2.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React2.createElement(Text, null, rawScroll.toFixed(2))),
154
- /* @__PURE__ */ React2.createElement(DebugRow, null, /* @__PURE__ */ React2.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React2.createElement(Text, null, scroll.toFixed(2)))
148
+ /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React3.createElement(Text, null, totalSize.toFixed(2))),
149
+ /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React3.createElement(Text, null, contentSize.toFixed(2))),
150
+ /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "At end:"), /* @__PURE__ */ React3.createElement(Text, null, String(state.isAtEnd))),
151
+ /* @__PURE__ */ React3.createElement(Text, null),
152
+ /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React3.createElement(Text, null, scrollAdjust.toFixed(2))),
153
+ /* @__PURE__ */ React3.createElement(Text, null),
154
+ /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React3.createElement(Text, null, rawScroll.toFixed(2))),
155
+ /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React3.createElement(Text, null, scroll.toFixed(2)))
155
156
  );
156
157
  });
157
158
  function useInterval(callback, delay) {
@@ -160,11 +161,6 @@ function useInterval(callback, delay) {
160
161
  return () => clearInterval(interval);
161
162
  }, [delay]);
162
163
  }
163
- var LeanViewComponent = React2.forwardRef((props, ref) => {
164
- return React2.createElement("RCTView", { ...props, ref });
165
- });
166
- LeanViewComponent.displayName = "RCTView";
167
- var LeanView = Platform.OS === "android" || Platform.OS === "ios" ? LeanViewComponent : View;
168
164
 
169
165
  // src/constants.ts
170
166
  var POSITION_OUT_OF_VIEW = -1e7;
@@ -198,7 +194,9 @@ function useValue$(key, params) {
198
194
  prevValue = newValue;
199
195
  if (!didQueueTask) {
200
196
  didQueueTask = true;
201
- if (delayValue === 0) {
197
+ if (delayValue === void 0) {
198
+ fn();
199
+ } else if (delayValue === 0) {
202
200
  queueMicrotask(fn);
203
201
  } else {
204
202
  setTimeout(fn, delayValue);
@@ -223,8 +221,8 @@ var PositionViewState = typedMemo(function PositionView({
223
221
  ...rest
224
222
  }) {
225
223
  const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
226
- return /* @__PURE__ */ React2.createElement(
227
- LeanView,
224
+ return /* @__PURE__ */ React3.createElement(
225
+ View,
228
226
  {
229
227
  ref: refView,
230
228
  style: [
@@ -251,7 +249,7 @@ var PositionViewAnimated = typedMemo(function PositionView2({
251
249
  } else {
252
250
  position = horizontal ? { left: position$ } : { top: position$ };
253
251
  }
254
- return /* @__PURE__ */ React2.createElement(Animated.View, { ref: refView, style: [style, position], ...rest });
252
+ return /* @__PURE__ */ React3.createElement(Animated.View, { ref: refView, style: [style, position], ...rest });
255
253
  });
256
254
  var PositionViewSticky = typedMemo(function PositionViewSticky2({
257
255
  id,
@@ -264,8 +262,8 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
264
262
  ...rest
265
263
  }) {
266
264
  const [position = POSITION_OUT_OF_VIEW, headerSize] = useArr$([`containerPosition${id}`, "headerSize"]);
267
- const transform = React2.useMemo(() => {
268
- if (animatedScrollY && stickyOffset) {
265
+ const transform = React3.useMemo(() => {
266
+ if (animatedScrollY && stickyOffset !== void 0) {
269
267
  const stickyPosition = animatedScrollY.interpolate({
270
268
  extrapolate: "clamp",
271
269
  inputRange: [position + headerSize, position + 5e3 + headerSize],
@@ -274,8 +272,8 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
274
272
  return horizontal ? [{ translateX: stickyPosition }] : [{ translateY: stickyPosition }];
275
273
  }
276
274
  }, [animatedScrollY, headerSize, horizontal, stickyOffset, position]);
277
- const viewStyle = React2.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
278
- return /* @__PURE__ */ React2.createElement(Animated.View, { ref: refView, style: viewStyle, ...rest });
275
+ const viewStyle = React3.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
276
+ return /* @__PURE__ */ React3.createElement(Animated.View, { ref: refView, style: viewStyle, ...rest });
279
277
  });
280
278
  var PositionView3 = IsNewArchitecture ? PositionViewState : PositionViewAnimated;
281
279
  var symbolFirst = Symbol();
@@ -428,7 +426,30 @@ function useSyncLayout() {
428
426
  // src/components/Separator.tsx
429
427
  function Separator({ ItemSeparatorComponent, leadingItem }) {
430
428
  const isLastItem = useIsLastItem();
431
- return isLastItem ? null : /* @__PURE__ */ React2.createElement(ItemSeparatorComponent, { leadingItem });
429
+ return isLastItem ? null : /* @__PURE__ */ React3.createElement(ItemSeparatorComponent, { leadingItem });
430
+ }
431
+ function useOnLayoutSync({
432
+ ref,
433
+ onLayoutProp,
434
+ onLayoutChange
435
+ }, deps = []) {
436
+ const onLayout = useCallback(
437
+ (event) => {
438
+ onLayoutChange(event.nativeEvent.layout, false);
439
+ onLayoutProp == null ? void 0 : onLayoutProp(event);
440
+ },
441
+ [onLayoutChange]
442
+ );
443
+ if (IsNewArchitecture) {
444
+ useLayoutEffect(() => {
445
+ if (ref.current) {
446
+ ref.current.measure((x, y, width, height) => {
447
+ onLayoutChange({ height, width, x, y }, true);
448
+ });
449
+ }
450
+ }, deps);
451
+ }
452
+ return { onLayout };
432
453
  }
433
454
 
434
455
  // src/components/Container.tsx
@@ -456,7 +477,7 @@ var Container = typedMemo(function Container2({
456
477
  const [layoutRenderCount, forceLayoutRender] = useState(0);
457
478
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
458
479
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
459
- let didLayout = false;
480
+ const didLayoutRef = useRef(false);
460
481
  const style = useMemo(() => {
461
482
  let paddingStyles;
462
483
  if (columnWrapperStyle) {
@@ -506,15 +527,16 @@ var Container = typedMemo(function Container2({
506
527
  value: data
507
528
  };
508
529
  }, [id, itemKey, index, data]);
509
- const onLayout = (event) => {
530
+ const onLayoutChange = (rectangle) => {
510
531
  var _a, _b;
511
532
  if (!isNullOrUndefined(itemKey)) {
512
- didLayout = true;
513
- let layout = event.nativeEvent.layout;
514
- const size = layout[horizontal ? "width" : "height"];
533
+ didLayoutRef.current = true;
534
+ let layout = rectangle;
535
+ const size = Math.floor(rectangle[horizontal ? "width" : "height"] * 8) / 8;
515
536
  const doUpdate = () => {
516
537
  refLastSize.current = { height: layout.height, width: layout.width };
517
538
  updateItemSize2(itemKey, layout);
539
+ didLayoutRef.current = true;
518
540
  };
519
541
  if (IsNewArchitecture || size > 0) {
520
542
  doUpdate();
@@ -526,25 +548,20 @@ var Container = typedMemo(function Container2({
526
548
  }
527
549
  }
528
550
  };
529
- if (IsNewArchitecture) {
530
- useLayoutEffect(() => {
531
- var _a, _b;
532
- if (!isNullOrUndefined(itemKey)) {
533
- const measured = (_b = (_a = ref.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
534
- if (measured) {
535
- const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
536
- if (size) {
537
- updateItemSize2(itemKey, measured);
538
- }
539
- }
540
- }
541
- }, [itemKey, layoutRenderCount]);
542
- } else {
551
+ const { onLayout } = useOnLayoutSync(
552
+ {
553
+ onLayoutChange,
554
+ ref
555
+ },
556
+ [itemKey, layoutRenderCount]
557
+ );
558
+ if (!IsNewArchitecture) {
543
559
  useEffect(() => {
544
560
  if (!isNullOrUndefined(itemKey)) {
545
561
  const timeout = setTimeout(() => {
546
- if (!didLayout && refLastSize.current) {
562
+ if (!didLayoutRef.current && refLastSize.current) {
547
563
  updateItemSize2(itemKey, refLastSize.current);
564
+ didLayoutRef.current = true;
548
565
  }
549
566
  }, 16);
550
567
  return () => {
@@ -554,7 +571,7 @@ var Container = typedMemo(function Container2({
554
571
  }, [itemKey]);
555
572
  }
556
573
  const PositionComponent = isSticky ? PositionViewSticky : PositionView3;
557
- return /* @__PURE__ */ React2.createElement(
574
+ return /* @__PURE__ */ React3.createElement(
558
575
  PositionComponent,
559
576
  {
560
577
  animatedScrollY: isSticky ? animatedScrollY : void 0,
@@ -567,7 +584,7 @@ var Container = typedMemo(function Container2({
567
584
  stickyOffset: isSticky ? stickyOffset : void 0,
568
585
  style
569
586
  },
570
- /* @__PURE__ */ React2.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React2.createElement(Separator, { ItemSeparatorComponent, leadingItem: renderedItemInfo.item }))
587
+ /* @__PURE__ */ React3.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3.createElement(Separator, { ItemSeparatorComponent, leadingItem: renderedItemInfo.item }))
571
588
  );
572
589
  });
573
590
 
@@ -585,14 +602,18 @@ var Containers = typedMemo(function Containers2({
585
602
  const [numContainers, numColumns] = useArr$(["numContainersPooled", "numColumns"]);
586
603
  const animSize = useValue$("totalSize", {
587
604
  // Use a microtask if increasing the size significantly, otherwise use a timeout
588
- delay: (value, prevValue) => !prevValue || value - prevValue > 20 ? 0 : 200
605
+ // If this is the initial scroll, we don't want to delay because we want to update the size immediately
606
+ delay: (value, prevValue) => {
607
+ var _a;
608
+ return !((_a = ctx.internalState) == null ? void 0 : _a.initialScroll) ? !prevValue || value - prevValue > 20 ? 0 : 200 : void 0;
609
+ }
589
610
  });
590
611
  const animOpacity = waitForInitialLayout && !IsNewArchitecture ? useValue$("containersDidLayout", { getValue: (value) => value ? 1 : 0 }) : void 0;
591
612
  const otherAxisSize = useValue$("otherAxisSize", { delay: 0 });
592
613
  const containers = [];
593
614
  for (let i = 0; i < numContainers; i++) {
594
615
  containers.push(
595
- /* @__PURE__ */ React2.createElement(
616
+ /* @__PURE__ */ React3.createElement(
596
617
  Container,
597
618
  {
598
619
  getRenderedItem: getRenderedItem2,
@@ -627,13 +648,18 @@ var Containers = typedMemo(function Containers2({
627
648
  }
628
649
  }
629
650
  }
630
- return /* @__PURE__ */ React2.createElement(Animated.View, { style }, containers);
651
+ return /* @__PURE__ */ React3.createElement(Animated.View, { style }, containers);
631
652
  });
653
+ var LayoutView = ({ onLayoutChange, refView, ...rest }) => {
654
+ const ref = refView != null ? refView : useRef();
655
+ const { onLayout } = useOnLayoutSync({ onLayoutChange, ref });
656
+ return /* @__PURE__ */ React.createElement(View, { ...rest, onLayout, ref });
657
+ };
632
658
  function ScrollAdjust() {
633
659
  const bias = 1e7;
634
660
  const [scrollAdjust, scrollAdjustUserOffset] = useArr$(["scrollAdjust", "scrollAdjustUserOffset"]);
635
661
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0) + bias;
636
- return /* @__PURE__ */ React2.createElement(
662
+ return /* @__PURE__ */ React3.createElement(
637
663
  View,
638
664
  {
639
665
  style: {
@@ -648,88 +674,26 @@ function ScrollAdjust() {
648
674
  }
649
675
  function SnapWrapper({ ScrollComponent, ...props }) {
650
676
  const [snapToOffsets] = useArr$(["snapToOffsets"]);
651
- return /* @__PURE__ */ React2__default.createElement(ScrollComponent, { ...props, snapToOffsets });
652
- }
653
- function useThrottleDebounce(mode) {
654
- const timeoutRef = useRef(null);
655
- const lastCallTimeRef = useRef(0);
656
- const lastArgsRef = useRef(null);
657
- const clearTimeoutRef = () => {
658
- if (timeoutRef.current) {
659
- clearTimeout(timeoutRef.current);
660
- timeoutRef.current = null;
661
- }
662
- };
663
- const execute = useCallback(
664
- (callback, delay, ...args) => {
665
- {
666
- const now = Date.now();
667
- lastArgsRef.current = args;
668
- if (now - lastCallTimeRef.current >= delay) {
669
- lastCallTimeRef.current = now;
670
- callback(...args);
671
- clearTimeoutRef();
672
- } else {
673
- clearTimeoutRef();
674
- timeoutRef.current = setTimeout(
675
- () => {
676
- if (lastArgsRef.current) {
677
- lastCallTimeRef.current = Date.now();
678
- callback(...lastArgsRef.current);
679
- timeoutRef.current = null;
680
- lastArgsRef.current = null;
681
- }
682
- },
683
- delay - (now - lastCallTimeRef.current)
684
- );
685
- }
686
- }
687
- },
688
- [mode]
689
- );
690
- return execute;
691
- }
692
-
693
- // src/hooks/useSyncLayout.tsx
694
- function useSyncLayout2({
695
- onChange
696
- }) {
697
- const ref = useRef(null);
698
- const onLayout = useCallback(
699
- (event) => {
700
- onChange(event.nativeEvent.layout, false);
701
- },
702
- [onChange]
703
- );
704
- if (IsNewArchitecture) {
705
- useLayoutEffect(() => {
706
- if (ref.current) {
707
- ref.current.measure((x, y, width, height) => {
708
- onChange({ height, width, x, y }, true);
709
- });
710
- }
711
- }, []);
712
- }
713
- return { onLayout, ref };
677
+ return /* @__PURE__ */ React3__default.createElement(ScrollComponent, { ...props, snapToOffsets });
714
678
  }
715
679
 
716
680
  // src/components/ListComponent.tsx
717
681
  var getComponent = (Component) => {
718
- if (React2.isValidElement(Component)) {
682
+ if (React3.isValidElement(Component)) {
719
683
  return Component;
720
684
  }
721
685
  if (Component) {
722
- return /* @__PURE__ */ React2.createElement(Component, null);
686
+ return /* @__PURE__ */ React3.createElement(Component, null);
723
687
  }
724
688
  return null;
725
689
  };
726
690
  var Padding = () => {
727
691
  const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
728
- return /* @__PURE__ */ React2.createElement(Animated.View, { style: { paddingTop: animPaddingTop } });
692
+ return /* @__PURE__ */ React3.createElement(Animated.View, { style: { paddingTop: animPaddingTop } });
729
693
  };
730
694
  var PaddingDevMode = () => {
731
695
  const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
732
- return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(Animated.View, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React2.createElement(
696
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(Animated.View, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React3.createElement(
733
697
  Animated.View,
734
698
  {
735
699
  style: {
@@ -772,14 +736,11 @@ var ListComponent = typedMemo(function ListComponent2({
772
736
  ...rest
773
737
  }) {
774
738
  const ctx = useStateContext();
775
- const { onLayout: onLayoutHeaderSync, ref: refHeader } = useSyncLayout2({
776
- onChange: onLayoutHeader
777
- });
778
739
  const ScrollComponent = renderScrollComponent ? useMemo(
779
- () => React2.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
740
+ () => React3.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
780
741
  [renderScrollComponent]
781
742
  ) : Animated.ScrollView;
782
- React2.useEffect(() => {
743
+ React3.useEffect(() => {
783
744
  if (canRender) {
784
745
  setTimeout(() => {
785
746
  scrollAdjustHandler.setMounted();
@@ -787,7 +748,7 @@ var ListComponent = typedMemo(function ListComponent2({
787
748
  }
788
749
  }, [canRender]);
789
750
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
790
- return /* @__PURE__ */ React2.createElement(
751
+ return /* @__PURE__ */ React3.createElement(
791
752
  SnapOrScroll,
792
753
  {
793
754
  ...rest,
@@ -806,11 +767,11 @@ var ListComponent = typedMemo(function ListComponent2({
806
767
  ScrollComponent: snapToIndices ? ScrollComponent : void 0,
807
768
  style
808
769
  },
809
- maintainVisibleContentPosition && /* @__PURE__ */ React2.createElement(ScrollAdjust, null),
810
- ENABLE_DEVMODE ? /* @__PURE__ */ React2.createElement(PaddingDevMode, null) : /* @__PURE__ */ React2.createElement(Padding, null),
811
- ListHeaderComponent && /* @__PURE__ */ React2.createElement(View, { onLayout: onLayoutHeaderSync, ref: refHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
770
+ maintainVisibleContentPosition && /* @__PURE__ */ React3.createElement(ScrollAdjust, null),
771
+ ENABLE_DEVMODE ? /* @__PURE__ */ React3.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3.createElement(Padding, null),
772
+ ListHeaderComponent && /* @__PURE__ */ React3.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
812
773
  ListEmptyComponent && getComponent(ListEmptyComponent),
813
- canRender && !ListEmptyComponent && /* @__PURE__ */ React2.createElement(
774
+ canRender && !ListEmptyComponent && /* @__PURE__ */ React3.createElement(
814
775
  Containers,
815
776
  {
816
777
  getRenderedItem: getRenderedItem2,
@@ -821,22 +782,22 @@ var ListComponent = typedMemo(function ListComponent2({
821
782
  waitForInitialLayout
822
783
  }
823
784
  ),
824
- ListFooterComponent && /* @__PURE__ */ React2.createElement(
825
- View,
785
+ ListFooterComponent && /* @__PURE__ */ React3.createElement(
786
+ LayoutView,
826
787
  {
827
- onLayout: (event) => {
828
- const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
788
+ onLayoutChange: (layout) => {
789
+ const size = layout[horizontal ? "width" : "height"];
829
790
  set$(ctx, "footerSize", size);
830
791
  },
831
792
  style: ListFooterComponentStyle
832
793
  },
833
794
  getComponent(ListFooterComponent)
834
795
  ),
835
- __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React2.createElement(DevNumbers, null)
796
+ __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React3.createElement(DevNumbers, null)
836
797
  );
837
798
  });
838
- var DevNumbers = __DEV__ && React2.memo(function DevNumbers2() {
839
- return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React2.createElement(
799
+ var DevNumbers = __DEV__ && React3.memo(function DevNumbers2() {
800
+ return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3.createElement(
840
801
  View,
841
802
  {
842
803
  key: index,
@@ -848,7 +809,7 @@ var DevNumbers = __DEV__ && React2.memo(function DevNumbers2() {
848
809
  width: "100%"
849
810
  }
850
811
  },
851
- /* @__PURE__ */ React2.createElement(Text, { style: { color: "red" } }, index * 100)
812
+ /* @__PURE__ */ React3.createElement(Text, { style: { color: "red" } }, index * 100)
852
813
  ));
853
814
  });
854
815
 
@@ -860,7 +821,7 @@ function getId(state, index) {
860
821
  }
861
822
  const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
862
823
  const id = ret;
863
- state.idCache.set(index, id);
824
+ state.idCache[index] = id;
864
825
  return id;
865
826
  }
866
827
 
@@ -946,7 +907,7 @@ var finishScrollTo = (state) => {
946
907
  // src/core/scrollTo.ts
947
908
  function scrollTo(state, params = {}) {
948
909
  var _a;
949
- const { animated, noScrollingTo } = params;
910
+ const { animated, noScrollingTo, isInitialScroll } = params;
950
911
  const {
951
912
  refScroller,
952
913
  props: { horizontal }
@@ -957,14 +918,21 @@ function scrollTo(state, params = {}) {
957
918
  state.scrollingTo = params;
958
919
  }
959
920
  state.scrollPending = offset;
960
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
961
- animated: !!animated,
962
- x: horizontal ? offset : 0,
963
- y: horizontal ? 0 : offset
964
- });
921
+ if (!params.isInitialScroll || Platform.OS === "android") {
922
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
923
+ animated: !!animated,
924
+ x: horizontal ? offset : 0,
925
+ y: horizontal ? 0 : offset
926
+ });
927
+ }
965
928
  if (!animated) {
966
929
  state.scroll = offset;
967
930
  setTimeout(() => finishScrollTo(state), 100);
931
+ if (isInitialScroll) {
932
+ setTimeout(() => {
933
+ state.initialScroll = void 0;
934
+ }, 500);
935
+ }
968
936
  }
969
937
  }
970
938
 
@@ -1059,7 +1027,16 @@ function prepareMVCP(ctx, state, dataChanged) {
1059
1027
  if (targetId !== void 0 && prevPosition !== void 0) {
1060
1028
  const newPosition = positions.get(targetId);
1061
1029
  if (newPosition !== void 0) {
1062
- positionDiff = newPosition - prevPosition;
1030
+ const totalSize = peek$(ctx, "totalSize");
1031
+ let diff = newPosition - prevPosition;
1032
+ if (state.scroll + state.scrollLength > totalSize) {
1033
+ if (diff > 0) {
1034
+ diff = Math.max(0, totalSize - state.scroll - state.scrollLength);
1035
+ } else {
1036
+ diff = 0;
1037
+ }
1038
+ }
1039
+ positionDiff = diff;
1063
1040
  }
1064
1041
  }
1065
1042
  if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
@@ -1068,6 +1045,68 @@ function prepareMVCP(ctx, state, dataChanged) {
1068
1045
  };
1069
1046
  }
1070
1047
 
1048
+ // src/core/prepareColumnStartState.ts
1049
+ function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1050
+ var _a;
1051
+ const numColumns = peek$(ctx, "numColumns");
1052
+ let rowStartIndex = startIndex;
1053
+ const columnAtStart = state.columns.get(state.idCache[startIndex]);
1054
+ if (columnAtStart !== 1) {
1055
+ rowStartIndex = findRowStartIndex(state, numColumns, startIndex);
1056
+ }
1057
+ let currentRowTop = 0;
1058
+ const curId = state.idCache[rowStartIndex];
1059
+ const column = state.columns.get(curId);
1060
+ if (rowStartIndex > 0) {
1061
+ const prevIndex = rowStartIndex - 1;
1062
+ const prevId = state.idCache[prevIndex];
1063
+ const prevPosition = (_a = state.positions.get(prevId)) != null ? _a : 0;
1064
+ const prevRowStart = findRowStartIndex(state, numColumns, prevIndex);
1065
+ const prevRowHeight = calculateRowMaxSize(state, prevRowStart, prevIndex, useAverageSize);
1066
+ currentRowTop = prevPosition + prevRowHeight;
1067
+ }
1068
+ return {
1069
+ column,
1070
+ currentRowTop,
1071
+ startIndex: rowStartIndex
1072
+ };
1073
+ }
1074
+ function findRowStartIndex(state, numColumns, index) {
1075
+ if (numColumns <= 1) {
1076
+ return Math.max(0, index);
1077
+ }
1078
+ let rowStart = Math.max(0, index);
1079
+ while (rowStart > 0) {
1080
+ const columnForIndex = state.columns.get(state.idCache[rowStart]);
1081
+ if (columnForIndex === 1) {
1082
+ break;
1083
+ }
1084
+ rowStart--;
1085
+ }
1086
+ return rowStart;
1087
+ }
1088
+ function calculateRowMaxSize(state, startIndex, endIndex, useAverageSize) {
1089
+ if (endIndex < startIndex) {
1090
+ return 0;
1091
+ }
1092
+ const { data } = state.props;
1093
+ if (!data) {
1094
+ return 0;
1095
+ }
1096
+ let maxSize = 0;
1097
+ for (let i = startIndex; i <= endIndex; i++) {
1098
+ if (i < 0 || i >= data.length) {
1099
+ continue;
1100
+ }
1101
+ const id = state.idCache[i];
1102
+ const size = getItemSize(state, id, i, data[i], useAverageSize);
1103
+ if (size > maxSize) {
1104
+ maxSize = size;
1105
+ }
1106
+ }
1107
+ return maxSize;
1108
+ }
1109
+
1071
1110
  // src/utils/setPaddingTop.ts
1072
1111
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1073
1112
  if (stylePaddingTop !== void 0) {
@@ -1127,6 +1166,7 @@ function updateTotalSize(ctx, state) {
1127
1166
  }
1128
1167
  function addTotalSize(ctx, state, key, add) {
1129
1168
  const { alignItemsAtEnd } = state.props;
1169
+ const prevTotalSize = state.totalSize;
1130
1170
  if (key === null) {
1131
1171
  state.totalSize = add;
1132
1172
  if (state.timeoutSetPaddingTop) {
@@ -1136,9 +1176,11 @@ function addTotalSize(ctx, state, key, add) {
1136
1176
  } else {
1137
1177
  state.totalSize += add;
1138
1178
  }
1139
- set$(ctx, "totalSize", state.totalSize);
1140
- if (alignItemsAtEnd) {
1141
- updateAlignItemsPaddingTop(ctx, state);
1179
+ if (prevTotalSize !== state.totalSize) {
1180
+ set$(ctx, "totalSize", state.totalSize);
1181
+ if (alignItemsAtEnd) {
1182
+ updateAlignItemsPaddingTop(ctx, state);
1183
+ }
1142
1184
  }
1143
1185
  }
1144
1186
 
@@ -1159,7 +1201,7 @@ function updateSnapToOffsets(ctx, state) {
1159
1201
 
1160
1202
  // src/core/updateItemPositions.ts
1161
1203
  function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottomBuffered } = { scrollBottomBuffered: -1, startIndex: 0 }) {
1162
- var _a, _b, _c, _d, _e, _f;
1204
+ var _a, _b, _c, _d;
1163
1205
  const {
1164
1206
  columns,
1165
1207
  indexByKey,
@@ -1169,41 +1211,47 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1169
1211
  props: { getEstimatedItemSize, snapToIndices, enableAverages }
1170
1212
  } = state;
1171
1213
  const data = state.props.data;
1214
+ const dataLength = data.length;
1172
1215
  const numColumns = peek$(ctx, "numColumns");
1216
+ const hasColumns = numColumns > 1;
1173
1217
  const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1174
1218
  const maxVisibleArea = scrollBottomBuffered + 1e3;
1175
1219
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1176
1220
  let currentRowTop = 0;
1177
1221
  let column = 1;
1178
1222
  let maxSizeInRow = 0;
1179
- const hasColumns = numColumns > 1;
1180
1223
  if (startIndex > 0) {
1181
- const prevIndex = startIndex - 1;
1182
- const prevId = (_a = idCache.get(prevIndex)) != null ? _a : getId(state, prevIndex);
1183
- const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1184
1224
  if (hasColumns) {
1185
- const prevColumn = (_c = columns.get(prevId)) != null ? _c : 1;
1186
- currentRowTop = prevPosition;
1187
- column = prevColumn % numColumns + 1;
1188
- } else {
1189
- const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(state, prevId, prevIndex, data[prevIndex], useAverageSize);
1225
+ const { startIndex: processedStartIndex, currentRowTop: initialRowTop } = prepareColumnStartState(
1226
+ ctx,
1227
+ state,
1228
+ startIndex,
1229
+ useAverageSize
1230
+ );
1231
+ startIndex = processedStartIndex;
1232
+ currentRowTop = initialRowTop;
1233
+ } else if (startIndex < dataLength) {
1234
+ const prevIndex = startIndex - 1;
1235
+ const prevId = getId(state, prevIndex);
1236
+ const prevPosition = (_a = positions.get(prevId)) != null ? _a : 0;
1237
+ const prevSize = (_b = sizesKnown.get(prevId)) != null ? _b : getItemSize(state, prevId, prevIndex, data[prevIndex], useAverageSize);
1190
1238
  currentRowTop = prevPosition + prevSize;
1191
1239
  }
1192
1240
  }
1193
1241
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1194
1242
  let didBreakEarly = false;
1195
1243
  let breakAt;
1196
- const dataLength = data.length;
1197
1244
  for (let i = startIndex; i < dataLength; i++) {
1198
1245
  if (breakAt && i > breakAt) {
1199
1246
  didBreakEarly = true;
1200
1247
  break;
1201
1248
  }
1202
- if (!dataChanged && currentRowTop > maxVisibleArea) {
1203
- breakAt = i + 10;
1249
+ if (breakAt === void 0 && !dataChanged && currentRowTop > maxVisibleArea) {
1250
+ const itemsPerRow = hasColumns ? numColumns : 1;
1251
+ breakAt = i + itemsPerRow + 10;
1204
1252
  }
1205
- const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1206
- const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(state, id, i, data[i], useAverageSize);
1253
+ const id = (_c = idCache[i]) != null ? _c : getId(state, i);
1254
+ const size = (_d = sizesKnown.get(id)) != null ? _d : getItemSize(state, id, i, data[i], useAverageSize);
1207
1255
  if (__DEV__ && needsIndexByKey) {
1208
1256
  if (indexByKeyForChecking.has(id)) {
1209
1257
  console.error(
@@ -1440,9 +1488,12 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1440
1488
  var batchedUpdates = unstable_batchedUpdates || ((callback) => callback());
1441
1489
 
1442
1490
  // src/utils/checkAllSizesKnown.ts
1491
+ function isNullOrUndefined2(value) {
1492
+ return value === null || value === void 0;
1493
+ }
1443
1494
  function checkAllSizesKnown(state) {
1444
1495
  const { startBuffered, endBuffered, sizesKnown } = state;
1445
- if (endBuffered !== null) {
1496
+ if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
1446
1497
  let areAllKnown = true;
1447
1498
  for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1448
1499
  const key = getId(state, i);
@@ -1459,6 +1510,8 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1459
1510
  const { stickyContainerPool, containerItemTypes } = state;
1460
1511
  const result = [];
1461
1512
  const availableContainers = [];
1513
+ const pendingRemovalSet = new Set(pendingRemoval);
1514
+ let pendingRemovalChanged = false;
1462
1515
  const stickyIndicesSet = state.props.stickyIndicesSet;
1463
1516
  const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
1464
1517
  const canReuseContainer = (containerIndex, requiredType) => {
@@ -1474,12 +1527,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1474
1527
  let foundContainer = false;
1475
1528
  for (const containerIndex of stickyContainerPool) {
1476
1529
  const key = peek$(ctx, `containerItemKey${containerIndex}`);
1477
- const isPendingRemoval = pendingRemoval.includes(containerIndex);
1530
+ const isPendingRemoval = pendingRemovalSet.has(containerIndex);
1478
1531
  if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType)) {
1479
1532
  result.push(containerIndex);
1480
- if (isPendingRemoval) {
1481
- const index = pendingRemoval.indexOf(containerIndex);
1482
- pendingRemoval.splice(index, 1);
1533
+ if (isPendingRemoval && pendingRemovalSet.delete(containerIndex)) {
1534
+ pendingRemovalChanged = true;
1483
1535
  }
1484
1536
  foundContainer = true;
1485
1537
  if (requiredItemTypes) typeIndex++;
@@ -1499,13 +1551,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1499
1551
  }
1500
1552
  const key = peek$(ctx, `containerItemKey${u}`);
1501
1553
  let isOk = key === void 0;
1502
- if (!isOk) {
1503
- const index = pendingRemoval.indexOf(u);
1504
- if (index !== -1) {
1505
- pendingRemoval.splice(index, 1);
1506
- const requiredType = neededTypes[typeIndex];
1507
- isOk = canReuseContainer(u, requiredType);
1508
- }
1554
+ if (!isOk && pendingRemovalSet.has(u)) {
1555
+ pendingRemovalSet.delete(u);
1556
+ pendingRemovalChanged = true;
1557
+ const requiredType = neededTypes[typeIndex];
1558
+ isOk = canReuseContainer(u, requiredType);
1509
1559
  }
1510
1560
  if (isOk) {
1511
1561
  result.push(u);
@@ -1563,6 +1613,12 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1563
1613
  }
1564
1614
  }
1565
1615
  }
1616
+ if (pendingRemovalChanged) {
1617
+ pendingRemoval.length = 0;
1618
+ for (const value of pendingRemovalSet) {
1619
+ pendingRemoval.push(value);
1620
+ }
1621
+ }
1566
1622
  return result.sort(comparatorDefault);
1567
1623
  }
1568
1624
  function comparatorByDistance(a, b) {
@@ -1700,17 +1756,16 @@ function setDidLayout(ctx, state) {
1700
1756
  onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1701
1757
  }
1702
1758
  };
1703
- if (Platform.OS === "android" || !IsNewArchitecture) {
1704
- if (initialScroll) {
1705
- queueMicrotask(() => {
1759
+ if (Platform.OS === "android" && initialScroll) {
1760
+ if (IsNewArchitecture) {
1761
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1762
+ requestAnimationFrame(() => {
1706
1763
  scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1707
- requestAnimationFrame(() => {
1708
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1709
- setIt();
1710
- });
1764
+ setIt();
1711
1765
  });
1712
1766
  } else {
1713
- queueMicrotask(setIt);
1767
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1768
+ setIt();
1714
1769
  }
1715
1770
  } else {
1716
1771
  setIt();
@@ -1723,7 +1778,8 @@ function findCurrentStickyIndex(stickyArray, scroll, state) {
1723
1778
  const idCache = state.idCache;
1724
1779
  const positions = state.positions;
1725
1780
  for (let i = stickyArray.length - 1; i >= 0; i--) {
1726
- const stickyId = (_a = idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
1781
+ const stickyIndex = stickyArray[i];
1782
+ const stickyId = (_a = idCache[stickyIndex]) != null ? _a : getId(state, stickyIndex);
1727
1783
  const stickyPos = stickyId ? positions.get(stickyId) : void 0;
1728
1784
  if (stickyPos !== void 0 && scroll >= stickyPos) {
1729
1785
  return i;
@@ -1736,40 +1792,43 @@ function getActiveStickyIndices(ctx, state, stickyIndices) {
1736
1792
  Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyIndices.has(idx))
1737
1793
  );
1738
1794
  }
1739
- function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll, needNewContainers, startBuffered, endBuffered) {
1795
+ function handleStickyActivation(ctx, state, stickyIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
1740
1796
  var _a;
1741
1797
  const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
1742
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1743
1798
  state.activeStickyIndex = currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : void 0;
1744
1799
  for (let offset = 0; offset <= 1; offset++) {
1745
1800
  const idx = currentStickyIdx - offset;
1746
1801
  if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
1747
1802
  const stickyIndex = stickyArray[idx];
1748
- const stickyId = (_a = state.idCache.get(stickyIndex)) != null ? _a : getId(state, stickyIndex);
1803
+ const stickyId = (_a = state.idCache[stickyIndex]) != null ? _a : getId(state, stickyIndex);
1749
1804
  if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered)) {
1750
1805
  needNewContainers.push(stickyIndex);
1751
1806
  }
1752
1807
  }
1753
1808
  }
1754
- function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pendingRemoval) {
1809
+ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
1755
1810
  var _a, _b, _c;
1756
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1757
1811
  for (const containerIndex of state.stickyContainerPool) {
1758
1812
  const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
1759
1813
  const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
1760
1814
  if (itemIndex === void 0) continue;
1761
1815
  const arrayIdx = stickyArray.indexOf(itemIndex);
1762
- if (arrayIdx === -1) continue;
1816
+ if (arrayIdx === -1) {
1817
+ state.stickyContainerPool.delete(containerIndex);
1818
+ set$(ctx, `containerSticky${containerIndex}`, false);
1819
+ set$(ctx, `containerStickyOffset${containerIndex}`, void 0);
1820
+ continue;
1821
+ }
1763
1822
  const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
1764
1823
  if (isRecentSticky) continue;
1765
1824
  const nextIndex = stickyArray[arrayIdx + 1];
1766
1825
  let shouldRecycle = false;
1767
1826
  if (nextIndex) {
1768
- const nextId = (_a = state.idCache.get(nextIndex)) != null ? _a : getId(state, nextIndex);
1827
+ const nextId = (_a = state.idCache[nextIndex]) != null ? _a : getId(state, nextIndex);
1769
1828
  const nextPos = nextId ? state.positions.get(nextId) : void 0;
1770
1829
  shouldRecycle = nextPos !== void 0 && scroll > nextPos + scrollBuffer * 2;
1771
1830
  } else {
1772
- const currentId = (_b = state.idCache.get(itemIndex)) != null ? _b : getId(state, itemIndex);
1831
+ const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
1773
1832
  if (currentId) {
1774
1833
  const currentPos = state.positions.get(currentId);
1775
1834
  const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
@@ -1797,7 +1856,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1797
1856
  sizes,
1798
1857
  startBufferedId: startBufferedIdOrig,
1799
1858
  viewabilityConfigCallbackPairs,
1800
- props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, scrollBuffer }
1859
+ props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, onStickyHeaderChange, scrollBuffer }
1801
1860
  } = state;
1802
1861
  const { data } = state.props;
1803
1862
  const stickyIndicesArr = state.props.stickyIndicesArr || [];
@@ -1832,6 +1891,10 @@ function calculateItemsInView(ctx, state, params = {}) {
1832
1891
  set$(ctx, "debugRawScroll", scrollState);
1833
1892
  set$(ctx, "debugComputedScroll", scroll);
1834
1893
  }
1894
+ const previousStickyIndex = state.activeStickyIndex;
1895
+ const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
1896
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : void 0;
1897
+ state.activeStickyIndex = nextActiveStickyIndex;
1835
1898
  let scrollBufferTop = scrollBuffer;
1836
1899
  let scrollBufferBottom = scrollBuffer;
1837
1900
  if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
@@ -1853,7 +1916,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1853
1916
  const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
1854
1917
  if (dataChanged) {
1855
1918
  indexByKey.clear();
1856
- idCache.clear();
1919
+ idCache.length = 0;
1857
1920
  positions.clear();
1858
1921
  }
1859
1922
  const startIndex = dataChanged ? 0 : (_a = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _a : 0;
@@ -1869,7 +1932,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1869
1932
  let endBuffered = null;
1870
1933
  let loopStart = !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1871
1934
  for (let i = loopStart; i >= 0; i--) {
1872
- const id = (_b = idCache.get(i)) != null ? _b : getId(state, i);
1935
+ const id = (_b = idCache[i]) != null ? _b : getId(state, i);
1873
1936
  const top = positions.get(id);
1874
1937
  const size = (_c = sizes.get(id)) != null ? _c : getItemSize(state, id, i, data[i]);
1875
1938
  const bottom = top + size;
@@ -1897,7 +1960,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1897
1960
  let firstFullyOnScreenIndex;
1898
1961
  const dataLength = data.length;
1899
1962
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
1900
- const id = (_d = idCache.get(i)) != null ? _d : getId(state, i);
1963
+ const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1901
1964
  const size = (_e = sizes.get(id)) != null ? _e : getItemSize(state, id, i, data[i]);
1902
1965
  const top = positions.get(id);
1903
1966
  if (!foundEnd) {
@@ -1927,7 +1990,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1927
1990
  }
1928
1991
  const idsInView = [];
1929
1992
  for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
1930
- const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
1993
+ const id = (_f = idCache[i]) != null ? _f : getId(state, i);
1931
1994
  idsInView.push(id);
1932
1995
  }
1933
1996
  Object.assign(state, {
@@ -1959,7 +2022,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1959
2022
  let numContainers2 = prevNumContainers;
1960
2023
  const needNewContainers = [];
1961
2024
  for (let i = startBuffered; i <= endBuffered; i++) {
1962
- const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
2025
+ const id = (_g = idCache[i]) != null ? _g : getId(state, i);
1963
2026
  if (!containerItemKeys.has(id)) {
1964
2027
  needNewContainers.push(i);
1965
2028
  }
@@ -1970,7 +2033,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1970
2033
  state,
1971
2034
  stickyIndicesSet,
1972
2035
  stickyIndicesArr,
1973
- scroll,
2036
+ currentStickyIdx,
1974
2037
  needNewContainers,
1975
2038
  startBuffered,
1976
2039
  endBuffered
@@ -1996,7 +2059,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1996
2059
  for (let idx = 0; idx < needNewContainers.length; idx++) {
1997
2060
  const i = needNewContainers[idx];
1998
2061
  const containerIndex = availableContainers[idx];
1999
- const id = (_h = idCache.get(i)) != null ? _h : getId(state, i);
2062
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
2000
2063
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
2001
2064
  if (oldKey && oldKey !== id) {
2002
2065
  containerItemKeys.delete(oldKey);
@@ -2010,7 +2073,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2010
2073
  if (stickyIndicesSet.has(i)) {
2011
2074
  set$(ctx, `containerSticky${containerIndex}`, true);
2012
2075
  const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2013
- set$(ctx, `containerStickyOffset${containerIndex}`, new Animated.Value(topPadding));
2076
+ set$(ctx, `containerStickyOffset${containerIndex}`, topPadding);
2014
2077
  state.stickyContainerPool.add(containerIndex);
2015
2078
  } else {
2016
2079
  set$(ctx, `containerSticky${containerIndex}`, false);
@@ -2029,7 +2092,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2029
2092
  }
2030
2093
  }
2031
2094
  if (stickyIndicesArr.length > 0) {
2032
- handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, pendingRemoval);
2095
+ handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2033
2096
  }
2034
2097
  for (let i = 0; i < numContainers; i++) {
2035
2098
  const itemKey = peek$(ctx, `containerItemKey${i}`);
@@ -2051,7 +2114,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2051
2114
  const itemIndex = indexByKey.get(itemKey);
2052
2115
  const item = data[itemIndex];
2053
2116
  if (item !== void 0) {
2054
- const id = (_i = idCache.get(itemIndex)) != null ? _i : getId(state, itemIndex);
2117
+ const id = (_i = idCache[itemIndex]) != null ? _i : getId(state, itemIndex);
2055
2118
  const position = positions.get(id);
2056
2119
  if (position === void 0) {
2057
2120
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
@@ -2081,6 +2144,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2081
2144
  if (viewabilityConfigCallbackPairs) {
2082
2145
  updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
2083
2146
  }
2147
+ if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
2148
+ const item = data[nextActiveStickyIndex];
2149
+ if (item !== void 0) {
2150
+ onStickyHeaderChange({ index: nextActiveStickyIndex, item });
2151
+ }
2152
+ }
2084
2153
  });
2085
2154
  }
2086
2155
 
@@ -2239,7 +2308,9 @@ function doInitialAllocateContainers(ctx, state) {
2239
2308
  let totalSize = 0;
2240
2309
  const num = Math.min(20, data.length);
2241
2310
  for (let i = 0; i < num; i++) {
2242
- totalSize += fn(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "");
2311
+ const item = data[i];
2312
+ const itemType = getItemType ? (_a = getItemType(item, i)) != null ? _a : "" : "";
2313
+ totalSize += fn(i, item, itemType);
2243
2314
  }
2244
2315
  averageItemSize = totalSize / num;
2245
2316
  } else {
@@ -2268,7 +2339,9 @@ function doInitialAllocateContainers(ctx, state) {
2268
2339
  // src/core/handleLayout.ts
2269
2340
  function handleLayout(ctx, state, layout, setCanRender) {
2270
2341
  const { maintainScrollAtEnd } = state.props;
2271
- const scrollLength = layout[state.props.horizontal ? "width" : "height"];
2342
+ const measuredLength = layout[state.props.horizontal ? "width" : "height"];
2343
+ const previousLength = state.scrollLength;
2344
+ const scrollLength = measuredLength > 0 ? measuredLength : previousLength;
2272
2345
  const otherAxisSize = layout[state.props.horizontal ? "height" : "width"];
2273
2346
  const needsCalculate = !state.lastLayout || scrollLength > state.scrollLength || state.lastLayout.x !== layout.x || state.lastLayout.y !== layout.y;
2274
2347
  state.lastLayout = layout;
@@ -2279,7 +2352,9 @@ function handleLayout(ctx, state, layout, setCanRender) {
2279
2352
  state.otherAxisSize = otherAxisSize;
2280
2353
  state.lastBatchingAction = Date.now();
2281
2354
  state.scrollForNextCalculateItemsInView = void 0;
2282
- doInitialAllocateContainers(ctx, state);
2355
+ if (scrollLength > 0) {
2356
+ doInitialAllocateContainers(ctx, state);
2357
+ }
2283
2358
  if (needsCalculate) {
2284
2359
  calculateItemsInView(ctx, state, { doMVCP: true });
2285
2360
  }
@@ -2295,14 +2370,14 @@ function handleLayout(ctx, state, layout, setCanRender) {
2295
2370
  if (state) {
2296
2371
  state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2297
2372
  }
2298
- if (__DEV__ && scrollLength === 0) {
2373
+ if (__DEV__ && measuredLength === 0) {
2299
2374
  warnDevOnce(
2300
2375
  "height0",
2301
2376
  `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.`
2302
2377
  );
2303
2378
  }
2304
- setCanRender(true);
2305
2379
  }
2380
+ setCanRender(true);
2306
2381
  }
2307
2382
 
2308
2383
  // src/core/onScroll.ts
@@ -2362,7 +2437,7 @@ var ScrollAdjustHandler = class {
2362
2437
  this.context = ctx;
2363
2438
  }
2364
2439
  requestAdjust(add) {
2365
- const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
2440
+ const oldAdjustTop = this.appliedAdjust;
2366
2441
  this.appliedAdjust = add + oldAdjustTop;
2367
2442
  const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
2368
2443
  if (this.mounted) {
@@ -2381,7 +2456,7 @@ var ScrollAdjustHandler = class {
2381
2456
 
2382
2457
  // src/core/updateItemSize.ts
2383
2458
  function updateItemSize(ctx, state, itemKey, sizeObj) {
2384
- var _a, _b;
2459
+ var _a;
2385
2460
  const {
2386
2461
  sizesKnown,
2387
2462
  props: {
@@ -2396,17 +2471,17 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2396
2471
  }
2397
2472
  } = state;
2398
2473
  if (!data) return;
2474
+ const index = state.indexByKey.get(itemKey);
2399
2475
  if (getFixedItemSize) {
2400
- const index2 = state.indexByKey.get(itemKey);
2401
- if (index2 === void 0) {
2476
+ if (index === void 0) {
2402
2477
  return;
2403
2478
  }
2404
- const itemData = state.props.data[index2];
2479
+ const itemData = state.props.data[index];
2405
2480
  if (itemData === void 0) {
2406
2481
  return;
2407
2482
  }
2408
- const type = getItemType ? (_a = getItemType(itemData, index2)) != null ? _a : "" : "";
2409
- const size2 = getFixedItemSize(index2, itemData, type);
2483
+ const type = getItemType ? (_a = getItemType(itemData, index)) != null ? _a : "" : "";
2484
+ const size2 = getFixedItemSize(index, itemData, type);
2410
2485
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
2411
2486
  return;
2412
2487
  }
@@ -2416,15 +2491,11 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2416
2491
  let shouldMaintainScrollAtEnd = false;
2417
2492
  let minIndexSizeChanged;
2418
2493
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2419
- const index = state.indexByKey.get(itemKey);
2420
2494
  const prevSizeKnown = state.sizesKnown.get(itemKey);
2421
2495
  const diff = updateOneItemSize(state, itemKey, sizeObj);
2422
2496
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2423
2497
  if (diff !== 0) {
2424
2498
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
2425
- if (((_b = state.scrollingTo) == null ? void 0 : _b.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
2426
- requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
2427
- }
2428
2499
  const { startBuffered, endBuffered } = state;
2429
2500
  needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2430
2501
  if (!needsRecalculate) {
@@ -2556,18 +2627,59 @@ function getRenderedItem(ctx, state, key) {
2556
2627
  return null;
2557
2628
  }
2558
2629
  let renderedItem = null;
2559
- if (renderItem && data[index]) {
2630
+ const extraData = peek$(ctx, "extraData");
2631
+ const item = data[index];
2632
+ if (renderItem && !isNullOrUndefined(item)) {
2560
2633
  const itemProps = {
2561
2634
  data,
2562
- extraData: peek$(ctx, "extraData"),
2635
+ extraData,
2563
2636
  index,
2564
- item: data[index],
2565
- type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
2637
+ item,
2638
+ type: getItemType ? (_a = getItemType(item, index)) != null ? _a : "" : ""
2566
2639
  };
2567
- renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React2__default.createElement(renderItem, itemProps);
2640
+ renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React3__default.createElement(renderItem, itemProps);
2568
2641
  }
2569
2642
  return { index, item: data[index], renderedItem };
2570
2643
  }
2644
+ function useThrottleDebounce(mode) {
2645
+ const timeoutRef = useRef(null);
2646
+ const lastCallTimeRef = useRef(0);
2647
+ const lastArgsRef = useRef(null);
2648
+ const clearTimeoutRef = () => {
2649
+ if (timeoutRef.current) {
2650
+ clearTimeout(timeoutRef.current);
2651
+ timeoutRef.current = null;
2652
+ }
2653
+ };
2654
+ const execute = useCallback(
2655
+ (callback, delay, ...args) => {
2656
+ {
2657
+ const now = Date.now();
2658
+ lastArgsRef.current = args;
2659
+ if (now - lastCallTimeRef.current >= delay) {
2660
+ lastCallTimeRef.current = now;
2661
+ callback(...args);
2662
+ clearTimeoutRef();
2663
+ } else {
2664
+ clearTimeoutRef();
2665
+ timeoutRef.current = setTimeout(
2666
+ () => {
2667
+ if (lastArgsRef.current) {
2668
+ lastCallTimeRef.current = Date.now();
2669
+ callback(...lastArgsRef.current);
2670
+ timeoutRef.current = null;
2671
+ lastArgsRef.current = null;
2672
+ }
2673
+ },
2674
+ delay - (now - lastCallTimeRef.current)
2675
+ );
2676
+ }
2677
+ }
2678
+ },
2679
+ [mode]
2680
+ );
2681
+ return execute;
2682
+ }
2571
2683
 
2572
2684
  // src/utils/throttledOnScroll.ts
2573
2685
  function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
@@ -2584,14 +2696,14 @@ var LegendList = typedMemo(
2584
2696
  const isChildrenMode = children !== void 0 && dataProp === void 0;
2585
2697
  const processedProps = isChildrenMode ? {
2586
2698
  ...restProps,
2587
- data: (isArray(children) ? children : React2.Children.toArray(children)).flat(1),
2699
+ data: (isArray(children) ? children : React3.Children.toArray(children)).flat(1),
2588
2700
  renderItem: ({ item }) => item
2589
2701
  } : {
2590
2702
  ...restProps,
2591
2703
  data: dataProp || [],
2592
2704
  renderItem: renderItemProp
2593
2705
  };
2594
- return /* @__PURE__ */ React2.createElement(StateProvider, null, /* @__PURE__ */ React2.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
2706
+ return /* @__PURE__ */ React3.createElement(StateProvider, null, /* @__PURE__ */ React3.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
2595
2707
  })
2596
2708
  );
2597
2709
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
@@ -2631,6 +2743,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2631
2743
  onScroll: onScrollProp,
2632
2744
  onStartReached,
2633
2745
  onStartReachedThreshold = 0.5,
2746
+ onStickyHeaderChange,
2634
2747
  onViewableItemsChanged,
2635
2748
  progressViewOffset,
2636
2749
  recycleItems = false,
@@ -2650,7 +2763,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2650
2763
  } = props;
2651
2764
  const [renderNum, setRenderNum] = useState(0);
2652
2765
  const initialScroll = initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
2653
- const [canRender, setCanRender] = React2.useState(!IsNewArchitecture);
2766
+ const [canRender, setCanRender] = React3.useState(!IsNewArchitecture);
2654
2767
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
2655
2768
  const style = { ...StyleSheet.flatten(styleProp) };
2656
2769
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
@@ -2664,60 +2777,63 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2664
2777
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
2665
2778
  const refState = useRef();
2666
2779
  if (!refState.current) {
2667
- const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : Dimensions.get("window"))[horizontal ? "width" : "height"];
2668
- refState.current = {
2669
- activeStickyIndex: void 0,
2670
- averageSizes: {},
2671
- columns: /* @__PURE__ */ new Map(),
2672
- containerItemKeys: /* @__PURE__ */ new Set(),
2673
- containerItemTypes: /* @__PURE__ */ new Map(),
2674
- dataChangeNeedsScrollUpdate: false,
2675
- enableScrollForNextCalculateItemsInView: true,
2676
- endBuffered: -1,
2677
- endNoBuffer: -1,
2678
- endReachedBlockedByTimer: false,
2679
- firstFullyOnScreenIndex: -1,
2680
- idCache: /* @__PURE__ */ new Map(),
2681
- idsInView: [],
2682
- indexByKey: /* @__PURE__ */ new Map(),
2683
- initialScroll,
2684
- isAtEnd: false,
2685
- isAtStart: false,
2686
- isEndReached: false,
2687
- isStartReached: false,
2688
- lastBatchingAction: Date.now(),
2689
- lastLayout: void 0,
2690
- loadStartTime: Date.now(),
2691
- minIndexSizeChanged: 0,
2692
- nativeMarginTop: 0,
2693
- positions: /* @__PURE__ */ new Map(),
2694
- props: {},
2695
- queuedCalculateItemsInView: 0,
2696
- refScroller: void 0,
2697
- scroll: 0,
2698
- scrollAdjustHandler: new ScrollAdjustHandler(ctx),
2699
- scrollForNextCalculateItemsInView: void 0,
2700
- scrollHistory: [],
2701
- scrollLength: initialScrollLength,
2702
- scrollPending: 0,
2703
- scrollPrev: 0,
2704
- scrollPrevTime: 0,
2705
- scrollProcessingEnabled: true,
2706
- scrollTime: 0,
2707
- sizes: /* @__PURE__ */ new Map(),
2708
- sizesKnown: /* @__PURE__ */ new Map(),
2709
- startBuffered: -1,
2710
- startNoBuffer: -1,
2711
- startReachedBlockedByTimer: false,
2712
- stickyContainerPool: /* @__PURE__ */ new Set(),
2713
- stickyContainers: /* @__PURE__ */ new Map(),
2714
- timeoutSizeMessage: 0,
2715
- timeouts: /* @__PURE__ */ new Set(),
2716
- totalSize: 0,
2717
- viewabilityConfigCallbackPairs: void 0
2718
- };
2719
- set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2720
- set$(ctx, "extraData", extraData);
2780
+ if (!ctx.internalState) {
2781
+ const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : Dimensions.get("window"))[horizontal ? "width" : "height"];
2782
+ ctx.internalState = {
2783
+ activeStickyIndex: void 0,
2784
+ averageSizes: {},
2785
+ columns: /* @__PURE__ */ new Map(),
2786
+ containerItemKeys: /* @__PURE__ */ new Set(),
2787
+ containerItemTypes: /* @__PURE__ */ new Map(),
2788
+ dataChangeNeedsScrollUpdate: false,
2789
+ enableScrollForNextCalculateItemsInView: true,
2790
+ endBuffered: -1,
2791
+ endNoBuffer: -1,
2792
+ endReachedBlockedByTimer: false,
2793
+ firstFullyOnScreenIndex: -1,
2794
+ idCache: [],
2795
+ idsInView: [],
2796
+ indexByKey: /* @__PURE__ */ new Map(),
2797
+ initialScroll,
2798
+ isAtEnd: false,
2799
+ isAtStart: false,
2800
+ isEndReached: false,
2801
+ isStartReached: false,
2802
+ lastBatchingAction: Date.now(),
2803
+ lastLayout: void 0,
2804
+ loadStartTime: Date.now(),
2805
+ minIndexSizeChanged: 0,
2806
+ nativeMarginTop: 0,
2807
+ positions: /* @__PURE__ */ new Map(),
2808
+ props: {},
2809
+ queuedCalculateItemsInView: 0,
2810
+ refScroller: void 0,
2811
+ scroll: 0,
2812
+ scrollAdjustHandler: new ScrollAdjustHandler(ctx),
2813
+ scrollForNextCalculateItemsInView: void 0,
2814
+ scrollHistory: [],
2815
+ scrollLength: initialScrollLength,
2816
+ scrollPending: 0,
2817
+ scrollPrev: 0,
2818
+ scrollPrevTime: 0,
2819
+ scrollProcessingEnabled: true,
2820
+ scrollTime: 0,
2821
+ sizes: /* @__PURE__ */ new Map(),
2822
+ sizesKnown: /* @__PURE__ */ new Map(),
2823
+ startBuffered: -1,
2824
+ startNoBuffer: -1,
2825
+ startReachedBlockedByTimer: false,
2826
+ stickyContainerPool: /* @__PURE__ */ new Set(),
2827
+ stickyContainers: /* @__PURE__ */ new Map(),
2828
+ timeoutSizeMessage: 0,
2829
+ timeouts: /* @__PURE__ */ new Set(),
2830
+ totalSize: 0,
2831
+ viewabilityConfigCallbackPairs: void 0
2832
+ };
2833
+ set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2834
+ set$(ctx, "extraData", extraData);
2835
+ }
2836
+ refState.current = ctx.internalState;
2721
2837
  }
2722
2838
  const state = refState.current;
2723
2839
  const isFirst = !state.props.renderItem;
@@ -2750,6 +2866,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2750
2866
  onScroll: throttleScrollFn,
2751
2867
  onStartReached,
2752
2868
  onStartReachedThreshold,
2869
+ onStickyHeaderChange,
2753
2870
  recycleItems: !!recycleItems,
2754
2871
  renderItem,
2755
2872
  scrollBuffer,
@@ -2800,7 +2917,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2800
2917
  }
2801
2918
  refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
2802
2919
  if (initialContentOffset2 > 0) {
2803
- scrollTo(state, { animated: false, index, offset: initialContentOffset2 });
2920
+ scrollTo(state, {
2921
+ animated: false,
2922
+ index,
2923
+ isInitialScroll: true,
2924
+ offset: initialContentOffset2,
2925
+ viewPosition: index === dataProp.length - 1 ? 1 : 0
2926
+ });
2804
2927
  }
2805
2928
  return initialContentOffset2;
2806
2929
  }
@@ -2838,7 +2961,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2838
2961
  }
2839
2962
  }, [snapToIndices]);
2840
2963
  useLayoutEffect(() => {
2841
- const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainersCallback();
2964
+ const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainers(ctx, state);
2842
2965
  if (!didAllocateContainers) {
2843
2966
  checkResetContainers(
2844
2967
  ctx,
@@ -2852,30 +2975,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2852
2975
  useLayoutEffect(() => {
2853
2976
  set$(ctx, "extraData", extraData);
2854
2977
  }, [extraData]);
2855
- useLayoutEffect(() => {
2856
- var _a2;
2857
- if (IsNewArchitecture) {
2858
- let measured;
2859
- (_a2 = refScroller.current) == null ? void 0 : _a2.measure((x, y, width, height) => {
2860
- measured = { height, width, x, y };
2861
- });
2862
- if (measured) {
2863
- const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
2864
- if (size) {
2865
- handleLayout(ctx, state, measured, setCanRender);
2866
- }
2867
- }
2868
- }
2869
- }, []);
2870
2978
  useLayoutEffect(initializeStateVars, [
2871
2979
  memoizedLastItemKeys.join(","),
2872
2980
  numColumnsProp,
2873
2981
  stylePaddingTopState,
2874
2982
  stylePaddingBottomState
2875
2983
  ]);
2876
- const doInitialAllocateContainersCallback = () => {
2877
- return doInitialAllocateContainers(ctx, state);
2878
- };
2879
2984
  useEffect(() => {
2880
2985
  const viewability = setupViewability({
2881
2986
  onViewableItemsChanged,
@@ -2887,16 +2992,18 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2887
2992
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
2888
2993
  if (!IsNewArchitecture) {
2889
2994
  useInit(() => {
2890
- doInitialAllocateContainersCallback();
2995
+ doInitialAllocateContainers(ctx, state);
2891
2996
  });
2892
2997
  }
2893
- const onLayout = useCallback((event) => {
2894
- const layout = event.nativeEvent.layout;
2998
+ const onLayoutChange = useCallback((layout) => {
2895
2999
  handleLayout(ctx, state, layout, setCanRender);
2896
- if (onLayoutProp) {
2897
- onLayoutProp(event);
2898
- }
2899
3000
  }, []);
3001
+ const { onLayout } = useOnLayoutSync({
3002
+ onLayoutChange,
3003
+ onLayoutProp,
3004
+ ref: refScroller
3005
+ // the type of ScrollView doesn't include measure?
3006
+ });
2900
3007
  useImperativeHandle(forwardedRef, () => {
2901
3008
  const scrollIndexIntoView = (options) => {
2902
3009
  const state2 = refState.current;
@@ -3005,7 +3112,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3005
3112
  }
3006
3113
  return onScrollFn;
3007
3114
  }, [stickyIndices == null ? void 0 : stickyIndices.length, horizontal, scrollEventThrottle]);
3008
- return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(
3115
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
3009
3116
  ListComponent,
3010
3117
  {
3011
3118
  ...rest,
@@ -3036,9 +3143,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3036
3143
  },
3037
3144
  onScroll: onScrollHandler,
3038
3145
  recycleItems,
3039
- refreshControl: refreshControl ? stylePaddingTopState > 0 ? React2.cloneElement(refreshControl, {
3146
+ refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControl, {
3040
3147
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
3041
- }) : refreshControl : onRefresh && /* @__PURE__ */ React2.createElement(
3148
+ }) : refreshControl : onRefresh && /* @__PURE__ */ React3.createElement(
3042
3149
  RefreshControl,
3043
3150
  {
3044
3151
  onRefresh,
@@ -3055,7 +3162,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3055
3162
  updateItemSize: fns.updateItemSize,
3056
3163
  waitForInitialLayout
3057
3164
  }
3058
- ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React2.createElement(DebugView, { state: refState.current }));
3165
+ ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3.createElement(DebugView, { state: refState.current }));
3059
3166
  });
3060
3167
 
3061
3168
  export { LegendList, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };