@legendapp/list 2.0.0-next.9 → 2.1.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.
package/index.mjs CHANGED
@@ -1,17 +1,32 @@
1
- import * as React3 from 'react';
2
- import React3__default, { useReducer, useEffect, createContext, useRef, useState, useMemo, useLayoutEffect, useCallback, useImperativeHandle, useContext, forwardRef, memo } from 'react';
3
- import { View, Text, Platform, Animated, ScrollView, StyleSheet, Dimensions, RefreshControl, unstable_batchedUpdates } from 'react-native';
1
+ import * as React4 from 'react';
2
+ import React4__default, { forwardRef, useReducer, useEffect, createContext, useRef, useState, useMemo, useImperativeHandle, useCallback, useLayoutEffect, memo, useContext } from 'react';
4
3
  import { useSyncExternalStore } from 'use-sync-external-store/shim';
4
+ import { unstable_batchedUpdates } from 'react-dom';
5
5
 
6
- // src/components/LazyLegendList.tsx
7
- var ContextState = React3.createContext(null);
6
+ // src/components/LegendList.tsx
7
+ var AnimatedView = forwardRef(function AnimatedView2(props, ref) {
8
+ return /* @__PURE__ */ React4.createElement("div", { ref, ...props });
9
+ });
10
+ var View = forwardRef(function View2(props, ref) {
11
+ return /* @__PURE__ */ React4.createElement("div", { ref, ...props });
12
+ });
13
+ var Text = View;
14
+
15
+ // src/platform/Animated.tsx
16
+ var createAnimatedValue = (value) => value;
17
+
18
+ // src/state/state.tsx
19
+ var ContextState = React4.createContext(null);
8
20
  function StateProvider({ children }) {
9
- const [value] = React3.useState(() => ({
21
+ const [value] = React4.useState(() => ({
22
+ animatedScrollY: createAnimatedValue(0),
10
23
  columnWrapperStyle: void 0,
24
+ internalState: void 0,
11
25
  listeners: /* @__PURE__ */ new Map(),
12
26
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
13
27
  mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
14
28
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
29
+ mapViewabilityConfigStates: /* @__PURE__ */ new Map(),
15
30
  mapViewabilityValues: /* @__PURE__ */ new Map(),
16
31
  values: /* @__PURE__ */ new Map([
17
32
  ["alignItemsPaddingTop", 0],
@@ -22,10 +37,10 @@ function StateProvider({ children }) {
22
37
  ]),
23
38
  viewRefs: /* @__PURE__ */ new Map()
24
39
  }));
25
- return /* @__PURE__ */ React3.createElement(ContextState.Provider, { value }, children);
40
+ return /* @__PURE__ */ React4.createElement(ContextState.Provider, { value }, children);
26
41
  }
27
42
  function useStateContext() {
28
- return React3.useContext(ContextState);
43
+ return React4.useContext(ContextState);
29
44
  }
30
45
  function createSelectorFunctionsArr(ctx, signalNames) {
31
46
  let lastValues = [];
@@ -95,23 +110,23 @@ function getContentSize(ctx) {
95
110
  return headerSize + footerSize + totalSize + stylePaddingTop;
96
111
  }
97
112
  function useArr$(signalNames) {
98
- const ctx = React3.useContext(ContextState);
99
- const { subscribe, get } = React3.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
113
+ const ctx = React4.useContext(ContextState);
114
+ const { subscribe, get } = React4.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
100
115
  const value = useSyncExternalStore(subscribe, get);
101
116
  return value;
102
117
  }
103
118
  function useSelector$(signalName, selector) {
104
- const ctx = React3.useContext(ContextState);
105
- const { subscribe, get } = React3.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
119
+ const ctx = React4.useContext(ContextState);
120
+ const { subscribe, get } = React4.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
106
121
  const value = useSyncExternalStore(subscribe, () => selector(get()[0]));
107
122
  return value;
108
123
  }
109
124
 
110
125
  // src/components/DebugView.tsx
111
126
  var DebugRow = ({ children }) => {
112
- return /* @__PURE__ */ React3.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
127
+ return /* @__PURE__ */ React4.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
113
128
  };
114
- var DebugView = React3.memo(function DebugView2({ state }) {
129
+ var DebugView = React4.memo(function DebugView2({ state }) {
115
130
  const ctx = useStateContext();
116
131
  const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
117
132
  "totalSize",
@@ -126,7 +141,7 @@ var DebugView = React3.memo(function DebugView2({ state }) {
126
141
  useInterval(() => {
127
142
  forceUpdate();
128
143
  }, 100);
129
- return /* @__PURE__ */ React3.createElement(
144
+ return /* @__PURE__ */ React4.createElement(
130
145
  View,
131
146
  {
132
147
  pointerEvents: "none",
@@ -142,14 +157,12 @@ var DebugView = React3.memo(function DebugView2({ state }) {
142
157
  top: 0
143
158
  }
144
159
  },
145
- /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React3.createElement(Text, null, totalSize.toFixed(2))),
146
- /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React3.createElement(Text, null, contentSize.toFixed(2))),
147
- /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "At end:"), /* @__PURE__ */ React3.createElement(Text, null, String(state.isAtEnd))),
148
- /* @__PURE__ */ React3.createElement(Text, null),
149
- /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React3.createElement(Text, null, scrollAdjust.toFixed(2))),
150
- /* @__PURE__ */ React3.createElement(Text, null),
151
- /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React3.createElement(Text, null, rawScroll.toFixed(2))),
152
- /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React3.createElement(Text, null, scroll.toFixed(2)))
160
+ /* @__PURE__ */ React4.createElement(DebugRow, null, /* @__PURE__ */ React4.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React4.createElement(Text, null, totalSize.toFixed(2))),
161
+ /* @__PURE__ */ React4.createElement(DebugRow, null, /* @__PURE__ */ React4.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React4.createElement(Text, null, contentSize.toFixed(2))),
162
+ /* @__PURE__ */ React4.createElement(DebugRow, null, /* @__PURE__ */ React4.createElement(Text, null, "At end:"), /* @__PURE__ */ React4.createElement(Text, null, String(state.isAtEnd))),
163
+ /* @__PURE__ */ React4.createElement(DebugRow, null, /* @__PURE__ */ React4.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React4.createElement(Text, null, scrollAdjust.toFixed(2))),
164
+ /* @__PURE__ */ React4.createElement(DebugRow, null, /* @__PURE__ */ React4.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React4.createElement(Text, null, rawScroll.toFixed(2))),
165
+ /* @__PURE__ */ React4.createElement(DebugRow, null, /* @__PURE__ */ React4.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React4.createElement(Text, null, scroll.toFixed(2)))
153
166
  );
154
167
  });
155
168
  function useInterval(callback, delay) {
@@ -158,24 +171,141 @@ function useInterval(callback, delay) {
158
171
  return () => clearInterval(interval);
159
172
  }, [delay]);
160
173
  }
161
- var LeanViewComponent = React3.forwardRef((props, ref) => {
162
- return React3.createElement("RCTView", { ...props, ref });
163
- });
164
- LeanViewComponent.displayName = "RCTView";
165
- var LeanView = Platform.OS === "android" || Platform.OS === "ios" ? LeanViewComponent : View;
174
+ var globalResizeObserver = null;
175
+ function getGlobalResizeObserver() {
176
+ if (!globalResizeObserver) {
177
+ globalResizeObserver = new ResizeObserver((entries) => {
178
+ for (const entry of entries) {
179
+ const callbacks = callbackMap.get(entry.target);
180
+ if (callbacks) {
181
+ for (const callback of callbacks) {
182
+ callback(entry);
183
+ }
184
+ }
185
+ }
186
+ });
187
+ }
188
+ return globalResizeObserver;
189
+ }
190
+ var callbackMap = /* @__PURE__ */ new WeakMap();
191
+ function useResizeObserver(element, callback) {
192
+ useEffect(() => {
193
+ if (!element) return;
194
+ const observer = getGlobalResizeObserver();
195
+ let callbacks = callbackMap.get(element);
196
+ if (!callbacks) {
197
+ callbacks = /* @__PURE__ */ new Set();
198
+ callbackMap.set(element, callbacks);
199
+ observer.observe(element);
200
+ }
201
+ callbacks.add(callback);
202
+ return () => {
203
+ const callbacks2 = callbackMap.get(element);
204
+ if (callbacks2) {
205
+ callbacks2.delete(callback);
206
+ if (callbacks2.size === 0) {
207
+ callbackMap.delete(element);
208
+ observer.unobserve(element);
209
+ }
210
+ }
211
+ };
212
+ }, [element, callback]);
213
+ }
166
214
 
167
- // src/components/Separator.tsx
168
- function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
169
- const [lastItemKeys] = useArr$(["lastItemKeys"]);
170
- const isALastItem = lastItemKeys.includes(itemKey);
171
- return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
215
+ // src/hooks/useSyncLayout.tsx
216
+ function useSyncLayout({
217
+ ref,
218
+ onLayoutChange
219
+ }) {
220
+ var _a, _b;
221
+ useResizeObserver(
222
+ ((_b = (_a = ref.current) == null ? void 0 : _a.getScrollableNode) == null ? void 0 : _b.call(_a)) || ref.current,
223
+ useCallback(
224
+ (entry) => {
225
+ onLayoutChange(entry.contentRect, false);
226
+ },
227
+ [onLayoutChange]
228
+ )
229
+ );
230
+ useLayoutEffect(() => {
231
+ if (ref.current) {
232
+ const rect = ref.current.getBoundingClientRect();
233
+ onLayoutChange(
234
+ {
235
+ height: rect.height,
236
+ width: rect.width,
237
+ x: rect.left,
238
+ y: rect.top
239
+ },
240
+ true
241
+ );
242
+ }
243
+ }, []);
244
+ return {};
172
245
  }
173
246
 
247
+ // src/components/LayoutView.tsx
248
+ var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
249
+ const ref = refView != null ? refView : useRef();
250
+ useSyncLayout({ onLayoutChange, ref });
251
+ return /* @__PURE__ */ React4.createElement("div", { ...rest, ref }, children);
252
+ };
253
+
174
254
  // src/constants.ts
175
255
  var POSITION_OUT_OF_VIEW = -1e7;
176
256
  var ENABLE_DEVMODE = __DEV__ && false;
177
257
  var ENABLE_DEBUG_VIEW = __DEV__ && false;
178
- var IsNewArchitecture = global.nativeFabricUIManager != null;
258
+ var typedForwardRef = forwardRef;
259
+ var typedMemo = memo;
260
+
261
+ // src/components/PositionView.tsx
262
+ var PositionViewState = typedMemo(function PositionView({
263
+ id,
264
+ horizontal,
265
+ style,
266
+ refView,
267
+ ...rest
268
+ }) {
269
+ const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
270
+ const base = Array.isArray(style) ? Object.assign({}, ...style) : style;
271
+ const combinedStyle = horizontal ? { ...base, left: position } : { ...base, top: position };
272
+ return /* @__PURE__ */ React4.createElement(LayoutView, { refView, style: combinedStyle, ...rest });
273
+ });
274
+ var PositionViewSticky = typedMemo(function PositionViewSticky2({
275
+ id,
276
+ horizontal,
277
+ style,
278
+ refView,
279
+ index,
280
+ ...rest
281
+ }) {
282
+ const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
283
+ const viewStyle = React4.useMemo(() => {
284
+ const base = Array.isArray(style) ? Object.assign({}, ...style) : style;
285
+ const axisStyle = horizontal ? { transform: `translateX(${position}px)` } : { top: position };
286
+ return {
287
+ ...base,
288
+ zIndex: index + 1e3,
289
+ ...axisStyle
290
+ };
291
+ }, [style, position, horizontal, index]);
292
+ return /* @__PURE__ */ React4.createElement(LayoutView, { refView, style: viewStyle, ...rest });
293
+ });
294
+ var PositionView2 = PositionViewState;
295
+ function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
296
+ const [lastItemKeys] = useArr$(["lastItemKeys"]);
297
+ const isALastItem = lastItemKeys.includes(itemKey);
298
+ return isALastItem ? null : /* @__PURE__ */ React4.createElement(ItemSeparatorComponent, { leadingItem });
299
+ }
300
+
301
+ // src/constants-platform.ts
302
+ var IsNewArchitecture = true;
303
+
304
+ // src/platform/Platform.ts
305
+ var Platform = {
306
+ // Widen the type to avoid unreachable-branch lints in cross-platform code that compares against other OSes
307
+ OS: "web"
308
+ };
179
309
  var symbolFirst = Symbol();
180
310
  function useInit(cb) {
181
311
  const refValue = useRef(symbolFirst);
@@ -312,8 +442,12 @@ function useListScrollSize() {
312
442
  const [scrollSize] = useArr$(["scrollSize"]);
313
443
  return scrollSize;
314
444
  }
315
- var typedForwardRef = forwardRef;
316
- var typedMemo = memo;
445
+ function useSyncLayout2() {
446
+ {
447
+ const { triggerLayout: syncLayout } = useContext(ContextContainer);
448
+ return syncLayout;
449
+ }
450
+ }
317
451
 
318
452
  // src/components/Container.tsx
319
453
  var Container = typedMemo(function Container2({
@@ -325,51 +459,56 @@ var Container = typedMemo(function Container2({
325
459
  ItemSeparatorComponent
326
460
  }) {
327
461
  const ctx = useStateContext();
328
- const columnWrapperStyle = ctx.columnWrapperStyle;
329
- const [column = 0, data, itemKey, position = POSITION_OUT_OF_VIEW, numColumns, extraData] = useArr$([
462
+ const { columnWrapperStyle } = ctx;
463
+ const [column = 0, data, itemKey, numColumns, extraData, isSticky] = useArr$([
330
464
  `containerColumn${id}`,
331
465
  `containerItemData${id}`,
332
466
  `containerItemKey${id}`,
333
- `containerPosition${id}`,
334
467
  "numColumns",
335
- "extraData"
468
+ "extraData",
469
+ `containerSticky${id}`
336
470
  ]);
337
471
  const refLastSize = useRef();
338
472
  const ref = useRef(null);
339
- const [layoutRenderCount, forceLayoutRender] = useState(0);
473
+ const [_, forceLayoutRender] = useState(0);
340
474
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
341
475
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
342
- let didLayout = false;
343
- let paddingStyles;
344
- if (columnWrapperStyle) {
345
- const { columnGap, rowGap, gap } = columnWrapperStyle;
346
- if (horizontal) {
347
- paddingStyles = {
348
- paddingRight: columnGap || gap || void 0,
349
- paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
350
- };
351
- } else {
352
- paddingStyles = {
353
- paddingBottom: rowGap || gap || void 0,
354
- paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
355
- };
476
+ const style = useMemo(() => {
477
+ let paddingStyles;
478
+ if (columnWrapperStyle) {
479
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
480
+ if (horizontal) {
481
+ const py = numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0;
482
+ paddingStyles = {
483
+ paddingBottom: py,
484
+ paddingRight: columnGap || gap || void 0,
485
+ paddingTop: py
486
+ };
487
+ } else {
488
+ const px = numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0;
489
+ paddingStyles = {
490
+ paddingBottom: rowGap || gap || void 0,
491
+ paddingLeft: px,
492
+ paddingRight: px
493
+ };
494
+ }
356
495
  }
357
- }
358
- const style = horizontal ? {
359
- flexDirection: ItemSeparatorComponent ? "row" : void 0,
360
- height: otherAxisSize,
361
- left: position,
362
- position: "absolute",
363
- top: otherAxisPos,
364
- ...paddingStyles || {}
365
- } : {
366
- left: otherAxisPos,
367
- position: "absolute",
368
- right: numColumns > 1 ? null : 0,
369
- top: position,
370
- width: otherAxisSize,
371
- ...paddingStyles || {}
372
- };
496
+ return horizontal ? {
497
+ flexDirection: ItemSeparatorComponent ? "row" : void 0,
498
+ height: otherAxisSize,
499
+ left: 0,
500
+ position: "absolute",
501
+ top: otherAxisPos,
502
+ ...paddingStyles || {}
503
+ } : {
504
+ left: otherAxisPos,
505
+ position: "absolute",
506
+ right: numColumns > 1 ? void 0 : 0,
507
+ top: 0,
508
+ width: otherAxisSize,
509
+ ...paddingStyles || {}
510
+ };
511
+ }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
373
512
  const renderedItemInfo = useMemo(
374
513
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
375
514
  [itemKey, data, extraData]
@@ -387,104 +526,183 @@ var Container = typedMemo(function Container2({
387
526
  value: data
388
527
  };
389
528
  }, [id, itemKey, index, data]);
390
- const onLayout = (event) => {
391
- var _a, _b;
529
+ const onLayoutChange = (rectangle) => {
392
530
  if (!isNullOrUndefined(itemKey)) {
393
- didLayout = true;
394
- let layout = event.nativeEvent.layout;
395
- const size = layout[horizontal ? "width" : "height"];
531
+ let layout = rectangle;
532
+ layout[horizontal ? "width" : "height"];
396
533
  const doUpdate = () => {
397
534
  refLastSize.current = { height: layout.height, width: layout.width };
398
535
  updateItemSize2(itemKey, layout);
399
536
  };
400
- if (IsNewArchitecture || size > 0) {
537
+ {
401
538
  doUpdate();
402
- } else {
403
- (_b = (_a = ref.current) == null ? void 0 : _a.measure) == null ? void 0 : _b.call(_a, (_x, _y, width, height) => {
404
- layout = { height, width };
405
- doUpdate();
406
- });
407
539
  }
408
540
  }
409
541
  };
410
- if (IsNewArchitecture) {
411
- useLayoutEffect(() => {
412
- var _a, _b;
413
- if (!isNullOrUndefined(itemKey)) {
414
- const measured = (_b = (_a = ref.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
415
- if (measured) {
416
- const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
417
- if (size) {
418
- updateItemSize2(itemKey, measured);
419
- }
542
+ const PositionComponent = isSticky ? PositionViewSticky : PositionView2;
543
+ return /* @__PURE__ */ React4.createElement(ContextContainer.Provider, { value: contextValue }, /* @__PURE__ */ React4.createElement(
544
+ PositionComponent,
545
+ {
546
+ horizontal,
547
+ id,
548
+ index,
549
+ key: recycleItems ? void 0 : itemKey,
550
+ onLayoutChange,
551
+ refView: ref,
552
+ style
553
+ },
554
+ renderedItem,
555
+ renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React4.createElement(
556
+ Separator,
557
+ {
558
+ ItemSeparatorComponent,
559
+ itemKey,
560
+ leadingItem: renderedItemInfo.item
561
+ }
562
+ )
563
+ ));
564
+ });
565
+
566
+ // src/utils/reordering.ts
567
+ var mapFn = (element) => {
568
+ const indexStr = element.getAttribute("index");
569
+ return [element, indexStr === null ? null : parseInt(indexStr)];
570
+ };
571
+ function sortDOMElementsPatience(container) {
572
+ const elements = Array.from(container.children);
573
+ if (elements.length <= 1) return elements;
574
+ const items = elements.map(mapFn);
575
+ items.sort((a, b) => {
576
+ const aKey = a[1];
577
+ const bKey = b[1];
578
+ if (aKey === null) {
579
+ return 1;
580
+ }
581
+ if (bKey === null) {
582
+ return -1;
583
+ }
584
+ return aKey - bKey;
585
+ });
586
+ const targetPositions = /* @__PURE__ */ new Map();
587
+ items.forEach((item, index) => {
588
+ targetPositions.set(item[0], index);
589
+ });
590
+ const currentPositions = elements.map((el) => targetPositions.get(el));
591
+ const lis = findLIS(currentPositions);
592
+ const stableIndices = new Set(lis);
593
+ for (let targetPos = 0; targetPos < items.length; targetPos++) {
594
+ const element = items[targetPos][0];
595
+ const currentPos = elements.indexOf(element);
596
+ if (!stableIndices.has(currentPos)) {
597
+ let nextStableElement = null;
598
+ for (let i = targetPos + 1; i < items.length; i++) {
599
+ const nextEl = items[i][0];
600
+ const nextCurrentPos = elements.indexOf(nextEl);
601
+ if (stableIndices.has(nextCurrentPos)) {
602
+ nextStableElement = nextEl;
603
+ break;
420
604
  }
421
605
  }
422
- }, [itemKey, layoutRenderCount]);
423
- } else {
424
- useEffect(() => {
425
- if (!isNullOrUndefined(itemKey)) {
426
- const timeout = setTimeout(() => {
427
- if (!didLayout && refLastSize.current) {
428
- updateItemSize2(itemKey, refLastSize.current);
429
- }
430
- }, 16);
431
- return () => {
432
- clearTimeout(timeout);
433
- };
606
+ if (nextStableElement) {
607
+ container.insertBefore(element, nextStableElement);
608
+ } else {
609
+ container.appendChild(element);
434
610
  }
435
- }, [itemKey]);
611
+ }
436
612
  }
437
- return /* @__PURE__ */ React3.createElement(LeanView, { key: recycleItems ? void 0 : itemKey, onLayout, ref, style }, /* @__PURE__ */ React3.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3.createElement(
438
- Separator,
439
- {
440
- ItemSeparatorComponent,
441
- itemKey,
442
- leadingItem: renderedItemInfo.item
613
+ }
614
+ function findLIS(arr) {
615
+ const n = arr.length;
616
+ const tails = [];
617
+ const predecessors = new Array(n).fill(-1);
618
+ const indices = [];
619
+ for (let i = 0; i < n; i++) {
620
+ const num = arr[i];
621
+ let left = 0, right = tails.length;
622
+ while (left < right) {
623
+ const mid = Math.floor((left + right) / 2);
624
+ if (arr[indices[mid]] < num) {
625
+ left = mid + 1;
626
+ } else {
627
+ right = mid;
628
+ }
443
629
  }
444
- )));
445
- });
446
- var useAnimatedValue = (initialValue) => {
447
- return useRef(new Animated.Value(initialValue)).current;
448
- };
630
+ if (left === tails.length) {
631
+ tails.push(num);
632
+ indices.push(i);
633
+ } else {
634
+ tails[left] = num;
635
+ indices[left] = i;
636
+ }
637
+ if (left > 0) {
638
+ predecessors[i] = indices[left - 1];
639
+ }
640
+ }
641
+ const result = [];
642
+ let k = indices[indices.length - 1];
643
+ while (k !== -1) {
644
+ result.unshift(k);
645
+ k = predecessors[k];
646
+ }
647
+ return result;
648
+ }
449
649
 
450
- // src/hooks/useValue$.ts
451
- function useValue$(key, params) {
452
- var _a;
453
- const { getValue, delay } = params || {};
650
+ // src/hooks/useDOMOrder.ts
651
+ function useDOMOrder(ref) {
454
652
  const ctx = useStateContext();
455
- const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
456
- useMemo(() => {
457
- let newValue;
458
- let prevValue;
459
- let didQueueTask = false;
460
- listen$(ctx, key, (v) => {
461
- newValue = getValue ? getValue(v) : v;
462
- if (delay !== void 0) {
463
- const fn = () => {
464
- didQueueTask = false;
465
- if (newValue !== void 0) {
466
- animValue.setValue(newValue);
467
- }
468
- };
469
- const delayValue = typeof delay === "function" ? delay(newValue, prevValue) : delay;
470
- prevValue = newValue;
471
- if (!didQueueTask) {
472
- didQueueTask = true;
473
- if (delayValue === 0) {
474
- queueMicrotask(fn);
475
- } else {
476
- setTimeout(fn, delayValue);
477
- }
478
- }
479
- } else {
480
- animValue.setValue(newValue);
653
+ const debounceRef = useRef(void 0);
654
+ useEffect(() => {
655
+ const unsubscribe = listen$(ctx, "lastPositionUpdate", () => {
656
+ if (debounceRef.current !== void 0) {
657
+ clearTimeout(debounceRef.current);
481
658
  }
659
+ debounceRef.current = setTimeout(() => {
660
+ const parent = ref.current;
661
+ if (parent) {
662
+ sortDOMElementsPatience(parent);
663
+ }
664
+ debounceRef.current = void 0;
665
+ }, 500);
482
666
  });
483
- }, []);
484
- return animValue;
667
+ return () => {
668
+ unsubscribe();
669
+ if (debounceRef.current !== void 0) {
670
+ clearTimeout(debounceRef.current);
671
+ }
672
+ };
673
+ }, [ctx]);
485
674
  }
486
675
 
487
676
  // src/components/Containers.tsx
677
+ var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColumns, children }) {
678
+ const ref = useRef(null);
679
+ const ctx = useStateContext();
680
+ const columnWrapperStyle = ctx.columnWrapperStyle;
681
+ const [totalSize, otherAxisSize] = useArr$(["totalSize", "otherAxisSize"]);
682
+ useDOMOrder(ref);
683
+ const style = horizontal ? { minHeight: otherAxisSize, width: totalSize } : { height: totalSize, minWidth: otherAxisSize };
684
+ if (columnWrapperStyle && numColumns > 1) {
685
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
686
+ const gapX = columnGap || gap || 0;
687
+ const gapY = rowGap || gap || 0;
688
+ if (horizontal) {
689
+ if (gapY) {
690
+ style.marginTop = style.marginBottom = -gapY / 2;
691
+ }
692
+ if (gapX) {
693
+ style.marginRight = -gapX;
694
+ }
695
+ } else {
696
+ if (gapX) {
697
+ style.marginLeft = style.marginRight = -gapX;
698
+ }
699
+ if (gapY) {
700
+ style.marginBottom = -gapY;
701
+ }
702
+ }
703
+ }
704
+ return /* @__PURE__ */ React4.createElement("div", { ref, style }, children);
705
+ });
488
706
  var Containers = typedMemo(function Containers2({
489
707
  horizontal,
490
708
  recycleItems,
@@ -493,19 +711,11 @@ var Containers = typedMemo(function Containers2({
493
711
  updateItemSize: updateItemSize2,
494
712
  getRenderedItem: getRenderedItem2
495
713
  }) {
496
- const ctx = useStateContext();
497
- const columnWrapperStyle = ctx.columnWrapperStyle;
498
714
  const [numContainers, numColumns] = useArr$(["numContainersPooled", "numColumns"]);
499
- const animSize = useValue$("totalSize", {
500
- // Use a microtask if increasing the size significantly, otherwise use a timeout
501
- delay: (value, prevValue) => !prevValue || value - prevValue > 20 ? 0 : 200
502
- });
503
- const animOpacity = waitForInitialLayout && !IsNewArchitecture ? useValue$("containersDidLayout", { getValue: (value) => value ? 1 : 0 }) : void 0;
504
- const otherAxisSize = useValue$("otherAxisSize", { delay: 0 });
505
715
  const containers = [];
506
716
  for (let i = 0; i < numContainers; i++) {
507
717
  containers.push(
508
- /* @__PURE__ */ React3.createElement(
718
+ /* @__PURE__ */ React4.createElement(
509
719
  Container,
510
720
  {
511
721
  getRenderedItem: getRenderedItem2,
@@ -519,45 +729,209 @@ var Containers = typedMemo(function Containers2({
519
729
  )
520
730
  );
521
731
  }
522
- const style = horizontal ? { minHeight: otherAxisSize, opacity: animOpacity, width: animSize } : { height: animSize, minWidth: otherAxisSize, opacity: animOpacity };
523
- if (columnWrapperStyle && numColumns > 1) {
524
- const { columnGap, rowGap, gap } = columnWrapperStyle;
525
- const gapX = columnGap || gap || 0;
526
- const gapY = rowGap || gap || 0;
527
- if (horizontal) {
528
- if (gapY) {
529
- style.marginVertical = -gapY / 2;
732
+ return /* @__PURE__ */ React4.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
733
+ });
734
+ var DevNumbers = __DEV__ && React4.memo(function DevNumbers2() {
735
+ return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React4.createElement(
736
+ View,
737
+ {
738
+ key: index,
739
+ style: {
740
+ height: 100,
741
+ pointerEvents: "none",
742
+ position: "absolute",
743
+ top: index * 100,
744
+ width: "100%"
530
745
  }
531
- if (gapX) {
532
- style.marginRight = -gapX;
746
+ },
747
+ /* @__PURE__ */ React4.createElement(Text, { style: { color: "red" } }, index * 100)
748
+ ));
749
+ });
750
+ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
751
+ children,
752
+ style,
753
+ contentContainerStyle,
754
+ horizontal = false,
755
+ contentOffset,
756
+ maintainVisibleContentPosition,
757
+ onScroll: onScroll2,
758
+ onMomentumScrollEnd,
759
+ showsHorizontalScrollIndicator = true,
760
+ showsVerticalScrollIndicator = true,
761
+ refreshControl,
762
+ onLayout,
763
+ ScrollComponent,
764
+ ...props
765
+ }, ref) {
766
+ const scrollRef = useRef(null);
767
+ const contentRef = useRef(null);
768
+ const momentumTimeout = useRef(null);
769
+ useImperativeHandle(ref, () => {
770
+ const api = {
771
+ getBoundingClientRect: () => {
772
+ var _a;
773
+ return (_a = scrollRef.current) == null ? void 0 : _a.getBoundingClientRect();
774
+ },
775
+ getScrollableNode: () => scrollRef.current,
776
+ getScrollResponder: () => scrollRef.current,
777
+ scrollBy: (options) => {
778
+ const el = scrollRef.current;
779
+ if (!el) return;
780
+ const { x = 0, y = 0, animated = true } = options;
781
+ el.scrollBy({ behavior: animated ? "smooth" : "auto", left: x, top: y });
782
+ },
783
+ scrollTo: (options) => {
784
+ const el = scrollRef.current;
785
+ if (!el) return;
786
+ const { x = 0, y = 0, animated = true } = options;
787
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", left: x, top: y });
788
+ },
789
+ scrollToEnd: (options = {}) => {
790
+ const el = scrollRef.current;
791
+ if (!el) return;
792
+ const { animated = true } = options;
793
+ if (horizontal) {
794
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", left: el.scrollWidth });
795
+ } else {
796
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", top: el.scrollHeight });
797
+ }
798
+ },
799
+ scrollToOffset: (params) => {
800
+ const el = scrollRef.current;
801
+ if (!el) return;
802
+ const { offset, animated = true } = params;
803
+ if (horizontal) {
804
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", left: offset });
805
+ } else {
806
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", top: offset });
807
+ }
533
808
  }
534
- } else {
535
- if (gapX) {
536
- style.marginHorizontal = -gapX;
809
+ };
810
+ return api;
811
+ }, [horizontal]);
812
+ const handleScroll = useCallback(
813
+ (event) => {
814
+ if (!onScroll2 || !(event == null ? void 0 : event.target)) {
815
+ return;
537
816
  }
538
- if (gapY) {
539
- style.marginBottom = -gapY;
817
+ const target = event.target;
818
+ const scrollEvent = {
819
+ nativeEvent: {
820
+ contentOffset: {
821
+ x: target.scrollLeft,
822
+ y: target.scrollTop
823
+ },
824
+ contentSize: {
825
+ height: target.scrollHeight,
826
+ width: target.scrollWidth
827
+ },
828
+ layoutMeasurement: {
829
+ height: target.clientHeight,
830
+ width: target.clientWidth
831
+ }
832
+ }
833
+ };
834
+ onScroll2(scrollEvent);
835
+ if (onMomentumScrollEnd) {
836
+ if (momentumTimeout.current != null) clearTimeout(momentumTimeout.current);
837
+ momentumTimeout.current = setTimeout(() => {
838
+ onMomentumScrollEnd({
839
+ nativeEvent: {
840
+ contentOffset: scrollEvent.nativeEvent.contentOffset
841
+ }
842
+ });
843
+ }, 100);
540
844
  }
845
+ },
846
+ [onScroll2, onMomentumScrollEnd]
847
+ );
848
+ useLayoutEffect(() => {
849
+ const element = scrollRef.current;
850
+ if (!element) return;
851
+ element.addEventListener("scroll", handleScroll, { passive: true });
852
+ return () => {
853
+ element.removeEventListener("scroll", handleScroll);
854
+ };
855
+ }, [handleScroll]);
856
+ useLayoutEffect(() => {
857
+ if (contentOffset && scrollRef.current) {
858
+ scrollRef.current.scrollLeft = contentOffset.x || 0;
859
+ scrollRef.current.scrollTop = contentOffset.y || 0;
541
860
  }
542
- }
543
- return /* @__PURE__ */ React3.createElement(Animated.View, { style }, containers);
861
+ }, [contentOffset]);
862
+ useLayoutEffect(() => {
863
+ if (!onLayout || !scrollRef.current) return;
864
+ const element = scrollRef.current;
865
+ const fireLayout = () => {
866
+ const rect = element.getBoundingClientRect();
867
+ onLayout({
868
+ nativeEvent: {
869
+ layout: {
870
+ height: rect.height,
871
+ width: rect.width,
872
+ x: rect.left,
873
+ y: rect.top
874
+ }
875
+ }
876
+ });
877
+ };
878
+ fireLayout();
879
+ const resizeObserver = new ResizeObserver(() => {
880
+ fireLayout();
881
+ });
882
+ resizeObserver.observe(element);
883
+ return () => resizeObserver.disconnect();
884
+ }, [onLayout]);
885
+ const scrollViewStyle = {
886
+ overflow: "auto",
887
+ overflowX: horizontal ? "auto" : showsHorizontalScrollIndicator ? "auto" : "hidden",
888
+ overflowY: horizontal ? showsVerticalScrollIndicator ? "auto" : "hidden" : "auto",
889
+ position: "relative",
890
+ // Ensure proper positioning context
891
+ WebkitOverflowScrolling: "touch",
892
+ // iOS momentum scrolling
893
+ ...style
894
+ };
895
+ const contentStyle = {
896
+ display: horizontal ? "flex" : "block",
897
+ flexDirection: horizontal ? "row" : void 0,
898
+ minHeight: horizontal ? void 0 : "100%",
899
+ minWidth: horizontal ? "100%" : void 0,
900
+ ...contentContainerStyle
901
+ };
902
+ return /* @__PURE__ */ React4.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React4.createElement("div", { ref: contentRef, style: contentStyle }, children));
544
903
  });
904
+ function useValueListener$(key, callback) {
905
+ const ctx = useStateContext();
906
+ useLayoutEffect(() => {
907
+ listen$(ctx, key, (value) => {
908
+ callback(value);
909
+ });
910
+ }, []);
911
+ }
912
+
913
+ // src/components/ScrollAdjust.tsx
545
914
  function ScrollAdjust() {
546
- const bias = 1e7;
547
- const [scrollAdjust, scrollAdjustUserOffset] = useArr$(["scrollAdjust", "scrollAdjustUserOffset"]);
548
- const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0) + bias;
549
- return /* @__PURE__ */ React3.createElement(
550
- View,
551
- {
552
- style: {
553
- height: 0,
554
- left: 0,
555
- position: "absolute",
556
- top: scrollOffset,
557
- width: 0
915
+ const ctx = useStateContext();
916
+ const lastScrollOffsetRef = React4.useRef(0);
917
+ const callback = React4.useCallback(() => {
918
+ var _a;
919
+ const scrollAdjust = peek$(ctx, "scrollAdjust");
920
+ const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
921
+ const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
922
+ const scrollView = (_a = ctx.internalState) == null ? void 0 : _a.refScroller.current;
923
+ if (scrollView && scrollOffset !== lastScrollOffsetRef.current) {
924
+ const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
925
+ if (scrollDelta !== 0) {
926
+ scrollView.scrollBy(0, scrollDelta);
927
+ console.log("ScrollAdjust (web scrollBy)", scrollDelta, "total offset:", scrollOffset);
558
928
  }
929
+ lastScrollOffsetRef.current = scrollOffset;
559
930
  }
560
- );
931
+ }, []);
932
+ useValueListener$("scrollAdjust", callback);
933
+ useValueListener$("scrollAdjustUserOffset", callback);
934
+ return null;
561
935
  }
562
936
 
563
937
  // src/components/SnapWrapper.tsx
@@ -565,46 +939,31 @@ function SnapWrapper({ ScrollComponent, ...props }) {
565
939
  const [snapToOffsets] = useArr$(["snapToOffsets"]);
566
940
  return /* @__PURE__ */ React.createElement(ScrollComponent, { ...props, snapToOffsets });
567
941
  }
568
- function useSyncLayout({
569
- onChange
570
- }) {
571
- const ref = useRef(null);
572
- const onLayout = useCallback(
573
- (event) => {
574
- onChange(event.nativeEvent.layout, false);
575
- },
576
- [onChange]
577
- );
578
- if (IsNewArchitecture) {
579
- useLayoutEffect(() => {
580
- if (ref.current) {
581
- ref.current.measure((x, y, width, height) => {
582
- onChange({ height, width, x, y }, true);
583
- });
584
- }
585
- }, []);
586
- }
587
- return { onLayout, ref };
942
+
943
+ // src/hooks/useValue$.ts
944
+ function useValue$(key, params) {
945
+ const [value] = useArr$([key]);
946
+ return value;
588
947
  }
589
948
 
590
949
  // src/components/ListComponent.tsx
591
950
  var getComponent = (Component) => {
592
- if (React3.isValidElement(Component)) {
951
+ if (React4.isValidElement(Component)) {
593
952
  return Component;
594
953
  }
595
954
  if (Component) {
596
- return /* @__PURE__ */ React3.createElement(Component, null);
955
+ return /* @__PURE__ */ React4.createElement(Component, null);
597
956
  }
598
957
  return null;
599
958
  };
600
959
  var Padding = () => {
601
- const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
602
- return /* @__PURE__ */ React3.createElement(Animated.View, { style: { paddingTop: animPaddingTop } });
960
+ const animPaddingTop = useValue$("alignItemsPaddingTop");
961
+ return /* @__PURE__ */ React4.createElement(AnimatedView, { style: { paddingTop: animPaddingTop } });
603
962
  };
604
963
  var PaddingDevMode = () => {
605
- const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
606
- return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(Animated.View, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React3.createElement(
607
- Animated.View,
964
+ const animPaddingTop = useValue$("alignItemsPaddingTop");
965
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(AnimatedView, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React4.createElement(
966
+ AnimatedView,
608
967
  {
609
968
  style: {
610
969
  backgroundColor: "green",
@@ -642,17 +1001,16 @@ var ListComponent = typedMemo(function ListComponent2({
642
1001
  scrollAdjustHandler,
643
1002
  onLayoutHeader,
644
1003
  snapToIndices,
1004
+ stickyIndices,
645
1005
  ...rest
646
1006
  }) {
647
1007
  const ctx = useStateContext();
648
- const { onLayout: onLayoutHeaderSync, ref: refHeader } = useSyncLayout({
649
- onChange: onLayoutHeader
650
- });
1008
+ const refHeader = React4.useRef(null);
651
1009
  const ScrollComponent = renderScrollComponent ? useMemo(
652
- () => React3.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
1010
+ () => React4.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
653
1011
  [renderScrollComponent]
654
- ) : ScrollView;
655
- React3.useEffect(() => {
1012
+ ) : ListComponentScrollView;
1013
+ React4.useEffect(() => {
656
1014
  if (canRender) {
657
1015
  setTimeout(() => {
658
1016
  scrollAdjustHandler.setMounted();
@@ -660,16 +1018,17 @@ var ListComponent = typedMemo(function ListComponent2({
660
1018
  }
661
1019
  }, [canRender]);
662
1020
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
663
- return /* @__PURE__ */ React3.createElement(
1021
+ const contentContainerStyleWeb = useMemo(() => {
1022
+ const base = contentContainerStyle || void 0;
1023
+ if (!horizontal) return base;
1024
+ if (base && base.height === "100%") return base;
1025
+ return { ...base || {}, height: "100%" };
1026
+ }, [horizontal, (contentContainerStyle == null ? void 0 : contentContainerStyle.height) === "100%" ? 1 : 0]);
1027
+ return /* @__PURE__ */ React4.createElement(
664
1028
  SnapOrScroll,
665
1029
  {
666
1030
  ...rest,
667
- contentContainerStyle: [
668
- contentContainerStyle,
669
- horizontal ? {
670
- height: "100%"
671
- } : {}
672
- ],
1031
+ contentContainerStyle: contentContainerStyleWeb,
673
1032
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
674
1033
  horizontal,
675
1034
  maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
@@ -679,11 +1038,19 @@ var ListComponent = typedMemo(function ListComponent2({
679
1038
  ScrollComponent: snapToIndices ? ScrollComponent : void 0,
680
1039
  style
681
1040
  },
682
- maintainVisibleContentPosition && /* @__PURE__ */ React3.createElement(ScrollAdjust, null),
683
- ENABLE_DEVMODE ? /* @__PURE__ */ React3.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3.createElement(Padding, null),
684
- ListHeaderComponent && /* @__PURE__ */ React3.createElement(View, { onLayout: onLayoutHeaderSync, ref: refHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1041
+ maintainVisibleContentPosition && /* @__PURE__ */ React4.createElement(ScrollAdjust, null),
1042
+ ENABLE_DEVMODE ? /* @__PURE__ */ React4.createElement(PaddingDevMode, null) : /* @__PURE__ */ React4.createElement(Padding, null),
1043
+ ListHeaderComponent && /* @__PURE__ */ React4.createElement(
1044
+ LayoutView,
1045
+ {
1046
+ onLayoutChange: onLayoutHeader,
1047
+ refView: refHeader,
1048
+ style: ListHeaderComponentStyle
1049
+ },
1050
+ getComponent(ListHeaderComponent)
1051
+ ),
685
1052
  ListEmptyComponent && getComponent(ListEmptyComponent),
686
- canRender && /* @__PURE__ */ React3.createElement(
1053
+ canRender && /* @__PURE__ */ React4.createElement(
687
1054
  Containers,
688
1055
  {
689
1056
  getRenderedItem: getRenderedItem2,
@@ -694,17 +1061,18 @@ var ListComponent = typedMemo(function ListComponent2({
694
1061
  waitForInitialLayout
695
1062
  }
696
1063
  ),
697
- ListFooterComponent && /* @__PURE__ */ React3.createElement(
698
- View,
1064
+ ListFooterComponent && /* @__PURE__ */ React4.createElement(
1065
+ LayoutView,
699
1066
  {
700
- onLayout: (event) => {
701
- const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
1067
+ onLayoutChange: (layout) => {
1068
+ const size = layout[horizontal ? "width" : "height"];
702
1069
  set$(ctx, "footerSize", size);
703
1070
  },
704
1071
  style: ListFooterComponentStyle
705
1072
  },
706
1073
  getComponent(ListFooterComponent)
707
- )
1074
+ ),
1075
+ __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React4.createElement(DevNumbers, null)
708
1076
  );
709
1077
  });
710
1078
 
@@ -725,33 +1093,45 @@ function calculateOffsetForIndex(ctx, state, index) {
725
1093
  let position = 0;
726
1094
  if (index !== void 0) {
727
1095
  position = (state == null ? void 0 : state.positions.get(getId(state, index))) || 0;
728
- }
729
- const paddingTop = peek$(ctx, "stylePaddingTop");
730
- if (paddingTop) {
731
- position += paddingTop;
732
- }
733
- const headerSize = peek$(ctx, "headerSize");
734
- if (headerSize) {
735
- position += headerSize;
1096
+ const paddingTop = peek$(ctx, "stylePaddingTop");
1097
+ if (paddingTop) {
1098
+ position += paddingTop;
1099
+ }
1100
+ const headerSize = peek$(ctx, "headerSize");
1101
+ if (headerSize) {
1102
+ position += headerSize;
1103
+ }
736
1104
  }
737
1105
  return position;
738
1106
  }
739
1107
 
740
1108
  // src/utils/getItemSize.ts
741
1109
  function getItemSize(state, key, index, data, useAverageSize) {
1110
+ var _a, _b;
742
1111
  const {
743
1112
  sizesKnown,
744
1113
  sizes,
745
1114
  scrollingTo,
746
- props: { estimatedItemSize, getEstimatedItemSize }
1115
+ averageSizes,
1116
+ props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
747
1117
  } = state;
748
1118
  const sizeKnown = sizesKnown.get(key);
749
1119
  if (sizeKnown !== void 0) {
750
1120
  return sizeKnown;
751
1121
  }
752
1122
  let size;
753
- if (useAverageSize !== void 0 && sizeKnown === void 0 && !getEstimatedItemSize && !scrollingTo) {
754
- size = useAverageSize;
1123
+ const itemType = getItemType ? (_a = getItemType(data, index)) != null ? _a : "" : "";
1124
+ if (getFixedItemSize) {
1125
+ size = getFixedItemSize(index, data, itemType);
1126
+ if (size !== void 0) {
1127
+ sizesKnown.set(key, size);
1128
+ }
1129
+ }
1130
+ if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
1131
+ const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
1132
+ if (averageSizeForType !== void 0) {
1133
+ size = roundSize(averageSizeForType);
1134
+ }
755
1135
  }
756
1136
  if (size === void 0) {
757
1137
  size = sizes.get(key);
@@ -760,7 +1140,7 @@ function getItemSize(state, key, index, data, useAverageSize) {
760
1140
  }
761
1141
  }
762
1142
  if (size === void 0) {
763
- size = getEstimatedItemSize ? getEstimatedItemSize(index, data) : estimatedItemSize;
1143
+ size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
764
1144
  }
765
1145
  sizes.set(key, size);
766
1146
  return size;
@@ -779,11 +1159,46 @@ function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
779
1159
  return offset;
780
1160
  }
781
1161
 
1162
+ // src/core/finishScrollTo.ts
1163
+ var finishScrollTo = (state) => {
1164
+ if (state) {
1165
+ state.scrollingTo = void 0;
1166
+ state.scrollHistory.length = 0;
1167
+ }
1168
+ };
1169
+
1170
+ // src/core/scrollTo.ts
1171
+ function scrollTo(state, params = {}) {
1172
+ var _a;
1173
+ const { animated, noScrollingTo } = params;
1174
+ const {
1175
+ refScroller,
1176
+ props: { horizontal }
1177
+ } = state;
1178
+ const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1179
+ state.scrollHistory.length = 0;
1180
+ if (!noScrollingTo) {
1181
+ state.scrollingTo = params;
1182
+ }
1183
+ state.scrollPending = offset;
1184
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1185
+ animated: !!animated,
1186
+ x: horizontal ? offset : 0,
1187
+ y: horizontal ? 0 : offset
1188
+ });
1189
+ if (!animated) {
1190
+ state.scroll = offset;
1191
+ setTimeout(() => finishScrollTo(state), 100);
1192
+ }
1193
+ }
1194
+
782
1195
  // src/utils/requestAdjust.ts
783
- function requestAdjust(ctx, state, positionDiff) {
1196
+ function requestAdjust(ctx, state, positionDiff, dataChanged) {
784
1197
  if (Math.abs(positionDiff) > 0.1) {
785
1198
  const doit = () => {
786
- state.scrollAdjustHandler.requestAdjust(positionDiff);
1199
+ {
1200
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
1201
+ }
787
1202
  };
788
1203
  state.scroll += positionDiff;
789
1204
  state.scrollForNextCalculateItemsInView = void 0;
@@ -802,49 +1217,72 @@ function requestAdjust(ctx, state, positionDiff) {
802
1217
  if (state.ignoreScrollFromMVCPTimeout) {
803
1218
  clearTimeout(state.ignoreScrollFromMVCPTimeout);
804
1219
  }
805
- state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
806
- state.ignoreScrollFromMVCP = void 0;
807
- }, 100);
1220
+ state.ignoreScrollFromMVCPTimeout = setTimeout(
1221
+ () => {
1222
+ state.ignoreScrollFromMVCP = void 0;
1223
+ },
1224
+ 100
1225
+ );
808
1226
  } else {
809
1227
  requestAnimationFrame(doit);
810
1228
  }
811
1229
  }
812
1230
  }
813
1231
 
814
- // src/core/prepareMVCP.ts
815
- function prepareMVCP(ctx, state) {
1232
+ // src/core/mvcp.ts
1233
+ function prepareMVCP(ctx, state, dataChanged) {
816
1234
  const {
1235
+ idsInView,
817
1236
  positions,
818
1237
  scrollingTo,
819
1238
  props: { maintainVisibleContentPosition }
820
1239
  } = state;
821
1240
  let prevPosition;
822
1241
  let targetId;
823
- let targetIndex;
1242
+ const idsInViewWithPositions = [];
824
1243
  const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
825
1244
  if (maintainVisibleContentPosition) {
826
1245
  const indexByKey = state.indexByKey;
827
1246
  if (scrollTarget !== void 0) {
828
1247
  targetId = getId(state, scrollTarget);
829
- targetIndex = scrollTarget;
830
- } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
831
- targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
832
- targetIndex = indexByKey.get(targetId);
1248
+ } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1249
+ if (dataChanged) {
1250
+ for (let i = 0; i < idsInView.length; i++) {
1251
+ const id = idsInView[i];
1252
+ const index = indexByKey.get(id);
1253
+ if (index !== void 0) {
1254
+ idsInViewWithPositions.push({ id, position: positions.get(id) });
1255
+ }
1256
+ }
1257
+ } else {
1258
+ targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
1259
+ }
833
1260
  }
834
- if (targetId !== void 0 && targetIndex !== void 0) {
1261
+ if (targetId !== void 0) {
835
1262
  prevPosition = positions.get(targetId);
836
1263
  }
837
1264
  }
838
1265
  return () => {
1266
+ let positionDiff;
1267
+ if (dataChanged && targetId === void 0) {
1268
+ for (let i = 0; i < idsInViewWithPositions.length; i++) {
1269
+ const { id, position } = idsInViewWithPositions[i];
1270
+ const newPosition = positions.get(id);
1271
+ if (newPosition !== void 0) {
1272
+ positionDiff = newPosition - position;
1273
+ break;
1274
+ }
1275
+ }
1276
+ }
839
1277
  if (targetId !== void 0 && prevPosition !== void 0) {
840
1278
  const newPosition = positions.get(targetId);
841
1279
  if (newPosition !== void 0) {
842
- const positionDiff = newPosition - prevPosition;
843
- if (Math.abs(positionDiff) > 0.1) {
844
- requestAdjust(ctx, state, positionDiff);
845
- }
1280
+ positionDiff = newPosition - prevPosition;
846
1281
  }
847
1282
  }
1283
+ if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1284
+ requestAdjust(ctx, state, positionDiff);
1285
+ }
848
1286
  };
849
1287
  }
850
1288
 
@@ -853,10 +1291,10 @@ function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
853
1291
  if (stylePaddingTop !== void 0) {
854
1292
  const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
855
1293
  if (stylePaddingTop < prevStylePaddingTop) {
856
- let prevTotalSize = peek$(ctx, "totalSize");
1294
+ let prevTotalSize = peek$(ctx, "totalSize") || 0;
857
1295
  set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
858
1296
  state.timeoutSetPaddingTop = setTimeout(() => {
859
- prevTotalSize = peek$(ctx, "totalSize");
1297
+ prevTotalSize = peek$(ctx, "totalSize") || 0;
860
1298
  set$(ctx, "totalSize", prevTotalSize - prevStylePaddingTop);
861
1299
  }, 16);
862
1300
  }
@@ -920,43 +1358,6 @@ function addTotalSize(ctx, state, key, add) {
920
1358
  }
921
1359
  }
922
1360
 
923
- // src/utils/getScrollVelocity.ts
924
- var getScrollVelocity = (state) => {
925
- const { scrollHistory } = state;
926
- let velocity = 0;
927
- if (scrollHistory.length >= 1) {
928
- const newest = scrollHistory[scrollHistory.length - 1];
929
- let oldest;
930
- let start = 0;
931
- for (let i = 0; i < scrollHistory.length - 1; i++) {
932
- const entry = scrollHistory[i];
933
- const nextEntry = scrollHistory[i + 1];
934
- if (i > 0) {
935
- const prevEntry = scrollHistory[i - 1];
936
- const prevDirection = entry.scroll - prevEntry.scroll;
937
- const currentDirection = nextEntry.scroll - entry.scroll;
938
- if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
939
- start = i;
940
- break;
941
- }
942
- }
943
- }
944
- for (let i = start; i < scrollHistory.length - 1; i++) {
945
- const entry = scrollHistory[i];
946
- if (newest.time - entry.time <= 1e3) {
947
- oldest = entry;
948
- break;
949
- }
950
- }
951
- if (oldest) {
952
- const scrollDiff = newest.scroll - oldest.scroll;
953
- const timeDiff = newest.time - oldest.time;
954
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
955
- }
956
- }
957
- return velocity;
958
- };
959
-
960
1361
  // src/utils/updateSnapToOffsets.ts
961
1362
  function updateSnapToOffsets(ctx, state) {
962
1363
  const {
@@ -973,69 +1374,42 @@ function updateSnapToOffsets(ctx, state) {
973
1374
  }
974
1375
 
975
1376
  // src/core/updateAllPositions.ts
976
- function updateAllPositions(ctx, state, dataChanged) {
977
- var _a, _b, _c, _d, _e;
1377
+ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1378
+ var _a, _b, _c, _d, _e, _f;
978
1379
  const {
979
- averageSizes,
980
1380
  columns,
981
1381
  indexByKey,
982
1382
  positions,
983
- firstFullyOnScreenIndex,
984
1383
  idCache,
985
1384
  sizesKnown,
986
- props: { snapToIndices }
1385
+ props: { getEstimatedItemSize, snapToIndices, enableAverages }
987
1386
  } = state;
988
1387
  const data = state.props.data;
989
1388
  const numColumns = peek$(ctx, "numColumns");
990
1389
  const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
991
- const scrollVelocity = getScrollVelocity(state);
992
- if (dataChanged) {
993
- indexByKey.clear();
994
- idCache.clear();
995
- }
996
- const itemType = "";
997
- let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
998
- if (averageSize !== void 0) {
999
- averageSize = roundSize(averageSize);
1000
- }
1001
- const shouldUseBackwards = !dataChanged && scrollVelocity < 0 && firstFullyOnScreenIndex > 5 && firstFullyOnScreenIndex < data.length;
1002
- if (shouldUseBackwards && firstFullyOnScreenIndex !== void 0) {
1003
- const anchorId = getId(state, firstFullyOnScreenIndex);
1004
- const anchorPosition = positions.get(anchorId);
1005
- if (anchorPosition !== void 0) {
1006
- let currentRowTop2 = anchorPosition;
1007
- let maxSizeInRow2 = 0;
1008
- let bailout = false;
1009
- for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
1010
- const id = (_b = idCache.get(i)) != null ? _b : getId(state, i);
1011
- const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(state, id, i, data[i], averageSize);
1012
- const itemColumn = columns.get(id);
1013
- maxSizeInRow2 = Math.max(maxSizeInRow2, size);
1014
- if (itemColumn === 1) {
1015
- currentRowTop2 -= maxSizeInRow2;
1016
- maxSizeInRow2 = 0;
1017
- }
1018
- if (currentRowTop2 < -2e3) {
1019
- bailout = true;
1020
- break;
1021
- }
1022
- positions.set(id, currentRowTop2);
1023
- }
1024
- if (!bailout) {
1025
- updateTotalSize(ctx, state);
1026
- return;
1027
- }
1028
- }
1029
- }
1390
+ const useAverageSize = enableAverages && !getEstimatedItemSize;
1030
1391
  let currentRowTop = 0;
1031
1392
  let column = 1;
1032
1393
  let maxSizeInRow = 0;
1033
1394
  const hasColumns = numColumns > 1;
1395
+ if (startIndex > 0) {
1396
+ const prevIndex = startIndex - 1;
1397
+ const prevId = (_a = idCache.get(prevIndex)) != null ? _a : getId(state, prevIndex);
1398
+ const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1399
+ if (hasColumns) {
1400
+ const prevColumn = (_c = columns.get(prevId)) != null ? _c : 1;
1401
+ currentRowTop = prevPosition;
1402
+ column = prevColumn % numColumns + 1;
1403
+ } else {
1404
+ const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(state, prevId, prevIndex, data[prevIndex], useAverageSize);
1405
+ currentRowTop = prevPosition + prevSize;
1406
+ }
1407
+ }
1034
1408
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1035
1409
  const dataLength = data.length;
1036
- for (let i = 0; i < dataLength; i++) {
1037
- const id = (_d = idCache.get(i)) != null ? _d : getId(state, i);
1038
- const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(state, id, i, data[i], averageSize);
1410
+ for (let i = startIndex; i < dataLength; i++) {
1411
+ const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1412
+ const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(state, id, i, data[i], useAverageSize);
1039
1413
  if (__DEV__ && needsIndexByKey) {
1040
1414
  if (indexByKeyForChecking.has(id)) {
1041
1415
  console.error(
@@ -1070,32 +1444,18 @@ function updateAllPositions(ctx, state, dataChanged) {
1070
1444
  }
1071
1445
 
1072
1446
  // src/core/viewability.ts
1073
- var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
1074
- function setupViewability(props) {
1075
- let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
1076
- if (viewabilityConfig || onViewableItemsChanged) {
1077
- viewabilityConfigCallbackPairs = [
1078
- ...viewabilityConfigCallbackPairs || [],
1079
- {
1080
- onViewableItemsChanged,
1081
- viewabilityConfig: viewabilityConfig || {
1082
- viewAreaCoveragePercentThreshold: 0
1083
- }
1084
- }
1085
- ];
1447
+ function ensureViewabilityState(ctx, configId) {
1448
+ let map = ctx.mapViewabilityConfigStates;
1449
+ if (!map) {
1450
+ map = /* @__PURE__ */ new Map();
1451
+ ctx.mapViewabilityConfigStates = map;
1086
1452
  }
1087
- if (viewabilityConfigCallbackPairs) {
1088
- for (const pair of viewabilityConfigCallbackPairs) {
1089
- mapViewabilityConfigCallbackPairs.set(pair.viewabilityConfig.id, {
1090
- end: -1,
1091
- previousEnd: -1,
1092
- previousStart: -1,
1093
- start: -1,
1094
- viewableItems: []
1095
- });
1096
- }
1453
+ let state = map.get(configId);
1454
+ if (!state) {
1455
+ state = { end: -1, previousEnd: -1, previousStart: -1, start: -1, viewableItems: [] };
1456
+ map.set(configId, state);
1097
1457
  }
1098
- return viewabilityConfigCallbackPairs;
1458
+ return state;
1099
1459
  }
1100
1460
  function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
1101
1461
  const {
@@ -1103,9 +1463,7 @@ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollS
1103
1463
  props: { data }
1104
1464
  } = state;
1105
1465
  for (const viewabilityConfigCallbackPair of viewabilityConfigCallbackPairs) {
1106
- const viewabilityState = mapViewabilityConfigCallbackPairs.get(
1107
- viewabilityConfigCallbackPair.viewabilityConfig.id
1108
- );
1466
+ const viewabilityState = ensureViewabilityState(ctx, viewabilityConfigCallbackPair.viewabilityConfig.id);
1109
1467
  viewabilityState.start = start;
1110
1468
  viewabilityState.end = end;
1111
1469
  if (viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime) {
@@ -1122,7 +1480,7 @@ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollS
1122
1480
  function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize) {
1123
1481
  const { viewabilityConfig, onViewableItemsChanged } = viewabilityConfigCallbackPair;
1124
1482
  const configId = viewabilityConfig.id;
1125
- const viewabilityState = mapViewabilityConfigCallbackPairs.get(configId);
1483
+ const viewabilityState = ensureViewabilityState(ctx, configId);
1126
1484
  const { viewableItems: previousViewableItems, start, end } = viewabilityState;
1127
1485
  const viewabilityTokens = /* @__PURE__ */ new Map();
1128
1486
  for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
@@ -1201,6 +1559,15 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1201
1559
  }
1202
1560
  }
1203
1561
  }
1562
+ function shallowEqual(prev, next) {
1563
+ if (!prev) return false;
1564
+ const keys = Object.keys(next);
1565
+ for (let i = 0; i < keys.length; i++) {
1566
+ const k = keys[i];
1567
+ if (prev[k] !== next[k]) return false;
1568
+ }
1569
+ return true;
1570
+ }
1204
1571
  function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
1205
1572
  const { sizes, positions, scroll: scrollState } = state;
1206
1573
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
@@ -1229,7 +1596,8 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
1229
1596
  size,
1230
1597
  sizeVisible
1231
1598
  };
1232
- if (JSON.stringify(value) !== JSON.stringify(ctx.mapViewabilityAmountValues.get(containerId))) {
1599
+ const prev = ctx.mapViewabilityAmountValues.get(containerId);
1600
+ if (!shallowEqual(prev, value)) {
1233
1601
  ctx.mapViewabilityAmountValues.set(containerId, value);
1234
1602
  const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
1235
1603
  if (cb) {
@@ -1262,7 +1630,7 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1262
1630
  // src/utils/checkAllSizesKnown.ts
1263
1631
  function checkAllSizesKnown(state) {
1264
1632
  const { startBuffered, endBuffered, sizesKnown } = state;
1265
- if (endBuffered !== null) {
1633
+ if (endBuffered !== null && startBuffered >= 0 && endBuffered >= 0) {
1266
1634
  let areAllKnown = true;
1267
1635
  for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1268
1636
  const key = getId(state, i);
@@ -1274,35 +1642,79 @@ function checkAllSizesKnown(state) {
1274
1642
  }
1275
1643
 
1276
1644
  // src/utils/findAvailableContainers.ts
1277
- function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
1645
+ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
1278
1646
  const numContainers = peek$(ctx, "numContainers");
1647
+ const { stickyContainerPool, containerItemTypes } = state;
1279
1648
  const result = [];
1280
1649
  const availableContainers = [];
1281
- for (let u = 0; u < numContainers; u++) {
1650
+ const stickyIndicesSet = state.props.stickyIndicesSet;
1651
+ const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
1652
+ const canReuseContainer = (containerIndex, requiredType) => {
1653
+ if (!requiredType) return true;
1654
+ const existingType = containerItemTypes.get(containerIndex);
1655
+ if (!existingType) return true;
1656
+ return existingType === requiredType;
1657
+ };
1658
+ const neededTypes = requiredItemTypes ? [...requiredItemTypes] : [];
1659
+ let typeIndex = 0;
1660
+ for (let i = 0; i < stickyItemIndices.length; i++) {
1661
+ const requiredType = neededTypes[typeIndex];
1662
+ let foundContainer = false;
1663
+ for (const containerIndex of stickyContainerPool) {
1664
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
1665
+ const isPendingRemoval = pendingRemoval.includes(containerIndex);
1666
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType)) {
1667
+ result.push(containerIndex);
1668
+ if (isPendingRemoval) {
1669
+ const index = pendingRemoval.indexOf(containerIndex);
1670
+ pendingRemoval.splice(index, 1);
1671
+ }
1672
+ foundContainer = true;
1673
+ if (requiredItemTypes) typeIndex++;
1674
+ break;
1675
+ }
1676
+ }
1677
+ if (!foundContainer) {
1678
+ const newContainerIndex = numContainers + result.filter((index) => index >= numContainers).length;
1679
+ result.push(newContainerIndex);
1680
+ stickyContainerPool.add(newContainerIndex);
1681
+ if (requiredItemTypes) typeIndex++;
1682
+ }
1683
+ }
1684
+ for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
1685
+ if (stickyContainerPool.has(u)) {
1686
+ continue;
1687
+ }
1282
1688
  const key = peek$(ctx, `containerItemKey${u}`);
1283
1689
  let isOk = key === void 0;
1284
1690
  if (!isOk) {
1285
1691
  const index = pendingRemoval.indexOf(u);
1286
1692
  if (index !== -1) {
1287
1693
  pendingRemoval.splice(index, 1);
1288
- isOk = true;
1694
+ const requiredType = neededTypes[typeIndex];
1695
+ isOk = canReuseContainer(u, requiredType);
1289
1696
  }
1290
1697
  }
1291
1698
  if (isOk) {
1292
1699
  result.push(u);
1293
- if (result.length >= numNeeded) {
1294
- return result;
1700
+ if (requiredItemTypes) {
1701
+ typeIndex++;
1295
1702
  }
1296
1703
  }
1297
1704
  }
1298
- for (let u = 0; u < numContainers; u++) {
1705
+ for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
1706
+ if (stickyContainerPool.has(u)) {
1707
+ continue;
1708
+ }
1299
1709
  const key = peek$(ctx, `containerItemKey${u}`);
1300
1710
  if (key === void 0) continue;
1301
1711
  const index = state.indexByKey.get(key);
1302
- if (index < startBuffered) {
1303
- availableContainers.push({ distance: startBuffered - index, index: u });
1304
- } else if (index > endBuffered) {
1305
- availableContainers.push({ distance: index - endBuffered, index: u });
1712
+ const isOutOfView = index < startBuffered || index > endBuffered;
1713
+ if (isOutOfView) {
1714
+ const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
1715
+ if (!requiredItemTypes || typeIndex < neededTypes.length && canReuseContainer(u, neededTypes[typeIndex])) {
1716
+ availableContainers.push({ distance, index: u });
1717
+ }
1306
1718
  }
1307
1719
  }
1308
1720
  const remaining = numNeeded - result.length;
@@ -1314,6 +1726,9 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1314
1726
  }
1315
1727
  for (const container of availableContainers) {
1316
1728
  result.push(container.index);
1729
+ if (requiredItemTypes) {
1730
+ typeIndex++;
1731
+ }
1317
1732
  }
1318
1733
  }
1319
1734
  const stillNeeded = numNeeded - result.length;
@@ -1342,37 +1757,44 @@ function comparatorByDistance(a, b) {
1342
1757
  return b.distance - a.distance;
1343
1758
  }
1344
1759
 
1345
- // src/core/finishScrollTo.ts
1346
- var finishScrollTo = (state) => {
1347
- if (state) {
1348
- state.scrollingTo = void 0;
1349
- state.scrollHistory.length = 0;
1760
+ // src/utils/getScrollVelocity.ts
1761
+ var getScrollVelocity = (state) => {
1762
+ const { scrollHistory } = state;
1763
+ let velocity = 0;
1764
+ if (scrollHistory.length >= 1) {
1765
+ const newest = scrollHistory[scrollHistory.length - 1];
1766
+ let oldest;
1767
+ let start = 0;
1768
+ const now = Date.now();
1769
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
1770
+ const entry = scrollHistory[i];
1771
+ const nextEntry = scrollHistory[i + 1];
1772
+ if (i > 0) {
1773
+ const prevEntry = scrollHistory[i - 1];
1774
+ const prevDirection = entry.scroll - prevEntry.scroll;
1775
+ const currentDirection = nextEntry.scroll - entry.scroll;
1776
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1777
+ start = i;
1778
+ break;
1779
+ }
1780
+ }
1781
+ }
1782
+ for (let i = start; i < scrollHistory.length - 1; i++) {
1783
+ const entry = scrollHistory[i];
1784
+ if (now - entry.time <= 1e3) {
1785
+ oldest = entry;
1786
+ break;
1787
+ }
1788
+ }
1789
+ if (oldest && oldest !== newest) {
1790
+ const scrollDiff = newest.scroll - oldest.scroll;
1791
+ const timeDiff = newest.time - oldest.time;
1792
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1793
+ }
1350
1794
  }
1795
+ return velocity;
1351
1796
  };
1352
1797
 
1353
- // src/core/scrollTo.ts
1354
- function scrollTo(state, params = {}) {
1355
- var _a;
1356
- const { animated } = params;
1357
- const {
1358
- refScroller,
1359
- props: { horizontal }
1360
- } = state;
1361
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1362
- state.scrollHistory.length = 0;
1363
- state.scrollingTo = params;
1364
- state.scrollPending = offset;
1365
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1366
- animated: !!animated,
1367
- x: horizontal ? offset : 0,
1368
- y: horizontal ? 0 : offset
1369
- });
1370
- if (!animated) {
1371
- state.scroll = offset;
1372
- setTimeout(() => finishScrollTo(state), 100);
1373
- }
1374
- }
1375
-
1376
1798
  // src/core/scrollToIndex.ts
1377
1799
  function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1378
1800
  if (index >= state.props.data.length) {
@@ -1460,33 +1882,101 @@ function setDidLayout(ctx, state) {
1460
1882
  } = state;
1461
1883
  state.queuedInitialLayout = true;
1462
1884
  checkAtBottom(ctx, state);
1463
- if (!IsNewArchitecture && initialScroll) {
1464
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1885
+ const setIt = () => {
1886
+ set$(ctx, "containersDidLayout", true);
1887
+ if (onLoad) {
1888
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1889
+ }
1890
+ };
1891
+ {
1892
+ setIt();
1893
+ }
1894
+ }
1895
+
1896
+ // src/core/calculateItemsInView.ts
1897
+ function findCurrentStickyIndex(stickyArray, scroll, state) {
1898
+ var _a;
1899
+ const idCache = state.idCache;
1900
+ const positions = state.positions;
1901
+ for (let i = stickyArray.length - 1; i >= 0; i--) {
1902
+ const stickyId = (_a = idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
1903
+ const stickyPos = stickyId ? positions.get(stickyId) : void 0;
1904
+ if (stickyPos !== void 0 && scroll >= stickyPos) {
1905
+ return i;
1906
+ }
1907
+ }
1908
+ return -1;
1909
+ }
1910
+ function getActiveStickyIndices(ctx, state, stickyIndices) {
1911
+ return new Set(
1912
+ Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyIndices.has(idx))
1913
+ );
1914
+ }
1915
+ function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll, needNewContainers, startBuffered, endBuffered) {
1916
+ var _a;
1917
+ const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
1918
+ const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1919
+ for (let offset = 0; offset <= 1; offset++) {
1920
+ const idx = currentStickyIdx - offset;
1921
+ if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
1922
+ const stickyIndex = stickyArray[idx];
1923
+ const stickyId = (_a = state.idCache.get(stickyIndex)) != null ? _a : getId(state, stickyIndex);
1924
+ if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered)) {
1925
+ needNewContainers.push(stickyIndex);
1926
+ }
1465
1927
  }
1466
- set$(ctx, "containersDidLayout", true);
1467
- if (onLoad) {
1468
- onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1928
+ }
1929
+ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pendingRemoval) {
1930
+ var _a, _b, _c;
1931
+ const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1932
+ for (const containerIndex of state.stickyContainerPool) {
1933
+ const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
1934
+ const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
1935
+ if (itemIndex === void 0) continue;
1936
+ const arrayIdx = stickyArray.indexOf(itemIndex);
1937
+ if (arrayIdx === -1) continue;
1938
+ const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
1939
+ if (isRecentSticky) continue;
1940
+ const nextIndex = stickyArray[arrayIdx + 1];
1941
+ let shouldRecycle = false;
1942
+ if (nextIndex) {
1943
+ const nextId = (_a = state.idCache.get(nextIndex)) != null ? _a : getId(state, nextIndex);
1944
+ const nextPos = nextId ? state.positions.get(nextId) : void 0;
1945
+ shouldRecycle = nextPos !== void 0 && scroll > nextPos + scrollBuffer * 2;
1946
+ } else {
1947
+ const currentId = (_b = state.idCache.get(itemIndex)) != null ? _b : getId(state, itemIndex);
1948
+ if (currentId) {
1949
+ const currentPos = state.positions.get(currentId);
1950
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
1951
+ shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
1952
+ }
1953
+ }
1954
+ if (shouldRecycle) {
1955
+ pendingRemoval.push(containerIndex);
1956
+ }
1469
1957
  }
1470
1958
  }
1471
-
1472
- // src/core/calculateItemsInView.ts
1473
1959
  function calculateItemsInView(ctx, state, params = {}) {
1474
1960
  unstable_batchedUpdates(() => {
1475
1961
  var _a, _b, _c, _d, _e, _f, _g, _h;
1476
1962
  const {
1477
- scrollLength,
1478
- startBufferedId: startBufferedIdOrig,
1479
- positions,
1480
1963
  columns,
1481
1964
  containerItemKeys,
1965
+ enableScrollForNextCalculateItemsInView,
1482
1966
  idCache,
1483
- sizes,
1484
1967
  indexByKey,
1968
+ minIndexSizeChanged,
1969
+ positions,
1485
1970
  scrollForNextCalculateItemsInView,
1486
- enableScrollForNextCalculateItemsInView,
1487
- minIndexSizeChanged
1971
+ scrollLength,
1972
+ sizes,
1973
+ startBufferedId: startBufferedIdOrig,
1974
+ viewabilityConfigCallbackPairs,
1975
+ props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, scrollBuffer }
1488
1976
  } = state;
1489
- const data = state.props.data;
1977
+ const { data } = state.props;
1978
+ const stickyIndicesArr = state.props.stickyIndicesArr || [];
1979
+ const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
1490
1980
  const prevNumContainers = peek$(ctx, "numContainers");
1491
1981
  if (!data || scrollLength === 0 || !prevNumContainers) {
1492
1982
  return;
@@ -1498,14 +1988,22 @@ function calculateItemsInView(ctx, state, params = {}) {
1498
1988
  const { dataChanged, doMVCP } = params;
1499
1989
  const speed = getScrollVelocity(state);
1500
1990
  if (doMVCP || dataChanged) {
1501
- const checkMVCP = doMVCP ? prepareMVCP(ctx, state) : void 0;
1502
- updateAllPositions(ctx, state, dataChanged);
1991
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
1992
+ if (dataChanged) {
1993
+ indexByKey.clear();
1994
+ idCache.clear();
1995
+ positions.clear();
1996
+ }
1997
+ const startIndex = dataChanged ? 0 : minIndexSizeChanged != null ? minIndexSizeChanged : 0;
1998
+ updateAllPositions(ctx, state, dataChanged, startIndex);
1999
+ if (minIndexSizeChanged !== void 0) {
2000
+ state.minIndexSizeChanged = void 0;
2001
+ }
1503
2002
  checkMVCP == null ? void 0 : checkMVCP();
1504
2003
  }
1505
2004
  const scrollExtra = 0;
1506
2005
  const { queuedInitialLayout } = state;
1507
2006
  let { scroll: scrollState } = state;
1508
- const initialScroll = state.props.initialScroll;
1509
2007
  if (!queuedInitialLayout && initialScroll) {
1510
2008
  const updatedOffset = calculateOffsetWithOffsetPosition(
1511
2009
  state,
@@ -1517,16 +2015,15 @@ function calculateItemsInView(ctx, state, params = {}) {
1517
2015
  const scrollAdjustPad = -previousScrollAdjust - topPad;
1518
2016
  let scroll = scrollState + scrollExtra + scrollAdjustPad;
1519
2017
  if (scroll + scrollLength > totalSize) {
1520
- scroll = totalSize - scrollLength;
2018
+ scroll = Math.max(0, totalSize - scrollLength);
1521
2019
  }
1522
2020
  if (ENABLE_DEBUG_VIEW) {
1523
2021
  set$(ctx, "debugRawScroll", scrollState);
1524
2022
  set$(ctx, "debugComputedScroll", scroll);
1525
2023
  }
1526
- const scrollBuffer = state.props.scrollBuffer;
1527
2024
  let scrollBufferTop = scrollBuffer;
1528
2025
  let scrollBufferBottom = scrollBuffer;
1529
- if (speed > 0) {
2026
+ if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
1530
2027
  scrollBufferTop = scrollBuffer * 0.5;
1531
2028
  scrollBufferBottom = scrollBuffer * 1.5;
1532
2029
  } else {
@@ -1534,7 +2031,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1534
2031
  scrollBufferBottom = scrollBuffer * 0.5;
1535
2032
  }
1536
2033
  const scrollTopBuffered = scroll - scrollBufferTop;
1537
- const scrollBottom = scroll + scrollLength;
2034
+ const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
1538
2035
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1539
2036
  if (scrollForNextCalculateItemsInView) {
1540
2037
  const { top, bottom } = scrollForNextCalculateItemsInView;
@@ -1548,10 +2045,6 @@ function calculateItemsInView(ctx, state, params = {}) {
1548
2045
  let endNoBuffer = null;
1549
2046
  let endBuffered = null;
1550
2047
  let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1551
- if (minIndexSizeChanged !== void 0) {
1552
- loopStart = Math.min(minIndexSizeChanged, loopStart);
1553
- state.minIndexSizeChanged = void 0;
1554
- }
1555
2048
  for (let i = loopStart; i >= 0; i--) {
1556
2049
  const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
1557
2050
  const top = positions.get(id);
@@ -1634,7 +2127,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1634
2127
  if (dataChanged) {
1635
2128
  for (let i = 0; i < numContainers; i++) {
1636
2129
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1637
- if (!state.props.keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
2130
+ if (!keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1638
2131
  pendingRemoval.push(i);
1639
2132
  }
1640
2133
  }
@@ -1648,14 +2141,32 @@ function calculateItemsInView(ctx, state, params = {}) {
1648
2141
  needNewContainers.push(i);
1649
2142
  }
1650
2143
  }
2144
+ if (stickyIndicesArr.length > 0) {
2145
+ handleStickyActivation(
2146
+ ctx,
2147
+ state,
2148
+ stickyIndicesSet,
2149
+ stickyIndicesArr,
2150
+ scroll,
2151
+ needNewContainers,
2152
+ startBuffered,
2153
+ endBuffered
2154
+ );
2155
+ }
1651
2156
  if (needNewContainers.length > 0) {
2157
+ const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
2158
+ const itemType = getItemType(data[i], i);
2159
+ return itemType ? String(itemType) : "";
2160
+ }) : void 0;
1652
2161
  const availableContainers = findAvailableContainers(
1653
2162
  ctx,
1654
2163
  state,
1655
2164
  needNewContainers.length,
1656
2165
  startBuffered,
1657
2166
  endBuffered,
1658
- pendingRemoval
2167
+ pendingRemoval,
2168
+ requiredItemTypes,
2169
+ needNewContainers
1659
2170
  );
1660
2171
  for (let idx = 0; idx < needNewContainers.length; idx++) {
1661
2172
  const i = needNewContainers[idx];
@@ -1667,7 +2178,18 @@ function calculateItemsInView(ctx, state, params = {}) {
1667
2178
  }
1668
2179
  set$(ctx, `containerItemKey${containerIndex}`, id);
1669
2180
  set$(ctx, `containerItemData${containerIndex}`, data[i]);
2181
+ if (requiredItemTypes) {
2182
+ state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
2183
+ }
1670
2184
  containerItemKeys.add(id);
2185
+ if (stickyIndicesSet.has(i)) {
2186
+ set$(ctx, `containerSticky${containerIndex}`, true);
2187
+ const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2188
+ set$(ctx, `containerStickyOffset${containerIndex}`, createAnimatedValue(topPadding));
2189
+ state.stickyContainerPool.add(containerIndex);
2190
+ } else {
2191
+ state.stickyContainerPool.delete(containerIndex);
2192
+ }
1671
2193
  if (containerIndex >= numContainers2) {
1672
2194
  numContainers2 = containerIndex + 1;
1673
2195
  }
@@ -1680,12 +2202,22 @@ function calculateItemsInView(ctx, state, params = {}) {
1680
2202
  }
1681
2203
  }
1682
2204
  }
2205
+ if (stickyIndicesArr.length > 0) {
2206
+ handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, pendingRemoval);
2207
+ }
2208
+ let didChangePositions = false;
1683
2209
  for (let i = 0; i < numContainers; i++) {
1684
2210
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1685
2211
  if (pendingRemoval.includes(i)) {
1686
2212
  if (itemKey) {
1687
2213
  containerItemKeys.delete(itemKey);
1688
2214
  }
2215
+ state.containerItemTypes.delete(i);
2216
+ if (state.stickyContainerPool.has(i)) {
2217
+ set$(ctx, `containerSticky${i}`, false);
2218
+ set$(ctx, `containerStickyOffset${i}`, void 0);
2219
+ state.stickyContainerPool.delete(i);
2220
+ }
1689
2221
  set$(ctx, `containerItemKey${i}`, void 0);
1690
2222
  set$(ctx, `containerItemData${i}`, void 0);
1691
2223
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
@@ -1705,58 +2237,75 @@ function calculateItemsInView(ctx, state, params = {}) {
1705
2237
  const prevData = peek$(ctx, `containerItemData${i}`);
1706
2238
  if (position > POSITION_OUT_OF_VIEW && position !== prevPos) {
1707
2239
  set$(ctx, `containerPosition${i}`, position);
2240
+ didChangePositions = true;
1708
2241
  }
1709
2242
  if (column >= 0 && column !== prevColumn) {
1710
2243
  set$(ctx, `containerColumn${i}`, column);
1711
2244
  }
1712
- if (prevData !== item) {
2245
+ if (prevData !== item && (itemsAreEqual ? !itemsAreEqual(prevData, item, itemIndex, data) : true)) {
1713
2246
  set$(ctx, `containerItemData${i}`, data[itemIndex]);
1714
2247
  }
1715
2248
  }
1716
2249
  }
1717
2250
  }
1718
2251
  }
2252
+ if (didChangePositions) {
2253
+ set$(ctx, "lastPositionUpdate", Date.now());
2254
+ }
1719
2255
  if (!queuedInitialLayout && endBuffered !== null) {
1720
2256
  if (checkAllSizesKnown(state)) {
1721
2257
  setDidLayout(ctx, state);
1722
2258
  }
1723
2259
  }
1724
- if (state.viewabilityConfigCallbackPairs) {
1725
- updateViewableItems(
1726
- state,
1727
- ctx,
1728
- state.viewabilityConfigCallbackPairs,
1729
- scrollLength,
1730
- startNoBuffer,
1731
- endNoBuffer
1732
- );
2260
+ if (viewabilityConfigCallbackPairs) {
2261
+ updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
1733
2262
  }
1734
2263
  });
1735
2264
  }
1736
2265
 
1737
2266
  // src/core/doInitialAllocateContainers.ts
1738
2267
  function doInitialAllocateContainers(ctx, state) {
1739
- const { scrollLength } = state;
1740
- const data = state.props.data;
1741
- if (scrollLength > 0 && data.length > 0 && !peek$(ctx, "numContainers")) {
1742
- const averageItemSize = state.props.getEstimatedItemSize ? state.props.getEstimatedItemSize(0, data[0]) : state.props.estimatedItemSize;
1743
- const Extra = 1.5;
1744
- const numContainers = Math.ceil(
1745
- (scrollLength + state.props.scrollBuffer * 2) / averageItemSize * state.props.numColumns * Extra
1746
- );
2268
+ var _a;
2269
+ const {
2270
+ scrollLength,
2271
+ props: {
2272
+ data,
2273
+ getEstimatedItemSize,
2274
+ getFixedItemSize,
2275
+ getItemType,
2276
+ scrollBuffer,
2277
+ numColumns,
2278
+ estimatedItemSize
2279
+ }
2280
+ } = state;
2281
+ const hasContainers = peek$(ctx, "numContainers");
2282
+ if (scrollLength > 0 && data.length > 0 && !hasContainers) {
2283
+ let averageItemSize;
2284
+ const fn = getFixedItemSize || getEstimatedItemSize;
2285
+ if (fn) {
2286
+ let totalSize = 0;
2287
+ const num = Math.min(20, data.length);
2288
+ for (let i = 0; i < num; i++) {
2289
+ totalSize += fn(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "");
2290
+ }
2291
+ averageItemSize = totalSize / num;
2292
+ } else {
2293
+ averageItemSize = estimatedItemSize;
2294
+ }
2295
+ const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize * numColumns);
1747
2296
  for (let i = 0; i < numContainers; i++) {
1748
2297
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1749
2298
  set$(ctx, `containerColumn${i}`, -1);
1750
2299
  }
1751
2300
  set$(ctx, "numContainers", numContainers);
1752
2301
  set$(ctx, "numContainersPooled", numContainers * state.props.initialContainerPoolRatio);
1753
- if (!IsNewArchitecture) {
2302
+ if (state.lastLayout) {
1754
2303
  if (state.props.initialScroll) {
1755
2304
  requestAnimationFrame(() => {
1756
- calculateItemsInView(ctx, state);
2305
+ calculateItemsInView(ctx, state, { dataChanged: true });
1757
2306
  });
1758
2307
  } else {
1759
- calculateItemsInView(ctx, state);
2308
+ calculateItemsInView(ctx, state, { dataChanged: true });
1760
2309
  }
1761
2310
  }
1762
2311
  return true;
@@ -1776,16 +2325,18 @@ function doMaintainScrollAtEnd(ctx, state, animated) {
1776
2325
  }
1777
2326
  requestAnimationFrame(() => {
1778
2327
  var _a;
1779
- state.maintainingScrollAtEnd = true;
1780
- (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
1781
- animated
1782
- });
1783
- setTimeout(
1784
- () => {
1785
- state.maintainingScrollAtEnd = false;
1786
- },
1787
- 0
1788
- );
2328
+ if (state == null ? void 0 : state.isAtEnd) {
2329
+ state.maintainingScrollAtEnd = true;
2330
+ (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
2331
+ animated
2332
+ });
2333
+ setTimeout(
2334
+ () => {
2335
+ state.maintainingScrollAtEnd = false;
2336
+ },
2337
+ 0
2338
+ );
2339
+ }
1789
2340
  });
1790
2341
  return true;
1791
2342
  }
@@ -1822,44 +2373,57 @@ function checkAtTop(state) {
1822
2373
  // src/core/handleLayout.ts
1823
2374
  function handleLayout(ctx, state, layout, setCanRender) {
1824
2375
  const { maintainScrollAtEnd } = state.props;
1825
- const scrollLength = layout[state.props.horizontal ? "width" : "height"];
2376
+ const measuredLength = layout[state.props.horizontal ? "width" : "height"];
2377
+ const previousLength = state.scrollLength;
2378
+ const scrollLength = measuredLength > 0 ? measuredLength : previousLength;
1826
2379
  const otherAxisSize = layout[state.props.horizontal ? "height" : "width"];
1827
2380
  const needsCalculate = !state.lastLayout || scrollLength > state.scrollLength || state.lastLayout.x !== layout.x || state.lastLayout.y !== layout.y;
1828
2381
  state.lastLayout = layout;
1829
- const didChange = scrollLength !== state.scrollLength;
1830
2382
  const prevOtherAxisSize = state.otherAxisSize;
1831
- state.scrollLength = scrollLength;
1832
- state.otherAxisSize = otherAxisSize;
1833
- state.lastBatchingAction = Date.now();
1834
- state.scrollForNextCalculateItemsInView = void 0;
1835
- doInitialAllocateContainers(ctx, state);
1836
- if (needsCalculate) {
1837
- calculateItemsInView(ctx, state, { doMVCP: true });
1838
- }
1839
- if (didChange || otherAxisSize !== prevOtherAxisSize) {
1840
- set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
1841
- }
1842
- if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
1843
- doMaintainScrollAtEnd(ctx, state, false);
1844
- }
1845
- updateAlignItemsPaddingTop(ctx, state);
1846
- checkAtBottom(ctx, state);
1847
- checkAtTop(state);
1848
- if (state) {
1849
- state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
1850
- }
1851
- if (__DEV__ && scrollLength === 0) {
1852
- warnDevOnce(
1853
- "height0",
1854
- `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.`
1855
- );
2383
+ const didChange = scrollLength !== state.scrollLength || otherAxisSize !== prevOtherAxisSize;
2384
+ if (didChange) {
2385
+ state.scrollLength = scrollLength;
2386
+ state.otherAxisSize = otherAxisSize;
2387
+ state.lastBatchingAction = Date.now();
2388
+ state.scrollForNextCalculateItemsInView = void 0;
2389
+ if (scrollLength > 0) {
2390
+ doInitialAllocateContainers(ctx, state);
2391
+ }
2392
+ if (needsCalculate) {
2393
+ calculateItemsInView(ctx, state, { doMVCP: true });
2394
+ }
2395
+ if (didChange || otherAxisSize !== prevOtherAxisSize) {
2396
+ set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
2397
+ }
2398
+ if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
2399
+ doMaintainScrollAtEnd(ctx, state, false);
2400
+ }
2401
+ updateAlignItemsPaddingTop(ctx, state);
2402
+ checkAtBottom(ctx, state);
2403
+ checkAtTop(state);
2404
+ if (state) {
2405
+ state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2406
+ }
2407
+ if (__DEV__ && measuredLength === 0) {
2408
+ warnDevOnce(
2409
+ "height0",
2410
+ `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.`
2411
+ );
2412
+ }
2413
+ setCanRender(true);
1856
2414
  }
1857
- setCanRender(true);
1858
2415
  }
1859
2416
 
1860
2417
  // src/core/onScroll.ts
1861
2418
  function onScroll(ctx, state, event) {
1862
- var _a, _b, _c, _d, _e;
2419
+ var _a, _b, _c;
2420
+ const {
2421
+ scrollProcessingEnabled,
2422
+ props: { onScroll: onScrollProp }
2423
+ } = state;
2424
+ if (scrollProcessingEnabled === false) {
2425
+ return;
2426
+ }
1863
2427
  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
2428
  return;
1865
2429
  }
@@ -1872,16 +2436,25 @@ function onScroll(ctx, state, event) {
1872
2436
  }
1873
2437
  }
1874
2438
  state.scrollPending = newScroll;
1875
- updateScroll(ctx, state, newScroll);
1876
- (_e = (_d = state.props).onScroll) == null ? void 0 : _e.call(_d, event);
2439
+ {
2440
+ if (!state.onScrollRafScheduled) {
2441
+ state.onScrollRafScheduled = true;
2442
+ requestAnimationFrame(() => {
2443
+ state.onScrollRafScheduled = false;
2444
+ updateScroll(ctx, state, newScroll);
2445
+ });
2446
+ }
2447
+ }
2448
+ onScrollProp == null ? void 0 : onScrollProp(event);
1877
2449
  }
1878
2450
  function updateScroll(ctx, state, newScroll) {
1879
2451
  const scrollingTo = state.scrollingTo;
1880
2452
  state.hasScrolled = true;
1881
2453
  state.lastBatchingAction = Date.now();
1882
- const currentTime = performance.now();
2454
+ const currentTime = Date.now();
1883
2455
  if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
1884
- state.scrollHistory.push({ scroll: newScroll, time: currentTime });
2456
+ const adjust = state.scrollAdjustHandler.getAdjust();
2457
+ state.scrollHistory.push({ scroll: newScroll - adjust, time: currentTime });
1885
2458
  }
1886
2459
  if (state.scrollHistory.length > 5) {
1887
2460
  state.scrollHistory.shift();
@@ -1890,9 +2463,11 @@ function updateScroll(ctx, state, newScroll) {
1890
2463
  state.scrollPrevTime = state.scrollTime;
1891
2464
  state.scroll = newScroll;
1892
2465
  state.scrollTime = currentTime;
1893
- calculateItemsInView(ctx, state);
1894
- checkAtBottom(ctx, state);
1895
- checkAtTop(state);
2466
+ if (Math.abs(state.scroll - state.scrollPrev) > 2) {
2467
+ calculateItemsInView(ctx, state);
2468
+ checkAtBottom(ctx, state);
2469
+ checkAtTop(state);
2470
+ }
1896
2471
  }
1897
2472
 
1898
2473
  // src/core/ScrollAdjustHandler.ts
@@ -1915,13 +2490,19 @@ var ScrollAdjustHandler = class {
1915
2490
  setMounted() {
1916
2491
  this.mounted = true;
1917
2492
  }
2493
+ getAdjust() {
2494
+ return this.appliedAdjust;
2495
+ }
1918
2496
  };
1919
2497
 
1920
2498
  // src/core/updateItemSize.ts
1921
- function updateItemSizes(ctx, state, itemUpdates) {
1922
- var _a;
2499
+ function updateItemSize(ctx, state, itemKey, sizeObj) {
2500
+ var _a, _b;
1923
2501
  const {
2502
+ sizesKnown,
1924
2503
  props: {
2504
+ getFixedItemSize,
2505
+ getItemType,
1925
2506
  horizontal,
1926
2507
  maintainVisibleContentPosition,
1927
2508
  suggestEstimatedItemSize,
@@ -1931,47 +2512,60 @@ function updateItemSizes(ctx, state, itemUpdates) {
1931
2512
  }
1932
2513
  } = state;
1933
2514
  if (!data) return;
2515
+ if (getFixedItemSize) {
2516
+ const index2 = state.indexByKey.get(itemKey);
2517
+ if (index2 === void 0) {
2518
+ return;
2519
+ }
2520
+ const itemData = state.props.data[index2];
2521
+ if (itemData === void 0) {
2522
+ return;
2523
+ }
2524
+ const type = getItemType ? (_a = getItemType(itemData, index2)) != null ? _a : "" : "";
2525
+ const size2 = getFixedItemSize(index2, itemData, type);
2526
+ if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
2527
+ return;
2528
+ }
2529
+ }
1934
2530
  const containersDidLayout = peek$(ctx, "containersDidLayout");
1935
2531
  let needsRecalculate = !containersDidLayout;
1936
2532
  let shouldMaintainScrollAtEnd = false;
1937
2533
  let minIndexSizeChanged;
1938
2534
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
1939
- for (const { itemKey, sizeObj } of itemUpdates) {
1940
- const index = state.indexByKey.get(itemKey);
1941
- const prevSizeKnown = state.sizesKnown.get(itemKey);
1942
- const diff = updateOneItemSize(state, itemKey, sizeObj);
1943
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
1944
- if (diff !== 0) {
1945
- minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
1946
- if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
1947
- requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
1948
- }
1949
- const { startBuffered, endBuffered } = state;
1950
- needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
1951
- if (!needsRecalculate) {
1952
- const numContainers = ctx.values.get("numContainers");
1953
- for (let i = 0; i < numContainers; i++) {
1954
- if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
1955
- needsRecalculate = true;
1956
- break;
1957
- }
2535
+ const index = state.indexByKey.get(itemKey);
2536
+ const prevSizeKnown = state.sizesKnown.get(itemKey);
2537
+ const diff = updateOneItemSize(state, itemKey, sizeObj);
2538
+ const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2539
+ if (diff !== 0) {
2540
+ minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
2541
+ if (((_b = state.scrollingTo) == null ? void 0 : _b.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
2542
+ requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
2543
+ }
2544
+ const { startBuffered, endBuffered } = state;
2545
+ needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2546
+ if (!needsRecalculate) {
2547
+ const numContainers = ctx.values.get("numContainers");
2548
+ for (let i = 0; i < numContainers; i++) {
2549
+ if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
2550
+ needsRecalculate = true;
2551
+ break;
1958
2552
  }
1959
2553
  }
1960
- if (state.needsOtherAxisSize) {
1961
- const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
1962
- maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
1963
- }
1964
- if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
1965
- shouldMaintainScrollAtEnd = true;
1966
- }
1967
- onItemSizeChanged == null ? void 0 : onItemSizeChanged({
1968
- index,
1969
- itemData: state.props.data[index],
1970
- itemKey,
1971
- previous: size - diff,
1972
- size
1973
- });
1974
2554
  }
2555
+ if (state.needsOtherAxisSize) {
2556
+ const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
2557
+ maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
2558
+ }
2559
+ if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
2560
+ shouldMaintainScrollAtEnd = true;
2561
+ }
2562
+ onItemSizeChanged == null ? void 0 : onItemSizeChanged({
2563
+ index,
2564
+ itemData: state.props.data[index],
2565
+ itemKey,
2566
+ previous: size - diff,
2567
+ size
2568
+ });
1975
2569
  }
1976
2570
  if (minIndexSizeChanged !== void 0) {
1977
2571
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
@@ -2004,43 +2598,30 @@ function updateItemSizes(ctx, state, itemUpdates) {
2004
2598
  }
2005
2599
  }
2006
2600
  }
2007
- function updateItemSize(ctx, state, itemKey, sizeObj) {
2008
- const { queuedItemSizeUpdates, queuedItemSizeUpdatesWaiting } = state;
2009
- const containersDidLayout = peek$(ctx, "containersDidLayout");
2010
- if (!containersDidLayout || !queuedItemSizeUpdatesWaiting) {
2011
- updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
2012
- if (containersDidLayout) {
2013
- state.queuedItemSizeUpdatesWaiting = true;
2014
- requestAnimationFrame(() => {
2015
- state.queuedItemSizeUpdatesWaiting = false;
2016
- updateItemSizes(ctx, state, queuedItemSizeUpdates);
2017
- queuedItemSizeUpdates.length = 0;
2018
- });
2019
- }
2020
- } else {
2021
- queuedItemSizeUpdates.push({ itemKey, sizeObj });
2022
- }
2023
- }
2024
2601
  function updateOneItemSize(state, itemKey, sizeObj) {
2602
+ var _a;
2025
2603
  const {
2026
2604
  sizes,
2027
2605
  indexByKey,
2028
2606
  sizesKnown,
2029
2607
  averageSizes,
2030
- props: { data, horizontal }
2608
+ props: { data, horizontal, getEstimatedItemSize, getItemType, getFixedItemSize }
2031
2609
  } = state;
2032
2610
  if (!data) return 0;
2033
2611
  const index = indexByKey.get(itemKey);
2034
2612
  const prevSize = getItemSize(state, itemKey, index, data);
2035
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2613
+ const rawSize = horizontal ? sizeObj.width : sizeObj.height;
2614
+ const size = Math.round(rawSize) ;
2036
2615
  sizesKnown.set(itemKey, size);
2037
- const itemType = "";
2038
- let averages = averageSizes[itemType];
2039
- if (!averages) {
2040
- averages = averageSizes[itemType] = { avg: 0, num: 0 };
2616
+ if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
2617
+ const itemType = getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : "";
2618
+ let averages = averageSizes[itemType];
2619
+ if (!averages) {
2620
+ averages = averageSizes[itemType] = { avg: 0, num: 0 };
2621
+ }
2622
+ averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2623
+ averages.num++;
2041
2624
  }
2042
- averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2043
- averages.num++;
2044
2625
  if (!prevSize || Math.abs(prevSize - size) > 0.1) {
2045
2626
  sizes.set(itemKey, size);
2046
2627
  return size - prevSize;
@@ -2063,6 +2644,22 @@ var useCombinedRef = (...refs) => {
2063
2644
  return callback;
2064
2645
  };
2065
2646
 
2647
+ // src/platform/RefreshControl.tsx
2648
+ function RefreshControl(props) {
2649
+ return null;
2650
+ }
2651
+
2652
+ // src/platform/StyleSheet.tsx
2653
+ var StyleSheet = {
2654
+ create: (styles) => styles,
2655
+ flatten: (style) => style
2656
+ };
2657
+
2658
+ // src/platform/useStickyScrollHandler.ts
2659
+ function useStickyScrollHandler(stickyIndices, horizontal, ctx, onScroll2) {
2660
+ return onScroll2;
2661
+ }
2662
+
2066
2663
  // src/utils/createColumnWrapperStyle.ts
2067
2664
  function createColumnWrapperStyle(contentContainerStyle) {
2068
2665
  const { gap, columnGap, rowGap } = contentContainerStyle;
@@ -2078,87 +2675,201 @@ function createColumnWrapperStyle(contentContainerStyle) {
2078
2675
  }
2079
2676
  }
2080
2677
  function getRenderedItem(ctx, state, key) {
2678
+ var _a;
2081
2679
  if (!state) {
2082
2680
  return null;
2083
2681
  }
2084
2682
  const {
2085
2683
  indexByKey,
2086
- props: { data, renderItem: renderItem2 }
2684
+ props: { data, getItemType, renderItem }
2087
2685
  } = state;
2088
2686
  const index = indexByKey.get(key);
2089
2687
  if (index === void 0) {
2090
2688
  return null;
2091
2689
  }
2092
2690
  let renderedItem = null;
2093
- if (renderItem2) {
2691
+ if (renderItem && data[index]) {
2094
2692
  const itemProps = {
2693
+ data,
2095
2694
  extraData: peek$(ctx, "extraData"),
2096
2695
  index,
2097
- item: data[index]
2696
+ item: data[index],
2697
+ type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
2098
2698
  };
2099
- renderedItem = React3__default.createElement(renderItem2, itemProps);
2699
+ renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React4__default.createElement(renderItem, itemProps);
2100
2700
  }
2101
2701
  return { index, item: data[index], renderedItem };
2102
2702
  }
2703
+ function useThrottleDebounce(mode) {
2704
+ const timeoutRef = useRef(null);
2705
+ const lastCallTimeRef = useRef(0);
2706
+ const lastArgsRef = useRef(null);
2707
+ const clearTimeoutRef = () => {
2708
+ if (timeoutRef.current) {
2709
+ clearTimeout(timeoutRef.current);
2710
+ timeoutRef.current = null;
2711
+ }
2712
+ };
2713
+ const execute = useCallback(
2714
+ (callback, delay, ...args) => {
2715
+ {
2716
+ const now = Date.now();
2717
+ lastArgsRef.current = args;
2718
+ if (now - lastCallTimeRef.current >= delay) {
2719
+ lastCallTimeRef.current = now;
2720
+ callback(...args);
2721
+ clearTimeoutRef();
2722
+ } else {
2723
+ clearTimeoutRef();
2724
+ timeoutRef.current = setTimeout(
2725
+ () => {
2726
+ if (lastArgsRef.current) {
2727
+ lastCallTimeRef.current = Date.now();
2728
+ callback(...lastArgsRef.current);
2729
+ timeoutRef.current = null;
2730
+ lastArgsRef.current = null;
2731
+ }
2732
+ },
2733
+ delay - (now - lastCallTimeRef.current)
2734
+ );
2735
+ }
2736
+ }
2737
+ },
2738
+ [mode]
2739
+ );
2740
+ return execute;
2741
+ }
2742
+
2743
+ // src/utils/throttledOnScroll.ts
2744
+ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
2745
+ const throttle = useThrottleDebounce("throttle");
2746
+ return (event) => throttle(originalHandler, scrollEventThrottle, { nativeEvent: event.nativeEvent });
2747
+ }
2748
+
2749
+ // src/utils/updateAveragesOnDataChange.ts
2750
+ function updateAveragesOnDataChange(state, oldData, newData) {
2751
+ var _a;
2752
+ const {
2753
+ averageSizes,
2754
+ sizesKnown,
2755
+ indexByKey,
2756
+ props: { itemsAreEqual, getItemType, keyExtractor }
2757
+ } = state;
2758
+ if (!itemsAreEqual || !oldData.length || !newData.length) {
2759
+ for (const key in averageSizes) {
2760
+ delete averageSizes[key];
2761
+ }
2762
+ return;
2763
+ }
2764
+ const itemTypesToPreserve = {};
2765
+ const newDataLength = newData.length;
2766
+ const oldDataLength = oldData.length;
2767
+ for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
2768
+ const newItem = newData[newIndex];
2769
+ const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
2770
+ const oldIndex = indexByKey.get(id);
2771
+ if (oldIndex !== void 0 && oldIndex < oldDataLength) {
2772
+ const knownSize = sizesKnown.get(id);
2773
+ if (knownSize === void 0) continue;
2774
+ const oldItem = oldData[oldIndex];
2775
+ const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
2776
+ if (areEqual) {
2777
+ const itemType = getItemType ? (_a = getItemType(newItem, newIndex)) != null ? _a : "" : "";
2778
+ let typeData = itemTypesToPreserve[itemType];
2779
+ if (!typeData) {
2780
+ typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
2781
+ }
2782
+ typeData.totalSize += knownSize;
2783
+ typeData.count++;
2784
+ }
2785
+ }
2786
+ }
2787
+ for (const key in averageSizes) {
2788
+ delete averageSizes[key];
2789
+ }
2790
+ for (const itemType in itemTypesToPreserve) {
2791
+ const { totalSize, count } = itemTypesToPreserve[itemType];
2792
+ if (count > 0) {
2793
+ averageSizes[itemType] = {
2794
+ avg: totalSize / count,
2795
+ num: count
2796
+ };
2797
+ }
2798
+ }
2799
+ }
2103
2800
 
2104
2801
  // src/components/LegendList.tsx
2105
2802
  var DEFAULT_DRAW_DISTANCE = 250;
2106
2803
  var DEFAULT_ITEM_SIZE = 100;
2107
- var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
2108
- return /* @__PURE__ */ React3.createElement(StateProvider, null, /* @__PURE__ */ React3.createElement(LegendListInner, { ...props, ref: forwardedRef }));
2109
- });
2804
+ var LegendList = typedMemo(
2805
+ typedForwardRef(function LegendList2(props, forwardedRef) {
2806
+ const { children, data: dataProp, renderItem: renderItemProp, ...restProps } = props;
2807
+ const isChildrenMode = children !== void 0 && dataProp === void 0;
2808
+ const processedProps = isChildrenMode ? {
2809
+ ...restProps,
2810
+ data: (isArray(children) ? children : React4.Children.toArray(children)).flat(1),
2811
+ renderItem: ({ item }) => item
2812
+ } : {
2813
+ ...restProps,
2814
+ data: dataProp || [],
2815
+ renderItem: renderItemProp
2816
+ };
2817
+ return /* @__PURE__ */ React4.createElement(StateProvider, null, /* @__PURE__ */ React4.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
2818
+ })
2819
+ );
2110
2820
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
2111
- var _a;
2112
2821
  const {
2113
- data: dataProp = [],
2114
- initialScrollIndex: initialScrollIndexProp,
2115
- initialScrollOffset,
2116
- horizontal,
2117
- drawDistance = 250,
2118
- recycleItems = false,
2119
- onEndReachedThreshold = 0.5,
2120
- onStartReachedThreshold = 0.5,
2121
- maintainScrollAtEnd = false,
2122
- maintainScrollAtEndThreshold = 0.1,
2123
2822
  alignItemsAtEnd = false,
2124
- maintainVisibleContentPosition = false,
2125
- onScroll: onScrollProp,
2126
- onMomentumScrollEnd,
2127
- numColumns: numColumnsProp = 1,
2128
2823
  columnWrapperStyle,
2129
- keyExtractor: keyExtractorProp,
2130
- renderItem: renderItem2,
2131
- estimatedListSize,
2824
+ contentContainerStyle: contentContainerStyleProp,
2825
+ data: dataProp = [],
2826
+ drawDistance = 250,
2827
+ enableAverages = true,
2132
2828
  estimatedItemSize: estimatedItemSizeProp,
2829
+ estimatedListSize,
2830
+ extraData,
2133
2831
  getEstimatedItemSize,
2134
- suggestEstimatedItemSize,
2135
- ListHeaderComponent,
2832
+ getFixedItemSize,
2833
+ getItemType,
2834
+ horizontal,
2835
+ initialContainerPoolRatio = 2,
2836
+ initialScrollIndex: initialScrollIndexProp,
2837
+ initialScrollOffset: initialScrollOffsetProp,
2838
+ itemsAreEqual,
2839
+ keyExtractor: keyExtractorProp,
2136
2840
  ListEmptyComponent,
2841
+ ListHeaderComponent,
2842
+ maintainScrollAtEnd = false,
2843
+ maintainScrollAtEndThreshold = 0.1,
2844
+ maintainVisibleContentPosition = true,
2845
+ numColumns: numColumnsProp = 1,
2846
+ onEndReached,
2847
+ onEndReachedThreshold = 0.5,
2137
2848
  onItemSizeChanged,
2138
- refScrollView,
2139
- waitForInitialLayout = true,
2140
- extraData,
2141
- contentContainerStyle: contentContainerStyleProp,
2142
- style: styleProp,
2143
2849
  onLayout: onLayoutProp,
2850
+ onLoad,
2851
+ onMomentumScrollEnd,
2144
2852
  onRefresh,
2145
- refreshing,
2853
+ onScroll: onScrollProp,
2854
+ onStartReached,
2855
+ onStartReachedThreshold = 0.5,
2146
2856
  progressViewOffset,
2857
+ recycleItems = false,
2147
2858
  refreshControl,
2148
- initialContainerPoolRatio = 2,
2149
- viewabilityConfig,
2150
- viewabilityConfigCallbackPairs,
2859
+ refreshing,
2860
+ refScrollView,
2861
+ renderItem,
2862
+ scrollEventThrottle,
2151
2863
  snapToIndices,
2152
- onViewableItemsChanged,
2153
- onStartReached,
2154
- onEndReached,
2155
- onLoad,
2864
+ stickyIndices,
2865
+ style: styleProp,
2866
+ suggestEstimatedItemSize,
2867
+ waitForInitialLayout = true,
2156
2868
  ...rest
2157
2869
  } = props;
2158
2870
  const [renderNum, setRenderNum] = useState(0);
2159
- const initialScroll = typeof initialScrollIndexProp === "number" ? { index: initialScrollIndexProp } : initialScrollIndexProp;
2160
- const initialScrollIndex = initialScroll == null ? void 0 : initialScroll.index;
2161
- const [canRender, setCanRender] = React3.useState(!IsNewArchitecture);
2871
+ const initialScroll = initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
2872
+ const [canRender, setCanRender] = React4.useState(!IsNewArchitecture);
2162
2873
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
2163
2874
  const style = { ...StyleSheet.flatten(styleProp) };
2164
2875
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
@@ -2172,68 +2883,82 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2172
2883
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
2173
2884
  const refState = useRef();
2174
2885
  if (!refState.current) {
2175
- const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : Dimensions.get("window"))[horizontal ? "width" : "height"];
2176
- refState.current = {
2177
- averageSizes: {},
2178
- columns: /* @__PURE__ */ new Map(),
2179
- containerItemKeys: /* @__PURE__ */ new Set(),
2180
- enableScrollForNextCalculateItemsInView: true,
2181
- endBuffered: -1,
2182
- endNoBuffer: -1,
2183
- endReachedBlockedByTimer: false,
2184
- firstFullyOnScreenIndex: -1,
2185
- idCache: /* @__PURE__ */ new Map(),
2186
- idsInView: [],
2187
- indexByKey: /* @__PURE__ */ new Map(),
2188
- initialScroll,
2189
- isAtEnd: false,
2190
- isAtStart: false,
2191
- isEndReached: false,
2192
- isStartReached: false,
2193
- lastBatchingAction: Date.now(),
2194
- lastLayout: void 0,
2195
- loadStartTime: Date.now(),
2196
- minIndexSizeChanged: 0,
2197
- nativeMarginTop: 0,
2198
- pendingAdjust: 0,
2199
- positions: /* @__PURE__ */ new Map(),
2200
- props: {},
2201
- queuedCalculateItemsInView: 0,
2202
- queuedItemSizeUpdates: [],
2203
- refScroller: void 0,
2204
- scroll: 0,
2205
- scrollAdjustHandler: new ScrollAdjustHandler(ctx),
2206
- scrollForNextCalculateItemsInView: void 0,
2207
- scrollHistory: [],
2208
- scrollLength: initialScrollLength,
2209
- scrollPending: 0,
2210
- scrollPrev: 0,
2211
- scrollPrevTime: 0,
2212
- scrollTime: 0,
2213
- sizes: /* @__PURE__ */ new Map(),
2214
- sizesKnown: /* @__PURE__ */ new Map(),
2215
- startBuffered: -1,
2216
- startNoBuffer: -1,
2217
- startReachedBlockedByTimer: false,
2218
- timeoutSizeMessage: 0,
2219
- timeouts: /* @__PURE__ */ new Set(),
2220
- totalSize: 0,
2221
- viewabilityConfigCallbackPairs: void 0
2222
- };
2223
- set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2224
- set$(ctx, "extraData", extraData);
2886
+ if (!ctx.internalState) {
2887
+ const initialScrollLength = (estimatedListSize != null ? estimatedListSize : { height: 0, width: 0 } )[horizontal ? "width" : "height"];
2888
+ ctx.internalState = {
2889
+ activeStickyIndex: void 0,
2890
+ averageSizes: {},
2891
+ columns: /* @__PURE__ */ new Map(),
2892
+ containerItemKeys: /* @__PURE__ */ new Set(),
2893
+ containerItemTypes: /* @__PURE__ */ new Map(),
2894
+ enableScrollForNextCalculateItemsInView: true,
2895
+ endBuffered: -1,
2896
+ endNoBuffer: -1,
2897
+ endReachedBlockedByTimer: false,
2898
+ firstFullyOnScreenIndex: -1,
2899
+ idCache: /* @__PURE__ */ new Map(),
2900
+ idsInView: [],
2901
+ indexByKey: /* @__PURE__ */ new Map(),
2902
+ initialScroll,
2903
+ isAtEnd: false,
2904
+ isAtStart: false,
2905
+ isEndReached: false,
2906
+ isStartReached: false,
2907
+ lastBatchingAction: Date.now(),
2908
+ lastLayout: void 0,
2909
+ loadStartTime: Date.now(),
2910
+ minIndexSizeChanged: 0,
2911
+ nativeMarginTop: 0,
2912
+ positions: /* @__PURE__ */ new Map(),
2913
+ props: {},
2914
+ queuedCalculateItemsInView: 0,
2915
+ refScroller: void 0,
2916
+ scroll: 0,
2917
+ scrollAdjustHandler: new ScrollAdjustHandler(ctx),
2918
+ scrollForNextCalculateItemsInView: void 0,
2919
+ scrollHistory: [],
2920
+ scrollLength: initialScrollLength,
2921
+ scrollPending: 0,
2922
+ scrollPrev: 0,
2923
+ scrollPrevTime: 0,
2924
+ scrollProcessingEnabled: true,
2925
+ scrollTime: 0,
2926
+ sizes: /* @__PURE__ */ new Map(),
2927
+ sizesKnown: /* @__PURE__ */ new Map(),
2928
+ startBuffered: -1,
2929
+ startNoBuffer: -1,
2930
+ startReachedBlockedByTimer: false,
2931
+ stickyContainerPool: /* @__PURE__ */ new Set(),
2932
+ stickyContainers: /* @__PURE__ */ new Map(),
2933
+ timeoutSizeMessage: 0,
2934
+ timeouts: /* @__PURE__ */ new Set(),
2935
+ totalSize: 0,
2936
+ viewabilityConfigCallbackPairs: void 0
2937
+ };
2938
+ set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2939
+ set$(ctx, "extraData", extraData);
2940
+ }
2941
+ refState.current = ctx.internalState;
2225
2942
  }
2226
2943
  const state = refState.current;
2227
2944
  const isFirst = !state.props.renderItem;
2228
2945
  const didDataChange = state.props.data !== dataProp;
2946
+ const throttleScrollFn = (
2947
+ // @ts-expect-error TODO Fix this
2948
+ scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp
2949
+ );
2229
2950
  state.props = {
2230
2951
  alignItemsAtEnd,
2231
2952
  data: dataProp,
2953
+ enableAverages,
2232
2954
  estimatedItemSize,
2233
2955
  getEstimatedItemSize,
2956
+ getFixedItemSize,
2957
+ getItemType,
2234
2958
  horizontal: !!horizontal,
2235
2959
  initialContainerPoolRatio,
2236
2960
  initialScroll,
2961
+ itemsAreEqual,
2237
2962
  keyExtractor,
2238
2963
  maintainScrollAtEnd,
2239
2964
  maintainScrollAtEndThreshold,
@@ -2243,12 +2968,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2243
2968
  onEndReachedThreshold,
2244
2969
  onItemSizeChanged,
2245
2970
  onLoad,
2246
- onScroll: onScrollProp,
2971
+ onScroll: throttleScrollFn,
2247
2972
  onStartReached,
2248
2973
  onStartReachedThreshold,
2249
- renderItem: renderItem2,
2974
+ recycleItems: !!recycleItems,
2975
+ renderItem,
2250
2976
  scrollBuffer,
2251
2977
  snapToIndices,
2978
+ stickyIndicesArr: stickyIndices != null ? stickyIndices : [],
2979
+ stickyIndicesSet: useMemo(() => new Set(stickyIndices != null ? stickyIndices : []), [stickyIndices == null ? void 0 : stickyIndices.join(",")]),
2252
2980
  stylePaddingBottom: stylePaddingBottomState,
2253
2981
  stylePaddingTop: stylePaddingTopState,
2254
2982
  suggestEstimatedItemSize: !!suggestEstimatedItemSize
@@ -2257,6 +2985,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2257
2985
  const checkResetContainers = (isFirst2) => {
2258
2986
  const state2 = refState.current;
2259
2987
  if (state2) {
2988
+ if (!isFirst2 && state2.props.data !== dataProp) {
2989
+ updateAveragesOnDataChange(state2, state2.props.data, dataProp);
2990
+ }
2260
2991
  state2.props.data = dataProp;
2261
2992
  if (!isFirst2) {
2262
2993
  calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
@@ -2298,53 +3029,39 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2298
3029
  updateAllPositions(ctx, state);
2299
3030
  }
2300
3031
  const initialContentOffset = useMemo(() => {
2301
- const initialContentOffset2 = initialScrollOffset || calculateOffsetForIndex(ctx, state, initialScrollIndex);
2302
- refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
2303
- if (initialContentOffset2 > 0) {
2304
- scrollTo(state, { animated: false, index: initialScrollIndex, offset: initialContentOffset2 });
3032
+ if (initialScroll) {
3033
+ const { index, viewOffset } = initialScroll;
3034
+ let initialContentOffset2 = viewOffset || 0;
3035
+ if (index !== void 0) {
3036
+ initialContentOffset2 += calculateOffsetForIndex(ctx, state, index);
3037
+ }
3038
+ refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
3039
+ if (initialContentOffset2 > 0) {
3040
+ scrollTo(state, { animated: false, index, offset: initialContentOffset2 });
3041
+ }
3042
+ return initialContentOffset2;
2305
3043
  }
2306
- return initialContentOffset2;
3044
+ return 0;
2307
3045
  }, [renderNum]);
2308
3046
  if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
2309
- refState.current.lastBatchingAction = Date.now();
3047
+ state.lastBatchingAction = Date.now();
2310
3048
  if (!keyExtractorProp && !isFirst && didDataChange) {
2311
3049
  __DEV__ && warnDevOnce(
2312
3050
  "keyExtractor",
2313
3051
  "Changing data without a keyExtractor can cause slow performance and resetting scroll. If your list data can change you should use a keyExtractor with a unique id for best performance and behavior."
2314
3052
  );
2315
- refState.current.sizes.clear();
2316
- refState.current.positions.clear();
3053
+ state.sizes.clear();
3054
+ state.positions.clear();
2317
3055
  }
2318
3056
  }
2319
- useLayoutEffect(() => {
2320
- if (IsNewArchitecture) {
2321
- let measured;
2322
- refScroller.current.measure((x, y, width, height) => {
2323
- measured = { height, width, x, y };
2324
- });
2325
- if (measured) {
2326
- const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
2327
- if (size) {
2328
- handleLayout(ctx, state, measured, setCanRender);
2329
- }
2330
- }
2331
- }
2332
- if (!isFirst) {
2333
- calculateItemsInView(ctx, state, { doMVCP: true });
2334
- }
2335
- }, [dataProp]);
2336
3057
  const onLayoutHeader = useCallback((rect, fromLayoutEffect) => {
2337
3058
  const size = rect[horizontal ? "width" : "height"];
2338
3059
  set$(ctx, "headerSize", size);
2339
- if (initialScroll) {
2340
- if (IsNewArchitecture && Platform.OS !== "android") {
3060
+ if ((initialScroll == null ? void 0 : initialScroll.index) !== void 0) {
3061
+ {
2341
3062
  if (fromLayoutEffect) {
2342
3063
  setRenderNum((v) => v + 1);
2343
3064
  }
2344
- } else {
2345
- setTimeout(() => {
2346
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
2347
- }, 17);
2348
3065
  }
2349
3066
  }
2350
3067
  }, []);
@@ -2354,7 +3071,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2354
3071
  }
2355
3072
  }, [snapToIndices]);
2356
3073
  useLayoutEffect(() => {
2357
- const didAllocateContainers = doInitialAllocateContainersCallback();
3074
+ const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainersCallback();
2358
3075
  if (!didAllocateContainers) {
2359
3076
  checkResetContainers(
2360
3077
  /*isFirst*/
@@ -2365,6 +3082,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2365
3082
  useLayoutEffect(() => {
2366
3083
  set$(ctx, "extraData", extraData);
2367
3084
  }, [extraData]);
3085
+ const { onLayout } = useSyncLayout({
3086
+ onLayout: onLayoutProp,
3087
+ onLayoutChange: useCallback(
3088
+ (rectangle) => {
3089
+ handleLayout(ctx, state, rectangle, setCanRender);
3090
+ },
3091
+ [ctx, state, setCanRender]
3092
+ ),
3093
+ ref: refScroller
3094
+ });
2368
3095
  useLayoutEffect(initializeStateVars, [
2369
3096
  memoizedLastItemKeys.join(","),
2370
3097
  numColumnsProp,
@@ -2374,27 +3101,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2374
3101
  const doInitialAllocateContainersCallback = () => {
2375
3102
  return doInitialAllocateContainers(ctx, state);
2376
3103
  };
2377
- useEffect(() => {
2378
- const viewability = setupViewability({
2379
- onViewableItemsChanged,
2380
- viewabilityConfig,
2381
- viewabilityConfigCallbackPairs
2382
- });
2383
- state.viewabilityConfigCallbackPairs = viewability;
2384
- state.enableScrollForNextCalculateItemsInView = !viewability;
2385
- }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
2386
- if (!IsNewArchitecture) {
2387
- useInit(() => {
2388
- doInitialAllocateContainersCallback();
2389
- });
2390
- }
2391
- const onLayout = useCallback((event) => {
2392
- const layout = event.nativeEvent.layout;
2393
- handleLayout(ctx, state, layout, setCanRender);
2394
- if (onLayoutProp) {
2395
- onLayoutProp(event);
2396
- }
2397
- }, []);
2398
3104
  useImperativeHandle(forwardedRef, () => {
2399
3105
  const scrollIndexIntoView = (options) => {
2400
3106
  const state2 = refState.current;
@@ -2412,18 +3118,23 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2412
3118
  }
2413
3119
  };
2414
3120
  return {
2415
- flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
3121
+ flashScrollIndicators: () => {
3122
+ var _a, _b;
3123
+ return (_b = (_a = refScroller.current) == null ? void 0 : _a.flashScrollIndicators) == null ? void 0 : _b.call(_a);
3124
+ },
2416
3125
  getNativeScrollRef: () => refScroller.current,
2417
- getScrollableNode: () => refScroller.current.getScrollableNode(),
2418
- getScrollResponder: () => refScroller.current.getScrollResponder(),
3126
+ getScrollableNode: () => refScroller.current,
3127
+ getScrollResponder: () => refScroller.current,
2419
3128
  getState: () => {
2420
3129
  const state2 = refState.current;
2421
3130
  return state2 ? {
2422
3131
  contentLength: state2.totalSize,
3132
+ data: state2.props.data,
2423
3133
  end: state2.endNoBuffer,
2424
3134
  endBuffered: state2.endBuffered,
2425
3135
  isAtEnd: state2.isAtEnd,
2426
3136
  isAtStart: state2.isAtStart,
3137
+ positionAtIndex: (index) => state2.positions.get(getId(state2, index)),
2427
3138
  positions: state2.positions,
2428
3139
  scroll: state2.scroll,
2429
3140
  scrollLength: state2.scrollLength,
@@ -2450,7 +3161,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2450
3161
  const footerSize = peek$(ctx, "footerSize") || 0;
2451
3162
  scrollToIndex(ctx, state, {
2452
3163
  index,
2453
- viewOffset: -paddingBottom - footerSize,
3164
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
2454
3165
  viewPosition: 1,
2455
3166
  ...options
2456
3167
  });
@@ -2465,13 +3176,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2465
3176
  }
2466
3177
  },
2467
3178
  scrollToOffset: (params) => scrollTo(state, params),
3179
+ setScrollProcessingEnabled: (enabled) => {
3180
+ refState.current.scrollProcessingEnabled = enabled;
3181
+ },
2468
3182
  setVisibleContentAnchorOffset: (value) => {
2469
3183
  const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2470
3184
  set$(ctx, "scrollAdjustUserOffset", val);
2471
3185
  }
2472
3186
  };
2473
3187
  }, []);
2474
- if (Platform.OS === "web") {
3188
+ {
2475
3189
  useEffect(() => {
2476
3190
  if (initialContentOffset) {
2477
3191
  scrollTo(state, { animated: false, offset: initialContentOffset });
@@ -2486,7 +3200,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2486
3200
  }),
2487
3201
  []
2488
3202
  );
2489
- return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
3203
+ const onScrollHandler = useStickyScrollHandler(stickyIndices, horizontal, ctx, fns.onScroll);
3204
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(
2490
3205
  ListComponent,
2491
3206
  {
2492
3207
  ...rest,
@@ -2502,18 +3217,20 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2502
3217
  onLayout,
2503
3218
  onLayoutHeader,
2504
3219
  onMomentumScrollEnd: (event) => {
2505
- requestAnimationFrame(() => {
2506
- finishScrollTo(refState.current);
2507
- });
3220
+ {
3221
+ requestAnimationFrame(() => {
3222
+ finishScrollTo(refState.current);
3223
+ });
3224
+ }
2508
3225
  if (onMomentumScrollEnd) {
2509
3226
  onMomentumScrollEnd(event);
2510
3227
  }
2511
3228
  },
2512
- onScroll: fns.onScroll,
3229
+ onScroll: onScrollHandler,
2513
3230
  recycleItems,
2514
- refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControl, {
3231
+ refreshControl: refreshControl ? stylePaddingTopState > 0 ? React4.cloneElement(refreshControl, {
2515
3232
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
2516
- }) : refreshControl : onRefresh && /* @__PURE__ */ React3.createElement(
3233
+ }) : refreshControl : onRefresh && /* @__PURE__ */ React4.createElement(
2517
3234
  RefreshControl,
2518
3235
  {
2519
3236
  onRefresh,
@@ -2522,27 +3239,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2522
3239
  }
2523
3240
  ),
2524
3241
  refScrollView: combinedRef,
2525
- scrollAdjustHandler: (_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler,
2526
- scrollEventThrottle: Platform.OS === "web" ? 16 : void 0,
3242
+ scrollAdjustHandler: state.scrollAdjustHandler,
2527
3243
  snapToIndices,
3244
+ stickyIndices,
2528
3245
  style,
2529
3246
  updateItemSize: fns.updateItemSize,
2530
3247
  waitForInitialLayout
2531
3248
  }
2532
- ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3.createElement(DebugView, { state: refState.current }));
2533
- });
2534
-
2535
- // src/components/LazyLegendList.tsx
2536
- var typedForwardRef2 = forwardRef;
2537
- var renderItem = ({ item }) => item;
2538
- var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedRef) {
2539
- const { LegendList: LegendListProp, children, ...rest } = props;
2540
- const LegendListComponent = LegendListProp != null ? LegendListProp : LegendList;
2541
- const data = (isArray(children) ? children : React3.Children.toArray(children)).flat(1);
2542
- return (
2543
- // @ts-expect-error TODO: Fix this type
2544
- /* @__PURE__ */ React3.createElement(LegendListComponent, { ...rest, data, ref: forwardedRef, renderItem })
2545
- );
3249
+ ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React4.createElement(DebugView, { state: refState.current }));
2546
3250
  });
2547
3251
 
2548
- export { LazyLegendList, LegendList, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useViewability, useViewabilityAmount };
3252
+ export { LegendList, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout2 as useSyncLayout, useViewability, useViewabilityAmount };