@legendapp/list 3.0.0-beta.44 → 3.0.0-beta.45

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/react-native.js CHANGED
@@ -29,37 +29,6 @@ var ReactNative__namespace = /*#__PURE__*/_interopNamespace(ReactNative);
29
29
  ReactNative.Animated.View;
30
30
  var View = ReactNative.View;
31
31
  var Text = ReactNative.Text;
32
-
33
- // src/state/getContentInsetEnd.ts
34
- function getContentInsetEnd(state) {
35
- var _a3;
36
- const { props } = state;
37
- const horizontal = props.horizontal;
38
- const contentInset = props.contentInset;
39
- const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
40
- const overrideInset = (_a3 = state.contentInsetOverride) != null ? _a3 : void 0;
41
- if (overrideInset) {
42
- const mergedInset = { bottom: 0, right: 0, ...baseInset, ...overrideInset };
43
- return (horizontal ? mergedInset.right : mergedInset.bottom) || 0;
44
- }
45
- if (baseInset) {
46
- return (horizontal ? baseInset.right : baseInset.bottom) || 0;
47
- }
48
- return 0;
49
- }
50
-
51
- // src/state/getContentSize.ts
52
- function getContentSize(ctx) {
53
- var _a3;
54
- const { values, state } = ctx;
55
- const stylePaddingTop = values.get("stylePaddingTop") || 0;
56
- const stylePaddingBottom = state.props.stylePaddingBottom || 0;
57
- const headerSize = values.get("headerSize") || 0;
58
- const footerSize = values.get("footerSize") || 0;
59
- const contentInsetBottom = getContentInsetEnd(state);
60
- const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
61
- return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom + (contentInsetBottom || 0);
62
- }
63
32
  var createAnimatedValue = (value) => new ReactNative.Animated.Value(value);
64
33
 
65
34
  // src/state/state.tsx
@@ -83,6 +52,11 @@ function StateProvider({ children }) {
83
52
  ["headerSize", 0],
84
53
  ["numContainers", 0],
85
54
  ["activeStickyIndex", -1],
55
+ ["isAtEnd", false],
56
+ ["isAtStart", false],
57
+ ["isNearEnd", false],
58
+ ["isNearStart", false],
59
+ ["isWithinMaintainScrollAtEndThreshold", false],
86
60
  ["totalSize", 0],
87
61
  ["scrollAdjustPending", 0]
88
62
  ]),
@@ -174,29 +148,71 @@ function notifyPosition$(ctx, key, value) {
174
148
  function useArr$(signalNames) {
175
149
  const ctx = React2__namespace.useContext(ContextState);
176
150
  const { subscribe, get } = React2__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
177
- const value = shim.useSyncExternalStore(subscribe, get);
151
+ const value = shim.useSyncExternalStore(subscribe, get, get);
178
152
  return value;
179
153
  }
180
154
  function useSelector$(signalName, selector) {
181
155
  const ctx = React2__namespace.useContext(ContextState);
182
156
  const { subscribe, get } = React2__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
183
- const value = shim.useSyncExternalStore(subscribe, () => selector(get()[0]));
157
+ const getSelectedValue = React2__namespace.useCallback(() => selector(get()[0]), [get, selector]);
158
+ const value = shim.useSyncExternalStore(subscribe, getSelectedValue, getSelectedValue);
184
159
  return value;
185
160
  }
186
161
 
162
+ // src/state/getContentInsetEnd.ts
163
+ function getContentInsetEnd(ctx) {
164
+ var _a3, _b;
165
+ const state = ctx.state;
166
+ const { props } = state;
167
+ const horizontal = props.horizontal;
168
+ const contentInset = props.contentInset;
169
+ const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
170
+ const baseEndInset = (horizontal ? baseInset == null ? void 0 : baseInset.right : baseInset == null ? void 0 : baseInset.bottom) || 0;
171
+ const anchoredEndSpaceSize = peek$(ctx, "anchoredEndSpaceSize");
172
+ const anchoredEndInset = ((_a3 = props.anchoredEndSpace) == null ? void 0 : _a3.includeInEndInset) && anchoredEndSpaceSize ? anchoredEndSpaceSize : 0;
173
+ const overrideInset = (_b = state.contentInsetOverride) != null ? _b : void 0;
174
+ if (overrideInset) {
175
+ const mergedInset = { bottom: 0, right: 0, ...baseInset, ...overrideInset };
176
+ return Math.max((horizontal ? mergedInset.right : mergedInset.bottom) || 0, anchoredEndInset);
177
+ }
178
+ return Math.max(baseEndInset, anchoredEndInset);
179
+ }
180
+
181
+ // src/state/getContentSize.ts
182
+ function getContentSize(ctx) {
183
+ var _a3;
184
+ const { values, state } = ctx;
185
+ const stylePaddingTop = values.get("stylePaddingTop") || 0;
186
+ const stylePaddingBottom = state.props.stylePaddingBottom || 0;
187
+ const headerSize = values.get("headerSize") || 0;
188
+ const footerSize = values.get("footerSize") || 0;
189
+ const contentInsetBottom = getContentInsetEnd(ctx);
190
+ const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
191
+ return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom + (contentInsetBottom || 0);
192
+ }
193
+
187
194
  // src/components/DebugView.tsx
188
195
  var DebugRow = ({ children }) => {
189
196
  return /* @__PURE__ */ React2__namespace.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
190
197
  };
191
- React2__namespace.memo(function DebugView2({ state }) {
198
+ React2__namespace.memo(function DebugView2() {
192
199
  const ctx = useStateContext();
193
- const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
200
+ const [
201
+ totalSize = 0,
202
+ scrollAdjust = 0,
203
+ rawScroll = 0,
204
+ scroll = 0,
205
+ _numContainers = 0,
206
+ _numContainersPooled = 0,
207
+ isAtEnd = false
208
+ ] = useArr$([
194
209
  "totalSize",
195
210
  "scrollAdjust",
196
211
  "debugRawScroll",
197
212
  "debugComputedScroll",
198
213
  "numContainers",
199
- "numContainersPooled"
214
+ "numContainersPooled",
215
+ "isAtEnd"
200
216
  ]);
201
217
  const contentSize = getContentSize(ctx);
202
218
  const [, forceUpdate] = React2.useReducer((x) => x + 1, 0);
@@ -221,7 +237,7 @@ React2__namespace.memo(function DebugView2({ state }) {
221
237
  },
222
238
  /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React2__namespace.createElement(Text, null, totalSize.toFixed(2))),
223
239
  /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React2__namespace.createElement(Text, null, contentSize.toFixed(2))),
224
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(Text, null, "At end:"), /* @__PURE__ */ React2__namespace.createElement(Text, null, String(state.isAtEnd))),
240
+ /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(Text, null, "At end:"), /* @__PURE__ */ React2__namespace.createElement(Text, null, String(isAtEnd))),
225
241
  /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React2__namespace.createElement(Text, null, scrollAdjust.toFixed(2))),
226
242
  /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React2__namespace.createElement(Text, null, rawScroll.toFixed(2))),
227
243
  /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React2__namespace.createElement(Text, null, scroll.toFixed(2)))
@@ -234,6 +250,30 @@ function useInterval(callback, delay) {
234
250
  }, [delay]);
235
251
  }
236
252
 
253
+ // src/components/stickyPositionUtils.ts
254
+ function getStickyPushLimit(state, index, itemKey) {
255
+ if (!itemKey) {
256
+ return void 0;
257
+ }
258
+ const currentSize = state.sizes.get(itemKey);
259
+ if (!(currentSize && currentSize > 0)) {
260
+ return void 0;
261
+ }
262
+ const stickyIndexInArray = state.props.stickyIndicesArr.indexOf(index);
263
+ if (stickyIndexInArray === -1) {
264
+ return void 0;
265
+ }
266
+ const nextStickyIndex = state.props.stickyIndicesArr[stickyIndexInArray + 1];
267
+ if (nextStickyIndex === void 0) {
268
+ return void 0;
269
+ }
270
+ const nextStickyPosition = state.positions[nextStickyIndex];
271
+ if (nextStickyPosition === void 0) {
272
+ return void 0;
273
+ }
274
+ return nextStickyPosition - currentSize;
275
+ }
276
+
237
277
  // src/utils/devEnvironment.ts
238
278
  var metroDev = typeof __DEV__ !== "undefined" ? __DEV__ : void 0;
239
279
  var _a;
@@ -244,6 +284,7 @@ var IS_DEV = (_a2 = processDev != null ? processDev : metroDev) != null ? _a2 :
244
284
 
245
285
  // src/constants.ts
246
286
  var POSITION_OUT_OF_VIEW = -1e7;
287
+ var EDGE_POSITION_EPSILON = 1;
247
288
  var ENABLE_DEVMODE = IS_DEV && false;
248
289
  var ENABLE_DEBUG_VIEW = IS_DEV && false;
249
290
 
@@ -255,93 +296,26 @@ var useAnimatedValue = (initialValue) => {
255
296
  return animAnimatedValue;
256
297
  };
257
298
 
258
- // src/utils/helpers.ts
259
- function isFunction(obj) {
260
- return typeof obj === "function";
261
- }
262
- function isArray(obj) {
263
- return Array.isArray(obj);
264
- }
265
- var warned = /* @__PURE__ */ new Set();
266
- function warnDevOnce(id, text) {
267
- if (IS_DEV && !warned.has(id)) {
268
- warned.add(id);
269
- console.warn(`[legend-list] ${text}`);
270
- }
271
- }
272
- function roundSize(size) {
273
- return Math.floor(size * 8) / 8;
274
- }
275
- function isNullOrUndefined(value) {
276
- return value === null || value === void 0;
277
- }
278
- function comparatorDefault(a, b) {
279
- return a - b;
280
- }
281
- function getPadding(s, type) {
282
- var _a3, _b, _c;
283
- return (_c = (_b = (_a3 = s[`padding${type}`]) != null ? _a3 : s.paddingVertical) != null ? _b : s.padding) != null ? _c : 0;
284
- }
285
- function extractPadding(style, contentContainerStyle, type) {
286
- return getPadding(style, type) + getPadding(contentContainerStyle, type);
287
- }
288
- function findContainerId(ctx, key) {
289
- var _a3, _b;
290
- const directMatch = (_b = (_a3 = ctx.state) == null ? void 0 : _a3.containerItemKeys) == null ? void 0 : _b.get(key);
291
- if (directMatch !== void 0) {
292
- return directMatch;
293
- }
294
- const numContainers = peek$(ctx, "numContainers");
295
- for (let i = 0; i < numContainers; i++) {
296
- const itemKey = peek$(ctx, `containerItemKey${i}`);
297
- if (itemKey === key) {
298
- return i;
299
- }
300
- }
301
- return -1;
302
- }
303
-
304
299
  // src/hooks/useValue$.ts
