@legendapp/list 1.0.0-beta.2 → 1.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var React4 = require('react');
3
+ var React5 = require('react');
4
4
  var reactNative = require('react-native');
5
5
 
6
6
  function _interopNamespace(e) {
@@ -21,12 +21,12 @@ function _interopNamespace(e) {
21
21
  return Object.freeze(n);
22
22
  }
23
23
 
24
- var React4__namespace = /*#__PURE__*/_interopNamespace(React4);
24
+ var React5__namespace = /*#__PURE__*/_interopNamespace(React5);
25
25
 
26
26
  // src/LegendList.tsx
27
- var ContextState = React4__namespace.createContext(null);
27
+ var ContextState = React5__namespace.createContext(null);
28
28
  function StateProvider({ children }) {
29
- const [value] = React4__namespace.useState(() => ({
29
+ const [value] = React5__namespace.useState(() => ({
30
30
  listeners: /* @__PURE__ */ new Map(),
31
31
  values: /* @__PURE__ */ new Map(),
32
32
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
@@ -34,10 +34,10 @@ function StateProvider({ children }) {
34
34
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
35
35
  mapViewabilityAmountValues: /* @__PURE__ */ new Map()
36
36
  }));
37
- return /* @__PURE__ */ React4__namespace.createElement(ContextState.Provider, { value }, children);
37
+ return /* @__PURE__ */ React5__namespace.createElement(ContextState.Provider, { value }, children);
38
38
  }
39
39
  function useStateContext() {
40
- return React4__namespace.useContext(ContextState);
40
+ return React5__namespace.useContext(ContextState);
41
41
  }
42
42
  function createSelectorFunctions(ctx, signalName) {
43
43
  return {
@@ -46,9 +46,9 @@ function createSelectorFunctions(ctx, signalName) {
46
46
  };
47
47
  }
48
48
  function use$(signalName) {
49
- const ctx = React4__namespace.useContext(ContextState);
50
- const { subscribe, get } = React4__namespace.useMemo(() => createSelectorFunctions(ctx, signalName), []);
51
- const value = React4.useSyncExternalStore(subscribe, get);
49
+ const ctx = React5__namespace.useContext(ContextState);
50
+ const { subscribe, get } = React5__namespace.useMemo(() => createSelectorFunctions(ctx, signalName), []);
51
+ const value = React5.useSyncExternalStore(subscribe, get);
52
52
  return value;
53
53
  }
54
54
  function listen$(ctx, signalName, cb) {
@@ -77,76 +77,195 @@ function set$(ctx, signalName, value) {
77
77
  }
78
78
  }
79
79
  }
80
+ var symbolFirst = Symbol();
81
+ function useInit(cb) {
82
+ const refValue = React5.useRef(symbolFirst);
83
+ if (refValue.current === symbolFirst) {
84
+ refValue.current = cb();
85
+ }
86
+ return refValue.current;
87
+ }
88
+
89
+ // src/ContextContainer.ts
90
+ var ContextContainer = React5.createContext(null);
91
+ function useViewability(configId, callback) {
92
+ const ctx = useStateContext();
93
+ const { containerId } = React5.useContext(ContextContainer);
94
+ const key = containerId + configId;
95
+ useInit(() => {
96
+ const value = ctx.mapViewabilityValues.get(key);
97
+ if (value) {
98
+ callback(value);
99
+ }
100
+ });
101
+ ctx.mapViewabilityCallbacks.set(key, callback);
102
+ React5.useEffect(
103
+ () => () => {
104
+ ctx.mapViewabilityCallbacks.delete(key);
105
+ },
106
+ []
107
+ );
108
+ }
109
+ function useViewabilityAmount(callback) {
110
+ const ctx = useStateContext();
111
+ const { containerId } = React5.useContext(ContextContainer);
112
+ useInit(() => {
113
+ const value = ctx.mapViewabilityAmountValues.get(containerId);
114
+ if (value) {
115
+ callback(value);
116
+ }
117
+ });
118
+ ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
119
+ React5.useEffect(
120
+ () => () => {
121
+ ctx.mapViewabilityAmountCallbacks.delete(containerId);
122
+ },
123
+ []
124
+ );
125
+ }
126
+ function useRecyclingEffect(effect) {
127
+ const { index, value } = React5.useContext(ContextContainer);
128
+ const prevValues = React5.useRef({
129
+ prevIndex: void 0,
130
+ prevItem: void 0
131
+ });
132
+ React5.useEffect(() => {
133
+ let ret = void 0;
134
+ if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
135
+ ret = effect({
136
+ index,
137
+ item: value,
138
+ prevIndex: prevValues.current.prevIndex,
139
+ prevItem: prevValues.current.prevItem
140
+ });
141
+ }
142
+ prevValues.current = {
143
+ prevIndex: index,
144
+ prevItem: value
145
+ };
146
+ return ret;
147
+ }, [index, value]);
148
+ }
149
+ function useRecyclingState(valueOrFun) {
150
+ const { index, value } = React5.useContext(ContextContainer);
151
+ const stateInfo = React5.useState(
152
+ () => typeof valueOrFun === "function" ? valueOrFun({
153
+ index,
154
+ item: value,
155
+ prevIndex: void 0,
156
+ prevItem: void 0
157
+ }) : valueOrFun
158
+ );
159
+ useRecyclingEffect((state) => {
160
+ const newState = typeof valueOrFun === "function" ? valueOrFun(state) : valueOrFun;
161
+ stateInfo[1](newState);
162
+ });
163
+ return stateInfo;
164
+ }
165
+ var LeanView = React5__namespace.forwardRef((props, ref) => {
166
+ return React5__namespace.createElement("RCTView", { ...props, ref });
167
+ });
168
+ LeanView.displayName = "RCTView";
169
+
170
+ // src/constants.ts
171
+ var POSITION_OUT_OF_VIEW = -1e7;
172
+ var ANCHORED_POSITION_OUT_OF_VIEW = {
173
+ type: "top",
174
+ relativeCoordinate: POSITION_OUT_OF_VIEW,
175
+ top: POSITION_OUT_OF_VIEW
176
+ };
80
177
 
81
178
  // src/Container.tsx
179
+ var isNewArchitecture = global.nativeFabricUIManager != null;
82
180
  var Container = ({
83
181
  id,
84
182
  recycleItems,
85
183
  horizontal,
86
- waitForInitialLayout,
87
184
  getRenderedItem,
88
185
  updateItemSize,
89
186
  ItemSeparatorComponent
90
187
  }) => {
91
- const ctx = useStateContext();
92
- const position = use$(`containerPosition${id}`);
188
+ useStateContext();
189
+ const maintainVisibleContentPosition = use$("maintainVisibleContentPosition");
190
+ const position = use$(`containerPosition${id}`) || ANCHORED_POSITION_OUT_OF_VIEW;
93
191
  const column = use$(`containerColumn${id}`) || 0;
94
192
  const numColumns = use$("numColumns");
95
193
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
96
194
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
97
195
  const style = horizontal ? {
98
- flexDirection: "row",
196
+ flexDirection: ItemSeparatorComponent ? "row" : void 0,
99
197
  position: "absolute",
100
198
  top: otherAxisPos,
101
199
  bottom: numColumns > 1 ? null : 0,
102
200
  height: otherAxisSize,
103
- left: position
201
+ left: position.relativeCoordinate
104
202
  } : {
105
203
  position: "absolute",
106
204
  left: otherAxisPos,
107
205
  right: numColumns > 1 ? null : 0,
108
206
  width: otherAxisSize,
109
- top: position
207
+ top: position.relativeCoordinate
110
208
  };
111
- if (waitForInitialLayout) {
112
- const visible = use$(`containerDidLayout${id}`);
113
- style.opacity = visible ? 1 : 0;
114
- }
115
209
  const lastItemKey = use$("lastItemKey");
116
210
  const itemKey = use$(`containerItemKey${id}`);
117
211
  const data = use$(`containerItemData${id}`);
118
212
  const extraData = use$("extraData");
119
- const renderedItem = React4.useMemo(() => itemKey !== void 0 && getRenderedItem(itemKey, id), [itemKey, data, extraData]);
120
- return /* @__PURE__ */ React4__namespace.default.createElement(
121
- reactNative.View,
122
- {
123
- style,
124
- onLayout: (event) => {
125
- const key = peek$(ctx, `containerItemKey${id}`);
126
- if (key !== void 0) {
127
- const size = Math.floor(event.nativeEvent.layout[horizontal ? "width" : "height"] * 8) / 8;
128
- updateItemSize(id, key, size);
213
+ const renderedItemInfo = React5.useMemo(
214
+ () => itemKey !== void 0 && getRenderedItem(itemKey),
215
+ [itemKey, data, extraData]
216
+ );
217
+ const { index, renderedItem } = renderedItemInfo || {};
218
+ const onLayout = (event) => {
219
+ if (itemKey !== void 0) {
220
+ const size = Math.floor(event.nativeEvent.layout[horizontal ? "width" : "height"] * 8) / 8;
221
+ if (size === 0) {
222
+ console.log("[WARN] Container 0 height reported, possible bug in LegendList", id, itemKey);
223
+ return;
224
+ }
225
+ updateItemSize(id, itemKey, size);
226
+ }
227
+ };
228
+ const ref = React5.useRef(null);
229
+ if (isNewArchitecture) {
230
+ React5.useLayoutEffect(() => {
231
+ var _a, _b;
232
+ if (itemKey) {
233
+ const measured = (_b = (_a = ref.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
234
+ if (measured) {
235
+ const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
236
+ if (size) {
237
+ updateItemSize(id, itemKey, size);
238
+ }
129
239
  }
130
240
  }
131
- },
132
- /* @__PURE__ */ React4__namespace.default.createElement(React4__namespace.default.Fragment, { key: recycleItems ? void 0 : itemKey }, renderedItem, renderedItem && ItemSeparatorComponent && itemKey !== lastItemKey && ItemSeparatorComponent)
241
+ }, [itemKey]);
242
+ }
243
+ const contextValue = React5.useMemo(
244
+ () => ({ containerId: id, itemKey, index, value: data }),
245
+ [id, itemKey, index, data]
133
246
  );
247
+ const contentFragment = /* @__PURE__ */ React5__namespace.default.createElement(React5__namespace.default.Fragment, { key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React5__namespace.default.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItem && ItemSeparatorComponent && itemKey !== lastItemKey && ItemSeparatorComponent));
248
+ if (maintainVisibleContentPosition) {
249
+ const anchorStyle = position.type === "top" ? { position: "absolute", top: 0, left: 0, right: 0 } : { position: "absolute", bottom: 0, left: 0, right: 0 };
250
+ return /* @__PURE__ */ React5__namespace.default.createElement(LeanView, { style }, /* @__PURE__ */ React5__namespace.default.createElement(LeanView, { style: anchorStyle, onLayout, ref }, contentFragment));
251
+ }
252
+ return /* @__PURE__ */ React5__namespace.default.createElement(LeanView, { style, onLayout, ref }, contentFragment);
134
253
  };
135
254
  var useAnimatedValue = reactNative.useAnimatedValue || ((initialValue) => {
136
- return React4.useRef(new reactNative.Animated.Value(initialValue)).current;
255
+ return React5.useRef(new reactNative.Animated.Value(initialValue)).current;
137
256
  });
138
257
  function useValue$(key, getValue, key2) {
139
258
  var _a;
140
259
  const ctx = useStateContext();
141
- const animValue = useAnimatedValue((_a = peek$(ctx, key)) != null ? _a : 0);
142
- React4.useMemo(() => {
143
- listen$(ctx, key, (v) => animValue.setValue(v));
260
+ const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
261
+ React5.useMemo(() => {
262
+ listen$(ctx, key, (v) => animValue.setValue(getValue ? getValue(v) : v));
144
263
  }, []);
145
264
  return animValue;
146
265
  }
147
266
 
148
267
  // src/Containers.tsx
149
- var Containers = React4__namespace.memo(function Containers2({
268
+ var Containers = React5__namespace.memo(function Containers2({
150
269
  horizontal,
151
270
  recycleItems,
152
271
  ItemSeparatorComponent,
@@ -156,17 +275,17 @@ var Containers = React4__namespace.memo(function Containers2({
156
275
  }) {
157
276
  const numContainers = use$("numContainersPooled");
158
277
  const animSize = useValue$("totalSize");
278
+ const animOpacity = waitForInitialLayout ? useValue$("containersDidLayout", (value) => value ? 1 : 0) : void 0;
159
279
  const containers = [];
160
280
  for (let i = 0; i < numContainers; i++) {
161
281
  containers.push(
162
- /* @__PURE__ */ React4__namespace.createElement(
282
+ /* @__PURE__ */ React5__namespace.createElement(
163
283
  Container,
164
284
  {
165
285
  id: i,
166
286
  key: i,
167
287
  recycleItems,
168
288
  horizontal,
169
- waitForInitialLayout,
170
289
  getRenderedItem,
171
290
  updateItemSize,
172
291
  ItemSeparatorComponent
@@ -174,21 +293,21 @@ var Containers = React4__namespace.memo(function Containers2({
174
293
  )
175
294
  );
176
295
  }
177
- const style = horizontal ? { width: animSize } : { height: animSize };
178
- return /* @__PURE__ */ React4__namespace.createElement(reactNative.Animated.View, { style }, containers);
296
+ const style = horizontal ? { width: animSize, opacity: animOpacity } : { height: animSize, opacity: animOpacity };
297
+ return /* @__PURE__ */ React5__namespace.createElement(reactNative.Animated.View, { style }, containers);
179
298
  });
180
299
 
181
300
  // src/ListComponent.tsx
182
301
  var getComponent = (Component) => {
183
- if (React4__namespace.isValidElement(Component)) {
302
+ if (React5__namespace.isValidElement(Component)) {
184
303
  return Component;
185
304
  }
186
305
  if (Component) {
187
- return /* @__PURE__ */ React4__namespace.createElement(Component, null);
306
+ return /* @__PURE__ */ React5__namespace.createElement(Component, null);
188
307
  }
189
308
  return null;
190
309
  };
191
- var ListComponent = React4__namespace.memo(function ListComponent2({
310
+ var ListComponent = React5__namespace.memo(function ListComponent2({
192
311
  style,
193
312
  contentContainerStyle,
194
313
  horizontal,
@@ -204,7 +323,6 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
204
323
  ListFooterComponent,
205
324
  ListFooterComponentStyle,
206
325
  ListEmptyComponent,
207
- ListEmptyComponentStyle,
208
326
  getRenderedItem,
209
327
  updateItemSize,
210
328
  refScrollView,
@@ -215,12 +333,12 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
215
333
  const ctx = useStateContext();
216
334
  const animPaddingTop = useValue$("paddingTop");
217
335
  const animScrollAdjust = useValue$("scrollAdjust");
218
- const ScrollComponent = renderScrollComponent ? React4.useMemo(
219
- () => React4__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
336
+ const ScrollComponent = renderScrollComponent ? React5.useMemo(
337
+ () => React5__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
220
338
  [renderScrollComponent]
221
339
  ) : reactNative.ScrollView;
222
340
  const additionalSize = { marginTop: animScrollAdjust, paddingTop: animPaddingTop };
223
- return /* @__PURE__ */ React4__namespace.createElement(
341
+ return /* @__PURE__ */ React5__namespace.createElement(
224
342
  ScrollComponent,
225
343
  {
226
344
  ...rest,
@@ -238,8 +356,8 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
238
356
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
239
357
  ref: refScrollView
240
358
  },
241
- /* @__PURE__ */ React4__namespace.createElement(reactNative.Animated.View, { style: additionalSize }),
242
- ListHeaderComponent && /* @__PURE__ */ React4__namespace.createElement(
359
+ /* @__PURE__ */ React5__namespace.createElement(reactNative.Animated.View, { style: additionalSize }),
360
+ ListHeaderComponent && /* @__PURE__ */ React5__namespace.createElement(
243
361
  reactNative.Animated.View,
244
362
  {
245
363
  style: ListHeaderComponentStyle,
@@ -253,8 +371,8 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
253
371
  },
254
372
  getComponent(ListHeaderComponent)
255
373
  ),
256
- ListEmptyComponent && /* @__PURE__ */ React4__namespace.createElement(reactNative.Animated.View, { style: ListEmptyComponentStyle }, getComponent(ListEmptyComponent)),
257
- /* @__PURE__ */ React4__namespace.createElement(
374
+ ListEmptyComponent && getComponent(ListEmptyComponent),
375
+ /* @__PURE__ */ React5__namespace.createElement(
258
376
  Containers,
259
377
  {
260
378
  horizontal,
@@ -265,7 +383,7 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
265
383
  updateItemSize
266
384
  }
267
385
  ),
268
- ListFooterComponent && /* @__PURE__ */ React4__namespace.createElement(reactNative.View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
386
+ ListFooterComponent && /* @__PURE__ */ React5__namespace.createElement(reactNative.View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
269
387
  );
270
388
  });
271
389
 
@@ -305,14 +423,6 @@ var ScrollAdjustHandler = class {
305
423
  return this.appliedAdjust;
306
424
  }
307
425
  };
308
- var symbolFirst = Symbol();
309
- function useInit(cb) {
310
- const refValue = React4.useRef(symbolFirst);
311
- if (refValue.current === symbolFirst) {
312
- refValue.current = cb();
313
- }
314
- return refValue.current;
315
- }
316
426
 
317
427
  // src/viewability.ts
318
428
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
@@ -463,13 +573,12 @@ function maybeUpdateViewabilityCallback(ctx, configId, viewToken) {
463
573
 
464
574
  // src/LegendList.tsx
465
575
  var DEFAULT_DRAW_DISTANCE = 250;
466
- var POSITION_OUT_OF_VIEW = -1e7;
467
576
  var DEFAULT_ITEM_SIZE = 100;
468
- var LegendList = React4.forwardRef(function LegendList2(props, forwardedRef) {
469
- return /* @__PURE__ */ React4__namespace.createElement(StateProvider, null, /* @__PURE__ */ React4__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
577
+ var LegendList = React5.forwardRef(function LegendList2(props, forwardedRef) {
578
+ return /* @__PURE__ */ React5__namespace.createElement(StateProvider, null, /* @__PURE__ */ React5__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
470
579
  });
471
- var LegendListInner = React4.forwardRef(function LegendListInner2(props, forwardedRef) {
472
- var _a, _b, _c, _d;
580
+ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forwardedRef) {
581
+ var _a, _b, _c, _d, _e;
473
582
  const {
474
583
  data,
475
584
  initialScrollIndex,
@@ -495,15 +604,16 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
495
604
  onItemSizeChanged,
496
605
  scrollEventThrottle,
497
606
  refScrollView,
607
+ waitForInitialLayout = true,
498
608
  extraData,
499
609
  ...rest
500
610
  } = props;
501
611
  const { style, contentContainerStyle } = props;
502
612
  const ctx = useStateContext();
503
- const refScroller = React4.useRef(null);
613
+ const refScroller = React5.useRef(null);
504
614
  const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE;
505
615
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
506
- const refState = React4.useRef();
616
+ const refState = React5.useRef();
507
617
  const getId = (index) => {
508
618
  var _a2;
509
619
  const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
@@ -537,7 +647,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
537
647
  }
538
648
  return 0;
539
649
  };
540
- const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React4.useMemo(calculateInitialOffset, []);
650
+ const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React5.useMemo(calculateInitialOffset, []);
541
651
  if (!refState.current) {
542
652
  const initialScrollLength = reactNative.Dimensions.get("window")[horizontal ? "width" : "height"];
543
653
  refState.current = {
@@ -545,7 +655,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
545
655
  positions: /* @__PURE__ */ new Map(),
546
656
  columns: /* @__PURE__ */ new Map(),
547
657
  pendingAdjust: 0,
548
- animFrameLayout: null,
658
+ waitingForMicrotask: false,
549
659
  isStartReached: initialContentOffset < initialScrollLength * onStartReachedThreshold,
550
660
  isEndReached: false,
551
661
  isAtBottom: false,
@@ -578,7 +688,6 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
578
688
  belowAnchorElementPositions: void 0,
579
689
  rowHeights: /* @__PURE__ */ new Map(),
580
690
  startReachedBlockedByTimer: false,
581
- layoutsPending: /* @__PURE__ */ new Set(),
582
691
  scrollForNextCalculateItemsInView: void 0,
583
692
  enableScrollForNextCalculateItemsInView: true
584
693
  };
@@ -599,6 +708,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
599
708
  }
600
709
  }
601
710
  set$(ctx, "scrollAdjust", 0);
711
+ set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
602
712
  set$(ctx, "extraData", extraData);
603
713
  }
604
714
  const getAnchorElementIndex = () => {
@@ -609,7 +719,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
609
719
  }
610
720
  return void 0;
611
721
  };
612
- const addTotalSize = React4.useCallback((key, add, totalSizeBelowAnchor) => {
722
+ const addTotalSize = React5.useCallback((key, add, totalSizeBelowAnchor) => {
613
723
  const state = refState.current;
614
724
  const index = key === null ? 0 : state.indexByKey.get(key);
615
725
  let isAboveAnchor = false;
@@ -618,7 +728,6 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
618
728
  isAboveAnchor = true;
619
729
  }
620
730
  }
621
- state.totalSize;
622
731
  if (key === null) {
623
732
  state.totalSize = add;
624
733
  state.totalSizeBelowAnchor = totalSizeBelowAnchor;
@@ -699,7 +808,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
699
808
  }
700
809
  return res;
701
810
  };
702
- const calculateItemsInView = React4.useCallback((speed) => {
811
+ const calculateItemsInView = React5.useCallback((speed) => {
703
812
  const state = refState.current;
704
813
  const {
705
814
  data: data2,
@@ -708,12 +817,10 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
708
817
  startBufferedId: startBufferedIdOrig,
709
818
  positions,
710
819
  columns,
711
- scrollAdjustHandler,
712
- layoutsPending
820
+ scrollAdjustHandler
713
821
  } = state;
714
- if (state.animFrameLayout) {
715
- cancelAnimationFrame(state.animFrameLayout);
716
- state.animFrameLayout = null;
822
+ if (state.waitingForMicrotask) {
823
+ state.waitingForMicrotask = false;
717
824
  }
718
825
  if (!data2) {
719
826
  return;
@@ -721,7 +828,17 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
721
828
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
722
829
  const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
723
830
  const scrollExtra = Math.max(-16, Math.min(16, speed)) * 16;
724
- const scroll = scrollState - previousScrollAdjust - topPad - scrollExtra;
831
+ const scroll = scrollState - previousScrollAdjust - topPad;
832
+ let scrollBufferTop = scrollBuffer;
833
+ let scrollBufferBottom = scrollBuffer;
834
+ if (scrollExtra > 8) {
835
+ scrollBufferTop = 0;
836
+ scrollBufferBottom = scrollBuffer + scrollExtra;
837
+ }
838
+ if (scrollExtra < -8) {
839
+ scrollBufferTop = scrollBuffer - scrollExtra;
840
+ scrollBufferBottom = 0;
841
+ }
725
842
  if (state.scrollForNextCalculateItemsInView) {
726
843
  const { top: top2, bottom } = state.scrollForNextCalculateItemsInView;
727
844
  if (scroll > top2 && scroll < bottom) {
@@ -793,7 +910,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
793
910
  if (startNoBuffer === null && top + size > scroll) {
794
911
  startNoBuffer = i;
795
912
  }
796
- if (startBuffered === null && top + size > scroll - scrollBuffer) {
913
+ if (startBuffered === null && top + size > scroll - scrollBufferTop) {
797
914
  startBuffered = i;
798
915
  startBufferedId = id;
799
916
  }
@@ -801,7 +918,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
801
918
  if (top <= scrollBottom) {
802
919
  endNoBuffer = i;
803
920
  }
804
- if (top <= scrollBottom + scrollBuffer) {
921
+ if (top <= scrollBottom + scrollBufferBottom) {
805
922
  endBuffered = i;
806
923
  } else {
807
924
  break;
@@ -855,7 +972,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
855
972
  break;
856
973
  }
857
974
  const index = state.indexByKey.get(key);
858
- const pos = peek$(ctx, `containerPosition${u}`);
975
+ const pos = peek$(ctx, `containerPosition${u}`).top;
859
976
  if (index < startBuffered || index > endBuffered) {
860
977
  const distance = Math.abs(pos - top2);
861
978
  if (index < 0 || distance > furthestDistance) {
@@ -874,7 +991,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
874
991
  set$(ctx, `containerItemKey${containerId}`, id);
875
992
  const index = state.indexByKey.get(id);
876
993
  set$(ctx, `containerItemData${containerId}`, data2[index]);
877
- set$(ctx, `containerPosition${containerId}`, POSITION_OUT_OF_VIEW);
994
+ set$(ctx, `containerPosition${containerId}`, ANCHORED_POSITION_OUT_OF_VIEW);
878
995
  set$(ctx, `containerColumn${containerId}`, -1);
879
996
  if (__DEV__ && numContainers > peek$(ctx, "numContainersPooled")) {
880
997
  console.warn(
@@ -898,19 +1015,31 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
898
1015
  if (item) {
899
1016
  const id = getId(itemIndex);
900
1017
  if (itemKey !== id || itemIndex < startBuffered || itemIndex > endBuffered) {
901
- const prevPos = peek$(ctx, `containerPosition${i}`);
1018
+ const prevPos = peek$(ctx, `containerPosition${i}`).top;
902
1019
  const pos = positions.get(id) || 0;
903
1020
  const size = getItemSize(id, itemIndex, data2[i]);
904
1021
  if (pos + size >= scroll && pos <= scrollBottom || prevPos + size >= scroll && prevPos <= scrollBottom) {
905
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1022
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
906
1023
  }
907
1024
  } else {
908
- const pos = positions.get(id) || 0;
1025
+ const pos = {
1026
+ type: "top",
1027
+ relativeCoordinate: positions.get(id) || 0,
1028
+ top: positions.get(id) || 0
1029
+ };
909
1030
  const column2 = columns.get(id) || 1;
1031
+ if (maintainVisibleContentPosition && itemIndex < anchorElementIndex) {
1032
+ const currentRow = Math.floor(itemIndex / numColumnsProp);
1033
+ const rowHeight = getRowHeight(currentRow);
1034
+ const elementHeight = getItemSize(id, itemIndex, data2[i]);
1035
+ const diff = rowHeight - elementHeight;
1036
+ pos.relativeCoordinate = pos.top + getRowHeight(currentRow) - diff;
1037
+ pos.type = "bottom";
1038
+ }
910
1039
  const prevPos = peek$(ctx, `containerPosition${i}`);
911
1040
  const prevColumn = peek$(ctx, `containerColumn${i}`);
912
1041
  const prevData = peek$(ctx, `containerItemData${i}`);
913
- if (pos > POSITION_OUT_OF_VIEW && pos !== prevPos) {
1042
+ if (pos.relativeCoordinate > POSITION_OUT_OF_VIEW && pos.top !== prevPos.top) {
914
1043
  set$(ctx, `containerPosition${i}`, pos);
915
1044
  }
916
1045
  if (column2 >= 0 && column2 !== prevColumn) {
@@ -923,12 +1052,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
923
1052
  }
924
1053
  }
925
1054
  }
926
- if (layoutsPending.size > 0) {
927
- for (const containerId of layoutsPending) {
928
- set$(ctx, `containerDidLayout${containerId}`, true);
929
- }
930
- layoutsPending.clear();
931
- }
1055
+ set$(ctx, "containersDidLayout", true);
932
1056
  if (state.viewabilityConfigCallbackPairs) {
933
1057
  updateViewableItems(
934
1058
  state,
@@ -1021,13 +1145,13 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1021
1145
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1022
1146
  if (!keyExtractorProp || itemKey && state.indexByKey.get(itemKey) === void 0) {
1023
1147
  set$(ctx, `containerItemKey${i}`, void 0);
1024
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1148
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1025
1149
  set$(ctx, `containerColumn${i}`, -1);
1026
1150
  }
1027
1151
  }
1028
1152
  if (!keyExtractorProp) {
1029
1153
  state.sizes.clear();
1030
- state.positions;
1154
+ state.positions.clear();
1031
1155
  }
1032
1156
  calculateItemsInView(state.scrollVelocity);
1033
1157
  }
@@ -1049,13 +1173,48 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1049
1173
  let totalSize = 0;
1050
1174
  let totalSizeBelowIndex = 0;
1051
1175
  const indexByKey = /* @__PURE__ */ new Map();
1176
+ const newPositions = /* @__PURE__ */ new Map();
1052
1177
  let column = 1;
1053
1178
  let maxSizeInRow = 0;
1054
1179
  for (let i = 0; i < data.length; i++) {
1055
1180
  const key = getId(i);
1056
1181
  indexByKey.set(key, i);
1182
+ if (refState.current.positions.get(key) != null && refState.current.indexByKey.get(key) === i) {
1183
+ newPositions.set(key, refState.current.positions.get(key));
1184
+ }
1057
1185
  }
1058
1186
  refState.current.indexByKey = indexByKey;
1187
+ refState.current.positions = newPositions;
1188
+ if (maintainVisibleContentPosition) {
1189
+ if (refState.current.anchorElement == null || indexByKey.get(refState.current.anchorElement.id) == null) {
1190
+ if (data.length) {
1191
+ const newAnchorElement = {
1192
+ coordinate: 0,
1193
+ id: getId(0)
1194
+ };
1195
+ refState.current.anchorElement = newAnchorElement;
1196
+ (_a = refState.current.belowAnchorElementPositions) == null ? void 0 : _a.clear();
1197
+ refScroller.current.scrollTo({ x: 0, y: 0, animated: false });
1198
+ setTimeout(() => {
1199
+ calculateItemsInView(0);
1200
+ }, 0);
1201
+ } else {
1202
+ refState.current.startBufferedId = void 0;
1203
+ }
1204
+ }
1205
+ } else {
1206
+ if (refState.current.startBufferedId != null && newPositions.get(refState.current.startBufferedId) == null) {
1207
+ if (data.length) {
1208
+ refState.current.startBufferedId = getId(0);
1209
+ } else {
1210
+ refState.current.startBufferedId = void 0;
1211
+ }
1212
+ refScroller.current.scrollTo({ x: 0, y: 0, animated: false });
1213
+ setTimeout(() => {
1214
+ calculateItemsInView(0);
1215
+ }, 0);
1216
+ }
1217
+ }
1059
1218
  const anchorElementIndex = getAnchorElementIndex();
1060
1219
  for (let i = 0; i < data.length; i++) {
1061
1220
  const key = getId(i);
@@ -1076,18 +1235,18 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1076
1235
  }
1077
1236
  addTotalSize(null, totalSize, totalSizeBelowIndex);
1078
1237
  }
1079
- React4.useEffect(() => {
1238
+ React5.useEffect(() => {
1080
1239
  checkResetContainers(
1081
1240
  /*reset*/
1082
1241
  !isFirst
1083
1242
  );
1084
1243
  }, [isFirst, data, numColumnsProp]);
1085
- React4.useEffect(() => {
1244
+ React5.useEffect(() => {
1086
1245
  set$(ctx, "extraData", extraData);
1087
1246
  }, [extraData]);
1088
1247
  refState.current.renderItem = renderItem;
1089
- const lastItemKey = getId(data[data.length - 1]);
1090
- const stylePaddingTop = (_d = (_c = (_a = reactNative.StyleSheet.flatten(style)) == null ? void 0 : _a.paddingTop) != null ? _c : (_b = reactNative.StyleSheet.flatten(contentContainerStyle)) == null ? void 0 : _b.paddingTop) != null ? _d : 0;
1248
+ const lastItemKey = data.length > 0 ? getId(data.length - 1) : void 0;
1249
+ const stylePaddingTop = (_e = (_d = (_b = reactNative.StyleSheet.flatten(style)) == null ? void 0 : _b.paddingTop) != null ? _d : (_c = reactNative.StyleSheet.flatten(contentContainerStyle)) == null ? void 0 : _c.paddingTop) != null ? _e : 0;
1091
1250
  const initalizeStateVars = () => {
1092
1251
  set$(ctx, "lastItemKey", lastItemKey);
1093
1252
  set$(ctx, "numColumns", numColumnsProp);
@@ -1096,8 +1255,8 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1096
1255
  if (isFirst) {
1097
1256
  initalizeStateVars();
1098
1257
  }
1099
- React4.useEffect(initalizeStateVars, [lastItemKey, numColumnsProp, stylePaddingTop]);
1100
- const getRenderedItem = React4.useCallback((key, containerId) => {
1258
+ React5.useEffect(initalizeStateVars, [lastItemKey, numColumnsProp, stylePaddingTop]);
1259
+ const getRenderedItem = React5.useCallback((key) => {
1101
1260
  var _a2, _b2;
1102
1261
  const state = refState.current;
1103
1262
  if (!state) {
@@ -1108,89 +1267,27 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1108
1267
  if (index === void 0) {
1109
1268
  return null;
1110
1269
  }
1111
- const useViewability = (configId, callback) => {
1112
- const key2 = containerId + configId;
1113
- useInit(() => {
1114
- const value = ctx.mapViewabilityValues.get(key2);
1115
- if (value) {
1116
- callback(value);
1117
- }
1118
- });
1119
- ctx.mapViewabilityCallbacks.set(key2, callback);
1120
- React4.useEffect(
1121
- () => () => {
1122
- ctx.mapViewabilityCallbacks.delete(key2);
1123
- },
1124
- []
1125
- );
1270
+ const useViewability2 = (configId, callback) => {
1271
+ useViewability(configId, callback);
1126
1272
  };
1127
- const useViewabilityAmount = (callback) => {
1128
- useInit(() => {
1129
- const value = ctx.mapViewabilityAmountValues.get(containerId);
1130
- if (value) {
1131
- callback(value);
1132
- }
1133
- });
1134
- ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
1135
- React4.useEffect(
1136
- () => () => {
1137
- ctx.mapViewabilityAmountCallbacks.delete(containerId);
1138
- },
1139
- []
1140
- );
1273
+ const useViewabilityAmount2 = (callback) => {
1274
+ useViewabilityAmount(callback);
1141
1275
  };
1142
- const useRecyclingEffect = (effect) => {
1143
- React4.useEffect(() => {
1144
- const state2 = refState.current;
1145
- let prevIndex = index;
1146
- let prevItem = state2.data[index];
1147
- const signal = `containerItemKey${containerId}`;
1148
- const run = () => {
1149
- const data3 = state2.data;
1150
- if (data3) {
1151
- const newKey = peek$(ctx, signal);
1152
- const newIndex = state2.indexByKey.get(newKey);
1153
- const newItem = data3[newIndex];
1154
- if (newItem) {
1155
- effect({
1156
- index: newIndex,
1157
- item: newItem,
1158
- prevIndex,
1159
- prevItem
1160
- });
1161
- }
1162
- prevIndex = newIndex;
1163
- prevItem = newItem;
1164
- }
1165
- };
1166
- run();
1167
- return listen$(ctx, signal, run);
1168
- }, []);
1276
+ const useRecyclingEffect2 = (effect) => {
1277
+ useRecyclingEffect(effect);
1169
1278
  };
1170
- const useRecyclingState = (valueOrFun) => {
1171
- const stateInfo = React4.useState(
1172
- () => typeof valueOrFun === "function" ? valueOrFun({
1173
- index,
1174
- item: refState.current.data[index],
1175
- prevIndex: void 0,
1176
- prevItem: void 0
1177
- }) : valueOrFun
1178
- );
1179
- useRecyclingEffect((state2) => {
1180
- const newState = typeof valueOrFun === "function" ? valueOrFun(state2) : valueOrFun;
1181
- stateInfo[1](newState);
1182
- });
1183
- return stateInfo;
1279
+ const useRecyclingState2 = (valueOrFun) => {
1280
+ return useRecyclingState(valueOrFun);
1184
1281
  };
1185
1282
  const renderedItem = (_b2 = (_a2 = refState.current).renderItem) == null ? void 0 : _b2.call(_a2, {
1186
1283
  item: data2[index],
1187
1284
  index,
1188
- useViewability,
1189
- useViewabilityAmount,
1190
- useRecyclingEffect,
1191
- useRecyclingState
1285
+ useViewability: useViewability2,
1286
+ useViewabilityAmount: useViewabilityAmount2,
1287
+ useRecyclingEffect: useRecyclingEffect2,
1288
+ useRecyclingState: useRecyclingState2
1192
1289
  });
1193
- return renderedItem;
1290
+ return { index, renderedItem };
1194
1291
  }, []);
1195
1292
  useInit(() => {
1196
1293
  var _a2;
@@ -1202,29 +1299,25 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1202
1299
  const averageItemSize = (_a2 = estimatedItemSize != null ? estimatedItemSize : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(0, data[0])) != null ? _a2 : DEFAULT_ITEM_SIZE;
1203
1300
  const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) * numColumnsProp;
1204
1301
  for (let i = 0; i < numContainers; i++) {
1205
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1302
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1206
1303
  set$(ctx, `containerColumn${i}`, -1);
1207
1304
  }
1208
1305
  set$(ctx, "numContainers", numContainers);
1209
1306
  set$(ctx, "numContainersPooled", numContainers * 2);
1210
1307
  calculateItemsInView(state.scrollVelocity);
1211
1308
  });
1212
- const updateItemSize = React4.useCallback((containerId, itemKey, size) => {
1309
+ const updateItemSize = React5.useCallback((containerId, itemKey, size) => {
1213
1310
  var _a2;
1214
1311
  const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
1215
1312
  if (!data2) {
1216
1313
  return;
1217
1314
  }
1218
1315
  const state = refState.current;
1219
- const { sizes, indexByKey, idsInFirstRender, columns, sizesLaidOut } = state;
1316
+ const { sizes, indexByKey, columns, sizesLaidOut } = state;
1220
1317
  const index = indexByKey.get(itemKey);
1221
1318
  const numColumns = peek$(ctx, "numColumns");
1222
1319
  const row = Math.floor(index / numColumns);
1223
1320
  const prevSize = getRowHeight(row);
1224
- const measured = peek$(ctx, `containerDidLayout${containerId}`);
1225
- if (!measured) {
1226
- state.layoutsPending.add(containerId);
1227
- }
1228
1321
  if (!prevSize || Math.abs(prevSize - size) > 0.5) {
1229
1322
  let diff;
1230
1323
  if (numColumns > 1) {
@@ -1266,11 +1359,14 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1266
1359
  addTotalSize(itemKey, diff, 0);
1267
1360
  doMaintainScrollAtEnd(true);
1268
1361
  const scrollVelocity = state.scrollVelocity;
1269
- if (!state.animFrameLayout && (Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1)) {
1270
- if (!peek$(ctx, `containerDidLayout${containerId}`)) {
1271
- state.animFrameLayout = requestAnimationFrame(() => {
1272
- state.animFrameLayout = null;
1273
- calculateItemsInView(state.scrollVelocity);
1362
+ if (!state.waitingForMicrotask && (Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1)) {
1363
+ if (!peek$(ctx, "containersDidLayout")) {
1364
+ state.waitingForMicrotask = true;
1365
+ queueMicrotask(() => {
1366
+ if (state.waitingForMicrotask) {
1367
+ state.waitingForMicrotask = false;
1368
+ calculateItemsInView(state.scrollVelocity);
1369
+ }
1274
1370
  });
1275
1371
  } else {
1276
1372
  calculateItemsInView(state.scrollVelocity);
@@ -1279,16 +1375,14 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1279
1375
  if (onItemSizeChanged) {
1280
1376
  onItemSizeChanged({ size, previous: prevSize, index, itemKey, itemData: data2[index] });
1281
1377
  }
1282
- } else {
1283
- set$(ctx, `containerDidLayout${containerId}`, true);
1284
1378
  }
1285
1379
  }, []);
1286
- const handleScrollDebounced = React4.useCallback((velocity) => {
1380
+ const handleScrollDebounced = React5.useCallback((velocity) => {
1287
1381
  calculateItemsInView(velocity);
1288
1382
  checkAtBottom();
1289
1383
  checkAtTop();
1290
1384
  }, []);
1291
- const onLayout = React4.useCallback((event) => {
1385
+ const onLayout = React5.useCallback((event) => {
1292
1386
  const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
1293
1387
  refState.current.scrollLength = scrollLength;
1294
1388
  doMaintainScrollAtEnd(false);
@@ -1305,7 +1399,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1305
1399
  }
1306
1400
  }
1307
1401
  }, []);
1308
- const handleScroll = React4.useCallback(
1402
+ const handleScroll = React5.useCallback(
1309
1403
  (event, fromSelf) => {
1310
1404
  var _a2, _b2, _c2;
1311
1405
  if (((_b2 = (_a2 = event.nativeEvent) == null ? void 0 : _a2.contentSize) == null ? void 0 : _b2.height) === 0 && ((_c2 = event.nativeEvent.contentSize) == null ? void 0 : _c2.width) === 0) {
@@ -1347,7 +1441,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1347
1441
  },
1348
1442
  []
1349
1443
  );
1350
- React4.useImperativeHandle(
1444
+ React5.useImperativeHandle(
1351
1445
  forwardedRef,
1352
1446
  () => {
1353
1447
  const scrollToIndex = ({ index, animated }) => {
@@ -1376,7 +1470,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1376
1470
  },
1377
1471
  []
1378
1472
  );
1379
- return /* @__PURE__ */ React4__namespace.createElement(
1473
+ return /* @__PURE__ */ React5__namespace.createElement(
1380
1474
  ListComponent,
1381
1475
  {
1382
1476
  ...rest,
@@ -1401,9 +1495,14 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1401
1495
  ListEmptyComponent: data.length === 0 ? ListEmptyComponent : void 0,
1402
1496
  maintainVisibleContentPosition,
1403
1497
  scrollEventThrottle: scrollEventThrottle != null ? scrollEventThrottle : reactNative.Platform.OS === "web" ? 16 : void 0,
1498
+ waitForInitialLayout,
1404
1499
  style
1405
1500
  }
1406
1501
  );
1407
1502
  });
1408
1503
 
1409
1504
  exports.LegendList = LegendList;
1505
+ exports.useRecyclingEffect = useRecyclingEffect;
1506
+ exports.useRecyclingState = useRecyclingState;
1507
+ exports.useViewability = useViewability;
1508
+ exports.useViewabilityAmount = useViewabilityAmount;