@legendapp/list 2.0.0-next.8 → 2.1.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.mjs CHANGED
@@ -1,17 +1,477 @@
1
1
  import * as React3 from 'react';
2
- import React3__default, { useReducer, useEffect, createContext, useRef, useState, useMemo, useLayoutEffect, useCallback, useImperativeHandle, useContext, forwardRef, memo } from 'react';
3
- import { View, Text, Platform, Animated, ScrollView, StyleSheet, Dimensions, RefreshControl, unstable_batchedUpdates } from 'react-native';
2
+ import React3__default, { forwardRef, useReducer, useEffect, createContext, useRef, useState, useMemo, useImperativeHandle, useCallback, useLayoutEffect, memo, useContext } from 'react';
4
3
  import { useSyncExternalStore } from 'use-sync-external-store/shim';
5
4
 
6
- // src/components/LazyLegendList.tsx
5
+ var __create = Object.create;
6
+ var __defProp = Object.defineProperty;
7
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
8
+ var __getOwnPropNames = Object.getOwnPropertyNames;
9
+ var __getProtoOf = Object.getPrototypeOf;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
12
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
13
+ }) : x)(function(x) {
14
+ if (typeof require !== "undefined") return require.apply(this, arguments);
15
+ throw Error('Dynamic require of "' + x + '" is not supported');
16
+ });
17
+ var __commonJS = (cb, mod) => function __require2() {
18
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
19
+ };
20
+ var __copyProps = (to, from, except, desc) => {
21
+ if (from && typeof from === "object" || typeof from === "function") {
22
+ for (let key of __getOwnPropNames(from))
23
+ if (!__hasOwnProp.call(to, key) && key !== except)
24
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
+ // If the importer is in node compatibility mode or this is not an ESM
30
+ // file that has been converted to a CommonJS file using a Babel-
31
+ // compatible transform (i.e. "__esModule" has not been set), then set
32
+ // "default" to the CommonJS "module.exports" for node compatibility.
33
+ !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
+ mod
35
+ ));
36
+
37
+ // node_modules/react-dom/cjs/react-dom.production.js
38
+ var require_react_dom_production = __commonJS({
39
+ "node_modules/react-dom/cjs/react-dom.production.js"(exports) {
40
+ var React12 = __require("react");
41
+ function formatProdErrorMessage(code) {
42
+ var url = "https://react.dev/errors/" + code;
43
+ if (1 < arguments.length) {
44
+ url += "?args[]=" + encodeURIComponent(arguments[1]);
45
+ for (var i = 2; i < arguments.length; i++)
46
+ url += "&args[]=" + encodeURIComponent(arguments[i]);
47
+ }
48
+ return "Minified React error #" + code + "; visit " + url + " for the full message or use the non-minified dev environment for full errors and additional helpful warnings.";
49
+ }
50
+ function noop2() {
51
+ }
52
+ var Internals = {
53
+ d: {
54
+ f: noop2,
55
+ r: function() {
56
+ throw Error(formatProdErrorMessage(522));
57
+ },
58
+ D: noop2,
59
+ C: noop2,
60
+ L: noop2,
61
+ m: noop2,
62
+ X: noop2,
63
+ S: noop2,
64
+ M: noop2
65
+ },
66
+ p: 0,
67
+ findDOMNode: null
68
+ };
69
+ var REACT_PORTAL_TYPE = Symbol.for("react.portal");
70
+ function createPortal$1(children, containerInfo, implementation) {
71
+ var key = 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null;
72
+ return {
73
+ $$typeof: REACT_PORTAL_TYPE,
74
+ key: null == key ? null : "" + key,
75
+ children,
76
+ containerInfo,
77
+ implementation
78
+ };
79
+ }
80
+ var ReactSharedInternals = React12.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
81
+ function getCrossOriginStringAs(as, input) {
82
+ if ("font" === as) return "";
83
+ if ("string" === typeof input)
84
+ return "use-credentials" === input ? input : "";
85
+ }
86
+ exports.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = Internals;
87
+ exports.createPortal = function(children, container) {
88
+ var key = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null;
89
+ if (!container || 1 !== container.nodeType && 9 !== container.nodeType && 11 !== container.nodeType)
90
+ throw Error(formatProdErrorMessage(299));
91
+ return createPortal$1(children, container, null, key);
92
+ };
93
+ exports.flushSync = function(fn) {
94
+ var previousTransition = ReactSharedInternals.T, previousUpdatePriority = Internals.p;
95
+ try {
96
+ if (ReactSharedInternals.T = null, Internals.p = 2, fn) return fn();
97
+ } finally {
98
+ ReactSharedInternals.T = previousTransition, Internals.p = previousUpdatePriority, Internals.d.f();
99
+ }
100
+ };
101
+ exports.preconnect = function(href, options) {
102
+ "string" === typeof href && (options ? (options = options.crossOrigin, options = "string" === typeof options ? "use-credentials" === options ? options : "" : void 0) : options = null, Internals.d.C(href, options));
103
+ };
104
+ exports.prefetchDNS = function(href) {
105
+ "string" === typeof href && Internals.d.D(href);
106
+ };
107
+ exports.preinit = function(href, options) {
108
+ if ("string" === typeof href && options && "string" === typeof options.as) {
109
+ var as = options.as, crossOrigin = getCrossOriginStringAs(as, options.crossOrigin), integrity = "string" === typeof options.integrity ? options.integrity : void 0, fetchPriority = "string" === typeof options.fetchPriority ? options.fetchPriority : void 0;
110
+ "style" === as ? Internals.d.S(
111
+ href,
112
+ "string" === typeof options.precedence ? options.precedence : void 0,
113
+ {
114
+ crossOrigin,
115
+ integrity,
116
+ fetchPriority
117
+ }
118
+ ) : "script" === as && Internals.d.X(href, {
119
+ crossOrigin,
120
+ integrity,
121
+ fetchPriority,
122
+ nonce: "string" === typeof options.nonce ? options.nonce : void 0
123
+ });
124
+ }
125
+ };
126
+ exports.preinitModule = function(href, options) {
127
+ if ("string" === typeof href)
128
+ if ("object" === typeof options && null !== options) {
129
+ if (null == options.as || "script" === options.as) {
130
+ var crossOrigin = getCrossOriginStringAs(
131
+ options.as,
132
+ options.crossOrigin
133
+ );
134
+ Internals.d.M(href, {
135
+ crossOrigin,
136
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0,
137
+ nonce: "string" === typeof options.nonce ? options.nonce : void 0
138
+ });
139
+ }
140
+ } else null == options && Internals.d.M(href);
141
+ };
142
+ exports.preload = function(href, options) {
143
+ if ("string" === typeof href && "object" === typeof options && null !== options && "string" === typeof options.as) {
144
+ var as = options.as, crossOrigin = getCrossOriginStringAs(as, options.crossOrigin);
145
+ Internals.d.L(href, as, {
146
+ crossOrigin,
147
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0,
148
+ nonce: "string" === typeof options.nonce ? options.nonce : void 0,
149
+ type: "string" === typeof options.type ? options.type : void 0,
150
+ fetchPriority: "string" === typeof options.fetchPriority ? options.fetchPriority : void 0,
151
+ referrerPolicy: "string" === typeof options.referrerPolicy ? options.referrerPolicy : void 0,
152
+ imageSrcSet: "string" === typeof options.imageSrcSet ? options.imageSrcSet : void 0,
153
+ imageSizes: "string" === typeof options.imageSizes ? options.imageSizes : void 0,
154
+ media: "string" === typeof options.media ? options.media : void 0
155
+ });
156
+ }
157
+ };
158
+ exports.preloadModule = function(href, options) {
159
+ if ("string" === typeof href)
160
+ if (options) {
161
+ var crossOrigin = getCrossOriginStringAs(options.as, options.crossOrigin);
162
+ Internals.d.m(href, {
163
+ as: "string" === typeof options.as && "script" !== options.as ? options.as : void 0,
164
+ crossOrigin,
165
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0
166
+ });
167
+ } else Internals.d.m(href);
168
+ };
169
+ exports.requestFormReset = function(form) {
170
+ Internals.d.r(form);
171
+ };
172
+ exports.unstable_batchedUpdates = function(fn, a) {
173
+ return fn(a);
174
+ };
175
+ exports.useFormState = function(action, initialState, permalink) {
176
+ return ReactSharedInternals.H.useFormState(action, initialState, permalink);
177
+ };
178
+ exports.useFormStatus = function() {
179
+ return ReactSharedInternals.H.useHostTransitionStatus();
180
+ };
181
+ exports.version = "19.1.1";
182
+ }
183
+ });
184
+
185
+ // node_modules/react-dom/cjs/react-dom.development.js
186
+ var require_react_dom_development = __commonJS({
187
+ "node_modules/react-dom/cjs/react-dom.development.js"(exports) {
188
+ "production" !== process.env.NODE_ENV && function() {
189
+ function noop2() {
190
+ }
191
+ function testStringCoercion(value) {
192
+ return "" + value;
193
+ }
194
+ function createPortal$1(children, containerInfo, implementation) {
195
+ var key = 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null;
196
+ try {
197
+ testStringCoercion(key);
198
+ var JSCompiler_inline_result = false;
199
+ } catch (e) {
200
+ JSCompiler_inline_result = true;
201
+ }
202
+ JSCompiler_inline_result && (console.error(
203
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
204
+ "function" === typeof Symbol && Symbol.toStringTag && key[Symbol.toStringTag] || key.constructor.name || "Object"
205
+ ), testStringCoercion(key));
206
+ return {
207
+ $$typeof: REACT_PORTAL_TYPE,
208
+ key: null == key ? null : "" + key,
209
+ children,
210
+ containerInfo,
211
+ implementation
212
+ };
213
+ }
214
+ function getCrossOriginStringAs(as, input) {
215
+ if ("font" === as) return "";
216
+ if ("string" === typeof input)
217
+ return "use-credentials" === input ? input : "";
218
+ }
219
+ function getValueDescriptorExpectingObjectForWarning(thing) {
220
+ return null === thing ? "`null`" : void 0 === thing ? "`undefined`" : "" === thing ? "an empty string" : 'something with type "' + typeof thing + '"';
221
+ }
222
+ function getValueDescriptorExpectingEnumForWarning(thing) {
223
+ return null === thing ? "`null`" : void 0 === thing ? "`undefined`" : "" === thing ? "an empty string" : "string" === typeof thing ? JSON.stringify(thing) : "number" === typeof thing ? "`" + thing + "`" : 'something with type "' + typeof thing + '"';
224
+ }
225
+ function resolveDispatcher() {
226
+ var dispatcher = ReactSharedInternals.H;
227
+ null === dispatcher && console.error(
228
+ "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:\n1. You might have mismatching versions of React and the renderer (such as React DOM)\n2. You might be breaking the Rules of Hooks\n3. You might have more than one copy of React in the same app\nSee https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem."
229
+ );
230
+ return dispatcher;
231
+ }
232
+ "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
233
+ var React12 = __require("react"), Internals = {
234
+ d: {
235
+ f: noop2,
236
+ r: function() {
237
+ throw Error(
238
+ "Invalid form element. requestFormReset must be passed a form that was rendered by React."
239
+ );
240
+ },
241
+ D: noop2,
242
+ C: noop2,
243
+ L: noop2,
244
+ m: noop2,
245
+ X: noop2,
246
+ S: noop2,
247
+ M: noop2
248
+ },
249
+ p: 0,
250
+ findDOMNode: null
251
+ }, REACT_PORTAL_TYPE = Symbol.for("react.portal"), ReactSharedInternals = React12.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
252
+ "function" === typeof Map && null != Map.prototype && "function" === typeof Map.prototype.forEach && "function" === typeof Set && null != Set.prototype && "function" === typeof Set.prototype.clear && "function" === typeof Set.prototype.forEach || console.error(
253
+ "React depends on Map and Set built-in types. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills"
254
+ );
255
+ exports.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = Internals;
256
+ exports.createPortal = function(children, container) {
257
+ var key = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null;
258
+ if (!container || 1 !== container.nodeType && 9 !== container.nodeType && 11 !== container.nodeType)
259
+ throw Error("Target container is not a DOM element.");
260
+ return createPortal$1(children, container, null, key);
261
+ };
262
+ exports.flushSync = function(fn) {
263
+ var previousTransition = ReactSharedInternals.T, previousUpdatePriority = Internals.p;
264
+ try {
265
+ if (ReactSharedInternals.T = null, Internals.p = 2, fn)
266
+ return fn();
267
+ } finally {
268
+ ReactSharedInternals.T = previousTransition, Internals.p = previousUpdatePriority, Internals.d.f() && console.error(
269
+ "flushSync was called from inside a lifecycle method. React cannot flush when React is already rendering. Consider moving this call to a scheduler task or micro task."
270
+ );
271
+ }
272
+ };
273
+ exports.preconnect = function(href, options) {
274
+ "string" === typeof href && href ? null != options && "object" !== typeof options ? console.error(
275
+ "ReactDOM.preconnect(): Expected the `options` argument (second) to be an object but encountered %s instead. The only supported option at this time is `crossOrigin` which accepts a string.",
276
+ getValueDescriptorExpectingEnumForWarning(options)
277
+ ) : null != options && "string" !== typeof options.crossOrigin && console.error(
278
+ "ReactDOM.preconnect(): Expected the `crossOrigin` option (second argument) to be a string but encountered %s instead. Try removing this option or passing a string value instead.",
279
+ getValueDescriptorExpectingObjectForWarning(options.crossOrigin)
280
+ ) : console.error(
281
+ "ReactDOM.preconnect(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.",
282
+ getValueDescriptorExpectingObjectForWarning(href)
283
+ );
284
+ "string" === typeof href && (options ? (options = options.crossOrigin, options = "string" === typeof options ? "use-credentials" === options ? options : "" : void 0) : options = null, Internals.d.C(href, options));
285
+ };
286
+ exports.prefetchDNS = function(href) {
287
+ if ("string" !== typeof href || !href)
288
+ console.error(
289
+ "ReactDOM.prefetchDNS(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.",
290
+ getValueDescriptorExpectingObjectForWarning(href)
291
+ );
292
+ else if (1 < arguments.length) {
293
+ var options = arguments[1];
294
+ "object" === typeof options && options.hasOwnProperty("crossOrigin") ? console.error(
295
+ "ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. It looks like the you are attempting to set a crossOrigin property for this DNS lookup hint. Browsers do not perform DNS queries using CORS and setting this attribute on the resource hint has no effect. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.",
296
+ getValueDescriptorExpectingEnumForWarning(options)
297
+ ) : console.error(
298
+ "ReactDOM.prefetchDNS(): Expected only one argument, `href`, but encountered %s as a second argument instead. This argument is reserved for future options and is currently disallowed. Try calling ReactDOM.prefetchDNS() with just a single string argument, `href`.",
299
+ getValueDescriptorExpectingEnumForWarning(options)
300
+ );
301
+ }
302
+ "string" === typeof href && Internals.d.D(href);
303
+ };
304
+ exports.preinit = function(href, options) {
305
+ "string" === typeof href && href ? null == options || "object" !== typeof options ? console.error(
306
+ "ReactDOM.preinit(): Expected the `options` argument (second) to be an object with an `as` property describing the type of resource to be preinitialized but encountered %s instead.",
307
+ getValueDescriptorExpectingEnumForWarning(options)
308
+ ) : "style" !== options.as && "script" !== options.as && console.error(
309
+ 'ReactDOM.preinit(): Expected the `as` property in the `options` argument (second) to contain a valid value describing the type of resource to be preinitialized but encountered %s instead. Valid values for `as` are "style" and "script".',
310
+ getValueDescriptorExpectingEnumForWarning(options.as)
311
+ ) : console.error(
312
+ "ReactDOM.preinit(): Expected the `href` argument (first) to be a non-empty string but encountered %s instead.",
313
+ getValueDescriptorExpectingObjectForWarning(href)
314
+ );
315
+ if ("string" === typeof href && options && "string" === typeof options.as) {
316
+ var as = options.as, crossOrigin = getCrossOriginStringAs(as, options.crossOrigin), integrity = "string" === typeof options.integrity ? options.integrity : void 0, fetchPriority = "string" === typeof options.fetchPriority ? options.fetchPriority : void 0;
317
+ "style" === as ? Internals.d.S(
318
+ href,
319
+ "string" === typeof options.precedence ? options.precedence : void 0,
320
+ {
321
+ crossOrigin,
322
+ integrity,
323
+ fetchPriority
324
+ }
325
+ ) : "script" === as && Internals.d.X(href, {
326
+ crossOrigin,
327
+ integrity,
328
+ fetchPriority,
329
+ nonce: "string" === typeof options.nonce ? options.nonce : void 0
330
+ });
331
+ }
332
+ };
333
+ exports.preinitModule = function(href, options) {
334
+ var encountered = "";
335
+ "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
336
+ void 0 !== options && "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : options && "as" in options && "script" !== options.as && (encountered += " The `as` option encountered was " + getValueDescriptorExpectingEnumForWarning(options.as) + ".");
337
+ if (encountered)
338
+ console.error(
339
+ "ReactDOM.preinitModule(): Expected up to two arguments, a non-empty `href` string and, optionally, an `options` object with a valid `as` property.%s",
340
+ encountered
341
+ );
342
+ else
343
+ switch (encountered = options && "string" === typeof options.as ? options.as : "script", encountered) {
344
+ case "script":
345
+ break;
346
+ default:
347
+ encountered = getValueDescriptorExpectingEnumForWarning(encountered), console.error(
348
+ 'ReactDOM.preinitModule(): Currently the only supported "as" type for this function is "script" but received "%s" instead. This warning was generated for `href` "%s". In the future other module types will be supported, aligning with the import-attributes proposal. Learn more here: (https://github.com/tc39/proposal-import-attributes)',
349
+ encountered,
350
+ href
351
+ );
352
+ }
353
+ if ("string" === typeof href)
354
+ if ("object" === typeof options && null !== options) {
355
+ if (null == options.as || "script" === options.as)
356
+ encountered = getCrossOriginStringAs(
357
+ options.as,
358
+ options.crossOrigin
359
+ ), Internals.d.M(href, {
360
+ crossOrigin: encountered,
361
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0,
362
+ nonce: "string" === typeof options.nonce ? options.nonce : void 0
363
+ });
364
+ } else null == options && Internals.d.M(href);
365
+ };
366
+ exports.preload = function(href, options) {
367
+ var encountered = "";
368
+ "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
369
+ null == options || "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : "string" === typeof options.as && options.as || (encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".");
370
+ encountered && console.error(
371
+ 'ReactDOM.preload(): Expected two arguments, a non-empty `href` string and an `options` object with an `as` property valid for a `<link rel="preload" as="..." />` tag.%s',
372
+ encountered
373
+ );
374
+ if ("string" === typeof href && "object" === typeof options && null !== options && "string" === typeof options.as) {
375
+ encountered = options.as;
376
+ var crossOrigin = getCrossOriginStringAs(
377
+ encountered,
378
+ options.crossOrigin
379
+ );
380
+ Internals.d.L(href, encountered, {
381
+ crossOrigin,
382
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0,
383
+ nonce: "string" === typeof options.nonce ? options.nonce : void 0,
384
+ type: "string" === typeof options.type ? options.type : void 0,
385
+ fetchPriority: "string" === typeof options.fetchPriority ? options.fetchPriority : void 0,
386
+ referrerPolicy: "string" === typeof options.referrerPolicy ? options.referrerPolicy : void 0,
387
+ imageSrcSet: "string" === typeof options.imageSrcSet ? options.imageSrcSet : void 0,
388
+ imageSizes: "string" === typeof options.imageSizes ? options.imageSizes : void 0,
389
+ media: "string" === typeof options.media ? options.media : void 0
390
+ });
391
+ }
392
+ };
393
+ exports.preloadModule = function(href, options) {
394
+ var encountered = "";
395
+ "string" === typeof href && href || (encountered += " The `href` argument encountered was " + getValueDescriptorExpectingObjectForWarning(href) + ".");
396
+ void 0 !== options && "object" !== typeof options ? encountered += " The `options` argument encountered was " + getValueDescriptorExpectingObjectForWarning(options) + "." : options && "as" in options && "string" !== typeof options.as && (encountered += " The `as` option encountered was " + getValueDescriptorExpectingObjectForWarning(options.as) + ".");
397
+ encountered && console.error(
398
+ 'ReactDOM.preloadModule(): Expected two arguments, a non-empty `href` string and, optionally, an `options` object with an `as` property valid for a `<link rel="modulepreload" as="..." />` tag.%s',
399
+ encountered
400
+ );
401
+ "string" === typeof href && (options ? (encountered = getCrossOriginStringAs(
402
+ options.as,
403
+ options.crossOrigin
404
+ ), Internals.d.m(href, {
405
+ as: "string" === typeof options.as && "script" !== options.as ? options.as : void 0,
406
+ crossOrigin: encountered,
407
+ integrity: "string" === typeof options.integrity ? options.integrity : void 0
408
+ })) : Internals.d.m(href));
409
+ };
410
+ exports.requestFormReset = function(form) {
411
+ Internals.d.r(form);
412
+ };
413
+ exports.unstable_batchedUpdates = function(fn, a) {
414
+ return fn(a);
415
+ };
416
+ exports.useFormState = function(action, initialState, permalink) {
417
+ return resolveDispatcher().useFormState(action, initialState, permalink);
418
+ };
419
+ exports.useFormStatus = function() {
420
+ return resolveDispatcher().useHostTransitionStatus();
421
+ };
422
+ exports.version = "19.1.1";
423
+ "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
424
+ }();
425
+ }
426
+ });
427
+
428
+ // node_modules/react-dom/index.js
429
+ var require_react_dom = __commonJS({
430
+ "node_modules/react-dom/index.js"(exports, module) {
431
+ function checkDCE() {
432
+ if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined" || typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== "function") {
433
+ return;
434
+ }
435
+ if (process.env.NODE_ENV !== "production") {
436
+ throw new Error("^_^");
437
+ }
438
+ try {
439
+ __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);
440
+ } catch (err) {
441
+ console.error(err);
442
+ }
443
+ }
444
+ if (process.env.NODE_ENV === "production") {
445
+ checkDCE();
446
+ module.exports = require_react_dom_production();
447
+ } else {
448
+ module.exports = require_react_dom_development();
449
+ }
450
+ }
451
+ });
452
+ var AnimatedView = forwardRef(function AnimatedView2(props, ref) {
453
+ return /* @__PURE__ */ React.createElement("div", { ref, ...props });
454
+ });
455
+ var View = forwardRef(function View2(props, ref) {
456
+ return /* @__PURE__ */ React.createElement("div", { ref, ...props });
457
+ });
458
+ var Text = View;
459
+
460
+ // src/platform/Animated.tsx
461
+ var createAnimatedValue = (value) => value;
462
+
463
+ // src/state/state.tsx
7
464
  var ContextState = React3.createContext(null);
