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

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 React5 = require('react');
3
+ var React6 = require('react');
4
4
  var reactNative = require('react-native');
5
5
 
6
6
  function _interopNamespace(e) {
@@ -21,23 +21,24 @@ function _interopNamespace(e) {
21
21
  return Object.freeze(n);
22
22
  }
23
23
 
24
- var React5__namespace = /*#__PURE__*/_interopNamespace(React5);
24
+ var React6__namespace = /*#__PURE__*/_interopNamespace(React6);
25
25
 
26
26
  // src/LegendList.tsx
27
- var ContextState = React5__namespace.createContext(null);
27
+ var ContextState = React6__namespace.createContext(null);
28
28
  function StateProvider({ children }) {
29
- const [value] = React5__namespace.useState(() => ({
29
+ const [value] = React6__namespace.useState(() => ({
30
30
  listeners: /* @__PURE__ */ new Map(),
31
31
  values: /* @__PURE__ */ new Map(),
32
32
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
33
33
  mapViewabilityValues: /* @__PURE__ */ new Map(),
34
34
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
35
- mapViewabilityAmountValues: /* @__PURE__ */ new Map()
35
+ mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
36
+ columnWrapperStyle: void 0
36
37
  }));
37
- return /* @__PURE__ */ React5__namespace.createElement(ContextState.Provider, { value }, children);
38
+ return /* @__PURE__ */ React6__namespace.createElement(ContextState.Provider, { value }, children);
38
39
  }
39
40
  function useStateContext() {
40
- return React5__namespace.useContext(ContextState);
41
+ return React6__namespace.useContext(ContextState);
41
42
  }
42
43
  function createSelectorFunctions(ctx, signalName) {
43
44
  return {
@@ -46,9 +47,9 @@ function createSelectorFunctions(ctx, signalName) {
46
47
  };
47
48
  }
48
49
  function use$(signalName) {
49
- const ctx = React5__namespace.useContext(ContextState);
50
- const { subscribe, get } = React5__namespace.useMemo(() => createSelectorFunctions(ctx, signalName), []);
51
- const value = React5.useSyncExternalStore(subscribe, get);
50
+ const ctx = React6__namespace.useContext(ContextState);
51
+ const { subscribe, get } = React6__namespace.useMemo(() => createSelectorFunctions(ctx, signalName), []);
52
+ const value = React6.useSyncExternalStore(subscribe, get);
52
53
  return value;
53
54
  }
54
55
  function listen$(ctx, signalName, cb) {
@@ -77,9 +78,17 @@ function set$(ctx, signalName, value) {
77
78
  }
78
79
  }
79
80
  }
81
+ function getContentSize(ctx) {
82
+ const { values } = ctx;
83
+ const stylePaddingTop = values.get("stylePaddingTop") || 0;
84
+ const headerSize = values.get("headerSize") || 0;
85
+ const footerSize = values.get("footerSize") || 0;
86
+ const totalSize = values.get("totalSize") || 0;
87
+ return headerSize + footerSize + totalSize + stylePaddingTop;
88
+ }
80
89
  var symbolFirst = Symbol();
81
90
  function useInit(cb) {
82
- const refValue = React5.useRef(symbolFirst);
91
+ const refValue = React6.useRef(symbolFirst);
83
92
  if (refValue.current === symbolFirst) {
84
93
  refValue.current = cb();
85
94
  }
@@ -87,10 +96,10 @@ function useInit(cb) {
87
96
  }
88
97
 
89
98
  // src/ContextContainer.ts
90
- var ContextContainer = React5.createContext(null);
99
+ var ContextContainer = React6.createContext(null);
91
100
  function useViewability(configId, callback) {
92
101
  const ctx = useStateContext();
93
- const { containerId } = React5.useContext(ContextContainer);
102
+ const { containerId } = React6.useContext(ContextContainer);
94
103
  const key = containerId + configId;
95
104
  useInit(() => {
96
105
  const value = ctx.mapViewabilityValues.get(key);
@@ -99,7 +108,7 @@ function useViewability(configId, callback) {
99
108
  }
100
109
  });
101
110
  ctx.mapViewabilityCallbacks.set(key, callback);
102
- React5.useEffect(
111
+ React6.useEffect(
103
112
  () => () => {
104
113
  ctx.mapViewabilityCallbacks.delete(key);
105
114
  },
@@ -108,7 +117,7 @@ function useViewability(configId, callback) {
108
117
  }
109
118
  function useViewabilityAmount(callback) {
110
119
  const ctx = useStateContext();
111
- const { containerId } = React5.useContext(ContextContainer);
120
+ const { containerId } = React6.useContext(ContextContainer);
112
121
  useInit(() => {
113
122
  const value = ctx.mapViewabilityAmountValues.get(containerId);
114
123
  if (value) {
@@ -116,7 +125,7 @@ function useViewabilityAmount(callback) {
116
125
  }
117
126
  });
118
127
  ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
119
- React5.useEffect(
128
+ React6.useEffect(
120
129
  () => () => {
121
130
  ctx.mapViewabilityAmountCallbacks.delete(containerId);
122
131
  },
@@ -124,12 +133,12 @@ function useViewabilityAmount(callback) {
124
133
  );
125
134
  }
126
135
  function useRecyclingEffect(effect) {
127
- const { index, value } = React5.useContext(ContextContainer);
128
- const prevValues = React5.useRef({
136
+ const { index, value } = React6.useContext(ContextContainer);
137
+ const prevValues = React6.useRef({
129
138
  prevIndex: void 0,
130
139
  prevItem: void 0
131
140
  });
132
- React5.useEffect(() => {
141
+ React6.useEffect(() => {
133
142
  let ret = void 0;
134
143
  if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
135
144
  ret = effect({
@@ -147,8 +156,8 @@ function useRecyclingEffect(effect) {
147
156
  }, [index, value]);
148
157
  }
149
158
  function useRecyclingState(valueOrFun) {
150
- const { index, value } = React5.useContext(ContextContainer);
151
- const stateInfo = React5.useState(
159
+ const { index, value } = React6.useContext(ContextContainer);
160
+ const stateInfo = React6.useState(
152
161
  () => typeof valueOrFun === "function" ? valueOrFun({
153
162
  index,
154
163
  item: value,
@@ -162,10 +171,61 @@ function useRecyclingState(valueOrFun) {
162
171
  });
163
172
  return stateInfo;
164
173
  }
165
- var LeanView = React5__namespace.forwardRef((props, ref) => {
166
- return React5__namespace.createElement("RCTView", { ...props, ref });
174
+ var DebugRow = ({ children }) => {
175
+ return /* @__PURE__ */ React.createElement(reactNative.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" } }, children);
176
+ };
177
+ var DebugView = React6.memo(function DebugView2({ state }) {
178
+ const ctx = useStateContext();
179
+ const totalSize = use$("totalSize") || 0;
180
+ const totalSizeWithScrollAdjust = use$("totalSizeWithScrollAdjust") || 0;
181
+ const scrollAdjust = use$("scrollAdjust") || 0;
182
+ const rawScroll = use$("debugRawScroll") || 0;
183
+ const scroll = use$("debugComputedScroll") || 0;
184
+ const contentSize = getContentSize(ctx);
185
+ const [, forceUpdate] = React6.useReducer((x) => x + 1, 0);
186
+ use$("numContainers");
187
+ use$("numContainersPooled");
188
+ useInterval(() => {
189
+ forceUpdate();
190
+ }, 100);
191
+ return /* @__PURE__ */ React.createElement(
192
+ reactNative.View,
193
+ {
194
+ style: {
195
+ position: "absolute",
196
+ top: 0,
197
+ right: 0,
198
+ paddingLeft: 4,
199
+ paddingBottom: 4,
200
+ // height: 100,
201
+ backgroundColor: "#FFFFFFCC",
202
+ padding: 4,
203
+ borderRadius: 4
204
+ },
205
+ pointerEvents: "none"
206
+ },
207
+ /* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "TotalSize:"), /* @__PURE__ */ React.createElement(reactNative.Text, null, totalSize.toFixed(2))),
208
+ /* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "ContentSize:"), /* @__PURE__ */ React.createElement(reactNative.Text, null, contentSize.toFixed(2))),
209
+ /* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "At end:"), /* @__PURE__ */ React.createElement(reactNative.Text, null, String(state.isAtBottom))),
210
+ /* @__PURE__ */ React.createElement(reactNative.Text, null),
211
+ /* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "ScrollAdjust:"), /* @__PURE__ */ React.createElement(reactNative.Text, null, scrollAdjust.toFixed(2))),
212
+ /* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "TotalSizeReal: "), /* @__PURE__ */ React.createElement(reactNative.Text, null, totalSizeWithScrollAdjust.toFixed(2))),
213
+ /* @__PURE__ */ React.createElement(reactNative.Text, null),
214
+ /* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "RawScroll: "), /* @__PURE__ */ React.createElement(reactNative.Text, null, rawScroll.toFixed(2))),
215
+ /* @__PURE__ */ React.createElement(DebugRow, null, /* @__PURE__ */ React.createElement(reactNative.Text, null, "ComputedScroll: "), /* @__PURE__ */ React.createElement(reactNative.Text, null, scroll.toFixed(2)))
216
+ );
167
217
  });
168
- LeanView.displayName = "RCTView";
218
+ function useInterval(callback, delay) {
219
+ React6.useEffect(() => {
220
+ const interval = setInterval(callback, delay);
221
+ return () => clearInterval(interval);
222
+ }, [delay]);
223
+ }
224
+ var LeanViewComponent = React6__namespace.forwardRef((props, ref) => {
225
+ return React6__namespace.createElement("RCTView", { ...props, ref });
226
+ });
227
+ LeanViewComponent.displayName = "RCTView";
228
+ var LeanView = reactNative.Platform.OS === "android" || reactNative.Platform.OS === "ios" ? LeanViewComponent : reactNative.View;
169
229
 
170
230
  // src/constants.ts
171
231
  var POSITION_OUT_OF_VIEW = -1e7;
@@ -174,8 +234,11 @@ var ANCHORED_POSITION_OUT_OF_VIEW = {
174
234
  relativeCoordinate: POSITION_OUT_OF_VIEW,
175
235
  top: POSITION_OUT_OF_VIEW
176
236
  };
237
+ var ENABLE_DEVMODE = __DEV__ && false;
238
+ var ENABLE_DEBUG_VIEW = __DEV__ && false;
177
239
 
178
240
  // src/Container.tsx
241
+ var isNewArchitecture = global.nativeFabricUIManager != null;
179
242
  var Container = ({
180
243
  id,
181
244
  recycleItems,
@@ -185,12 +248,26 @@ var Container = ({
185
248
  ItemSeparatorComponent
186
249
  }) => {
187
250
  const ctx = useStateContext();
251
+ const columnWrapperStyle = ctx.columnWrapperStyle;
188
252
  const maintainVisibleContentPosition = use$("maintainVisibleContentPosition");
189
253
  const position = use$(`containerPosition${id}`) || ANCHORED_POSITION_OUT_OF_VIEW;
190
254
  const column = use$(`containerColumn${id}`) || 0;
191
255
  const numColumns = use$("numColumns");
256
+ const lastItemKeys = use$("lastItemKeys");
257
+ const itemKey = use$(`containerItemKey${id}`);
258
+ const data = use$(`containerItemData${id}`);
259
+ const extraData = use$("extraData");
260
+ const refLastSize = React6.useRef();
192
261
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
193
262
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
263
+ let verticalPaddingStyles;
264
+ if (columnWrapperStyle && !horizontal && numColumns > 1) {
265
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
266
+ verticalPaddingStyles = {
267
+ paddingBottom: !lastItemKeys.includes(itemKey) ? rowGap || gap || void 0 : void 0,
268
+ paddingHorizontal: (columnGap || gap || 0) / 2
269
+ };
270
+ }
194
271
  const style = horizontal ? {
195
272
  flexDirection: ItemSeparatorComponent ? "row" : void 0,
196
273
  position: "absolute",
@@ -203,76 +280,96 @@ var Container = ({
203
280
  left: otherAxisPos,
204
281
  right: numColumns > 1 ? null : 0,
205
282
  width: otherAxisSize,
206
- top: position.relativeCoordinate
283
+ top: position.relativeCoordinate,
284
+ ...verticalPaddingStyles || {}
207
285
  };
208
- const lastItemKey = use$("lastItemKey");
209
- const itemKey = use$(`containerItemKey${id}`);
210
- const data = use$(`containerItemData${id}`);
211
- const extraData = use$("extraData");
212
- const refLastSize = React5.useRef();
213
- const renderedItemInfo = React5.useMemo(
214
- () => itemKey !== void 0 && getRenderedItem(itemKey),
286
+ const renderedItemInfo = React6.useMemo(
287
+ () => itemKey !== void 0 ? getRenderedItem(itemKey) : null,
215
288
  [itemKey, data, extraData]
216
289
  );
217
290
  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
291
  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);
292
+ if (itemKey !== void 0) {
293
+ const layout = event.nativeEvent.layout;
294
+ const size = Math.floor(layout[horizontal ? "width" : "height"] * 8) / 8;
295
+ refLastSize.current = size;
296
+ updateItemSize(itemKey, size);
235
297
  }
236
298
  };
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);
299
+ const ref = React6.useRef(null);
300
+ if (isNewArchitecture) {
301
+ React6.useLayoutEffect(() => {
302
+ var _a, _b;
303
+ if (itemKey !== void 0) {
304
+ const measured = (_b = (_a = ref.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
305
+ if (measured) {
306
+ const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
307
+ if (size) {
308
+ updateItemSize(itemKey, size);
309
+ }
246
310
  }
247
311
  }
248
- }
249
- }, [itemKey]);
250
- const contextValue = React5.useMemo(
312
+ }, [itemKey]);
313
+ } else {
314
+ React6.useEffect(() => {
315
+ if (itemKey) {
316
+ const timeout = setTimeout(() => {
317
+ if (refLastSize.current) {
318
+ updateItemSize(itemKey, refLastSize.current);
319
+ }
320
+ }, 16);
321
+ return () => {
322
+ clearTimeout(timeout);
323
+ };
324
+ }
325
+ }, [itemKey]);
326
+ }
327
+ const contextValue = React6.useMemo(
251
328
  () => ({ containerId: id, itemKey, index, value: data }),
252
329
  [id, itemKey, index, data]
253
330
  );
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));
331
+ const contentFragment = /* @__PURE__ */ React6__namespace.default.createElement(React6__namespace.default.Fragment, { key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React6__namespace.default.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && !lastItemKeys.includes(itemKey) && /* @__PURE__ */ React6__namespace.default.createElement(ItemSeparatorComponent, { leadingItem: renderedItemInfo.item })));
255
332
  if (maintainVisibleContentPosition) {
256
333
  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));
334
+ if (ENABLE_DEVMODE) {
335
+ anchorStyle.borderColor = position.type === "top" ? "red" : "blue";
336
+ anchorStyle.borderWidth = 1;
337
+ }
338
+ return /* @__PURE__ */ React6__namespace.default.createElement(LeanView, { style }, /* @__PURE__ */ React6__namespace.default.createElement(LeanView, { style: anchorStyle, onLayout, ref }, contentFragment, ENABLE_DEVMODE && /* @__PURE__ */ React6__namespace.default.createElement(reactNative.Text, { style: { position: "absolute", top: 0, left: 0, zIndex: 1e3 } }, position.top)));
258
339
  }
259
- return /* @__PURE__ */ React5__namespace.default.createElement(LeanView, { style, onLayout, ref }, contentFragment);
340
+ return /* @__PURE__ */ React6__namespace.default.createElement(LeanView, { style, onLayout, ref }, contentFragment);
260
341
  };
261
- var useAnimatedValue = reactNative.useAnimatedValue || ((initialValue) => {
262
- return React5.useRef(new reactNative.Animated.Value(initialValue)).current;
263
- });
264
- function useValue$(key, getValue, key2) {
342
+ var typedForwardRef = React6.forwardRef;
343
+ var typedMemo = React6.memo;
344
+ var useAnimatedValue = (initialValue) => {
345
+ return React6.useRef(new reactNative.Animated.Value(initialValue)).current;
346
+ };
347
+
348
+ // src/useValue$.ts
349
+ function useValue$(key, getValue, useMicrotask) {
265
350
  var _a;
266
351
  const ctx = useStateContext();
267
352
  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));
353
+ React6.useMemo(() => {
354
+ let newValue = void 0;
355
+ listen$(ctx, key, (v) => {
356
+ if (useMicrotask && newValue === void 0) {
357
+ queueMicrotask(() => {
358
+ animValue.setValue(newValue);
359
+ newValue = void 0;
360
+ });
361
+ }
362
+ newValue = getValue ? getValue(v) : v;
363
+ if (!useMicrotask) {
364
+ animValue.setValue(newValue);
365
+ }
366
+ });
270
367
  }, []);
271
368
  return animValue;
272
369
  }
273
370
 
274
371
  // src/Containers.tsx
275
- var Containers = React5__namespace.memo(function Containers2({
372
+ var Containers = typedMemo(function Containers2({
276
373
  horizontal,
277
374
  recycleItems,
278
375
  ItemSeparatorComponent,
@@ -280,13 +377,21 @@ var Containers = React5__namespace.memo(function Containers2({
280
377
  updateItemSize,
281
378
  getRenderedItem
282
379
  }) {
380
+ const ctx = useStateContext();
381
+ const columnWrapperStyle = ctx.columnWrapperStyle;
382
+ const numColumns = use$("numColumns");
283
383
  const numContainers = use$("numContainersPooled");
284
- const animSize = useValue$("totalSize");
384
+ const animSize = useValue$(
385
+ "totalSizeWithScrollAdjust",
386
+ void 0,
387
+ /*useMicrotask*/
388
+ true
389
+ );
285
390
  const animOpacity = waitForInitialLayout ? useValue$("containersDidLayout", (value) => value ? 1 : 0) : void 0;
286
391
  const containers = [];
287
392
  for (let i = 0; i < numContainers; i++) {
288
393
  containers.push(
289
- /* @__PURE__ */ React5__namespace.createElement(
394
+ /* @__PURE__ */ React6__namespace.createElement(
290
395
  Container,
291
396
  {
292
397
  id: i,
@@ -301,20 +406,78 @@ var Containers = React5__namespace.memo(function Containers2({
301
406
  );
302
407
  }
303
408
  const style = horizontal ? { width: animSize, opacity: animOpacity } : { height: animSize, opacity: animOpacity };
304
- return /* @__PURE__ */ React5__namespace.createElement(reactNative.Animated.View, { style }, containers);
409
+ if (columnWrapperStyle && !horizontal && numColumns > 1) {
410
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
411
+ const mx = (columnGap || gap || 0) / 2;
412
+ if (mx) {
413
+ style.marginHorizontal = -mx;
414
+ }
415
+ }
416
+ return /* @__PURE__ */ React6__namespace.createElement(reactNative.Animated.View, { style }, containers);
305
417
  });
306
418
 
307
419
  // src/ListComponent.tsx
308
420
  var getComponent = (Component) => {
309
- if (React5__namespace.isValidElement(Component)) {
421
+ if (React6__namespace.isValidElement(Component)) {
310
422
  return Component;
311
423
  }
312
424
  if (Component) {
313
- return /* @__PURE__ */ React5__namespace.createElement(Component, null);
425
+ return /* @__PURE__ */ React6__namespace.createElement(Component, null);
314
426
  }
315
427
  return null;
316
428
  };
317
- var ListComponent = React5__namespace.memo(function ListComponent2({
429
+ var PaddingAndAdjust = () => {
430
+ const animPaddingTop = useValue$("paddingTop", (v) => v, true);
431
+ const animScrollAdjust = useValue$("scrollAdjust", (v) => v, true);
432
+ const additionalSize = { marginTop: animScrollAdjust, paddingTop: animPaddingTop };
433
+ return /* @__PURE__ */ React6__namespace.createElement(reactNative.Animated.View, { style: additionalSize });
434
+ };
435
+ var PaddingAndAdjustDevMode = () => {
436
+ const animPaddingTop = useValue$("paddingTop", (v) => v, true);
437
+ const animScrollAdjust = useValue$("scrollAdjust", (v) => v, true);
438
+ return /* @__PURE__ */ React6__namespace.createElement(React6__namespace.Fragment, null, /* @__PURE__ */ React6__namespace.createElement(reactNative.Animated.View, { style: { marginTop: animScrollAdjust } }), /* @__PURE__ */ React6__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React6__namespace.createElement(
439
+ reactNative.Animated.View,
440
+ {
441
+ style: {
442
+ position: "absolute",
443
+ top: reactNative.Animated.add(animScrollAdjust, reactNative.Animated.multiply(animScrollAdjust, -1)),
444
+ height: animPaddingTop,
445
+ left: 0,
446
+ right: 0,
447
+ backgroundColor: "green"
448
+ }
449
+ }
450
+ ), /* @__PURE__ */ React6__namespace.createElement(
451
+ reactNative.Animated.View,
452
+ {
453
+ style: {
454
+ position: "absolute",
455
+ top: animPaddingTop,
456
+ height: animScrollAdjust,
457
+ left: -16,
458
+ right: -16,
459
+ backgroundColor: "lightblue"
460
+ }
461
+ }
462
+ ), /* @__PURE__ */ React6__namespace.createElement(
463
+ reactNative.Animated.View,
464
+ {
465
+ style: {
466
+ position: "absolute",
467
+ top: animPaddingTop,
468
+ height: reactNative.Animated.multiply(animScrollAdjust, -1),
469
+ width: 8,
470
+ right: 4,
471
+ borderStyle: "dashed",
472
+ borderColor: "blue",
473
+ borderWidth: 1,
474
+ backgroundColor: "lightblue"
475
+ //backgroundColor: "blue",
476
+ }
477
+ }
478
+ ));
479
+ };
480
+ var ListComponent = typedMemo(function ListComponent2({
318
481
  style,
319
482
  contentContainerStyle,
320
483
  horizontal,
@@ -330,28 +493,27 @@ var ListComponent = React5__namespace.memo(function ListComponent2({
330
493
  ListFooterComponent,
331
494
  ListFooterComponentStyle,
332
495
  ListEmptyComponent,
333
- ListEmptyComponentStyle,
334
496
  getRenderedItem,
335
497
  updateItemSize,
336
498
  refScrollView,
337
499
  maintainVisibleContentPosition,
338
500
  renderScrollComponent,
501
+ onRefresh,
502
+ refreshing,
503
+ progressViewOffset,
339
504
  ...rest
340
505
  }) {
341
506
  const ctx = useStateContext();
342
- const animPaddingTop = useValue$("paddingTop");
343
- const animScrollAdjust = useValue$("scrollAdjust");
344
- const ScrollComponent = renderScrollComponent ? React5.useMemo(
345
- () => React5__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
507
+ const ScrollComponent = renderScrollComponent ? React6.useMemo(
508
+ () => React6__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
346
509
  [renderScrollComponent]
347
510
  ) : reactNative.ScrollView;
348
- const additionalSize = { marginTop: animScrollAdjust, paddingTop: animPaddingTop };
349
- return /* @__PURE__ */ React5__namespace.createElement(
511
+ return /* @__PURE__ */ React6__namespace.createElement(
350
512
  ScrollComponent,
351
513
  {
352
514
  ...rest,
353
515
  style,
354
- maintainVisibleContentPosition: maintainVisibleContentPosition ? { minIndexForVisible: 0 } : void 0,
516
+ maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
355
517
  contentContainerStyle: [
356
518
  contentContainerStyle,
357
519
  horizontal ? {
@@ -364,34 +526,41 @@ var ListComponent = React5__namespace.memo(function ListComponent2({
364
526
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
365
527
  ref: refScrollView
366
528
  },
367
- /* @__PURE__ */ React5__namespace.createElement(reactNative.Animated.View, { style: additionalSize }),
368
- ListHeaderComponent && /* @__PURE__ */ React5__namespace.createElement(
369
- reactNative.Animated.View,
529
+ ENABLE_DEVMODE ? /* @__PURE__ */ React6__namespace.createElement(PaddingAndAdjustDevMode, null) : /* @__PURE__ */ React6__namespace.createElement(PaddingAndAdjust, null),
530
+ ListHeaderComponent && /* @__PURE__ */ React6__namespace.createElement(
531
+ reactNative.View,
370
532
  {
371
533
  style: ListHeaderComponentStyle,
372
534
  onLayout: (event) => {
373
535
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
374
- const prevSize = peek$(ctx, "headerSize") || 0;
375
- if (size !== prevSize) {
376
- set$(ctx, "headerSize", size);
377
- }
536
+ set$(ctx, "headerSize", size);
378
537
  }
379
538
  },
380
539
  getComponent(ListHeaderComponent)
381
540
  ),
382
- ListEmptyComponent && /* @__PURE__ */ React5__namespace.createElement(reactNative.Animated.View, { style: ListEmptyComponentStyle }, getComponent(ListEmptyComponent)),
383
- /* @__PURE__ */ React5__namespace.createElement(
541
+ ListEmptyComponent && getComponent(ListEmptyComponent),
542
+ /* @__PURE__ */ React6__namespace.createElement(
384
543
  Containers,
385
544
  {
386
545
  horizontal,
387
546
  recycleItems,
388
547
  waitForInitialLayout,
389
548
  getRenderedItem,
390
- ItemSeparatorComponent: ItemSeparatorComponent && getComponent(ItemSeparatorComponent),
549
+ ItemSeparatorComponent,
391
550
  updateItemSize
392
551
  }
393
552
  ),
394
- ListFooterComponent && /* @__PURE__ */ React5__namespace.createElement(reactNative.View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
553
+ ListFooterComponent && /* @__PURE__ */ React6__namespace.createElement(
554
+ reactNative.View,
555
+ {
556
+ style: ListFooterComponentStyle,
557
+ onLayout: (event) => {
558
+ const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
559
+ set$(ctx, "footerSize", size);
560
+ }
561
+ },
562
+ getComponent(ListFooterComponent)
563
+ )
395
564
  );
396
565
  });
397
566
 
@@ -400,36 +569,63 @@ var ScrollAdjustHandler = class {
400
569
  constructor(ctx) {
401
570
  this.ctx = ctx;
402
571
  this.appliedAdjust = 0;
403
- this.pendingAdjust = 0;
404
572
  this.busy = false;
405
- this.firstAdjust = true;
573
+ this.isPaused = false;
574
+ this.isDisabled = false;
406
575
  this.context = ctx;
407
576
  }
577
+ doAjdust() {
578
+ set$(this.context, "scrollAdjust", this.appliedAdjust);
579
+ this.busy = false;
580
+ }
408
581
  requestAdjust(adjust, onAdjusted) {
582
+ if (this.isDisabled) {
583
+ return;
584
+ }
409
585
  const oldAdjustTop = peek$(this.context, "scrollAdjust");
410
586
  if (oldAdjustTop === adjust) {
411
587
  return;
412
588
  }
413
589
  this.appliedAdjust = adjust;
414
- this.pendingAdjust = adjust;
415
- const doAjdust = () => {
416
- set$(this.context, "scrollAdjust", this.pendingAdjust);
417
- onAdjusted(oldAdjustTop - this.pendingAdjust);
418
- this.busy = false;
419
- };
420
- if (!this.busy) {
590
+ if (!this.busy && !this.isPaused) {
421
591
  this.busy = true;
422
- if (this.firstAdjust) {
423
- this.firstAdjust = false;
424
- setTimeout(doAjdust, 50);
425
- } else {
426
- doAjdust();
427
- }
592
+ this.doAjdust();
593
+ onAdjusted(oldAdjustTop - adjust);
428
594
  }
429
595
  }
430
596
  getAppliedAdjust() {
431
597
  return this.appliedAdjust;
432
598
  }
599
+ pauseAdjust() {
600
+ this.isPaused = true;
601
+ }
602
+ setDisableAdjust(disable) {
603
+ this.isDisabled = disable;
604
+ }
605
+ // return true if it was paused
606
+ unPauseAdjust() {
607
+ if (this.isPaused) {
608
+ this.isPaused = false;
609
+ this.doAjdust();
610
+ return true;
611
+ }
612
+ return false;
613
+ }
614
+ };
615
+ var useCombinedRef = (...refs) => {
616
+ const callback = React6.useCallback((element) => {
617
+ for (const ref of refs) {
618
+ if (!ref) {
619
+ continue;
620
+ }
621
+ if (typeof ref === "function") {
622
+ ref(element);
623
+ } else {
624
+ ref.current = element;
625
+ }
626
+ }
627
+ }, refs);
628
+ return callback;
433
629
  };
434
630
 
435
631
  // src/viewability.ts
@@ -528,11 +724,13 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
528
724
  }
529
725
  }
530
726
  function isViewable(state, ctx, viewabilityConfig, key, scrollSize, item, index) {
531
- const { sizes, positions, scroll } = state;
727
+ const { sizes, positions, scroll: scrollState, scrollAdjustHandler } = state;
532
728
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
533
729
  const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
534
730
  const viewAreaMode = viewAreaCoveragePercentThreshold != null;
535
731
  const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
732
+ const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
733
+ const scroll = scrollState - previousScrollAdjust - topPad;
536
734
  const top = positions.get(key) - scroll + topPad;
537
735
  const size = sizes.get(key) || 0;
538
736
  const bottom = top + size;
@@ -582,13 +780,13 @@ function maybeUpdateViewabilityCallback(ctx, configId, viewToken) {
582
780
  // src/LegendList.tsx
583
781
  var DEFAULT_DRAW_DISTANCE = 250;
584
782
  var DEFAULT_ITEM_SIZE = 100;
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 }));
783
+ var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
784
+ return /* @__PURE__ */ React6__namespace.createElement(StateProvider, null, /* @__PURE__ */ React6__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
587
785
  });
588
- var LegendListInner = React5.forwardRef(function LegendListInner2(props, forwardedRef) {
589
- var _a, _b, _c, _d, _e;
786
+ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
787
+ var _a, _b, _c, _d;
590
788
  const {
591
- data,
789
+ data: dataProp,
592
790
  initialScrollIndex,
593
791
  initialScrollOffset,
594
792
  horizontal,
@@ -601,61 +799,87 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
601
799
  alignItemsAtEnd = false,
602
800
  maintainVisibleContentPosition = false,
603
801
  onScroll: onScrollProp,
802
+ onMomentumScrollEnd,
604
803
  numColumns: numColumnsProp = 1,
804
+ columnWrapperStyle,
605
805
  keyExtractor: keyExtractorProp,
606
806
  renderItem,
607
807
  estimatedItemSize,
608
808
  getEstimatedItemSize,
609
- onEndReached,
610
- onStartReached,
611
809
  ListEmptyComponent,
612
810
  onItemSizeChanged,
613
811
  scrollEventThrottle,
614
812
  refScrollView,
615
813
  waitForInitialLayout = true,
616
814
  extraData,
815
+ onLayout: onLayoutProp,
816
+ onRefresh,
817
+ refreshing,
818
+ progressViewOffset,
819
+ refreshControl,
820
+ initialContainerPoolRatio = 2,
821
+ viewabilityConfig,
822
+ viewabilityConfigCallbackPairs,
823
+ onViewableItemsChanged,
617
824
  ...rest
618
825
  } = props;
619
826
  const { style, contentContainerStyle } = props;
827
+ const callbacks = React6.useRef({
828
+ onStartReached: rest.onStartReached,
829
+ onEndReached: rest.onEndReached
830
+ });
831
+ callbacks.current.onStartReached = rest.onStartReached;
832
+ callbacks.current.onEndReached = rest.onEndReached;
620
833
  const ctx = useStateContext();
621
- const refScroller = React5.useRef(null);
622
- const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE;
834
+ ctx.columnWrapperStyle = columnWrapperStyle;
835
+ const refScroller = React6.useRef(null);
836
+ const combinedRef = useCombinedRef(refScroller, refScrollView);
837
+ const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
623
838
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
624
- const refState = React5.useRef();
839
+ const refState = React6.useRef();
625
840
  const getId = (index) => {
626
841
  var _a2;
627
- const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
628
- if (!data2) {
842
+ const data = (_a2 = refState.current) == null ? void 0 : _a2.data;
843
+ if (!data) {
629
844
  return "";
630
845
  }
631
- const ret = index < data2.length ? keyExtractor ? keyExtractor(data2[index], index) : index : null;
846
+ const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
632
847
  return `${ret}`;
633
848
  };
634
- const getItemSize = (key, index, data2) => {
849
+ const getItemSize = (key, index, data) => {
635
850
  var _a2;
636
851
  const sizeKnown = refState.current.sizes.get(key);
637
852
  if (sizeKnown !== void 0) {
638
853
  return sizeKnown;
639
854
  }
640
- const size = (_a2 = getEstimatedItemSize ? getEstimatedItemSize(index, data2) : estimatedItemSize) != null ? _a2 : DEFAULT_ITEM_SIZE;
855
+ const size = (_a2 = getEstimatedItemSize ? getEstimatedItemSize(index, data) : estimatedItemSize) != null ? _a2 : DEFAULT_ITEM_SIZE;
641
856
  refState.current.sizes.set(key, size);
642
857
  return size;
643
858
  };
644
- const calculateInitialOffset = (index = initialScrollIndex) => {
645
- if (index) {
859
+ const calculateOffsetForIndex = (index = initialScrollIndex) => {
860
+ var _a2;
861
+ const data = dataProp;
862
+ if (index !== void 0) {
646
863
  let offset = 0;
647
- if (getEstimatedItemSize) {
864
+ const canGetSize = !!refState.current;
865
+ if (canGetSize || getEstimatedItemSize) {
866
+ const sizeFn = (index2) => {
867
+ if (canGetSize) {
868
+ return getItemSize(getId(index2), index2, data[index2]);
869
+ }
870
+ return getEstimatedItemSize(index2, data[index2]);
871
+ };
648
872
  for (let i = 0; i < index; i++) {
649
- offset += getEstimatedItemSize(i, data[i]);
873
+ offset += sizeFn(i);
650
874
  }
651
875
  } else if (estimatedItemSize) {
652
876
  offset = index * estimatedItemSize;
653
877
  }
654
- return offset / numColumnsProp;
878
+ return offset / numColumnsProp - (((_a2 = refState.current) == null ? void 0 : _a2.scrollAdjustHandler.getAppliedAdjust()) || 0);
655
879
  }
656
880
  return 0;
657
881
  };
658
- const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React5.useMemo(calculateInitialOffset, []);
882
+ const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React6.useMemo(calculateOffsetForIndex, []);
659
883
  if (!refState.current) {
660
884
  const initialScrollLength = reactNative.Dimensions.get("window")[horizontal ? "width" : "height"];
661
885
  refState.current = {
@@ -663,14 +887,11 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
663
887
  positions: /* @__PURE__ */ new Map(),
664
888
  columns: /* @__PURE__ */ new Map(),
665
889
  pendingAdjust: 0,
666
- waitingForMicrotask: false,
667
890
  isStartReached: initialContentOffset < initialScrollLength * onStartReachedThreshold,
668
891
  isEndReached: false,
669
892
  isAtBottom: false,
670
893
  isAtTop: false,
671
- data,
672
- idsInFirstRender: void 0,
673
- hasScrolled: false,
894
+ data: dataProp,
674
895
  scrollLength: initialScrollLength,
675
896
  startBuffered: 0,
676
897
  startNoBuffer: 0,
@@ -690,23 +911,28 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
690
911
  indexByKey: /* @__PURE__ */ new Map(),
691
912
  scrollHistory: [],
692
913
  scrollVelocity: 0,
693
- sizesLaidOut: __DEV__ ? /* @__PURE__ */ new Map() : void 0,
914
+ sizesKnown: /* @__PURE__ */ new Map(),
694
915
  timeoutSizeMessage: 0,
695
916
  scrollTimer: void 0,
696
917
  belowAnchorElementPositions: void 0,
697
918
  rowHeights: /* @__PURE__ */ new Map(),
698
919
  startReachedBlockedByTimer: false,
920
+ endReachedBlockedByTimer: false,
699
921
  scrollForNextCalculateItemsInView: void 0,
700
- enableScrollForNextCalculateItemsInView: true
922
+ enableScrollForNextCalculateItemsInView: true,
923
+ minIndexSizeChanged: 0,
924
+ numPendingInitialLayout: 0,
925
+ queuedCalculateItemsInView: 0,
926
+ lastBatchingAction: Date.now(),
927
+ onScroll: onScrollProp
701
928
  };
702
- refState.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
703
929
  if (maintainVisibleContentPosition) {
704
930
  if (initialScrollIndex) {
705
931
  refState.current.anchorElement = {
706
932
  coordinate: initialContentOffset,
707
933
  id: getId(initialScrollIndex)
708
934
  };
709
- } else if (data.length) {
935
+ } else if (dataProp.length) {
710
936
  refState.current.anchorElement = {
711
937
  coordinate: initialContentOffset,
712
938
  id: getId(0)
@@ -719,6 +945,9 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
719
945
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
720
946
  set$(ctx, "extraData", extraData);
721
947
  }
948
+ const didDataChange = refState.current.data !== dataProp;
949
+ refState.current.data = dataProp;
950
+ refState.current.onScroll = onScrollProp;
722
951
  const getAnchorElementIndex = () => {
723
952
  const state = refState.current;
724
953
  if (state.anchorElement) {
@@ -727,16 +956,36 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
727
956
  }
728
957
  return void 0;
729
958
  };
730
- const addTotalSize = React5.useCallback((key, add, totalSizeBelowAnchor) => {
959
+ const setDidLayout = () => {
960
+ var _a2;
961
+ refState.current.queuedInitialLayout = true;
962
+ if (initialScrollIndex) {
963
+ const updatedOffset = calculateOffsetForIndex(initialScrollIndex);
964
+ (_a2 = refState.current) == null ? void 0 : _a2.scrollAdjustHandler.setDisableAdjust(true);
965
+ queueMicrotask(() => {
966
+ scrollTo(updatedOffset, false);
967
+ requestAnimationFrame(() => {
968
+ var _a3;
969
+ set$(ctx, "containersDidLayout", true);
970
+ (_a3 = refState.current) == null ? void 0 : _a3.scrollAdjustHandler.setDisableAdjust(false);
971
+ });
972
+ });
973
+ } else {
974
+ queueMicrotask(() => {
975
+ set$(ctx, "containersDidLayout", true);
976
+ });
977
+ }
978
+ };
979
+ const addTotalSize = React6.useCallback((key, add, totalSizeBelowAnchor) => {
731
980
  const state = refState.current;
732
- const index = key === null ? 0 : state.indexByKey.get(key);
981
+ const { indexByKey, anchorElement } = state;
982
+ const index = key === null ? 0 : indexByKey.get(key);
733
983
  let isAboveAnchor = false;
734
984
  if (maintainVisibleContentPosition) {
735
- if (state.anchorElement && index < getAnchorElementIndex()) {
985
+ if (anchorElement && index < getAnchorElementIndex()) {
736
986
  isAboveAnchor = true;
737
987
  }
738
988
  }
739
- state.totalSize;
740
989
  if (key === null) {
741
990
  state.totalSize = add;
742
991
  state.totalSizeBelowAnchor = totalSizeBelowAnchor;
@@ -746,29 +995,30 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
746
995
  state.totalSizeBelowAnchor += add;
747
996
  }
748
997
  }
749
- let applyAdjustValue = void 0;
750
- if (maintainVisibleContentPosition) {
751
- const newAdjust = state.anchorElement.coordinate - state.totalSizeBelowAnchor;
998
+ let applyAdjustValue = 0;
999
+ let resultSize = state.totalSize;
1000
+ if (maintainVisibleContentPosition && anchorElement !== void 0) {
1001
+ const newAdjust = anchorElement.coordinate - state.totalSizeBelowAnchor;
752
1002
  applyAdjustValue = -newAdjust;
753
1003
  state.belowAnchorElementPositions = buildElementPositionsBelowAnchor();
754
1004
  state.rowHeights.clear();
1005
+ if (applyAdjustValue !== void 0) {
1006
+ resultSize -= applyAdjustValue;
1007
+ state.scrollAdjustHandler.requestAdjust(applyAdjustValue, (diff) => {
1008
+ state.scroll -= diff;
1009
+ });
1010
+ }
755
1011
  }
756
- const totalSize = state.totalSize;
757
- let resultSize = totalSize;
758
- if (applyAdjustValue !== void 0) {
759
- resultSize -= applyAdjustValue;
760
- refState.current.scrollAdjustHandler.requestAdjust(applyAdjustValue, (diff) => {
761
- state.scroll -= diff;
762
- });
763
- }
764
- set$(ctx, "totalSize", resultSize);
1012
+ set$(ctx, "totalSize", state.totalSize);
1013
+ set$(ctx, "totalSizeWithScrollAdjust", resultSize);
765
1014
  if (alignItemsAtEnd) {
766
1015
  doUpdatePaddingTop();
767
1016
  }
768
1017
  }, []);
769
1018
  const getRowHeight = (n) => {
770
- const { rowHeights } = refState.current;
771
- if (numColumnsProp === 1) {
1019
+ const { rowHeights, data } = refState.current;
1020
+ const numColumns = peek$(ctx, "numColumns");
1021
+ if (numColumns === 1) {
772
1022
  const id = getId(n);
773
1023
  return getItemSize(id, n, data[n]);
774
1024
  }
@@ -776,8 +1026,8 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
776
1026
  return rowHeights.get(n) || 0;
777
1027
  }
778
1028
  let rowHeight = 0;
779
- const startEl = n * numColumnsProp;
780
- for (let i = startEl; i < startEl + numColumnsProp && i < data.length; i++) {
1029
+ const startEl = n * numColumns;
1030
+ for (let i = startEl; i < startEl + numColumns && i < data.length; i++) {
781
1031
  const id = getId(i);
782
1032
  const size = getItemSize(id, i, data[i]);
783
1033
  rowHeight = Math.max(rowHeight, size);
@@ -796,10 +1046,11 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
796
1046
  return /* @__PURE__ */ new Map();
797
1047
  }
798
1048
  const map = state.belowAnchorElementPositions || /* @__PURE__ */ new Map();
1049
+ const numColumns = peek$(ctx, "numColumns");
799
1050
  for (let i = anchorIndex - 1; i >= 0; i--) {
800
1051
  const id = getId(i);
801
- const rowNumber = Math.floor(i / numColumnsProp);
802
- if (i % numColumnsProp === 0) {
1052
+ const rowNumber = Math.floor(i / numColumns);
1053
+ if (i % numColumns === 0) {
803
1054
  top -= getRowHeight(rowNumber);
804
1055
  }
805
1056
  map.set(id, top);
@@ -807,37 +1058,61 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
807
1058
  return map;
808
1059
  };
809
1060
  const getElementPositionBelowAchor = (id) => {
1061
+ var _a2;
810
1062
  const state = refState.current;
811
1063
  if (!refState.current.belowAnchorElementPositions) {
812
1064
  state.belowAnchorElementPositions = buildElementPositionsBelowAnchor();
813
1065
  }
814
1066
  const res = state.belowAnchorElementPositions.get(id);
815
1067
  if (res === void 0) {
816
- throw new Error("Undefined position below achor");
1068
+ console.warn(`Undefined position below achor ${id} ${(_a2 = state.anchorElement) == null ? void 0 : _a2.id}`);
1069
+ return 0;
817
1070
  }
818
1071
  return res;
819
1072
  };
820
- const calculateItemsInView = React5.useCallback((speed) => {
1073
+ const calculateItemsInView = React6.useCallback(() => {
1074
+ var _a2;
821
1075
  const state = refState.current;
822
1076
  const {
823
- data: data2,
1077
+ data,
824
1078
  scrollLength,
825
- scroll: scrollState,
826
1079
  startBufferedId: startBufferedIdOrig,
827
1080
  positions,
828
1081
  columns,
829
- scrollAdjustHandler
1082
+ scrollAdjustHandler,
1083
+ scrollVelocity: speed
830
1084
  } = state;
831
- if (state.waitingForMicrotask) {
832
- state.waitingForMicrotask = false;
833
- }
834
- if (!data2) {
1085
+ if (!data || scrollLength === 0) {
835
1086
  return;
836
1087
  }
1088
+ const totalSize = peek$(ctx, "totalSizeWithScrollAdjust");
837
1089
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1090
+ const numColumns = peek$(ctx, "numColumns");
838
1091
  const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
839
1092
  const scrollExtra = Math.max(-16, Math.min(16, speed)) * 16;
840
- const scroll = scrollState - previousScrollAdjust - topPad - scrollExtra;
1093
+ let scrollState = state.scroll;
1094
+ if (!state.queuedInitialLayout && initialScrollIndex) {
1095
+ const updatedOffset = calculateOffsetForIndex(initialScrollIndex);
1096
+ scrollState = updatedOffset;
1097
+ }
1098
+ let scroll = scrollState - previousScrollAdjust - topPad;
1099
+ if (scroll + scrollLength > totalSize) {
1100
+ scroll = totalSize - scrollLength;
1101
+ }
1102
+ if (ENABLE_DEBUG_VIEW) {
1103
+ set$(ctx, "debugRawScroll", scrollState);
1104
+ set$(ctx, "debugComputedScroll", scroll);
1105
+ }
1106
+ let scrollBufferTop = scrollBuffer;
1107
+ let scrollBufferBottom = scrollBuffer;
1108
+ if (scrollExtra > 8) {
1109
+ scrollBufferTop = 0;
1110
+ scrollBufferBottom = scrollBuffer + scrollExtra;
1111
+ }
1112
+ if (scrollExtra < -8) {
1113
+ scrollBufferTop = scrollBuffer - scrollExtra;
1114
+ scrollBufferBottom = 0;
1115
+ }
841
1116
  if (state.scrollForNextCalculateItemsInView) {
842
1117
  const { top: top2, bottom } = state.scrollForNextCalculateItemsInView;
843
1118
  if (scroll > top2 && scroll < bottom) {
@@ -850,8 +1125,11 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
850
1125
  let startBufferedId = null;
851
1126
  let endNoBuffer = null;
852
1127
  let endBuffered = null;
853
- const originalStartId = startBufferedIdOrig && state.indexByKey.get(startBufferedIdOrig);
854
- let loopStart = originalStartId || 0;
1128
+ let loopStart = startBufferedIdOrig ? state.indexByKey.get(startBufferedIdOrig) || 0 : 0;
1129
+ if (state.minIndexSizeChanged !== void 0) {
1130
+ loopStart = Math.min(state.minIndexSizeChanged, loopStart);
1131
+ state.minIndexSizeChanged = void 0;
1132
+ }
855
1133
  const anchorElementIndex = getAnchorElementIndex();
856
1134
  for (let i = loopStart; i >= 0; i--) {
857
1135
  const id = getId(i);
@@ -864,7 +1142,7 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
864
1142
  }
865
1143
  const top2 = newPosition || positions.get(id);
866
1144
  if (top2 !== void 0) {
867
- const size = getItemSize(id, i, data2[i]);
1145
+ const size = getItemSize(id, i, data[i]);
868
1146
  const bottom = top2 + size;
869
1147
  if (bottom > scroll - scrollBuffer) {
870
1148
  loopStart = i;
@@ -873,7 +1151,6 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
873
1151
  }
874
1152
  }
875
1153
  }
876
- const numColumns = peek$(ctx, "numColumns");
877
1154
  const loopStartMod = loopStart % numColumns;
878
1155
  if (loopStartMod > 0) {
879
1156
  loopStart -= loopStartMod;
@@ -882,22 +1159,22 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
882
1159
  let column = 1;
883
1160
  let maxSizeInRow = 0;
884
1161
  const getInitialTop = (i) => {
885
- var _a2;
1162
+ var _a3;
886
1163
  const id = getId(i);
887
1164
  let topOffset = 0;
888
1165
  if (positions.get(id)) {
889
1166
  topOffset = positions.get(id);
890
1167
  }
891
- if (id === ((_a2 = state.anchorElement) == null ? void 0 : _a2.id)) {
892
- topOffset = initialContentOffset || 0;
1168
+ if (id === ((_a3 = state.anchorElement) == null ? void 0 : _a3.id)) {
1169
+ topOffset = state.anchorElement.coordinate;
893
1170
  }
894
1171
  return topOffset;
895
1172
  };
896
- for (let i = loopStart; i < data2.length; i++) {
1173
+ for (let i = loopStart; i < data.length; i++) {
897
1174
  const id = getId(i);
898
- const size = getItemSize(id, i, data2[i]);
1175
+ const size = getItemSize(id, i, data[i]);
899
1176
  maxSizeInRow = Math.max(maxSizeInRow, size);
900
- if (top === void 0) {
1177
+ if (top === void 0 || id === ((_a2 = state.anchorElement) == null ? void 0 : _a2.id)) {
901
1178
  top = getInitialTop(i);
902
1179
  }
903
1180
  if (positions.get(id) !== top) {
@@ -909,7 +1186,7 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
909
1186
  if (startNoBuffer === null && top + size > scroll) {
910
1187
  startNoBuffer = i;
911
1188
  }
912
- if (startBuffered === null && top + size > scroll - scrollBuffer) {
1189
+ if (startBuffered === null && top + size > scroll - scrollBufferTop) {
913
1190
  startBuffered = i;
914
1191
  startBufferedId = id;
915
1192
  }
@@ -917,7 +1194,7 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
917
1194
  if (top <= scrollBottom) {
918
1195
  endNoBuffer = i;
919
1196
  }
920
- if (top <= scrollBottom + scrollBuffer) {
1197
+ if (top <= scrollBottom + scrollBufferBottom) {
921
1198
  endBuffered = i;
922
1199
  } else {
923
1200
  break;
@@ -950,6 +1227,7 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
950
1227
  if (startBuffered !== null && endBuffered !== null) {
951
1228
  const prevNumContainers = ctx.values.get("numContainers");
952
1229
  let numContainers = prevNumContainers;
1230
+ let didWarnMoreContainers = false;
953
1231
  for (let i = startBuffered; i <= endBuffered; i++) {
954
1232
  let isContained = false;
955
1233
  const id = getId(i);
@@ -983,18 +1261,19 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
983
1261
  if (furthestIndex >= 0) {
984
1262
  set$(ctx, `containerItemKey${furthestIndex}`, id);
985
1263
  const index = state.indexByKey.get(id);
986
- set$(ctx, `containerItemData${furthestIndex}`, data2[index]);
1264
+ set$(ctx, `containerItemData${furthestIndex}`, data[index]);
987
1265
  } else {
988
1266
  const containerId = numContainers;
989
1267
  numContainers++;
990
1268
  set$(ctx, `containerItemKey${containerId}`, id);
991
1269
  const index = state.indexByKey.get(id);
992
- set$(ctx, `containerItemData${containerId}`, data2[index]);
1270
+ set$(ctx, `containerItemData${containerId}`, data[index]);
993
1271
  set$(ctx, `containerPosition${containerId}`, ANCHORED_POSITION_OUT_OF_VIEW);
994
1272
  set$(ctx, `containerColumn${containerId}`, -1);
995
- if (__DEV__ && numContainers > peek$(ctx, "numContainersPooled")) {
1273
+ if (__DEV__ && !didWarnMoreContainers && numContainers > peek$(ctx, "numContainersPooled")) {
1274
+ didWarnMoreContainers = true;
996
1275
  console.warn(
997
- "[legend-list] No container to recycle, so creating one on demand. This can be a performance issue and is likely caused by the estimatedItemSize being too small. Consider increasing estimatedItemSize. numContainers:",
1276
+ "[legend-list] No container to recycle, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize. numContainers:",
998
1277
  numContainers
999
1278
  );
1000
1279
  }
@@ -1004,19 +1283,19 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
1004
1283
  if (numContainers !== prevNumContainers) {
1005
1284
  set$(ctx, "numContainers", numContainers);
1006
1285
  if (numContainers > peek$(ctx, "numContainersPooled")) {
1007
- set$(ctx, "numContainersPooled", numContainers);
1286
+ set$(ctx, "numContainersPooled", Math.ceil(numContainers * 1.5));
1008
1287
  }
1009
1288
  }
1010
1289
  for (let i = 0; i < numContainers; i++) {
1011
1290
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1012
1291
  const itemIndex = state.indexByKey.get(itemKey);
1013
- const item = data2[itemIndex];
1014
- if (item) {
1292
+ const item = data[itemIndex];
1293
+ if (item !== void 0) {
1015
1294
  const id = getId(itemIndex);
1016
1295
  if (itemKey !== id || itemIndex < startBuffered || itemIndex > endBuffered) {
1017
1296
  const prevPos = peek$(ctx, `containerPosition${i}`).top;
1018
1297
  const pos = positions.get(id) || 0;
1019
- const size = getItemSize(id, itemIndex, data2[i]);
1298
+ const size = getItemSize(id, itemIndex, data[i]);
1020
1299
  if (pos + size >= scroll && pos <= scrollBottom || prevPos + size >= scroll && prevPos <= scrollBottom) {
1021
1300
  set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1022
1301
  }
@@ -1028,9 +1307,9 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
1028
1307
  };
1029
1308
  const column2 = columns.get(id) || 1;
1030
1309
  if (maintainVisibleContentPosition && itemIndex < anchorElementIndex) {
1031
- const currentRow = Math.floor(itemIndex / numColumnsProp);
1310
+ const currentRow = Math.floor(itemIndex / numColumns);
1032
1311
  const rowHeight = getRowHeight(currentRow);
1033
- const elementHeight = getItemSize(id, itemIndex, data2[i]);
1312
+ const elementHeight = getItemSize(id, itemIndex, data[i]);
1034
1313
  const diff = rowHeight - elementHeight;
1035
1314
  pos.relativeCoordinate = pos.top + getRowHeight(currentRow) - diff;
1036
1315
  pos.type = "bottom";
@@ -1045,13 +1324,25 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
1045
1324
  set$(ctx, `containerColumn${i}`, column2);
1046
1325
  }
1047
1326
  if (prevData !== item) {
1048
- set$(ctx, `containerItemData${i}`, data2[itemIndex]);
1327
+ set$(ctx, `containerItemData${i}`, data[itemIndex]);
1049
1328
  }
1050
1329
  }
1051
1330
  }
1052
1331
  }
1053
1332
  }
1054
- set$(ctx, "containersDidLayout", true);
1333
+ if (state.numPendingInitialLayout === 0) {
1334
+ state.numPendingInitialLayout = state.endBuffered - state.startBuffered + 1;
1335
+ }
1336
+ if (!state.queuedInitialLayout && endBuffered !== null) {
1337
+ let areAllKnown = true;
1338
+ for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1339
+ const key = getId(i);
1340
+ areAllKnown && (areAllKnown = state.sizesKnown.has(key));
1341
+ }
1342
+ if (areAllKnown) {
1343
+ setDidLayout();
1344
+ }
1345
+ }
1055
1346
  if (state.viewabilityConfigCallbackPairs) {
1056
1347
  updateViewableItems(
1057
1348
  state,
@@ -1066,16 +1357,27 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
1066
1357
  }, []);
1067
1358
  const doUpdatePaddingTop = () => {
1068
1359
  if (alignItemsAtEnd) {
1069
- const { scrollLength, totalSize } = refState.current;
1070
- const listPaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1071
- const paddingTop = Math.max(0, Math.floor(scrollLength - totalSize - listPaddingTop));
1360
+ const { scrollLength } = refState.current;
1361
+ const contentSize = getContentSize(ctx);
1362
+ const paddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1072
1363
  set$(ctx, "paddingTop", paddingTop);
1073
1364
  }
1074
1365
  };
1366
+ const scrollTo = (offset, animated) => {
1367
+ var _a2;
1368
+ (_a2 = refScroller.current) == null ? void 0 : _a2.scrollTo({
1369
+ x: horizontal ? offset : 0,
1370
+ y: horizontal ? 0 : offset,
1371
+ animated: !!animated
1372
+ });
1373
+ };
1075
1374
  const doMaintainScrollAtEnd = (animated) => {
1076
1375
  const state = refState.current;
1077
- if ((state == null ? void 0 : state.isAtBottom) && maintainScrollAtEnd) {
1078
- state.scroll = state.totalSize - state.scrollLength + peek$(ctx, "paddingTop");
1376
+ if ((state == null ? void 0 : state.isAtBottom) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
1377
+ const paddingTop = peek$(ctx, "paddingTop") || 0;
1378
+ if (paddingTop > 0) {
1379
+ state.scroll = 0;
1380
+ }
1079
1381
  requestAnimationFrame(() => {
1080
1382
  var _a2;
1081
1383
  (_a2 = refScroller.current) == null ? void 0 : _a2.scrollToEnd({
@@ -1085,28 +1387,48 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
1085
1387
  return true;
1086
1388
  }
1087
1389
  };
1390
+ const checkThreshold = (distance, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
1391
+ const distanceAbs = Math.abs(distance);
1392
+ const isAtThreshold = distanceAbs < threshold;
1393
+ if (!isReached && !isBlockedByTimer) {
1394
+ if (isAtThreshold) {
1395
+ onReached == null ? void 0 : onReached(distance);
1396
+ blockTimer == null ? void 0 : blockTimer(true);
1397
+ setTimeout(() => {
1398
+ blockTimer == null ? void 0 : blockTimer(false);
1399
+ }, 700);
1400
+ return true;
1401
+ }
1402
+ } else {
1403
+ if (distance >= 1.3 * threshold) {
1404
+ return false;
1405
+ }
1406
+ }
1407
+ return isReached;
1408
+ };
1088
1409
  const checkAtBottom = () => {
1089
1410
  if (!refState.current) {
1090
1411
  return;
1091
1412
  }
1092
- const { scrollLength, scroll, totalSize } = refState.current;
1093
- if (totalSize > 0) {
1094
- const distanceFromEnd = totalSize - scroll - scrollLength;
1095
- if (refState.current) {
1096
- refState.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1097
- }
1098
- if (onEndReached) {
1099
- if (!refState.current.isEndReached) {
1100
- if (distanceFromEnd < onEndReachedThreshold * scrollLength) {
1101
- refState.current.isEndReached = true;
1102
- onEndReached({ distanceFromEnd });
1103
- }
1104
- } else {
1105
- if (distanceFromEnd >= onEndReachedThreshold * scrollLength) {
1106
- refState.current.isEndReached = false;
1107
- }
1413
+ const { scrollLength, scroll, hasScrolled } = refState.current;
1414
+ const contentSize = getContentSize(ctx);
1415
+ if (contentSize > 0 && hasScrolled) {
1416
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1417
+ const distanceFromEndAbs = Math.abs(distanceFromEnd);
1418
+ refState.current.isAtBottom = distanceFromEndAbs < scrollLength * maintainScrollAtEndThreshold;
1419
+ refState.current.isEndReached = checkThreshold(
1420
+ distanceFromEnd,
1421
+ onEndReachedThreshold * scrollLength,
1422
+ refState.current.isEndReached,
1423
+ refState.current.endReachedBlockedByTimer,
1424
+ (distance) => {
1425
+ var _a2, _b2;
1426
+ return (_b2 = (_a2 = callbacks.current).onEndReached) == null ? void 0 : _b2.call(_a2, { distanceFromEnd: distance });
1427
+ },
1428
+ (block) => {
1429
+ refState.current.endReachedBlockedByTimer = block;
1108
1430
  }
1109
- }
1431
+ );
1110
1432
  }
1111
1433
  };
1112
1434
  const checkAtTop = () => {
@@ -1115,112 +1437,118 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
1115
1437
  }
1116
1438
  const { scrollLength, scroll } = refState.current;
1117
1439
  const distanceFromTop = scroll;
1118
- refState.current.isAtTop = distanceFromTop < 0;
1119
- if (onStartReached) {
1120
- if (!refState.current.isStartReached && !refState.current.startReachedBlockedByTimer) {
1121
- if (distanceFromTop < onStartReachedThreshold * scrollLength) {
1122
- refState.current.isStartReached = true;
1123
- onStartReached({ distanceFromStart: scroll });
1124
- refState.current.startReachedBlockedByTimer = true;
1125
- setTimeout(() => {
1126
- refState.current.startReachedBlockedByTimer = false;
1127
- }, 700);
1128
- }
1129
- } else {
1130
- if (distanceFromTop >= 1.3 * onStartReachedThreshold * scrollLength) {
1131
- refState.current.isStartReached = false;
1132
- }
1440
+ const distanceFromTopAbs = Math.abs(distanceFromTop);
1441
+ refState.current.isAtTop = distanceFromTopAbs < 0;
1442
+ refState.current.isStartReached = checkThreshold(
1443
+ distanceFromTop,
1444
+ onStartReachedThreshold * scrollLength,
1445
+ refState.current.isStartReached,
1446
+ refState.current.startReachedBlockedByTimer,
1447
+ (distance) => {
1448
+ var _a2, _b2;
1449
+ return (_b2 = (_a2 = callbacks.current).onStartReached) == null ? void 0 : _b2.call(_a2, { distanceFromStart: distance });
1450
+ },
1451
+ (block) => {
1452
+ refState.current.startReachedBlockedByTimer = block;
1133
1453
  }
1134
- }
1454
+ );
1135
1455
  };
1136
- const checkResetContainers = (reset) => {
1456
+ const checkResetContainers = (isFirst2) => {
1137
1457
  const state = refState.current;
1138
1458
  if (state) {
1139
- state.data = data;
1140
- if (reset) {
1459
+ state.data = dataProp;
1460
+ if (!isFirst2) {
1141
1461
  refState.current.scrollForNextCalculateItemsInView = void 0;
1142
1462
  const numContainers = peek$(ctx, "numContainers");
1143
1463
  for (let i = 0; i < numContainers; i++) {
1144
1464
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1145
1465
  if (!keyExtractorProp || itemKey && state.indexByKey.get(itemKey) === void 0) {
1146
1466
  set$(ctx, `containerItemKey${i}`, void 0);
1467
+ set$(ctx, `containerItemData${i}`, void 0);
1147
1468
  set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1148
1469
  set$(ctx, `containerColumn${i}`, -1);
1149
1470
  }
1150
1471
  }
1151
1472
  if (!keyExtractorProp) {
1152
- state.sizes.clear();
1153
1473
  state.positions.clear();
1154
1474
  }
1155
- calculateItemsInView(state.scrollVelocity);
1156
- }
1157
- const didMaintainScrollAtEnd = doMaintainScrollAtEnd(false);
1158
- if (!didMaintainScrollAtEnd && data.length > state.data.length) {
1159
- state.isEndReached = false;
1475
+ calculateItemsInView();
1476
+ const didMaintainScrollAtEnd = doMaintainScrollAtEnd(false);
1477
+ if (!didMaintainScrollAtEnd && dataProp.length > state.data.length) {
1478
+ state.isEndReached = false;
1479
+ }
1480
+ checkAtTop();
1481
+ checkAtBottom();
1160
1482
  }
1161
- checkAtTop();
1162
- checkAtBottom();
1163
1483
  }
1164
1484
  };
1165
- const isFirst = !refState.current.renderItem;
1166
- if (isFirst || data !== refState.current.data || numColumnsProp !== peek$(ctx, "numColumns")) {
1167
- if (!keyExtractorProp && !isFirst && data !== refState.current.data) {
1168
- refState.current.sizes.clear();
1169
- refState.current.positions.clear();
1170
- }
1171
- refState.current.data = data;
1485
+ const calcTotalSizesAndPositions = ({ forgetPositions = false }) => {
1486
+ var _a2, _b2;
1172
1487
  let totalSize = 0;
1173
1488
  let totalSizeBelowIndex = 0;
1174
1489
  const indexByKey = /* @__PURE__ */ new Map();
1175
1490
  const newPositions = /* @__PURE__ */ new Map();
1176
1491
  let column = 1;
1177
1492
  let maxSizeInRow = 0;
1178
- for (let i = 0; i < data.length; i++) {
1493
+ const numColumns = (_a2 = peek$(ctx, "numColumns")) != null ? _a2 : numColumnsProp;
1494
+ if (!refState.current) {
1495
+ return;
1496
+ }
1497
+ for (let i = 0; i < dataProp.length; i++) {
1179
1498
  const key = getId(i);
1499
+ if (__DEV__) {
1500
+ if (indexByKey.has(key)) {
1501
+ console.error(
1502
+ `[legend-list] Error: Detected overlapping key (${key}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`
1503
+ );
1504
+ }
1505
+ }
1180
1506
  indexByKey.set(key, i);
1181
- if (refState.current.positions.get(key) != null && refState.current.indexByKey.get(key) === i) {
1507
+ if (!forgetPositions && refState.current.positions.get(key) != null && refState.current.indexByKey.get(key) === i) {
1182
1508
  newPositions.set(key, refState.current.positions.get(key));
1183
1509
  }
1184
1510
  }
1185
1511
  refState.current.indexByKey = indexByKey;
1186
1512
  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 });
1513
+ if (!forgetPositions && !isFirst) {
1514
+ if (maintainVisibleContentPosition) {
1515
+ if (refState.current.anchorElement == null || indexByKey.get(refState.current.anchorElement.id) == null) {
1516
+ if (dataProp.length) {
1517
+ const newAnchorElement = {
1518
+ coordinate: 0,
1519
+ id: getId(0)
1520
+ };
1521
+ refState.current.anchorElement = newAnchorElement;
1522
+ (_b2 = refState.current.belowAnchorElementPositions) == null ? void 0 : _b2.clear();
1523
+ scrollTo(0, false);
1524
+ setTimeout(() => {
1525
+ calculateItemsInView();
1526
+ }, 0);
1527
+ } else {
1528
+ refState.current.startBufferedId = void 0;
1529
+ }
1530
+ }
1531
+ } else {
1532
+ if (refState.current.startBufferedId != null && newPositions.get(refState.current.startBufferedId) == null) {
1533
+ if (dataProp.length) {
1534
+ refState.current.startBufferedId = getId(0);
1535
+ } else {
1536
+ refState.current.startBufferedId = void 0;
1537
+ }
1538
+ scrollTo(0, false);
1197
1539
  setTimeout(() => {
1198
- calculateItemsInView(0);
1540
+ calculateItemsInView();
1199
1541
  }, 0);
1200
- } else {
1201
- refState.current.startBufferedId = void 0;
1202
1542
  }
1203
1543
  }
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
1544
  }
1217
1545
  const anchorElementIndex = getAnchorElementIndex();
1218
- for (let i = 0; i < data.length; i++) {
1546
+ for (let i = 0; i < dataProp.length; i++) {
1219
1547
  const key = getId(i);
1220
- const size = getItemSize(key, i, data[i]);
1548
+ const size = getItemSize(key, i, dataProp[i]);
1221
1549
  maxSizeInRow = Math.max(maxSizeInRow, size);
1222
1550
  column++;
1223
- if (column > numColumnsProp) {
1551
+ if (column > numColumns) {
1224
1552
  if (maintainVisibleContentPosition && anchorElementIndex !== void 0 && i < anchorElementIndex) {
1225
1553
  totalSizeBelowIndex += maxSizeInRow;
1226
1554
  }
@@ -1232,36 +1560,59 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
1232
1560
  if (maxSizeInRow > 0) {
1233
1561
  totalSize += maxSizeInRow;
1234
1562
  }
1563
+ const state = refState.current;
1564
+ state.ignoreScrollFromCalcTotal = true;
1565
+ requestAnimationFrame(() => {
1566
+ state.ignoreScrollFromCalcTotal = false;
1567
+ });
1235
1568
  addTotalSize(null, totalSize, totalSizeBelowIndex);
1236
- }
1237
- React5.useEffect(() => {
1238
- checkResetContainers(
1239
- /*reset*/
1240
- !isFirst
1569
+ };
1570
+ const isFirst = !refState.current.renderItem;
1571
+ const memoizedLastItemKeys = React6.useMemo(() => {
1572
+ if (!dataProp.length) return [];
1573
+ return Array.from(
1574
+ { length: Math.min(numColumnsProp, dataProp.length) },
1575
+ (_, i) => getId(dataProp.length - 1 - i)
1241
1576
  );
1242
- }, [isFirst, data, numColumnsProp]);
1243
- React5.useEffect(() => {
1244
- set$(ctx, "extraData", extraData);
1245
- }, [extraData]);
1246
- refState.current.renderItem = renderItem;
1247
- const lastItemKey = getId(data[data.length - 1]);
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;
1577
+ }, [dataProp, numColumnsProp]);
1249
1578
  const initalizeStateVars = () => {
1250
- set$(ctx, "lastItemKey", lastItemKey);
1579
+ set$(ctx, "lastItemKeys", memoizedLastItemKeys);
1251
1580
  set$(ctx, "numColumns", numColumnsProp);
1252
1581
  set$(ctx, "stylePaddingTop", stylePaddingTop);
1253
1582
  };
1254
1583
  if (isFirst) {
1255
1584
  initalizeStateVars();
1256
1585
  }
1257
- React5.useEffect(initalizeStateVars, [lastItemKey, numColumnsProp, stylePaddingTop]);
1258
- const getRenderedItem = React5.useCallback((key) => {
1586
+ if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
1587
+ refState.current.lastBatchingAction = Date.now();
1588
+ if (!keyExtractorProp && !isFirst && didDataChange) {
1589
+ refState.current.sizes.clear();
1590
+ refState.current.positions.clear();
1591
+ }
1592
+ calcTotalSizesAndPositions({ forgetPositions: false });
1593
+ }
1594
+ React6.useEffect(() => {
1595
+ const didAllocateContainers = doInitialAllocateContainers();
1596
+ if (!didAllocateContainers) {
1597
+ checkResetContainers(
1598
+ /*isFirst*/
1599
+ isFirst
1600
+ );
1601
+ }
1602
+ }, [isFirst, dataProp, numColumnsProp]);
1603
+ React6.useEffect(() => {
1604
+ set$(ctx, "extraData", extraData);
1605
+ }, [extraData]);
1606
+ refState.current.renderItem = renderItem;
1607
+ 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;
1608
+ React6.useEffect(initalizeStateVars, [memoizedLastItemKeys.join(","), numColumnsProp, stylePaddingTop]);
1609
+ const getRenderedItem = React6.useCallback((key) => {
1259
1610
  var _a2, _b2;
1260
1611
  const state = refState.current;
1261
1612
  if (!state) {
1262
1613
  return null;
1263
1614
  }
1264
- const { data: data2, indexByKey } = state;
1615
+ const { data, indexByKey } = state;
1265
1616
  const index = indexByKey.get(key);
1266
1617
  if (index === void 0) {
1267
1618
  return null;
@@ -1279,64 +1630,86 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
1279
1630
  return useRecyclingState(valueOrFun);
1280
1631
  };
1281
1632
  const renderedItem = (_b2 = (_a2 = refState.current).renderItem) == null ? void 0 : _b2.call(_a2, {
1282
- item: data2[index],
1633
+ item: data[index],
1283
1634
  index,
1635
+ extraData: peek$(ctx, "extraData"),
1284
1636
  useViewability: useViewability2,
1285
1637
  useViewabilityAmount: useViewabilityAmount2,
1286
1638
  useRecyclingEffect: useRecyclingEffect2,
1287
1639
  useRecyclingState: useRecyclingState2
1288
1640
  });
1289
- return { index, renderedItem };
1641
+ return { index, item: data[index], renderedItem };
1290
1642
  }, []);
1291
- useInit(() => {
1643
+ const doInitialAllocateContainers = () => {
1292
1644
  var _a2;
1293
1645
  const state = refState.current;
1294
- const viewability = setupViewability(props);
1646
+ const { scrollLength, data } = state;
1647
+ if (scrollLength > 0 && data.length > 0 && !peek$(ctx, "numContainers")) {
1648
+ const averageItemSize = (_a2 = estimatedItemSize != null ? estimatedItemSize : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(0, data[0])) != null ? _a2 : DEFAULT_ITEM_SIZE;
1649
+ const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) * numColumnsProp;
1650
+ for (let i = 0; i < numContainers; i++) {
1651
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1652
+ set$(ctx, `containerColumn${i}`, -1);
1653
+ }
1654
+ set$(ctx, "numContainers", numContainers);
1655
+ set$(ctx, "numContainersPooled", numContainers * initialContainerPoolRatio);
1656
+ if (initialScrollIndex) {
1657
+ requestAnimationFrame(() => {
1658
+ calculateItemsInView();
1659
+ });
1660
+ } else {
1661
+ calculateItemsInView();
1662
+ }
1663
+ return true;
1664
+ }
1665
+ };
1666
+ React6.useEffect(() => {
1667
+ const state = refState.current;
1668
+ const viewability = setupViewability({
1669
+ viewabilityConfig,
1670
+ viewabilityConfigCallbackPairs,
1671
+ onViewableItemsChanged
1672
+ });
1295
1673
  state.viewabilityConfigCallbackPairs = viewability;
1296
1674
  state.enableScrollForNextCalculateItemsInView = !viewability;
1297
- const scrollLength = state.scrollLength;
1298
- const averageItemSize = (_a2 = estimatedItemSize != null ? estimatedItemSize : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(0, data[0])) != null ? _a2 : DEFAULT_ITEM_SIZE;
1299
- const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) * numColumnsProp;
1300
- for (let i = 0; i < numContainers; i++) {
1301
- set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1302
- set$(ctx, `containerColumn${i}`, -1);
1303
- }
1304
- set$(ctx, "numContainers", numContainers);
1305
- set$(ctx, "numContainersPooled", numContainers * 2);
1306
- calculateItemsInView(state.scrollVelocity);
1675
+ }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
1676
+ useInit(() => {
1677
+ doInitialAllocateContainers();
1307
1678
  });
1308
- const updateItemSize = React5.useCallback((containerId, itemKey, size) => {
1309
- var _a2;
1310
- const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
1311
- if (!data2) {
1679
+ const updateItemSize = React6.useCallback((itemKey, size) => {
1680
+ const state = refState.current;
1681
+ const { sizes, indexByKey, sizesKnown, data, rowHeights } = state;
1682
+ if (!data) {
1312
1683
  return;
1313
1684
  }
1314
- const state = refState.current;
1315
- const { sizes, indexByKey, columns, sizesLaidOut } = state;
1316
1685
  const index = indexByKey.get(itemKey);
1317
1686
  const numColumns = peek$(ctx, "numColumns");
1318
- const row = Math.floor(index / numColumns);
1319
- const prevSize = getRowHeight(row);
1687
+ state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, index) : index;
1688
+ const prevSize = getItemSize(itemKey, index, data);
1689
+ let needsCalculate = false;
1690
+ if (state.numPendingInitialLayout > 0) {
1691
+ state.numPendingInitialLayout--;
1692
+ if (state.numPendingInitialLayout === 0) {
1693
+ needsCalculate = true;
1694
+ state.numPendingInitialLayout = -1;
1695
+ }
1696
+ }
1697
+ sizesKnown == null ? void 0 : sizesKnown.set(itemKey, size);
1320
1698
  if (!prevSize || Math.abs(prevSize - size) > 0.5) {
1321
1699
  let diff;
1700
+ needsCalculate = true;
1322
1701
  if (numColumns > 1) {
1323
- const prevMaxSizeInRow = getRowHeight(row);
1702
+ const rowNumber = Math.floor(index / numColumnsProp);
1703
+ const prevSizeInRow = getRowHeight(rowNumber);
1324
1704
  sizes.set(itemKey, size);
1325
- const column = columns.get(itemKey);
1326
- const loopStart = index - (column - 1);
1327
- let nextMaxSizeInRow = 0;
1328
- for (let i = loopStart; i < loopStart + numColumns && i < data2.length; i++) {
1329
- const id = getId(i);
1330
- const size2 = getItemSize(id, i, data2[i]);
1331
- nextMaxSizeInRow = Math.max(nextMaxSizeInRow, size2);
1332
- }
1333
- diff = nextMaxSizeInRow - prevMaxSizeInRow;
1705
+ rowHeights.delete(rowNumber);
1706
+ const sizeInRow = getRowHeight(rowNumber);
1707
+ diff = sizeInRow - prevSizeInRow;
1334
1708
  } else {
1335
1709
  sizes.set(itemKey, size);
1336
1710
  diff = size - prevSize;
1337
1711
  }
1338
1712
  if (__DEV__ && !estimatedItemSize && !getEstimatedItemSize) {
1339
- sizesLaidOut.set(itemKey, size);
1340
1713
  if (state.timeoutSizeMessage) {
1341
1714
  clearTimeout(state.timeoutSizeMessage);
1342
1715
  }
@@ -1344,7 +1717,7 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
1344
1717
  state.timeoutSizeMessage = void 0;
1345
1718
  let total = 0;
1346
1719
  let num = 0;
1347
- for (const [key, size2] of sizesLaidOut) {
1720
+ for (const [_, size2] of sizesKnown) {
1348
1721
  num++;
1349
1722
  total += size2;
1350
1723
  }
@@ -1356,38 +1729,48 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
1356
1729
  }
1357
1730
  refState.current.scrollForNextCalculateItemsInView = void 0;
1358
1731
  addTotalSize(itemKey, diff, 0);
1359
- doMaintainScrollAtEnd(true);
1732
+ doMaintainScrollAtEnd(false);
1733
+ if (onItemSizeChanged) {
1734
+ onItemSizeChanged({
1735
+ size,
1736
+ previous: prevSize,
1737
+ index,
1738
+ itemKey,
1739
+ itemData: data[index]
1740
+ });
1741
+ }
1742
+ }
1743
+ if (needsCalculate) {
1360
1744
  const scrollVelocity = 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
- }
1369
- });
1745
+ if ((Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1) && (!waitForInitialLayout || state.numPendingInitialLayout < 0)) {
1746
+ if (Date.now() - state.lastBatchingAction < 500) {
1747
+ if (!state.queuedCalculateItemsInView) {
1748
+ state.queuedCalculateItemsInView = requestAnimationFrame(() => {
1749
+ state.queuedCalculateItemsInView = void 0;
1750
+ calculateItemsInView();
1751
+ });
1752
+ }
1370
1753
  } else {
1371
- calculateItemsInView(state.scrollVelocity);
1754
+ calculateItemsInView();
1372
1755
  }
1373
1756
  }
1374
- if (onItemSizeChanged) {
1375
- onItemSizeChanged({ size, previous: prevSize, index, itemKey, itemData: data2[index] });
1376
- }
1377
1757
  }
1378
1758
  }, []);
1379
- const handleScrollDebounced = React5.useCallback((velocity) => {
1380
- calculateItemsInView(velocity);
1381
- checkAtBottom();
1382
- checkAtTop();
1383
- }, []);
1384
- const onLayout = React5.useCallback((event) => {
1759
+ const onLayout = React6.useCallback((event) => {
1760
+ const state = refState.current;
1385
1761
  const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
1386
- refState.current.scrollLength = scrollLength;
1762
+ const didChange = scrollLength !== state.scrollLength;
1763
+ state.scrollLength = scrollLength;
1764
+ state.lastBatchingAction = Date.now();
1765
+ state.scrollForNextCalculateItemsInView = void 0;
1766
+ doInitialAllocateContainers();
1387
1767
  doMaintainScrollAtEnd(false);
1388
1768
  doUpdatePaddingTop();
1389
1769
  checkAtBottom();
1390
1770
  checkAtTop();
1771
+ if (didChange) {
1772
+ calculateItemsInView();
1773
+ }
1391
1774
  if (__DEV__) {
1392
1775
  const isWidthZero = event.nativeEvent.layout.width === 0;
1393
1776
  const isHeightZero = event.nativeEvent.layout.height === 0;
@@ -1397,17 +1780,24 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
1397
1780
  );
1398
1781
  }
1399
1782
  }
1783
+ if (onLayoutProp) {
1784
+ onLayoutProp(event);
1785
+ }
1400
1786
  }, []);
1401
- const handleScroll = React5.useCallback(
1787
+ const handleScroll = React6.useCallback(
1402
1788
  (event, fromSelf) => {
1403
- var _a2, _b2, _c2;
1789
+ var _a2, _b2, _c2, _d2;
1404
1790
  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) {
1405
1791
  return;
1406
1792
  }
1407
1793
  const state = refState.current;
1794
+ const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
1795
+ if (state.ignoreScrollFromCalcTotal && newScroll !== 0) {
1796
+ return;
1797
+ }
1408
1798
  state.hasScrolled = true;
1799
+ state.lastBatchingAction = Date.now();
1409
1800
  const currentTime = performance.now();
1410
- const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
1411
1801
  if (!(state.scrollHistory.length === 0 && newScroll === initialContentOffset)) {
1412
1802
  state.scrollHistory.push({ scroll: newScroll, time: currentTime });
1413
1803
  }
@@ -1433,71 +1823,173 @@ var LegendListInner = React5.forwardRef(function LegendListInner2(props, forward
1433
1823
  state.scroll = newScroll;
1434
1824
  state.scrollTime = currentTime;
1435
1825
  state.scrollVelocity = velocity;
1436
- handleScrollDebounced(velocity);
1826
+ calculateItemsInView();
1827
+ checkAtBottom();
1828
+ checkAtTop();
1437
1829
  if (!fromSelf) {
1438
- onScrollProp == null ? void 0 : onScrollProp(event);
1830
+ (_d2 = state.onScroll) == null ? void 0 : _d2.call(state, event);
1439
1831
  }
1440
1832
  },
1441
1833
  []
1442
1834
  );
1443
- React5.useImperativeHandle(
1835
+ React6.useImperativeHandle(
1444
1836
  forwardedRef,
1445
1837
  () => {
1446
- const scrollToIndex = ({ index, animated }) => {
1447
- const offsetObj = calculateInitialOffset(index);
1448
- const offset = horizontal ? { x: offsetObj, y: 0 } : { x: 0, y: offsetObj };
1449
- refScroller.current.scrollTo({ ...offset, animated });
1838
+ const scrollToIndex = ({
1839
+ index,
1840
+ viewOffset = 0,
1841
+ animated = true,
1842
+ viewPosition = 0
1843
+ }) => {
1844
+ var _a2;
1845
+ const state = refState.current;
1846
+ const firstIndexOffset = calculateOffsetForIndex(index);
1847
+ let firstIndexScrollPostion = firstIndexOffset - viewOffset;
1848
+ const diff = Math.abs(state.scroll - firstIndexScrollPostion);
1849
+ const needsReanchoring = maintainVisibleContentPosition && diff > 100;
1850
+ state.scrollForNextCalculateItemsInView = void 0;
1851
+ if (needsReanchoring) {
1852
+ const id = getId(index);
1853
+ state.anchorElement = { id, coordinate: firstIndexOffset };
1854
+ (_a2 = state.belowAnchorElementPositions) == null ? void 0 : _a2.clear();
1855
+ state.positions.clear();
1856
+ calcTotalSizesAndPositions({ forgetPositions: true });
1857
+ state.startBufferedId = id;
1858
+ state.minIndexSizeChanged = index;
1859
+ firstIndexScrollPostion = firstIndexOffset - viewOffset + state.scrollAdjustHandler.getAppliedAdjust();
1860
+ }
1861
+ state.scrollAdjustHandler.setDisableAdjust(true);
1862
+ setTimeout(
1863
+ () => {
1864
+ state.scrollAdjustHandler.setDisableAdjust(false);
1865
+ calculateItemsInView();
1866
+ },
1867
+ animated ? 150 : 50
1868
+ );
1869
+ if (viewPosition) {
1870
+ firstIndexScrollPostion -= viewPosition * (state.scrollLength - getItemSize(getId(index), index, state.data[index]));
1871
+ }
1872
+ scrollTo(firstIndexScrollPostion, animated);
1873
+ const totalSizeWithScrollAdjust = peek$(ctx, "totalSizeWithScrollAdjust");
1874
+ if (maintainVisibleContentPosition && totalSizeWithScrollAdjust - firstIndexScrollPostion < state.scrollLength) {
1875
+ const doScrollTo = () => {
1876
+ scrollTo(firstIndexScrollPostion, animated);
1877
+ };
1878
+ setTimeout(doScrollTo, animated ? 150 : 50);
1879
+ if (animated) {
1880
+ setTimeout(doScrollTo, 350);
1881
+ }
1882
+ }
1883
+ };
1884
+ const scrollIndexIntoView = (options) => {
1885
+ if (refState.current) {
1886
+ const { index, ...rest2 } = options;
1887
+ const { startNoBuffer, endNoBuffer } = refState.current;
1888
+ if (index < startNoBuffer || index > endNoBuffer) {
1889
+ const viewPosition = index < startNoBuffer ? 0 : 1;
1890
+ scrollToIndex({
1891
+ ...rest2,
1892
+ viewPosition,
1893
+ index
1894
+ });
1895
+ }
1896
+ }
1450
1897
  };
1451
1898
  return {
1899
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
1452
1900
  getNativeScrollRef: () => refScroller.current,
1453
- getScrollableNode: refScroller.current.getScrollableNode,
1454
- getScrollResponder: refScroller.current.getScrollResponder,
1455
- flashScrollIndicators: refScroller.current.flashScrollIndicators,
1456
- scrollToIndex,
1457
- scrollToOffset: ({ offset, animated }) => {
1458
- const offsetObj = horizontal ? { x: offset, y: 0 } : { x: 0, y: offset };
1459
- refScroller.current.scrollTo({ ...offsetObj, animated });
1901
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
1902
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
1903
+ getState: () => {
1904
+ const state = refState.current;
1905
+ return state ? {
1906
+ contentLength: state.totalSize,
1907
+ end: state.endNoBuffer,
1908
+ endBuffered: state.endBuffered,
1909
+ isAtEnd: state.isAtBottom,
1910
+ isAtStart: state.isAtTop,
1911
+ scroll: state.scroll,
1912
+ scrollLength: state.scrollLength,
1913
+ start: state.startNoBuffer,
1914
+ startBuffered: state.startBuffered
1915
+ } : {};
1916
+ },
1917
+ scrollIndexIntoView,
1918
+ scrollItemIntoView: ({ item, ...props2 }) => {
1919
+ const { data } = refState.current;
1920
+ const index = data.indexOf(item);
1921
+ if (index !== -1) {
1922
+ scrollIndexIntoView({ index, ...props2 });
1923
+ }
1460
1924
  },
1461
- scrollToItem: ({ item, animated }) => {
1925
+ scrollToIndex,
1926
+ scrollToItem: ({ item, ...props2 }) => {
1927
+ const { data } = refState.current;
1462
1928
  const index = data.indexOf(item);
1463
1929
  if (index !== -1) {
1464
- scrollToIndex({ index, animated });
1930
+ scrollToIndex({ index, ...props2 });
1465
1931
  }
1466
1932
  },
1467
- scrollToEnd: refScroller.current.scrollToEnd
1933
+ scrollToOffset: ({ offset, animated }) => {
1934
+ scrollTo(offset, animated);
1935
+ },
1936
+ scrollToEnd: (options) => refScroller.current.scrollToEnd(options)
1468
1937
  };
1469
1938
  },
1470
1939
  []
1471
1940
  );
1472
- return /* @__PURE__ */ React5__namespace.createElement(
1941
+ if (reactNative.Platform.OS === "web") {
1942
+ React6.useEffect(() => {
1943
+ var _a2;
1944
+ if (initialContentOffset) {
1945
+ (_a2 = refState.current) == null ? void 0 : _a2.scrollAdjustHandler.setDisableAdjust(true);
1946
+ scrollTo(initialContentOffset, false);
1947
+ setTimeout(() => {
1948
+ var _a3;
1949
+ (_a3 = refState.current) == null ? void 0 : _a3.scrollAdjustHandler.setDisableAdjust(false);
1950
+ }, 0);
1951
+ }
1952
+ }, []);
1953
+ }
1954
+ return /* @__PURE__ */ React6__namespace.createElement(React6__namespace.Fragment, null, /* @__PURE__ */ React6__namespace.createElement(
1473
1955
  ListComponent,
1474
1956
  {
1475
1957
  ...rest,
1476
1958
  horizontal,
1477
- refScrollView: (r) => {
1478
- refScroller.current = r;
1479
- if (refScrollView) {
1480
- if (typeof refScrollView === "function") {
1481
- refScrollView(r);
1482
- } else {
1483
- refScrollView.current = r;
1484
- }
1485
- }
1486
- },
1959
+ refScrollView: combinedRef,
1487
1960
  initialContentOffset,
1488
1961
  getRenderedItem,
1489
1962
  updateItemSize,
1490
1963
  handleScroll,
1964
+ onMomentumScrollEnd: (event) => {
1965
+ const wasPaused = refState.current.scrollAdjustHandler.unPauseAdjust();
1966
+ if (wasPaused) {
1967
+ refState.current.scrollVelocity = 0;
1968
+ refState.current.scrollHistory = [];
1969
+ calculateItemsInView();
1970
+ }
1971
+ if (onMomentumScrollEnd) {
1972
+ onMomentumScrollEnd(event);
1973
+ }
1974
+ },
1491
1975
  onLayout,
1492
1976
  recycleItems,
1493
1977
  alignItemsAtEnd,
1494
- ListEmptyComponent: data.length === 0 ? ListEmptyComponent : void 0,
1978
+ ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
1495
1979
  maintainVisibleContentPosition,
1496
1980
  scrollEventThrottle: scrollEventThrottle != null ? scrollEventThrottle : reactNative.Platform.OS === "web" ? 16 : void 0,
1497
1981
  waitForInitialLayout,
1982
+ refreshControl: refreshControl != null ? refreshControl : onRefresh && /* @__PURE__ */ React6__namespace.createElement(
1983
+ reactNative.RefreshControl,
1984
+ {
1985
+ refreshing: !!refreshing,
1986
+ onRefresh,
1987
+ progressViewOffset
1988
+ }
1989
+ ),
1498
1990
  style
1499
1991
  }
1500
- );
1992
+ ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React6__namespace.createElement(DebugView, { state: refState.current }));
1501
1993
  });
1502
1994
 
1503
1995
  exports.LegendList = LegendList;