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

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,21 @@ 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
- }
422
+ var useCombinedRef = (...refs) => {
423
+ const callback = useCallback((element) => {
424
+ for (const ref of refs) {
425
+ if (!ref) {
426
+ continue;
427
+ }
428
+ if (typeof ref === "function") {
429
+ ref(element);
430
+ } else {
431
+ ref.current = element;
432
+ }
433
+ }
434
+ }, refs);
435
+ return callback;
436
+ };
294
437
 
295
438
  // src/viewability.ts
296
439
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
@@ -441,13 +584,12 @@ function maybeUpdateViewabilityCallback(ctx, configId, viewToken) {
441
584
 
442
585
  // src/LegendList.tsx
443
586
  var DEFAULT_DRAW_DISTANCE = 250;
444
- var POSITION_OUT_OF_VIEW = -1e7;
445
587
  var DEFAULT_ITEM_SIZE = 100;
446
588
  var LegendList = forwardRef(function LegendList2(props, forwardedRef) {
447
- return /* @__PURE__ */ React4.createElement(StateProvider, null, /* @__PURE__ */ React4.createElement(LegendListInner, { ...props, ref: forwardedRef }));
589
+ return /* @__PURE__ */ React5.createElement(StateProvider, null, /* @__PURE__ */ React5.createElement(LegendListInner, { ...props, ref: forwardedRef }));
448
590
  });
449
591
  var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef) {
450
- var _a, _b, _c, _d;
592
+ var _a, _b, _c, _d, _e, _f, _g;
451
593
  const {
452
594
  data,
453
595
  initialScrollIndex,
@@ -467,17 +609,25 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
467
609
  renderItem,
468
610
  estimatedItemSize,
469
611
  getEstimatedItemSize,
470
- onEndReached,
471
- onStartReached,
472
612
  ListEmptyComponent,
473
613
  onItemSizeChanged,
474
614
  scrollEventThrottle,
475
615
  refScrollView,
616
+ waitForInitialLayout = true,
617
+ extraData,
618
+ onLayout: onLayoutProp,
476
619
  ...rest
477
620
  } = props;
478
621
  const { style, contentContainerStyle } = props;
622
+ const callbacks = useRef({
623
+ onStartReached: rest.onStartReached,
624
+ onEndReached: rest.onEndReached
625
+ });
626
+ callbacks.current.onStartReached = rest.onStartReached;
627
+ callbacks.current.onEndReached = rest.onEndReached;
479
628
  const ctx = useStateContext();
480
629
  const refScroller = useRef(null);
630
+ const combinedRef = useCombinedRef(refScroller, refScrollView);
481
631
  const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE;
482
632
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
483
633
  const refState = useRef();
@@ -522,7 +672,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
522
672
  positions: /* @__PURE__ */ new Map(),
523
673
  columns: /* @__PURE__ */ new Map(),
524
674
  pendingAdjust: 0,
525
- animFrameLayout: null,
675
+ waitingForMicrotask: false,
526
676
  isStartReached: initialContentOffset < initialScrollLength * onStartReachedThreshold,
527
677
  isEndReached: false,
528
678
  isAtBottom: false,
@@ -555,9 +705,9 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
555
705
  belowAnchorElementPositions: void 0,
556
706
  rowHeights: /* @__PURE__ */ new Map(),
557
707
  startReachedBlockedByTimer: false,
558
- layoutsPending: /* @__PURE__ */ new Set(),
559
708
  scrollForNextCalculateItemsInView: void 0,
560
- enableScrollForNextCalculateItemsInView: true
709
+ enableScrollForNextCalculateItemsInView: true,
710
+ minIndexSizeChanged: 0
561
711
  };
562
712
  refState.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
563
713
  if (maintainVisibleContentPosition) {
@@ -576,6 +726,8 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
576
726
  }
577
727
  }
578
728
  set$(ctx, "scrollAdjust", 0);
729
+ set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
730
+ set$(ctx, "extraData", extraData);
579
731
  }
580
732
  const getAnchorElementIndex = () => {
581
733
  const state = refState.current;
@@ -587,14 +739,14 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
587
739
  };