8
465
  function StateProvider({ children }) {
9
466
  const [value] = React3.useState(() => ({
467
+ animatedScrollY: createAnimatedValue(0),
10
468
  columnWrapperStyle: void 0,
469
+ internalState: void 0,
11
470
  listeners: /* @__PURE__ */ new Map(),
12
471
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
13
472
  mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
14
473
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
474
+ mapViewabilityConfigStates: /* @__PURE__ */ new Map(),
15
475
  mapViewabilityValues: /* @__PURE__ */ new Map(),
16
476
  values: /* @__PURE__ */ new Map([
17
477
  ["alignItemsPaddingTop", 0],
@@ -145,9 +605,7 @@ var DebugView = React3.memo(function DebugView2({ state }) {
145
605
  /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React3.createElement(Text, null, totalSize.toFixed(2))),
146
606
  /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React3.createElement(Text, null, contentSize.toFixed(2))),
147
607
  /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "At end:"), /* @__PURE__ */ React3.createElement(Text, null, String(state.isAtEnd))),
148
- /* @__PURE__ */ React3.createElement(Text, null),
149
608
  /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React3.createElement(Text, null, scrollAdjust.toFixed(2))),
150
- /* @__PURE__ */ React3.createElement(Text, null),
151
609
  /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React3.createElement(Text, null, rawScroll.toFixed(2))),
152
610
  /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React3.createElement(Text, null, scroll.toFixed(2)))
153
611
  );
@@ -158,24 +616,141 @@ function useInterval(callback, delay) {
158
616
  return () => clearInterval(interval);
159
617
  }, [delay]);
160
618
  }
161
- var LeanViewComponent = React3.forwardRef((props, ref) => {
162
- return React3.createElement("RCTView", { ...props, ref });
163
- });
164
- LeanViewComponent.displayName = "RCTView";
165
- var LeanView = Platform.OS === "android" || Platform.OS === "ios" ? LeanViewComponent : View;
619
+ var globalResizeObserver = null;
620
+ function getGlobalResizeObserver() {
621
+ if (!globalResizeObserver) {
622
+ globalResizeObserver = new ResizeObserver((entries) => {
623
+ for (const entry of entries) {
624
+ const callbacks = callbackMap.get(entry.target);
625
+ if (callbacks) {
626
+ for (const callback of callbacks) {
627
+ callback(entry);
628
+ }
629
+ }
630
+ }
631
+ });
632
+ }
633
+ return globalResizeObserver;
634
+ }
635
+ var callbackMap = /* @__PURE__ */ new WeakMap();
636
+ function useResizeObserver(element, callback) {
637
+ useEffect(() => {
638
+ if (!element) return;
639
+ const observer = getGlobalResizeObserver();
640
+ let callbacks = callbackMap.get(element);
641
+ if (!callbacks) {
642
+ callbacks = /* @__PURE__ */ new Set();
643
+ callbackMap.set(element, callbacks);
644
+ observer.observe(element);
645
+ }
646
+ callbacks.add(callback);
647
+ return () => {
648
+ const callbacks2 = callbackMap.get(element);
649
+ if (callbacks2) {
650
+ callbacks2.delete(callback);
651
+ if (callbacks2.size === 0) {
652
+ callbackMap.delete(element);
653
+ observer.unobserve(element);
654
+ }
655
+ }
656
+ };
657
+ }, [element, callback]);
658
+ }
166
659
 
167
- // src/components/Separator.tsx
168
- function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
169
- const [lastItemKeys] = useArr$(["lastItemKeys"]);
170
- const isALastItem = lastItemKeys.includes(itemKey);
171
- return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
660
+ // src/hooks/useSyncLayout.tsx
661
+ function useSyncLayout({
662
+ ref,
663
+ onLayoutChange
664
+ }) {
665
+ var _a, _b;
666
+ useResizeObserver(
667
+ ((_b = (_a = ref.current) == null ? void 0 : _a.getScrollableNode) == null ? void 0 : _b.call(_a)) || ref.current,
668
+ useCallback(
669
+ (entry) => {
670
+ onLayoutChange(entry.contentRect, false);
671
+ },
672
+ [onLayoutChange]
673
+ )
674
+ );
675
+ useLayoutEffect(() => {
676
+ if (ref.current) {
677
+ const rect = ref.current.getBoundingClientRect();
678
+ onLayoutChange(
679
+ {
680
+ height: rect.height,
681
+ width: rect.width,
682
+ x: rect.left,
683
+ y: rect.top
684
+ },
685
+ true
686
+ );
687
+ }
688
+ }, []);
689
+ return {};
172
690
  }
173
691
 
692
+ // src/components/LayoutView.tsx
693
+ var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
694
+ const ref = refView != null ? refView : useRef();
695
+ useSyncLayout({ onLayoutChange, ref });
696
+ return /* @__PURE__ */ React.createElement("div", { ...rest, ref }, children);
697
+ };
698
+
174
699
  // src/constants.ts
175
700
  var POSITION_OUT_OF_VIEW = -1e7;
176
701
  var ENABLE_DEVMODE = __DEV__ && false;
177
702
  var ENABLE_DEBUG_VIEW = __DEV__ && false;
178
- var IsNewArchitecture = global.nativeFabricUIManager != null;
703
+ var typedForwardRef = forwardRef;
704
+ var typedMemo = memo;
705
+
706
+ // src/components/PositionView.tsx
707
+ var PositionViewState = typedMemo(function PositionView({
708
+ id,
709
+ horizontal,
710
+ style,
711
+ refView,
712
+ ...rest
713
+ }) {
714
+ const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
715
+ const base = Array.isArray(style) ? Object.assign({}, ...style) : style;
716
+ const combinedStyle = horizontal ? { ...base, left: position } : { ...base, top: position };
717
+ return /* @__PURE__ */ React3.createElement(LayoutView, { refView, style: combinedStyle, ...rest });
718
+ });
719
+ var PositionViewSticky = typedMemo(function PositionViewSticky2({
720
+ id,
721
+ horizontal,
722
+ style,
723
+ refView,
724
+ index,
725
+ ...rest
726
+ }) {
727
+ const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
728
+ const viewStyle = React3.useMemo(() => {
729
+ const base = Array.isArray(style) ? Object.assign({}, ...style) : style;
730
+ const axisStyle = horizontal ? { transform: `translateX(${position}px)` } : { top: position };
731
+ return {
732
+ ...base,
733
+ zIndex: index + 1e3,
734
+ ...axisStyle
735
+ };
736
+ }, [style, position, horizontal, index]);
737
+ return /* @__PURE__ */ React3.createElement(LayoutView, { refView, style: viewStyle, ...rest });
738
+ });
739
+ var PositionView2 = PositionViewState;
740
+ function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
741
+ const [lastItemKeys] = useArr$(["lastItemKeys"]);
742
+ const isALastItem = lastItemKeys.includes(itemKey);
743
+ return isALastItem ? null : /* @__PURE__ */ React3.createElement(ItemSeparatorComponent, { leadingItem });
744
+ }
745
+
746
+ // src/constants-platform.ts
747
+ var IsNewArchitecture = true;
748
+
749
+ // src/platform/Platform.ts
750
+ var Platform = {
751
+ // Widen the type to avoid unreachable-branch lints in cross-platform code that compares against other OSes
752
+ OS: "web"
753
+ };
179
754
  var symbolFirst = Symbol();
