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