588
740
  const addTotalSize = useCallback((key, add, totalSizeBelowAnchor) => {
589
741
  const state = refState.current;
590
- const index = key === null ? 0 : state.indexByKey.get(key);
742
+ const { scrollLength, indexByKey, anchorElement } = state;
743
+ const index = key === null ? 0 : indexByKey.get(key);
591
744
  let isAboveAnchor = false;
592
745
  if (maintainVisibleContentPosition) {
593
- if (state.anchorElement && index < getAnchorElementIndex()) {
746
+ if (anchorElement && index < getAnchorElementIndex()) {
594
747
  isAboveAnchor = true;
595
748
  }
596
749
  }
597
- state.totalSize;
598
750
  if (key === null) {
599
751
  state.totalSize = add;
600
752
  state.totalSizeBelowAnchor = totalSizeBelowAnchor;
@@ -605,19 +757,19 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
605
757
  }
606
758
  }
607
759
  let applyAdjustValue = void 0;
760
+ const totalSize = state.totalSize;
761
+ let resultSize = totalSize;
608
762
  if (maintainVisibleContentPosition) {
609
- const newAdjust = state.anchorElement.coordinate - state.totalSizeBelowAnchor;
763
+ const newAdjust = anchorElement.coordinate - state.totalSizeBelowAnchor;
610
764
  applyAdjustValue = -newAdjust;
611
765
  state.belowAnchorElementPositions = buildElementPositionsBelowAnchor();
612
766
  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
- });
767
+ if (applyAdjustValue !== void 0) {
768
+ resultSize -= applyAdjustValue;
769
+ refState.current.scrollAdjustHandler.requestAdjust(applyAdjustValue, (diff) => {
770
+ state.scroll -= diff;
771
+ });
772
+ }
621
773
  }
622
774
  set$(ctx, "totalSize", resultSize);
623
775
  if (alignItemsAtEnd) {
@@ -684,12 +836,10 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
684
836
  startBufferedId: startBufferedIdOrig,
685
837
  positions,
686
838
  columns,
687
- scrollAdjustHandler,
688
- layoutsPending
839
+ scrollAdjustHandler
689
840
  } = state;
