@legendapp/list 0.4.4 → 0.4.6

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.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ComponentProps, ReactNode, ForwardedRef, ReactElement } from 'react';
2
2
  import { ScrollView, StyleProp, ViewStyle, ScrollViewComponent, ScrollResponderMixin } from 'react-native';
3
3
 
4
- type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset'> & {
4
+ type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, "contentOffset"> & {
5
5
  data: ArrayLike<any> & T[];
6
6
  initialScrollOffset?: number;
7
7
  initialScrollIndex?: number;
@@ -52,6 +52,7 @@ interface InternalState {
52
52
  totalSize: number;
53
53
  timeouts: Set<number>;
54
54
  viewabilityConfigCallbackPairs: ViewabilityConfigCallbackPairs;
55
+ renderItem: (props: LegendListRenderItemProps<any>) => ReactNode;
55
56
  }
56
57
  interface ViewableRange<T> {
57
58
  startBuffered: number;
package/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ComponentProps, ReactNode, ForwardedRef, ReactElement } from 'react';
2
2
  import { ScrollView, StyleProp, ViewStyle, ScrollViewComponent, ScrollResponderMixin } from 'react-native';
3
3
 
4
- type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, 'contentOffset'> & {
4
+ type LegendListProps<T> = Omit<ComponentProps<typeof ScrollView>, "contentOffset"> & {
5
5
  data: ArrayLike<any> & T[];
6
6
  initialScrollOffset?: number;
7
7
  initialScrollIndex?: number;
@@ -52,6 +52,7 @@ interface InternalState {
52
52
  totalSize: number;
53
53
  timeouts: Set<number>;
54
54
  viewabilityConfigCallbackPairs: ViewabilityConfigCallbackPairs;
55
+ renderItem: (props: LegendListRenderItemProps<any>) => ReactNode;
55
56
  }
56
57
  interface ViewableRange<T> {
57
58
  startBuffered: number;
package/index.js CHANGED
@@ -33,7 +33,11 @@ function StateProvider({ children }) {
33
33
  const [value] = React6__namespace.useState(() => ({
34
34
  hooks: /* @__PURE__ */ new Map(),
35
35
  listeners: /* @__PURE__ */ new Map(),
36
- values: /* @__PURE__ */ new Map()
36
+ values: /* @__PURE__ */ new Map(),
37
+ mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
38
+ mapViewabilityValues: /* @__PURE__ */ new Map(),
39
+ mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
40
+ mapViewabilityAmountValues: /* @__PURE__ */ new Map()
37
41
  }));
38
42
  return /* @__PURE__ */ React6__namespace.createElement(ContextState.Provider, { value }, children);
39
43
  }
@@ -82,7 +86,7 @@ function $View({ $key, $style, ...rest }) {
82
86
  return /* @__PURE__ */ React6__namespace.createElement(LeanView, { style, ...rest });
83
87
  }
84
88
  function InnerContainer({ id, getRenderedItem, recycleItems, ItemSeparatorComponent }) {
85
- const itemIndex = use$(`containerIndex${id}`);
89
+ const itemIndex = use$(`containerItemIndex${id}`);
86
90
  const numItems = ItemSeparatorComponent ? use$("numItems") : 0;
87
91
  if (itemIndex < 0) {
88
92
  return null;
@@ -129,7 +133,7 @@ var Container = ({
129
133
  $key: `containerPosition${id}`,
130
134
  $style: createStyle,
131
135
  onLayout: (event) => {
132
- const index = peek$(ctx, `containerIndex${id}`);
136
+ const index = peek$(ctx, `containerItemIndex${id}`);
133
137
  if (index >= 0) {
134
138
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
135
139
  onLayout(index, size);
@@ -256,13 +260,7 @@ var ListComponent = React6__namespace.memo(function ListComponent2({
256
260
  },
257
261
  getComponent(ListHeaderComponent)
258
262
  ),
259
- ListEmptyComponent && /* @__PURE__ */ React6__namespace.createElement(
260
- reactNative.View,
261
- {
262
- style: ListEmptyComponentStyle
263
- },
264
- getComponent(ListEmptyComponent)
265
- ),
263
+ ListEmptyComponent && /* @__PURE__ */ React6__namespace.createElement(reactNative.View, { style: ListEmptyComponentStyle }, getComponent(ListEmptyComponent)),
266
264
  /* @__PURE__ */ React6__namespace.createElement(
267
265
  Containers,
268
266
  {
@@ -276,17 +274,26 @@ var ListComponent = React6__namespace.memo(function ListComponent2({
276
274
  ListFooterComponent && /* @__PURE__ */ React6__namespace.createElement(reactNative.View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
277
275
  );
278
276
  });
277
+ var symbolFirst = Symbol();
278
+ function useInit(cb) {
279
+ const refValue = React6.useRef(symbolFirst);
280
+ if (refValue.current === symbolFirst) {
281
+ refValue.current = cb();
282
+ }
283
+ return refValue.current;
284
+ }
279
285
 
280
286
  // src/viewability.ts
281
287
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
282
- var mapViewabilityCallbacks = /* @__PURE__ */ new Map();
283
- var mapViewabilityValues = /* @__PURE__ */ new Map();
284
- var mapViewabilityAmountCallbacks = /* @__PURE__ */ new Map();
285
- var mapViewabilityAmountValues = /* @__PURE__ */ new Map();
286
288
  function setupViewability(props) {
287
289
  let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
288
290
  viewabilityConfigCallbackPairs = viewabilityConfigCallbackPairs || [
289
- { viewabilityConfig: viewabilityConfig || { viewAreaCoveragePercentThreshold: 0 }, onViewableItemsChanged }
291
+ {
292
+ viewabilityConfig: viewabilityConfig || {
293
+ viewAreaCoveragePercentThreshold: 0
294
+ },
295
+ onViewableItemsChanged
296
+ }
290
297
  ];
291
298
  if (viewabilityConfigCallbackPairs) {
292
299
  for (const pair of viewabilityConfigCallbackPairs) {
@@ -352,12 +359,16 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
352
359
  }
353
360
  }
354
361
  }
355
- Object.assign(viewabilityState, { viewableItems, previousStart: start, previousEnd: end });
362
+ Object.assign(viewabilityState, {
363
+ viewableItems,
364
+ previousStart: start,
365
+ previousEnd: end
366
+ });
356
367
  if (changed.length > 0) {
357
368
  viewabilityState.viewableItems = viewableItems;
358
369
  for (let i = 0; i < changed.length; i++) {
359
370
  const change = changed[i];
360
- maybeUpdateViewabilityCallback(configId, change);
371
+ maybeUpdateViewabilityCallback(ctx, configId, change);
361
372
  }
362
373
  if (onViewableItemsChanged) {
363
374
  onViewableItemsChanged({ viewableItems, changed });
@@ -392,8 +403,8 @@ function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index)
392
403
  position: top,
393
404
  scrollSize
394
405
  };
395
- mapViewabilityAmountValues.set(containerId, value);
396
- const cb = mapViewabilityAmountCallbacks.get(containerId);
406
+ ctx.mapViewabilityAmountValues.set(containerId, value);
407
+ const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
397
408
  if (cb) {
398
409
  cb(value);
399
410
  }
@@ -402,32 +413,19 @@ function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index)
402
413
  function findContainerId(state, ctx, index) {
403
414
  const numContainers = peek$(ctx, "numContainers");
404
415
  for (let i = 0; i < numContainers; i++) {
405
- const itemIndex = peek$(ctx, `containerIndex${i}`);
416
+ const itemIndex = peek$(ctx, `containerItemIndex${i}`);
406
417
  if (itemIndex === index) {
407
418
  return i;
408
419
  }
409
420
  }
410
421
  return -1;
411
422
  }
412
- function maybeUpdateViewabilityCallback(configId, viewToken) {
423
+ function maybeUpdateViewabilityCallback(ctx, configId, viewToken) {
413
424
  const key = viewToken.key + configId;
414
- mapViewabilityValues.set(key, viewToken);
415
- const cb = mapViewabilityCallbacks.get(key);
425
+ ctx.mapViewabilityValues.set(key, viewToken);
426
+ const cb = ctx.mapViewabilityCallbacks.get(key);
416
427
  cb == null ? void 0 : cb(viewToken);
417
428
  }
418
- function registerViewabilityCallback(containerId, configId, callback) {
419
- const key = containerId + configId;
420
- mapViewabilityCallbacks.set(key, callback);
421
- return () => {
422
- mapViewabilityCallbacks.delete(key);
423
- };
424
- }
425
- function registerViewabilityAmountCallback(containerId, callback) {
426
- mapViewabilityAmountCallbacks.set(containerId, callback);
427
- return () => {
428
- mapViewabilityAmountCallbacks.delete(containerId);
429
- };
430
- }
431
429
 
432
430
  // src/LegendList.tsx
433
431
  var DEFAULT_SCROLL_BUFFER = 0;
@@ -522,11 +520,13 @@ var LegendListInner = React6.forwardRef(function LegendListInner2(props, forward
522
520
  scroll: initialContentOffset || 0,
523
521
  totalSize: 0,
524
522
  timeouts: /* @__PURE__ */ new Set(),
525
- viewabilityConfigCallbackPairs: void 0
523
+ viewabilityConfigCallbackPairs: void 0,
524
+ renderItem: void 0
526
525
  };
527
526
  refState.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
528
527
  }
529
528
  refState.current.data = data;
529
+ refState.current.renderItem = renderItem;
530
530
  set$(ctx, "numItems", data.length);
531
531
  set$(ctx, "stylePaddingTop", (_b = (_a = styleFlattened == null ? void 0 : styleFlattened.paddingTop) != null ? _a : contentContainerStyleFlattened == null ? void 0 : contentContainerStyleFlattened.paddingTop) != null ? _b : 0);
532
532
  const addTotalSize = React6.useCallback((add) => {
@@ -548,83 +548,93 @@ var LegendListInner = React6.forwardRef(function LegendListInner2(props, forward
548
548
  refState.current.animFrameTotalSize = requestAnimationFrame(doAdd);
549
549
  }
550
550
  }, []);
551
- const getRenderedItem = React6.useCallback(
552
- (index, containerIndex) => {
553
- var _a2;
554
- const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
555
- if (!data2) {
556
- return null;
557
- }
558
- const useViewability = (configId, callback) => {
559
- React6.useMemo(() => {
560
- const value = mapViewabilityValues.get(containerIndex + configId);
561
- if (value) {
562
- callback(value);
563
- }
564
- }, []);
565
- React6.useEffect(() => registerViewabilityCallback(containerIndex, configId, callback), []);
566
- };
567
- const useViewabilityAmount = (callback) => {
568
- React6.useMemo(() => {
569
- const value = mapViewabilityAmountValues.get(containerIndex);
570
- if (value) {
571
- callback(value);
572
- }
573
- }, []);
574
- React6.useEffect(() => registerViewabilityAmountCallback(containerIndex, callback), []);
575
- };
576
- const useRecyclingEffect = (effect) => {
577
- React6.useEffect(() => {
578
- let prevIndex = index;
579
- let prevItem = data2[index];
580
- const signal = `containerIndex${containerIndex}`;
581
- listen$(ctx, signal, () => {
582
- var _a3;
583
- const data3 = (_a3 = refState.current) == null ? void 0 : _a3.data;
584
- if (data3) {
585
- const newIndex = peek$(ctx, signal);
586
- const newItem = data3[newIndex];
587
- if (newItem) {
588
- effect({
589
- index: newIndex,
590
- item: newItem,
591
- prevIndex,
592
- prevItem
593
- });
594
- }
595
- prevIndex = newIndex;
596
- prevItem = newItem;
551
+ const getRenderedItem = React6.useCallback((index, containerId) => {
552
+ var _a2, _b2, _c;
553
+ const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
554
+ if (!data2) {
555
+ return null;
556
+ }
557
+ const useViewability = (configId, callback) => {
558
+ const key = containerId + configId;
559
+ useInit(() => {
560
+ const value = ctx.mapViewabilityValues.get(key);
561
+ if (value) {
562
+ callback(value);
563
+ }
564
+ });
565
+ ctx.mapViewabilityCallbacks.set(key, callback);
566
+ React6.useEffect(
567
+ () => () => {
568
+ ctx.mapViewabilityCallbacks.delete(key);
569
+ },
570
+ []
571
+ );
572
+ };
573
+ const useViewabilityAmount = (callback) => {
574
+ useInit(() => {
575
+ const value = ctx.mapViewabilityAmountValues.get(containerId);
576
+ if (value) {
577
+ callback(value);
578
+ }
579
+ });
580
+ ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
581
+ React6.useEffect(
582
+ () => () => {
583
+ ctx.mapViewabilityAmountCallbacks.delete(containerId);
584
+ },
585
+ []
586
+ );
587
+ };
588
+ const useRecyclingEffect = (effect) => {
589
+ React6.useEffect(() => {
590
+ const state = refState.current;
591
+ let prevIndex = index;
592
+ let prevItem = state.data[index];
593
+ const signal = `containerItemIndex${containerId}`;
594
+ listen$(ctx, signal, () => {
595
+ const data3 = state.data;
596
+ if (data3) {
597
+ const newIndex = peek$(ctx, signal);
598
+ const newItem = data3[newIndex];
599
+ if (newItem) {
600
+ effect({
601
+ index: newIndex,
602
+ item: newItem,
603
+ prevIndex,
604
+ prevItem
605
+ });
597
606
  }
598
- });
599
- }, []);
600
- };
601
- const useRecyclingState = (updateState) => {
602
- const stateInfo = React6.useState(
603
- () => updateState({
604
- index,
605
- item: data2[index],
606
- prevIndex: void 0,
607
- prevItem: void 0
608
- })
609
- );
610
- useRecyclingEffect((state) => {
611
- const newState = updateState(state);
612
- stateInfo[1](newState);
607
+ prevIndex = newIndex;
608
+ prevItem = newItem;
609
+ }
613
610
  });
614
- return stateInfo;
615
- };
616
- const renderedItem = renderItem == null ? void 0 : renderItem({
617
- item: data2[index],
618
- index,
619
- useViewability,
620
- useViewabilityAmount,
621
- useRecyclingEffect,
622
- useRecyclingState
611
+ }, []);
612
+ };
613
+ const useRecyclingState = (updateState) => {
614
+ const stateInfo = React6.useState(
615
+ () => updateState({
616
+ index,
617
+ item: refState.current.data[index],
618
+ prevIndex: void 0,
619
+ prevItem: void 0
620
+ })
621
+ );
622
+ useRecyclingEffect((state) => {
623
+ const newState = updateState(state);
624
+ stateInfo[1](newState);
623
625
  });
624
- return renderedItem;
625
- },
626
- [renderItem]
627
- );
626
+ return stateInfo;
627
+ };
628
+ const renderedItem = (_c = (_b2 = refState.current).renderItem) == null ? void 0 : _c.call(_b2, {
629
+ item: data2[index],
630
+ index,
631
+ useViewability,
632
+ useViewabilityAmount,
633
+ useRecyclingEffect,
634
+ useRecyclingState
635
+ });
636
+ return renderedItem;
637
+ }, []);
628
638
  const calculateItemsInView = React6.useCallback(() => {
629
639
  reactNative.unstable_batchedUpdates(() => {
630
640
  var _a2, _b2, _c;
@@ -632,10 +642,7 @@ var LegendListInner = React6.forwardRef(function LegendListInner2(props, forward
632
642
  data: data2,
633
643
  scrollLength,
634
644
  scroll: scrollState,
635
- startNoBuffer: startNoBufferState,
636
- startBuffered: startBufferedState,
637
- endNoBuffer: endNoBufferState,
638
- endBuffered: endBufferedState
645
+ startBuffered: startBufferedState
639
646
  } = refState.current;
640
647
  if (!data2) {
641
648
  return;
@@ -699,20 +706,21 @@ var LegendListInner = React6.forwardRef(function LegendListInner2(props, forward
699
706
  let numContainers = prevNumContainers;
700
707
  for (let i = startBuffered; i <= endBuffered; i++) {
701
708
  let isContained = false;
709
+ const id = getId(i);
702
710
  for (let j = 0; j < numContainers; j++) {
703
- const index = peek$(ctx, `containerIndex${j}`);
704
- if (index === i) {
711
+ const index = peek$(ctx, `containerItemIndex${j}`);
712
+ const key = peek$(ctx, `containerItemKey${j}`);
713
+ if (index === i && key === id) {
705
714
  isContained = true;
706
715
  break;
707
716
  }
708
717
  }
709
718
  if (!isContained) {
710
- const id = getId(i);
711
719
  const top2 = positions.get(id) || 0;
712
720
  let furthestIndex = -1;
713
721
  let furthestDistance = 0;
714
722
  for (let u = 0; u < numContainers; u++) {
715
- const index = peek$(ctx, `containerIndex${u}`);
723
+ const index = peek$(ctx, `containerItemIndex${u}`);
716
724
  if (index < 0) {
717
725
  furthestIndex = u;
718
726
  break;
@@ -727,7 +735,8 @@ var LegendListInner = React6.forwardRef(function LegendListInner2(props, forward
727
735
  }
728
736
  }
729
737
  if (furthestIndex >= 0) {
730
- set$(ctx, `containerIndex${furthestIndex}`, i);
738
+ set$(ctx, `containerItemIndex${furthestIndex}`, i);
739
+ set$(ctx, `containerItemKey${furthestIndex}`, id);
731
740
  } else {
732
741
  if (__DEV__) {
733
742
  console.warn(
@@ -737,7 +746,8 @@ var LegendListInner = React6.forwardRef(function LegendListInner2(props, forward
737
746
  }
738
747
  const containerId = numContainers;
739
748
  numContainers++;
740
- set$(ctx, `containerIndex${containerId}`, i);
749
+ set$(ctx, `containerItemIndex${containerId}`, i);
750
+ set$(ctx, `containerItemKey${containerId}`, id);
741
751
  set$(ctx, `containerPosition${containerId}`, POSITION_OUT_OF_VIEW);
742
752
  }
743
753
  }
@@ -746,11 +756,12 @@ var LegendListInner = React6.forwardRef(function LegendListInner2(props, forward
746
756
  set$(ctx, "numContainers", numContainers);
747
757
  }
748
758
  for (let i = 0; i < numContainers; i++) {
749
- const itemIndex = peek$(ctx, `containerIndex${i}`);
759
+ const itemIndex = peek$(ctx, `containerItemIndex${i}`);
760
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
750
761
  const item = data2[itemIndex];
751
762
  if (item) {
752
763
  const id = getId(itemIndex);
753
- if (itemIndex < startBuffered || itemIndex > endBuffered) {
764
+ if (itemKey !== id || itemIndex < startBuffered || itemIndex > endBuffered) {
754
765
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
755
766
  } else {
756
767
  const pos = (_c = positions.get(id)) != null ? _c : -1;
@@ -775,26 +786,26 @@ var LegendListInner = React6.forwardRef(function LegendListInner2(props, forward
775
786
  }
776
787
  });
777
788
  }, []);
778
- React6.useMemo(() => {
779
- var _a2, _b2;
789
+ useInit(() => {
790
+ var _a2;
780
791
  refState.current.viewabilityConfigCallbackPairs = setupViewability(props);
781
792
  const scrollLength = refState.current.scrollLength;
782
793
  const averageItemSize = estimatedItemSize != null ? estimatedItemSize : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(0, data[0]);
783
794
  const numContainers = initialNumContainers || Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) + 4;
784
795
  for (let i = 0; i < numContainers; i++) {
785
- set$(ctx, `containerIndex${i}`, -1);
796
+ set$(ctx, `containerItemIndex${i}`, -1);
786
797
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
787
798
  }
788
799
  set$(ctx, "numContainers", numContainers);
789
800
  calculateItemsInView();
790
- const sizes = (_a2 = refState.current) == null ? void 0 : _a2.sizes;
801
+ const sizes = refState.current.sizes;
791
802
  let totalSize = 0;
792
803
  for (let i = 0; i < data.length; i++) {
793
804
  const id = getId(i);
794
- totalSize += (_b2 = sizes.get(id)) != null ? _b2 : getItemSize(i, data[i]);
805
+ totalSize += (_a2 = sizes.get(id)) != null ? _a2 : getItemSize(i, data[i]);
795
806
  }
796
807
  addTotalSize(totalSize);
797
- }, []);
808
+ });
798
809
  const checkAtBottom = () => {
799
810
  var _a2;
800
811
  const { scrollLength, scroll } = refState.current;
@@ -819,9 +830,9 @@ var LegendListInner = React6.forwardRef(function LegendListInner2(props, forward
819
830
  const numContainers = peek$(ctx, "numContainers");
820
831
  if (data.length < numContainers) {
821
832
  for (let i = 0; i < numContainers; i++) {
822
- const itemIndex = peek$(ctx, `containerIndex${i}`);
833
+ const itemIndex = peek$(ctx, `containerItemIndex${i}`);
823
834
  if (itemIndex >= data.length) {
824
- set$(ctx, `containerIndex${i}`, -1);
835
+ set$(ctx, `containerItemIndex${i}`, -1);
825
836
  }
826
837
  }
827
838
  }
@@ -829,19 +840,19 @@ var LegendListInner = React6.forwardRef(function LegendListInner2(props, forward
829
840
  checkAtBottom();
830
841
  }, [data]);
831
842
  const updateItemSize = React6.useCallback((index, size) => {
832
- var _a2, _b2, _c, _d;
843
+ var _a2, _b2, _c;
833
844
  const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
834
845
  if (!data2) {
835
846
  return;
836
847
  }
837
- const sizes = (_b2 = refState.current) == null ? void 0 : _b2.sizes;
848
+ const sizes = refState.current.sizes;
838
849
  const id = getId(index);
839
- const wasInFirstRender = (_c = refState.current) == null ? void 0 : _c.idsInFirstRender.has(id);
850
+ const wasInFirstRender = (_b2 = refState.current) == null ? void 0 : _b2.idsInFirstRender.has(id);
840
851
  const prevSize = sizes.get(id) || (wasInFirstRender ? getItemSize(index, data2[index]) : 0);
841
852
  if (!prevSize || Math.abs(prevSize - size) > 0.5) {
842
853
  sizes.set(id, size);
843
854
  addTotalSize(size - prevSize);
844
- if (((_d = refState.current) == null ? void 0 : _d.isAtBottom) && maintainScrollAtEnd) {
855
+ if (((_c = refState.current) == null ? void 0 : _c.isAtBottom) && maintainScrollAtEnd) {
845
856
  requestAnimationFrame(() => {
846
857
  var _a3;
847
858
  (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
@@ -868,6 +879,15 @@ var LegendListInner = React6.forwardRef(function LegendListInner2(props, forward
868
879
  const onLayout = React6.useCallback((event) => {
869
880
  const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
870
881
  refState.current.scrollLength = scrollLength;
882
+ if (__DEV__) {
883
+ const isWidthZero = event.nativeEvent.layout.width === 0;
884
+ const isHeightZero = event.nativeEvent.layout.height === 0;
885
+ if (isWidthZero || isHeightZero) {
886
+ console.warn(
887
+ `[legend-list] List ${isWidthZero ? "width" : "height"} is 0. You may need to set a style or \`flex: \` for the list, because children are absolutely positioned.`
888
+ );
889
+ }
890
+ }
871
891
  }, []);
872
892
  const handleScroll = React6.useCallback(
873
893
  (event, fromSelf) => {
@@ -887,37 +907,41 @@ var LegendListInner = React6.forwardRef(function LegendListInner2(props, forward
887
907
  },
888
908
  []
889
909
  );
890
- React6.useImperativeHandle(forwardedRef, () => {
891
- const scrollToIndex = ({ index, animated }) => {
892
- const offsetObj = calculateInitialOffset(index);
893
- const offset = horizontal ? { x: offsetObj, y: 0 } : { x: 0, y: offsetObj };
894
- refScroller.current.scrollTo({ ...offset, animated });
895
- };
896
- return {
897
- getNativeScrollRef: () => refScroller.current,
898
- getScrollableNode: refScroller.current.getScrollableNode,
899
- getScrollResponder: refScroller.current.getScrollResponder,
900
- flashScrollIndicators: refScroller.current.flashScrollIndicators,
901
- scrollToIndex,
902
- scrollToOffset: ({ offset, animated }) => {
903
- const offsetObj = horizontal ? { x: offset, y: 0 } : { x: 0, y: offset };
904
- refScroller.current.scrollTo({ ...offsetObj, animated });
905
- },
906
- scrollToItem: ({ item, animated }) => {
907
- const index = data.indexOf(item);
908
- if (index !== -1) {
909
- scrollToIndex({ index, animated });
910
- }
911
- },
912
- scrollToEnd: refScroller.current.scrollToEnd
913
- };
914
- }, []);
910
+ React6.useImperativeHandle(
911
+ forwardedRef,
912
+ () => {
913
+ const scrollToIndex = ({ index, animated }) => {
914
+ const offsetObj = calculateInitialOffset(index);
915
+ const offset = horizontal ? { x: offsetObj, y: 0 } : { x: 0, y: offsetObj };
916
+ refScroller.current.scrollTo({ ...offset, animated });
917
+ };
918
+ return {
919
+ getNativeScrollRef: () => refScroller.current,
920
+ getScrollableNode: refScroller.current.getScrollableNode,
921
+ getScrollResponder: refScroller.current.getScrollResponder,
922
+ flashScrollIndicators: refScroller.current.flashScrollIndicators,
923
+ scrollToIndex,
924
+ scrollToOffset: ({ offset, animated }) => {
925
+ const offsetObj = horizontal ? { x: offset, y: 0 } : { x: 0, y: offset };
926
+ refScroller.current.scrollTo({ ...offsetObj, animated });
927
+ },
928
+ scrollToItem: ({ item, animated }) => {
929
+ const index = data.indexOf(item);
930
+ if (index !== -1) {
931
+ scrollToIndex({ index, animated });
932
+ }
933
+ },
934
+ scrollToEnd: refScroller.current.scrollToEnd
935
+ };
936
+ },
937
+ []
938
+ );
915
939
  return /* @__PURE__ */ React6__namespace.createElement(
916
940
  ListComponent,
917
941
  {
918
942
  ...rest,
919
943
  contentContainerStyle,
920
- style,
944
+ style: [style],
921
945
  horizontal,
922
946
  refScroller,
923
947
  initialContentOffset,
package/index.mjs CHANGED
@@ -12,7 +12,11 @@ function StateProvider({ children }) {
12
12
  const [value] = React6.useState(() => ({
13
13
  hooks: /* @__PURE__ */ new Map(),
14
14
  listeners: /* @__PURE__ */ new Map(),
15
- values: /* @__PURE__ */ new Map()
15
+ values: /* @__PURE__ */ new Map(),
16
+ mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
17
+ mapViewabilityValues: /* @__PURE__ */ new Map(),
18
+ mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
19
+ mapViewabilityAmountValues: /* @__PURE__ */ new Map()
16
20
  }));
17
21
  return /* @__PURE__ */ React6.createElement(ContextState.Provider, { value }, children);
18
22
  }
@@ -61,7 +65,7 @@ function $View({ $key, $style, ...rest }) {
61
65
  return /* @__PURE__ */ React6.createElement(LeanView, { style, ...rest });
62
66
  }
63
67
  function InnerContainer({ id, getRenderedItem, recycleItems, ItemSeparatorComponent }) {
64
- const itemIndex = use$(`containerIndex${id}`);
68
+ const itemIndex = use$(`containerItemIndex${id}`);
65
69
  const numItems = ItemSeparatorComponent ? use$("numItems") : 0;
66
70
  if (itemIndex < 0) {
67
71
  return null;
@@ -108,7 +112,7 @@ var Container = ({
108
112
  $key: `containerPosition${id}`,
109
113
  $style: createStyle,
110
114
  onLayout: (event) => {
111
- const index = peek$(ctx, `containerIndex${id}`);
115
+ const index = peek$(ctx, `containerItemIndex${id}`);
112
116
  if (index >= 0) {
113
117
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
114
118
  onLayout(index, size);
@@ -235,13 +239,7 @@ var ListComponent = React6.memo(function ListComponent2({
235
239
  },
236
240
  getComponent(ListHeaderComponent)
237
241
  ),
238
- ListEmptyComponent && /* @__PURE__ */ React6.createElement(
239
- View,
240
- {
241
- style: ListEmptyComponentStyle
242
- },
243
- getComponent(ListEmptyComponent)
244
- ),
242
+ ListEmptyComponent && /* @__PURE__ */ React6.createElement(View, { style: ListEmptyComponentStyle }, getComponent(ListEmptyComponent)),
245
243
  /* @__PURE__ */ React6.createElement(
246
244
  Containers,
247
245
  {
@@ -255,17 +253,26 @@ var ListComponent = React6.memo(function ListComponent2({
255
253
  ListFooterComponent && /* @__PURE__ */ React6.createElement(View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
256
254
  );
257
255
  });
256
+ var symbolFirst = Symbol();
257
+ function useInit(cb) {
258
+ const refValue = useRef(symbolFirst);
259
+ if (refValue.current === symbolFirst) {
260
+ refValue.current = cb();
261
+ }
262
+ return refValue.current;
263
+ }
258
264
 
259
265
  // src/viewability.ts
260
266
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
261
- var mapViewabilityCallbacks = /* @__PURE__ */ new Map();
262
- var mapViewabilityValues = /* @__PURE__ */ new Map();
263
- var mapViewabilityAmountCallbacks = /* @__PURE__ */ new Map();
264
- var mapViewabilityAmountValues = /* @__PURE__ */ new Map();
265
267
  function setupViewability(props) {
266
268
  let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
267
269
  viewabilityConfigCallbackPairs = viewabilityConfigCallbackPairs || [
268
- { viewabilityConfig: viewabilityConfig || { viewAreaCoveragePercentThreshold: 0 }, onViewableItemsChanged }
270
+ {
271
+ viewabilityConfig: viewabilityConfig || {
272
+ viewAreaCoveragePercentThreshold: 0
273
+ },
274
+ onViewableItemsChanged
275
+ }
269
276
  ];
270
277
  if (viewabilityConfigCallbackPairs) {
271
278
  for (const pair of viewabilityConfigCallbackPairs) {
@@ -331,12 +338,16 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
331
338
  }
332
339
  }
333
340
  }
334
- Object.assign(viewabilityState, { viewableItems, previousStart: start, previousEnd: end });
341
+ Object.assign(viewabilityState, {
342
+ viewableItems,
343
+ previousStart: start,
344
+ previousEnd: end
345
+ });
335
346
  if (changed.length > 0) {
336
347
  viewabilityState.viewableItems = viewableItems;
337
348
  for (let i = 0; i < changed.length; i++) {
338
349
  const change = changed[i];
339
- maybeUpdateViewabilityCallback(configId, change);
350
+ maybeUpdateViewabilityCallback(ctx, configId, change);
340
351
  }
341
352
  if (onViewableItemsChanged) {
342
353
  onViewableItemsChanged({ viewableItems, changed });
@@ -371,8 +382,8 @@ function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index)
371
382
  position: top,
372
383
  scrollSize
373
384
  };
374
- mapViewabilityAmountValues.set(containerId, value);
375
- const cb = mapViewabilityAmountCallbacks.get(containerId);
385
+ ctx.mapViewabilityAmountValues.set(containerId, value);
386
+ const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
376
387
  if (cb) {
377
388
  cb(value);
378
389
  }
@@ -381,32 +392,19 @@ function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index)
381
392
  function findContainerId(state, ctx, index) {
382
393
  const numContainers = peek$(ctx, "numContainers");
383
394
  for (let i = 0; i < numContainers; i++) {
384
- const itemIndex = peek$(ctx, `containerIndex${i}`);
395
+ const itemIndex = peek$(ctx, `containerItemIndex${i}`);
385
396
  if (itemIndex === index) {
386
397
  return i;
387
398
  }
388
399
  }
389
400
  return -1;
390
401
  }
391
- function maybeUpdateViewabilityCallback(configId, viewToken) {
402
+ function maybeUpdateViewabilityCallback(ctx, configId, viewToken) {
392
403
  const key = viewToken.key + configId;
393
- mapViewabilityValues.set(key, viewToken);
394
- const cb = mapViewabilityCallbacks.get(key);
404
+ ctx.mapViewabilityValues.set(key, viewToken);
405
+ const cb = ctx.mapViewabilityCallbacks.get(key);
395
406
  cb == null ? void 0 : cb(viewToken);
396
407
  }
397
- function registerViewabilityCallback(containerId, configId, callback) {
398
- const key = containerId + configId;
399
- mapViewabilityCallbacks.set(key, callback);
400
- return () => {
401
- mapViewabilityCallbacks.delete(key);
402
- };
403
- }
404
- function registerViewabilityAmountCallback(containerId, callback) {
405
- mapViewabilityAmountCallbacks.set(containerId, callback);
406
- return () => {
407
- mapViewabilityAmountCallbacks.delete(containerId);
408
- };
409
- }
410
408
 
411
409
  // src/LegendList.tsx
412
410
  var DEFAULT_SCROLL_BUFFER = 0;
@@ -501,11 +499,13 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
501
499
  scroll: initialContentOffset || 0,
502
500
  totalSize: 0,
503
501
  timeouts: /* @__PURE__ */ new Set(),
504
- viewabilityConfigCallbackPairs: void 0
502
+ viewabilityConfigCallbackPairs: void 0,
503
+ renderItem: void 0
505
504
  };
506
505
  refState.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
507
506
  }
508
507
  refState.current.data = data;
508
+ refState.current.renderItem = renderItem;
509
509
  set$(ctx, "numItems", data.length);
510
510
  set$(ctx, "stylePaddingTop", (_b = (_a = styleFlattened == null ? void 0 : styleFlattened.paddingTop) != null ? _a : contentContainerStyleFlattened == null ? void 0 : contentContainerStyleFlattened.paddingTop) != null ? _b : 0);
511
511
  const addTotalSize = useCallback((add) => {
@@ -527,83 +527,93 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
527
527
  refState.current.animFrameTotalSize = requestAnimationFrame(doAdd);
528
528
  }
529
529
  }, []);
530
- const getRenderedItem = useCallback(
531
- (index, containerIndex) => {
532
- var _a2;
533
- const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
534
- if (!data2) {
535
- return null;
536
- }
537
- const useViewability = (configId, callback) => {
538
- useMemo(() => {
539
- const value = mapViewabilityValues.get(containerIndex + configId);
540
- if (value) {
541
- callback(value);
542
- }
543
- }, []);
544
- useEffect(() => registerViewabilityCallback(containerIndex, configId, callback), []);
545
- };
546
- const useViewabilityAmount = (callback) => {
547
- useMemo(() => {
548
- const value = mapViewabilityAmountValues.get(containerIndex);
549
- if (value) {
550
- callback(value);
551
- }
552
- }, []);
553
- useEffect(() => registerViewabilityAmountCallback(containerIndex, callback), []);
554
- };
555
- const useRecyclingEffect = (effect) => {
556
- useEffect(() => {
557
- let prevIndex = index;
558
- let prevItem = data2[index];
559
- const signal = `containerIndex${containerIndex}`;
560
- listen$(ctx, signal, () => {
561
- var _a3;
562
- const data3 = (_a3 = refState.current) == null ? void 0 : _a3.data;
563
- if (data3) {
564
- const newIndex = peek$(ctx, signal);
565
- const newItem = data3[newIndex];
566
- if (newItem) {
567
- effect({
568
- index: newIndex,
569
- item: newItem,
570
- prevIndex,
571
- prevItem
572
- });
573
- }
574
- prevIndex = newIndex;
575
- prevItem = newItem;
530
+ const getRenderedItem = useCallback((index, containerId) => {
531
+ var _a2, _b2, _c;
532
+ const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
533
+ if (!data2) {
534
+ return null;
535
+ }
536
+ const useViewability = (configId, callback) => {
537
+ const key = containerId + configId;
538
+ useInit(() => {
539
+ const value = ctx.mapViewabilityValues.get(key);
540
+ if (value) {
541
+ callback(value);
542
+ }
543
+ });
544
+ ctx.mapViewabilityCallbacks.set(key, callback);
545
+ useEffect(
546
+ () => () => {
547
+ ctx.mapViewabilityCallbacks.delete(key);
548
+ },
549
+ []
550
+ );
551
+ };
552
+ const useViewabilityAmount = (callback) => {
553
+ useInit(() => {
554
+ const value = ctx.mapViewabilityAmountValues.get(containerId);
555
+ if (value) {
556
+ callback(value);
557
+ }
558
+ });
559
+ ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
560
+ useEffect(
561
+ () => () => {
562
+ ctx.mapViewabilityAmountCallbacks.delete(containerId);
563
+ },
564
+ []
565
+ );
566
+ };
567
+ const useRecyclingEffect = (effect) => {
568
+ useEffect(() => {
569
+ const state = refState.current;
570
+ let prevIndex = index;
571
+ let prevItem = state.data[index];
572
+ const signal = `containerItemIndex${containerId}`;
573
+ listen$(ctx, signal, () => {
574
+ const data3 = state.data;
575
+ if (data3) {
576
+ const newIndex = peek$(ctx, signal);
577
+ const newItem = data3[newIndex];
578
+ if (newItem) {
579
+ effect({
580
+ index: newIndex,
581
+ item: newItem,
582
+ prevIndex,
583
+ prevItem
584
+ });
576
585
  }
577
- });
578
- }, []);
579
- };
580
- const useRecyclingState = (updateState) => {
581
- const stateInfo = useState(
582
- () => updateState({
583
- index,
584
- item: data2[index],
585
- prevIndex: void 0,
586
- prevItem: void 0
587
- })
588
- );
589
- useRecyclingEffect((state) => {
590
- const newState = updateState(state);
591
- stateInfo[1](newState);
586
+ prevIndex = newIndex;
587
+ prevItem = newItem;
588
+ }
592
589
  });
593
- return stateInfo;
594
- };
595
- const renderedItem = renderItem == null ? void 0 : renderItem({
596
- item: data2[index],
597
- index,
598
- useViewability,
599
- useViewabilityAmount,
600
- useRecyclingEffect,
601
- useRecyclingState
590
+ }, []);
591
+ };
592
+ const useRecyclingState = (updateState) => {
593
+ const stateInfo = useState(
594
+ () => updateState({
595
+ index,
596
+ item: refState.current.data[index],
597
+ prevIndex: void 0,
598
+ prevItem: void 0
599
+ })
600
+ );
601
+ useRecyclingEffect((state) => {
602
+ const newState = updateState(state);
603
+ stateInfo[1](newState);
602
604
  });
603
- return renderedItem;
604
- },
605
- [renderItem]
606
- );
605
+ return stateInfo;
606
+ };
607
+ const renderedItem = (_c = (_b2 = refState.current).renderItem) == null ? void 0 : _c.call(_b2, {
608
+ item: data2[index],
609
+ index,
610
+ useViewability,
611
+ useViewabilityAmount,
612
+ useRecyclingEffect,
613
+ useRecyclingState
614
+ });
615
+ return renderedItem;
616
+ }, []);
607
617
  const calculateItemsInView = useCallback(() => {
608
618
  unstable_batchedUpdates(() => {
609
619
  var _a2, _b2, _c;
@@ -611,10 +621,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
611
621
  data: data2,
612
622
  scrollLength,
613
623
  scroll: scrollState,
614
- startNoBuffer: startNoBufferState,
615
- startBuffered: startBufferedState,
616
- endNoBuffer: endNoBufferState,
617
- endBuffered: endBufferedState
624
+ startBuffered: startBufferedState
618
625
  } = refState.current;
619
626
  if (!data2) {
620
627
  return;
@@ -678,20 +685,21 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
678
685
  let numContainers = prevNumContainers;
679
686
  for (let i = startBuffered; i <= endBuffered; i++) {
680
687
  let isContained = false;
688
+ const id = getId(i);
681
689
  for (let j = 0; j < numContainers; j++) {
682
- const index = peek$(ctx, `containerIndex${j}`);
683
- if (index === i) {
690
+ const index = peek$(ctx, `containerItemIndex${j}`);
691
+ const key = peek$(ctx, `containerItemKey${j}`);
692
+ if (index === i && key === id) {
684
693
  isContained = true;
685
694
  break;
686
695
  }
687
696
  }
688
697
  if (!isContained) {
689
- const id = getId(i);
690
698
  const top2 = positions.get(id) || 0;
691
699
  let furthestIndex = -1;
692
700
  let furthestDistance = 0;
693
701
  for (let u = 0; u < numContainers; u++) {
694
- const index = peek$(ctx, `containerIndex${u}`);
702
+ const index = peek$(ctx, `containerItemIndex${u}`);
695
703
  if (index < 0) {
696
704
  furthestIndex = u;
697
705
  break;
@@ -706,7 +714,8 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
706
714
  }
707
715
  }
708
716
  if (furthestIndex >= 0) {
709
- set$(ctx, `containerIndex${furthestIndex}`, i);
717
+ set$(ctx, `containerItemIndex${furthestIndex}`, i);
718
+ set$(ctx, `containerItemKey${furthestIndex}`, id);
710
719
  } else {
711
720
  if (__DEV__) {
712
721
  console.warn(
@@ -716,7 +725,8 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
716
725
  }
717
726
  const containerId = numContainers;
718
727
  numContainers++;
719
- set$(ctx, `containerIndex${containerId}`, i);
728
+ set$(ctx, `containerItemIndex${containerId}`, i);
729
+ set$(ctx, `containerItemKey${containerId}`, id);
720
730
  set$(ctx, `containerPosition${containerId}`, POSITION_OUT_OF_VIEW);
721
731
  }
722
732
  }
@@ -725,11 +735,12 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
725
735
  set$(ctx, "numContainers", numContainers);
726
736
  }
727
737
  for (let i = 0; i < numContainers; i++) {
728
- const itemIndex = peek$(ctx, `containerIndex${i}`);
738
+ const itemIndex = peek$(ctx, `containerItemIndex${i}`);
739
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
729
740
  const item = data2[itemIndex];
730
741
  if (item) {
731
742
  const id = getId(itemIndex);
732
- if (itemIndex < startBuffered || itemIndex > endBuffered) {
743
+ if (itemKey !== id || itemIndex < startBuffered || itemIndex > endBuffered) {
733
744
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
734
745
  } else {
735
746
  const pos = (_c = positions.get(id)) != null ? _c : -1;
@@ -754,26 +765,26 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
754
765
  }
755
766
  });
756
767
  }, []);
757
- useMemo(() => {
758
- var _a2, _b2;
768
+ useInit(() => {
769
+ var _a2;
759
770
  refState.current.viewabilityConfigCallbackPairs = setupViewability(props);
760
771
  const scrollLength = refState.current.scrollLength;
761
772
  const averageItemSize = estimatedItemSize != null ? estimatedItemSize : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(0, data[0]);
762
773
  const numContainers = initialNumContainers || Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) + 4;
763
774
  for (let i = 0; i < numContainers; i++) {
764
- set$(ctx, `containerIndex${i}`, -1);
775
+ set$(ctx, `containerItemIndex${i}`, -1);
765
776
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
766
777
  }
767
778
  set$(ctx, "numContainers", numContainers);
768
779
  calculateItemsInView();
769
- const sizes = (_a2 = refState.current) == null ? void 0 : _a2.sizes;
780
+ const sizes = refState.current.sizes;
770
781
  let totalSize = 0;
771
782
  for (let i = 0; i < data.length; i++) {
772
783
  const id = getId(i);
773
- totalSize += (_b2 = sizes.get(id)) != null ? _b2 : getItemSize(i, data[i]);
784
+ totalSize += (_a2 = sizes.get(id)) != null ? _a2 : getItemSize(i, data[i]);
774
785
  }
775
786
  addTotalSize(totalSize);
776
- }, []);
787
+ });
777
788
  const checkAtBottom = () => {
778
789
  var _a2;
779
790
  const { scrollLength, scroll } = refState.current;
@@ -798,9 +809,9 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
798
809
  const numContainers = peek$(ctx, "numContainers");
799
810
  if (data.length < numContainers) {
800
811
  for (let i = 0; i < numContainers; i++) {
801
- const itemIndex = peek$(ctx, `containerIndex${i}`);
812
+ const itemIndex = peek$(ctx, `containerItemIndex${i}`);
802
813
  if (itemIndex >= data.length) {
803
- set$(ctx, `containerIndex${i}`, -1);
814
+ set$(ctx, `containerItemIndex${i}`, -1);
804
815
  }
805
816
  }
806
817
  }
@@ -808,19 +819,19 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
808
819
  checkAtBottom();
809
820
  }, [data]);
810
821
  const updateItemSize = useCallback((index, size) => {
811
- var _a2, _b2, _c, _d;
822
+ var _a2, _b2, _c;
812
823
  const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
813
824
  if (!data2) {
814
825
  return;
815
826
  }
816
- const sizes = (_b2 = refState.current) == null ? void 0 : _b2.sizes;
827
+ const sizes = refState.current.sizes;
817
828
  const id = getId(index);
818
- const wasInFirstRender = (_c = refState.current) == null ? void 0 : _c.idsInFirstRender.has(id);
829
+ const wasInFirstRender = (_b2 = refState.current) == null ? void 0 : _b2.idsInFirstRender.has(id);
819
830
  const prevSize = sizes.get(id) || (wasInFirstRender ? getItemSize(index, data2[index]) : 0);
820
831
  if (!prevSize || Math.abs(prevSize - size) > 0.5) {
821
832
  sizes.set(id, size);
822
833
  addTotalSize(size - prevSize);
823
- if (((_d = refState.current) == null ? void 0 : _d.isAtBottom) && maintainScrollAtEnd) {
834
+ if (((_c = refState.current) == null ? void 0 : _c.isAtBottom) && maintainScrollAtEnd) {
824
835
  requestAnimationFrame(() => {
825
836
  var _a3;
826
837
  (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
@@ -847,6 +858,15 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
847
858
  const onLayout = useCallback((event) => {
848
859
  const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
849
860
  refState.current.scrollLength = scrollLength;
861
+ if (__DEV__) {
862
+ const isWidthZero = event.nativeEvent.layout.width === 0;
863
+ const isHeightZero = event.nativeEvent.layout.height === 0;
864
+ if (isWidthZero || isHeightZero) {
865
+ console.warn(
866
+ `[legend-list] List ${isWidthZero ? "width" : "height"} is 0. You may need to set a style or \`flex: \` for the list, because children are absolutely positioned.`
867
+ );
868
+ }
869
+ }
850
870
  }, []);
851
871
  const handleScroll = useCallback(
852
872
  (event, fromSelf) => {
@@ -866,37 +886,41 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
866
886
  },
867
887
  []
868
888
  );
869
- useImperativeHandle(forwardedRef, () => {
870
- const scrollToIndex = ({ index, animated }) => {
871
- const offsetObj = calculateInitialOffset(index);
872
- const offset = horizontal ? { x: offsetObj, y: 0 } : { x: 0, y: offsetObj };
873
- refScroller.current.scrollTo({ ...offset, animated });
874
- };
875
- return {
876
- getNativeScrollRef: () => refScroller.current,
877
- getScrollableNode: refScroller.current.getScrollableNode,
878
- getScrollResponder: refScroller.current.getScrollResponder,
879
- flashScrollIndicators: refScroller.current.flashScrollIndicators,
880
- scrollToIndex,
881
- scrollToOffset: ({ offset, animated }) => {
882
- const offsetObj = horizontal ? { x: offset, y: 0 } : { x: 0, y: offset };
883
- refScroller.current.scrollTo({ ...offsetObj, animated });
884
- },
885
- scrollToItem: ({ item, animated }) => {
886
- const index = data.indexOf(item);
887
- if (index !== -1) {
888
- scrollToIndex({ index, animated });
889
- }
890
- },
891
- scrollToEnd: refScroller.current.scrollToEnd
892
- };
893
- }, []);
889
+ useImperativeHandle(
890
+ forwardedRef,
891
+ () => {
892
+ const scrollToIndex = ({ index, animated }) => {
893
+ const offsetObj = calculateInitialOffset(index);
894
+ const offset = horizontal ? { x: offsetObj, y: 0 } : { x: 0, y: offsetObj };
895
+ refScroller.current.scrollTo({ ...offset, animated });
896
+ };
897
+ return {
898
+ getNativeScrollRef: () => refScroller.current,
899
+ getScrollableNode: refScroller.current.getScrollableNode,
900
+ getScrollResponder: refScroller.current.getScrollResponder,
901
+ flashScrollIndicators: refScroller.current.flashScrollIndicators,
902
+ scrollToIndex,
903
+ scrollToOffset: ({ offset, animated }) => {
904
+ const offsetObj = horizontal ? { x: offset, y: 0 } : { x: 0, y: offset };
905
+ refScroller.current.scrollTo({ ...offsetObj, animated });
906
+ },
907
+ scrollToItem: ({ item, animated }) => {
908
+ const index = data.indexOf(item);
909
+ if (index !== -1) {
910
+ scrollToIndex({ index, animated });
911
+ }
912
+ },
913
+ scrollToEnd: refScroller.current.scrollToEnd
914
+ };
915
+ },
916
+ []
917
+ );
894
918
  return /* @__PURE__ */ React6.createElement(
895
919
  ListComponent,
896
920
  {
897
921
  ...rest,
898
922
  contentContainerStyle,
899
- style,
923
+ style: [style],
900
924
  horizontal,
901
925
  refScroller,
902
926
  initialContentOffset,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
4
4
  "description": "legend-list",
5
5
  "sideEffects": false,
6
6
  "private": false,