@legendapp/list 1.1.3 → 2.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -3,7 +3,6 @@
3
3
  var React2 = require('react');
4
4
  var reactNative = require('react-native');
5
5
  var shim = require('use-sync-external-store/shim');
6
- var list = require('@legendapp/list');
7
6
 
8
7
  function _interopNamespace(e) {
9
8
  if (e && e.__esModule) return e;
@@ -31,7 +30,6 @@ function StateProvider({ children }) {
31
30
  const [value] = React2__namespace.useState(() => ({
32
31
  listeners: /* @__PURE__ */ new Map(),
33
32
  values: /* @__PURE__ */ new Map([
34
- ["paddingTop", 0],
35
33
  ["alignItemsPaddingTop", 0],
36
34
  ["stylePaddingTop", 0],
37
35
  ["headerSize", 0]
@@ -134,17 +132,8 @@ var DebugRow = ({ children }) => {
134
132
  };
135
133
  var DebugView = React2__namespace.memo(function DebugView2({ state }) {
136
134
  const ctx = useStateContext();
137
- const [
138
- totalSize = 0,
139
- totalSizeWithScrollAdjust = 0,
140
- scrollAdjust = 0,
141
- rawScroll = 0,
142
- scroll = 0,
143
- numContainers = 0,
144
- numContainersPooled = 0
145
- ] = useArr$([
135
+ const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, numContainers = 0, numContainersPooled = 0] = useArr$([
146
136
  "totalSize",
147
- "totalSizeWithScrollAdjust",
148
137
  "scrollAdjust",
149
138
  "debugRawScroll",
150
139
  "debugComputedScroll",
@@ -177,7 +166,6 @@ var DebugView = React2__namespace.memo(function DebugView2({ state }) {
177
166
  /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "At end:"), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, String(state.isAtEnd))),
178
167
  /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null),
179
168
  /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "ScrollAdjust:"), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, scrollAdjust.toFixed(2))),
180
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "TotalSizeReal: "), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, totalSizeWithScrollAdjust.toFixed(2))),
181
169
  /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null),
182
170
  /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "RawScroll: "), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, rawScroll.toFixed(2))),
183
171
  /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "ComputedScroll: "), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, scroll.toFixed(2)))
@@ -332,11 +320,6 @@ var LeanView = reactNative.Platform.OS === "android" || reactNative.Platform.OS
332
320
 
333
321
  // src/constants.ts
334
322
  var POSITION_OUT_OF_VIEW = -1e7;
335
- var ANCHORED_POSITION_OUT_OF_VIEW = {
336
- type: "top",
337
- relativeCoordinate: POSITION_OUT_OF_VIEW,
338
- top: POSITION_OUT_OF_VIEW
339
- };
340
323
  var ENABLE_DEVMODE = __DEV__ && false;
341
324
  var ENABLE_DEBUG_VIEW = __DEV__ && false;
342
325
  var IsNewArchitecture = global.nativeFabricUIManager != null;
