@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.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var React2 = require('react');
3
+ var React3 = require('react');
4
4
  var reactNative = require('react-native');
5
5
  var shim = require('use-sync-external-store/shim');
6
6
 
@@ -22,14 +22,15 @@ function _interopNamespace(e) {
22
22
  return Object.freeze(n);
23
23
  }
24
24
 
25
- var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
25
+ var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
26
26
 
27
27
  // src/components/LegendList.tsx
28
- var ContextState = React2__namespace.createContext(null);
28
+ var ContextState = React3__namespace.createContext(null);
29
29
  function StateProvider({ children }) {
30
- const [value] = React2__namespace.useState(() => ({
30
+ const [value] = React3__namespace.useState(() => ({
31
31
  animatedScrollY: new reactNative.Animated.Value(0),
32
32
  columnWrapperStyle: void 0,
33
+ internalState: void 0,
33
34
  listeners: /* @__PURE__ */ new Map(),
34
35
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
35
36
  mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
@@ -45,10 +46,10 @@ function StateProvider({ children }) {
45
46
  ]),
46
47
  viewRefs: /* @__PURE__ */ new Map()
47
48
  }));
48
- return /* @__PURE__ */ React2__namespace.createElement(ContextState.Provider, { value }, children);
49
+ return /* @__PURE__ */ React3__namespace.createElement(ContextState.Provider, { value }, children);
49
50
  }
50
51
  function useStateContext() {
51
- return React2__namespace.useContext(ContextState);
52
+ return React3__namespace.useContext(ContextState);
52
53
  }
53
54
  function createSelectorFunctionsArr(ctx, signalNames) {
54
55
  let lastValues = [];
@@ -118,23 +119,23 @@ function getContentSize(ctx) {
118
119
  return headerSize + footerSize + totalSize + stylePaddingTop;
119
120
  }
120
121
  function useArr$(signalNames) {
121
- const ctx = React2__namespace.useContext(ContextState);
122
- const { subscribe, get } = React2__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
122
+ const ctx = React3__namespace.useContext(ContextState);
123
+ const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
123
124
  const value = shim.useSyncExternalStore(subscribe, get);
124
125
  return value;
125
126
  }
126
127
  function useSelector$(signalName, selector) {
127
- const ctx = React2__namespace.useContext(ContextState);
128
- const { subscribe, get } = React2__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
128
+ const ctx = React3__namespace.useContext(ContextState);
129
+ const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
129
130
  const value = shim.useSyncExternalStore(subscribe, () => selector(get()[0]));
130
131
  return value;
131
132
  }
132
133
 
133
134
  // src/components/DebugView.tsx
134
135
  var DebugRow = ({ children }) => {
135
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
136
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
136
137
  };
137
- var DebugView = React2__namespace.memo(function DebugView2({ state }) {
138
+ var DebugView = React3__namespace.memo(function DebugView2({ state }) {
138
139
  const ctx = useStateContext();
139
140
  const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
140
141
  "totalSize",
@@ -145,11 +146,11 @@ var DebugView = React2__namespace.memo(function DebugView2({ state }) {
145
146
  "numContainersPooled"
146
147
  ]);
147
148
  const contentSize = getContentSize(ctx);
148
- const [, forceUpdate] = React2.useReducer((x) => x + 1, 0);
149
+ const [, forceUpdate] = React3.useReducer((x) => x + 1, 0);
149
150
  useInterval(() => {
150
151
  forceUpdate();
151
152
  }, 100);
152
- return /* @__PURE__ */ React2__namespace.createElement(
153
+ return /* @__PURE__ */ React3__namespace.createElement(
153
154
  reactNative.View,
154
155
  {
155
156
  pointerEvents: "none",
@@ -165,27 +166,22 @@ var DebugView = React2__namespace.memo(function DebugView2({ state }) {
165
166
  top: 0
166
167
  }
167
168
  },
168
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "TotalSize:"), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, totalSize.toFixed(2))),
169
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "ContentSize:"), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, contentSize.toFixed(2))),
170
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "At end:"), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, String(state.isAtEnd))),
171
- /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null),
172
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "ScrollAdjust:"), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, scrollAdjust.toFixed(2))),
173
- /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null),
174
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "RawScroll: "), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, rawScroll.toFixed(2))),
175
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "ComputedScroll: "), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, scroll.toFixed(2)))
169
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "TotalSize:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, totalSize.toFixed(2))),
170
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "ContentSize:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, contentSize.toFixed(2))),
171
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "At end:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, String(state.isAtEnd))),
172
+ /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null),
173
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "ScrollAdjust:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, scrollAdjust.toFixed(2))),
174
+ /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null),
175
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "RawScroll: "), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, rawScroll.toFixed(2))),
176
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "ComputedScroll: "), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, scroll.toFixed(2)))
176
177
  );
177
178
  });
