@legendapp/list 1.0.0-beta.2 → 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,76 +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
211
  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);
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);
129
246
  }
130
247
  }
131
- },
132
- /* @__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]
133
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);
134
260
  };
135
261
  var useAnimatedValue = reactNative.useAnimatedValue || ((initialValue) => {
136
- return React4.useRef(new reactNative.Animated.Value(initialValue)).current;
262
+ return React5.useRef(new reactNative.Animated.Value(initialValue)).current;
137
263
  });
138
264
  function useValue$(key, getValue, key2) {
139
265
  var _a;
140
266
  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));
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));
144
270
  }, []);
145
271
  return animValue;
146
272
  }
147
273
 
148
274
  // src/Containers.tsx
149
- var Containers = React4__namespace.memo(function Containers2({
275
+ var Containers = React5__namespace.memo(function Containers2({
150
276
  horizontal,
151
277
  recycleItems,
152
278
  ItemSeparatorComponent,
@@ -156,17 +282,17 @@ var Containers = React4__namespace.memo(function Containers2({
156
282
  }) {
157
283
  const numContainers = use$("numContainersPooled");
158
284
  const animSize = useValue$("totalSize");
285
+ const animOpacity = waitForInitialLayout ? useValue$("containersDidLayout", (value) => value ? 1 : 0) : void 0;
159
286
  const containers = [];
160
287
  for (let i = 0; i < numContainers; i++) {
161
288
  containers.push(
162
- /* @__PURE__ */ React4__namespace.createElement(
289
+ /* @__PURE__ */ React5__namespace.createElement(
163
290
  Container,
164
291
  {
165
292
  id: i,
166
293
  key: i,
167
294
  recycleItems,
168
295
  horizontal,
169
- waitForInitialLayout,
170
296
  getRenderedItem,
171
297
  updateItemSize,
172
298
  ItemSeparatorComponent
@@ -174,21 +300,21 @@ var Containers = React4__namespace.memo(function Containers2({
174
300
  )
175
301
  );
176
302
  }
177
- const style = horizontal ? { width: animSize } : { height: animSize };
178
- 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);
179
305
  });
180
306
 
181
307
  // src/ListComponent.tsx