305
300
  function useValue$(key, params) {
306
- const { getValue, delay } = params || {};
301
+ const { getValue } = params || {};
307
302
  const ctx = useStateContext();
308
303
  const getNewValue = () => {
309
304
  var _a3;
310
305
  return (_a3 = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a3 : 0;
311
306
  };
312
307
  const animValue = useAnimatedValue(getNewValue());
313
- React2.useMemo(() => {
314
- let prevValue;
315
- let didQueueTask = false;
316
- listen$(ctx, key, () => {
317
- const newValue = getNewValue();
318
- if (delay !== void 0) {
319
- const fn = () => {
320
- didQueueTask = false;
321
- const latestValue = getNewValue();
322
- if (latestValue !== void 0) {
323
- animValue.setValue(latestValue);
324
- }
325
- };
326
- const delayValue = isFunction(delay) ? delay(newValue, prevValue) : delay;
327
- prevValue = newValue;
328
- if (!didQueueTask) {
329
- didQueueTask = true;
330
- if (delayValue === void 0) {
331
- fn();
332
- } else if (delayValue === 0) {
333
- queueMicrotask(fn);
334
- } else {
335
- setTimeout(fn, delayValue);
336
- }
337
- }
338
- } else {
339
- animValue.setValue(newValue);
340
- }
341
- });
342
- }, []);
308
+ React2.useLayoutEffect(() => {
309
+ const syncCurrentValue = () => {
310
+ animValue.setValue(getNewValue());
311
+ };
312
+ const unsubscribe = listen$(ctx, key, syncCurrentValue);
313
+ syncCurrentValue();
314
+ return unsubscribe;
315
+ }, [animValue, ctx, key]);
343
316
  return animValue;
344
317
  }
318
+ var typedForwardRef = React2__namespace.forwardRef;
345
319
  var typedMemo = React2__namespace.memo;
346
320
  var getComponent = (Component) => {
347
321
  if (React2__namespace.isValidElement(Component)) {
@@ -361,18 +335,8 @@ var PositionViewState = typedMemo(function PositionViewState2({
361
335
  refView,
362
336
  ...rest
363
337
  }) {
364
- const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
365
- return /* @__PURE__ */ React2__namespace.createElement(
366
- ReactNative.View,
367
- {
368
- ref: refView,
369
- style: [
370
- style,
371
- horizontal ? { transform: [{ translateX: position }] } : { transform: [{ translateY: position }] }
372
- ],
373
- ...rest
374
- }
375
- );
338
+ const [position = POSITION_OUT_OF_VIEW, _itemKey] = useArr$([`containerPosition${id}`, `containerItemKey${id}`]);
339
+ return /* @__PURE__ */ React2__namespace.createElement(ReactNative.View, { ref: refView, style: [style, horizontal ? { left: position } : { top: position }], ...rest });
376
340
  });
377
341
  var PositionViewAnimated = typedMemo(function PositionViewAnimated2({
378
342
  id,
@@ -403,25 +367,46 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
403
367
  children,
404
368
  ...rest
405
369
  }) {
406
- const [position = POSITION_OUT_OF_VIEW, headerSize = 0, stylePaddingTop = 0] = useArr$([
370
+ const ctx = useStateContext();
371
+ const [position = POSITION_OUT_OF_VIEW, headerSize = 0, stylePaddingTop = 0, itemKey, _totalSize = 0] = useArr$([
407
372
  `containerPosition${id}`,
408
373
  "headerSize",
409
- "stylePaddingTop"
374
+ "stylePaddingTop",
375
+ `containerItemKey${id}`,
376
+ "totalSize"
410
377
  ]);
378
+ const pushLimit = React2__namespace.useMemo(
379
+ () => getStickyPushLimit(ctx.state, index, itemKey),
380
+ [ctx.state, index, itemKey, _totalSize]
381
+ );
411
382
  const transform = React2__namespace.useMemo(() => {
412
383
  var _a3;
413
384
  if (animatedScrollY) {
414
385
  const stickyConfigOffset = (_a3 = stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset) != null ? _a3 : 0;
415
386
  const stickyStart = position + headerSize + stylePaddingTop - stickyConfigOffset;
416
- const stickyPosition = animatedScrollY.interpolate({
417
- extrapolateLeft: "clamp",
418
- extrapolateRight: "extend",
419
- inputRange: [stickyStart, stickyStart + 5e3],
420
- outputRange: [position, position + 5e3]
421
- });
387
+ let stickyPosition;
388
+ if (pushLimit !== void 0) {
389
+ if (pushLimit <= position) {
390
+ stickyPosition = pushLimit;
391
+ } else {
392
+ stickyPosition = animatedScrollY.interpolate({
393
+ extrapolateLeft: "clamp",
394
+ extrapolateRight: "clamp",
395
+ inputRange: [stickyStart, stickyStart + (pushLimit - position)],
396
+ outputRange: [position, pushLimit]
397
+ });
398
+ }
399
+ } else {
400
+ stickyPosition = animatedScrollY.interpolate({
401
+ extrapolateLeft: "clamp",
402
+ extrapolateRight: "extend",
403
+ inputRange: [stickyStart, stickyStart + 5e3],
404
+ outputRange: [position, position + 5e3]
405
+ });
406
+ }
422
407
  return horizontal ? [{ translateX: stickyPosition }] : [{ translateY: stickyPosition }];
423
408
  }
424
- }, [animatedScrollY, headerSize, horizontal, position, stylePaddingTop, stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset]);
409
+ }, [animatedScrollY, headerSize, horizontal, position, pushLimit, stylePaddingTop, stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset]);
425
410
  const viewStyle = React2__namespace.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
426
411
  const renderStickyHeaderBackdrop = React2__namespace.useMemo(() => {
427
412
  if (!(stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.backdropComponent)) {
@@ -446,6 +431,52 @@ function useInit(cb) {
446
431
  React2.useState(() => cb());
447
432
  }
448
433
 
434
+ // src/utils/helpers.ts
435
+ function isFunction(obj) {
436
+ return typeof obj === "function";
437
+ }
438
+ function isArray(obj) {
439
+ return Array.isArray(obj);
440
+ }
441
+ var warned = /* @__PURE__ */ new Set();
442
+ function warnDevOnce(id, text) {
443
+ if (IS_DEV && !warned.has(id)) {
444
+ warned.add(id);
445
+ console.warn(`[legend-list] ${text}`);
446
+ }
447
+ }
448
+ function roundSize(size) {
449
+ return Math.floor(size * 8) / 8;
450
+ }
451
+ function isNullOrUndefined(value) {
452
+ return value === null || value === void 0;
453
+ }
454
+ function comparatorDefault(a, b) {
455
+ return a - b;
456
+ }
457
+ function getPadding(s, type) {
458
+ var _a3, _b, _c;
459
+ return (_c = (_b = (_a3 = s[`padding${type}`]) != null ? _a3 : s.paddingVertical) != null ? _b : s.padding) != null ? _c : 0;
460
+ }
461
+ function extractPadding(style, contentContainerStyle, type) {
462
+ return getPadding(style, type) + getPadding(contentContainerStyle, type);
463
+ }
464
+ function findContainerId(ctx, key) {
465
+ var _a3, _b;
466
+ const directMatch = (_b = (_a3 = ctx.state) == null ? void 0 : _a3.containerItemKeys) == null ? void 0 : _b.get(key);
467
+ if (directMatch !== void 0) {
468
+ return directMatch;
469
+ }
470
+ const numContainers = peek$(ctx, "numContainers");
471
+ for (let i = 0; i < numContainers; i++) {
472
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
473
+ if (itemKey === key) {
474
+ return i;
475
+ }
476
+ }
477
+ return -1;
478
+ }
479
+
449
480
  // src/state/ContextContainer.ts
450
481
  var ContextContainer = React2.createContext(null);
451
482
  function useContextContainer() {
@@ -613,11 +644,11 @@ function useOnLayoutSync({
613
644
  const { layout } = event.nativeEvent;
614
645
  if (layout.height !== ((_a3 = lastLayoutRef.current) == null ? void 0 : _a3.height) || layout.width !== ((_b = lastLayoutRef.current) == null ? void 0 : _b.width)) {
615
646
  onLayoutChange(layout, false);
616
- onLayoutProp == null ? void 0 : onLayoutProp(event);
617
647
  lastLayoutRef.current = layout;
618
648
  }
649
+ onLayoutProp == null ? void 0 : onLayoutProp(event);
619
650
  },
620
- [onLayoutChange]
651
+ [onLayoutChange, onLayoutProp]
621
652
  );
622
653
  if (IsNewArchitecture) {
623
654
  React2.useLayoutEffect(() => {
@@ -634,8 +665,6 @@ function useOnLayoutSync({
634
665
  }
635
666
  var Platform2 = ReactNative.Platform;
636
667
  var PlatformAdjustBreaksScroll = Platform2.OS === "android";
637
- var typedForwardRef = React2__namespace.forwardRef;
638
- var typedMemo2 = React2__namespace.memo;
639
668
 
640
669
  // src/utils/isInMVCPActiveMode.native.ts
641
670
  function isInMVCPActiveMode(state) {
@@ -643,7 +672,7 @@ function isInMVCPActiveMode(state) {
643
672
  }
644
673
 
645
674
  // src/components/Container.tsx
646
- var Container = typedMemo2(function Container2({
675
+ var Container = typedMemo(function Container2({
647
676
  id,
648
677
  recycleItems,
649
678
  horizontal,
@@ -687,17 +716,20 @@ var Container = typedMemo2(function Container2({
687
716
  const { columnGap, rowGap, gap } = columnWrapperStyle;
688
717
  if (horizontal) {
689
718
  paddingStyles = {
719
+ paddingBottom: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0,
690
720
  paddingRight: columnGap || gap || void 0,
691
- paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
721
+ paddingTop: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
692
722
  };
693
723
  } else {
694
724
  paddingStyles = {
695
725
  paddingBottom: rowGap || gap || void 0,
696
- paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
726
+ paddingLeft: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0,
727
+ paddingRight: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
697
728
  };
698
729
  }
699
730
  }
700
731
  return horizontal ? {
732
+ boxSizing: paddingStyles ? "border-box" : void 0,
701
733
  flexDirection: ItemSeparatorComponent ? "row" : void 0,
702
734
  height: otherAxisSize,
703
735
  left: 0,
@@ -705,6 +737,7 @@ var Container = typedMemo2(function Container2({
705
737
  top: otherAxisPos,
706
738
  ...paddingStyles || {}
707
739
  } : {
740
+ boxSizing: paddingStyles ? "border-box" : void 0,
708
741
  left: otherAxisPos,
709
742
  position: "absolute",
710
743
  right: numColumns > 1 ? null : 0,
@@ -838,16 +871,9 @@ var Containers = typedMemo(function Containers2({
838
871
  const ctx = useStateContext();
839
872
  const columnWrapperStyle = ctx.columnWrapperStyle;
840
873
  const [numContainers, numColumns] = useArr$(["numContainersPooled", "numColumns"]);
841
- const animSize = useValue$("totalSize", {
842
- // Use a microtask if increasing the size significantly, otherwise use a timeout
843
- // If this is the initial scroll, we don't want to delay because we want to update the size immediately
844
- delay: (value, prevValue) => {
845
- var _a3;
846
- return !((_a3 = ctx.state) == null ? void 0 : _a3.initialScroll) ? !prevValue || value - prevValue > 20 ? 0 : 200 : void 0;
847
- }
848
- });
874
+ const animSize = useValue$("totalSize");
875
+ const otherAxisSize = useValue$("otherAxisSize");
849
876
  const animOpacity = useValue$("readyToRender", { getValue: (value) => value ? 1 : 0 });
850
- const otherAxisSize = useValue$("otherAxisSize", { delay: 0 });
851
877
  const containers = [];
852
878
  for (let i = 0; i < numContainers; i++) {
853
879
  containers.push(
@@ -891,17 +917,20 @@ var Containers = typedMemo(function Containers2({
891
917
  });
892
918
  var ListComponentScrollView = ReactNative.Animated.ScrollView;
893
919
  function ScrollAdjust() {
920
+ var _a3;
921
+ const ctx = useStateContext();
894
922
  const bias = 1e7;
895
923
  const [scrollAdjust, scrollAdjustUserOffset] = useArr$(["scrollAdjust", "scrollAdjustUserOffset"]);
896
924
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0) + bias;
925
+ const horizontal = !!((_a3 = ctx.state) == null ? void 0 : _a3.props.horizontal);
897
926
  return /* @__PURE__ */ React2__namespace.createElement(
898
927
  ReactNative.View,
899
928
  {
900
929
  style: {
901
930
  height: 0,
902
- left: 0,
931
+ left: horizontal ? scrollOffset : 0,
903
932
  position: "absolute",
904
- top: scrollOffset,
933
+ top: horizontal ? 0 : scrollOffset,
905
934
  width: 0
906
935
  }
907
936
  }
@@ -911,14 +940,25 @@ function SnapWrapper({ ScrollComponent, ...props }) {
911
940
  const [snapToOffsets] = useArr$(["snapToOffsets"]);
912
941
  return /* @__PURE__ */ React2__namespace.createElement(ScrollComponent, { ...props, snapToOffsets });
913
942
  }
943
+ function WebAnchoredEndSpace({ horizontal }) {
944
+ const ctx = useStateContext();
945
+ const [anchoredEndSpaceSize] = useArr$(["anchoredEndSpaceSize"]);
946
+ const shouldRenderAnchoredEndSpace = !!ctx.state.props.anchoredEndSpace && (anchoredEndSpaceSize || 0) > 0;
947
+ if (!shouldRenderAnchoredEndSpace) {
948
+ return null;
949
+ }
950
+ const style = horizontal ? { height: "100%", width: anchoredEndSpaceSize || 0 } : { height: anchoredEndSpaceSize || 0 };
951
+ return /* @__PURE__ */ React2__namespace.createElement("div", { style }, null);
952
+ }
914
953
  var LayoutView = ({ onLayoutChange, refView, ...rest }) => {
915
- const ref = refView != null ? refView : React2.useRef(null);
954
+ const localRef = React2.useRef(null);
955
+ const ref = refView != null ? refView : localRef;
916
956
  const { onLayout } = useOnLayoutSync({ onLayoutChange, ref });
917
957
  return /* @__PURE__ */ React2__namespace.createElement(ReactNative.View, { ...rest, onLayout, ref });
918
958
  };
919
959
 
920
960
  // src/components/ListComponent.tsx
921
- var ListComponent = typedMemo2(function ListComponent2({
961
+ var ListComponent = typedMemo(function ListComponent2({
922
962
  canRender,
923
963
  style,
924
964
  contentContainerStyle,
@@ -948,12 +988,14 @@ var ListComponent = typedMemo2(function ListComponent2({
948
988
  }) {
949
989
  const ctx = useStateContext();
950
990
  const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
951
- const ScrollComponent = renderScrollComponent ? React2.useMemo(
952
- () => React2__namespace.forwardRef(
991
+ const ScrollComponent = React2.useMemo(() => {
992
+ if (!renderScrollComponent) {
993
+ return ListComponentScrollView;
994
+ }
995
+ return React2__namespace.forwardRef(
953
996
  (props, ref) => renderScrollComponent({ ...props, ref })
954
- ),
955
- [renderScrollComponent]
956
- ) : ListComponentScrollView;
997
+ );
998
+ }, [renderScrollComponent]);
957
999
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
958
1000
  React2.useLayoutEffect(() => {
959
1001
  if (!ListHeaderComponent) {
@@ -1013,183 +1055,90 @@ var ListComponent = typedMemo2(function ListComponent2({
1013
1055
  }
1014
1056
  ),
1015
1057
  ListFooterComponent && /* @__PURE__ */ React2__namespace.createElement(LayoutView, { onLayoutChange: onLayoutFooterInternal, style: ListFooterComponentStyle }, getComponent(ListFooterComponent)),
1058
+ Platform2.OS === "web" && /* @__PURE__ */ React2__namespace.createElement(WebAnchoredEndSpace, { horizontal }),
1016
1059
  IS_DEV && ENABLE_DEVMODE
1017
1060
  );
1018
1061
  });
1019
-
1020
- // src/core/calculateOffsetForIndex.ts
1021
- function calculateOffsetForIndex(ctx, index) {
1022
- const state = ctx.state;
1023
- return index !== void 0 ? state.positions[index] || 0 : 0;
1062
+ var WEB_UNBOUNDED_HEIGHT_MIN_DATA_LENGTH = 100;
1063
+ var WEB_UNBOUNDED_HEIGHT_CONTAINER_RATIO = 0.9;
1064
+ var WEB_UNBOUNDED_HEIGHT_VIEWPORT_RATIO = 0.9;
1065
+ function useDevChecksImpl(props) {
1066
+ const ctx = useStateContext();
1067
+ const { childrenMode, keyExtractor, renderScrollComponent, stickyHeaderIndices, stickyIndices, useWindowScroll } = props;
1068
+ React2.useEffect(() => {
1069
+ if (stickyIndices && !stickyHeaderIndices) {
1070
+ warnDevOnce(
1071
+ "stickyIndices",
1072
+ "stickyIndices has been renamed to stickyHeaderIndices. Please update your props to use stickyHeaderIndices."
1073
+ );
1074
+ }
1075
+ }, [stickyHeaderIndices, stickyIndices]);
1076
+ React2.useEffect(() => {
1077
+ if (useWindowScroll && renderScrollComponent) {
1078
+ warnDevOnce(
1079
+ "useWindowScrollRenderScrollComponent",
1080
+ "useWindowScroll is not supported when renderScrollComponent is provided."
1081
+ );
1082
+ }
1083
+ }, [renderScrollComponent, useWindowScroll]);
1084
+ React2.useEffect(() => {
1085
+ if (!keyExtractor && !ctx.state.isFirst && ctx.state.didDataChange && !childrenMode) {
1086
+ warnDevOnce(
1087
+ "keyExtractor",
1088
+ "Changing data without a keyExtractor can cause slow performance and resetting scroll. If your list data can change you should use a keyExtractor with a unique id for best performance and behavior."
1089
+ );
1090
+ }
1091
+ }, [childrenMode, ctx, keyExtractor]);
1092
+ React2.useEffect(() => {
1093
+ const state = ctx.state;
1094
+ const dataLength = state.props.data.length;
1095
+ const useWindowScrollResolved = state.props.useWindowScroll;
1096
+ if (Platform2.OS !== "web" || useWindowScrollResolved || dataLength < WEB_UNBOUNDED_HEIGHT_MIN_DATA_LENGTH) {
1097
+ return;
1098
+ }
1099
+ const warnIfUnboundedOuterSize = () => {
1100
+ const readyToRender = peek$(ctx, "readyToRender");
1101
+ const numContainers = peek$(ctx, "numContainers") || 0;
1102
+ const totalSize = peek$(ctx, "totalSize") || 0;
1103
+ const scrollLength = ctx.state.scrollLength || 0;
1104
+ if (!readyToRender || totalSize <= 0 || scrollLength <= 0) {
1105
+ return;
1106
+ }
1107
+ const rendersAlmostEverything = numContainers >= Math.ceil(dataLength * WEB_UNBOUNDED_HEIGHT_CONTAINER_RATIO);
1108
+ const viewportMatchesContent = scrollLength >= totalSize * WEB_UNBOUNDED_HEIGHT_VIEWPORT_RATIO;
1109
+ if (rendersAlmostEverything && viewportMatchesContent) {
1110
+ warnDevOnce(
1111
+ "webUnboundedOuterSize",
1112
+ "LegendList appears to have an unbounded outer height on web, so virtualization is effectively disabled. Set a bounded height or flex: 1 on the list container, or use useWindowScroll."
1113
+ );
1114
+ }
1115
+ };
1116
+ warnIfUnboundedOuterSize();
1117
+ const unsubscribe = [
1118
+ listen$(ctx, "numContainers", warnIfUnboundedOuterSize),
1119
+ listen$(ctx, "readyToRender", warnIfUnboundedOuterSize),
1120
+ listen$(ctx, "totalSize", warnIfUnboundedOuterSize)
1121
+ ];
1122
+ return () => {
1123
+ for (const unsub of unsubscribe) {
1124
+ unsub();
1125
+ }
1126
+ };
1127
+ }, [ctx]);
1024
1128
  }
1025
-
1026
- // src/core/getTopOffsetAdjustment.ts
1027
- function getTopOffsetAdjustment(ctx) {
1028
- return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1129
+ function useDevChecksNoop(_props) {
1029
1130
  }
1131
+ var useDevChecks = IS_DEV ? useDevChecksImpl : useDevChecksNoop;
1030
1132
 
1031
- // src/utils/getId.ts
1032
- function getId(state, index) {
1033
- const { data, keyExtractor } = state.props;
1034
- if (!data) {
1035
- return "";
1036
- }
1037
- const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
1038
- const id = ret;
1039
- state.idCache[index] = id;
1040
- return id;
1041
- }
1042
-
1043
- // src/core/addTotalSize.ts
1044
- function addTotalSize(ctx, key, add) {
1045
- const state = ctx.state;
1046
- const prevTotalSize = state.totalSize;
1047
- let totalSize = state.totalSize;
1048
- if (key === null) {
1049
- totalSize = add;
1050
- if (state.timeoutSetPaddingTop) {
1051
- clearTimeout(state.timeoutSetPaddingTop);
1052
- state.timeoutSetPaddingTop = void 0;
1053
- }
1054
- } else {
1055
- totalSize += add;
1056
- }
1057
- if (prevTotalSize !== totalSize) {
1058
- if (!IsNewArchitecture && state.initialScroll && totalSize < prevTotalSize) {
1059
- state.pendingTotalSize = totalSize;
1060
- } else {
1061
- state.pendingTotalSize = void 0;
1062
- state.totalSize = totalSize;
1063
- set$(ctx, "totalSize", totalSize);
1064
- }
1065
- }
1066
- }
1067
-
1068
- // src/core/setSize.ts
1069
- function setSize(ctx, itemKey, size) {
1070
- const state = ctx.state;
1071
- const { sizes } = state;
1072
- const previousSize = sizes.get(itemKey);
1073
- const diff = previousSize !== void 0 ? size - previousSize : size;
1074
- if (diff !== 0) {
1075
- addTotalSize(ctx, itemKey, diff);
1076
- }
1077
- sizes.set(itemKey, size);
1078
- }
1079
-
1080
- // src/utils/getItemSize.ts
1081
- function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1082
- var _a3, _b;
1083
- const state = ctx.state;
1084
- const {
1085
- sizesKnown,
1086
- sizes,
1087
- averageSizes,
1088
- props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType },
1089
- scrollingTo
1090
- } = state;
1091
- const sizeKnown = sizesKnown.get(key);
1092
- if (sizeKnown !== void 0) {
1093
- return sizeKnown;
1094
- }
1095
- let size;
1096
- if (preferCachedSize) {
1097
- const cachedSize = sizes.get(key);
1098
- if (cachedSize !== void 0) {
1099
- return cachedSize;
1100
- }
1101
- }
1102
- const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1103
- if (getFixedItemSize) {
1104
- size = getFixedItemSize(data, index, itemType);
1105
- if (size !== void 0) {
1106
- sizesKnown.set(key, size);
1107
- }
1108
- }
1109
- if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
1110
- const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
1111
- if (averageSizeForType !== void 0) {
1112
- size = roundSize(averageSizeForType);
1113
- }
1114
- }
1115
- if (size === void 0) {
1116
- size = sizes.get(key);
1117
- if (size !== void 0) {
1118
- return size;
1119
- }
1120
- }
1121
- if (size === void 0) {
1122
- size = getEstimatedItemSize ? getEstimatedItemSize(data, index, itemType) : estimatedItemSize;
1123
- }
1124
- setSize(ctx, key, size);
1125
- return size;
1126
- }
1127
- function getItemSizeAtIndex(ctx, index) {
1128
- if (index === void 0 || index < 0) {
1129
- return void 0;
1130
- }
1131
- const targetId = getId(ctx.state, index);
1132
- return getItemSize(ctx, targetId, index, ctx.state.props.data[index]);
1133
- }
1134
-
1135
- // src/core/calculateOffsetWithOffsetPosition.ts
1136
- function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
1137
- var _a3;
1138
- const state = ctx.state;
1139
- const { index, viewOffset, viewPosition } = params;
1140
- let offset = offsetParam;
1141
- if (viewOffset) {
1142
- offset -= viewOffset;
1143
- }
1144
- if (index !== void 0) {
1145
- const topOffsetAdjustment = getTopOffsetAdjustment(ctx);
1146
- if (topOffsetAdjustment) {
1147
- offset += topOffsetAdjustment;
1148
- }
1149
- }
1150
- if (viewPosition !== void 0 && index !== void 0) {
1151
- const dataLength = state.props.data.length;
1152
- if (dataLength === 0) {
1153
- return offset;
1154
- }
1155
- const isOutOfBounds = index < 0 || index >= dataLength;
1156
- const fallbackEstimatedSize = (_a3 = state.props.estimatedItemSize) != null ? _a3 : 0;
1157
- const itemSize = isOutOfBounds ? fallbackEstimatedSize : getItemSize(ctx, getId(state, index), index, state.props.data[index]);
1158
- const trailingInset = getContentInsetEnd(state);
1159
- offset -= viewPosition * (state.scrollLength - trailingInset - itemSize);
1160
- if (!isOutOfBounds && index === state.props.data.length - 1) {
1161
- const footerSize = peek$(ctx, "footerSize") || 0;
1162
- offset += footerSize;
1163
- }
1164
- }
1165
- return offset;
1166
- }
1167
-
1168
- // src/core/clampScrollOffset.ts
1169
- function clampScrollOffset(ctx, offset, scrollTarget) {
1170
- const state = ctx.state;
1171
- const contentSize = getContentSize(ctx);
1172
- let clampedOffset = offset;
1173
- if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength) && (Platform2.OS !== "android" || state.lastLayout)) {
1174
- const baseMaxOffset = Math.max(0, contentSize - state.scrollLength);
1175
- const viewOffset = scrollTarget == null ? void 0 : scrollTarget.viewOffset;
1176
- const extraEndOffset = typeof viewOffset === "number" && viewOffset < 0 ? -viewOffset : 0;
1177
- const maxOffset = baseMaxOffset + extraEndOffset;
1178
- clampedOffset = Math.min(offset, maxOffset);
1179
- }
1180
- clampedOffset = Math.max(0, clampedOffset);
1181
- return clampedOffset;
1182
- }
1183
-
1184
- // src/core/deferredPublicOnScroll.ts
1185
- function withResolvedContentOffset(state, event, resolvedOffset) {
1186
- return {
1187
- ...event,
1188
- nativeEvent: {
1189
- ...event.nativeEvent,
1190
- contentOffset: state.props.horizontal ? { x: resolvedOffset, y: 0 } : { x: 0, y: resolvedOffset }
1191
- }
1192
- };
1133
+ // src/core/deferredPublicOnScroll.ts
1134
+ function withResolvedContentOffset(state, event, resolvedOffset) {
1135
+ return {
1136
+ ...event,
1137
+ nativeEvent: {
1138
+ ...event.nativeEvent,
1139
+ contentOffset: state.props.horizontal ? { x: resolvedOffset, y: 0 } : { x: 0, y: resolvedOffset }
1140
+ }
1141
+ };
1193
1142
  }
1194
1143
  function releaseDeferredPublicOnScroll(ctx, resolvedOffset) {
1195
1144
  var _a3, _b, _c, _d;
@@ -1268,63 +1217,489 @@ var initialScrollCompletion = {
1268
1217
  if (!state.initialScrollSession) {
1269
1218
  return;
1270
1219
  }
1271
- const completion = ensureInitialScrollSessionCompletion(state, state.initialScrollSession.kind);
1272
- completion.didDispatchNativeScroll = void 0;
1273
- completion.didRetrySilentInitialScroll = void 0;
1220
+ const completion = ensureInitialScrollSessionCompletion(state, state.initialScrollSession.kind);
1221
+ completion.didDispatchNativeScroll = void 0;
1222
+ completion.didRetrySilentInitialScroll = void 0;
1223
+ }
1224
+ };
1225
+ var initialScrollWatchdog = {
1226
+ clear(state) {
1227
+ initialScrollWatchdog.set(state, void 0);
1228
+ },
1229
+ didObserveProgress(newScroll, watchdog) {
1230
+ const previousDistance = Math.abs(watchdog.startScroll - watchdog.targetOffset);
1231
+ const nextDistance = Math.abs(newScroll - watchdog.targetOffset);
1232
+ return nextDistance <= INITIAL_SCROLL_MIN_TARGET_OFFSET || nextDistance + INITIAL_SCROLL_MIN_TARGET_OFFSET < previousDistance;
1233
+ },
1234
+ get(state) {
1235
+ var _a3, _b;
1236
+ return (_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.watchdog;
1237
+ },
1238
+ hasNonZeroTargetOffset(targetOffset) {
1239
+ return targetOffset !== void 0 && targetOffset > INITIAL_SCROLL_MIN_TARGET_OFFSET;
1240
+ },
1241
+ isAtZeroTargetOffset(targetOffset) {
1242
+ return targetOffset <= INITIAL_SCROLL_MIN_TARGET_OFFSET;
1243
+ },
1244
+ set(state, watchdog) {
1245
+ var _a3, _b;
1246
+ if (!watchdog && !((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.watchdog)) {
1247
+ return;
1248
+ }
1249
+ const completion = ensureInitialScrollSessionCompletion(state);
1250
+ completion.watchdog = watchdog ? {
1251
+ startScroll: watchdog.startScroll,
1252
+ targetOffset: watchdog.targetOffset
1253
+ } : void 0;
1254
+ }
1255
+ };
1256
+ function setInitialScrollSession(state, options = {}) {
1257
+ var _a3, _b, _c;
1258
+ const existingSession = state.initialScrollSession;
1259
+ const kind = (_a3 = options.kind) != null ? _a3 : existingSession == null ? void 0 : existingSession.kind;
1260
+ const completion = existingSession == null ? void 0 : existingSession.completion;
1261
+ const hasBootstrapOverride = Object.hasOwn(options, "bootstrap");
1262
+ const bootstrap = kind === "bootstrap" ? hasBootstrapOverride ? options.bootstrap : (existingSession == null ? void 0 : existingSession.kind) === "bootstrap" ? existingSession.bootstrap : void 0 : void 0;
1263
+ if (!kind) {
1264
+ return clearInitialScrollSession(state);
1265
+ }
1266
+ if (!state.initialScroll && !bootstrap && !hasInitialScrollSessionCompletion(completion)) {
1267
+ return clearInitialScrollSession(state);
1268
+ }
1269
+ const previousDataLength = (_c = (_b = options.previousDataLength) != null ? _b : existingSession == null ? void 0 : existingSession.previousDataLength) != null ? _c : 0;
1270
+ state.initialScrollSession = createInitialScrollSession({
1271
+ bootstrap,
1272
+ completion,
1273
+ kind,
1274
+ previousDataLength
1275
+ });
1276
+ return state.initialScrollSession;
1277
+ }
1278
+
1279
+ // src/utils/checkThreshold.ts
1280
+ var HYSTERESIS_MULTIPLIER = 1.3;
1281
+ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot, allowReentryOnChange) => {
1282
+ const absDistance = Math.abs(distance);
1283
+ const within = atThreshold || threshold > 0 && absDistance <= threshold;
1284
+ const updateSnapshot = () => {
1285
+ setSnapshot({
1286
+ atThreshold,
1287
+ contentSize: context.contentSize,
1288
+ dataLength: context.dataLength,
1289
+ scrollPosition: context.scrollPosition
1290
+ });
1291
+ };
1292
+ if (!wasReached) {
1293
+ if (!within) {
1294
+ return false;
1295
+ }
1296
+ onReached(distance);
1297
+ updateSnapshot();
1298
+ return true;
1299
+ }
1300
+ const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
1301
+ if (reset) {
1302
+ setSnapshot(void 0);
1303
+ return false;
1304
+ }
1305
+ if (within) {
1306
+ const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
1307
+ if (changed) {
1308
+ if (allowReentryOnChange) {
1309
+ onReached(distance);
1310
+ }
1311
+ updateSnapshot();
1312
+ }
1313
+ }
1314
+ return true;
1315
+ };
1316
+
1317
+ // src/utils/hasActiveInitialScroll.ts
1318
+ function hasActiveInitialScroll(state) {
1319
+ return !!(state == null ? void 0 : state.initialScroll) && !state.didFinishInitialScroll;
1320
+ }
1321
+
1322
+ // src/utils/checkAtBottom.ts
1323
+ function checkAtBottom(ctx) {
1324
+ var _a3;
1325
+ const state = ctx.state;
1326
+ if (!state) {
1327
+ return;
1328
+ }
1329
+ const {
1330
+ queuedInitialLayout,
1331
+ scrollLength,
1332
+ scroll,
1333
+ maintainingScrollAtEnd,
1334
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1335
+ } = state;
1336
+ const contentSize = getContentSize(ctx);
1337
+ if (contentSize > 0 && queuedInitialLayout) {
1338
+ const insetEnd = getContentInsetEnd(ctx);
1339
+ const distanceFromEnd = contentSize - scroll - scrollLength - insetEnd;
1340
+ const isContentLess = contentSize < scrollLength;
1341
+ set$(ctx, "isAtEnd", isContentLess || distanceFromEnd <= EDGE_POSITION_EPSILON);
1342
+ set$(ctx, "isNearEnd", isContentLess || distanceFromEnd <= onEndReachedThreshold * scrollLength);
1343
+ set$(
1344
+ ctx,
1345
+ "isWithinMaintainScrollAtEndThreshold",
1346
+ isContentLess || distanceFromEnd <= maintainScrollAtEndThreshold * scrollLength
1347
+ );
1348
+ const shouldSkipThresholdChecks = hasActiveInitialScroll(state) || maintainingScrollAtEnd;
1349
+ if (!shouldSkipThresholdChecks) {
1350
+ state.isEndReached = checkThreshold(
1351
+ distanceFromEnd,
1352
+ isContentLess,
1353
+ onEndReachedThreshold * scrollLength,
1354
+ state.isEndReached,
1355
+ state.endReachedSnapshot,
1356
+ {
1357
+ contentSize,
1358
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1359
+ scrollPosition: scroll
1360
+ },
1361
+ (distance) => {
1362
+ var _a4, _b;
1363
+ return (_b = (_a4 = state.props).onEndReached) == null ? void 0 : _b.call(_a4, { distanceFromEnd: distance });
1364
+ },
1365
+ (snapshot) => {
1366
+ state.endReachedSnapshot = snapshot;
1367
+ },
1368
+ true
1369
+ );
1370
+ }
1371
+ }
1372
+ }
1373
+
1374
+ // src/utils/checkAtTop.ts
1375
+ function checkAtTop(ctx) {
1376
+ const state = ctx == null ? void 0 : ctx.state;
1377
+ if (!state) {
1378
+ return;
1379
+ }
1380
+ const {
1381
+ dataChangeEpoch,
1382
+ isStartReached,
1383
+ props: { data, onStartReachedThreshold },
1384
+ scroll,
1385
+ scrollLength,
1386
+ startReachedSnapshot,
1387
+ startReachedSnapshotDataChangeEpoch,
1388
+ totalSize
1389
+ } = state;
1390
+ const dataLength = data.length;
1391
+ const threshold = onStartReachedThreshold * scrollLength;
1392
+ const dataChanged = startReachedSnapshotDataChangeEpoch !== dataChangeEpoch;
1393
+ const withinThreshold = threshold > 0 && Math.abs(scroll) <= threshold;
1394
+ const allowReentryOnDataChange = !!isStartReached && withinThreshold && !!dataChanged && !isInMVCPActiveMode(state);
1395
+ if (isStartReached && threshold > 0 && scroll > threshold && startReachedSnapshot && (dataChanged || startReachedSnapshot.contentSize !== totalSize || startReachedSnapshot.dataLength !== dataLength)) {
1396
+ state.isStartReached = false;
1397
+ state.startReachedSnapshot = void 0;
1398
+ state.startReachedSnapshotDataChangeEpoch = void 0;
1399
+ }
1400
+ set$(ctx, "isAtStart", scroll <= EDGE_POSITION_EPSILON);
1401
+ set$(ctx, "isNearStart", scroll <= threshold);
1402
+ const shouldSkipThresholdChecks = hasActiveInitialScroll(state) || !!state.scrollingTo;
1403
+ const shouldDeferDataChangeRefire = isStartReached && withinThreshold && dataChanged && !allowReentryOnDataChange;
1404
+ if (!shouldSkipThresholdChecks && !shouldDeferDataChangeRefire) {
1405
+ state.isStartReached = checkThreshold(
1406
+ scroll,
1407
+ false,
1408
+ threshold,
1409
+ state.isStartReached,
1410
+ allowReentryOnDataChange ? void 0 : startReachedSnapshot,
1411
+ {
1412
+ contentSize: totalSize,
1413
+ dataLength,
1414
+ scrollPosition: scroll
1415
+ },
1416
+ (distance) => {
1417
+ var _a3, _b;
1418
+ return (_b = (_a3 = state.props).onStartReached) == null ? void 0 : _b.call(_a3, { distanceFromStart: distance });
1419
+ },
1420
+ (snapshot) => {
1421
+ state.startReachedSnapshot = snapshot;
1422
+ state.startReachedSnapshotDataChangeEpoch = snapshot ? dataChangeEpoch : void 0;
1423
+ },
1424
+ allowReentryOnDataChange
1425
+ );
1426
+ }
1427
+ }
1428
+
1429
+ // src/utils/checkThresholds.ts
1430
+ function checkThresholds(ctx) {
1431
+ checkAtBottom(ctx);
1432
+ checkAtTop(ctx);
1433
+ }
1434
+
1435
+ // src/core/recalculateSettledScroll.ts
1436
+ function recalculateSettledScroll(ctx) {
1437
+ var _a3, _b;
1438
+ const state = ctx.state;
1439
+ if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1440
+ (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1441
+ }
1442
+ checkThresholds(ctx);
1443
+ }
1444
+
1445
+ // src/utils/setInitialRenderState.ts
1446
+ function setInitialRenderState(ctx, {
1447
+ didLayout,
1448
+ didInitialScroll
1449
+ }) {
1450
+ const { state } = ctx;
1451
+ const {
1452
+ loadStartTime,
1453
+ props: { onLoad }
1454
+ } = state;
1455
+ if (didLayout) {
1456
+ state.didContainersLayout = true;
1457
+ }
1458
+ if (didInitialScroll) {
1459
+ state.didFinishInitialScroll = true;
1460
+ }
1461
+ const isReadyToRender = Boolean(state.didContainersLayout && state.didFinishInitialScroll);
1462
+ if (isReadyToRender && !peek$(ctx, "readyToRender")) {
1463
+ set$(ctx, "readyToRender", true);
1464
+ if (onLoad) {
1465
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1466
+ }
1467
+ }
1468
+ }
1469
+
1470
+ // src/core/finishInitialScroll.ts
1471
+ var PRESERVED_INITIAL_SCROLL_FALLBACK_CLEAR_DELAY_MS = 2e3;
1472
+ function syncInitialScrollOffset(state, offset) {
1473
+ state.scroll = offset;
1474
+ state.scrollPending = offset;
1475
+ state.scrollPrev = offset;
1476
+ }
1477
+ function clearPreservedInitialScrollTargetTimeout(state) {
1478
+ if (state.timeoutPreservedInitialScrollClear !== void 0) {
1479
+ clearTimeout(state.timeoutPreservedInitialScrollClear);
1480
+ state.timeoutPreservedInitialScrollClear = void 0;
1481
+ }
1482
+ }
1483
+ function clearPreservedInitialScrollTarget(state) {
1484
+ clearPreservedInitialScrollTargetTimeout(state);
1485
+ state.clearPreservedInitialScrollOnNextFinish = void 0;
1486
+ state.initialScroll = void 0;
1487
+ setInitialScrollSession(state);
1488
+ }
1489
+ function finishInitialScroll(ctx, options) {
1490
+ var _a3, _b, _c;
1491
+ const state = ctx.state;
1492
+ if ((options == null ? void 0 : options.resolvedOffset) !== void 0) {
1493
+ syncInitialScrollOffset(state, options.resolvedOffset);
1494
+ } else if ((options == null ? void 0 : options.syncObservedOffset) && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset") {
1495
+ const observedOffset = (_c = (_b = state.refScroller.current) == null ? void 0 : _b.getCurrentScrollOffset) == null ? void 0 : _c.call(_b);
1496
+ if (typeof observedOffset === "number" && Number.isFinite(observedOffset)) {
1497
+ syncInitialScrollOffset(state, observedOffset);
1498
+ }
1499
+ }
1500
+ const complete = () => {
1501
+ var _a4, _b2, _c2, _d, _e;
1502
+ const shouldReleaseDeferredPublicOnScroll = Platform2.OS === "web" && ((_a4 = state.initialScrollSession) == null ? void 0 : _a4.kind) === "bootstrap";
1503
+ const finalScrollOffset = (_d = (_c2 = (_b2 = options == null ? void 0 : options.resolvedOffset) != null ? _b2 : state.scrollPending) != null ? _c2 : state.scroll) != null ? _d : 0;
1504
+ initialScrollWatchdog.clear(state);
1505
+ if ((options == null ? void 0 : options.preserveTarget) && state.initialScroll) {
1506
+ state.clearPreservedInitialScrollOnNextFinish = void 0;
1507
+ setInitialScrollSession(state);
1508
+ clearPreservedInitialScrollTargetTimeout(state);
1509
+ if (options == null ? void 0 : options.schedulePreservedTargetClear) {
1510
+ state.timeoutPreservedInitialScrollClear = setTimeout(() => {
1511
+ var _a5;
1512
+ state.timeoutPreservedInitialScrollClear = void 0;
1513
+ if (!state.didFinishInitialScroll || ((_a5 = state.scrollingTo) == null ? void 0 : _a5.isInitialScroll) || !state.initialScroll) {
1514
+ return;
1515
+ }
1516
+ clearPreservedInitialScrollTarget(state);
1517
+ }, PRESERVED_INITIAL_SCROLL_FALLBACK_CLEAR_DELAY_MS);
1518
+ }
1519
+ } else {
1520
+ clearPreservedInitialScrollTarget(state);
1521
+ }
1522
+ if (options == null ? void 0 : options.recalculateItems) {
1523
+ recalculateSettledScroll(ctx);
1524
+ }
1525
+ setInitialRenderState(ctx, { didInitialScroll: true });
1526
+ if (shouldReleaseDeferredPublicOnScroll) {
1527
+ releaseDeferredPublicOnScroll(ctx, finalScrollOffset);
1528
+ }
1529
+ (_e = options == null ? void 0 : options.onFinished) == null ? void 0 : _e.call(options);
1530
+ };
1531
+ if (options == null ? void 0 : options.waitForCompletionFrame) {
1532
+ requestAnimationFrame(complete);
1533
+ return;
1534
+ }
1535
+ complete();
1536
+ }
1537
+
1538
+ // src/core/calculateOffsetForIndex.ts
1539
+ function calculateOffsetForIndex(ctx, index) {
1540
+ const state = ctx.state;
1541
+ return index !== void 0 ? state.positions[index] || 0 : 0;
1542
+ }
1543
+
1544
+ // src/core/getTopOffsetAdjustment.ts
1545
+ function getTopOffsetAdjustment(ctx) {
1546
+ return (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1547
+ }
1548
+
1549
+ // src/utils/getId.ts
1550
+ function getId(state, index) {
1551
+ const { data, keyExtractor } = state.props;
1552
+ if (!data) {
1553
+ return "";
1554
+ }
1555
+ const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
1556
+ const id = ret;
1557
+ state.idCache[index] = id;
1558
+ return id;
1559
+ }
1560
+
1561
+ // src/core/addTotalSize.ts
1562
+ function addTotalSize(ctx, key, add) {
1563
+ const state = ctx.state;
1564
+ const prevTotalSize = state.totalSize;
1565
+ let totalSize = state.totalSize;
1566
+ if (key === null) {
1567
+ totalSize = add;
1568
+ if (state.timeoutSetPaddingTop) {
1569
+ clearTimeout(state.timeoutSetPaddingTop);
1570
+ state.timeoutSetPaddingTop = void 0;
1571
+ }
1572
+ } else {
1573
+ totalSize += add;
1574
+ }
1575
+ if (prevTotalSize !== totalSize) {
1576
+ if (!IsNewArchitecture && state.initialScroll && totalSize < prevTotalSize) {
1577
+ state.pendingTotalSize = totalSize;
1578
+ } else {
1579
+ state.pendingTotalSize = void 0;
1580
+ state.totalSize = totalSize;
1581
+ set$(ctx, "totalSize", totalSize);
1582
+ }
1583
+ }
1584
+ }
1585
+
1586
+ // src/core/setSize.ts
1587
+ function setSize(ctx, itemKey, size) {
1588
+ const state = ctx.state;
1589
+ const { sizes } = state;
1590
+ const previousSize = sizes.get(itemKey);
1591
+ const diff = previousSize !== void 0 ? size - previousSize : size;
1592
+ if (diff !== 0) {
1593
+ addTotalSize(ctx, itemKey, diff);
1594
+ }
1595
+ sizes.set(itemKey, size);
1596
+ }
1597
+
1598
+ // src/utils/getItemSize.ts
1599
+ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1600
+ var _a3, _b, _c;
1601
+ const state = ctx.state;
1602
+ const {
1603
+ sizesKnown,
1604
+ sizes,
1605
+ averageSizes,
1606
+ props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType },
1607
+ scrollingTo
1608
+ } = state;
1609
+ const sizeKnown = sizesKnown.get(key);
1610
+ if (sizeKnown !== void 0) {
1611
+ return sizeKnown;
1612
+ }
1613
+ let size;
1614
+ const renderedSize = sizes.get(key);
1615
+ if (preferCachedSize) {
1616
+ if (renderedSize !== void 0) {
1617
+ return renderedSize;
1618
+ }
1619
+ }
1620
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1621
+ if (getFixedItemSize) {
1622
+ size = getFixedItemSize(data, index, itemType);
1623
+ if (size !== void 0) {
1624
+ sizesKnown.set(key, size);
1625
+ }
1626
+ }
1627
+ if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
1628
+ const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
1629
+ if (averageSizeForType !== void 0) {
1630
+ size = roundSize(averageSizeForType);
1631
+ }
1274
1632
  }
1275
- };
1276
- var initialScrollWatchdog = {
1277
- clear(state) {
1278
- initialScrollWatchdog.set(state, void 0);
1279
- },
1280
- didObserveProgress(newScroll, watchdog) {
1281
- const previousDistance = Math.abs(watchdog.startScroll - watchdog.targetOffset);
1282
- const nextDistance = Math.abs(newScroll - watchdog.targetOffset);
1283
- return nextDistance <= INITIAL_SCROLL_MIN_TARGET_OFFSET || nextDistance + INITIAL_SCROLL_MIN_TARGET_OFFSET < previousDistance;
1284
- },
1285
- get(state) {
1286
- var _a3, _b;
1287
- return (_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.watchdog;
1288
- },
1289
- hasNonZeroTargetOffset(targetOffset) {
1290
- return targetOffset !== void 0 && targetOffset > INITIAL_SCROLL_MIN_TARGET_OFFSET;
1291
- },
1292
- isAtZeroTargetOffset(targetOffset) {
1293
- return targetOffset <= INITIAL_SCROLL_MIN_TARGET_OFFSET;
1294
- },
1295
- set(state, watchdog) {
1296
- var _a3, _b;
1297
- if (!watchdog && !((_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.completion) == null ? void 0 : _b.watchdog)) {
1298
- return;
1633
+ if (size === void 0 && renderedSize !== void 0) {
1634
+ return renderedSize;
1635
+ }
1636
+ if (size === void 0 && useAverageSize && sizeKnown === void 0 && scrollingTo) {
1637
+ const averageSizeForType = (_c = scrollingTo.averageSizeSnapshot) == null ? void 0 : _c[itemType];
1638
+ if (averageSizeForType !== void 0) {
1639
+ size = roundSize(averageSizeForType);
1299
1640
  }
1300
- const completion = ensureInitialScrollSessionCompletion(state);
1301
- completion.watchdog = watchdog ? {
1302
- startScroll: watchdog.startScroll,
1303
- targetOffset: watchdog.targetOffset
1304
- } : void 0;
1305
1641
  }
1306
- };
1307
- function setInitialScrollSession(state, options = {}) {
1308
- var _a3, _b, _c;
1309
- const existingSession = state.initialScrollSession;
1310
- const kind = (_a3 = options.kind) != null ? _a3 : existingSession == null ? void 0 : existingSession.kind;
1311
- const completion = existingSession == null ? void 0 : existingSession.completion;
1312
- const hasBootstrapOverride = Object.hasOwn(options, "bootstrap");
1313
- const bootstrap = kind === "bootstrap" ? hasBootstrapOverride ? options.bootstrap : (existingSession == null ? void 0 : existingSession.kind) === "bootstrap" ? existingSession.bootstrap : void 0 : void 0;
1314
- if (!kind) {
1315
- return clearInitialScrollSession(state);
1642
+ if (size === void 0) {
1643
+ size = getEstimatedItemSize ? getEstimatedItemSize(data, index, itemType) : estimatedItemSize;
1316
1644
  }
1317
- if (!state.initialScroll && !bootstrap && !hasInitialScrollSessionCompletion(completion)) {
1318
- return clearInitialScrollSession(state);
1645
+ setSize(ctx, key, size);
1646
+ return size;
1647
+ }
1648
+ function getItemSizeAtIndex(ctx, index) {
1649
+ if (index === void 0 || index < 0) {
1650
+ return void 0;
1319
1651
  }
1320
- const previousDataLength = (_c = (_b = options.previousDataLength) != null ? _b : existingSession == null ? void 0 : existingSession.previousDataLength) != null ? _c : 0;
1321
- state.initialScrollSession = createInitialScrollSession({
1322
- bootstrap,
1323
- completion,
1324
- kind,
1325
- previousDataLength
1326
- });
1327
- return state.initialScrollSession;
1652
+ const targetId = getId(ctx.state, index);
1653
+ return getItemSize(ctx, targetId, index, ctx.state.props.data[index]);
1654
+ }
1655
+
1656
+ // src/core/calculateOffsetWithOffsetPosition.ts
1657
+ function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
1658
+ var _a3;
1659
+ const state = ctx.state;
1660
+ const { index, viewOffset, viewPosition } = params;
1661
+ let offset = offsetParam;
1662
+ if (viewOffset) {
1663
+ offset -= viewOffset;
1664
+ }
1665
+ if (index !== void 0) {
1666
+ const topOffsetAdjustment = getTopOffsetAdjustment(ctx);
1667
+ if (topOffsetAdjustment) {
1668
+ offset += topOffsetAdjustment;
1669
+ }
1670
+ }
1671
+ if (viewPosition !== void 0 && index !== void 0) {
1672
+ const dataLength = state.props.data.length;
1673
+ if (dataLength === 0) {
1674
+ return offset;
1675
+ }
1676
+ const isOutOfBounds = index < 0 || index >= dataLength;
1677
+ const fallbackEstimatedSize = (_a3 = state.props.estimatedItemSize) != null ? _a3 : 0;
1678
+ const itemSize = isOutOfBounds ? fallbackEstimatedSize : getItemSize(ctx, getId(state, index), index, state.props.data[index]);
1679
+ const trailingInset = getContentInsetEnd(ctx);
1680
+ offset -= viewPosition * (state.scrollLength - trailingInset - itemSize);
1681
+ if (!isOutOfBounds && index === state.props.data.length - 1) {
1682
+ const footerSize = peek$(ctx, "footerSize") || 0;
1683
+ offset += footerSize;
1684
+ }
1685
+ }
1686
+ return offset;
1687
+ }
1688
+
1689
+ // src/core/clampScrollOffset.ts
1690
+ function clampScrollOffset(ctx, offset, scrollTarget) {
1691
+ const state = ctx.state;
1692
+ const contentSize = getContentSize(ctx);
1693
+ let clampedOffset = offset;
1694
+ if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength) && (Platform2.OS !== "android" || state.lastLayout)) {
1695
+ const baseMaxOffset = Math.max(0, contentSize - state.scrollLength);
1696
+ const viewOffset = scrollTarget == null ? void 0 : scrollTarget.viewOffset;
1697
+ const extraEndOffset = typeof viewOffset === "number" && viewOffset < 0 ? -viewOffset : 0;
1698
+ const maxOffset = baseMaxOffset + extraEndOffset;
1699
+ clampedOffset = Math.min(offset, maxOffset);
1700
+ }
1701
+ clampedOffset = Math.max(0, clampedOffset);
1702
+ return clampedOffset;
1328
1703
  }
1329
1704
 
1330
1705
  // src/core/finishScrollTo.ts
@@ -1345,15 +1720,20 @@ function finishScrollTo(ctx) {
1345
1720
  }
1346
1721
  if (scrollingTo.isInitialScroll || state.initialScroll) {
1347
1722
  const isOffsetSession = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset";
1723
+ const shouldPreserveResizeTarget = !!scrollingTo.isInitialScroll && !state.clearPreservedInitialScrollOnNextFinish && state.props.data.length > 0 && ((_b = state.initialScroll) == null ? void 0 : _b.viewPosition) === 1;
1348
1724
  finishInitialScroll(ctx, {
1349
- onFinished: resolvePendingScroll,
1350
- preserveTarget: isOffsetSession && state.props.data.length === 0 || !!scrollingTo.isInitialScroll && !!((_b = state.initialScroll) == null ? void 0 : _b.preserveForFooterLayout),
1725
+ onFinished: () => {
1726
+ resolvePendingScroll == null ? void 0 : resolvePendingScroll();
1727
+ },
1728
+ preserveTarget: isOffsetSession && state.props.data.length === 0 || shouldPreserveResizeTarget,
1351
1729
  recalculateItems: true,
1730
+ schedulePreservedTargetClear: shouldPreserveResizeTarget,
1352
1731
  syncObservedOffset: isOffsetSession,
1353
1732
  waitForCompletionFrame: !!scrollingTo.waitForInitialScrollCompletionFrame
1354
1733
  });
1355
1734
  return;
1356
1735
  }
1736
+ recalculateSettledScroll(ctx);
1357
1737
  resolvePendingScroll == null ? void 0 : resolvePendingScroll();
1358
1738
  }
1359
1739
  }
@@ -1528,6 +1908,17 @@ function doScrollTo(ctx, params) {
1528
1908
  }
1529
1909
 
1530
1910
  // src/core/scrollTo.ts
1911
+ function getAverageSizeSnapshot(state) {
1912
+ if (Object.keys(state.averageSizes).length === 0) {
1913
+ return void 0;
1914
+ }
1915
+ const snapshot = {};
1916
+ for (const itemType in state.averageSizes) {
1917
+ const averages = state.averageSizes[itemType];
1918
+ snapshot[itemType] = averages.avg;
1919
+ }
1920
+ return snapshot;
1921
+ }
1531
1922
  function syncInitialScrollNativeWatchdog(state, options) {
1532
1923
  var _a3;
1533
1924
  const { isInitialScroll, requestedOffset, targetOffset } = options;
@@ -1575,8 +1966,10 @@ function scrollTo(ctx, params) {
1575
1966
  if (isInitialScroll) {
1576
1967
  initialScrollCompletion.resetFlags(state);
1577
1968
  }
1969
+ const averageSizeSnapshot = getAverageSizeSnapshot(state);
1578
1970
  state.scrollingTo = {
1579
1971
  ...scrollTarget,
1972
+ ...averageSizeSnapshot ? { averageSizeSnapshot } : {},
1580
1973
  targetOffset,
1581
1974
  waitForInitialScrollCompletionFrame
1582
1975
  };
@@ -1630,183 +2023,10 @@ function scrollToIndex(ctx, {
1630
2023
  offset: firstIndexOffset,
1631
2024
  viewOffset,
1632
2025
  viewPosition: viewPosition != null ? viewPosition : 0
1633
- });
1634
- }
1635
-
1636
- // src/utils/checkThreshold.ts
1637
- var HYSTERESIS_MULTIPLIER = 1.3;
1638
- var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot, allowReentryOnChange) => {
1639
- const absDistance = Math.abs(distance);
1640
- const within = atThreshold || threshold > 0 && absDistance <= threshold;
1641
- const updateSnapshot = () => {
1642
- setSnapshot({
1643
- atThreshold,
1644
- contentSize: context.contentSize,
1645
- dataLength: context.dataLength,
1646
- scrollPosition: context.scrollPosition
1647
- });
1648
- };
1649
- if (!wasReached) {
1650
- if (!within) {
1651
- return false;
1652
- }
1653
- onReached(distance);
1654
- updateSnapshot();
1655
- return true;
1656
- }
1657
- const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
1658
- if (reset) {
1659
- setSnapshot(void 0);
1660
- return false;
1661
- }
1662
- if (within) {
1663
- const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
1664
- if (changed) {
1665
- if (allowReentryOnChange) {
1666
- onReached(distance);
1667
- }
1668
- updateSnapshot();
1669
- }
1670
- }
1671
- return true;
1672
- };
1673
-
1674
- // src/utils/checkAtBottom.ts
1675
- function checkAtBottom(ctx) {
1676
- var _a3;
1677
- const state = ctx.state;
1678
- if (!state || state.initialScroll) {
1679
- return;
1680
- }
1681
- const {
1682
- queuedInitialLayout,
1683
- scrollLength,
1684
- scroll,
1685
- maintainingScrollAtEnd,
1686
- props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1687
- } = state;
1688
- if (state.initialScroll) {
1689
- return;
1690
- }
1691
- const contentSize = getContentSize(ctx);
1692
- if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1693
- const insetEnd = getContentInsetEnd(state);
1694
- const distanceFromEnd = contentSize - scroll - scrollLength - insetEnd;
1695
- const isContentLess = contentSize < scrollLength;
1696
- state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1697
- state.isEndReached = checkThreshold(
1698
- distanceFromEnd,
1699
- isContentLess,
1700
- onEndReachedThreshold * scrollLength,
1701
- state.isEndReached,
1702
- state.endReachedSnapshot,
1703
- {
1704
- contentSize,
1705
- dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1706
- scrollPosition: scroll
1707
- },
1708
- (distance) => {
1709
- var _a4, _b;
1710
- return (_b = (_a4 = state.props).onEndReached) == null ? void 0 : _b.call(_a4, { distanceFromEnd: distance });
1711
- },
1712
- (snapshot) => {
1713
- state.endReachedSnapshot = snapshot;
1714
- },
1715
- true
1716
- );
1717
- }
1718
- }
1719
-
1720
- // src/utils/checkAtTop.ts
1721
- function checkAtTop(ctx) {
1722
- const state = ctx == null ? void 0 : ctx.state;
1723
- if (!state || state.initialScroll || state.scrollingTo) {
1724
- return;
1725
- }
1726
- const {
1727
- dataChangeEpoch,
1728
- isStartReached,
1729
- props: { data, onStartReachedThreshold },
1730
- scroll,
1731
- scrollLength,
1732
- startReachedSnapshot,
1733
- startReachedSnapshotDataChangeEpoch,
1734
- totalSize
1735
- } = state;
1736
- const dataLength = data.length;
1737
- const threshold = onStartReachedThreshold * scrollLength;
1738
- const dataChanged = startReachedSnapshotDataChangeEpoch !== dataChangeEpoch;
1739
- const withinThreshold = threshold > 0 && Math.abs(scroll) <= threshold;
1740
- const allowReentryOnDataChange = !!isStartReached && withinThreshold && !!dataChanged && !isInMVCPActiveMode(state);
1741
- if (isStartReached && threshold > 0 && scroll > threshold && startReachedSnapshot && (dataChanged || startReachedSnapshot.contentSize !== totalSize || startReachedSnapshot.dataLength !== dataLength)) {
1742
- state.isStartReached = false;
1743
- state.startReachedSnapshot = void 0;
1744
- state.startReachedSnapshotDataChangeEpoch = void 0;
1745
- }
1746
- state.isAtStart = scroll <= 0;
1747
- if (isStartReached && withinThreshold && dataChanged && !allowReentryOnDataChange) {
1748
- return;
1749
- }
1750
- state.isStartReached = checkThreshold(
1751
- scroll,
1752
- false,
1753
- threshold,
1754
- state.isStartReached,
1755
- allowReentryOnDataChange ? void 0 : startReachedSnapshot,
1756
- {
1757
- contentSize: totalSize,
1758
- dataLength,
1759
- scrollPosition: scroll
1760
- },
1761
- (distance) => {
1762
- var _a3, _b;
1763
- return (_b = (_a3 = state.props).onStartReached) == null ? void 0 : _b.call(_a3, { distanceFromStart: distance });
1764
- },
1765
- (snapshot) => {
1766
- state.startReachedSnapshot = snapshot;
1767
- state.startReachedSnapshotDataChangeEpoch = snapshot ? dataChangeEpoch : void 0;
1768
- },
1769
- allowReentryOnDataChange
1770
- );
1771
- }
1772
-
1773
- // src/utils/checkThresholds.ts
1774
- function checkThresholds(ctx) {
1775
- checkAtBottom(ctx);
1776
- checkAtTop(ctx);
1777
- }
1778
-
1779
- // src/utils/setInitialRenderState.ts
1780
- function setInitialRenderState(ctx, {
1781
- didLayout,
1782
- didInitialScroll
1783
- }) {
1784
- const { state } = ctx;
1785
- const {
1786
- loadStartTime,
1787
- props: { onLoad }
1788
- } = state;
1789
- if (didLayout) {
1790
- state.didContainersLayout = true;
1791
- }
1792
- if (didInitialScroll) {
1793
- state.didFinishInitialScroll = true;
1794
- }
1795
- const isReadyToRender = Boolean(state.didContainersLayout && state.didFinishInitialScroll);
1796
- if (isReadyToRender && !peek$(ctx, "readyToRender")) {
1797
- set$(ctx, "readyToRender", true);
1798
- if (onLoad) {
1799
- onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1800
- }
1801
- }
2026
+ });
1802
2027
  }
1803
2028
 
1804
2029
  // src/core/initialScroll.ts
1805
- function syncInitialScrollOffset(state, offset) {
1806
- state.scroll = offset;
1807
- state.scrollPending = offset;
1808
- state.scrollPrev = offset;
1809
- }
1810
2030
  function dispatchInitialScroll(ctx, params) {
1811
2031
  const { forceScroll, resolvedOffset, target, waitForCompletionFrame } = params;
1812
2032
  const requestedIndex = target.index;
@@ -1827,6 +2047,11 @@ function dispatchInitialScroll(ctx, params) {
1827
2047
  }
1828
2048
  function setInitialScrollTarget(state, target, options) {
1829
2049
  var _a3;
2050
+ state.clearPreservedInitialScrollOnNextFinish = void 0;
2051
+ if (state.timeoutPreservedInitialScrollClear !== void 0) {
2052
+ clearTimeout(state.timeoutPreservedInitialScrollClear);
2053
+ state.timeoutPreservedInitialScrollClear = void 0;
2054
+ }
1830
2055
  state.initialScroll = target;
1831
2056
  if ((options == null ? void 0 : options.resetDidFinish) && state.didFinishInitialScroll) {
1832
2057
  state.didFinishInitialScroll = false;
@@ -1835,44 +2060,6 @@ function setInitialScrollTarget(state, target, options) {
1835
2060
  kind: ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset" ? "offset" : "bootstrap"
1836
2061
  });
1837
2062
  }
1838
- function finishInitialScroll(ctx, options) {
1839
- var _a3, _b, _c;
1840
- const state = ctx.state;
1841
- if ((options == null ? void 0 : options.resolvedOffset) !== void 0) {
1842
- syncInitialScrollOffset(state, options.resolvedOffset);
1843
- } else if ((options == null ? void 0 : options.syncObservedOffset) && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset") {
1844
- const observedOffset = (_c = (_b = state.refScroller.current) == null ? void 0 : _b.getCurrentScrollOffset) == null ? void 0 : _c.call(_b);
1845
- if (typeof observedOffset === "number" && Number.isFinite(observedOffset)) {
1846
- syncInitialScrollOffset(state, observedOffset);
1847
- }
1848
- }
1849
- const complete = () => {
1850
- var _a4, _b2, _c2, _d, _e, _f, _g;
1851
- const shouldReleaseDeferredPublicOnScroll = Platform2.OS === "web" && ((_a4 = state.initialScrollSession) == null ? void 0 : _a4.kind) === "bootstrap";
1852
- const finalScrollOffset = (_d = (_c2 = (_b2 = options == null ? void 0 : options.resolvedOffset) != null ? _b2 : state.scrollPending) != null ? _c2 : state.scroll) != null ? _d : 0;
1853
- initialScrollWatchdog.clear(state);
1854
- if (!(options == null ? void 0 : options.preserveTarget)) {
1855
- state.initialScroll = void 0;
1856
- }
1857
- setInitialScrollSession(state);
1858
- if ((options == null ? void 0 : options.recalculateItems) && ((_e = state.props) == null ? void 0 : _e.data)) {
1859
- (_f = state.triggerCalculateItemsInView) == null ? void 0 : _f.call(state, { forceFullItemPositions: true });
1860
- }
1861
- if (options == null ? void 0 : options.recalculateItems) {
1862
- checkThresholds(ctx);
1863
- }
1864
- setInitialRenderState(ctx, { didInitialScroll: true });
1865
- if (shouldReleaseDeferredPublicOnScroll) {
1866
- releaseDeferredPublicOnScroll(ctx, finalScrollOffset);
1867
- }
1868
- (_g = options == null ? void 0 : options.onFinished) == null ? void 0 : _g.call(options);
1869
- };
1870
- if (options == null ? void 0 : options.waitForCompletionFrame) {
1871
- requestAnimationFrame(complete);
1872
- return;
1873
- }
1874
- complete();
1875
- }
1876
2063
  function resolveInitialScrollOffset(ctx, initialScroll) {
1877
2064
  var _a3, _b;
1878
2065
  const state = ctx.state;
@@ -1966,13 +2153,18 @@ function advanceCurrentInitialScrollSession(ctx, options) {
1966
2153
  function isNullOrUndefined2(value) {
1967
2154
  return value === null || value === void 0;
1968
2155
  }
1969
- function getMountedBufferedIndices(state) {
1970
- const { startBuffered, endBuffered } = state;
1971
- if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
1972
- return Array.from(state.containerItemKeys.keys()).map((key) => state.indexByKey.get(key)).filter((index) => index !== void 0 && index >= startBuffered && index <= endBuffered).sort((a, b) => a - b);
2156
+ function getMountedIndicesInRange(state, start, end) {
2157
+ if (!isNullOrUndefined2(end) && !isNullOrUndefined2(start) && start >= 0 && end >= 0) {
2158
+ return Array.from(state.containerItemKeys.keys()).map((key) => state.indexByKey.get(key)).filter((index) => index !== void 0 && index >= start && index <= end).sort((a, b) => a - b);
1973
2159
  }
1974
2160
  return [];
1975
2161
  }
2162
+ function getMountedBufferedIndices(state) {
2163
+ return getMountedIndicesInRange(state, state.startBuffered, state.endBuffered);
2164
+ }
2165
+ function getMountedNoBufferIndices(state) {
2166
+ return getMountedIndicesInRange(state, state.startNoBuffer, state.endNoBuffer);
2167
+ }
1976
2168
  function checkAllSizesKnown(state, indices = getMountedBufferedIndices(state)) {
1977
2169
  return indices.length > 0 && indices.every((index) => {
1978
2170
  const key = getId(state, index);
@@ -2191,16 +2383,22 @@ function createRetargetedBottomAlignedInitialScroll(options) {
2191
2383
  function areEquivalentBootstrapInitialScrollTargets(current, next) {
2192
2384
  return current.index === next.index && current.preserveForBottomPadding === next.preserveForBottomPadding && current.preserveForFooterLayout === next.preserveForFooterLayout && current.viewOffset === next.viewOffset && current.viewPosition === next.viewPosition;
2193
2385
  }
2194
- function clearPendingInitialScrollFooterLayout(state, target) {
2386
+ function clearPendingInitialScrollFooterLayout(ctx, options) {
2387
+ const { dataLength, stylePaddingBottom, target } = options;
2388
+ const state = ctx.state;
2195
2389
  if (!shouldPreserveInitialScrollForFooterLayout(target)) {
2196
2390
  return;
2197
2391
  }
2198
- if (state.didFinishInitialScroll && !getBootstrapInitialScrollSession(state)) {
2199
- state.initialScroll = void 0;
2200
- setInitialScrollSession(state);
2201
- return;
2202
- }
2203
- setInitialScrollTarget(state, { ...target, preserveForFooterLayout: void 0 });
2392
+ const clearedFooterTarget = createInitialScrollAtEndTarget({
2393
+ dataLength,
2394
+ footerSize: 0,
2395
+ preserveForFooterLayout: void 0,
2396
+ stylePaddingBottom
2397
+ });
2398
+ setInitialScrollTarget(state, clearedFooterTarget);
2399
+ }
2400
+ function clearFinishedViewportRetargetableInitialScroll(state) {
2401
+ clearPreservedInitialScrollTarget(state);
2204
2402
  }
2205
2403
  function didFinishedInitialScrollMoveAwayFromTarget(ctx, target, epsilon = DEFAULT_BOOTSTRAP_REVEAL_EPSILON) {
2206
2404
  const state = ctx.state;
@@ -2215,6 +2413,25 @@ function getObservedBootstrapInitialScrollOffset(state) {
2215
2413
  const observedOffset = (_b = (_a3 = state.refScroller.current) == null ? void 0 : _a3.getCurrentScrollOffset) == null ? void 0 : _b.call(_a3);
2216
2414
  return typeof observedOffset === "number" && Number.isFinite(observedOffset) ? observedOffset : (_d = (_c = state.scrollPending) != null ? _c : state.scroll) != null ? _d : 0;
2217
2415
  }
2416
+ function clearFinishedBootstrapInitialScrollTargetIfMovedAway(ctx) {
2417
+ var _a3, _b;
2418
+ const state = ctx.state;
2419
+ const initialScroll = state.initialScroll;
2420
+ if (!state.didFinishInitialScroll || ((_a3 = state.scrollingTo) == null ? void 0 : _a3.isInitialScroll) || (initialScroll == null ? void 0 : initialScroll.viewPosition) !== 1) {
2421
+ return;
2422
+ }
2423
+ if (didFinishedInitialScrollMoveAwayFromTarget(ctx, initialScroll)) {
2424
+ if (shouldPreserveInitialScrollForFooterLayout(initialScroll)) {
2425
+ clearPendingInitialScrollFooterLayout(ctx, {
2426
+ dataLength: state.props.data.length,
2427
+ stylePaddingBottom: (_b = state.props.stylePaddingBottom) != null ? _b : 0,
2428
+ target: initialScroll
2429
+ });
2430
+ return;
2431
+ }
2432
+ clearFinishedViewportRetargetableInitialScroll(state);
2433
+ }
2434
+ }
2218
2435
  function startBootstrapInitialScrollOnMount(ctx, options) {
2219
2436
  var _a3, _b, _c;
2220
2437
  const { initialScrollAtEnd, target } = options;
@@ -2251,15 +2468,16 @@ function handleBootstrapInitialScrollDataChange(ctx, options) {
2251
2468
  }
2252
2469
  const shouldResetDidFinish = !!(state.didFinishInitialScroll && previousDataLength === 0 && dataLength > 0 && initialScroll.index !== void 0);
2253
2470
  const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2471
+ const shouldClearFinishedResizePreservation = didDataChange && dataLength > 0 && state.didFinishInitialScroll && !bootstrapInitialScroll && !shouldResetDidFinish;
2472
+ if (shouldClearFinishedResizePreservation) {
2473
+ clearPreservedInitialScrollTarget(state);
2474
+ return;
2475
+ }
2254
2476
  const shouldRetargetBottomAligned = dataLength > 0 && (initialScrollAtEnd || isRetargetableBottomAlignedInitialScrollTarget(initialScroll));
2255
2477
  if (!didDataChange && !shouldResetDidFinish && !shouldRetargetBottomAligned) {
2256
2478
  return;
2257
2479
  }
2258
2480
  if (shouldRetargetBottomAligned) {
2259
- if (!shouldResetDidFinish && didFinishedInitialScrollMoveAwayFromTarget(ctx, initialScroll)) {
2260
- clearPendingInitialScrollFooterLayout(state, initialScroll);
2261
- return;
2262
- }
2263
2481
  const updatedInitialScroll = initialScrollAtEnd ? createInitialScrollAtEndTarget({
2264
2482
  dataLength,
2265
2483
  footerSize: peek$(ctx, "footerSize") || 0,
@@ -2272,6 +2490,14 @@ function handleBootstrapInitialScrollDataChange(ctx, options) {
2272
2490
  stylePaddingBottom,
2273
2491
  target: initialScroll
2274
2492
  });
2493
+ if (!shouldResetDidFinish && didFinishedInitialScrollMoveAwayFromTarget(ctx, initialScroll)) {
2494
+ clearPendingInitialScrollFooterLayout(ctx, {
2495
+ dataLength,
2496
+ stylePaddingBottom,
2497
+ target: initialScroll
2498
+ });
2499
+ return;
2500
+ }
2275
2501
  if (!areEquivalentBootstrapInitialScrollTargets(initialScroll, updatedInitialScroll) || !!bootstrapInitialScroll || shouldResetDidFinish || didDataChange) {
2276
2502
  setInitialScrollTarget(state, updatedInitialScroll, {
2277
2503
  resetDidFinish: shouldResetDidFinish
@@ -2313,7 +2539,11 @@ function handleBootstrapInitialScrollFooterLayout(ctx, options) {
2313
2539
  return;
2314
2540
  }
2315
2541
  if (didFinishedInitialScrollMoveAwayFromTarget(ctx, initialScroll)) {
2316
- clearPendingInitialScrollFooterLayout(state, initialScroll);
2542
+ clearPendingInitialScrollFooterLayout(ctx, {
2543
+ dataLength,
2544
+ stylePaddingBottom,
2545
+ target: initialScroll
2546
+ });
2317
2547
  } else {
2318
2548
  const updatedInitialScroll = createInitialScrollAtEndTarget({
2319
2549
  dataLength,
@@ -2323,10 +2553,15 @@ function handleBootstrapInitialScrollFooterLayout(ctx, options) {
2323
2553
  });
2324
2554
  const didTargetChange = initialScroll.index !== updatedInitialScroll.index || initialScroll.viewPosition !== updatedInitialScroll.viewPosition || initialScroll.viewOffset !== updatedInitialScroll.viewOffset;
2325
2555
  if (!didTargetChange) {
2326
- clearPendingInitialScrollFooterLayout(state, initialScroll);
2556
+ clearPendingInitialScrollFooterLayout(ctx, {
2557
+ dataLength,
2558
+ stylePaddingBottom,
2559
+ target: initialScroll
2560
+ });
2327
2561
  } else {
2562
+ const didFinishInitialScroll = !!state.didFinishInitialScroll;
2328
2563
  setInitialScrollTarget(state, updatedInitialScroll, {
2329
- resetDidFinish: !!state.didFinishInitialScroll
2564
+ resetDidFinish: didFinishInitialScroll
2330
2565
  });
2331
2566
  rearmBootstrapInitialScroll(ctx, {
2332
2567
  scroll: resolveInitialScrollOffset(ctx, updatedInitialScroll),
@@ -2335,6 +2570,29 @@ function handleBootstrapInitialScrollFooterLayout(ctx, options) {
2335
2570
  }
2336
2571
  }
2337
2572
  }
2573
+ function handleBootstrapInitialScrollLayoutChange(ctx) {
2574
+ const state = ctx.state;
2575
+ const initialScroll = state.initialScroll;
2576
+ if (isOffsetInitialScrollSession(state) || state.props.data.length === 0 || !initialScroll) {
2577
+ return;
2578
+ }
2579
+ const bootstrapInitialScroll = getBootstrapInitialScrollSession(state);
2580
+ if (!bootstrapInitialScroll && initialScroll.viewPosition !== 1) {
2581
+ return;
2582
+ }
2583
+ const didFinishInitialScroll = state.didFinishInitialScroll;
2584
+ if (didFinishInitialScroll) {
2585
+ setInitialScrollTarget(state, initialScroll, {
2586
+ resetDidFinish: true
2587
+ });
2588
+ state.clearPreservedInitialScrollOnNextFinish = true;
2589
+ }
2590
+ rearmBootstrapInitialScroll(ctx, {
2591
+ scroll: resolveInitialScrollOffset(ctx, initialScroll),
2592
+ seedContentOffset: didFinishInitialScroll && !bootstrapInitialScroll ? getObservedBootstrapInitialScrollOffset(state) : void 0,
2593
+ targetIndexSeed: initialScroll.index
2594
+ });
2595
+ }
2338
2596
  function evaluateBootstrapInitialScroll(ctx) {
2339
2597
  var _a3, _b;
2340
2598
  const state = ctx.state;
@@ -2392,7 +2650,7 @@ function evaluateBootstrapInitialScroll(ctx) {
2392
2650
  queueBootstrapInitialScrollReevaluation(state);
2393
2651
  return;
2394
2652
  }
2395
- if (Platform2.OS !== "web" && Platform2.OS !== "android" && Math.abs(bootstrapInitialScroll.seedContentOffset - resolvedOffset) <= 1) {
2653
+ if (Platform2.OS !== "web" && Platform2.OS !== "android" && Math.abs(bootstrapInitialScroll.seedContentOffset - resolvedOffset) <= 1 && Math.abs(getObservedBootstrapInitialScrollOffset(state) - resolvedOffset) <= 1) {
2396
2654
  finishBootstrapInitialScrollWithoutScroll(ctx, resolvedOffset);
2397
2655
  } else {
2398
2656
  clearBootstrapInitialScrollSession(state);
@@ -2405,12 +2663,15 @@ function evaluateBootstrapInitialScroll(ctx) {
2405
2663
  }
2406
2664
  }
2407
2665
  function finishBootstrapInitialScrollWithoutScroll(ctx, resolvedOffset) {
2666
+ var _a3;
2408
2667
  const state = ctx.state;
2409
2668
  clearBootstrapInitialScrollSession(state);
2669
+ const shouldPreserveResizeTarget = !state.clearPreservedInitialScrollOnNextFinish && state.props.data.length > 0 && ((_a3 = state.initialScroll) == null ? void 0 : _a3.viewPosition) === 1;
2410
2670
  finishInitialScroll(ctx, {
2411
- preserveTarget: shouldPreserveInitialScrollForFooterLayout(state.initialScroll),
2671
+ preserveTarget: shouldPreserveResizeTarget,
2412
2672
  recalculateItems: true,
2413
- resolvedOffset
2673
+ resolvedOffset,
2674
+ schedulePreservedTargetClear: shouldPreserveResizeTarget
2414
2675
  });
2415
2676
  }
2416
2677
  function abortBootstrapInitialScroll(ctx) {
@@ -2687,7 +2948,7 @@ function resolvePendingNativeMVCPAdjust(ctx, newScroll) {
2687
2948
  settlePendingNativeMVCPAdjust(ctx, remainingAfterManual, nativeDelta);
2688
2949
  return true;
2689
2950
  }
2690
- if (state.pendingMaintainScrollAtEnd && state.isAtEnd && progressTowardAmount > MVCP_POSITION_EPSILON) {
2951
+ if (state.pendingMaintainScrollAtEnd && peek$(ctx, "isWithinMaintainScrollAtEndThreshold") && progressTowardAmount > MVCP_POSITION_EPSILON) {
2691
2952
  settlePendingNativeMVCPAdjust(ctx, remainingAfterManual, nativeDelta);
2692
2953
  return true;
2693
2954
  }
@@ -2852,6 +3113,86 @@ function prepareMVCP(ctx, dataChanged) {
2852
3113
  }
2853
3114
  }
2854
3115
 
3116
+ // src/core/syncMountedContainer.ts
3117
+ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
3118
+ var _a3, _b, _c, _d, _e, _f, _g, _h;
3119
+ const state = ctx.state;
3120
+ const {
3121
+ columns,
3122
+ columnSpans,
3123
+ positions,
3124
+ props: { data, itemsAreEqual, keyExtractor }
3125
+ } = state;
3126
+ const item = data[itemIndex];
3127
+ if (item === void 0) {
3128
+ return { didChangePosition: false, didRefreshData: false };
3129
+ }
3130
+ const updateLayout = (_a3 = options == null ? void 0 : options.updateLayout) != null ? _a3 : true;
3131
+ let didChangePosition = false;
3132
+ let didRefreshData = false;
3133
+ if (updateLayout) {
3134
+ const positionValue = positions[itemIndex];
3135
+ if (positionValue === void 0) {
3136
+ set$(ctx, `containerPosition${containerIndex}`, POSITION_OUT_OF_VIEW);
3137
+ return { didChangePosition: false, didRefreshData: false };
3138
+ }
3139
+ const position = (positionValue || 0) - ((_b = options == null ? void 0 : options.scrollAdjustPending) != null ? _b : 0);
3140
+ const column = columns[itemIndex] || 1;
3141
+ const span = columnSpans[itemIndex] || 1;
3142
+ const prevPos = peek$(ctx, `containerPosition${containerIndex}`);
3143
+ const prevColumn = peek$(ctx, `containerColumn${containerIndex}`);
3144
+ const prevSpan = peek$(ctx, `containerSpan${containerIndex}`);
3145
+ if (position > POSITION_OUT_OF_VIEW && position !== prevPos) {
3146
+ set$(ctx, `containerPosition${containerIndex}`, position);
3147
+ didChangePosition = true;
3148
+ }
3149
+ if (column >= 0 && column !== prevColumn) {
3150
+ set$(ctx, `containerColumn${containerIndex}`, column);
3151
+ }
3152
+ if (span !== prevSpan) {
3153
+ set$(ctx, `containerSpan${containerIndex}`, span);
3154
+ }
3155
+ }
3156
+ const prevData = peek$(ctx, `containerItemData${containerIndex}`);
3157
+ if (prevData !== item) {
3158
+ const pendingDataComparison = ((_c = state.pendingDataComparison) == null ? void 0 : _c.previousData) === state.previousData && ((_d = state.pendingDataComparison) == null ? void 0 : _d.nextData) === data ? state.pendingDataComparison : void 0;
3159
+ const cachedComparison = (_e = pendingDataComparison == null ? void 0 : pendingDataComparison.byIndex[itemIndex]) != null ? _e : 0;
3160
+ if (cachedComparison === 2) {
3161
+ set$(ctx, `containerItemData${containerIndex}`, item);
3162
+ didRefreshData = true;
3163
+ } else if (cachedComparison !== 1) {
3164
+ const itemKey = (_g = (_f = peek$(ctx, `containerItemKey${containerIndex}`)) != null ? _f : state.idCache[itemIndex]) != null ? _g : getId(state, itemIndex);
3165
+ const prevKey = keyExtractor == null ? void 0 : keyExtractor(prevData, itemIndex);
3166
+ if (prevData === void 0 || !keyExtractor || prevKey !== itemKey) {
3167
+ set$(ctx, `containerItemData${containerIndex}`, item);
3168
+ didRefreshData = true;
3169
+ } else if (!itemsAreEqual) {
3170
+ set$(ctx, `containerItemData${containerIndex}`, item);
3171
+ didRefreshData = true;
3172
+ } else {
3173
+ const isEqual = itemsAreEqual(prevData, item, itemIndex, data);
3174
+ if (!state.pendingDataComparison || state.pendingDataComparison.previousData !== state.previousData || state.pendingDataComparison.nextData !== data) {
3175
+ if (state.previousData) {
3176
+ state.pendingDataComparison = {
3177
+ byIndex: [],
3178
+ nextData: data,
3179
+ previousData: state.previousData
3180
+ };
3181
+ }
3182
+ }
3183
+ if ((_h = state.pendingDataComparison) == null ? void 0 : _h.byIndex) {
3184
+ state.pendingDataComparison.byIndex[itemIndex] = isEqual ? 1 : 2;
3185
+ }
3186
+ if (!isEqual) {
3187
+ set$(ctx, `containerItemData${containerIndex}`, item);
3188
+ didRefreshData = true;
3189
+ }
3190
+ }
3191
+ }
3192
+ }
3193
+ return { didChangePosition, didRefreshData };
3194
+ }
3195
+
2855
3196
  // src/core/prepareColumnStartState.ts
2856
3197
  function prepareColumnStartState(ctx, startIndex, useAverageSize) {
2857
3198
  var _a3;
@@ -3014,9 +3355,10 @@ function updateSnapToOffsets(ctx) {
3014
3355
  }
3015
3356
 
3016
3357
  // src/core/updateItemPositions.ts
3017
- function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP } = {
3358
+ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP, optimizeForVisibleWindow = false } = {
3018
3359
  doMVCP: false,
3019
3360
  forceFullUpdate: false,
3361
+ optimizeForVisibleWindow: false,
3020
3362
  scrollBottomBuffered: -1,
3021
3363
  startIndex: 0
3022
3364
  }) {
@@ -3041,7 +3383,7 @@ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffere
3041
3383
  const layoutConfig = overrideItemLayout ? { span: 1 } : void 0;
3042
3384
  const lastScrollDelta = state.lastScrollDelta;
3043
3385
  const velocity = getScrollVelocity(state);
3044
- const shouldOptimize = !forceFullUpdate && !dataChanged && (Math.abs(velocity) > 0 || Platform2.OS === "web" && state.scrollLength > 0 && lastScrollDelta > state.scrollLength);
3386
+ const shouldOptimize = !forceFullUpdate && !dataChanged && (optimizeForVisibleWindow || Math.abs(velocity) > 0 || Platform2.OS === "web" && state.scrollLength > 0 && lastScrollDelta > state.scrollLength);
3045
3387
  const maxVisibleArea = scrollBottomBuffered + 1e3;
3046
3388
  const useAverageSize = !getEstimatedItemSize;
3047
3389
  const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_b = peek$(ctx, "scrollAdjustPending")) != null ? _b : 0) !== 0;
@@ -3156,7 +3498,15 @@ function ensureViewabilityState(ctx, configId) {
3156
3498
  }
3157
3499
  let state = map.get(configId);
3158
3500
  if (!state) {
3159
- state = { end: -1, previousEnd: -1, previousStart: -1, start: -1, viewableItems: [] };
3501
+ state = {
3502
+ end: -1,
3503
+ endBuffered: -1,
3504
+ previousEnd: -1,
3505
+ previousStart: -1,
3506
+ start: -1,
3507
+ startBuffered: -1,
3508
+ viewableItems: []
3509
+ };
3160
3510
  map.set(configId, state);
3161
3511
  }
3162
3512
  return state;
@@ -3176,7 +3526,7 @@ function setupViewability(props) {
3176
3526
  }
3177
3527
  return viewabilityConfigCallbackPairs;
3178
3528
  }
3179
- function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
3529
+ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end, startBuffered = start, endBuffered = end) {
3180
3530
  const {
3181
3531
  timeouts,
3182
3532
  props: { data }
@@ -3185,6 +3535,8 @@ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollS
3185
3535
  const viewabilityState = ensureViewabilityState(ctx, viewabilityConfigCallbackPair.viewabilityConfig.id);
3186
3536
  viewabilityState.start = start;
3187
3537
  viewabilityState.end = end;
3538
+ viewabilityState.startBuffered = startBuffered;
3539
+ viewabilityState.endBuffered = endBuffered;
3188
3540
  if (viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime) {
3189
3541
  const timer = setTimeout(() => {
3190
3542
  timeouts.delete(timer);
@@ -3200,7 +3552,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
3200
3552
  const { viewabilityConfig, onViewableItemsChanged } = viewabilityConfigCallbackPair;
3201
3553
  const configId = viewabilityConfig.id;
3202
3554
  const viewabilityState = ensureViewabilityState(ctx, configId);
3203
- const { viewableItems: previousViewableItems, start, end } = viewabilityState;
3555
+ const { viewableItems: previousViewableItems, start, end, startBuffered, endBuffered } = viewabilityState;
3204
3556
  const viewabilityTokens = /* @__PURE__ */ new Map();
3205
3557
  for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
3206
3558
  viewabilityTokens.set(
@@ -3269,7 +3621,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
3269
3621
  maybeUpdateViewabilityCallback(ctx, configId, change.containerId, change);
3270
3622
  }
3271
3623
  if (onViewableItemsChanged) {
3272
- onViewableItemsChanged({ changed, viewableItems });
3624
+ onViewableItemsChanged({ changed, end, endBuffered, start, startBuffered, viewableItems });
3273
3625
  }
3274
3626
  }
3275
3627
  for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
@@ -3581,7 +3933,6 @@ function calculateItemsInView(ctx, params = {}) {
3581
3933
  alwaysRenderIndicesSet,
3582
3934
  drawDistance,
3583
3935
  getItemType,
3584
- itemsAreEqual,
3585
3936
  keyExtractor,
3586
3937
  onStickyHeaderChange
3587
3938
  },
@@ -3608,11 +3959,11 @@ function calculateItemsInView(ctx, params = {}) {
3608
3959
  const numColumns = peek$(ctx, "numColumns");
3609
3960
  const speed = getScrollVelocity(state);
3610
3961
  const scrollExtra = 0;
3611
- const { queuedInitialLayout } = state;
3612
- const scrollState = suppressInitialScrollSideEffects ? (_b = bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.scroll) != null ? _b : state.scroll : !queuedInitialLayout && state.initialScroll ? (
3962
+ const { initialScroll, queuedInitialLayout } = state;
3963
+ const scrollState = suppressInitialScrollSideEffects ? (_b = bootstrapInitialScrollState == null ? void 0 : bootstrapInitialScrollState.scroll) != null ? _b : state.scroll : !queuedInitialLayout && hasActiveInitialScroll(state) && initialScroll ? (
3613
3964
  // Before the initial layout settles, keep viewport math anchored to the
3614
3965
  // current initial-scroll target instead of transient native adjustments.
3615
- resolveInitialScrollOffset(ctx, state.initialScroll)
3966
+ resolveInitialScrollOffset(ctx, initialScroll)
3616
3967
  ) : state.scroll;
3617
3968
  const scrollAdjustPending = (_c = peek$(ctx, "scrollAdjustPending")) != null ? _c : 0;
3618
3969
  const scrollAdjustPad = scrollAdjustPending - topPad;
@@ -3657,9 +4008,11 @@ function calculateItemsInView(ctx, params = {}) {
3657
4008
  columnSpans.length = 0;
3658
4009
  }
3659
4010
  const startIndex = forceFullItemPositions || dataChanged ? 0 : (_d = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _d : 0;
4011
+ const optimizeForVisibleWindow = !forceFullItemPositions && !dataChanged && numColumns > 1 && minIndexSizeChanged !== void 0;
3660
4012
  updateItemPositions(ctx, dataChanged, {
3661
4013
  doMVCP,
3662
4014
  forceFullUpdate: !!forceFullItemPositions,
4015
+ optimizeForVisibleWindow,
3663
4016
  scrollBottomBuffered,
3664
4017
  startIndex
3665
4018
  });
@@ -3907,33 +4260,11 @@ function calculateItemsInView(ctx, params = {}) {
3907
4260
  set$(ctx, `containerSpan${i}`, 1);
3908
4261
  } else {
3909
4262
  const itemIndex = indexByKey.get(itemKey);
3910
- const item = data[itemIndex];
3911
- if (item !== void 0) {
3912
- const positionValue = positions[itemIndex];
3913
- if (positionValue === void 0) {
3914
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
3915
- } else {
3916
- const position = (positionValue || 0) - scrollAdjustPending;
3917
- const column = columns[itemIndex] || 1;
3918
- const span = columnSpans[itemIndex] || 1;
3919
- const prevPos = peek$(ctx, `containerPosition${i}`);
3920
- const prevColumn = peek$(ctx, `containerColumn${i}`);
3921
- const prevSpan = peek$(ctx, `containerSpan${i}`);
3922
- const prevData = peek$(ctx, `containerItemData${i}`);
3923
- if (position > POSITION_OUT_OF_VIEW && position !== prevPos) {
3924
- set$(ctx, `containerPosition${i}`, position);
3925
- didChangePositions = true;
3926
- }
3927
- if (column >= 0 && column !== prevColumn) {
3928
- set$(ctx, `containerColumn${i}`, column);
3929
- }
3930
- if (span !== prevSpan) {
3931
- set$(ctx, `containerSpan${i}`, span);
3932
- }
3933
- if (prevData !== item && (itemsAreEqual ? !itemsAreEqual(prevData, item, itemIndex, data) : true)) {
3934
- set$(ctx, `containerItemData${i}`, item);
3935
- }
3936
- }
4263
+ if (itemIndex !== void 0) {
4264
+ didChangePositions = syncMountedContainer(ctx, i, itemIndex, {
4265
+ scrollAdjustPending,
4266
+ updateLayout: true
4267
+ }).didChangePosition || didChangePositions;
3937
4268
  }
3938
4269
  }
3939
4270
  }
@@ -3944,7 +4275,10 @@ function calculateItemsInView(ctx, params = {}) {
3944
4275
  evaluateBootstrapInitialScroll(ctx);
3945
4276
  return;
3946
4277
  }
3947
- if (!queuedInitialLayout && endBuffered !== null && checkAllSizesKnown(state)) {
4278
+ const mountedBufferedIndices = getMountedBufferedIndices(state);
4279
+ const mountedNoBufferIndices = getMountedNoBufferIndices(state);
4280
+ const readinessIndices = hasActiveInitialScroll(state) ? mountedBufferedIndices : mountedNoBufferIndices.length > 0 ? mountedNoBufferIndices : mountedBufferedIndices;
4281
+ if (!queuedInitialLayout && readinessIndices.length > 0 && checkAllSizesKnown(state, readinessIndices)) {
3948
4282
  setDidLayout(ctx);
3949
4283
  handleInitialScrollLayoutReady(ctx);
3950
4284
  }
@@ -3955,7 +4289,9 @@ function calculateItemsInView(ctx, params = {}) {
3955
4289
  viewabilityConfigCallbackPairs,
3956
4290
  scrollLength,
3957
4291
  startNoBuffer,
3958
- endNoBuffer
4292
+ endNoBuffer,
4293
+ startBuffered != null ? startBuffered : startNoBuffer,
4294
+ endBuffered != null ? endBuffered : endNoBuffer
3959
4295
  );
3960
4296
  }
3961
4297
  if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
@@ -3967,37 +4303,17 @@ function calculateItemsInView(ctx, params = {}) {
3967
4303
  });
3968
4304
  }
3969
4305
 
3970
- // src/core/checkActualChange.ts
3971
- function checkActualChange(state, dataProp, previousData) {
3972
- if (!previousData || !dataProp || dataProp.length !== previousData.length) {
3973
- return true;
3974
- }
3975
- const {
3976
- idCache,
3977
- props: { keyExtractor }
3978
- } = state;
3979
- for (let i = 0; i < dataProp.length; i++) {
3980
- if (dataProp[i] !== previousData[i]) {
3981
- return true;
3982
- }
3983
- if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
3984
- return true;
3985
- }
3986
- }
3987
- return false;
3988
- }
3989
-
3990
4306
  // src/core/doMaintainScrollAtEnd.ts
3991
4307
  function doMaintainScrollAtEnd(ctx) {
3992
4308
  const state = ctx.state;
3993
4309
  const {
3994
4310
  didContainersLayout,
3995
- isAtEnd,
3996
4311
  pendingNativeMVCPAdjust,
3997
4312
  refScroller,
3998
4313
  props: { maintainScrollAtEnd }
3999
4314
  } = state;
4000
- const shouldMaintainScrollAtEnd = !!(isAtEnd && maintainScrollAtEnd && didContainersLayout);
4315
+ const isWithinMaintainScrollAtEndThreshold = peek$(ctx, "isWithinMaintainScrollAtEndThreshold");
4316
+ const shouldMaintainScrollAtEnd = !!(isWithinMaintainScrollAtEndThreshold && maintainScrollAtEnd && didContainersLayout);
4001
4317
  if (pendingNativeMVCPAdjust) {
4002
4318
  state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
4003
4319
  return false;
@@ -4010,7 +4326,7 @@ function doMaintainScrollAtEnd(ctx) {
4010
4326
  }
4011
4327
  requestAnimationFrame(() => {
4012
4328
  var _a3;
4013
- if (state.isAtEnd) {
4329
+ if (peek$(ctx, "isWithinMaintainScrollAtEndThreshold")) {
4014
4330
  state.maintainingScrollAtEnd = true;
4015
4331
  (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
4016
4332
  animated: maintainScrollAtEnd.animated
@@ -4028,68 +4344,22 @@ function doMaintainScrollAtEnd(ctx) {
4028
4344
  return false;
4029
4345
  }
4030
4346
 
4031
- // src/utils/updateAveragesOnDataChange.ts
4032
- function updateAveragesOnDataChange(state, oldData, newData) {
4033
- var _a3;
4034
- const {
4035
- averageSizes,
4036
- sizesKnown,
4037
- indexByKey,
4038
- props: { itemsAreEqual, getItemType, keyExtractor }
4039
- } = state;
4040
- if (!itemsAreEqual || !oldData.length || !newData.length) {
4041
- for (const key in averageSizes) {
4042
- delete averageSizes[key];
4043
- }
4044
- return;
4045
- }
4046
- const itemTypesToPreserve = {};
4047
- const newDataLength = newData.length;
4048
- const oldDataLength = oldData.length;
4049
- for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
4050
- const newItem = newData[newIndex];
4051
- const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
4052
- const oldIndex = indexByKey.get(id);
4053
- if (oldIndex !== void 0 && oldIndex < oldDataLength) {
4054
- const knownSize = sizesKnown.get(id);
4055
- if (knownSize === void 0) continue;
4056
- const oldItem = oldData[oldIndex];
4057
- const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
4058
- if (areEqual) {
4059
- const itemType = getItemType ? (_a3 = getItemType(newItem, newIndex)) != null ? _a3 : "" : "";
4060
- let typeData = itemTypesToPreserve[itemType];
4061
- if (!typeData) {
4062
- typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
4063
- }
4064
- typeData.totalSize += knownSize;
4065
- typeData.count++;
4066
- }
4067
- }
4068
- }
4069
- for (const key in averageSizes) {
4070
- delete averageSizes[key];
4071
- }
4072
- for (const itemType in itemTypesToPreserve) {
4073
- const { totalSize, count } = itemTypesToPreserve[itemType];
4074
- if (count > 0) {
4075
- averageSizes[itemType] = {
4076
- avg: totalSize / count,
4077
- num: count
4078
- };
4079
- }
4080
- }
4081
- }
4082
-
4083
4347
  // src/core/checkResetContainers.ts
4084
- function checkResetContainers(ctx, dataProp) {
4348
+ function checkResetContainers(ctx, dataProp, { didColumnsChange = false } = {}) {
4085
4349
  const state = ctx.state;
4086
4350
  const { previousData } = state;
4087
- if (previousData) {
4088
- updateAveragesOnDataChange(state, previousData, dataProp);
4089
- }
4090
4351
  const { maintainScrollAtEnd } = state.props;
4352
+ if (didColumnsChange) {
4353
+ state.sizes.clear();
4354
+ state.sizesKnown.clear();
4355
+ for (const key in state.averageSizes) {
4356
+ delete state.averageSizes[key];
4357
+ }
4358
+ state.minIndexSizeChanged = 0;
4359
+ state.scrollForNextCalculateItemsInView = void 0;
4360
+ }
4091
4361
  calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
4092
- const shouldMaintainScrollAtEnd = maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.onDataChange;
4362
+ const shouldMaintainScrollAtEnd = !didColumnsChange && (maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.onDataChange);
4093
4363
  const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx);
4094
4364
  if (!didMaintainScrollAtEnd && previousData && dataProp.length > previousData.length) {
4095
4365
  state.isEndReached = false;
@@ -4100,6 +4370,53 @@ function checkResetContainers(ctx, dataProp) {
4100
4370
  delete state.previousData;
4101
4371
  }
4102
4372
 
4373
+ // src/core/checkStructuralDataChange.ts
4374
+ function checkStructuralDataChange(state, dataProp, previousData) {
4375
+ var _a3;
4376
+ state.pendingDataComparison = void 0;
4377
+ if (!previousData || !dataProp || dataProp.length !== previousData.length) {
4378
+ return true;
4379
+ }
4380
+ const {
4381
+ idCache,
4382
+ props: { itemsAreEqual, keyExtractor }
4383
+ } = state;
4384
+ let byIndex;
4385
+ for (let i = 0; i < dataProp.length; i++) {
4386
+ if (dataProp[i] === previousData[i]) {
4387
+ continue;
4388
+ }
4389
+ if (!keyExtractor) {
4390
+ if (byIndex) {
4391
+ state.pendingDataComparison = { byIndex, nextData: dataProp, previousData };
4392
+ }
4393
+ return true;
4394
+ }
4395
+ const previousKey = (_a3 = idCache[i]) != null ? _a3 : keyExtractor(previousData[i], i);
4396
+ const nextKey = keyExtractor(dataProp[i], i);
4397
+ if (previousKey !== nextKey) {
4398
+ if (byIndex) {
4399
+ state.pendingDataComparison = { byIndex, nextData: dataProp, previousData };
4400
+ }
4401
+ return true;
4402
+ }
4403
+ if (!itemsAreEqual) {
4404
+ if (byIndex) {
4405
+ state.pendingDataComparison = { byIndex, nextData: dataProp, previousData };
4406
+ }
4407
+ return true;
4408
+ }
4409
+ const isEqual = itemsAreEqual(previousData[i], dataProp[i], i, dataProp);
4410
+ byIndex != null ? byIndex : byIndex = [];
4411
+ byIndex[i] = isEqual ? 1 : 2;
4412
+ if (!isEqual) {
4413
+ state.pendingDataComparison = { byIndex, nextData: dataProp, previousData };
4414
+ return true;
4415
+ }
4416
+ }
4417
+ return false;
4418
+ }
4419
+
4103
4420
  // src/core/doInitialAllocateContainers.ts
4104
4421
  function doInitialAllocateContainers(ctx) {
4105
4422
  var _a3, _b, _c;
@@ -4344,6 +4661,7 @@ function onScroll(ctx, event) {
4344
4661
  state.scrollPending = newScroll;
4345
4662
  updateScroll(ctx, newScroll, insetChanged);
4346
4663
  trackInitialScrollNativeProgress(state, newScroll);
4664
+ clearFinishedBootstrapInitialScrollTargetIfMovedAway(ctx);
4347
4665
  if (state.scrollingTo) {
4348
4666
  checkFinishedScroll(ctx);
4349
4667
  }
@@ -4407,6 +4725,43 @@ var ScrollAdjustHandler = class {
4407
4725
  }
4408
4726
  };
4409
4727
 
4728
+ // src/core/updateAnchoredEndSpace.ts
4729
+ function maybeUpdateAnchoredEndSpace(ctx) {
4730
+ var _a3;
4731
+ const state = ctx.state;
4732
+ const anchoredEndSpace = state.props.anchoredEndSpace;
4733
+ const previousSize = peek$(ctx, "anchoredEndSpaceSize");
4734
+ let nextSize = 0;
4735
+ if (anchoredEndSpace) {
4736
+ const { anchorIndex, anchorMaxSize, anchorOffset = 0 } = anchoredEndSpace;
4737
+ const { data } = state.props;
4738
+ if (anchorIndex >= 0 && anchorIndex < data.length && state.scrollLength > 0) {
4739
+ let contentBelowAnchor = 0;
4740
+ const footerSize = ctx.values.get("footerSize") || 0;
4741
+ const stylePaddingBottom = state.props.stylePaddingBottom || 0;
4742
+ for (let index = anchorIndex; index < data.length; index++) {
4743
+ const itemKey = getId(state, index);
4744
+ const size = itemKey ? state.sizesKnown.get(itemKey) : void 0;
4745
+ const effectiveSize = index === anchorIndex && anchorMaxSize !== void 0 ? Math.min(size || 0, Math.max(0, anchorMaxSize)) : size;
4746
+ if (effectiveSize !== null && effectiveSize !== void 0 && effectiveSize > 0) {
4747
+ contentBelowAnchor += effectiveSize;
4748
+ }
4749
+ }
4750
+ contentBelowAnchor += footerSize + stylePaddingBottom;
4751
+ nextSize = Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
4752
+ }
4753
+ }
4754
+ if (previousSize === nextSize) {
4755
+ return nextSize;
4756
+ }
4757
+ set$(ctx, "anchoredEndSpaceSize", nextSize);
4758
+ (_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
4759
+ if (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset) {
4760
+ updateScroll(ctx, state.scroll, true);
4761
+ }
4762
+ return nextSize;
4763
+ }
4764
+
4410
4765
  // src/core/updateItemSize.ts
4411
4766
  function runOrScheduleMVCPRecalculate(ctx) {
4412
4767
  const state = ctx.state;
@@ -4490,6 +4845,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
4490
4845
  previous: size - diff,
4491
4846
  size
4492
4847
  });
4848
+ maybeUpdateAnchoredEndSpace(ctx);
4493
4849
  }
4494
4850
  if (minIndexSizeChanged !== void 0) {
4495
4851
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
@@ -4620,26 +4976,13 @@ function createColumnWrapperStyle(contentContainerStyle) {
4620
4976
  }
4621
4977
  }
4622
4978
 
4623
- // src/utils/hasActiveMVCPAnchorLock.ts
4624
- function hasActiveMVCPAnchorLock(state) {
4625
- const lock = state.mvcpAnchorLock;
4626
- if (!lock) {
4627
- return false;
4628
- }
4629
- if (Date.now() > lock.expiresAt) {
4630
- state.mvcpAnchorLock = void 0;
4631
- return false;
4632
- }
4633
- return true;
4634
- }
4635
-
4636
4979
  // src/utils/createImperativeHandle.ts
4637
4980
  function createImperativeHandle(ctx) {
4638
4981
  const state = ctx.state;
4639
4982
  const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
4640
4983
  const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
4641
4984
  let imperativeScrollToken = 0;
4642
- const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0 || hasActiveMVCPAnchorLock(state);
4985
+ const isSettlingAfterDataChange = () => !!state.didDataChange || !!state.didColumnsChange || state.queuedMVCPRecalculate !== void 0 || state.ignoreScrollFromMVCP !== void 0;
4643
4986
  const runWhenSettled = (token, run) => {
4644
4987
  const startedAt = Date.now();
4645
4988
  let stableFrames = 0;
@@ -4661,9 +5004,10 @@ function createImperativeHandle(ctx) {
4661
5004
  };
4662
5005
  requestAnimationFrame(check);
4663
5006
  };
4664
- const runScrollWithPromise = (run) => new Promise((resolve) => {
5007
+ const runScrollWithPromise = (run, options) => new Promise((resolve) => {
4665
5008
  var _a3;
4666
5009
  const token = ++imperativeScrollToken;
5010
+ const shouldWaitOneFrame = !!(options == null ? void 0 : options.shouldWaitOneFrame);
4667
5011
  (_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
4668
5012
  state.pendingScrollResolve = resolve;
4669
5013
  const runNow = () => {
@@ -4678,11 +5022,12 @@ function createImperativeHandle(ctx) {
4678
5022
  resolve();
4679
5023
  }
4680
5024
  };
5025
+ const execute = shouldWaitOneFrame ? () => requestAnimationFrame(runNow) : runNow;
4681
5026
  if (isSettlingAfterDataChange()) {
4682
- runWhenSettled(token, runNow);
4683
- return;
5027
+ runWhenSettled(token, execute);
5028
+ } else {
5029
+ execute();
4684
5030
  }
4685
- runNow();
4686
5031
  });
4687
5032
  const scrollIndexIntoView = (options) => {
4688
5033
  if (state) {
@@ -4739,10 +5084,13 @@ function createImperativeHandle(ctx) {
4739
5084
  },
4740
5085
  end: state.endNoBuffer,
4741
5086
  endBuffered: state.endBuffered,
4742
- isAtEnd: state.isAtEnd,
4743
- isAtStart: state.isAtStart,
5087
+ isAtEnd: peek$(ctx, "isAtEnd"),
5088
+ isAtStart: peek$(ctx, "isAtStart"),
4744
5089
  isEndReached: state.isEndReached,
5090
+ isNearEnd: peek$(ctx, "isNearEnd"),
5091
+ isNearStart: peek$(ctx, "isNearStart"),
4745
5092
  isStartReached: state.isStartReached,
5093
+ isWithinMaintainScrollAtEndThreshold: peek$(ctx, "isWithinMaintainScrollAtEndThreshold"),
4746
5094
  listen: (signalName, cb) => listen$(ctx, signalName, cb),
4747
5095
  listenToPosition: (key, cb) => listenPosition$(ctx, key, cb),
4748
5096
  positionAtIndex: (index) => state.positions[index],
@@ -4789,10 +5137,15 @@ function createImperativeHandle(ctx) {
4789
5137
  }
4790
5138
  return false;
4791
5139
  }),
4792
- scrollToIndex: (params) => runScrollWithPromise(() => {
4793
- scrollToIndex(ctx, params);
4794
- return true;
4795
- }),
5140
+ scrollToIndex: (params) => runScrollWithPromise(
5141
+ () => {
5142
+ scrollToIndex(ctx, params);
5143
+ return true;
5144
+ },
5145
+ {
5146
+ shouldWaitOneFrame: params.index >= 0 && params.index >= state.props.data.length
5147
+ }
5148
+ ),
4796
5149
  scrollToItem: ({ item, ...props }) => runScrollWithPromise(() => {
4797
5150
  const data = state.props.data;
4798
5151
  const index = data.indexOf(item);
@@ -4888,7 +5241,7 @@ function getRenderedItem(ctx, key) {
4888
5241
  item,
4889
5242
  type: getItemType ? (_a3 = getItemType(item, index)) != null ? _a3 : "" : ""
4890
5243
  };
4891
- renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React2__namespace.default.createElement(renderItem, itemProps);
5244
+ renderedItem = React2__namespace.default.createElement(renderItem, itemProps);
4892
5245
  }
4893
5246
  return { index, item: data[index], renderedItem };
4894
5247
  }
@@ -5003,7 +5356,7 @@ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
5003
5356
  }
5004
5357
 
5005
5358
  // src/components/LegendList.tsx
5006
- var LegendList = typedMemo2(
5359
+ var LegendList = typedMemo(
5007
5360
  // biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
5008
5361
  typedForwardRef(function LegendList2(props, forwardedRef) {
5009
5362
  const { children, data: dataProp, renderItem: renderItemProp, ...restProps } = props;
@@ -5022,9 +5375,18 @@ var LegendList = typedMemo2(
5022
5375
  })
5023
5376
  );
5024
5377
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
5025
- var _a3, _b, _c, _d, _e, _f, _g;
5378
+ var _a3, _b, _c, _d, _e, _f, _g, _h;
5379
+ const noopOnScroll = React2.useCallback((_event) => {
5380
+ }, []);
5381
+ if (props.recycleItems === void 0) {
5382
+ warnDevOnce(
5383
+ "recycleItems-omitted",
5384
+ "recycleItems was not provided, so it defaults to false. Set recycleItems explicitly to true for better performance with recycling-aware rows, or false to preserve remount-on-reuse behavior."
5385
+ );
5386
+ }
5026
5387
  const {
5027
5388
  alignItemsAtEnd = false,
5389
+ anchoredEndSpace,
5028
5390
  alwaysRender,
5029
5391
  columnWrapperStyle,
5030
5392
  contentContainerStyle: contentContainerStyleProp,
@@ -5090,7 +5452,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5090
5452
  const positionComponentInternal = props.positionComponentInternal;
5091
5453
  const stickyPositionComponentInternal = props.stickyPositionComponentInternal;
5092
5454
  const {
5093
- childrenMode,
5094
5455
  positionComponentInternal: _positionComponentInternal,
5095
5456
  stickyPositionComponentInternal: _stickyPositionComponentInternal,
5096
5457
  ...restProps
@@ -5154,18 +5515,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5154
5515
  dataVersion,
5155
5516
  keyExtractor
5156
5517
  ]);
5157
- if (IS_DEV && stickyIndicesDeprecated && !stickyHeaderIndicesProp) {
5158
- warnDevOnce(
5159
- "stickyIndices",
5160
- "stickyIndices has been renamed to stickyHeaderIndices. Please update your props to use stickyHeaderIndices."
5161
- );
5162
- }
5163
- if (IS_DEV && useWindowScroll && renderScrollComponent) {
5164
- warnDevOnce(
5165
- "useWindowScrollRenderScrollComponent",
5166
- "useWindowScroll is not supported when renderScrollComponent is provided."
5167
- );
5168
- }
5169
5518
  const useWindowScrollResolved = Platform2.OS === "web" && !!useWindowScroll && !renderScrollComponent;
5170
5519
  const refState = React2.useRef(void 0);
5171
5520
  const hasOverrideItemLayout = !!overrideItemLayout;
@@ -5174,7 +5523,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5174
5523
  if (!ctx.state) {
5175
5524
  const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : getWindowSize())[horizontal ? "width" : "height"];
5176
5525
  ctx.state = {
5177
- activeStickyIndex: -1,
5178
5526
  averageSizes: {},
5179
5527
  columnSpans: [],
5180
5528
  columns: [],
@@ -5198,8 +5546,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5198
5546
  kind: initialScrollUsesOffsetOnly ? "offset" : "bootstrap",
5199
5547
  previousDataLength: dataProp.length
5200
5548
  } : void 0,
5201
- isAtEnd: false,
5202
- isAtStart: false,
5203
5549
  isEndReached: null,
5204
5550
  isFirst: true,
5205
5551
  isStartReached: null,
@@ -5210,6 +5556,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5210
5556
  minIndexSizeChanged: 0,
5211
5557
  nativeContentInset: void 0,
5212
5558
  nativeMarginTop: 0,
5559
+ pendingDataComparison: void 0,
5213
5560
  pendingNativeMVCPAdjust: void 0,
5214
5561
  positions: [],
5215
5562
  props: {},
@@ -5248,22 +5595,29 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5248
5595
  }
5249
5596
  const state = refState.current;
5250
5597
  const isFirstLocal = state.isFirst;
5251
- state.didColumnsChange = numColumnsProp !== state.props.numColumns;
5598
+ const previousNumColumnsProp = state.props.numColumns;
5599
+ state.didColumnsChange = numColumnsProp !== previousNumColumnsProp;
5252
5600
  const didDataReferenceChangeLocal = state.props.data !== dataProp;
5253
5601
  const didDataVersionChangeLocal = state.props.dataVersion !== dataVersion;
5254
- const didDataChangeLocal = didDataVersionChangeLocal || didDataReferenceChangeLocal && checkActualChange(state, dataProp, state.props.data);
5602
+ const didDataChangeLocal = didDataVersionChangeLocal || didDataReferenceChangeLocal && checkStructuralDataChange(state, dataProp, state.props.data);
5603
+ if (didDataChangeLocal && state.didFinishInitialScroll && ((_f = state.initialScroll) == null ? void 0 : _f.viewPosition) === 1 && state.props.data.length > 0) {
5604
+ clearPreservedInitialScrollTarget(state);
5605
+ }
5255
5606
  if (didDataChangeLocal) {
5256
5607
  state.dataChangeEpoch += 1;
5257
5608
  state.dataChangeNeedsScrollUpdate = true;
5258
5609
  state.didDataChange = true;
5259
5610
  state.previousData = state.props.data;
5260
5611
  }
5261
- const throttleScrollFn = scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp;
5612
+ const throttledOnScroll = useThrottledOnScroll(onScrollProp != null ? onScrollProp : noopOnScroll, scrollEventThrottle != null ? scrollEventThrottle : 0);
5613
+ const throttleScrollFn = scrollEventThrottle && onScrollProp ? throttledOnScroll : onScrollProp;
5614
+ const anchoredEndSpaceResolved = Platform2.OS === "web" && anchoredEndSpace ? { ...anchoredEndSpace, includeInEndInset: true } : anchoredEndSpace;
5262
5615
  state.props = {
5263
5616
  alignItemsAtEnd,
5264
5617
  alwaysRender,
5265
5618
  alwaysRenderIndicesArr: alwaysRenderIndices.arr,
5266
5619
  alwaysRenderIndicesSet: alwaysRenderIndices.set,
5620
+ anchoredEndSpace: anchoredEndSpaceResolved,
5267
5621
  animatedProps: animatedPropsInternal,
5268
5622
  contentInset,
5269
5623
  data: dataProp,
@@ -5353,16 +5707,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5353
5707
  if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
5354
5708
  refState.current.lastBatchingAction = Date.now();
5355
5709
  if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
5356
- IS_DEV && !childrenMode && warnDevOnce(
5357
- "keyExtractor",
5358
- "Changing data without a keyExtractor can cause slow performance and resetting scroll. If your list data can change you should use a keyExtractor with a unique id for best performance and behavior."
5359
- );
5360
5710
  refState.current.sizes.clear();
5361
5711
  refState.current.positions.length = 0;
5362
5712
  refState.current.totalSize = 0;
5363
5713
  set$(ctx, "totalSize", 0);
5364
5714
  }
5365
5715
  }
5716
+ if (IS_DEV) {
5717
+ useDevChecks(props);
5718
+ }
5366
5719
  React2.useLayoutEffect(() => {
5367
5720
  handleInitialScrollDataChange(ctx, {
5368
5721
  dataLength: dataProp.length,
@@ -5372,6 +5725,17 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5372
5725
  useBootstrapInitialScroll: usesBootstrapInitialScroll
5373
5726
  });
5374
5727
  }, [dataProp.length, didDataChangeLocal, initialScrollAtEnd, stylePaddingBottomState, usesBootstrapInitialScroll]);
5728
+ React2.useLayoutEffect(() => {
5729
+ maybeUpdateAnchoredEndSpace(ctx);
5730
+ }, [
5731
+ ctx,
5732
+ dataProp,
5733
+ dataVersion,
5734
+ anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex,
5735
+ anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorMaxSize,
5736
+ anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorOffset,
5737
+ numColumnsProp
5738
+ ]);
5375
5739
  const onLayoutFooter = React2.useCallback(
5376
5740
  (layout) => {
5377
5741
  if (!usesBootstrapInitialScroll) {
@@ -5387,14 +5751,21 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5387
5751
  [dataProp.length, initialScrollAtEnd, horizontal, stylePaddingBottomState, usesBootstrapInitialScroll]
5388
5752
  );
5389
5753
  const onLayoutChange = React2.useCallback(
5390
- (layout) => {
5754
+ (layout, fromLayoutEffect) => {
5755
+ const previousScrollLength = state.scrollLength;
5756
+ const previousOtherAxisSize = state.otherAxisSize;
5391
5757
  handleLayout(ctx, layout, setCanRender);
5758
+ maybeUpdateAnchoredEndSpace(ctx);
5759
+ const didLayoutAffectBootstrapTarget = previousScrollLength !== state.scrollLength || previousOtherAxisSize !== state.otherAxisSize;
5760
+ if (usesBootstrapInitialScroll && !fromLayoutEffect && didLayoutAffectBootstrapTarget) {
5761
+ handleBootstrapInitialScrollLayoutChange(ctx);
5762
+ }
5392
5763
  if (usesBootstrapInitialScroll) {
5393
5764
  return;
5394
5765
  }
5395
5766
  advanceCurrentInitialScrollSession(ctx);
5396
5767
  },
5397
- [usesBootstrapInitialScroll]
5768
+ [dataProp.length, initialScrollAtEnd, stylePaddingBottomState, usesBootstrapInitialScroll]
5398
5769
  );
5399
5770
  const { onLayout } = useOnLayoutSync({
5400
5771
  onLayoutChange,
@@ -5407,6 +5778,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5407
5778
  updateSnapToOffsets(ctx);
5408
5779
  }
5409
5780
  }, [snapToIndices]);
5781
+ React2.useLayoutEffect(
5782
+ () => initializeStateVars(true),
5783
+ [dataVersion, memoizedLastItemKeys.join(","), numColumnsProp, stylePaddingBottomState, stylePaddingTopState]
5784
+ );
5410
5785
  React2.useLayoutEffect(() => {
5411
5786
  const {
5412
5787
  didColumnsChange,
@@ -5416,7 +5791,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5416
5791
  } = state;
5417
5792
  const didAllocateContainers = data.length > 0 && doInitialAllocateContainers(ctx);
5418
5793
  if (!didAllocateContainers && !isFirst && (didDataChange || didColumnsChange)) {
5419
- checkResetContainers(ctx, data);
5794
+ checkResetContainers(ctx, data, { didColumnsChange });
5795
+ }
5796
+ if (didDataChange) {
5797
+ state.pendingDataComparison = void 0;
5420
5798
  }
5421
5799
  state.didColumnsChange = false;
5422
5800
  state.didDataChange = false;
@@ -5431,10 +5809,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5431
5809
  (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { forceFullItemPositions: true });
5432
5810
  }
5433
5811
  }, [extraData, hasOverrideItemLayout, numColumnsProp]);
5434
- React2.useLayoutEffect(
5435
- () => initializeStateVars(true),
5436
- [dataVersion, memoizedLastItemKeys.join(","), numColumnsProp, stylePaddingBottomState, stylePaddingTopState]
5437
- );
5438
5812
  React2.useEffect(() => {
5439
5813
  if (!onMetricsChange) {
5440
5814
  return;
@@ -5467,20 +5841,18 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5467
5841
  state.viewabilityConfigCallbackPairs = viewability;
5468
5842
  state.enableScrollForNextCalculateItemsInView = !viewability;
5469
5843
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
5470
- if (!IsNewArchitecture) {
5471
- useInit(() => {
5844
+ useInit(() => {
5845
+ if (!IsNewArchitecture) {
5472
5846
  doInitialAllocateContainers(ctx);
5473
- });
5474
- }
5847
+ }
5848
+ });
5475
5849
  React2.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx), []);
5476
- if (Platform2.OS === "web") {
5477
- React2.useEffect(() => {
5478
- if (usesBootstrapInitialScroll) {
5479
- return;
5480
- }
5481
- advanceCurrentInitialScrollSession(ctx);
5482
- }, [usesBootstrapInitialScroll]);
5483
- }
5850
+ React2.useEffect(() => {
5851
+ if (Platform2.OS !== "web" || usesBootstrapInitialScroll) {
5852
+ return;
5853
+ }
5854
+ advanceCurrentInitialScrollSession(ctx);
5855
+ }, [ctx, usesBootstrapInitialScroll]);
5484
5856
  const fns = React2.useMemo(
5485
5857
  () => ({
5486
5858
  getRenderedItem: (key) => getRenderedItem(ctx, key),
@@ -5518,7 +5890,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5518
5890
  onScroll: onScrollHandler,
5519
5891
  recycleItems,
5520
5892
  refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React2__namespace.cloneElement(refreshControlElement, {
5521
- progressViewOffset: ((_f = refreshControlElement.props.progressViewOffset) != null ? _f : 0) + stylePaddingTopState
5893
+ progressViewOffset: ((_g = refreshControlElement.props.progressViewOffset) != null ? _g : 0) + stylePaddingTopState
5522
5894
  }) : refreshControlElement : onRefresh && /* @__PURE__ */ React2__namespace.createElement(
5523
5895
  ReactNative.RefreshControl,
5524
5896
  {
@@ -5529,7 +5901,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5529
5901
  ),
5530
5902
  refScrollView: combinedRef,
5531
5903
  renderScrollComponent,
5532
- scrollAdjustHandler: (_g = refState.current) == null ? void 0 : _g.scrollAdjustHandler,
5904
+ scrollAdjustHandler: (_h = refState.current) == null ? void 0 : _h.scrollAdjustHandler,
5533
5905
  scrollEventThrottle: 0,
5534
5906
  snapToIndices,
5535
5907
  stickyHeaderIndices,
@@ -5544,9 +5916,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5544
5916
  var LegendListRuntime = LegendList;
5545
5917
  var internal = {
5546
5918
  getComponent,
5919
+ getStickyPushLimit,
5547
5920
  IsNewArchitecture,
5548
5921
  POSITION_OUT_OF_VIEW,
5549
5922
  peek$,
5923
+ typedForwardRef,
5924
+ typedMemo,
5550
5925
  useArr$,
5551
5926
  useCombinedRef,
5552
5927
  useStateContext
@@ -5558,8 +5933,6 @@ var internal2 = internal;
5558
5933
 
5559
5934
  exports.LegendList = LegendList3;
5560
5935
  exports.internal = internal2;
5561
- exports.typedForwardRef = typedForwardRef;
5562
- exports.typedMemo = typedMemo2;
5563
5936
  exports.useIsLastItem = useIsLastItem;
5564
5937
  exports.useListScrollSize = useListScrollSize;
5565
5938
  exports.useRecyclingEffect = useRecyclingEffect;