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

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,75 +77,202 @@ 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
82
179
  var Container = ({
83
180
  id,
84
181
  recycleItems,
85
182
  horizontal,
86
- waitForInitialLayout,
87
183
  getRenderedItem,
88
184
  updateItemSize,
89
185
  ItemSeparatorComponent
90
186
  }) => {
91
187
  const ctx = useStateContext();
92
- const position = use$(`containerPosition${id}`);
188
+ const maintainVisibleContentPosition = use$("maintainVisibleContentPosition");
189
+ const position = use$(`containerPosition${id}`) || ANCHORED_POSITION_OUT_OF_VIEW;
93
190
  const column = use$(`containerColumn${id}`) || 0;
94
191
  const numColumns = use$("numColumns");
95
192
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
96
193
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
97
194
  const style = horizontal ? {
98
- flexDirection: "row",
195
+ flexDirection: ItemSeparatorComponent ? "row" : void 0,
99
196
  position: "absolute",
100
197
  top: otherAxisPos,
101
198
  bottom: numColumns > 1 ? null : 0,
102
199
  height: otherAxisSize,
103
- left: position
200
+ left: position.relativeCoordinate
104
201
  } : {
105
202
  position: "absolute",
106
203
  left: otherAxisPos,
107
204
  right: numColumns > 1 ? null : 0,
108
205
  width: otherAxisSize,
109
- top: position
206
+ top: position.relativeCoordinate
110
207
  };
111
- if (waitForInitialLayout) {
112
- const visible = use$(`containerDidLayout${id}`);
113
- style.opacity = visible ? 1 : 0;
114
- }
115
208
  const lastItemKey = use$("lastItemKey");
116
209
  const itemKey = use$(`containerItemKey${id}`);
117
210
  const data = use$(`containerItemData${id}`);
118
- const renderedItem = React4.useMemo(() => itemKey !== void 0 && getRenderedItem(itemKey, id), [itemKey, data]);
119
- return /* @__PURE__ */ React4__namespace.default.createElement(
120
- reactNative.View,
121
- {
122
- style,
123
- onLayout: (event) => {
124
- const key = peek$(ctx, `containerItemKey${id}`);
125
- if (key !== void 0) {
126
- const size = Math.floor(event.nativeEvent.layout[horizontal ? "width" : "height"] * 8) / 8;
127
- updateItemSize(id, key, size);
211
+ const extraData = use$("extraData");
212
+ const refLastSize = React5.useRef();
213
+ const renderedItemInfo = React5.useMemo(
214
+ () => itemKey !== void 0 && getRenderedItem(itemKey),
215
+ [itemKey, data, extraData]
216
+ );
217
+ const { index, renderedItem } = renderedItemInfo || {};
218
+ React5.useEffect(() => {
219
+ if (itemKey) {
220
+ const timeout = setTimeout(() => {
221
+ if (refLastSize.current) {
222
+ updateItemSize(id, itemKey, refLastSize.current);
223
+ }
224
+ }, 16);
225
+ return () => {
226
+ clearTimeout(timeout);
227
+ };
228
+ }
229
+ }, [itemKey]);
230
+ const onLayout = (event) => {
231
+ const key = peek$(ctx, `containerItemKey${id}`);
232
+ if (key !== void 0) {
233
+ const size = Math.floor(event.nativeEvent.layout[horizontal ? "width" : "height"] * 8) / 8;
234
+ updateItemSize(id, key, size);
235
+ }
236
+ };
237
+ const ref = React5.useRef(null);
238
+ React5.useLayoutEffect(() => {
239
+ var _a, _b;
240
+ if (itemKey) {
241
+ const measured = (_b = (_a = ref.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
242
+ if (measured) {
243
+ const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
244
+ if (size) {
245
+ updateItemSize(id, itemKey, size);
128
246
  }
129
247
  }
130
- },
131
- /* @__PURE__ */ React4__namespace.default.createElement(React4__namespace.default.Fragment, { key: recycleItems ? void 0 : itemKey }, renderedItem, renderedItem && ItemSeparatorComponent && itemKey !== lastItemKey && ItemSeparatorComponent)
248
+ }
249
+ }, [itemKey]);
250
+ const contextValue = React5.useMemo(
251
+ () => ({ containerId: id, itemKey, index, value: data }),
252
+ [id, itemKey, index, data]
132
253
  );
254
+ 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));
255
+ if (maintainVisibleContentPosition) {
256
+ const anchorStyle = position.type === "top" ? { position: "absolute", top: 0, left: 0, right: 0 } : { position: "absolute", bottom: 0, left: 0, right: 0 };
257
+ return /* @__PURE__ */ React5__namespace.default.createElement(LeanView, { style, ref }, /* @__PURE__ */ React5__namespace.default.createElement(LeanView, { style: anchorStyle, onLayout }, contentFragment));
258
+ }
259
+ return /* @__PURE__ */ React5__namespace.default.createElement(LeanView, { style, onLayout, ref }, contentFragment);
133
260
  };
134
261
  var useAnimatedValue = reactNative.useAnimatedValue || ((initialValue) => {
135
- return React4.useRef(new reactNative.Animated.Value(initialValue)).current;
262
+ return React5.useRef(new reactNative.Animated.Value(initialValue)).current;
136
263
  });
137
264
  function useValue$(key, getValue, key2) {
138
265
  var _a;
139
266
  const ctx = useStateContext();
140
- const animValue = useAnimatedValue((_a = peek$(ctx, key)) != null ? _a : 0);
141
- React4.useMemo(() => {
142
- listen$(ctx, key, (v) => animValue.setValue(v));
267
+ const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
268
+ React5.useMemo(() => {
269
+ listen$(ctx, key, (v) => animValue.setValue(getValue ? getValue(v) : v));
143
270
  }, []);
144
271
  return animValue;
145
272
  }
146
273
 
147
274
  // src/Containers.tsx
148
- var Containers = React4__namespace.memo(function Containers2({
275
+ var Containers = React5__namespace.memo(function Containers2({
149
276
  horizontal,
150
277
  recycleItems,
151
278
  ItemSeparatorComponent,
@@ -155,17 +282,17 @@ var Containers = React4__namespace.memo(function Containers2({
155
282
  }) {
156
283
  const numContainers = use$("numContainersPooled");
157
284
  const animSize = useValue$("totalSize");
285
+ const animOpacity = waitForInitialLayout ? useValue$("containersDidLayout", (value) => value ? 1 : 0) : void 0;
158
286
  const containers = [];
159
287
  for (let i = 0; i < numContainers; i++) {
160
288
  containers.push(
161
- /* @__PURE__ */ React4__namespace.createElement(
289
+ /* @__PURE__ */ React5__namespace.createElement(
162
290
  Container,
163
291
  {
164
292
  id: i,
165
293
  key: i,
166
294
  recycleItems,
167
295
  horizontal,
168
- waitForInitialLayout,
169
296
  getRenderedItem,
170
297
  updateItemSize,
171
298
  ItemSeparatorComponent
@@ -173,21 +300,21 @@ var Containers = React4__namespace.memo(function Containers2({
173
300
  )
174
301
  );
175
302
  }
176
- const style = horizontal ? { width: animSize } : { height: animSize };
177
- return /* @__PURE__ */ React4__namespace.createElement(reactNative.Animated.View, { style }, containers);
303
+ const style = horizontal ? { width: animSize, opacity: animOpacity } : { height: animSize, opacity: animOpacity };
304
+ return /* @__PURE__ */ React5__namespace.createElement(reactNative.Animated.View, { style }, containers);
178
305
  });
179
306
 
180
307
  // src/ListComponent.tsx
181
308
  var getComponent = (Component) => {
182
- if (React4__namespace.isValidElement(Component)) {
309
+ if (React5__namespace.isValidElement(Component)) {
183
310
  return Component;
184
311
  }
185
312
  if (Component) {
186
- return /* @__PURE__ */ React4__namespace.createElement(Component, null);
313
+ return /* @__PURE__ */ React5__namespace.createElement(Component, null);
187
314
  }
188
315
  return null;
189
316
  };
190
- var ListComponent = React4__namespace.memo(function ListComponent2({
317
+ var ListComponent = React5__namespace.memo(function ListComponent2({
191
318
  style,
192
319
  contentContainerStyle,
193
320
  horizontal,
@@ -214,12 +341,12 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
214
341
  const ctx = useStateContext();
215
342
  const animPaddingTop = useValue$("paddingTop");
216
343
  const animScrollAdjust = useValue$("scrollAdjust");
217
- const ScrollComponent = renderScrollComponent ? React4.useMemo(
218
- () => React4__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
344
+ const ScrollComponent = renderScrollComponent ? React5.useMemo(
345
+ () => React5__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
219
346
  [renderScrollComponent]
220
347
  ) : reactNative.ScrollView;
221
348
  const additionalSize = { marginTop: animScrollAdjust, paddingTop: animPaddingTop };
222
- return /* @__PURE__ */ React4__namespace.createElement(
349
+ return /* @__PURE__ */ React5__namespace.createElement(
223
350
  ScrollComponent,
224
351
  {
225
352
  ...rest,
@@ -237,8 +364,8 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
237
364
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
238
365
  ref: refScrollView
239
366
  },
240
- /* @__PURE__ */ React4__namespace.createElement(reactNative.Animated.View, { style: additionalSize }),
241
- ListHeaderComponent && /* @__PURE__ */ React4__namespace.createElement(
367
+ /* @__PURE__ */ React5__namespace.createElement(reactNative.Animated.View, { style: additionalSize }),
368
+ ListHeaderComponent && /* @__PURE__ */ React5__namespace.createElement(
242
369
  reactNative.Animated.View,
243
370
  {
244
371
  style: ListHeaderComponentStyle,
@@ -252,8 +379,8 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
252
379
  },
253
380
  getComponent(ListHeaderComponent)
254
381
  ),
255
- ListEmptyComponent && /* @__PURE__ */ React4__namespace.createElement(reactNative.Animated.View, { style: ListEmptyComponentStyle }, getComponent(ListEmptyComponent)),
256
- /* @__PURE__ */ React4__namespace.createElement(
382
+ ListEmptyComponent && /* @__PURE__ */ React5__namespace.createElement(reactNative.Animated.View, { style: ListEmptyComponentStyle }, getComponent(ListEmptyComponent)),
383
+ /* @__PURE__ */ React5__namespace.createElement(
257
384
  Containers,
258
385
  {
259
386
  horizontal,
@@ -264,7 +391,7 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
264
391
  updateItemSize
265
392
  }
266
393
  ),
267
- ListFooterComponent && /* @__PURE__ */ React4__namespace.createElement(reactNative.View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
394
+ ListFooterComponent && /* @__PURE__ */ React5__namespace.createElement(reactNative.View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
268
395
  );
269
396
  });
270
397
 
@@ -304,14 +431,6 @@ var ScrollAdjustHandler = class {
304
431
  return this.appliedAdjust;
305
432
  }
306
433
  };
307
- var symbolFirst = Symbol();
308
- function useInit(cb) {
309
- const refValue = React4.useRef(symbolFirst);
310
- if (refValue.current === symbolFirst) {
311
- refValue.current = cb();
312
- }
313
- return refValue.current;
314
- }
315
434
 
316
435
  // src/viewability.ts
317
436
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
@@ -462,13 +581,12 @@ function maybeUpdateViewabilityCallback(ctx, configId, viewToken) {
462
581
 
463
582
  // src/LegendList.tsx
464
583
  var DEFAULT_DRAW_DISTANCE = 250;
465
- var POSITION_OUT_OF_VIEW = -1e7;
466
584
  var DEFAULT_ITEM_SIZE = 100;
467
- var LegendList = React4.forwardRef(function LegendList2(props, forwardedRef) {
468
- return /* @__PURE__ */ React4__namespace.createElement(StateProvider, null, /* @__PURE__ */ React4__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
585
+ var LegendList = React5.forwardRef(function LegendList2(props, forwardedRef) {
586
+ return /* @__PURE__ */ React5__namespace.createElement(StateProvider, null, /* @__PURE__ */ React5__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
469
587
  });
470
- var LegendListInner = React4.forwardRef(function LegendListInner2(props, forwardedRef) {
471
- var _a, _b, _c, _d;
588
+ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forwardedRef) {
589
+ var _a, _b, _c, _d, _e;
472
590
  const {
473
591
  data,
474
592
  initialScrollIndex,
@@ -494,14 +612,16 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
494
612
  onItemSizeChanged,
495
613
  scrollEventThrottle,
496
614
  refScrollView,
615
+ waitForInitialLayout = true,
616
+ extraData,
497
617
  ...rest
498
618
  } = props;
499
619
  const { style, contentContainerStyle } = props;
500
620
  const ctx = useStateContext();
501
- const refScroller = React4.useRef(null);
621
+ const refScroller = React5.useRef(null);
502
622
  const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE;
503
623
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
504
- const refState = React4.useRef();
624
+ const refState = React5.useRef();
505
625
  const getId = (index) => {
506
626
  var _a2;
507
627
  const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
@@ -535,7 +655,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
535
655
  }
536
656
  return 0;
537
657
  };
538
- const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React4.useMemo(calculateInitialOffset, []);
658
+ const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React5.useMemo(calculateInitialOffset, []);
539
659
  if (!refState.current) {
540
660
  const initialScrollLength = reactNative.Dimensions.get("window")[horizontal ? "width" : "height"];
541
661
  refState.current = {
@@ -543,7 +663,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
543
663
  positions: /* @__PURE__ */ new Map(),
544
664
  columns: /* @__PURE__ */ new Map(),
545
665
  pendingAdjust: 0,
546
- animFrameLayout: null,
666
+ waitingForMicrotask: false,
547
667
  isStartReached: initialContentOffset < initialScrollLength * onStartReachedThreshold,
548
668
  isEndReached: false,
549
669
  isAtBottom: false,
@@ -576,7 +696,6 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
576
696
  belowAnchorElementPositions: void 0,
577
697
  rowHeights: /* @__PURE__ */ new Map(),
578
698
  startReachedBlockedByTimer: false,
579
- layoutsPending: /* @__PURE__ */ new Set(),
580
699
  scrollForNextCalculateItemsInView: void 0,
581
700
  enableScrollForNextCalculateItemsInView: true
582
701
  };
@@ -597,6 +716,8 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
597
716
  }
598
717
  }
599
718
  set$(ctx, "scrollAdjust", 0);
719
+ set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
720
+ set$(ctx, "extraData", extraData);
600
721
  }
601
722
  const getAnchorElementIndex = () => {
602
723
  const state = refState.current;
@@ -606,7 +727,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
606
727
  }
607
728
  return void 0;
608
729
  };
609
- const addTotalSize = React4.useCallback((key, add, totalSizeBelowAnchor) => {
730
+ const addTotalSize = React5.useCallback((key, add, totalSizeBelowAnchor) => {
610
731
  const state = refState.current;
611
732
  const index = key === null ? 0 : state.indexByKey.get(key);
612
733
  let isAboveAnchor = false;
@@ -696,7 +817,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
696
817
  }
697
818
  return res;
698
819
  };
699
- const calculateItemsInView = React4.useCallback((speed) => {
820
+ const calculateItemsInView = React5.useCallback((speed) => {
700
821
  const state = refState.current;
701
822
  const {
702
823
  data: data2,
@@ -705,12 +826,10 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
705
826
  startBufferedId: startBufferedIdOrig,
706
827
  positions,
707
828
  columns,
708
- scrollAdjustHandler,
709
- layoutsPending
829
+ scrollAdjustHandler
710
830
  } = state;
711
- if (state.animFrameLayout) {
712
- cancelAnimationFrame(state.animFrameLayout);
713
- state.animFrameLayout = null;
831
+ if (state.waitingForMicrotask) {
832
+ state.waitingForMicrotask = false;
714
833
  }
715
834
  if (!data2) {
716
835
  return;
@@ -818,9 +937,9 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
818
937
  endBuffered,
819
938
  endNoBuffer
820
939
  });
821
- const nextTop = Math.ceil(startBuffered ? positions.get(startBufferedId) + scrollBuffer : 0);
940
+ const nextTop = Math.ceil(startBuffered !== null ? positions.get(startBufferedId) + scrollBuffer : 0);
822
941
  const nextBottom = Math.floor(
823
- endBuffered ? (positions.get(getId(endBuffered + 1)) || 0) - scrollLength - scrollBuffer : 0
942
+ endBuffered !== null ? (positions.get(getId(endBuffered + 1)) || 0) - scrollLength - scrollBuffer : 0
824
943
  );
825
944
  if (state.enableScrollForNextCalculateItemsInView) {
826
945
  state.scrollForNextCalculateItemsInView = nextTop >= 0 && nextBottom >= 0 ? {
@@ -852,7 +971,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
852
971
  break;
853
972
  }
854
973
  const index = state.indexByKey.get(key);
855
- const pos = peek$(ctx, `containerPosition${u}`);
974
+ const pos = peek$(ctx, `containerPosition${u}`).top;
856
975
  if (index < startBuffered || index > endBuffered) {
857
976
  const distance = Math.abs(pos - top2);
858
977
  if (index < 0 || distance > furthestDistance) {
@@ -871,7 +990,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
871
990
  set$(ctx, `containerItemKey${containerId}`, id);
872
991
  const index = state.indexByKey.get(id);
873
992
  set$(ctx, `containerItemData${containerId}`, data2[index]);
874
- set$(ctx, `containerPosition${containerId}`, POSITION_OUT_OF_VIEW);
993
+ set$(ctx, `containerPosition${containerId}`, ANCHORED_POSITION_OUT_OF_VIEW);
875
994
  set$(ctx, `containerColumn${containerId}`, -1);
876
995
  if (__DEV__ && numContainers > peek$(ctx, "numContainersPooled")) {
877
996
  console.warn(
@@ -895,19 +1014,31 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
895
1014
  if (item) {
896
1015
  const id = getId(itemIndex);
897
1016
  if (itemKey !== id || itemIndex < startBuffered || itemIndex > endBuffered) {
898
- const prevPos = peek$(ctx, `containerPosition${i}`);
1017
+ const prevPos = peek$(ctx, `containerPosition${i}`).top;
899
1018
  const pos = positions.get(id) || 0;
900
1019
  const size = getItemSize(id, itemIndex, data2[i]);
901
1020
  if (pos + size >= scroll && pos <= scrollBottom || prevPos + size >= scroll && prevPos <= scrollBottom) {
902
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1021
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
903
1022
  }
904
1023
  } else {
905
- const pos = positions.get(id) || 0;
1024
+ const pos = {
1025
+ type: "top",
1026
+ relativeCoordinate: positions.get(id) || 0,
1027
+ top: positions.get(id) || 0
1028
+ };
906
1029
  const column2 = columns.get(id) || 1;
1030
+ if (maintainVisibleContentPosition && itemIndex < anchorElementIndex) {
1031
+ const currentRow = Math.floor(itemIndex / numColumnsProp);
1032
+ const rowHeight = getRowHeight(currentRow);
1033
+ const elementHeight = getItemSize(id, itemIndex, data2[i]);
1034
+ const diff = rowHeight - elementHeight;
1035
+ pos.relativeCoordinate = pos.top + getRowHeight(currentRow) - diff;
1036
+ pos.type = "bottom";
1037
+ }
907
1038
  const prevPos = peek$(ctx, `containerPosition${i}`);
908
1039
  const prevColumn = peek$(ctx, `containerColumn${i}`);
909
1040
  const prevData = peek$(ctx, `containerItemData${i}`);
910
- if (pos > POSITION_OUT_OF_VIEW && pos !== prevPos) {
1041
+ if (pos.relativeCoordinate > POSITION_OUT_OF_VIEW && pos.top !== prevPos.top) {
911
1042
  set$(ctx, `containerPosition${i}`, pos);
912
1043
  }
913
1044
  if (column2 >= 0 && column2 !== prevColumn) {
@@ -920,12 +1051,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
920
1051
  }
921
1052
  }
922
1053
  }
923
- if (layoutsPending.size > 0) {
924
- for (const containerId of layoutsPending) {
925
- set$(ctx, `containerDidLayout${containerId}`, true);
926
- }
927
- layoutsPending.clear();
928
- }
1054
+ set$(ctx, "containersDidLayout", true);
929
1055
  if (state.viewabilityConfigCallbackPairs) {
930
1056
  updateViewableItems(
931
1057
  state,
@@ -1018,13 +1144,13 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1018
1144
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1019
1145
  if (!keyExtractorProp || itemKey && state.indexByKey.get(itemKey) === void 0) {
1020
1146
  set$(ctx, `containerItemKey${i}`, void 0);
1021
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1147
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1022
1148
  set$(ctx, `containerColumn${i}`, -1);
1023
1149
  }
1024
1150
  }
1025
1151
  if (!keyExtractorProp) {
1026
1152
  state.sizes.clear();
1027
- state.positions;
1153
+ state.positions.clear();
1028
1154
  }
1029
1155
  calculateItemsInView(state.scrollVelocity);
1030
1156
  }
@@ -1046,13 +1172,48 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1046
1172
  let totalSize = 0;
1047
1173
  let totalSizeBelowIndex = 0;
1048
1174
  const indexByKey = /* @__PURE__ */ new Map();
1175
+ const newPositions = /* @__PURE__ */ new Map();
1049
1176
  let column = 1;
1050
1177
  let maxSizeInRow = 0;
1051
1178
  for (let i = 0; i < data.length; i++) {
1052
1179
  const key = getId(i);
1053
1180
  indexByKey.set(key, i);
1181
+ if (refState.current.positions.get(key) != null && refState.current.indexByKey.get(key) === i) {
1182
+ newPositions.set(key, refState.current.positions.get(key));
1183
+ }
1054
1184
  }
1055
1185
  refState.current.indexByKey = indexByKey;
1186
+ refState.current.positions = newPositions;
1187
+ if (maintainVisibleContentPosition) {
1188
+ if (refState.current.anchorElement == null || indexByKey.get(refState.current.anchorElement.id) == null) {
1189
+ if (data.length) {
1190
+ const newAnchorElement = {
1191
+ coordinate: 0,
1192
+ id: getId(0)
1193
+ };
1194
+ refState.current.anchorElement = newAnchorElement;
1195
+ (_a = refState.current.belowAnchorElementPositions) == null ? void 0 : _a.clear();
1196
+ refScroller.current.scrollTo({ x: 0, y: 0, animated: false });
1197
+ setTimeout(() => {
1198
+ calculateItemsInView(0);
1199
+ }, 0);
1200
+ } else {
1201
+ refState.current.startBufferedId = void 0;
1202
+ }
1203
+ }
1204
+ } else {
1205
+ if (refState.current.startBufferedId != null && newPositions.get(refState.current.startBufferedId) == null) {
1206
+ if (data.length) {
1207
+ refState.current.startBufferedId = getId(0);
1208
+ } else {
1209
+ refState.current.startBufferedId = void 0;
1210
+ }
1211
+ refScroller.current.scrollTo({ x: 0, y: 0, animated: false });
1212
+ setTimeout(() => {
1213
+ calculateItemsInView(0);
1214
+ }, 0);
1215
+ }
1216
+ }
1056
1217
  const anchorElementIndex = getAnchorElementIndex();
1057
1218
  for (let i = 0; i < data.length; i++) {
1058
1219
  const key = getId(i);
@@ -1073,15 +1234,18 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1073
1234
  }
1074
1235
  addTotalSize(null, totalSize, totalSizeBelowIndex);
1075
1236
  }
1076
- React4.useEffect(() => {
1237
+ React5.useEffect(() => {
1077
1238
  checkResetContainers(
1078
1239
  /*reset*/
1079
1240
  !isFirst
1080
1241
  );
1081
1242
  }, [isFirst, data, numColumnsProp]);
1243
+ React5.useEffect(() => {
1244
+ set$(ctx, "extraData", extraData);
1245
+ }, [extraData]);
1082
1246
  refState.current.renderItem = renderItem;
1083
1247
  const lastItemKey = getId(data[data.length - 1]);
1084
- 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 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;
1085
1249
  const initalizeStateVars = () => {
1086
1250
  set$(ctx, "lastItemKey", lastItemKey);
1087
1251
  set$(ctx, "numColumns", numColumnsProp);
@@ -1090,8 +1254,8 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1090
1254
  if (isFirst) {
1091
1255
  initalizeStateVars();
1092
1256
  }
1093
- React4.useEffect(initalizeStateVars, [lastItemKey, numColumnsProp, stylePaddingTop]);
1094
- const getRenderedItem = React4.useCallback((key, containerId) => {
1257
+ React5.useEffect(initalizeStateVars, [lastItemKey, numColumnsProp, stylePaddingTop]);
1258
+ const getRenderedItem = React5.useCallback((key) => {
1095
1259
  var _a2, _b2;
1096
1260
  const state = refState.current;
1097
1261
  if (!state) {
@@ -1102,89 +1266,27 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1102
1266
  if (index === void 0) {
1103
1267
  return null;
1104
1268
  }
1105
- const useViewability = (configId, callback) => {
1106
- const key2 = containerId + configId;
1107
- useInit(() => {
1108
- const value = ctx.mapViewabilityValues.get(key2);
1109
- if (value) {
1110
- callback(value);
1111
- }
1112
- });
1113
- ctx.mapViewabilityCallbacks.set(key2, callback);
1114
- React4.useEffect(
1115
- () => () => {
1116
- ctx.mapViewabilityCallbacks.delete(key2);
1117
- },
1118
- []
1119
- );
1269
+ const useViewability2 = (configId, callback) => {
1270
+ useViewability(configId, callback);
1120
1271
  };
1121
- const useViewabilityAmount = (callback) => {
1122
- useInit(() => {
1123
- const value = ctx.mapViewabilityAmountValues.get(containerId);
1124
- if (value) {
1125
- callback(value);
1126
- }
1127
- });
1128
- ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
1129
- React4.useEffect(
1130
- () => () => {
1131
- ctx.mapViewabilityAmountCallbacks.delete(containerId);
1132
- },
1133
- []
1134
- );
1272
+ const useViewabilityAmount2 = (callback) => {
1273
+ useViewabilityAmount(callback);
1135
1274
  };
1136
- const useRecyclingEffect = (effect) => {
1137
- React4.useEffect(() => {
1138
- const state2 = refState.current;
1139
- let prevIndex = index;
1140
- let prevItem = state2.data[index];
1141
- const signal = `containerItemKey${containerId}`;
1142
- const run = () => {
1143
- const data3 = state2.data;
1144
- if (data3) {
1145
- const newKey = peek$(ctx, signal);
1146
- const newIndex = state2.indexByKey.get(newKey);
1147
- const newItem = data3[newIndex];
1148
- if (newItem) {
1149
- effect({
1150
- index: newIndex,
1151
- item: newItem,
1152
- prevIndex,
1153
- prevItem
1154
- });
1155
- }
1156
- prevIndex = newIndex;
1157
- prevItem = newItem;
1158
- }
1159
- };
1160
- run();
1161
- return listen$(ctx, signal, run);
1162
- }, []);
1275
+ const useRecyclingEffect2 = (effect) => {
1276
+ useRecyclingEffect(effect);
1163
1277
  };
1164
- const useRecyclingState = (valueOrFun) => {
1165
- const stateInfo = React4.useState(
1166
- () => typeof valueOrFun === "function" ? valueOrFun({
1167
- index,
1168
- item: refState.current.data[index],
1169
- prevIndex: void 0,
1170
- prevItem: void 0
1171
- }) : valueOrFun
1172
- );
1173
- useRecyclingEffect((state2) => {
1174
- const newState = typeof valueOrFun === "function" ? valueOrFun(state2) : valueOrFun;
1175
- stateInfo[1](newState);
1176
- });
1177
- return stateInfo;
1278
+ const useRecyclingState2 = (valueOrFun) => {
1279
+ return useRecyclingState(valueOrFun);
1178
1280
  };
1179
1281
  const renderedItem = (_b2 = (_a2 = refState.current).renderItem) == null ? void 0 : _b2.call(_a2, {
1180
1282
  item: data2[index],
1181
1283
  index,
1182
- useViewability,
1183
- useViewabilityAmount,
1184
- useRecyclingEffect,
1185
- useRecyclingState
1284
+ useViewability: useViewability2,
1285
+ useViewabilityAmount: useViewabilityAmount2,
1286
+ useRecyclingEffect: useRecyclingEffect2,
1287
+ useRecyclingState: useRecyclingState2
1186
1288
  });
1187
- return renderedItem;
1289
+ return { index, renderedItem };
1188
1290
  }, []);
1189
1291
  useInit(() => {
1190
1292
  var _a2;
@@ -1196,29 +1298,25 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1196
1298
  const averageItemSize = (_a2 = estimatedItemSize != null ? estimatedItemSize : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(0, data[0])) != null ? _a2 : DEFAULT_ITEM_SIZE;
1197
1299
  const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) * numColumnsProp;
1198
1300
  for (let i = 0; i < numContainers; i++) {
1199
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1301
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1200
1302
  set$(ctx, `containerColumn${i}`, -1);
1201
1303
  }
1202
1304
  set$(ctx, "numContainers", numContainers);
1203
1305
  set$(ctx, "numContainersPooled", numContainers * 2);
1204
1306
  calculateItemsInView(state.scrollVelocity);
1205
1307
  });
1206
- const updateItemSize = React4.useCallback((containerId, itemKey, size) => {
1308
+ const updateItemSize = React5.useCallback((containerId, itemKey, size) => {
1207
1309
  var _a2;
1208
1310
  const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
1209
1311
  if (!data2) {
1210
1312
  return;
1211
1313
  }
1212
1314
  const state = refState.current;
1213
- const { sizes, indexByKey, idsInFirstRender, columns, sizesLaidOut } = state;
1315
+ const { sizes, indexByKey, columns, sizesLaidOut } = state;
1214
1316
  const index = indexByKey.get(itemKey);
1215
1317
  const numColumns = peek$(ctx, "numColumns");
1216
1318
  const row = Math.floor(index / numColumns);
1217
1319
  const prevSize = getRowHeight(row);
1218
- const measured = peek$(ctx, `containerDidLayout${containerId}`);
1219
- if (!measured) {
1220
- state.layoutsPending.add(containerId);
1221
- }
1222
1320
  if (!prevSize || Math.abs(prevSize - size) > 0.5) {
1223
1321
  let diff;
1224
1322
  if (numColumns > 1) {
@@ -1260,11 +1358,14 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1260
1358
  addTotalSize(itemKey, diff, 0);
1261
1359
  doMaintainScrollAtEnd(true);
1262
1360
  const scrollVelocity = state.scrollVelocity;
1263
- if (!state.animFrameLayout && (Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1)) {
1264
- if (!peek$(ctx, `containerDidLayout${containerId}`)) {
1265
- state.animFrameLayout = requestAnimationFrame(() => {
1266
- state.animFrameLayout = null;
1267
- calculateItemsInView(state.scrollVelocity);
1361
+ if (!state.waitingForMicrotask && (Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1)) {
1362
+ if (!peek$(ctx, "containersDidLayout")) {
1363
+ state.waitingForMicrotask = true;
1364
+ queueMicrotask(() => {
1365
+ if (state.waitingForMicrotask) {
1366
+ state.waitingForMicrotask = false;
1367
+ calculateItemsInView(state.scrollVelocity);
1368
+ }
1268
1369
  });
1269
1370
  } else {
1270
1371
  calculateItemsInView(state.scrollVelocity);
@@ -1273,16 +1374,14 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1273
1374
  if (onItemSizeChanged) {
1274
1375
  onItemSizeChanged({ size, previous: prevSize, index, itemKey, itemData: data2[index] });
1275
1376
  }
1276
- } else {
1277
- set$(ctx, `containerDidLayout${containerId}`, true);
1278
1377
  }
1279
1378
  }, []);
1280
- const handleScrollDebounced = React4.useCallback((velocity) => {
1379
+ const handleScrollDebounced = React5.useCallback((velocity) => {
1281
1380
  calculateItemsInView(velocity);
1282
1381
  checkAtBottom();
1283
1382
  checkAtTop();
1284
1383
  }, []);
1285
- const onLayout = React4.useCallback((event) => {
1384
+ const onLayout = React5.useCallback((event) => {
1286
1385
  const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
1287
1386
  refState.current.scrollLength = scrollLength;
1288
1387
  doMaintainScrollAtEnd(false);
@@ -1299,7 +1398,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1299
1398
  }
1300
1399
  }
1301
1400
  }, []);
1302
- const handleScroll = React4.useCallback(
1401
+ const handleScroll = React5.useCallback(
1303
1402
  (event, fromSelf) => {
1304
1403
  var _a2, _b2, _c2;
1305
1404
  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) {
@@ -1341,7 +1440,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1341
1440
  },
1342
1441
  []
1343
1442
  );
1344
- React4.useImperativeHandle(
1443
+ React5.useImperativeHandle(
1345
1444
  forwardedRef,
1346
1445
  () => {
1347
1446
  const scrollToIndex = ({ index, animated }) => {
@@ -1370,7 +1469,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1370
1469
  },
1371
1470
  []
1372
1471
  );
1373
- return /* @__PURE__ */ React4__namespace.createElement(
1472
+ return /* @__PURE__ */ React5__namespace.createElement(
1374
1473
  ListComponent,
1375
1474
  {
1376
1475
  ...rest,
@@ -1395,9 +1494,14 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1395
1494
  ListEmptyComponent: data.length === 0 ? ListEmptyComponent : void 0,
1396
1495
  maintainVisibleContentPosition,
1397
1496
  scrollEventThrottle: scrollEventThrottle != null ? scrollEventThrottle : reactNative.Platform.OS === "web" ? 16 : void 0,
1497
+ waitForInitialLayout,
1398
1498
  style
1399
1499
  }
1400
1500
  );
1401
1501
  });
1402
1502
 
1403
1503
  exports.LegendList = LegendList;
1504
+ exports.useRecyclingEffect = useRecyclingEffect;
1505
+ exports.useRecyclingState = useRecyclingState;
1506
+ exports.useViewability = useViewability;
1507
+ exports.useViewabilityAmount = useViewabilityAmount;