690
- if (state.animFrameLayout) {
691
- cancelAnimationFrame(state.animFrameLayout);
692
- state.animFrameLayout = null;
841
+ if (state.waitingForMicrotask) {
842
+ state.waitingForMicrotask = false;
693
843
  }
694
844
  if (!data2) {
695
845
  return;
@@ -697,7 +847,17 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
697
847
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
698
848
  const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
699
849
  const scrollExtra = Math.max(-16, Math.min(16, speed)) * 16;
700
- const scroll = scrollState - previousScrollAdjust - topPad - scrollExtra;
850
+ const scroll = scrollState - previousScrollAdjust - topPad;
851
+ let scrollBufferTop = scrollBuffer;
852
+ let scrollBufferBottom = scrollBuffer;
853
+ if (scrollExtra > 8) {
854
+ scrollBufferTop = 0;
855
+ scrollBufferBottom = scrollBuffer + scrollExtra;
856
+ }
857
+ if (scrollExtra < -8) {
858
+ scrollBufferTop = scrollBuffer - scrollExtra;
859
+ scrollBufferBottom = 0;
860
+ }
701
861
  if (state.scrollForNextCalculateItemsInView) {
702
862
  const { top: top2, bottom } = state.scrollForNextCalculateItemsInView;
703
863
  if (scroll > top2 && scroll < bottom) {
@@ -710,8 +870,11 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
710
870
  let startBufferedId = null;
711
871
  let endNoBuffer = null;
712
872
  let endBuffered = null;
713
- const originalStartId = startBufferedIdOrig && state.indexByKey.get(startBufferedIdOrig);
714
- let loopStart = originalStartId || 0;
873
+ let loopStart = startBufferedIdOrig ? state.indexByKey.get(startBufferedIdOrig) || 0 : 0;
874
+ if (state.minIndexSizeChanged !== void 0) {
875
+ loopStart = Math.min(state.minIndexSizeChanged, loopStart);
876
+ state.minIndexSizeChanged = void 0;
877
+ }
715
878
  const anchorElementIndex = getAnchorElementIndex();
716
879
  for (let i = loopStart; i >= 0; i--) {
717
880
  const id = getId(i);
@@ -769,7 +932,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
769
932
  if (startNoBuffer === null && top + size > scroll) {
770
933
  startNoBuffer = i;
771
934
  }
772
- if (startBuffered === null && top + size > scroll - scrollBuffer) {
935
+ if (startBuffered === null && top + size > scroll - scrollBufferTop) {
773
936
  startBuffered = i;
774
937
  startBufferedId = id;
775
938
  }
@@ -777,7 +940,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
777
940
  if (top <= scrollBottom) {
778
941
  endNoBuffer = i;
779
942
  }
780
- if (top <= scrollBottom + scrollBuffer) {
943
+ if (top <= scrollBottom + scrollBufferBottom) {
781
944
  endBuffered = i;
782
945
  } else {
783
946
  break;
@@ -797,9 +960,9 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
797
960
  endBuffered,
798
961
  endNoBuffer
799
962
  });
800
- const nextTop = Math.ceil(startBuffered ? positions.get(startBufferedId) + scrollBuffer : 0);
963
+ const nextTop = Math.ceil(startBuffered !== null ? positions.get(startBufferedId) + scrollBuffer : 0);
801
964
  const nextBottom = Math.floor(
802
- endBuffered ? (positions.get(getId(endBuffered + 1)) || 0) - scrollLength - scrollBuffer : 0
965
+ endBuffered !== null ? (positions.get(getId(endBuffered + 1)) || 0) - scrollLength - scrollBuffer : 0
803
966
  );
804
967
  if (state.enableScrollForNextCalculateItemsInView) {
805
968
  state.scrollForNextCalculateItemsInView = nextTop >= 0 && nextBottom >= 0 ? {
@@ -831,7 +994,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
831
994
  break;
832
995
  }
833
996
  const index = state.indexByKey.get(key);
834
- const pos = peek$(ctx, `containerPosition${u}`);
997
+ const pos = peek$(ctx, `containerPosition${u}`).top;
835
998
  if (index < startBuffered || index > endBuffered) {
836
999
  const distance = Math.abs(pos - top2);
837
1000
  if (index < 0 || distance > furthestDistance) {
@@ -850,7 +1013,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
850
1013
  set$(ctx, `containerItemKey${containerId}`, id);
851
1014
  const index = state.indexByKey.get(id);
852
1015
  set$(ctx, `containerItemData${containerId}`, data2[index]);
853
- set$(ctx, `containerPosition${containerId}`, POSITION_OUT_OF_VIEW);
1016
+ set$(ctx, `containerPosition${containerId}`, ANCHORED_POSITION_OUT_OF_VIEW);
854
1017
  set$(ctx, `containerColumn${containerId}`, -1);
855
1018
  if (__DEV__ && numContainers > peek$(ctx, "numContainersPooled")) {
856
1019
  console.warn(
@@ -874,19 +1037,31 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
874
1037
  if (item) {
875
1038
  const id = getId(itemIndex);
876
1039
  if (itemKey !== id || itemIndex < startBuffered || itemIndex > endBuffered) {
877
- const prevPos = peek$(ctx, `containerPosition${i}`);
1040
+ const prevPos = peek$(ctx, `containerPosition${i}`).top;
878
1041
  const pos = positions.get(id) || 0;
879
1042
  const size = getItemSize(id, itemIndex, data2[i]);
880
1043
  if (pos + size >= scroll && pos <= scrollBottom || prevPos + size >= scroll && prevPos <= scrollBottom) {
881
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1044
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
882
1045
  }
883
1046
  } else {
884
- const pos = positions.get(id) || 0;
1047
+ const pos = {
1048
+ type: "top",
1049
+ relativeCoordinate: positions.get(id) || 0,
1050
+ top: positions.get(id) || 0
1051
+ };
885
1052
  const column2 = columns.get(id) || 1;
1053
+ if (maintainVisibleContentPosition && itemIndex < anchorElementIndex) {
1054
+ const currentRow = Math.floor(itemIndex / numColumnsProp);
1055
+ const rowHeight = getRowHeight(currentRow);
1056
+ const elementHeight = getItemSize(id, itemIndex, data2[i]);
1057
+ const diff = rowHeight - elementHeight;
1058
+ pos.relativeCoordinate = pos.top + getRowHeight(currentRow) - diff;
1059
+ pos.type = "bottom";
1060
+ }
886
1061
  const prevPos = peek$(ctx, `containerPosition${i}`);
887
1062
  const prevColumn = peek$(ctx, `containerColumn${i}`);
888
1063
  const prevData = peek$(ctx, `containerItemData${i}`);
889
- if (pos > POSITION_OUT_OF_VIEW && pos !== prevPos) {
1064
+ if (pos.relativeCoordinate > POSITION_OUT_OF_VIEW && pos.top !== prevPos.top) {
890
1065
  set$(ctx, `containerPosition${i}`, pos);
891
1066
  }
892
1067
  if (column2 >= 0 && column2 !== prevColumn) {
@@ -899,12 +1074,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
899
1074
  }
900
1075
  }
901
1076
  }
902
- if (layoutsPending.size > 0) {
903
- for (const containerId of layoutsPending) {
904
- set$(ctx, `containerDidLayout${containerId}`, true);
905
- }
906
- layoutsPending.clear();
907
- }
1077
+ set$(ctx, "containersDidLayout", true);
908
1078
  if (state.viewabilityConfigCallbackPairs) {
909
1079
  updateViewableItems(
910
1080
  state,
@@ -948,6 +1118,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
948
1118
  if (refState.current) {
949
1119
  refState.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
950
1120
  }
1121
+ const { onEndReached } = callbacks.current;
951
1122
  if (onEndReached) {
952
1123
  if (!refState.current.isEndReached) {
953
1124
  if (distanceFromEnd < onEndReachedThreshold * scrollLength) {
@@ -969,6 +1140,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
969
1140
  const { scrollLength, scroll } = refState.current;
970
1141
  const distanceFromTop = scroll;
971
1142
  refState.current.isAtTop = distanceFromTop < 0;
1143
+ const { onStartReached } = callbacks.current;
972
1144
  if (onStartReached) {
973
1145
  if (!refState.current.isStartReached && !refState.current.startReachedBlockedByTimer) {
974
1146
  if (distanceFromTop < onStartReachedThreshold * scrollLength) {
@@ -997,13 +1169,13 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
997
1169
  const itemKey = peek$(ctx, `containerItemKey${i}`);
998
1170
  if (!keyExtractorProp || itemKey && state.indexByKey.get(itemKey) === void 0) {
999
1171
  set$(ctx, `containerItemKey${i}`, void 0);
1000
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1172
+ set$(ctx, `containerItemData${i}`, void 0);
1173
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1001
1174
  set$(ctx, `containerColumn${i}`, -1);
1002
1175
  }
1003
1176
  }
1004
1177
  if (!keyExtractorProp) {
1005
- state.sizes.clear();
1006
- state.positions;
1178
+ state.positions.clear();
1007
1179
  }
1008
1180
  calculateItemsInView(state.scrollVelocity);
1009
1181
  }
@@ -1018,20 +1190,63 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1018
1190
  const isFirst = !refState.current.renderItem;
1019
1191
  if (isFirst || data !== refState.current.data || numColumnsProp !== peek$(ctx, "numColumns")) {
1020
1192
  if (!keyExtractorProp && !isFirst && data !== refState.current.data) {
1021
- refState.current.sizes.clear();
1022
1193
  refState.current.positions.clear();
1023
1194
  }
1024
1195
  refState.current.data = data;
1025
1196
  let totalSize = 0;
1026
1197
  let totalSizeBelowIndex = 0;
1027
1198
  const indexByKey = /* @__PURE__ */ new Map();
1199
+ const newPositions = /* @__PURE__ */ new Map();
1028
1200
  let column = 1;
1029
1201
  let maxSizeInRow = 0;
1030
1202
  for (let i = 0; i < data.length; i++) {
1031
1203
  const key = getId(i);
1204
+ if (__DEV__) {
1205
+ if (indexByKey.has(key)) {
1206
+ console.error(
1207
+ `[legend-list] Error: Detected overlapping key (${key}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`
1208
+ );
1209
+ }
1210
+ }
1032
1211
  indexByKey.set(key, i);
1212
+ if (refState.current.positions.get(key) != null && refState.current.indexByKey.get(key) === i) {
1213
+ newPositions.set(key, refState.current.positions.get(key));
1214
+ }
1033
1215
  }
1034
1216
  refState.current.indexByKey = indexByKey;
1217
+ refState.current.positions = newPositions;
1218
+ if (!isFirst) {
1219
+ if (maintainVisibleContentPosition) {
1220
+ if (refState.current.anchorElement == null || indexByKey.get(refState.current.anchorElement.id) == null) {
1221
+ if (data.length) {
1222
+ const newAnchorElement = {
1223
+ coordinate: 0,
1224
+ id: getId(0)
1225
+ };
1226
+ refState.current.anchorElement = newAnchorElement;
1227
+ (_a = refState.current.belowAnchorElementPositions) == null ? void 0 : _a.clear();
1228
+ (_b = refScroller.current) == null ? void 0 : _b.scrollTo({ x: 0, y: 0, animated: false });
1229
+ setTimeout(() => {
1230
+ calculateItemsInView(0);
1231
+ }, 0);
1232
+ } else {
1233
+ refState.current.startBufferedId = void 0;
1234
+ }
1235
+ }
1236
+ } else {
1237
+ if (refState.current.startBufferedId != null && newPositions.get(refState.current.startBufferedId) == null) {
1238
+ if (data.length) {
1239
+ refState.current.startBufferedId = getId(0);
1240
+ } else {
1241
+ refState.current.startBufferedId = void 0;
1242
+ }
1243
+ (_c = refScroller.current) == null ? void 0 : _c.scrollTo({ x: 0, y: 0, animated: false });
1244
+ setTimeout(() => {
1245
+ calculateItemsInView(0);
1246
+ }, 0);
1247
+ }
1248
+ }
1249
+ }
1035
1250
  const anchorElementIndex = getAnchorElementIndex();
1036
1251
  for (let i = 0; i < data.length; i++) {
1037
1252
  const key = getId(i);
@@ -1058,9 +1273,12 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1058
1273
  !isFirst
1059
1274
  );
1060
1275
  }, [isFirst, data, numColumnsProp]);
1276
+ useEffect(() => {
1277
+ set$(ctx, "extraData", extraData);
1278
+ }, [extraData]);
1061
1279
  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;
1280
+ const lastItemKey = data.length > 0 ? getId(data.length - 1) : void 0;
1281
+ 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
1282
  const initalizeStateVars = () => {
1065
1283
  set$(ctx, "lastItemKey", lastItemKey);
1066
1284
  set$(ctx, "numColumns", numColumnsProp);
@@ -1070,7 +1288,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1070
1288
  initalizeStateVars();
1071
1289
  }
1072
1290
  useEffect(initalizeStateVars, [lastItemKey, numColumnsProp, stylePaddingTop]);
1073
- const getRenderedItem = useCallback((key, containerId) => {
1291
+ const getRenderedItem = useCallback((key) => {
1074
1292
  var _a2, _b2;
1075
1293
  const state = refState.current;
1076
1294
  if (!state) {
@@ -1081,89 +1299,27 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1081
1299
  if (index === void 0) {
1082
1300
  return null;
1083
1301
  }
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
- );
1302
+ const useViewability2 = (configId, callback) => {
1303
+ useViewability(configId, callback);
1099
1304
  };
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
- );
1305
+ const useViewabilityAmount2 = (callback) => {
1306
+ useViewabilityAmount(callback);
1114
1307
  };
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
- }, []);
1308
+ const useRecyclingEffect2 = (effect) => {
1309
+ useRecyclingEffect(effect);
1142
1310
  };
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;
1311
+ const useRecyclingState2 = (valueOrFun) => {
1312
+ return useRecyclingState(valueOrFun);
1157
1313
  };
1158
1314
  const renderedItem = (_b2 = (_a2 = refState.current).renderItem) == null ? void 0 : _b2.call(_a2, {
1159
1315
  item: data2[index],
1160
1316
  index,
1161
- useViewability,
1162
- useViewabilityAmount,
1163
- useRecyclingEffect,
1164
- useRecyclingState
1317
+ useViewability: useViewability2,
1318
+ useViewabilityAmount: useViewabilityAmount2,
1319
+ useRecyclingEffect: useRecyclingEffect2,
1320
+ useRecyclingState: useRecyclingState2
1165
1321
  });
1166
- return renderedItem;
1322
+ return { index, renderedItem };
1167
1323
  }, []);
1168
1324
  useInit(() => {
1169
1325
  var _a2;
@@ -1175,7 +1331,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1175
1331
  const averageItemSize = (_a2 = estimatedItemSize != null ? estimatedItemSize : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(0, data[0])) != null ? _a2 : DEFAULT_ITEM_SIZE;
1176
1332
  const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) * numColumnsProp;
1177
1333
  for (let i = 0; i < numContainers; i++) {
1178
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1334
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1179
1335
  set$(ctx, `containerColumn${i}`, -1);
1180
1336
  }
1181
1337
  set$(ctx, "numContainers", numContainers);
@@ -1183,25 +1339,18 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1183
1339
  calculateItemsInView(state.scrollVelocity);
1184
1340
  });
1185
1341
  const updateItemSize = useCallback((containerId, itemKey, size) => {
1186
- var _a2;
1187
- const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
1342
+ const state = refState.current;
1343
+ const { sizes, indexByKey, columns, sizesLaidOut, data: data2 } = state;
1188
1344
  if (!data2) {
1189
1345
  return;
1190
1346
  }
1191
- const state = refState.current;
1192
- const { sizes, indexByKey, idsInFirstRender, columns, sizesLaidOut } = state;
1193
1347
  const index = indexByKey.get(itemKey);
1194
1348
  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
- }
1349
+ state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, index) : index;
1350
+ const prevSize = getItemSize(itemKey, index, data2);
1201
1351
  if (!prevSize || Math.abs(prevSize - size) > 0.5) {
1202
1352
  let diff;
1203
1353
  if (numColumns > 1) {
1204
- const prevMaxSizeInRow = getRowHeight(row);
1205
1354
  sizes.set(itemKey, size);
1206
1355
  const column = columns.get(itemKey);
1207
1356
  const loopStart = index - (column - 1);
@@ -1211,7 +1360,7 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1211
1360
  const size2 = getItemSize(id, i, data2[i]);
1212
1361
  nextMaxSizeInRow = Math.max(nextMaxSizeInRow, size2);
1213
1362
  }
1214
- diff = nextMaxSizeInRow - prevMaxSizeInRow;
1363
+ diff = nextMaxSizeInRow - prevSize;
1215
1364
  } else {
1216
1365
  sizes.set(itemKey, size);
1217
1366
  diff = size - prevSize;
@@ -1239,11 +1388,14 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1239
1388
  addTotalSize(itemKey, diff, 0);
1240
1389
  doMaintainScrollAtEnd(true);
1241
1390
  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);
1391
+ if (!state.waitingForMicrotask && (Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1)) {
1392
+ if (!peek$(ctx, "containersDidLayout")) {
1393
+ state.waitingForMicrotask = true;
1394
+ queueMicrotask(() => {
1395
+ if (state.waitingForMicrotask) {
1396
+ state.waitingForMicrotask = false;
1397
+ calculateItemsInView(state.scrollVelocity);
1398
+ }
1247
1399
  });
1248
1400
  } else {
1249
1401
  calculateItemsInView(state.scrollVelocity);
@@ -1252,8 +1404,6 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1252
1404
  if (onItemSizeChanged) {
1253
1405
  onItemSizeChanged({ size, previous: prevSize, index, itemKey, itemData: data2[index] });
1254
1406
  }
1255
- } else {
1256
- set$(ctx, `containerDidLayout${containerId}`, true);
1257
1407
  }
1258
1408
  }, []);
1259
1409
  const handleScrollDebounced = useCallback((velocity) => {
@@ -1263,11 +1413,15 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1263
1413
  }, []);
1264
1414
  const onLayout = useCallback((event) => {
1265
1415
  const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
1416
+ const didChange = scrollLength !== refState.current.scrollLength;
1266
1417
  refState.current.scrollLength = scrollLength;
1267
1418
  doMaintainScrollAtEnd(false);
1268
1419
  doUpdatePaddingTop();
1269
1420
  checkAtBottom();
1270
1421
  checkAtTop();
1422
+ if (didChange) {
1423
+ calculateItemsInView(0);
1424
+ }
1271
1425
  if (__DEV__) {
1272
1426
  const isWidthZero = event.nativeEvent.layout.width === 0;
1273
1427
  const isHeightZero = event.nativeEvent.layout.height === 0;
@@ -1277,6 +1431,9 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1277
1431
  );
1278
1432
  }
1279
1433
  }
1434
+ if (onLayoutProp) {
1435
+ onLayoutProp(event);
1436
+ }
1280
1437
  }, []);
1281
1438
  const handleScroll = useCallback(
1282
1439
  (event, fromSelf) => {
@@ -1330,9 +1487,9 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1330
1487
  };
1331
1488
  return {
1332
1489
  getNativeScrollRef: () => refScroller.current,
1333
- getScrollableNode: refScroller.current.getScrollableNode,
1334
- getScrollResponder: refScroller.current.getScrollResponder,
1335
- flashScrollIndicators: refScroller.current.flashScrollIndicators,
1490
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
1491
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
1492
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
1336
1493
  scrollToIndex,
1337
1494
  scrollToOffset: ({ offset, animated }) => {
1338
1495
  const offsetObj = horizontal ? { x: offset, y: 0 } : { x: 0, y: offset };
@@ -1344,26 +1501,17 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1344
1501
  scrollToIndex({ index, animated });
1345
1502
  }
1346
1503
  },
1347
- scrollToEnd: refScroller.current.scrollToEnd
1504
+ scrollToEnd: () => refScroller.current.scrollToEnd()
1348
1505
  };
1349
1506
  },
1350
1507
  []
1351
1508
  );
1352
- return /* @__PURE__ */ React4.createElement(
1509
+ return /* @__PURE__ */ React5.createElement(
1353
1510
  ListComponent,
1354
1511
  {
1355
1512
  ...rest,
1356
1513
  horizontal,
1357
- refScrollView: (r) => {
1358
- refScroller.current = r;
1359
- if (refScrollView) {
1360
- if (typeof refScrollView === "function") {
1361
- refScrollView(r);
1362
- } else {
1363
- refScrollView.current = r;
1364
- }
1365
- }
1366
- },
1514
+ refScrollView: combinedRef,
1367
1515
  initialContentOffset,
1368
1516
  getRenderedItem,
1369
1517
  updateItemSize,
@@ -1374,9 +1522,10 @@ var LegendListInner = forwardRef(function LegendListInner2(props, forwardedRef)
1374
1522
  ListEmptyComponent: data.length === 0 ? ListEmptyComponent : void 0,
1375
1523
  maintainVisibleContentPosition,
1376
1524
  scrollEventThrottle: scrollEventThrottle != null ? scrollEventThrottle : Platform.OS === "web" ? 16 : void 0,
1525
+ waitForInitialLayout,
1377
1526
  style
1378
1527
  }
1379
1528
  );
1380
1529
  });
1381
1530
 
1382
- export { LegendList };
1531
+ export { LegendList, useRecyclingEffect, useRecyclingState, useViewability, useViewabilityAmount };