@@ -352,23 +335,13 @@ var Container = ({
352
335
  }) => {
353
336
  const ctx = useStateContext();
354
337
  const columnWrapperStyle = ctx.columnWrapperStyle;
355
- const [
356
- maintainVisibleContentPosition,
357
- position = ANCHORED_POSITION_OUT_OF_VIEW,
358
- column = 0,
359
- numColumns,
360
- lastItemKeys,
361
- itemKey,
362
- data,
363
- extraData
364
- ] = useArr$([
365
- "maintainVisibleContentPosition",
366
- `containerPosition${id}`,
338
+ const [column = 0, data, itemKey, position = POSITION_OUT_OF_VIEW, numColumns, lastItemKeys, extraData] = useArr$([
367
339
  `containerColumn${id}`,
340
+ `containerItemData${id}`,
341
+ `containerItemKey${id}`,
342
+ `containerPosition${id}`,
368
343
  "numColumns",
369
344
  "lastItemKeys",
370
- `containerItemKey${id}`,
371
- `containerItemData${id}`,
372
345
  "extraData"
373
346
  ]);
374
347
  const refLastSize = React2.useRef();
@@ -377,6 +350,7 @@ var Container = ({
377
350
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
378
351
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
379
352
  const isALastItem = lastItemKeys.includes(itemKey);
353
+ let didLayout = false;
380
354
  let paddingStyles;
381
355
  if (columnWrapperStyle) {
382
356
  const { columnGap, rowGap, gap } = columnWrapperStyle;
@@ -397,14 +371,14 @@ var Container = ({
397
371
  position: "absolute",
398
372
  top: otherAxisPos,
399
373
  height: otherAxisSize,
400
- left: position.relativeCoordinate,
374
+ left: position,
401
375
  ...paddingStyles || {}
402
376
  } : {
403
377
  position: "absolute",
404
378
  left: otherAxisPos,
405
379
  right: numColumns > 1 ? null : 0,
406
380
  width: otherAxisSize,
407
- top: position.relativeCoordinate,
381
+ top: position,
408
382
  ...paddingStyles || {}
409
383
  };
410
384
  const renderedItemInfo = React2.useMemo(
@@ -415,9 +389,14 @@ var Container = ({
415
389
  const triggerLayout = React2.useCallback(() => {
416
390
  forceLayoutRender((v) => v + 1);
417
391
  }, []);
392
+ const contextValue = React2.useMemo(() => {
393
+ ctx.viewRefs.set(id, ref);
394
+ return { containerId: id, itemKey, index, value: data, triggerLayout };
395
+ }, [id, itemKey, index, data]);
418
396
  const onLayout = (event) => {
419
397
  var _a, _b;
420
398
  if (!isNullOrUndefined(itemKey)) {
399
+ didLayout = true;
421
400
  let layout = event.nativeEvent.layout;
422
401
  const size = layout[horizontal ? "width" : "height"];
423
402
  const doUpdate = () => {
@@ -451,7 +430,7 @@ var Container = ({
451
430
  React2.useEffect(() => {
452
431
  if (!isNullOrUndefined(itemKey)) {
453
432
  const timeout = setTimeout(() => {
454
- if (refLastSize.current) {
433
+ if (!didLayout && refLastSize.current) {
455
434
  updateItemSize(itemKey, refLastSize.current);
456
435
  }
457
436
  }, 16);
@@ -461,20 +440,7 @@ var Container = ({
461
440
  }
462
441
  }, [itemKey]);
463
442
  }
464
- const contextValue = React2.useMemo(() => {
465
- ctx.viewRefs.set(id, ref);
466
- return { containerId: id, itemKey, index, value: data, triggerLayout };
467
- }, [id, itemKey, index, data]);
468
- const contentFragment = /* @__PURE__ */ React2__namespace.default.createElement(React2__namespace.default.Fragment, { key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React2__namespace.default.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && !isALastItem && /* @__PURE__ */ React2__namespace.default.createElement(ItemSeparatorComponent, { leadingItem: renderedItemInfo.item })));
469
- if (maintainVisibleContentPosition) {
470
- const anchorStyle = horizontal ? position.type === "top" ? { position: "absolute", left: 0, top: 0, bottom: 0, flexDirection: "row", alignItems: "stretch" } : { position: "absolute", right: 0, top: 0, bottom: 0, flexDirection: "row", alignItems: "stretch" } : position.type === "top" ? { position: "absolute", top: 0, left: 0, right: 0 } : { position: "absolute", bottom: 0, left: 0, right: 0 };
471
- if (__DEV__ && ENABLE_DEVMODE) {
472
- anchorStyle.borderColor = position.type === "top" ? "red" : "blue";
473
- anchorStyle.borderWidth = 1;
474
- }
475
- return /* @__PURE__ */ React2__namespace.default.createElement(LeanView, { style }, /* @__PURE__ */ React2__namespace.default.createElement(LeanView, { style: [anchorStyle, paddingStyles], onLayout, ref }, contentFragment, __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React2__namespace.default.createElement(reactNative.Text, { style: { position: "absolute", top: 0, left: 0, zIndex: 1e3 } }, position.top)));
476
- }
477
- return /* @__PURE__ */ React2__namespace.default.createElement(LeanView, { style, onLayout, ref }, contentFragment);
443
+ return /* @__PURE__ */ React2__namespace.createElement(LeanView, { style, onLayout, ref, key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React2__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && !isALastItem && /* @__PURE__ */ React2__namespace.createElement(ItemSeparatorComponent, { leadingItem: renderedItemInfo.item })));
478
444
  };
479
445
  var typedForwardRef = React2.forwardRef;
480
446
  var typedMemo = React2.memo;
@@ -483,21 +449,35 @@ var useAnimatedValue = (initialValue) => {
483
449
  };
484
450
 
485
451
  // src/useValue$.ts
486
- function useValue$(key, getValue, useMicrotask) {
452
+ function useValue$(key, params) {
487
453
  var _a;
454
+ const { getValue, delay } = params || {};
488
455
  const ctx = useStateContext();
489
456
  const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
490
457
  React2.useMemo(() => {
491
458
  let newValue = void 0;
459
+ let prevValue = void 0;
460
+ let didQueueTask = false;
492
461
  listen$(ctx, key, (v) => {
493
- if (useMicrotask && newValue === void 0) {
494
- queueMicrotask(() => {
495
- animValue.setValue(newValue);
496
- newValue = void 0;
497
- });
498
- }
499
462
  newValue = getValue ? getValue(v) : v;
500
- if (!useMicrotask) {
463
+ if (delay !== void 0) {
464
+ const fn = () => {
465
+ didQueueTask = false;
466
+ if (newValue !== void 0) {
467
+ animValue.setValue(newValue);
468
+ }
469
+ };
470
+ const delayValue = typeof delay === "function" ? delay(newValue, prevValue) : delay;
471
+ prevValue = newValue;
472
+ if (!didQueueTask) {
473
+ didQueueTask = true;
474
+ if (delayValue === 0) {
475
+ queueMicrotask(fn);
476
+ } else {
477
+ setTimeout(fn, delayValue);
478
+ }
479
+ }
480
+ } else {
501
481
  animValue.setValue(newValue);
502
482
  }
503
483
  });
@@ -517,19 +497,12 @@ var Containers = typedMemo(function Containers2({
517
497
  const ctx = useStateContext();
518
498
  const columnWrapperStyle = ctx.columnWrapperStyle;
519
499
  const [numContainers, numColumns] = useArr$(["numContainersPooled", "numColumns"]);
520
- const animSize = useValue$(
521
- "totalSizeWithScrollAdjust",
522
- void 0,
523
- /*useMicrotask*/
524
- true
525
- );
526
- const animOpacity = waitForInitialLayout ? useValue$("containersDidLayout", (value) => value ? 1 : 0) : void 0;
527
- const otherAxisSize = useValue$(
528
- "otherAxisSize",
529
- void 0,
530
- /*useMicrotask*/
531
- true
532
- );
500
+ const animSize = useValue$("totalSize", {
501
+ // Use a microtask if increasing the size significantly, otherwise use a timeout
502
+ delay: (value, prevValue) => !prevValue || value - prevValue > 20 ? 0 : 200
503
+ });
504
+ const animOpacity = waitForInitialLayout && !IsNewArchitecture ? useValue$("containersDidLayout", { getValue: (value) => value ? 1 : 0 }) : void 0;
505
+ const otherAxisSize = useValue$("otherAxisSize", { delay: 0 });
533
506
  const containers = [];
534
507
  for (let i = 0; i < numContainers; i++) {
535
508
  containers.push(
@@ -564,33 +537,41 @@ var Containers = typedMemo(function Containers2({
564
537
  }
565
538
  return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style }, containers);
566
539
  });
567
- function ListHeaderComponentContainer({
568
- children,
569
- style,
570
- ctx,
571
- horizontal,
572
- waitForInitialLayout
573
- }) {
574
- var _a;
575
- const hasData = ((_a = peek$(ctx, "lastItemKeys")) == null ? void 0 : _a.length) > 0;
576
- const scrollAdjust = useValue$("scrollAdjust", (v) => v != null ? v : 0, true);
577
- const animOpacity = waitForInitialLayout ? useValue$("containersDidLayout", (value) => value ? 1 : 0) : void 0;
578
- const additionalSize = {
579
- transform: [{ translateY: reactNative.Animated.multiply(scrollAdjust, -1) }],
580
- // Header should show if there's no data yet, but containersDidLayout will be false until it has some data
581
- opacity: hasData ? animOpacity : 1
582
- };
540
+ function ScrollAdjust() {
541
+ const bias = 1e7;
542
+ const [scrollAdjust, scrollAdjustUserOffset] = useArr$(["scrollAdjust", "scrollAdjustUserOffset"]);
543
+ const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0) + bias;
583
544
  return /* @__PURE__ */ React2__namespace.createElement(
584
- reactNative.Animated.View,
545
+ reactNative.View,
585
546
  {
586
- style: [style, additionalSize],
587
- onLayout: (event) => {
588
- const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
589
- set$(ctx, "headerSize", size);
547
+ style: {
548
+ position: "absolute",
549
+ height: 0,
550
+ width: 0,
551
+ top: scrollOffset,
552
+ left: 0
590
553
  }
554
+ }
555
+ );
556
+ }
557
+ function useSyncLayout({
558
+ onChange
559
+ }) {
560
+ const ref = React2.useRef(null);
561
+ const onLayout = React2.useCallback(
562
+ (event) => {
563
+ onChange(event.nativeEvent.layout, false);
591
564
  },
592
- children
565
+ [onChange]
593
566
  );
567
+ React2.useLayoutEffect(() => {
568
+ if (ref.current) {
569
+ ref.current.measure((x, y, width, height) => {
570
+ onChange({ x, y, width, height }, true);
571
+ });
572
+ }
573
+ }, []);
574
+ return { onLayout, ref };
594
575
  }
595
576
 
596
577
  // src/ListComponent.tsx
@@ -603,58 +584,28 @@ var getComponent = (Component) => {
603
584
  }
604
585
  return null;
605
586
  };
606
- var PaddingAndAdjust = () => {
607
- const animPaddingTop = useValue$("paddingTop", (v) => v, true);
608
- const animScrollAdjust = useValue$("scrollAdjust", (v) => v, true);
609
- const additionalSize = { marginTop: animScrollAdjust, paddingTop: animPaddingTop };
610
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style: additionalSize });
587
+ var Padding = () => {
588
+ const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
589
+ return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } });
611
590
  };
612
- var PaddingAndAdjustDevMode = () => {
613
- const animPaddingTop = useValue$("paddingTop", (v) => v, true);
614
- const animScrollAdjust = useValue$("scrollAdjust", (v) => v, true);
615
- return /* @__PURE__ */ React2__namespace.createElement(React2__namespace.Fragment, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style: { marginTop: animScrollAdjust } }), /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React2__namespace.createElement(
591
+ var PaddingDevMode = () => {
592
+ const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
593
+ return /* @__PURE__ */ React2__namespace.createElement(React2__namespace.Fragment, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React2__namespace.createElement(
616
594
  reactNative.Animated.View,
617
595
  {
618
596
  style: {
619
597
  position: "absolute",
620
- top: reactNative.Animated.add(animScrollAdjust, reactNative.Animated.multiply(animScrollAdjust, -1)),
598
+ top: 0,
621
599
  height: animPaddingTop,
622
600
  left: 0,
623
601
  right: 0,
624
602
  backgroundColor: "green"
625
603
  }
626
604
  }
627
- ), /* @__PURE__ */ React2__namespace.createElement(
628
- reactNative.Animated.View,
629
- {
630
- style: {
631
- position: "absolute",
632
- top: animPaddingTop,
633
- height: animScrollAdjust,
634
- left: -16,
635
- right: -16,
636
- backgroundColor: "lightblue"
637
- }
638
- }
639
- ), /* @__PURE__ */ React2__namespace.createElement(
640
- reactNative.Animated.View,
641
- {
642
- style: {
643
- position: "absolute",
644
- top: animPaddingTop,
645
- height: reactNative.Animated.multiply(animScrollAdjust, -1),
646
- width: 8,
647
- right: 4,
648
- borderStyle: "dashed",
649
- borderColor: "blue",
650
- borderWidth: 1,
651
- backgroundColor: "lightblue"
652
- //backgroundColor: "blue",
653
- }
654
- }
655
605
  ));
656
606
  };
657
607
  var ListComponent = typedMemo(function ListComponent2({
608
+ canRender,
658
609
  style,
659
610
  contentContainerStyle,
660
611
  horizontal,
@@ -675,13 +626,25 @@ var ListComponent = typedMemo(function ListComponent2({
675
626
  refScrollView,
676
627
  maintainVisibleContentPosition,
677
628
  renderScrollComponent,
629
+ scrollAdjustHandler,
630
+ onLayoutHeader,
678
631
  ...rest
679
632
  }) {
680
633
  const ctx = useStateContext();
634
+ const { onLayout: onLayoutHeaderSync, ref: refHeader } = useSyncLayout({
635
+ onChange: onLayoutHeader
636
+ });
681
637
  const ScrollComponent = renderScrollComponent ? React2.useMemo(
682
638
  () => React2__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
683
639
  [renderScrollComponent]
684
640
  ) : reactNative.ScrollView;
641
+ React2__namespace.useEffect(() => {
642
+ if (canRender) {
643
+ setTimeout(() => {
644
+ scrollAdjustHandler.setMounted();
645
+ }, 0);
646
+ }
647
+ }, [canRender]);
685
648
  return /* @__PURE__ */ React2__namespace.createElement(
686
649
  ScrollComponent,
687
650
  {
@@ -700,19 +663,11 @@ var ListComponent = typedMemo(function ListComponent2({
700
663
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
701
664
  ref: refScrollView
702
665
  },
703
- ENABLE_DEVMODE ? /* @__PURE__ */ React2__namespace.createElement(PaddingAndAdjustDevMode, null) : /* @__PURE__ */ React2__namespace.createElement(PaddingAndAdjust, null),
704
- ListHeaderComponent && /* @__PURE__ */ React2__namespace.createElement(
705
- ListHeaderComponentContainer,
706
- {
707
- style: ListHeaderComponentStyle,
708
- ctx,
709
- horizontal,
710
- waitForInitialLayout
711
- },
712
- getComponent(ListHeaderComponent)
713
- ),
666
+ maintainVisibleContentPosition && /* @__PURE__ */ React2__namespace.createElement(ScrollAdjust, null),
667
+ ENABLE_DEVMODE ? /* @__PURE__ */ React2__namespace.createElement(PaddingDevMode, null) : /* @__PURE__ */ React2__namespace.createElement(Padding, null),
668
+ ListHeaderComponent && /* @__PURE__ */ React2__namespace.createElement(reactNative.View, { style: ListHeaderComponentStyle, onLayout: onLayoutHeaderSync, ref: refHeader }, getComponent(ListHeaderComponent)),
714
669
  ListEmptyComponent && getComponent(ListEmptyComponent),
715
- /* @__PURE__ */ React2__namespace.createElement(
670
+ canRender && /* @__PURE__ */ React2__namespace.createElement(
716
671
  Containers,
717
672
  {
718
673
  horizontal,
@@ -740,49 +695,22 @@ var ListComponent = typedMemo(function ListComponent2({
740
695
  // src/ScrollAdjustHandler.ts
741
696
  var ScrollAdjustHandler = class {
742
697
  constructor(ctx) {
743
- this.ctx = ctx;
744
698
  this.appliedAdjust = 0;
745
- this.busy = false;
746
- this.isPaused = false;
747
- this.isDisabled = false;
699
+ this.mounted = false;
748
700
  this.context = ctx;
749
701
  }
750
- doAjdust() {
751
- set$(this.context, "scrollAdjust", this.appliedAdjust);
752
- this.busy = false;
753
- }
754
- requestAdjust(adjust, onAdjusted) {
755
- if (this.isDisabled) {
756
- return;
757
- }
758
- const oldAdjustTop = peek$(this.context, "scrollAdjust");
759
- if (oldAdjustTop === adjust) {
760
- return;
761
- }
762
- this.appliedAdjust = adjust;
763
- if (!this.busy && !this.isPaused) {
764
- this.busy = true;
765
- this.doAjdust();
766
- onAdjusted(oldAdjustTop - adjust);
702
+ requestAdjust(add) {
703
+ const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
704
+ this.appliedAdjust = add + oldAdjustTop;
705
+ const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
706
+ if (this.mounted) {
707
+ set();
708
+ } else {
709
+ requestAnimationFrame(set);
767
710
  }
768
711
  }
769
- getAppliedAdjust() {
770
- return this.appliedAdjust;
771
- }
772
- pauseAdjust() {
773
- this.isPaused = true;
774
- }
775
- setDisableAdjust(disable) {
776
- this.isDisabled = disable;
777
- }
778
- // return true if it was paused
779
- unPauseAdjust() {
780
- if (this.isPaused) {
781
- this.isPaused = false;
782
- this.doAjdust();
783
- return true;
784
- }
785
- return false;
712
+ setMounted() {
713
+ this.mounted = true;
786
714
  }
787
715
  };
788
716
  var useCombinedRef = (...refs) => {
@@ -930,13 +858,12 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
930
858
  }
931
859
  }
932
860
  function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
933
- const { sizes, positions, scroll: scrollState, scrollAdjustHandler } = state;
861
+ const { sizes, positions, scroll: scrollState } = state;
934
862
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
935
863
  const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
936
864
  const viewAreaMode = viewAreaCoveragePercentThreshold != null;
937
865
  const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
938
- const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
939
- const scroll = scrollState - previousScrollAdjust - topPad;
866
+ const scroll = scrollState - topPad;
940
867
  const top = positions.get(key) - scroll;
941
868
  const size = sizes.get(key) || 0;
942
869
  const bottom = top + size;
@@ -1008,6 +935,7 @@ var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
1008
935
  return /* @__PURE__ */ React2__namespace.createElement(StateProvider, null, /* @__PURE__ */ React2__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
1009
936
  });
1010
937
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
938
+ var _a;
1011
939
  const {
1012
940
  data: dataProp = [],
1013
941
  initialScrollIndex: initialScrollIndexProp,
@@ -1050,9 +978,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1050
978
  onViewableItemsChanged,
1051
979
  ...rest
1052
980
  } = props;
981
+ const [renderNum, setRenderNum] = React2.useState(0);
1053
982
  const initialScroll = typeof initialScrollIndexProp === "number" ? { index: initialScrollIndexProp } : initialScrollIndexProp;
1054
983
  const initialScrollIndex = initialScroll == null ? void 0 : initialScroll.index;
1055
984
  const refLoadStartTime = React2.useRef(Date.now());
985
+ const [canRender, setCanRender] = React2__namespace.useState(!IsNewArchitecture);
1056
986
  const callbacks = React2.useRef({
1057
987
  onStartReached: rest.onStartReached,
1058
988
  onEndReached: rest.onEndReached
@@ -1063,12 +993,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1063
993
  const style = { ...reactNative.StyleSheet.flatten(styleProp) };
1064
994
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
1065
995
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
1066
- if (style == null ? void 0 : style.paddingTop) {
1067
- style.paddingTop = void 0;
1068
- }
1069
- if (contentContainerStyle == null ? void 0 : contentContainerStyle.paddingTop) {
1070
- contentContainerStyle.paddingTop = void 0;
1071
- }
1072
996
  const ctx = useStateContext();
1073
997
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
1074
998
  const refScroller = React2.useRef(null);
@@ -1078,56 +1002,45 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1078
1002
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
1079
1003
  const refState = React2.useRef();
1080
1004
  const getId = (index) => {
1081
- var _a;
1082
- const data = (_a = refState.current) == null ? void 0 : _a.data;
1083
- if (!data) {
1005
+ const state = refState.current;
1006
+ if (!(state == null ? void 0 : state.data)) {
1084
1007
  return "";
1085
1008
  }
1009
+ const data = state.data;
1086
1010
  const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
1087
- return `${ret}`;
1011
+ const id = ret;
1012
+ state.idCache.set(index, id);
1013
+ return id;
1088
1014
  };
1089
1015
  const getItemSize = (key, index, data, useAverageSize = false) => {
1090
1016
  const state = refState.current;
1091
- state.sizesKnown.get(key);
1017
+ const sizeKnown = state.sizesKnown.get(key);
1018
+ if (sizeKnown !== void 0) {
1019
+ return sizeKnown;
1020
+ }
1092
1021
  const sizePrevious = state.sizes.get(key);
1093
- let size;
1094
- peek$(ctx, "numColumns");
1095
- if (size === void 0 && sizePrevious !== void 0) {
1022
+ if (sizePrevious !== void 0) {
1096
1023
  return sizePrevious;
1097
1024
  }
1098
- if (size === void 0) {
1099
- size = getEstimatedItemSize ? getEstimatedItemSize(index, data) : estimatedItemSize;
1100
- }
1025
+ const size = getEstimatedItemSize ? getEstimatedItemSize(index, data) : estimatedItemSize;
1101
1026
  state.sizes.set(key, size);
1102
1027
  return size;
1103
1028
  };
1104
- const calculateOffsetForIndex = (indexParam) => {
1105
- var _a;
1106
- const isFromInit = indexParam === void 0;
1107
- const index = isFromInit ? initialScrollIndex : indexParam;
1108
- const data = dataProp;
1029
+ const calculateOffsetForIndex = (index) => {
1030
+ var _a2;
1031
+ let position = 0;
1109
1032
  if (index !== void 0) {
1110
- let offset = 0;
1111
- const canGetSize = !!refState.current;
1112
- if (canGetSize || getEstimatedItemSize) {
1113
- const sizeFn = (index2) => {
1114
- if (canGetSize) {
1115
- return getItemSize(getId(index2), index2, data[index2], true);
1116
- }
1117
- return getEstimatedItemSize(index2, data[index2]);
1118
- };
1119
- for (let i = 0; i < index; i++) {
1120
- offset += sizeFn(i);
1121
- }
1122
- } else {
1123
- offset = index * estimatedItemSize;
1124
- }
1125
- const adjust = peek$(ctx, "containersDidLayout") ? ((_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler.getAppliedAdjust()) || 0 : 0;
1126
- const stylePaddingTop = isFromInit ? stylePaddingTopState : peek$(ctx, "stylePaddingTop");
1127
- const topPad = (stylePaddingTop != null ? stylePaddingTop : 0) + peek$(ctx, "headerSize");
1128
- return offset / numColumnsProp - adjust + topPad;
1033
+ position = ((_a2 = refState.current) == null ? void 0 : _a2.positions.get(getId(index))) || 0;
1129
1034
  }
1130
- return 0;
1035
+ const paddingTop = peek$(ctx, "stylePaddingTop");
1036
+ if (paddingTop) {
1037
+ position += paddingTop;
1038
+ }
1039
+ const headerSize = peek$(ctx, "headerSize");
1040
+ if (headerSize) {
1041
+ position += headerSize;
1042
+ }
1043
+ return position;
1131
1044
  };
1132
1045
  const calculateOffsetWithOffsetPosition = (offsetParam, params) => {
1133
1046
  const { index, viewOffset, viewPosition } = params;
@@ -1141,15 +1054,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1141
1054
  }
1142
1055
  return offset;
1143
1056
  };
1144
- const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React2.useMemo(() => calculateOffsetForIndex(void 0), []);
1145
1057
  if (!refState.current) {
1146
- const initialScrollLength = (estimatedListSize != null ? estimatedListSize : reactNative.Dimensions.get("window"))[horizontal ? "width" : "height"];
1058
+ const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { width: 0, height: 0 } : reactNative.Dimensions.get("window"))[horizontal ? "width" : "height"];
1147
1059
  refState.current = {
1148
1060
  sizes: /* @__PURE__ */ new Map(),
1149
1061
  positions: /* @__PURE__ */ new Map(),
1150
1062
  columns: /* @__PURE__ */ new Map(),
1151
1063
  pendingAdjust: 0,
1152
- isStartReached: initialContentOffset < initialScrollLength * onStartReachedThreshold,
1064
+ isStartReached: false,
1153
1065
  isEndReached: false,
1154
1066
  isAtEnd: false,
1155
1067
  isAtStart: false,
@@ -1159,9 +1071,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1159
1071
  startNoBuffer: -1,
1160
1072
  endBuffered: -1,
1161
1073
  endNoBuffer: -1,
1162
- scroll: initialContentOffset || 0,
1074
+ firstFullyOnScreenIndex: -1,
1075
+ scroll: 0,
1163
1076
  totalSize: 0,
1164
- totalSizeBelowAnchor: 0,
1165
1077
  timeouts: /* @__PURE__ */ new Set(),
1166
1078
  viewabilityConfigCallbackPairs: void 0,
1167
1079
  renderItem: void 0,
@@ -1173,12 +1085,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1173
1085
  scrollPending: 0,
1174
1086
  indexByKey: /* @__PURE__ */ new Map(),
1175
1087
  scrollHistory: [],
1176
- scrollVelocity: 0,
1177
1088
  sizesKnown: /* @__PURE__ */ new Map(),
1178
1089
  timeoutSizeMessage: 0,
1179
- scrollTimer: void 0,
1180
- belowAnchorElementPositions: void 0,
1181
- rowHeights: /* @__PURE__ */ new Map(),
1182
1090
  startReachedBlockedByTimer: false,
1183
1091
  endReachedBlockedByTimer: false,
1184
1092
  scrollForNextCalculateItemsInView: void 0,
@@ -1187,41 +1095,126 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1187
1095
  queuedCalculateItemsInView: 0,
1188
1096
  lastBatchingAction: Date.now(),
1189
1097
  averageSizes: {},
1190
- onScroll: onScrollProp
1098
+ onScroll: onScrollProp,
1099
+ idsInView: [],
1100
+ containerItemKeys: /* @__PURE__ */ new Set(),
1101
+ idCache: /* @__PURE__ */ new Map()
1191
1102
  };
1192
- const dataLength = dataProp.length;
1193
- if (maintainVisibleContentPosition && dataLength > 0) {
1194
- if (initialScrollIndex && initialScrollIndex < dataLength) {
1195
- refState.current.anchorElement = {
1196
- coordinate: initialContentOffset,
1197
- id: getId(initialScrollIndex)
1198
- };
1199
- } else if (dataLength > 0) {
1200
- refState.current.anchorElement = {
1201
- coordinate: initialContentOffset,
1202
- id: getId(0)
1203
- };
1204
- } else {
1205
- __DEV__ && warnDevOnce(
1206
- "maintainVisibleContentPosition",
1207
- "[legend-list] maintainVisibleContentPosition was not able to find an anchor element"
1208
- );
1209
- }
1210
- }
1211
- set$(ctx, "scrollAdjust", 0);
1212
1103
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
1213
1104
  set$(ctx, "extraData", extraData);
1214
1105
  }
1215
1106
  const didDataChange = refState.current.data !== dataProp;
1216
1107
  refState.current.data = dataProp;
1217
1108
  refState.current.onScroll = onScrollProp;
1218
- const getAnchorElementIndex = () => {
1219
- const state = refState.current;
1220
- if (state.anchorElement) {
1221
- const el = state.indexByKey.get(state.anchorElement.id);
1222
- return el;
1109
+ const getScrollVelocity = () => {
1110
+ const { scrollHistory } = refState.current;
1111
+ let velocity = 0;
1112
+ if (scrollHistory.length >= 1) {
1113
+ const newest = scrollHistory[scrollHistory.length - 1];
1114
+ let oldest;
1115
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
1116
+ const entry = scrollHistory[i];
1117
+ const nextEntry = scrollHistory[i + 1];
1118
+ if (i > 0) {
1119
+ const prevEntry = scrollHistory[i - 1];
1120
+ const prevDirection = entry.scroll - prevEntry.scroll;
1121
+ const currentDirection = nextEntry.scroll - entry.scroll;
1122
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1123
+ break;
1124
+ }
1125
+ }
1126
+ }
1127
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
1128
+ const entry = scrollHistory[i];
1129
+ if (newest.time - entry.time <= 1e3) {
1130
+ oldest = entry;
1131
+ break;
1132
+ }
1133
+ }
1134
+ if (oldest) {
1135
+ const scrollDiff = newest.scroll - oldest.scroll;
1136
+ const timeDiff = newest.time - oldest.time;
1137
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1138
+ }
1139
+ }
1140
+ return velocity;
1141
+ };
1142
+ const updateAllPositions = (dataChanged) => {
1143
+ var _a2, _b, _c;
1144
+ const { columns, data, indexByKey, positions, firstFullyOnScreenIndex, idCache, sizes } = refState.current;
1145
+ const numColumns = (_a2 = peek$(ctx, "numColumns")) != null ? _a2 : numColumnsProp;
1146
+ const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1147
+ const scrollVelocity = getScrollVelocity();
1148
+ if (dataChanged) {
1149
+ indexByKey.clear();
1150
+ idCache.clear();
1151
+ }
1152
+ const shouldUseBackwards = !dataChanged && scrollVelocity < 0 && firstFullyOnScreenIndex > 5 && firstFullyOnScreenIndex < data.length;
1153
+ if (shouldUseBackwards && firstFullyOnScreenIndex !== void 0) {
1154
+ const anchorId = getId(firstFullyOnScreenIndex);
1155
+ const anchorPosition = positions.get(anchorId);
1156
+ if (anchorPosition !== void 0) {
1157
+ let currentRowTop2 = anchorPosition;
1158
+ let maxSizeInRow2 = 0;
1159
+ let bailout = false;
1160
+ for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
1161
+ const id = getId(i);
1162
+ const size = getItemSize(id, i, data[i], false);
1163
+ const itemColumn = columns.get(id);
1164
+ maxSizeInRow2 = Math.max(maxSizeInRow2, size);
1165
+ if (itemColumn === 1) {
1166
+ currentRowTop2 -= maxSizeInRow2;
1167
+ maxSizeInRow2 = 0;
1168
+ }
1169
+ if (currentRowTop2 < -2e3) {
1170
+ bailout = true;
1171
+ break;
1172
+ }
1173
+ positions.set(id, currentRowTop2);
1174
+ }
1175
+ if (!bailout) {
1176
+ updateTotalSize();
1177
+ return;
1178
+ }
1179
+ }
1180
+ }
1181
+ let currentRowTop = 0;
1182
+ let column = 1;
1183
+ let maxSizeInRow = 0;
1184
+ const hasColumns = numColumns > 1;
1185
+ const needsIndexByKey = dataChanged || indexByKey.size === 0;
1186
+ const dataLength = data.length;
1187
+ for (let i = 0; i < dataLength; i++) {
1188
+ const id = (_b = idCache.get(i)) != null ? _b : getId(i);
1189
+ const size = (_c = sizes.get(id)) != null ? _c : getItemSize(id, i, data[i], false);
1190
+ if (__DEV__ && needsIndexByKey) {
1191
+ if (indexByKeyForChecking.has(id)) {
1192
+ console.error(
1193
+ `[legend-list] Error: Detected overlapping key (${id}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`
1194
+ );
1195
+ }
1196
+ indexByKeyForChecking.set(id, i);
1197
+ }
1198
+ positions.set(id, currentRowTop);
1199
+ if (needsIndexByKey) {
1200
+ indexByKey.set(id, i);
1201
+ }
1202
+ columns.set(id, column);
1203
+ if (hasColumns) {
1204
+ if (size > maxSizeInRow) {
1205
+ maxSizeInRow = size;
1206
+ }
1207
+ column++;
1208
+ if (column > numColumns) {
1209
+ currentRowTop += maxSizeInRow;
1210
+ column = 1;
1211
+ maxSizeInRow = 0;
1212
+ }
1213
+ } else {
1214
+ currentRowTop += size;
1215
+ }
1223
1216
  }
1224
- return void 0;
1217
+ updateTotalSize();
1225
1218
  };
1226
1219
  const scrollToIndex = ({
1227
1220
  index,
@@ -1229,7 +1222,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1229
1222
  animated = true,
1230
1223
  viewPosition
1231
1224
  }) => {
1232
- var _a;
1233
1225
  const state = refState.current;
1234
1226
  if (index >= state.data.length) {
1235
1227
  index = state.data.length - 1;
@@ -1238,220 +1230,33 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1238
1230
  }
1239
1231
  const firstIndexOffset = calculateOffsetForIndex(index);
1240
1232
  const isLast = index === state.data.length - 1;
1241
- if (isLast && viewPosition !== void 0) {
1233
+ if (isLast && viewPosition === void 0) {
1242
1234
  viewPosition = 1;
1243
1235
  }
1244
- let firstIndexScrollPostion = firstIndexOffset - viewOffset;
1245
- const diff = Math.abs(state.scroll - firstIndexScrollPostion);
1246
- const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
1247
- const needsReanchoring = maintainVisibleContentPosition && diff > 100;
1236
+ const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1248
1237
  state.scrollForNextCalculateItemsInView = void 0;
1249
- if (needsReanchoring) {
1250
- const id = getId(index);
1251
- state.anchorElement = { id, coordinate: firstIndexOffset - topPad };
1252
- (_a = state.belowAnchorElementPositions) == null ? void 0 : _a.clear();
1253
- state.positions.clear();
1254
- calcTotalSizesAndPositions({ forgetPositions: true });
1255
- state.startBufferedId = id;
1256
- state.minIndexSizeChanged = index;
1257
- firstIndexScrollPostion = firstIndexOffset - viewOffset + state.scrollAdjustHandler.getAppliedAdjust();
1258
- }
1259
1238
  scrollTo({ offset: firstIndexScrollPostion, animated, index, viewPosition: viewPosition != null ? viewPosition : 0, viewOffset });
1260
1239
  };
1261
1240
  const setDidLayout = () => {
1262
1241
  refState.current.queuedInitialLayout = true;
1263
1242
  checkAtBottom();
1264
- const setIt = () => {
1265
- set$(ctx, "containersDidLayout", true);
1266
- if (props.onLoad) {
1267
- props.onLoad({ elapsedTimeInMs: Date.now() - refLoadStartTime.current });
1268
- }
1269
- };
1270
- if (initialScroll) {
1271
- queueMicrotask(() => {
1272
- scrollToIndex({ ...initialScroll, animated: false });
1273
- requestAnimationFrame(() => {
1274
- if (!IsNewArchitecture) {
1275
- scrollToIndex({ ...initialScroll, animated: false });
1276
- }
1277
- setIt();
1278
- });
1279
- });
1280
- } else {
1281
- queueMicrotask(setIt);
1243
+ set$(ctx, "containersDidLayout", true);
1244
+ if (props.onLoad) {
1245
+ props.onLoad({ elapsedTimeInMs: Date.now() - refLoadStartTime.current });
1282
1246
  }
1283
1247
  };
1284
- const addTotalSize = React2.useCallback((key, add, totalSizeBelowAnchor) => {
1248
+ const addTotalSize = React2.useCallback((key, add) => {
1285
1249
  const state = refState.current;
1286
- const { indexByKey, anchorElement } = state;
1287
- const index = key === null ? 0 : indexByKey.get(key);
1288
- let isAboveAnchor = false;
1289
- if (maintainVisibleContentPosition) {
1290
- if (anchorElement && index < getAnchorElementIndex()) {
1291
- isAboveAnchor = true;
1292
- }
1293
- }
1294
1250
  if (key === null) {
1295
1251
  state.totalSize = add;
1296
- state.totalSizeBelowAnchor = totalSizeBelowAnchor;
1297
1252
  } else {
1298
1253
  state.totalSize += add;
1299
- if (isAboveAnchor) {
1300
- state.totalSizeBelowAnchor += add;
1301
- }
1302
- }
1303
- let applyAdjustValue = 0;
1304
- let resultSize = state.totalSize;
1305
- if (maintainVisibleContentPosition && anchorElement !== void 0) {
1306
- const newAdjust = anchorElement.coordinate - state.totalSizeBelowAnchor;
1307
- applyAdjustValue = -newAdjust;
1308
- state.belowAnchorElementPositions = buildElementPositionsBelowAnchor();
1309
- state.rowHeights.clear();
1310
- if (applyAdjustValue !== void 0) {
1311
- resultSize -= applyAdjustValue;
1312
- state.scrollAdjustHandler.requestAdjust(applyAdjustValue, (diff) => {
1313
- state.scroll -= diff;
1314
- });
1315
- }
1316
1254
  }
1317
1255
  set$(ctx, "totalSize", state.totalSize);
1318
- set$(ctx, "totalSizeWithScrollAdjust", resultSize);
1319
1256
  if (alignItemsAtEnd) {
1320
1257
  updateAlignItemsPaddingTop();
1321
1258
  }
1322
1259
  }, []);
1323
- const getRowHeight = (n) => {
1324
- const { rowHeights, data } = refState.current;
1325
- const numColumns = peek$(ctx, "numColumns");
1326
- if (numColumns === 1) {
1327
- const id = getId(n);
1328
- return getItemSize(id, n, data[n]);
1329
- }
1330
- if (rowHeights.has(n)) {
1331
- return rowHeights.get(n) || 0;
1332
- }
1333
- let rowHeight = 0;
1334
- const startEl = n * numColumns;
1335
- for (let i = startEl; i < startEl + numColumns && i < data.length; i++) {
1336
- const id = getId(i);
1337
- const size = getItemSize(id, i, data[i]);
1338
- rowHeight = Math.max(rowHeight, size);
1339
- }
1340
- rowHeights.set(n, rowHeight);
1341
- return rowHeight;
1342
- };
1343
- const buildElementPositionsBelowAnchor = () => {
1344
- const state = refState.current;
1345
- if (!state.anchorElement) {
1346
- return /* @__PURE__ */ new Map();
1347
- }
1348
- const anchorIndex = state.indexByKey.get(state.anchorElement.id);
1349
- if (anchorIndex === 0) {
1350
- return /* @__PURE__ */ new Map();
1351
- }
1352
- const map = state.belowAnchorElementPositions || /* @__PURE__ */ new Map();
1353
- const numColumns = peek$(ctx, "numColumns");
1354
- let top = state.anchorElement.coordinate;
1355
- for (let i = anchorIndex - 1; i >= 0; i--) {
1356
- const id = getId(i);
1357
- const rowNumber = Math.floor(i / numColumns);
1358
- if (i % numColumns === 0) {
1359
- top -= getRowHeight(rowNumber);
1360
- }
1361
- map.set(id, top);
1362
- }
1363
- return map;
1364
- };
1365
- const disableScrollJumps = (timeout) => {
1366
- const state = refState.current;
1367
- if (state.scrollingTo === void 0) {
1368
- state.disableScrollJumpsFrom = state.scroll - state.scrollAdjustHandler.getAppliedAdjust();
1369
- state.scrollHistory.length = 0;
1370
- setTimeout(() => {
1371
- state.disableScrollJumpsFrom = void 0;
1372
- if (state.scrollPending !== void 0 && state.scrollPending !== state.scroll) {
1373
- updateScroll(state.scrollPending);
1374
- }
1375
- }, timeout);
1376
- }
1377
- };
1378
- const getElementPositionBelowAchor = (id) => {
1379
- var _a;
1380
- const state = refState.current;
1381
- if (!refState.current.belowAnchorElementPositions) {
1382
- state.belowAnchorElementPositions = buildElementPositionsBelowAnchor();
1383
- }
1384
- const res = state.belowAnchorElementPositions.get(id);
1385
- if (res === void 0) {
1386
- console.warn(`Undefined position below anchor ${id} ${(_a = state.anchorElement) == null ? void 0 : _a.id}`);
1387
- return 0;
1388
- }
1389
- return res;
1390
- };
1391
- const fixGaps = React2.useCallback(() => {
1392
- var _a;
1393
- const state = refState.current;
1394
- const { data, scrollLength, positions, startBuffered, endBuffered } = state;
1395
- const numColumns = peek$(ctx, "numColumns");
1396
- if (!data || scrollLength === 0 || numColumns > 1) {
1397
- return;
1398
- }
1399
- const numContainers = ctx.values.get("numContainers");
1400
- let numMeasurements = 0;
1401
- for (let i = 0; i < numContainers; i++) {
1402
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1403
- const isSizeKnown = state.sizesKnown.get(itemKey);
1404
- if (itemKey && !isSizeKnown) {
1405
- const containerRef = ctx.viewRefs.get(i);
1406
- if (containerRef) {
1407
- let measured;
1408
- (_a = containerRef.current) == null ? void 0 : _a.measure((x, y, width, height) => {
1409
- measured = { width, height };
1410
- });
1411
- numMeasurements++;
1412
- if (measured) {
1413
- updateItemSize(
1414
- itemKey,
1415
- measured,
1416
- /*fromFixGaps*/
1417
- true
1418
- );
1419
- }
1420
- }
1421
- }
1422
- }
1423
- if (numMeasurements > 0) {
1424
- let top;
1425
- const diffs = /* @__PURE__ */ new Map();
1426
- for (let i = startBuffered; i <= endBuffered; i++) {
1427
- const id = getId(i);
1428
- if (top === void 0) {
1429
- top = positions.get(id);
1430
- }
1431
- if (positions.get(id) !== top) {
1432
- diffs.set(id, top - positions.get(id));
1433
- positions.set(id, top);
1434
- }
1435
- const size = getItemSize(id, i, data[i]);
1436
- const bottom = top + size;
1437
- top = bottom;
1438
- }
1439
- for (let i = 0; i < numContainers; i++) {
1440
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1441
- const diff = diffs.get(itemKey);
1442
- if (diff) {
1443
- const prevPos = peek$(ctx, `containerPosition${i}`);
1444
- const newPos = prevPos.top + diff;
1445
- if (prevPos.top !== newPos) {
1446
- const pos = { ...prevPos };
1447
- pos.relativeCoordinate += diff;
1448
- pos.top += diff;
1449
- set$(ctx, `containerPosition${i}`, pos);
1450
- }
1451
- }
1452
- }
1453
- }
1454
- }, []);
1455
1260
  const checkAllSizesKnown = React2.useCallback(() => {
1456
1261
  const { startBuffered, endBuffered, sizesKnown } = refState.current;
1457
1262
  if (endBuffered !== null) {
@@ -1464,8 +1269,70 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1464
1269
  }
1465
1270
  return false;
1466
1271
  }, []);
1467
- const calculateItemsInView = React2.useCallback((isReset) => {
1468
- var _a;
1272
+ const requestAdjust = (positionDiff) => {
1273
+ if (Math.abs(positionDiff) > 0.1) {
1274
+ const state = refState.current;
1275
+ const doit = () => {
1276
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
1277
+ };
1278
+ state.scroll += positionDiff;
1279
+ state.scrollForNextCalculateItemsInView = void 0;
1280
+ if (peek$(ctx, "containersDidLayout")) {
1281
+ doit();
1282
+ } else {
1283
+ requestAnimationFrame(doit);
1284
+ }
1285
+ const threshold = state.scroll - positionDiff / 2;
1286
+ if (!state.ignoreScrollFromMVCP) {
1287
+ state.ignoreScrollFromMVCP = {};
1288
+ }
1289
+ if (positionDiff > 0) {
1290
+ state.ignoreScrollFromMVCP.lt = threshold;
1291
+ } else {
1292
+ state.ignoreScrollFromMVCP.gt = threshold;
1293
+ }
1294
+ if (state.ignoreScrollFromMVCPTimeout) {
1295
+ clearTimeout(state.ignoreScrollFromMVCPTimeout);
1296
+ }
1297
+ state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
1298
+ state.ignoreScrollFromMVCP = void 0;
1299
+ }, 100);
1300
+ }
1301
+ };
1302
+ const prepareMVCP = React2.useCallback(() => {
1303
+ const state = refState.current;
1304
+ const { positions, scrollingTo } = state;
1305
+ let prevPosition;
1306
+ let targetId;
1307
+ let targetIndex;
1308
+ const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1309
+ if (maintainVisibleContentPosition) {
1310
+ const indexByKey = state.indexByKey;
1311
+ if (scrollTarget !== void 0) {
1312
+ targetId = getId(scrollTarget);
1313
+ targetIndex = scrollTarget;
1314
+ } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1315
+ targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
1316
+ targetIndex = indexByKey.get(targetId);
1317
+ }
1318
+ if (targetId !== void 0 && targetIndex !== void 0) {
1319
+ prevPosition = positions.get(targetId);
1320
+ }
1321
+ }
1322
+ return () => {
1323
+ if (targetId !== void 0 && prevPosition !== void 0) {
1324
+ const newPosition = positions.get(targetId);
1325
+ if (newPosition !== void 0) {
1326
+ const positionDiff = newPosition - prevPosition;
1327
+ if (Math.abs(positionDiff) > 0.1) {
1328
+ requestAdjust(positionDiff);
1329
+ }
1330
+ }
1331
+ }
1332
+ };
1333
+ }, []);
1334
+ const calculateItemsInView = React2.useCallback((params = {}) => {
1335
+ var _a2, _b, _c, _d, _e, _f, _g, _h;
1469
1336
  const state = refState.current;
1470
1337
  const {
1471
1338
  data,
@@ -1473,20 +1340,33 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1473
1340
  startBufferedId: startBufferedIdOrig,
1474
1341
  positions,
1475
1342
  columns,
1476
- scrollAdjustHandler,
1477
- scrollVelocity: speed
1343
+ containerItemKeys,
1344
+ idCache,
1345
+ sizes,
1346
+ indexByKey,
1347
+ scrollForNextCalculateItemsInView,
1348
+ enableScrollForNextCalculateItemsInView,
1349
+ minIndexSizeChanged
1478
1350
  } = state;
1479
1351
  if (!data || scrollLength === 0) {
1480
1352
  return;
1481
1353
  }
1482
- const totalSize = peek$(ctx, "totalSizeWithScrollAdjust");
1354
+ const totalSize = peek$(ctx, "totalSize");
1483
1355
  const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
1484
1356
  const numColumns = peek$(ctx, "numColumns");
1485
- const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
1486
- let scrollState = state.scroll;
1357
+ const previousScrollAdjust = 0;
1358
+ const { dataChanged, doMVCP } = params;
1359
+ const speed = getScrollVelocity();
1360
+ if (doMVCP || dataChanged) {
1361
+ const checkMVCP = doMVCP ? prepareMVCP() : void 0;
1362
+ updateAllPositions(dataChanged);
1363
+ checkMVCP == null ? void 0 : checkMVCP();
1364
+ }
1487
1365
  const scrollExtra = 0;
1488
- const useAverageSize = !state.disableScrollJumpsFrom && speed >= 0 && peek$(ctx, "containersDidLayout");
1489
- if (!state.queuedInitialLayout && initialScroll) {
1366
+ const useAverageSize = false;
1367
+ const { queuedInitialLayout } = state;
1368
+ let { scroll: scrollState } = state;
1369
+ if (!queuedInitialLayout && initialScroll) {
1490
1370
  const updatedOffset = calculateOffsetWithOffsetPosition(
1491
1371
  calculateOffsetForIndex(initialScroll.index),
1492
1372
  initialScroll
@@ -1504,21 +1384,19 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1504
1384
  }
1505
1385
  let scrollBufferTop = scrollBuffer;
1506
1386
  let scrollBufferBottom = scrollBuffer;
1507
- if (Math.abs(speed) > 4) {
1508
- if (speed > 0) {
1509
- scrollBufferTop = scrollBuffer * 0.1;
1510
- scrollBufferBottom = scrollBuffer * 1.9;
1511
- } else {
1512
- scrollBufferTop = scrollBuffer * 1.9;
1513
- scrollBufferBottom = scrollBuffer * 0.1;
1514
- }
1387
+ if (speed > 0) {
1388
+ scrollBufferTop = scrollBuffer * 0.5;
1389
+ scrollBufferBottom = scrollBuffer * 1.5;
1390
+ } else {
1391
+ scrollBufferTop = scrollBuffer * 1.5;
1392
+ scrollBufferBottom = scrollBuffer * 0.5;
1515
1393
  }
1516
1394
  const scrollTopBuffered = scroll - scrollBufferTop;
1517
1395
  const scrollBottom = scroll + scrollLength;
1518
1396
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1519
- if (state.scrollForNextCalculateItemsInView) {
1520
- const { top: top2, bottom } = state.scrollForNextCalculateItemsInView;
1521
- if (scrollTopBuffered > top2 && scrollBottomBuffered < bottom) {
1397
+ if (scrollForNextCalculateItemsInView) {
1398
+ const { top, bottom } = scrollForNextCalculateItemsInView;
1399
+ if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
1522
1400
  return;
1523
1401
  }
1524
1402
  }
@@ -1527,51 +1405,26 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1527
1405
  let startBufferedId = null;
1528
1406
  let endNoBuffer = null;
1529
1407
  let endBuffered = null;
1530
- let loopStart = startBufferedIdOrig ? state.indexByKey.get(startBufferedIdOrig) || 0 : 0;
1531
- if (state.minIndexSizeChanged !== void 0) {
1532
- loopStart = Math.min(state.minIndexSizeChanged, loopStart);
1408
+ let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1409
+ if (minIndexSizeChanged !== void 0) {
1410
+ loopStart = Math.min(minIndexSizeChanged, loopStart);
1533
1411
  state.minIndexSizeChanged = void 0;
1534
1412
  }
1535
- const anchorElementIndex = getAnchorElementIndex();
1536
1413
  for (let i = loopStart; i >= 0; i--) {
1537
- const id = getId(i);
1538
- let newPosition;
1539
- if (maintainVisibleContentPosition && anchorElementIndex && i < anchorElementIndex) {
1540
- newPosition = getElementPositionBelowAchor(id);
1541
- if (newPosition !== void 0) {
1542
- positions.set(id, newPosition);
1543
- }
1544
- }
1545
- const top2 = newPosition || positions.get(id);
1546
- if (top2 !== void 0) {
1547
- const size = getItemSize(id, i, data[i], useAverageSize);
1548
- const bottom = top2 + size;
1549
- if (bottom > scroll - scrollBuffer) {
1550
- loopStart = i;
1551
- } else {
1552
- break;
1553
- }
1414
+ const id = (_a2 = idCache.get(i)) != null ? _a2 : getId(i);
1415
+ const top = positions.get(id);
1416
+ const size = (_b = sizes.get(id)) != null ? _b : getItemSize(id, i, data[i], useAverageSize);
1417
+ const bottom = top + size;
1418
+ if (bottom > scroll - scrollBuffer) {
1419
+ loopStart = i;
1420
+ } else {
1421
+ break;
1554
1422
  }
1555
1423
  }
1556
1424
  const loopStartMod = loopStart % numColumns;
1557
1425
  if (loopStartMod > 0) {
1558
1426
  loopStart -= loopStartMod;
1559
1427
  }
1560
- let top = void 0;
1561
- let column = 1;
1562
- let maxSizeInRow = 0;
1563
- const getInitialTop = (i) => {
1564
- var _a2;
1565
- const id = getId(i);
1566
- let topOffset = 0;
1567
- if (positions.get(id)) {
1568
- topOffset = positions.get(id);
1569
- }
1570
- if (id === ((_a2 = state.anchorElement) == null ? void 0 : _a2.id)) {
1571
- topOffset = state.anchorElement.coordinate;
1572
- }
1573
- return topOffset;
1574
- };
1575
1428
  let foundEnd = false;
1576
1429
  let nextTop;
1577
1430
  let nextBottom;
@@ -1580,27 +1433,23 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1580
1433
  for (let i = 0; i < prevNumContainers; i++) {
1581
1434
  const key = peek$(ctx, `containerItemKey${i}`);
1582
1435
  if (key !== void 0) {
1583
- const index = state.indexByKey.get(key);
1436
+ const index = indexByKey.get(key);
1584
1437
  maxIndexRendered = Math.max(maxIndexRendered, index);
1585
1438
  }
1586
1439
  }
1587
- for (let i = Math.max(0, loopStart); i < data.length && (!foundEnd || i <= maxIndexRendered); i++) {
1588
- const id = getId(i);
1589
- const size = getItemSize(id, i, data[i], useAverageSize);
1590
- maxSizeInRow = Math.max(maxSizeInRow, size);
1591
- if (top === void 0 || id === ((_a = state.anchorElement) == null ? void 0 : _a.id)) {
1592
- top = getInitialTop(i);
1593
- }
1594
- if (positions.get(id) !== top) {
1595
- positions.set(id, top);
1596
- }
1597
- if (columns.get(id) !== column) {
1598
- columns.set(id, column);
1599
- }
1440
+ let firstFullyOnScreenIndex;
1441
+ const dataLength = data.length;
1442
+ for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
1443
+ const id = (_c = idCache.get(i)) != null ? _c : getId(i);
1444
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(id, i, data[i], useAverageSize);
1445
+ const top = positions.get(id);
1600
1446
  if (!foundEnd) {
1601
1447
  if (startNoBuffer === null && top + size > scroll) {
1602
1448
  startNoBuffer = i;
1603
1449
  }
1450
+ if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10) {
1451
+ firstFullyOnScreenIndex = i;
1452
+ }
1604
1453
  if (startBuffered === null && top + size > scrollTopBuffered) {
1605
1454
  startBuffered = i;
1606
1455
  startBufferedId = id;
@@ -1612,46 +1461,49 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1612
1461
  }
1613
1462
  if (top <= scrollBottomBuffered) {
1614
1463
  endBuffered = i;
1615
- nextBottom = top + maxSizeInRow - scrollLength;
1464
+ nextBottom = top + size;
1616
1465
  } else {
1617
1466
  foundEnd = true;
1618
1467
  }
1619
1468
  }
1620
1469
  }
1621
- column++;
1622
- if (column > numColumns) {
1623
- top += maxSizeInRow;
1624
- column = 1;
1625
- maxSizeInRow = 0;
1626
- }
1470
+ }
1471
+ const idsInView = [];
1472
+ for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
1473
+ const id = (_e = idCache.get(i)) != null ? _e : getId(i);
1474
+ idsInView.push(id);
1627
1475
  }
1628
1476
  Object.assign(state, {
1629
1477
  startBuffered,
1630
1478
  startBufferedId,
1631
1479
  startNoBuffer,
1632
1480
  endBuffered,
1633
- endNoBuffer
1481
+ endNoBuffer,
1482
+ idsInView,
1483
+ firstFullyOnScreenIndex
1634
1484
  });
1635
- if (state.enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0 && state.disableScrollJumpsFrom === void 0) {
1485
+ if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
1636
1486
  state.scrollForNextCalculateItemsInView = nextTop !== void 0 && nextBottom !== void 0 ? {
1637
1487
  top: nextTop,
1638
1488
  bottom: nextBottom
1639
1489
  } : void 0;
1640
1490
  }
1491
+ const numContainers = peek$(ctx, "numContainers");
1492
+ const pendingRemoval = [];
1493
+ if (dataChanged) {
1494
+ for (let i = 0; i < numContainers; i++) {
1495
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
1496
+ if (!keyExtractorProp || itemKey && indexByKey.get(itemKey) === void 0) {
1497
+ pendingRemoval.push(i);
1498
+ }
1499
+ }
1500
+ }
1641
1501
  if (startBuffered !== null && endBuffered !== null) {
1642
- let numContainers = prevNumContainers;
1502
+ let numContainers2 = prevNumContainers;
1643
1503
  const needNewContainers = [];
1644
- const isContained = (i) => {
1645
- const id = getId(i);
1646
- for (let j = 0; j < numContainers; j++) {
1647
- const key = peek$(ctx, `containerItemKey${j}`);
1648
- if (key === id) {
1649
- return true;
1650
- }
1651
- }
1652
- };
1653
1504
  for (let i = startBuffered; i <= endBuffered; i++) {
1654
- if (!isContained(i)) {
1505
+ const id = (_f = idCache.get(i)) != null ? _f : getId(i);
1506
+ if (!containerItemKeys.has(id)) {
1655
1507
  needNewContainers.push(i);
1656
1508
  }
1657
1509
  }
@@ -1659,75 +1511,79 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1659
1511
  const availableContainers = findAvailableContainers(
1660
1512
  needNewContainers.length,
1661
1513
  startBuffered,
1662
- endBuffered
1514
+ endBuffered,
1515
+ pendingRemoval
1663
1516
  );
1664
1517
  for (let idx = 0; idx < needNewContainers.length; idx++) {
1665
1518
  const i = needNewContainers[idx];
1666
1519
  const containerIndex = availableContainers[idx];
1667
- const id = getId(i);
1520
+ const id = (_g = idCache.get(i)) != null ? _g : getId(i);
1521
+ const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
1522
+ if (oldKey && oldKey !== id) {
1523
+ containerItemKeys.delete(oldKey);
1524
+ }
1668
1525
  set$(ctx, `containerItemKey${containerIndex}`, id);
1669
1526
  set$(ctx, `containerItemData${containerIndex}`, data[i]);
1670
- if (containerIndex >= numContainers) {
1671
- numContainers = containerIndex + 1;
1527
+ containerItemKeys.add(id);
1528
+ if (containerIndex >= numContainers2) {
1529
+ numContainers2 = containerIndex + 1;
1672
1530
  }
1673
1531
  }
1674
- if (numContainers !== prevNumContainers) {
1675
- set$(ctx, "numContainers", numContainers);
1676
- if (numContainers > peek$(ctx, "numContainersPooled")) {
1677
- set$(ctx, "numContainersPooled", Math.ceil(numContainers * 1.5));
1532
+ if (numContainers2 !== prevNumContainers) {
1533
+ set$(ctx, "numContainers", numContainers2);
1534
+ if (numContainers2 > peek$(ctx, "numContainersPooled")) {
1535
+ set$(ctx, "numContainersPooled", Math.ceil(numContainers2 * 1.5));
1678
1536
  }
1679
1537
  }
1680
1538
  }
1681
- for (let i = 0; i < numContainers; i++) {
1539
+ for (let i = 0; i < numContainers2; i++) {
1682
1540
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1683
- const itemIndex = state.indexByKey.get(itemKey);
1684
- const item = data[itemIndex];
1685
- if (item !== void 0) {
1686
- const id = getId(itemIndex);
1687
- const position = positions.get(id);
1688
- if (position === void 0) {
1689
- set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1690
- } else {
1691
- const pos = {
1692
- type: "top",
1693
- relativeCoordinate: positions.get(id),
1694
- top: positions.get(id)
1695
- };
1696
- const column2 = columns.get(id) || 1;
1697
- if (maintainVisibleContentPosition && itemIndex < anchorElementIndex) {
1698
- const currentRow = Math.floor(itemIndex / numColumns);
1699
- const rowHeight = getRowHeight(currentRow);
1700
- const elementHeight = getItemSize(id, itemIndex, data[i]);
1701
- const diff = rowHeight - elementHeight;
1702
- pos.relativeCoordinate = pos.top + getRowHeight(currentRow) - diff;
1703
- pos.type = "bottom";
1704
- }
1705
- const prevPos = peek$(ctx, `containerPosition${i}`);
1706
- const prevColumn = peek$(ctx, `containerColumn${i}`);
1707
- const prevData = peek$(ctx, `containerItemData${i}`);
1708
- if (!prevPos || pos.relativeCoordinate > POSITION_OUT_OF_VIEW && pos.top !== prevPos.top) {
1709
- set$(ctx, `containerPosition${i}`, pos);
1710
- }
1711
- if (column2 >= 0 && column2 !== prevColumn) {
1712
- set$(ctx, `containerColumn${i}`, column2);
1713
- }
1714
- if (prevData !== item) {
1715
- set$(ctx, `containerItemData${i}`, data[itemIndex]);
1541
+ if (pendingRemoval.includes(i)) {
1542
+ if (itemKey) {
1543
+ containerItemKeys.delete(itemKey);
1544
+ }
1545
+ set$(ctx, `containerItemKey${i}`, void 0);
1546
+ set$(ctx, `containerItemData${i}`, void 0);
1547
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1548
+ set$(ctx, `containerColumn${i}`, -1);
1549
+ } else {
1550
+ const itemIndex = indexByKey.get(itemKey);
1551
+ const item = data[itemIndex];
1552
+ if (item !== void 0) {
1553
+ const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(itemIndex);
1554
+ const position = positions.get(id);
1555
+ if (position === void 0) {
1556
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1557
+ } else {
1558
+ const pos = positions.get(id);
1559
+ const column = columns.get(id) || 1;
1560
+ const prevPos = peek$(ctx, `containerPosition${i}`);
1561
+ const prevColumn = peek$(ctx, `containerColumn${i}`);
1562
+ const prevData = peek$(ctx, `containerItemData${i}`);
1563
+ if (!prevPos || pos > POSITION_OUT_OF_VIEW && pos !== prevPos) {
1564
+ set$(ctx, `containerPosition${i}`, pos);
1565
+ }
1566
+ if (column >= 0 && column !== prevColumn) {
1567
+ set$(ctx, `containerColumn${i}`, column);
1568
+ }
1569
+ if (prevData !== item) {
1570
+ set$(ctx, `containerItemData${i}`, data[itemIndex]);
1571
+ }
1716
1572
  }
1717
1573
  }
1718
1574
  }
1719
1575
  }
1720
1576
  }
1721
- if (!state.queuedInitialLayout && endBuffered !== null) {
1577
+ if (!queuedInitialLayout && endBuffered !== null) {
1722
1578
  if (checkAllSizesKnown()) {
1723
1579
  setDidLayout();
1724
1580
  }
1725
1581
  }
1726
- if (state.viewabilityConfigCallbackPairs) {
1582
+ if (viewabilityConfigCallbackPairs) {
1727
1583
  updateViewableItems(
1728
1584
  state,
1729
1585
  ctx,
1730
- state.viewabilityConfigCallbackPairs,
1586
+ viewabilityConfigCallbackPairs,
1731
1587
  getId,
1732
1588
  scrollLength,
1733
1589
  startNoBuffer,
@@ -1742,10 +1598,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1742
1598
  if (stylePaddingTop !== void 0) {
1743
1599
  const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1744
1600
  if (stylePaddingTop < prevStylePaddingTop) {
1745
- const prevTotalSize = peek$(ctx, "totalSizeWithScrollAdjust") || 0;
1746
- set$(ctx, "totalSizeWithScrollAdjust", prevTotalSize + prevStylePaddingTop);
1601
+ const prevTotalSize = peek$(ctx, "totalSize") || 0;
1602
+ set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
1747
1603
  setTimeout(() => {
1748
- set$(ctx, "totalSizeWithScrollAdjust", prevTotalSize);
1604
+ set$(ctx, "totalSize", prevTotalSize);
1749
1605
  }, 16);
1750
1606
  }
1751
1607
  set$(ctx, "stylePaddingTop", stylePaddingTop);
@@ -1753,11 +1609,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1753
1609
  if (alignItemsPaddingTop !== void 0) {
1754
1610
  set$(ctx, "alignItemsPaddingTop", alignItemsPaddingTop);
1755
1611
  }
1756
- set$(
1757
- ctx,
1758
- "paddingTop",
1759
- (stylePaddingTop != null ? stylePaddingTop : peek$(ctx, "stylePaddingTop")) + (alignItemsPaddingTop != null ? alignItemsPaddingTop : peek$(ctx, "alignItemsPaddingTop"))
1760
- );
1761
1612
  };
1762
1613
  const updateAlignItemsPaddingTop = () => {
1763
1614
  if (alignItemsAtEnd) {
@@ -1774,27 +1625,25 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1774
1625
  const state = refState.current;
1775
1626
  if (state) {
1776
1627
  state.scrollingTo = void 0;
1777
- state.scrollAdjustHandler.setDisableAdjust(false);
1778
1628
  state.scrollHistory.length = 0;
1779
- calculateItemsInView();
1780
1629
  }
1781
1630
  };
1782
1631
  const scrollTo = (params = {}) => {
1783
- var _a;
1632
+ var _a2;
1784
1633
  const state = refState.current;
1785
1634
  const { animated } = params;
1786
1635
  const offset = calculateOffsetWithOffsetPosition(params.offset, params);
1787
- state.scrollAdjustHandler.setDisableAdjust(true);
1788
1636
  state.scrollHistory.length = 0;
1789
1637
  state.scrollingTo = params;
1790
1638
  state.scrollPending = offset;
1791
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1639
+ (_a2 = refScroller.current) == null ? void 0 : _a2.scrollTo({
1792
1640
  x: horizontal ? offset : 0,
1793
1641
  y: horizontal ? 0 : offset,
1794
1642
  animated: !!animated
1795
1643
  });
1796
1644
  if (!animated) {
1797
- requestAnimationFrame(finishScrollTo);
1645
+ refState.current.scroll = offset;
1646
+ setTimeout(finishScrollTo, 100);
1798
1647
  }
1799
1648
  };
1800
1649
  const doMaintainScrollAtEnd = (animated) => {
@@ -1804,11 +1653,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1804
1653
  if (paddingTop > 0) {
1805
1654
  state.scroll = 0;
1806
1655
  }
1807
- state.disableScrollJumpsFrom = void 0;
1808
1656
  requestAnimationFrame(() => {
1809
- var _a;
1657
+ var _a2;
1810
1658
  state.maintainingScrollAtEnd = true;
1811
- (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
1659
+ (_a2 = refScroller.current) == null ? void 0 : _a2.scrollToEnd({
1812
1660
  animated
1813
1661
  });
1814
1662
  setTimeout(
@@ -1857,8 +1705,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1857
1705
  refState.current.isEndReached,
1858
1706
  refState.current.endReachedBlockedByTimer,
1859
1707
  (distance) => {
1860
- var _a, _b;
1861
- return (_b = (_a = callbacks.current).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1708
+ var _a2, _b;
1709
+ return (_b = (_a2 = callbacks.current).onEndReached) == null ? void 0 : _b.call(_a2, { distanceFromEnd: distance });
1862
1710
  },
1863
1711
  (block) => {
1864
1712
  refState.current.endReachedBlockedByTimer = block;
@@ -1880,8 +1728,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1880
1728
  refState.current.isStartReached,
1881
1729
  refState.current.startReachedBlockedByTimer,
1882
1730
  (distance) => {
1883
- var _a, _b;
1884
- return (_b = (_a = callbacks.current).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
1731
+ var _a2, _b;
1732
+ return (_b = (_a2 = callbacks.current).onStartReached) == null ? void 0 : _b.call(_a2, { distanceFromStart: distance });
1885
1733
  },
1886
1734
  (block) => {
1887
1735
  refState.current.startReachedBlockedByTimer = block;
@@ -1893,30 +1741,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1893
1741
  if (state) {
1894
1742
  state.data = dataProp;
1895
1743
  if (!isFirst2) {
1896
- const totalSizeBefore = state.previousTotalSize;
1897
- const totalSizeAfter = state.totalSize;
1898
- const scrollDiff = state.scroll - state.scrollPrev;
1899
- const sizeDiff = totalSizeAfter - totalSizeBefore;
1900
- if (Math.abs(scrollDiff - sizeDiff) < 10) {
1901
- disableScrollJumps(1e3);
1902
- }
1903
- const numContainers = peek$(ctx, "numContainers");
1904
- for (let i = 0; i < numContainers; i++) {
1905
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1906
- if (!keyExtractorProp || itemKey && state.indexByKey.get(itemKey) === void 0) {
1907
- set$(ctx, `containerItemKey${i}`, void 0);
1908
- set$(ctx, `containerItemData${i}`, void 0);
1909
- set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1910
- set$(ctx, `containerColumn${i}`, -1);
1911
- }
1912
- }
1913
- if (!keyExtractorProp) {
1914
- state.positions.clear();
1915
- }
1916
- calculateItemsInView(
1917
- /*isReset*/
1918
- true
1919
- );
1744
+ calculateItemsInView({ dataChanged: true, doMVCP: true });
1920
1745
  const didMaintainScrollAtEnd = doMaintainScrollAtEnd(false);
1921
1746
  if (!didMaintainScrollAtEnd && dataProp.length > state.data.length) {
1922
1747
  state.isEndReached = false;
@@ -1928,106 +1753,40 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1928
1753
  }
1929
1754
  }
1930
1755
  };
1931
- const calcTotalSizesAndPositions = ({ forgetPositions = false }) => {
1932
- var _a, _b;
1933
- const state = refState.current;
1934
- let totalSize = 0;
1935
- let totalSizeBelowIndex = 0;
1936
- const indexByKey = /* @__PURE__ */ new Map();
1937
- const newPositions = /* @__PURE__ */ new Map();
1938
- let column = 1;
1939
- let maxSizeInRow = 0;
1940
- const numColumns = (_a = peek$(ctx, "numColumns")) != null ? _a : numColumnsProp;
1941
- if (!state) {
1942
- return;
1943
- }
1944
- for (let i = 0; i < dataProp.length; i++) {
1945
- const key = getId(i);
1946
- if (__DEV__) {
1947
- if (indexByKey.has(key)) {
1948
- console.error(
1949
- `[legend-list] Error: Detected overlapping key (${key}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`
1950
- );
1951
- }
1952
- }
1953
- indexByKey.set(key, i);
1954
- if (!forgetPositions && state.positions.get(key) != null && state.indexByKey.get(key) === i) {
1955
- newPositions.set(key, state.positions.get(key));
1956
- }
1957
- }
1958
- state.indexByKey = indexByKey;
1959
- state.positions = newPositions;
1960
- if (!forgetPositions && !isFirst) {
1961
- if (maintainVisibleContentPosition) {
1962
- if (state.anchorElement == null || indexByKey.get(state.anchorElement.id) == null) {
1963
- if (dataProp.length) {
1964
- const newAnchorElement = {
1965
- coordinate: 0,
1966
- id: getId(0)
1967
- };
1968
- state.anchorElement = newAnchorElement;
1969
- (_b = state.belowAnchorElementPositions) == null ? void 0 : _b.clear();
1970
- scrollTo({ offset: 0, animated: false });
1971
- setTimeout(() => {
1972
- calculateItemsInView(
1973
- /*reset*/
1974
- true
1975
- );
1976
- }, 0);
1977
- } else {
1978
- state.startBufferedId = void 0;
1979
- }
1980
- }
1981
- } else {
1982
- if (state.startBufferedId != null && newPositions.get(state.startBufferedId) == null) {
1983
- if (dataProp.length) {
1984
- state.startBufferedId = getId(0);
1985
- } else {
1986
- state.startBufferedId = void 0;
1756
+ const updateTotalSize = () => {
1757
+ const { data, positions } = refState.current;
1758
+ if (data.length === 0) {
1759
+ addTotalSize(null, 0);
1760
+ } else {
1761
+ const lastId = getId(data.length - 1);
1762
+ if (lastId !== void 0) {
1763
+ const lastPosition = positions.get(lastId);
1764
+ if (lastPosition !== void 0) {
1765
+ const lastSize = getItemSize(lastId, data.length - 1, data[dataProp.length - 1]);
1766
+ if (lastSize !== void 0) {
1767
+ const totalSize = lastPosition + lastSize;
1768
+ addTotalSize(null, totalSize);
1987
1769
  }
1988
- scrollTo({ offset: 0, animated: false });
1989
- setTimeout(() => {
1990
- calculateItemsInView(
1991
- /*reset*/
1992
- true
1993
- );
1994
- }, 0);
1995
1770
  }
1996
1771
  }
1997
1772
  }
1998
- const anchorElementIndex = getAnchorElementIndex();
1999
- for (let i = 0; i < dataProp.length; i++) {
2000
- const key = getId(i);
2001
- const size = getItemSize(key, i, dataProp[i]);
2002
- maxSizeInRow = Math.max(maxSizeInRow, size);
2003
- column++;
2004
- if (column > numColumns) {
2005
- if (maintainVisibleContentPosition && anchorElementIndex !== void 0 && i < anchorElementIndex) {
2006
- totalSizeBelowIndex += maxSizeInRow;
2007
- }
2008
- totalSize += maxSizeInRow;
2009
- column = 1;
2010
- maxSizeInRow = 0;
2011
- }
2012
- }
2013
- if (maxSizeInRow > 0) {
2014
- totalSize += maxSizeInRow;
2015
- }
2016
- state.ignoreScrollFromCalcTotal = true;
2017
- requestAnimationFrame(() => {
2018
- state.ignoreScrollFromCalcTotal = false;
2019
- });
2020
- addTotalSize(null, totalSize, totalSizeBelowIndex);
2021
1773
  };
2022
- const findAvailableContainers = (numNeeded, startBuffered, endBuffered) => {
1774
+ const findAvailableContainers = (numNeeded, startBuffered, endBuffered, pendingRemoval) => {
2023
1775
  const state = refState.current;
2024
1776
  const numContainers = peek$(ctx, "numContainers");
2025
- if (numNeeded === 0) return [];
2026
1777
  const result = [];
2027
1778
  const availableContainers = [];
2028
1779
  for (let u = 0; u < numContainers; u++) {
2029
1780
  const key = peek$(ctx, `containerItemKey${u}`);
2030
- if (key === void 0) {
1781
+ let isOk = key === void 0;
1782
+ if (!isOk) {
1783
+ const index = pendingRemoval.indexOf(u);
1784
+ if (index !== -1) {
1785
+ pendingRemoval.splice(index, 1);
1786
+ isOk = true;
1787
+ }
1788
+ }
1789
+ if (isOk) {
2031
1790
  result.push(u);
2032
1791
  if (result.length >= numNeeded) {
2033
1792
  return result;
@@ -2093,14 +1852,21 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2093
1852
  refState.current.stylePaddingBottom = stylePaddingBottomState;
2094
1853
  const paddingDiff = stylePaddingTopState - prevPaddingTop;
2095
1854
  if (paddingDiff && prevPaddingTop !== void 0 && reactNative.Platform.OS === "ios") {
2096
- queueMicrotask(() => {
2097
- scrollTo({ offset: refState.current.scrollPending + paddingDiff, animated: false });
2098
- });
1855
+ requestAdjust(paddingDiff);
2099
1856
  }
2100
1857
  };
2101
1858
  if (isFirst) {
2102
1859
  initalizeStateVars();
1860
+ updateAllPositions();
2103
1861
  }
1862
+ const initialContentOffset = React2.useMemo(() => {
1863
+ const initialContentOffset2 = initialScrollOffset || calculateOffsetForIndex(initialScrollIndex);
1864
+ refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
1865
+ if (initialContentOffset2 > 0) {
1866
+ scrollTo({ offset: initialContentOffset2, animated: false, index: initialScrollIndex });
1867
+ }
1868
+ return initialContentOffset2;
1869
+ }, [renderNum]);
2104
1870
  if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
2105
1871
  refState.current.lastBatchingAction = Date.now();
2106
1872
  if (!keyExtractorProp && !isFirst && didDataChange) {
@@ -2111,22 +1877,38 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2111
1877
  refState.current.sizes.clear();
2112
1878
  refState.current.positions.clear();
2113
1879
  }
2114
- refState.current.previousTotalSize = peek$(ctx, "totalSize");
2115
- calcTotalSizesAndPositions({ forgetPositions: false });
2116
1880
  }
2117
- React2.useEffect(() => {
2118
- if (initialScroll && ListHeaderComponent) {
2119
- const dispose = listen$(ctx, "headerSize", (size) => {
2120
- if (size > 0) {
2121
- scrollToIndex({ ...initialScroll, animated: false });
2122
- dispose == null ? void 0 : dispose();
1881
+ React2.useLayoutEffect(() => {
1882
+ var _a2, _b;
1883
+ if (IsNewArchitecture) {
1884
+ const measured = (_b = (_a2 = refScroller.current) == null ? void 0 : _a2.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a2);
1885
+ if (measured) {
1886
+ const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
1887
+ if (size) {
1888
+ handleLayout(measured);
2123
1889
  }
2124
- });
2125
- setTimeout(dispose, 0);
2126
- return dispose;
1890
+ }
1891
+ }
1892
+ if (!isFirst) {
1893
+ calculateItemsInView({ doMVCP: true });
1894
+ }
1895
+ }, [dataProp]);
1896
+ const onLayoutHeader = React2.useCallback((rect, fromLayoutEffect) => {
1897
+ const size = rect[horizontal ? "width" : "height"];
1898
+ set$(ctx, "headerSize", size);
1899
+ if (initialScroll) {
1900
+ if (IsNewArchitecture && reactNative.Platform.OS !== "android") {
1901
+ if (fromLayoutEffect) {
1902
+ setRenderNum((v) => v + 1);
1903
+ }
1904
+ } else {
1905
+ setTimeout(() => {
1906
+ scrollToIndex({ ...initialScroll, animated: false });
1907
+ }, 17);
1908
+ }
2127
1909
  }
2128
1910
  }, []);
2129
- React2.useEffect(() => {
1911
+ React2.useLayoutEffect(() => {
2130
1912
  const didAllocateContainers = doInitialAllocateContainers();
2131
1913
  if (!didAllocateContainers) {
2132
1914
  checkResetContainers(
@@ -2135,11 +1917,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2135
1917
  );
2136
1918
  }
2137
1919
  }, [dataProp, numColumnsProp]);
2138
- React2.useEffect(() => {
1920
+ React2.useLayoutEffect(() => {
2139
1921
  set$(ctx, "extraData", extraData);
2140
1922
  }, [extraData]);
2141
1923
  refState.current.renderItem = renderItem2;
2142
- React2.useEffect(initalizeStateVars, [
1924
+ React2.useLayoutEffect(initalizeStateVars, [
2143
1925
  memoizedLastItemKeys.join(","),
2144
1926
  numColumnsProp,
2145
1927
  stylePaddingTopState,
@@ -2172,25 +1954,24 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2172
1954
  const { scrollLength, data } = state;
2173
1955
  if (scrollLength > 0 && data.length > 0 && !peek$(ctx, "numContainers")) {
2174
1956
  const averageItemSize = getEstimatedItemSize ? getEstimatedItemSize(0, data[0]) : estimatedItemSize;
2175
- const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) * numColumnsProp;
1957
+ const Extra = 1.5;
1958
+ const numContainers = Math.ceil(
1959
+ (scrollLength + scrollBuffer * 2) / averageItemSize * numColumnsProp * Extra
1960
+ );
2176
1961
  for (let i = 0; i < numContainers; i++) {
2177
- set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1962
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2178
1963
  set$(ctx, `containerColumn${i}`, -1);
2179
1964
  }
2180
1965
  set$(ctx, "numContainers", numContainers);
2181
1966
  set$(ctx, "numContainersPooled", numContainers * initialContainerPoolRatio);
2182
- if (initialScroll) {
2183
- requestAnimationFrame(() => {
2184
- calculateItemsInView(
2185
- /*isReset*/
2186
- true
2187
- );
2188
- });
2189
- } else {
2190
- calculateItemsInView(
2191
- /*isReset*/
2192
- true
2193
- );
1967
+ if (!IsNewArchitecture) {
1968
+ if (initialScroll) {
1969
+ requestAnimationFrame(() => {
1970
+ calculateItemsInView();
1971
+ });
1972
+ } else {
1973
+ calculateItemsInView();
1974
+ }
2194
1975
  }
2195
1976
  return true;
2196
1977
  }
@@ -2205,131 +1986,137 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2205
1986
  state.viewabilityConfigCallbackPairs = viewability;
2206
1987
  state.enableScrollForNextCalculateItemsInView = !viewability;
2207
1988
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
2208
- useInit(() => {
2209
- doInitialAllocateContainers();
2210
- });
2211
- const updateItemSize = React2.useCallback(
2212
- (itemKey, sizeObj, fromFixGaps) => {
1989
+ if (!IsNewArchitecture) {
1990
+ useInit(() => {
1991
+ doInitialAllocateContainers();
1992
+ });
1993
+ }
1994
+ const updateOneItemSize = React2.useCallback((itemKey, sizeObj) => {
1995
+ const state = refState.current;
1996
+ const { sizes, indexByKey, sizesKnown, data, averageSizes } = state;
1997
+ if (!data) return 0;
1998
+ const index = indexByKey.get(itemKey);
1999
+ const prevSize = getItemSize(itemKey, index, data);
2000
+ const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2001
+ sizesKnown.set(itemKey, size);
2002
+ const itemType = "";
2003
+ let averages = averageSizes[itemType];
2004
+ if (!averages) {
2005
+ averages = averageSizes[itemType] = { num: 0, avg: 0 };
2006
+ }
2007
+ averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2008
+ averages.num++;
2009
+ if (!prevSize || Math.abs(prevSize - size) > 0.1) {
2010
+ sizes.set(itemKey, size);
2011
+ return size - prevSize;
2012
+ }
2013
+ return 0;
2014
+ }, []);
2015
+ const updateItemSizes = React2.useCallback(
2016
+ (itemUpdates) => {
2017
+ var _a2;
2213
2018
  const state = refState.current;
2214
- const {
2215
- sizes,
2216
- indexByKey,
2217
- sizesKnown,
2218
- data,
2219
- rowHeights,
2220
- startBuffered,
2221
- endBuffered,
2222
- averageSizes,
2223
- queuedInitialLayout
2224
- } = state;
2225
- if (!data) {
2226
- return;
2227
- }
2228
- const index = indexByKey.get(itemKey);
2229
- const numColumns = peek$(ctx, "numColumns");
2230
- state.scrollForNextCalculateItemsInView = void 0;
2231
- state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, index) : index;
2232
- const prevSize = getItemSize(itemKey, index, data);
2233
- const prevSizeKnown = sizesKnown.get(itemKey);
2234
- let needsCalculate = false;
2235
- let needsUpdateContainersDidLayout = false;
2236
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2237
- sizesKnown.set(itemKey, size);
2238
- const itemType = "";
2239
- let averages = averageSizes[itemType];
2240
- if (!averages) {
2241
- averages = averageSizes[itemType] = {
2242
- num: 0,
2243
- avg: 0
2244
- };
2245
- }
2246
- averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2247
- averages.num++;
2248
- if (!prevSize || Math.abs(prevSize - size) > 0.1) {
2249
- let diff;
2250
- needsCalculate = true;
2251
- if (numColumns > 1) {
2252
- const rowNumber = Math.floor(index / numColumnsProp);
2253
- const prevSizeInRow = getRowHeight(rowNumber);
2254
- sizes.set(itemKey, size);
2255
- rowHeights.delete(rowNumber);
2256
- const sizeInRow = getRowHeight(rowNumber);
2257
- diff = sizeInRow - prevSizeInRow;
2258
- } else {
2259
- sizes.set(itemKey, size);
2260
- diff = size - prevSize;
2261
- }
2262
- if (__DEV__ && suggestEstimatedItemSize) {
2263
- if (state.timeoutSizeMessage) {
2264
- clearTimeout(state.timeoutSizeMessage);
2019
+ if (!state.data) return;
2020
+ let needsRecalculate = false;
2021
+ let shouldMaintainScrollAtEnd = false;
2022
+ let minIndexSizeChanged;
2023
+ let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2024
+ for (const { itemKey, sizeObj } of itemUpdates) {
2025
+ const index = state.indexByKey.get(itemKey);
2026
+ const prevSizeKnown = state.sizesKnown.get(itemKey);
2027
+ const diff = updateOneItemSize(itemKey, sizeObj);
2028
+ const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2029
+ if (diff !== 0) {
2030
+ minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
2031
+ if (((_a2 = state.scrollingTo) == null ? void 0 : _a2.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index) {
2032
+ requestAdjust(diff * state.scrollingTo.viewPosition);
2265
2033
  }
2266
- state.timeoutSizeMessage = setTimeout(() => {
2267
- state.timeoutSizeMessage = void 0;
2268
- const num = sizesKnown.size;
2269
- const avg = state.averageSizes[""].avg;
2270
- console.warn(
2271
- `[legend-list] estimatedItemSize or getEstimatedItemSize are not defined. Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`
2272
- );
2273
- }, 1e3);
2274
- }
2275
- state.scrollForNextCalculateItemsInView = void 0;
2276
- addTotalSize(itemKey, diff, 0);
2277
- if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
2278
- doMaintainScrollAtEnd(false);
2279
- }
2280
- if (onItemSizeChanged) {
2281
- onItemSizeChanged({
2034
+ const { startBuffered, endBuffered } = state;
2035
+ needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2036
+ if (!needsRecalculate) {
2037
+ const numContainers = ctx.values.get("numContainers");
2038
+ for (let i = 0; i < numContainers; i++) {
2039
+ if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
2040
+ needsRecalculate = true;
2041
+ break;
2042
+ }
2043
+ }
2044
+ }
2045
+ if (state.needsOtherAxisSize) {
2046
+ const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
2047
+ maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
2048
+ }
2049
+ if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
2050
+ shouldMaintainScrollAtEnd = true;
2051
+ }
2052
+ onItemSizeChanged == null ? void 0 : onItemSizeChanged({
2282
2053
  size,
2283
- previous: prevSize,
2054
+ previous: size - diff,
2284
2055
  index,
2285
2056
  itemKey,
2286
- itemData: data[index]
2057
+ itemData: state.data[index]
2287
2058
  });
2288
2059
  }
2289
2060
  }
2290
- if (!queuedInitialLayout && checkAllSizesKnown()) {
2291
- needsUpdateContainersDidLayout = true;
2061
+ if (minIndexSizeChanged !== void 0) {
2062
+ state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
2292
2063
  }
2293
- let isInView = index >= startBuffered && index <= endBuffered;
2294
- if (!isInView) {
2295
- const numContainers = ctx.values.get("numContainers");
2296
- for (let i = 0; i < numContainers; i++) {
2297
- if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
2298
- isInView = true;
2299
- break;
2300
- }
2301
- }
2064
+ if (__DEV__ && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
2065
+ if (state.timeoutSizeMessage) clearTimeout(state.timeoutSizeMessage);
2066
+ state.timeoutSizeMessage = setTimeout(() => {
2067
+ var _a3;
2068
+ state.timeoutSizeMessage = void 0;
2069
+ const num = state.sizesKnown.size;
2070
+ const avg = (_a3 = state.averageSizes[""]) == null ? void 0 : _a3.avg;
2071
+ console.warn(
2072
+ `[legend-list] Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`
2073
+ );
2074
+ }, 1e3);
2302
2075
  }
2303
- if (needsUpdateContainersDidLayout || !fromFixGaps && needsCalculate && (isInView || !queuedInitialLayout)) {
2304
- const scrollVelocity = state.scrollVelocity;
2305
- let didCalculate = false;
2306
- if ((Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1 || state.scrollingTo !== void 0) && (!waitForInitialLayout || needsUpdateContainersDidLayout || queuedInitialLayout)) {
2307
- if (Date.now() - state.lastBatchingAction < 500) {
2308
- if (!state.queuedCalculateItemsInView) {
2309
- state.queuedCalculateItemsInView = requestAnimationFrame(() => {
2310
- state.queuedCalculateItemsInView = void 0;
2311
- calculateItemsInView();
2312
- });
2313
- }
2314
- } else {
2315
- calculateItemsInView();
2316
- didCalculate = true;
2317
- }
2318
- }
2319
- if (!didCalculate && !needsUpdateContainersDidLayout && IsNewArchitecture) {
2320
- fixGaps();
2321
- }
2076
+ const cur = peek$(ctx, "otherAxisSize");
2077
+ if (!cur || maxOtherAxisSize > cur) {
2078
+ set$(ctx, "otherAxisSize", maxOtherAxisSize);
2322
2079
  }
2323
- if (state.needsOtherAxisSize) {
2324
- const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
2325
- const cur = peek$(ctx, "otherAxisSize");
2326
- if (!cur || otherAxisSize > cur) {
2327
- set$(ctx, "otherAxisSize", otherAxisSize);
2080
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
2081
+ if (containersDidLayout || checkAllSizesKnown()) {
2082
+ if (needsRecalculate) {
2083
+ state.scrollForNextCalculateItemsInView = void 0;
2084
+ calculateItemsInView({ doMVCP: true });
2085
+ }
2086
+ if (shouldMaintainScrollAtEnd) {
2087
+ doMaintainScrollAtEnd(false);
2328
2088
  }
2329
2089
  }
2330
2090
  },
2331
2091
  []
2332
2092
  );
2093
+ const updateItemSize = React2.useCallback((itemKey, sizeObj) => {
2094
+ var _a2, _b;
2095
+ if (IsNewArchitecture) {
2096
+ const { sizesKnown } = refState.current;
2097
+ const numContainers = ctx.values.get("numContainers");
2098
+ const changes = [];
2099
+ for (let i = 0; i < numContainers; i++) {
2100
+ const containerItemKey = peek$(ctx, `containerItemKey${i}`);
2101
+ if (itemKey === containerItemKey) {
2102
+ changes.push({ itemKey, sizeObj });
2103
+ } else if (!sizesKnown.has(containerItemKey) && containerItemKey !== void 0) {
2104
+ const containerRef = ctx.viewRefs.get(i);
2105
+ if (containerRef) {
2106
+ const measured = (_b = (_a2 = containerRef.current) == null ? void 0 : _a2.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a2);
2107
+ if (measured) {
2108
+ changes.push({ itemKey: containerItemKey, sizeObj: measured });
2109
+ }
2110
+ }
2111
+ }
2112
+ }
2113
+ if (changes.length > 0) {
2114
+ updateItemSizes(changes);
2115
+ }
2116
+ } else {
2117
+ updateItemSizes([{ itemKey, sizeObj }]);
2118
+ }
2119
+ }, []);
2333
2120
  const handleLayout = React2.useCallback((size) => {
2334
2121
  const scrollLength = size[horizontal ? "width" : "height"];
2335
2122
  const otherAxisSize = size[horizontal ? "height" : "width"];
@@ -2341,16 +2128,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2341
2128
  state.lastBatchingAction = Date.now();
2342
2129
  state.scrollForNextCalculateItemsInView = void 0;
2343
2130
  doInitialAllocateContainers();
2344
- doMaintainScrollAtEnd(false);
2345
- updateAlignItemsPaddingTop();
2346
- checkAtBottom();
2347
- checkAtTop();
2348
2131
  if (didChange) {
2349
- calculateItemsInView();
2132
+ calculateItemsInView({ doMVCP: true });
2350
2133
  }
2351
2134
  if (didChange || otherAxisSize !== prevOtherAxisSize) {
2352
2135
  set$(ctx, "scrollSize", { width: size.width, height: size.height });
2353
2136
  }
2137
+ doMaintainScrollAtEnd(false);
2138
+ updateAlignItemsPaddingTop();
2139
+ checkAtBottom();
2140
+ checkAtTop();
2354
2141
  if (refState.current) {
2355
2142
  refState.current.needsOtherAxisSize = otherAxisSize - (stylePaddingTopState || 0) < 10;
2356
2143
  }
@@ -2360,40 +2147,32 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2360
2147
  `List ${horizontal ? "width" : "height"} is 0. You may need to set a style or \`flex: \` for the list, because children are absolutely positioned.`
2361
2148
  );
2362
2149
  }
2150
+ calculateItemsInView({ doMVCP: true });
2151
+ setCanRender(true);
2363
2152
  }, []);
2364
2153
  const onLayout = React2.useCallback((event) => {
2365
2154
  const layout = event.nativeEvent.layout;
2366
2155
  handleLayout(layout);
2367
- layout[horizontal ? "width" : "height"];
2368
- layout[horizontal ? "height" : "width"];
2369
2156
  if (onLayoutProp) {
2370
2157
  onLayoutProp(event);
2371
2158
  }
2372
2159
  }, []);
2373
- if (IsNewArchitecture) {
2374
- React2.useLayoutEffect(() => {
2375
- var _a, _b;
2376
- const measured = (_b = (_a = refScroller.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
2377
- if (measured) {
2378
- const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
2379
- if (size) {
2380
- handleLayout(measured);
2381
- }
2382
- }
2383
- }, []);
2384
- }
2385
2160
  const handleScroll = React2.useCallback(
2386
2161
  (event) => {
2387
- var _a, _b, _c, _d;
2388
- if (((_b = (_a = event.nativeEvent) == null ? void 0 : _a.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
2162
+ var _a2, _b, _c, _d;
2163
+ if (((_b = (_a2 = event.nativeEvent) == null ? void 0 : _a2.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
2389
2164
  return;
2390
2165
  }
2391
2166
  const state = refState.current;
2392
2167
  const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
2393
- state.scrollPending = newScroll;
2394
- if (state.ignoreScrollFromCalcTotal && newScroll !== 0) {
2395
- return;
2168
+ const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
2169
+ if (ignoreScrollFromMVCP && !state.scrollingTo) {
2170
+ const { lt, gt } = ignoreScrollFromMVCP;
2171
+ if (lt && newScroll < lt || gt && newScroll > gt) {
2172
+ return;
2173
+ }
2396
2174
  }
2175
+ state.scrollPending = newScroll;
2397
2176
  updateScroll(newScroll);
2398
2177
  (_d = state.onScroll) == null ? void 0 : _d.call(state, event);
2399
2178
  },
@@ -2402,53 +2181,19 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2402
2181
  const updateScroll = React2.useCallback((newScroll) => {
2403
2182
  const state = refState.current;
2404
2183
  const scrollingTo = state.scrollingTo;
2405
- if (scrollingTo !== void 0 && Math.abs(newScroll - scrollingTo.offset) < 10) {
2406
- finishScrollTo();
2407
- }
2408
- if (state.disableScrollJumpsFrom !== void 0) {
2409
- const scrollMinusAdjust = newScroll - state.scrollAdjustHandler.getAppliedAdjust();
2410
- if (Math.abs(scrollMinusAdjust - state.disableScrollJumpsFrom) > 200) {
2411
- return;
2412
- }
2413
- state.disableScrollJumpsFrom = void 0;
2414
- }
2415
2184
  state.hasScrolled = true;
2416
2185
  state.lastBatchingAction = Date.now();
2417
2186
  const currentTime = performance.now();
2418
- if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === initialContentOffset)) {
2187
+ if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
2419
2188
  state.scrollHistory.push({ scroll: newScroll, time: currentTime });
2420
2189
  }
2421
2190
  if (state.scrollHistory.length > 5) {
2422
2191
  state.scrollHistory.shift();
2423
2192
  }
2424
- if (state.scrollTimer !== void 0) {
2425
- clearTimeout(state.scrollTimer);
2426
- }
2427
- state.scrollTimer = setTimeout(() => {
2428
- state.scrollVelocity = 0;
2429
- }, 500);
2430
- let velocity = 0;
2431
- if (state.scrollHistory.length >= 2) {
2432
- const newest = state.scrollHistory[state.scrollHistory.length - 1];
2433
- let oldest;
2434
- for (let i = 0; i < state.scrollHistory.length - 1; i++) {
2435
- const entry = state.scrollHistory[i];
2436
- if (newest.time - entry.time <= 100) {
2437
- oldest = entry;
2438
- break;
2439
- }
2440
- }
2441
- if (oldest) {
2442
- const scrollDiff = newest.scroll - oldest.scroll;
2443
- const timeDiff = newest.time - oldest.time;
2444
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
2445
- }
2446
- }
2447
2193
  state.scrollPrev = state.scroll;
2448
2194
  state.scrollPrevTime = state.scrollTime;
2449
2195
  state.scroll = newScroll;
2450
2196
  state.scrollTime = currentTime;
2451
- state.scrollVelocity = velocity;
2452
2197
  calculateItemsInView();
2453
2198
  checkAtBottom();
2454
2199
  checkAtTop();
@@ -2486,7 +2231,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2486
2231
  scroll: state.scroll,
2487
2232
  scrollLength: state.scrollLength,
2488
2233
  start: state.startNoBuffer,
2489
- startBuffered: state.startBuffered
2234
+ startBuffered: state.startBuffered,
2235
+ sizes: state.sizesKnown,
2236
+ sizeAtIndex: (index) => state.sizesKnown.get(getId(index))
2490
2237
  } : {};
2491
2238
  },
2492
2239
  scrollIndexIntoView,
@@ -2512,8 +2259,17 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2512
2259
  if (index !== -1) {
2513
2260
  const paddingBottom = stylePaddingBottom || 0;
2514
2261
  const footerSize = peek$(ctx, "footerSize") || 0;
2515
- scrollToIndex({ index, viewPosition: 1, viewOffset: -paddingBottom - footerSize, ...options });
2262
+ scrollToIndex({
2263
+ index,
2264
+ viewPosition: 1,
2265
+ viewOffset: -paddingBottom - footerSize,
2266
+ ...options
2267
+ });
2516
2268
  }
2269
+ },
2270
+ setVisibleContentAnchorOffset: (value) => {
2271
+ const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2272
+ set$(ctx, "scrollAdjustUserOffset", val);
2517
2273
  }
2518
2274
  };
2519
2275
  },
@@ -2521,14 +2277,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2521
2277
  );
2522
2278
  if (reactNative.Platform.OS === "web") {
2523
2279
  React2.useEffect(() => {
2524
- var _a;
2525
2280
  if (initialContentOffset) {
2526
- (_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler.setDisableAdjust(true);
2527
2281
  scrollTo({ offset: initialContentOffset, animated: false });
2528
- setTimeout(() => {
2529
- var _a2;
2530
- (_a2 = refState.current) == null ? void 0 : _a2.scrollAdjustHandler.setDisableAdjust(false);
2531
- }, 0);
2532
2282
  }
2533
2283
  }, []);
2534
2284
  }
@@ -2536,6 +2286,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2536
2286
  ListComponent,
2537
2287
  {
2538
2288
  ...rest,
2289
+ canRender,
2539
2290
  horizontal,
2540
2291
  refScrollView: combinedRef,
2541
2292
  initialContentOffset,
@@ -2543,23 +2294,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2543
2294
  updateItemSize,
2544
2295
  handleScroll,
2545
2296
  onMomentumScrollEnd: (event) => {
2546
- var _a;
2547
- const scrollingTo = (_a = refState.current) == null ? void 0 : _a.scrollingTo;
2548
- if (scrollingTo !== void 0) {
2549
- requestAnimationFrame(() => {
2550
- scrollTo({ ...scrollingTo, animated: false });
2551
- refState.current.scrollingTo = void 0;
2552
- requestAnimationFrame(() => {
2553
- refState.current.scrollAdjustHandler.setDisableAdjust(false);
2554
- });
2555
- });
2556
- }
2557
- const wasPaused = refState.current.scrollAdjustHandler.unPauseAdjust();
2558
- if (wasPaused) {
2559
- refState.current.scrollVelocity = 0;
2560
- refState.current.scrollHistory = [];
2561
- calculateItemsInView();
2562
- }
2297
+ requestAnimationFrame(() => {
2298
+ finishScrollTo();
2299
+ });
2563
2300
  if (onMomentumScrollEnd) {
2564
2301
  onMomentumScrollEnd(event);
2565
2302
  }
@@ -2583,7 +2320,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2583
2320
  }
2584
2321
  ),
2585
2322
  style,
2586
- contentContainerStyle
2323
+ contentContainerStyle,
2324
+ scrollAdjustHandler: (_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler,
2325
+ onLayoutHeader
2587
2326
  }
2588
2327
  ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React2__namespace.createElement(DebugView, { state: refState.current }));
2589
2328
  });
@@ -2591,7 +2330,7 @@ var typedForwardRef2 = React2.forwardRef;
2591
2330
  var renderItem = ({ item }) => item;
2592
2331
  var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedRef) {
2593
2332
  const { LegendList: LegendListProp, children, ...rest } = props;
2594
- const LegendListComponent = LegendListProp != null ? LegendListProp : list.LegendList;
2333
+ const LegendListComponent = LegendListProp != null ? LegendListProp : LegendList;
2595
2334
  const data = (isArray(children) ? children : React2__namespace.Children.toArray(children)).flat(1);
2596
2335
  return (
2597
2336
  // @ts-expect-error TODO: Fix this type