@legendapp/list 3.0.0-beta.31 → 3.0.0-beta.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/.DS_Store +0 -0
  2. package/README.md +7 -1
  3. package/animated.d.ts +600 -6
  4. package/animated.js +2 -2
  5. package/animated.mjs +1 -1
  6. package/index.d.ts +462 -109
  7. package/index.js +290 -147
  8. package/index.mjs +290 -147
  9. package/index.native.js +245 -122
  10. package/index.native.mjs +246 -123
  11. package/keyboard-controller.d.ts +611 -6
  12. package/keyboard-controller.js +2 -2
  13. package/keyboard-controller.mjs +1 -1
  14. package/keyboard.d.ts +204 -8
  15. package/keyboard.js +66 -52
  16. package/keyboard.mjs +69 -54
  17. package/{index.d.mts → list-react-native.d.ts} +103 -33
  18. package/list-react-native.js +4234 -0
  19. package/list-react-native.mjs +4204 -0
  20. package/{index.native.d.mts → list-react.d.ts} +363 -41
  21. package/list-react.js +4426 -0
  22. package/list-react.mjs +4396 -0
  23. package/package.json +52 -1
  24. package/reanimated.d.ts +595 -7
  25. package/reanimated.js +156 -11
  26. package/reanimated.mjs +153 -8
  27. package/section-list.d.ts +610 -14
  28. package/section-list.js +6 -6
  29. package/section-list.mjs +1 -1
  30. package/animated.d.mts +0 -9
  31. package/animated.native.d.mts +0 -9
  32. package/animated.native.d.ts +0 -9
  33. package/animated.native.js +0 -9
  34. package/animated.native.mjs +0 -7
  35. package/index.native.d.ts +0 -810
  36. package/keyboard-controller.d.mts +0 -12
  37. package/keyboard-controller.native.d.mts +0 -12
  38. package/keyboard-controller.native.d.ts +0 -12
  39. package/keyboard-controller.native.js +0 -69
  40. package/keyboard-controller.native.mjs +0 -48
  41. package/keyboard.d.mts +0 -13
  42. package/keyboard.native.d.mts +0 -13
  43. package/keyboard.native.d.ts +0 -13
  44. package/keyboard.native.js +0 -399
  45. package/keyboard.native.mjs +0 -377
  46. package/reanimated.d.mts +0 -18
  47. package/reanimated.native.d.mts +0 -18
  48. package/reanimated.native.d.ts +0 -18
  49. package/reanimated.native.js +0 -89
  50. package/reanimated.native.mjs +0 -65
  51. package/section-list.d.mts +0 -112
  52. package/section-list.native.d.mts +0 -112
  53. package/section-list.native.d.ts +0 -112
  54. package/section-list.native.js +0 -293
  55. package/section-list.native.mjs +0 -271