178
179
  function useInterval(callback, delay) {
179
- React2.useEffect(() => {
180
+ React3.useEffect(() => {
180
181
  const interval = setInterval(callback, delay);
181
182
  return () => clearInterval(interval);
182
183
  }, [delay]);
183
184
  }
184
- var LeanViewComponent = React2__namespace.forwardRef((props, ref) => {
185
- return React2__namespace.createElement("RCTView", { ...props, ref });
186
- });
187
- LeanViewComponent.displayName = "RCTView";
188
- var LeanView = reactNative.Platform.OS === "android" || reactNative.Platform.OS === "ios" ? LeanViewComponent : reactNative.View;
189
185
 
190
186
  // src/constants.ts
191
187
  var POSITION_OUT_OF_VIEW = -1e7;
@@ -193,7 +189,7 @@ var ENABLE_DEVMODE = __DEV__ && false;
193
189
  var ENABLE_DEBUG_VIEW = __DEV__ && false;
194
190
  var IsNewArchitecture = global.nativeFabricUIManager != null;
195
191
  var useAnimatedValue = (initialValue) => {
196
- return React2.useRef(new reactNative.Animated.Value(initialValue)).current;
192
+ return React3.useRef(new reactNative.Animated.Value(initialValue)).current;
197
193
  };
198
194
 
199
195
  // src/hooks/useValue$.ts
@@ -202,7 +198,7 @@ function useValue$(key, params) {
202
198
  const { getValue, delay } = params || {};
203
199
  const ctx = useStateContext();
204
200
  const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
205
- React2.useMemo(() => {
201
+ React3.useMemo(() => {
206
202
  let newValue;
207
203
  let prevValue;
208
204
  let didQueueTask = false;
@@ -219,7 +215,9 @@ function useValue$(key, params) {
219
215
  prevValue = newValue;
220
216
  if (!didQueueTask) {
221
217
  didQueueTask = true;
222
- if (delayValue === 0) {
218
+ if (delayValue === void 0) {
219
+ fn();
220
+ } else if (delayValue === 0) {
223
221
  queueMicrotask(fn);
224
222
  } else {
225
223
  setTimeout(fn, delayValue);
@@ -232,8 +230,8 @@ function useValue$(key, params) {
232
230
  }, []);
233
231
  return animValue;
234
232
  }
235
- var typedForwardRef = React2.forwardRef;
236
- var typedMemo = React2.memo;
233
+ var typedForwardRef = React3.forwardRef;
234
+ var typedMemo = React3.memo;
237
235
 
238
236
  // src/components/PositionView.tsx
239
237
  var PositionViewState = typedMemo(function PositionView({
@@ -244,8 +242,8 @@ var PositionViewState = typedMemo(function PositionView({
244
242
  ...rest
245
243
  }) {
246
244
  const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
247
- return /* @__PURE__ */ React2__namespace.createElement(
248
- LeanView,
245
+ return /* @__PURE__ */ React3__namespace.createElement(
246
+ reactNative.View,
249
247
  {
250
248
  ref: refView,
251
249
  style: [
@@ -272,7 +270,7 @@ var PositionViewAnimated = typedMemo(function PositionView2({
272
270
  } else {
273
271
  position = horizontal ? { left: position$ } : { top: position$ };
274
272
  }
275
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { ref: refView, style: [style, position], ...rest });
273
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.Animated.View, { ref: refView, style: [style, position], ...rest });
276
274
  });
277
275
  var PositionViewSticky = typedMemo(function PositionViewSticky2({
278
276
  id,
@@ -285,8 +283,8 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
285
283
  ...rest
286
284
  }) {
287
285
  const [position = POSITION_OUT_OF_VIEW, headerSize] = useArr$([`containerPosition${id}`, "headerSize"]);
288
- const transform = React2__namespace.useMemo(() => {
289
- if (animatedScrollY && stickyOffset) {
286
+ const transform = React3__namespace.useMemo(() => {
287
+ if (animatedScrollY && stickyOffset !== void 0) {
290
288
  const stickyPosition = animatedScrollY.interpolate({
291
289
  extrapolate: "clamp",
292
290
  inputRange: [position + headerSize, position + 5e3 + headerSize],
@@ -295,13 +293,13 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
295
293
  return horizontal ? [{ translateX: stickyPosition }] : [{ translateY: stickyPosition }];
296
294
  }
297
295
  }, [animatedScrollY, headerSize, horizontal, stickyOffset, position]);
298
- const viewStyle = React2__namespace.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
299
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { ref: refView, style: viewStyle, ...rest });
296
+ const viewStyle = React3__namespace.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
297
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.Animated.View, { ref: refView, style: viewStyle, ...rest });
300
298
  });
301
299
  var PositionView3 = IsNewArchitecture ? PositionViewState : PositionViewAnimated;
302
300
  var symbolFirst = Symbol();
303
301
  function useInit(cb) {
304
- const refValue = React2.useRef(symbolFirst);
302
+ const refValue = React3.useRef(symbolFirst);
305
303
  if (refValue.current === symbolFirst) {
306
304
  refValue.current = cb();
307
305
  }
@@ -340,10 +338,10 @@ function extractPadding(style, contentContainerStyle, type) {
340
338
  }
341
339
 
342
340
  // src/state/ContextContainer.ts
343
- var ContextContainer = React2.createContext(null);
341
+ var ContextContainer = React3.createContext(null);
344
342
  function useViewability(callback, configId) {
345
343
  const ctx = useStateContext();
346
- const { containerId } = React2.useContext(ContextContainer);
344
+ const { containerId } = React3.useContext(ContextContainer);
347
345
  const key = containerId + (configId != null ? configId : "");
348
346
  useInit(() => {
349
347
  const value = ctx.mapViewabilityValues.get(key);
@@ -352,7 +350,7 @@ function useViewability(callback, configId) {
352
350
  }
353
351
  });
354
352
  ctx.mapViewabilityCallbacks.set(key, callback);
355
- React2.useEffect(
353
+ React3.useEffect(
356
354
  () => () => {
357
355
  ctx.mapViewabilityCallbacks.delete(key);
358
356
  },
@@ -361,7 +359,7 @@ function useViewability(callback, configId) {
361
359
  }
362
360
  function useViewabilityAmount(callback) {
363
361
  const ctx = useStateContext();
364
- const { containerId } = React2.useContext(ContextContainer);
362
+ const { containerId } = React3.useContext(ContextContainer);
365
363
  useInit(() => {
366
364
  const value = ctx.mapViewabilityAmountValues.get(containerId);
367
365
  if (value) {
@@ -369,7 +367,7 @@ function useViewabilityAmount(callback) {
369
367
  }
370
368
  });
371
369
  ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
372
- React2.useEffect(
370
+ React3.useEffect(
373
371
  () => () => {
374
372
  ctx.mapViewabilityAmountCallbacks.delete(containerId);
375
373
  },
@@ -377,12 +375,12 @@ function useViewabilityAmount(callback) {
377
375
  );
378
376
  }
379
377
  function useRecyclingEffect(effect) {
380
- const { index, value } = React2.useContext(ContextContainer);
381
- const prevValues = React2.useRef({
378
+ const { index, value } = React3.useContext(ContextContainer);
379
+ const prevValues = React3.useRef({
382
380
  prevIndex: void 0,
383
381
  prevItem: void 0
384
382
  });
385
- React2.useEffect(() => {
383
+ React3.useEffect(() => {
386
384
  let ret;
387
385
  if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
388
386
  ret = effect({
@@ -400,12 +398,12 @@ function useRecyclingEffect(effect) {
400
398
  }, [index, value, effect]);
401
399
  }
402
400
  function useRecyclingState(valueOrFun) {
403
- const { index, value, itemKey, triggerLayout } = React2.useContext(ContextContainer);
404
- const refState = React2.useRef({
401
+ const { index, value, itemKey, triggerLayout } = React3.useContext(ContextContainer);
402
+ const refState = React3.useRef({
405
403
  itemKey: null,
406
404
  value: null
407
405
  });
408
- const [_, setRenderNum] = React2.useState(0);
406
+ const [_, setRenderNum] = React3.useState(0);
409
407
  const state = refState.current;
410
408
  if (state.itemKey !== itemKey) {
411
409
  state.itemKey = itemKey;
@@ -416,7 +414,7 @@ function useRecyclingState(valueOrFun) {
416
414
  prevItem: void 0
417
415
  }) : valueOrFun;
418
416
  }
419
- const setState = React2.useCallback(
417
+ const setState = React3.useCallback(
420
418
  (newState) => {
421
419
  state.value = isFunction(newState) ? newState(state.value) : newState;
422
420
  setRenderNum((v) => v + 1);
@@ -427,7 +425,7 @@ function useRecyclingState(valueOrFun) {
427
425
  return [state.value, setState];
428
426
  }
429
427
  function useIsLastItem() {
430
- const { itemKey } = React2.useContext(ContextContainer);
428
+ const { itemKey } = React3.useContext(ContextContainer);
431
429
  const isLast = useSelector$("lastItemKeys", (lastItemKeys) => (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false);
432
430
  return isLast;
433
431
  }
@@ -439,7 +437,7 @@ var noop = () => {
439
437
  };
440
438
  function useSyncLayout() {
441
439
  if (IsNewArchitecture) {
442
- const { triggerLayout: syncLayout } = React2.useContext(ContextContainer);
440
+ const { triggerLayout: syncLayout } = React3.useContext(ContextContainer);
443
441
  return syncLayout;
444
442
  } else {
445
443
  return noop;
@@ -449,7 +447,30 @@ function useSyncLayout() {
449
447
  // src/components/Separator.tsx
450
448
  function Separator({ ItemSeparatorComponent, leadingItem }) {
451
449
  const isLastItem = useIsLastItem();
452
- return isLastItem ? null : /* @__PURE__ */ React2__namespace.createElement(ItemSeparatorComponent, { leadingItem });
450
+ return isLastItem ? null : /* @__PURE__ */ React3__namespace.createElement(ItemSeparatorComponent, { leadingItem });
451
+ }
452
+ function useOnLayoutSync({
453
+ ref,
454
+ onLayoutProp,
455
+ onLayoutChange
456
+ }, deps = []) {
457
+ const onLayout = React3.useCallback(
458
+ (event) => {
459
+ onLayoutChange(event.nativeEvent.layout, false);
460
+ onLayoutProp == null ? void 0 : onLayoutProp(event);
461
+ },
462
+ [onLayoutChange]
463
+ );
464
+ if (IsNewArchitecture) {
465
+ React3.useLayoutEffect(() => {
466
+ if (ref.current) {
467
+ ref.current.measure((x, y, width, height) => {
468
+ onLayoutChange({ height, width, x, y }, true);
469
+ });
470
+ }
471
+ }, deps);
472
+ }
473
+ return { onLayout };
453
474
  }
454
475
 
455
476
  // src/components/Container.tsx
@@ -472,13 +493,13 @@ var Container = typedMemo(function Container2({
472
493
  `containerSticky${id}`,
473
494
  `containerStickyOffset${id}`
474
495
  ]);
475
- const refLastSize = React2.useRef();
476
- const ref = React2.useRef(null);
477
- const [layoutRenderCount, forceLayoutRender] = React2.useState(0);
496
+ const refLastSize = React3.useRef();
497
+ const ref = React3.useRef(null);
498
+ const [layoutRenderCount, forceLayoutRender] = React3.useState(0);
478
499
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
479
500
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
480
- let didLayout = false;
481
- const style = React2.useMemo(() => {
501
+ const didLayoutRef = React3.useRef(false);
502
+ const style = React3.useMemo(() => {
482
503
  let paddingStyles;
483
504
  if (columnWrapperStyle) {
484
505
  const { columnGap, rowGap, gap } = columnWrapperStyle;
@@ -510,12 +531,12 @@ var Container = typedMemo(function Container2({
510
531
  ...paddingStyles || {}
511
532
  };
512
533
  }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
513
- const renderedItemInfo = React2.useMemo(
534
+ const renderedItemInfo = React3.useMemo(
514
535
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
515
536
  [itemKey, data, extraData]
516
537
  );
517
538
  const { index, renderedItem } = renderedItemInfo || {};
518
- const contextValue = React2.useMemo(() => {
539
+ const contextValue = React3.useMemo(() => {
519
540
  ctx.viewRefs.set(id, ref);
520
541
  return {
521
542
  containerId: id,
@@ -527,15 +548,16 @@ var Container = typedMemo(function Container2({
527
548
  value: data
528
549
  };
529
550
  }, [id, itemKey, index, data]);
530
- const onLayout = (event) => {
551
+ const onLayoutChange = (rectangle) => {
531
552
  var _a, _b;
532
553
  if (!isNullOrUndefined(itemKey)) {
533
- didLayout = true;
534
- let layout = event.nativeEvent.layout;
535
- const size = layout[horizontal ? "width" : "height"];
554
+ didLayoutRef.current = true;
555
+ let layout = rectangle;
556
+ const size = Math.floor(rectangle[horizontal ? "width" : "height"] * 8) / 8;
536
557
  const doUpdate = () => {
537
558
  refLastSize.current = { height: layout.height, width: layout.width };
538
559
  updateItemSize2(itemKey, layout);
560
+ didLayoutRef.current = true;
539
561
  };
540
562
  if (IsNewArchitecture || size > 0) {
541
563
  doUpdate();
@@ -547,25 +569,20 @@ var Container = typedMemo(function Container2({
547
569
  }
548
570
  }
549
571
  };
550
- if (IsNewArchitecture) {
551
- React2.useLayoutEffect(() => {
552
- var _a, _b;
553
- if (!isNullOrUndefined(itemKey)) {
554
- const measured = (_b = (_a = ref.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
555
- if (measured) {
556
- const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
557
- if (size) {
558
- updateItemSize2(itemKey, measured);
559
- }
560
- }
561
- }
562
- }, [itemKey, layoutRenderCount]);
563
- } else {
564
- React2.useEffect(() => {
572
+ const { onLayout } = useOnLayoutSync(
573
+ {
574
+ onLayoutChange,
575
+ ref
576
+ },
577
+ [itemKey, layoutRenderCount]
578
+ );
579
+ if (!IsNewArchitecture) {
580
+ React3.useEffect(() => {
565
581
  if (!isNullOrUndefined(itemKey)) {
566
582
  const timeout = setTimeout(() => {
567
- if (!didLayout && refLastSize.current) {
583
+ if (!didLayoutRef.current && refLastSize.current) {
568
584
  updateItemSize2(itemKey, refLastSize.current);
585
+ didLayoutRef.current = true;
569
586
  }
570
587
  }, 16);
571
588
  return () => {
@@ -575,7 +592,7 @@ var Container = typedMemo(function Container2({
575
592
  }, [itemKey]);
576
593
  }
577
594
  const PositionComponent = isSticky ? PositionViewSticky : PositionView3;
578
- return /* @__PURE__ */ React2__namespace.createElement(
595
+ return /* @__PURE__ */ React3__namespace.createElement(
579
596
  PositionComponent,
580
597
  {
581
598
  animatedScrollY: isSticky ? animatedScrollY : void 0,
@@ -588,7 +605,7 @@ var Container = typedMemo(function Container2({
588
605
  stickyOffset: isSticky ? stickyOffset : void 0,
589
606
  style
590
607
  },
591
- /* @__PURE__ */ React2__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React2__namespace.createElement(Separator, { ItemSeparatorComponent, leadingItem: renderedItemInfo.item }))
608
+ /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(Separator, { ItemSeparatorComponent, leadingItem: renderedItemInfo.item }))
592
609
  );
593
610
  });
594
611
 
@@ -606,14 +623,18 @@ var Containers = typedMemo(function Containers2({
606
623
  const [numContainers, numColumns] = useArr$(["numContainersPooled", "numColumns"]);
607
624
  const animSize = useValue$("totalSize", {
608
625
  // Use a microtask if increasing the size significantly, otherwise use a timeout
609
- delay: (value, prevValue) => !prevValue || value - prevValue > 20 ? 0 : 200
626
+ // If this is the initial scroll, we don't want to delay because we want to update the size immediately
627
+ delay: (value, prevValue) => {
628
+ var _a;
629
+ return !((_a = ctx.internalState) == null ? void 0 : _a.initialScroll) ? !prevValue || value - prevValue > 20 ? 0 : 200 : void 0;
630
+ }
610
631
  });
611
632
  const animOpacity = waitForInitialLayout && !IsNewArchitecture ? useValue$("containersDidLayout", { getValue: (value) => value ? 1 : 0 }) : void 0;
612
633
  const otherAxisSize = useValue$("otherAxisSize", { delay: 0 });
613
634
  const containers = [];
614
635
  for (let i = 0; i < numContainers; i++) {
615
636
  containers.push(
616
- /* @__PURE__ */ React2__namespace.createElement(
637
+ /* @__PURE__ */ React3__namespace.createElement(
617
638
  Container,
618
639
  {
619
640
  getRenderedItem: getRenderedItem2,
@@ -648,13 +669,18 @@ var Containers = typedMemo(function Containers2({
648
669
  }
649
670
  }
650
671
  }
651
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style }, containers);
672
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.Animated.View, { style }, containers);
652
673
  });
674
+ var LayoutView = ({ onLayoutChange, refView, ...rest }) => {
675
+ const ref = refView != null ? refView : React3.useRef();
676
+ const { onLayout } = useOnLayoutSync({ onLayoutChange, ref });
677
+ return /* @__PURE__ */ React.createElement(reactNative.View, { ...rest, onLayout, ref });
678
+ };
653
679
  function ScrollAdjust() {
654
680
  const bias = 1e7;
655
681
  const [scrollAdjust, scrollAdjustUserOffset] = useArr$(["scrollAdjust", "scrollAdjustUserOffset"]);
656
682
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0) + bias;
657
- return /* @__PURE__ */ React2__namespace.createElement(
683
+ return /* @__PURE__ */ React3__namespace.createElement(
658
684
  reactNative.View,
659
685
  {
660
686
  style: {
@@ -669,88 +695,26 @@ function ScrollAdjust() {
669
695
  }
670
696
  function SnapWrapper({ ScrollComponent, ...props }) {
671
697
  const [snapToOffsets] = useArr$(["snapToOffsets"]);
672
- return /* @__PURE__ */ React2__namespace.default.createElement(ScrollComponent, { ...props, snapToOffsets });
673
- }
674
- function useThrottleDebounce(mode) {
675
- const timeoutRef = React2.useRef(null);
676
- const lastCallTimeRef = React2.useRef(0);
677
- const lastArgsRef = React2.useRef(null);
678
- const clearTimeoutRef = () => {
679
- if (timeoutRef.current) {
680
- clearTimeout(timeoutRef.current);
681
- timeoutRef.current = null;
682
- }
683
- };
684
- const execute = React2.useCallback(
685
- (callback, delay, ...args) => {
686
- {
687
- const now = Date.now();
688
- lastArgsRef.current = args;
689
- if (now - lastCallTimeRef.current >= delay) {
690
- lastCallTimeRef.current = now;
691
- callback(...args);
692
- clearTimeoutRef();
693
- } else {
694
- clearTimeoutRef();
695
- timeoutRef.current = setTimeout(
696
- () => {
697
- if (lastArgsRef.current) {
698
- lastCallTimeRef.current = Date.now();
699
- callback(...lastArgsRef.current);
700
- timeoutRef.current = null;
701
- lastArgsRef.current = null;
702
- }
703
- },
704
- delay - (now - lastCallTimeRef.current)
705
- );
706
- }
707
- }
708
- },
709
- [mode]
710
- );
711
- return execute;
712
- }
713
-
714
- // src/hooks/useSyncLayout.tsx
715
- function useSyncLayout2({
716
- onChange
717
- }) {
718
- const ref = React2.useRef(null);
719
- const onLayout = React2.useCallback(
720
- (event) => {
721
- onChange(event.nativeEvent.layout, false);
722
- },
723
- [onChange]
724
- );
725
- if (IsNewArchitecture) {
726
- React2.useLayoutEffect(() => {
727
- if (ref.current) {
728
- ref.current.measure((x, y, width, height) => {
729
- onChange({ height, width, x, y }, true);
730
- });
731
- }
732
- }, []);
733
- }
734
- return { onLayout, ref };
698
+ return /* @__PURE__ */ React3__namespace.default.createElement(ScrollComponent, { ...props, snapToOffsets });
735
699
  }
736
700
 
737
701
  // src/components/ListComponent.tsx
738
702
  var getComponent = (Component) => {
739
- if (React2__namespace.isValidElement(Component)) {
703
+ if (React3__namespace.isValidElement(Component)) {
740
704
  return Component;
741
705
  }
742
706
  if (Component) {
743
- return /* @__PURE__ */ React2__namespace.createElement(Component, null);
707
+ return /* @__PURE__ */ React3__namespace.createElement(Component, null);
744
708
  }
745
709
  return null;
746
710
  };
747
711
  var Padding = () => {
748
712
  const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
749
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } });
713
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } });
750
714
  };
751
715
  var PaddingDevMode = () => {
752
716
  const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
753
- return /* @__PURE__ */ React2__namespace.createElement(React2__namespace.Fragment, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React2__namespace.createElement(
717
+ return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React3__namespace.createElement(
754
718
  reactNative.Animated.View,
755
719
  {
756
720
  style: {
@@ -793,14 +757,11 @@ var ListComponent = typedMemo(function ListComponent2({
793
757
  ...rest
794
758
  }) {
795
759
  const ctx = useStateContext();
796
- const { onLayout: onLayoutHeaderSync, ref: refHeader } = useSyncLayout2({
797
- onChange: onLayoutHeader
798
- });
799
- const ScrollComponent = renderScrollComponent ? React2.useMemo(
800
- () => React2__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
760
+ const ScrollComponent = renderScrollComponent ? React3.useMemo(
761
+ () => React3__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
801
762
  [renderScrollComponent]
802
763
  ) : reactNative.Animated.ScrollView;
803
- React2__namespace.useEffect(() => {
764
+ React3__namespace.useEffect(() => {
804
765
  if (canRender) {
805
766
  setTimeout(() => {
806
767
  scrollAdjustHandler.setMounted();
@@ -808,7 +769,7 @@ var ListComponent = typedMemo(function ListComponent2({
808
769
  }
809
770
  }, [canRender]);
810
771
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
811
- return /* @__PURE__ */ React2__namespace.createElement(
772
+ return /* @__PURE__ */ React3__namespace.createElement(
812
773
  SnapOrScroll,
813
774
  {
814
775
  ...rest,
@@ -827,11 +788,11 @@ var ListComponent = typedMemo(function ListComponent2({
827
788
  ScrollComponent: snapToIndices ? ScrollComponent : void 0,
828
789
  style
829
790
  },
830
- maintainVisibleContentPosition && /* @__PURE__ */ React2__namespace.createElement(ScrollAdjust, null),
831
- ENABLE_DEVMODE ? /* @__PURE__ */ React2__namespace.createElement(PaddingDevMode, null) : /* @__PURE__ */ React2__namespace.createElement(Padding, null),
832
- ListHeaderComponent && /* @__PURE__ */ React2__namespace.createElement(reactNative.View, { onLayout: onLayoutHeaderSync, ref: refHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
791
+ maintainVisibleContentPosition && /* @__PURE__ */ React3__namespace.createElement(ScrollAdjust, null),
792
+ ENABLE_DEVMODE ? /* @__PURE__ */ React3__namespace.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3__namespace.createElement(Padding, null),
793
+ ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
833
794
  ListEmptyComponent && getComponent(ListEmptyComponent),
834
- canRender && !ListEmptyComponent && /* @__PURE__ */ React2__namespace.createElement(
795
+ canRender && !ListEmptyComponent && /* @__PURE__ */ React3__namespace.createElement(
835
796
  Containers,
836
797
  {
837
798
  getRenderedItem: getRenderedItem2,
@@ -842,22 +803,22 @@ var ListComponent = typedMemo(function ListComponent2({
842
803
  waitForInitialLayout
843
804
  }
844
805
  ),
845
- ListFooterComponent && /* @__PURE__ */ React2__namespace.createElement(
846
- reactNative.View,
806
+ ListFooterComponent && /* @__PURE__ */ React3__namespace.createElement(
807
+ LayoutView,
847
808
  {
848
- onLayout: (event) => {
849
- const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
809
+ onLayoutChange: (layout) => {
810
+ const size = layout[horizontal ? "width" : "height"];
850
811
  set$(ctx, "footerSize", size);
851
812
  },
852
813
  style: ListFooterComponentStyle
853
814
  },
854
815
  getComponent(ListFooterComponent)
855
816
  ),
856
- __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React2__namespace.createElement(DevNumbers, null)
817
+ __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React3__namespace.createElement(DevNumbers, null)
857
818
  );
858
819
  });
859
- var DevNumbers = __DEV__ && React2__namespace.memo(function DevNumbers2() {
860
- return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React2__namespace.createElement(
820
+ var DevNumbers = __DEV__ && React3__namespace.memo(function DevNumbers2() {
821
+ return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3__namespace.createElement(
861
822
  reactNative.View,
862
823
  {
863
824
  key: index,
@@ -869,7 +830,7 @@ var DevNumbers = __DEV__ && React2__namespace.memo(function DevNumbers2() {
869
830
  width: "100%"
870
831
  }
871
832
  },
872
- /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, { style: { color: "red" } }, index * 100)
833
+ /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, { style: { color: "red" } }, index * 100)
873
834
  ));
874
835
  });
875
836
 
@@ -881,7 +842,7 @@ function getId(state, index) {
881
842
  }
882
843
  const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
883
844
  const id = ret;
884
- state.idCache.set(index, id);
845
+ state.idCache[index] = id;
885
846
  return id;
886
847
  }
887
848
 
@@ -967,7 +928,7 @@ var finishScrollTo = (state) => {
967
928
  // src/core/scrollTo.ts
968
929
  function scrollTo(state, params = {}) {
969
930
  var _a;
970
- const { animated, noScrollingTo } = params;
931
+ const { animated, noScrollingTo, isInitialScroll } = params;
971
932
  const {
972
933
  refScroller,
973
934
  props: { horizontal }
@@ -978,14 +939,21 @@ function scrollTo(state, params = {}) {
978
939
  state.scrollingTo = params;
979
940
  }
980
941
  state.scrollPending = offset;
981
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
982
- animated: !!animated,
983
- x: horizontal ? offset : 0,
984
- y: horizontal ? 0 : offset
985
- });
942
+ if (!params.isInitialScroll || reactNative.Platform.OS === "android") {
943
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
944
+ animated: !!animated,
945
+ x: horizontal ? offset : 0,
946
+ y: horizontal ? 0 : offset
947
+ });
948
+ }
986
949
  if (!animated) {
987
950
  state.scroll = offset;
988
951
  setTimeout(() => finishScrollTo(state), 100);
952
+ if (isInitialScroll) {
953
+ setTimeout(() => {
954
+ state.initialScroll = void 0;
955
+ }, 500);
956
+ }
989
957
  }
990
958
  }
991
959
 
@@ -1080,7 +1048,16 @@ function prepareMVCP(ctx, state, dataChanged) {
1080
1048
  if (targetId !== void 0 && prevPosition !== void 0) {
1081
1049
  const newPosition = positions.get(targetId);
1082
1050
  if (newPosition !== void 0) {
1083
- positionDiff = newPosition - prevPosition;
1051
+ const totalSize = peek$(ctx, "totalSize");
1052
+ let diff = newPosition - prevPosition;
1053
+ if (state.scroll + state.scrollLength > totalSize) {
1054
+ if (diff > 0) {
1055
+ diff = Math.max(0, totalSize - state.scroll - state.scrollLength);
1056
+ } else {
1057
+ diff = 0;
1058
+ }
1059
+ }
1060
+ positionDiff = diff;
1084
1061
  }
1085
1062
  }
1086
1063
  if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
@@ -1089,6 +1066,68 @@ function prepareMVCP(ctx, state, dataChanged) {
1089
1066
  };
1090
1067
  }
1091
1068
 
1069
+ // src/core/prepareColumnStartState.ts
1070
+ function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1071
+ var _a;
1072
+ const numColumns = peek$(ctx, "numColumns");
1073
+ let rowStartIndex = startIndex;
1074
+ const columnAtStart = state.columns.get(state.idCache[startIndex]);
1075
+ if (columnAtStart !== 1) {
1076
+ rowStartIndex = findRowStartIndex(state, numColumns, startIndex);
1077
+ }
1078
+ let currentRowTop = 0;
1079
+ const curId = state.idCache[rowStartIndex];
1080
+ const column = state.columns.get(curId);
1081
+ if (rowStartIndex > 0) {
1082
+ const prevIndex = rowStartIndex - 1;
1083
+ const prevId = state.idCache[prevIndex];
1084
+ const prevPosition = (_a = state.positions.get(prevId)) != null ? _a : 0;
1085
+ const prevRowStart = findRowStartIndex(state, numColumns, prevIndex);
1086
+ const prevRowHeight = calculateRowMaxSize(state, prevRowStart, prevIndex, useAverageSize);
1087
+ currentRowTop = prevPosition + prevRowHeight;
1088
+ }
1089
+ return {
1090
+ column,
1091
+ currentRowTop,
1092
+ startIndex: rowStartIndex
1093
+ };
1094
+ }
1095
+ function findRowStartIndex(state, numColumns, index) {
1096
+ if (numColumns <= 1) {
1097
+ return Math.max(0, index);
1098
+ }
1099
+ let rowStart = Math.max(0, index);
1100
+ while (rowStart > 0) {
1101
+ const columnForIndex = state.columns.get(state.idCache[rowStart]);
1102
+ if (columnForIndex === 1) {
1103
+ break;
1104
+ }
1105
+ rowStart--;
1106
+ }
1107
+ return rowStart;
1108
+ }
1109
+ function calculateRowMaxSize(state, startIndex, endIndex, useAverageSize) {
1110
+ if (endIndex < startIndex) {
1111
+ return 0;
1112
+ }
1113
+ const { data } = state.props;
1114
+ if (!data) {
1115
+ return 0;
1116
+ }
1117
+ let maxSize = 0;
1118
+ for (let i = startIndex; i <= endIndex; i++) {
1119
+ if (i < 0 || i >= data.length) {
1120
+ continue;
1121
+ }
1122
+ const id = state.idCache[i];
1123
+ const size = getItemSize(state, id, i, data[i], useAverageSize);
1124
+ if (size > maxSize) {
1125
+ maxSize = size;
1126
+ }
1127
+ }
1128
+ return maxSize;
1129
+ }
1130
+
1092
1131
  // src/utils/setPaddingTop.ts
1093
1132
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1094
1133
  if (stylePaddingTop !== void 0) {
@@ -1148,6 +1187,7 @@ function updateTotalSize(ctx, state) {
1148
1187
  }
1149
1188
  function addTotalSize(ctx, state, key, add) {
1150
1189
  const { alignItemsAtEnd } = state.props;
1190
+ const prevTotalSize = state.totalSize;
1151
1191
  if (key === null) {
1152
1192
  state.totalSize = add;
1153
1193
  if (state.timeoutSetPaddingTop) {
@@ -1157,9 +1197,11 @@ function addTotalSize(ctx, state, key, add) {
1157
1197
  } else {
1158
1198
  state.totalSize += add;
1159
1199
  }
1160
- set$(ctx, "totalSize", state.totalSize);
1161
- if (alignItemsAtEnd) {
1162
- updateAlignItemsPaddingTop(ctx, state);
1200
+ if (prevTotalSize !== state.totalSize) {
1201
+ set$(ctx, "totalSize", state.totalSize);
1202
+ if (alignItemsAtEnd) {
1203
+ updateAlignItemsPaddingTop(ctx, state);
1204
+ }
1163
1205
  }
1164
1206
  }
1165
1207
 
@@ -1180,7 +1222,7 @@ function updateSnapToOffsets(ctx, state) {
1180
1222
 
1181
1223
  // src/core/updateItemPositions.ts
1182
1224
  function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottomBuffered } = { scrollBottomBuffered: -1, startIndex: 0 }) {
1183
- var _a, _b, _c, _d, _e, _f;
1225
+ var _a, _b, _c, _d;
1184
1226
  const {
1185
1227
  columns,
1186
1228
  indexByKey,
@@ -1190,41 +1232,47 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1190
1232
  props: { getEstimatedItemSize, snapToIndices, enableAverages }
1191
1233
  } = state;
1192
1234
  const data = state.props.data;
1235
+ const dataLength = data.length;
1193
1236
  const numColumns = peek$(ctx, "numColumns");
1237
+ const hasColumns = numColumns > 1;
1194
1238
  const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1195
1239
  const maxVisibleArea = scrollBottomBuffered + 1e3;
1196
1240
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1197
1241
  let currentRowTop = 0;
1198
1242
  let column = 1;
1199
1243
  let maxSizeInRow = 0;
1200
- const hasColumns = numColumns > 1;
1201
1244
  if (startIndex > 0) {
1202
- const prevIndex = startIndex - 1;
1203
- const prevId = (_a = idCache.get(prevIndex)) != null ? _a : getId(state, prevIndex);
1204
- const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1205
1245
  if (hasColumns) {
1206
- const prevColumn = (_c = columns.get(prevId)) != null ? _c : 1;
1207
- currentRowTop = prevPosition;
1208
- column = prevColumn % numColumns + 1;
1209
- } else {
1210
- const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(state, prevId, prevIndex, data[prevIndex], useAverageSize);
1246
+ const { startIndex: processedStartIndex, currentRowTop: initialRowTop } = prepareColumnStartState(
1247
+ ctx,
1248
+ state,
1249
+ startIndex,
1250
+ useAverageSize
1251
+ );
1252
+ startIndex = processedStartIndex;
1253
+ currentRowTop = initialRowTop;
1254
+ } else if (startIndex < dataLength) {
1255
+ const prevIndex = startIndex - 1;
1256
+ const prevId = getId(state, prevIndex);
1257
+ const prevPosition = (_a = positions.get(prevId)) != null ? _a : 0;
1258
+ const prevSize = (_b = sizesKnown.get(prevId)) != null ? _b : getItemSize(state, prevId, prevIndex, data[prevIndex], useAverageSize);
1211
1259
  currentRowTop = prevPosition + prevSize;
1212
1260
  }
1213
1261
  }
1214
1262
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1215
1263
  let didBreakEarly = false;
1216
1264
  let breakAt;
1217
- const dataLength = data.length;
1218
1265
  for (let i = startIndex; i < dataLength; i++) {
1219
1266
  if (breakAt && i > breakAt) {
1220
1267
  didBreakEarly = true;
1221
1268
  break;
1222
1269
  }
1223
- if (!dataChanged && currentRowTop > maxVisibleArea) {
1224
- breakAt = i + 10;
1270
+ if (breakAt === void 0 && !dataChanged && currentRowTop > maxVisibleArea) {
1271
+ const itemsPerRow = hasColumns ? numColumns : 1;
1272
+ breakAt = i + itemsPerRow + 10;
1225
1273
  }
1226
- const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1227
- const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(state, id, i, data[i], useAverageSize);
1274
+ const id = (_c = idCache[i]) != null ? _c : getId(state, i);
1275
+ const size = (_d = sizesKnown.get(id)) != null ? _d : getItemSize(state, id, i, data[i], useAverageSize);
1228
1276
  if (__DEV__ && needsIndexByKey) {
1229
1277
  if (indexByKeyForChecking.has(id)) {
1230
1278
  console.error(
@@ -1461,9 +1509,12 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1461
1509
  var batchedUpdates = reactNative.unstable_batchedUpdates || ((callback) => callback());
1462
1510
 
1463
1511
  // src/utils/checkAllSizesKnown.ts
1512
+ function isNullOrUndefined2(value) {
1513
+ return value === null || value === void 0;
1514
+ }
1464
1515
  function checkAllSizesKnown(state) {
1465
1516
  const { startBuffered, endBuffered, sizesKnown } = state;
1466
- if (endBuffered !== null) {
1517
+ if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
1467
1518
  let areAllKnown = true;
1468
1519
  for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1469
1520
  const key = getId(state, i);
@@ -1480,6 +1531,8 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1480
1531
  const { stickyContainerPool, containerItemTypes } = state;
1481
1532
  const result = [];
1482
1533
  const availableContainers = [];
1534
+ const pendingRemovalSet = new Set(pendingRemoval);
1535
+ let pendingRemovalChanged = false;
1483
1536
  const stickyIndicesSet = state.props.stickyIndicesSet;
1484
1537
  const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
1485
1538
  const canReuseContainer = (containerIndex, requiredType) => {
@@ -1495,12 +1548,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1495
1548
  let foundContainer = false;
1496
1549
  for (const containerIndex of stickyContainerPool) {
1497
1550
  const key = peek$(ctx, `containerItemKey${containerIndex}`);
1498
- const isPendingRemoval = pendingRemoval.includes(containerIndex);
1551
+ const isPendingRemoval = pendingRemovalSet.has(containerIndex);
1499
1552
  if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType)) {
1500
1553
  result.push(containerIndex);
1501
- if (isPendingRemoval) {
1502
- const index = pendingRemoval.indexOf(containerIndex);
1503
- pendingRemoval.splice(index, 1);
1554
+ if (isPendingRemoval && pendingRemovalSet.delete(containerIndex)) {
1555
+ pendingRemovalChanged = true;
1504
1556
  }
1505
1557
  foundContainer = true;
1506
1558
  if (requiredItemTypes) typeIndex++;
@@ -1520,13 +1572,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1520
1572
  }
1521
1573
  const key = peek$(ctx, `containerItemKey${u}`);
1522
1574
  let isOk = key === void 0;
1523
- if (!isOk) {
1524
- const index = pendingRemoval.indexOf(u);
1525
- if (index !== -1) {
1526
- pendingRemoval.splice(index, 1);
1527
- const requiredType = neededTypes[typeIndex];
1528
- isOk = canReuseContainer(u, requiredType);
1529
- }
1575
+ if (!isOk && pendingRemovalSet.has(u)) {
1576
+ pendingRemovalSet.delete(u);
1577
+ pendingRemovalChanged = true;
1578
+ const requiredType = neededTypes[typeIndex];
1579
+ isOk = canReuseContainer(u, requiredType);
1530
1580
  }
1531
1581
  if (isOk) {
1532
1582
  result.push(u);
@@ -1584,6 +1634,12 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1584
1634
  }
1585
1635
  }
1586
1636
  }
1637
+ if (pendingRemovalChanged) {
1638
+ pendingRemoval.length = 0;
1639
+ for (const value of pendingRemovalSet) {
1640
+ pendingRemoval.push(value);
1641
+ }
1642
+ }
1587
1643
  return result.sort(comparatorDefault);
1588
1644
  }
1589
1645
  function comparatorByDistance(a, b) {
@@ -1721,17 +1777,16 @@ function setDidLayout(ctx, state) {
1721
1777
  onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1722
1778
  }
1723
1779
  };
1724
- if (reactNative.Platform.OS === "android" || !IsNewArchitecture) {
1725
- if (initialScroll) {
1726
- queueMicrotask(() => {
1780
+ if (reactNative.Platform.OS === "android" && initialScroll) {
1781
+ if (IsNewArchitecture) {
1782
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1783
+ requestAnimationFrame(() => {
1727
1784
  scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1728
- requestAnimationFrame(() => {
1729
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1730
- setIt();
1731
- });
1785
+ setIt();
1732
1786
  });
1733
1787
  } else {
1734
- queueMicrotask(setIt);
1788
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1789
+ setIt();
1735
1790
  }
1736
1791
  } else {
1737
1792
  setIt();
@@ -1744,7 +1799,8 @@ function findCurrentStickyIndex(stickyArray, scroll, state) {
1744
1799
  const idCache = state.idCache;
1745
1800
  const positions = state.positions;
1746
1801
  for (let i = stickyArray.length - 1; i >= 0; i--) {
1747
- const stickyId = (_a = idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
1802
+ const stickyIndex = stickyArray[i];
1803
+ const stickyId = (_a = idCache[stickyIndex]) != null ? _a : getId(state, stickyIndex);
1748
1804
  const stickyPos = stickyId ? positions.get(stickyId) : void 0;
1749
1805
  if (stickyPos !== void 0 && scroll >= stickyPos) {
1750
1806
  return i;
@@ -1757,40 +1813,43 @@ function getActiveStickyIndices(ctx, state, stickyIndices) {
1757
1813
  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))
1758
1814
  );
1759
1815
  }
1760
- function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll, needNewContainers, startBuffered, endBuffered) {
1816
+ function handleStickyActivation(ctx, state, stickyIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
1761
1817
  var _a;
1762
1818
  const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
1763
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1764
1819
  state.activeStickyIndex = currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : void 0;
1765
1820
  for (let offset = 0; offset <= 1; offset++) {
1766
1821
  const idx = currentStickyIdx - offset;
1767
1822
  if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
1768
1823
  const stickyIndex = stickyArray[idx];
1769
- const stickyId = (_a = state.idCache.get(stickyIndex)) != null ? _a : getId(state, stickyIndex);
1824
+ const stickyId = (_a = state.idCache[stickyIndex]) != null ? _a : getId(state, stickyIndex);
1770
1825
  if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered)) {
1771
1826
  needNewContainers.push(stickyIndex);
1772
1827
  }
1773
1828
  }
1774
1829
  }
1775
- function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pendingRemoval) {
1830
+ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
1776
1831
  var _a, _b, _c;
1777
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1778
1832
  for (const containerIndex of state.stickyContainerPool) {
1779
1833
  const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
1780
1834
  const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
1781
1835
  if (itemIndex === void 0) continue;
1782
1836
  const arrayIdx = stickyArray.indexOf(itemIndex);
1783
- if (arrayIdx === -1) continue;
1837
+ if (arrayIdx === -1) {
1838
+ state.stickyContainerPool.delete(containerIndex);
1839
+ set$(ctx, `containerSticky${containerIndex}`, false);
1840
+ set$(ctx, `containerStickyOffset${containerIndex}`, void 0);
1841
+ continue;
1842
+ }
1784
1843
  const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
1785
1844
  if (isRecentSticky) continue;
1786
1845
  const nextIndex = stickyArray[arrayIdx + 1];
1787
1846
  let shouldRecycle = false;
1788
1847
  if (nextIndex) {
1789
- const nextId = (_a = state.idCache.get(nextIndex)) != null ? _a : getId(state, nextIndex);
1848
+ const nextId = (_a = state.idCache[nextIndex]) != null ? _a : getId(state, nextIndex);
1790
1849
  const nextPos = nextId ? state.positions.get(nextId) : void 0;
1791
1850
  shouldRecycle = nextPos !== void 0 && scroll > nextPos + scrollBuffer * 2;
1792
1851
  } else {
1793
- const currentId = (_b = state.idCache.get(itemIndex)) != null ? _b : getId(state, itemIndex);
1852
+ const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
1794
1853
  if (currentId) {
1795
1854
  const currentPos = state.positions.get(currentId);
1796
1855
  const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
@@ -1818,7 +1877,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1818
1877
  sizes,
1819
1878
  startBufferedId: startBufferedIdOrig,
1820
1879
  viewabilityConfigCallbackPairs,
1821
- props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, scrollBuffer }
1880
+ props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, onStickyHeaderChange, scrollBuffer }
1822
1881
  } = state;
1823
1882
  const { data } = state.props;
1824
1883
  const stickyIndicesArr = state.props.stickyIndicesArr || [];
@@ -1853,6 +1912,10 @@ function calculateItemsInView(ctx, state, params = {}) {
1853
1912
  set$(ctx, "debugRawScroll", scrollState);
1854
1913
  set$(ctx, "debugComputedScroll", scroll);
1855
1914
  }
1915
+ const previousStickyIndex = state.activeStickyIndex;
1916
+ const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
1917
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : void 0;
1918
+ state.activeStickyIndex = nextActiveStickyIndex;
1856
1919
  let scrollBufferTop = scrollBuffer;
1857
1920
  let scrollBufferBottom = scrollBuffer;
1858
1921
  if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
@@ -1874,7 +1937,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1874
1937
  const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
1875
1938
  if (dataChanged) {
1876
1939
  indexByKey.clear();
1877
- idCache.clear();
1940
+ idCache.length = 0;
1878
1941
  positions.clear();
1879
1942
  }
1880
1943
  const startIndex = dataChanged ? 0 : (_a = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _a : 0;
@@ -1890,7 +1953,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1890
1953
  let endBuffered = null;
1891
1954
  let loopStart = !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1892
1955
  for (let i = loopStart; i >= 0; i--) {
1893
- const id = (_b = idCache.get(i)) != null ? _b : getId(state, i);
1956
+ const id = (_b = idCache[i]) != null ? _b : getId(state, i);
1894
1957
  const top = positions.get(id);
1895
1958
  const size = (_c = sizes.get(id)) != null ? _c : getItemSize(state, id, i, data[i]);
1896
1959
  const bottom = top + size;
@@ -1918,7 +1981,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1918
1981
  let firstFullyOnScreenIndex;
1919
1982
  const dataLength = data.length;
1920
1983
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
1921
- const id = (_d = idCache.get(i)) != null ? _d : getId(state, i);
1984
+ const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1922
1985
  const size = (_e = sizes.get(id)) != null ? _e : getItemSize(state, id, i, data[i]);
1923
1986
  const top = positions.get(id);
1924
1987
  if (!foundEnd) {
@@ -1948,7 +2011,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1948
2011
  }
1949
2012
  const idsInView = [];
1950
2013
  for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
1951
- const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
2014
+ const id = (_f = idCache[i]) != null ? _f : getId(state, i);
1952
2015
  idsInView.push(id);
1953
2016
  }
1954
2017
  Object.assign(state, {
@@ -1980,7 +2043,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1980
2043
  let numContainers2 = prevNumContainers;
1981
2044
  const needNewContainers = [];
1982
2045
  for (let i = startBuffered; i <= endBuffered; i++) {
1983
- const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
2046
+ const id = (_g = idCache[i]) != null ? _g : getId(state, i);
1984
2047
  if (!containerItemKeys.has(id)) {
1985
2048
  needNewContainers.push(i);
1986
2049
  }
@@ -1991,7 +2054,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1991
2054
  state,
1992
2055
  stickyIndicesSet,
1993
2056
  stickyIndicesArr,
1994
- scroll,
2057
+ currentStickyIdx,
1995
2058
  needNewContainers,
1996
2059
  startBuffered,
1997
2060
  endBuffered
@@ -2017,7 +2080,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2017
2080
  for (let idx = 0; idx < needNewContainers.length; idx++) {
2018
2081
  const i = needNewContainers[idx];
2019
2082
  const containerIndex = availableContainers[idx];
2020
- const id = (_h = idCache.get(i)) != null ? _h : getId(state, i);
2083
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
2021
2084
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
2022
2085
  if (oldKey && oldKey !== id) {
2023
2086
  containerItemKeys.delete(oldKey);
@@ -2031,7 +2094,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2031
2094
  if (stickyIndicesSet.has(i)) {
2032
2095
  set$(ctx, `containerSticky${containerIndex}`, true);
2033
2096
  const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2034
- set$(ctx, `containerStickyOffset${containerIndex}`, new reactNative.Animated.Value(topPadding));
2097
+ set$(ctx, `containerStickyOffset${containerIndex}`, topPadding);
2035
2098
  state.stickyContainerPool.add(containerIndex);
2036
2099
  } else {
2037
2100
  set$(ctx, `containerSticky${containerIndex}`, false);
@@ -2050,7 +2113,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2050
2113
  }
2051
2114
  }
2052
2115
  if (stickyIndicesArr.length > 0) {
2053
- handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, pendingRemoval);
2116
+ handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2054
2117
  }
2055
2118
  for (let i = 0; i < numContainers; i++) {
2056
2119
  const itemKey = peek$(ctx, `containerItemKey${i}`);
@@ -2072,7 +2135,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2072
2135
  const itemIndex = indexByKey.get(itemKey);
2073
2136
  const item = data[itemIndex];
2074
2137
  if (item !== void 0) {
2075
- const id = (_i = idCache.get(itemIndex)) != null ? _i : getId(state, itemIndex);
2138
+ const id = (_i = idCache[itemIndex]) != null ? _i : getId(state, itemIndex);
2076
2139
  const position = positions.get(id);
2077
2140
  if (position === void 0) {
2078
2141
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
@@ -2102,6 +2165,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2102
2165
  if (viewabilityConfigCallbackPairs) {
2103
2166
  updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
2104
2167
  }
2168
+ if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
2169
+ const item = data[nextActiveStickyIndex];
2170
+ if (item !== void 0) {
2171
+ onStickyHeaderChange({ index: nextActiveStickyIndex, item });
2172
+ }
2173
+ }
2105
2174
  });
2106
2175
  }
2107
2176
 
@@ -2260,7 +2329,9 @@ function doInitialAllocateContainers(ctx, state) {
2260
2329
  let totalSize = 0;
2261
2330
  const num = Math.min(20, data.length);
2262
2331
  for (let i = 0; i < num; i++) {
2263
- totalSize += fn(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "");
2332
+ const item = data[i];
2333
+ const itemType = getItemType ? (_a = getItemType(item, i)) != null ? _a : "" : "";
2334
+ totalSize += fn(i, item, itemType);
2264
2335
  }
2265
2336
  averageItemSize = totalSize / num;
2266
2337
  } else {
@@ -2289,7 +2360,9 @@ function doInitialAllocateContainers(ctx, state) {
2289
2360
  // src/core/handleLayout.ts
2290
2361
  function handleLayout(ctx, state, layout, setCanRender) {
2291
2362
  const { maintainScrollAtEnd } = state.props;
2292
- const scrollLength = layout[state.props.horizontal ? "width" : "height"];
2363
+ const measuredLength = layout[state.props.horizontal ? "width" : "height"];
2364
+ const previousLength = state.scrollLength;
2365
+ const scrollLength = measuredLength > 0 ? measuredLength : previousLength;
2293
2366
  const otherAxisSize = layout[state.props.horizontal ? "height" : "width"];
2294
2367
  const needsCalculate = !state.lastLayout || scrollLength > state.scrollLength || state.lastLayout.x !== layout.x || state.lastLayout.y !== layout.y;
2295
2368
  state.lastLayout = layout;
@@ -2300,7 +2373,9 @@ function handleLayout(ctx, state, layout, setCanRender) {
2300
2373
  state.otherAxisSize = otherAxisSize;
2301
2374
  state.lastBatchingAction = Date.now();
2302
2375
  state.scrollForNextCalculateItemsInView = void 0;
2303
- doInitialAllocateContainers(ctx, state);
2376
+ if (scrollLength > 0) {
2377
+ doInitialAllocateContainers(ctx, state);
2378
+ }
2304
2379
  if (needsCalculate) {
2305
2380
  calculateItemsInView(ctx, state, { doMVCP: true });
2306
2381
  }
@@ -2316,14 +2391,14 @@ function handleLayout(ctx, state, layout, setCanRender) {
2316
2391
  if (state) {
2317
2392
  state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2318
2393
  }
2319
- if (__DEV__ && scrollLength === 0) {
2394
+ if (__DEV__ && measuredLength === 0) {
2320
2395
  warnDevOnce(
2321
2396
  "height0",
2322
2397
  `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.`
2323
2398
  );
2324
2399
  }
2325
- setCanRender(true);
2326
2400
  }
2401
+ setCanRender(true);
2327
2402
  }
2328
2403
 
2329
2404
  // src/core/onScroll.ts
@@ -2383,7 +2458,7 @@ var ScrollAdjustHandler = class {
2383
2458
  this.context = ctx;
2384
2459
  }
2385
2460
  requestAdjust(add) {
2386
- const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
2461
+ const oldAdjustTop = this.appliedAdjust;
2387
2462
  this.appliedAdjust = add + oldAdjustTop;
2388
2463
  const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
2389
2464
  if (this.mounted) {
@@ -2402,7 +2477,7 @@ var ScrollAdjustHandler = class {
2402
2477
 
2403
2478
  // src/core/updateItemSize.ts
2404
2479
  function updateItemSize(ctx, state, itemKey, sizeObj) {
2405
- var _a, _b;
2480
+ var _a;
2406
2481
  const {
2407
2482
  sizesKnown,
2408
2483
  props: {
@@ -2417,17 +2492,17 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2417
2492
  }
2418
2493
  } = state;
2419
2494
  if (!data) return;
2495
+ const index = state.indexByKey.get(itemKey);
2420
2496
  if (getFixedItemSize) {
2421
- const index2 = state.indexByKey.get(itemKey);
2422
- if (index2 === void 0) {
2497
+ if (index === void 0) {
2423
2498
  return;
2424
2499
  }
2425
- const itemData = state.props.data[index2];
2500
+ const itemData = state.props.data[index];
2426
2501
  if (itemData === void 0) {
2427
2502
  return;
2428
2503
  }
2429
- const type = getItemType ? (_a = getItemType(itemData, index2)) != null ? _a : "" : "";
2430
- const size2 = getFixedItemSize(index2, itemData, type);
2504
+ const type = getItemType ? (_a = getItemType(itemData, index)) != null ? _a : "" : "";
2505
+ const size2 = getFixedItemSize(index, itemData, type);
2431
2506
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
2432
2507
  return;
2433
2508
  }
@@ -2437,15 +2512,11 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2437
2512
  let shouldMaintainScrollAtEnd = false;
2438
2513
  let minIndexSizeChanged;
2439
2514
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2440
- const index = state.indexByKey.get(itemKey);
2441
2515
  const prevSizeKnown = state.sizesKnown.get(itemKey);
2442
2516
  const diff = updateOneItemSize(state, itemKey, sizeObj);
2443
2517
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2444
2518
  if (diff !== 0) {
2445
2519
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
2446
- if (((_b = state.scrollingTo) == null ? void 0 : _b.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
2447
- requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
2448
- }
2449
2520
  const { startBuffered, endBuffered } = state;
2450
2521
  needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2451
2522
  if (!needsRecalculate) {
@@ -2534,7 +2605,7 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2534
2605
  return 0;
2535
2606
  }
2536
2607
  var useCombinedRef = (...refs) => {
2537
- const callback = React2.useCallback((element) => {
2608
+ const callback = React3.useCallback((element) => {
2538
2609
  for (const ref of refs) {
2539
2610
  if (!ref) {
2540
2611
  continue;
@@ -2577,18 +2648,59 @@ function getRenderedItem(ctx, state, key) {
2577
2648
  return null;
2578
2649
  }
2579
2650
  let renderedItem = null;
2580
- if (renderItem && data[index]) {
2651
+ const extraData = peek$(ctx, "extraData");
2652
+ const item = data[index];
2653
+ if (renderItem && !isNullOrUndefined(item)) {
2581
2654
  const itemProps = {
2582
2655
  data,
2583
- extraData: peek$(ctx, "extraData"),
2656
+ extraData,
2584
2657
  index,
2585
- item: data[index],
2586
- type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
2658
+ item,
2659
+ type: getItemType ? (_a = getItemType(item, index)) != null ? _a : "" : ""
2587
2660
  };
2588
- renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React2__namespace.default.createElement(renderItem, itemProps);
2661
+ renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React3__namespace.default.createElement(renderItem, itemProps);
2589
2662
  }
2590
2663
  return { index, item: data[index], renderedItem };
2591
2664
  }
2665
+ function useThrottleDebounce(mode) {
2666
+ const timeoutRef = React3.useRef(null);
2667
+ const lastCallTimeRef = React3.useRef(0);
2668
+ const lastArgsRef = React3.useRef(null);
2669
+ const clearTimeoutRef = () => {
2670
+ if (timeoutRef.current) {
2671
+ clearTimeout(timeoutRef.current);
2672
+ timeoutRef.current = null;
2673
+ }
2674
+ };
2675
+ const execute = React3.useCallback(
2676
+ (callback, delay, ...args) => {
2677
+ {
2678
+ const now = Date.now();
2679
+ lastArgsRef.current = args;
2680
+ if (now - lastCallTimeRef.current >= delay) {
2681
+ lastCallTimeRef.current = now;
2682
+ callback(...args);
2683
+ clearTimeoutRef();
2684
+ } else {
2685
+ clearTimeoutRef();
2686
+ timeoutRef.current = setTimeout(
2687
+ () => {
2688
+ if (lastArgsRef.current) {
2689
+ lastCallTimeRef.current = Date.now();
2690
+ callback(...lastArgsRef.current);
2691
+ timeoutRef.current = null;
2692
+ lastArgsRef.current = null;
2693
+ }
2694
+ },
2695
+ delay - (now - lastCallTimeRef.current)
2696
+ );
2697
+ }
2698
+ }
2699
+ },
2700
+ [mode]
2701
+ );
2702
+ return execute;
2703
+ }
2592
2704
 
2593
2705
  // src/utils/throttledOnScroll.ts
2594
2706
  function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
@@ -2605,14 +2717,14 @@ var LegendList = typedMemo(
2605
2717
  const isChildrenMode = children !== void 0 && dataProp === void 0;
2606
2718
  const processedProps = isChildrenMode ? {
2607
2719
  ...restProps,
2608
- data: (isArray(children) ? children : React2__namespace.Children.toArray(children)).flat(1),
2720
+ data: (isArray(children) ? children : React3__namespace.Children.toArray(children)).flat(1),
2609
2721
  renderItem: ({ item }) => item
2610
2722
  } : {
2611
2723
  ...restProps,
2612
2724
  data: dataProp || [],
2613
2725
  renderItem: renderItemProp
2614
2726
  };
2615
- return /* @__PURE__ */ React2__namespace.createElement(StateProvider, null, /* @__PURE__ */ React2__namespace.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
2727
+ return /* @__PURE__ */ React3__namespace.createElement(StateProvider, null, /* @__PURE__ */ React3__namespace.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
2616
2728
  })
2617
2729
  );
2618
2730
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
@@ -2652,6 +2764,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2652
2764
  onScroll: onScrollProp,
2653
2765
  onStartReached,
2654
2766
  onStartReachedThreshold = 0.5,
2767
+ onStickyHeaderChange,
2655
2768
  onViewableItemsChanged,
2656
2769
  progressViewOffset,
2657
2770
  recycleItems = false,
@@ -2669,76 +2782,79 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2669
2782
  waitForInitialLayout = true,
2670
2783
  ...rest
2671
2784
  } = props;
2672
- const [renderNum, setRenderNum] = React2.useState(0);
2785
+ const [renderNum, setRenderNum] = React3.useState(0);
2673
2786
  const initialScroll = initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
2674
- const [canRender, setCanRender] = React2__namespace.useState(!IsNewArchitecture);
2787
+ const [canRender, setCanRender] = React3__namespace.useState(!IsNewArchitecture);
2675
2788
  const contentContainerStyle = { ...reactNative.StyleSheet.flatten(contentContainerStyleProp) };
2676
2789
  const style = { ...reactNative.StyleSheet.flatten(styleProp) };
2677
2790
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
2678
2791
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
2679
2792
  const ctx = useStateContext();
2680
2793
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
2681
- const refScroller = React2.useRef(null);
2794
+ const refScroller = React3.useRef(null);
2682
2795
  const combinedRef = useCombinedRef(refScroller, refScrollView);
2683
2796
  const estimatedItemSize = estimatedItemSizeProp != null ? estimatedItemSizeProp : DEFAULT_ITEM_SIZE;
2684
2797
  const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
2685
2798
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
2686
- const refState = React2.useRef();
2799
+ const refState = React3.useRef();
2687
2800
  if (!refState.current) {
2688
- const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : reactNative.Dimensions.get("window"))[horizontal ? "width" : "height"];
2689
- refState.current = {
2690
- activeStickyIndex: void 0,
2691
- averageSizes: {},
2692
- columns: /* @__PURE__ */ new Map(),
2693
- containerItemKeys: /* @__PURE__ */ new Set(),
2694
- containerItemTypes: /* @__PURE__ */ new Map(),
2695
- dataChangeNeedsScrollUpdate: false,
2696
- enableScrollForNextCalculateItemsInView: true,
2697
- endBuffered: -1,
2698
- endNoBuffer: -1,
2699
- endReachedBlockedByTimer: false,
2700
- firstFullyOnScreenIndex: -1,
2701
- idCache: /* @__PURE__ */ new Map(),
2702
- idsInView: [],
2703
- indexByKey: /* @__PURE__ */ new Map(),
2704
- initialScroll,
2705
- isAtEnd: false,
2706
- isAtStart: false,
2707
- isEndReached: false,
2708
- isStartReached: false,
2709
- lastBatchingAction: Date.now(),
2710
- lastLayout: void 0,
2711
- loadStartTime: Date.now(),
2712
- minIndexSizeChanged: 0,
2713
- nativeMarginTop: 0,
2714
- positions: /* @__PURE__ */ new Map(),
2715
- props: {},
2716
- queuedCalculateItemsInView: 0,
2717
- refScroller: void 0,
2718
- scroll: 0,
2719
- scrollAdjustHandler: new ScrollAdjustHandler(ctx),
2720
- scrollForNextCalculateItemsInView: void 0,
2721
- scrollHistory: [],
2722
- scrollLength: initialScrollLength,
2723
- scrollPending: 0,
2724
- scrollPrev: 0,
2725
- scrollPrevTime: 0,
2726
- scrollProcessingEnabled: true,
2727
- scrollTime: 0,
2728
- sizes: /* @__PURE__ */ new Map(),
2729
- sizesKnown: /* @__PURE__ */ new Map(),
2730
- startBuffered: -1,
2731
- startNoBuffer: -1,
2732
- startReachedBlockedByTimer: false,
2733
- stickyContainerPool: /* @__PURE__ */ new Set(),
2734
- stickyContainers: /* @__PURE__ */ new Map(),
2735
- timeoutSizeMessage: 0,
2736
- timeouts: /* @__PURE__ */ new Set(),
2737
- totalSize: 0,
2738
- viewabilityConfigCallbackPairs: void 0
2739
- };
2740
- set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2741
- set$(ctx, "extraData", extraData);
2801
+ if (!ctx.internalState) {
2802
+ const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : reactNative.Dimensions.get("window"))[horizontal ? "width" : "height"];
2803
+ ctx.internalState = {
2804
+ activeStickyIndex: void 0,
2805
+ averageSizes: {},
2806
+ columns: /* @__PURE__ */ new Map(),
2807
+ containerItemKeys: /* @__PURE__ */ new Set(),
2808
+ containerItemTypes: /* @__PURE__ */ new Map(),
2809
+ dataChangeNeedsScrollUpdate: false,
2810
+ enableScrollForNextCalculateItemsInView: true,
2811
+ endBuffered: -1,
2812
+ endNoBuffer: -1,
2813
+ endReachedBlockedByTimer: false,
2814
+ firstFullyOnScreenIndex: -1,
2815
+ idCache: [],
2816
+ idsInView: [],
2817
+ indexByKey: /* @__PURE__ */ new Map(),
2818
+ initialScroll,
2819
+ isAtEnd: false,
2820
+ isAtStart: false,
2821
+ isEndReached: false,
2822
+ isStartReached: false,
2823
+ lastBatchingAction: Date.now(),
2824
+ lastLayout: void 0,
2825
+ loadStartTime: Date.now(),
2826
+ minIndexSizeChanged: 0,
2827
+ nativeMarginTop: 0,
2828
+ positions: /* @__PURE__ */ new Map(),
2829
+ props: {},
2830
+ queuedCalculateItemsInView: 0,
2831
+ refScroller: void 0,
2832
+ scroll: 0,
2833
+ scrollAdjustHandler: new ScrollAdjustHandler(ctx),
2834
+ scrollForNextCalculateItemsInView: void 0,
2835
+ scrollHistory: [],
2836
+ scrollLength: initialScrollLength,
2837
+ scrollPending: 0,
2838
+ scrollPrev: 0,
2839
+ scrollPrevTime: 0,
2840
+ scrollProcessingEnabled: true,
2841
+ scrollTime: 0,
2842
+ sizes: /* @__PURE__ */ new Map(),
2843
+ sizesKnown: /* @__PURE__ */ new Map(),
2844
+ startBuffered: -1,
2845
+ startNoBuffer: -1,
2846
+ startReachedBlockedByTimer: false,
2847
+ stickyContainerPool: /* @__PURE__ */ new Set(),
2848
+ stickyContainers: /* @__PURE__ */ new Map(),
2849
+ timeoutSizeMessage: 0,
2850
+ timeouts: /* @__PURE__ */ new Set(),
2851
+ totalSize: 0,
2852
+ viewabilityConfigCallbackPairs: void 0
2853
+ };
2854
+ set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2855
+ set$(ctx, "extraData", extraData);
2856
+ }
2857
+ refState.current = ctx.internalState;
2742
2858
  }
2743
2859
  const state = refState.current;
2744
2860
  const isFirst = !state.props.renderItem;
@@ -2771,18 +2887,19 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2771
2887
  onScroll: throttleScrollFn,
2772
2888
  onStartReached,
2773
2889
  onStartReachedThreshold,
2890
+ onStickyHeaderChange,
2774
2891
  recycleItems: !!recycleItems,
2775
2892
  renderItem,
2776
2893
  scrollBuffer,
2777
2894
  snapToIndices,
2778
2895
  stickyIndicesArr: stickyIndices != null ? stickyIndices : [],
2779
- stickyIndicesSet: React2.useMemo(() => new Set(stickyIndices != null ? stickyIndices : []), [stickyIndices == null ? void 0 : stickyIndices.join(",")]),
2896
+ stickyIndicesSet: React3.useMemo(() => new Set(stickyIndices != null ? stickyIndices : []), [stickyIndices == null ? void 0 : stickyIndices.join(",")]),
2780
2897
  stylePaddingBottom: stylePaddingBottomState,
2781
2898
  stylePaddingTop: stylePaddingTopState,
2782
2899
  suggestEstimatedItemSize: !!suggestEstimatedItemSize
2783
2900
  };
2784
2901
  state.refScroller = refScroller;
2785
- const memoizedLastItemKeys = React2.useMemo(() => {
2902
+ const memoizedLastItemKeys = React3.useMemo(() => {
2786
2903
  if (!dataProp.length) return [];
2787
2904
  return Array.from(
2788
2905
  { length: Math.min(numColumnsProp, dataProp.length) },
@@ -2812,7 +2929,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2812
2929
  true
2813
2930
  );
2814
2931
  }
2815
- const initialContentOffset = React2.useMemo(() => {
2932
+ const initialContentOffset = React3.useMemo(() => {
2816
2933
  if (initialScroll) {
2817
2934
  const { index, viewOffset } = initialScroll;
2818
2935
  let initialContentOffset2 = viewOffset || 0;
@@ -2821,7 +2938,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2821
2938
  }
2822
2939
  refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
2823
2940
  if (initialContentOffset2 > 0) {
2824
- scrollTo(state, { animated: false, index, offset: initialContentOffset2 });
2941
+ scrollTo(state, {
2942
+ animated: false,
2943
+ index,
2944
+ isInitialScroll: true,
2945
+ offset: initialContentOffset2,
2946
+ viewPosition: index === dataProp.length - 1 ? 1 : 0
2947
+ });
2825
2948
  }
2826
2949
  return initialContentOffset2;
2827
2950
  }
@@ -2838,7 +2961,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2838
2961
  refState.current.positions.clear();
2839
2962
  }
2840
2963
  }
2841
- const onLayoutHeader = React2.useCallback((rect, fromLayoutEffect) => {
2964
+ const onLayoutHeader = React3.useCallback((rect, fromLayoutEffect) => {
2842
2965
  const size = rect[horizontal ? "width" : "height"];
2843
2966
  set$(ctx, "headerSize", size);
2844
2967
  if ((initialScroll == null ? void 0 : initialScroll.index) !== void 0) {
@@ -2853,13 +2976,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2853
2976
  }
2854
2977
  }
2855
2978
  }, []);
2856
- React2.useLayoutEffect(() => {
2979
+ React3.useLayoutEffect(() => {
2857
2980
  if (snapToIndices) {
2858
2981
  updateSnapToOffsets(ctx, state);
2859
2982
  }
2860
2983
  }, [snapToIndices]);
2861
- React2.useLayoutEffect(() => {
2862
- const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainersCallback();
2984
+ React3.useLayoutEffect(() => {
2985
+ const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainers(ctx, state);
2863
2986
  if (!didAllocateContainers) {
2864
2987
  checkResetContainers(
2865
2988
  ctx,
@@ -2870,34 +2993,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2870
2993
  );
2871
2994
  }
2872
2995
  }, [dataProp, numColumnsProp]);
2873
- React2.useLayoutEffect(() => {
2996
+ React3.useLayoutEffect(() => {
2874
2997
  set$(ctx, "extraData", extraData);
2875
2998
  }, [extraData]);
2876
- React2.useLayoutEffect(() => {
2877
- var _a2;
2878
- if (IsNewArchitecture) {
2879
- let measured;
2880
- (_a2 = refScroller.current) == null ? void 0 : _a2.measure((x, y, width, height) => {
2881
- measured = { height, width, x, y };
2882
- });
2883
- if (measured) {
2884
- const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
2885
- if (size) {
2886
- handleLayout(ctx, state, measured, setCanRender);
2887
- }
2888
- }
2889
- }
2890
- }, []);
2891
- React2.useLayoutEffect(initializeStateVars, [
2999
+ React3.useLayoutEffect(initializeStateVars, [
2892
3000
  memoizedLastItemKeys.join(","),
2893
3001
  numColumnsProp,
2894
3002
  stylePaddingTopState,
2895
3003
  stylePaddingBottomState
2896
3004
  ]);
2897
- const doInitialAllocateContainersCallback = () => {
2898
- return doInitialAllocateContainers(ctx, state);
2899
- };
2900
- React2.useEffect(() => {
3005
+ React3.useEffect(() => {
2901
3006
  const viewability = setupViewability({
2902
3007
  onViewableItemsChanged,
2903
3008
  viewabilityConfig,
@@ -2908,17 +3013,19 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2908
3013
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
2909
3014
  if (!IsNewArchitecture) {
2910
3015
  useInit(() => {
2911
- doInitialAllocateContainersCallback();
3016
+ doInitialAllocateContainers(ctx, state);
2912
3017
  });
2913
3018
  }
2914
- const onLayout = React2.useCallback((event) => {
2915
- const layout = event.nativeEvent.layout;
3019
+ const onLayoutChange = React3.useCallback((layout) => {
2916
3020
  handleLayout(ctx, state, layout, setCanRender);
2917
- if (onLayoutProp) {
2918
- onLayoutProp(event);
2919
- }
2920
3021
  }, []);
2921
- React2.useImperativeHandle(forwardedRef, () => {
3022
+ const { onLayout } = useOnLayoutSync({
3023
+ onLayoutChange,
3024
+ onLayoutProp,
3025
+ ref: refScroller
3026
+ // the type of ScrollView doesn't include measure?
3027
+ });
3028
+ React3.useImperativeHandle(forwardedRef, () => {
2922
3029
  const scrollIndexIntoView = (options) => {
2923
3030
  const state2 = refState.current;
2924
3031
  if (state2) {
@@ -3001,13 +3108,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3001
3108
  };
3002
3109
  }, []);
3003
3110
  if (reactNative.Platform.OS === "web") {
3004
- React2.useEffect(() => {
3111
+ React3.useEffect(() => {
3005
3112
  if (initialContentOffset) {
3006
3113
  scrollTo(state, { animated: false, offset: initialContentOffset });
3007
3114
  }
3008
3115
  }, []);
3009
3116
  }
3010
- const fns = React2.useMemo(
3117
+ const fns = React3.useMemo(
3011
3118
  () => ({
3012
3119
  getRenderedItem: (key) => getRenderedItem(ctx, state, key),
3013
3120
  onScroll: (event) => onScroll(ctx, state, event),
@@ -3015,7 +3122,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3015
3122
  }),
3016
3123
  []
3017
3124
  );
3018
- const onScrollHandler = React2.useMemo(() => {
3125
+ const onScrollHandler = React3.useMemo(() => {
3019
3126
  const onScrollFn = fns.onScroll;
3020
3127
  if (stickyIndices == null ? void 0 : stickyIndices.length) {
3021
3128
  const { animatedScrollY } = ctx;
@@ -3026,7 +3133,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3026
3133
  }
3027
3134
  return onScrollFn;
3028
3135
  }, [stickyIndices == null ? void 0 : stickyIndices.length, horizontal, scrollEventThrottle]);
3029
- return /* @__PURE__ */ React2__namespace.createElement(React2__namespace.Fragment, null, /* @__PURE__ */ React2__namespace.createElement(
3136
+ return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement(
3030
3137
  ListComponent,
3031
3138
  {
3032
3139
  ...rest,
@@ -3057,9 +3164,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3057
3164
  },
3058
3165
  onScroll: onScrollHandler,
3059
3166
  recycleItems,
3060
- refreshControl: refreshControl ? stylePaddingTopState > 0 ? React2__namespace.cloneElement(refreshControl, {
3167
+ refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
3061
3168
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
3062
- }) : refreshControl : onRefresh && /* @__PURE__ */ React2__namespace.createElement(
3169
+ }) : refreshControl : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
3063
3170
  reactNative.RefreshControl,
3064
3171
  {
3065
3172
  onRefresh,
@@ -3076,7 +3183,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3076
3183
  updateItemSize: fns.updateItemSize,
3077
3184
  waitForInitialLayout
3078
3185
  }
3079
- ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React2__namespace.createElement(DebugView, { state: refState.current }));
3186
+ ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3__namespace.createElement(DebugView, { state: refState.current }));
3080
3187
  });
3081
3188
 
3082
3189
  exports.LegendList = LegendList;