180
755
  function useInit(cb) {
181
756
  const refValue = useRef(symbolFirst);
@@ -312,8 +887,12 @@ function useListScrollSize() {
312
887
  const [scrollSize] = useArr$(["scrollSize"]);
313
888
  return scrollSize;
314
889
  }
315
- var typedForwardRef = forwardRef;
316
- var typedMemo = memo;
890
+ function useSyncLayout2() {
891
+ {
892
+ const { triggerLayout: syncLayout } = useContext(ContextContainer);
893
+ return syncLayout;
894
+ }
895
+ }
317
896
 
318
897
  // src/components/Container.tsx
319
898
  var Container = typedMemo(function Container2({
@@ -325,51 +904,56 @@ var Container = typedMemo(function Container2({
325
904
  ItemSeparatorComponent
326
905
  }) {
327
906
  const ctx = useStateContext();
328
- const columnWrapperStyle = ctx.columnWrapperStyle;
329
- const [column = 0, data, itemKey, position = POSITION_OUT_OF_VIEW, numColumns, extraData] = useArr$([
907
+ const { columnWrapperStyle } = ctx;
908
+ const [column = 0, data, itemKey, numColumns, extraData, isSticky] = useArr$([
330
909
  `containerColumn${id}`,
331
910
  `containerItemData${id}`,
332
911
  `containerItemKey${id}`,
333
- `containerPosition${id}`,
334
912
  "numColumns",
335
- "extraData"
913
+ "extraData",
914
+ `containerSticky${id}`
336
915
  ]);
337
916
  const refLastSize = useRef();
338
917
  const ref = useRef(null);
339
- const [layoutRenderCount, forceLayoutRender] = useState(0);
918
+ const [_, forceLayoutRender] = useState(0);
340
919
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
341
920
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
342
- let didLayout = false;
343
- let paddingStyles;
344
- if (columnWrapperStyle) {
345
- const { columnGap, rowGap, gap } = columnWrapperStyle;
346
- if (horizontal) {
347
- paddingStyles = {
348
- paddingRight: columnGap || gap || void 0,
349
- paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
350
- };
351
- } else {
352
- paddingStyles = {
353
- paddingBottom: rowGap || gap || void 0,
354
- paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
355
- };
921
+ const style = useMemo(() => {
922
+ let paddingStyles;
923
+ if (columnWrapperStyle) {
924
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
925
+ if (horizontal) {
926
+ const py = numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0;
927
+ paddingStyles = {
928
+ paddingBottom: py,
929
+ paddingRight: columnGap || gap || void 0,
930
+ paddingTop: py
931
+ };
932
+ } else {
933
+ const px = numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0;
934
+ paddingStyles = {
935
+ paddingBottom: rowGap || gap || void 0,
936
+ paddingLeft: px,
937
+ paddingRight: px
938
+ };
939
+ }
356
940
  }
357
- }
358
- const style = horizontal ? {
359
- flexDirection: ItemSeparatorComponent ? "row" : void 0,
360
- height: otherAxisSize,
361
- left: position,
362
- position: "absolute",
363
- top: otherAxisPos,
364
- ...paddingStyles || {}
365
- } : {
366
- left: otherAxisPos,
367
- position: "absolute",
368
- right: numColumns > 1 ? null : 0,
369
- top: position,
370
- width: otherAxisSize,
371
- ...paddingStyles || {}
372
- };
941
+ return horizontal ? {
942
+ flexDirection: ItemSeparatorComponent ? "row" : void 0,
943
+ height: otherAxisSize,
944
+ left: 0,
945
+ position: "absolute",
946
+ top: otherAxisPos,
947
+ ...paddingStyles || {}
948
+ } : {
949
+ left: otherAxisPos,
950
+ position: "absolute",
951
+ right: numColumns > 1 ? void 0 : 0,
952
+ top: 0,
953
+ width: otherAxisSize,
954
+ ...paddingStyles || {}
955
+ };
956
+ }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
373
957
  const renderedItemInfo = useMemo(
374
958
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
375
959
  [itemKey, data, extraData]
@@ -387,104 +971,183 @@ var Container = typedMemo(function Container2({
387
971
  value: data
388
972
  };
389
973
  }, [id, itemKey, index, data]);
390
- const onLayout = (event) => {
391
- var _a, _b;
974
+ const onLayoutChange = (rectangle) => {
392
975
  if (!isNullOrUndefined(itemKey)) {
393
- didLayout = true;
394
- let layout = event.nativeEvent.layout;
395
- const size = layout[horizontal ? "width" : "height"];
976
+ let layout = rectangle;
977
+ layout[horizontal ? "width" : "height"];
396
978
  const doUpdate = () => {
397
979
  refLastSize.current = { height: layout.height, width: layout.width };
398
980
  updateItemSize2(itemKey, layout);
399
981
  };
400
- if (IsNewArchitecture || size > 0) {
982
+ {
401
983
  doUpdate();
402
- } else {
403
- (_b = (_a = ref.current) == null ? void 0 : _a.measure) == null ? void 0 : _b.call(_a, (_x, _y, width, height) => {
404
- layout = { height, width };
405
- doUpdate();
406
- });
407
984
  }
408
985
  }
409
986
  };
410
- if (IsNewArchitecture) {
411
- useLayoutEffect(() => {
412
- var _a, _b;
413
- if (!isNullOrUndefined(itemKey)) {
414
- const measured = (_b = (_a = ref.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
415
- if (measured) {
416
- const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
417
- if (size) {
418
- updateItemSize2(itemKey, measured);
419
- }
987
+ const PositionComponent = isSticky ? PositionViewSticky : PositionView2;
988
+ return /* @__PURE__ */ React.createElement(ContextContainer.Provider, { value: contextValue }, /* @__PURE__ */ React.createElement(
989
+ PositionComponent,
990
+ {
991
+ horizontal,
992
+ id,
993
+ index,
994
+ key: recycleItems ? void 0 : itemKey,
995
+ onLayoutChange,
996
+ refView: ref,
997
+ style
998
+ },
999
+ renderedItem,
1000
+ renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React.createElement(
1001
+ Separator,
1002
+ {
1003
+ ItemSeparatorComponent,
1004
+ itemKey,
1005
+ leadingItem: renderedItemInfo.item
1006
+ }
1007
+ )
1008
+ ));
1009
+ });
1010
+
1011
+ // src/utils/reordering.ts
1012
+ var mapFn = (element) => {
1013
+ const indexStr = element.getAttribute("index");
1014
+ return [element, indexStr === null ? null : parseInt(indexStr)];
1015
+ };
1016
+ function sortDOMElementsPatience(container) {
1017
+ const elements = Array.from(container.children);
1018
+ if (elements.length <= 1) return elements;
1019
+ const items = elements.map(mapFn);
1020
+ items.sort((a, b) => {
1021
+ const aKey = a[1];
1022
+ const bKey = b[1];
1023
+ if (aKey === null) {
1024
+ return 1;
1025
+ }
1026
+ if (bKey === null) {
1027
+ return -1;
1028
+ }
1029
+ return aKey - bKey;
1030
+ });
1031
+ const targetPositions = /* @__PURE__ */ new Map();
1032
+ items.forEach((item, index) => {
1033
+ targetPositions.set(item[0], index);
1034
+ });
1035
+ const currentPositions = elements.map((el) => targetPositions.get(el));
1036
+ const lis = findLIS(currentPositions);
1037
+ const stableIndices = new Set(lis);
1038
+ for (let targetPos = 0; targetPos < items.length; targetPos++) {
1039
+ const element = items[targetPos][0];
1040
+ const currentPos = elements.indexOf(element);
1041
+ if (!stableIndices.has(currentPos)) {
1042
+ let nextStableElement = null;
1043
+ for (let i = targetPos + 1; i < items.length; i++) {
1044
+ const nextEl = items[i][0];
1045
+ const nextCurrentPos = elements.indexOf(nextEl);
1046
+ if (stableIndices.has(nextCurrentPos)) {
1047
+ nextStableElement = nextEl;
1048
+ break;
420
1049
  }
421
1050
  }
422
- }, [itemKey, layoutRenderCount]);
423
- } else {
424
- useEffect(() => {
425
- if (!isNullOrUndefined(itemKey)) {
426
- const timeout = setTimeout(() => {
427
- if (!didLayout && refLastSize.current) {
428
- updateItemSize2(itemKey, refLastSize.current);
429
- }
430
- }, 16);
431
- return () => {
432
- clearTimeout(timeout);
433
- };
1051
+ if (nextStableElement) {
1052
+ container.insertBefore(element, nextStableElement);
1053
+ } else {
1054
+ container.appendChild(element);
434
1055
  }
435
- }, [itemKey]);
1056
+ }
436
1057
  }
437
- return /* @__PURE__ */ React3.createElement(LeanView, { key: recycleItems ? void 0 : itemKey, onLayout, ref, style }, /* @__PURE__ */ React3.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3.createElement(
438
- Separator,
439
- {
440
- ItemSeparatorComponent,
441
- itemKey,
442
- leadingItem: renderedItemInfo.item
1058
+ }
1059
+ function findLIS(arr) {
1060
+ const n = arr.length;
1061
+ const tails = [];
1062
+ const predecessors = new Array(n).fill(-1);
1063
+ const indices = [];
1064
+ for (let i = 0; i < n; i++) {
1065
+ const num = arr[i];
1066
+ let left = 0, right = tails.length;
1067
+ while (left < right) {
1068
+ const mid = Math.floor((left + right) / 2);
1069
+ if (arr[indices[mid]] < num) {
1070
+ left = mid + 1;
1071
+ } else {
1072
+ right = mid;
1073
+ }
443
1074
  }
444
- )));
445
- });
446
- var useAnimatedValue = (initialValue) => {
447
- return useRef(new Animated.Value(initialValue)).current;
448
- };
1075
+ if (left === tails.length) {
1076
+ tails.push(num);
1077
+ indices.push(i);
1078
+ } else {
1079
+ tails[left] = num;
1080
+ indices[left] = i;
1081
+ }
1082
+ if (left > 0) {
1083
+ predecessors[i] = indices[left - 1];
1084
+ }
1085
+ }
1086
+ const result = [];
1087
+ let k = indices[indices.length - 1];
1088
+ while (k !== -1) {
1089
+ result.unshift(k);
1090
+ k = predecessors[k];
1091
+ }
1092
+ return result;
1093
+ }
449
1094
 
450
- // src/hooks/useValue$.ts
451
- function useValue$(key, params) {
452
- var _a;
453
- const { getValue, delay } = params || {};
1095
+ // src/hooks/useDOMOrder.ts
1096
+ function useDOMOrder(ref) {
454
1097
  const ctx = useStateContext();
455
- const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
456
- useMemo(() => {
457
- let newValue;
458
- let prevValue;
459
- let didQueueTask = false;
460
- listen$(ctx, key, (v) => {
461
- newValue = getValue ? getValue(v) : v;
462
- if (delay !== void 0) {
463
- const fn = () => {
464
- didQueueTask = false;
465
- if (newValue !== void 0) {
466
- animValue.setValue(newValue);
467
- }
468
- };
469
- const delayValue = typeof delay === "function" ? delay(newValue, prevValue) : delay;
470
- prevValue = newValue;
471
- if (!didQueueTask) {
472
- didQueueTask = true;
473
- if (delayValue === 0) {
474
- queueMicrotask(fn);
475
- } else {
476
- setTimeout(fn, delayValue);
477
- }
478
- }
479
- } else {
480
- animValue.setValue(newValue);
1098
+ const debounceRef = useRef(void 0);
1099
+ useEffect(() => {
1100
+ const unsubscribe = listen$(ctx, "lastPositionUpdate", () => {
1101
+ if (debounceRef.current !== void 0) {
1102
+ clearTimeout(debounceRef.current);
481
1103
  }
1104
+ debounceRef.current = setTimeout(() => {
1105
+ const parent = ref.current;
1106
+ if (parent) {
1107
+ sortDOMElementsPatience(parent);
1108
+ }
1109
+ debounceRef.current = void 0;
1110
+ }, 500);
482
1111
  });
483
- }, []);
484
- return animValue;
1112
+ return () => {
1113
+ unsubscribe();
1114
+ if (debounceRef.current !== void 0) {
1115
+ clearTimeout(debounceRef.current);
1116
+ }
1117
+ };
1118
+ }, [ctx]);
485
1119
  }
486
1120
 
487
1121
  // src/components/Containers.tsx
1122
+ var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColumns, children }) {
1123
+ const ref = useRef(null);
1124
+ const ctx = useStateContext();
1125
+ const columnWrapperStyle = ctx.columnWrapperStyle;
1126
+ const [totalSize, otherAxisSize] = useArr$(["totalSize", "otherAxisSize"]);
1127
+ useDOMOrder(ref);
1128
+ const style = horizontal ? { minHeight: otherAxisSize, width: totalSize } : { height: totalSize, minWidth: otherAxisSize };
1129
+ if (columnWrapperStyle && numColumns > 1) {
1130
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
1131
+ const gapX = columnGap || gap || 0;
1132
+ const gapY = rowGap || gap || 0;
1133
+ if (horizontal) {
1134
+ if (gapY) {
1135
+ style.marginTop = style.marginBottom = -gapY / 2;
1136
+ }
1137
+ if (gapX) {
1138
+ style.marginRight = -gapX;
1139
+ }
1140
+ } else {
1141
+ if (gapX) {
1142
+ style.marginLeft = style.marginRight = -gapX;
1143
+ }
1144
+ if (gapY) {
1145
+ style.marginBottom = -gapY;
1146
+ }
1147
+ }
1148
+ }
1149
+ return /* @__PURE__ */ React3.createElement("div", { ref, style }, children);
1150
+ });
488
1151
  var Containers = typedMemo(function Containers2({
489
1152
  horizontal,
490
1153
  recycleItems,
@@ -493,15 +1156,7 @@ var Containers = typedMemo(function Containers2({
493
1156
  updateItemSize: updateItemSize2,
494
1157
  getRenderedItem: getRenderedItem2
495
1158
  }) {
496
- const ctx = useStateContext();
497
- const columnWrapperStyle = ctx.columnWrapperStyle;
498
1159
  const [numContainers, numColumns] = useArr$(["numContainersPooled", "numColumns"]);
499
- const animSize = useValue$("totalSize", {
500
- // Use a microtask if increasing the size significantly, otherwise use a timeout
501
- delay: (value, prevValue) => !prevValue || value - prevValue > 20 ? 0 : 200
502
- });
503
- const animOpacity = waitForInitialLayout && !IsNewArchitecture ? useValue$("containersDidLayout", { getValue: (value) => value ? 1 : 0 }) : void 0;
504
- const otherAxisSize = useValue$("otherAxisSize", { delay: 0 });
505
1160
  const containers = [];
506
1161
  for (let i = 0; i < numContainers; i++) {
507
1162
  containers.push(
@@ -519,45 +1174,209 @@ var Containers = typedMemo(function Containers2({
519
1174
  )
520
1175
  );
521
1176
  }
522
- const style = horizontal ? { minHeight: otherAxisSize, opacity: animOpacity, width: animSize } : { height: animSize, minWidth: otherAxisSize, opacity: animOpacity };
523
- if (columnWrapperStyle && numColumns > 1) {
524
- const { columnGap, rowGap, gap } = columnWrapperStyle;
525
- const gapX = columnGap || gap || 0;
526
- const gapY = rowGap || gap || 0;
527
- if (horizontal) {
528
- if (gapY) {
529
- style.marginVertical = -gapY / 2;
1177
+ return /* @__PURE__ */ React3.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
1178
+ });
1179
+ var DevNumbers = __DEV__ && React3.memo(function DevNumbers2() {
1180
+ return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3.createElement(
1181
+ View,
1182
+ {
1183
+ key: index,
1184
+ style: {
1185
+ height: 100,
1186
+ pointerEvents: "none",
1187
+ position: "absolute",
1188
+ top: index * 100,
1189
+ width: "100%"
530
1190
  }
531
- if (gapX) {
532
- style.marginRight = -gapX;
1191
+ },
1192
+ /* @__PURE__ */ React3.createElement(Text, { style: { color: "red" } }, index * 100)
1193
+ ));
1194
+ });
1195
+ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
1196
+ children,
1197
+ style,
1198
+ contentContainerStyle,
1199
+ horizontal = false,
1200
+ contentOffset,
1201
+ maintainVisibleContentPosition,
1202
+ onScroll: onScroll2,
1203
+ onMomentumScrollEnd,
1204
+ showsHorizontalScrollIndicator = true,
1205
+ showsVerticalScrollIndicator = true,
1206
+ refreshControl,
1207
+ onLayout,
1208
+ ScrollComponent,
1209
+ ...props
1210
+ }, ref) {
1211
+ const scrollRef = useRef(null);
1212
+ const contentRef = useRef(null);
1213
+ const momentumTimeout = useRef(null);
1214
+ useImperativeHandle(ref, () => {
1215
+ const api = {
1216
+ getBoundingClientRect: () => {
1217
+ var _a;
1218
+ return (_a = scrollRef.current) == null ? void 0 : _a.getBoundingClientRect();
1219
+ },
1220
+ getScrollableNode: () => scrollRef.current,
1221
+ getScrollResponder: () => scrollRef.current,
1222
+ scrollBy: (options) => {
1223
+ const el = scrollRef.current;
1224
+ if (!el) return;
1225
+ const { x = 0, y = 0, animated = true } = options;
1226
+ el.scrollBy({ behavior: animated ? "smooth" : "auto", left: x, top: y });
1227
+ },
1228
+ scrollTo: (options) => {
1229
+ const el = scrollRef.current;
1230
+ if (!el) return;
1231
+ const { x = 0, y = 0, animated = true } = options;
1232
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", left: x, top: y });
1233
+ },
1234
+ scrollToEnd: (options = {}) => {
1235
+ const el = scrollRef.current;
1236
+ if (!el) return;
1237
+ const { animated = true } = options;
1238
+ if (horizontal) {
1239
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", left: el.scrollWidth });
1240
+ } else {
1241
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", top: el.scrollHeight });
1242
+ }
1243
+ },
1244
+ scrollToOffset: (params) => {
1245
+ const el = scrollRef.current;
1246
+ if (!el) return;
1247
+ const { offset, animated = true } = params;
1248
+ if (horizontal) {
1249
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", left: offset });
1250
+ } else {
1251
+ el.scrollTo({ behavior: animated ? "smooth" : "auto", top: offset });
1252
+ }
533
1253
  }
534
- } else {
535
- if (gapX) {
536
- style.marginHorizontal = -gapX;
1254
+ };
1255
+ return api;
1256
+ }, [horizontal]);
1257
+ const handleScroll = useCallback(
1258
+ (event) => {
1259
+ if (!onScroll2 || !(event == null ? void 0 : event.target)) {
1260
+ return;
537
1261
  }
538
- if (gapY) {
539
- style.marginBottom = -gapY;
1262
+ const target = event.target;
1263
+ const scrollEvent = {
1264
+ nativeEvent: {
1265
+ contentOffset: {
1266
+ x: target.scrollLeft,
1267
+ y: target.scrollTop
1268
+ },
1269
+ contentSize: {
1270
+ height: target.scrollHeight,
1271
+ width: target.scrollWidth
1272
+ },
1273
+ layoutMeasurement: {
1274
+ height: target.clientHeight,
1275
+ width: target.clientWidth
1276
+ }
1277
+ }
1278
+ };
1279
+ onScroll2(scrollEvent);
1280
+ if (onMomentumScrollEnd) {
1281
+ if (momentumTimeout.current != null) clearTimeout(momentumTimeout.current);
1282
+ momentumTimeout.current = setTimeout(() => {
1283
+ onMomentumScrollEnd({
1284
+ nativeEvent: {
1285
+ contentOffset: scrollEvent.nativeEvent.contentOffset
1286
+ }
1287
+ });
1288
+ }, 100);
540
1289
  }
1290
+ },
1291
+ [onScroll2, onMomentumScrollEnd]
1292
+ );
1293
+ useLayoutEffect(() => {
1294
+ const element = scrollRef.current;
1295
+ if (!element) return;
1296
+ element.addEventListener("scroll", handleScroll, { passive: true });
1297
+ return () => {
1298
+ element.removeEventListener("scroll", handleScroll);
1299
+ };
1300
+ }, [handleScroll]);
1301
+ useLayoutEffect(() => {
1302
+ if (contentOffset && scrollRef.current) {
1303
+ scrollRef.current.scrollLeft = contentOffset.x || 0;
1304
+ scrollRef.current.scrollTop = contentOffset.y || 0;
541
1305
  }
542
- }
543
- return /* @__PURE__ */ React3.createElement(Animated.View, { style }, containers);
1306
+ }, [contentOffset]);
1307
+ useLayoutEffect(() => {
1308
+ if (!onLayout || !scrollRef.current) return;
1309
+ const element = scrollRef.current;
1310
+ const fireLayout = () => {
1311
+ const rect = element.getBoundingClientRect();
1312
+ onLayout({
1313
+ nativeEvent: {
1314
+ layout: {
1315
+ height: rect.height,
1316
+ width: rect.width,
1317
+ x: rect.left,
1318
+ y: rect.top
1319
+ }
1320
+ }
1321
+ });
1322
+ };
1323
+ fireLayout();
1324
+ const resizeObserver = new ResizeObserver(() => {
1325
+ fireLayout();
1326
+ });
1327
+ resizeObserver.observe(element);
1328
+ return () => resizeObserver.disconnect();
1329
+ }, [onLayout]);
1330
+ const scrollViewStyle = {
1331
+ overflow: "auto",
1332
+ overflowX: horizontal ? "auto" : showsHorizontalScrollIndicator ? "auto" : "hidden",
1333
+ overflowY: horizontal ? showsVerticalScrollIndicator ? "auto" : "hidden" : "auto",
1334
+ position: "relative",
1335
+ // Ensure proper positioning context
1336
+ WebkitOverflowScrolling: "touch",
1337
+ // iOS momentum scrolling
1338
+ ...style
1339
+ };
1340
+ const contentStyle = {
1341
+ display: horizontal ? "flex" : "block",
1342
+ flexDirection: horizontal ? "row" : void 0,
1343
+ minHeight: horizontal ? void 0 : "100%",
1344
+ minWidth: horizontal ? "100%" : void 0,
1345
+ ...contentContainerStyle
1346
+ };
1347
+ return /* @__PURE__ */ React.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React.createElement("div", { ref: contentRef, style: contentStyle }, children));
544
1348
  });
1349
+ function useValueListener$(key, callback) {
1350
+ const ctx = useStateContext();
1351
+ useLayoutEffect(() => {
1352
+ listen$(ctx, key, (value) => {
1353
+ callback(value);
1354
+ });
1355
+ }, []);
1356
+ }
1357
+
1358
+ // src/components/ScrollAdjust.tsx
545
1359
  function ScrollAdjust() {
546
- const bias = 1e7;
547
- const [scrollAdjust, scrollAdjustUserOffset] = useArr$(["scrollAdjust", "scrollAdjustUserOffset"]);
548
- const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0) + bias;
549
- return /* @__PURE__ */ React3.createElement(
550
- View,
551
- {
552
- style: {
553
- height: 0,
554
- left: 0,
555
- position: "absolute",
556
- top: scrollOffset,
557
- width: 0
1360
+ const ctx = useStateContext();
1361
+ const lastScrollOffsetRef = React3.useRef(0);
1362
+ const callback = React3.useCallback(() => {
1363
+ var _a;
1364
+ const scrollAdjust = peek$(ctx, "scrollAdjust");
1365
+ const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
1366
+ const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
1367
+ const scrollView = (_a = ctx.internalState) == null ? void 0 : _a.refScroller.current;
1368
+ if (scrollView && scrollOffset !== lastScrollOffsetRef.current) {
1369
+ const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
1370
+ if (scrollDelta !== 0) {
1371
+ scrollView.scrollBy(0, scrollDelta);
1372
+ console.log("ScrollAdjust (web scrollBy)", scrollDelta, "total offset:", scrollOffset);
558
1373
  }
1374
+ lastScrollOffsetRef.current = scrollOffset;
559
1375
  }
560
- );
1376
+ }, []);
1377
+ useValueListener$("scrollAdjust", callback);
1378
+ useValueListener$("scrollAdjustUserOffset", callback);
1379
+ return null;
561
1380
  }
562
1381
 
563
1382
  // src/components/SnapWrapper.tsx
@@ -565,26 +1384,11 @@ function SnapWrapper({ ScrollComponent, ...props }) {
565
1384
  const [snapToOffsets] = useArr$(["snapToOffsets"]);
566
1385
  return /* @__PURE__ */ React.createElement(ScrollComponent, { ...props, snapToOffsets });
567
1386
  }
568
- function useSyncLayout({
569
- onChange
570
- }) {
571
- const ref = useRef(null);
572
- const onLayout = useCallback(
573
- (event) => {
574
- onChange(event.nativeEvent.layout, false);
575
- },
576
- [onChange]
577
- );
578
- if (IsNewArchitecture) {
579
- useLayoutEffect(() => {
580
- if (ref.current) {
581
- ref.current.measure((x, y, width, height) => {
582
- onChange({ height, width, x, y }, true);
583
- });
584
- }
585
- }, []);
586
- }
587
- return { onLayout, ref };
1387
+
1388
+ // src/hooks/useValue$.ts
1389
+ function useValue$(key, params) {
1390
+ const [value] = useArr$([key]);
1391
+ return value;
588
1392
  }
589
1393
 
590
1394
  // src/components/ListComponent.tsx
@@ -598,13 +1402,13 @@ var getComponent = (Component) => {
598
1402
  return null;
599
1403
  };
600
1404
  var Padding = () => {
601
- const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
602
- return /* @__PURE__ */ React3.createElement(Animated.View, { style: { paddingTop: animPaddingTop } });
1405
+ const animPaddingTop = useValue$("alignItemsPaddingTop");
1406
+ return /* @__PURE__ */ React3.createElement(AnimatedView, { style: { paddingTop: animPaddingTop } });
603
1407
  };
604
1408
  var PaddingDevMode = () => {
605
- const animPaddingTop = useValue$("alignItemsPaddingTop", { delay: 0 });
606
- return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(Animated.View, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React3.createElement(
607
- Animated.View,
1409
+ const animPaddingTop = useValue$("alignItemsPaddingTop");
1410
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(AnimatedView, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React3.createElement(
1411
+ AnimatedView,
608
1412
  {
609
1413
  style: {
610
1414
  backgroundColor: "green",
@@ -642,16 +1446,15 @@ var ListComponent = typedMemo(function ListComponent2({
642
1446
  scrollAdjustHandler,
643
1447
  onLayoutHeader,
644
1448
  snapToIndices,
1449
+ stickyIndices,
645
1450
  ...rest
646
1451
  }) {
647
1452
  const ctx = useStateContext();
648
- const { onLayout: onLayoutHeaderSync, ref: refHeader } = useSyncLayout({
649
- onChange: onLayoutHeader
650
- });
1453
+ const refHeader = React3.useRef(null);
651
1454
  const ScrollComponent = renderScrollComponent ? useMemo(
652
1455
  () => React3.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
653
1456
  [renderScrollComponent]
654
- ) : ScrollView;
1457
+ ) : ListComponentScrollView;
655
1458
  React3.useEffect(() => {
656
1459
  if (canRender) {
657
1460
  setTimeout(() => {
@@ -660,16 +1463,17 @@ var ListComponent = typedMemo(function ListComponent2({
660
1463
  }
661
1464
  }, [canRender]);
662
1465
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1466
+ const contentContainerStyleWeb = useMemo(() => {
1467
+ const base = contentContainerStyle || void 0;
1468
+ if (!horizontal) return base;
1469
+ if (base && base.height === "100%") return base;
1470
+ return { ...base || {}, height: "100%" };
1471
+ }, [horizontal, (contentContainerStyle == null ? void 0 : contentContainerStyle.height) === "100%" ? 1 : 0]);
663
1472
  return /* @__PURE__ */ React3.createElement(
664
1473
  SnapOrScroll,
665
1474
  {
666
1475
  ...rest,
667
- contentContainerStyle: [
668
- contentContainerStyle,
669
- horizontal ? {
670
- height: "100%"
671
- } : {}
672
- ],
1476
+ contentContainerStyle: contentContainerStyleWeb,
673
1477
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
674
1478
  horizontal,
675
1479
  maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
@@ -681,7 +1485,15 @@ var ListComponent = typedMemo(function ListComponent2({
681
1485
  },
682
1486
  maintainVisibleContentPosition && /* @__PURE__ */ React3.createElement(ScrollAdjust, null),
683
1487
  ENABLE_DEVMODE ? /* @__PURE__ */ React3.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3.createElement(Padding, null),
684
- ListHeaderComponent && /* @__PURE__ */ React3.createElement(View, { onLayout: onLayoutHeaderSync, ref: refHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1488
+ ListHeaderComponent && /* @__PURE__ */ React3.createElement(
1489
+ LayoutView,
1490
+ {
1491
+ onLayoutChange: onLayoutHeader,
1492
+ refView: refHeader,
1493
+ style: ListHeaderComponentStyle
1494
+ },
1495
+ getComponent(ListHeaderComponent)
1496
+ ),
685
1497
  ListEmptyComponent && getComponent(ListEmptyComponent),
686
1498
  canRender && /* @__PURE__ */ React3.createElement(
687
1499
  Containers,
@@ -695,16 +1507,17 @@ var ListComponent = typedMemo(function ListComponent2({
695
1507
  }
696
1508
  ),
697
1509
  ListFooterComponent && /* @__PURE__ */ React3.createElement(
698
- View,
1510
+ LayoutView,
699
1511
  {
700
- onLayout: (event) => {
701
- const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
1512
+ onLayoutChange: (layout) => {
1513
+ const size = layout[horizontal ? "width" : "height"];
702
1514
  set$(ctx, "footerSize", size);
703
1515
  },
704
1516
  style: ListFooterComponentStyle
705
1517
  },
706
1518
  getComponent(ListFooterComponent)
707
- )
1519
+ ),
1520
+ __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React3.createElement(DevNumbers, null)
708
1521
  );
709
1522
  });
710
1523
 
@@ -725,33 +1538,45 @@ function calculateOffsetForIndex(ctx, state, index) {
725
1538
  let position = 0;
726
1539
  if (index !== void 0) {
727
1540
  position = (state == null ? void 0 : state.positions.get(getId(state, index))) || 0;
728
- }
729
- const paddingTop = peek$(ctx, "stylePaddingTop");
730
- if (paddingTop) {
731
- position += paddingTop;
732
- }
733
- const headerSize = peek$(ctx, "headerSize");
734
- if (headerSize) {
735
- position += headerSize;
1541
+ const paddingTop = peek$(ctx, "stylePaddingTop");
1542
+ if (paddingTop) {
1543
+ position += paddingTop;
1544
+ }
1545
+ const headerSize = peek$(ctx, "headerSize");
1546
+ if (headerSize) {
1547
+ position += headerSize;
1548
+ }
736
1549
  }
737
1550
  return position;
738
1551
  }
739
1552
 
740
1553
  // src/utils/getItemSize.ts
741
1554
  function getItemSize(state, key, index, data, useAverageSize) {
1555
+ var _a, _b;
742
1556
  const {
743
1557
  sizesKnown,
744
1558
  sizes,
745
1559
  scrollingTo,
746
- props: { estimatedItemSize, getEstimatedItemSize }
1560
+ averageSizes,
1561
+ props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
747
1562
  } = state;
748
1563
  const sizeKnown = sizesKnown.get(key);
749
1564
  if (sizeKnown !== void 0) {
750
1565
  return sizeKnown;
751
1566
  }
752
1567
  let size;
753
- if (useAverageSize !== void 0 && sizeKnown === void 0 && !getEstimatedItemSize && !scrollingTo) {
754
- size = useAverageSize;
1568
+ const itemType = getItemType ? (_a = getItemType(data, index)) != null ? _a : "" : "";
1569
+ if (getFixedItemSize) {
1570
+ size = getFixedItemSize(index, data, itemType);
1571
+ if (size !== void 0) {
1572
+ sizesKnown.set(key, size);
1573
+ }
1574
+ }
1575
+ if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
1576
+ const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
1577
+ if (averageSizeForType !== void 0) {
1578
+ size = roundSize(averageSizeForType);
1579
+ }
755
1580
  }
756
1581
  if (size === void 0) {
757
1582
  size = sizes.get(key);
@@ -760,7 +1585,7 @@ function getItemSize(state, key, index, data, useAverageSize) {
760
1585
  }
761
1586
  }
762
1587
  if (size === void 0) {
763
- size = getEstimatedItemSize ? getEstimatedItemSize(index, data) : estimatedItemSize;
1588
+ size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
764
1589
  }
765
1590
  sizes.set(key, size);
766
1591
  return size;
@@ -779,11 +1604,46 @@ function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
779
1604
  return offset;
780
1605
  }
781
1606
 
1607
+ // src/core/finishScrollTo.ts
1608
+ var finishScrollTo = (state) => {
1609
+ if (state) {
1610
+ state.scrollingTo = void 0;
1611
+ state.scrollHistory.length = 0;
1612
+ }
1613
+ };
1614
+
1615
+ // src/core/scrollTo.ts
1616
+ function scrollTo(state, params = {}) {
1617
+ var _a;
1618
+ const { animated, noScrollingTo } = params;
1619
+ const {
1620
+ refScroller,
1621
+ props: { horizontal }
1622
+ } = state;
1623
+ const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1624
+ state.scrollHistory.length = 0;
1625
+ if (!noScrollingTo) {
1626
+ state.scrollingTo = params;
1627
+ }
1628
+ state.scrollPending = offset;
1629
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1630
+ animated: !!animated,
1631
+ x: horizontal ? offset : 0,
1632
+ y: horizontal ? 0 : offset
1633
+ });
1634
+ if (!animated) {
1635
+ state.scroll = offset;
1636
+ setTimeout(() => finishScrollTo(state), 100);
1637
+ }
1638
+ }
1639
+
782
1640
  // src/utils/requestAdjust.ts
783
- function requestAdjust(ctx, state, positionDiff) {
1641
+ function requestAdjust(ctx, state, positionDiff, dataChanged) {
784
1642
  if (Math.abs(positionDiff) > 0.1) {
785
1643
  const doit = () => {
786
- state.scrollAdjustHandler.requestAdjust(positionDiff);
1644
+ {
1645
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
1646
+ }
787
1647
  };
788
1648
  state.scroll += positionDiff;
789
1649
  state.scrollForNextCalculateItemsInView = void 0;
@@ -802,49 +1662,72 @@ function requestAdjust(ctx, state, positionDiff) {
802
1662
  if (state.ignoreScrollFromMVCPTimeout) {
803
1663
  clearTimeout(state.ignoreScrollFromMVCPTimeout);
804
1664
  }
805
- state.ignoreScrollFromMVCPTimeout = setTimeout(() => {
806
- state.ignoreScrollFromMVCP = void 0;
807
- }, 100);
1665
+ state.ignoreScrollFromMVCPTimeout = setTimeout(
1666
+ () => {
1667
+ state.ignoreScrollFromMVCP = void 0;
1668
+ },
1669
+ 100
1670
+ );
808
1671
  } else {
809
1672
  requestAnimationFrame(doit);
810
1673
  }
811
1674
  }
812
1675
  }
813
1676
 
814
- // src/core/prepareMVCP.ts
815
- function prepareMVCP(ctx, state) {
1677
+ // src/core/mvcp.ts
1678
+ function prepareMVCP(ctx, state, dataChanged) {
816
1679
  const {
1680
+ idsInView,
817
1681
  positions,
818
1682
  scrollingTo,
819
1683
  props: { maintainVisibleContentPosition }
820
1684
  } = state;
821
1685
  let prevPosition;
822
1686
  let targetId;
823
- let targetIndex;
1687
+ const idsInViewWithPositions = [];
824
1688
  const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
825
1689
  if (maintainVisibleContentPosition) {
826
1690
  const indexByKey = state.indexByKey;
827
1691
  if (scrollTarget !== void 0) {
828
1692
  targetId = getId(state, scrollTarget);
829
- targetIndex = scrollTarget;
830
- } else if (state.idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
831
- targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
832
- targetIndex = indexByKey.get(targetId);
1693
+ } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1694
+ if (dataChanged) {
1695
+ for (let i = 0; i < idsInView.length; i++) {
1696
+ const id = idsInView[i];
1697
+ const index = indexByKey.get(id);
1698
+ if (index !== void 0) {
1699
+ idsInViewWithPositions.push({ id, position: positions.get(id) });
1700
+ }
1701
+ }
1702
+ } else {
1703
+ targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
1704
+ }
833
1705
  }
834
- if (targetId !== void 0 && targetIndex !== void 0) {
1706
+ if (targetId !== void 0) {
835
1707
  prevPosition = positions.get(targetId);
836
1708
  }
837
1709
  }
838
1710
  return () => {
1711
+ let positionDiff;
1712
+ if (dataChanged && targetId === void 0) {
1713
+ for (let i = 0; i < idsInViewWithPositions.length; i++) {
1714
+ const { id, position } = idsInViewWithPositions[i];
1715
+ const newPosition = positions.get(id);
1716
+ if (newPosition !== void 0) {
1717
+ positionDiff = newPosition - position;
1718
+ break;
1719
+ }
1720
+ }
1721
+ }
839
1722
  if (targetId !== void 0 && prevPosition !== void 0) {
840
1723
  const newPosition = positions.get(targetId);
841
1724
  if (newPosition !== void 0) {
842
- const positionDiff = newPosition - prevPosition;
843
- if (Math.abs(positionDiff) > 0.1) {
844
- requestAdjust(ctx, state, positionDiff);
845
- }
1725
+ positionDiff = newPosition - prevPosition;
846
1726
  }
847
1727
  }
1728
+ if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1729
+ requestAdjust(ctx, state, positionDiff);
1730
+ }
848
1731
  };
849
1732
  }
850
1733
 
@@ -853,10 +1736,10 @@ function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
853
1736
  if (stylePaddingTop !== void 0) {
854
1737
  const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
855
1738
  if (stylePaddingTop < prevStylePaddingTop) {
856
- let prevTotalSize = peek$(ctx, "totalSize");
1739
+ let prevTotalSize = peek$(ctx, "totalSize") || 0;
857
1740
  set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
858
1741
  state.timeoutSetPaddingTop = setTimeout(() => {
859
- prevTotalSize = peek$(ctx, "totalSize");
1742
+ prevTotalSize = peek$(ctx, "totalSize") || 0;
860
1743
  set$(ctx, "totalSize", prevTotalSize - prevStylePaddingTop);
861
1744
  }, 16);
862
1745
  }
@@ -920,43 +1803,6 @@ function addTotalSize(ctx, state, key, add) {
920
1803
  }
921
1804
  }
922
1805
 
923
- // src/utils/getScrollVelocity.ts
924
- var getScrollVelocity = (state) => {
925
- const { scrollHistory } = state;
926
- let velocity = 0;
927
- if (scrollHistory.length >= 1) {
928
- const newest = scrollHistory[scrollHistory.length - 1];
929
- let oldest;
930
- let start = 0;
931
- for (let i = 0; i < scrollHistory.length - 1; i++) {
932
- const entry = scrollHistory[i];
933
- const nextEntry = scrollHistory[i + 1];
934
- if (i > 0) {
935
- const prevEntry = scrollHistory[i - 1];
936
- const prevDirection = entry.scroll - prevEntry.scroll;
937
- const currentDirection = nextEntry.scroll - entry.scroll;
938
- if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
939
- start = i;
940
- break;
941
- }
942
- }
943
- }
944
- for (let i = start; i < scrollHistory.length - 1; i++) {
945
- const entry = scrollHistory[i];
946
- if (newest.time - entry.time <= 1e3) {
947
- oldest = entry;
948
- break;
949
- }
950
- }
951
- if (oldest) {
952
- const scrollDiff = newest.scroll - oldest.scroll;
953
- const timeDiff = newest.time - oldest.time;
954
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
955
- }
956
- }
957
- return velocity;
958
- };
959
-
960
1806
  // src/utils/updateSnapToOffsets.ts
961
1807
  function updateSnapToOffsets(ctx, state) {
962
1808
  const {
@@ -973,69 +1819,42 @@ function updateSnapToOffsets(ctx, state) {
973
1819
  }
974
1820
 
975
1821
  // src/core/updateAllPositions.ts
976
- function updateAllPositions(ctx, state, dataChanged) {
977
- var _a, _b, _c, _d, _e;
1822
+ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1823
+ var _a, _b, _c, _d, _e, _f;
978
1824
  const {
979
- averageSizes,
980
1825
  columns,
981
1826
  indexByKey,
982
1827
  positions,
983
- firstFullyOnScreenIndex,
984
1828
  idCache,
985
1829
  sizesKnown,
986
- props: { snapToIndices }
1830
+ props: { getEstimatedItemSize, snapToIndices, enableAverages }
987
1831
  } = state;
988
1832
  const data = state.props.data;
989
1833
  const numColumns = peek$(ctx, "numColumns");
990
1834
  const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
991
- const scrollVelocity = getScrollVelocity(state);
992
- if (dataChanged) {
993
- indexByKey.clear();
994
- idCache.clear();
995
- }
996
- const itemType = "";
997
- let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
998
- if (averageSize !== void 0) {
999
- averageSize = roundSize(averageSize);
1000
- }
1001
- const shouldUseBackwards = !dataChanged && scrollVelocity < 0 && firstFullyOnScreenIndex > 5 && firstFullyOnScreenIndex < data.length;
1002
- if (shouldUseBackwards && firstFullyOnScreenIndex !== void 0) {
1003
- const anchorId = getId(state, firstFullyOnScreenIndex);
1004
- const anchorPosition = positions.get(anchorId);
1005
- if (anchorPosition !== void 0) {
1006
- let currentRowTop2 = anchorPosition;
1007
- let maxSizeInRow2 = 0;
1008
- let bailout = false;
1009
- for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
1010
- const id = (_b = idCache.get(i)) != null ? _b : getId(state, i);
1011
- const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(state, id, i, data[i], averageSize);
1012
- const itemColumn = columns.get(id);
1013
- maxSizeInRow2 = Math.max(maxSizeInRow2, size);
1014
- if (itemColumn === 1) {
1015
- currentRowTop2 -= maxSizeInRow2;
1016
- maxSizeInRow2 = 0;
1017
- }
1018
- if (currentRowTop2 < -2e3) {
1019
- bailout = true;
1020
- break;
1021
- }
1022
- positions.set(id, currentRowTop2);
1023
- }
1024
- if (!bailout) {
1025
- updateTotalSize(ctx, state);
1026
- return;
1027
- }
1028
- }
1029
- }
1835
+ const useAverageSize = enableAverages && !getEstimatedItemSize;
1030
1836
  let currentRowTop = 0;
1031
1837
  let column = 1;
1032
1838
  let maxSizeInRow = 0;
1033
1839
  const hasColumns = numColumns > 1;
1840
+ if (startIndex > 0) {
1841
+ const prevIndex = startIndex - 1;
1842
+ const prevId = (_a = idCache.get(prevIndex)) != null ? _a : getId(state, prevIndex);
1843
+ const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1844
+ if (hasColumns) {
1845
+ const prevColumn = (_c = columns.get(prevId)) != null ? _c : 1;
1846
+ currentRowTop = prevPosition;
1847
+ column = prevColumn % numColumns + 1;
1848
+ } else {
1849
+ const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(state, prevId, prevIndex, data[prevIndex], useAverageSize);
1850
+ currentRowTop = prevPosition + prevSize;
1851
+ }
1852
+ }
1034
1853
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1035
1854
  const dataLength = data.length;
1036
- for (let i = 0; i < dataLength; i++) {
1037
- const id = (_d = idCache.get(i)) != null ? _d : getId(state, i);
1038
- const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(state, id, i, data[i], averageSize);
1855
+ for (let i = startIndex; i < dataLength; i++) {
1856
+ const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1857
+ const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(state, id, i, data[i], useAverageSize);
1039
1858
  if (__DEV__ && needsIndexByKey) {
1040
1859
  if (indexByKeyForChecking.has(id)) {
1041
1860
  console.error(
@@ -1070,32 +1889,18 @@ function updateAllPositions(ctx, state, dataChanged) {
1070
1889
  }
1071
1890
 
1072
1891
  // src/core/viewability.ts
1073
- var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
1074
- function setupViewability(props) {
1075
- let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
1076
- if (viewabilityConfig || onViewableItemsChanged) {
1077
- viewabilityConfigCallbackPairs = [
1078
- ...viewabilityConfigCallbackPairs || [],
1079
- {
1080
- onViewableItemsChanged,
1081
- viewabilityConfig: viewabilityConfig || {
1082
- viewAreaCoveragePercentThreshold: 0
1083
- }
1084
- }
1085
- ];
1892
+ function ensureViewabilityState(ctx, configId) {
1893
+ let map = ctx.mapViewabilityConfigStates;
1894
+ if (!map) {
1895
+ map = /* @__PURE__ */ new Map();
1896
+ ctx.mapViewabilityConfigStates = map;
1086
1897
  }
1087
- if (viewabilityConfigCallbackPairs) {
1088
- for (const pair of viewabilityConfigCallbackPairs) {
1089
- mapViewabilityConfigCallbackPairs.set(pair.viewabilityConfig.id, {
1090
- end: -1,
1091
- previousEnd: -1,
1092
- previousStart: -1,
1093
- start: -1,
1094
- viewableItems: []
1095
- });
1096
- }
1898
+ let state = map.get(configId);
1899
+ if (!state) {
1900
+ state = { end: -1, previousEnd: -1, previousStart: -1, start: -1, viewableItems: [] };
1901
+ map.set(configId, state);
1097
1902
  }
1098
- return viewabilityConfigCallbackPairs;
1903
+ return state;
1099
1904
  }
1100
1905
  function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
1101
1906
  const {
@@ -1103,9 +1908,7 @@ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollS
1103
1908
  props: { data }
1104
1909
  } = state;
1105
1910
  for (const viewabilityConfigCallbackPair of viewabilityConfigCallbackPairs) {
1106
- const viewabilityState = mapViewabilityConfigCallbackPairs.get(
1107
- viewabilityConfigCallbackPair.viewabilityConfig.id
1108
- );
1911
+ const viewabilityState = ensureViewabilityState(ctx, viewabilityConfigCallbackPair.viewabilityConfig.id);
1109
1912
  viewabilityState.start = start;
1110
1913
  viewabilityState.end = end;
1111
1914
  if (viewabilityConfigCallbackPair.viewabilityConfig.minimumViewTime) {
@@ -1122,7 +1925,7 @@ function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollS
1122
1925
  function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, state, ctx, scrollSize) {
1123
1926
  const { viewabilityConfig, onViewableItemsChanged } = viewabilityConfigCallbackPair;
1124
1927
  const configId = viewabilityConfig.id;
1125
- const viewabilityState = mapViewabilityConfigCallbackPairs.get(configId);
1928
+ const viewabilityState = ensureViewabilityState(ctx, configId);
1126
1929
  const { viewableItems: previousViewableItems, start, end } = viewabilityState;
1127
1930
  const viewabilityTokens = /* @__PURE__ */ new Map();
1128
1931
  for (const [containerId, value] of ctx.mapViewabilityAmountValues) {
@@ -1201,6 +2004,15 @@ function updateViewableItemsWithConfig(data, viewabilityConfigCallbackPair, stat
1201
2004
  }
1202
2005
  }
1203
2006
  }
2007
+ function shallowEqual(prev, next) {
2008
+ if (!prev) return false;
2009
+ const keys = Object.keys(next);
2010
+ for (let i = 0; i < keys.length; i++) {
2011
+ const k = keys[i];
2012
+ if (prev[k] !== next[k]) return false;
2013
+ }
2014
+ return true;
2015
+ }
1204
2016
  function computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index) {
1205
2017
  const { sizes, positions, scroll: scrollState } = state;
1206
2018
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
@@ -1229,7 +2041,8 @@ function computeViewability(state, ctx, viewabilityConfig, containerId, key, scr
1229
2041
  size,
1230
2042
  sizeVisible
1231
2043
  };
1232
- if (JSON.stringify(value) !== JSON.stringify(ctx.mapViewabilityAmountValues.get(containerId))) {
2044
+ const prev = ctx.mapViewabilityAmountValues.get(containerId);
2045
+ if (!shallowEqual(prev, value)) {
1233
2046
  ctx.mapViewabilityAmountValues.set(containerId, value);
1234
2047
  const cb = ctx.mapViewabilityAmountCallbacks.get(containerId);
1235
2048
  if (cb) {
@@ -1259,10 +2072,13 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1259
2072
  cb == null ? void 0 : cb(viewToken);
1260
2073
  }
1261
2074
 
2075
+ // src/platform/batchedUpdates.ts
2076
+ var import_react_dom = __toESM(require_react_dom());
2077
+
1262
2078
  // src/utils/checkAllSizesKnown.ts
1263
2079
  function checkAllSizesKnown(state) {
1264
2080
  const { startBuffered, endBuffered, sizesKnown } = state;
1265
- if (endBuffered !== null) {
2081
+ if (endBuffered !== null && startBuffered >= 0 && endBuffered >= 0) {
1266
2082
  let areAllKnown = true;
1267
2083
  for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1268
2084
  const key = getId(state, i);
@@ -1274,35 +2090,79 @@ function checkAllSizesKnown(state) {
1274
2090
  }
1275
2091
 
1276
2092
  // src/utils/findAvailableContainers.ts
1277
- function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
2093
+ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
1278
2094
  const numContainers = peek$(ctx, "numContainers");
2095
+ const { stickyContainerPool, containerItemTypes } = state;
1279
2096
  const result = [];
1280
2097
  const availableContainers = [];
1281
- for (let u = 0; u < numContainers; u++) {
2098
+ const stickyIndicesSet = state.props.stickyIndicesSet;
2099
+ const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
2100
+ const canReuseContainer = (containerIndex, requiredType) => {
2101
+ if (!requiredType) return true;
2102
+ const existingType = containerItemTypes.get(containerIndex);
2103
+ if (!existingType) return true;
2104
+ return existingType === requiredType;
2105
+ };
2106
+ const neededTypes = requiredItemTypes ? [...requiredItemTypes] : [];
2107
+ let typeIndex = 0;
2108
+ for (let i = 0; i < stickyItemIndices.length; i++) {
2109
+ const requiredType = neededTypes[typeIndex];
2110
+ let foundContainer = false;
2111
+ for (const containerIndex of stickyContainerPool) {
2112
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
2113
+ const isPendingRemoval = pendingRemoval.includes(containerIndex);
2114
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType)) {
2115
+ result.push(containerIndex);
2116
+ if (isPendingRemoval) {
2117
+ const index = pendingRemoval.indexOf(containerIndex);
2118
+ pendingRemoval.splice(index, 1);
2119
+ }
2120
+ foundContainer = true;
2121
+ if (requiredItemTypes) typeIndex++;
2122
+ break;
2123
+ }
2124
+ }
2125
+ if (!foundContainer) {
2126
+ const newContainerIndex = numContainers + result.filter((index) => index >= numContainers).length;
2127
+ result.push(newContainerIndex);
2128
+ stickyContainerPool.add(newContainerIndex);
2129
+ if (requiredItemTypes) typeIndex++;
2130
+ }
2131
+ }
2132
+ for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
2133
+ if (stickyContainerPool.has(u)) {
2134
+ continue;
2135
+ }
1282
2136
  const key = peek$(ctx, `containerItemKey${u}`);
1283
2137
  let isOk = key === void 0;
1284
2138
  if (!isOk) {
1285
2139
  const index = pendingRemoval.indexOf(u);
1286
2140
  if (index !== -1) {
1287
2141
  pendingRemoval.splice(index, 1);
1288
- isOk = true;
2142
+ const requiredType = neededTypes[typeIndex];
2143
+ isOk = canReuseContainer(u, requiredType);
1289
2144
  }
1290
2145
  }
1291
2146
  if (isOk) {
1292
2147
  result.push(u);
1293
- if (result.length >= numNeeded) {
1294
- return result;
2148
+ if (requiredItemTypes) {
2149
+ typeIndex++;
1295
2150
  }
1296
2151
  }
1297
2152
  }
1298
- for (let u = 0; u < numContainers; u++) {
2153
+ for (let u = 0; u < numContainers && result.length < numNeeded; u++) {
2154
+ if (stickyContainerPool.has(u)) {
2155
+ continue;
2156
+ }
1299
2157
  const key = peek$(ctx, `containerItemKey${u}`);
1300
2158
  if (key === void 0) continue;
1301
2159
  const index = state.indexByKey.get(key);
1302
- if (index < startBuffered) {
1303
- availableContainers.push({ distance: startBuffered - index, index: u });
1304
- } else if (index > endBuffered) {
1305
- availableContainers.push({ distance: index - endBuffered, index: u });
2160
+ const isOutOfView = index < startBuffered || index > endBuffered;
2161
+ if (isOutOfView) {
2162
+ const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
2163
+ if (!requiredItemTypes || typeIndex < neededTypes.length && canReuseContainer(u, neededTypes[typeIndex])) {
2164
+ availableContainers.push({ distance, index: u });
2165
+ }
1306
2166
  }
1307
2167
  }
1308
2168
  const remaining = numNeeded - result.length;
@@ -1314,6 +2174,9 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1314
2174
  }
1315
2175
  for (const container of availableContainers) {
1316
2176
  result.push(container.index);
2177
+ if (requiredItemTypes) {
2178
+ typeIndex++;
2179
+ }
1317
2180
  }
1318
2181
  }
1319
2182
  const stillNeeded = numNeeded - result.length;
@@ -1342,37 +2205,44 @@ function comparatorByDistance(a, b) {
1342
2205
  return b.distance - a.distance;
1343
2206
  }
1344
2207
 
1345
- // src/core/finishScrollTo.ts
1346
- var finishScrollTo = (state) => {
1347
- if (state) {
1348
- state.scrollingTo = void 0;
1349
- state.scrollHistory.length = 0;
2208
+ // src/utils/getScrollVelocity.ts
2209
+ var getScrollVelocity = (state) => {
2210
+ const { scrollHistory } = state;
2211
+ let velocity = 0;
2212
+ if (scrollHistory.length >= 1) {
2213
+ const newest = scrollHistory[scrollHistory.length - 1];
2214
+ let oldest;
2215
+ let start = 0;
2216
+ const now = Date.now();
2217
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
2218
+ const entry = scrollHistory[i];
2219
+ const nextEntry = scrollHistory[i + 1];
2220
+ if (i > 0) {
2221
+ const prevEntry = scrollHistory[i - 1];
2222
+ const prevDirection = entry.scroll - prevEntry.scroll;
2223
+ const currentDirection = nextEntry.scroll - entry.scroll;
2224
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
2225
+ start = i;
2226
+ break;
2227
+ }
2228
+ }
2229
+ }
2230
+ for (let i = start; i < scrollHistory.length - 1; i++) {
2231
+ const entry = scrollHistory[i];
2232
+ if (now - entry.time <= 1e3) {
2233
+ oldest = entry;
2234
+ break;
2235
+ }
2236
+ }
2237
+ if (oldest && oldest !== newest) {
2238
+ const scrollDiff = newest.scroll - oldest.scroll;
2239
+ const timeDiff = newest.time - oldest.time;
2240
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
2241
+ }
1350
2242
  }
2243
+ return velocity;
1351
2244
  };
1352
2245
 
1353
- // src/core/scrollTo.ts
1354
- function scrollTo(state, params = {}) {
1355
- var _a;
1356
- const { animated } = params;
1357
- const {
1358
- refScroller,
1359
- props: { horizontal }
1360
- } = state;
1361
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1362
- state.scrollHistory.length = 0;
1363
- state.scrollingTo = params;
1364
- state.scrollPending = offset;
1365
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1366
- animated: !!animated,
1367
- x: horizontal ? offset : 0,
1368
- y: horizontal ? 0 : offset
1369
- });
1370
- if (!animated) {
1371
- state.scroll = offset;
1372
- setTimeout(() => finishScrollTo(state), 100);
1373
- }
1374
- }
1375
-
1376
2246
  // src/core/scrollToIndex.ts
1377
2247
  function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1378
2248
  if (index >= state.props.data.length) {
@@ -1460,33 +2330,101 @@ function setDidLayout(ctx, state) {
1460
2330
  } = state;
1461
2331
  state.queuedInitialLayout = true;
1462
2332
  checkAtBottom(ctx, state);
1463
- if (!IsNewArchitecture && initialScroll) {
1464
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
2333
+ const setIt = () => {
2334
+ set$(ctx, "containersDidLayout", true);
2335
+ if (onLoad) {
2336
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
2337
+ }
2338
+ };
2339
+ {
2340
+ setIt();
2341
+ }
2342
+ }
2343
+
2344
+ // src/core/calculateItemsInView.ts
2345
+ function findCurrentStickyIndex(stickyArray, scroll, state) {
2346
+ var _a;
2347
+ const idCache = state.idCache;
2348
+ const positions = state.positions;
2349
+ for (let i = stickyArray.length - 1; i >= 0; i--) {
2350
+ const stickyId = (_a = idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
2351
+ const stickyPos = stickyId ? positions.get(stickyId) : void 0;
2352
+ if (stickyPos !== void 0 && scroll >= stickyPos) {
2353
+ return i;
2354
+ }
2355
+ }
2356
+ return -1;
2357
+ }
2358
+ function getActiveStickyIndices(ctx, state, stickyIndices) {
2359
+ return new Set(
2360
+ Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyIndices.has(idx))
2361
+ );
2362
+ }
2363
+ function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll, needNewContainers, startBuffered, endBuffered) {
2364
+ var _a;
2365
+ const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
2366
+ const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
2367
+ for (let offset = 0; offset <= 1; offset++) {
2368
+ const idx = currentStickyIdx - offset;
2369
+ if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
2370
+ const stickyIndex = stickyArray[idx];
2371
+ const stickyId = (_a = state.idCache.get(stickyIndex)) != null ? _a : getId(state, stickyIndex);
2372
+ if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered)) {
2373
+ needNewContainers.push(stickyIndex);
2374
+ }
1465
2375
  }
1466
- set$(ctx, "containersDidLayout", true);
1467
- if (onLoad) {
1468
- onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
2376
+ }
2377
+ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pendingRemoval) {
2378
+ var _a, _b, _c;
2379
+ const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
2380
+ for (const containerIndex of state.stickyContainerPool) {
2381
+ const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
2382
+ const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
2383
+ if (itemIndex === void 0) continue;
2384
+ const arrayIdx = stickyArray.indexOf(itemIndex);
2385
+ if (arrayIdx === -1) continue;
2386
+ const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
2387
+ if (isRecentSticky) continue;
2388
+ const nextIndex = stickyArray[arrayIdx + 1];
2389
+ let shouldRecycle = false;
2390
+ if (nextIndex) {
2391
+ const nextId = (_a = state.idCache.get(nextIndex)) != null ? _a : getId(state, nextIndex);
2392
+ const nextPos = nextId ? state.positions.get(nextId) : void 0;
2393
+ shouldRecycle = nextPos !== void 0 && scroll > nextPos + scrollBuffer * 2;
2394
+ } else {
2395
+ const currentId = (_b = state.idCache.get(itemIndex)) != null ? _b : getId(state, itemIndex);
2396
+ if (currentId) {
2397
+ const currentPos = state.positions.get(currentId);
2398
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
2399
+ shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
2400
+ }
2401
+ }
2402
+ if (shouldRecycle) {
2403
+ pendingRemoval.push(containerIndex);
2404
+ }
1469
2405
  }
1470
2406
  }
1471
-
1472
- // src/core/calculateItemsInView.ts
1473
2407
  function calculateItemsInView(ctx, state, params = {}) {
1474
- unstable_batchedUpdates(() => {
2408
+ (0, import_react_dom.unstable_batchedUpdates)(() => {
1475
2409
  var _a, _b, _c, _d, _e, _f, _g, _h;
1476
2410
  const {
1477
- scrollLength,
1478
- startBufferedId: startBufferedIdOrig,
1479
- positions,
1480
2411
  columns,
1481
2412
  containerItemKeys,
2413
+ enableScrollForNextCalculateItemsInView,
1482
2414
  idCache,
1483
- sizes,
1484
2415
  indexByKey,
2416
+ minIndexSizeChanged,
2417
+ positions,
1485
2418
  scrollForNextCalculateItemsInView,
1486
- enableScrollForNextCalculateItemsInView,
1487
- minIndexSizeChanged
2419
+ scrollLength,
2420
+ sizes,
2421
+ startBufferedId: startBufferedIdOrig,
2422
+ viewabilityConfigCallbackPairs,
2423
+ props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, scrollBuffer }
1488
2424
  } = state;
1489
- const data = state.props.data;
2425
+ const { data } = state.props;
2426
+ const stickyIndicesArr = state.props.stickyIndicesArr || [];
2427
+ const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
1490
2428
  const prevNumContainers = peek$(ctx, "numContainers");
1491
2429
  if (!data || scrollLength === 0 || !prevNumContainers) {
1492
2430
  return;
@@ -1498,14 +2436,22 @@ function calculateItemsInView(ctx, state, params = {}) {
1498
2436
  const { dataChanged, doMVCP } = params;
1499
2437
  const speed = getScrollVelocity(state);
1500
2438
  if (doMVCP || dataChanged) {
1501
- const checkMVCP = doMVCP ? prepareMVCP(ctx, state) : void 0;
1502
- updateAllPositions(ctx, state, dataChanged);
2439
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
2440
+ if (dataChanged) {
2441
+ indexByKey.clear();
2442
+ idCache.clear();
2443
+ positions.clear();
2444
+ }
2445
+ const startIndex = dataChanged ? 0 : minIndexSizeChanged != null ? minIndexSizeChanged : 0;
2446
+ updateAllPositions(ctx, state, dataChanged, startIndex);
2447
+ if (minIndexSizeChanged !== void 0) {
2448
+ state.minIndexSizeChanged = void 0;
2449
+ }
1503
2450
  checkMVCP == null ? void 0 : checkMVCP();
1504
2451
  }
1505
2452
  const scrollExtra = 0;
1506
2453
  const { queuedInitialLayout } = state;
1507
2454
  let { scroll: scrollState } = state;
1508
- const initialScroll = state.props.initialScroll;
1509
2455
  if (!queuedInitialLayout && initialScroll) {
1510
2456
  const updatedOffset = calculateOffsetWithOffsetPosition(
1511
2457
  state,
@@ -1517,16 +2463,15 @@ function calculateItemsInView(ctx, state, params = {}) {
1517
2463
  const scrollAdjustPad = -previousScrollAdjust - topPad;
1518
2464
  let scroll = scrollState + scrollExtra + scrollAdjustPad;
1519
2465
  if (scroll + scrollLength > totalSize) {
1520
- scroll = totalSize - scrollLength;
2466
+ scroll = Math.max(0, totalSize - scrollLength);
1521
2467
  }
1522
2468
  if (ENABLE_DEBUG_VIEW) {
1523
2469
  set$(ctx, "debugRawScroll", scrollState);
1524
2470
  set$(ctx, "debugComputedScroll", scroll);
1525
2471
  }
1526
- const scrollBuffer = state.props.scrollBuffer;
1527
2472
  let scrollBufferTop = scrollBuffer;
1528
2473
  let scrollBufferBottom = scrollBuffer;
1529
- if (speed > 0) {
2474
+ if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
1530
2475
  scrollBufferTop = scrollBuffer * 0.5;
1531
2476
  scrollBufferBottom = scrollBuffer * 1.5;
1532
2477
  } else {
@@ -1534,7 +2479,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1534
2479
  scrollBufferBottom = scrollBuffer * 0.5;
1535
2480
  }
1536
2481
  const scrollTopBuffered = scroll - scrollBufferTop;
1537
- const scrollBottom = scroll + scrollLength;
2482
+ const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
1538
2483
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
1539
2484
  if (scrollForNextCalculateItemsInView) {
1540
2485
  const { top, bottom } = scrollForNextCalculateItemsInView;
@@ -1548,10 +2493,6 @@ function calculateItemsInView(ctx, state, params = {}) {
1548
2493
  let endNoBuffer = null;
1549
2494
  let endBuffered = null;
1550
2495
  let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1551
- if (minIndexSizeChanged !== void 0) {
1552
- loopStart = Math.min(minIndexSizeChanged, loopStart);
1553
- state.minIndexSizeChanged = void 0;
1554
- }
1555
2496
  for (let i = loopStart; i >= 0; i--) {
1556
2497
  const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
1557
2498
  const top = positions.get(id);
@@ -1634,7 +2575,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1634
2575
  if (dataChanged) {
1635
2576
  for (let i = 0; i < numContainers; i++) {
1636
2577
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1637
- if (!state.props.keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
2578
+ if (!keyExtractor || itemKey && indexByKey.get(itemKey) === void 0) {
1638
2579
  pendingRemoval.push(i);
1639
2580
  }
1640
2581
  }
@@ -1648,14 +2589,32 @@ function calculateItemsInView(ctx, state, params = {}) {
1648
2589
  needNewContainers.push(i);
1649
2590
  }
1650
2591
  }
2592
+ if (stickyIndicesArr.length > 0) {
2593
+ handleStickyActivation(
2594
+ ctx,
2595
+ state,
2596
+ stickyIndicesSet,
2597
+ stickyIndicesArr,
2598
+ scroll,
2599
+ needNewContainers,
2600
+ startBuffered,
2601
+ endBuffered
2602
+ );
2603
+ }
1651
2604
  if (needNewContainers.length > 0) {
2605
+ const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
2606
+ const itemType = getItemType(data[i], i);
2607
+ return itemType ? String(itemType) : "";
2608
+ }) : void 0;
1652
2609
  const availableContainers = findAvailableContainers(
1653
2610
  ctx,
1654
2611
  state,
1655
2612
  needNewContainers.length,
1656
2613
  startBuffered,
1657
2614
  endBuffered,
1658
- pendingRemoval
2615
+ pendingRemoval,
2616
+ requiredItemTypes,
2617
+ needNewContainers
1659
2618
  );
1660
2619
  for (let idx = 0; idx < needNewContainers.length; idx++) {
1661
2620
  const i = needNewContainers[idx];
@@ -1667,7 +2626,18 @@ function calculateItemsInView(ctx, state, params = {}) {
1667
2626
  }
1668
2627
  set$(ctx, `containerItemKey${containerIndex}`, id);
1669
2628
  set$(ctx, `containerItemData${containerIndex}`, data[i]);
2629
+ if (requiredItemTypes) {
2630
+ state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
2631
+ }
1670
2632
  containerItemKeys.add(id);
2633
+ if (stickyIndicesSet.has(i)) {
2634
+ set$(ctx, `containerSticky${containerIndex}`, true);
2635
+ const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2636
+ set$(ctx, `containerStickyOffset${containerIndex}`, createAnimatedValue(topPadding));
2637
+ state.stickyContainerPool.add(containerIndex);
2638
+ } else {
2639
+ state.stickyContainerPool.delete(containerIndex);
2640
+ }
1671
2641
  if (containerIndex >= numContainers2) {
1672
2642
  numContainers2 = containerIndex + 1;
1673
2643
  }
@@ -1680,12 +2650,22 @@ function calculateItemsInView(ctx, state, params = {}) {
1680
2650
  }
1681
2651
  }
1682
2652
  }
2653
+ if (stickyIndicesArr.length > 0) {
2654
+ handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, pendingRemoval);
2655
+ }
2656
+ let didChangePositions = false;
1683
2657
  for (let i = 0; i < numContainers; i++) {
1684
2658
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1685
2659
  if (pendingRemoval.includes(i)) {
1686
2660
  if (itemKey) {
1687
2661
  containerItemKeys.delete(itemKey);
1688
2662
  }
2663
+ state.containerItemTypes.delete(i);
2664
+ if (state.stickyContainerPool.has(i)) {
2665
+ set$(ctx, `containerSticky${i}`, false);
2666
+ set$(ctx, `containerStickyOffset${i}`, void 0);
2667
+ state.stickyContainerPool.delete(i);
2668
+ }
1689
2669
  set$(ctx, `containerItemKey${i}`, void 0);
1690
2670
  set$(ctx, `containerItemData${i}`, void 0);
1691
2671
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
@@ -1705,58 +2685,75 @@ function calculateItemsInView(ctx, state, params = {}) {
1705
2685
  const prevData = peek$(ctx, `containerItemData${i}`);
1706
2686
  if (position > POSITION_OUT_OF_VIEW && position !== prevPos) {
1707
2687
  set$(ctx, `containerPosition${i}`, position);
2688
+ didChangePositions = true;
1708
2689
  }
1709
2690
  if (column >= 0 && column !== prevColumn) {
1710
2691
  set$(ctx, `containerColumn${i}`, column);
1711
2692
  }
1712
- if (prevData !== item) {
2693
+ if (prevData !== item && (itemsAreEqual ? !itemsAreEqual(prevData, item, itemIndex, data) : true)) {
1713
2694
  set$(ctx, `containerItemData${i}`, data[itemIndex]);
1714
2695
  }
1715
2696
  }
1716
2697
  }
1717
2698
  }
1718
2699
  }
2700
+ if (didChangePositions) {
2701
+ set$(ctx, "lastPositionUpdate", Date.now());
2702
+ }
1719
2703
  if (!queuedInitialLayout && endBuffered !== null) {
1720
2704
  if (checkAllSizesKnown(state)) {
1721
2705
  setDidLayout(ctx, state);
1722
2706
  }
1723
2707
  }
1724
- if (state.props.viewabilityConfigCallbackPairs) {
1725
- updateViewableItems(
1726
- state,
1727
- ctx,
1728
- state.props.viewabilityConfigCallbackPairs,
1729
- scrollLength,
1730
- startNoBuffer,
1731
- endNoBuffer
1732
- );
2708
+ if (viewabilityConfigCallbackPairs) {
2709
+ updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
1733
2710
  }
1734
2711
  });
1735
2712
  }
1736
2713
 
1737
2714
  // src/core/doInitialAllocateContainers.ts
1738
2715
  function doInitialAllocateContainers(ctx, state) {
1739
- const { scrollLength } = state;
1740
- const data = state.props.data;
1741
- if (scrollLength > 0 && data.length > 0 && !peek$(ctx, "numContainers")) {
1742
- const averageItemSize = state.props.getEstimatedItemSize ? state.props.getEstimatedItemSize(0, data[0]) : state.props.estimatedItemSize;
1743
- const Extra = 1.5;
1744
- const numContainers = Math.ceil(
1745
- (scrollLength + state.props.scrollBuffer * 2) / averageItemSize * state.props.numColumns * Extra
1746
- );
2716
+ var _a;
2717
+ const {
2718
+ scrollLength,
2719
+ props: {
2720
+ data,
2721
+ getEstimatedItemSize,
2722
+ getFixedItemSize,
2723
+ getItemType,
2724
+ scrollBuffer,
2725
+ numColumns,
2726
+ estimatedItemSize
2727
+ }
2728
+ } = state;
2729
+ const hasContainers = peek$(ctx, "numContainers");
2730
+ if (scrollLength > 0 && data.length > 0 && !hasContainers) {
2731
+ let averageItemSize;
2732
+ const fn = getFixedItemSize || getEstimatedItemSize;
2733
+ if (fn) {
2734
+ let totalSize = 0;
2735
+ const num = Math.min(20, data.length);
2736
+ for (let i = 0; i < num; i++) {
2737
+ totalSize += fn(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "");
2738
+ }
2739
+ averageItemSize = totalSize / num;
2740
+ } else {
2741
+ averageItemSize = estimatedItemSize;
2742
+ }
2743
+ const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize * numColumns);
1747
2744
  for (let i = 0; i < numContainers; i++) {
1748
2745
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1749
2746
  set$(ctx, `containerColumn${i}`, -1);
1750
2747
  }
1751
2748
  set$(ctx, "numContainers", numContainers);
1752
2749
  set$(ctx, "numContainersPooled", numContainers * state.props.initialContainerPoolRatio);
1753
- if (!IsNewArchitecture) {
2750
+ if (state.lastLayout) {
1754
2751
  if (state.props.initialScroll) {
1755
2752
  requestAnimationFrame(() => {
1756
- calculateItemsInView(ctx, state);
2753
+ calculateItemsInView(ctx, state, { dataChanged: true });
1757
2754
  });
1758
2755
  } else {
1759
- calculateItemsInView(ctx, state);
2756
+ calculateItemsInView(ctx, state, { dataChanged: true });
1760
2757
  }
1761
2758
  }
1762
2759
  return true;
@@ -1776,16 +2773,18 @@ function doMaintainScrollAtEnd(ctx, state, animated) {
1776
2773
  }
1777
2774
  requestAnimationFrame(() => {
1778
2775
  var _a;
1779
- state.maintainingScrollAtEnd = true;
1780
- (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
1781
- animated
1782
- });
1783
- setTimeout(
1784
- () => {
1785
- state.maintainingScrollAtEnd = false;
1786
- },
1787
- 0
1788
- );
2776
+ if (state == null ? void 0 : state.isAtEnd) {
2777
+ state.maintainingScrollAtEnd = true;
2778
+ (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
2779
+ animated
2780
+ });
2781
+ setTimeout(
2782
+ () => {
2783
+ state.maintainingScrollAtEnd = false;
2784
+ },
2785
+ 0
2786
+ );
2787
+ }
1789
2788
  });
1790
2789
  return true;
1791
2790
  }
@@ -1822,44 +2821,57 @@ function checkAtTop(state) {
1822
2821
  // src/core/handleLayout.ts
1823
2822
  function handleLayout(ctx, state, layout, setCanRender) {
1824
2823
  const { maintainScrollAtEnd } = state.props;
1825
- const scrollLength = layout[state.props.horizontal ? "width" : "height"];
2824
+ const measuredLength = layout[state.props.horizontal ? "width" : "height"];
2825
+ const previousLength = state.scrollLength;
2826
+ const scrollLength = measuredLength > 0 ? measuredLength : previousLength;
1826
2827
  const otherAxisSize = layout[state.props.horizontal ? "height" : "width"];
1827
2828
  const needsCalculate = !state.lastLayout || scrollLength > state.scrollLength || state.lastLayout.x !== layout.x || state.lastLayout.y !== layout.y;
1828
2829
  state.lastLayout = layout;
1829
- const didChange = scrollLength !== state.scrollLength;
1830
2830
  const prevOtherAxisSize = state.otherAxisSize;
1831
- state.scrollLength = scrollLength;
1832
- state.otherAxisSize = otherAxisSize;
1833
- state.lastBatchingAction = Date.now();
1834
- state.scrollForNextCalculateItemsInView = void 0;
1835
- doInitialAllocateContainers(ctx, state);
1836
- if (needsCalculate) {
1837
- calculateItemsInView(ctx, state, { doMVCP: true });
1838
- }
1839
- if (didChange || otherAxisSize !== prevOtherAxisSize) {
1840
- set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
1841
- }
1842
- if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
1843
- doMaintainScrollAtEnd(ctx, state, false);
1844
- }
1845
- updateAlignItemsPaddingTop(ctx, state);
1846
- checkAtBottom(ctx, state);
1847
- checkAtTop(state);
1848
- if (state) {
1849
- state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
1850
- }
1851
- if (__DEV__ && scrollLength === 0) {
1852
- warnDevOnce(
1853
- "height0",
1854
- `List ${state.props.horizontal ? "width" : "height"} is 0. You may need to set a style or \`flex: \` for the list, because children are absolutely positioned.`
1855
- );
2831
+ const didChange = scrollLength !== state.scrollLength || otherAxisSize !== prevOtherAxisSize;
2832
+ if (didChange) {
2833
+ state.scrollLength = scrollLength;
2834
+ state.otherAxisSize = otherAxisSize;
2835
+ state.lastBatchingAction = Date.now();
2836
+ state.scrollForNextCalculateItemsInView = void 0;
2837
+ if (scrollLength > 0) {
2838
+ doInitialAllocateContainers(ctx, state);
2839
+ }
2840
+ if (needsCalculate) {
2841
+ calculateItemsInView(ctx, state, { doMVCP: true });
2842
+ }
2843
+ if (didChange || otherAxisSize !== prevOtherAxisSize) {
2844
+ set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
2845
+ }
2846
+ if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
2847
+ doMaintainScrollAtEnd(ctx, state, false);
2848
+ }
2849
+ updateAlignItemsPaddingTop(ctx, state);
2850
+ checkAtBottom(ctx, state);
2851
+ checkAtTop(state);
2852
+ if (state) {
2853
+ state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2854
+ }
2855
+ if (__DEV__ && measuredLength === 0) {
2856
+ warnDevOnce(
2857
+ "height0",
2858
+ `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.`
2859
+ );
2860
+ }
2861
+ setCanRender(true);
1856
2862
  }
1857
- setCanRender(true);
1858
2863
  }
1859
2864
 
1860
2865
  // src/core/onScroll.ts
1861
2866
  function onScroll(ctx, state, event) {
1862
- var _a, _b, _c, _d, _e;
2867
+ var _a, _b, _c;
2868
+ const {
2869
+ scrollProcessingEnabled,
2870
+ props: { onScroll: onScrollProp }
2871
+ } = state;
2872
+ if (scrollProcessingEnabled === false) {
2873
+ return;
2874
+ }
1863
2875
  if (((_b = (_a = event.nativeEvent) == null ? void 0 : _a.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
1864
2876
  return;
1865
2877
  }
@@ -1872,16 +2884,25 @@ function onScroll(ctx, state, event) {
1872
2884
  }
1873
2885
  }
1874
2886
  state.scrollPending = newScroll;
1875
- updateScroll(ctx, state, newScroll);
1876
- (_e = (_d = state.props).onScroll) == null ? void 0 : _e.call(_d, event);
2887
+ {
2888
+ if (!state.onScrollRafScheduled) {
2889
+ state.onScrollRafScheduled = true;
2890
+ requestAnimationFrame(() => {
2891
+ state.onScrollRafScheduled = false;
2892
+ updateScroll(ctx, state, newScroll);
2893
+ });
2894
+ }
2895
+ }
2896
+ onScrollProp == null ? void 0 : onScrollProp(event);
1877
2897
  }
1878
2898
  function updateScroll(ctx, state, newScroll) {
1879
2899
  const scrollingTo = state.scrollingTo;
1880
2900
  state.hasScrolled = true;
1881
2901
  state.lastBatchingAction = Date.now();
1882
- const currentTime = performance.now();
2902
+ const currentTime = Date.now();
1883
2903
  if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
1884
- state.scrollHistory.push({ scroll: newScroll, time: currentTime });
2904
+ const adjust = state.scrollAdjustHandler.getAdjust();
2905
+ state.scrollHistory.push({ scroll: newScroll - adjust, time: currentTime });
1885
2906
  }
1886
2907
  if (state.scrollHistory.length > 5) {
1887
2908
  state.scrollHistory.shift();
@@ -1890,9 +2911,11 @@ function updateScroll(ctx, state, newScroll) {
1890
2911
  state.scrollPrevTime = state.scrollTime;
1891
2912
  state.scroll = newScroll;
1892
2913
  state.scrollTime = currentTime;
1893
- calculateItemsInView(ctx, state);
1894
- checkAtBottom(ctx, state);
1895
- checkAtTop(state);
2914
+ if (Math.abs(state.scroll - state.scrollPrev) > 2) {
2915
+ calculateItemsInView(ctx, state);
2916
+ checkAtBottom(ctx, state);
2917
+ checkAtTop(state);
2918
+ }
1896
2919
  }
1897
2920
 
1898
2921
  // src/core/ScrollAdjustHandler.ts
@@ -1915,13 +2938,19 @@ var ScrollAdjustHandler = class {
1915
2938
  setMounted() {
1916
2939
  this.mounted = true;
1917
2940
  }
2941
+ getAdjust() {
2942
+ return this.appliedAdjust;
2943
+ }
1918
2944
  };
1919
2945
 
1920
2946
  // src/core/updateItemSize.ts
1921
- function updateItemSizes(ctx, state, itemUpdates) {
1922
- var _a;
2947
+ function updateItemSize(ctx, state, itemKey, sizeObj) {
2948
+ var _a, _b;
1923
2949
  const {
2950
+ sizesKnown,
1924
2951
  props: {
2952
+ getFixedItemSize,
2953
+ getItemType,
1925
2954
  horizontal,
1926
2955
  maintainVisibleContentPosition,
1927
2956
  suggestEstimatedItemSize,
@@ -1931,47 +2960,60 @@ function updateItemSizes(ctx, state, itemUpdates) {
1931
2960
  }
1932
2961
  } = state;
1933
2962
  if (!data) return;
2963
+ if (getFixedItemSize) {
2964
+ const index2 = state.indexByKey.get(itemKey);
2965
+ if (index2 === void 0) {
2966
+ return;
2967
+ }
2968
+ const itemData = state.props.data[index2];
2969
+ if (itemData === void 0) {
2970
+ return;
2971
+ }
2972
+ const type = getItemType ? (_a = getItemType(itemData, index2)) != null ? _a : "" : "";
2973
+ const size2 = getFixedItemSize(index2, itemData, type);
2974
+ if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
2975
+ return;
2976
+ }
2977
+ }
1934
2978
  const containersDidLayout = peek$(ctx, "containersDidLayout");
1935
2979
  let needsRecalculate = !containersDidLayout;
1936
2980
  let shouldMaintainScrollAtEnd = false;
1937
2981
  let minIndexSizeChanged;
1938
2982
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
1939
- for (const { itemKey, sizeObj } of itemUpdates) {
1940
- const index = state.indexByKey.get(itemKey);
1941
- const prevSizeKnown = state.sizesKnown.get(itemKey);
1942
- const diff = updateOneItemSize(state, itemKey, sizeObj);
1943
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
1944
- if (diff !== 0) {
1945
- minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
1946
- if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
1947
- requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
1948
- }
1949
- const { startBuffered, endBuffered } = state;
1950
- needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
1951
- if (!needsRecalculate) {
1952
- const numContainers = ctx.values.get("numContainers");
1953
- for (let i = 0; i < numContainers; i++) {
1954
- if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
1955
- needsRecalculate = true;
1956
- break;
1957
- }
2983
+ const index = state.indexByKey.get(itemKey);
2984
+ const prevSizeKnown = state.sizesKnown.get(itemKey);
2985
+ const diff = updateOneItemSize(state, itemKey, sizeObj);
2986
+ const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2987
+ if (diff !== 0) {
2988
+ minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
2989
+ if (((_b = state.scrollingTo) == null ? void 0 : _b.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
2990
+ requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
2991
+ }
2992
+ const { startBuffered, endBuffered } = state;
2993
+ needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2994
+ if (!needsRecalculate) {
2995
+ const numContainers = ctx.values.get("numContainers");
2996
+ for (let i = 0; i < numContainers; i++) {
2997
+ if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
2998
+ needsRecalculate = true;
2999
+ break;
1958
3000
  }
1959
3001
  }
1960
- if (state.needsOtherAxisSize) {
1961
- const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
1962
- maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
1963
- }
1964
- if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
1965
- shouldMaintainScrollAtEnd = true;
1966
- }
1967
- onItemSizeChanged == null ? void 0 : onItemSizeChanged({
1968
- index,
1969
- itemData: state.props.data[index],
1970
- itemKey,
1971
- previous: size - diff,
1972
- size
1973
- });
1974
3002
  }
3003
+ if (state.needsOtherAxisSize) {
3004
+ const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
3005
+ maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
3006
+ }
3007
+ if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
3008
+ shouldMaintainScrollAtEnd = true;
3009
+ }
3010
+ onItemSizeChanged == null ? void 0 : onItemSizeChanged({
3011
+ index,
3012
+ itemData: state.props.data[index],
3013
+ itemKey,
3014
+ previous: size - diff,
3015
+ size
3016
+ });
1975
3017
  }
1976
3018
  if (minIndexSizeChanged !== void 0) {
1977
3019
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
@@ -2004,43 +3046,30 @@ function updateItemSizes(ctx, state, itemUpdates) {
2004
3046
  }
2005
3047
  }
2006
3048
  }
2007
- function updateItemSize(ctx, state, itemKey, sizeObj) {
2008
- const { queuedItemSizeUpdates, queuedItemSizeUpdatesWaiting } = state;
2009
- const containersDidLayout = peek$(ctx, "containersDidLayout");
2010
- if (!containersDidLayout || !queuedItemSizeUpdatesWaiting) {
2011
- updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
2012
- if (containersDidLayout) {
2013
- state.queuedItemSizeUpdatesWaiting = true;
2014
- requestAnimationFrame(() => {
2015
- state.queuedItemSizeUpdatesWaiting = false;
2016
- updateItemSizes(ctx, state, queuedItemSizeUpdates);
2017
- queuedItemSizeUpdates.length = 0;
2018
- });
2019
- }
2020
- } else {
2021
- queuedItemSizeUpdates.push({ itemKey, sizeObj });
2022
- }
2023
- }
2024
3049
  function updateOneItemSize(state, itemKey, sizeObj) {
3050
+ var _a;
2025
3051
  const {
2026
3052
  sizes,
2027
3053
  indexByKey,
2028
3054
  sizesKnown,
2029
3055
  averageSizes,
2030
- props: { data, horizontal }
3056
+ props: { data, horizontal, getEstimatedItemSize, getItemType, getFixedItemSize }
2031
3057
  } = state;
2032
3058
  if (!data) return 0;
2033
3059
  const index = indexByKey.get(itemKey);
2034
3060
  const prevSize = getItemSize(state, itemKey, index, data);
2035
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
3061
+ const rawSize = horizontal ? sizeObj.width : sizeObj.height;
3062
+ const size = Math.round(rawSize) ;
2036
3063
  sizesKnown.set(itemKey, size);
2037
- const itemType = "";
2038
- let averages = averageSizes[itemType];
2039
- if (!averages) {
2040
- averages = averageSizes[itemType] = { avg: 0, num: 0 };
3064
+ if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
3065
+ const itemType = getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : "";
3066
+ let averages = averageSizes[itemType];
3067
+ if (!averages) {
3068
+ averages = averageSizes[itemType] = { avg: 0, num: 0 };
3069
+ }
3070
+ averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
3071
+ averages.num++;
2041
3072
  }
2042
- averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2043
- averages.num++;
2044
3073
  if (!prevSize || Math.abs(prevSize - size) > 0.1) {
2045
3074
  sizes.set(itemKey, size);
2046
3075
  return size - prevSize;
@@ -2063,6 +3092,22 @@ var useCombinedRef = (...refs) => {
2063
3092
  return callback;
2064
3093
  };
2065
3094
 
3095
+ // src/platform/RefreshControl.tsx
3096
+ function RefreshControl(props) {
3097
+ return null;
3098
+ }
3099
+
3100
+ // src/platform/StyleSheet.tsx
3101
+ var StyleSheet = {
3102
+ create: (styles) => styles,
3103
+ flatten: (style) => style
3104
+ };
3105
+
3106
+ // src/platform/useStickyScrollHandler.ts
3107
+ function useStickyScrollHandler(stickyIndices, horizontal, ctx, onScroll2) {
3108
+ return onScroll2;
3109
+ }
3110
+
2066
3111
  // src/utils/createColumnWrapperStyle.ts
2067
3112
  function createColumnWrapperStyle(contentContainerStyle) {
2068
3113
  const { gap, columnGap, rowGap } = contentContainerStyle;
@@ -2078,86 +3123,200 @@ function createColumnWrapperStyle(contentContainerStyle) {
2078
3123
  }
2079
3124
  }
2080
3125
  function getRenderedItem(ctx, state, key) {
3126
+ var _a;
2081
3127
  if (!state) {
2082
3128
  return null;
2083
3129
  }
2084
3130
  const {
2085
3131
  indexByKey,
2086
- props: { data, renderItem: renderItem2 }
3132
+ props: { data, getItemType, renderItem }
2087
3133
  } = state;
2088
3134
  const index = indexByKey.get(key);
2089
3135
  if (index === void 0) {
2090
3136
  return null;
2091
3137
  }
2092
3138
  let renderedItem = null;
2093
- if (renderItem2) {
3139
+ if (renderItem && data[index]) {
2094
3140
  const itemProps = {
3141
+ data,
2095
3142
  extraData: peek$(ctx, "extraData"),
2096
3143
  index,
2097
- item: data[index]
3144
+ item: data[index],
3145
+ type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
2098
3146
  };
2099
- renderedItem = React3__default.createElement(renderItem2, itemProps);
3147
+ renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React3__default.createElement(renderItem, itemProps);
2100
3148
  }
2101
3149
  return { index, item: data[index], renderedItem };
2102
3150
  }
3151
+ function useThrottleDebounce(mode) {
3152
+ const timeoutRef = useRef(null);
3153
+ const lastCallTimeRef = useRef(0);
3154
+ const lastArgsRef = useRef(null);
3155
+ const clearTimeoutRef = () => {
3156
+ if (timeoutRef.current) {
3157
+ clearTimeout(timeoutRef.current);
3158
+ timeoutRef.current = null;
3159
+ }
3160
+ };
3161
+ const execute = useCallback(
3162
+ (callback, delay, ...args) => {
3163
+ {
3164
+ const now = Date.now();
3165
+ lastArgsRef.current = args;
3166
+ if (now - lastCallTimeRef.current >= delay) {
3167
+ lastCallTimeRef.current = now;
3168
+ callback(...args);
3169
+ clearTimeoutRef();
3170
+ } else {
3171
+ clearTimeoutRef();
3172
+ timeoutRef.current = setTimeout(
3173
+ () => {
3174
+ if (lastArgsRef.current) {
3175
+ lastCallTimeRef.current = Date.now();
3176
+ callback(...lastArgsRef.current);
3177
+ timeoutRef.current = null;
3178
+ lastArgsRef.current = null;
3179
+ }
3180
+ },
3181
+ delay - (now - lastCallTimeRef.current)
3182
+ );
3183
+ }
3184
+ }
3185
+ },
3186
+ [mode]
3187
+ );
3188
+ return execute;
3189
+ }
3190
+
3191
+ // src/utils/throttledOnScroll.ts
3192
+ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
3193
+ const throttle = useThrottleDebounce("throttle");
3194
+ return (event) => throttle(originalHandler, scrollEventThrottle, { nativeEvent: event.nativeEvent });
3195
+ }
3196
+
3197
+ // src/utils/updateAveragesOnDataChange.ts
3198
+ function updateAveragesOnDataChange(state, oldData, newData) {
3199
+ var _a;
3200
+ const {
3201
+ averageSizes,
3202
+ sizesKnown,
3203
+ indexByKey,
3204
+ props: { itemsAreEqual, getItemType, keyExtractor }
3205
+ } = state;
3206
+ if (!itemsAreEqual || !oldData.length || !newData.length) {
3207
+ for (const key in averageSizes) {
3208
+ delete averageSizes[key];
3209
+ }
3210
+ return;
3211
+ }
3212
+ const itemTypesToPreserve = {};
3213
+ const newDataLength = newData.length;
3214
+ const oldDataLength = oldData.length;
3215
+ for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
3216
+ const newItem = newData[newIndex];
3217
+ const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
3218
+ const oldIndex = indexByKey.get(id);
3219
+ if (oldIndex !== void 0 && oldIndex < oldDataLength) {
3220
+ const knownSize = sizesKnown.get(id);
3221
+ if (knownSize === void 0) continue;
3222
+ const oldItem = oldData[oldIndex];
3223
+ const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
3224
+ if (areEqual) {
3225
+ const itemType = getItemType ? (_a = getItemType(newItem, newIndex)) != null ? _a : "" : "";
3226
+ let typeData = itemTypesToPreserve[itemType];
3227
+ if (!typeData) {
3228
+ typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
3229
+ }
3230
+ typeData.totalSize += knownSize;
3231
+ typeData.count++;
3232
+ }
3233
+ }
3234
+ }
3235
+ for (const key in averageSizes) {
3236
+ delete averageSizes[key];
3237
+ }
3238
+ for (const itemType in itemTypesToPreserve) {
3239
+ const { totalSize, count } = itemTypesToPreserve[itemType];
3240
+ if (count > 0) {
3241
+ averageSizes[itemType] = {
3242
+ avg: totalSize / count,
3243
+ num: count
3244
+ };
3245
+ }
3246
+ }
3247
+ }
2103
3248
 
2104
3249
  // src/components/LegendList.tsx
2105
3250
  var DEFAULT_DRAW_DISTANCE = 250;
2106
3251
  var DEFAULT_ITEM_SIZE = 100;
2107
- var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
2108
- return /* @__PURE__ */ React3.createElement(StateProvider, null, /* @__PURE__ */ React3.createElement(LegendListInner, { ...props, ref: forwardedRef }));
2109
- });
3252
+ var LegendList = typedMemo(
3253
+ typedForwardRef(function LegendList2(props, forwardedRef) {
3254
+ const { children, data: dataProp, renderItem: renderItemProp, ...restProps } = props;
3255
+ const isChildrenMode = children !== void 0 && dataProp === void 0;
3256
+ const processedProps = isChildrenMode ? {
3257
+ ...restProps,
3258
+ data: (isArray(children) ? children : React3.Children.toArray(children)).flat(1),
3259
+ renderItem: ({ item }) => item
3260
+ } : {
3261
+ ...restProps,
3262
+ data: dataProp || [],
3263
+ renderItem: renderItemProp
3264
+ };
3265
+ return /* @__PURE__ */ React3.createElement(StateProvider, null, /* @__PURE__ */ React3.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
3266
+ })
3267
+ );
2110
3268
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
2111
- var _a;
2112
3269
  const {
2113
- data: dataProp = [],
2114
- initialScrollIndex: initialScrollIndexProp,
2115
- initialScrollOffset,
2116
- horizontal,
2117
- drawDistance = 250,
2118
- recycleItems = false,
2119
- onEndReachedThreshold = 0.5,
2120
- onStartReachedThreshold = 0.5,
2121
- maintainScrollAtEnd = false,
2122
- maintainScrollAtEndThreshold = 0.1,
2123
3270
  alignItemsAtEnd = false,
2124
- maintainVisibleContentPosition = false,
2125
- onScroll: onScrollProp,
2126
- onMomentumScrollEnd,
2127
- numColumns: numColumnsProp = 1,
2128
3271
  columnWrapperStyle,
2129
- keyExtractor: keyExtractorProp,
2130
- renderItem: renderItem2,
2131
- estimatedListSize,
3272
+ contentContainerStyle: contentContainerStyleProp,
3273
+ data: dataProp = [],
3274
+ drawDistance = 250,
3275
+ enableAverages = true,
2132
3276
  estimatedItemSize: estimatedItemSizeProp,
3277
+ estimatedListSize,
3278
+ extraData,
2133
3279
  getEstimatedItemSize,
2134
- suggestEstimatedItemSize,
2135
- ListHeaderComponent,
3280
+ getFixedItemSize,
3281
+ getItemType,
3282
+ horizontal,
3283
+ initialContainerPoolRatio = 2,
3284
+ initialScrollIndex: initialScrollIndexProp,
3285
+ initialScrollOffset: initialScrollOffsetProp,
3286
+ itemsAreEqual,
3287
+ keyExtractor: keyExtractorProp,
2136
3288
  ListEmptyComponent,
3289
+ ListHeaderComponent,
3290
+ maintainScrollAtEnd = false,
3291
+ maintainScrollAtEndThreshold = 0.1,
3292
+ maintainVisibleContentPosition = true,
3293
+ numColumns: numColumnsProp = 1,
3294
+ onEndReached,
3295
+ onEndReachedThreshold = 0.5,
2137
3296
  onItemSizeChanged,
2138
- refScrollView,
2139
- waitForInitialLayout = true,
2140
- extraData,
2141
- contentContainerStyle: contentContainerStyleProp,
2142
- style: styleProp,
2143
3297
  onLayout: onLayoutProp,
3298
+ onLoad,
3299
+ onMomentumScrollEnd,
2144
3300
  onRefresh,
2145
- refreshing,
3301
+ onScroll: onScrollProp,
3302
+ onStartReached,
3303
+ onStartReachedThreshold = 0.5,
2146
3304
  progressViewOffset,
3305
+ recycleItems = false,
2147
3306
  refreshControl,
2148
- initialContainerPoolRatio = 2,
2149
- viewabilityConfig,
2150
- viewabilityConfigCallbackPairs,
3307
+ refreshing,
3308
+ refScrollView,
3309
+ renderItem,
3310
+ scrollEventThrottle,
2151
3311
  snapToIndices,
2152
- onViewableItemsChanged,
2153
- onStartReached,
2154
- onEndReached,
2155
- onLoad,
3312
+ stickyIndices,
3313
+ style: styleProp,
3314
+ suggestEstimatedItemSize,
3315
+ waitForInitialLayout = true,
2156
3316
  ...rest
2157
3317
  } = props;
2158
3318
  const [renderNum, setRenderNum] = useState(0);
2159
- const initialScroll = typeof initialScrollIndexProp === "number" ? { index: initialScrollIndexProp } : initialScrollIndexProp;
2160
- const initialScrollIndex = initialScroll == null ? void 0 : initialScroll.index;
3319
+ const initialScroll = initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
2161
3320
  const [canRender, setCanRender] = React3.useState(!IsNewArchitecture);
2162
3321
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
2163
3322
  const style = { ...StyleSheet.flatten(styleProp) };
@@ -2172,68 +3331,82 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2172
3331
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
2173
3332
  const refState = useRef();
2174
3333
  if (!refState.current) {
2175
- const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : Dimensions.get("window"))[horizontal ? "width" : "height"];
2176
- refState.current = {
2177
- averageSizes: {},
2178
- columns: /* @__PURE__ */ new Map(),
2179
- containerItemKeys: /* @__PURE__ */ new Set(),
2180
- enableScrollForNextCalculateItemsInView: true,
2181
- endBuffered: -1,
2182
- endNoBuffer: -1,
2183
- endReachedBlockedByTimer: false,
2184
- firstFullyOnScreenIndex: -1,
2185
- idCache: /* @__PURE__ */ new Map(),
2186
- idsInView: [],
2187
- indexByKey: /* @__PURE__ */ new Map(),
2188
- initialScroll,
2189
- isAtEnd: false,
2190
- isAtStart: false,
2191
- isEndReached: false,
2192
- isStartReached: false,
2193
- lastBatchingAction: Date.now(),
2194
- lastLayout: void 0,
2195
- loadStartTime: Date.now(),
2196
- minIndexSizeChanged: 0,
2197
- nativeMarginTop: 0,
2198
- pendingAdjust: 0,
2199
- positions: /* @__PURE__ */ new Map(),
2200
- props: {},
2201
- queuedCalculateItemsInView: 0,
2202
- queuedItemSizeUpdates: [],
2203
- refScroller: void 0,
2204
- scroll: 0,
2205
- scrollAdjustHandler: new ScrollAdjustHandler(ctx),
2206
- scrollForNextCalculateItemsInView: void 0,
2207
- scrollHistory: [],
2208
- scrollLength: initialScrollLength,
2209
- scrollPending: 0,
2210
- scrollPrev: 0,
2211
- scrollPrevTime: 0,
2212
- scrollTime: 0,
2213
- sizes: /* @__PURE__ */ new Map(),
2214
- sizesKnown: /* @__PURE__ */ new Map(),
2215
- startBuffered: -1,
2216
- startNoBuffer: -1,
2217
- startReachedBlockedByTimer: false,
2218
- timeoutSizeMessage: 0,
2219
- timeouts: /* @__PURE__ */ new Set(),
2220
- totalSize: 0,
2221
- viewabilityConfigCallbackPairs: void 0
2222
- };
2223
- set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2224
- set$(ctx, "extraData", extraData);
3334
+ if (!ctx.internalState) {
3335
+ const initialScrollLength = (estimatedListSize != null ? estimatedListSize : { height: 0, width: 0 } )[horizontal ? "width" : "height"];
3336
+ ctx.internalState = {
3337
+ activeStickyIndex: void 0,
3338
+ averageSizes: {},
3339
+ columns: /* @__PURE__ */ new Map(),
3340
+ containerItemKeys: /* @__PURE__ */ new Set(),
3341
+ containerItemTypes: /* @__PURE__ */ new Map(),
3342
+ enableScrollForNextCalculateItemsInView: true,
3343
+ endBuffered: -1,
3344
+ endNoBuffer: -1,
3345
+ endReachedBlockedByTimer: false,
3346
+ firstFullyOnScreenIndex: -1,
3347
+ idCache: /* @__PURE__ */ new Map(),
3348
+ idsInView: [],
3349
+ indexByKey: /* @__PURE__ */ new Map(),
3350
+ initialScroll,
3351
+ isAtEnd: false,
3352
+ isAtStart: false,
3353
+ isEndReached: false,
3354
+ isStartReached: false,
3355
+ lastBatchingAction: Date.now(),
3356
+ lastLayout: void 0,
3357
+ loadStartTime: Date.now(),
3358
+ minIndexSizeChanged: 0,
3359
+ nativeMarginTop: 0,
3360
+ positions: /* @__PURE__ */ new Map(),
3361
+ props: {},
3362
+ queuedCalculateItemsInView: 0,
3363
+ refScroller: void 0,
3364
+ scroll: 0,
3365
+ scrollAdjustHandler: new ScrollAdjustHandler(ctx),
3366
+ scrollForNextCalculateItemsInView: void 0,
3367
+ scrollHistory: [],
3368
+ scrollLength: initialScrollLength,
3369
+ scrollPending: 0,
3370
+ scrollPrev: 0,
3371
+ scrollPrevTime: 0,
3372
+ scrollProcessingEnabled: true,
3373
+ scrollTime: 0,
3374
+ sizes: /* @__PURE__ */ new Map(),
3375
+ sizesKnown: /* @__PURE__ */ new Map(),
3376
+ startBuffered: -1,
3377
+ startNoBuffer: -1,
3378
+ startReachedBlockedByTimer: false,
3379
+ stickyContainerPool: /* @__PURE__ */ new Set(),
3380
+ stickyContainers: /* @__PURE__ */ new Map(),
3381
+ timeoutSizeMessage: 0,
3382
+ timeouts: /* @__PURE__ */ new Set(),
3383
+ totalSize: 0,
3384
+ viewabilityConfigCallbackPairs: void 0
3385
+ };
3386
+ set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
3387
+ set$(ctx, "extraData", extraData);
3388
+ }
3389
+ refState.current = ctx.internalState;
2225
3390
  }
2226
3391
  const state = refState.current;
2227
3392
  const isFirst = !state.props.renderItem;
2228
3393
  const didDataChange = state.props.data !== dataProp;
3394
+ const throttleScrollFn = (
3395
+ // @ts-expect-error TODO Fix this
3396
+ scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp
3397
+ );
2229
3398
  state.props = {
2230
3399
  alignItemsAtEnd,
2231
3400
  data: dataProp,
3401
+ enableAverages,
2232
3402
  estimatedItemSize,
2233
3403
  getEstimatedItemSize,
3404
+ getFixedItemSize,
3405
+ getItemType,
2234
3406
  horizontal: !!horizontal,
2235
3407
  initialContainerPoolRatio,
2236
3408
  initialScroll,
3409
+ itemsAreEqual,
2237
3410
  keyExtractor,
2238
3411
  maintainScrollAtEnd,
2239
3412
  maintainScrollAtEndThreshold,
@@ -2243,21 +3416,26 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2243
3416
  onEndReachedThreshold,
2244
3417
  onItemSizeChanged,
2245
3418
  onLoad,
2246
- onScroll: onScrollProp,
3419
+ onScroll: throttleScrollFn,
2247
3420
  onStartReached,
2248
3421
  onStartReachedThreshold,
2249
- renderItem: renderItem2,
3422
+ recycleItems: !!recycleItems,
3423
+ renderItem,
2250
3424
  scrollBuffer,
2251
3425
  snapToIndices,
3426
+ stickyIndicesArr: stickyIndices != null ? stickyIndices : [],
3427
+ stickyIndicesSet: useMemo(() => new Set(stickyIndices != null ? stickyIndices : []), [stickyIndices == null ? void 0 : stickyIndices.join(",")]),
2252
3428
  stylePaddingBottom: stylePaddingBottomState,
2253
3429
  stylePaddingTop: stylePaddingTopState,
2254
- suggestEstimatedItemSize: !!suggestEstimatedItemSize,
2255
- viewabilityConfigCallbackPairs: void 0
3430
+ suggestEstimatedItemSize: !!suggestEstimatedItemSize
2256
3431
  };
2257
3432
  state.refScroller = refScroller;
2258
3433
  const checkResetContainers = (isFirst2) => {
2259
3434
  const state2 = refState.current;
2260
3435
  if (state2) {
3436
+ if (!isFirst2 && state2.props.data !== dataProp) {
3437
+ updateAveragesOnDataChange(state2, state2.props.data, dataProp);
3438
+ }
2261
3439
  state2.props.data = dataProp;
2262
3440
  if (!isFirst2) {
2263
3441
  calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
@@ -2299,53 +3477,39 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2299
3477
  updateAllPositions(ctx, state);
2300
3478
  }
2301
3479
  const initialContentOffset = useMemo(() => {
2302
- const initialContentOffset2 = initialScrollOffset || calculateOffsetForIndex(ctx, state, initialScrollIndex);
2303
- refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
2304
- if (initialContentOffset2 > 0) {
2305
- scrollTo(state, { animated: false, index: initialScrollIndex, offset: initialContentOffset2 });
3480
+ if (initialScroll) {
3481
+ const { index, viewOffset } = initialScroll;
3482
+ let initialContentOffset2 = viewOffset || 0;
3483
+ if (index !== void 0) {
3484
+ initialContentOffset2 += calculateOffsetForIndex(ctx, state, index);
3485
+ }
3486
+ refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
3487
+ if (initialContentOffset2 > 0) {
3488
+ scrollTo(state, { animated: false, index, offset: initialContentOffset2 });
3489
+ }
3490
+ return initialContentOffset2;
2306
3491
  }
2307
- return initialContentOffset2;
3492
+ return 0;
2308
3493
  }, [renderNum]);
2309
3494
  if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
2310
- refState.current.lastBatchingAction = Date.now();
3495
+ state.lastBatchingAction = Date.now();
2311
3496
  if (!keyExtractorProp && !isFirst && didDataChange) {
2312
3497
  __DEV__ && warnDevOnce(
2313
3498
  "keyExtractor",
2314
3499
  "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."
2315
3500
  );
2316
- refState.current.sizes.clear();
2317
- refState.current.positions.clear();
3501
+ state.sizes.clear();
3502
+ state.positions.clear();
2318
3503
  }
2319
3504
  }
2320
- useLayoutEffect(() => {
2321
- if (IsNewArchitecture) {
2322
- let measured;
2323
- refScroller.current.measure((x, y, width, height) => {
2324
- measured = { height, width, x, y };
2325
- });
2326
- if (measured) {
2327
- const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
2328
- if (size) {
2329
- handleLayout(ctx, state, measured, setCanRender);
2330
- }
2331
- }
2332
- }
2333
- if (!isFirst) {
2334
- calculateItemsInView(ctx, state, { doMVCP: true });
2335
- }
2336
- }, [dataProp]);
2337
3505
  const onLayoutHeader = useCallback((rect, fromLayoutEffect) => {
2338
3506
  const size = rect[horizontal ? "width" : "height"];
2339
3507
  set$(ctx, "headerSize", size);
2340
- if (initialScroll) {
2341
- if (IsNewArchitecture && Platform.OS !== "android") {
3508
+ if ((initialScroll == null ? void 0 : initialScroll.index) !== void 0) {
3509
+ {
2342
3510
  if (fromLayoutEffect) {
2343
3511
  setRenderNum((v) => v + 1);
2344
3512
  }
2345
- } else {
2346
- setTimeout(() => {
2347
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
2348
- }, 17);
2349
3513
  }
2350
3514
  }
2351
3515
  }, []);
@@ -2355,7 +3519,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2355
3519
  }
2356
3520
  }, [snapToIndices]);
2357
3521
  useLayoutEffect(() => {
2358
- const didAllocateContainers = doInitialAllocateContainersCallback();
3522
+ const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainersCallback();
2359
3523
  if (!didAllocateContainers) {
2360
3524
  checkResetContainers(
2361
3525
  /*isFirst*/
@@ -2366,6 +3530,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2366
3530
  useLayoutEffect(() => {
2367
3531
  set$(ctx, "extraData", extraData);
2368
3532
  }, [extraData]);
3533
+ const { onLayout } = useSyncLayout({
3534
+ onLayout: onLayoutProp,
3535
+ onLayoutChange: useCallback(
3536
+ (rectangle) => {
3537
+ handleLayout(ctx, state, rectangle, setCanRender);
3538
+ },
3539
+ [ctx, state, setCanRender]
3540
+ ),
3541
+ ref: refScroller
3542
+ });
2369
3543
  useLayoutEffect(initializeStateVars, [
2370
3544
  memoizedLastItemKeys.join(","),
2371
3545
  numColumnsProp,
@@ -2375,28 +3549,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2375
3549
  const doInitialAllocateContainersCallback = () => {
2376
3550
  return doInitialAllocateContainers(ctx, state);
2377
3551
  };
2378
- useEffect(() => {
2379
- const viewability = setupViewability({
2380
- onViewableItemsChanged,
2381
- viewabilityConfig,
2382
- viewabilityConfigCallbackPairs
2383
- });
2384
- state.viewabilityConfigCallbackPairs = viewability;
2385
- state.props.viewabilityConfigCallbackPairs = viewability;
2386
- state.enableScrollForNextCalculateItemsInView = !viewability;
2387
- }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
2388
- if (!IsNewArchitecture) {
2389
- useInit(() => {
2390
- doInitialAllocateContainersCallback();
2391
- });
2392
- }
2393
- const onLayout = useCallback((event) => {
2394
- const layout = event.nativeEvent.layout;
2395
- handleLayout(ctx, state, layout, setCanRender);
2396
- if (onLayoutProp) {
2397
- onLayoutProp(event);
2398
- }
2399
- }, []);
2400
3552
  useImperativeHandle(forwardedRef, () => {
2401
3553
  const scrollIndexIntoView = (options) => {
2402
3554
  const state2 = refState.current;
@@ -2414,18 +3566,23 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2414
3566
  }
2415
3567
  };
2416
3568
  return {
2417
- flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
3569
+ flashScrollIndicators: () => {
3570
+ var _a, _b;
3571
+ return (_b = (_a = refScroller.current) == null ? void 0 : _a.flashScrollIndicators) == null ? void 0 : _b.call(_a);
3572
+ },
2418
3573
  getNativeScrollRef: () => refScroller.current,
2419
- getScrollableNode: () => refScroller.current.getScrollableNode(),
2420
- getScrollResponder: () => refScroller.current.getScrollResponder(),
3574
+ getScrollableNode: () => refScroller.current,
3575
+ getScrollResponder: () => refScroller.current,
2421
3576
  getState: () => {
2422
3577
  const state2 = refState.current;
2423
3578
  return state2 ? {
2424
3579
  contentLength: state2.totalSize,
3580
+ data: state2.props.data,
2425
3581
  end: state2.endNoBuffer,
2426
3582
  endBuffered: state2.endBuffered,
2427
3583
  isAtEnd: state2.isAtEnd,
2428
3584
  isAtStart: state2.isAtStart,
3585
+ positionAtIndex: (index) => state2.positions.get(getId(state2, index)),
2429
3586
  positions: state2.positions,
2430
3587
  scroll: state2.scroll,
2431
3588
  scrollLength: state2.scrollLength,
@@ -2452,7 +3609,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2452
3609
  const footerSize = peek$(ctx, "footerSize") || 0;
2453
3610
  scrollToIndex(ctx, state, {
2454
3611
  index,
2455
- viewOffset: -paddingBottom - footerSize,
3612
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
2456
3613
  viewPosition: 1,
2457
3614
  ...options
2458
3615
  });
@@ -2467,13 +3624,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2467
3624
  }
2468
3625
  },
2469
3626
  scrollToOffset: (params) => scrollTo(state, params),
3627
+ setScrollProcessingEnabled: (enabled) => {
3628
+ refState.current.scrollProcessingEnabled = enabled;
3629
+ },
2470
3630
  setVisibleContentAnchorOffset: (value) => {
2471
3631
  const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
2472
3632
  set$(ctx, "scrollAdjustUserOffset", val);
2473
3633
  }
2474
3634
  };
2475
3635
  }, []);
2476
- if (Platform.OS === "web") {
3636
+ {
2477
3637
  useEffect(() => {
2478
3638
  if (initialContentOffset) {
2479
3639
  scrollTo(state, { animated: false, offset: initialContentOffset });
@@ -2488,6 +3648,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2488
3648
  }),
2489
3649
  []
2490
3650
  );
3651
+ const onScrollHandler = useStickyScrollHandler(stickyIndices, horizontal, ctx, fns.onScroll);
2491
3652
  return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
2492
3653
  ListComponent,
2493
3654
  {
@@ -2504,14 +3665,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2504
3665
  onLayout,
2505
3666
  onLayoutHeader,
2506
3667
  onMomentumScrollEnd: (event) => {
2507
- requestAnimationFrame(() => {
2508
- finishScrollTo(refState.current);
2509
- });
3668
+ {
3669
+ requestAnimationFrame(() => {
3670
+ finishScrollTo(refState.current);
3671
+ });
3672
+ }
2510
3673
  if (onMomentumScrollEnd) {
2511
3674
  onMomentumScrollEnd(event);
2512
3675
  }
2513
3676
  },
2514
- onScroll: fns.onScroll,
3677
+ onScroll: onScrollHandler,
2515
3678
  recycleItems,
2516
3679
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControl, {
2517
3680
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
@@ -2524,27 +3687,38 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2524
3687
  }
2525
3688
  ),
2526
3689
  refScrollView: combinedRef,
2527
- scrollAdjustHandler: (_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler,
2528
- scrollEventThrottle: Platform.OS === "web" ? 16 : void 0,
3690
+ scrollAdjustHandler: state.scrollAdjustHandler,
2529
3691
  snapToIndices,
3692
+ stickyIndices,
2530
3693
  style,
2531
3694
  updateItemSize: fns.updateItemSize,
2532
3695
  waitForInitialLayout
2533
3696
  }
2534
3697
  ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3.createElement(DebugView, { state: refState.current }));
2535
3698
  });
3699
+ /*! Bundled license information:
2536
3700
 
2537
- // src/components/LazyLegendList.tsx
2538
- var typedForwardRef2 = forwardRef;
2539
- var renderItem = ({ item }) => item;
2540
- var LazyLegendList = typedForwardRef2(function LazyLegendList2(props, forwardedRef) {
2541
- const { LegendList: LegendListProp, children, ...rest } = props;
2542
- const LegendListComponent = LegendListProp != null ? LegendListProp : LegendList;
2543
- const data = (isArray(children) ? children : React3.Children.toArray(children)).flat(1);
2544
- return (
2545
- // @ts-expect-error TODO: Fix this type
2546
- /* @__PURE__ */ React3.createElement(LegendListComponent, { ...rest, data, ref: forwardedRef, renderItem })
2547
- );
2548
- });
3701
+ react-dom/cjs/react-dom.production.js:
3702
+ (**
3703
+ * @license React
3704
+ * react-dom.production.js
3705
+ *
3706
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3707
+ *
3708
+ * This source code is licensed under the MIT license found in the
3709
+ * LICENSE file in the root directory of this source tree.
3710
+ *)
3711
+
3712
+ react-dom/cjs/react-dom.development.js:
3713
+ (**
3714
+ * @license React
3715
+ * react-dom.development.js
3716
+ *
3717
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3718
+ *
3719
+ * This source code is licensed under the MIT license found in the
3720
+ * LICENSE file in the root directory of this source tree.
3721
+ *)
3722
+ */
2549
3723
 
2550
- export { LazyLegendList, LegendList, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useViewability, useViewabilityAmount };
3724
+ export { LegendList, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout2 as useSyncLayout, useViewability, useViewabilityAmount };