package/list-react.js ADDED
@@ -0,0 +1,4426 @@
1
+ 'use strict';
2
+
3
+ var React3 = require('react');
4
+ var shim = require('use-sync-external-store/shim');
5
+ var reactDom = require('react-dom');
6
+
7
+ function _interopNamespace(e) {
8
+ if (e && e.__esModule) return e;
9
+ var n = Object.create(null);
10
+ if (e) {
11
+ Object.keys(e).forEach(function (k) {
12
+ if (k !== 'default') {
13
+ var d = Object.getOwnPropertyDescriptor(e, k);
14
+ Object.defineProperty(n, k, d.get ? d : {
15
+ enumerable: true,
16
+ get: function () { return e[k]; }
17
+ });
18
+ }
19
+ });
20
+ }
21
+ n.default = e;
22
+ return Object.freeze(n);
23
+ }
24
+
25
+ var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
26
+
27
+ // src/components/LegendList.tsx
28
+ React3.forwardRef(function AnimatedView2(props, ref) {
29
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref, ...props });
30
+ });
31
+ var View = React3.forwardRef(function View2(props, ref) {
32
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref, ...props });
33
+ });
34
+ var Text = View;
35
+
36
+ // src/state/getContentInsetEnd.ts
37
+ function getContentInsetEnd(state) {
38
+ var _a3;
39
+ const { props } = state;
40
+ const horizontal = props.horizontal;
41
+ const contentInset = props.contentInset;
42
+ const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
43
+ const overrideInset = (_a3 = state.contentInsetOverride) != null ? _a3 : void 0;
44
+ if (overrideInset) {
45
+ const mergedInset = { bottom: 0, right: 0, ...baseInset, ...overrideInset };
46
+ return (horizontal ? mergedInset.right : mergedInset.bottom) || 0;
47
+ }
48
+ if (baseInset) {
49
+ return (horizontal ? baseInset.right : baseInset.bottom) || 0;
50
+ }
51
+ return 0;
52
+ }
53
+
54
+ // src/state/getContentSize.ts
55
+ function getContentSize(ctx) {
56
+ var _a3;
57
+ const { values, state } = ctx;
58
+ const stylePaddingTop = values.get("stylePaddingTop") || 0;
59
+ const stylePaddingBottom = state.props.stylePaddingBottom || 0;
60
+ const headerSize = values.get("headerSize") || 0;
61
+ const footerSize = values.get("footerSize") || 0;
62
+ const contentInsetBottom = getContentInsetEnd(state);
63
+ const totalSize = (_a3 = state.pendingTotalSize) != null ? _a3 : values.get("totalSize");
64
+ return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom + (contentInsetBottom || 0);
65
+ }
66
+
67
+ // src/platform/Animated.tsx
68
+ var createAnimatedValue = (value) => value;
69
+
70
+ // src/state/state.tsx
71
+ var ContextState = React3__namespace.createContext(null);
72
+ var contextNum = 0;
73
+ function StateProvider({ children }) {
74
+ const [value] = React3__namespace.useState(() => ({
75
+ animatedScrollY: createAnimatedValue(0),
76
+ columnWrapperStyle: void 0,
77
+ contextNum: contextNum++,
78
+ listeners: /* @__PURE__ */ new Map(),
79
+ mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
80
+ mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
81
+ mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
82
+ mapViewabilityConfigStates: /* @__PURE__ */ new Map(),
83
+ mapViewabilityValues: /* @__PURE__ */ new Map(),
84
+ positionListeners: /* @__PURE__ */ new Map(),
85
+ state: void 0,
86
+ values: /* @__PURE__ */ new Map([
87
+ ["stylePaddingTop", 0],
88
+ ["headerSize", 0],
89
+ ["numContainers", 0],
90
+ ["activeStickyIndex", -1],
91
+ ["totalSize", 0],
92
+ ["scrollAdjustPending", 0]
93
+ ]),
94
+ viewRefs: /* @__PURE__ */ new Map()
95
+ }));
96
+ return /* @__PURE__ */ React3__namespace.createElement(ContextState.Provider, { value }, children);
97
+ }
98
+ function useStateContext() {
99
+ return React3__namespace.useContext(ContextState);
100
+ }
101
+ function createSelectorFunctionsArr(ctx, signalNames) {
102
+ let lastValues = [];
103
+ let lastSignalValues = [];
104
+ return {
105
+ get: () => {
106
+ const currentValues = [];
107
+ let hasChanged = false;
108
+ for (let i = 0; i < signalNames.length; i++) {
109
+ const value = peek$(ctx, signalNames[i]);
110
+ currentValues.push(value);
111
+ if (value !== lastSignalValues[i]) {
112
+ hasChanged = true;
113
+ }
114
+ }
115
+ lastSignalValues = currentValues;
116
+ if (hasChanged) {
117
+ lastValues = currentValues;
118
+ }
119
+ return lastValues;
120
+ },
121
+ subscribe: (cb) => {
122
+ const listeners = [];
123
+ for (const signalName of signalNames) {
124
+ listeners.push(listen$(ctx, signalName, cb));
125
+ }
126
+ return () => {
127
+ for (const listener of listeners) {
128
+ listener();
129
+ }
130
+ };
131
+ }
132
+ };
133
+ }
134
+ function listen$(ctx, signalName, cb) {
135
+ const { listeners } = ctx;
136
+ let setListeners = listeners.get(signalName);
137
+ if (!setListeners) {
138
+ setListeners = /* @__PURE__ */ new Set();
139
+ listeners.set(signalName, setListeners);
140
+ }
141
+ setListeners.add(cb);
142
+ return () => setListeners.delete(cb);
143
+ }
144
+ function peek$(ctx, signalName) {
145
+ const { values } = ctx;
146
+ return values.get(signalName);
147
+ }
148
+ function set$(ctx, signalName, value) {
149
+ const { listeners, values } = ctx;
150
+ if (values.get(signalName) !== value) {
151
+ values.set(signalName, value);
152
+ const setListeners = listeners.get(signalName);
153
+ if (setListeners) {
154
+ for (const listener of setListeners) {
155
+ listener(value);
156
+ }
157
+ }
158
+ }
159
+ }
160
+ function listenPosition$(ctx, key, cb) {
161
+ const { positionListeners } = ctx;
162
+ let setListeners = positionListeners.get(key);
163
+ if (!setListeners) {
164
+ setListeners = /* @__PURE__ */ new Set();
165
+ positionListeners.set(key, setListeners);
166
+ }
167
+ setListeners.add(cb);
168
+ return () => setListeners.delete(cb);
169
+ }
170
+ function notifyPosition$(ctx, key, value) {
171
+ const { positionListeners } = ctx;
172
+ const setListeners = positionListeners.get(key);
173
+ if (setListeners) {
174
+ for (const listener of setListeners) {
175
+ listener(value);
176
+ }
177
+ }
178
+ }
179
+ function useArr$(signalNames) {
180
+ const ctx = React3__namespace.useContext(ContextState);
181
+ const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
182
+ const value = shim.useSyncExternalStore(subscribe, get);
183
+ return value;
184
+ }
185
+ function useSelector$(signalName, selector) {
186
+ const ctx = React3__namespace.useContext(ContextState);
187
+ const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
188
+ const value = shim.useSyncExternalStore(subscribe, () => selector(get()[0]));
189
+ return value;
190
+ }
191
+
192
+ // src/components/DebugView.tsx
193
+ var DebugRow = ({ children }) => {
194
+ return /* @__PURE__ */ React3__namespace.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
195
+ };
196
+ React3__namespace.memo(function DebugView2({ state }) {
197
+ const ctx = useStateContext();
198
+ const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
199
+ "totalSize",
200
+ "scrollAdjust",
201
+ "debugRawScroll",
202
+ "debugComputedScroll",
203
+ "numContainers",
204
+ "numContainersPooled"
205
+ ]);
206
+ const contentSize = getContentSize(ctx);
207
+ const [, forceUpdate] = React3.useReducer((x) => x + 1, 0);
208
+ useInterval(() => {
209
+ forceUpdate();
210
+ }, 100);
211
+ return /* @__PURE__ */ React3__namespace.createElement(
212
+ View,
213
+ {
214
+ pointerEvents: "none",
215
+ style: {
216
+ // height: 100,
217
+ backgroundColor: "#FFFFFFCC",
218
+ borderRadius: 4,
219
+ padding: 4,
220
+ paddingBottom: 4,
221
+ paddingLeft: 4,
222
+ position: "absolute",
223
+ right: 0,
224
+ top: 0
225
+ }
226
+ },
227
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, totalSize.toFixed(2))),
228
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, contentSize.toFixed(2))),
229
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "At end:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, String(state.isAtEnd))),
230
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, scrollAdjust.toFixed(2))),
231
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React3__namespace.createElement(Text, null, rawScroll.toFixed(2))),
232
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React3__namespace.createElement(Text, null, scroll.toFixed(2)))
233
+ );
234
+ });
235
+ function useInterval(callback, delay) {
236
+ React3.useEffect(() => {
237
+ const interval = setInterval(callback, delay);
238
+ return () => clearInterval(interval);
239
+ }, [delay]);
240
+ }
241
+
242
+ // src/utils/devEnvironment.ts
243
+ var metroDev = typeof __DEV__ !== "undefined" ? __DEV__ : void 0;
244
+ var _a;
245
+ var envMode = typeof process !== "undefined" && typeof process.env === "object" && process.env ? (_a = process.env.NODE_ENV) != null ? _a : process.env.MODE : void 0;
246
+ var processDev = typeof envMode === "string" ? envMode.toLowerCase() !== "production" : void 0;
247
+ var _a2;
248
+ var IS_DEV = (_a2 = processDev != null ? processDev : metroDev) != null ? _a2 : false;
249
+
250
+ // src/constants.ts
251
+ var POSITION_OUT_OF_VIEW = -1e7;
252
+ var ENABLE_DEVMODE = IS_DEV && false;
253
+ var ENABLE_DEBUG_VIEW = IS_DEV && false;
254
+ var typedForwardRef = React3.forwardRef;
255
+ var typedMemo = React3.memo;
256
+
257
+ // src/utils/helpers.ts
258
+ function isFunction(obj) {
259
+ return typeof obj === "function";
260
+ }
261
+ function isArray(obj) {
262
+ return Array.isArray(obj);
263
+ }
264
+ var warned = /* @__PURE__ */ new Set();
265
+ function warnDevOnce(id, text) {
266
+ if (IS_DEV && !warned.has(id)) {
267
+ warned.add(id);
268
+ console.warn(`[legend-list] ${text}`);
269
+ }
270
+ }
271
+ function roundSize(size) {
272
+ return Math.floor(size * 8) / 8;
273
+ }
274
+ function isNullOrUndefined(value) {
275
+ return value === null || value === void 0;
276
+ }
277
+ function comparatorDefault(a, b) {
278
+ return a - b;
279
+ }
280
+ function getPadding(s, type) {
281
+ var _a3, _b, _c;
282
+ return (_c = (_b = (_a3 = s[`padding${type}`]) != null ? _a3 : s.paddingVertical) != null ? _b : s.padding) != null ? _c : 0;
283
+ }
284
+ function extractPadding(style, contentContainerStyle, type) {
285
+ return getPadding(style, type) + getPadding(contentContainerStyle, type);
286
+ }
287
+ function findContainerId(ctx, key) {
288
+ var _a3, _b;
289
+ const directMatch = (_b = (_a3 = ctx.state) == null ? void 0 : _a3.containerItemKeys) == null ? void 0 : _b.get(key);
290
+ if (directMatch !== void 0) {
291
+ return directMatch;
292
+ }
293
+ const numContainers = peek$(ctx, "numContainers");
294
+ for (let i = 0; i < numContainers; i++) {
295
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
296
+ if (itemKey === key) {
297
+ return i;
298
+ }
299
+ }
300
+ return -1;
301
+ }
302
+
303
+ // src/components/PositionView.tsx
304
+ var PositionViewState = typedMemo(function PositionViewState2({
305
+ id,
306
+ horizontal,
307
+ style,
308
+ refView,
309
+ ...props
310
+ }) {
311
+ const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
312
+ const base = {
313
+ contain: "paint layout style"
314
+ };
315
+ const composed = isArray(style) ? Object.assign({}, ...style) : style;
316
+ const combinedStyle = horizontal ? { ...base, ...composed, left: position } : { ...base, ...composed, top: position };
317
+ const { animatedScrollY, onLayout, index, ...webProps } = props;
318
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, ...webProps, style: combinedStyle });
319
+ });
320
+ var PositionViewSticky = typedMemo(function PositionViewSticky2({
321
+ id,
322
+ horizontal,
323
+ style,
324
+ refView,
325
+ index,
326
+ animatedScrollY: _animatedScrollY,
327
+ stickyHeaderConfig,
328
+ children,
329
+ ...rest
330
+ }) {
331
+ const [position = POSITION_OUT_OF_VIEW, activeStickyIndex] = useArr$([
332
+ `containerPosition${id}`,
333
+ "activeStickyIndex"
334
+ ]);
335
+ const base = {
336
+ contain: "paint layout style"
337
+ };
338
+ const composed = React3__namespace.useMemo(
339
+ () => {
340
+ var _a3;
341
+ return (_a3 = isArray(style) ? Object.assign({}, ...style) : style) != null ? _a3 : {};
342
+ },
343
+ [style]
344
+ );
345
+ const viewStyle = React3__namespace.useMemo(() => {
346
+ var _a3;
347
+ const styleBase = { ...base, ...composed };
348
+ delete styleBase.transform;
349
+ const stickyConfigOffset = (_a3 = stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset) != null ? _a3 : 0;
350
+ const offset = stickyConfigOffset != null ? stickyConfigOffset : 0;
351
+ const isActive = activeStickyIndex === index;
352
+ styleBase.position = isActive ? "sticky" : "absolute";
353
+ styleBase.zIndex = index + 1e3;
354
+ if (horizontal) {
355
+ styleBase.left = isActive ? offset : position;
356
+ } else {
357
+ styleBase.top = isActive ? offset : position;
358
+ }
359
+ return styleBase;
360
+ }, [composed, horizontal, position, index, activeStickyIndex, stickyHeaderConfig == null ? void 0 : stickyHeaderConfig.offset]);
361
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: viewStyle, ...rest }, children);
362
+ });
363
+ var PositionView = PositionViewState;
364
+ function useInit(cb) {
365
+ React3.useState(() => cb());
366
+ }
367
+
368
+ // src/state/ContextContainer.ts
369
+ var ContextContainer = React3.createContext(null);
370
+ function useContextContainer() {
371
+ return React3.useContext(ContextContainer);
372
+ }
373
+ function useViewability(callback, configId) {
374
+ const ctx = useStateContext();
375
+ const containerContext = useContextContainer();
376
+ useInit(() => {
377
+ if (!containerContext) {
378
+ return;
379
+ }
380
+ const { containerId } = containerContext;
381
+ const key = containerId + (configId != null ? configId : "");
382
+ const value = ctx.mapViewabilityValues.get(key);
383
+ if (value) {
384
+ callback(value);
385
+ }
386
+ });
387
+ React3.useEffect(() => {
388
+ if (!containerContext) {
389
+ return;
390
+ }
391
+ const { containerId } = containerContext;
392
+ const key = containerId + (configId != null ? configId : "");
393
+ ctx.mapViewabilityCallbacks.set(key, callback);
394
+ return () => {
395
+ ctx.mapViewabilityCallbacks.delete(key);
396
+ };
397
+ }, [ctx, callback, configId, containerContext]);
398
+ }
399
+ function useViewabilityAmount(callback) {
400
+ const ctx = useStateContext();
401
+ const containerContext = useContextContainer();
402
+ useInit(() => {
403
+ if (!containerContext) {
404
+ return;
405
+ }
406
+ const { containerId } = containerContext;
407
+ const value = ctx.mapViewabilityAmountValues.get(containerId);
408
+ if (value) {
409
+ callback(value);
410
+ }
411
+ });
412
+ React3.useEffect(() => {
413
+ if (!containerContext) {
414
+ return;
415
+ }
416
+ const { containerId } = containerContext;
417
+ ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
418
+ return () => {
419
+ ctx.mapViewabilityAmountCallbacks.delete(containerId);
420
+ };
421
+ }, [ctx, callback, containerContext]);
422
+ }
423
+ function useRecyclingEffect(effect) {
424
+ const containerContext = useContextContainer();
425
+ const prevValues = React3.useRef({
426
+ prevIndex: void 0,
427
+ prevItem: void 0
428
+ });
429
+ React3.useEffect(() => {
430
+ if (!containerContext) {
431
+ return;
432
+ }
433
+ const { index, value } = containerContext;
434
+ let ret;
435
+ if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
436
+ ret = effect({
437
+ index,
438
+ item: value,
439
+ prevIndex: prevValues.current.prevIndex,
440
+ prevItem: prevValues.current.prevItem
441
+ });
442
+ }
443
+ prevValues.current = {
444
+ prevIndex: index,
445
+ prevItem: value
446
+ };
447
+ return ret;
448
+ }, [effect, containerContext]);
449
+ }
450
+ function useRecyclingState(valueOrFun) {
451
+ var _a3, _b;
452
+ const containerContext = useContextContainer();
453
+ const computeValue = (ctx) => {
454
+ if (isFunction(valueOrFun)) {
455
+ const initializer = valueOrFun;
456
+ return ctx ? initializer({
457
+ index: ctx.index,
458
+ item: ctx.value,
459
+ prevIndex: void 0,
460
+ prevItem: void 0
461
+ }) : initializer();
462
+ }
463
+ return valueOrFun;
464
+ };
465
+ const [stateValue, setStateValue] = React3.useState(() => {
466
+ return computeValue(containerContext);
467
+ });
468
+ const prevItemKeyRef = React3.useRef((_a3 = containerContext == null ? void 0 : containerContext.itemKey) != null ? _a3 : null);
469
+ const currentItemKey = (_b = containerContext == null ? void 0 : containerContext.itemKey) != null ? _b : null;
470
+ if (currentItemKey !== null && prevItemKeyRef.current !== currentItemKey) {
471
+ prevItemKeyRef.current = currentItemKey;
472
+ setStateValue(computeValue(containerContext));
473
+ }
474
+ const triggerLayout = containerContext == null ? void 0 : containerContext.triggerLayout;
475
+ const setState = React3.useCallback(
476
+ (newState) => {
477
+ if (!triggerLayout) {
478
+ return;
479
+ }
480
+ setStateValue((prevValue) => {
481
+ return isFunction(newState) ? newState(prevValue) : newState;
482
+ });
483
+ triggerLayout();
484
+ },
485
+ [triggerLayout]
486
+ );
487
+ return [stateValue, setState];
488
+ }
489
+ function useIsLastItem() {
490
+ const containerContext = useContextContainer();
491
+ const isLast = useSelector$("lastItemKeys", (lastItemKeys) => {
492
+ if (containerContext) {
493
+ const { itemKey } = containerContext;
494
+ if (!isNullOrUndefined(itemKey)) {
495
+ return (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false;
496
+ }
497
+ }
498
+ return false;
499
+ });
500
+ return isLast;
501
+ }
502
+ function useListScrollSize() {
503
+ const [scrollSize] = useArr$(["scrollSize"]);
504
+ return scrollSize;
505
+ }
506
+ var noop = () => {
507
+ };
508
+ function useSyncLayout() {
509
+ const containerContext = useContextContainer();
510
+ if (containerContext) {
511
+ const { triggerLayout: syncLayout } = containerContext;
512
+ return syncLayout;
513
+ } else {
514
+ return noop;
515
+ }
516
+ }
517
+
518
+ // src/components/Separator.tsx
519
+ function Separator({ ItemSeparatorComponent, leadingItem }) {
520
+ const isLastItem = useIsLastItem();
521
+ return isLastItem ? null : /* @__PURE__ */ React3__namespace.createElement(ItemSeparatorComponent, { leadingItem });
522
+ }
523
+
524
+ // src/hooks/createResizeObserver.ts
525
+ var globalResizeObserver = null;
526
+ function getGlobalResizeObserver() {
527
+ if (!globalResizeObserver) {
528
+ globalResizeObserver = new ResizeObserver((entries) => {
529
+ for (const entry of entries) {
530
+ const callbacks = callbackMap.get(entry.target);
531
+ if (callbacks) {
532
+ for (const callback of callbacks) {
533
+ callback(entry);
534
+ }
535
+ }
536
+ }
537
+ });
538
+ }
539
+ return globalResizeObserver;
540
+ }
541
+ var callbackMap = /* @__PURE__ */ new WeakMap();
542
+ function createResizeObserver(element, callback) {
543
+ if (typeof ResizeObserver === "undefined") {
544
+ return () => {
545
+ };
546
+ }
547
+ if (!element) {
548
+ return () => {
549
+ };
550
+ }
551
+ const observer = getGlobalResizeObserver();
552
+ let callbacks = callbackMap.get(element);
553
+ if (!callbacks) {
554
+ callbacks = /* @__PURE__ */ new Set();
555
+ callbackMap.set(element, callbacks);
556
+ observer.observe(element);
557
+ }
558
+ callbacks.add(callback);
559
+ return () => {
560
+ if (callbacks) {
561
+ callbacks.delete(callback);
562
+ if (callbacks.size === 0) {
563
+ callbackMap.delete(element);
564
+ observer.unobserve(element);
565
+ }
566
+ }
567
+ };
568
+ }
569
+
570
+ // src/hooks/useOnLayoutSync.tsx
571
+ function useOnLayoutSync({
572
+ ref,
573
+ onLayoutProp,
574
+ onLayoutChange,
575
+ webLayoutResync
576
+ }, deps) {
577
+ React3.useLayoutEffect(() => {
578
+ var _a3, _b;
579
+ const current = ref.current;
580
+ const scrollableNode = (_b = (_a3 = current == null ? void 0 : current.getScrollableNode) == null ? void 0 : _a3.call(current)) != null ? _b : null;
581
+ const element = scrollableNode || current;
582
+ if (!element) {
583
+ return;
584
+ }
585
+ const emit = (layout, fromLayoutEffect) => {
586
+ if (layout.height === 0 && layout.width === 0) {
587
+ return;
588
+ }
589
+ onLayoutChange(layout, fromLayoutEffect);
590
+ onLayoutProp == null ? void 0 : onLayoutProp({ nativeEvent: { layout } });
591
+ };
592
+ const rect = element.getBoundingClientRect();
593
+ emit(toLayout(rect), true);
594
+ let prevRect = rect;
595
+ return createResizeObserver(element, (entry) => {
596
+ var _a4;
597
+ const target = entry.target instanceof HTMLElement ? entry.target : void 0;
598
+ const rectObserved = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
599
+ const didSizeChange = rectObserved.width !== prevRect.width || rectObserved.height !== prevRect.height;
600
+ const shouldResyncLayout = !!(webLayoutResync == null ? void 0 : webLayoutResync());
601
+ if (didSizeChange || shouldResyncLayout) {
602
+ prevRect = rectObserved;
603
+ emit(toLayout(rectObserved), false);
604
+ }
605
+ });
606
+ }, deps || []);
607
+ return {};
608
+ }
609
+ function toLayout(rect) {
610
+ if (!rect) {
611
+ return { height: 0, width: 0, x: 0, y: 0 };
612
+ }
613
+ return {
614
+ height: rect.height,
615
+ width: rect.width,
616
+ x: rect.left,
617
+ y: rect.top
618
+ };
619
+ }
620
+
621
+ // src/platform/Platform.ts
622
+ var Platform = {
623
+ // Widen the type to avoid unreachable-branch lints in cross-platform code that compares against other OSes
624
+ OS: "web"
625
+ };
626
+
627
+ // src/utils/isInMVCPActiveMode.ts
628
+ function isInMVCPActiveMode(state) {
629
+ const lock = state.mvcpAnchorLock;
630
+ if (lock && Date.now() > lock.expiresAt) {
631
+ state.mvcpAnchorLock = void 0;
632
+ }
633
+ return state.dataChangeNeedsScrollUpdate || !!state.mvcpAnchorLock;
634
+ }
635
+
636
+ // src/components/Container.tsx
637
+ var Container = typedMemo(function Container2({
638
+ id,
639
+ recycleItems,
640
+ horizontal,
641
+ getRenderedItem: getRenderedItem2,
642
+ updateItemSize: updateItemSize2,
643
+ ItemSeparatorComponent,
644
+ stickyHeaderConfig
645
+ }) {
646
+ const ctx = useStateContext();
647
+ const { columnWrapperStyle, animatedScrollY } = ctx;
648
+ const stickyPositionComponentInternal = ctx.state.props.stickyPositionComponentInternal;
649
+ const [column = 0, span = 1, data, itemKey, numColumns = 1, extraData, isSticky] = useArr$([
650
+ `containerColumn${id}`,
651
+ `containerSpan${id}`,
652
+ `containerItemData${id}`,
653
+ `containerItemKey${id}`,
654
+ "numColumns",
655
+ "extraData",
656
+ `containerSticky${id}`
657
+ ]);
658
+ const itemLayoutRef = React3.useRef({
659
+ didLayout: false,
660
+ horizontal,
661
+ itemKey,
662
+ pendingShrinkToken: 0,
663
+ updateItemSize: updateItemSize2
664
+ });
665
+ itemLayoutRef.current.horizontal = horizontal;
666
+ itemLayoutRef.current.itemKey = itemKey;
667
+ itemLayoutRef.current.updateItemSize = updateItemSize2;
668
+ const ref = React3.useRef(null);
669
+ const [layoutRenderCount, forceLayoutRender] = React3.useState(0);
670
+ const resolvedColumn = column > 0 ? column : 1;
671
+ const resolvedSpan = Math.min(Math.max(span || 1, 1), numColumns);
672
+ const otherAxisPos = numColumns > 1 ? `${(resolvedColumn - 1) / numColumns * 100}%` : 0;
673
+ const otherAxisSize = numColumns > 1 ? `${resolvedSpan / numColumns * 100}%` : void 0;
674
+ const style = React3.useMemo(() => {
675
+ let paddingStyles;
676
+ if (columnWrapperStyle) {
677
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
678
+ if (horizontal) {
679
+ paddingStyles = {
680
+ paddingRight: columnGap || gap || void 0,
681
+ paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
682
+ };
683
+ } else {
684
+ paddingStyles = {
685
+ paddingBottom: rowGap || gap || void 0,
686
+ paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
687
+ };
688
+ }
689
+ }
690
+ return horizontal ? {
691
+ flexDirection: ItemSeparatorComponent ? "row" : void 0,
692
+ height: otherAxisSize,
693
+ left: 0,
694
+ position: "absolute",
695
+ top: otherAxisPos,
696
+ ...paddingStyles || {}
697
+ } : {
698
+ left: otherAxisPos,
699
+ position: "absolute",
700
+ right: numColumns > 1 ? null : 0,
701
+ top: 0,
702
+ width: otherAxisSize,
703
+ ...paddingStyles || {}
704
+ };
705
+ }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
706
+ const renderedItemInfo = React3.useMemo(
707
+ () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
708
+ [itemKey, data, extraData]
709
+ );
710
+ const { index, renderedItem } = renderedItemInfo || {};
711
+ const contextValue = React3.useMemo(() => {
712
+ ctx.viewRefs.set(id, ref);
713
+ return {
714
+ containerId: id,
715
+ index,
716
+ itemKey,
717
+ triggerLayout: () => {
718
+ forceLayoutRender((v) => v + 1);
719
+ },
720
+ value: data
721
+ };
722
+ }, [id, itemKey, index, data]);
723
+ const onLayoutChange = React3.useCallback((rectangle) => {
724
+ const {
725
+ horizontal: currentHorizontal,
726
+ itemKey: currentItemKey,
727
+ updateItemSize: updateItemSizeFn,
728
+ lastSize,
729
+ pendingShrinkToken
730
+ } = itemLayoutRef.current;
731
+ if (isNullOrUndefined(currentItemKey)) {
732
+ return;
733
+ }
734
+ itemLayoutRef.current.didLayout = true;
735
+ let layout = rectangle;
736
+ const axis = currentHorizontal ? "width" : "height";
737
+ const size = roundSize(rectangle[axis]);
738
+ const prevSize = lastSize ? roundSize(lastSize[axis]) : void 0;
739
+ const doUpdate = () => {
740
+ itemLayoutRef.current.lastSize = layout;
741
+ updateItemSizeFn(currentItemKey, layout);
742
+ itemLayoutRef.current.didLayout = true;
743
+ };
744
+ const shouldDeferWebShrinkLayoutUpdate = !isInMVCPActiveMode(ctx.state) && prevSize !== void 0 && size + 1 < prevSize;
745
+ if (shouldDeferWebShrinkLayoutUpdate) {
746
+ const token = pendingShrinkToken + 1;
747
+ itemLayoutRef.current.pendingShrinkToken = token;
748
+ requestAnimationFrame(() => {
749
+ var _a4;
750
+ if (itemLayoutRef.current.pendingShrinkToken !== token) {
751
+ return;
752
+ }
753
+ const element = ref.current;
754
+ const rect = (_a4 = element == null ? void 0 : element.getBoundingClientRect) == null ? void 0 : _a4.call(element);
755
+ if (rect) {
756
+ layout = { height: rect.height, width: rect.width };
757
+ }
758
+ doUpdate();
759
+ });
760
+ return;
761
+ }
762
+ {
763
+ doUpdate();
764
+ }
765
+ }, []);
766
+ const { onLayout } = useOnLayoutSync(
767
+ {
768
+ onLayoutChange,
769
+ ref,
770
+ webLayoutResync: () => isInMVCPActiveMode(ctx.state)
771
+ },
772
+ [itemKey, layoutRenderCount]
773
+ );
774
+ const PositionComponent = isSticky ? stickyPositionComponentInternal ? stickyPositionComponentInternal : PositionViewSticky : PositionView;
775
+ return /* @__PURE__ */ React3__namespace.createElement(
776
+ PositionComponent,
777
+ {
778
+ animatedScrollY: isSticky ? animatedScrollY : void 0,
779
+ horizontal,
780
+ id,
781
+ index,
782
+ key: recycleItems ? void 0 : itemKey,
783
+ onLayout,
784
+ refView: ref,
785
+ stickyHeaderConfig,
786
+ style
787
+ },
788
+ /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(Separator, { ItemSeparatorComponent, leadingItem: renderedItemInfo.item }))
789
+ );
790
+ });
791
+
792
+ // src/utils/reordering.ts
793
+ var mapFn = (element) => {
794
+ const indexStr = element.getAttribute("index");
795
+ return [element, indexStr === null ? null : parseInt(indexStr)];
796
+ };
797
+ function sortDOMElements(container) {
798
+ const elements = Array.from(container.children);
799
+ if (elements.length <= 1) return elements;
800
+ const items = elements.map(mapFn);
801
+ items.sort((a, b) => {
802
+ const aKey = a[1];
803
+ const bKey = b[1];
804
+ if (aKey === null) {
805
+ return 1;
806
+ }
807
+ if (bKey === null) {
808
+ return -1;
809
+ }
810
+ return aKey - bKey;
811
+ });
812
+ const targetPositions = /* @__PURE__ */ new Map();
813
+ items.forEach((item, index) => {
814
+ targetPositions.set(item[0], index);
815
+ });
816
+ const currentPositions = elements.map((el) => targetPositions.get(el));
817
+ const lis = findLIS(currentPositions);
818
+ const stableIndices = new Set(lis);
819
+ for (let targetPos = 0; targetPos < items.length; targetPos++) {
820
+ const element = items[targetPos][0];
821
+ const currentPos = elements.indexOf(element);
822
+ if (!stableIndices.has(currentPos)) {
823
+ let nextStableElement = null;
824
+ for (let i = targetPos + 1; i < items.length; i++) {
825
+ const nextEl = items[i][0];
826
+ const nextCurrentPos = elements.indexOf(nextEl);
827
+ if (stableIndices.has(nextCurrentPos)) {
828
+ nextStableElement = nextEl;
829
+ break;
830
+ }
831
+ }
832
+ if (nextStableElement) {
833
+ container.insertBefore(element, nextStableElement);
834
+ } else {
835
+ container.appendChild(element);
836
+ }
837
+ }
838
+ }
839
+ }
840
+ function findLIS(arr) {
841
+ const n = arr.length;
842
+ const tails = [];
843
+ const predecessors = new Array(n).fill(-1);
844
+ const indices = [];
845
+ for (let i = 0; i < n; i++) {
846
+ const num = arr[i];
847
+ let left = 0, right = tails.length;
848
+ while (left < right) {
849
+ const mid = Math.floor((left + right) / 2);
850
+ if (arr[indices[mid]] < num) {
851
+ left = mid + 1;
852
+ } else {
853
+ right = mid;
854
+ }
855
+ }
856
+ if (left === tails.length) {
857
+ tails.push(num);
858
+ indices.push(i);
859
+ } else {
860
+ tails[left] = num;
861
+ indices[left] = i;
862
+ }
863
+ if (left > 0) {
864
+ predecessors[i] = indices[left - 1];
865
+ }
866
+ }
867
+ const result = [];
868
+ let k = indices[indices.length - 1];
869
+ while (k !== -1) {
870
+ result.unshift(k);
871
+ k = predecessors[k];
872
+ }
873
+ return result;
874
+ }
875
+
876
+ // src/hooks/useDOMOrder.ts
877
+ function useDOMOrder(ref) {
878
+ const ctx = useStateContext();
879
+ const debounceRef = React3.useRef(void 0);
880
+ React3.useEffect(() => {
881
+ const unsubscribe = listen$(ctx, "lastPositionUpdate", () => {
882
+ if (debounceRef.current !== void 0) {
883
+ clearTimeout(debounceRef.current);
884
+ }
885
+ debounceRef.current = setTimeout(() => {
886
+ const parent = ref.current;
887
+ if (parent) {
888
+ sortDOMElements(parent);
889
+ }
890
+ debounceRef.current = void 0;
891
+ }, 500);
892
+ });
893
+ return () => {
894
+ unsubscribe();
895
+ if (debounceRef.current !== void 0) {
896
+ clearTimeout(debounceRef.current);
897
+ }
898
+ };
899
+ }, [ctx]);
900
+ }
901
+
902
+ // src/components/Containers.tsx
903
+ var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColumns, children }) {
904
+ const ref = React3.useRef(null);
905
+ const ctx = useStateContext();
906
+ const columnWrapperStyle = ctx.columnWrapperStyle;
907
+ const [totalSize, otherAxisSize] = useArr$(["totalSize", "otherAxisSize"]);
908
+ useDOMOrder(ref);
909
+ const style = horizontal ? { minHeight: otherAxisSize, position: "relative", width: totalSize } : { height: totalSize, minWidth: otherAxisSize, position: "relative" };
910
+ if (columnWrapperStyle && numColumns > 1) {
911
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
912
+ const gapX = columnGap || gap || 0;
913
+ const gapY = rowGap || gap || 0;
914
+ if (horizontal) {
915
+ if (gapY) {
916
+ style.marginTop = style.marginBottom = -gapY / 2;
917
+ }
918
+ if (gapX) {
919
+ style.marginRight = -gapX;
920
+ }
921
+ } else {
922
+ if (gapX) {
923
+ style.marginLeft = style.marginRight = -gapX;
924
+ }
925
+ if (gapY) {
926
+ style.marginBottom = -gapY;
927
+ }
928
+ }
929
+ }
930
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref, style }, children);
931
+ });
932
+ var Containers = typedMemo(function Containers2({
933
+ horizontal,
934
+ recycleItems,
935
+ ItemSeparatorComponent,
936
+ waitForInitialLayout,
937
+ updateItemSize: updateItemSize2,
938
+ getRenderedItem: getRenderedItem2,
939
+ stickyHeaderConfig
940
+ }) {
941
+ const [numContainers, numColumns] = useArr$(["numContainersPooled", "numColumns"]);
942
+ const containers = [];
943
+ for (let i = 0; i < numContainers; i++) {
944
+ containers.push(
945
+ /* @__PURE__ */ React3__namespace.createElement(
946
+ Container,
947
+ {
948
+ getRenderedItem: getRenderedItem2,
949
+ horizontal,
950
+ ItemSeparatorComponent,
951
+ id: i,
952
+ key: i,
953
+ recycleItems,
954
+ stickyHeaderConfig,
955
+ updateItemSize: updateItemSize2
956
+ }
957
+ )
958
+ );
959
+ }
960
+ return /* @__PURE__ */ React3__namespace.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
961
+ });
962
+
963
+ // src/platform/StyleSheet.tsx
964
+ function flattenStyles(styles) {
965
+ if (isArray(styles)) {
966
+ return Object.assign({}, ...styles.filter(Boolean));
967
+ }
968
+ return styles;
969
+ }
970
+ var StyleSheet = {
971
+ create: (styles) => styles,
972
+ flatten: (style) => flattenStyles(style)
973
+ };
974
+
975
+ // src/components/ListComponentScrollView.tsx
976
+ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView2({
977
+ children,
978
+ style,
979
+ contentContainerStyle,
980
+ horizontal = false,
981
+ contentOffset,
982
+ maintainVisibleContentPosition,
983
+ onScroll: onScroll2,
984
+ onMomentumScrollEnd,
985
+ showsHorizontalScrollIndicator = true,
986
+ showsVerticalScrollIndicator = true,
987
+ refreshControl,
988
+ onLayout,
989
+ ...props
990
+ }, ref) {
991
+ const scrollRef = React3.useRef(null);
992
+ const contentRef = React3.useRef(null);
993
+ React3.useImperativeHandle(ref, () => {
994
+ const api = {
995
+ getBoundingClientRect: () => {
996
+ var _a3;
997
+ return (_a3 = scrollRef.current) == null ? void 0 : _a3.getBoundingClientRect();
998
+ },
999
+ getScrollableNode: () => scrollRef.current,
1000
+ getScrollResponder: () => scrollRef.current,
1001
+ scrollBy: (x, y) => {
1002
+ const el = scrollRef.current;
1003
+ if (!el) return;
1004
+ el.scrollBy(x, y);
1005
+ },
1006
+ scrollTo: (options) => {
1007
+ const el = scrollRef.current;
1008
+ if (!el) return;
1009
+ const { x = 0, y = 0, animated = true } = options;
1010
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", left: x, top: y });
1011
+ },
1012
+ scrollToEnd: (options = {}) => {
1013
+ const el = scrollRef.current;
1014
+ if (!el) return;
1015
+ const { animated = true } = options;
1016
+ if (horizontal) {
1017
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", left: el.scrollWidth });
1018
+ } else {
1019
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", top: el.scrollHeight });
1020
+ }
1021
+ },
1022
+ scrollToOffset: (params) => {
1023
+ const el = scrollRef.current;
1024
+ if (!el) return;
1025
+ const { offset, animated = true } = params;
1026
+ if (horizontal) {
1027
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", left: offset });
1028
+ } else {
1029
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", top: offset });
1030
+ }
1031
+ }
1032
+ };
1033
+ return api;
1034
+ }, [horizontal]);
1035
+ const handleScroll = React3.useCallback(
1036
+ (event) => {
1037
+ if (!onScroll2 || !(event == null ? void 0 : event.target)) {
1038
+ return;
1039
+ }
1040
+ const target = event.target;
1041
+ const scrollEvent = {
1042
+ nativeEvent: {
1043
+ contentOffset: {
1044
+ x: target.scrollLeft,
1045
+ y: target.scrollTop
1046
+ },
1047
+ contentSize: {
1048
+ height: target.scrollHeight,
1049
+ width: target.scrollWidth
1050
+ },
1051
+ layoutMeasurement: {
1052
+ height: target.clientHeight,
1053
+ width: target.clientWidth
1054
+ }
1055
+ }
1056
+ };
1057
+ onScroll2(scrollEvent);
1058
+ },
1059
+ [onScroll2, onMomentumScrollEnd]
1060
+ );
1061
+ React3.useLayoutEffect(() => {
1062
+ const element = scrollRef.current;
1063
+ if (!element) return;
1064
+ element.addEventListener("scroll", handleScroll);
1065
+ return () => {
1066
+ element.removeEventListener("scroll", handleScroll);
1067
+ };
1068
+ }, [handleScroll]);
1069
+ React3.useEffect(() => {
1070
+ const doScroll = () => {
1071
+ if (contentOffset && scrollRef.current) {
1072
+ scrollRef.current.scrollLeft = contentOffset.x || 0;
1073
+ scrollRef.current.scrollTop = contentOffset.y || 0;
1074
+ }
1075
+ };
1076
+ doScroll();
1077
+ requestAnimationFrame(doScroll);
1078
+ }, [contentOffset == null ? void 0 : contentOffset.x, contentOffset == null ? void 0 : contentOffset.y]);
1079
+ React3.useLayoutEffect(() => {
1080
+ if (!onLayout || !scrollRef.current) return;
1081
+ const element = scrollRef.current;
1082
+ const fireLayout = () => {
1083
+ const rect = element.getBoundingClientRect();
1084
+ onLayout({
1085
+ nativeEvent: {
1086
+ layout: {
1087
+ height: rect.height,
1088
+ width: rect.width,
1089
+ x: rect.left,
1090
+ y: rect.top
1091
+ }
1092
+ }
1093
+ });
1094
+ };
1095
+ fireLayout();
1096
+ const resizeObserver = new ResizeObserver(() => {
1097
+ fireLayout();
1098
+ });
1099
+ resizeObserver.observe(element);
1100
+ return () => resizeObserver.disconnect();
1101
+ }, [onLayout]);
1102
+ const scrollViewStyle = {
1103
+ overflow: "auto",
1104
+ overflowX: horizontal ? "auto" : showsHorizontalScrollIndicator ? "auto" : "hidden",
1105
+ overflowY: horizontal ? showsVerticalScrollIndicator ? "auto" : "hidden" : "auto",
1106
+ position: "relative",
1107
+ // Ensure proper positioning context
1108
+ WebkitOverflowScrolling: "touch",
1109
+ // iOS momentum scrolling
1110
+ ...StyleSheet.flatten(style)
1111
+ };
1112
+ const contentStyle = {
1113
+ display: horizontal ? "flex" : "block",
1114
+ flexDirection: horizontal ? "row" : void 0,
1115
+ minHeight: horizontal ? void 0 : "100%",
1116
+ minWidth: horizontal ? "100%" : void 0,
1117
+ ...StyleSheet.flatten(contentContainerStyle)
1118
+ };
1119
+ const { contentInset, scrollEventThrottle, ScrollComponent, ...webProps } = props;
1120
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: scrollRef, ...webProps, style: scrollViewStyle }, refreshControl, /* @__PURE__ */ React3__namespace.createElement("div", { ref: contentRef, style: contentStyle }, children));
1121
+ });
1122
+ function useValueListener$(key, callback) {
1123
+ const ctx = useStateContext();
1124
+ React3.useLayoutEffect(() => {
1125
+ const unsubscribe = listen$(ctx, key, (value) => {
1126
+ callback(value);
1127
+ });
1128
+ return unsubscribe;
1129
+ }, [callback, ctx, key]);
1130
+ }
1131
+
1132
+ // src/components/ScrollAdjust.tsx
1133
+ function ScrollAdjust() {
1134
+ const ctx = useStateContext();
1135
+ const lastScrollOffsetRef = React3__namespace.useRef(0);
1136
+ const resetPaddingRafRef = React3__namespace.useRef(void 0);
1137
+ const callback = React3__namespace.useCallback(() => {
1138
+ var _a3;
1139
+ const scrollAdjust = peek$(ctx, "scrollAdjust");
1140
+ const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
1141
+ const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
1142
+ const scrollView = (_a3 = ctx.state) == null ? void 0 : _a3.refScroller.current;
1143
+ if (scrollView && scrollOffset !== lastScrollOffsetRef.current) {
1144
+ const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
1145
+ if (scrollDelta !== 0) {
1146
+ const el = scrollView.getScrollableNode();
1147
+ const prevScroll = el.scrollTop;
1148
+ const nextScroll = prevScroll + scrollDelta;
1149
+ const totalSize = el.scrollHeight;
1150
+ if (scrollDelta > 0 && !ctx.state.adjustingFromInitialMount && totalSize < nextScroll + el.clientHeight) {
1151
+ const paddingBottom = ctx.state.props.stylePaddingBottom || 0;
1152
+ const child = el.firstElementChild;
1153
+ const pad = (nextScroll + el.clientHeight - totalSize) * 2;
1154
+ child.style.paddingBottom = `${pad}px`;
1155
+ void el.offsetHeight;
1156
+ scrollView.scrollBy(0, scrollDelta);
1157
+ if (resetPaddingRafRef.current !== void 0) {
1158
+ cancelAnimationFrame(resetPaddingRafRef.current);
1159
+ }
1160
+ resetPaddingRafRef.current = requestAnimationFrame(() => {
1161
+ resetPaddingRafRef.current = void 0;
1162
+ child.style.paddingBottom = paddingBottom ? `${paddingBottom}px` : "0";
1163
+ });
1164
+ } else {
1165
+ scrollView.scrollBy(0, scrollDelta);
1166
+ }
1167
+ }
1168
+ lastScrollOffsetRef.current = scrollOffset;
1169
+ }
1170
+ }, [ctx]);
1171
+ useValueListener$("scrollAdjust", callback);
1172
+ useValueListener$("scrollAdjustUserOffset", callback);
1173
+ return null;
1174
+ }
1175
+ function SnapWrapper({ ScrollComponent, ...props }) {
1176
+ const [snapToOffsets] = useArr$(["snapToOffsets"]);
1177
+ return /* @__PURE__ */ React3__namespace.createElement(ScrollComponent, { ...props, snapToOffsets });
1178
+ }
1179
+ var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
1180
+ const ref = refView != null ? refView : React3.useRef();
1181
+ useOnLayoutSync({ onLayoutChange, ref });
1182
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ...rest, ref }, children);
1183
+ };
1184
+ var getComponent = (Component) => {
1185
+ if (React3__namespace.isValidElement(Component)) {
1186
+ return Component;
1187
+ }
1188
+ if (Component) {
1189
+ return /* @__PURE__ */ React3__namespace.createElement(Component, null);
1190
+ }
1191
+ return null;
1192
+ };
1193
+
1194
+ // src/components/ListComponent.tsx
1195
+ var ListComponent = typedMemo(function ListComponent2({
1196
+ canRender,
1197
+ style,
1198
+ contentContainerStyle,
1199
+ horizontal,
1200
+ initialContentOffset,
1201
+ recycleItems,
1202
+ ItemSeparatorComponent,
1203
+ alignItemsAtEnd: _alignItemsAtEnd,
1204
+ waitForInitialLayout,
1205
+ onScroll: onScroll2,
1206
+ onLayout,
1207
+ ListHeaderComponent,
1208
+ ListHeaderComponentStyle,
1209
+ ListFooterComponent,
1210
+ ListFooterComponentStyle,
1211
+ ListEmptyComponent,
1212
+ getRenderedItem: getRenderedItem2,
1213
+ updateItemSize: updateItemSize2,
1214
+ refScrollView,
1215
+ renderScrollComponent,
1216
+ scrollAdjustHandler,
1217
+ onLayoutHeader,
1218
+ snapToIndices,
1219
+ stickyHeaderConfig,
1220
+ stickyHeaderIndices,
1221
+ ...rest
1222
+ }) {
1223
+ const ctx = useStateContext();
1224
+ const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
1225
+ const ScrollComponent = renderScrollComponent ? React3.useMemo(
1226
+ () => React3__namespace.forwardRef(
1227
+ (props, ref) => renderScrollComponent({ ...props, ref })
1228
+ ),
1229
+ [renderScrollComponent]
1230
+ ) : ListComponentScrollView;
1231
+ const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1232
+ React3.useLayoutEffect(() => {
1233
+ if (!ListHeaderComponent) {
1234
+ set$(ctx, "headerSize", 0);
1235
+ }
1236
+ if (!ListFooterComponent) {
1237
+ set$(ctx, "footerSize", 0);
1238
+ }
1239
+ }, [ListHeaderComponent, ListFooterComponent, ctx]);
1240
+ return /* @__PURE__ */ React3__namespace.createElement(
1241
+ SnapOrScroll,
1242
+ {
1243
+ ...rest,
1244
+ contentContainerStyle: [
1245
+ contentContainerStyle,
1246
+ horizontal ? {
1247
+ height: "100%"
1248
+ } : {}
1249
+ ],
1250
+ contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
1251
+ horizontal,
1252
+ maintainVisibleContentPosition: maintainVisibleContentPosition.size || maintainVisibleContentPosition.data ? { minIndexForVisible: 0 } : void 0,
1253
+ onLayout,
1254
+ onScroll: onScroll2,
1255
+ ref: refScrollView,
1256
+ ScrollComponent: snapToIndices ? ScrollComponent : void 0,
1257
+ style
1258
+ },
1259
+ /* @__PURE__ */ React3__namespace.createElement(ScrollAdjust, null),
1260
+ ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1261
+ ListEmptyComponent && getComponent(ListEmptyComponent),
1262
+ canRender && !ListEmptyComponent && /* @__PURE__ */ React3__namespace.createElement(
1263
+ Containers,
1264
+ {
1265
+ getRenderedItem: getRenderedItem2,
1266
+ horizontal,
1267
+ ItemSeparatorComponent,
1268
+ recycleItems,
1269
+ stickyHeaderConfig,
1270
+ updateItemSize: updateItemSize2,
1271
+ waitForInitialLayout
1272
+ }
1273
+ ),
1274
+ ListFooterComponent && /* @__PURE__ */ React3__namespace.createElement(
1275
+ LayoutView,
1276
+ {
1277
+ onLayoutChange: (layout) => {
1278
+ const size = layout[horizontal ? "width" : "height"];
1279
+ set$(ctx, "footerSize", size);
1280
+ },
1281
+ style: ListFooterComponentStyle
1282
+ },
1283
+ getComponent(ListFooterComponent)
1284
+ ),
1285
+ IS_DEV && ENABLE_DEVMODE
1286
+ );
1287
+ });
1288
+
1289
+ // src/utils/getId.ts
1290
+ function getId(state, index) {
1291
+ const { data, keyExtractor } = state.props;
1292
+ if (!data) {
1293
+ return "";
1294
+ }
1295
+ const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
1296
+ const id = ret;
1297
+ state.idCache[index] = id;
1298
+ return id;
1299
+ }
1300
+
1301
+ // src/core/calculateOffsetForIndex.ts
1302
+ function calculateOffsetForIndex(ctx, index) {
1303
+ const state = ctx.state;
1304
+ let position = 0;
1305
+ if (index !== void 0) {
1306
+ position = state.positions.get(getId(state, index)) || 0;
1307
+ const paddingTop = peek$(ctx, "stylePaddingTop");
1308
+ if (paddingTop) {
1309
+ position += paddingTop;
1310
+ }
1311
+ const headerSize = peek$(ctx, "headerSize");
1312
+ if (headerSize) {
1313
+ position += headerSize;
1314
+ }
1315
+ }
1316
+ return position;
1317
+ }
1318
+
1319
+ // src/core/addTotalSize.ts
1320
+ function addTotalSize(ctx, key, add) {
1321
+ const state = ctx.state;
1322
+ const prevTotalSize = state.totalSize;
1323
+ let totalSize = state.totalSize;
1324
+ if (key === null) {
1325
+ totalSize = add;
1326
+ if (state.timeoutSetPaddingTop) {
1327
+ clearTimeout(state.timeoutSetPaddingTop);
1328
+ state.timeoutSetPaddingTop = void 0;
1329
+ }
1330
+ } else {
1331
+ totalSize += add;
1332
+ }
1333
+ if (prevTotalSize !== totalSize) {
1334
+ {
1335
+ state.pendingTotalSize = void 0;
1336
+ state.totalSize = totalSize;
1337
+ set$(ctx, "totalSize", totalSize);
1338
+ }
1339
+ }
1340
+ }
1341
+
1342
+ // src/core/setSize.ts
1343
+ function setSize(ctx, itemKey, size) {
1344
+ const state = ctx.state;
1345
+ const { sizes } = state;
1346
+ const previousSize = sizes.get(itemKey);
1347
+ const diff = previousSize !== void 0 ? size - previousSize : size;
1348
+ if (diff !== 0) {
1349
+ addTotalSize(ctx, itemKey, diff);
1350
+ }
1351
+ sizes.set(itemKey, size);
1352
+ }
1353
+
1354
+ // src/utils/getItemSize.ts
1355
+ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize) {
1356
+ var _a3, _b;
1357
+ const state = ctx.state;
1358
+ const {
1359
+ sizesKnown,
1360
+ sizes,
1361
+ averageSizes,
1362
+ props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType },
1363
+ scrollingTo
1364
+ } = state;
1365
+ const sizeKnown = sizesKnown.get(key);
1366
+ if (sizeKnown !== void 0) {
1367
+ return sizeKnown;
1368
+ }
1369
+ let size;
1370
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1371
+ if (preferCachedSize) {
1372
+ const cachedSize = sizes.get(key);
1373
+ if (cachedSize !== void 0) {
1374
+ return cachedSize;
1375
+ }
1376
+ }
1377
+ if (getFixedItemSize) {
1378
+ size = getFixedItemSize(data, index, itemType);
1379
+ if (size !== void 0) {
1380
+ sizesKnown.set(key, size);
1381
+ }
1382
+ }
1383
+ if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
1384
+ const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
1385
+ if (averageSizeForType !== void 0) {
1386
+ size = roundSize(averageSizeForType);
1387
+ }
1388
+ }
1389
+ if (size === void 0) {
1390
+ size = sizes.get(key);
1391
+ if (size !== void 0) {
1392
+ return size;
1393
+ }
1394
+ }
1395
+ if (size === void 0) {
1396
+ size = getEstimatedItemSize ? getEstimatedItemSize(data, index, itemType) : estimatedItemSize;
1397
+ }
1398
+ setSize(ctx, key, size);
1399
+ return size;
1400
+ }
1401
+
1402
+ // src/core/calculateOffsetWithOffsetPosition.ts
1403
+ function calculateOffsetWithOffsetPosition(ctx, offsetParam, params) {
1404
+ const state = ctx.state;
1405
+ const { index, viewOffset, viewPosition } = params;
1406
+ let offset = offsetParam;
1407
+ if (viewOffset) {
1408
+ offset -= viewOffset;
1409
+ }
1410
+ if (viewPosition !== void 0 && index !== void 0) {
1411
+ const itemSize = getItemSize(ctx, getId(state, index), index, state.props.data[index]);
1412
+ const trailingInset = getContentInsetEnd(state);
1413
+ offset -= viewPosition * (state.scrollLength - trailingInset - itemSize);
1414
+ }
1415
+ return offset;
1416
+ }
1417
+
1418
+ // src/core/clampScrollOffset.ts
1419
+ function clampScrollOffset(ctx, offset, scrollTarget) {
1420
+ const state = ctx.state;
1421
+ const contentSize = getContentSize(ctx);
1422
+ let clampedOffset = offset;
1423
+ if (Number.isFinite(contentSize) && Number.isFinite(state.scrollLength) && (Platform.OS !== "android")) {
1424
+ const baseMaxOffset = Math.max(0, contentSize - state.scrollLength);
1425
+ const viewOffset = scrollTarget == null ? void 0 : scrollTarget.viewOffset;
1426
+ const extraEndOffset = typeof viewOffset === "number" && viewOffset < 0 ? -viewOffset : 0;
1427
+ const maxOffset = baseMaxOffset + extraEndOffset;
1428
+ clampedOffset = Math.min(offset, maxOffset);
1429
+ }
1430
+ clampedOffset = Math.max(0, clampedOffset);
1431
+ return clampedOffset;
1432
+ }
1433
+
1434
+ // src/utils/checkThreshold.ts
1435
+ var HYSTERESIS_MULTIPLIER = 1.3;
1436
+ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot, allowReentryOnChange) => {
1437
+ const absDistance = Math.abs(distance);
1438
+ const within = atThreshold || threshold > 0 && absDistance <= threshold;
1439
+ const updateSnapshot = () => {
1440
+ setSnapshot({
1441
+ atThreshold,
1442
+ contentSize: context.contentSize,
1443
+ dataLength: context.dataLength,
1444
+ scrollPosition: context.scrollPosition
1445
+ });
1446
+ };
1447
+ if (!wasReached) {
1448
+ if (!within) {
1449
+ return false;
1450
+ }
1451
+ onReached(distance);
1452
+ updateSnapshot();
1453
+ return true;
1454
+ }
1455
+ const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
1456
+ if (reset) {
1457
+ setSnapshot(void 0);
1458
+ return false;
1459
+ }
1460
+ if (within) {
1461
+ const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
1462
+ if (changed) {
1463
+ if (allowReentryOnChange) {
1464
+ onReached(distance);
1465
+ }
1466
+ updateSnapshot();
1467
+ }
1468
+ }
1469
+ return true;
1470
+ };
1471
+
1472
+ // src/utils/checkAtBottom.ts
1473
+ function checkAtBottom(ctx) {
1474
+ var _a3;
1475
+ const state = ctx.state;
1476
+ if (!state || state.initialScroll) {
1477
+ return;
1478
+ }
1479
+ const {
1480
+ queuedInitialLayout,
1481
+ scrollLength,
1482
+ scroll,
1483
+ maintainingScrollAtEnd,
1484
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1485
+ } = state;
1486
+ if (state.initialScroll) {
1487
+ return;
1488
+ }
1489
+ const contentSize = getContentSize(ctx);
1490
+ if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1491
+ const insetEnd = getContentInsetEnd(state);
1492
+ const distanceFromEnd = contentSize - scroll - scrollLength - insetEnd;
1493
+ const isContentLess = contentSize < scrollLength;
1494
+ state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1495
+ state.isEndReached = checkThreshold(
1496
+ distanceFromEnd,
1497
+ isContentLess,
1498
+ onEndReachedThreshold * scrollLength,
1499
+ state.isEndReached,
1500
+ state.endReachedSnapshot,
1501
+ {
1502
+ contentSize,
1503
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1504
+ scrollPosition: scroll
1505
+ },
1506
+ (distance) => {
1507
+ var _a4, _b;
1508
+ return (_b = (_a4 = state.props).onEndReached) == null ? void 0 : _b.call(_a4, { distanceFromEnd: distance });
1509
+ },
1510
+ (snapshot) => {
1511
+ state.endReachedSnapshot = snapshot;
1512
+ },
1513
+ true
1514
+ );
1515
+ }
1516
+ }
1517
+
1518
+ // src/utils/checkAtTop.ts
1519
+ function checkAtTop(ctx) {
1520
+ var _a3;
1521
+ const state = ctx == null ? void 0 : ctx.state;
1522
+ if (!state || state.initialScroll || state.scrollingTo) {
1523
+ return;
1524
+ }
1525
+ const {
1526
+ scrollLength,
1527
+ scroll,
1528
+ props: { onStartReachedThreshold }
1529
+ } = state;
1530
+ const distanceFromTop = scroll;
1531
+ state.isAtStart = distanceFromTop <= 0;
1532
+ state.isStartReached = checkThreshold(
1533
+ distanceFromTop,
1534
+ false,
1535
+ onStartReachedThreshold * scrollLength,
1536
+ state.isStartReached,
1537
+ state.startReachedSnapshot,
1538
+ {
1539
+ contentSize: state.totalSize,
1540
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1541
+ scrollPosition: scroll
1542
+ },
1543
+ (distance) => {
1544
+ var _a4, _b;
1545
+ return (_b = (_a4 = state.props).onStartReached) == null ? void 0 : _b.call(_a4, { distanceFromStart: distance });
1546
+ },
1547
+ (snapshot) => {
1548
+ state.startReachedSnapshot = snapshot;
1549
+ },
1550
+ false
1551
+ );
1552
+ }
1553
+
1554
+ // src/utils/checkThresholds.ts
1555
+ function checkThresholds(ctx) {
1556
+ checkAtBottom(ctx);
1557
+ checkAtTop(ctx);
1558
+ }
1559
+
1560
+ // src/utils/setInitialRenderState.ts
1561
+ function setInitialRenderState(ctx, {
1562
+ didLayout,
1563
+ didInitialScroll
1564
+ }) {
1565
+ const { state } = ctx;
1566
+ const {
1567
+ loadStartTime,
1568
+ props: { onLoad }
1569
+ } = state;
1570
+ if (didLayout) {
1571
+ state.didContainersLayout = true;
1572
+ }
1573
+ if (didInitialScroll) {
1574
+ state.didFinishInitialScroll = true;
1575
+ }
1576
+ const isReadyToRender = Boolean(state.didContainersLayout && state.didFinishInitialScroll);
1577
+ if (isReadyToRender && !peek$(ctx, "readyToRender")) {
1578
+ set$(ctx, "readyToRender", true);
1579
+ if (onLoad) {
1580
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1581
+ }
1582
+ }
1583
+ }
1584
+
1585
+ // src/core/finishScrollTo.ts
1586
+ function finishScrollTo(ctx) {
1587
+ var _a3, _b;
1588
+ const state = ctx.state;
1589
+ if (state == null ? void 0 : state.scrollingTo) {
1590
+ const scrollingTo = state.scrollingTo;
1591
+ state.scrollHistory.length = 0;
1592
+ state.initialScroll = void 0;
1593
+ state.initialAnchor = void 0;
1594
+ state.scrollingTo = void 0;
1595
+ if (state.pendingTotalSize !== void 0) {
1596
+ addTotalSize(ctx, null, state.pendingTotalSize);
1597
+ }
1598
+ if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1599
+ (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1600
+ }
1601
+ {
1602
+ state.scrollAdjustHandler.commitPendingAdjust(scrollingTo);
1603
+ }
1604
+ setInitialRenderState(ctx, { didInitialScroll: true });
1605
+ checkThresholds(ctx);
1606
+ }
1607
+ }
1608
+
1609
+ // src/core/doScrollTo.ts
1610
+ var SCROLL_END_IDLE_MS = 80;
1611
+ var SCROLL_END_MAX_MS = 1500;
1612
+ var SMOOTH_SCROLL_DURATION_MS = 320;
1613
+ var SCROLL_END_TARGET_EPSILON = 1;
1614
+ function doScrollTo(ctx, params) {
1615
+ const state = ctx.state;
1616
+ const { animated, horizontal, offset } = params;
1617
+ const scroller = state.refScroller.current;
1618
+ const node = typeof (scroller == null ? void 0 : scroller.getScrollableNode) === "function" ? scroller.getScrollableNode() : scroller;
1619
+ if (node) {
1620
+ const left = horizontal ? offset : 0;
1621
+ const top = horizontal ? 0 : offset;
1622
+ node.scrollTo({ behavior: animated ? "smooth" : "auto", left, top });
1623
+ if (animated) {
1624
+ listenForScrollEnd(ctx, node, {
1625
+ horizontal: !!horizontal,
1626
+ targetOffset: offset
1627
+ });
1628
+ } else {
1629
+ state.scroll = offset;
1630
+ setTimeout(() => {
1631
+ finishScrollTo(ctx);
1632
+ }, 100);
1633
+ }
1634
+ }
1635
+ }
1636
+ function listenForScrollEnd(ctx, node, params) {
1637
+ const { horizontal, targetOffset } = params;
1638
+ const supportsScrollEnd = "onscrollend" in node;
1639
+ let idleTimeout;
1640
+ let maxTimeout;
1641
+ let settled = false;
1642
+ const targetToken = ctx.state.scrollingTo;
1643
+ const cleanup = () => {
1644
+ node.removeEventListener("scroll", onScroll2);
1645
+ if (supportsScrollEnd) {
1646
+ node.removeEventListener("scrollend", onScrollEnd);
1647
+ }
1648
+ if (idleTimeout) {
1649
+ clearTimeout(idleTimeout);
1650
+ }
1651
+ if (maxTimeout) {
1652
+ clearTimeout(maxTimeout);
1653
+ }
1654
+ };
1655
+ const finish = (reason) => {
1656
+ if (settled) return;
1657
+ if (targetToken !== ctx.state.scrollingTo) {
1658
+ settled = true;
1659
+ cleanup();
1660
+ return;
1661
+ }
1662
+ const currentOffset = horizontal ? node.scrollLeft : node.scrollTop;
1663
+ const isNearTarget = Math.abs(currentOffset - targetOffset) <= SCROLL_END_TARGET_EPSILON;
1664
+ if (reason === "scrollend" && !isNearTarget) {
1665
+ return;
1666
+ }
1667
+ settled = true;
1668
+ cleanup();
1669
+ finishScrollTo(ctx);
1670
+ };
1671
+ const onScroll2 = () => {
1672
+ if (idleTimeout) {
1673
+ clearTimeout(idleTimeout);
1674
+ }
1675
+ idleTimeout = setTimeout(() => finish("idle"), SCROLL_END_IDLE_MS);
1676
+ };
1677
+ const onScrollEnd = () => finish("scrollend");
1678
+ node.addEventListener("scroll", onScroll2);
1679
+ if (supportsScrollEnd) {
1680
+ node.addEventListener("scrollend", onScrollEnd);
1681
+ maxTimeout = setTimeout(() => finish("max"), SCROLL_END_MAX_MS);
1682
+ } else {
1683
+ idleTimeout = setTimeout(() => finish("idle"), SMOOTH_SCROLL_DURATION_MS);
1684
+ maxTimeout = setTimeout(() => finish("max"), SCROLL_END_MAX_MS);
1685
+ }
1686
+ }
1687
+
1688
+ // src/core/scrollTo.ts
1689
+ function scrollTo(ctx, params) {
1690
+ const state = ctx.state;
1691
+ const { noScrollingTo, forceScroll, ...scrollTarget } = params;
1692
+ const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1693
+ const {
1694
+ props: { horizontal }
1695
+ } = state;
1696
+ if (state.animFrameCheckFinishedScroll) {
1697
+ cancelAnimationFrame(ctx.state.animFrameCheckFinishedScroll);
1698
+ }
1699
+ if (state.timeoutCheckFinishedScrollFallback) {
1700
+ clearTimeout(ctx.state.timeoutCheckFinishedScrollFallback);
1701
+ }
1702
+ let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, scrollTargetOffset, scrollTarget);
1703
+ offset = clampScrollOffset(ctx, offset, scrollTarget);
1704
+ state.scrollHistory.length = 0;
1705
+ if (!noScrollingTo) {
1706
+ state.scrollingTo = scrollTarget;
1707
+ }
1708
+ state.scrollPending = offset;
1709
+ if (forceScroll || !isInitialScroll || Platform.OS === "android") {
1710
+ doScrollTo(ctx, { animated, horizontal, offset });
1711
+ } else {
1712
+ state.scroll = offset;
1713
+ }
1714
+ }
1715
+
1716
+ // src/core/updateScroll.ts
1717
+ function updateScroll(ctx, newScroll, forceUpdate) {
1718
+ const state = ctx.state;
1719
+ const { scrollingTo, scrollAdjustHandler, lastScrollAdjustForHistory } = state;
1720
+ const prevScroll = state.scroll;
1721
+ state.hasScrolled = true;
1722
+ state.lastBatchingAction = Date.now();
1723
+ const currentTime = Date.now();
1724
+ const adjust = scrollAdjustHandler.getAdjust();
1725
+ const adjustChanged = lastScrollAdjustForHistory !== void 0 && Math.abs(adjust - lastScrollAdjustForHistory) > 0.1;
1726
+ if (adjustChanged) {
1727
+ state.scrollHistory.length = 0;
1728
+ }
1729
+ state.lastScrollAdjustForHistory = adjust;
1730
+ if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
1731
+ if (!adjustChanged) {
1732
+ state.scrollHistory.push({ scroll: newScroll, time: currentTime });
1733
+ }
1734
+ }
1735
+ if (state.scrollHistory.length > 5) {
1736
+ state.scrollHistory.shift();
1737
+ }
1738
+ state.scrollPrev = prevScroll;
1739
+ state.scrollPrevTime = state.scrollTime;
1740
+ state.scroll = newScroll;
1741
+ state.scrollTime = currentTime;
1742
+ const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
1743
+ if (ignoreScrollFromMVCP && !scrollingTo) {
1744
+ const { lt, gt } = ignoreScrollFromMVCP;
1745
+ if (lt && newScroll < lt || gt && newScroll > gt) {
1746
+ state.ignoreScrollFromMVCPIgnored = true;
1747
+ return;
1748
+ }
1749
+ }
1750
+ const scrollDelta = Math.abs(newScroll - prevScroll);
1751
+ const scrollLength = state.scrollLength;
1752
+ const lastCalculated = state.scrollLastCalculate;
1753
+ const useAggressiveItemRecalculation = isInMVCPActiveMode(state);
1754
+ const shouldUpdate = useAggressiveItemRecalculation || forceUpdate || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
1755
+ if (shouldUpdate) {
1756
+ state.scrollLastCalculate = state.scroll;
1757
+ state.ignoreScrollFromMVCPIgnored = false;
1758
+ state.lastScrollDelta = scrollDelta;
1759
+ const runCalculateItems = () => {
1760
+ var _a3;
1761
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1762
+ checkThresholds(ctx);
1763
+ };
1764
+ if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength) {
1765
+ reactDom.flushSync(runCalculateItems);
1766
+ } else {
1767
+ runCalculateItems();
1768
+ }
1769
+ state.dataChangeNeedsScrollUpdate = false;
1770
+ state.lastScrollDelta = 0;
1771
+ }
1772
+ }
1773
+
1774
+ // src/utils/requestAdjust.ts
1775
+ function requestAdjust(ctx, positionDiff, dataChanged) {
1776
+ const state = ctx.state;
1777
+ if (Math.abs(positionDiff) > 0.1) {
1778
+ const doit = () => {
1779
+ {
1780
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
1781
+ if (state.adjustingFromInitialMount) {
1782
+ state.adjustingFromInitialMount--;
1783
+ }
1784
+ }
1785
+ };
1786
+ state.scroll += positionDiff;
1787
+ state.scrollForNextCalculateItemsInView = void 0;
1788
+ const readyToRender = peek$(ctx, "readyToRender");
1789
+ if (readyToRender) {
1790
+ doit();
1791
+ } else {
1792
+ state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
1793
+ requestAnimationFrame(doit);
1794
+ }
1795
+ }
1796
+ }
1797
+
1798
+ // src/core/mvcp.ts
1799
+ var MVCP_POSITION_EPSILON = 0.1;
1800
+ var MVCP_ANCHOR_LOCK_TTL_MS = 300;
1801
+ var MVCP_ANCHOR_LOCK_QUIET_PASSES_TO_RELEASE = 2;
1802
+ function resolveAnchorLock(state, enableMVCPAnchorLock, mvcpData, now) {
1803
+ if (!enableMVCPAnchorLock) {
1804
+ state.mvcpAnchorLock = void 0;
1805
+ return void 0;
1806
+ }
1807
+ const lock = state.mvcpAnchorLock;
1808
+ if (!lock) {
1809
+ return void 0;
1810
+ }
1811
+ const isExpired = now > lock.expiresAt;
1812
+ const isMissing = state.indexByKey.get(lock.id) === void 0;
1813
+ if (isExpired || isMissing || !mvcpData) {
1814
+ state.mvcpAnchorLock = void 0;
1815
+ return void 0;
1816
+ }
1817
+ return lock;
1818
+ }
1819
+ function updateAnchorLock(state, params) {
1820
+ {
1821
+ const { anchorId, anchorPosition, dataChanged, now, positionDiff } = params;
1822
+ const enableMVCPAnchorLock = !!dataChanged || !!state.mvcpAnchorLock;
1823
+ const mvcpData = state.props.maintainVisibleContentPosition.data;
1824
+ if (!enableMVCPAnchorLock || !mvcpData || state.scrollingTo || !anchorId || anchorPosition === void 0) {
1825
+ return;
1826
+ }
1827
+ const existingLock = state.mvcpAnchorLock;
1828
+ const quietPasses = !dataChanged && Math.abs(positionDiff) <= MVCP_POSITION_EPSILON && (existingLock == null ? void 0 : existingLock.id) === anchorId ? existingLock.quietPasses + 1 : 0;
1829
+ if (!dataChanged && quietPasses >= MVCP_ANCHOR_LOCK_QUIET_PASSES_TO_RELEASE) {
1830
+ state.mvcpAnchorLock = void 0;
1831
+ return;
1832
+ }
1833
+ state.mvcpAnchorLock = {
1834
+ expiresAt: now + MVCP_ANCHOR_LOCK_TTL_MS,
1835
+ id: anchorId,
1836
+ position: anchorPosition,
1837
+ quietPasses
1838
+ };
1839
+ }
1840
+ }
1841
+ function prepareMVCP(ctx, dataChanged) {
1842
+ const state = ctx.state;
1843
+ const { idsInView, positions, props } = state;
1844
+ const {
1845
+ maintainVisibleContentPosition: { data: mvcpData, size: mvcpScroll, shouldRestorePosition }
1846
+ } = props;
1847
+ const now = Date.now();
1848
+ const enableMVCPAnchorLock = (!!dataChanged || !!state.mvcpAnchorLock);
1849
+ const scrollingTo = state.scrollingTo;
1850
+ const anchorLock = resolveAnchorLock(state, enableMVCPAnchorLock, mvcpData, now) ;
1851
+ let prevPosition;
1852
+ let targetId;
1853
+ const idsInViewWithPositions = [];
1854
+ const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1855
+ const scrollingToViewPosition = scrollingTo == null ? void 0 : scrollingTo.viewPosition;
1856
+ const isEndAnchoredScrollTarget = scrollTarget !== void 0 && state.props.data.length > 0 && scrollTarget >= state.props.data.length - 1 && (scrollingToViewPosition != null ? scrollingToViewPosition : 0) > 0;
1857
+ const shouldMVCP = dataChanged ? mvcpData : mvcpScroll;
1858
+ const indexByKey = state.indexByKey;
1859
+ if (shouldMVCP) {
1860
+ if (anchorLock && scrollTarget === void 0) {
1861
+ targetId = anchorLock.id;
1862
+ prevPosition = anchorLock.position;
1863
+ } else if (scrollTarget !== void 0) {
1864
+ targetId = getId(state, scrollTarget);
1865
+ } else if (idsInView.length > 0 && state.didContainersLayout && !dataChanged) {
1866
+ targetId = idsInView.find((id) => indexByKey.get(id) !== void 0);
1867
+ }
1868
+ if (dataChanged && idsInView.length > 0 && state.didContainersLayout) {
1869
+ for (let i = 0; i < idsInView.length; i++) {
1870
+ const id = idsInView[i];
1871
+ const index = indexByKey.get(id);
1872
+ if (index !== void 0) {
1873
+ idsInViewWithPositions.push({ id, position: positions.get(id) });
1874
+ }
1875
+ }
1876
+ }
1877
+ if (targetId !== void 0 && prevPosition === void 0) {
1878
+ prevPosition = positions.get(targetId);
1879
+ }
1880
+ return () => {
1881
+ let positionDiff = 0;
1882
+ let anchorIdForLock = anchorLock == null ? void 0 : anchorLock.id;
1883
+ let anchorPositionForLock;
1884
+ let skipTargetAnchor = false;
1885
+ const data = state.props.data;
1886
+ const shouldValidateLockedAnchor = dataChanged && mvcpData && scrollTarget === void 0 && targetId !== void 0 && (anchorLock == null ? void 0 : anchorLock.id) === targetId && shouldRestorePosition !== void 0;
1887
+ if (shouldValidateLockedAnchor && targetId !== void 0) {
1888
+ const index = indexByKey.get(targetId);
1889
+ if (index !== void 0) {
1890
+ const item = data[index];
1891
+ skipTargetAnchor = item === void 0 || !shouldRestorePosition(item, index, data);
1892
+ if (skipTargetAnchor && (anchorLock == null ? void 0 : anchorLock.id) === targetId) {
1893
+ state.mvcpAnchorLock = void 0;
1894
+ }
1895
+ }
1896
+ }
1897
+ const shouldUseFallbackVisibleAnchor = dataChanged && mvcpData && scrollTarget === void 0 && (targetId === void 0 || positions.get(targetId) === void 0 || skipTargetAnchor);
1898
+ if (shouldUseFallbackVisibleAnchor) {
1899
+ for (let i = 0; i < idsInViewWithPositions.length; i++) {
1900
+ const { id, position } = idsInViewWithPositions[i];
1901
+ const index = indexByKey.get(id);
1902
+ if (index !== void 0 && shouldRestorePosition) {
1903
+ const item = data[index];
1904
+ if (item === void 0 || !shouldRestorePosition(item, index, data)) {
1905
+ continue;
1906
+ }
1907
+ }
1908
+ const newPosition = positions.get(id);
1909
+ if (newPosition !== void 0) {
1910
+ positionDiff = newPosition - position;
1911
+ anchorIdForLock = id;
1912
+ anchorPositionForLock = newPosition;
1913
+ break;
1914
+ }
1915
+ }
1916
+ }
1917
+ if (!skipTargetAnchor && targetId !== void 0 && prevPosition !== void 0) {
1918
+ const newPosition = positions.get(targetId);
1919
+ if (newPosition !== void 0) {
1920
+ const totalSize = getContentSize(ctx);
1921
+ let diff = newPosition - prevPosition;
1922
+ if (diff !== 0 && isEndAnchoredScrollTarget && state.scroll + state.scrollLength > totalSize) {
1923
+ if (diff > 0) {
1924
+ diff = Math.max(0, totalSize - state.scroll - state.scrollLength);
1925
+ } else {
1926
+ diff = 0;
1927
+ }
1928
+ }
1929
+ positionDiff = diff;
1930
+ anchorIdForLock = targetId;
1931
+ anchorPositionForLock = newPosition;
1932
+ }
1933
+ }
1934
+ if (scrollingToViewPosition && scrollingToViewPosition > 0) {
1935
+ const newSize = getItemSize(ctx, targetId, scrollTarget, state.props.data[scrollTarget]);
1936
+ const prevSize = scrollingTo == null ? void 0 : scrollingTo.itemSize;
1937
+ if (newSize !== void 0 && prevSize !== void 0 && newSize !== prevSize) {
1938
+ const diff = newSize - prevSize;
1939
+ if (diff !== 0) {
1940
+ positionDiff += diff * scrollingToViewPosition;
1941
+ scrollingTo.itemSize = newSize;
1942
+ }
1943
+ }
1944
+ }
1945
+ updateAnchorLock(state, {
1946
+ anchorId: anchorIdForLock,
1947
+ anchorPosition: anchorPositionForLock,
1948
+ dataChanged,
1949
+ now,
1950
+ positionDiff
1951
+ });
1952
+ if (Math.abs(positionDiff) > MVCP_POSITION_EPSILON) {
1953
+ requestAdjust(ctx, positionDiff);
1954
+ }
1955
+ };
1956
+ }
1957
+ }
1958
+
1959
+ // src/core/prepareColumnStartState.ts
1960
+ function prepareColumnStartState(ctx, startIndex, useAverageSize) {
1961
+ var _a3;
1962
+ const state = ctx.state;
1963
+ const numColumns = peek$(ctx, "numColumns");
1964
+ let rowStartIndex = startIndex;
1965
+ const columnAtStart = state.columns.get(state.idCache[startIndex]);
1966
+ if (columnAtStart !== 1) {
1967
+ rowStartIndex = findRowStartIndex(state, numColumns, startIndex);
1968
+ }
1969
+ let currentRowTop = 0;
1970
+ const curId = state.idCache[rowStartIndex];
1971
+ const column = state.columns.get(curId);
1972
+ if (rowStartIndex > 0) {
1973
+ const prevIndex = rowStartIndex - 1;
1974
+ const prevId = state.idCache[prevIndex];
1975
+ const prevPosition = (_a3 = state.positions.get(prevId)) != null ? _a3 : 0;
1976
+ const prevRowStart = findRowStartIndex(state, numColumns, prevIndex);
1977
+ const prevRowHeight = calculateRowMaxSize(ctx, prevRowStart, prevIndex, useAverageSize);
1978
+ currentRowTop = prevPosition + prevRowHeight;
1979
+ }
1980
+ return {
1981
+ column,
1982
+ currentRowTop,
1983
+ startIndex: rowStartIndex
1984
+ };
1985
+ }
1986
+ function findRowStartIndex(state, numColumns, index) {
1987
+ if (numColumns <= 1) {
1988
+ return Math.max(0, index);
1989
+ }
1990
+ let rowStart = Math.max(0, index);
1991
+ while (rowStart > 0) {
1992
+ const columnForIndex = state.columns.get(state.idCache[rowStart]);
1993
+ if (columnForIndex === 1) {
1994
+ break;
1995
+ }
1996
+ rowStart--;
1997
+ }
1998
+ return rowStart;
1999
+ }
2000
+ function calculateRowMaxSize(ctx, startIndex, endIndex, useAverageSize) {
2001
+ const state = ctx.state;
2002
+ if (endIndex < startIndex) {
2003
+ return 0;
2004
+ }
2005
+ const { data } = state.props;
2006
+ if (!data) {
2007
+ return 0;
2008
+ }
2009
+ let maxSize = 0;
2010
+ for (let i = startIndex; i <= endIndex; i++) {
2011
+ if (i < 0 || i >= data.length) {
2012
+ continue;
2013
+ }
2014
+ const id = state.idCache[i];
2015
+ const size = getItemSize(ctx, id, i, data[i], useAverageSize);
2016
+ if (size > maxSize) {
2017
+ maxSize = size;
2018
+ }
2019
+ }
2020
+ return maxSize;
2021
+ }
2022
+
2023
+ // src/core/updateTotalSize.ts
2024
+ function updateTotalSize(ctx) {
2025
+ var _a3, _b, _c;
2026
+ const state = ctx.state;
2027
+ const {
2028
+ positions,
2029
+ props: { data }
2030
+ } = state;
2031
+ const numColumns = (_a3 = peek$(ctx, "numColumns")) != null ? _a3 : 1;
2032
+ if (data.length === 0) {
2033
+ addTotalSize(ctx, null, 0);
2034
+ } else {
2035
+ const lastId = getId(state, data.length - 1);
2036
+ if (lastId !== void 0) {
2037
+ const lastPosition = positions.get(lastId);
2038
+ if (lastPosition !== void 0) {
2039
+ if (numColumns > 1) {
2040
+ let rowStart = data.length - 1;
2041
+ while (rowStart > 0) {
2042
+ const rowId = (_b = state.idCache[rowStart]) != null ? _b : getId(state, rowStart);
2043
+ const column = state.columns.get(rowId);
2044
+ if (column === 1 || column === void 0) {
2045
+ break;
2046
+ }
2047
+ rowStart -= 1;
2048
+ }
2049
+ let maxSize = 0;
2050
+ for (let i = rowStart; i < data.length; i++) {
2051
+ const rowId = (_c = state.idCache[i]) != null ? _c : getId(state, i);
2052
+ const size = getItemSize(ctx, rowId, i, data[i]);
2053
+ if (size > maxSize) {
2054
+ maxSize = size;
2055
+ }
2056
+ }
2057
+ addTotalSize(ctx, null, lastPosition + maxSize);
2058
+ } else {
2059
+ const lastSize = getItemSize(ctx, lastId, data.length - 1, data[data.length - 1]);
2060
+ if (lastSize !== void 0) {
2061
+ const totalSize = lastPosition + lastSize;
2062
+ addTotalSize(ctx, null, totalSize);
2063
+ }
2064
+ }
2065
+ }
2066
+ }
2067
+ }
2068
+ }
2069
+
2070
+ // src/utils/getScrollVelocity.ts
2071
+ var getScrollVelocity = (state) => {
2072
+ const { scrollHistory } = state;
2073
+ const newestIndex = scrollHistory.length - 1;
2074
+ if (newestIndex < 1) {
2075
+ return 0;
2076
+ }
2077
+ const newest = scrollHistory[newestIndex];
2078
+ const now = Date.now();
2079
+ let direction = 0;
2080
+ for (let i = newestIndex; i > 0; i--) {
2081
+ const delta = scrollHistory[i].scroll - scrollHistory[i - 1].scroll;
2082
+ if (delta !== 0) {
2083
+ direction = Math.sign(delta);
2084
+ break;
2085
+ }
2086
+ }
2087
+ if (direction === 0) {
2088
+ return 0;
2089
+ }
2090
+ let oldest = newest;
2091
+ for (let i = newestIndex - 1; i >= 0; i--) {
2092
+ const current = scrollHistory[i];
2093
+ const next = scrollHistory[i + 1];
2094
+ const delta = next.scroll - current.scroll;
2095
+ const deltaSign = Math.sign(delta);
2096
+ if (deltaSign !== 0 && deltaSign !== direction) {
2097
+ break;
2098
+ }
2099
+ if (now - current.time > 1e3) {
2100
+ break;
2101
+ }
2102
+ oldest = current;
2103
+ }
2104
+ const scrollDiff = newest.scroll - oldest.scroll;
2105
+ const timeDiff = newest.time - oldest.time;
2106
+ return timeDiff > 0 ? scrollDiff / timeDiff : 0;
2107
+ };
2108
+
2109
+ // src/utils/updateSnapToOffsets.ts
2110
+ function updateSnapToOffsets(ctx) {
2111
+ const state = ctx.state;
2112
+ const {
2113
+ positions,
2114
+ props: { snapToIndices }
2115
+ } = state;
2116
+ const snapToOffsets = Array(snapToIndices.length);
2117
+ for (let i = 0; i < snapToIndices.length; i++) {
2118
+ const idx = snapToIndices[i];
2119
+ const key = getId(state, idx);
2120
+ snapToOffsets[i] = positions.get(key);
2121
+ }
2122
+ set$(ctx, "snapToOffsets", snapToOffsets);
2123
+ }
2124
+
2125
+ // src/core/updateItemPositions.ts
2126
+ function updateItemPositions(ctx, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP } = {
2127
+ doMVCP: false,
2128
+ forceFullUpdate: false,
2129
+ scrollBottomBuffered: -1,
2130
+ startIndex: 0
2131
+ }) {
2132
+ var _a3, _b, _c, _d, _e, _f;
2133
+ const state = ctx.state;
2134
+ const {
2135
+ columns,
2136
+ columnSpans,
2137
+ indexByKey,
2138
+ positions,
2139
+ idCache,
2140
+ sizesKnown,
2141
+ props: { data, getEstimatedItemSize, overrideItemLayout, snapToIndices },
2142
+ scrollingTo
2143
+ } = state;
2144
+ const dataLength = data.length;
2145
+ const numColumns = (_a3 = peek$(ctx, "numColumns")) != null ? _a3 : 1;
2146
+ const hasColumns = numColumns > 1;
2147
+ const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
2148
+ const extraData = peek$(ctx, "extraData");
2149
+ const layoutConfig = overrideItemLayout ? { span: 1 } : void 0;
2150
+ const lastScrollDelta = state.lastScrollDelta;
2151
+ const velocity = getScrollVelocity(state);
2152
+ const shouldOptimize = !forceFullUpdate && !dataChanged && (Math.abs(velocity) > 0 || state.scrollLength > 0 && lastScrollDelta > state.scrollLength);
2153
+ const maxVisibleArea = scrollBottomBuffered + 1e3;
2154
+ const useAverageSize = !getEstimatedItemSize;
2155
+ const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_b = peek$(ctx, "scrollAdjustPending")) != null ? _b : 0) !== 0;
2156
+ let currentRowTop = 0;
2157
+ let column = 1;
2158
+ let maxSizeInRow = 0;
2159
+ if (dataChanged) {
2160
+ columnSpans.clear();
2161
+ }
2162
+ if (startIndex > 0) {
2163
+ if (hasColumns) {
2164
+ const { startIndex: processedStartIndex, currentRowTop: initialRowTop } = prepareColumnStartState(
2165
+ ctx,
2166
+ startIndex,
2167
+ useAverageSize
2168
+ );
2169
+ startIndex = processedStartIndex;
2170
+ currentRowTop = initialRowTop;
2171
+ } else if (startIndex < dataLength) {
2172
+ const prevIndex = startIndex - 1;
2173
+ const prevId = getId(state, prevIndex);
2174
+ const prevPosition = (_c = positions.get(prevId)) != null ? _c : 0;
2175
+ const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(ctx, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
2176
+ currentRowTop = prevPosition + prevSize;
2177
+ }
2178
+ }
2179
+ const needsIndexByKey = dataChanged || indexByKey.size === 0;
2180
+ let didBreakEarly = false;
2181
+ let breakAt;
2182
+ for (let i = startIndex; i < dataLength; i++) {
2183
+ if (shouldOptimize && breakAt !== void 0 && i > breakAt) {
2184
+ didBreakEarly = true;
2185
+ break;
2186
+ }
2187
+ if (shouldOptimize && breakAt === void 0 && !scrollingTo && !dataChanged && currentRowTop > maxVisibleArea) {
2188
+ const itemsPerRow = hasColumns ? numColumns : 1;
2189
+ breakAt = i + itemsPerRow + 10;
2190
+ }
2191
+ const id = (_e = idCache[i]) != null ? _e : getId(state, i);
2192
+ let span = 1;
2193
+ if (hasColumns && overrideItemLayout && layoutConfig) {
2194
+ layoutConfig.span = 1;
2195
+ overrideItemLayout(layoutConfig, data[i], i, numColumns, extraData);
2196
+ const requestedSpan = layoutConfig.span;
2197
+ if (requestedSpan !== void 0 && Number.isFinite(requestedSpan)) {
2198
+ span = Math.max(1, Math.min(numColumns, Math.round(requestedSpan)));
2199
+ }
2200
+ }
2201
+ if (hasColumns && column + span - 1 > numColumns) {
2202
+ currentRowTop += maxSizeInRow;
2203
+ column = 1;
2204
+ maxSizeInRow = 0;
2205
+ }
2206
+ const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(ctx, id, i, data[i], useAverageSize, preferCachedSize);
2207
+ if (IS_DEV && needsIndexByKey) {
2208
+ if (indexByKeyForChecking.has(id)) {
2209
+ console.error(
2210
+ `[legend-list] Error: Detected overlapping key (${id}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`
2211
+ );
2212
+ }
2213
+ indexByKeyForChecking.set(id, i);
2214
+ }
2215
+ if (currentRowTop !== positions.get(id)) {
2216
+ positions.set(id, currentRowTop);
2217
+ notifyPosition$(ctx, id, currentRowTop);
2218
+ }
2219
+ if (needsIndexByKey) {
2220
+ indexByKey.set(id, i);
2221
+ }
2222
+ columns.set(id, column);
2223
+ columnSpans.set(id, span);
2224
+ if (hasColumns) {
2225
+ if (size > maxSizeInRow) {
2226
+ maxSizeInRow = size;
2227
+ }
2228
+ column += span;
2229
+ if (column > numColumns) {
2230
+ currentRowTop += maxSizeInRow;
2231
+ column = 1;
2232
+ maxSizeInRow = 0;
2233
+ }
2234
+ } else {
2235
+ currentRowTop += size;
2236
+ }
2237
+ }
2238
+ if (!didBreakEarly) {
2239
+ updateTotalSize(ctx);
2240
+ }
2241
+ if (snapToIndices) {
2242
+ updateSnapToOffsets(ctx);
2243
+ }
2244
+ }
2245
+
2246
+ // src/core/viewability.ts
2247
+ function ensureViewabilityState(ctx, configId) {
2248
+ let map = ctx.mapViewabilityConfigStates;
2249
+ if (!map) {
2250
+ map = /* @__PURE__ */ new Map();
2251
+ ctx.mapViewabilityConfigStates = map;
2252
+ }
2253
+ let state = map.get(configId);
2254
+ if (!state) {
2255
+ state = { end: -1, previousEnd: -1, previousStart: -1, start: -1, viewableItems: [] };
2256
+ map.set(configId, state);
2257
+ }
2258
+ return state;
2259
+ }
2260
+ function setupViewability(props) {
2261
+ let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
2262
+ if (viewabilityConfig || onViewableItemsChanged) {
2263
+ viewabilityConfigCallbackPairs = [
2264
+ ...viewabilityConfigCallbackPairs || [],
2265
+ {
2266
+ onViewableItemsChanged,
2267
+ viewabilityConfig: viewabilityConfig || {
2268
+ viewAreaCoveragePercentThreshold: 0
2269
+ }
2270
+ }
2271
+ ];
2272
+ }
2273
+ return viewabilityConfigCallbackPairs;
2274
+ }
2275
+ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
2276
+ const {
2277
+ timeouts,
2278
+ props: { data }
2279
+ } = state;
2280
+ for (const viewabilityConfigCallbackPair of viewabilityConfigCallbackPairs) {
2281
+ const viewabilityState = ensureViewabilityState(ctx, viewabilityConfigCallbackPair.viewabilityConfig.id);
2282
+ viewabilityState.start = start;
2283
+ viewabilityState.end = end;
2284
+ if (viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime) {
2285
+ const timer = setTimeout(() => {
2286
+ timeouts.delete(timer);
2287
+ updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
2288
+ }, viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime);
2289
+ timeouts.add(timer);
2290
+ } else {
2291
+ updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize);
2292
+ }
2293
+ }
2294
+ }
2295
+ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize) {
2296
+ const { viewabilityConfig, onViewableItemsChanged } = viewabilityConfigCallbackPair;
2297
+ const configId = viewabilityConfig.id;
2298
+ const viewabilityState = ensureViewabilityState(ctx, configId);
2299
+ const { viewableItems: previousViewableItems, start, end } = viewabilityState;
2300
+ const viewabilityTokens = /* @__PURE__ */ new Map();
2301
+ for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
2302
+ viewabilityTokens.set(
2303
+ containerId,
2304
+ computeViewability(
2305
+ state,
2306
+ ctx,
2307
+ viewabilityConfig,
2308
+ containerId,
2309
+ value.key,
2310
+ scrollSize,
2311
+ value.item,
2312
+ value.index
2313
+ )
2314
+ );
2315
+ }
2316
+ const changed = [];
2317
+ if (previousViewableItems) {
2318
+ for (const viewToken of previousViewableItems) {
2319
+ const containerId = findContainerId(ctx, viewToken.key);
2320
+ if (!checkIsViewable(
2321
+ state,
2322
+ ctx,
2323
+ viewabilityConfig,
2324
+ containerId,
2325
+ viewToken.key,
2326
+ scrollSize,
2327
+ viewToken.item,
2328
+ viewToken.index
2329
+ )) {
2330
+ viewToken.isViewable = false;
2331
+ changed.push(viewToken);
2332
+ }
2333
+ }
2334
+ }
2335
+ const viewableItems = [];
2336
+ for (let i = start; i <= end; i++) {
2337
+ const item = data[i];
2338
+ if (item) {
2339
+ const key = getId(state, i);
2340
+ const containerId = findContainerId(ctx, key);
2341
+ if (checkIsViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, i)) {
2342
+ const viewToken = {
2343
+ containerId,
2344
+ index: i,
2345
+ isViewable: true,
2346
+ item,
2347
+ key
2348
+ };
2349
+ viewableItems.push(viewToken);
2350
+ if (!(previousViewableItems == null ? void 0 : previousViewableItems.find((v) => v.key === viewToken.key))) {
2351
+ changed.push(viewToken);
2352
+ }
2353
+ }
2354
+ }
2355
+ }
2356
+ Object.assign(viewabilityState, {
2357
+ previousEnd: end,
2358
+ previousStart: start,
2359
+ viewableItems
2360
+ });
2361
+ if (changed.length > 0) {
2362
+ viewabilityState.viewableItems = viewableItems;
2363
+ for (let i = 0; i < changed.length; i++) {
2364
+ const change = changed[i];
2365
+ maybeUpdateViewabilityCallback(ctx, configId, change.containerId, change);
2366
+ }
2367
+ if (onViewableItemsChanged) {
2368
+ onViewableItemsChanged({ changed, viewableItems });
2369
+ }
2370
+ }
2371
+ for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
2372
+ if (value.sizeVisible < 0) {
2373
+ ctx.mapViewabilityAmountValues.delete(containerId);
2374
+ }
2375
+ }
2376
+ }
2377
+ function shallowEqual(prev, next) {
2378
+ if (!prev) return false;
2379
+ const keys = Object.keys(next);
2380
+ for (let i = 0; i < keys.length; i++) {
2381
+ const k = keys[i];
2382
+ if (prev[k] !== next[k]) return false;
2383
+ }
2384
+ return true;
2385
+ }
2386
+ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
2387
+ const { sizes, positions, scroll: scrollState } = state;
2388
+ const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2389
+ const { itemVisiblePercentThreshold, viewAreaCoveragePercentThreshold } = viewabilityConfig;
2390
+ const viewAreaMode = viewAreaCoveragePercentThreshold != null;
2391
+ const viewablePercentThreshold = viewAreaMode ? viewAreaCoveragePercentThreshold : itemVisiblePercentThreshold;
2392
+ const scroll = scrollState - topPad;
2393
+ const top = positions.get(key) - scroll;
2394
+ const size = sizes.get(key) || 0;
2395
+ const bottom = top + size;
2396
+ const isEntirelyVisible = top >= 0 && bottom <= scrollSize && bottom > top;
2397
+ const sizeVisible = isEntirelyVisible ? size : Math.min(bottom, scrollSize) - Math.max(top, 0);
2398
+ const percentVisible = size ? isEntirelyVisible ? 100 : 100 * (sizeVisible / size) : 0;
2399
+ const percentOfScroller = size ? 100 * (sizeVisible / scrollSize) : 0;
2400
+ const percent = isEntirelyVisible ? 100 : viewAreaMode ? percentOfScroller : percentVisible;
2401
+ const isViewable = percent >= viewablePercentThreshold;
2402
+ const value = {
2403
+ containerId,
2404
+ index,
2405
+ isViewable,
2406
+ item,
2407
+ key,
2408
+ percentOfScroller,
2409
+ percentVisible,
2410
+ scrollSize,
2411
+ size,
2412
+ sizeVisible
2413
+ };
2414
+ const prev = ctx.mapViewabilityAmountValues.get(containerId);
2415
+ if (!shallowEqual(prev, value)) {
2416
+ ctx.mapViewabilityAmountValues.set(containerId, value);
2417
+ const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
2418
+ if (cb) {
2419
+ cb(value);
2420
+ }
2421
+ }
2422
+ return value;
2423
+ }
2424
+ function checkIsViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
2425
+ let value = ctx.mapViewabilityAmountValues.get(containerId);
2426
+ if (!value || value.key !== key) {
2427
+ value = computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
2428
+ }
2429
+ return value.isViewable;
2430
+ }
2431
+ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
2432
+ const key = containerId + configId;
2433
+ ctx.mapViewabilityValues.set(key, viewToken);
2434
+ const cb = ctx.mapViewabilityCallbacks.get(key);
2435
+ cb == null ? void 0 : cb(viewToken);
2436
+ }
2437
+
2438
+ // src/utils/checkAllSizesKnown.ts
2439
+ function isNullOrUndefined2(value) {
2440
+ return value === null || value === void 0;
2441
+ }
2442
+ function checkAllSizesKnown(state) {
2443
+ const { startBuffered, endBuffered, sizesKnown } = state;
2444
+ if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
2445
+ let areAllKnown = true;
2446
+ for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
2447
+ const key = getId(state, i);
2448
+ areAllKnown && (areAllKnown = sizesKnown.has(key));
2449
+ }
2450
+ return areAllKnown;
2451
+ }
2452
+ return false;
2453
+ }
2454
+
2455
+ // src/utils/findAvailableContainers.ts
2456
+ function findAvailableContainers(ctx, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
2457
+ const numContainers = peek$(ctx, "numContainers");
2458
+ const state = ctx.state;
2459
+ const { stickyContainerPool, containerItemTypes } = state;
2460
+ const result = [];
2461
+ const availableContainers = [];
2462
+ const pendingRemovalSet = new Set(pendingRemoval);
2463
+ let pendingRemovalChanged = false;
2464
+ const stickyIndicesSet = state.props.stickyIndicesSet;
2465
+ const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
2466
+ const canReuseContainer = (containerIndex, requiredType) => {
2467
+ if (!requiredType) return true;
2468
+ const existingType = containerItemTypes.get(containerIndex);
2469
+ if (!existingType) return true;
2470
+ return existingType === requiredType;
2471
+ };
2472
+ const neededTypes = requiredItemTypes ? [...requiredItemTypes] : [];
2473
+ let typeIndex = 0;
2474
+ for (let i = 0; i < stickyItemIndices.length; i++) {
2475
+ const requiredType = neededTypes[typeIndex];
2476
+ let foundContainer = false;
2477
+ for (const containerIndex of stickyContainerPool) {
2478
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
2479
+ const isPendingRemoval = pendingRemovalSet.has(containerIndex);
2480
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType) && !result.includes(containerIndex)) {
2481
+ result.push(containerIndex);
2482
+ if (isPendingRemoval && pendingRemovalSet.delete(containerIndex)) {
2483
+ pendingRemovalChanged = true;
2484
+ }
2485
+ foundContainer = true;
2486
+ if (requiredItemTypes) typeIndex++;
2487
+ break;
2488
+ }
2489
+ }
2490
+ if (!foundContainer) {
2491
+ const newContainerIndex = numContainers + result.filter((index) => index >= numContainers).length;
2492
+ result.push(newContainerIndex);
2493
+ stickyContainerPool.add(newContainerIndex);
2494
+ if (requiredItemTypes) typeIndex++;
2495
+ }
2496
+ }
2497
+ for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
2498
+ if (stickyContainerPool.has(u)) {
2499
+ continue;
2500
+ }
2501
+ const key = peek$(ctx, `containerItemKey${u}`);
2502
+ const requiredType = neededTypes[typeIndex];
2503
+ const isPending = key !== void 0 && pendingRemovalSet.has(u);
2504
+ const canUse = key === void 0 || isPending && canReuseContainer(u, requiredType);
2505
+ if (canUse) {
2506
+ if (isPending) {
2507
+ pendingRemovalSet.delete(u);
2508
+ pendingRemovalChanged = true;
2509
+ }
2510
+ result.push(u);
2511
+ if (requiredItemTypes) {
2512
+ typeIndex++;
2513
+ }
2514
+ }
2515
+ }
2516
+ for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
2517
+ if (stickyContainerPool.has(u)) {
2518
+ continue;
2519
+ }
2520
+ const key = peek$(ctx, `containerItemKey${u}`);
2521
+ if (key === void 0) continue;
2522
+ const index = state.indexByKey.get(key);
2523
+ const isOutOfView = index < startBuffered || index > endBuffered;
2524
+ if (isOutOfView) {
2525
+ const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
2526
+ if (!requiredItemTypes || typeIndex < neededTypes.length && canReuseContainer(u, neededTypes[typeIndex])) {
2527
+ availableContainers.push({ distance, index: u });
2528
+ }
2529
+ }
2530
+ }
2531
+ const remaining = numNeeded - result.length;
2532
+ if (remaining > 0) {
2533
+ if (availableContainers.length > 0) {
2534
+ if (availableContainers.length > remaining) {
2535
+ availableContainers.sort(comparatorByDistance);
2536
+ availableContainers.length = remaining;
2537
+ }
2538
+ for (const container of availableContainers) {
2539
+ result.push(container.index);
2540
+ if (requiredItemTypes) {
2541
+ typeIndex++;
2542
+ }
2543
+ }
2544
+ }
2545
+ const stillNeeded = numNeeded - result.length;
2546
+ if (stillNeeded > 0) {
2547
+ for (let i = 0; i < stillNeeded; i++) {
2548
+ result.push(numContainers + i);
2549
+ }
2550
+ if (IS_DEV && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
2551
+ console.warn(
2552
+ "[legend-list] No unused container available, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize or increasing initialContainerPoolRatio.",
2553
+ {
2554
+ debugInfo: {
2555
+ numContainers,
2556
+ numContainersPooled: peek$(ctx, "numContainersPooled"),
2557
+ numNeeded,
2558
+ stillNeeded
2559
+ }
2560
+ }
2561
+ );
2562
+ }
2563
+ }
2564
+ }
2565
+ if (pendingRemovalChanged) {
2566
+ pendingRemoval.length = 0;
2567
+ for (const value of pendingRemovalSet) {
2568
+ pendingRemoval.push(value);
2569
+ }
2570
+ }
2571
+ return result.sort(comparatorDefault);
2572
+ }
2573
+ function comparatorByDistance(a, b) {
2574
+ return b.distance - a.distance;
2575
+ }
2576
+
2577
+ // src/core/scrollToIndex.ts
2578
+ function scrollToIndex(ctx, { index, viewOffset = 0, animated = true, viewPosition }) {
2579
+ const state = ctx.state;
2580
+ const { data } = state.props;
2581
+ if (index >= data.length) {
2582
+ index = data.length - 1;
2583
+ } else if (index < 0) {
2584
+ index = 0;
2585
+ }
2586
+ const firstIndexOffset = calculateOffsetForIndex(ctx, index);
2587
+ const isLast = index === data.length - 1;
2588
+ if (isLast && viewPosition === void 0) {
2589
+ viewPosition = 1;
2590
+ }
2591
+ state.scrollForNextCalculateItemsInView = void 0;
2592
+ const targetId = getId(state, index);
2593
+ const itemSize = getItemSize(ctx, targetId, index, state.props.data[index]);
2594
+ scrollTo(ctx, {
2595
+ animated,
2596
+ index,
2597
+ itemSize,
2598
+ offset: firstIndexOffset,
2599
+ viewOffset,
2600
+ viewPosition: viewPosition != null ? viewPosition : 0
2601
+ });
2602
+ }
2603
+
2604
+ // src/utils/setDidLayout.ts
2605
+ function setDidLayout(ctx) {
2606
+ const state = ctx.state;
2607
+ const { initialScroll } = state;
2608
+ state.queuedInitialLayout = true;
2609
+ checkAtBottom(ctx);
2610
+ if ((initialScroll == null ? void 0 : initialScroll.index) !== void 0) {
2611
+ const target = initialScroll;
2612
+ const runScroll = () => scrollToIndex(ctx, { ...target, animated: false });
2613
+ runScroll();
2614
+ requestAnimationFrame(runScroll);
2615
+ }
2616
+ setInitialRenderState(ctx, { didLayout: true });
2617
+ }
2618
+
2619
+ // src/core/calculateItemsInView.ts
2620
+ function findCurrentStickyIndex(stickyArray, scroll, state) {
2621
+ var _a3;
2622
+ const idCache = state.idCache;
2623
+ const positions = state.positions;
2624
+ for (let i = stickyArray.length - 1; i >= 0; i--) {
2625
+ const stickyIndex = stickyArray[i];
2626
+ const stickyId = (_a3 = idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
2627
+ const stickyPos = stickyId ? positions.get(stickyId) : void 0;
2628
+ if (stickyPos !== void 0 && scroll >= stickyPos) {
2629
+ return i;
2630
+ }
2631
+ }
2632
+ return -1;
2633
+ }
2634
+ function getActiveStickyIndices(ctx, stickyHeaderIndices) {
2635
+ const state = ctx.state;
2636
+ return new Set(
2637
+ Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyHeaderIndices.has(idx))
2638
+ );
2639
+ }
2640
+ function handleStickyActivation(ctx, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, needNewContainersSet, startBuffered, endBuffered) {
2641
+ var _a3;
2642
+ const state = ctx.state;
2643
+ const activeIndices = getActiveStickyIndices(ctx, stickyHeaderIndices);
2644
+ set$(ctx, "activeStickyIndex", currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : -1);
2645
+ for (let offset = 0; offset <= 1; offset++) {
2646
+ const idx = currentStickyIdx - offset;
2647
+ if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
2648
+ const stickyIndex = stickyArray[idx];
2649
+ const stickyId = (_a3 = state.idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
2650
+ if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered) && !needNewContainersSet.has(stickyIndex)) {
2651
+ needNewContainersSet.add(stickyIndex);
2652
+ needNewContainers.push(stickyIndex);
2653
+ }
2654
+ }
2655
+ }
2656
+ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentStickyIdx, pendingRemoval, alwaysRenderIndicesSet) {
2657
+ var _a3, _b, _c;
2658
+ const state = ctx.state;
2659
+ for (const containerIndex of state.stickyContainerPool) {
2660
+ const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
2661
+ const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
2662
+ if (itemIndex === void 0) continue;
2663
+ if (alwaysRenderIndicesSet.has(itemIndex)) continue;
2664
+ const arrayIdx = stickyArray.indexOf(itemIndex);
2665
+ if (arrayIdx === -1) {
2666
+ state.stickyContainerPool.delete(containerIndex);
2667
+ set$(ctx, `containerSticky${containerIndex}`, false);
2668
+ continue;
2669
+ }
2670
+ const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
2671
+ if (isRecentSticky) continue;
2672
+ const nextIndex = stickyArray[arrayIdx + 1];
2673
+ let shouldRecycle = false;
2674
+ if (nextIndex) {
2675
+ const nextId = (_a3 = state.idCache[nextIndex]) != null ? _a3 : getId(state, nextIndex);
2676
+ const nextPos = nextId ? state.positions.get(nextId) : void 0;
2677
+ shouldRecycle = nextPos !== void 0 && scroll > nextPos + drawDistance * 2;
2678
+ } else {
2679
+ const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
2680
+ if (currentId) {
2681
+ const currentPos = state.positions.get(currentId);
2682
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, currentId, itemIndex, state.props.data[itemIndex]);
2683
+ shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + drawDistance * 3;
2684
+ }
2685
+ }
2686
+ if (shouldRecycle) {
2687
+ pendingRemoval.push(containerIndex);
2688
+ }
2689
+ }
2690
+ }
2691
+ function calculateItemsInView(ctx, params = {}) {
2692
+ const state = ctx.state;
2693
+ reactDom.unstable_batchedUpdates(() => {
2694
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
2695
+ const {
2696
+ columns,
2697
+ columnSpans,
2698
+ containerItemKeys,
2699
+ enableScrollForNextCalculateItemsInView,
2700
+ idCache,
2701
+ indexByKey,
2702
+ initialScroll,
2703
+ minIndexSizeChanged,
2704
+ positions,
2705
+ props: {
2706
+ alwaysRenderIndicesArr,
2707
+ alwaysRenderIndicesSet,
2708
+ drawDistance,
2709
+ getItemType,
2710
+ itemsAreEqual,
2711
+ keyExtractor,
2712
+ onStickyHeaderChange
2713
+ },
2714
+ scrollForNextCalculateItemsInView,
2715
+ scrollLength,
2716
+ sizes,
2717
+ startBufferedId: startBufferedIdOrig,
2718
+ viewabilityConfigCallbackPairs
2719
+ } = state;
2720
+ const { data } = state.props;
2721
+ const stickyIndicesArr = state.props.stickyIndicesArr || [];
2722
+ const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
2723
+ const alwaysRenderArr = alwaysRenderIndicesArr || [];
2724
+ const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
2725
+ const { dataChanged, doMVCP, forceFullItemPositions } = params;
2726
+ const prevNumContainers = peek$(ctx, "numContainers");
2727
+ if (!data || scrollLength === 0 || !prevNumContainers) {
2728
+ return;
2729
+ }
2730
+ const totalSize = getContentSize(ctx);
2731
+ const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
2732
+ const numColumns = peek$(ctx, "numColumns");
2733
+ const speed = getScrollVelocity(state);
2734
+ const scrollExtra = 0;
2735
+ const { queuedInitialLayout } = state;
2736
+ let { scroll: scrollState } = state;
2737
+ if (!queuedInitialLayout && initialScroll) {
2738
+ const updatedOffset = calculateOffsetWithOffsetPosition(
2739
+ ctx,
2740
+ calculateOffsetForIndex(ctx, initialScroll.index),
2741
+ initialScroll
2742
+ );
2743
+ scrollState = updatedOffset;
2744
+ }
2745
+ const scrollAdjustPending = (_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0;
2746
+ const scrollAdjustPad = scrollAdjustPending - topPad;
2747
+ let scroll = Math.round(scrollState + scrollExtra + scrollAdjustPad);
2748
+ if (scroll + scrollLength > totalSize) {
2749
+ scroll = Math.max(0, totalSize - scrollLength);
2750
+ }
2751
+ const previousStickyIndex = peek$(ctx, "activeStickyIndex");
2752
+ const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
2753
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : -1;
2754
+ if (currentStickyIdx >= 0 || previousStickyIndex >= 0) {
2755
+ set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
2756
+ }
2757
+ let scrollBufferTop = drawDistance;
2758
+ let scrollBufferBottom = drawDistance;
2759
+ if (speed > 0 || speed === 0 && scroll < Math.max(50, drawDistance)) {
2760
+ scrollBufferTop = drawDistance * 0.5;
2761
+ scrollBufferBottom = drawDistance * 1.5;
2762
+ } else {
2763
+ scrollBufferTop = drawDistance * 1.5;
2764
+ scrollBufferBottom = drawDistance * 0.5;
2765
+ }
2766
+ const scrollTopBuffered = scroll - scrollBufferTop;
2767
+ const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
2768
+ const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
2769
+ if (!dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
2770
+ const { top, bottom } = scrollForNextCalculateItemsInView;
2771
+ if (top === null && bottom === null) {
2772
+ state.scrollForNextCalculateItemsInView = void 0;
2773
+ } else if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
2774
+ if (!isInMVCPActiveMode(state)) {
2775
+ return;
2776
+ }
2777
+ }
2778
+ }
2779
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, dataChanged) : void 0;
2780
+ if (dataChanged) {
2781
+ indexByKey.clear();
2782
+ idCache.length = 0;
2783
+ positions.clear();
2784
+ }
2785
+ const startIndex = forceFullItemPositions || dataChanged ? 0 : (_b = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _b : 0;
2786
+ updateItemPositions(ctx, dataChanged, {
2787
+ doMVCP,
2788
+ forceFullUpdate: !!forceFullItemPositions,
2789
+ scrollBottomBuffered,
2790
+ startIndex
2791
+ });
2792
+ if (minIndexSizeChanged !== void 0) {
2793
+ state.minIndexSizeChanged = void 0;
2794
+ }
2795
+ checkMVCP == null ? void 0 : checkMVCP();
2796
+ let startNoBuffer = null;
2797
+ let startBuffered = null;
2798
+ let startBufferedId = null;
2799
+ let endNoBuffer = null;
2800
+ let endBuffered = null;
2801
+ let loopStart = !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2802
+ for (let i = loopStart; i >= 0; i--) {
2803
+ const id = (_c = idCache[i]) != null ? _c : getId(state, i);
2804
+ const top = positions.get(id);
2805
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(ctx, id, i, data[i]);
2806
+ const bottom = top + size;
2807
+ if (bottom > scroll - scrollBufferTop) {
2808
+ loopStart = i;
2809
+ } else {
2810
+ break;
2811
+ }
2812
+ }
2813
+ if (numColumns > 1) {
2814
+ while (loopStart > 0) {
2815
+ const loopId = (_e = idCache[loopStart]) != null ? _e : getId(state, loopStart);
2816
+ const loopColumn = columns.get(loopId);
2817
+ if (loopColumn === 1 || loopColumn === void 0) {
2818
+ break;
2819
+ }
2820
+ loopStart -= 1;
2821
+ }
2822
+ }
2823
+ let foundEnd = false;
2824
+ let nextTop;
2825
+ let nextBottom;
2826
+ let maxIndexRendered = 0;
2827
+ for (let i = 0; i < prevNumContainers; i++) {
2828
+ const key = peek$(ctx, `containerItemKey${i}`);
2829
+ if (key !== void 0) {
2830
+ const index = indexByKey.get(key);
2831
+ maxIndexRendered = Math.max(maxIndexRendered, index);
2832
+ }
2833
+ }
2834
+ let firstFullyOnScreenIndex;
2835
+ const dataLength = data.length;
2836
+ for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
2837
+ const id = (_f = idCache[i]) != null ? _f : getId(state, i);
2838
+ const size = (_g = sizes.get(id)) != null ? _g : getItemSize(ctx, id, i, data[i]);
2839
+ const top = positions.get(id);
2840
+ if (!foundEnd) {
2841
+ if (startNoBuffer === null && top + size > scroll) {
2842
+ startNoBuffer = i;
2843
+ }
2844
+ if (firstFullyOnScreenIndex === void 0 && top >= scroll - 10) {
2845
+ firstFullyOnScreenIndex = i;
2846
+ }
2847
+ if (startBuffered === null && top + size > scrollTopBuffered) {
2848
+ startBuffered = i;
2849
+ startBufferedId = id;
2850
+ if (scrollTopBuffered < 0) {
2851
+ nextTop = null;
2852
+ } else {
2853
+ nextTop = top;
2854
+ }
2855
+ }
2856
+ if (startNoBuffer !== null) {
2857
+ if (top <= scrollBottom) {
2858
+ endNoBuffer = i;
2859
+ }
2860
+ if (top <= scrollBottomBuffered) {
2861
+ endBuffered = i;
2862
+ if (scrollBottomBuffered > totalSize) {
2863
+ nextBottom = null;
2864
+ } else {
2865
+ nextBottom = top + size;
2866
+ }
2867
+ } else {
2868
+ foundEnd = true;
2869
+ }
2870
+ }
2871
+ }
2872
+ }
2873
+ const idsInView = [];
2874
+ for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
2875
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
2876
+ idsInView.push(id);
2877
+ }
2878
+ Object.assign(state, {
2879
+ endBuffered,
2880
+ endNoBuffer,
2881
+ firstFullyOnScreenIndex,
2882
+ idsInView,
2883
+ startBuffered,
2884
+ startBufferedId,
2885
+ startNoBuffer
2886
+ });
2887
+ if (enableScrollForNextCalculateItemsInView && nextTop !== void 0 && nextBottom !== void 0) {
2888
+ state.scrollForNextCalculateItemsInView = isNullOrUndefined(nextTop) && isNullOrUndefined(nextBottom) ? void 0 : {
2889
+ bottom: nextBottom,
2890
+ top: nextTop
2891
+ };
2892
+ }
2893
+ let numContainers = prevNumContainers;
2894
+ const pendingRemoval = [];
2895
+ if (dataChanged) {
2896
+ for (let i = 0; i < numContainers; i++) {
2897
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
2898
+ if (!keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
2899
+ pendingRemoval.push(i);
2900
+ }
2901
+ }
2902
+ }
2903
+ if (startBuffered !== null && endBuffered !== null) {
2904
+ const needNewContainers = [];
2905
+ const needNewContainersSet = /* @__PURE__ */ new Set();
2906
+ for (let i = startBuffered; i <= endBuffered; i++) {
2907
+ const id = (_i = idCache[i]) != null ? _i : getId(state, i);
2908
+ if (!containerItemKeys.has(id)) {
2909
+ needNewContainersSet.add(i);
2910
+ needNewContainers.push(i);
2911
+ }
2912
+ }
2913
+ if (alwaysRenderArr.length > 0) {
2914
+ for (const index of alwaysRenderArr) {
2915
+ if (index < 0 || index >= dataLength) continue;
2916
+ const id = (_j = idCache[index]) != null ? _j : getId(state, index);
2917
+ if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
2918
+ needNewContainersSet.add(index);
2919
+ needNewContainers.push(index);
2920
+ }
2921
+ }
2922
+ }
2923
+ if (stickyIndicesArr.length > 0) {
2924
+ handleStickyActivation(
2925
+ ctx,
2926
+ stickyIndicesSet,
2927
+ stickyIndicesArr,
2928
+ currentStickyIdx,
2929
+ needNewContainers,
2930
+ needNewContainersSet,
2931
+ startBuffered,
2932
+ endBuffered
2933
+ );
2934
+ } else if (previousStickyIndex !== -1) {
2935
+ set$(ctx, "activeStickyIndex", -1);
2936
+ }
2937
+ if (needNewContainers.length > 0) {
2938
+ const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
2939
+ const itemType = getItemType(data[i], i);
2940
+ return itemType !== void 0 ? String(itemType) : "";
2941
+ }) : void 0;
2942
+ const availableContainers = findAvailableContainers(
2943
+ ctx,
2944
+ needNewContainers.length,
2945
+ startBuffered,
2946
+ endBuffered,
2947
+ pendingRemoval,
2948
+ requiredItemTypes,
2949
+ needNewContainers
2950
+ );
2951
+ for (let idx = 0; idx < needNewContainers.length; idx++) {
2952
+ const i = needNewContainers[idx];
2953
+ const containerIndex = availableContainers[idx];
2954
+ const id = (_k = idCache[i]) != null ? _k : getId(state, i);
2955
+ const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
2956
+ if (oldKey && oldKey !== id) {
2957
+ containerItemKeys.delete(oldKey);
2958
+ }
2959
+ set$(ctx, `containerItemKey${containerIndex}`, id);
2960
+ set$(ctx, `containerItemData${containerIndex}`, data[i]);
2961
+ if (requiredItemTypes) {
2962
+ state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
2963
+ }
2964
+ containerItemKeys.set(id, containerIndex);
2965
+ const containerSticky = `containerSticky${containerIndex}`;
2966
+ const isSticky = stickyIndicesSet.has(i);
2967
+ const isAlwaysRender = alwaysRenderSet.has(i);
2968
+ if (isSticky) {
2969
+ set$(ctx, containerSticky, true);
2970
+ state.stickyContainerPool.add(containerIndex);
2971
+ } else {
2972
+ if (peek$(ctx, containerSticky)) {
2973
+ set$(ctx, containerSticky, false);
2974
+ }
2975
+ if (isAlwaysRender) {
2976
+ state.stickyContainerPool.add(containerIndex);
2977
+ } else if (state.stickyContainerPool.has(containerIndex)) {
2978
+ state.stickyContainerPool.delete(containerIndex);
2979
+ }
2980
+ }
2981
+ if (containerIndex >= numContainers) {
2982
+ numContainers = containerIndex + 1;
2983
+ }
2984
+ }
2985
+ if (numContainers !== prevNumContainers) {
2986
+ set$(ctx, "numContainers", numContainers);
2987
+ if (numContainers > peek$(ctx, "numContainersPooled")) {
2988
+ set$(ctx, "numContainersPooled", Math.ceil(numContainers * 1.5));
2989
+ }
2990
+ }
2991
+ }
2992
+ if (alwaysRenderArr.length > 0) {
2993
+ for (const index of alwaysRenderArr) {
2994
+ if (index < 0 || index >= dataLength) continue;
2995
+ const id = (_l = idCache[index]) != null ? _l : getId(state, index);
2996
+ const containerIndex = containerItemKeys.get(id);
2997
+ if (containerIndex !== void 0) {
2998
+ state.stickyContainerPool.add(containerIndex);
2999
+ }
3000
+ }
3001
+ }
3002
+ }
3003
+ if (state.stickyContainerPool.size > 0) {
3004
+ handleStickyRecycling(
3005
+ ctx,
3006
+ stickyIndicesArr,
3007
+ scroll,
3008
+ drawDistance,
3009
+ currentStickyIdx,
3010
+ pendingRemoval,
3011
+ alwaysRenderSet
3012
+ );
3013
+ }
3014
+ let didChangePositions = false;
3015
+ for (let i = 0; i < numContainers; i++) {
3016
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
3017
+ if (pendingRemoval.includes(i)) {
3018
+ if (itemKey !== void 0) {
3019
+ containerItemKeys.delete(itemKey);
3020
+ }
3021
+ state.containerItemTypes.delete(i);
3022
+ if (state.stickyContainerPool.has(i)) {
3023
+ set$(ctx, `containerSticky${i}`, false);
3024
+ state.stickyContainerPool.delete(i);
3025
+ }
3026
+ set$(ctx, `containerItemKey${i}`, void 0);
3027
+ set$(ctx, `containerItemData${i}`, void 0);
3028
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
3029
+ set$(ctx, `containerColumn${i}`, -1);
3030
+ set$(ctx, `containerSpan${i}`, 1);
3031
+ } else {
3032
+ const itemIndex = indexByKey.get(itemKey);
3033
+ const item = data[itemIndex];
3034
+ if (item !== void 0) {
3035
+ const id = (_m = idCache[itemIndex]) != null ? _m : getId(state, itemIndex);
3036
+ const positionValue = positions.get(id);
3037
+ if (positionValue === void 0) {
3038
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
3039
+ } else {
3040
+ const position = (positionValue || 0) - scrollAdjustPending;
3041
+ const column = columns.get(id) || 1;
3042
+ const span = columnSpans.get(id) || 1;
3043
+ const prevPos = peek$(ctx, `containerPosition${i}`);
3044
+ const prevColumn = peek$(ctx, `containerColumn${i}`);
3045
+ const prevSpan = peek$(ctx, `containerSpan${i}`);
3046
+ const prevData = peek$(ctx, `containerItemData${i}`);
3047
+ if (position > POSITION_OUT_OF_VIEW && position !== prevPos) {
3048
+ set$(ctx, `containerPosition${i}`, position);
3049
+ didChangePositions = true;
3050
+ }
3051
+ if (column >= 0 && column !== prevColumn) {
3052
+ set$(ctx, `containerColumn${i}`, column);
3053
+ }
3054
+ if (span !== prevSpan) {
3055
+ set$(ctx, `containerSpan${i}`, span);
3056
+ }
3057
+ if (prevData !== item && (itemsAreEqual ? !itemsAreEqual(prevData, item, itemIndex, data) : true)) {
3058
+ set$(ctx, `containerItemData${i}`, item);
3059
+ }
3060
+ }
3061
+ }
3062
+ }
3063
+ }
3064
+ if (didChangePositions) {
3065
+ set$(ctx, "lastPositionUpdate", Date.now());
3066
+ }
3067
+ if (!queuedInitialLayout && endBuffered !== null) {
3068
+ if (checkAllSizesKnown(state)) {
3069
+ setDidLayout(ctx);
3070
+ }
3071
+ }
3072
+ if (viewabilityConfigCallbackPairs) {
3073
+ updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
3074
+ }
3075
+ if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
3076
+ const item = data[nextActiveStickyIndex];
3077
+ if (item !== void 0) {
3078
+ onStickyHeaderChange({ index: nextActiveStickyIndex, item });
3079
+ }
3080
+ }
3081
+ });
3082
+ }
3083
+
3084
+ // src/core/checkActualChange.ts
3085
+ function checkActualChange(state, dataProp, previousData) {
3086
+ if (!previousData || !dataProp || dataProp.length !== previousData.length) {
3087
+ return true;
3088
+ }
3089
+ const {
3090
+ idCache,
3091
+ props: { keyExtractor }
3092
+ } = state;
3093
+ for (let i = 0; i < dataProp.length; i++) {
3094
+ if (dataProp[i] !== previousData[i]) {
3095
+ return true;
3096
+ }
3097
+ if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
3098
+ return true;
3099
+ }
3100
+ }
3101
+ return false;
3102
+ }
3103
+
3104
+ // src/core/checkFinishedScroll.ts
3105
+ function checkFinishedScroll(ctx) {
3106
+ ctx.state.animFrameCheckFinishedScroll = requestAnimationFrame(() => checkFinishedScrollFrame(ctx));
3107
+ }
3108
+ function checkFinishedScrollFrame(ctx) {
3109
+ const scrollingTo = ctx.state.scrollingTo;
3110
+ if (scrollingTo) {
3111
+ const { state } = ctx;
3112
+ state.animFrameCheckFinishedScroll = void 0;
3113
+ const scroll = state.scrollPending;
3114
+ const adjust = state.scrollAdjustHandler.getAdjust();
3115
+ const clampedTargetOffset = clampScrollOffset(
3116
+ ctx,
3117
+ scrollingTo.offset - (scrollingTo.viewOffset || 0),
3118
+ scrollingTo
3119
+ );
3120
+ const maxOffset = clampScrollOffset(ctx, scroll, scrollingTo);
3121
+ const diff1 = Math.abs(scroll - clampedTargetOffset);
3122
+ const diff2 = Math.abs(diff1 - adjust);
3123
+ const isNotOverscrolled = Math.abs(scroll - maxOffset) < 1;
3124
+ const isAtTarget = diff1 < 1 || !scrollingTo.animated && diff2 < 1;
3125
+ if (isNotOverscrolled && isAtTarget) {
3126
+ finishScrollTo(ctx);
3127
+ }
3128
+ }
3129
+ }
3130
+ function checkFinishedScrollFallback(ctx) {
3131
+ const state = ctx.state;
3132
+ const scrollingTo = state.scrollingTo;
3133
+ const slowTimeout = (scrollingTo == null ? void 0 : scrollingTo.isInitialScroll) || !state.didContainersLayout;
3134
+ state.timeoutCheckFinishedScrollFallback = setTimeout(
3135
+ () => {
3136
+ let numChecks = 0;
3137
+ const checkHasScrolled = () => {
3138
+ state.timeoutCheckFinishedScrollFallback = void 0;
3139
+ const isStillScrollingTo = state.scrollingTo;
3140
+ if (isStillScrollingTo) {
3141
+ numChecks++;
3142
+ if (state.hasScrolled || numChecks > 5) {
3143
+ finishScrollTo(ctx);
3144
+ } else {
3145
+ state.timeoutCheckFinishedScrollFallback = setTimeout(checkHasScrolled, 100);
3146
+ }
3147
+ }
3148
+ };
3149
+ checkHasScrolled();
3150
+ },
3151
+ slowTimeout ? 500 : 100
3152
+ );
3153
+ }
3154
+
3155
+ // src/core/doMaintainScrollAtEnd.ts
3156
+ function doMaintainScrollAtEnd(ctx, animated) {
3157
+ const state = ctx.state;
3158
+ const {
3159
+ didContainersLayout,
3160
+ isAtEnd,
3161
+ refScroller,
3162
+ props: { maintainScrollAtEnd }
3163
+ } = state;
3164
+ if (isAtEnd && maintainScrollAtEnd && didContainersLayout) {
3165
+ const contentSize = getContentSize(ctx);
3166
+ if (contentSize < state.scrollLength) {
3167
+ state.scroll = 0;
3168
+ }
3169
+ requestAnimationFrame(() => {
3170
+ var _a3;
3171
+ if (state.isAtEnd) {
3172
+ state.maintainingScrollAtEnd = true;
3173
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
3174
+ animated
3175
+ });
3176
+ setTimeout(
3177
+ () => {
3178
+ state.maintainingScrollAtEnd = false;
3179
+ },
3180
+ 0
3181
+ );
3182
+ }
3183
+ });
3184
+ return true;
3185
+ }
3186
+ return false;
3187
+ }
3188
+
3189
+ // src/utils/updateAveragesOnDataChange.ts
3190
+ function updateAveragesOnDataChange(state, oldData, newData) {
3191
+ var _a3;
3192
+ const {
3193
+ averageSizes,
3194
+ sizesKnown,
3195
+ indexByKey,
3196
+ props: { itemsAreEqual, getItemType, keyExtractor }
3197
+ } = state;
3198
+ if (!itemsAreEqual || !oldData.length || !newData.length) {
3199
+ for (const key in averageSizes) {
3200
+ delete averageSizes[key];
3201
+ }
3202
+ return;
3203
+ }
3204
+ const itemTypesToPreserve = {};
3205
+ const newDataLength = newData.length;
3206
+ const oldDataLength = oldData.length;
3207
+ for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
3208
+ const newItem = newData[newIndex];
3209
+ const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
3210
+ const oldIndex = indexByKey.get(id);
3211
+ if (oldIndex !== void 0 && oldIndex < oldDataLength) {
3212
+ const knownSize = sizesKnown.get(id);
3213
+ if (knownSize === void 0) continue;
3214
+ const oldItem = oldData[oldIndex];
3215
+ const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
3216
+ if (areEqual) {
3217
+ const itemType = getItemType ? (_a3 = getItemType(newItem, newIndex)) != null ? _a3 : "" : "";
3218
+ let typeData = itemTypesToPreserve[itemType];
3219
+ if (!typeData) {
3220
+ typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
3221
+ }
3222
+ typeData.totalSize += knownSize;
3223
+ typeData.count++;
3224
+ }
3225
+ }
3226
+ }
3227
+ for (const key in averageSizes) {
3228
+ delete averageSizes[key];
3229
+ }
3230
+ for (const itemType in itemTypesToPreserve) {
3231
+ const { totalSize, count } = itemTypesToPreserve[itemType];
3232
+ if (count > 0) {
3233
+ averageSizes[itemType] = {
3234
+ avg: totalSize / count,
3235
+ num: count
3236
+ };
3237
+ }
3238
+ }
3239
+ }
3240
+
3241
+ // src/core/checkResetContainers.ts
3242
+ function checkResetContainers(ctx, dataProp) {
3243
+ const state = ctx.state;
3244
+ const { previousData } = state;
3245
+ if (previousData) {
3246
+ updateAveragesOnDataChange(state, previousData, dataProp);
3247
+ }
3248
+ const { maintainScrollAtEnd } = state.props;
3249
+ calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
3250
+ const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
3251
+ const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, false);
3252
+ if (!didMaintainScrollAtEnd && previousData && dataProp.length > previousData.length) {
3253
+ state.isEndReached = false;
3254
+ }
3255
+ if (!didMaintainScrollAtEnd) {
3256
+ checkThresholds(ctx);
3257
+ }
3258
+ delete state.previousData;
3259
+ }
3260
+
3261
+ // src/core/doInitialAllocateContainers.ts
3262
+ function doInitialAllocateContainers(ctx) {
3263
+ var _a3, _b, _c;
3264
+ const state = ctx.state;
3265
+ const {
3266
+ scrollLength,
3267
+ props: {
3268
+ data,
3269
+ drawDistance,
3270
+ getEstimatedItemSize,
3271
+ getFixedItemSize,
3272
+ getItemType,
3273
+ numColumns,
3274
+ estimatedItemSize
3275
+ }
3276
+ } = state;
3277
+ const hasContainers = peek$(ctx, "numContainers");
3278
+ if (scrollLength > 0 && data.length > 0 && !hasContainers) {
3279
+ let averageItemSize;
3280
+ if (getFixedItemSize || getEstimatedItemSize) {
3281
+ let totalSize = 0;
3282
+ const num = Math.min(20, data.length);
3283
+ for (let i = 0; i < num; i++) {
3284
+ const item = data[i];
3285
+ if (item !== void 0) {
3286
+ const itemType = (_a3 = getItemType == null ? void 0 : getItemType(item, i)) != null ? _a3 : "";
3287
+ totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(item, i, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(item, i, itemType)) != null ? _c : estimatedItemSize;
3288
+ }
3289
+ }
3290
+ averageItemSize = totalSize / num;
3291
+ } else {
3292
+ averageItemSize = estimatedItemSize;
3293
+ }
3294
+ const numContainers = Math.ceil((scrollLength + drawDistance * 2) / averageItemSize * numColumns);
3295
+ for (let i = 0; i < numContainers; i++) {
3296
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
3297
+ set$(ctx, `containerColumn${i}`, -1);
3298
+ set$(ctx, `containerSpan${i}`, 1);
3299
+ }
3300
+ set$(ctx, "numContainers", numContainers);
3301
+ set$(ctx, "numContainersPooled", numContainers * state.props.initialContainerPoolRatio);
3302
+ if (state.lastLayout) {
3303
+ if (state.initialScroll) {
3304
+ requestAnimationFrame(() => {
3305
+ calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
3306
+ });
3307
+ } else {
3308
+ calculateItemsInView(ctx, { dataChanged: true, doMVCP: true });
3309
+ }
3310
+ }
3311
+ return true;
3312
+ }
3313
+ }
3314
+
3315
+ // src/core/handleLayout.ts
3316
+ function handleLayout(ctx, layout, setCanRender) {
3317
+ const state = ctx.state;
3318
+ const { maintainScrollAtEnd } = state.props;
3319
+ const measuredLength = layout[state.props.horizontal ? "width" : "height"];
3320
+ const previousLength = state.scrollLength;
3321
+ const scrollLength = measuredLength > 0 ? measuredLength : previousLength;
3322
+ const otherAxisSize = layout[state.props.horizontal ? "height" : "width"];
3323
+ const needsCalculate = !state.lastLayout || scrollLength > state.scrollLength || state.lastLayout.x !== layout.x || state.lastLayout.y !== layout.y;
3324
+ state.lastLayout = layout;
3325
+ const prevOtherAxisSize = state.otherAxisSize;
3326
+ const didChange = scrollLength !== state.scrollLength || otherAxisSize !== prevOtherAxisSize;
3327
+ if (didChange) {
3328
+ state.scrollLength = scrollLength;
3329
+ state.otherAxisSize = otherAxisSize;
3330
+ state.lastBatchingAction = Date.now();
3331
+ state.scrollForNextCalculateItemsInView = void 0;
3332
+ if (scrollLength > 0) {
3333
+ doInitialAllocateContainers(ctx);
3334
+ }
3335
+ if (needsCalculate) {
3336
+ calculateItemsInView(ctx, { doMVCP: true });
3337
+ }
3338
+ if (didChange || otherAxisSize !== prevOtherAxisSize) {
3339
+ set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
3340
+ }
3341
+ if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
3342
+ doMaintainScrollAtEnd(ctx, false);
3343
+ }
3344
+ checkThresholds(ctx);
3345
+ if (state) {
3346
+ state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
3347
+ }
3348
+ if (IS_DEV && measuredLength === 0) {
3349
+ warnDevOnce(
3350
+ "height0",
3351
+ `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.`
3352
+ );
3353
+ }
3354
+ }
3355
+ setCanRender(true);
3356
+ }
3357
+
3358
+ // src/core/onScroll.ts
3359
+ function onScroll(ctx, event) {
3360
+ var _a3, _b, _c, _d;
3361
+ const state = ctx.state;
3362
+ const {
3363
+ scrollProcessingEnabled,
3364
+ props: { onScroll: onScrollProp }
3365
+ } = state;
3366
+ if (scrollProcessingEnabled === false) {
3367
+ return;
3368
+ }
3369
+ if (((_b = (_a3 = event.nativeEvent) == null ? void 0 : _a3.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
3370
+ return;
3371
+ }
3372
+ let insetChanged = false;
3373
+ if ((_d = event.nativeEvent) == null ? void 0 : _d.contentInset) {
3374
+ const { contentInset } = event.nativeEvent;
3375
+ const prevInset = state.nativeContentInset;
3376
+ if (!prevInset || prevInset.top !== contentInset.top || prevInset.bottom !== contentInset.bottom || prevInset.left !== contentInset.left || prevInset.right !== contentInset.right) {
3377
+ state.nativeContentInset = contentInset;
3378
+ insetChanged = true;
3379
+ }
3380
+ }
3381
+ let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
3382
+ if (state.scrollingTo && state.scrollingTo.offset >= newScroll) {
3383
+ const maxOffset = clampScrollOffset(ctx, newScroll, state.scrollingTo);
3384
+ if (newScroll !== maxOffset && Math.abs(newScroll - maxOffset) > 1) {
3385
+ newScroll = maxOffset;
3386
+ scrollTo(ctx, {
3387
+ forceScroll: true,
3388
+ isInitialScroll: true,
3389
+ noScrollingTo: true,
3390
+ offset: newScroll
3391
+ });
3392
+ return;
3393
+ }
3394
+ }
3395
+ state.scrollPending = newScroll;
3396
+ updateScroll(ctx, newScroll, insetChanged);
3397
+ if (state.scrollingTo) {
3398
+ checkFinishedScroll(ctx);
3399
+ }
3400
+ onScrollProp == null ? void 0 : onScrollProp(event);
3401
+ }
3402
+
3403
+ // src/core/ScrollAdjustHandler.ts
3404
+ var ScrollAdjustHandler = class {
3405
+ constructor(ctx) {
3406
+ this.appliedAdjust = 0;
3407
+ this.pendingAdjust = 0;
3408
+ this.ctx = ctx;
3409
+ }
3410
+ requestAdjust(add) {
3411
+ const scrollingTo = this.ctx.state.scrollingTo;
3412
+ if ((scrollingTo == null ? void 0 : scrollingTo.animated) && !scrollingTo.isInitialScroll) {
3413
+ this.pendingAdjust += add;
3414
+ set$(this.ctx, "scrollAdjustPending", this.pendingAdjust);
3415
+ } else {
3416
+ this.appliedAdjust += add;
3417
+ set$(this.ctx, "scrollAdjust", this.appliedAdjust);
3418
+ }
3419
+ if (this.ctx.state.scrollingTo) {
3420
+ checkFinishedScroll(this.ctx);
3421
+ }
3422
+ }
3423
+ getAdjust() {
3424
+ return this.appliedAdjust;
3425
+ }
3426
+ commitPendingAdjust(scrollTarget) {
3427
+ {
3428
+ const state = this.ctx.state;
3429
+ const pending = this.pendingAdjust;
3430
+ this.pendingAdjust = 0;
3431
+ if (pending !== 0) {
3432
+ let targetScroll;
3433
+ if ((scrollTarget == null ? void 0 : scrollTarget.index) !== void 0) {
3434
+ const currentOffset = calculateOffsetForIndex(this.ctx, scrollTarget.index);
3435
+ targetScroll = calculateOffsetWithOffsetPosition(this.ctx, currentOffset, scrollTarget);
3436
+ targetScroll = clampScrollOffset(this.ctx, targetScroll, scrollTarget);
3437
+ } else {
3438
+ targetScroll = clampScrollOffset(this.ctx, state.scroll + pending);
3439
+ }
3440
+ const adjustment = targetScroll - state.scroll;
3441
+ if (Math.abs(adjustment) > 0.1 || Math.abs(pending) > 0.1) {
3442
+ this.appliedAdjust += adjustment;
3443
+ state.scroll = targetScroll;
3444
+ state.scrollForNextCalculateItemsInView = void 0;
3445
+ set$(this.ctx, "scrollAdjust", this.appliedAdjust);
3446
+ }
3447
+ set$(this.ctx, "scrollAdjustPending", 0);
3448
+ calculateItemsInView(this.ctx);
3449
+ }
3450
+ }
3451
+ }
3452
+ };
3453
+
3454
+ // src/core/updateItemSize.ts
3455
+ function runOrScheduleMVCPRecalculate(ctx) {
3456
+ const state = ctx.state;
3457
+ {
3458
+ if (!state.mvcpAnchorLock) {
3459
+ if (state.queuedMVCPRecalculate !== void 0) {
3460
+ cancelAnimationFrame(state.queuedMVCPRecalculate);
3461
+ state.queuedMVCPRecalculate = void 0;
3462
+ }
3463
+ calculateItemsInView(ctx, { doMVCP: true });
3464
+ return;
3465
+ }
3466
+ if (state.queuedMVCPRecalculate !== void 0) {
3467
+ return;
3468
+ }
3469
+ state.queuedMVCPRecalculate = requestAnimationFrame(() => {
3470
+ state.queuedMVCPRecalculate = void 0;
3471
+ calculateItemsInView(ctx, { doMVCP: true });
3472
+ });
3473
+ }
3474
+ }
3475
+ function updateItemSize(ctx, itemKey, sizeObj) {
3476
+ var _a3;
3477
+ const state = ctx.state;
3478
+ const {
3479
+ didContainersLayout,
3480
+ sizesKnown,
3481
+ props: {
3482
+ getFixedItemSize,
3483
+ getItemType,
3484
+ horizontal,
3485
+ suggestEstimatedItemSize,
3486
+ onItemSizeChanged,
3487
+ data,
3488
+ maintainScrollAtEnd
3489
+ }
3490
+ } = state;
3491
+ if (!data) return;
3492
+ const index = state.indexByKey.get(itemKey);
3493
+ if (getFixedItemSize) {
3494
+ if (index === void 0) {
3495
+ return;
3496
+ }
3497
+ const itemData = state.props.data[index];
3498
+ if (itemData === void 0) {
3499
+ return;
3500
+ }
3501
+ const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
3502
+ const size2 = getFixedItemSize(itemData, index, type);
3503
+ if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
3504
+ return;
3505
+ }
3506
+ }
3507
+ let needsRecalculate = !didContainersLayout;
3508
+ let shouldMaintainScrollAtEnd = false;
3509
+ let minIndexSizeChanged;
3510
+ let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
3511
+ const prevSizeKnown = state.sizesKnown.get(itemKey);
3512
+ const diff = updateOneItemSize(ctx, itemKey, sizeObj);
3513
+ const size = roundSize(horizontal ? sizeObj.width : sizeObj.height);
3514
+ if (diff !== 0) {
3515
+ minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
3516
+ const { startBuffered, endBuffered } = state;
3517
+ needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
3518
+ if (!needsRecalculate && state.containerItemKeys.has(itemKey)) {
3519
+ needsRecalculate = true;
3520
+ }
3521
+ if (state.needsOtherAxisSize) {
3522
+ const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
3523
+ maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
3524
+ }
3525
+ if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
3526
+ shouldMaintainScrollAtEnd = true;
3527
+ }
3528
+ onItemSizeChanged == null ? void 0 : onItemSizeChanged({
3529
+ index,
3530
+ itemData: state.props.data[index],
3531
+ itemKey,
3532
+ previous: size - diff,
3533
+ size
3534
+ });
3535
+ }
3536
+ if (minIndexSizeChanged !== void 0) {
3537
+ state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
3538
+ }
3539
+ if (IS_DEV && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
3540
+ if (state.timeoutSizeMessage) clearTimeout(state.timeoutSizeMessage);
3541
+ state.timeoutSizeMessage = setTimeout(() => {
3542
+ var _a4;
3543
+ state.timeoutSizeMessage = void 0;
3544
+ const num = state.sizesKnown.size;
3545
+ const avg = (_a4 = state.averageSizes[""]) == null ? void 0 : _a4.avg;
3546
+ console.warn(
3547
+ `[legend-list] Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`
3548
+ );
3549
+ }, 1e3);
3550
+ }
3551
+ const cur = peek$(ctx, "otherAxisSize");
3552
+ if (!cur || maxOtherAxisSize > cur) {
3553
+ set$(ctx, "otherAxisSize", maxOtherAxisSize);
3554
+ }
3555
+ if (didContainersLayout || checkAllSizesKnown(state)) {
3556
+ if (needsRecalculate) {
3557
+ state.scrollForNextCalculateItemsInView = void 0;
3558
+ runOrScheduleMVCPRecalculate(ctx);
3559
+ }
3560
+ if (shouldMaintainScrollAtEnd) {
3561
+ if (maintainScrollAtEnd === true || maintainScrollAtEnd.onItemLayout) {
3562
+ doMaintainScrollAtEnd(ctx, false);
3563
+ }
3564
+ }
3565
+ }
3566
+ }
3567
+ function updateOneItemSize(ctx, itemKey, sizeObj) {
3568
+ var _a3;
3569
+ const state = ctx.state;
3570
+ const {
3571
+ indexByKey,
3572
+ sizesKnown,
3573
+ averageSizes,
3574
+ props: { data, horizontal, getEstimatedItemSize, getItemType, getFixedItemSize }
3575
+ } = state;
3576
+ if (!data) return 0;
3577
+ const index = indexByKey.get(itemKey);
3578
+ const prevSize = getItemSize(ctx, itemKey, index, data[index]);
3579
+ const rawSize = horizontal ? sizeObj.width : sizeObj.height;
3580
+ const size = Math.round(rawSize) ;
3581
+ const prevSizeKnown = sizesKnown.get(itemKey);
3582
+ sizesKnown.set(itemKey, size);
3583
+ if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
3584
+ const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
3585
+ let averages = averageSizes[itemType];
3586
+ if (!averages) {
3587
+ averages = averageSizes[itemType] = { avg: 0, num: 0 };
3588
+ }
3589
+ if (averages.num === 0) {
3590
+ averages.avg = size;
3591
+ averages.num++;
3592
+ } else if (prevSizeKnown !== void 0 && prevSizeKnown > 0) {
3593
+ averages.avg += (size - prevSizeKnown) / averages.num;
3594
+ } else {
3595
+ averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
3596
+ averages.num++;
3597
+ }
3598
+ }
3599
+ if (!prevSize || Math.abs(prevSize - size) > 0.1) {
3600
+ setSize(ctx, itemKey, size);
3601
+ return size - prevSize;
3602
+ }
3603
+ return 0;
3604
+ }
3605
+ function useWrapIfItem(fn) {
3606
+ return React3.useMemo(
3607
+ () => fn ? (arg1, arg2, arg3) => arg1 !== void 0 && arg2 !== void 0 ? fn(arg1, arg2, arg3) : void 0 : void 0,
3608
+ [fn]
3609
+ );
3610
+ }
3611
+ var useCombinedRef = (...refs) => {
3612
+ const callback = React3.useCallback((element) => {
3613
+ for (const ref of refs) {
3614
+ if (!ref) {
3615
+ continue;
3616
+ }
3617
+ if (isFunction(ref)) {
3618
+ ref(element);
3619
+ } else {
3620
+ ref.current = element;
3621
+ }
3622
+ }
3623
+ }, refs);
3624
+ return callback;
3625
+ };
3626
+
3627
+ // src/platform/RefreshControl.tsx
3628
+ function RefreshControl(_props) {
3629
+ return null;
3630
+ }
3631
+
3632
+ // src/platform/useStickyScrollHandler.ts
3633
+ function useStickyScrollHandler(_stickyHeaderIndices, _horizontal, _ctx, onScroll2) {
3634
+ return onScroll2;
3635
+ }
3636
+
3637
+ // src/utils/createColumnWrapperStyle.ts
3638
+ function createColumnWrapperStyle(contentContainerStyle) {
3639
+ const { gap, columnGap, rowGap } = contentContainerStyle;
3640
+ if (gap || columnGap || rowGap) {
3641
+ contentContainerStyle.gap = void 0;
3642
+ contentContainerStyle.columnGap = void 0;
3643
+ contentContainerStyle.rowGap = void 0;
3644
+ return {
3645
+ columnGap,
3646
+ gap,
3647
+ rowGap
3648
+ };
3649
+ }
3650
+ }
3651
+
3652
+ // src/utils/createImperativeHandle.ts
3653
+ function createImperativeHandle(ctx) {
3654
+ const state = ctx.state;
3655
+ const scrollIndexIntoView = (options) => {
3656
+ if (state) {
3657
+ const { index, ...rest } = options;
3658
+ const { startNoBuffer, endNoBuffer } = state;
3659
+ if (index < startNoBuffer || index > endNoBuffer) {
3660
+ const viewPosition = index < startNoBuffer ? 0 : 1;
3661
+ scrollToIndex(ctx, {
3662
+ ...rest,
3663
+ index,
3664
+ viewPosition
3665
+ });
3666
+ }
3667
+ }
3668
+ };
3669
+ const refScroller = state.refScroller;
3670
+ const clearCaches = (options) => {
3671
+ var _a3, _b;
3672
+ const mode = (_a3 = options == null ? void 0 : options.mode) != null ? _a3 : "sizes";
3673
+ state.sizes.clear();
3674
+ state.sizesKnown.clear();
3675
+ for (const key in state.averageSizes) {
3676
+ delete state.averageSizes[key];
3677
+ }
3678
+ state.minIndexSizeChanged = 0;
3679
+ state.scrollForNextCalculateItemsInView = void 0;
3680
+ state.pendingTotalSize = void 0;
3681
+ state.totalSize = 0;
3682
+ set$(ctx, "totalSize", 0);
3683
+ if (mode === "full") {
3684
+ state.indexByKey.clear();
3685
+ state.idCache.length = 0;
3686
+ state.positions.clear();
3687
+ state.columns.clear();
3688
+ state.columnSpans.clear();
3689
+ }
3690
+ (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
3691
+ };
3692
+ return {
3693
+ clearCaches,
3694
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
3695
+ getNativeScrollRef: () => refScroller.current,
3696
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
3697
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
3698
+ getState: () => ({
3699
+ activeStickyIndex: peek$(ctx, "activeStickyIndex"),
3700
+ contentLength: getContentSize(ctx),
3701
+ data: state.props.data,
3702
+ elementAtIndex: (index) => {
3703
+ var _a3;
3704
+ return (_a3 = ctx.viewRefs.get(findContainerId(ctx, getId(state, index)))) == null ? void 0 : _a3.current;
3705
+ },
3706
+ end: state.endNoBuffer,
3707
+ endBuffered: state.endBuffered,
3708
+ isAtEnd: state.isAtEnd,
3709
+ isAtStart: state.isAtStart,
3710
+ listen: (signalName, cb) => listen$(ctx, signalName, cb),
3711
+ listenToPosition: (key, cb) => listenPosition$(ctx, key, cb),
3712
+ positionAtIndex: (index) => state.positions.get(getId(state, index)),
3713
+ positions: state.positions,
3714
+ scroll: state.scroll,
3715
+ scrollLength: state.scrollLength,
3716
+ scrollVelocity: getScrollVelocity(state),
3717
+ sizeAtIndex: (index) => state.sizesKnown.get(getId(state, index)),
3718
+ sizes: state.sizesKnown,
3719
+ start: state.startNoBuffer,
3720
+ startBuffered: state.startBuffered
3721
+ }),
3722
+ reportContentInset: (inset) => {
3723
+ state.contentInsetOverride = inset != null ? inset : void 0;
3724
+ updateScroll(ctx, state.scroll, true);
3725
+ },
3726
+ scrollIndexIntoView,
3727
+ scrollItemIntoView: ({ item, ...props }) => {
3728
+ const data = state.props.data;
3729
+ const index = data.indexOf(item);
3730
+ if (index !== -1) {
3731
+ scrollIndexIntoView({ index, ...props });
3732
+ }
3733
+ },
3734
+ scrollToEnd: (options) => {
3735
+ const data = state.props.data;
3736
+ const stylePaddingBottom = state.props.stylePaddingBottom;
3737
+ const index = data.length - 1;
3738
+ if (index !== -1) {
3739
+ const paddingBottom = stylePaddingBottom || 0;
3740
+ const footerSize = peek$(ctx, "footerSize") || 0;
3741
+ scrollToIndex(ctx, {
3742
+ ...options,
3743
+ index,
3744
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
3745
+ viewPosition: 1
3746
+ });
3747
+ }
3748
+ },
3749
+ scrollToIndex: (params) => scrollToIndex(ctx, params),
3750
+ scrollToItem: ({ item, ...props }) => {
3751
+ const data = state.props.data;
3752
+ const index = data.indexOf(item);
3753
+ if (index !== -1) {
3754
+ scrollToIndex(ctx, { index, ...props });
3755
+ }
3756
+ },
3757
+ scrollToOffset: (params) => scrollTo(ctx, params),
3758
+ setScrollProcessingEnabled: (enabled) => {
3759
+ state.scrollProcessingEnabled = enabled;
3760
+ },
3761
+ setVisibleContentAnchorOffset: (value) => {
3762
+ const val = isFunction(value) ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
3763
+ set$(ctx, "scrollAdjustUserOffset", val);
3764
+ }
3765
+ };
3766
+ }
3767
+
3768
+ // src/utils/getAlwaysRenderIndices.ts
3769
+ var sortAsc = (a, b) => a - b;
3770
+ var toCount = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;
3771
+ var addIndex = (result, dataLength, index) => {
3772
+ if (index >= 0 && index < dataLength) {
3773
+ result.add(index);
3774
+ }
3775
+ };
3776
+ function getAlwaysRenderIndices(config, data, keyExtractor) {
3777
+ var _a3, _b;
3778
+ if (!config || data.length === 0) {
3779
+ return [];
3780
+ }
3781
+ const result = /* @__PURE__ */ new Set();
3782
+ const dataLength = data.length;
3783
+ const topCount = toCount(config.top);
3784
+ if (topCount > 0) {
3785
+ for (let i = 0; i < Math.min(topCount, dataLength); i++) {
3786
+ addIndex(result, dataLength, i);
3787
+ }
3788
+ }
3789
+ const bottomCount = toCount(config.bottom);
3790
+ if (bottomCount > 0) {
3791
+ for (let i = Math.max(0, dataLength - bottomCount); i < dataLength; i++) {
3792
+ addIndex(result, dataLength, i);
3793
+ }
3794
+ }
3795
+ if ((_a3 = config.indices) == null ? void 0 : _a3.length) {
3796
+ for (const index of config.indices) {
3797
+ if (!Number.isFinite(index)) continue;
3798
+ addIndex(result, dataLength, Math.floor(index));
3799
+ }
3800
+ }
3801
+ if ((_b = config.keys) == null ? void 0 : _b.length) {
3802
+ const keys = new Set(config.keys);
3803
+ for (let i = 0; i < dataLength && keys.size > 0; i++) {
3804
+ const key = keyExtractor(data[i], i);
3805
+ if (keys.has(key)) {
3806
+ addIndex(result, dataLength, i);
3807
+ keys.delete(key);
3808
+ }
3809
+ }
3810
+ }
3811
+ const indices = Array.from(result);
3812
+ indices.sort(sortAsc);
3813
+ return indices;
3814
+ }
3815
+ function getRenderedItem(ctx, key) {
3816
+ var _a3;
3817
+ const state = ctx.state;
3818
+ if (!state) {
3819
+ return null;
3820
+ }
3821
+ const {
3822
+ indexByKey,
3823
+ props: { data, getItemType, renderItem }
3824
+ } = state;
3825
+ const index = indexByKey.get(key);
3826
+ if (index === void 0) {
3827
+ return null;
3828
+ }
3829
+ let renderedItem = null;
3830
+ const extraData = peek$(ctx, "extraData");
3831
+ const item = data[index];
3832
+ if (renderItem && !isNullOrUndefined(item)) {
3833
+ const itemProps = {
3834
+ data,
3835
+ extraData,
3836
+ index,
3837
+ item,
3838
+ type: getItemType ? (_a3 = getItemType(item, index)) != null ? _a3 : "" : ""
3839
+ };
3840
+ renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React3__namespace.default.createElement(renderItem, itemProps);
3841
+ }
3842
+ return { index, item: data[index], renderedItem };
3843
+ }
3844
+
3845
+ // src/utils/normalizeMaintainVisibleContentPosition.ts
3846
+ function normalizeMaintainVisibleContentPosition(value) {
3847
+ var _a3, _b;
3848
+ if (value === true) {
3849
+ return { data: true, size: true };
3850
+ }
3851
+ if (value && typeof value === "object") {
3852
+ return {
3853
+ data: (_a3 = value.data) != null ? _a3 : false,
3854
+ shouldRestorePosition: value.shouldRestorePosition,
3855
+ size: (_b = value.size) != null ? _b : true
3856
+ };
3857
+ }
3858
+ if (value === false) {
3859
+ return { data: false, size: false };
3860
+ }
3861
+ return { data: false, size: true };
3862
+ }
3863
+
3864
+ // src/utils/setPaddingTop.ts
3865
+ function setPaddingTop(ctx, { stylePaddingTop }) {
3866
+ const state = ctx.state;
3867
+ if (stylePaddingTop !== void 0) {
3868
+ const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
3869
+ if (stylePaddingTop < prevStylePaddingTop) {
3870
+ let prevTotalSize = peek$(ctx, "totalSize") || 0;
3871
+ set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
3872
+ state.timeoutSetPaddingTop = setTimeout(() => {
3873
+ prevTotalSize = peek$(ctx, "totalSize") || 0;
3874
+ set$(ctx, "totalSize", prevTotalSize - prevStylePaddingTop);
3875
+ }, 16);
3876
+ }
3877
+ set$(ctx, "stylePaddingTop", stylePaddingTop);
3878
+ }
3879
+ }
3880
+ function useThrottleDebounce(mode) {
3881
+ const timeoutRef = React3.useRef(null);
3882
+ const lastCallTimeRef = React3.useRef(0);
3883
+ const lastArgsRef = React3.useRef(null);
3884
+ const clearTimeoutRef = () => {
3885
+ if (timeoutRef.current) {
3886
+ clearTimeout(timeoutRef.current);
3887
+ timeoutRef.current = null;
3888
+ }
3889
+ };
3890
+ const execute = React3.useCallback(
3891
+ (callback, delay, ...args) => {
3892
+ {
3893
+ const now = Date.now();
3894
+ lastArgsRef.current = args;
3895
+ if (now - lastCallTimeRef.current >= delay) {
3896
+ lastCallTimeRef.current = now;
3897
+ callback(...args);
3898
+ clearTimeoutRef();
3899
+ } else {
3900
+ clearTimeoutRef();
3901
+ timeoutRef.current = setTimeout(
3902
+ () => {
3903
+ if (lastArgsRef.current) {
3904
+ lastCallTimeRef.current = Date.now();
3905
+ callback(...lastArgsRef.current);
3906
+ timeoutRef.current = null;
3907
+ lastArgsRef.current = null;
3908
+ }
3909
+ },
3910
+ delay - (now - lastCallTimeRef.current)
3911
+ );
3912
+ }
3913
+ }
3914
+ },
3915
+ [mode]
3916
+ );
3917
+ return execute;
3918
+ }
3919
+
3920
+ // src/utils/throttledOnScroll.ts
3921
+ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
3922
+ const throttle = useThrottleDebounce("throttle");
3923
+ return (event) => throttle(originalHandler, scrollEventThrottle, { nativeEvent: event.nativeEvent });
3924
+ }
3925
+
3926
+ // src/components/LegendList.tsx
3927
+ var LegendList = typedMemo(
3928
+ // biome-ignore lint/nursery/noShadow: const function name shadowing is intentional
3929
+ typedForwardRef(function LegendList2(props, forwardedRef) {
3930
+ const { children, data: dataProp, renderItem: renderItemProp, ...restProps } = props;
3931
+ const isChildrenMode = children !== void 0 && dataProp === void 0;
3932
+ const processedProps = isChildrenMode ? {
3933
+ ...restProps,
3934
+ childrenMode: true,
3935
+ data: (isArray(children) ? children : React3__namespace.Children.toArray(children)).flat(1),
3936
+ renderItem: ({ item }) => item
3937
+ } : {
3938
+ ...restProps,
3939
+ data: dataProp || [],
3940
+ renderItem: renderItemProp
3941
+ };
3942
+ return /* @__PURE__ */ React3__namespace.createElement(StateProvider, null, /* @__PURE__ */ React3__namespace.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
3943
+ })
3944
+ );
3945
+ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
3946
+ var _a3, _b, _c, _d;
3947
+ const {
3948
+ alignItemsAtEnd = false,
3949
+ alwaysRender,
3950
+ columnWrapperStyle,
3951
+ contentContainerStyle: contentContainerStyleProp,
3952
+ contentInset,
3953
+ data: dataProp = [],
3954
+ dataVersion,
3955
+ drawDistance = 250,
3956
+ estimatedItemSize = 100,
3957
+ estimatedListSize,
3958
+ extraData,
3959
+ getEstimatedItemSize,
3960
+ getFixedItemSize,
3961
+ getItemType,
3962
+ horizontal,
3963
+ initialContainerPoolRatio = 2,
3964
+ initialScrollAtEnd = false,
3965
+ initialScrollIndex: initialScrollIndexProp,
3966
+ initialScrollOffset: initialScrollOffsetProp,
3967
+ itemsAreEqual,
3968
+ keyExtractor: keyExtractorProp,
3969
+ ListEmptyComponent,
3970
+ ListHeaderComponent,
3971
+ maintainScrollAtEnd = false,
3972
+ maintainScrollAtEndThreshold = 0.1,
3973
+ maintainVisibleContentPosition: maintainVisibleContentPositionProp,
3974
+ numColumns: numColumnsProp = 1,
3975
+ overrideItemLayout,
3976
+ onEndReached,
3977
+ onEndReachedThreshold = 0.5,
3978
+ onItemSizeChanged,
3979
+ onMetricsChange,
3980
+ onLayout: onLayoutProp,
3981
+ onLoad,
3982
+ onMomentumScrollEnd,
3983
+ onRefresh,
3984
+ onScroll: onScrollProp,
3985
+ onStartReached,
3986
+ onStartReachedThreshold = 0.5,
3987
+ onStickyHeaderChange,
3988
+ onViewableItemsChanged,
3989
+ progressViewOffset,
3990
+ recycleItems = false,
3991
+ refreshControl,
3992
+ refreshing,
3993
+ refScrollView,
3994
+ renderItem,
3995
+ scrollEventThrottle,
3996
+ snapToIndices,
3997
+ stickyHeaderIndices: stickyHeaderIndicesProp,
3998
+ stickyIndices: stickyIndicesDeprecated,
3999
+ // TODOV3: Remove from v3 release
4000
+ style: styleProp,
4001
+ suggestEstimatedItemSize,
4002
+ viewabilityConfig,
4003
+ viewabilityConfigCallbackPairs,
4004
+ waitForInitialLayout = true,
4005
+ ...rest
4006
+ } = props;
4007
+ const animatedPropsInternal = props.animatedPropsInternal;
4008
+ const stickyPositionComponentInternal = props.stickyPositionComponentInternal;
4009
+ const {
4010
+ childrenMode,
4011
+ stickyPositionComponentInternal: _stickyPositionComponentInternal,
4012
+ ...restProps
4013
+ } = rest;
4014
+ const contentContainerStyleBase = StyleSheet.flatten(contentContainerStyleProp);
4015
+ const shouldFlexGrow = alignItemsAtEnd && (horizontal ? (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minWidth) == null : (contentContainerStyleBase == null ? void 0 : contentContainerStyleBase.minHeight) == null);
4016
+ const contentContainerStyle = {
4017
+ ...contentContainerStyleBase,
4018
+ ...alignItemsAtEnd ? {
4019
+ display: "flex",
4020
+ flexDirection: horizontal ? "row" : "column",
4021
+ ...shouldFlexGrow ? { flexGrow: 1 } : {},
4022
+ justifyContent: "flex-end"
4023
+ } : {}
4024
+ };
4025
+ const style = { ...StyleSheet.flatten(styleProp) };
4026
+ const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
4027
+ const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
4028
+ const maintainVisibleContentPositionConfig = normalizeMaintainVisibleContentPosition(
4029
+ maintainVisibleContentPositionProp
4030
+ );
4031
+ const [renderNum, setRenderNum] = React3.useState(0);
4032
+ const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState, viewPosition: 1 } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? {
4033
+ index: initialScrollIndexProp.index || 0,
4034
+ viewOffset: initialScrollIndexProp.viewOffset || (initialScrollIndexProp.viewPosition === 1 ? -stylePaddingBottomState : 0),
4035
+ viewPosition: initialScrollIndexProp.viewPosition || 0
4036
+ } : {
4037
+ index: initialScrollIndexProp || 0,
4038
+ viewOffset: initialScrollOffsetProp || 0
4039
+ } : void 0;
4040
+ const [canRender, setCanRender] = React3__namespace.useState(false);
4041
+ const ctx = useStateContext();
4042
+ ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
4043
+ const refScroller = React3.useRef(null);
4044
+ const combinedRef = useCombinedRef(refScroller, refScrollView);
4045
+ const keyExtractor = keyExtractorProp != null ? keyExtractorProp : ((_item, index) => index.toString());
4046
+ const stickyHeaderIndices = stickyHeaderIndicesProp != null ? stickyHeaderIndicesProp : stickyIndicesDeprecated;
4047
+ const alwaysRenderIndices = React3.useMemo(() => {
4048
+ const indices = getAlwaysRenderIndices(alwaysRender, dataProp, keyExtractor);
4049
+ return { arr: indices, set: new Set(indices) };
4050
+ }, [
4051
+ alwaysRender == null ? void 0 : alwaysRender.top,
4052
+ alwaysRender == null ? void 0 : alwaysRender.bottom,
4053
+ (_a3 = alwaysRender == null ? void 0 : alwaysRender.indices) == null ? void 0 : _a3.join(","),
4054
+ (_b = alwaysRender == null ? void 0 : alwaysRender.keys) == null ? void 0 : _b.join(","),
4055
+ dataProp,
4056
+ dataVersion,
4057
+ keyExtractor
4058
+ ]);
4059
+ if (IS_DEV && stickyIndicesDeprecated && !stickyHeaderIndicesProp) {
4060
+ warnDevOnce(
4061
+ "stickyIndices",
4062
+ "stickyIndices has been renamed to stickyHeaderIndices. Please update your props to use stickyHeaderIndices."
4063
+ );
4064
+ }
4065
+ const refState = React3.useRef();
4066
+ const hasOverrideItemLayout = !!overrideItemLayout;
4067
+ const prevHasOverrideItemLayout = React3.useRef(hasOverrideItemLayout);
4068
+ if (!refState.current) {
4069
+ if (!ctx.state) {
4070
+ const initialScrollLength = (estimatedListSize != null ? estimatedListSize : { height: 0, width: 0 } )[horizontal ? "width" : "height"];
4071
+ ctx.state = {
4072
+ activeStickyIndex: -1,
4073
+ averageSizes: {},
4074
+ columnSpans: /* @__PURE__ */ new Map(),
4075
+ columns: /* @__PURE__ */ new Map(),
4076
+ containerItemKeys: /* @__PURE__ */ new Map(),
4077
+ containerItemTypes: /* @__PURE__ */ new Map(),
4078
+ contentInsetOverride: void 0,
4079
+ dataChangeNeedsScrollUpdate: false,
4080
+ didColumnsChange: false,
4081
+ didDataChange: false,
4082
+ enableScrollForNextCalculateItemsInView: true,
4083
+ endBuffered: -1,
4084
+ endNoBuffer: -1,
4085
+ endReachedSnapshot: void 0,
4086
+ firstFullyOnScreenIndex: -1,
4087
+ idCache: [],
4088
+ idsInView: [],
4089
+ indexByKey: /* @__PURE__ */ new Map(),
4090
+ initialAnchor: (initialScrollProp == null ? void 0 : initialScrollProp.index) !== void 0 && (initialScrollProp == null ? void 0 : initialScrollProp.viewPosition) !== void 0 ? {
4091
+ attempts: 0,
4092
+ index: initialScrollProp.index,
4093
+ settledTicks: 0,
4094
+ viewOffset: (_c = initialScrollProp.viewOffset) != null ? _c : 0,
4095
+ viewPosition: initialScrollProp.viewPosition
4096
+ } : void 0,
4097
+ initialScroll: initialScrollProp,
4098
+ isAtEnd: false,
4099
+ isAtStart: false,
4100
+ isEndReached: null,
4101
+ isFirst: true,
4102
+ isStartReached: null,
4103
+ lastBatchingAction: Date.now(),
4104
+ lastLayout: void 0,
4105
+ lastScrollDelta: 0,
4106
+ loadStartTime: Date.now(),
4107
+ minIndexSizeChanged: 0,
4108
+ nativeContentInset: void 0,
4109
+ nativeMarginTop: 0,
4110
+ positions: /* @__PURE__ */ new Map(),
4111
+ props: {},
4112
+ queuedCalculateItemsInView: 0,
4113
+ refScroller: void 0,
4114
+ scroll: 0,
4115
+ scrollAdjustHandler: new ScrollAdjustHandler(ctx),
4116
+ scrollForNextCalculateItemsInView: void 0,
4117
+ scrollHistory: [],
4118
+ scrollLength: initialScrollLength,
4119
+ scrollPending: 0,
4120
+ scrollPrev: 0,
4121
+ scrollPrevTime: 0,
4122
+ scrollProcessingEnabled: true,
4123
+ scrollTime: 0,
4124
+ sizes: /* @__PURE__ */ new Map(),
4125
+ sizesKnown: /* @__PURE__ */ new Map(),
4126
+ startBuffered: -1,
4127
+ startNoBuffer: -1,
4128
+ startReachedSnapshot: void 0,
4129
+ stickyContainerPool: /* @__PURE__ */ new Set(),
4130
+ stickyContainers: /* @__PURE__ */ new Map(),
4131
+ timeoutSizeMessage: 0,
4132
+ timeouts: /* @__PURE__ */ new Set(),
4133
+ totalSize: 0,
4134
+ viewabilityConfigCallbackPairs: void 0
4135
+ };
4136
+ const internalState = ctx.state;
4137
+ internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, params);
4138
+ set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPositionConfig);
4139
+ set$(ctx, "extraData", extraData);
4140
+ }
4141
+ refState.current = ctx.state;
4142
+ }
4143
+ const state = refState.current;
4144
+ const isFirstLocal = state.isFirst;
4145
+ state.didColumnsChange = numColumnsProp !== state.props.numColumns;
4146
+ const didDataChangeLocal = state.props.dataVersion !== dataVersion || state.props.data !== dataProp && checkActualChange(state, dataProp, state.props.data);
4147
+ if (didDataChangeLocal) {
4148
+ state.dataChangeNeedsScrollUpdate = true;
4149
+ state.didDataChange = true;
4150
+ state.previousData = state.props.data;
4151
+ }
4152
+ const throttleScrollFn = scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp;
4153
+ state.props = {
4154
+ alignItemsAtEnd,
4155
+ alwaysRender,
4156
+ alwaysRenderIndicesArr: alwaysRenderIndices.arr,
4157
+ alwaysRenderIndicesSet: alwaysRenderIndices.set,
4158
+ animatedProps: animatedPropsInternal,
4159
+ contentInset,
4160
+ data: dataProp,
4161
+ dataVersion,
4162
+ drawDistance,
4163
+ estimatedItemSize,
4164
+ getEstimatedItemSize: useWrapIfItem(getEstimatedItemSize),
4165
+ getFixedItemSize: useWrapIfItem(getFixedItemSize),
4166
+ getItemType: useWrapIfItem(getItemType),
4167
+ horizontal: !!horizontal,
4168
+ initialContainerPoolRatio,
4169
+ itemsAreEqual,
4170
+ keyExtractor: useWrapIfItem(keyExtractor),
4171
+ maintainScrollAtEnd,
4172
+ maintainScrollAtEndThreshold,
4173
+ maintainVisibleContentPosition: maintainVisibleContentPositionConfig,
4174
+ numColumns: numColumnsProp,
4175
+ onEndReached,
4176
+ onEndReachedThreshold,
4177
+ onItemSizeChanged,
4178
+ onLoad,
4179
+ onScroll: throttleScrollFn,
4180
+ onStartReached,
4181
+ onStartReachedThreshold,
4182
+ onStickyHeaderChange,
4183
+ overrideItemLayout,
4184
+ recycleItems: !!recycleItems,
4185
+ renderItem,
4186
+ snapToIndices,
4187
+ stickyIndicesArr: stickyHeaderIndices != null ? stickyHeaderIndices : [],
4188
+ stickyIndicesSet: React3.useMemo(() => new Set(stickyHeaderIndices != null ? stickyHeaderIndices : []), [stickyHeaderIndices == null ? void 0 : stickyHeaderIndices.join(",")]),
4189
+ stickyPositionComponentInternal,
4190
+ stylePaddingBottom: stylePaddingBottomState,
4191
+ stylePaddingTop: stylePaddingTopState,
4192
+ suggestEstimatedItemSize: !!suggestEstimatedItemSize
4193
+ };
4194
+ state.refScroller = refScroller;
4195
+ const memoizedLastItemKeys = React3.useMemo(() => {
4196
+ if (!dataProp.length) return [];
4197
+ return Array.from(
4198
+ { length: Math.min(numColumnsProp, dataProp.length) },
4199
+ (_, i) => getId(state, dataProp.length - 1 - i)
4200
+ );
4201
+ }, [dataProp, dataVersion, numColumnsProp]);
4202
+ const initializeStateVars = (shouldAdjustPadding) => {
4203
+ set$(ctx, "lastItemKeys", memoizedLastItemKeys);
4204
+ set$(ctx, "numColumns", numColumnsProp);
4205
+ const prevPaddingTop = peek$(ctx, "stylePaddingTop");
4206
+ setPaddingTop(ctx, { stylePaddingTop: stylePaddingTopState });
4207
+ refState.current.props.stylePaddingBottom = stylePaddingBottomState;
4208
+ let paddingDiff = stylePaddingTopState - prevPaddingTop;
4209
+ if (shouldAdjustPadding && maintainVisibleContentPositionConfig.size && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") ;
4210
+ };
4211
+ if (isFirstLocal) {
4212
+ initializeStateVars(false);
4213
+ updateItemPositions(
4214
+ ctx,
4215
+ /*dataChanged*/
4216
+ true
4217
+ );
4218
+ }
4219
+ const initialContentOffset = React3.useMemo(() => {
4220
+ let value;
4221
+ const { initialScroll, initialAnchor } = refState.current;
4222
+ if (initialScroll) {
4223
+ if (initialScroll.contentOffset !== void 0) {
4224
+ value = initialScroll.contentOffset;
4225
+ } else {
4226
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, initialScroll.index) : 0;
4227
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, baseOffset, initialScroll);
4228
+ const clampedOffset = clampScrollOffset(ctx, resolvedOffset, initialScroll);
4229
+ const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
4230
+ refState.current.initialScroll = updatedInitialScroll;
4231
+ state.initialScroll = updatedInitialScroll;
4232
+ value = clampedOffset;
4233
+ }
4234
+ } else {
4235
+ refState.current.initialAnchor = void 0;
4236
+ value = 0;
4237
+ }
4238
+ if (!value) {
4239
+ setInitialRenderState(ctx, { didInitialScroll: true });
4240
+ }
4241
+ return value;
4242
+ }, [renderNum]);
4243
+ if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
4244
+ refState.current.lastBatchingAction = Date.now();
4245
+ if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
4246
+ IS_DEV && !childrenMode && warnDevOnce(
4247
+ "keyExtractor",
4248
+ "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."
4249
+ );
4250
+ refState.current.sizes.clear();
4251
+ refState.current.positions.clear();
4252
+ refState.current.totalSize = 0;
4253
+ set$(ctx, "totalSize", 0);
4254
+ }
4255
+ }
4256
+ const onLayoutHeader = React3.useCallback((rect, fromLayoutEffect) => {
4257
+ const { initialScroll } = refState.current;
4258
+ const size = rect[horizontal ? "width" : "height"];
4259
+ set$(ctx, "headerSize", size);
4260
+ if ((initialScroll == null ? void 0 : initialScroll.index) !== void 0) {
4261
+ {
4262
+ if (fromLayoutEffect) {
4263
+ setRenderNum((v) => v + 1);
4264
+ }
4265
+ }
4266
+ }
4267
+ }, []);
4268
+ const doInitialScroll = React3.useCallback(() => {
4269
+ const { initialScroll, didFinishInitialScroll, queuedInitialLayout, scrollingTo } = state;
4270
+ if (initialScroll && !queuedInitialLayout && !didFinishInitialScroll && !scrollingTo) {
4271
+ scrollTo(ctx, {
4272
+ animated: false,
4273
+ index: initialScroll == null ? void 0 : initialScroll.index,
4274
+ isInitialScroll: true,
4275
+ offset: initialContentOffset,
4276
+ precomputedWithViewOffset: true
4277
+ });
4278
+ }
4279
+ }, [initialContentOffset]);
4280
+ const onLayoutChange = React3.useCallback((layout) => {
4281
+ doInitialScroll();
4282
+ handleLayout(ctx, layout, setCanRender);
4283
+ }, []);
4284
+ const { onLayout } = useOnLayoutSync({
4285
+ onLayoutChange,
4286
+ onLayoutProp,
4287
+ ref: refScroller
4288
+ // the type of ScrollView doesn't include measure?
4289
+ });
4290
+ React3.useLayoutEffect(() => {
4291
+ if (snapToIndices) {
4292
+ updateSnapToOffsets(ctx);
4293
+ }
4294
+ }, [snapToIndices]);
4295
+ React3.useLayoutEffect(() => {
4296
+ const {
4297
+ didColumnsChange,
4298
+ didDataChange,
4299
+ isFirst,
4300
+ props: { data }
4301
+ } = state;
4302
+ const didAllocateContainers = data.length > 0 && doInitialAllocateContainers(ctx);
4303
+ if (!didAllocateContainers && !isFirst && (didDataChange || didColumnsChange)) {
4304
+ checkResetContainers(ctx, data);
4305
+ }
4306
+ state.didColumnsChange = false;
4307
+ state.didDataChange = false;
4308
+ state.isFirst = false;
4309
+ }, [dataProp, dataVersion, numColumnsProp]);
4310
+ React3.useLayoutEffect(() => {
4311
+ var _a4;
4312
+ set$(ctx, "extraData", extraData);
4313
+ const didToggleOverride = prevHasOverrideItemLayout.current !== hasOverrideItemLayout;
4314
+ prevHasOverrideItemLayout.current = hasOverrideItemLayout;
4315
+ if ((hasOverrideItemLayout || didToggleOverride) && numColumnsProp > 1) {
4316
+ (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { forceFullItemPositions: true });
4317
+ }
4318
+ }, [extraData, hasOverrideItemLayout, numColumnsProp]);
4319
+ React3.useLayoutEffect(
4320
+ () => initializeStateVars(true),
4321
+ [dataVersion, memoizedLastItemKeys.join(","), numColumnsProp, stylePaddingBottomState, stylePaddingTopState]
4322
+ );
4323
+ React3.useEffect(() => {
4324
+ if (!onMetricsChange) {
4325
+ return;
4326
+ }
4327
+ let lastMetrics;
4328
+ const emitMetrics = () => {
4329
+ const metrics = {
4330
+ footerSize: peek$(ctx, "footerSize") || 0,
4331
+ headerSize: peek$(ctx, "headerSize") || 0
4332
+ };
4333
+ if (!lastMetrics || metrics.headerSize !== lastMetrics.headerSize || metrics.footerSize !== lastMetrics.footerSize) {
4334
+ lastMetrics = metrics;
4335
+ onMetricsChange(metrics);
4336
+ }
4337
+ };
4338
+ emitMetrics();
4339
+ const unsubscribe = [listen$(ctx, "headerSize", emitMetrics), listen$(ctx, "footerSize", emitMetrics)];
4340
+ return () => {
4341
+ for (const unsub of unsubscribe) {
4342
+ unsub();
4343
+ }
4344
+ };
4345
+ }, [ctx, onMetricsChange]);
4346
+ React3.useEffect(() => {
4347
+ const viewability = setupViewability({
4348
+ onViewableItemsChanged,
4349
+ viewabilityConfig,
4350
+ viewabilityConfigCallbackPairs
4351
+ });
4352
+ state.viewabilityConfigCallbackPairs = viewability;
4353
+ state.enableScrollForNextCalculateItemsInView = !viewability;
4354
+ }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
4355
+ React3.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx), []);
4356
+ {
4357
+ React3.useEffect(doInitialScroll, []);
4358
+ }
4359
+ const fns = React3.useMemo(
4360
+ () => ({
4361
+ getRenderedItem: (key) => getRenderedItem(ctx, key),
4362
+ onMomentumScrollEnd: (event) => {
4363
+ checkFinishedScrollFallback(ctx);
4364
+ if (onMomentumScrollEnd) {
4365
+ onMomentumScrollEnd(event);
4366
+ }
4367
+ },
4368
+ onScroll: (event) => onScroll(ctx, event),
4369
+ updateItemSize: (itemKey, sizeObj) => updateItemSize(ctx, itemKey, sizeObj)
4370
+ }),
4371
+ []
4372
+ );
4373
+ const onScrollHandler = useStickyScrollHandler(stickyHeaderIndices, horizontal, ctx, fns.onScroll);
4374
+ return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement(
4375
+ ListComponent,
4376
+ {
4377
+ ...restProps,
4378
+ alignItemsAtEnd,
4379
+ canRender,
4380
+ contentContainerStyle,
4381
+ contentInset,
4382
+ getRenderedItem: fns.getRenderedItem,
4383
+ horizontal,
4384
+ initialContentOffset,
4385
+ ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
4386
+ ListHeaderComponent,
4387
+ onLayout,
4388
+ onLayoutHeader,
4389
+ onMomentumScrollEnd: fns.onMomentumScrollEnd,
4390
+ onScroll: onScrollHandler,
4391
+ recycleItems,
4392
+ refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
4393
+ progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
4394
+ }) : refreshControl : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
4395
+ RefreshControl,
4396
+ {
4397
+ onRefresh,
4398
+ progressViewOffset: (progressViewOffset || 0) + stylePaddingTopState,
4399
+ refreshing: !!refreshing
4400
+ }
4401
+ ),
4402
+ refScrollView: combinedRef,
4403
+ scrollAdjustHandler: (_d = refState.current) == null ? void 0 : _d.scrollAdjustHandler,
4404
+ scrollEventThrottle: 0,
4405
+ snapToIndices,
4406
+ stickyHeaderIndices,
4407
+ style,
4408
+ updateItemSize: fns.updateItemSize,
4409
+ waitForInitialLayout
4410
+ }
4411
+ ), IS_DEV && ENABLE_DEBUG_VIEW);
4412
+ });
4413
+
4414
+ // src/react.ts
4415
+ var LegendList3 = LegendList;
4416
+
4417
+ exports.LegendList = LegendList3;
4418
+ exports.typedForwardRef = typedForwardRef;
4419
+ exports.typedMemo = typedMemo;
4420
+ exports.useIsLastItem = useIsLastItem;
4421
+ exports.useListScrollSize = useListScrollSize;
4422
+ exports.useRecyclingEffect = useRecyclingEffect;
4423
+ exports.useRecyclingState = useRecyclingState;
4424
+ exports.useSyncLayout = useSyncLayout;
4425
+ exports.useViewability = useViewability;
4426
+ exports.useViewabilityAmount = useViewabilityAmount;