@legendapp/list 2.0.0-next.0 → 2.0.0-next.1

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.
Files changed (5) hide show
  1. package/index.d.mts +48 -6
  2. package/index.d.ts +48 -6
  3. package/index.js +1395 -1238
  4. package/index.mjs +1347 -1190
  5. package/package.json +1 -1
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var React2 = require('react');
3
+ var React3 = require('react');
4
4
  var reactNative = require('react-native');
5
5
  var shim = require('use-sync-external-store/shim');
6
6
 
@@ -22,12 +22,12 @@ function _interopNamespace(e) {
22
22
  return Object.freeze(n);
23
23
  }
24
24
 
25
- var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
25
+ var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
26
26
 
27
27
  // src/LegendList.tsx
28
- var ContextState = React2__namespace.createContext(null);
28
+ var ContextState = React3__namespace.createContext(null);
29
29
  function StateProvider({ children }) {
30
- const [value] = React2__namespace.useState(() => ({
30
+ const [value] = React3__namespace.useState(() => ({
31
31
  listeners: /* @__PURE__ */ new Map(),
32
32
  values: /* @__PURE__ */ new Map([
33
33
  ["alignItemsPaddingTop", 0],
@@ -41,10 +41,10 @@ function StateProvider({ children }) {
41
41
  columnWrapperStyle: void 0,
42
42
  viewRefs: /* @__PURE__ */ new Map()
43
43
  }));
44
- return /* @__PURE__ */ React2__namespace.createElement(ContextState.Provider, { value }, children);
44
+ return /* @__PURE__ */ React3__namespace.createElement(ContextState.Provider, { value }, children);
45
45
  }
46
46
  function useStateContext() {
47
- return React2__namespace.useContext(ContextState);
47
+ return React3__namespace.useContext(ContextState);
48
48
  }
49
49
  function createSelectorFunctionsArr(ctx, signalNames) {
50
50
  let lastValues = [];
@@ -114,23 +114,23 @@ function getContentSize(ctx) {
114
114
  return headerSize + footerSize + totalSize + stylePaddingTop;
115
115
  }
116
116
  function useArr$(signalNames) {
117
- const ctx = React2__namespace.useContext(ContextState);
118
- const { subscribe, get } = React2__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
117
+ const ctx = React3__namespace.useContext(ContextState);
118
+ const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
119
119
  const value = shim.useSyncExternalStore(subscribe, get);
120
120
  return value;
121
121
  }
122
122
  function useSelector$(signalName, selector) {
123
- const ctx = React2__namespace.useContext(ContextState);
124
- const { subscribe, get } = React2__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
123
+ const ctx = React3__namespace.useContext(ContextState);
124
+ const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
125
125
  const value = shim.useSyncExternalStore(subscribe, () => selector(get()[0]));
126
126
  return value;
127
127
  }
128
128
 
129
129
  // src/DebugView.tsx
130
130
  var DebugRow = ({ children }) => {
131
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" } }, children);
131
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "space-between" } }, children);
132
132
  };
133
- var DebugView = React2__namespace.memo(function DebugView2({ state }) {
133
+ var DebugView = React3__namespace.memo(function DebugView2({ state }) {
134
134
  const ctx = useStateContext();
135
135
  const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, numContainers = 0, numContainersPooled = 0] = useArr$([
136
136
  "totalSize",
@@ -141,11 +141,11 @@ var DebugView = React2__namespace.memo(function DebugView2({ state }) {
141
141
  "numContainersPooled"
142
142
  ]);
143
143
  const contentSize = getContentSize(ctx);
144
- const [, forceUpdate] = React2.useReducer((x) => x + 1, 0);
144
+ const [, forceUpdate] = React3.useReducer((x) => x + 1, 0);
145
145
  useInterval(() => {
146
146
  forceUpdate();
147
147
  }, 100);
148
- return /* @__PURE__ */ React2__namespace.createElement(
148
+ return /* @__PURE__ */ React3__namespace.createElement(
149
149
  reactNative.View,
150
150
  {
151
151
  style: {
@@ -161,18 +161,18 @@ var DebugView = React2__namespace.memo(function DebugView2({ state }) {
161
161
  },
162
162
  pointerEvents: "none"
163
163
  },
164
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "TotalSize:"), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, totalSize.toFixed(2))),
165
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "ContentSize:"), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, contentSize.toFixed(2))),
166
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "At end:"), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, String(state.isAtEnd))),
167
- /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null),
168
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "ScrollAdjust:"), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, scrollAdjust.toFixed(2))),
169
- /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null),
170
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "RawScroll: "), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, rawScroll.toFixed(2))),
171
- /* @__PURE__ */ React2__namespace.createElement(DebugRow, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, "ComputedScroll: "), /* @__PURE__ */ React2__namespace.createElement(reactNative.Text, null, scroll.toFixed(2)))
164
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "TotalSize:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, totalSize.toFixed(2))),
165
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "ContentSize:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, contentSize.toFixed(2))),
166
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "At end:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, String(state.isAtEnd))),
167
+ /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null),
168
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "ScrollAdjust:"), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, scrollAdjust.toFixed(2))),
169
+ /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null),
170
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "RawScroll: "), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, rawScroll.toFixed(2))),
171
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, "ComputedScroll: "), /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, null, scroll.toFixed(2)))
172
172
  );
173
173
  });
