@legendapp/list 1.0.0-beta.1 → 1.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.mjs CHANGED
@@ -1,11 +1,11 @@
1
- import * as React4 from 'react';
2
- import React4__default, { useMemo, forwardRef, useRef, useCallback, useEffect, useImperativeHandle, useSyncExternalStore, useState } from 'react';
1
+ import * as React5 from 'react';
2
+ import React5__default, { createContext, useMemo, forwardRef, useRef, useCallback, useEffect, useImperativeHandle, useSyncExternalStore, useContext, useState, useLayoutEffect } from 'react';
3
3
  import { Animated, ScrollView, View, Dimensions, StyleSheet, Platform, useAnimatedValue as useAnimatedValue$1 } from 'react-native';
4
4
 
5
5
  // src/LegendList.tsx
6
- var ContextState = React4.createContext(null);
6
+ var ContextState = React5.createContext(null);
7
7
  function StateProvider({ children }) {
8
- const [value] = React4.useState(() => ({
8
+ const [value] = React5.useState(() => ({
9
9
  listeners: /* @__PURE__ */ new Map(),
10
10
  values: /* @__PURE__ */ new Map(),
11
11
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
@@ -13,10 +13,10 @@ function StateProvider({ children }) {
13
13
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
14
14
  mapViewabilityAmountValues: /* @__PURE__ */ new Map()
15
15
  }));
16
- return /* @__PURE__ */ React4.createElement(ContextState.Provider, { value }, children);
16
+ return /* @__PURE__ */ React5.createElement(ContextState.Provider, { value }, children);
17
17
  }
18
18
  function useStateContext() {
19
- return React4.useContext(ContextState);
19
+ return React5.useContext(ContextState);
20
20
  }
21
21
  function createSelectorFunctions(ctx, signalName) {
22
22
  return {
@@ -25,8 +25,8 @@ function createSelectorFunctions(ctx, signalName) {
25
25
  };
26
26
  }
27
27
  function use$(signalName) {
28
- const ctx = React4.useContext(ContextState);
29
- const { subscribe, get } = React4.useMemo(() => createSelectorFunctions(ctx, signalName), []);
28
+ const ctx = React5.useContext(ContextState);
29
+ const { subscribe, get } = React5.useMemo(() => createSelectorFunctions(ctx, signalName), []);
30
30
  const value = useSyncExternalStore(subscribe, get);
31
31
  return value;
32
32
  }
@@ -56,75 +56,207 @@ function set$(ctx, signalName, value) {
56
56
  }
57
57
  }
58
58
  }
59
+ var symbolFirst = Symbol();
60
+ function useInit(cb) {
61
+ const refValue = useRef(symbolFirst);
62
+ if (refValue.current === symbolFirst) {
63
+ refValue.current = cb();
64
+ }
65
+ return refValue.current;
66
+ }
67
+
68
+ // src/ContextContainer.ts
69
+ var ContextContainer = createContext(null);
70
+ function useViewability(configId, callback) {
71
+ const ctx = useStateContext();
72
+ const { containerId } = useContext(ContextContainer);
73
+ const key = containerId + configId;
74
+ useInit(() => {
75
+ const value = ctx.mapViewabilityValues.get(key);
76
+ if (value) {
77
+ callback(value);
78
+ }
79
+ });
80
+ ctx.mapViewabilityCallbacks.set(key, callback);
81
+ useEffect(
82
+ () => () => {
83
+ ctx.mapViewabilityCallbacks.delete(key);
84
+ },
85
+ []
86
+ );
87
+ }
88
+ function useViewabilityAmount(callback) {
89
+ const ctx = useStateContext();
90
+ const { containerId } = useContext(ContextContainer);
91
+ useInit(() => {
92
+ const value = ctx.mapViewabilityAmountValues.get(containerId);
93
+ if (value) {
94
+ callback(value);
95
+ }
96
+ });
97
+ ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
98
+ useEffect(
99
+ () => () => {
100
+ ctx.mapViewabilityAmountCallbacks.delete(containerId);
101
+ },
102
+ []
103
+ );
104
+ }
105
+ function useRecyclingEffect(effect) {
106
+ const { index, value } = useContext(ContextContainer);
107
+ const prevValues = useRef({
108
+ prevIndex: void 0,
109
+ prevItem: void 0
110
+ });
111
+ useEffect(() => {
112
+ let ret = void 0;
113
+ if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
114
+ ret = effect({
115
+ index,
116
+ item: value,
117
+ prevIndex: prevValues.current.prevIndex,
118
+ prevItem: prevValues.current.prevItem
119
+ });
120
+ }
121
+ prevValues.current = {
122
+ prevIndex: index,
123
+ prevItem: value
124
+ };
125
+ return ret;
126
+ }, [index, value]);
127
+ }
128
+ function useRecyclingState(valueOrFun) {
129
+ const { index, value } = useContext(ContextContainer);
130
+ const stateInfo = useState(
131
+ () => typeof valueOrFun === "function" ? valueOrFun({
132
+ index,
133
+ item: value,
134
+ prevIndex: void 0,
135
+ prevItem: void 0
136
+ }) : valueOrFun
137
+ );
138
+ useRecyclingEffect((state) => {
139
+ const newState = typeof valueOrFun === "function" ? valueOrFun(state) : valueOrFun;
140
+ stateInfo[1](newState);
141
+ });
142
+ return stateInfo;
143
+ }
144
+ var LeanView = React5.forwardRef((props, ref) => {
145
+ return React5.createElement("RCTView", { ...props, ref });
146
+ });
147
+ LeanView.displayName = "RCTView";
148
+
149
+ // src/constants.ts
150
+ var POSITION_OUT_OF_VIEW = -1e7;
151
+ var ANCHORED_POSITION_OUT_OF_VIEW = {
152
+ type: "top",
153
+ relativeCoordinate: POSITION_OUT_OF_VIEW,
154
+ top: POSITION_OUT_OF_VIEW
155
+ };
59
156
 
60
157
  // src/Container.tsx
158
+ var isNewArchitecture = global.nativeFabricUIManager != null;
61
159
  var Container = ({
62
160
  id,
63
161
  recycleItems,
64
162
  horizontal,
65
- waitForInitialLayout,
66
163
  getRenderedItem,
67
164
  updateItemSize,
68
165
  ItemSeparatorComponent
69
166
  }) => {
70
- const ctx = useStateContext();
71
- const position = use$(`containerPosition${id}`);
167
+ useStateContext();
168
+ const maintainVisibleContentPosition = use$("maintainVisibleContentPosition");
169
+ const position = use$(`containerPosition${id}`) || ANCHORED_POSITION_OUT_OF_VIEW;
72
170
  const column = use$(`containerColumn${id}`) || 0;
73
171
  const numColumns = use$("numColumns");
74
172
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
75
173
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
76
174
  const style = horizontal ? {
77
- flexDirection: "row",
175
+ flexDirection: ItemSeparatorComponent ? "row" : void 0,
78
176
  position: "absolute",
79
177
  top: otherAxisPos,
80
178
  bottom: numColumns > 1 ? null : 0,
81
179
  height: otherAxisSize,
82
- left: position
180
+ left: position.relativeCoordinate
83
181
  } : {
84
182
  position: "absolute",
85
183
  left: otherAxisPos,
86
184
  right: numColumns > 1 ? null : 0,
87
185
  width: otherAxisSize,
88
- top: position
186
+ top: position.relativeCoordinate
89
187
  };
90
- if (waitForInitialLayout) {
91
- const visible = use$(`containerDidLayout${id}`);
92
- style.opacity = visible ? 1 : 0;
93
- }
94
188
  const lastItemKey = use$("lastItemKey");
95
189
  const itemKey = use$(`containerItemKey${id}`);
96
190
  const data = use$(`containerItemData${id}`);
97
- const renderedItem = useMemo(() => itemKey !== void 0 && getRenderedItem(itemKey, id), [itemKey, data]);
98
- return /* @__PURE__ */ React4__default.createElement(
99
- View,
100
- {
101
- style,
102
- onLayout: (event) => {
103
- const key = peek$(ctx, `containerItemKey${id}`);
104
- if (key !== void 0) {
105
- const size = Math.floor(event.nativeEvent.layout[horizontal ? "width" : "height"] * 8) / 8;
106
- updateItemSize(id, key, size);
191
+ const extraData = use$("extraData");
192
+ const renderedItemInfo = useMemo(
193
+ () => itemKey !== void 0 && getRenderedItem(itemKey),
194
+ [itemKey, data, extraData]
195
+ );
196
+ const { index, renderedItem } = renderedItemInfo || {};
197
+ const onLayout = (event) => {
198
+ if (itemKey !== void 0) {
199
+ const size = Math.floor(event.nativeEvent.layout[horizontal ? "width" : "height"] * 8) / 8;
200
+ if (size === 0) {
201
+ console.log("[WARN] Container 0 height reported, possible bug in LegendList", id, itemKey);
202
+ return;
203
+ }
204
+ updateItemSize(id, itemKey, size);
205
+ }
206
+ };
207
+ const ref = useRef(null);
208
+ if (isNewArchitecture) {
209
+ useLayoutEffect(() => {
210
+ var _a, _b;
211
+ if (itemKey !== void 0) {
212
+ const measured = (_b = (_a = ref.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
213
+ if (measured) {
214
+ const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
215
+ if (size) {
216
+ updateItemSize(id, itemKey, size);
217
+ }
107
218
  }
108
219
  }
109
- },
110
- /* @__PURE__ */ React4__default.createElement(React4__default.Fragment, { key: recycleItems ? void 0 : itemKey }, renderedItem, renderedItem && ItemSeparatorComponent && itemKey !== lastItemKey && ItemSeparatorComponent)
220
+ }, [itemKey]);
221
+ }
222
+ const contextValue = useMemo(
223
+ () => ({ containerId: id, itemKey, index, value: data }),
224
+ [id, itemKey, index, data]
111
225
  );
226
+ const contentFragment = /* @__PURE__ */ React5__default.createElement(React5__default.Fragment, { key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React5__default.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItem && ItemSeparatorComponent && itemKey !== lastItemKey && ItemSeparatorComponent));
227
+ if (maintainVisibleContentPosition) {
228
+ const anchorStyle = position.type === "top" ? { position: "absolute", top: 0, left: 0, right: 0 } : { position: "absolute", bottom: 0, left: 0, right: 0 };
229
+ return /* @__PURE__ */ React5__default.createElement(LeanView, { style }, /* @__PURE__ */ React5__default.createElement(LeanView, { style: anchorStyle, onLayout, ref }, contentFragment));
230
+ }
231
+ return /* @__PURE__ */ React5__default.createElement(LeanView, { style, onLayout, ref }, contentFragment);
112
232
  };
113
233
  var useAnimatedValue = useAnimatedValue$1 || ((initialValue) => {
114
234
  return useRef(new Animated.Value(initialValue)).current;
115
235
  });
116
- function useValue$(key, getValue, key2) {
236
+ function useValue$(key, getValue, useMicrotask) {
117
237
  var _a;
118
238
  const ctx = useStateContext();
119
- const animValue = useAnimatedValue((_a = peek$(ctx, key)) != null ? _a : 0);
239
+ const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
120
240
  useMemo(() => {
121
- listen$(ctx, key, (v) => animValue.setValue(v));
241
+ let newValue = void 0;
242
+ listen$(ctx, key, (v) => {
243
+ if (useMicrotask && newValue === void 0) {
244
+ queueMicrotask(() => {
245
+ animValue.setValue(newValue);
246
+ newValue = void 0;
247
+ });
248
+ }
249
+ newValue = getValue ? getValue(v) : v;
250
+ if (!useMicrotask) {
251
+ animValue.setValue(newValue);
252
+ }
253
+ });
122
254
  }, []);
123
255
  return animValue;
124
256
  }
125
257
 
126
258
  // src/Containers.tsx
127
- var Containers = React4.memo(function Containers2({
259
+ var Containers = React5.memo(function Containers2({
128
260
  horizontal,
129
261
  recycleItems,
130
262
  ItemSeparatorComponent,
@@ -133,18 +265,23 @@ var Containers = React4.memo(function Containers2({
133
265
  getRenderedItem
134
266
  }) {
135
267
  const numContainers = use$("numContainersPooled");
136
- const animSize = useValue$("totalSize");
268
+ const animSize = useValue$(
269
+ "totalSize",
270
+ void 0,
271
+ /*useMicrotask*/
272
+ true
273
+ );
274
+ const animOpacity = waitForInitialLayout ? useValue$("containersDidLayout", (value) => value ? 1 : 0) : void 0;
137
275
  const containers = [];
138
276
  for (let i = 0; i < numContainers; i++) {
139
277
  containers.push(
140
- /* @__PURE__ */ React4.createElement(
278
+ /* @__PURE__ */ React5.createElement(
141
279
  Container,
142
280
  {
143
281
  id: i,
144
282
  key: i,
145
283
  recycleItems,
146
284
  horizontal,
147
- waitForInitialLayout,
148
285
  getRenderedItem,
149
286
  updateItemSize,
150
287
  ItemSeparatorComponent
@@ -152,21 +289,21 @@ var Containers = React4.memo(function Containers2({
152
289
  )
153
290
  );
154
291
  }
155
- const style = horizontal ? { width: animSize } : { height: animSize };
156
- return /* @__PURE__ */ React4.createElement(Animated.View, { style }, containers);
292
+ const style = horizontal ? { width: animSize, opacity: animOpacity } : { height: animSize, opacity: animOpacity };
293
+ return /* @__PURE__ */ React5.createElement(Animated.View, { style }, containers);
157
294
  });
158
295
 
159
296
  // src/ListComponent.tsx
160
297
  var getComponent = (Component) => {
161
- if (React4.isValidElement(Component)) {
298
+ if (React5.isValidElement(Component)) {
162
299
  return Component;
163
300
  }
164
301
  if (Component) {
165
- return /* @__PURE__ */ React4.createElement(Component, null);
302
+ return /* @__PURE__ */ React5.createElement(Component, null);
166
303
  }
167
304
  return null;
168
305
  };
169
- var ListComponent = React4.memo(function ListComponent2({
306
+ var ListComponent = React5.memo(function ListComponent2({
170
307
  style,
171
308
  contentContainerStyle,
172
309
  horizontal,
@@ -182,7 +319,6 @@ var ListComponent = React4.memo(function ListComponent2({
182
319
  ListFooterComponent,
183
320
  ListFooterComponentStyle,
184
321
  ListEmptyComponent,
185
- ListEmptyComponentStyle,
186
322
  getRenderedItem,
187
323
  updateItemSize,
188
324
  refScrollView,
@@ -194,16 +330,16 @@ var ListComponent = React4.memo(function ListComponent2({
194
330
  const animPaddingTop = useValue$("paddingTop");
195
331
  const animScrollAdjust = useValue$("scrollAdjust");
196
332
  const ScrollComponent = renderScrollComponent ? useMemo(
197
- () => React4.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
333
+ () => React5.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
198
334
  [renderScrollComponent]
199
335
  ) : ScrollView;
200
336
  const additionalSize = { marginTop: animScrollAdjust, paddingTop: animPaddingTop };
201
- return /* @__PURE__ */ React4.createElement(
337
+ return /* @__PURE__ */ React5.createElement(
202
338
  ScrollComponent,
203
339
  {
204
340
  ...rest,
205
341
  style,
206
- maintainVisibleContentPosition: maintainVisibleContentPosition ? { minIndexForVisible: 0 } : void 0,
342
+ maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
207
343
  contentContainerStyle: [
208
344
  contentContainerStyle,
209
345
  horizontal ? {
@@ -216,8 +352,8 @@ var ListComponent = React4.memo(function ListComponent2({
216
352
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
217
353
  ref: refScrollView
218
354
  },
219
- /* @__PURE__ */ React4.createElement(Animated.View, { style: additionalSize }),
220
- ListHeaderComponent && /* @__PURE__ */ React4.createElement(
355
+ /* @__PURE__ */ React5.createElement(Animated.View, { style: additionalSize }),
356
+ ListHeaderComponent && /* @__PURE__ */ React5.createElement(
221
357
  Animated.View,
222
358
  {
223
359
  style: ListHeaderComponentStyle,
@@ -231,8 +367,8 @@ var ListComponent = React4.memo(function ListComponent2({
231
367
  },
232
368
  getComponent(ListHeaderComponent)
233
369
  ),
234
- ListEmptyComponent && /* @__PURE__ */ React4.createElement(Animated.View, { style: ListEmptyComponentStyle }, getComponent(ListEmptyComponent)),
235
- /* @__PURE__ */ React4.createElement(
370
+ ListEmptyComponent && getComponent(ListEmptyComponent),
371
+ /* @__PURE__ */ React5.createElement(
236
372
  Containers,
237
373
  {
238
374
  horizontal,
@@ -243,7 +379,7 @@ var ListComponent = React4.memo(function ListComponent2({
243
379
  updateItemSize
244
380
  }
245
381
  ),
246
- ListFooterComponent && /* @__PURE__ */ React4.createElement(View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
382
+ ListFooterComponent && /* @__PURE__ */ React5.createElement(View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
247
383
  );
248
384
  });
249
385
 
@@ -283,14 +419,6 @@ var ScrollAdjustHandler = class {
283
419
  return this.appliedAdjust;
284
420
  }
285
421
  };
286
- var symbolFirst = Symbol();
287
- function useInit(cb) {
288
- const refValue = useRef(symbolFirst);
289
- if (refValue.current === symbolFirst) {
290
- refValue.current = cb();
291
- }
292
- return refValue.current;
293
- }
294
422
 
295
423
  // src/viewability.ts
296
424
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
@@ -441,13 +569,12 @@ function maybeUpdateViewabilityCallback(ctx, configId, viewToken) {
441
569
 
442
570
  // src/LegendList.tsx
443
571
  var DEFAULT_DRAW_DISTANCE = 250;
444
- var POSITION_OUT_OF_VIEW = -1e7;
445
572
  var DEFAULT_ITEM_SIZE = 100;
446
573
  var LegendList = forwardRef(function LegendList2(props, forwardedRef) {
447
- return /* @__PURE__ */ React4.createElement(StateProvider, null, /* @__PURE__ */ React4.createElement(LegendListInner, { ...props, ref: forwardedRef }));
574
+ return /* @__PURE__ */ React5.createElement(StateProvider, null, /* @__PURE__ */ React5.createElement(LegendListInner, { ...props, ref: forwardedRef }));
448
575
  });
449
576
  var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef) {
450
- var _a, _b, _c, _d;
577
+ var _a, _b, _c, _d, _e, _f, _g;
451
578
  const {
452
579
  data,
453
580
  initialScrollIndex,
@@ -467,15 +594,22 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
467
594
  renderItem,
468
595
  estimatedItemSize,
469
596
  getEstimatedItemSize,
470
- onEndReached,
471
- onStartReached,
472
597
  ListEmptyComponent,
473
598
  onItemSizeChanged,
474
599
  scrollEventThrottle,
475
600
  refScrollView,
601
+ waitForInitialLayout = true,
602
+ extraData,
603
+ onLayout: onLayoutProp,
476
604
  ...rest
477
605
  } = props;
478
606
  const { style, contentContainerStyle } = props;
607
+ const callbacks = useRef({
608
+ onStartReached: rest.onStartReached,
609
+ onEndReached: rest.onEndReached
610
+ });
611
+ callbacks.current.onStartReached = rest.onStartReached;
612
+ callbacks.current.onEndReached = rest.onEndReached;
479
613
  const ctx = useStateContext();
480
614
  const refScroller = useRef(null);
481
615
  const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE;
@@ -522,7 +656,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
522
656
  positions: /* @__PURE__ */ new Map(),
523
657
  columns: /* @__PURE__ */ new Map(),
524
658
  pendingAdjust: 0,
525
- animFrameLayout: null,
659
+ waitingForMicrotask: false,
526
660
  isStartReached: initialContentOffset < initialScrollLength * onStartReachedThreshold,
527
661
  isEndReached: false,
528
662
  isAtBottom: false,
@@ -555,9 +689,9 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
555
689
  belowAnchorElementPositions: void 0,
556
690
  rowHeights: /* @__PURE__ */ new Map(),
557
691
  startReachedBlockedByTimer: false,
558
- layoutsPending: /* @__PURE__ */ new Set(),
559
692
  scrollForNextCalculateItemsInView: void 0,
560
- enableScrollForNextCalculateItemsInView: true
693
+ enableScrollForNextCalculateItemsInView: true,
694
+ minIndexSizeChanged: 0
561
695
  };
562
696
  refState.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
563
697
  if (maintainVisibleContentPosition) {
@@ -576,6 +710,8 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
576
710
  }
577
711
  }
578
712
  set$(ctx, "scrollAdjust", 0);
713
+ set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
714
+ set$(ctx, "extraData", extraData);
579
715
  }
580
716
  const getAnchorElementIndex = () => {
581
717
  const state = refState.current;
@@ -587,14 +723,14 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
587
723
  };
588
724
  const addTotalSize = useCallback((key, add, totalSizeBelowAnchor) => {
589
725
  const state = refState.current;
590
- const index = key === null ? 0 : state.indexByKey.get(key);
726
+ const { scrollLength, indexByKey, anchorElement } = state;
727
+ const index = key === null ? 0 : indexByKey.get(key);
591
728
  let isAboveAnchor = false;
592
729
  if (maintainVisibleContentPosition) {
593
- if (state.anchorElement && index < getAnchorElementIndex()) {
730
+ if (anchorElement && index < getAnchorElementIndex()) {
594
731
  isAboveAnchor = true;
595
732
  }
596
733
  }
597
- state.totalSize;
598
734
  if (key === null) {
599
735
  state.totalSize = add;
600
736
  state.totalSizeBelowAnchor = totalSizeBelowAnchor;
@@ -605,19 +741,19 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
605
741
  }
606
742
  }
607
743
  let applyAdjustValue = void 0;
608
- if (maintainVisibleContentPosition) {
609
- const newAdjust = state.anchorElement.coordinate - state.totalSizeBelowAnchor;
744
+ const totalSize = state.totalSize;
745
+ let resultSize = totalSize;
746
+ if (maintainVisibleContentPosition && totalSize > scrollLength) {
747
+ const newAdjust = anchorElement.coordinate - state.totalSizeBelowAnchor;
610
748
  applyAdjustValue = -newAdjust;
611
749
  state.belowAnchorElementPositions = buildElementPositionsBelowAnchor();
612
750
  state.rowHeights.clear();
613
- }
614
- const totalSize = state.totalSize;
615
- let resultSize = totalSize;
616
- if (applyAdjustValue !== void 0) {
617
- resultSize -= applyAdjustValue;
618
- refState.current.scrollAdjustHandler.requestAdjust(applyAdjustValue, (diff) => {
619
- state.scroll -= diff;
620
- });
751
+ if (applyAdjustValue !== void 0) {
752
+ resultSize -= applyAdjustValue;
753
+ refState.current.scrollAdjustHandler.requestAdjust(applyAdjustValue, (diff) => {
754
+ state.scroll -= diff;
755
+ });
756
+ }
621
757
  }
622
758
  set$(ctx, "totalSize", resultSize);
623
759
  if (alignItemsAtEnd) {
@@ -684,12 +820,10 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
684
820
  startBufferedId: startBufferedIdOrig,
685
821
  positions,
686
822
  columns,
687
- scrollAdjustHandler,
688
- layoutsPending
823
+ scrollAdjustHandler
689
824
  } = state;
690
- if (state.animFrameLayout) {
691
- cancelAnimationFrame(state.animFrameLayout);
692
- state.animFrameLayout = null;
825
+ if (state.waitingForMicrotask) {
826
+ state.waitingForMicrotask = false;
693
827
  }
694
828
  if (!data2) {
695
829
  return;
@@ -697,7 +831,17 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
697
831
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
698
832
  const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
699
833
  const scrollExtra = Math.max(-16, Math.min(16, speed)) * 16;
700
- const scroll = scrollState - previousScrollAdjust - topPad - scrollExtra;
834
+ const scroll = scrollState - previousScrollAdjust - topPad;
835
+ let scrollBufferTop = scrollBuffer;
836
+ let scrollBufferBottom = scrollBuffer;
837
+ if (scrollExtra > 8) {
838
+ scrollBufferTop = 0;
839
+ scrollBufferBottom = scrollBuffer + scrollExtra;
840
+ }
841
+ if (scrollExtra < -8) {
842
+ scrollBufferTop = scrollBuffer - scrollExtra;
843
+ scrollBufferBottom = 0;
844
+ }
701
845
  if (state.scrollForNextCalculateItemsInView) {
702
846
  const { top: top2, bottom } = state.scrollForNextCalculateItemsInView;
703
847
  if (scroll > top2 && scroll < bottom) {
@@ -710,8 +854,11 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
710
854
  let startBufferedId = null;
711
855
  let endNoBuffer = null;
712
856
  let endBuffered = null;
713
- const originalStartId = startBufferedIdOrig && state.indexByKey.get(startBufferedIdOrig);
714
- let loopStart = originalStartId || 0;
857
+ let loopStart = startBufferedIdOrig ? state.indexByKey.get(startBufferedIdOrig) || 0 : 0;
858
+ if (state.minIndexSizeChanged !== void 0) {
859
+ loopStart = Math.min(state.minIndexSizeChanged, loopStart);
860
+ state.minIndexSizeChanged = void 0;
861
+ }
715
862
  const anchorElementIndex = getAnchorElementIndex();
716
863
  for (let i = loopStart; i >= 0; i--) {
717
864
  const id = getId(i);
@@ -769,7 +916,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
769
916
  if (startNoBuffer === null && top + size > scroll) {
770
917
  startNoBuffer = i;
771
918
  }
772
- if (startBuffered === null && top + size > scroll - scrollBuffer) {
919
+ if (startBuffered === null && top + size > scroll - scrollBufferTop) {
773
920
  startBuffered = i;
774
921
  startBufferedId = id;
775
922
  }
@@ -777,7 +924,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
777
924
  if (top <= scrollBottom) {
778
925
  endNoBuffer = i;
779
926
  }
780
- if (top <= scrollBottom + scrollBuffer) {
927
+ if (top <= scrollBottom + scrollBufferBottom) {
781
928
  endBuffered = i;
782
929
  } else {
783
930
  break;
@@ -797,9 +944,9 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
797
944
  endBuffered,
798
945
  endNoBuffer
799
946
  });
800
- const nextTop = Math.ceil(startBuffered ? positions.get(startBufferedId) + scrollBuffer : 0);
947
+ const nextTop = Math.ceil(startBuffered !== null ? positions.get(startBufferedId) + scrollBuffer : 0);
801
948
  const nextBottom = Math.floor(
802
- endBuffered ? (positions.get(getId(endBuffered + 1)) || 0) - scrollLength - scrollBuffer : 0
949
+ endBuffered !== null ? (positions.get(getId(endBuffered + 1)) || 0) - scrollLength - scrollBuffer : 0
803
950
  );
804
951
  if (state.enableScrollForNextCalculateItemsInView) {
805
952
  state.scrollForNextCalculateItemsInView = nextTop >= 0 && nextBottom >= 0 ? {
@@ -831,7 +978,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
831
978
  break;
832
979
  }
833
980
  const index = state.indexByKey.get(key);
834
- const pos = peek$(ctx, `containerPosition${u}`);
981
+ const pos = peek$(ctx, `containerPosition${u}`).top;
835
982
  if (index < startBuffered || index > endBuffered) {
836
983
  const distance = Math.abs(pos - top2);
837
984
  if (index < 0 || distance > furthestDistance) {
@@ -850,7 +997,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
850
997
  set$(ctx, `containerItemKey${containerId}`, id);
851
998
  const index = state.indexByKey.get(id);
852
999
  set$(ctx, `containerItemData${containerId}`, data2[index]);
853
- set$(ctx, `containerPosition${containerId}`, POSITION_OUT_OF_VIEW);
1000
+ set$(ctx, `containerPosition${containerId}`, ANCHORED_POSITION_OUT_OF_VIEW);
854
1001
  set$(ctx, `containerColumn${containerId}`, -1);
855
1002
  if (__DEV__ && numContainers > peek$(ctx, "numContainersPooled")) {
856
1003
  console.warn(
@@ -874,19 +1021,31 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
874
1021
  if (item) {
875
1022
  const id = getId(itemIndex);
876
1023
  if (itemKey !== id || itemIndex < startBuffered || itemIndex > endBuffered) {
877
- const prevPos = peek$(ctx, `containerPosition${i}`);
1024
+ const prevPos = peek$(ctx, `containerPosition${i}`).top;
878
1025
  const pos = positions.get(id) || 0;
879
1026
  const size = getItemSize(id, itemIndex, data2[i]);
880
1027
  if (pos + size >= scroll && pos <= scrollBottom || prevPos + size >= scroll && prevPos <= scrollBottom) {
881
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1028
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
882
1029
  }
883
1030
  } else {
884
- const pos = positions.get(id) || 0;
1031
+ const pos = {
1032
+ type: "top",
1033
+ relativeCoordinate: positions.get(id) || 0,
1034
+ top: positions.get(id) || 0
1035
+ };
885
1036
  const column2 = columns.get(id) || 1;
1037
+ if (maintainVisibleContentPosition && itemIndex < anchorElementIndex) {
1038
+ const currentRow = Math.floor(itemIndex / numColumnsProp);
1039
+ const rowHeight = getRowHeight(currentRow);
1040
+ const elementHeight = getItemSize(id, itemIndex, data2[i]);
1041
+ const diff = rowHeight - elementHeight;
1042
+ pos.relativeCoordinate = pos.top + getRowHeight(currentRow) - diff;
1043
+ pos.type = "bottom";
1044
+ }
886
1045
  const prevPos = peek$(ctx, `containerPosition${i}`);
887
1046
  const prevColumn = peek$(ctx, `containerColumn${i}`);
888
1047
  const prevData = peek$(ctx, `containerItemData${i}`);
889
- if (pos > POSITION_OUT_OF_VIEW && pos !== prevPos) {
1048
+ if (pos.relativeCoordinate > POSITION_OUT_OF_VIEW && pos.top !== prevPos.top) {
890
1049
  set$(ctx, `containerPosition${i}`, pos);
891
1050
  }
892
1051
  if (column2 >= 0 && column2 !== prevColumn) {
@@ -899,12 +1058,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
899
1058
  }
900
1059
  }
901
1060
  }
902
- if (layoutsPending.size > 0) {
903
- for (const containerId of layoutsPending) {
904
- set$(ctx, `containerDidLayout${containerId}`, true);
905
- }
906
- layoutsPending.clear();
907
- }
1061
+ set$(ctx, "containersDidLayout", true);
908
1062
  if (state.viewabilityConfigCallbackPairs) {
909
1063
  updateViewableItems(
910
1064
  state,
@@ -948,6 +1102,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
948
1102
  if (refState.current) {
949
1103
  refState.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
950
1104
  }
1105
+ const { onEndReached } = callbacks.current;
951
1106
  if (onEndReached) {
952
1107
  if (!refState.current.isEndReached) {
953
1108
  if (distanceFromEnd < onEndReachedThreshold * scrollLength) {
@@ -969,6 +1124,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
969
1124
  const { scrollLength, scroll } = refState.current;
970
1125
  const distanceFromTop = scroll;
971
1126
  refState.current.isAtTop = distanceFromTop < 0;
1127
+ const { onStartReached } = callbacks.current;
972
1128
  if (onStartReached) {
973
1129
  if (!refState.current.isStartReached && !refState.current.startReachedBlockedByTimer) {
974
1130
  if (distanceFromTop < onStartReachedThreshold * scrollLength) {
@@ -997,13 +1153,13 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
997
1153
  const itemKey = peek$(ctx, `containerItemKey${i}`);
998
1154
  if (!keyExtractorProp || itemKey && state.indexByKey.get(itemKey) === void 0) {
999
1155
  set$(ctx, `containerItemKey${i}`, void 0);
1000
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1156
+ set$(ctx, `containerItemData${i}`, void 0);
1157
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1001
1158
  set$(ctx, `containerColumn${i}`, -1);
1002
1159
  }
1003
1160
  }
1004
1161
  if (!keyExtractorProp) {
1005
- state.sizes.clear();
1006
- state.positions;
1162
+ state.positions.clear();
1007
1163
  }
1008
1164
  calculateItemsInView(state.scrollVelocity);
1009
1165
  }
@@ -1018,20 +1174,63 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1018
1174
  const isFirst = !refState.current.renderItem;
1019
1175
  if (isFirst || data !== refState.current.data || numColumnsProp !== peek$(ctx, "numColumns")) {
1020
1176
  if (!keyExtractorProp && !isFirst && data !== refState.current.data) {
1021
- refState.current.sizes.clear();
1022
1177
  refState.current.positions.clear();
1023
1178
  }
1024
1179
  refState.current.data = data;
1025
1180
  let totalSize = 0;
1026
1181
  let totalSizeBelowIndex = 0;
1027
1182
  const indexByKey = /* @__PURE__ */ new Map();
1183
+ const newPositions = /* @__PURE__ */ new Map();
1028
1184
  let column = 1;
1029
1185
  let maxSizeInRow = 0;
1030
1186
  for (let i = 0; i < data.length; i++) {
1031
1187
  const key = getId(i);
1188
+ if (__DEV__) {
1189
+ if (indexByKey.has(key)) {
1190
+ console.error(
1191
+ `[legend-list] Error: Detected overlapping key (${key}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`
1192
+ );
1193
+ }
1194
+ }
1032
1195
  indexByKey.set(key, i);
1196
+ if (refState.current.positions.get(key) != null && refState.current.indexByKey.get(key) === i) {
1197
+ newPositions.set(key, refState.current.positions.get(key));
1198
+ }
1033
1199
  }
1034
1200
  refState.current.indexByKey = indexByKey;
1201
+ refState.current.positions = newPositions;
1202
+ if (!isFirst) {
1203
+ if (maintainVisibleContentPosition) {
1204
+ if (refState.current.anchorElement == null || indexByKey.get(refState.current.anchorElement.id) == null) {
1205
+ if (data.length) {
1206
+ const newAnchorElement = {
1207
+ coordinate: 0,
1208
+ id: getId(0)
1209
+ };
1210
+ refState.current.anchorElement = newAnchorElement;
1211
+ (_a = refState.current.belowAnchorElementPositions) == null ? void 0 : _a.clear();
1212
+ (_b = refScroller.current) == null ? void 0 : _b.scrollTo({ x: 0, y: 0, animated: false });
1213
+ setTimeout(() => {
1214
+ calculateItemsInView(0);
1215
+ }, 0);
1216
+ } else {
1217
+ refState.current.startBufferedId = void 0;
1218
+ }
1219
+ }
1220
+ } else {
1221
+ if (refState.current.startBufferedId != null && newPositions.get(refState.current.startBufferedId) == null) {
1222
+ if (data.length) {
1223
+ refState.current.startBufferedId = getId(0);
1224
+ } else {
1225
+ refState.current.startBufferedId = void 0;
1226
+ }
1227
+ (_c = refScroller.current) == null ? void 0 : _c.scrollTo({ x: 0, y: 0, animated: false });
1228
+ setTimeout(() => {
1229
+ calculateItemsInView(0);
1230
+ }, 0);
1231
+ }
1232
+ }
1233
+ }
1035
1234
  const anchorElementIndex = getAnchorElementIndex();
1036
1235
  for (let i = 0; i < data.length; i++) {
1037
1236
  const key = getId(i);
@@ -1058,9 +1257,12 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1058
1257
  !isFirst
1059
1258
  );
1060
1259
  }, [isFirst, data, numColumnsProp]);
1260
+ useEffect(() => {
1261
+ set$(ctx, "extraData", extraData);
1262
+ }, [extraData]);
1061
1263
  refState.current.renderItem = renderItem;
1062
- const lastItemKey = getId(data[data.length - 1]);
1063
- const stylePaddingTop = (_d = (_c = (_a = StyleSheet.flatten(style)) == null ? void 0 : _a.paddingTop) != null ? _c : (_b = StyleSheet.flatten(contentContainerStyle)) == null ? void 0 : _b.paddingTop) != null ? _d : 0;
1264
+ const lastItemKey = data.length > 0 ? getId(data.length - 1) : void 0;
1265
+ const stylePaddingTop = (_g = (_f = (_d = StyleSheet.flatten(style)) == null ? void 0 : _d.paddingTop) != null ? _f : (_e = StyleSheet.flatten(contentContainerStyle)) == null ? void 0 : _e.paddingTop) != null ? _g : 0;
1064
1266
  const initalizeStateVars = () => {
1065
1267
  set$(ctx, "lastItemKey", lastItemKey);
1066
1268
  set$(ctx, "numColumns", numColumnsProp);
@@ -1070,7 +1272,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1070
1272
  initalizeStateVars();
1071
1273
  }
1072
1274
  useEffect(initalizeStateVars, [lastItemKey, numColumnsProp, stylePaddingTop]);
1073
- const getRenderedItem = useCallback((key, containerId) => {
1275
+ const getRenderedItem = useCallback((key) => {
1074
1276
  var _a2, _b2;
1075
1277
  const state = refState.current;
1076
1278
  if (!state) {
@@ -1081,89 +1283,27 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1081
1283
  if (index === void 0) {
1082
1284
  return null;
1083
1285
  }
1084
- const useViewability = (configId, callback) => {
1085
- const key2 = containerId + configId;
1086
- useInit(() => {
1087
- const value = ctx.mapViewabilityValues.get(key2);
1088
- if (value) {
1089
- callback(value);
1090
- }
1091
- });
1092
- ctx.mapViewabilityCallbacks.set(key2, callback);
1093
- useEffect(
1094
- () => () => {
1095
- ctx.mapViewabilityCallbacks.delete(key2);
1096
- },
1097
- []
1098
- );
1286
+ const useViewability2 = (configId, callback) => {
1287
+ useViewability(configId, callback);
1099
1288
  };
1100
- const useViewabilityAmount = (callback) => {
1101
- useInit(() => {
1102
- const value = ctx.mapViewabilityAmountValues.get(containerId);
1103
- if (value) {
1104
- callback(value);
1105
- }
1106
- });
1107
- ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
1108
- useEffect(
1109
- () => () => {
1110
- ctx.mapViewabilityAmountCallbacks.delete(containerId);
1111
- },
1112
- []
1113
- );
1289
+ const useViewabilityAmount2 = (callback) => {
1290
+ useViewabilityAmount(callback);
1114
1291
  };
1115
- const useRecyclingEffect = (effect) => {
1116
- useEffect(() => {
1117
- const state2 = refState.current;
1118
- let prevIndex = index;
1119
- let prevItem = state2.data[index];
1120
- const signal = `containerItemKey${containerId}`;
1121
- const run = () => {
1122
- const data3 = state2.data;
1123
- if (data3) {
1124
- const newKey = peek$(ctx, signal);
1125
- const newIndex = state2.indexByKey.get(newKey);
1126
- const newItem = data3[newIndex];
1127
- if (newItem) {
1128
- effect({
1129
- index: newIndex,
1130
- item: newItem,
1131
- prevIndex,
1132
- prevItem
1133
- });
1134
- }
1135
- prevIndex = newIndex;
1136
- prevItem = newItem;
1137
- }
1138
- };
1139
- run();
1140
- return listen$(ctx, signal, run);
1141
- }, []);
1292
+ const useRecyclingEffect2 = (effect) => {
1293
+ useRecyclingEffect(effect);
1142
1294
  };
1143
- const useRecyclingState = (valueOrFun) => {
1144
- const stateInfo = useState(
1145
- () => typeof valueOrFun === "function" ? valueOrFun({
1146
- index,
1147
- item: refState.current.data[index],
1148
- prevIndex: void 0,
1149
- prevItem: void 0
1150
- }) : valueOrFun
1151
- );
1152
- useRecyclingEffect((state2) => {
1153
- const newState = typeof valueOrFun === "function" ? valueOrFun(state2) : valueOrFun;
1154
- stateInfo[1](newState);
1155
- });
1156
- return stateInfo;
1295
+ const useRecyclingState2 = (valueOrFun) => {
1296
+ return useRecyclingState(valueOrFun);
1157
1297
  };
1158
1298
  const renderedItem = (_b2 = (_a2 = refState.current).renderItem) == null ? void 0 : _b2.call(_a2, {
1159
1299
  item: data2[index],
1160
1300
  index,
1161
- useViewability,
1162
- useViewabilityAmount,
1163
- useRecyclingEffect,
1164
- useRecyclingState
1301
+ useViewability: useViewability2,
1302
+ useViewabilityAmount: useViewabilityAmount2,
1303
+ useRecyclingEffect: useRecyclingEffect2,
1304
+ useRecyclingState: useRecyclingState2
1165
1305
  });
1166
- return renderedItem;
1306
+ return { index, renderedItem };
1167
1307
  }, []);
1168
1308
  useInit(() => {
1169
1309
  var _a2;
@@ -1175,7 +1315,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1175
1315
  const averageItemSize = (_a2 = estimatedItemSize != null ? estimatedItemSize : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(0, data[0])) != null ? _a2 : DEFAULT_ITEM_SIZE;
1176
1316
  const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) * numColumnsProp;
1177
1317
  for (let i = 0; i < numContainers; i++) {
1178
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1318
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1179
1319
  set$(ctx, `containerColumn${i}`, -1);
1180
1320
  }
1181
1321
  set$(ctx, "numContainers", numContainers);
@@ -1183,25 +1323,18 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1183
1323
  calculateItemsInView(state.scrollVelocity);
1184
1324
  });
1185
1325
  const updateItemSize = useCallback((containerId, itemKey, size) => {
1186
- var _a2;
1187
- const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
1326
+ const state = refState.current;
1327
+ const { sizes, indexByKey, columns, sizesLaidOut, data: data2 } = state;
1188
1328
  if (!data2) {
1189
1329
  return;
1190
1330
  }
1191
- const state = refState.current;
1192
- const { sizes, indexByKey, idsInFirstRender, columns, sizesLaidOut } = state;
1193
1331
  const index = indexByKey.get(itemKey);
1194
1332
  const numColumns = peek$(ctx, "numColumns");
1195
- const row = Math.floor(index / numColumns);
1196
- const prevSize = getRowHeight(row);
1197
- const measured = peek$(ctx, `containerDidLayout${containerId}`);
1198
- if (!measured) {
1199
- state.layoutsPending.add(containerId);
1200
- }
1333
+ state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, index) : index;
1334
+ const prevSize = getItemSize(itemKey, index, data2);
1201
1335
  if (!prevSize || Math.abs(prevSize - size) > 0.5) {
1202
1336
  let diff;
1203
1337
  if (numColumns > 1) {
1204
- const prevMaxSizeInRow = getRowHeight(row);
1205
1338
  sizes.set(itemKey, size);
1206
1339
  const column = columns.get(itemKey);
1207
1340
  const loopStart = index - (column - 1);
@@ -1211,7 +1344,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1211
1344
  const size2 = getItemSize(id, i, data2[i]);
1212
1345
  nextMaxSizeInRow = Math.max(nextMaxSizeInRow, size2);
1213
1346
  }
1214
- diff = nextMaxSizeInRow - prevMaxSizeInRow;
1347
+ diff = nextMaxSizeInRow - prevSize;
1215
1348
  } else {
1216
1349
  sizes.set(itemKey, size);
1217
1350
  diff = size - prevSize;
@@ -1239,11 +1372,14 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1239
1372
  addTotalSize(itemKey, diff, 0);
1240
1373
  doMaintainScrollAtEnd(true);
1241
1374
  const scrollVelocity = state.scrollVelocity;
1242
- if (!state.animFrameLayout && (Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1)) {
1243
- if (!peek$(ctx, `containerDidLayout${containerId}`)) {
1244
- state.animFrameLayout = requestAnimationFrame(() => {
1245
- state.animFrameLayout = null;
1246
- calculateItemsInView(state.scrollVelocity);
1375
+ if (!state.waitingForMicrotask && (Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1)) {
1376
+ if (!peek$(ctx, "containersDidLayout")) {
1377
+ state.waitingForMicrotask = true;
1378
+ queueMicrotask(() => {
1379
+ if (state.waitingForMicrotask) {
1380
+ state.waitingForMicrotask = false;
1381
+ calculateItemsInView(state.scrollVelocity);
1382
+ }
1247
1383
  });
1248
1384
  } else {
1249
1385
  calculateItemsInView(state.scrollVelocity);
@@ -1252,8 +1388,6 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1252
1388
  if (onItemSizeChanged) {
1253
1389
  onItemSizeChanged({ size, previous: prevSize, index, itemKey, itemData: data2[index] });
1254
1390
  }
1255
- } else {
1256
- set$(ctx, `containerDidLayout${containerId}`, true);
1257
1391
  }
1258
1392
  }, []);
1259
1393
  const handleScrollDebounced = useCallback((velocity) => {
@@ -1263,11 +1397,15 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1263
1397
  }, []);
1264
1398
  const onLayout = useCallback((event) => {
1265
1399
  const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
1400
+ const didChange = scrollLength !== refState.current.scrollLength;
1266
1401
  refState.current.scrollLength = scrollLength;
1267
1402
  doMaintainScrollAtEnd(false);
1268
1403
  doUpdatePaddingTop();
1269
1404
  checkAtBottom();
1270
1405
  checkAtTop();
1406
+ if (didChange) {
1407
+ calculateItemsInView(0);
1408
+ }
1271
1409
  if (__DEV__) {
1272
1410
  const isWidthZero = event.nativeEvent.layout.width === 0;
1273
1411
  const isHeightZero = event.nativeEvent.layout.height === 0;
@@ -1277,6 +1415,9 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1277
1415
  );
1278
1416
  }
1279
1417
  }
1418
+ if (onLayoutProp) {
1419
+ onLayoutProp(event);
1420
+ }
1280
1421
  }, []);
1281
1422
  const handleScroll = useCallback(
1282
1423
  (event, fromSelf) => {
@@ -1330,9 +1471,9 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1330
1471
  };
1331
1472
  return {
1332
1473
  getNativeScrollRef: () => refScroller.current,
1333
- getScrollableNode: refScroller.current.getScrollableNode,
1334
- getScrollResponder: refScroller.current.getScrollResponder,
1335
- flashScrollIndicators: refScroller.current.flashScrollIndicators,
1474
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
1475
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
1476
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
1336
1477
  scrollToIndex,
1337
1478
  scrollToOffset: ({ offset, animated }) => {
1338
1479
  const offsetObj = horizontal ? { x: offset, y: 0 } : { x: 0, y: offset };
@@ -1344,12 +1485,12 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1344
1485
  scrollToIndex({ index, animated });
1345
1486
  }
1346
1487
  },
1347
- scrollToEnd: refScroller.current.scrollToEnd
1488
+ scrollToEnd: () => refScroller.current.scrollToEnd()
1348
1489
  };
1349
1490
  },
1350
1491
  []
1351
1492
  );
1352
- return /* @__PURE__ */ React4.createElement(
1493
+ return /* @__PURE__ */ React5.createElement(
1353
1494
  ListComponent,
1354
1495
  {
1355
1496
  ...rest,
@@ -1374,9 +1515,10 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1374
1515
  ListEmptyComponent: data.length === 0 ? ListEmptyComponent : void 0,
1375
1516
  maintainVisibleContentPosition,
1376
1517
  scrollEventThrottle: scrollEventThrottle != null ? scrollEventThrottle : Platform.OS === "web" ? 16 : void 0,
1518
+ waitForInitialLayout,
1377
1519
  style
1378
1520
  }
1379
1521
  );
1380
1522
  });
1381
1523
 
1382
- export { LegendList };
1524
+ export { LegendList, useRecyclingEffect, useRecyclingState, useViewability, useViewabilityAmount };