182
308
  var getComponent = (Component) => {
183
- if (React4__namespace.isValidElement(Component)) {
309
+ if (React5__namespace.isValidElement(Component)) {
184
310
  return Component;
185
311
  }
186
312
  if (Component) {
187
- return /* @__PURE__ */ React4__namespace.createElement(Component, null);
313
+ return /* @__PURE__ */ React5__namespace.createElement(Component, null);
188
314
  }
189
315
  return null;
190
316
  };
191
- var ListComponent = React4__namespace.memo(function ListComponent2({
317
+ var ListComponent = React5__namespace.memo(function ListComponent2({
192
318
  style,
193
319
  contentContainerStyle,
194
320
  horizontal,
@@ -215,12 +341,12 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
215
341
  const ctx = useStateContext();
216
342
  const animPaddingTop = useValue$("paddingTop");
217
343
  const animScrollAdjust = useValue$("scrollAdjust");
218
- const ScrollComponent = renderScrollComponent ? React4.useMemo(
219
- () => React4__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
344
+ const ScrollComponent = renderScrollComponent ? React5.useMemo(
345
+ () => React5__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
220
346
  [renderScrollComponent]
221
347
  ) : reactNative.ScrollView;
222
348
  const additionalSize = { marginTop: animScrollAdjust, paddingTop: animPaddingTop };
223
- return /* @__PURE__ */ React4__namespace.createElement(
349
+ return /* @__PURE__ */ React5__namespace.createElement(
224
350
  ScrollComponent,
225
351
  {
226
352
  ...rest,
@@ -238,8 +364,8 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
238
364
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
239
365
  ref: refScrollView
240
366
  },
241
- /* @__PURE__ */ React4__namespace.createElement(reactNative.Animated.View, { style: additionalSize }),
242
- ListHeaderComponent && /* @__PURE__ */ React4__namespace.createElement(
367
+ /* @__PURE__ */ React5__namespace.createElement(reactNative.Animated.View, { style: additionalSize }),
368
+ ListHeaderComponent && /* @__PURE__ */ React5__namespace.createElement(
243
369
  reactNative.Animated.View,
244
370
  {
245
371
  style: ListHeaderComponentStyle,
@@ -253,8 +379,8 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
253
379
  },
254
380
  getComponent(ListHeaderComponent)
255
381
  ),
256
- ListEmptyComponent && /* @__PURE__ */ React4__namespace.createElement(reactNative.Animated.View, { style: ListEmptyComponentStyle }, getComponent(ListEmptyComponent)),
257
- /* @__PURE__ */ React4__namespace.createElement(
382
+ ListEmptyComponent && /* @__PURE__ */ React5__namespace.createElement(reactNative.Animated.View, { style: ListEmptyComponentStyle }, getComponent(ListEmptyComponent)),
383
+ /* @__PURE__ */ React5__namespace.createElement(
258
384
  Containers,
259
385
  {
260
386
  horizontal,
@@ -265,7 +391,7 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
265
391
  updateItemSize
266
392
  }
267
393
  ),
268
- ListFooterComponent && /* @__PURE__ */ React4__namespace.createElement(reactNative.View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
394
+ ListFooterComponent && /* @__PURE__ */ React5__namespace.createElement(reactNative.View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
269
395
  );
270
396
  });
271
397
 
@@ -305,14 +431,6 @@ var ScrollAdjustHandler = class {
305
431
  return this.appliedAdjust;
306
432
  }
307
433
  };
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
434
 
317
435
  // src/viewability.ts
318
436
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
@@ -463,13 +581,12 @@ function maybeUpdateViewabilityCallback(ctx, configId, viewToken) {
463
581
 
464
582
  // src/LegendList.tsx
465
583
  var DEFAULT_DRAW_DISTANCE = 250;
466
- var POSITION_OUT_OF_VIEW = -1e7;
467
584
  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 }));
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 }));
470
587
  });
471
- var LegendListInner = React4.forwardRef(function LegendListInner2(props, forwardedRef) {
472
- var _a, _b, _c, _d;
588
+ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forwardedRef) {
589
+ var _a, _b, _c, _d, _e;
473
590
  const {
474
591
  data,
475
592
  initialScrollIndex,
@@ -495,15 +612,16 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
495
612
  onItemSizeChanged,
496
613
  scrollEventThrottle,
497
614
  refScrollView,
615
+ waitForInitialLayout = true,
498
616
  extraData,
499
617
  ...rest
500
618
  } = props;
501
619
  const { style, contentContainerStyle } = props;
502
620
  const ctx = useStateContext();
503
- const refScroller = React4.useRef(null);
621
+ const refScroller = React5.useRef(null);
504
622
  const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE;
505
623
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
506
- const refState = React4.useRef();
624
+ const refState = React5.useRef();
507
625
  const getId = (index) => {
508
626
  var _a2;
509
627
  const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
@@ -537,7 +655,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
537
655
  }
538
656
  return 0;
539
657
  };
540
- const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React4.useMemo(calculateInitialOffset, []);
658
+ const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React5.useMemo(calculateInitialOffset, []);
541
659
  if (!refState.current) {
542
660
  const initialScrollLength = reactNative.Dimensions.get("window")[horizontal ? "width" : "height"];
543
661
  refState.current = {
@@ -545,7 +663,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
545
663
  positions: /* @__PURE__ */ new Map(),
546
664
  columns: /* @__PURE__ */ new Map(),
547
665
  pendingAdjust: 0,
548
- animFrameLayout: null,
666
+ waitingForMicrotask: false,
549
667
  isStartReached: initialContentOffset < initialScrollLength * onStartReachedThreshold,
550
668
  isEndReached: false,
551
669
  isAtBottom: false,
@@ -578,7 +696,6 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
578
696
  belowAnchorElementPositions: void 0,
579
697
  rowHeights: /* @__PURE__ */ new Map(),
580
698
  startReachedBlockedByTimer: false,
581
- layoutsPending: /* @__PURE__ */ new Set(),
582
699
  scrollForNextCalculateItemsInView: void 0,
583
700
  enableScrollForNextCalculateItemsInView: true
584
701
  };
@@ -599,6 +716,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
599
716
  }
600
717
  }
601
718
  set$(ctx, "scrollAdjust", 0);
719
+ set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
602
720
  set$(ctx, "extraData", extraData);
603
721
  }
604
722
  const getAnchorElementIndex = () => {
@@ -609,7 +727,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
609
727
  }
610
728
  return void 0;
611
729
  };
612
- const addTotalSize = React4.useCallback((key, add, totalSizeBelowAnchor) => {
730
+ const addTotalSize = React5.useCallback((key, add, totalSizeBelowAnchor) => {
613
731
  const state = refState.current;
614
732
  const index = key === null ? 0 : state.indexByKey.get(key);
615
733
  let isAboveAnchor = false;
@@ -699,7 +817,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
699
817
  }
700
818
  return res;
701
819
  };
702
- const calculateItemsInView = React4.useCallback((speed) => {
820
+ const calculateItemsInView = React5.useCallback((speed) => {
703
821
  const state = refState.current;
704
822
  const {
705
823
  data: data2,
@@ -708,12 +826,10 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
708
826
  startBufferedId: startBufferedIdOrig,
709
827
  positions,
710
828
  columns,
711
- scrollAdjustHandler,
712
- layoutsPending
829
+ scrollAdjustHandler
713
830
  } = state;
714
- if (state.animFrameLayout) {
715
- cancelAnimationFrame(state.animFrameLayout);
716
- state.animFrameLayout = null;
831
+ if (state.waitingForMicrotask) {
832
+ state.waitingForMicrotask = false;
717
833
  }
718
834
  if (!data2) {
719
835
  return;
@@ -855,7 +971,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
855
971
  break;
856
972
  }
857
973
  const index = state.indexByKey.get(key);
858
- const pos = peek$(ctx, `containerPosition${u}`);
974
+ const pos = peek$(ctx, `containerPosition${u}`).top;
859
975
  if (index < startBuffered || index > endBuffered) {
860
976
  const distance = Math.abs(pos - top2);
861
977
  if (index < 0 || distance > furthestDistance) {
@@ -874,7 +990,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
874
990
  set$(ctx, `containerItemKey${containerId}`, id);
875
991
  const index = state.indexByKey.get(id);
876
992
  set$(ctx, `containerItemData${containerId}`, data2[index]);
877
- set$(ctx, `containerPosition${containerId}`, POSITION_OUT_OF_VIEW);
993
+ set$(ctx, `containerPosition${containerId}`, ANCHORED_POSITION_OUT_OF_VIEW);
878
994
  set$(ctx, `containerColumn${containerId}`, -1);
879
995
  if (__DEV__ && numContainers > peek$(ctx, "numContainersPooled")) {
880
996
  console.warn(
@@ -898,19 +1014,31 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
898
1014
  if (item) {
899
1015
  const id = getId(itemIndex);
900
1016
  if (itemKey !== id || itemIndex < startBuffered || itemIndex > endBuffered) {
901
- const prevPos = peek$(ctx, `containerPosition${i}`);
1017
+ const prevPos = peek$(ctx, `containerPosition${i}`).top;
902
1018
  const pos = positions.get(id) || 0;
903
1019
  const size = getItemSize(id, itemIndex, data2[i]);
904
1020
  if (pos + size >= scroll && pos <= scrollBottom || prevPos + size >= scroll && prevPos <= scrollBottom) {
905
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1021
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
906
1022
  }
907
1023
  } else {
908
- 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
+ };
909
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
+ }
910
1038
  const prevPos = peek$(ctx, `containerPosition${i}`);
911
1039
  const prevColumn = peek$(ctx, `containerColumn${i}`);
912
1040
  const prevData = peek$(ctx, `containerItemData${i}`);
913
- if (pos > POSITION_OUT_OF_VIEW && pos !== prevPos) {
1041
+ if (pos.relativeCoordinate > POSITION_OUT_OF_VIEW && pos.top !== prevPos.top) {
914
1042
  set$(ctx, `containerPosition${i}`, pos);
915
1043
  }
916
1044
  if (column2 >= 0 && column2 !== prevColumn) {
@@ -923,12 +1051,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
923
1051
  }
924
1052
  }
925
1053
  }
926
- if (layoutsPending.size > 0) {
927
- for (const containerId of layoutsPending) {
928
- set$(ctx, `containerDidLayout${containerId}`, true);
929
- }
930
- layoutsPending.clear();
931
- }
1054
+ set$(ctx, "containersDidLayout", true);
932
1055
  if (state.viewabilityConfigCallbackPairs) {
933
1056
  updateViewableItems(
934
1057
  state,
@@ -1021,13 +1144,13 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1021
1144
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1022
1145
  if (!keyExtractorProp || itemKey && state.indexByKey.get(itemKey) === void 0) {
1023
1146
  set$(ctx, `containerItemKey${i}`, void 0);
1024
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1147
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1025
1148
  set$(ctx, `containerColumn${i}`, -1);
1026
1149
  }
1027
1150
  }
1028
1151
  if (!keyExtractorProp) {
1029
1152
  state.sizes.clear();
1030
- state.positions;
1153
+ state.positions.clear();
1031
1154
  }
1032
1155
  calculateItemsInView(state.scrollVelocity);
1033
1156
  }
@@ -1049,13 +1172,48 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1049
1172
  let totalSize = 0;
1050
1173
  let totalSizeBelowIndex = 0;
1051
1174
  const indexByKey = /* @__PURE__ */ new Map();
1175
+ const newPositions = /* @__PURE__ */ new Map();
1052
1176
  let column = 1;
1053
1177
  let maxSizeInRow = 0;
1054
1178
  for (let i = 0; i < data.length; i++) {
1055
1179
  const key = getId(i);
1056
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
+ }
1057
1184
  }
1058
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
+ }
1059
1217
  const anchorElementIndex = getAnchorElementIndex();
1060
1218
  for (let i = 0; i < data.length; i++) {
1061
1219
  const key = getId(i);
@@ -1076,18 +1234,18 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1076
1234
  }
1077
1235
  addTotalSize(null, totalSize, totalSizeBelowIndex);
1078
1236
  }
1079
- React4.useEffect(() => {
1237
+ React5.useEffect(() => {
1080
1238
  checkResetContainers(
1081
1239
  /*reset*/
1082
1240
  !isFirst
1083
1241
  );
1084
1242
  }, [isFirst, data, numColumnsProp]);
1085
- React4.useEffect(() => {
1243
+ React5.useEffect(() => {
1086
1244
  set$(ctx, "extraData", extraData);
1087
1245
  }, [extraData]);
1088
1246
  refState.current.renderItem = renderItem;
1089
1247
  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 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
1249
  const initalizeStateVars = () => {
1092
1250
  set$(ctx, "lastItemKey", lastItemKey);
1093
1251
  set$(ctx, "numColumns", numColumnsProp);
@@ -1096,8 +1254,8 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1096
1254
  if (isFirst) {
1097
1255
  initalizeStateVars();
1098
1256
  }
1099
- React4.useEffect(initalizeStateVars, [lastItemKey, numColumnsProp, stylePaddingTop]);
1100
- const getRenderedItem = React4.useCallback((key, containerId) => {
1257
+ React5.useEffect(initalizeStateVars, [lastItemKey, numColumnsProp, stylePaddingTop]);
1258
+ const getRenderedItem = React5.useCallback((key) => {
1101
1259
  var _a2, _b2;
1102
1260
  const state = refState.current;
1103
1261
  if (!state) {
@@ -1108,89 +1266,27 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1108
1266
  if (index === void 0) {
1109
1267
  return null;
1110
1268
  }
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
- );
1269
+ const useViewability2 = (configId, callback) => {
1270
+ useViewability(configId, callback);
1126
1271
  };
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
- );
1272
+ const useViewabilityAmount2 = (callback) => {
1273
+ useViewabilityAmount(callback);
1141
1274
  };
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
- }, []);
1275
+ const useRecyclingEffect2 = (effect) => {
1276
+ useRecyclingEffect(effect);
1169
1277
  };
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;
1278
+ const useRecyclingState2 = (valueOrFun) => {
1279
+ return useRecyclingState(valueOrFun);
1184
1280
  };
1185
1281
  const renderedItem = (_b2 = (_a2 = refState.current).renderItem) == null ? void 0 : _b2.call(_a2, {
1186
1282
  item: data2[index],
1187
1283
  index,
1188
- useViewability,
1189
- useViewabilityAmount,
1190
- useRecyclingEffect,
1191
- useRecyclingState
1284
+ useViewability: useViewability2,
1285
+ useViewabilityAmount: useViewabilityAmount2,
1286
+ useRecyclingEffect: useRecyclingEffect2,
1287
+ useRecyclingState: useRecyclingState2
1192
1288
  });
1193
- return renderedItem;
1289
+ return { index, renderedItem };
1194
1290
  }, []);
1195
1291
  useInit(() => {
1196
1292
  var _a2;
@@ -1202,29 +1298,25 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1202
1298
  const averageItemSize = (_a2 = estimatedItemSize != null ? estimatedItemSize : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(0, data[0])) != null ? _a2 : DEFAULT_ITEM_SIZE;
1203
1299
  const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) * numColumnsProp;
1204
1300
  for (let i = 0; i < numContainers; i++) {
1205
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1301
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1206
1302
  set$(ctx, `containerColumn${i}`, -1);
1207
1303
  }
1208
1304
  set$(ctx, "numContainers", numContainers);
1209
1305
  set$(ctx, "numContainersPooled", numContainers * 2);
1210
1306
  calculateItemsInView(state.scrollVelocity);
1211
1307
  });
1212
- const updateItemSize = React4.useCallback((containerId, itemKey, size) => {
1308
+ const updateItemSize = React5.useCallback((containerId, itemKey, size) => {
1213
1309
  var _a2;
1214
1310
  const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
1215
1311
  if (!data2) {
1216
1312
  return;
1217
1313
  }
1218
1314
  const state = refState.current;
1219
- const { sizes, indexByKey, idsInFirstRender, columns, sizesLaidOut } = state;
1315
+ const { sizes, indexByKey, columns, sizesLaidOut } = state;
1220
1316
  const index = indexByKey.get(itemKey);
1221
1317
  const numColumns = peek$(ctx, "numColumns");
1222
1318
  const row = Math.floor(index / numColumns);
1223
1319
  const prevSize = getRowHeight(row);
1224
- const measured = peek$(ctx, `containerDidLayout${containerId}`);
1225
- if (!measured) {
1226
- state.layoutsPending.add(containerId);
1227
- }
1228
1320
  if (!prevSize || Math.abs(prevSize - size) > 0.5) {
1229
1321
  let diff;
1230
1322
  if (numColumns > 1) {
@@ -1266,11 +1358,14 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1266
1358
  addTotalSize(itemKey, diff, 0);
1267
1359
  doMaintainScrollAtEnd(true);
1268
1360
  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);
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
+ }
1274
1369
  });
1275
1370
  } else {
1276
1371
  calculateItemsInView(state.scrollVelocity);
@@ -1279,16 +1374,14 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1279
1374
  if (onItemSizeChanged) {
1280
1375
  onItemSizeChanged({ size, previous: prevSize, index, itemKey, itemData: data2[index] });
1281
1376
  }
1282
- } else {
1283
- set$(ctx, `containerDidLayout${containerId}`, true);
1284
1377
  }
1285
1378
  }, []);
1286
- const handleScrollDebounced = React4.useCallback((velocity) => {
1379
+ const handleScrollDebounced = React5.useCallback((velocity) => {
1287
1380
  calculateItemsInView(velocity);
1288
1381
  checkAtBottom();
1289
1382
  checkAtTop();
1290
1383
  }, []);
1291
- const onLayout = React4.useCallback((event) => {
1384
+ const onLayout = React5.useCallback((event) => {
1292
1385
  const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
1293
1386
  refState.current.scrollLength = scrollLength;
1294
1387
  doMaintainScrollAtEnd(false);
@@ -1305,7 +1398,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1305
1398
  }
1306
1399
  }
1307
1400
  }, []);
1308
- const handleScroll = React4.useCallback(
1401
+ const handleScroll = React5.useCallback(
1309
1402
  (event, fromSelf) => {
1310
1403
  var _a2, _b2, _c2;
1311
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) {
@@ -1347,7 +1440,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1347
1440
  },
1348
1441
  []
1349
1442
  );
1350
- React4.useImperativeHandle(
1443
+ React5.useImperativeHandle(
1351
1444
  forwardedRef,
1352
1445
  () => {
1353
1446
  const scrollToIndex = ({ index, animated }) => {
@@ -1376,7 +1469,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1376
1469
  },
1377
1470
  []
1378
1471
  );
1379
- return /* @__PURE__ */ React4__namespace.createElement(
1472
+ return /* @__PURE__ */ React5__namespace.createElement(
1380
1473
  ListComponent,
1381
1474
  {
1382
1475
  ...rest,
@@ -1401,9 +1494,14 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1401
1494
  ListEmptyComponent: data.length === 0 ? ListEmptyComponent : void 0,
1402
1495
  maintainVisibleContentPosition,
1403
1496
  scrollEventThrottle: scrollEventThrottle != null ? scrollEventThrottle : reactNative.Platform.OS === "web" ? 16 : void 0,
1497
+ waitForInitialLayout,
1404
1498
  style
1405
1499
  }
1406
1500
  );
1407
1501
  });
1408
1502
 
1409
1503
  exports.LegendList = LegendList;
1504
+ exports.useRecyclingEffect = useRecyclingEffect;
1505
+ exports.useRecyclingState = useRecyclingState;
1506
+ exports.useViewability = useViewability;
1507
+ exports.useViewabilityAmount = useViewabilityAmount;