174
174
  function useInterval(callback, delay) {
175
- React2.useEffect(() => {
175
+ React3.useEffect(() => {
176
176
  const interval = setInterval(callback, delay);
177
177
  return () => clearInterval(interval);
178
178
  }, [delay]);
@@ -192,12 +192,12 @@ function warnDevOnce(id, text) {
192
192
  console.warn(`[legend-list] ${text}`);
193
193
  }
194
194
  }
195
+ function roundSize(size) {
196
+ return Math.floor(size * 8) / 8;
197
+ }
195
198
  function isNullOrUndefined(value) {
196
199
  return value === null || value === void 0;
197
200
  }
198
- function comparatorByDistance(a, b) {
199
- return b.distance - a.distance;
200
- }
201
201
  function comparatorDefault(a, b) {
202
202
  return a - b;
203
203
  }
@@ -210,7 +210,7 @@ function extractPadding(style, contentContainerStyle, type) {
210
210
  }
211
211
  var symbolFirst = Symbol();
212
212
  function useInit(cb) {
213
- const refValue = React2.useRef(symbolFirst);
213
+ const refValue = React3.useRef(symbolFirst);
214
214
  if (refValue.current === symbolFirst) {
215
215
  refValue.current = cb();
216
216
  }
@@ -218,10 +218,10 @@ function useInit(cb) {
218
218
  }
219
219
 
220
220
  // src/ContextContainer.ts
221
- var ContextContainer = React2.createContext(null);
221
+ var ContextContainer = React3.createContext(null);
222
222
  function useViewability(callback, configId) {
223
223
  const ctx = useStateContext();
224
- const { containerId } = React2.useContext(ContextContainer);
224
+ const { containerId } = React3.useContext(ContextContainer);
225
225
  const key = containerId + (configId != null ? configId : "");
226
226
  useInit(() => {
227
227
  const value = ctx.mapViewabilityValues.get(key);
@@ -230,7 +230,7 @@ function useViewability(callback, configId) {
230
230
  }
231
231
  });
232
232
  ctx.mapViewabilityCallbacks.set(key, callback);
233
- React2.useEffect(
233
+ React3.useEffect(
234
234
  () => () => {
235
235
  ctx.mapViewabilityCallbacks.delete(key);
236
236
  },
@@ -239,7 +239,7 @@ function useViewability(callback, configId) {
239
239
  }
240
240
  function useViewabilityAmount(callback) {
241
241
  const ctx = useStateContext();
242
- const { containerId } = React2.useContext(ContextContainer);
242
+ const { containerId } = React3.useContext(ContextContainer);
243
243
  useInit(() => {
244
244
  const value = ctx.mapViewabilityAmountValues.get(containerId);
245
245
  if (value) {
@@ -247,7 +247,7 @@ function useViewabilityAmount(callback) {
247
247
  }
248
248
  });
249
249
  ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
250
- React2.useEffect(
250
+ React3.useEffect(
251
251
  () => () => {
252
252
  ctx.mapViewabilityAmountCallbacks.delete(containerId);
253
253
  },
@@ -255,12 +255,12 @@ function useViewabilityAmount(callback) {
255
255
  );
256
256
  }
257
257
  function useRecyclingEffect(effect) {
258
- const { index, value } = React2.useContext(ContextContainer);
259
- const prevValues = React2.useRef({
258
+ const { index, value } = React3.useContext(ContextContainer);
259
+ const prevValues = React3.useRef({
260
260
  prevIndex: void 0,
261
261
  prevItem: void 0
262
262
  });
263
- React2.useEffect(() => {
263
+ React3.useEffect(() => {
264
264
  let ret = void 0;
265
265
  if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
266
266
  ret = effect({
@@ -278,33 +278,34 @@ function useRecyclingEffect(effect) {
278
278
  }, [index, value]);
279
279
  }
280
280
  function useRecyclingState(valueOrFun) {
281
- const { index, value, itemKey, triggerLayout } = React2.useContext(ContextContainer);
282
- const refState = React2.useRef({
281
+ const { index, value, itemKey, triggerLayout } = React3.useContext(ContextContainer);
282
+ const refState = React3.useRef({
283
283
  itemKey: null,
284
284
  value: null
285
285
  });
286
- const [_, setRenderNum] = React2.useState(0);
287
- if (refState.current.itemKey !== itemKey) {
288
- refState.current.itemKey = itemKey;
289
- refState.current.value = isFunction(valueOrFun) ? valueOrFun({
286
+ const [_, setRenderNum] = React3.useState(0);
287
+ const state = refState.current;
288
+ if (state.itemKey !== itemKey) {
289
+ state.itemKey = itemKey;
290
+ state.value = isFunction(valueOrFun) ? valueOrFun({
290
291
  index,
291
292
  item: value,
292
293
  prevIndex: void 0,
293
294
  prevItem: void 0
294
295
  }) : valueOrFun;
295
296
  }
296
- const setState = React2.useCallback(
297
+ const setState = React3.useCallback(
297
298
  (newState) => {
298
- refState.current.value = isFunction(newState) ? newState(refState.current.value) : newState;
299
+ state.value = isFunction(newState) ? newState(state.value) : newState;
299
300
  setRenderNum((v) => v + 1);
300
301
  triggerLayout();
301
302
  },
302
- [triggerLayout]
303
+ [triggerLayout, state]
303
304
  );
304
- return [refState.current.value, setState];
305
+ return [state.value, setState];
305
306
  }
306
307
  function useIsLastItem() {
307
- const { itemKey } = React2.useContext(ContextContainer);
308
+ const { itemKey } = React3.useContext(ContextContainer);
308
309
  const isLast = useSelector$("lastItemKeys", (lastItemKeys) => (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false);
309
310
  return isLast;
310
311
  }
@@ -312,12 +313,19 @@ function useListScrollSize() {
312
313
  const [scrollSize] = useArr$(["scrollSize"]);
313
314
  return scrollSize;
314
315
  }
315
- var LeanViewComponent = React2__namespace.forwardRef((props, ref) => {
316
- return React2__namespace.createElement("RCTView", { ...props, ref });
316
+ var LeanViewComponent = React3__namespace.forwardRef((props, ref) => {
317
+ return React3__namespace.createElement("RCTView", { ...props, ref });
317
318
  });
318
319
  LeanViewComponent.displayName = "RCTView";
319
320
  var LeanView = reactNative.Platform.OS === "android" || reactNative.Platform.OS === "ios" ? LeanViewComponent : reactNative.View;
320
321
 
322
+ // src/Separator.tsx
323
+ function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
324
+ const [lastItemKeys] = useArr$(["lastItemKeys"]);
325
+ const isALastItem = lastItemKeys.includes(itemKey);
326
+ return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
327
+ }
328
+
321
329
  // src/constants.ts
322
330
  var POSITION_OUT_OF_VIEW = -1e7;
323
331
  var ENABLE_DEVMODE = __DEV__ && false;
@@ -329,39 +337,37 @@ var Container = ({
329
337
  id,
330
338
  recycleItems,
331
339
  horizontal,
332
- getRenderedItem,
333
- updateItemSize,
340
+ getRenderedItem: getRenderedItem2,
341
+ updateItemSize: updateItemSize2,
334
342
  ItemSeparatorComponent
335
343
  }) => {
336
344
  const ctx = useStateContext();
337
345
  const columnWrapperStyle = ctx.columnWrapperStyle;
338
- const [column = 0, data, itemKey, position = POSITION_OUT_OF_VIEW, numColumns, lastItemKeys, extraData] = useArr$([
346
+ const [column = 0, data, itemKey, position = POSITION_OUT_OF_VIEW, numColumns, extraData] = useArr$([
339
347
  `containerColumn${id}`,
340
348
  `containerItemData${id}`,
341
349
  `containerItemKey${id}`,
342
350
  `containerPosition${id}`,
343
351
  "numColumns",
344
- "lastItemKeys",
345
352
  "extraData"
346
353
  ]);
347
- const refLastSize = React2.useRef();
348
- const ref = React2.useRef(null);
349
- const [layoutRenderCount, forceLayoutRender] = React2.useState(0);
354
+ const refLastSize = React3.useRef();
355
+ const ref = React3.useRef(null);
356
+ const [layoutRenderCount, forceLayoutRender] = React3.useState(0);
350
357
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
351
358
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
352
- const isALastItem = lastItemKeys.includes(itemKey);
353
359
  let didLayout = false;
354
360
  let paddingStyles;
355
361
  if (columnWrapperStyle) {
356
362
  const { columnGap, rowGap, gap } = columnWrapperStyle;
357
363
  if (horizontal) {
358
364
  paddingStyles = {
359
- paddingRight: !isALastItem ? columnGap || gap || void 0 : void 0,
365
+ paddingRight: columnGap || gap || void 0,
360
366
  paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
361
367
  };
362
368
  } else {
363
369
  paddingStyles = {
364
- paddingBottom: !isALastItem ? rowGap || gap || void 0 : void 0,
370
+ paddingBottom: rowGap || gap || void 0,
365
371
  paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
366
372
  };
367
373
  }
@@ -381,15 +387,15 @@ var Container = ({
381
387
  top: position,
382
388
  ...paddingStyles || {}
383
389
  };
384
- const renderedItemInfo = React2.useMemo(
385
- () => itemKey !== void 0 ? getRenderedItem(itemKey) : null,
390
+ const renderedItemInfo = React3.useMemo(
391
+ () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
386
392
  [itemKey, data, extraData]
387
393
  );
388
394
  const { index, renderedItem } = renderedItemInfo || {};
389
- const triggerLayout = React2.useCallback(() => {
395
+ const triggerLayout = React3.useCallback(() => {
390
396
  forceLayoutRender((v) => v + 1);
391
397
  }, []);
392
- const contextValue = React2.useMemo(() => {
398
+ const contextValue = React3.useMemo(() => {
393
399
  ctx.viewRefs.set(id, ref);
394
400
  return { containerId: id, itemKey, index, value: data, triggerLayout };
395
401
  }, [id, itemKey, index, data]);
@@ -401,7 +407,7 @@ var Container = ({
401
407
  const size = layout[horizontal ? "width" : "height"];
402
408
  const doUpdate = () => {
403
409
  refLastSize.current = { width: layout.width, height: layout.height };
404
- updateItemSize(itemKey, layout);
410
+ updateItemSize2(itemKey, layout);
405
411
  };
406
412
  if (IsNewArchitecture || size > 0) {
407
413
  doUpdate();
@@ -414,24 +420,24 @@ var Container = ({
414
420
  }
415
421
  };
416
422
  if (IsNewArchitecture) {
417
- React2.useLayoutEffect(() => {
423
+ React3.useLayoutEffect(() => {
418
424
  var _a, _b;
419
425
  if (!isNullOrUndefined(itemKey)) {
420
426
  const measured = (_b = (_a = ref.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
421
427
  if (measured) {
422
428
  const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
423
429
  if (size) {
424
- updateItemSize(itemKey, measured);
430
+ updateItemSize2(itemKey, measured);
425
431
  }
426
432
  }
427
433
  }
428
- }, [itemKey, layoutRenderCount, isALastItem]);
434
+ }, [itemKey, layoutRenderCount]);
429
435
  } else {
430
- React2.useEffect(() => {
436
+ React3.useEffect(() => {
431
437
  if (!isNullOrUndefined(itemKey)) {
432
438
  const timeout = setTimeout(() => {
433
439
  if (!didLayout && refLastSize.current) {
434
- updateItemSize(itemKey, refLastSize.current);
440
+ updateItemSize2(itemKey, refLastSize.current);
435
441
  }
436
442
  }, 16);
437
443
  return () => {
@@ -440,12 +446,19 @@ var Container = ({
440
446
  }
441
447
  }, [itemKey]);
442
448
  }
443
- return /* @__PURE__ */ React2__namespace.createElement(LeanView, { style, onLayout, ref, key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React2__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && !isALastItem && /* @__PURE__ */ React2__namespace.createElement(ItemSeparatorComponent, { leadingItem: renderedItemInfo.item })));
449
+ return /* @__PURE__ */ React3__namespace.createElement(LeanView, { style, onLayout, ref, key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(
450
+ Separator,
451
+ {
452
+ itemKey,
453
+ ItemSeparatorComponent,
454
+ leadingItem: renderedItemInfo.item
455
+ }
456
+ )));
444
457
  };
445
- var typedForwardRef = React2.forwardRef;
446
- var typedMemo = React2.memo;
458
+ var typedForwardRef = React3.forwardRef;
459
+ var typedMemo = React3.memo;
447
460
  var useAnimatedValue = (initialValue) => {
448
- return React2.useRef(new reactNative.Animated.Value(initialValue)).current;
461
+ return React3.useRef(new reactNative.Animated.Value(initialValue)).current;
449
462
  };
450
463
 
451
464
  // src/useValue$.ts
@@ -454,7 +467,7 @@ function useValue$(key, params) {
454
467
  const { getValue, delay } = params || {};
455
468
  const ctx = useStateContext();
456
469
  const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
457
- React2.useMemo(() => {
470
+ React3.useMemo(() => {
458
471
  let newValue = void 0;
459
472
  let prevValue = void 0;
460
473
  let didQueueTask = false;
@@ -491,8 +504,8 @@ var Containers = typedMemo(function Containers2({
491
504
  recycleItems,
492
505
  ItemSeparatorComponent,
493
506
  waitForInitialLayout,
494
- updateItemSize,
495
- getRenderedItem
507
+ updateItemSize: updateItemSize2,
508
+ getRenderedItem: getRenderedItem2
496
509
  }) {
497
510
  const ctx = useStateContext();
498
511
  const columnWrapperStyle = ctx.columnWrapperStyle;
@@ -506,15 +519,15 @@ var Containers = typedMemo(function Containers2({
506
519
  const containers = [];
507
520
  for (let i = 0; i < numContainers; i++) {
508
521
  containers.push(
509
- /* @__PURE__ */ React2__namespace.createElement(
522
+ /* @__PURE__ */ React3__namespace.createElement(
510
523
  Container,
511
524
  {
512
525
  id: i,
513
526
  key: i,
514
527
  recycleItems,
515
528
  horizontal,
516
- getRenderedItem,
517
- updateItemSize,
529
+ getRenderedItem: getRenderedItem2,
530
+ updateItemSize: updateItemSize2,
518
531
  ItemSeparatorComponent
519
532
  }
520
533
  )
@@ -523,25 +536,31 @@ var Containers = typedMemo(function Containers2({
523
536
  const style = horizontal ? { width: animSize, opacity: animOpacity, minHeight: otherAxisSize } : { height: animSize, opacity: animOpacity, minWidth: otherAxisSize };
524
537
  if (columnWrapperStyle && numColumns > 1) {
525
538
  const { columnGap, rowGap, gap } = columnWrapperStyle;
539
+ const gapX = columnGap || gap || 0;
540
+ const gapY = rowGap || gap || 0;
526
541
  if (horizontal) {
527
- const my = (rowGap || gap || 0) / 2;
528
- if (my) {
529
- style.marginVertical = -my;
542
+ if (gapY) {
543
+ style.marginVertical = -gapY / 2;
544
+ }
545
+ if (gapX) {
546
+ style.marginRight = -gapX;
530
547
  }
531
548
  } else {
532
- const mx = (columnGap || gap || 0) / 2;
533
- if (mx) {
534
- style.marginHorizontal = -mx;
549
+ if (gapX) {
550
+ style.marginHorizontal = -gapX;
551
+ }
552
+ if (gapY) {
553
+ style.marginBottom = -gapY;
535
554
  }
536
555
  }
537
556
  }
538
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style }, containers);
557
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.Animated.View, { style }, containers);
539
558
  });
540
559
  function ScrollAdjust() {
541
560
  const bias = 1e7;
542
561
  const [scrollAdjust, scrollAdjustUserOffset] = useArr$(["scrollAdjust", "scrollAdjustUserOffset"]);
543
562
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0) + bias;
544
- return /* @__PURE__ */ React2__namespace.createElement(
563
+ return /* @__PURE__ */ React3__namespace.createElement(
545
564
  reactNative.View,
546
565
  {
547
566
  style: {
@@ -557,14 +576,14 @@ function ScrollAdjust() {
557
576
  function useSyncLayout({
558
577
  onChange
559
578
  }) {
560
- const ref = React2.useRef(null);
561
- const onLayout = React2.useCallback(
579
+ const ref = React3.useRef(null);
580
+ const onLayout = React3.useCallback(
562
581
  (event) => {
563
582
  onChange(event.nativeEvent.layout, false);
564
583
  },
565
584
  [onChange]
566
585
  );
567
- React2.useLayoutEffect(() => {
586
+ React3.useLayoutEffect(() => {
568
587
  if (ref.current) {
569
588
  ref.current.measure((x, y, width, height) => {
570
589
  onChange({ x, y, width, height }, true);
@@ -576,21 +595,21 @@ function useSyncLayout({
576
595
 
577
596
  // src/ListComponent.tsx
578
597
  var getComponent = (Component) => {
579
- if (React2__namespace.isValidElement(Component)) {
598
+ if (React3__namespace.isValidElement(Component)) {
580
599
  return Component;
581
600
  }
582
601
  if (Component) {
583
- return /* @__PURE__ */ React2__namespace.createElement(Component, null);
602
+ return /* @__PURE__ */ React3__namespace.createElement(Component, null);
584
603
  }
585
604
  return null;
586
605
  };
587
606
  var Padding = () => {
588
607
  const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
589
- return /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } });
608
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } });
590
609
  };
591
610
  var PaddingDevMode = () => {
592
611
  const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
593
- return /* @__PURE__ */ React2__namespace.createElement(React2__namespace.Fragment, null, /* @__PURE__ */ React2__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React2__namespace.createElement(
612
+ return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React3__namespace.createElement(
594
613
  reactNative.Animated.View,
595
614
  {
596
615
  style: {
@@ -614,15 +633,15 @@ var ListComponent = typedMemo(function ListComponent2({
614
633
  ItemSeparatorComponent,
615
634
  alignItemsAtEnd,
616
635
  waitForInitialLayout,
617
- handleScroll,
636
+ onScroll: onScroll2,
618
637
  onLayout,
619
638
  ListHeaderComponent,
620
639
  ListHeaderComponentStyle,
621
640
  ListFooterComponent,
622
641
  ListFooterComponentStyle,
623
642
  ListEmptyComponent,
624
- getRenderedItem,
625
- updateItemSize,
643
+ getRenderedItem: getRenderedItem2,
644
+ updateItemSize: updateItemSize2,
626
645
  refScrollView,
627
646
  maintainVisibleContentPosition,
628
647
  renderScrollComponent,
@@ -634,18 +653,18 @@ var ListComponent = typedMemo(function ListComponent2({
634
653
  const { onLayout: onLayoutHeaderSync, ref: refHeader } = useSyncLayout({
635
654
  onChange: onLayoutHeader
636
655
  });
637
- const ScrollComponent = renderScrollComponent ? React2.useMemo(
638
- () => React2__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
656
+ const ScrollComponent = renderScrollComponent ? React3.useMemo(
657
+ () => React3__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
639
658
  [renderScrollComponent]
640
659
  ) : reactNative.ScrollView;
641
- React2__namespace.useEffect(() => {
660
+ React3__namespace.useEffect(() => {
642
661
  if (canRender) {
643
662
  setTimeout(() => {
644
663
  scrollAdjustHandler.setMounted();
645
664
  }, 0);
646
665
  }
647
666
  }, [canRender]);
648
- return /* @__PURE__ */ React2__namespace.createElement(
667
+ return /* @__PURE__ */ React3__namespace.createElement(
649
668
  ScrollComponent,
650
669
  {
651
670
  ...rest,
@@ -657,28 +676,28 @@ var ListComponent = typedMemo(function ListComponent2({
657
676
  height: "100%"
658
677
  } : {}
659
678
  ],
660
- onScroll: handleScroll,
679
+ onScroll: onScroll2,
661
680
  onLayout,
662
681
  horizontal,
663
682
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
664
683
  ref: refScrollView
665
684
  },
666
- maintainVisibleContentPosition && /* @__PURE__ */ React2__namespace.createElement(ScrollAdjust, null),
667
- ENABLE_DEVMODE ? /* @__PURE__ */ React2__namespace.createElement(PaddingDevMode, null) : /* @__PURE__ */ React2__namespace.createElement(Padding, null),
668
- ListHeaderComponent && /* @__PURE__ */ React2__namespace.createElement(reactNative.View, { style: ListHeaderComponentStyle, onLayout: onLayoutHeaderSync, ref: refHeader }, getComponent(ListHeaderComponent)),
685
+ maintainVisibleContentPosition && /* @__PURE__ */ React3__namespace.createElement(ScrollAdjust, null),
686
+ ENABLE_DEVMODE ? /* @__PURE__ */ React3__namespace.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3__namespace.createElement(Padding, null),
687
+ ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(reactNative.View, { style: ListHeaderComponentStyle, onLayout: onLayoutHeaderSync, ref: refHeader }, getComponent(ListHeaderComponent)),
669
688
  ListEmptyComponent && getComponent(ListEmptyComponent),
670
- canRender && /* @__PURE__ */ React2__namespace.createElement(
689
+ canRender && /* @__PURE__ */ React3__namespace.createElement(
671
690
  Containers,
672
691
  {
673
692
  horizontal,
674
693
  recycleItems,
675
694
  waitForInitialLayout,
676
- getRenderedItem,
695
+ getRenderedItem: getRenderedItem2,
677
696
  ItemSeparatorComponent,
678
- updateItemSize
697
+ updateItemSize: updateItemSize2
679
698
  }
680
699
  ),
681
- ListFooterComponent && /* @__PURE__ */ React2__namespace.createElement(
700
+ ListFooterComponent && /* @__PURE__ */ React3__namespace.createElement(
682
701
  reactNative.View,
683
702
  {
684
703
  style: ListFooterComponentStyle,
@@ -713,22 +732,545 @@ var ScrollAdjustHandler = class {
713
732
  this.mounted = true;
714
733
  }
715
734
  };
716
- var useCombinedRef = (...refs) => {
717
- const callback = React2.useCallback((element) => {
718
- for (const ref of refs) {
719
- if (!ref) {
720
- continue;
735
+
736
+ // src/getId.ts
737
+ function getId(state, index) {
738
+ const { data, keyExtractor } = state.props;
739
+ if (!data) {
740
+ return "";
741
+ }
742
+ const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
743
+ const id = ret;
744
+ state.idCache.set(index, id);
745
+ return id;
746
+ }
747
+
748
+ // src/calculateOffsetForIndex.ts
749
+ function calculateOffsetForIndex(ctx, state, index) {
750
+ let position = 0;
751
+ if (index !== void 0) {
752
+ position = (state == null ? void 0 : state.positions.get(getId(state, index))) || 0;
753
+ }
754
+ const paddingTop = peek$(ctx, "stylePaddingTop");
755
+ if (paddingTop) {
756
+ position += paddingTop;
757
+ }
758
+ const headerSize = peek$(ctx, "headerSize");
759
+ if (headerSize) {
760
+ position += headerSize;
761
+ }
762
+ return position;
763
+ }
764
+
765
+ // src/getItemSize.ts
766
+ function getItemSize(state, key, index, data, useAverageSize) {
767
+ const {
768
+ sizesKnown,
769
+ sizes,
770
+ scrollingTo,
771
+ props: { estimatedItemSize, getEstimatedItemSize }
772
+ } = state;
773
+ const sizeKnown = sizesKnown.get(key);
774
+ if (sizeKnown !== void 0) {
775
+ return sizeKnown;
776
+ }
777
+ let size;
778
+ if (IsNewArchitecture && useAverageSize !== void 0 && sizeKnown === void 0 && !getEstimatedItemSize && !scrollingTo) {
779
+ size = useAverageSize;
780
+ }
781
+ if (size === void 0) {
782
+ size = sizes.get(key);
783
+ if (size !== void 0) {
784
+ return size;
785
+ }
786
+ }
787
+ if (size === void 0) {
788
+ size = getEstimatedItemSize ? getEstimatedItemSize(index, data) : estimatedItemSize;
789
+ }
790
+ sizes.set(key, size);
791
+ return size;
792
+ }
793
+
794
+ // src/calculateOffsetWithOffsetPosition.ts
795
+ function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
796
+ const { index, viewOffset, viewPosition } = params;
797
+ let offset = offsetParam;
798
+ if (viewOffset) {
799
+ offset -= viewOffset;
800
+ }
801
+ if (viewPosition !== void 0 && index !== void 0) {
802
+ offset -= viewPosition * (state.scrollLength - getItemSize(state, getId(state, index), index, state.props.data[index]));
803
+ }
804
+ return offset;
805
+ }
806
+
807
+ // src/checkAllSizesKnown.ts
808
+ function checkAllSizesKnown(state) {
809
+ const { startBuffered, endBuffered, sizesKnown } = state;
810
+ if (endBuffered !== null) {
811
+ let areAllKnown = true;
812
+ for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
813
+ const key = getId(state, i);
814
+ areAllKnown && (areAllKnown = sizesKnown.has(key));
815
+ }
816
+ return areAllKnown;
817
+ }
818
+ return false;
819
+ }
820
+
821
+ // src/findAvailableContainers.ts
822
+ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
823
+ const numContainers = peek$(ctx, "numContainers");
824
+ const result = [];
825
+ const availableContainers = [];
826
+ for (let u = 0; u < numContainers; u++) {
827
+ const key = peek$(ctx, `containerItemKey${u}`);
828
+ let isOk = key === void 0;
829
+ if (!isOk) {
830
+ const index = pendingRemoval.indexOf(u);
831
+ if (index !== -1) {
832
+ pendingRemoval.splice(index, 1);
833
+ isOk = true;
721
834
  }
722
- if (isFunction(ref)) {
723
- ref(element);
724
- } else {
725
- ref.current = element;
835
+ }
836
+ if (isOk) {
837
+ result.push(u);
838
+ if (result.length >= numNeeded) {
839
+ return result;
726
840
  }
727
841
  }
728
- }, refs);
729
- return callback;
842
+ }
843
+ for (let u = 0; u < numContainers; u++) {
844
+ const key = peek$(ctx, `containerItemKey${u}`);
845
+ if (key === void 0) continue;
846
+ const index = state.indexByKey.get(key);
847
+ if (index < startBuffered) {
848
+ availableContainers.push({ index: u, distance: startBuffered - index });
849
+ } else if (index > endBuffered) {
850
+ availableContainers.push({ index: u, distance: index - endBuffered });
851
+ }
852
+ }
853
+ const remaining = numNeeded - result.length;
854
+ if (remaining > 0) {
855
+ if (availableContainers.length > 0) {
856
+ if (availableContainers.length > remaining) {
857
+ availableContainers.sort(comparatorByDistance);
858
+ availableContainers.length = remaining;
859
+ }
860
+ for (const container of availableContainers) {
861
+ result.push(container.index);
862
+ }
863
+ }
864
+ const stillNeeded = numNeeded - result.length;
865
+ if (stillNeeded > 0) {
866
+ for (let i = 0; i < stillNeeded; i++) {
867
+ result.push(numContainers + i);
868
+ }
869
+ if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
870
+ console.warn(
871
+ "[legend-list] No unused container available, 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 or increasing initialContainerPoolRatio.",
872
+ {
873
+ debugInfo: {
874
+ numContainers,
875
+ numNeeded,
876
+ stillNeeded,
877
+ numContainersPooled: peek$(ctx, "numContainersPooled")
878
+ }
879
+ }
880
+ );
881
+ }
882
+ }
883
+ }
884
+ return result.sort(comparatorDefault);
885
+ }
886
+ function comparatorByDistance(a, b) {
887
+ return b.distance - a.distance;
888
+ }
889
+
890
+ // src/getScrollVelocity.ts
891
+ var getScrollVelocity = (state) => {
892
+ const { scrollHistory } = state;
893
+ let velocity = 0;
894
+ if (scrollHistory.length >= 1) {
895
+ const newest = scrollHistory[scrollHistory.length - 1];
896
+ let oldest;
897
+ let start = 0;
898
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
899
+ const entry = scrollHistory[i];
900
+ const nextEntry = scrollHistory[i + 1];
901
+ if (i > 0) {
902
+ const prevEntry = scrollHistory[i - 1];
903
+ const prevDirection = entry.scroll - prevEntry.scroll;
904
+ const currentDirection = nextEntry.scroll - entry.scroll;
905
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
906
+ start = i;
907
+ break;
908
+ }
909
+ }
910
+ }
911
+ for (let i = start; i < scrollHistory.length - 1; i++) {
912
+ const entry = scrollHistory[i];
913
+ if (newest.time - entry.time <= 1e3) {
914
+ oldest = entry;
915
+ break;
916
+ }
917
+ }
918
+ if (oldest) {
919
+ const scrollDiff = newest.scroll - oldest.scroll;
920
+ const timeDiff = newest.time - oldest.time;
921
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
922
+ }
923
+ }
924
+ return velocity;
925
+ };
926
+
927
+ // src/requestAdjust.ts
928
+ function requestAdjust(ctx, state, positionDiff) {
929
+ if (Math.abs(positionDiff) > 0.1) {
930
+ const doit = () => {
931
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
932
+ };
933
+ state.scroll += positionDiff;
934
+ state.scrollForNextCalculateItemsInView = void 0;
935
+ if (peek$(ctx, "containersDidLayout")) {
936
+ doit();
937
+ } else {
938
+ requestAnimationFrame(doit);
939
+ }
940
+ const threshold = state.scroll - positionDiff / 2;
941
+ if (!state.ignoreScrollFromMVCP) {
942
+ state.ignoreScrollFromMVCP = {};
943
+ }
944
+ if (positionDiff > 0) {
945
+ state.ignoreScrollFromMVCP.lt = threshold;
946
+ } else {
947
+ state.ignoreScrollFromMVCP.gt = threshold;
948
+ }
949
+ if (state.ignoreScrollFromMVCPTimeout) {
950
+ clearTimeout(state.ignoreScrollFromMVCPTimeout);
951
+ }
952
+ state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
953
+ state.ignoreScrollFromMVCP = void 0;
954
+ }, 100);
955
+ }
956
+ }
957
+
958
+ // src/prepareMVCP.ts
959
+ function prepareMVCP(ctx, state) {
960
+ const {
961
+ positions,
962
+ scrollingTo,
963
+ props: { maintainVisibleContentPosition }
964
+ } = state;
965
+ let prevPosition;
966
+ let targetId;
967
+ let targetIndex;
968
+ const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
969
+ if (maintainVisibleContentPosition) {
970
+ const indexByKey = state.indexByKey;
971
+ if (scrollTarget !== void 0) {
972
+ targetId = getId(state, scrollTarget);
973
+ targetIndex = scrollTarget;
974
+ } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
975
+ targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
976
+ targetIndex = indexByKey.get(targetId);
977
+ }
978
+ if (targetId !== void 0 && targetIndex !== void 0) {
979
+ prevPosition = positions.get(targetId);
980
+ }
981
+ }
982
+ return () => {
983
+ if (targetId !== void 0 && prevPosition !== void 0) {
984
+ const newPosition = positions.get(targetId);
985
+ if (newPosition !== void 0) {
986
+ const positionDiff = newPosition - prevPosition;
987
+ if (Math.abs(positionDiff) > 0.1) {
988
+ requestAdjust(ctx, state, positionDiff);
989
+ }
990
+ }
991
+ }
992
+ };
993
+ }
994
+
995
+ // src/checkThreshold.ts
996
+ var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
997
+ const distanceAbs = Math.abs(distance);
998
+ const isAtThreshold = atThreshold || distanceAbs < threshold;
999
+ if (!isReached && !isBlockedByTimer) {
1000
+ if (isAtThreshold) {
1001
+ onReached == null ? void 0 : onReached(distance);
1002
+ blockTimer == null ? void 0 : blockTimer(true);
1003
+ setTimeout(() => {
1004
+ blockTimer == null ? void 0 : blockTimer(false);
1005
+ }, 700);
1006
+ return true;
1007
+ }
1008
+ } else {
1009
+ if (distance >= 1.3 * threshold) {
1010
+ return false;
1011
+ }
1012
+ }
1013
+ return isReached;
1014
+ };
1015
+
1016
+ // src/checkAtBottom.ts
1017
+ function checkAtBottom(ctx, state) {
1018
+ if (!state) {
1019
+ return;
1020
+ }
1021
+ const {
1022
+ queuedInitialLayout,
1023
+ scrollLength,
1024
+ scroll,
1025
+ maintainingScrollAtEnd,
1026
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1027
+ } = state;
1028
+ const contentSize = getContentSize(ctx);
1029
+ if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1030
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1031
+ const isContentLess = contentSize < scrollLength;
1032
+ state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1033
+ state.isEndReached = checkThreshold(
1034
+ distanceFromEnd,
1035
+ isContentLess,
1036
+ onEndReachedThreshold * scrollLength,
1037
+ state.isEndReached,
1038
+ state.endReachedBlockedByTimer,
1039
+ (distance) => {
1040
+ var _a, _b;
1041
+ return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1042
+ },
1043
+ (block) => {
1044
+ state.endReachedBlockedByTimer = block;
1045
+ }
1046
+ );
1047
+ }
1048
+ }
1049
+
1050
+ // src/finishScrollTo.ts
1051
+ var finishScrollTo = (state) => {
1052
+ if (state) {
1053
+ state.scrollingTo = void 0;
1054
+ state.scrollHistory.length = 0;
1055
+ }
730
1056
  };
731
1057
 
1058
+ // src/scrollTo.ts
1059
+ function scrollTo(state, params = {}) {
1060
+ var _a;
1061
+ const { animated } = params;
1062
+ const {
1063
+ refScroller,
1064
+ props: { horizontal }
1065
+ } = state;
1066
+ const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1067
+ state.scrollHistory.length = 0;
1068
+ state.scrollingTo = params;
1069
+ state.scrollPending = offset;
1070
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1071
+ x: horizontal ? offset : 0,
1072
+ y: horizontal ? 0 : offset,
1073
+ animated: !!animated
1074
+ });
1075
+ if (!animated) {
1076
+ state.scroll = offset;
1077
+ setTimeout(() => finishScrollTo(state), 100);
1078
+ }
1079
+ }
1080
+
1081
+ // src/scrollToIndex.ts
1082
+ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1083
+ if (index >= state.props.data.length) {
1084
+ index = state.props.data.length - 1;
1085
+ } else if (index < 0) {
1086
+ index = 0;
1087
+ }
1088
+ const firstIndexOffset = calculateOffsetForIndex(ctx, state, index);
1089
+ const isLast = index === state.props.data.length - 1;
1090
+ if (isLast && viewPosition === void 0) {
1091
+ viewPosition = 1;
1092
+ }
1093
+ const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1094
+ state.scrollForNextCalculateItemsInView = void 0;
1095
+ scrollTo(state, {
1096
+ offset: firstIndexScrollPostion,
1097
+ animated,
1098
+ index,
1099
+ viewPosition: viewPosition != null ? viewPosition : 0,
1100
+ viewOffset
1101
+ });
1102
+ }
1103
+
1104
+ // src/setDidLayout.ts
1105
+ function setDidLayout(ctx, state) {
1106
+ const {
1107
+ loadStartTime,
1108
+ initialScroll,
1109
+ props: { onLoad }
1110
+ } = state;
1111
+ state.queuedInitialLayout = true;
1112
+ checkAtBottom(ctx, state);
1113
+ if (!IsNewArchitecture && initialScroll) {
1114
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1115
+ }
1116
+ set$(ctx, "containersDidLayout", true);
1117
+ if (onLoad) {
1118
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1119
+ }
1120
+ }
1121
+
1122
+ // src/setPaddingTop.ts
1123
+ function setPaddingTop(ctx, { stylePaddingTop, alignItemsPaddingTop }) {
1124
+ if (stylePaddingTop !== void 0) {
1125
+ const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1126
+ if (stylePaddingTop < prevStylePaddingTop) {
1127
+ const prevTotalSize = peek$(ctx, "totalSize") || 0;
1128
+ set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
1129
+ setTimeout(() => {
1130
+ set$(ctx, "totalSize", prevTotalSize);
1131
+ }, 16);
1132
+ }
1133
+ set$(ctx, "stylePaddingTop", stylePaddingTop);
1134
+ }
1135
+ if (alignItemsPaddingTop !== void 0) {
1136
+ set$(ctx, "alignItemsPaddingTop", alignItemsPaddingTop);
1137
+ }
1138
+ }
1139
+
1140
+ // src/updateAlignItemsPaddingTop.ts
1141
+ function updateAlignItemsPaddingTop(ctx, state) {
1142
+ const {
1143
+ scrollLength,
1144
+ props: { alignItemsAtEnd, data }
1145
+ } = state;
1146
+ if (alignItemsAtEnd) {
1147
+ let alignItemsPaddingTop = 0;
1148
+ if ((data == null ? void 0 : data.length) > 0) {
1149
+ const contentSize = getContentSize(ctx);
1150
+ alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1151
+ }
1152
+ setPaddingTop(ctx, { alignItemsPaddingTop });
1153
+ }
1154
+ }
1155
+
1156
+ // src/updateTotalSize.ts
1157
+ function updateTotalSize(ctx, state) {
1158
+ const {
1159
+ positions,
1160
+ props: { data }
1161
+ } = state;
1162
+ if (data.length === 0) {
1163
+ addTotalSize(ctx, state, null, 0);
1164
+ } else {
1165
+ const lastId = getId(state, data.length - 1);
1166
+ if (lastId !== void 0) {
1167
+ const lastPosition = positions.get(lastId);
1168
+ if (lastPosition !== void 0) {
1169
+ const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
1170
+ if (lastSize !== void 0) {
1171
+ const totalSize = lastPosition + lastSize;
1172
+ addTotalSize(ctx, state, null, totalSize);
1173
+ }
1174
+ }
1175
+ }
1176
+ }
1177
+ }
1178
+ function addTotalSize(ctx, state, key, add) {
1179
+ const { alignItemsAtEnd } = state.props;
1180
+ {
1181
+ state.totalSize = add;
1182
+ }
1183
+ set$(ctx, "totalSize", state.totalSize);
1184
+ if (alignItemsAtEnd) {
1185
+ updateAlignItemsPaddingTop(ctx, state);
1186
+ }
1187
+ }
1188
+
1189
+ // src/updateAllPositions.ts
1190
+ function updateAllPositions(ctx, state, dataChanged) {
1191
+ var _a, _b, _c, _d, _e;
1192
+ const { averageSizes, columns, indexByKey, positions, firstFullyOnScreenIndex, idCache, sizesKnown } = state;
1193
+ const data = state.props.data;
1194
+ const numColumns = peek$(ctx, "numColumns");
1195
+ const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1196
+ const scrollVelocity = getScrollVelocity(state);
1197
+ if (dataChanged) {
1198
+ indexByKey.clear();
1199
+ idCache.clear();
1200
+ }
1201
+ const itemType = "";
1202
+ let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
1203
+ if (averageSize !== void 0) {
1204
+ averageSize = roundSize(averageSize);
1205
+ }
1206
+ const shouldUseBackwards = !dataChanged && scrollVelocity < 0 && firstFullyOnScreenIndex > 5 && firstFullyOnScreenIndex < data.length;
1207
+ if (shouldUseBackwards && firstFullyOnScreenIndex !== void 0) {
1208
+ const anchorId = getId(state, firstFullyOnScreenIndex);
1209
+ const anchorPosition = positions.get(anchorId);
1210
+ if (anchorPosition !== void 0) {
1211
+ let currentRowTop2 = anchorPosition;
1212
+ let maxSizeInRow2 = 0;
1213
+ let bailout = false;
1214
+ for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
1215
+ const id = (_b = idCache.get(i)) != null ? _b : getId(state, i);
1216
+ const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(state, id, i, data[i], averageSize);
1217
+ const itemColumn = columns.get(id);
1218
+ maxSizeInRow2 = Math.max(maxSizeInRow2, size);
1219
+ if (itemColumn === 1) {
1220
+ currentRowTop2 -= maxSizeInRow2;
1221
+ maxSizeInRow2 = 0;
1222
+ }
1223
+ if (currentRowTop2 < -2e3) {
1224
+ bailout = true;
1225
+ break;
1226
+ }
1227
+ positions.set(id, currentRowTop2);
1228
+ }
1229
+ if (!bailout) {
1230
+ updateTotalSize(ctx, state);
1231
+ return;
1232
+ }
1233
+ }
1234
+ }
1235
+ let currentRowTop = 0;
1236
+ let column = 1;
1237
+ let maxSizeInRow = 0;
1238
+ const hasColumns = numColumns > 1;
1239
+ const needsIndexByKey = dataChanged || indexByKey.size === 0;
1240
+ const dataLength = data.length;
1241
+ for (let i = 0; i < dataLength; i++) {
1242
+ const id = (_d = idCache.get(i)) != null ? _d : getId(state, i);
1243
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(state, id, i, data[i], averageSize);
1244
+ if (__DEV__ && needsIndexByKey) {
1245
+ if (indexByKeyForChecking.has(id)) {
1246
+ console.error(
1247
+ `[legend-list] Error: Detected overlapping key (${id}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`
1248
+ );
1249
+ }
1250
+ indexByKeyForChecking.set(id, i);
1251
+ }
1252
+ positions.set(id, currentRowTop);
1253
+ if (needsIndexByKey) {
1254
+ indexByKey.set(id, i);
1255
+ }
1256
+ columns.set(id, column);
1257
+ if (hasColumns) {
1258
+ if (size > maxSizeInRow) {
1259
+ maxSizeInRow = size;
1260
+ }
1261
+ column++;
1262
+ if (column > numColumns) {
1263
+ currentRowTop += maxSizeInRow;
1264
+ column = 1;
1265
+ maxSizeInRow = 0;
1266
+ }
1267
+ } else {
1268
+ currentRowTop += size;
1269
+ }
1270
+ }
1271
+ updateTotalSize(ctx, state);
1272
+ }
1273
+
732
1274
  // src/viewability.ts
733
1275
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
734
1276
  function setupViewability(props) {
@@ -757,7 +1299,7 @@ function setupViewability(props) {
757
1299
  }
758
1300
  return viewabilityConfigCallbackPairs;
759
1301
  }
760
- function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, getId, scrollSize, start, end) {
1302
+ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
761
1303
  for (const viewabilityConfigCallbackPair of viewabilityConfigCallbackPairs) {
762
1304
  const viewabilityState = mapViewabilityConfigCallbackPairs.get(
763
1305
  viewabilityConfigCallbackPair.viewabilityConfig.id
@@ -767,15 +1309,15 @@ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, getId,
767
1309
  if (viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime) {
768
1310
  const timer = setTimeout(() => {
769
1311
  state.timeouts.delete(timer);
770
- updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, getId, state, ctx, scrollSize);
1312
+ updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
771
1313
  }, viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime);
772
1314
  state.timeouts.add(timer);
773
1315
  } else {
774
- updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, getId, state, ctx, scrollSize);
1316
+ updateViewableItemsWithConfig(state.data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
775
1317
  }
776
1318
  }
777
1319
  }
778
- function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getId, state, ctx, scrollSize) {
1320
+ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize) {
779
1321
  const { viewabilityConfig, onViewableItemsChanged } = viewabilityConfigCallbackPair;
780
1322
  const configId = viewabilityConfig.id;
781
1323
  const viewabilityState = mapViewabilityConfigCallbackPairs.get(configId);
@@ -819,7 +1361,7 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, getI
819
1361
  for (let i = start; i <= end; i++) {
820
1362
  const item = data[i];
821
1363
  if (item) {
822
- const key = getId(i);
1364
+ const key = getId(state, i);
823
1365
  const containerId = findContainerId(ctx, key);
824
1366
  if (isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
825
1367
  const viewToken = {
@@ -915,9 +1457,299 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
915
1457
  cb == null ? void 0 : cb(viewToken);
916
1458
  }
917
1459
 
918
- // src/LegendList.tsx
919
- var DEFAULT_DRAW_DISTANCE = 250;
920
- var DEFAULT_ITEM_SIZE = 100;
1460
+ // src/calculateItemsInView.ts
1461
+ function calculateItemsInView(ctx, state, params = {}) {
1462
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1463
+ const {
1464
+ scrollLength,
1465
+ startBufferedId: startBufferedIdOrig,
1466
+ positions,
1467
+ columns,
1468
+ containerItemKeys,
1469
+ idCache,
1470
+ sizes,
1471
+ indexByKey,
1472
+ scrollForNextCalculateItemsInView,
1473
+ enableScrollForNextCalculateItemsInView,
1474
+ minIndexSizeChanged
1475
+ } = state;
1476
+ const data = state.props.data;
1477
+ if (!data || scrollLength === 0) {
1478
+ return;
1479
+ }
1480
+ const totalSize = peek$(ctx, "totalSize");
1481
+ const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
1482
+ const numColumns = peek$(ctx, "numColumns");
1483
+ const previousScrollAdjust = 0;
1484
+ const { dataChanged, doMVCP } = params;
1485
+ const speed = getScrollVelocity(state);
1486
+ if (doMVCP || dataChanged) {
1487
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state) : void 0;
1488
+ updateAllPositions(ctx, state, dataChanged);
1489
+ checkMVCP == null ? void 0 : checkMVCP();
1490
+ }
1491
+ const scrollExtra = 0;
1492
+ const { queuedInitialLayout } = state;
1493
+ let { scroll: scrollState } = state;
1494
+ const initialScroll = state.props.initialScroll;
1495
+ if (!queuedInitialLayout && initialScroll) {
1496
+ const updatedOffset = calculateOffsetWithOffsetPosition(
1497
+ state,
1498
+ calculateOffsetForIndex(ctx, state, initialScroll.index),
1499
+ initialScroll
1500
+ );
1501
+ scrollState = updatedOffset;
1502
+ }
1503
+ const scrollAdjustPad = -previousScrollAdjust - topPad;
1504
+ let scroll = scrollState + scrollExtra + scrollAdjustPad;
1505
+ if (scroll + scrollLength > totalSize) {
1506
+ scroll = totalSize - scrollLength;
1507
+ }
1508
+ if (ENABLE_DEBUG_VIEW) {
1509
+ set$(ctx, "debugRawScroll", scrollState);
1510
+ set$(ctx, "debugComputedScroll", scroll);
1511
+ }
1512
+ const scrollBuffer = state.props.scrollBuffer;
1513
+ let scrollBufferTop = scrollBuffer;
1514
+ let scrollBufferBottom = scrollBuffer;
1515
+ if (speed > 0) {
1516
+ scrollBufferTop = scrollBuffer * 0.5;
1517
+ scrollBufferBottom = scrollBuffer * 1.5;
1518
+ } else {
1519
+ scrollBufferTop = scrollBuffer * 1.5;
1520
+ scrollBufferBottom = scrollBuffer * 0.5;
1521
+ }
1522
+ const scrollTopBuffered = scroll - scrollBufferTop;
1523
+ const scrollBottom = scroll + scrollLength;
1524
+ const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1525
+ if (scrollForNextCalculateItemsInView) {
1526
+ const { top, bottom } = scrollForNextCalculateItemsInView;
1527
+ if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
1528
+ return;
1529
+ }
1530
+ }
1531
+ let startNoBuffer = null;
1532
+ let startBuffered = null;
1533
+ let startBufferedId = null;
1534
+ let endNoBuffer = null;
1535
+ let endBuffered = null;
1536
+ let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1537
+ if (minIndexSizeChanged !== void 0) {
1538
+ loopStart = Math.min(minIndexSizeChanged, loopStart);
1539
+ state.minIndexSizeChanged = void 0;
1540
+ }
1541
+ for (let i = loopStart; i >= 0; i--) {
1542
+ const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
1543
+ const top = positions.get(id);
1544
+ const size = (_b = sizes.get(id)) != null ? _b : getItemSize(state, id, i, data[i]);
1545
+ const bottom = top + size;
1546
+ if (bottom > scroll - scrollBuffer) {
1547
+ loopStart = i;
1548
+ } else {
1549
+ break;
1550
+ }
1551
+ }
1552
+ const loopStartMod = loopStart % numColumns;
1553
+ if (loopStartMod > 0) {
1554
+ loopStart -= loopStartMod;
1555
+ }
1556
+ let foundEnd = false;
1557
+ let nextTop;
1558
+ let nextBottom;
1559
+ const prevNumContainers = ctx.values.get("numContainers");
1560
+ let maxIndexRendered = 0;
1561
+ for (let i = 0; i < prevNumContainers; i++) {
1562
+ const key = peek$(ctx, `containerItemKey${i}`);
1563
+ if (key !== void 0) {
1564
+ const index = indexByKey.get(key);
1565
+ maxIndexRendered = Math.max(maxIndexRendered, index);
1566
+ }
1567
+ }
1568
+ let firstFullyOnScreenIndex;
1569
+ const dataLength = data.length;
1570
+ for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
1571
+ const id = (_c = idCache.get(i)) != null ? _c : getId(state, i);
1572
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(state, id, i, data[i]);
1573
+ const top = positions.get(id);
1574
+ if (!foundEnd) {
1575
+ if (startNoBuffer === null && top + size > scroll) {
1576
+ startNoBuffer = i;
1577
+ }
1578
+ if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10) {
1579
+ firstFullyOnScreenIndex = i;
1580
+ }
1581
+ if (startBuffered === null && top + size > scrollTopBuffered) {
1582
+ startBuffered = i;
1583
+ startBufferedId = id;
1584
+ nextTop = top;
1585
+ }
1586
+ if (startNoBuffer !== null) {
1587
+ if (top <= scrollBottom) {
1588
+ endNoBuffer = i;
1589
+ }
1590
+ if (top <= scrollBottomBuffered) {
1591
+ endBuffered = i;
1592
+ nextBottom = top + size;
1593
+ } else {
1594
+ foundEnd = true;
1595
+ }
1596
+ }
1597
+ }
1598
+ }
1599
+ const idsInView = [];
1600
+ for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
1601
+ const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1602
+ idsInView.push(id);
1603
+ }
1604
+ Object.assign(state, {
1605
+ startBuffered,
1606
+ startBufferedId,
1607
+ startNoBuffer,
1608
+ endBuffered,
1609
+ endNoBuffer,
1610
+ idsInView,
1611
+ firstFullyOnScreenIndex
1612
+ });
1613
+ if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
1614
+ state.scrollForNextCalculateItemsInView = nextTop !== void 0 && nextBottom !== void 0 ? {
1615
+ top: nextTop,
1616
+ bottom: nextBottom
1617
+ } : void 0;
1618
+ }
1619
+ const numContainers = peek$(ctx, "numContainers");
1620
+ const pendingRemoval = [];
1621
+ if (dataChanged) {
1622
+ for (let i = 0; i < numContainers; i++) {
1623
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
1624
+ if (!state.props.keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1625
+ pendingRemoval.push(i);
1626
+ }
1627
+ }
1628
+ }
1629
+ if (startBuffered !== null && endBuffered !== null) {
1630
+ let numContainers2 = prevNumContainers;
1631
+ const needNewContainers = [];
1632
+ for (let i = startBuffered; i <= endBuffered; i++) {
1633
+ const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
1634
+ if (!containerItemKeys.has(id)) {
1635
+ needNewContainers.push(i);
1636
+ }
1637
+ }
1638
+ if (needNewContainers.length > 0) {
1639
+ const availableContainers = findAvailableContainers(
1640
+ ctx,
1641
+ state,
1642
+ needNewContainers.length,
1643
+ startBuffered,
1644
+ endBuffered,
1645
+ pendingRemoval
1646
+ );
1647
+ for (let idx = 0; idx < needNewContainers.length; idx++) {
1648
+ const i = needNewContainers[idx];
1649
+ const containerIndex = availableContainers[idx];
1650
+ const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
1651
+ const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
1652
+ if (oldKey && oldKey !== id) {
1653
+ containerItemKeys.delete(oldKey);
1654
+ }
1655
+ set$(ctx, `containerItemKey${containerIndex}`, id);
1656
+ set$(ctx, `containerItemData${containerIndex}`, data[i]);
1657
+ containerItemKeys.add(id);
1658
+ if (containerIndex >= numContainers2) {
1659
+ numContainers2 = containerIndex + 1;
1660
+ }
1661
+ }
1662
+ if (numContainers2 !== prevNumContainers) {
1663
+ set$(ctx, "numContainers", numContainers2);
1664
+ if (numContainers2 > peek$(ctx, "numContainersPooled")) {
1665
+ set$(ctx, "numContainersPooled", Math.ceil(numContainers2 * 1.5));
1666
+ }
1667
+ }
1668
+ }
1669
+ }
1670
+ for (let i = 0; i < numContainers; i++) {
1671
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
1672
+ if (pendingRemoval.includes(i)) {
1673
+ if (itemKey) {
1674
+ containerItemKeys.delete(itemKey);
1675
+ }
1676
+ set$(ctx, `containerItemKey${i}`, void 0);
1677
+ set$(ctx, `containerItemData${i}`, void 0);
1678
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1679
+ set$(ctx, `containerColumn${i}`, -1);
1680
+ } else {
1681
+ const itemIndex = indexByKey.get(itemKey);
1682
+ const item = data[itemIndex];
1683
+ if (item !== void 0) {
1684
+ const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
1685
+ const position = positions.get(id);
1686
+ if (position === void 0) {
1687
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1688
+ } else {
1689
+ const pos = positions.get(id);
1690
+ const column = columns.get(id) || 1;
1691
+ const prevPos = peek$(ctx, `containerPosition${i}`);
1692
+ const prevColumn = peek$(ctx, `containerColumn${i}`);
1693
+ const prevData = peek$(ctx, `containerItemData${i}`);
1694
+ if (!prevPos || pos > POSITION_OUT_OF_VIEW && pos !== prevPos) {
1695
+ set$(ctx, `containerPosition${i}`, pos);
1696
+ }
1697
+ if (column >= 0 && column !== prevColumn) {
1698
+ set$(ctx, `containerColumn${i}`, column);
1699
+ }
1700
+ if (prevData !== item) {
1701
+ set$(ctx, `containerItemData${i}`, data[itemIndex]);
1702
+ }
1703
+ }
1704
+ }
1705
+ }
1706
+ }
1707
+ if (!queuedInitialLayout && endBuffered !== null) {
1708
+ if (checkAllSizesKnown(state)) {
1709
+ setDidLayout(ctx, state);
1710
+ }
1711
+ }
1712
+ if (state.props.viewabilityConfigCallbackPairs) {
1713
+ updateViewableItems(
1714
+ state,
1715
+ ctx,
1716
+ state.props.viewabilityConfigCallbackPairs,
1717
+ scrollLength,
1718
+ startNoBuffer,
1719
+ endNoBuffer
1720
+ );
1721
+ }
1722
+ }
1723
+
1724
+ // src/checkAtTop.ts
1725
+ function checkAtTop(state) {
1726
+ if (!state) {
1727
+ return;
1728
+ }
1729
+ const {
1730
+ scrollLength,
1731
+ scroll,
1732
+ props: { onStartReachedThreshold }
1733
+ } = state;
1734
+ const distanceFromTop = scroll;
1735
+ state.isAtStart = distanceFromTop <= 0;
1736
+ state.isStartReached = checkThreshold(
1737
+ distanceFromTop,
1738
+ false,
1739
+ onStartReachedThreshold * scrollLength,
1740
+ state.isStartReached,
1741
+ state.startReachedBlockedByTimer,
1742
+ (distance) => {
1743
+ var _a, _b;
1744
+ return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
1745
+ },
1746
+ (block) => {
1747
+ state.startReachedBlockedByTimer = block;
1748
+ }
1749
+ );
1750
+ }
1751
+
1752
+ // src/createColumnWrapperStyle.ts
921
1753
  function createColumnWrapperStyle(contentContainerStyle) {
922
1754
  const { gap, columnGap, rowGap } = contentContainerStyle;
923
1755
  if (gap || columnGap || rowGap) {
@@ -931,15 +1763,318 @@ function createColumnWrapperStyle(contentContainerStyle) {
931
1763
  };
932
1764
  }
933
1765
  }
934
- var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
935
- return /* @__PURE__ */ React2__namespace.createElement(StateProvider, null, /* @__PURE__ */ React2__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
936
- });
937
- var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
938
- var _a;
939
- const {
940
- data: dataProp = [],
941
- initialScrollIndex: initialScrollIndexProp,
942
- initialScrollOffset,
1766
+
1767
+ // src/doInitialAllocateContainers.ts
1768
+ function doInitialAllocateContainers(ctx, state) {
1769
+ const { scrollLength } = state;
1770
+ const data = state.props.data;
1771
+ if (scrollLength > 0 && data.length > 0 && !peek$(ctx, "numContainers")) {
1772
+ const averageItemSize = state.props.getEstimatedItemSize ? state.props.getEstimatedItemSize(0, data[0]) : state.props.estimatedItemSize;
1773
+ const Extra = 1.5;
1774
+ const numContainers = Math.ceil(
1775
+ (scrollLength + state.props.scrollBuffer * 2) / averageItemSize * state.props.numColumns * Extra
1776
+ );
1777
+ for (let i = 0; i < numContainers; i++) {
1778
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1779
+ set$(ctx, `containerColumn${i}`, -1);
1780
+ }
1781
+ set$(ctx, "numContainers", numContainers);
1782
+ set$(ctx, "numContainersPooled", numContainers * state.props.initialContainerPoolRatio);
1783
+ if (!IsNewArchitecture) {
1784
+ if (state.props.initialScroll) {
1785
+ requestAnimationFrame(() => {
1786
+ calculateItemsInView(ctx, state);
1787
+ });
1788
+ } else {
1789
+ calculateItemsInView(ctx, state);
1790
+ }
1791
+ }
1792
+ return true;
1793
+ }
1794
+ }
1795
+
1796
+ // src/doMaintainScrollAtEnd.ts
1797
+ function doMaintainScrollAtEnd(ctx, state, animated) {
1798
+ const {
1799
+ refScroller,
1800
+ props: { maintainScrollAtEnd }
1801
+ } = state;
1802
+ if ((state == null ? void 0 : state.isAtEnd) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
1803
+ const paddingTop = peek$(ctx, "alignItemsPaddingTop");
1804
+ if (paddingTop > 0) {
1805
+ state.scroll = 0;
1806
+ }
1807
+ requestAnimationFrame(() => {
1808
+ var _a;
1809
+ state.maintainingScrollAtEnd = true;
1810
+ (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
1811
+ animated
1812
+ });
1813
+ setTimeout(
1814
+ () => {
1815
+ state.maintainingScrollAtEnd = false;
1816
+ },
1817
+ 0
1818
+ );
1819
+ });
1820
+ return true;
1821
+ }
1822
+ }
1823
+ function getRenderedItem(ctx, state, key) {
1824
+ if (!state) {
1825
+ return null;
1826
+ }
1827
+ const {
1828
+ indexByKey,
1829
+ props: { data, renderItem: renderItem2 }
1830
+ } = state;
1831
+ const index = indexByKey.get(key);
1832
+ if (index === void 0) {
1833
+ return null;
1834
+ }
1835
+ let renderedItem = null;
1836
+ if (renderItem2) {
1837
+ const itemProps = {
1838
+ item: data[index],
1839
+ index,
1840
+ extraData: peek$(ctx, "extraData")
1841
+ };
1842
+ renderedItem = React3__namespace.default.createElement(renderItem2, itemProps);
1843
+ }
1844
+ return { index, item: data[index], renderedItem };
1845
+ }
1846
+
1847
+ // src/handleLayout.ts
1848
+ function handleLayout(ctx, state, size, setCanRender) {
1849
+ const scrollLength = size[state.props.horizontal ? "width" : "height"];
1850
+ const otherAxisSize = size[state.props.horizontal ? "height" : "width"];
1851
+ const didChange = scrollLength !== state.scrollLength;
1852
+ const prevOtherAxisSize = state.otherAxisSize;
1853
+ state.scrollLength = scrollLength;
1854
+ state.otherAxisSize = otherAxisSize;
1855
+ state.lastBatchingAction = Date.now();
1856
+ state.scrollForNextCalculateItemsInView = void 0;
1857
+ doInitialAllocateContainers(ctx, state);
1858
+ if (didChange) {
1859
+ calculateItemsInView(ctx, state, { doMVCP: true });
1860
+ }
1861
+ if (didChange || otherAxisSize !== prevOtherAxisSize) {
1862
+ set$(ctx, "scrollSize", { width: size.width, height: size.height });
1863
+ }
1864
+ doMaintainScrollAtEnd(ctx, state, false);
1865
+ updateAlignItemsPaddingTop(ctx, state);
1866
+ checkAtBottom(ctx, state);
1867
+ checkAtTop(state);
1868
+ if (state) {
1869
+ state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
1870
+ }
1871
+ if (__DEV__ && scrollLength === 0) {
1872
+ warnDevOnce(
1873
+ "height0",
1874
+ `List ${state.props.horizontal ? "width" : "height"} is 0. You may need to set a style or \`flex: \` for the list, because children are absolutely positioned.`
1875
+ );
1876
+ }
1877
+ calculateItemsInView(ctx, state, { doMVCP: true });
1878
+ setCanRender(true);
1879
+ }
1880
+
1881
+ // src/onScroll.ts
1882
+ function onScroll(ctx, state, event) {
1883
+ var _a, _b, _c, _d, _e;
1884
+ if (((_b = (_a = event.nativeEvent) == null ? void 0 : _a.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
1885
+ return;
1886
+ }
1887
+ const newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
1888
+ const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
1889
+ if (ignoreScrollFromMVCP && !state.scrollingTo) {
1890
+ const { lt, gt } = ignoreScrollFromMVCP;
1891
+ if (lt && newScroll < lt || gt && newScroll > gt) {
1892
+ return;
1893
+ }
1894
+ }
1895
+ state.scrollPending = newScroll;
1896
+ updateScroll(ctx, state, newScroll);
1897
+ (_e = (_d = state.props).onScroll) == null ? void 0 : _e.call(_d, event);
1898
+ }
1899
+ function updateScroll(ctx, state, newScroll) {
1900
+ const scrollingTo = state.scrollingTo;
1901
+ state.hasScrolled = true;
1902
+ state.lastBatchingAction = Date.now();
1903
+ const currentTime = performance.now();
1904
+ if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
1905
+ state.scrollHistory.push({ scroll: newScroll, time: currentTime });
1906
+ }
1907
+ if (state.scrollHistory.length > 5) {
1908
+ state.scrollHistory.shift();
1909
+ }
1910
+ state.scrollPrev = state.scroll;
1911
+ state.scrollPrevTime = state.scrollTime;
1912
+ state.scroll = newScroll;
1913
+ state.scrollTime = currentTime;
1914
+ calculateItemsInView(ctx, state);
1915
+ checkAtBottom(ctx, state);
1916
+ checkAtTop(state);
1917
+ }
1918
+
1919
+ // src/updateItemSize.ts
1920
+ function updateItemSizes(ctx, state, itemUpdates) {
1921
+ var _a;
1922
+ const {
1923
+ props: { horizontal, maintainVisibleContentPosition, suggestEstimatedItemSize, onItemSizeChanged, data }
1924
+ } = state;
1925
+ if (!data) return;
1926
+ let needsRecalculate = false;
1927
+ let shouldMaintainScrollAtEnd = false;
1928
+ let minIndexSizeChanged;
1929
+ let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
1930
+ for (const { itemKey, sizeObj } of itemUpdates) {
1931
+ const index = state.indexByKey.get(itemKey);
1932
+ const prevSizeKnown = state.sizesKnown.get(itemKey);
1933
+ const diff = updateOneItemSize(state, itemKey, sizeObj);
1934
+ const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
1935
+ if (diff !== 0) {
1936
+ minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
1937
+ if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index) {
1938
+ requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
1939
+ }
1940
+ const { startBuffered, endBuffered } = state;
1941
+ needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
1942
+ if (!needsRecalculate) {
1943
+ const numContainers = ctx.values.get("numContainers");
1944
+ for (let i = 0; i < numContainers; i++) {
1945
+ if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
1946
+ needsRecalculate = true;
1947
+ break;
1948
+ }
1949
+ }
1950
+ }
1951
+ if (state.needsOtherAxisSize) {
1952
+ const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
1953
+ maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
1954
+ }
1955
+ if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
1956
+ shouldMaintainScrollAtEnd = true;
1957
+ }
1958
+ onItemSizeChanged == null ? void 0 : onItemSizeChanged({
1959
+ size,
1960
+ previous: size - diff,
1961
+ index,
1962
+ itemKey,
1963
+ itemData: state.props.data[index]
1964
+ });
1965
+ }
1966
+ }
1967
+ if (minIndexSizeChanged !== void 0) {
1968
+ state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
1969
+ }
1970
+ if (__DEV__ && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
1971
+ if (state.timeoutSizeMessage) clearTimeout(state.timeoutSizeMessage);
1972
+ state.timeoutSizeMessage = setTimeout(() => {
1973
+ var _a2;
1974
+ state.timeoutSizeMessage = void 0;
1975
+ const num = state.sizesKnown.size;
1976
+ const avg = (_a2 = state.averageSizes[""]) == null ? void 0 : _a2.avg;
1977
+ console.warn(
1978
+ `[legend-list] Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`
1979
+ );
1980
+ }, 1e3);
1981
+ }
1982
+ const cur = peek$(ctx, "otherAxisSize");
1983
+ if (!cur || maxOtherAxisSize > cur) {
1984
+ set$(ctx, "otherAxisSize", maxOtherAxisSize);
1985
+ }
1986
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
1987
+ if (containersDidLayout || checkAllSizesKnown(state)) {
1988
+ if (needsRecalculate) {
1989
+ state.scrollForNextCalculateItemsInView = void 0;
1990
+ calculateItemsInView(ctx, state, { doMVCP: true });
1991
+ }
1992
+ if (shouldMaintainScrollAtEnd) {
1993
+ doMaintainScrollAtEnd(ctx, state, false);
1994
+ }
1995
+ }
1996
+ }
1997
+ function updateItemSize(ctx, state, itemKey, sizeObj) {
1998
+ var _a, _b;
1999
+ if (IsNewArchitecture) {
2000
+ const { sizesKnown } = state;
2001
+ const numContainers = ctx.values.get("numContainers");
2002
+ const changes = [];
2003
+ for (let i = 0; i < numContainers; i++) {
2004
+ const containerItemKey = peek$(ctx, `containerItemKey${i}`);
2005
+ if (itemKey === containerItemKey) {
2006
+ changes.push({ itemKey, sizeObj });
2007
+ } else if (!sizesKnown.has(containerItemKey) && containerItemKey !== void 0) {
2008
+ const containerRef = ctx.viewRefs.get(i);
2009
+ if (containerRef) {
2010
+ const measured = (_b = (_a = containerRef.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
2011
+ if (measured) {
2012
+ changes.push({ itemKey: containerItemKey, sizeObj: measured });
2013
+ }
2014
+ }
2015
+ }
2016
+ }
2017
+ if (changes.length > 0) {
2018
+ updateItemSizes(ctx, state, changes);
2019
+ }
2020
+ } else {
2021
+ updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
2022
+ }
2023
+ }
2024
+ function updateOneItemSize(state, itemKey, sizeObj) {
2025
+ const {
2026
+ sizes,
2027
+ indexByKey,
2028
+ sizesKnown,
2029
+ averageSizes,
2030
+ props: { data, horizontal }
2031
+ } = state;
2032
+ if (!data) return 0;
2033
+ const index = indexByKey.get(itemKey);
2034
+ const prevSize = getItemSize(state, itemKey, index, data);
2035
+ const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2036
+ sizesKnown.set(itemKey, size);
2037
+ const itemType = "";
2038
+ let averages = averageSizes[itemType];
2039
+ if (!averages) {
2040
+ averages = averageSizes[itemType] = { num: 0, avg: 0 };
2041
+ }
2042
+ averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2043
+ averages.num++;
2044
+ if (!prevSize || Math.abs(prevSize - size) > 0.1) {
2045
+ sizes.set(itemKey, size);
2046
+ return size - prevSize;
2047
+ }
2048
+ return 0;
2049
+ }
2050
+ var useCombinedRef = (...refs) => {
2051
+ const callback = React3.useCallback((element) => {
2052
+ for (const ref of refs) {
2053
+ if (!ref) {
2054
+ continue;
2055
+ }
2056
+ if (isFunction(ref)) {
2057
+ ref(element);
2058
+ } else {
2059
+ ref.current = element;
2060
+ }
2061
+ }
2062
+ }, refs);
2063
+ return callback;
2064
+ };
2065
+
2066
+ // src/LegendList.tsx
2067
+ var DEFAULT_DRAW_DISTANCE = 250;
2068
+ var DEFAULT_ITEM_SIZE = 100;
2069
+ var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
2070
+ return /* @__PURE__ */ React3__namespace.createElement(StateProvider, null, /* @__PURE__ */ React3__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
2071
+ });
2072
+ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
2073
+ var _a;
2074
+ const {
2075
+ data: dataProp = [],
2076
+ initialScrollIndex: initialScrollIndexProp,
2077
+ initialScrollOffset,
943
2078
  horizontal,
944
2079
  drawDistance = 250,
945
2080
  recycleItems = false,
@@ -976,84 +2111,27 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
976
2111
  viewabilityConfig,
977
2112
  viewabilityConfigCallbackPairs,
978
2113
  onViewableItemsChanged,
2114
+ onStartReached,
2115
+ onEndReached,
2116
+ onLoad,
979
2117
  ...rest
980
2118
  } = props;
981
- const [renderNum, setRenderNum] = React2.useState(0);
2119
+ const [renderNum, setRenderNum] = React3.useState(0);
982
2120
  const initialScroll = typeof initialScrollIndexProp === "number" ? { index: initialScrollIndexProp } : initialScrollIndexProp;
983
2121
  const initialScrollIndex = initialScroll == null ? void 0 : initialScroll.index;
984
- const refLoadStartTime = React2.useRef(Date.now());
985
- const [canRender, setCanRender] = React2__namespace.useState(!IsNewArchitecture);
986
- const callbacks = React2.useRef({
987
- onStartReached: rest.onStartReached,
988
- onEndReached: rest.onEndReached
989
- });
990
- callbacks.current.onStartReached = rest.onStartReached;
991
- callbacks.current.onEndReached = rest.onEndReached;
2122
+ const [canRender, setCanRender] = React3__namespace.useState(!IsNewArchitecture);
992
2123
  const contentContainerStyle = { ...reactNative.StyleSheet.flatten(contentContainerStyleProp) };
993
2124
  const style = { ...reactNative.StyleSheet.flatten(styleProp) };
994
2125
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
995
2126
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
996
2127
  const ctx = useStateContext();
997
2128
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
998
- const refScroller = React2.useRef(null);
2129
+ const refScroller = React3.useRef(null);
999
2130
  const combinedRef = useCombinedRef(refScroller, refScrollView);
1000
2131
  const estimatedItemSize = estimatedItemSizeProp != null ? estimatedItemSizeProp : DEFAULT_ITEM_SIZE;
1001
2132
  const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
1002
2133
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
1003
- const refState = React2.useRef();
1004
- const getId = (index) => {
1005
- const state = refState.current;
1006
- if (!(state == null ? void 0 : state.data)) {
1007
- return "";
1008
- }
1009
- const data = state.data;
1010
- const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
1011
- const id = ret;
1012
- state.idCache.set(index, id);
1013
- return id;
1014
- };
1015
- const getItemSize = (key, index, data, useAverageSize = false) => {
1016
- const state = refState.current;
1017
- const sizeKnown = state.sizesKnown.get(key);
1018
- if (sizeKnown !== void 0) {
1019
- return sizeKnown;
1020
- }
1021
- const sizePrevious = state.sizes.get(key);
1022
- if (sizePrevious !== void 0) {
1023
- return sizePrevious;
1024
- }
1025
- const size = getEstimatedItemSize ? getEstimatedItemSize(index, data) : estimatedItemSize;
1026
- state.sizes.set(key, size);
1027
- return size;
1028
- };
1029
- const calculateOffsetForIndex = (index) => {
1030
- var _a2;
1031
- let position = 0;
1032
- if (index !== void 0) {
1033
- position = ((_a2 = refState.current) == null ? void 0 : _a2.positions.get(getId(index))) || 0;
1034
- }
1035
- const paddingTop = peek$(ctx, "stylePaddingTop");
1036
- if (paddingTop) {
1037
- position += paddingTop;
1038
- }
1039
- const headerSize = peek$(ctx, "headerSize");
1040
- if (headerSize) {
1041
- position += headerSize;
1042
- }
1043
- return position;
1044
- };
1045
- const calculateOffsetWithOffsetPosition = (offsetParam, params) => {
1046
- const { index, viewOffset, viewPosition } = params;
1047
- let offset = offsetParam;
1048
- const state = refState.current;
1049
- if (viewOffset) {
1050
- offset -= viewOffset;
1051
- }
1052
- if (viewPosition !== void 0 && index !== void 0) {
1053
- offset -= viewPosition * (state.scrollLength - getItemSize(getId(index), index, state.data[index]));
1054
- }
1055
- return offset;
1056
- };
2134
+ const refState = React3.useRef();
1057
2135
  if (!refState.current) {
1058
2136
  const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { width: 0, height: 0 } : reactNative.Dimensions.get("window"))[horizontal ? "width" : "height"];
1059
2137
  refState.current = {
@@ -1065,7 +2143,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1065
2143
  isEndReached: false,
1066
2144
  isAtEnd: false,
1067
2145
  isAtStart: false,
1068
- data: dataProp,
1069
2146
  scrollLength: initialScrollLength,
1070
2147
  startBuffered: -1,
1071
2148
  startNoBuffer: -1,
@@ -1076,7 +2153,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1076
2153
  totalSize: 0,
1077
2154
  timeouts: /* @__PURE__ */ new Set(),
1078
2155
  viewabilityConfigCallbackPairs: void 0,
1079
- renderItem: void 0,
1080
2156
  scrollAdjustHandler: new ScrollAdjustHandler(ctx),
1081
2157
  nativeMarginTop: 0,
1082
2158
  scrollPrev: 0,
@@ -1095,775 +2171,93 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1095
2171
  queuedCalculateItemsInView: 0,
1096
2172
  lastBatchingAction: Date.now(),
1097
2173
  averageSizes: {},
1098
- onScroll: onScrollProp,
1099
2174
  idsInView: [],
1100
2175
  containerItemKeys: /* @__PURE__ */ new Set(),
1101
- idCache: /* @__PURE__ */ new Map()
2176
+ idCache: /* @__PURE__ */ new Map(),
2177
+ props: {},
2178
+ refScroller: void 0,
2179
+ loadStartTime: Date.now(),
2180
+ initialScroll
1102
2181
  };
1103
2182
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
1104
2183
  set$(ctx, "extraData", extraData);
1105
2184
  }
1106
- const didDataChange = refState.current.data !== dataProp;
1107
- refState.current.data = dataProp;
1108
- refState.current.onScroll = onScrollProp;
1109
- const getScrollVelocity = () => {
1110
- const { scrollHistory } = refState.current;
1111
- let velocity = 0;
1112
- if (scrollHistory.length >= 1) {
1113
- const newest = scrollHistory[scrollHistory.length - 1];
1114
- let oldest;
1115
- for (let i = 0; i < scrollHistory.length - 1; i++) {
1116
- const entry = scrollHistory[i];
1117
- const nextEntry = scrollHistory[i + 1];
1118
- if (i > 0) {
1119
- const prevEntry = scrollHistory[i - 1];
1120
- const prevDirection = entry.scroll - prevEntry.scroll;
1121
- const currentDirection = nextEntry.scroll - entry.scroll;
1122
- if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1123
- break;
1124
- }
1125
- }
1126
- }
1127
- for (let i = 0; i < scrollHistory.length - 1; i++) {
1128
- const entry = scrollHistory[i];
1129
- if (newest.time - entry.time <= 1e3) {
1130
- oldest = entry;
1131
- break;
1132
- }
1133
- }
1134
- if (oldest) {
1135
- const scrollDiff = newest.scroll - oldest.scroll;
1136
- const timeDiff = newest.time - oldest.time;
1137
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1138
- }
1139
- }
1140
- return velocity;
1141
- };
1142
- const updateAllPositions = (dataChanged) => {
1143
- var _a2, _b, _c;
1144
- const { columns, data, indexByKey, positions, firstFullyOnScreenIndex, idCache, sizes } = refState.current;
1145
- const numColumns = (_a2 = peek$(ctx, "numColumns")) != null ? _a2 : numColumnsProp;
1146
- const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1147
- const scrollVelocity = getScrollVelocity();
1148
- if (dataChanged) {
1149
- indexByKey.clear();
1150
- idCache.clear();
1151
- }
1152
- const shouldUseBackwards = !dataChanged && scrollVelocity < 0 && firstFullyOnScreenIndex > 5 && firstFullyOnScreenIndex < data.length;
1153
- if (shouldUseBackwards && firstFullyOnScreenIndex !== void 0) {
1154
- const anchorId = getId(firstFullyOnScreenIndex);
1155
- const anchorPosition = positions.get(anchorId);
1156
- if (anchorPosition !== void 0) {
1157
- let currentRowTop2 = anchorPosition;
1158
- let maxSizeInRow2 = 0;
1159
- let bailout = false;
1160
- for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
1161
- const id = getId(i);
1162
- const size = getItemSize(id, i, data[i], false);
1163
- const itemColumn = columns.get(id);
1164
- maxSizeInRow2 = Math.max(maxSizeInRow2, size);
1165
- if (itemColumn === 1) {
1166
- currentRowTop2 -= maxSizeInRow2;
1167
- maxSizeInRow2 = 0;
1168
- }
1169
- if (currentRowTop2 < -2e3) {
1170
- bailout = true;
1171
- break;
1172
- }
1173
- positions.set(id, currentRowTop2);
1174
- }
1175
- if (!bailout) {
1176
- updateTotalSize();
1177
- return;
1178
- }
1179
- }
1180
- }
1181
- let currentRowTop = 0;
1182
- let column = 1;
1183
- let maxSizeInRow = 0;
1184
- const hasColumns = numColumns > 1;
1185
- const needsIndexByKey = dataChanged || indexByKey.size === 0;
1186
- const dataLength = data.length;
1187
- for (let i = 0; i < dataLength; i++) {
1188
- const id = (_b = idCache.get(i)) != null ? _b : getId(i);
1189
- const size = (_c = sizes.get(id)) != null ? _c : getItemSize(id, i, data[i], false);
1190
- if (__DEV__ && needsIndexByKey) {
1191
- if (indexByKeyForChecking.has(id)) {
1192
- console.error(
1193
- `[legend-list] Error: Detected overlapping key (${id}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`
1194
- );
1195
- }
1196
- indexByKeyForChecking.set(id, i);
1197
- }
1198
- positions.set(id, currentRowTop);
1199
- if (needsIndexByKey) {
1200
- indexByKey.set(id, i);
1201
- }
1202
- columns.set(id, column);
1203
- if (hasColumns) {
1204
- if (size > maxSizeInRow) {
1205
- maxSizeInRow = size;
1206
- }
1207
- column++;
1208
- if (column > numColumns) {
1209
- currentRowTop += maxSizeInRow;
1210
- column = 1;
1211
- maxSizeInRow = 0;
1212
- }
1213
- } else {
1214
- currentRowTop += size;
1215
- }
1216
- }
1217
- updateTotalSize();
1218
- };
1219
- const scrollToIndex = ({
1220
- index,
1221
- viewOffset = 0,
1222
- animated = true,
1223
- viewPosition
1224
- }) => {
1225
- const state = refState.current;
1226
- if (index >= state.data.length) {
1227
- index = state.data.length - 1;
1228
- } else if (index < 0) {
1229
- index = 0;
1230
- }
1231
- const firstIndexOffset = calculateOffsetForIndex(index);
1232
- const isLast = index === state.data.length - 1;
1233
- if (isLast && viewPosition === void 0) {
1234
- viewPosition = 1;
1235
- }
1236
- const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1237
- state.scrollForNextCalculateItemsInView = void 0;
1238
- scrollTo({ offset: firstIndexScrollPostion, animated, index, viewPosition: viewPosition != null ? viewPosition : 0, viewOffset });
1239
- };
1240
- const setDidLayout = () => {
1241
- refState.current.queuedInitialLayout = true;
1242
- checkAtBottom();
1243
- set$(ctx, "containersDidLayout", true);
1244
- if (props.onLoad) {
1245
- props.onLoad({ elapsedTimeInMs: Date.now() - refLoadStartTime.current });
1246
- }
1247
- };
1248
- const addTotalSize = React2.useCallback((key, add) => {
1249
- const state = refState.current;
1250
- if (key === null) {
1251
- state.totalSize = add;
1252
- } else {
1253
- state.totalSize += add;
1254
- }
1255
- set$(ctx, "totalSize", state.totalSize);
1256
- if (alignItemsAtEnd) {
1257
- updateAlignItemsPaddingTop();
1258
- }
1259
- }, []);
1260
- const checkAllSizesKnown = React2.useCallback(() => {
1261
- const { startBuffered, endBuffered, sizesKnown } = refState.current;
1262
- if (endBuffered !== null) {
1263
- let areAllKnown = true;
1264
- for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1265
- const key = getId(i);
1266
- areAllKnown && (areAllKnown = sizesKnown.has(key));
1267
- }
1268
- return areAllKnown;
1269
- }
1270
- return false;
1271
- }, []);
1272
- const requestAdjust = (positionDiff) => {
1273
- if (Math.abs(positionDiff) > 0.1) {
1274
- const state = refState.current;
1275
- const doit = () => {
1276
- state.scrollAdjustHandler.requestAdjust(positionDiff);
1277
- };
1278
- state.scroll += positionDiff;
1279
- state.scrollForNextCalculateItemsInView = void 0;
1280
- if (peek$(ctx, "containersDidLayout")) {
1281
- doit();
1282
- } else {
1283
- requestAnimationFrame(doit);
1284
- }
1285
- const threshold = state.scroll - positionDiff / 2;
1286
- if (!state.ignoreScrollFromMVCP) {
1287
- state.ignoreScrollFromMVCP = {};
1288
- }
1289
- if (positionDiff > 0) {
1290
- state.ignoreScrollFromMVCP.lt = threshold;
1291
- } else {
1292
- state.ignoreScrollFromMVCP.gt = threshold;
1293
- }
1294
- if (state.ignoreScrollFromMVCPTimeout) {
1295
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
1296
- }
1297
- state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
1298
- state.ignoreScrollFromMVCP = void 0;
1299
- }, 100);
1300
- }
1301
- };
1302
- const prepareMVCP = React2.useCallback(() => {
1303
- const state = refState.current;
1304
- const { positions, scrollingTo } = state;
1305
- let prevPosition;
1306
- let targetId;
1307
- let targetIndex;
1308
- const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1309
- if (maintainVisibleContentPosition) {
1310
- const indexByKey = state.indexByKey;
1311
- if (scrollTarget !== void 0) {
1312
- targetId = getId(scrollTarget);
1313
- targetIndex = scrollTarget;
1314
- } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1315
- targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
1316
- targetIndex = indexByKey.get(targetId);
1317
- }
1318
- if (targetId !== void 0 && targetIndex !== void 0) {
1319
- prevPosition = positions.get(targetId);
1320
- }
1321
- }
1322
- return () => {
1323
- if (targetId !== void 0 && prevPosition !== void 0) {
1324
- const newPosition = positions.get(targetId);
1325
- if (newPosition !== void 0) {
1326
- const positionDiff = newPosition - prevPosition;
1327
- if (Math.abs(positionDiff) > 0.1) {
1328
- requestAdjust(positionDiff);
1329
- }
1330
- }
1331
- }
1332
- };
1333
- }, []);
1334
- const calculateItemsInView = React2.useCallback((params = {}) => {
1335
- var _a2, _b, _c, _d, _e, _f, _g, _h;
1336
- const state = refState.current;
1337
- const {
1338
- data,
1339
- scrollLength,
1340
- startBufferedId: startBufferedIdOrig,
1341
- positions,
1342
- columns,
1343
- containerItemKeys,
1344
- idCache,
1345
- sizes,
1346
- indexByKey,
1347
- scrollForNextCalculateItemsInView,
1348
- enableScrollForNextCalculateItemsInView,
1349
- minIndexSizeChanged
1350
- } = state;
1351
- if (!data || scrollLength === 0) {
1352
- return;
1353
- }
1354
- const totalSize = peek$(ctx, "totalSize");
1355
- const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
1356
- const numColumns = peek$(ctx, "numColumns");
1357
- const previousScrollAdjust = 0;
1358
- const { dataChanged, doMVCP } = params;
1359
- const speed = getScrollVelocity();
1360
- if (doMVCP || dataChanged) {
1361
- const checkMVCP = doMVCP ? prepareMVCP() : void 0;
1362
- updateAllPositions(dataChanged);
1363
- checkMVCP == null ? void 0 : checkMVCP();
1364
- }
1365
- const scrollExtra = 0;
1366
- const useAverageSize = false;
1367
- const { queuedInitialLayout } = state;
1368
- let { scroll: scrollState } = state;
1369
- if (!queuedInitialLayout && initialScroll) {
1370
- const updatedOffset = calculateOffsetWithOffsetPosition(
1371
- calculateOffsetForIndex(initialScroll.index),
1372
- initialScroll
1373
- );
1374
- scrollState = updatedOffset;
1375
- }
1376
- const scrollAdjustPad = -previousScrollAdjust - topPad;
1377
- let scroll = scrollState + scrollExtra + scrollAdjustPad;
1378
- if (scroll + scrollLength > totalSize) {
1379
- scroll = totalSize - scrollLength;
1380
- }
1381
- if (ENABLE_DEBUG_VIEW) {
1382
- set$(ctx, "debugRawScroll", scrollState);
1383
- set$(ctx, "debugComputedScroll", scroll);
1384
- }
1385
- let scrollBufferTop = scrollBuffer;
1386
- let scrollBufferBottom = scrollBuffer;
1387
- if (speed > 0) {
1388
- scrollBufferTop = scrollBuffer * 0.5;
1389
- scrollBufferBottom = scrollBuffer * 1.5;
1390
- } else {
1391
- scrollBufferTop = scrollBuffer * 1.5;
1392
- scrollBufferBottom = scrollBuffer * 0.5;
1393
- }
1394
- const scrollTopBuffered = scroll - scrollBufferTop;
1395
- const scrollBottom = scroll + scrollLength;
1396
- const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1397
- if (scrollForNextCalculateItemsInView) {
1398
- const { top, bottom } = scrollForNextCalculateItemsInView;
1399
- if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
1400
- return;
1401
- }
1402
- }
1403
- let startNoBuffer = null;
1404
- let startBuffered = null;
1405
- let startBufferedId = null;
1406
- let endNoBuffer = null;
1407
- let endBuffered = null;
1408
- let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1409
- if (minIndexSizeChanged !== void 0) {
1410
- loopStart = Math.min(minIndexSizeChanged, loopStart);
1411
- state.minIndexSizeChanged = void 0;
1412
- }
1413
- for (let i = loopStart; i >= 0; i--) {
1414
- const id = (_a2 = idCache.get(i)) != null ? _a2 : getId(i);
1415
- const top = positions.get(id);
1416
- const size = (_b = sizes.get(id)) != null ? _b : getItemSize(id, i, data[i], useAverageSize);
1417
- const bottom = top + size;
1418
- if (bottom > scroll - scrollBuffer) {
1419
- loopStart = i;
1420
- } else {
1421
- break;
1422
- }
1423
- }
1424
- const loopStartMod = loopStart % numColumns;
1425
- if (loopStartMod > 0) {
1426
- loopStart -= loopStartMod;
1427
- }
1428
- let foundEnd = false;
1429
- let nextTop;
1430
- let nextBottom;
1431
- const prevNumContainers = ctx.values.get("numContainers");
1432
- let maxIndexRendered = 0;
1433
- for (let i = 0; i < prevNumContainers; i++) {
1434
- const key = peek$(ctx, `containerItemKey${i}`);
1435
- if (key !== void 0) {
1436
- const index = indexByKey.get(key);
1437
- maxIndexRendered = Math.max(maxIndexRendered, index);
1438
- }
1439
- }
1440
- let firstFullyOnScreenIndex;
1441
- const dataLength = data.length;
1442
- for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
1443
- const id = (_c = idCache.get(i)) != null ? _c : getId(i);
1444
- const size = (_d = sizes.get(id)) != null ? _d : getItemSize(id, i, data[i], useAverageSize);
1445
- const top = positions.get(id);
1446
- if (!foundEnd) {
1447
- if (startNoBuffer === null && top + size > scroll) {
1448
- startNoBuffer = i;
1449
- }
1450
- if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10) {
1451
- firstFullyOnScreenIndex = i;
1452
- }
1453
- if (startBuffered === null && top + size > scrollTopBuffered) {
1454
- startBuffered = i;
1455
- startBufferedId = id;
1456
- nextTop = top;
1457
- }
1458
- if (startNoBuffer !== null) {
1459
- if (top <= scrollBottom) {
1460
- endNoBuffer = i;
1461
- }
1462
- if (top <= scrollBottomBuffered) {
1463
- endBuffered = i;
1464
- nextBottom = top + size;
1465
- } else {
1466
- foundEnd = true;
1467
- }
1468
- }
1469
- }
1470
- }
1471
- const idsInView = [];
1472
- for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
1473
- const id = (_e = idCache.get(i)) != null ? _e : getId(i);
1474
- idsInView.push(id);
1475
- }
1476
- Object.assign(state, {
1477
- startBuffered,
1478
- startBufferedId,
1479
- startNoBuffer,
1480
- endBuffered,
1481
- endNoBuffer,
1482
- idsInView,
1483
- firstFullyOnScreenIndex
1484
- });
1485
- if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
1486
- state.scrollForNextCalculateItemsInView = nextTop !== void 0 && nextBottom !== void 0 ? {
1487
- top: nextTop,
1488
- bottom: nextBottom
1489
- } : void 0;
1490
- }
1491
- const numContainers = peek$(ctx, "numContainers");
1492
- const pendingRemoval = [];
1493
- if (dataChanged) {
1494
- for (let i = 0; i < numContainers; i++) {
1495
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1496
- if (!keyExtractorProp || itemKey && indexByKey.get(itemKey) === void 0) {
1497
- pendingRemoval.push(i);
1498
- }
1499
- }
1500
- }
1501
- if (startBuffered !== null && endBuffered !== null) {
1502
- let numContainers2 = prevNumContainers;
1503
- const needNewContainers = [];
1504
- for (let i = startBuffered; i <= endBuffered; i++) {
1505
- const id = (_f = idCache.get(i)) != null ? _f : getId(i);
1506
- if (!containerItemKeys.has(id)) {
1507
- needNewContainers.push(i);
1508
- }
1509
- }
1510
- if (needNewContainers.length > 0) {
1511
- const availableContainers = findAvailableContainers(
1512
- needNewContainers.length,
1513
- startBuffered,
1514
- endBuffered,
1515
- pendingRemoval
1516
- );
1517
- for (let idx = 0; idx < needNewContainers.length; idx++) {
1518
- const i = needNewContainers[idx];
1519
- const containerIndex = availableContainers[idx];
1520
- const id = (_g = idCache.get(i)) != null ? _g : getId(i);
1521
- const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
1522
- if (oldKey && oldKey !== id) {
1523
- containerItemKeys.delete(oldKey);
1524
- }
1525
- set$(ctx, `containerItemKey${containerIndex}`, id);
1526
- set$(ctx, `containerItemData${containerIndex}`, data[i]);
1527
- containerItemKeys.add(id);
1528
- if (containerIndex >= numContainers2) {
1529
- numContainers2 = containerIndex + 1;
1530
- }
1531
- }
1532
- if (numContainers2 !== prevNumContainers) {
1533
- set$(ctx, "numContainers", numContainers2);
1534
- if (numContainers2 > peek$(ctx, "numContainersPooled")) {
1535
- set$(ctx, "numContainersPooled", Math.ceil(numContainers2 * 1.5));
1536
- }
1537
- }
1538
- }
1539
- for (let i = 0; i < numContainers2; i++) {
1540
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1541
- if (pendingRemoval.includes(i)) {
1542
- if (itemKey) {
1543
- containerItemKeys.delete(itemKey);
1544
- }
1545
- set$(ctx, `containerItemKey${i}`, void 0);
1546
- set$(ctx, `containerItemData${i}`, void 0);
1547
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1548
- set$(ctx, `containerColumn${i}`, -1);
1549
- } else {
1550
- const itemIndex = indexByKey.get(itemKey);
1551
- const item = data[itemIndex];
1552
- if (item !== void 0) {
1553
- const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(itemIndex);
1554
- const position = positions.get(id);
1555
- if (position === void 0) {
1556
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1557
- } else {
1558
- const pos = positions.get(id);
1559
- const column = columns.get(id) || 1;
1560
- const prevPos = peek$(ctx, `containerPosition${i}`);
1561
- const prevColumn = peek$(ctx, `containerColumn${i}`);
1562
- const prevData = peek$(ctx, `containerItemData${i}`);
1563
- if (!prevPos || pos > POSITION_OUT_OF_VIEW && pos !== prevPos) {
1564
- set$(ctx, `containerPosition${i}`, pos);
1565
- }
1566
- if (column >= 0 && column !== prevColumn) {
1567
- set$(ctx, `containerColumn${i}`, column);
1568
- }
1569
- if (prevData !== item) {
1570
- set$(ctx, `containerItemData${i}`, data[itemIndex]);
1571
- }
1572
- }
1573
- }
1574
- }
1575
- }
1576
- }
1577
- if (!queuedInitialLayout && endBuffered !== null) {
1578
- if (checkAllSizesKnown()) {
1579
- setDidLayout();
1580
- }
1581
- }
1582
- if (viewabilityConfigCallbackPairs) {
1583
- updateViewableItems(
1584
- state,
1585
- ctx,
1586
- viewabilityConfigCallbackPairs,
1587
- getId,
1588
- scrollLength,
1589
- startNoBuffer,
1590
- endNoBuffer
1591
- );
1592
- }
1593
- }, []);
1594
- const setPaddingTop = ({
1595
- stylePaddingTop,
1596
- alignItemsPaddingTop
1597
- }) => {
1598
- if (stylePaddingTop !== void 0) {
1599
- const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1600
- if (stylePaddingTop < prevStylePaddingTop) {
1601
- const prevTotalSize = peek$(ctx, "totalSize") || 0;
1602
- set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
1603
- setTimeout(() => {
1604
- set$(ctx, "totalSize", prevTotalSize);
1605
- }, 16);
1606
- }
1607
- set$(ctx, "stylePaddingTop", stylePaddingTop);
1608
- }
1609
- if (alignItemsPaddingTop !== void 0) {
1610
- set$(ctx, "alignItemsPaddingTop", alignItemsPaddingTop);
1611
- }
1612
- };
1613
- const updateAlignItemsPaddingTop = () => {
1614
- if (alignItemsAtEnd) {
1615
- const { data, scrollLength } = refState.current;
1616
- let alignItemsPaddingTop = 0;
1617
- if ((data == null ? void 0 : data.length) > 0) {
1618
- const contentSize = getContentSize(ctx);
1619
- alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1620
- }
1621
- setPaddingTop({ alignItemsPaddingTop });
1622
- }
1623
- };
1624
- const finishScrollTo = () => {
1625
- const state = refState.current;
1626
- if (state) {
1627
- state.scrollingTo = void 0;
1628
- state.scrollHistory.length = 0;
1629
- }
1630
- };
1631
- const scrollTo = (params = {}) => {
1632
- var _a2;
1633
- const state = refState.current;
1634
- const { animated } = params;
1635
- const offset = calculateOffsetWithOffsetPosition(params.offset, params);
1636
- state.scrollHistory.length = 0;
1637
- state.scrollingTo = params;
1638
- state.scrollPending = offset;
1639
- (_a2 = refScroller.current) == null ? void 0 : _a2.scrollTo({
1640
- x: horizontal ? offset : 0,
1641
- y: horizontal ? 0 : offset,
1642
- animated: !!animated
1643
- });
1644
- if (!animated) {
1645
- refState.current.scroll = offset;
1646
- setTimeout(finishScrollTo, 100);
1647
- }
1648
- };
1649
- const doMaintainScrollAtEnd = (animated) => {
1650
- const state = refState.current;
1651
- if ((state == null ? void 0 : state.isAtEnd) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
1652
- const paddingTop = peek$(ctx, "alignItemsPaddingTop");
1653
- if (paddingTop > 0) {
1654
- state.scroll = 0;
1655
- }
1656
- requestAnimationFrame(() => {
1657
- var _a2;
1658
- state.maintainingScrollAtEnd = true;
1659
- (_a2 = refScroller.current) == null ? void 0 : _a2.scrollToEnd({
1660
- animated
1661
- });
1662
- setTimeout(
1663
- () => {
1664
- state.maintainingScrollAtEnd = false;
1665
- },
1666
- 0
1667
- );
1668
- });
1669
- return true;
1670
- }
1671
- };
1672
- const checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
1673
- const distanceAbs = Math.abs(distance);
1674
- const isAtThreshold = atThreshold || distanceAbs < threshold;
1675
- if (!isReached && !isBlockedByTimer) {
1676
- if (isAtThreshold) {
1677
- onReached == null ? void 0 : onReached(distance);
1678
- blockTimer == null ? void 0 : blockTimer(true);
1679
- setTimeout(() => {
1680
- blockTimer == null ? void 0 : blockTimer(false);
1681
- }, 700);
1682
- return true;
1683
- }
1684
- } else {
1685
- if (distance >= 1.3 * threshold) {
1686
- return false;
1687
- }
1688
- }
1689
- return isReached;
1690
- };
1691
- const checkAtBottom = () => {
1692
- if (!refState.current) {
1693
- return;
1694
- }
1695
- const { queuedInitialLayout, scrollLength, scroll, maintainingScrollAtEnd } = refState.current;
1696
- const contentSize = getContentSize(ctx);
1697
- if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1698
- const distanceFromEnd = contentSize - scroll - scrollLength;
1699
- const isContentLess = contentSize < scrollLength;
1700
- refState.current.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1701
- refState.current.isEndReached = checkThreshold(
1702
- distanceFromEnd,
1703
- isContentLess,
1704
- onEndReachedThreshold * scrollLength,
1705
- refState.current.isEndReached,
1706
- refState.current.endReachedBlockedByTimer,
1707
- (distance) => {
1708
- var _a2, _b;
1709
- return (_b = (_a2 = callbacks.current).onEndReached) == null ? void 0 : _b.call(_a2, { distanceFromEnd: distance });
1710
- },
1711
- (block) => {
1712
- refState.current.endReachedBlockedByTimer = block;
1713
- }
1714
- );
1715
- }
1716
- };
1717
- const checkAtTop = () => {
1718
- if (!refState.current) {
1719
- return;
1720
- }
1721
- const { scrollLength, scroll } = refState.current;
1722
- const distanceFromTop = scroll;
1723
- refState.current.isAtStart = distanceFromTop <= 0;
1724
- refState.current.isStartReached = checkThreshold(
1725
- distanceFromTop,
1726
- false,
1727
- onStartReachedThreshold * scrollLength,
1728
- refState.current.isStartReached,
1729
- refState.current.startReachedBlockedByTimer,
1730
- (distance) => {
1731
- var _a2, _b;
1732
- return (_b = (_a2 = callbacks.current).onStartReached) == null ? void 0 : _b.call(_a2, { distanceFromStart: distance });
1733
- },
1734
- (block) => {
1735
- refState.current.startReachedBlockedByTimer = block;
1736
- }
1737
- );
2185
+ const state = refState.current;
2186
+ const isFirst = !state.props.renderItem;
2187
+ const didDataChange = state.props.data !== dataProp;
2188
+ state.props = {
2189
+ alignItemsAtEnd,
2190
+ data: dataProp,
2191
+ estimatedItemSize,
2192
+ maintainScrollAtEnd,
2193
+ maintainScrollAtEndThreshold,
2194
+ onEndReachedThreshold,
2195
+ onStartReachedThreshold,
2196
+ stylePaddingBottom: stylePaddingBottomState,
2197
+ horizontal: !!horizontal,
2198
+ maintainVisibleContentPosition,
2199
+ onItemSizeChanged,
2200
+ suggestEstimatedItemSize: !!suggestEstimatedItemSize,
2201
+ keyExtractor,
2202
+ onScroll: onScrollProp,
2203
+ getEstimatedItemSize,
2204
+ onStartReached,
2205
+ onEndReached,
2206
+ onLoad,
2207
+ renderItem: renderItem2,
2208
+ initialScroll,
2209
+ scrollBuffer,
2210
+ viewabilityConfigCallbackPairs: void 0,
2211
+ numColumns: numColumnsProp,
2212
+ initialContainerPoolRatio,
2213
+ stylePaddingTop: stylePaddingTopState
1738
2214
  };
2215
+ state.refScroller = refScroller;
1739
2216
  const checkResetContainers = (isFirst2) => {
1740
- const state = refState.current;
1741
- if (state) {
1742
- state.data = dataProp;
2217
+ const state2 = refState.current;
2218
+ if (state2) {
2219
+ state2.props.data = dataProp;
1743
2220
  if (!isFirst2) {
1744
- calculateItemsInView({ dataChanged: true, doMVCP: true });
1745
- const didMaintainScrollAtEnd = doMaintainScrollAtEnd(false);
1746
- if (!didMaintainScrollAtEnd && dataProp.length > state.data.length) {
1747
- state.isEndReached = false;
2221
+ calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
2222
+ const didMaintainScrollAtEnd = doMaintainScrollAtEnd(ctx, state2, false);
2223
+ if (!didMaintainScrollAtEnd && dataProp.length > state2.props.data.length) {
2224
+ state2.isEndReached = false;
1748
2225
  }
1749
2226
  if (!didMaintainScrollAtEnd) {
1750
- checkAtTop();
1751
- checkAtBottom();
1752
- }
1753
- }
1754
- }
1755
- };
1756
- const updateTotalSize = () => {
1757
- const { data, positions } = refState.current;
1758
- if (data.length === 0) {
1759
- addTotalSize(null, 0);
1760
- } else {
1761
- const lastId = getId(data.length - 1);
1762
- if (lastId !== void 0) {
1763
- const lastPosition = positions.get(lastId);
1764
- if (lastPosition !== void 0) {
1765
- const lastSize = getItemSize(lastId, data.length - 1, data[dataProp.length - 1]);
1766
- if (lastSize !== void 0) {
1767
- const totalSize = lastPosition + lastSize;
1768
- addTotalSize(null, totalSize);
1769
- }
2227
+ checkAtTop(state2);
2228
+ checkAtBottom(ctx, state2);
1770
2229
  }
1771
2230
  }
1772
2231
  }
1773
2232
  };
1774
- const findAvailableContainers = (numNeeded, startBuffered, endBuffered, pendingRemoval) => {
1775
- const state = refState.current;
1776
- const numContainers = peek$(ctx, "numContainers");
1777
- const result = [];
1778
- const availableContainers = [];
1779
- for (let u = 0; u < numContainers; u++) {
1780
- const key = peek$(ctx, `containerItemKey${u}`);
1781
- let isOk = key === void 0;
1782
- if (!isOk) {
1783
- const index = pendingRemoval.indexOf(u);
1784
- if (index !== -1) {
1785
- pendingRemoval.splice(index, 1);
1786
- isOk = true;
1787
- }
1788
- }
1789
- if (isOk) {
1790
- result.push(u);
1791
- if (result.length >= numNeeded) {
1792
- return result;
1793
- }
1794
- }
1795
- }
1796
- for (let u = 0; u < numContainers; u++) {
1797
- const key = peek$(ctx, `containerItemKey${u}`);
1798
- if (key === void 0) continue;
1799
- const index = state.indexByKey.get(key);
1800
- if (index < startBuffered) {
1801
- availableContainers.push({ index: u, distance: startBuffered - index });
1802
- } else if (index > endBuffered) {
1803
- availableContainers.push({ index: u, distance: index - endBuffered });
1804
- }
1805
- }
1806
- const remaining = numNeeded - result.length;
1807
- if (remaining > 0) {
1808
- if (availableContainers.length > 0) {
1809
- if (availableContainers.length > remaining) {
1810
- availableContainers.sort(comparatorByDistance);
1811
- availableContainers.length = remaining;
1812
- }
1813
- for (const container of availableContainers) {
1814
- result.push(container.index);
1815
- }
1816
- }
1817
- const stillNeeded = numNeeded - result.length;
1818
- if (stillNeeded > 0) {
1819
- for (let i = 0; i < stillNeeded; i++) {
1820
- result.push(numContainers + i);
1821
- }
1822
- if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
1823
- console.warn(
1824
- "[legend-list] No unused container available, 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 or increasing initialContainerPoolRatio.",
1825
- {
1826
- debugInfo: {
1827
- numContainers,
1828
- numNeeded,
1829
- stillNeeded,
1830
- numContainersPooled: peek$(ctx, "numContainersPooled")
1831
- }
1832
- }
1833
- );
1834
- }
1835
- }
1836
- }
1837
- return result.sort(comparatorDefault);
1838
- };
1839
- const isFirst = !refState.current.renderItem;
1840
- const memoizedLastItemKeys = React2.useMemo(() => {
2233
+ const memoizedLastItemKeys = React3.useMemo(() => {
1841
2234
  if (!dataProp.length) return [];
1842
2235
  return Array.from(
1843
2236
  { length: Math.min(numColumnsProp, dataProp.length) },
1844
- (_, i) => getId(dataProp.length - 1 - i)
2237
+ (_, i) => getId(state, dataProp.length - 1 - i)
1845
2238
  );
1846
2239
  }, [dataProp, numColumnsProp]);
1847
2240
  const initalizeStateVars = () => {
1848
2241
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
1849
2242
  set$(ctx, "numColumns", numColumnsProp);
1850
2243
  const prevPaddingTop = peek$(ctx, "stylePaddingTop");
1851
- setPaddingTop({ stylePaddingTop: stylePaddingTopState });
1852
- refState.current.stylePaddingBottom = stylePaddingBottomState;
2244
+ setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
2245
+ refState.current.props.stylePaddingBottom = stylePaddingBottomState;
1853
2246
  const paddingDiff = stylePaddingTopState - prevPaddingTop;
1854
2247
  if (paddingDiff && prevPaddingTop !== void 0 && reactNative.Platform.OS === "ios") {
1855
- requestAdjust(paddingDiff);
2248
+ calculateItemsInView(ctx, state, { doMVCP: true });
2249
+ requestAdjust(ctx, state, paddingDiff);
1856
2250
  }
1857
2251
  };
1858
2252
  if (isFirst) {
1859
2253
  initalizeStateVars();
1860
- updateAllPositions();
2254
+ updateAllPositions(ctx, state);
1861
2255
  }
1862
- const initialContentOffset = React2.useMemo(() => {
1863
- const initialContentOffset2 = initialScrollOffset || calculateOffsetForIndex(initialScrollIndex);
2256
+ const initialContentOffset = React3.useMemo(() => {
2257
+ const initialContentOffset2 = initialScrollOffset || calculateOffsetForIndex(ctx, state, initialScrollIndex);
1864
2258
  refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
1865
2259
  if (initialContentOffset2 > 0) {
1866
- scrollTo({ offset: initialContentOffset2, animated: false, index: initialScrollIndex });
2260
+ scrollTo(state, { offset: initialContentOffset2, animated: false, index: initialScrollIndex });
1867
2261
  }
1868
2262
  return initialContentOffset2;
1869
2263
  }, [renderNum]);
@@ -1878,22 +2272,22 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1878
2272
  refState.current.positions.clear();
1879
2273
  }
1880
2274
  }
1881
- React2.useLayoutEffect(() => {
2275
+ React3.useLayoutEffect(() => {
1882
2276
  var _a2, _b;
1883
2277
  if (IsNewArchitecture) {
1884
2278
  const measured = (_b = (_a2 = refScroller.current) == null ? void 0 : _a2.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a2);
1885
2279
  if (measured) {
1886
2280
  const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
1887
2281
  if (size) {
1888
- handleLayout(measured);
2282
+ handleLayout(ctx, state, measured, setCanRender);
1889
2283
  }
1890
2284
  }
1891
2285
  }
1892
2286
  if (!isFirst) {
1893
- calculateItemsInView({ doMVCP: true });
2287
+ calculateItemsInView(ctx, state, { doMVCP: true });
1894
2288
  }
1895
2289
  }, [dataProp]);
1896
- const onLayoutHeader = React2.useCallback((rect, fromLayoutEffect) => {
2290
+ const onLayoutHeader = React3.useCallback((rect, fromLayoutEffect) => {
1897
2291
  const size = rect[horizontal ? "width" : "height"];
1898
2292
  set$(ctx, "headerSize", size);
1899
2293
  if (initialScroll) {
@@ -1903,13 +2297,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1903
2297
  }
1904
2298
  } else {
1905
2299
  setTimeout(() => {
1906
- scrollToIndex({ ...initialScroll, animated: false });
2300
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1907
2301
  }, 17);
1908
2302
  }
1909
2303
  }
1910
2304
  }, []);
1911
- React2.useLayoutEffect(() => {
1912
- const didAllocateContainers = doInitialAllocateContainers();
2305
+ React3.useLayoutEffect(() => {
2306
+ const didAllocateContainers = doInitialAllocateContainersCallback();
1913
2307
  if (!didAllocateContainers) {
1914
2308
  checkResetContainers(
1915
2309
  /*isFirst*/
@@ -1917,297 +2311,51 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
1917
2311
  );
1918
2312
  }
1919
2313
  }, [dataProp, numColumnsProp]);
1920
- React2.useLayoutEffect(() => {
2314
+ React3.useLayoutEffect(() => {
1921
2315
  set$(ctx, "extraData", extraData);
1922
2316
  }, [extraData]);
1923
- refState.current.renderItem = renderItem2;
1924
- React2.useLayoutEffect(initalizeStateVars, [
2317
+ React3.useLayoutEffect(initalizeStateVars, [
1925
2318
  memoizedLastItemKeys.join(","),
1926
2319
  numColumnsProp,
1927
2320
  stylePaddingTopState,
1928
2321
  stylePaddingBottomState
1929
2322
  ]);
1930
- const getRenderedItem = React2.useCallback((key) => {
1931
- const state = refState.current;
1932
- if (!state) {
1933
- return null;
1934
- }
1935
- const { data, indexByKey } = state;
1936
- const index = indexByKey.get(key);
1937
- if (index === void 0) {
1938
- return null;
1939
- }
1940
- const renderItemProp = refState.current.renderItem;
1941
- let renderedItem = null;
1942
- if (renderItemProp) {
1943
- const itemProps = {
1944
- item: data[index],
1945
- index,
1946
- extraData: peek$(ctx, "extraData")
1947
- };
1948
- renderedItem = React2__namespace.createElement(renderItemProp, itemProps);
1949
- }
1950
- return { index, item: data[index], renderedItem };
1951
- }, []);
1952
- const doInitialAllocateContainers = () => {
1953
- const state = refState.current;
1954
- const { scrollLength, data } = state;
1955
- if (scrollLength > 0 && data.length > 0 && !peek$(ctx, "numContainers")) {
1956
- const averageItemSize = getEstimatedItemSize ? getEstimatedItemSize(0, data[0]) : estimatedItemSize;
1957
- const Extra = 1.5;
1958
- const numContainers = Math.ceil(
1959
- (scrollLength + scrollBuffer * 2) / averageItemSize * numColumnsProp * Extra
1960
- );
1961
- for (let i = 0; i < numContainers; i++) {
1962
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1963
- set$(ctx, `containerColumn${i}`, -1);
1964
- }
1965
- set$(ctx, "numContainers", numContainers);
1966
- set$(ctx, "numContainersPooled", numContainers * initialContainerPoolRatio);
1967
- if (!IsNewArchitecture) {
1968
- if (initialScroll) {
1969
- requestAnimationFrame(() => {
1970
- calculateItemsInView();
1971
- });
1972
- } else {
1973
- calculateItemsInView();
1974
- }
1975
- }
1976
- return true;
1977
- }
2323
+ const doInitialAllocateContainersCallback = () => {
2324
+ return doInitialAllocateContainers(ctx, state);
1978
2325
  };
1979
- React2.useEffect(() => {
1980
- const state = refState.current;
2326
+ React3.useEffect(() => {
1981
2327
  const viewability = setupViewability({
1982
2328
  viewabilityConfig,
1983
2329
  viewabilityConfigCallbackPairs,
1984
2330
  onViewableItemsChanged
1985
2331
  });
1986
2332
  state.viewabilityConfigCallbackPairs = viewability;
2333
+ state.props.viewabilityConfigCallbackPairs = viewability;
1987
2334
  state.enableScrollForNextCalculateItemsInView = !viewability;
1988
2335
  }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
1989
2336
  if (!IsNewArchitecture) {
1990
2337
  useInit(() => {
1991
- doInitialAllocateContainers();
2338
+ doInitialAllocateContainersCallback();
1992
2339
  });
1993
2340
  }
1994
- const updateOneItemSize = React2.useCallback((itemKey, sizeObj) => {
1995
- const state = refState.current;
1996
- const { sizes, indexByKey, sizesKnown, data, averageSizes } = state;
1997
- if (!data) return 0;
1998
- const index = indexByKey.get(itemKey);
1999
- const prevSize = getItemSize(itemKey, index, data);
2000
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2001
- sizesKnown.set(itemKey, size);
2002
- const itemType = "";
2003
- let averages = averageSizes[itemType];
2004
- if (!averages) {
2005
- averages = averageSizes[itemType] = { num: 0, avg: 0 };
2006
- }
2007
- averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2008
- averages.num++;
2009
- if (!prevSize || Math.abs(prevSize - size) > 0.1) {
2010
- sizes.set(itemKey, size);
2011
- return size - prevSize;
2012
- }
2013
- return 0;
2014
- }, []);
2015
- const updateItemSizes = React2.useCallback(
2016
- (itemUpdates) => {
2017
- var _a2;
2018
- const state = refState.current;
2019
- if (!state.data) return;
2020
- let needsRecalculate = false;
2021
- let shouldMaintainScrollAtEnd = false;
2022
- let minIndexSizeChanged;
2023
- let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2024
- for (const { itemKey, sizeObj } of itemUpdates) {
2025
- const index = state.indexByKey.get(itemKey);
2026
- const prevSizeKnown = state.sizesKnown.get(itemKey);
2027
- const diff = updateOneItemSize(itemKey, sizeObj);
2028
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2029
- if (diff !== 0) {
2030
- minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
2031
- if (((_a2 = state.scrollingTo) == null ? void 0 : _a2.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index) {
2032
- requestAdjust(diff * state.scrollingTo.viewPosition);
2033
- }
2034
- const { startBuffered, endBuffered } = state;
2035
- needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2036
- if (!needsRecalculate) {
2037
- const numContainers = ctx.values.get("numContainers");
2038
- for (let i = 0; i < numContainers; i++) {
2039
- if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
2040
- needsRecalculate = true;
2041
- break;
2042
- }
2043
- }
2044
- }
2045
- if (state.needsOtherAxisSize) {
2046
- const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
2047
- maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
2048
- }
2049
- if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
2050
- shouldMaintainScrollAtEnd = true;
2051
- }
2052
- onItemSizeChanged == null ? void 0 : onItemSizeChanged({
2053
- size,
2054
- previous: size - diff,
2055
- index,
2056
- itemKey,
2057
- itemData: state.data[index]
2058
- });
2059
- }
2060
- }
2061
- if (minIndexSizeChanged !== void 0) {
2062
- state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
2063
- }
2064
- if (__DEV__ && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
2065
- if (state.timeoutSizeMessage) clearTimeout(state.timeoutSizeMessage);
2066
- state.timeoutSizeMessage = setTimeout(() => {
2067
- var _a3;
2068
- state.timeoutSizeMessage = void 0;
2069
- const num = state.sizesKnown.size;
2070
- const avg = (_a3 = state.averageSizes[""]) == null ? void 0 : _a3.avg;
2071
- console.warn(
2072
- `[legend-list] Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`
2073
- );
2074
- }, 1e3);
2075
- }
2076
- const cur = peek$(ctx, "otherAxisSize");
2077
- if (!cur || maxOtherAxisSize > cur) {
2078
- set$(ctx, "otherAxisSize", maxOtherAxisSize);
2079
- }
2080
- const containersDidLayout = peek$(ctx, "containersDidLayout");
2081
- if (containersDidLayout || checkAllSizesKnown()) {
2082
- if (needsRecalculate) {
2083
- state.scrollForNextCalculateItemsInView = void 0;
2084
- calculateItemsInView({ doMVCP: true });
2085
- }
2086
- if (shouldMaintainScrollAtEnd) {
2087
- doMaintainScrollAtEnd(false);
2088
- }
2089
- }
2090
- },
2091
- []
2092
- );
2093
- const updateItemSize = React2.useCallback((itemKey, sizeObj) => {
2094
- var _a2, _b;
2095
- if (IsNewArchitecture) {
2096
- const { sizesKnown } = refState.current;
2097
- const numContainers = ctx.values.get("numContainers");
2098
- const changes = [];
2099
- for (let i = 0; i < numContainers; i++) {
2100
- const containerItemKey = peek$(ctx, `containerItemKey${i}`);
2101
- if (itemKey === containerItemKey) {
2102
- changes.push({ itemKey, sizeObj });
2103
- } else if (!sizesKnown.has(containerItemKey) && containerItemKey !== void 0) {
2104
- const containerRef = ctx.viewRefs.get(i);
2105
- if (containerRef) {
2106
- const measured = (_b = (_a2 = containerRef.current) == null ? void 0 : _a2.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a2);
2107
- if (measured) {
2108
- changes.push({ itemKey: containerItemKey, sizeObj: measured });
2109
- }
2110
- }
2111
- }
2112
- }
2113
- if (changes.length > 0) {
2114
- updateItemSizes(changes);
2115
- }
2116
- } else {
2117
- updateItemSizes([{ itemKey, sizeObj }]);
2118
- }
2119
- }, []);
2120
- const handleLayout = React2.useCallback((size) => {
2121
- const scrollLength = size[horizontal ? "width" : "height"];
2122
- const otherAxisSize = size[horizontal ? "height" : "width"];
2123
- const state = refState.current;
2124
- const didChange = scrollLength !== state.scrollLength;
2125
- const prevOtherAxisSize = state.otherAxisSize;
2126
- state.scrollLength = scrollLength;
2127
- state.otherAxisSize = otherAxisSize;
2128
- state.lastBatchingAction = Date.now();
2129
- state.scrollForNextCalculateItemsInView = void 0;
2130
- doInitialAllocateContainers();
2131
- if (didChange) {
2132
- calculateItemsInView({ doMVCP: true });
2133
- }
2134
- if (didChange || otherAxisSize !== prevOtherAxisSize) {
2135
- set$(ctx, "scrollSize", { width: size.width, height: size.height });
2136
- }
2137
- doMaintainScrollAtEnd(false);
2138
- updateAlignItemsPaddingTop();
2139
- checkAtBottom();
2140
- checkAtTop();
2141
- if (refState.current) {
2142
- refState.current.needsOtherAxisSize = otherAxisSize - (stylePaddingTopState || 0) < 10;
2143
- }
2144
- if (__DEV__ && scrollLength === 0) {
2145
- warnDevOnce(
2146
- "height0",
2147
- `List ${horizontal ? "width" : "height"} is 0. You may need to set a style or \`flex: \` for the list, because children are absolutely positioned.`
2148
- );
2149
- }
2150
- calculateItemsInView({ doMVCP: true });
2151
- setCanRender(true);
2152
- }, []);
2153
- const onLayout = React2.useCallback((event) => {
2341
+ const onLayout = React3.useCallback((event) => {
2154
2342
  const layout = event.nativeEvent.layout;
2155
- handleLayout(layout);
2343
+ handleLayout(ctx, state, layout, setCanRender);
2156
2344
  if (onLayoutProp) {
2157
2345
  onLayoutProp(event);
2158
2346
  }
2159
2347
  }, []);
2160
- const handleScroll = React2.useCallback(
2161
- (event) => {
2162
- var _a2, _b, _c, _d;
2163
- if (((_b = (_a2 = event.nativeEvent) == null ? void 0 : _a2.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
2164
- return;
2165
- }
2166
- const state = refState.current;
2167
- const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
2168
- const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
2169
- if (ignoreScrollFromMVCP && !state.scrollingTo) {
2170
- const { lt, gt } = ignoreScrollFromMVCP;
2171
- if (lt && newScroll < lt || gt && newScroll > gt) {
2172
- return;
2173
- }
2174
- }
2175
- state.scrollPending = newScroll;
2176
- updateScroll(newScroll);
2177
- (_d = state.onScroll) == null ? void 0 : _d.call(state, event);
2178
- },
2179
- []
2180
- );
2181
- const updateScroll = React2.useCallback((newScroll) => {
2182
- const state = refState.current;
2183
- const scrollingTo = state.scrollingTo;
2184
- state.hasScrolled = true;
2185
- state.lastBatchingAction = Date.now();
2186
- const currentTime = performance.now();
2187
- if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
2188
- state.scrollHistory.push({ scroll: newScroll, time: currentTime });
2189
- }
2190
- if (state.scrollHistory.length > 5) {
2191
- state.scrollHistory.shift();
2192
- }
2193
- state.scrollPrev = state.scroll;
2194
- state.scrollPrevTime = state.scrollTime;
2195
- state.scroll = newScroll;
2196
- state.scrollTime = currentTime;
2197
- calculateItemsInView();
2198
- checkAtBottom();
2199
- checkAtTop();
2200
- }, []);
2201
- React2.useImperativeHandle(
2348
+ React3.useImperativeHandle(
2202
2349
  forwardedRef,
2203
2350
  () => {
2204
2351
  const scrollIndexIntoView = (options) => {
2205
- if (refState.current) {
2352
+ const state2 = refState.current;
2353
+ if (state2) {
2206
2354
  const { index, ...rest2 } = options;
2207
- const { startNoBuffer, endNoBuffer } = refState.current;
2355
+ const { startNoBuffer, endNoBuffer } = state2;
2208
2356
  if (index < startNoBuffer || index > endNoBuffer) {
2209
2357
  const viewPosition = index < startNoBuffer ? 0 : 1;
2210
- scrollToIndex({
2358
+ scrollToIndex(ctx, state2, {
2211
2359
  ...rest2,
2212
2360
  viewPosition,
2213
2361
  index
@@ -2221,45 +2369,46 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2221
2369
  getScrollableNode: () => refScroller.current.getScrollableNode(),
2222
2370
  getScrollResponder: () => refScroller.current.getScrollResponder(),
2223
2371
  getState: () => {
2224
- const state = refState.current;
2225
- return state ? {
2226
- contentLength: state.totalSize,
2227
- end: state.endNoBuffer,
2228
- endBuffered: state.endBuffered,
2229
- isAtEnd: state.isAtEnd,
2230
- isAtStart: state.isAtStart,
2231
- scroll: state.scroll,
2232
- scrollLength: state.scrollLength,
2233
- start: state.startNoBuffer,
2234
- startBuffered: state.startBuffered,
2235
- sizes: state.sizesKnown,
2236
- sizeAtIndex: (index) => state.sizesKnown.get(getId(index))
2372
+ const state2 = refState.current;
2373
+ return state2 ? {
2374
+ contentLength: state2.totalSize,
2375
+ end: state2.endNoBuffer,
2376
+ endBuffered: state2.endBuffered,
2377
+ isAtEnd: state2.isAtEnd,
2378
+ isAtStart: state2.isAtStart,
2379
+ scroll: state2.scroll,
2380
+ scrollLength: state2.scrollLength,
2381
+ start: state2.startNoBuffer,
2382
+ startBuffered: state2.startBuffered,
2383
+ sizes: state2.sizesKnown,
2384
+ sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index))
2237
2385
  } : {};
2238
2386
  },
2239
2387
  scrollIndexIntoView,
2240
2388
  scrollItemIntoView: ({ item, ...props2 }) => {
2241
- const { data } = refState.current;
2389
+ const data = refState.current.props.data;
2242
2390
  const index = data.indexOf(item);
2243
2391
  if (index !== -1) {
2244
2392
  scrollIndexIntoView({ index, ...props2 });
2245
2393
  }
2246
2394
  },
2247
- scrollToIndex,
2395
+ scrollToIndex: (params) => scrollToIndex(ctx, state, params),
2248
2396
  scrollToItem: ({ item, ...props2 }) => {
2249
- const { data } = refState.current;
2397
+ const data = refState.current.props.data;
2250
2398
  const index = data.indexOf(item);
2251
2399
  if (index !== -1) {
2252
- scrollToIndex({ index, ...props2 });
2400
+ scrollToIndex(ctx, state, { index, ...props2 });
2253
2401
  }
2254
2402
  },
2255
- scrollToOffset: (params) => scrollTo(params),
2403
+ scrollToOffset: (params) => scrollTo(state, params),
2256
2404
  scrollToEnd: (options) => {
2257
- const { data, stylePaddingBottom } = refState.current;
2405
+ const data = refState.current.props.data;
2406
+ const stylePaddingBottom = refState.current.props.stylePaddingBottom;
2258
2407
  const index = data.length - 1;
2259
2408
  if (index !== -1) {
2260
2409
  const paddingBottom = stylePaddingBottom || 0;
2261
2410
  const footerSize = peek$(ctx, "footerSize") || 0;
2262
- scrollToIndex({
2411
+ scrollToIndex(ctx, state, {
2263
2412
  index,
2264
2413
  viewPosition: 1,
2265
2414
  viewOffset: -paddingBottom - footerSize,
@@ -2276,13 +2425,21 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2276
2425
  []
2277
2426
  );
2278
2427
  if (reactNative.Platform.OS === "web") {
2279
- React2.useEffect(() => {
2428
+ React3.useEffect(() => {
2280
2429
  if (initialContentOffset) {
2281
- scrollTo({ offset: initialContentOffset, animated: false });
2430
+ scrollTo(state, { offset: initialContentOffset, animated: false });
2282
2431
  }
2283
2432
  }, []);
2284
2433
  }
2285
- return /* @__PURE__ */ React2__namespace.createElement(React2__namespace.Fragment, null, /* @__PURE__ */ React2__namespace.createElement(
2434
+ const fns = React3.useMemo(
2435
+ () => ({
2436
+ updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, state, itemKey, sizeObj),
2437
+ getRenderedItem: (key) => getRenderedItem(ctx, state, key),
2438
+ onScroll: (event) => onScroll(ctx, state, event)
2439
+ }),
2440
+ []
2441
+ );
2442
+ return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement(
2286
2443
  ListComponent,
2287
2444
  {
2288
2445
  ...rest,
@@ -2290,12 +2447,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2290
2447
  horizontal,
2291
2448
  refScrollView: combinedRef,
2292
2449
  initialContentOffset,
2293
- getRenderedItem,
2294
- updateItemSize,
2295
- handleScroll,
2450
+ getRenderedItem: fns.getRenderedItem,
2451
+ updateItemSize: fns.updateItemSize,
2452
+ onScroll: fns.onScroll,
2296
2453
  onMomentumScrollEnd: (event) => {
2297
2454
  requestAnimationFrame(() => {
2298
- finishScrollTo();
2455
+ finishScrollTo(refState.current);
2299
2456
  });
2300
2457
  if (onMomentumScrollEnd) {
2301
2458
  onMomentumScrollEnd(event);
@@ -2309,9 +2466,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2309
2466
  maintainVisibleContentPosition,
2310
2467
  scrollEventThrottle: reactNative.Platform.OS === "web" ? 16 : void 0,
2311
2468
  waitForInitialLayout,
2312
- refreshControl: refreshControl ? stylePaddingTopState > 0 ? React2__namespace.cloneElement(refreshControl, {
2469
+ refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
2313
2470
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
2314
- }) : refreshControl : onRefresh && /* @__PURE__ */ React2__namespace.createElement(
2471
+ }) : refreshControl : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
2315
2472
  reactNative.RefreshControl,
2316
2473
  {
2317
2474
  refreshing: !!refreshing,
@@ -2324,17 +2481,17 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2324
2481
  scrollAdjustHandler: (_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler,
2325
2482
  onLayoutHeader
2326
2483
  }
2327
- ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React2__namespace.createElement(DebugView, { state: refState.current }));
2484
+ ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3__namespace.createElement(DebugView, { state: refState.current }));
2328
2485
  });
2329
- var typedForwardRef2 = React2.forwardRef;
2486
+ var typedForwardRef2 = React3.forwardRef;
2330
2487
  var renderItem = ({ item }) => item;
2331
2488
  var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedRef) {
2332
2489
  const { LegendList: LegendListProp, children, ...rest } = props;
2333
2490
  const LegendListComponent = LegendListProp != null ? LegendListProp : LegendList;
2334
- const data = (isArray(children) ? children : React2__namespace.Children.toArray(children)).flat(1);
2491
+ const data = (isArray(children) ? children : React3__namespace.Children.toArray(children)).flat(1);
2335
2492
  return (
2336
2493
  // @ts-expect-error TODO: Fix this type
2337
- /* @__PURE__ */ React2__namespace.createElement(LegendListComponent, { ...rest, data, renderItem, ref: forwardedRef })
2494
+ /* @__PURE__ */ React3__namespace.createElement(LegendListComponent, { ...rest, data, renderItem, ref: forwardedRef })
2338
2495
  );
2339
2496
  });
2340
2497