@legendapp/list 2.1.0-next.0 → 3.0.0-beta.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,459 +1,14 @@
1
1
  import * as React3 from 'react';
2
- import React3__default, { forwardRef, useReducer, useEffect, createContext, useRef, useState, useMemo, useImperativeHandle, useCallback, useLayoutEffect, memo, useContext } from 'react';
2
+ import React3__default, { forwardRef, useReducer, useEffect, createContext, useRef, useState, useMemo, useCallback, useImperativeHandle, useLayoutEffect, memo, useContext } from 'react';
3
3
  import { useSyncExternalStore } from 'use-sync-external-store/shim';
4
+ import { unstable_batchedUpdates } from 'react-dom';
4
5
 
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 });
6
+ // src/components/LegendList.tsx
7
+ forwardRef(function AnimatedView2(props, ref) {
8
+ return /* @__PURE__ */ React3.createElement("div", { ref, ...props });
454
9
  });
455
10
  var View = forwardRef(function View2(props, ref) {
456
- return /* @__PURE__ */ React.createElement("div", { ref, ...props });
11
+ return /* @__PURE__ */ React3.createElement("div", { ref, ...props });
457
12
  });
458
13
  var Text = View;
459
14
 
@@ -478,7 +33,10 @@ function StateProvider({ children }) {
478
33
  ["stylePaddingTop", 0],
479
34
  ["headerSize", 0],
480
35
  ["numContainers", 0],
481
- ["totalSize", 0]
36
+ ["activeStickyIndex", void 0],
37
+ ["totalSize", 0],
38
+ ["scrollAdjustPending", 0],
39
+ ["scrollingTo", void 0]
482
40
  ]),
483
41
  viewRefs: /* @__PURE__ */ new Map()
484
42
  }));
@@ -547,11 +105,12 @@ function set$(ctx, signalName, value) {
547
105
  }
548
106
  }
549
107
  function getContentSize(ctx) {
108
+ var _a3, _b;
550
109
  const { values } = ctx;
551
110
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
552
111
  const headerSize = values.get("headerSize") || 0;
553
112
  const footerSize = values.get("footerSize") || 0;
554
- const totalSize = values.get("totalSize");
113
+ const totalSize = (_b = (_a3 = ctx.internalState) == null ? void 0 : _a3.pendingTotalSize) != null ? _b : values.get("totalSize");
555
114
  return headerSize + footerSize + totalSize + stylePaddingTop;
556
115
  }
557
116
  function useArr$(signalNames) {
@@ -616,93 +175,63 @@ function useInterval(callback, delay) {
616
175
  return () => clearInterval(interval);
617
176
  }, [delay]);
618
177
  }
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
- }
659
-
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 {};
690
- }
691
178
 
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
- };
179
+ // src/utils/devEnvironment.ts
180
+ var metroDev = typeof __DEV__ !== "undefined" ? __DEV__ : void 0;
181
+ var _a;
182
+ var envMode = typeof process !== "undefined" && typeof process.env === "object" && process.env ? (_a = process.env.NODE_ENV) != null ? _a : process.env.MODE : void 0;
183
+ var processDev = typeof envMode === "string" ? envMode.toLowerCase() !== "production" : void 0;
184
+ var _a2;
185
+ var IS_DEV = (_a2 = metroDev != null ? metroDev : processDev) != null ? _a2 : false;
698
186
 
699
187
  // src/constants.ts
700
188
  var POSITION_OUT_OF_VIEW = -1e7;
701
- var ENABLE_DEVMODE = __DEV__ && false;
702
- var ENABLE_DEBUG_VIEW = __DEV__ && false;
189
+ var ENABLE_DEVMODE = IS_DEV && false;
190
+ var ENABLE_DEBUG_VIEW = IS_DEV && false;
703
191
  var typedForwardRef = forwardRef;
704
192
  var typedMemo = memo;
705
193
 
194
+ // src/utils/helpers.ts
195
+ function isFunction(obj) {
196
+ return typeof obj === "function";
197
+ }
198
+ function isArray(obj) {
199
+ return Array.isArray(obj);
200
+ }
201
+ var warned = /* @__PURE__ */ new Set();
202
+ function warnDevOnce(id, text) {
203
+ if (IS_DEV && !warned.has(id)) {
204
+ warned.add(id);
205
+ console.warn(`[legend-list] ${text}`);
206
+ }
207
+ }
208
+ function roundSize(size) {
209
+ return Math.floor(size * 8) / 8;
210
+ }
211
+ function isNullOrUndefined(value) {
212
+ return value === null || value === void 0;
213
+ }
214
+ function comparatorDefault(a, b) {
215
+ return a - b;
216
+ }
217
+ function getPadding(s, type) {
218
+ var _a3, _b, _c;
219
+ return (_c = (_b = (_a3 = s[`padding${type}`]) != null ? _a3 : s.paddingVertical) != null ? _b : s.padding) != null ? _c : 0;
220
+ }
221
+ function extractPadding(style, contentContainerStyle, type) {
222
+ return getPadding(style, type) + getPadding(contentContainerStyle, type);
223
+ }
224
+ function findContainerId(ctx, key) {
225
+ const numContainers = peek$(ctx, "numContainers");
226
+ for (let i = 0; i < numContainers; i++) {
227
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
228
+ if (itemKey === key) {
229
+ return i;
230
+ }
231
+ }
232
+ return -1;
233
+ }
234
+
706
235
  // src/components/PositionView.tsx
707
236
  var PositionViewState = typedMemo(function PositionView({
708
237
  id,
@@ -712,9 +241,12 @@ var PositionViewState = typedMemo(function PositionView({
712
241
  ...rest
713
242
  }) {
714
243
  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 });
244
+ const base = {
245
+ contain: "paint layout style"
246
+ };
247
+ const composed = isArray(style) ? Object.assign({}, ...style) : style;
248
+ const combinedStyle = horizontal ? { ...base, ...composed, left: position } : { ...base, ...composed, top: position };
249
+ return /* @__PURE__ */ React3.createElement("div", { ref: refView, style: combinedStyle, ...rest });
718
250
  });
719
251
  var PositionViewSticky = typedMemo(function PositionViewSticky2({
720
252
  id,
@@ -722,35 +254,47 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
722
254
  style,
723
255
  refView,
724
256
  index,
257
+ stickyOffset,
258
+ animatedScrollY: _animatedScrollY,
259
+ children,
725
260
  ...rest
726
261
  }) {
727
- const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
262
+ const [position = POSITION_OUT_OF_VIEW, headerSize = 0, activeStickyIndex] = useArr$([
263
+ `containerPosition${id}`,
264
+ "headerSize",
265
+ "activeStickyIndex"
266
+ ]);
267
+ const base = {
268
+ contain: "paint layout style"
269
+ };
270
+ const composed = React3.useMemo(
271
+ () => {
272
+ var _a3;
273
+ return (_a3 = isArray(style) ? Object.assign({}, ...style) : style) != null ? _a3 : {};
274
+ },
275
+ [style]
276
+ );
728
277
  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 });
278
+ var _a3;
279
+ const styleBase = { ...base, ...composed };
280
+ delete styleBase.transform;
281
+ const offset = (_a3 = stickyOffset != null ? stickyOffset : headerSize) != null ? _a3 : 0;
282
+ const isActive = activeStickyIndex === index;
283
+ styleBase.position = isActive ? "sticky" : "absolute";
284
+ styleBase.zIndex = index + 1e3;
285
+ if (horizontal) {
286
+ styleBase.left = isActive ? offset : position;
287
+ } else {
288
+ styleBase.top = isActive ? offset : position;
289
+ }
290
+ return styleBase;
291
+ }, [composed, horizontal, position, index, stickyOffset, headerSize, activeStickyIndex]);
292
+ return /* @__PURE__ */ React3.createElement("div", { ref: refView, style: viewStyle, ...rest }, children);
738
293
  });
739
294
  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
295
 
746
296
  // src/constants-platform.ts
747
297
  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
- };
754
298
  var symbolFirst = Symbol();
755
299
  function useInit(cb) {
756
300
  const refValue = useRef(symbolFirst);
@@ -760,37 +304,6 @@ function useInit(cb) {
760
304
  return refValue.current;
761
305
  }
762
306
 
763
- // src/utils/helpers.ts
764
- function isFunction(obj) {
765
- return typeof obj === "function";
766
- }
767
- function isArray(obj) {
768
- return Array.isArray(obj);
769
- }
770
- var warned = /* @__PURE__ */ new Set();
771
- function warnDevOnce(id, text) {
772
- if (__DEV__ && !warned.has(id)) {
773
- warned.add(id);
774
- console.warn(`[legend-list] ${text}`);
775
- }
776
- }
777
- function roundSize(size) {
778
- return Math.floor(size * 8) / 8;
779
- }
780
- function isNullOrUndefined(value) {
781
- return value === null || value === void 0;
782
- }
783
- function comparatorDefault(a, b) {
784
- return a - b;
785
- }
786
- function getPadding(s, type) {
787
- var _a, _b, _c;
788
- return (_c = (_b = (_a = s[`padding${type}`]) != null ? _a : s.paddingVertical) != null ? _b : s.padding) != null ? _c : 0;
789
- }
790
- function extractPadding(style, contentContainerStyle, type) {
791
- return getPadding(style, type) + getPadding(contentContainerStyle, type);
792
- }
793
-
794
307
  // src/state/ContextContainer.ts
795
308
  var ContextContainer = createContext(null);
796
309
  function useViewability(callback, configId) {
@@ -887,57 +400,163 @@ function useListScrollSize() {
887
400
  const [scrollSize] = useArr$(["scrollSize"]);
888
401
  return scrollSize;
889
402
  }
890
- function useSyncLayout2() {
403
+ function useSyncLayout() {
891
404
  {
892
405
  const { triggerLayout: syncLayout } = useContext(ContextContainer);
893
406
  return syncLayout;
894
407
  }
895
408
  }
896
409
 
897
- // src/components/Container.tsx
898
- var Container = typedMemo(function Container2({
899
- id,
900
- recycleItems,
901
- horizontal,
902
- getRenderedItem: getRenderedItem2,
903
- updateItemSize: updateItemSize2,
904
- ItemSeparatorComponent
905
- }) {
906
- const ctx = useStateContext();
907
- const { columnWrapperStyle } = ctx;
908
- const [column = 0, data, itemKey, numColumns, extraData, isSticky] = useArr$([
909
- `containerColumn${id}`,
910
- `containerItemData${id}`,
911
- `containerItemKey${id}`,
912
- "numColumns",
913
- "extraData",
914
- `containerSticky${id}`
915
- ]);
916
- const refLastSize = useRef();
917
- const ref = useRef(null);
918
- const [_, forceLayoutRender] = useState(0);
919
- const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
920
- const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
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
- };
410
+ // src/components/Separator.tsx
411
+ function Separator({ ItemSeparatorComponent, leadingItem }) {
412
+ const isLastItem = useIsLastItem();
413
+ return isLastItem ? null : /* @__PURE__ */ React3.createElement(ItemSeparatorComponent, { leadingItem });
414
+ }
415
+
416
+ // src/hooks/createResizeObserver.ts
417
+ var globalResizeObserver = null;
418
+ function getGlobalResizeObserver() {
419
+ if (!globalResizeObserver) {
420
+ globalResizeObserver = new ResizeObserver((entries) => {
421
+ for (const entry of entries) {
422
+ const callbacks = callbackMap.get(entry.target);
423
+ if (callbacks) {
424
+ for (const callback of callbacks) {
425
+ callback(entry);
426
+ }
427
+ }
939
428
  }
940
- }
429
+ });
430
+ }
431
+ return globalResizeObserver;
432
+ }
433
+ var callbackMap = /* @__PURE__ */ new WeakMap();
434
+ function createResizeObserver(element, callback) {
435
+ if (typeof ResizeObserver === "undefined") {
436
+ return () => {
437
+ };
438
+ }
439
+ if (!element) {
440
+ return () => {
441
+ };
442
+ }
443
+ const observer = getGlobalResizeObserver();
444
+ let callbacks = callbackMap.get(element);
445
+ if (!callbacks) {
446
+ callbacks = /* @__PURE__ */ new Set();
447
+ callbackMap.set(element, callbacks);
448
+ observer.observe(element);
449
+ }
450
+ callbacks.add(callback);
451
+ return () => {
452
+ const callbacks2 = callbackMap.get(element);
453
+ if (callbacks2) {
454
+ callbacks2.delete(callback);
455
+ if (callbacks2.size === 0) {
456
+ callbackMap.delete(element);
457
+ observer.unobserve(element);
458
+ }
459
+ }
460
+ };
461
+ }
462
+
463
+ // src/hooks/useOnLayoutSync.tsx
464
+ function useOnLayoutSync({
465
+ ref,
466
+ onLayoutProp,
467
+ onLayoutChange
468
+ }, deps) {
469
+ useLayoutEffect(() => {
470
+ var _a3, _b;
471
+ const current = ref.current;
472
+ const scrollableNode = (_b = (_a3 = current == null ? void 0 : current.getScrollableNode) == null ? void 0 : _a3.call(current)) != null ? _b : null;
473
+ const element = scrollableNode || current;
474
+ if (!element) {
475
+ return;
476
+ }
477
+ const emit = (layout, fromLayoutEffect) => {
478
+ if (layout.height === 0 && layout.width === 0) {
479
+ return;
480
+ }
481
+ onLayoutChange(layout, fromLayoutEffect);
482
+ onLayoutProp == null ? void 0 : onLayoutProp({ nativeEvent: { layout } });
483
+ };
484
+ const rect = element.getBoundingClientRect();
485
+ emit(toLayout(rect), true);
486
+ let prevRect = rect;
487
+ return createResizeObserver(element, (entry) => {
488
+ var _a4;
489
+ const target = entry.target instanceof HTMLElement ? entry.target : void 0;
490
+ const rect2 = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
491
+ if (rect2.width !== prevRect.width || rect2.height !== prevRect.height) {
492
+ prevRect = rect2;
493
+ emit(toLayout(rect2), false);
494
+ }
495
+ });
496
+ }, deps || []);
497
+ return {};
498
+ }
499
+ function toLayout(rect) {
500
+ if (!rect) {
501
+ return { height: 0, width: 0, x: 0, y: 0 };
502
+ }
503
+ return {
504
+ height: rect.height,
505
+ width: rect.width,
506
+ x: rect.left,
507
+ y: rect.top
508
+ };
509
+ }
510
+
511
+ // src/components/Container.tsx
512
+ var Container = typedMemo(function Container2({
513
+ id,
514
+ recycleItems,
515
+ horizontal,
516
+ getRenderedItem: getRenderedItem2,
517
+ updateItemSize: updateItemSize2,
518
+ ItemSeparatorComponent
519
+ }) {
520
+ const ctx = useStateContext();
521
+ const { columnWrapperStyle, animatedScrollY } = ctx;
522
+ const [column = 0, data, itemKey, numColumns, extraData, isSticky, stickyOffset] = useArr$([
523
+ `containerColumn${id}`,
524
+ `containerItemData${id}`,
525
+ `containerItemKey${id}`,
526
+ "numColumns",
527
+ "extraData",
528
+ `containerSticky${id}`,
529
+ `containerStickyOffset${id}`
530
+ ]);
531
+ const itemLayoutRef = useRef({
532
+ horizontal,
533
+ itemKey,
534
+ updateItemSize: updateItemSize2
535
+ });
536
+ itemLayoutRef.current.horizontal = horizontal;
537
+ itemLayoutRef.current.itemKey = itemKey;
538
+ itemLayoutRef.current.updateItemSize = updateItemSize2;
539
+ const ref = useRef(null);
540
+ const [layoutRenderCount, forceLayoutRender] = useState(0);
541
+ const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
542
+ const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
543
+ const didLayoutRef = useRef(false);
544
+ const style = useMemo(() => {
545
+ let paddingStyles;
546
+ if (columnWrapperStyle) {
547
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
548
+ if (horizontal) {
549
+ paddingStyles = {
550
+ paddingRight: columnGap || gap || void 0,
551
+ paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
552
+ };
553
+ } else {
554
+ paddingStyles = {
555
+ paddingBottom: rowGap || gap || void 0,
556
+ paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
557
+ };
558
+ }
559
+ }
941
560
  return horizontal ? {
942
561
  flexDirection: ItemSeparatorComponent ? "row" : void 0,
943
562
  height: otherAxisSize,
@@ -948,7 +567,7 @@ var Container = typedMemo(function Container2({
948
567
  } : {
949
568
  left: otherAxisPos,
950
569
  position: "absolute",
951
- right: numColumns > 1 ? void 0 : 0,
570
+ right: numColumns > 1 ? null : 0,
952
571
  top: 0,
953
572
  width: otherAxisSize,
954
573
  ...paddingStyles || {}
@@ -971,49 +590,64 @@ var Container = typedMemo(function Container2({
971
590
  value: data
972
591
  };
973
592
  }, [id, itemKey, index, data]);
974
- const onLayoutChange = (rectangle) => {
975
- if (!isNullOrUndefined(itemKey)) {
976
- let layout = rectangle;
977
- layout[horizontal ? "width" : "height"];
978
- const doUpdate = () => {
979
- refLastSize.current = { height: layout.height, width: layout.width };
980
- updateItemSize2(itemKey, layout);
981
- };
982
- {
983
- doUpdate();
984
- }
593
+ const onLayoutChange = useCallback((rectangle) => {
594
+ const {
595
+ horizontal: currentHorizontal,
596
+ itemKey: currentItemKey,
597
+ updateItemSize: updateItemSizeFn
598
+ } = itemLayoutRef.current;
599
+ if (isNullOrUndefined(currentItemKey)) {
600
+ return;
985
601
  }
986
- };
602
+ didLayoutRef.current = true;
603
+ let layout = rectangle;
604
+ roundSize(rectangle[currentHorizontal ? "width" : "height"]);
605
+ const doUpdate = () => {
606
+ itemLayoutRef.current.lastSize = { height: layout.height, width: layout.width };
607
+ updateItemSizeFn(currentItemKey, layout);
608
+ didLayoutRef.current = true;
609
+ };
610
+ {
611
+ doUpdate();
612
+ }
613
+ }, []);
614
+ const { onLayout } = useOnLayoutSync(
615
+ {
616
+ onLayoutChange,
617
+ ref
618
+ },
619
+ [itemKey, layoutRenderCount]
620
+ );
987
621
  const PositionComponent = isSticky ? PositionViewSticky : PositionView2;
988
- return /* @__PURE__ */ React.createElement(ContextContainer.Provider, { value: contextValue }, /* @__PURE__ */ React.createElement(
622
+ return /* @__PURE__ */ React3.createElement(
989
623
  PositionComponent,
990
624
  {
625
+ animatedScrollY: isSticky ? animatedScrollY : void 0,
991
626
  horizontal,
992
627
  id,
993
628
  index,
994
629
  key: recycleItems ? void 0 : itemKey,
995
- onLayoutChange,
630
+ onLayout,
996
631
  refView: ref,
632
+ stickyOffset: isSticky ? stickyOffset : void 0,
997
633
  style
998
634
  },
999
- renderedItem,
1000
- renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React.createElement(
1001
- Separator,
1002
- {
1003
- ItemSeparatorComponent,
1004
- itemKey,
1005
- leadingItem: renderedItemInfo.item
1006
- }
1007
- )
1008
- ));
635
+ /* @__PURE__ */ React3.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3.createElement(Separator, { ItemSeparatorComponent, leadingItem: renderedItemInfo.item }))
636
+ );
1009
637
  });
1010
638
 
639
+ // src/platform/Platform.ts
640
+ var Platform = {
641
+ // Widen the type to avoid unreachable-branch lints in cross-platform code that compares against other OSes
642
+ OS: "web"
643
+ };
644
+
1011
645
  // src/utils/reordering.ts
1012
646
  var mapFn = (element) => {
1013
647
  const indexStr = element.getAttribute("index");
1014
648
  return [element, indexStr === null ? null : parseInt(indexStr)];
1015
649
  };
1016
- function sortDOMElementsPatience(container) {
650
+ function sortDOMElements(container) {
1017
651
  const elements = Array.from(container.children);
1018
652
  if (elements.length <= 1) return elements;
1019
653
  const items = elements.map(mapFn);
@@ -1104,7 +738,7 @@ function useDOMOrder(ref) {
1104
738
  debounceRef.current = setTimeout(() => {
1105
739
  const parent = ref.current;
1106
740
  if (parent) {
1107
- sortDOMElementsPatience(parent);
741
+ sortDOMElements(parent);
1108
742
  }
1109
743
  debounceRef.current = void 0;
1110
744
  }, 500);
@@ -1125,7 +759,7 @@ var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColum
1125
759
  const columnWrapperStyle = ctx.columnWrapperStyle;
1126
760
  const [totalSize, otherAxisSize] = useArr$(["totalSize", "otherAxisSize"]);
1127
761
  useDOMOrder(ref);
1128
- const style = horizontal ? { minHeight: otherAxisSize, width: totalSize } : { height: totalSize, minWidth: otherAxisSize };
762
+ const style = horizontal ? { minHeight: otherAxisSize, position: "relative", width: totalSize } : { height: totalSize, minWidth: otherAxisSize, position: "relative" };
1129
763
  if (columnWrapperStyle && numColumns > 1) {
1130
764
  const { columnGap, rowGap, gap } = columnWrapperStyle;
1131
765
  const gapX = columnGap || gap || 0;
@@ -1176,22 +810,38 @@ var Containers = typedMemo(function Containers2({
1176
810
  }
1177
811
  return /* @__PURE__ */ React3.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
1178
812
  });
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%"
1190
- }
1191
- },
1192
- /* @__PURE__ */ React3.createElement(Text, { style: { color: "red" } }, index * 100)
1193
- ));
1194
- });
813
+ function DevNumbers() {
814
+ return IS_DEV && React3.memo(function DevNumbers2() {
815
+ return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3.createElement(
816
+ "div",
817
+ {
818
+ key: index,
819
+ style: {
820
+ height: 100,
821
+ pointerEvents: "none",
822
+ position: "absolute",
823
+ top: index * 100,
824
+ width: "100%"
825
+ }
826
+ },
827
+ /* @__PURE__ */ React3.createElement("div", { style: { color: "red" } }, index * 100)
828
+ ));
829
+ });
830
+ }
831
+
832
+ // src/platform/StyleSheet.tsx
833
+ function flattenStyles(styles) {
834
+ if (isArray(styles)) {
835
+ return Object.assign({}, ...styles.filter(Boolean));
836
+ }
837
+ return styles;
838
+ }
839
+ var StyleSheet = {
840
+ create: (styles) => styles,
841
+ flatten: (style) => flattenStyles(style)
842
+ };
843
+
844
+ // src/components/ListComponentScrollView.tsx
1195
845
  var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
1196
846
  children,
1197
847
  style,
@@ -1205,7 +855,6 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
1205
855
  showsVerticalScrollIndicator = true,
1206
856
  refreshControl,
1207
857
  onLayout,
1208
- ScrollComponent,
1209
858
  ...props
1210
859
  }, ref) {
1211
860
  const scrollRef = useRef(null);
@@ -1214,16 +863,15 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
1214
863
  useImperativeHandle(ref, () => {
1215
864
  const api = {
1216
865
  getBoundingClientRect: () => {
1217
- var _a;
1218
- return (_a = scrollRef.current) == null ? void 0 : _a.getBoundingClientRect();
866
+ var _a3;
867
+ return (_a3 = scrollRef.current) == null ? void 0 : _a3.getBoundingClientRect();
1219
868
  },
1220
869
  getScrollableNode: () => scrollRef.current,
1221
870
  getScrollResponder: () => scrollRef.current,
1222
- scrollBy: (options) => {
871
+ scrollBy: (x, y) => {
1223
872
  const el = scrollRef.current;
1224
873
  if (!el) return;
1225
- const { x = 0, y = 0, animated = true } = options;
1226
- el.scrollBy({ behavior: animated ? "smooth" : "auto", left: x, top: y });
874
+ el.scrollBy(x, y);
1227
875
  },
1228
876
  scrollTo: (options) => {
1229
877
  const el = scrollRef.current;
@@ -1293,17 +941,21 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
1293
941
  useLayoutEffect(() => {
1294
942
  const element = scrollRef.current;
1295
943
  if (!element) return;
1296
- element.addEventListener("scroll", handleScroll, { passive: true });
944
+ element.addEventListener("scroll", handleScroll);
1297
945
  return () => {
1298
946
  element.removeEventListener("scroll", handleScroll);
1299
947
  };
1300
948
  }, [handleScroll]);
1301
- useLayoutEffect(() => {
1302
- if (contentOffset && scrollRef.current) {
1303
- scrollRef.current.scrollLeft = contentOffset.x || 0;
1304
- scrollRef.current.scrollTop = contentOffset.y || 0;
1305
- }
1306
- }, [contentOffset]);
949
+ useEffect(() => {
950
+ const doScroll = () => {
951
+ if (contentOffset && scrollRef.current) {
952
+ scrollRef.current.scrollLeft = contentOffset.x || 0;
953
+ scrollRef.current.scrollTop = contentOffset.y || 0;
954
+ }
955
+ };
956
+ doScroll();
957
+ requestAnimationFrame(doScroll);
958
+ }, [contentOffset == null ? void 0 : contentOffset.x, contentOffset == null ? void 0 : contentOffset.y]);
1307
959
  useLayoutEffect(() => {
1308
960
  if (!onLayout || !scrollRef.current) return;
1309
961
  const element = scrollRef.current;
@@ -1335,24 +987,45 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
1335
987
  // Ensure proper positioning context
1336
988
  WebkitOverflowScrolling: "touch",
1337
989
  // iOS momentum scrolling
1338
- ...style
990
+ ...StyleSheet.flatten(style)
1339
991
  };
1340
992
  const contentStyle = {
1341
993
  display: horizontal ? "flex" : "block",
1342
994
  flexDirection: horizontal ? "row" : void 0,
1343
995
  minHeight: horizontal ? void 0 : "100%",
1344
996
  minWidth: horizontal ? "100%" : void 0,
1345
- ...contentContainerStyle
997
+ ...StyleSheet.flatten(contentContainerStyle)
1346
998
  };
1347
- return /* @__PURE__ */ React.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React.createElement("div", { ref: contentRef, style: contentStyle }, children));
999
+ return /* @__PURE__ */ React3.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React3.createElement("div", { ref: contentRef, style: contentStyle }, children));
1348
1000
  });
1001
+ function Padding() {
1002
+ const [paddingTop] = useArr$(["alignItemsPaddingTop"]);
1003
+ return /* @__PURE__ */ React3.createElement("div", { style: { paddingTop } });
1004
+ }
1005
+ function PaddingDevMode() {
1006
+ const [paddingTop] = useArr$(["alignItemsPaddingTop"]);
1007
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("div", { style: { paddingTop } }), /* @__PURE__ */ React3.createElement(
1008
+ "div",
1009
+ {
1010
+ style: {
1011
+ backgroundColor: "green",
1012
+ height: paddingTop,
1013
+ left: 0,
1014
+ position: "absolute",
1015
+ right: 0,
1016
+ top: 0
1017
+ }
1018
+ }
1019
+ ));
1020
+ }
1349
1021
  function useValueListener$(key, callback) {
1350
1022
  const ctx = useStateContext();
1351
1023
  useLayoutEffect(() => {
1352
- listen$(ctx, key, (value) => {
1024
+ const unsubscribe = listen$(ctx, key, (value) => {
1353
1025
  callback(value);
1354
1026
  });
1355
- }, []);
1027
+ return unsubscribe;
1028
+ }, [callback, ctx, key]);
1356
1029
  }
1357
1030
 
1358
1031
  // src/components/ScrollAdjust.tsx
@@ -1360,16 +1033,34 @@ function ScrollAdjust() {
1360
1033
  const ctx = useStateContext();
1361
1034
  const lastScrollOffsetRef = React3.useRef(0);
1362
1035
  const callback = React3.useCallback(() => {
1363
- var _a;
1036
+ var _a3;
1364
1037
  const scrollAdjust = peek$(ctx, "scrollAdjust");
1365
1038
  const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
1366
1039
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
1367
- const scrollView = (_a = ctx.internalState) == null ? void 0 : _a.refScroller.current;
1040
+ const scrollView = (_a3 = ctx.internalState) == null ? void 0 : _a3.refScroller.current;
1368
1041
  if (scrollView && scrollOffset !== lastScrollOffsetRef.current) {
1369
1042
  const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
1370
1043
  if (scrollDelta !== 0) {
1371
- scrollView.scrollBy(0, scrollDelta);
1372
- console.log("ScrollAdjust (web scrollBy)", scrollDelta, "total offset:", scrollOffset);
1044
+ const el = scrollView.getScrollableNode();
1045
+ const prevScroll = el.scrollTop;
1046
+ const nextScroll = prevScroll + scrollDelta;
1047
+ const totalSize = el.scrollHeight;
1048
+ if (scrollDelta > 0 && !ctx.internalState.adjustingFromInitialMount && totalSize < nextScroll + el.clientHeight) {
1049
+ const child = el.firstElementChild;
1050
+ const prevPaddingBottom = child.style.paddingBottom;
1051
+ const pad = (nextScroll + el.clientHeight - totalSize) * 2;
1052
+ child.style.paddingBottom = `${pad}px`;
1053
+ void el.offsetHeight;
1054
+ scrollView.scrollBy(0, scrollDelta);
1055
+ setTimeout(() => {
1056
+ child.style.paddingBottom = prevPaddingBottom;
1057
+ }, 100);
1058
+ } else {
1059
+ scrollView.scrollBy(0, scrollDelta);
1060
+ }
1061
+ if (IS_DEV) {
1062
+ console.log("ScrollAdjust (web scrollBy)", scrollDelta, "total offset:", scrollOffset);
1063
+ }
1373
1064
  }
1374
1065
  lastScrollOffsetRef.current = scrollOffset;
1375
1066
  }
@@ -1378,18 +1069,15 @@ function ScrollAdjust() {
1378
1069
  useValueListener$("scrollAdjustUserOffset", callback);
1379
1070
  return null;
1380
1071
  }
1381
-
1382
- // src/components/SnapWrapper.tsx
1383
1072
  function SnapWrapper({ ScrollComponent, ...props }) {
1384
1073
  const [snapToOffsets] = useArr$(["snapToOffsets"]);
1385
- return /* @__PURE__ */ React.createElement(ScrollComponent, { ...props, snapToOffsets });
1386
- }
1387
-
1388
- // src/hooks/useValue$.ts
1389
- function useValue$(key, params) {
1390
- const [value] = useArr$([key]);
1391
- return value;
1074
+ return /* @__PURE__ */ React3.createElement(ScrollComponent, { ...props, snapToOffsets });
1392
1075
  }
1076
+ var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
1077
+ const ref = refView != null ? refView : useRef();
1078
+ useOnLayoutSync({ onLayoutChange, ref });
1079
+ return /* @__PURE__ */ React3.createElement("div", { ...rest, ref }, children);
1080
+ };
1393
1081
 
1394
1082
  // src/components/ListComponent.tsx
1395
1083
  var getComponent = (Component) => {
@@ -1401,26 +1089,6 @@ var getComponent = (Component) => {
1401
1089
  }
1402
1090
  return null;
1403
1091
  };
1404
- var Padding = () => {
1405
- const animPaddingTop = useValue$("alignItemsPaddingTop");
1406
- return /* @__PURE__ */ React3.createElement(AnimatedView, { style: { paddingTop: animPaddingTop } });
1407
- };
1408
- var PaddingDevMode = () => {
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,
1412
- {
1413
- style: {
1414
- backgroundColor: "green",
1415
- height: animPaddingTop,
1416
- left: 0,
1417
- position: "absolute",
1418
- right: 0,
1419
- top: 0
1420
- }
1421
- }
1422
- ));
1423
- };
1424
1092
  var ListComponent = typedMemo(function ListComponent2({
1425
1093
  canRender,
1426
1094
  style,
@@ -1446,11 +1114,10 @@ var ListComponent = typedMemo(function ListComponent2({
1446
1114
  scrollAdjustHandler,
1447
1115
  onLayoutHeader,
1448
1116
  snapToIndices,
1449
- stickyIndices,
1117
+ stickyHeaderIndices,
1450
1118
  ...rest
1451
1119
  }) {
1452
1120
  const ctx = useStateContext();
1453
- const refHeader = React3.useRef(null);
1454
1121
  const ScrollComponent = renderScrollComponent ? useMemo(
1455
1122
  () => React3.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
1456
1123
  [renderScrollComponent]
@@ -1463,39 +1130,30 @@ var ListComponent = typedMemo(function ListComponent2({
1463
1130
  }
1464
1131
  }, [canRender]);
1465
1132
  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]);
1472
1133
  return /* @__PURE__ */ React3.createElement(
1473
1134
  SnapOrScroll,
1474
1135
  {
1475
1136
  ...rest,
1476
- contentContainerStyle: contentContainerStyleWeb,
1137
+ contentContainerStyle: [
1138
+ contentContainerStyle,
1139
+ horizontal ? {
1140
+ height: "100%"
1141
+ } : {}
1142
+ ],
1477
1143
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
1478
1144
  horizontal,
1479
- maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
1145
+ maintainVisibleContentPosition: maintainVisibleContentPosition ? { minIndexForVisible: 0 } : void 0,
1480
1146
  onLayout,
1481
1147
  onScroll: onScroll2,
1482
1148
  ref: refScrollView,
1483
1149
  ScrollComponent: snapToIndices ? ScrollComponent : void 0,
1484
1150
  style
1485
1151
  },
1486
- maintainVisibleContentPosition && /* @__PURE__ */ React3.createElement(ScrollAdjust, null),
1152
+ /* @__PURE__ */ React3.createElement(ScrollAdjust, null),
1487
1153
  ENABLE_DEVMODE ? /* @__PURE__ */ React3.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3.createElement(Padding, null),
1488
- ListHeaderComponent && /* @__PURE__ */ React3.createElement(
1489
- LayoutView,
1490
- {
1491
- onLayoutChange: onLayoutHeader,
1492
- refView: refHeader,
1493
- style: ListHeaderComponentStyle
1494
- },
1495
- getComponent(ListHeaderComponent)
1496
- ),
1154
+ ListHeaderComponent && /* @__PURE__ */ React3.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1497
1155
  ListEmptyComponent && getComponent(ListEmptyComponent),
1498
- canRender && /* @__PURE__ */ React3.createElement(
1156
+ canRender && !ListEmptyComponent && /* @__PURE__ */ React3.createElement(
1499
1157
  Containers,
1500
1158
  {
1501
1159
  getRenderedItem: getRenderedItem2,
@@ -1517,7 +1175,7 @@ var ListComponent = typedMemo(function ListComponent2({
1517
1175
  },
1518
1176
  getComponent(ListFooterComponent)
1519
1177
  ),
1520
- __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React3.createElement(DevNumbers, null)
1178
+ IS_DEV && ENABLE_DEVMODE && /* @__PURE__ */ React3.createElement(DevNumbers, null)
1521
1179
  );
1522
1180
  });
1523
1181
 
@@ -1529,7 +1187,7 @@ function getId(state, index) {
1529
1187
  }
1530
1188
  const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
1531
1189
  const id = ret;
1532
- state.idCache.set(index, id);
1190
+ state.idCache[index] = id;
1533
1191
  return id;
1534
1192
  }
1535
1193
 
@@ -1550,13 +1208,84 @@ function calculateOffsetForIndex(ctx, state, index) {
1550
1208
  return position;
1551
1209
  }
1552
1210
 
1211
+ // src/utils/setPaddingTop.ts
1212
+ function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1213
+ if (stylePaddingTop !== void 0) {
1214
+ const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1215
+ if (stylePaddingTop < prevStylePaddingTop) {
1216
+ let prevTotalSize = peek$(ctx, "totalSize") || 0;
1217
+ set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
1218
+ state.timeoutSetPaddingTop = setTimeout(() => {
1219
+ prevTotalSize = peek$(ctx, "totalSize") || 0;
1220
+ set$(ctx, "totalSize", prevTotalSize - prevStylePaddingTop);
1221
+ }, 16);
1222
+ }
1223
+ set$(ctx, "stylePaddingTop", stylePaddingTop);
1224
+ }
1225
+ if (alignItemsPaddingTop !== void 0) {
1226
+ set$(ctx, "alignItemsPaddingTop", alignItemsPaddingTop);
1227
+ }
1228
+ }
1229
+
1230
+ // src/utils/updateAlignItemsPaddingTop.ts
1231
+ function updateAlignItemsPaddingTop(ctx, state) {
1232
+ const {
1233
+ scrollLength,
1234
+ props: { alignItemsAtEnd, data }
1235
+ } = state;
1236
+ if (alignItemsAtEnd) {
1237
+ let alignItemsPaddingTop = 0;
1238
+ if ((data == null ? void 0 : data.length) > 0) {
1239
+ const contentSize = getContentSize(ctx);
1240
+ alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1241
+ }
1242
+ setPaddingTop(ctx, state, { alignItemsPaddingTop });
1243
+ }
1244
+ }
1245
+
1246
+ // src/core/addTotalSize.ts
1247
+ function addTotalSize(ctx, state, key, add) {
1248
+ const { alignItemsAtEnd } = state.props;
1249
+ const prevTotalSize = state.totalSize;
1250
+ let totalSize = state.totalSize;
1251
+ if (key === null) {
1252
+ totalSize = add;
1253
+ if (state.timeoutSetPaddingTop) {
1254
+ clearTimeout(state.timeoutSetPaddingTop);
1255
+ state.timeoutSetPaddingTop = void 0;
1256
+ }
1257
+ } else {
1258
+ totalSize += add;
1259
+ }
1260
+ if (prevTotalSize !== totalSize) {
1261
+ {
1262
+ state.pendingTotalSize = void 0;
1263
+ state.totalSize = totalSize;
1264
+ set$(ctx, "totalSize", totalSize);
1265
+ if (alignItemsAtEnd) {
1266
+ updateAlignItemsPaddingTop(ctx, state);
1267
+ }
1268
+ }
1269
+ }
1270
+ }
1271
+
1272
+ // src/core/setSize.ts
1273
+ function setSize(ctx, state, itemKey, size) {
1274
+ const { sizes } = state;
1275
+ const previousSize = sizes.get(itemKey);
1276
+ const diff = previousSize !== void 0 ? size - previousSize : size;
1277
+ if (diff !== 0) {
1278
+ addTotalSize(ctx, state, itemKey, diff);
1279
+ }
1280
+ sizes.set(itemKey, size);
1281
+ }
1282
+
1553
1283
  // src/utils/getItemSize.ts
1554
- function getItemSize(state, key, index, data, useAverageSize) {
1555
- var _a, _b;
1284
+ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedSize) {
1285
+ var _a3, _b;
1556
1286
  const {
1557
1287
  sizesKnown,
1558
1288
  sizes,
1559
- scrollingTo,
1560
1289
  averageSizes,
1561
1290
  props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
1562
1291
  } = state;
@@ -1565,7 +1294,14 @@ function getItemSize(state, key, index, data, useAverageSize) {
1565
1294
  return sizeKnown;
1566
1295
  }
1567
1296
  let size;
1568
- const itemType = getItemType ? (_a = getItemType(data, index)) != null ? _a : "" : "";
1297
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1298
+ const scrollingTo = peek$(ctx, "scrollingTo");
1299
+ if (preferCachedSize) {
1300
+ const cachedSize = sizes.get(key);
1301
+ if (cachedSize !== void 0) {
1302
+ return cachedSize;
1303
+ }
1304
+ }
1569
1305
  if (getFixedItemSize) {
1570
1306
  size = getFixedItemSize(index, data, itemType);
1571
1307
  if (size !== void 0) {
@@ -1587,53 +1323,234 @@ function getItemSize(state, key, index, data, useAverageSize) {
1587
1323
  if (size === void 0) {
1588
1324
  size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
1589
1325
  }
1590
- sizes.set(key, size);
1326
+ setSize(ctx, state, key, size);
1591
1327
  return size;
1592
1328
  }
1593
1329
 
1594
1330
  // src/core/calculateOffsetWithOffsetPosition.ts
1595
- function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
1331
+ function calculateOffsetWithOffsetPosition(ctx, state, offsetParam, params) {
1596
1332
  const { index, viewOffset, viewPosition } = params;
1597
1333
  let offset = offsetParam;
1598
1334
  if (viewOffset) {
1599
1335
  offset -= viewOffset;
1600
1336
  }
1601
1337
  if (viewPosition !== void 0 && index !== void 0) {
1602
- offset -= viewPosition * (state.scrollLength - getItemSize(state, getId(state, index), index, state.props.data[index]));
1338
+ offset -= viewPosition * (state.scrollLength - getItemSize(ctx, state, getId(state, index), index, state.props.data[index]));
1603
1339
  }
1604
1340
  return offset;
1605
1341
  }
1606
1342
 
1607
1343
  // src/core/finishScrollTo.ts
1608
- var finishScrollTo = (state) => {
1344
+ function finishScrollTo(ctx, state) {
1345
+ var _a3, _b;
1609
1346
  if (state) {
1610
- state.scrollingTo = void 0;
1611
1347
  state.scrollHistory.length = 0;
1348
+ state.initialScroll = void 0;
1349
+ state.initialAnchor = void 0;
1350
+ set$(ctx, "scrollingTo", void 0);
1351
+ if (state.pendingTotalSize !== void 0) {
1352
+ addTotalSize(ctx, state, null, state.pendingTotalSize);
1353
+ }
1354
+ if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1355
+ (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1356
+ }
1612
1357
  }
1613
- };
1358
+ }
1614
1359
 
1615
1360
  // src/core/scrollTo.ts
1616
- function scrollTo(state, params = {}) {
1617
- var _a;
1618
- const { animated, noScrollingTo } = params;
1361
+ function scrollTo(ctx, state, params) {
1362
+ var _a3;
1363
+ const { noScrollingTo, ...scrollTarget } = params;
1364
+ const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1619
1365
  const {
1620
1366
  refScroller,
1621
1367
  props: { horizontal }
1622
1368
  } = state;
1623
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1369
+ let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1370
+ if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
1371
+ const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
1372
+ offset = Math.min(offset, maxOffset);
1373
+ }
1624
1374
  state.scrollHistory.length = 0;
1625
1375
  if (!noScrollingTo) {
1626
- state.scrollingTo = params;
1376
+ set$(ctx, "scrollingTo", scrollTarget);
1627
1377
  }
1628
1378
  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
- });
1379
+ if (!isInitialScroll || Platform.OS === "android") {
1380
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollTo({
1381
+ animated: !!animated,
1382
+ x: horizontal ? offset : 0,
1383
+ y: horizontal ? 0 : offset
1384
+ });
1385
+ }
1634
1386
  if (!animated) {
1635
1387
  state.scroll = offset;
1636
- setTimeout(() => finishScrollTo(state), 100);
1388
+ {
1389
+ const unlisten = listen$(ctx, "containersDidLayout", (value) => {
1390
+ if (value && peek$(ctx, "scrollingTo")) {
1391
+ finishScrollTo(ctx, state);
1392
+ unlisten();
1393
+ }
1394
+ });
1395
+ }
1396
+ if (isInitialScroll) {
1397
+ setTimeout(() => {
1398
+ state.initialScroll = void 0;
1399
+ }, 500);
1400
+ }
1401
+ }
1402
+ }
1403
+
1404
+ // src/utils/checkThreshold.ts
1405
+ var HYSTERESIS_MULTIPLIER = 1.3;
1406
+ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
1407
+ const absDistance = Math.abs(distance);
1408
+ const within = atThreshold || threshold > 0 && absDistance <= threshold;
1409
+ const updateSnapshot = () => {
1410
+ setSnapshot == null ? void 0 : setSnapshot({
1411
+ atThreshold,
1412
+ contentSize: context.contentSize,
1413
+ dataLength: context.dataLength,
1414
+ scrollPosition: context.scrollPosition
1415
+ });
1416
+ };
1417
+ if (!wasReached) {
1418
+ if (!within) {
1419
+ return false;
1420
+ }
1421
+ onReached == null ? void 0 : onReached(distance);
1422
+ updateSnapshot();
1423
+ return true;
1424
+ }
1425
+ const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
1426
+ if (reset) {
1427
+ setSnapshot == null ? void 0 : setSnapshot(void 0);
1428
+ return false;
1429
+ }
1430
+ if (within) {
1431
+ const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
1432
+ if (changed) {
1433
+ onReached == null ? void 0 : onReached(distance);
1434
+ updateSnapshot();
1435
+ }
1436
+ }
1437
+ return true;
1438
+ };
1439
+
1440
+ // src/utils/checkAtBottom.ts
1441
+ function checkAtBottom(ctx, state) {
1442
+ var _a3;
1443
+ if (!state) {
1444
+ return;
1445
+ }
1446
+ const {
1447
+ queuedInitialLayout,
1448
+ scrollLength,
1449
+ scroll,
1450
+ maintainingScrollAtEnd,
1451
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1452
+ } = state;
1453
+ const contentSize = getContentSize(ctx);
1454
+ if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1455
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1456
+ const isContentLess = contentSize < scrollLength;
1457
+ state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1458
+ state.isEndReached = checkThreshold(
1459
+ distanceFromEnd,
1460
+ isContentLess,
1461
+ onEndReachedThreshold * scrollLength,
1462
+ state.isEndReached,
1463
+ state.endReachedSnapshot,
1464
+ {
1465
+ contentSize,
1466
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1467
+ scrollPosition: scroll
1468
+ },
1469
+ (distance) => {
1470
+ var _a4, _b;
1471
+ return (_b = (_a4 = state.props).onEndReached) == null ? void 0 : _b.call(_a4, { distanceFromEnd: distance });
1472
+ },
1473
+ (snapshot) => {
1474
+ state.endReachedSnapshot = snapshot;
1475
+ }
1476
+ );
1477
+ }
1478
+ }
1479
+
1480
+ // src/utils/checkAtTop.ts
1481
+ function checkAtTop(state) {
1482
+ var _a3;
1483
+ if (!state) {
1484
+ return;
1485
+ }
1486
+ const {
1487
+ scrollLength,
1488
+ scroll,
1489
+ props: { onStartReachedThreshold }
1490
+ } = state;
1491
+ const distanceFromTop = scroll;
1492
+ state.isAtStart = distanceFromTop <= 0;
1493
+ state.isStartReached = checkThreshold(
1494
+ distanceFromTop,
1495
+ false,
1496
+ onStartReachedThreshold * scrollLength,
1497
+ state.isStartReached,
1498
+ state.startReachedSnapshot,
1499
+ {
1500
+ contentSize: state.totalSize,
1501
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1502
+ scrollPosition: scroll
1503
+ },
1504
+ (distance) => {
1505
+ var _a4, _b;
1506
+ return (_b = (_a4 = state.props).onStartReached) == null ? void 0 : _b.call(_a4, { distanceFromStart: distance });
1507
+ },
1508
+ (snapshot) => {
1509
+ state.startReachedSnapshot = snapshot;
1510
+ }
1511
+ );
1512
+ }
1513
+
1514
+ // src/core/updateScroll.ts
1515
+ function updateScroll(ctx, state, newScroll, forceUpdate) {
1516
+ var _a3;
1517
+ const scrollingTo = peek$(ctx, "scrollingTo");
1518
+ state.hasScrolled = true;
1519
+ state.lastBatchingAction = Date.now();
1520
+ const currentTime = Date.now();
1521
+ const adjust = state.scrollAdjustHandler.getAdjust();
1522
+ const lastHistoryAdjust = state.lastScrollAdjustForHistory;
1523
+ const adjustChanged = lastHistoryAdjust !== void 0 && Math.abs(adjust - lastHistoryAdjust) > 0.1;
1524
+ if (adjustChanged) {
1525
+ state.scrollHistory.length = 0;
1526
+ }
1527
+ state.lastScrollAdjustForHistory = adjust;
1528
+ if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
1529
+ if (!adjustChanged) {
1530
+ state.scrollHistory.push({ scroll: newScroll, time: currentTime });
1531
+ }
1532
+ }
1533
+ if (state.scrollHistory.length > 5) {
1534
+ state.scrollHistory.shift();
1535
+ }
1536
+ state.scrollPrev = state.scroll;
1537
+ state.scrollPrevTime = state.scrollTime;
1538
+ state.scroll = newScroll;
1539
+ state.scrollTime = currentTime;
1540
+ const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
1541
+ if (ignoreScrollFromMVCP && !scrollingTo) {
1542
+ const { lt, gt } = ignoreScrollFromMVCP;
1543
+ if (lt && newScroll < lt || gt && newScroll > gt) {
1544
+ state.ignoreScrollFromMVCPIgnored = true;
1545
+ return;
1546
+ }
1547
+ }
1548
+ if (state.dataChangeNeedsScrollUpdate || Math.abs(state.scroll - state.scrollPrev) > 2) {
1549
+ state.ignoreScrollFromMVCPIgnored = false;
1550
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1551
+ checkAtBottom(ctx, state);
1552
+ checkAtTop(state);
1553
+ state.dataChangeNeedsScrollUpdate = false;
1637
1554
  }
1638
1555
  }
1639
1556
 
@@ -1643,6 +1560,9 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1643
1560
  const doit = () => {
1644
1561
  {
1645
1562
  state.scrollAdjustHandler.requestAdjust(positionDiff);
1563
+ if (state.adjustingFromInitialMount) {
1564
+ state.adjustingFromInitialMount--;
1565
+ }
1646
1566
  }
1647
1567
  };
1648
1568
  state.scroll += positionDiff;
@@ -1650,44 +1570,77 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1650
1570
  const didLayout = peek$(ctx, "containersDidLayout");
1651
1571
  if (didLayout) {
1652
1572
  doit();
1653
- const threshold = state.scroll - positionDiff / 2;
1654
- if (!state.ignoreScrollFromMVCP) {
1655
- state.ignoreScrollFromMVCP = {};
1656
- }
1657
- if (positionDiff > 0) {
1658
- state.ignoreScrollFromMVCP.lt = threshold;
1659
- } else {
1660
- state.ignoreScrollFromMVCP.gt = threshold;
1661
- }
1662
- if (state.ignoreScrollFromMVCPTimeout) {
1663
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
1664
- }
1665
- state.ignoreScrollFromMVCPTimeout = setTimeout(
1666
- () => {
1667
- state.ignoreScrollFromMVCP = void 0;
1668
- },
1669
- 100
1670
- );
1671
1573
  } else {
1574
+ state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
1672
1575
  requestAnimationFrame(doit);
1673
1576
  }
1674
1577
  }
1675
1578
  }
1676
1579
 
1580
+ // src/core/ensureInitialAnchor.ts
1581
+ var INITIAL_ANCHOR_TOLERANCE = 0.5;
1582
+ var INITIAL_ANCHOR_MAX_ATTEMPTS = 4;
1583
+ var INITIAL_ANCHOR_SETTLED_TICKS = 2;
1584
+ function ensureInitialAnchor(ctx, state) {
1585
+ var _a3, _b, _c, _d, _e;
1586
+ const anchor = state.initialAnchor;
1587
+ const item = state.props.data[anchor.index];
1588
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
1589
+ if (!containersDidLayout) {
1590
+ return;
1591
+ }
1592
+ const id = getId(state, anchor.index);
1593
+ if (state.positions.get(id) === void 0) {
1594
+ return;
1595
+ }
1596
+ const size = getItemSize(ctx, state, id, anchor.index, item, true, true);
1597
+ if (size === void 0) {
1598
+ return;
1599
+ }
1600
+ const availableSpace = Math.max(0, state.scrollLength - size);
1601
+ const desiredOffset = calculateOffsetForIndex(ctx, state, anchor.index) - ((_a3 = anchor.viewOffset) != null ? _a3 : 0) - ((_b = anchor.viewPosition) != null ? _b : 0) * availableSpace;
1602
+ const contentSize = getContentSize(ctx);
1603
+ const maxOffset = Math.max(0, contentSize - state.scrollLength);
1604
+ const clampedDesiredOffset = Math.max(0, Math.min(desiredOffset, maxOffset));
1605
+ const delta = clampedDesiredOffset - state.scroll;
1606
+ if (Math.abs(delta) <= INITIAL_ANCHOR_TOLERANCE) {
1607
+ const settledTicks = ((_c = anchor.settledTicks) != null ? _c : 0) + 1;
1608
+ if (settledTicks >= INITIAL_ANCHOR_SETTLED_TICKS) {
1609
+ state.initialAnchor = void 0;
1610
+ } else {
1611
+ anchor.settledTicks = settledTicks;
1612
+ }
1613
+ return;
1614
+ }
1615
+ if (((_d = anchor.attempts) != null ? _d : 0) >= INITIAL_ANCHOR_MAX_ATTEMPTS) {
1616
+ state.initialAnchor = void 0;
1617
+ return;
1618
+ }
1619
+ const lastDelta = anchor.lastDelta;
1620
+ if (lastDelta !== void 0 && Math.abs(delta) >= Math.abs(lastDelta)) {
1621
+ state.initialAnchor = void 0;
1622
+ return;
1623
+ }
1624
+ Object.assign(anchor, {
1625
+ attempts: ((_e = anchor.attempts) != null ? _e : 0) + 1,
1626
+ lastDelta: delta,
1627
+ settledTicks: 0
1628
+ });
1629
+ requestAdjust(ctx, state, delta);
1630
+ }
1631
+
1677
1632
  // src/core/mvcp.ts
1678
1633
  function prepareMVCP(ctx, state, dataChanged) {
1679
- const {
1680
- idsInView,
1681
- positions,
1682
- scrollingTo,
1683
- props: { maintainVisibleContentPosition }
1684
- } = state;
1634
+ const { idsInView, positions, props } = state;
1635
+ const { maintainVisibleContentPosition } = props;
1636
+ const scrollingTo = peek$(ctx, "scrollingTo");
1685
1637
  let prevPosition;
1686
1638
  let targetId;
1687
1639
  const idsInViewWithPositions = [];
1688
1640
  const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1689
- if (maintainVisibleContentPosition) {
1690
- const indexByKey = state.indexByKey;
1641
+ const shouldMVCP = !dataChanged || maintainVisibleContentPosition;
1642
+ const indexByKey = state.indexByKey;
1643
+ if (shouldMVCP) {
1691
1644
  if (scrollTarget !== void 0) {
1692
1645
  targetId = getId(state, scrollTarget);
1693
1646
  } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
@@ -1700,70 +1653,106 @@ function prepareMVCP(ctx, state, dataChanged) {
1700
1653
  }
1701
1654
  }
1702
1655
  } else {
1703
- targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
1656
+ targetId = idsInView.find((id) => indexByKey.get(id) !== void 0);
1704
1657
  }
1705
1658
  }
1706
1659
  if (targetId !== void 0) {
1707
1660
  prevPosition = positions.get(targetId);
1708
1661
  }
1709
- }
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);
1662
+ return () => {
1663
+ let positionDiff;
1664
+ if (dataChanged && targetId === void 0 && maintainVisibleContentPosition) {
1665
+ for (let i = 0; i < idsInViewWithPositions.length; i++) {
1666
+ const { id, position } = idsInViewWithPositions[i];
1667
+ const newPosition = positions.get(id);
1668
+ if (newPosition !== void 0) {
1669
+ positionDiff = newPosition - position;
1670
+ break;
1671
+ }
1672
+ }
1673
+ }
1674
+ if (targetId !== void 0 && prevPosition !== void 0) {
1675
+ const newPosition = positions.get(targetId);
1716
1676
  if (newPosition !== void 0) {
1717
- positionDiff = newPosition - position;
1718
- break;
1677
+ const totalSize = getContentSize(ctx);
1678
+ let diff = newPosition - prevPosition;
1679
+ if (diff !== 0 && state.scroll + state.scrollLength > totalSize) {
1680
+ if (diff > 0) {
1681
+ diff = Math.max(0, totalSize - state.scroll - state.scrollLength);
1682
+ } else {
1683
+ diff = 0;
1684
+ }
1685
+ }
1686
+ positionDiff = diff;
1719
1687
  }
1720
1688
  }
1721
- }
1722
- if (targetId !== void 0 && prevPosition !== void 0) {
1723
- const newPosition = positions.get(targetId);
1724
- if (newPosition !== void 0) {
1725
- positionDiff = newPosition - prevPosition;
1689
+ if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1690
+ requestAdjust(ctx, state, positionDiff);
1726
1691
  }
1727
- }
1728
- if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1729
- requestAdjust(ctx, state, positionDiff);
1730
- }
1731
- };
1692
+ };
1693
+ }
1732
1694
  }
1733
1695
 
1734
- // src/utils/setPaddingTop.ts
1735
- function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1736
- if (stylePaddingTop !== void 0) {
1737
- const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1738
- if (stylePaddingTop < prevStylePaddingTop) {
1739
- let prevTotalSize = peek$(ctx, "totalSize") || 0;
1740
- set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
1741
- state.timeoutSetPaddingTop = setTimeout(() => {
1742
- prevTotalSize = peek$(ctx, "totalSize") || 0;
1743
- set$(ctx, "totalSize", prevTotalSize - prevStylePaddingTop);
1744
- }, 16);
1745
- }
1746
- set$(ctx, "stylePaddingTop", stylePaddingTop);
1696
+ // src/core/prepareColumnStartState.ts
1697
+ function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1698
+ var _a3;
1699
+ const numColumns = peek$(ctx, "numColumns");
1700
+ let rowStartIndex = startIndex;
1701
+ const columnAtStart = state.columns.get(state.idCache[startIndex]);
1702
+ if (columnAtStart !== 1) {
1703
+ rowStartIndex = findRowStartIndex(state, numColumns, startIndex);
1747
1704
  }
1748
- if (alignItemsPaddingTop !== void 0) {
1749
- set$(ctx, "alignItemsPaddingTop", alignItemsPaddingTop);
1705
+ let currentRowTop = 0;
1706
+ const curId = state.idCache[rowStartIndex];
1707
+ const column = state.columns.get(curId);
1708
+ if (rowStartIndex > 0) {
1709
+ const prevIndex = rowStartIndex - 1;
1710
+ const prevId = state.idCache[prevIndex];
1711
+ const prevPosition = (_a3 = state.positions.get(prevId)) != null ? _a3 : 0;
1712
+ const prevRowStart = findRowStartIndex(state, numColumns, prevIndex);
1713
+ const prevRowHeight = calculateRowMaxSize(ctx, state, prevRowStart, prevIndex, useAverageSize);
1714
+ currentRowTop = prevPosition + prevRowHeight;
1750
1715
  }
1716
+ return {
1717
+ column,
1718
+ currentRowTop,
1719
+ startIndex: rowStartIndex
1720
+ };
1751
1721
  }
1752
-
1753
- // src/utils/updateAlignItemsPaddingTop.ts
1754
- function updateAlignItemsPaddingTop(ctx, state) {
1755
- const {
1756
- scrollLength,
1757
- props: { alignItemsAtEnd, data }
1758
- } = state;
1759
- if (alignItemsAtEnd) {
1760
- let alignItemsPaddingTop = 0;
1761
- if ((data == null ? void 0 : data.length) > 0) {
1762
- const contentSize = getContentSize(ctx);
1763
- alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1722
+ function findRowStartIndex(state, numColumns, index) {
1723
+ if (numColumns <= 1) {
1724
+ return Math.max(0, index);
1725
+ }
1726
+ let rowStart = Math.max(0, index);
1727
+ while (rowStart > 0) {
1728
+ const columnForIndex = state.columns.get(state.idCache[rowStart]);
1729
+ if (columnForIndex === 1) {
1730
+ break;
1731
+ }
1732
+ rowStart--;
1733
+ }
1734
+ return rowStart;
1735
+ }
1736
+ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1737
+ if (endIndex < startIndex) {
1738
+ return 0;
1739
+ }
1740
+ const { data } = state.props;
1741
+ if (!data) {
1742
+ return 0;
1743
+ }
1744
+ let maxSize = 0;
1745
+ for (let i = startIndex; i <= endIndex; i++) {
1746
+ if (i < 0 || i >= data.length) {
1747
+ continue;
1748
+ }
1749
+ const id = state.idCache[i];
1750
+ const size = getItemSize(ctx, state, id, i, data[i], useAverageSize);
1751
+ if (size > maxSize) {
1752
+ maxSize = size;
1764
1753
  }
1765
- setPaddingTop(ctx, state, { alignItemsPaddingTop });
1766
1754
  }
1755
+ return maxSize;
1767
1756
  }
1768
1757
 
1769
1758
  // src/core/updateTotalSize.ts
@@ -1779,29 +1768,53 @@ function updateTotalSize(ctx, state) {
1779
1768
  if (lastId !== void 0) {
1780
1769
  const lastPosition = positions.get(lastId);
1781
1770
  if (lastPosition !== void 0) {
1782
- const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
1771
+ const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
1783
1772
  if (lastSize !== void 0) {
1784
1773
  const totalSize = lastPosition + lastSize;
1785
1774
  addTotalSize(ctx, state, null, totalSize);
1786
1775
  }
1787
1776
  }
1788
1777
  }
1789
- }
1790
- }
1791
- function addTotalSize(ctx, state, key, add) {
1792
- const { alignItemsAtEnd } = state.props;
1793
- {
1794
- state.totalSize = add;
1795
- if (state.timeoutSetPaddingTop) {
1796
- clearTimeout(state.timeoutSetPaddingTop);
1797
- state.timeoutSetPaddingTop = void 0;
1778
+ }
1779
+ }
1780
+
1781
+ // src/utils/getScrollVelocity.ts
1782
+ var getScrollVelocity = (state) => {
1783
+ const { scrollHistory } = state;
1784
+ let velocity = 0;
1785
+ if (scrollHistory.length >= 1) {
1786
+ const newest = scrollHistory[scrollHistory.length - 1];
1787
+ let oldest;
1788
+ let start = 0;
1789
+ const now = Date.now();
1790
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
1791
+ const entry = scrollHistory[i];
1792
+ const nextEntry = scrollHistory[i + 1];
1793
+ if (i > 0) {
1794
+ const prevEntry = scrollHistory[i - 1];
1795
+ const prevDirection = entry.scroll - prevEntry.scroll;
1796
+ const currentDirection = nextEntry.scroll - entry.scroll;
1797
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1798
+ start = i;
1799
+ break;
1800
+ }
1801
+ }
1802
+ }
1803
+ for (let i = start; i < scrollHistory.length - 1; i++) {
1804
+ const entry = scrollHistory[i];
1805
+ if (now - entry.time <= 1e3) {
1806
+ oldest = entry;
1807
+ break;
1808
+ }
1809
+ }
1810
+ if (oldest && oldest !== newest) {
1811
+ const scrollDiff = newest.scroll - oldest.scroll;
1812
+ const timeDiff = newest.time - oldest.time;
1813
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1798
1814
  }
1799
1815
  }
1800
- set$(ctx, "totalSize", state.totalSize);
1801
- if (alignItemsAtEnd) {
1802
- updateAlignItemsPaddingTop(ctx, state);
1803
- }
1804
- }
1816
+ return velocity;
1817
+ };
1805
1818
 
1806
1819
  // src/utils/updateSnapToOffsets.ts
1807
1820
  function updateSnapToOffsets(ctx, state) {
@@ -1818,9 +1831,14 @@ function updateSnapToOffsets(ctx, state) {
1818
1831
  set$(ctx, "snapToOffsets", snapToOffsets);
1819
1832
  }
1820
1833
 
1821
- // src/core/updateAllPositions.ts
1822
- function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1823
- var _a, _b, _c, _d, _e, _f;
1834
+ // src/core/updateItemPositions.ts
1835
+ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP } = {
1836
+ doMVCP: false,
1837
+ forceFullUpdate: false,
1838
+ scrollBottomBuffered: -1,
1839
+ startIndex: 0
1840
+ }) {
1841
+ var _a3, _b, _c, _d, _e;
1824
1842
  const {
1825
1843
  columns,
1826
1844
  indexByKey,
@@ -1830,32 +1848,51 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1830
1848
  props: { getEstimatedItemSize, snapToIndices, enableAverages }
1831
1849
  } = state;
1832
1850
  const data = state.props.data;
1851
+ const dataLength = data.length;
1833
1852
  const numColumns = peek$(ctx, "numColumns");
1834
- const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1853
+ const scrollingTo = peek$(ctx, "scrollingTo");
1854
+ const hasColumns = numColumns > 1;
1855
+ const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1856
+ const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1857
+ const maxVisibleArea = scrollBottomBuffered + 1e3;
1835
1858
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1859
+ const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0;
1836
1860
  let currentRowTop = 0;
1837
1861
  let column = 1;
1838
1862
  let maxSizeInRow = 0;
1839
- const hasColumns = numColumns > 1;
1840
1863
  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
1864
  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);
1865
+ const { startIndex: processedStartIndex, currentRowTop: initialRowTop } = prepareColumnStartState(
1866
+ ctx,
1867
+ state,
1868
+ startIndex,
1869
+ useAverageSize
1870
+ );
1871
+ startIndex = processedStartIndex;
1872
+ currentRowTop = initialRowTop;
1873
+ } else if (startIndex < dataLength) {
1874
+ const prevIndex = startIndex - 1;
1875
+ const prevId = getId(state, prevIndex);
1876
+ const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1877
+ const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1850
1878
  currentRowTop = prevPosition + prevSize;
1851
1879
  }
1852
1880
  }
1853
1881
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1854
- const dataLength = data.length;
1882
+ let didBreakEarly = false;
1883
+ let breakAt;
1855
1884
  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);
1858
- if (__DEV__ && needsIndexByKey) {
1885
+ if (shouldOptimize && breakAt !== void 0 && i > breakAt) {
1886
+ didBreakEarly = true;
1887
+ break;
1888
+ }
1889
+ if (shouldOptimize && breakAt === void 0 && !scrollingTo && !dataChanged && currentRowTop > maxVisibleArea) {
1890
+ const itemsPerRow = hasColumns ? numColumns : 1;
1891
+ breakAt = i + itemsPerRow + 10;
1892
+ }
1893
+ const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1894
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, state, id, i, data[i], useAverageSize, preferCachedSize);
1895
+ if (IS_DEV && needsIndexByKey) {
1859
1896
  if (indexByKeyForChecking.has(id)) {
1860
1897
  console.error(
1861
1898
  `[legend-list] Error: Detected overlapping key (${id}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`
@@ -1882,7 +1919,9 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1882
1919
  currentRowTop += size;
1883
1920
  }
1884
1921
  }
1885
- updateTotalSize(ctx, state);
1922
+ if (!didBreakEarly) {
1923
+ updateTotalSize(ctx, state);
1924
+ }
1886
1925
  if (snapToIndices) {
1887
1926
  updateSnapToOffsets(ctx, state);
1888
1927
  }
@@ -1902,6 +1941,21 @@ function ensureViewabilityState(ctx, configId) {
1902
1941
  }
1903
1942
  return state;
1904
1943
  }
1944
+ function setupViewability(props) {
1945
+ let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
1946
+ if (viewabilityConfig || onViewableItemsChanged) {
1947
+ viewabilityConfigCallbackPairs = [
1948
+ ...viewabilityConfigCallbackPairs || [],
1949
+ {
1950
+ onViewableItemsChanged,
1951
+ viewabilityConfig: viewabilityConfig || {
1952
+ viewAreaCoveragePercentThreshold: 0
1953
+ }
1954
+ }
1955
+ ];
1956
+ }
1957
+ return viewabilityConfigCallbackPairs;
1958
+ }
1905
1959
  function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
1906
1960
  const {
1907
1961
  timeouts,
@@ -2055,16 +2109,6 @@ function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize,
2055
2109
  const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
2056
2110
  return value.isViewable;
2057
2111
  }
2058
- function findContainerId(ctx, key) {
2059
- const numContainers = peek$(ctx, "numContainers");
2060
- for (let i = 0; i < numContainers; i++) {
2061
- const itemKey = peek$(ctx, `containerItemKey${i}`);
2062
- if (itemKey === key) {
2063
- return i;
2064
- }
2065
- }
2066
- return -1;
2067
- }
2068
2112
  function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
2069
2113
  const key = containerId + configId;
2070
2114
  ctx.mapViewabilityValues.set(key, viewToken);
@@ -2072,13 +2116,13 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
2072
2116
  cb == null ? void 0 : cb(viewToken);
2073
2117
  }
2074
2118
 
2075
- // src/platform/batchedUpdates.ts
2076
- var import_react_dom = __toESM(require_react_dom());
2077
-
2078
2119
  // src/utils/checkAllSizesKnown.ts
2120
+ function isNullOrUndefined2(value) {
2121
+ return value === null || value === void 0;
2122
+ }
2079
2123
  function checkAllSizesKnown(state) {
2080
2124
  const { startBuffered, endBuffered, sizesKnown } = state;
2081
- if (endBuffered !== null && startBuffered >= 0 && endBuffered >= 0) {
2125
+ if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
2082
2126
  let areAllKnown = true;
2083
2127
  for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
2084
2128
  const key = getId(state, i);
@@ -2095,6 +2139,8 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
2095
2139
  const { stickyContainerPool, containerItemTypes } = state;
2096
2140
  const result = [];
2097
2141
  const availableContainers = [];
2142
+ const pendingRemovalSet = new Set(pendingRemoval);
2143
+ let pendingRemovalChanged = false;
2098
2144
  const stickyIndicesSet = state.props.stickyIndicesSet;
2099
2145
  const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
2100
2146
  const canReuseContainer = (containerIndex, requiredType) => {
@@ -2110,12 +2156,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
2110
2156
  let foundContainer = false;
2111
2157
  for (const containerIndex of stickyContainerPool) {
2112
2158
  const key = peek$(ctx, `containerItemKey${containerIndex}`);
2113
- const isPendingRemoval = pendingRemoval.includes(containerIndex);
2114
- if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType)) {
2159
+ const isPendingRemoval = pendingRemovalSet.has(containerIndex);
2160
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType) && !result.includes(containerIndex)) {
2115
2161
  result.push(containerIndex);
2116
- if (isPendingRemoval) {
2117
- const index = pendingRemoval.indexOf(containerIndex);
2118
- pendingRemoval.splice(index, 1);
2162
+ if (isPendingRemoval && pendingRemovalSet.delete(containerIndex)) {
2163
+ pendingRemovalChanged = true;
2119
2164
  }
2120
2165
  foundContainer = true;
2121
2166
  if (requiredItemTypes) typeIndex++;
@@ -2135,13 +2180,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
2135
2180
  }
2136
2181
  const key = peek$(ctx, `containerItemKey${u}`);
2137
2182
  let isOk = key === void 0;
2138
- if (!isOk) {
2139
- const index = pendingRemoval.indexOf(u);
2140
- if (index !== -1) {
2141
- pendingRemoval.splice(index, 1);
2142
- const requiredType = neededTypes[typeIndex];
2143
- isOk = canReuseContainer(u, requiredType);
2144
- }
2183
+ if (!isOk && pendingRemovalSet.has(u)) {
2184
+ pendingRemovalSet.delete(u);
2185
+ pendingRemovalChanged = true;
2186
+ const requiredType = neededTypes[typeIndex];
2187
+ isOk = canReuseContainer(u, requiredType);
2145
2188
  }
2146
2189
  if (isOk) {
2147
2190
  result.push(u);
@@ -2184,7 +2227,7 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
2184
2227
  for (let i = 0; i < stillNeeded; i++) {
2185
2228
  result.push(numContainers + i);
2186
2229
  }
2187
- if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
2230
+ if (IS_DEV && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
2188
2231
  console.warn(
2189
2232
  "[legend-list] No unused container available, so creating one on demand. This can be a minor performance issue and is likely caused by the estimatedItemSize being too large. Consider decreasing estimatedItemSize or increasing initialContainerPoolRatio.",
2190
2233
  {
@@ -2199,50 +2242,18 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
2199
2242
  }
2200
2243
  }
2201
2244
  }
2245
+ if (pendingRemovalChanged) {
2246
+ pendingRemoval.length = 0;
2247
+ for (const value of pendingRemovalSet) {
2248
+ pendingRemoval.push(value);
2249
+ }
2250
+ }
2202
2251
  return result.sort(comparatorDefault);
2203
2252
  }
2204
2253
  function comparatorByDistance(a, b) {
2205
2254
  return b.distance - a.distance;
2206
2255
  }
2207
2256
 
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
- }
2242
- }
2243
- return velocity;
2244
- };
2245
-
2246
2257
  // src/core/scrollToIndex.ts
2247
2258
  function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
2248
2259
  if (index >= state.props.data.length) {
@@ -2255,72 +2266,16 @@ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, vie
2255
2266
  if (isLast && viewPosition === void 0) {
2256
2267
  viewPosition = 1;
2257
2268
  }
2258
- const firstIndexScrollPostion = firstIndexOffset - viewOffset;
2259
2269
  state.scrollForNextCalculateItemsInView = void 0;
2260
- scrollTo(state, {
2270
+ scrollTo(ctx, state, {
2261
2271
  animated,
2262
2272
  index,
2263
- offset: firstIndexScrollPostion,
2273
+ offset: firstIndexOffset,
2264
2274
  viewOffset,
2265
2275
  viewPosition: viewPosition != null ? viewPosition : 0
2266
2276
  });
2267
2277
  }
2268
2278
 
2269
- // src/utils/checkThreshold.ts
2270
- var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
2271
- const distanceAbs = Math.abs(distance);
2272
- const isAtThreshold = atThreshold || distanceAbs < threshold;
2273
- if (!isReached && !isBlockedByTimer) {
2274
- if (isAtThreshold) {
2275
- onReached == null ? void 0 : onReached(distance);
2276
- blockTimer == null ? void 0 : blockTimer(true);
2277
- setTimeout(() => {
2278
- blockTimer == null ? void 0 : blockTimer(false);
2279
- }, 700);
2280
- return true;
2281
- }
2282
- } else {
2283
- if (distance >= 1.3 * threshold) {
2284
- return false;
2285
- }
2286
- }
2287
- return isReached;
2288
- };
2289
-
2290
- // src/utils/checkAtBottom.ts
2291
- function checkAtBottom(ctx, state) {
2292
- if (!state) {
2293
- return;
2294
- }
2295
- const {
2296
- queuedInitialLayout,
2297
- scrollLength,
2298
- scroll,
2299
- maintainingScrollAtEnd,
2300
- props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
2301
- } = state;
2302
- const contentSize = getContentSize(ctx);
2303
- if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
2304
- const distanceFromEnd = contentSize - scroll - scrollLength;
2305
- const isContentLess = contentSize < scrollLength;
2306
- state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
2307
- state.isEndReached = checkThreshold(
2308
- distanceFromEnd,
2309
- isContentLess,
2310
- onEndReachedThreshold * scrollLength,
2311
- state.isEndReached,
2312
- state.endReachedBlockedByTimer,
2313
- (distance) => {
2314
- var _a, _b;
2315
- return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
2316
- },
2317
- (block) => {
2318
- state.endReachedBlockedByTimer = block;
2319
- }
2320
- );
2321
- }
2322
- }
2323
-
2324
2279
  // src/utils/setDidLayout.ts
2325
2280
  function setDidLayout(ctx, state) {
2326
2281
  const {
@@ -2343,11 +2298,12 @@ function setDidLayout(ctx, state) {
2343
2298
 
2344
2299
  // src/core/calculateItemsInView.ts
2345
2300
  function findCurrentStickyIndex(stickyArray, scroll, state) {
2346
- var _a;
2301
+ var _a3;
2347
2302
  const idCache = state.idCache;
2348
2303
  const positions = state.positions;
2349
2304
  for (let i = stickyArray.length - 1; i >= 0; i--) {
2350
- const stickyId = (_a = idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
2305
+ const stickyIndex = stickyArray[i];
2306
+ const stickyId = (_a3 = idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
2351
2307
  const stickyPos = stickyId ? positions.get(stickyId) : void 0;
2352
2308
  if (stickyPos !== void 0 && scroll >= stickyPos) {
2353
2309
  return i;
@@ -2355,47 +2311,51 @@ function findCurrentStickyIndex(stickyArray, scroll, state) {
2355
2311
  }
2356
2312
  return -1;
2357
2313
  }
2358
- function getActiveStickyIndices(ctx, state, stickyIndices) {
2314
+ function getActiveStickyIndices(ctx, state, stickyHeaderIndices) {
2359
2315
  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))
2316
+ Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyHeaderIndices.has(idx))
2361
2317
  );
2362
2318
  }
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);
2319
+ function handleStickyActivation(ctx, state, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
2320
+ var _a3;
2321
+ const activeIndices = getActiveStickyIndices(ctx, state, stickyHeaderIndices);
2322
+ state.activeStickyIndex = currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : void 0;
2367
2323
  for (let offset = 0; offset <= 1; offset++) {
2368
2324
  const idx = currentStickyIdx - offset;
2369
2325
  if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
2370
2326
  const stickyIndex = stickyArray[idx];
2371
- const stickyId = (_a = state.idCache.get(stickyIndex)) != null ? _a : getId(state, stickyIndex);
2327
+ const stickyId = (_a3 = state.idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
2372
2328
  if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered)) {
2373
2329
  needNewContainers.push(stickyIndex);
2374
2330
  }
2375
2331
  }
2376
2332
  }
2377
- function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pendingRemoval) {
2378
- var _a, _b, _c;
2379
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
2333
+ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
2334
+ var _a3, _b, _c;
2380
2335
  for (const containerIndex of state.stickyContainerPool) {
2381
2336
  const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
2382
2337
  const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
2383
2338
  if (itemIndex === void 0) continue;
2384
2339
  const arrayIdx = stickyArray.indexOf(itemIndex);
2385
- if (arrayIdx === -1) continue;
2340
+ if (arrayIdx === -1) {
2341
+ state.stickyContainerPool.delete(containerIndex);
2342
+ set$(ctx, `containerSticky${containerIndex}`, false);
2343
+ set$(ctx, `containerStickyOffset${containerIndex}`, void 0);
2344
+ continue;
2345
+ }
2386
2346
  const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
2387
2347
  if (isRecentSticky) continue;
2388
2348
  const nextIndex = stickyArray[arrayIdx + 1];
2389
2349
  let shouldRecycle = false;
2390
2350
  if (nextIndex) {
2391
- const nextId = (_a = state.idCache.get(nextIndex)) != null ? _a : getId(state, nextIndex);
2351
+ const nextId = (_a3 = state.idCache[nextIndex]) != null ? _a3 : getId(state, nextIndex);
2392
2352
  const nextPos = nextId ? state.positions.get(nextId) : void 0;
2393
2353
  shouldRecycle = nextPos !== void 0 && scroll > nextPos + scrollBuffer * 2;
2394
2354
  } else {
2395
- const currentId = (_b = state.idCache.get(itemIndex)) != null ? _b : getId(state, itemIndex);
2355
+ const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
2396
2356
  if (currentId) {
2397
2357
  const currentPos = state.positions.get(currentId);
2398
- const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
2358
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, state, currentId, itemIndex, state.props.data[itemIndex]);
2399
2359
  shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
2400
2360
  }
2401
2361
  }
@@ -2405,62 +2365,53 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pe
2405
2365
  }
2406
2366
  }
2407
2367
  function calculateItemsInView(ctx, state, params = {}) {
2408
- (0, import_react_dom.unstable_batchedUpdates)(() => {
2409
- var _a, _b, _c, _d, _e, _f, _g, _h;
2368
+ unstable_batchedUpdates(() => {
2369
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2410
2370
  const {
2411
2371
  columns,
2412
2372
  containerItemKeys,
2413
2373
  enableScrollForNextCalculateItemsInView,
2414
2374
  idCache,
2415
2375
  indexByKey,
2376
+ initialScroll,
2416
2377
  minIndexSizeChanged,
2417
2378
  positions,
2379
+ props: { getItemType, itemsAreEqual, keyExtractor, onStickyHeaderChange, scrollBuffer },
2418
2380
  scrollForNextCalculateItemsInView,
2419
2381
  scrollLength,
2420
2382
  sizes,
2421
2383
  startBufferedId: startBufferedIdOrig,
2422
- viewabilityConfigCallbackPairs,
2423
- props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, scrollBuffer }
2384
+ viewabilityConfigCallbackPairs
2424
2385
  } = state;
2425
2386
  const { data } = state.props;
2426
2387
  const stickyIndicesArr = state.props.stickyIndicesArr || [];
2427
2388
  const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
2428
2389
  const prevNumContainers = peek$(ctx, "numContainers");
2429
2390
  if (!data || scrollLength === 0 || !prevNumContainers) {
2391
+ if (state.initialAnchor) {
2392
+ ensureInitialAnchor(ctx, state);
2393
+ }
2430
2394
  return;
2431
2395
  }
2432
- const totalSize = peek$(ctx, "totalSize");
2396
+ const totalSize = getContentSize(ctx);
2433
2397
  const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
2434
2398
  const numColumns = peek$(ctx, "numColumns");
2435
- const previousScrollAdjust = 0;
2436
- const { dataChanged, doMVCP } = params;
2399
+ const { dataChanged, doMVCP, forceFullItemPositions } = params;
2437
2400
  const speed = getScrollVelocity(state);
2438
- if (doMVCP || 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
- }
2450
- checkMVCP == null ? void 0 : checkMVCP();
2451
- }
2452
2401
  const scrollExtra = 0;
2453
2402
  const { queuedInitialLayout } = state;
2454
2403
  let { scroll: scrollState } = state;
2455
2404
  if (!queuedInitialLayout && initialScroll) {
2456
2405
  const updatedOffset = calculateOffsetWithOffsetPosition(
2406
+ ctx,
2457
2407
  state,
2458
2408
  calculateOffsetForIndex(ctx, state, initialScroll.index),
2459
2409
  initialScroll
2460
2410
  );
2461
2411
  scrollState = updatedOffset;
2462
2412
  }
2463
- const scrollAdjustPad = -previousScrollAdjust - topPad;
2413
+ const scrollAdjustPending = (_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0;
2414
+ const scrollAdjustPad = scrollAdjustPending - topPad;
2464
2415
  let scroll = scrollState + scrollExtra + scrollAdjustPad;
2465
2416
  if (scroll + scrollLength > totalSize) {
2466
2417
  scroll = Math.max(0, totalSize - scrollLength);
@@ -2469,6 +2420,11 @@ function calculateItemsInView(ctx, state, params = {}) {
2469
2420
  set$(ctx, "debugRawScroll", scrollState);
2470
2421
  set$(ctx, "debugComputedScroll", scroll);
2471
2422
  }
2423
+ const previousStickyIndex = state.activeStickyIndex;
2424
+ const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
2425
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : void 0;
2426
+ state.activeStickyIndex = nextActiveStickyIndex;
2427
+ set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
2472
2428
  let scrollBufferTop = scrollBuffer;
2473
2429
  let scrollBufferBottom = scrollBuffer;
2474
2430
  if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
@@ -2481,22 +2437,42 @@ function calculateItemsInView(ctx, state, params = {}) {
2481
2437
  const scrollTopBuffered = scroll - scrollBufferTop;
2482
2438
  const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
2483
2439
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
2484
- if (scrollForNextCalculateItemsInView) {
2440
+ if (!dataChanged && scrollForNextCalculateItemsInView) {
2485
2441
  const { top, bottom } = scrollForNextCalculateItemsInView;
2486
2442
  if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
2443
+ if (state.initialAnchor) {
2444
+ ensureInitialAnchor(ctx, state);
2445
+ }
2487
2446
  return;
2488
2447
  }
2489
2448
  }
2449
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
2450
+ if (dataChanged) {
2451
+ indexByKey.clear();
2452
+ idCache.length = 0;
2453
+ positions.clear();
2454
+ }
2455
+ const startIndex = dataChanged ? 0 : (_b = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _b : 0;
2456
+ updateItemPositions(ctx, state, dataChanged, {
2457
+ doMVCP,
2458
+ forceFullUpdate: !!forceFullItemPositions,
2459
+ scrollBottomBuffered,
2460
+ startIndex
2461
+ });
2462
+ if (minIndexSizeChanged !== void 0) {
2463
+ state.minIndexSizeChanged = void 0;
2464
+ }
2465
+ checkMVCP == null ? void 0 : checkMVCP();
2490
2466
  let startNoBuffer = null;
2491
2467
  let startBuffered = null;
2492
2468
  let startBufferedId = null;
2493
2469
  let endNoBuffer = null;
2494
2470
  let endBuffered = null;
2495
- let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2471
+ let loopStart = !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2496
2472
  for (let i = loopStart; i >= 0; i--) {
2497
- const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
2473
+ const id = (_c = idCache[i]) != null ? _c : getId(state, i);
2498
2474
  const top = positions.get(id);
2499
- const size = (_b = sizes.get(id)) != null ? _b : getItemSize(state, id, i, data[i]);
2475
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i]);
2500
2476
  const bottom = top + size;
2501
2477
  if (bottom > scroll - scrollBuffer) {
2502
2478
  loopStart = i;
@@ -2522,8 +2498,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2522
2498
  let firstFullyOnScreenIndex;
2523
2499
  const dataLength = data.length;
2524
2500
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
2525
- const id = (_c = idCache.get(i)) != null ? _c : getId(state, i);
2526
- const size = (_d = sizes.get(id)) != null ? _d : getItemSize(state, id, i, data[i]);
2501
+ const id = (_e = idCache[i]) != null ? _e : getId(state, i);
2502
+ const size = (_f = sizes.get(id)) != null ? _f : getItemSize(ctx, state, id, i, data[i]);
2527
2503
  const top = positions.get(id);
2528
2504
  if (!foundEnd) {
2529
2505
  if (startNoBuffer === null && top + size > scroll) {
@@ -2552,7 +2528,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2552
2528
  }
2553
2529
  const idsInView = [];
2554
2530
  for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
2555
- const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
2531
+ const id = (_g = idCache[i]) != null ? _g : getId(state, i);
2556
2532
  idsInView.push(id);
2557
2533
  }
2558
2534
  Object.assign(state, {
@@ -2584,7 +2560,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2584
2560
  let numContainers2 = prevNumContainers;
2585
2561
  const needNewContainers = [];
2586
2562
  for (let i = startBuffered; i <= endBuffered; i++) {
2587
- const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
2563
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
2588
2564
  if (!containerItemKeys.has(id)) {
2589
2565
  needNewContainers.push(i);
2590
2566
  }
@@ -2595,11 +2571,14 @@ function calculateItemsInView(ctx, state, params = {}) {
2595
2571
  state,
2596
2572
  stickyIndicesSet,
2597
2573
  stickyIndicesArr,
2598
- scroll,
2574
+ currentStickyIdx,
2599
2575
  needNewContainers,
2600
2576
  startBuffered,
2601
2577
  endBuffered
2602
2578
  );
2579
+ } else {
2580
+ state.activeStickyIndex = void 0;
2581
+ set$(ctx, "activeStickyIndex", void 0);
2603
2582
  }
2604
2583
  if (needNewContainers.length > 0) {
2605
2584
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
@@ -2619,7 +2598,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2619
2598
  for (let idx = 0; idx < needNewContainers.length; idx++) {
2620
2599
  const i = needNewContainers[idx];
2621
2600
  const containerIndex = availableContainers[idx];
2622
- const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
2601
+ const id = (_i = idCache[i]) != null ? _i : getId(state, i);
2623
2602
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
2624
2603
  if (oldKey && oldKey !== id) {
2625
2604
  containerItemKeys.delete(oldKey);
@@ -2633,9 +2612,10 @@ function calculateItemsInView(ctx, state, params = {}) {
2633
2612
  if (stickyIndicesSet.has(i)) {
2634
2613
  set$(ctx, `containerSticky${containerIndex}`, true);
2635
2614
  const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2636
- set$(ctx, `containerStickyOffset${containerIndex}`, createAnimatedValue(topPadding));
2615
+ set$(ctx, `containerStickyOffset${containerIndex}`, topPadding);
2637
2616
  state.stickyContainerPool.add(containerIndex);
2638
2617
  } else {
2618
+ set$(ctx, `containerSticky${containerIndex}`, false);
2639
2619
  state.stickyContainerPool.delete(containerIndex);
2640
2620
  }
2641
2621
  if (containerIndex >= numContainers2) {
@@ -2651,13 +2631,13 @@ function calculateItemsInView(ctx, state, params = {}) {
2651
2631
  }
2652
2632
  }
2653
2633
  if (stickyIndicesArr.length > 0) {
2654
- handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, pendingRemoval);
2634
+ handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2655
2635
  }
2656
2636
  let didChangePositions = false;
2657
2637
  for (let i = 0; i < numContainers; i++) {
2658
2638
  const itemKey = peek$(ctx, `containerItemKey${i}`);
2659
2639
  if (pendingRemoval.includes(i)) {
2660
- if (itemKey) {
2640
+ if (itemKey !== void 0) {
2661
2641
  containerItemKeys.delete(itemKey);
2662
2642
  }
2663
2643
  state.containerItemTypes.delete(i);
@@ -2674,11 +2654,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2674
2654
  const itemIndex = indexByKey.get(itemKey);
2675
2655
  const item = data[itemIndex];
2676
2656
  if (item !== void 0) {
2677
- const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
2678
- const position = positions.get(id);
2679
- if (position === void 0) {
2657
+ const id = (_j = idCache[itemIndex]) != null ? _j : getId(state, itemIndex);
2658
+ const positionValue = positions.get(id);
2659
+ if (positionValue === void 0) {
2680
2660
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2681
2661
  } else {
2662
+ const position = (positionValue || 0) - scrollAdjustPending;
2682
2663
  const column = columns.get(id) || 1;
2683
2664
  const prevPos = peek$(ctx, `containerPosition${i}`);
2684
2665
  const prevColumn = peek$(ctx, `containerColumn${i}`);
@@ -2691,29 +2672,161 @@ function calculateItemsInView(ctx, state, params = {}) {
2691
2672
  set$(ctx, `containerColumn${i}`, column);
2692
2673
  }
2693
2674
  if (prevData !== item && (itemsAreEqual ? !itemsAreEqual(prevData, item, itemIndex, data) : true)) {
2694
- set$(ctx, `containerItemData${i}`, data[itemIndex]);
2675
+ set$(ctx, `containerItemData${i}`, item);
2695
2676
  }
2696
2677
  }
2697
2678
  }
2698
2679
  }
2699
2680
  }
2700
- if (didChangePositions) {
2701
- set$(ctx, "lastPositionUpdate", Date.now());
2702
- }
2703
- if (!queuedInitialLayout && endBuffered !== null) {
2704
- if (checkAllSizesKnown(state)) {
2705
- setDidLayout(ctx, state);
2706
- }
2707
- }
2708
- if (viewabilityConfigCallbackPairs) {
2709
- updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
2681
+ if (didChangePositions) {
2682
+ set$(ctx, "lastPositionUpdate", Date.now());
2683
+ }
2684
+ if (!queuedInitialLayout && endBuffered !== null) {
2685
+ if (checkAllSizesKnown(state)) {
2686
+ setDidLayout(ctx, state);
2687
+ }
2688
+ }
2689
+ if (viewabilityConfigCallbackPairs) {
2690
+ updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
2691
+ }
2692
+ if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
2693
+ const item = data[nextActiveStickyIndex];
2694
+ if (item !== void 0) {
2695
+ onStickyHeaderChange({ index: nextActiveStickyIndex, item });
2696
+ }
2697
+ }
2698
+ });
2699
+ if (state.initialAnchor) {
2700
+ ensureInitialAnchor(ctx, state);
2701
+ }
2702
+ }
2703
+
2704
+ // src/core/checkActualChange.ts
2705
+ function checkActualChange(state, dataProp, previousData) {
2706
+ if (!previousData || !dataProp || dataProp.length !== previousData.length) {
2707
+ return true;
2708
+ }
2709
+ const {
2710
+ idCache,
2711
+ props: { keyExtractor }
2712
+ } = state;
2713
+ for (let i = 0; i < dataProp.length; i++) {
2714
+ if (dataProp[i] !== previousData[i]) {
2715
+ return true;
2716
+ }
2717
+ if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
2718
+ return true;
2719
+ }
2720
+ }
2721
+ return false;
2722
+ }
2723
+
2724
+ // src/core/doMaintainScrollAtEnd.ts
2725
+ function doMaintainScrollAtEnd(ctx, state, animated) {
2726
+ const {
2727
+ refScroller,
2728
+ props: { maintainScrollAtEnd }
2729
+ } = state;
2730
+ if ((state == null ? void 0 : state.isAtEnd) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
2731
+ const paddingTop = peek$(ctx, "alignItemsPaddingTop");
2732
+ if (paddingTop > 0) {
2733
+ state.scroll = 0;
2734
+ }
2735
+ requestAnimationFrame(() => {
2736
+ var _a3;
2737
+ if (state == null ? void 0 : state.isAtEnd) {
2738
+ state.maintainingScrollAtEnd = true;
2739
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
2740
+ animated
2741
+ });
2742
+ setTimeout(
2743
+ () => {
2744
+ state.maintainingScrollAtEnd = false;
2745
+ },
2746
+ 0
2747
+ );
2748
+ }
2749
+ });
2750
+ return true;
2751
+ }
2752
+ return false;
2753
+ }
2754
+
2755
+ // src/utils/updateAveragesOnDataChange.ts
2756
+ function updateAveragesOnDataChange(state, oldData, newData) {
2757
+ var _a3;
2758
+ const {
2759
+ averageSizes,
2760
+ sizesKnown,
2761
+ indexByKey,
2762
+ props: { itemsAreEqual, getItemType, keyExtractor }
2763
+ } = state;
2764
+ if (!itemsAreEqual || !oldData.length || !newData.length) {
2765
+ for (const key in averageSizes) {
2766
+ delete averageSizes[key];
2767
+ }
2768
+ return;
2769
+ }
2770
+ const itemTypesToPreserve = {};
2771
+ const newDataLength = newData.length;
2772
+ const oldDataLength = oldData.length;
2773
+ for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
2774
+ const newItem = newData[newIndex];
2775
+ const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
2776
+ const oldIndex = indexByKey.get(id);
2777
+ if (oldIndex !== void 0 && oldIndex < oldDataLength) {
2778
+ const knownSize = sizesKnown.get(id);
2779
+ if (knownSize === void 0) continue;
2780
+ const oldItem = oldData[oldIndex];
2781
+ const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
2782
+ if (areEqual) {
2783
+ const itemType = getItemType ? (_a3 = getItemType(newItem, newIndex)) != null ? _a3 : "" : "";
2784
+ let typeData = itemTypesToPreserve[itemType];
2785
+ if (!typeData) {
2786
+ typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
2787
+ }
2788
+ typeData.totalSize += knownSize;
2789
+ typeData.count++;
2790
+ }
2791
+ }
2792
+ }
2793
+ for (const key in averageSizes) {
2794
+ delete averageSizes[key];
2795
+ }
2796
+ for (const itemType in itemTypesToPreserve) {
2797
+ const { totalSize, count } = itemTypesToPreserve[itemType];
2798
+ if (count > 0) {
2799
+ averageSizes[itemType] = {
2800
+ avg: totalSize / count,
2801
+ num: count
2802
+ };
2710
2803
  }
2711
- });
2804
+ }
2805
+ }
2806
+
2807
+ // src/core/checkResetContainers.ts
2808
+ function checkResetContainers(ctx, state, dataProp) {
2809
+ const { previousData } = state;
2810
+ if (previousData) {
2811
+ updateAveragesOnDataChange(state, previousData, dataProp);
2812
+ }
2813
+ const { maintainScrollAtEnd } = state.props;
2814
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2815
+ const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
2816
+ const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state, false);
2817
+ if (!didMaintainScrollAtEnd && previousData && dataProp.length > previousData.length) {
2818
+ state.isEndReached = false;
2819
+ }
2820
+ if (!didMaintainScrollAtEnd) {
2821
+ checkAtTop(state);
2822
+ checkAtBottom(ctx, state);
2823
+ }
2824
+ delete state.previousData;
2712
2825
  }
2713
2826
 
2714
2827
  // src/core/doInitialAllocateContainers.ts
2715
2828
  function doInitialAllocateContainers(ctx, state) {
2716
- var _a;
2829
+ var _a3, _b, _c;
2717
2830
  const {
2718
2831
  scrollLength,
2719
2832
  props: {
@@ -2729,12 +2842,13 @@ function doInitialAllocateContainers(ctx, state) {
2729
2842
  const hasContainers = peek$(ctx, "numContainers");
2730
2843
  if (scrollLength > 0 && data.length > 0 && !hasContainers) {
2731
2844
  let averageItemSize;
2732
- const fn = getFixedItemSize || getEstimatedItemSize;
2733
- if (fn) {
2845
+ if (getFixedItemSize || getEstimatedItemSize) {
2734
2846
  let totalSize = 0;
2735
2847
  const num = Math.min(20, data.length);
2736
2848
  for (let i = 0; i < num; i++) {
2737
- totalSize += fn(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "");
2849
+ const item = data[i];
2850
+ const itemType = getItemType ? (_a3 = getItemType(item, i)) != null ? _a3 : "" : "";
2851
+ totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(i, item, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(i, item, itemType)) != null ? _c : estimatedItemSize;
2738
2852
  }
2739
2853
  averageItemSize = totalSize / num;
2740
2854
  } else {
@@ -2748,76 +2862,18 @@ function doInitialAllocateContainers(ctx, state) {
2748
2862
  set$(ctx, "numContainers", numContainers);
2749
2863
  set$(ctx, "numContainersPooled", numContainers * state.props.initialContainerPoolRatio);
2750
2864
  if (state.lastLayout) {
2751
- if (state.props.initialScroll) {
2865
+ if (state.initialScroll) {
2752
2866
  requestAnimationFrame(() => {
2753
- calculateItemsInView(ctx, state, { dataChanged: true });
2867
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2754
2868
  });
2755
2869
  } else {
2756
- calculateItemsInView(ctx, state, { dataChanged: true });
2870
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2757
2871
  }
2758
2872
  }
2759
2873
  return true;
2760
2874
  }
2761
2875
  }
2762
2876
 
2763
- // src/core/doMaintainScrollAtEnd.ts
2764
- function doMaintainScrollAtEnd(ctx, state, animated) {
2765
- const {
2766
- refScroller,
2767
- props: { maintainScrollAtEnd }
2768
- } = state;
2769
- if ((state == null ? void 0 : state.isAtEnd) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
2770
- const paddingTop = peek$(ctx, "alignItemsPaddingTop");
2771
- if (paddingTop > 0) {
2772
- state.scroll = 0;
2773
- }
2774
- requestAnimationFrame(() => {
2775
- var _a;
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
- }
2788
- });
2789
- return true;
2790
- }
2791
- }
2792
-
2793
- // src/utils/checkAtTop.ts
2794
- function checkAtTop(state) {
2795
- if (!state) {
2796
- return;
2797
- }
2798
- const {
2799
- scrollLength,
2800
- scroll,
2801
- props: { onStartReachedThreshold }
2802
- } = state;
2803
- const distanceFromTop = scroll;
2804
- state.isAtStart = distanceFromTop <= 0;
2805
- state.isStartReached = checkThreshold(
2806
- distanceFromTop,
2807
- false,
2808
- onStartReachedThreshold * scrollLength,
2809
- state.isStartReached,
2810
- state.startReachedBlockedByTimer,
2811
- (distance) => {
2812
- var _a, _b;
2813
- return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
2814
- },
2815
- (block) => {
2816
- state.startReachedBlockedByTimer = block;
2817
- }
2818
- );
2819
- }
2820
-
2821
2877
  // src/core/handleLayout.ts
2822
2878
  function handleLayout(ctx, state, layout, setCanRender) {
2823
2879
  const { maintainScrollAtEnd } = state.props;
@@ -2852,19 +2908,19 @@ function handleLayout(ctx, state, layout, setCanRender) {
2852
2908
  if (state) {
2853
2909
  state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2854
2910
  }
2855
- if (__DEV__ && measuredLength === 0) {
2911
+ if (IS_DEV && measuredLength === 0) {
2856
2912
  warnDevOnce(
2857
2913
  "height0",
2858
2914
  `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
2915
  );
2860
2916
  }
2861
- setCanRender(true);
2862
2917
  }
2918
+ setCanRender(true);
2863
2919
  }
2864
2920
 
2865
2921
  // src/core/onScroll.ts
2866
2922
  function onScroll(ctx, state, event) {
2867
- var _a, _b, _c;
2923
+ var _a3, _b, _c;
2868
2924
  const {
2869
2925
  scrollProcessingEnabled,
2870
2926
  props: { onScroll: onScrollProp }
@@ -2872,67 +2928,51 @@ function onScroll(ctx, state, event) {
2872
2928
  if (scrollProcessingEnabled === false) {
2873
2929
  return;
2874
2930
  }
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) {
2931
+ if (((_b = (_a3 = event.nativeEvent) == null ? void 0 : _a3.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
2876
2932
  return;
2877
2933
  }
2878
2934
  const newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
2879
- const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
2880
- if (ignoreScrollFromMVCP && !state.scrollingTo) {
2881
- const { lt, gt } = ignoreScrollFromMVCP;
2882
- if (lt && newScroll < lt || gt && newScroll > gt) {
2883
- return;
2884
- }
2885
- }
2886
2935
  state.scrollPending = newScroll;
2887
- {
2888
- if (!state.onScrollRafScheduled) {
2889
- state.onScrollRafScheduled = true;
2890
- requestAnimationFrame(() => {
2891
- state.onScrollRafScheduled = false;
2892
- updateScroll(ctx, state, newScroll);
2893
- });
2894
- }
2895
- }
2936
+ updateScroll(ctx, state, newScroll);
2896
2937
  onScrollProp == null ? void 0 : onScrollProp(event);
2897
2938
  }
2898
- function updateScroll(ctx, state, newScroll) {
2899
- const scrollingTo = state.scrollingTo;
2900
- state.hasScrolled = true;
2901
- state.lastBatchingAction = Date.now();
2902
- const currentTime = Date.now();
2903
- if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
2904
- const adjust = state.scrollAdjustHandler.getAdjust();
2905
- state.scrollHistory.push({ scroll: newScroll - adjust, time: currentTime });
2906
- }
2907
- if (state.scrollHistory.length > 5) {
2908
- state.scrollHistory.shift();
2909
- }
2910
- state.scrollPrev = state.scroll;
2911
- state.scrollPrevTime = state.scrollTime;
2912
- state.scroll = newScroll;
2913
- state.scrollTime = currentTime;
2914
- if (Math.abs(state.scroll - state.scrollPrev) > 2) {
2915
- calculateItemsInView(ctx, state);
2916
- checkAtBottom(ctx, state);
2917
- checkAtTop(state);
2918
- }
2919
- }
2920
2939
 
2921
2940
  // src/core/ScrollAdjustHandler.ts
2922
2941
  var ScrollAdjustHandler = class {
2923
2942
  constructor(ctx) {
2924
2943
  this.appliedAdjust = 0;
2944
+ this.pendingAdjust = 0;
2925
2945
  this.mounted = false;
2926
2946
  this.context = ctx;
2947
+ {
2948
+ const commitPendingAdjust = () => {
2949
+ const state = this.context.internalState;
2950
+ const pending = this.pendingAdjust;
2951
+ if (pending !== 0) {
2952
+ this.pendingAdjust = 0;
2953
+ this.appliedAdjust += pending;
2954
+ state.scroll += pending;
2955
+ state.scrollForNextCalculateItemsInView = void 0;
2956
+ set$(this.context, "scrollAdjustPending", 0);
2957
+ set$(this.context, "scrollAdjust", this.appliedAdjust);
2958
+ calculateItemsInView(this.context, this.context.internalState);
2959
+ }
2960
+ };
2961
+ listen$(this.context, "scrollingTo", (value) => {
2962
+ if (value === void 0) {
2963
+ commitPendingAdjust();
2964
+ }
2965
+ });
2966
+ }
2927
2967
  }
2928
2968
  requestAdjust(add) {
2929
- const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
2930
- this.appliedAdjust = add + oldAdjustTop;
2931
- const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
2932
- if (this.mounted) {
2933
- set();
2969
+ const scrollingTo = peek$(this.context, "scrollingTo");
2970
+ if ((scrollingTo == null ? void 0 : scrollingTo.animated) && !scrollingTo.isInitialScroll) {
2971
+ this.pendingAdjust += add;
2972
+ set$(this.context, "scrollAdjustPending", this.pendingAdjust);
2934
2973
  } else {
2935
- requestAnimationFrame(set);
2974
+ this.appliedAdjust += add;
2975
+ set$(this.context, "scrollAdjust", this.appliedAdjust);
2936
2976
  }
2937
2977
  }
2938
2978
  setMounted() {
@@ -2945,14 +2985,13 @@ var ScrollAdjustHandler = class {
2945
2985
 
2946
2986
  // src/core/updateItemSize.ts
2947
2987
  function updateItemSize(ctx, state, itemKey, sizeObj) {
2948
- var _a, _b;
2988
+ var _a3;
2949
2989
  const {
2950
2990
  sizesKnown,
2951
2991
  props: {
2952
2992
  getFixedItemSize,
2953
2993
  getItemType,
2954
2994
  horizontal,
2955
- maintainVisibleContentPosition,
2956
2995
  suggestEstimatedItemSize,
2957
2996
  onItemSizeChanged,
2958
2997
  data,
@@ -2960,17 +2999,17 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2960
2999
  }
2961
3000
  } = state;
2962
3001
  if (!data) return;
3002
+ const index = state.indexByKey.get(itemKey);
2963
3003
  if (getFixedItemSize) {
2964
- const index2 = state.indexByKey.get(itemKey);
2965
- if (index2 === void 0) {
3004
+ if (index === void 0) {
2966
3005
  return;
2967
3006
  }
2968
- const itemData = state.props.data[index2];
3007
+ const itemData = state.props.data[index];
2969
3008
  if (itemData === void 0) {
2970
3009
  return;
2971
3010
  }
2972
- const type = getItemType ? (_a = getItemType(itemData, index2)) != null ? _a : "" : "";
2973
- const size2 = getFixedItemSize(index2, itemData, type);
3011
+ const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
3012
+ const size2 = getFixedItemSize(index, itemData, type);
2974
3013
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
2975
3014
  return;
2976
3015
  }
@@ -2980,15 +3019,11 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2980
3019
  let shouldMaintainScrollAtEnd = false;
2981
3020
  let minIndexSizeChanged;
2982
3021
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2983
- const index = state.indexByKey.get(itemKey);
2984
3022
  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;
3023
+ const diff = updateOneItemSize(ctx, state, itemKey, sizeObj);
3024
+ const size = roundSize(horizontal ? sizeObj.width : sizeObj.height);
2987
3025
  if (diff !== 0) {
2988
3026
  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
3027
  const { startBuffered, endBuffered } = state;
2993
3028
  needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2994
3029
  if (!needsRecalculate) {
@@ -3018,13 +3053,13 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
3018
3053
  if (minIndexSizeChanged !== void 0) {
3019
3054
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
3020
3055
  }
3021
- if (__DEV__ && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
3056
+ if (IS_DEV && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
3022
3057
  if (state.timeoutSizeMessage) clearTimeout(state.timeoutSizeMessage);
3023
3058
  state.timeoutSizeMessage = setTimeout(() => {
3024
- var _a2;
3059
+ var _a4;
3025
3060
  state.timeoutSizeMessage = void 0;
3026
3061
  const num = state.sizesKnown.size;
3027
- const avg = (_a2 = state.averageSizes[""]) == null ? void 0 : _a2.avg;
3062
+ const avg = (_a4 = state.averageSizes[""]) == null ? void 0 : _a4.avg;
3028
3063
  console.warn(
3029
3064
  `[legend-list] Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`
3030
3065
  );
@@ -3046,8 +3081,8 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
3046
3081
  }
3047
3082
  }
3048
3083
  }
3049
- function updateOneItemSize(state, itemKey, sizeObj) {
3050
- var _a;
3084
+ function updateOneItemSize(ctx, state, itemKey, sizeObj) {
3085
+ var _a3;
3051
3086
  const {
3052
3087
  sizes,
3053
3088
  indexByKey,
@@ -3057,12 +3092,12 @@ function updateOneItemSize(state, itemKey, sizeObj) {
3057
3092
  } = state;
3058
3093
  if (!data) return 0;
3059
3094
  const index = indexByKey.get(itemKey);
3060
- const prevSize = getItemSize(state, itemKey, index, data);
3095
+ const prevSize = getItemSize(ctx, state, itemKey, index, data[index]);
3061
3096
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
3062
3097
  const size = Math.round(rawSize) ;
3063
3098
  sizesKnown.set(itemKey, size);
3064
3099
  if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
3065
- const itemType = getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : "";
3100
+ const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
3066
3101
  let averages = averageSizes[itemType];
3067
3102
  if (!averages) {
3068
3103
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -3071,7 +3106,7 @@ function updateOneItemSize(state, itemKey, sizeObj) {
3071
3106
  averages.num++;
3072
3107
  }
3073
3108
  if (!prevSize || Math.abs(prevSize - size) > 0.1) {
3074
- sizes.set(itemKey, size);
3109
+ setSize(ctx, state, itemKey, size);
3075
3110
  return size - prevSize;
3076
3111
  }
3077
3112
  return 0;
@@ -3093,18 +3128,12 @@ var useCombinedRef = (...refs) => {
3093
3128
  };
3094
3129
 
3095
3130
  // src/platform/RefreshControl.tsx
3096
- function RefreshControl(props) {
3131
+ function RefreshControl(_props) {
3097
3132
  return null;
3098
3133
  }
3099
3134
 
3100
- // src/platform/StyleSheet.tsx
3101
- var StyleSheet = {
3102
- create: (styles) => styles,
3103
- flatten: (style) => style
3104
- };
3105
-
3106
3135
  // src/platform/useStickyScrollHandler.ts
3107
- function useStickyScrollHandler(stickyIndices, horizontal, ctx, onScroll2) {
3136
+ function useStickyScrollHandler(_stickyHeaderIndices, _horizontal, _ctx, onScroll2) {
3108
3137
  return onScroll2;
3109
3138
  }
3110
3139
 
@@ -3122,8 +3151,93 @@ function createColumnWrapperStyle(contentContainerStyle) {
3122
3151
  };
3123
3152
  }
3124
3153
  }
3154
+
3155
+ // src/utils/createImperativeHandle.ts
3156
+ function createImperativeHandle(ctx, state) {
3157
+ const scrollIndexIntoView = (options) => {
3158
+ if (state) {
3159
+ const { index, ...rest } = options;
3160
+ const { startNoBuffer, endNoBuffer } = state;
3161
+ if (index < startNoBuffer || index > endNoBuffer) {
3162
+ const viewPosition = index < startNoBuffer ? 0 : 1;
3163
+ scrollToIndex(ctx, state, {
3164
+ ...rest,
3165
+ index,
3166
+ viewPosition
3167
+ });
3168
+ }
3169
+ }
3170
+ };
3171
+ const refScroller = state.refScroller;
3172
+ return {
3173
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
3174
+ getNativeScrollRef: () => refScroller.current,
3175
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
3176
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
3177
+ getState: () => ({
3178
+ activeStickyIndex: state.activeStickyIndex,
3179
+ contentLength: state.totalSize,
3180
+ data: state.props.data,
3181
+ elementAtIndex: (index) => {
3182
+ var _a3;
3183
+ return (_a3 = ctx.viewRefs.get(findContainerId(ctx, getId(state, index)))) == null ? void 0 : _a3.current;
3184
+ },
3185
+ end: state.endNoBuffer,
3186
+ endBuffered: state.endBuffered,
3187
+ isAtEnd: state.isAtEnd,
3188
+ isAtStart: state.isAtStart,
3189
+ positionAtIndex: (index) => state.positions.get(getId(state, index)),
3190
+ positions: state.positions,
3191
+ scroll: state.scroll,
3192
+ scrollLength: state.scrollLength,
3193
+ sizeAtIndex: (index) => state.sizesKnown.get(getId(state, index)),
3194
+ sizes: state.sizesKnown,
3195
+ start: state.startNoBuffer,
3196
+ startBuffered: state.startBuffered
3197
+ }),
3198
+ scrollIndexIntoView,
3199
+ scrollItemIntoView: ({ item, ...props }) => {
3200
+ const data = state.props.data;
3201
+ const index = data.indexOf(item);
3202
+ if (index !== -1) {
3203
+ scrollIndexIntoView({ index, ...props });
3204
+ }
3205
+ },
3206
+ scrollToEnd: (options) => {
3207
+ const data = state.props.data;
3208
+ const stylePaddingBottom = state.props.stylePaddingBottom;
3209
+ const index = data.length - 1;
3210
+ if (index !== -1) {
3211
+ const paddingBottom = stylePaddingBottom || 0;
3212
+ const footerSize = peek$(ctx, "footerSize") || 0;
3213
+ scrollToIndex(ctx, state, {
3214
+ index,
3215
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
3216
+ viewPosition: 1,
3217
+ ...options
3218
+ });
3219
+ }
3220
+ },
3221
+ scrollToIndex: (params) => scrollToIndex(ctx, state, params),
3222
+ scrollToItem: ({ item, ...props }) => {
3223
+ const data = state.props.data;
3224
+ const index = data.indexOf(item);
3225
+ if (index !== -1) {
3226
+ scrollToIndex(ctx, state, { index, ...props });
3227
+ }
3228
+ },
3229
+ scrollToOffset: (params) => scrollTo(ctx, state, params),
3230
+ setScrollProcessingEnabled: (enabled) => {
3231
+ state.scrollProcessingEnabled = enabled;
3232
+ },
3233
+ setVisibleContentAnchorOffset: (value) => {
3234
+ const val = isFunction(value) ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
3235
+ set$(ctx, "scrollAdjustUserOffset", val);
3236
+ }
3237
+ };
3238
+ }
3125
3239
  function getRenderedItem(ctx, state, key) {
3126
- var _a;
3240
+ var _a3;
3127
3241
  if (!state) {
3128
3242
  return null;
3129
3243
  }
@@ -3136,13 +3250,15 @@ function getRenderedItem(ctx, state, key) {
3136
3250
  return null;
3137
3251
  }
3138
3252
  let renderedItem = null;
3139
- if (renderItem && data[index]) {
3253
+ const extraData = peek$(ctx, "extraData");
3254
+ const item = data[index];
3255
+ if (renderItem && !isNullOrUndefined(item)) {
3140
3256
  const itemProps = {
3141
3257
  data,
3142
- extraData: peek$(ctx, "extraData"),
3258
+ extraData,
3143
3259
  index,
3144
- item: data[index],
3145
- type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
3260
+ item,
3261
+ type: getItemType ? (_a3 = getItemType(item, index)) != null ? _a3 : "" : ""
3146
3262
  };
3147
3263
  renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React3__default.createElement(renderItem, itemProps);
3148
3264
  }
@@ -3194,58 +3310,6 @@ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
3194
3310
  return (event) => throttle(originalHandler, scrollEventThrottle, { nativeEvent: event.nativeEvent });
3195
3311
  }
3196
3312
 
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
- }
3248
-
3249
3313
  // src/components/LegendList.tsx
3250
3314
  var DEFAULT_DRAW_DISTANCE = 250;
3251
3315
  var DEFAULT_ITEM_SIZE = 100;
@@ -3266,11 +3330,13 @@ var LegendList = typedMemo(
3266
3330
  })
3267
3331
  );
3268
3332
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
3333
+ var _a3, _b;
3269
3334
  const {
3270
3335
  alignItemsAtEnd = false,
3271
3336
  columnWrapperStyle,
3272
3337
  contentContainerStyle: contentContainerStyleProp,
3273
3338
  data: dataProp = [],
3339
+ dataVersion,
3274
3340
  drawDistance = 250,
3275
3341
  enableAverages = true,
3276
3342
  estimatedItemSize: estimatedItemSizeProp,
@@ -3281,6 +3347,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3281
3347
  getItemType,
3282
3348
  horizontal,
3283
3349
  initialContainerPoolRatio = 2,
3350
+ initialScrollAtEnd = false,
3284
3351
  initialScrollIndex: initialScrollIndexProp,
3285
3352
  initialScrollOffset: initialScrollOffsetProp,
3286
3353
  itemsAreEqual,
@@ -3289,7 +3356,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3289
3356
  ListHeaderComponent,
3290
3357
  maintainScrollAtEnd = false,
3291
3358
  maintainScrollAtEndThreshold = 0.1,
3292
- maintainVisibleContentPosition = true,
3359
+ maintainVisibleContentPosition = false,
3293
3360
  numColumns: numColumnsProp = 1,
3294
3361
  onEndReached,
3295
3362
  onEndReachedThreshold = 0.5,
@@ -3301,6 +3368,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3301
3368
  onScroll: onScrollProp,
3302
3369
  onStartReached,
3303
3370
  onStartReachedThreshold = 0.5,
3371
+ onStickyHeaderChange,
3372
+ onViewableItemsChanged,
3304
3373
  progressViewOffset,
3305
3374
  recycleItems = false,
3306
3375
  refreshControl,
@@ -3309,19 +3378,22 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3309
3378
  renderItem,
3310
3379
  scrollEventThrottle,
3311
3380
  snapToIndices,
3312
- stickyIndices,
3381
+ stickyHeaderIndices: stickyHeaderIndicesProp,
3382
+ stickyIndices: stickyIndicesDeprecated,
3313
3383
  style: styleProp,
3314
3384
  suggestEstimatedItemSize,
3385
+ viewabilityConfig,
3386
+ viewabilityConfigCallbackPairs,
3315
3387
  waitForInitialLayout = true,
3316
3388
  ...rest
3317
3389
  } = props;
3318
- const [renderNum, setRenderNum] = useState(0);
3319
- const initialScroll = initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
3320
- const [canRender, setCanRender] = React3.useState(!IsNewArchitecture);
3321
3390
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
3322
3391
  const style = { ...StyleSheet.flatten(styleProp) };
3323
3392
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
3324
3393
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
3394
+ const [renderNum, setRenderNum] = useState(0);
3395
+ const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
3396
+ const [canRender, setCanRender] = React3.useState(!IsNewArchitecture);
3325
3397
  const ctx = useStateContext();
3326
3398
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
3327
3399
  const refScroller = useRef(null);
@@ -3329,6 +3401,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3329
3401
  const estimatedItemSize = estimatedItemSizeProp != null ? estimatedItemSizeProp : DEFAULT_ITEM_SIZE;
3330
3402
  const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
3331
3403
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
3404
+ const stickyHeaderIndices = stickyHeaderIndicesProp != null ? stickyHeaderIndicesProp : stickyIndicesDeprecated;
3405
+ if (IS_DEV && stickyIndicesDeprecated && !stickyHeaderIndicesProp) {
3406
+ warnDevOnce(
3407
+ "stickyIndices",
3408
+ "stickyIndices has been renamed to stickyHeaderIndices. Please update your props to use stickyHeaderIndices."
3409
+ );
3410
+ }
3332
3411
  const refState = useRef();
3333
3412
  if (!refState.current) {
3334
3413
  if (!ctx.internalState) {
@@ -3339,18 +3418,29 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3339
3418
  columns: /* @__PURE__ */ new Map(),
3340
3419
  containerItemKeys: /* @__PURE__ */ new Set(),
3341
3420
  containerItemTypes: /* @__PURE__ */ new Map(),
3421
+ dataChangeNeedsScrollUpdate: false,
3422
+ didColumnsChange: false,
3423
+ didDataChange: false,
3342
3424
  enableScrollForNextCalculateItemsInView: true,
3343
3425
  endBuffered: -1,
3344
3426
  endNoBuffer: -1,
3345
- endReachedBlockedByTimer: false,
3427
+ endReachedSnapshot: void 0,
3346
3428
  firstFullyOnScreenIndex: -1,
3347
- idCache: /* @__PURE__ */ new Map(),
3429
+ idCache: [],
3348
3430
  idsInView: [],
3349
3431
  indexByKey: /* @__PURE__ */ new Map(),
3350
- initialScroll,
3432
+ initialAnchor: (initialScrollProp == null ? void 0 : initialScrollProp.index) !== void 0 && (initialScrollProp == null ? void 0 : initialScrollProp.viewPosition) !== void 0 ? {
3433
+ attempts: 0,
3434
+ index: initialScrollProp.index,
3435
+ settledTicks: 0,
3436
+ viewOffset: (_a3 = initialScrollProp.viewOffset) != null ? _a3 : 0,
3437
+ viewPosition: initialScrollProp.viewPosition
3438
+ } : void 0,
3439
+ initialScroll: initialScrollProp,
3351
3440
  isAtEnd: false,
3352
3441
  isAtStart: false,
3353
3442
  isEndReached: false,
3443
+ isFirst: true,
3354
3444
  isStartReached: false,
3355
3445
  lastBatchingAction: Date.now(),
3356
3446
  lastLayout: void 0,
@@ -3375,7 +3465,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3375
3465
  sizesKnown: /* @__PURE__ */ new Map(),
3376
3466
  startBuffered: -1,
3377
3467
  startNoBuffer: -1,
3378
- startReachedBlockedByTimer: false,
3468
+ startReachedSnapshot: void 0,
3379
3469
  stickyContainerPool: /* @__PURE__ */ new Set(),
3380
3470
  stickyContainers: /* @__PURE__ */ new Map(),
3381
3471
  timeoutSizeMessage: 0,
@@ -3383,21 +3473,27 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3383
3473
  totalSize: 0,
3384
3474
  viewabilityConfigCallbackPairs: void 0
3385
3475
  };
3476
+ const internalState = ctx.internalState;
3477
+ internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, internalState, params);
3386
3478
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
3387
3479
  set$(ctx, "extraData", extraData);
3388
3480
  }
3389
3481
  refState.current = ctx.internalState;
3390
3482
  }
3391
3483
  const state = refState.current;
3392
- const isFirst = !state.props.renderItem;
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
- );
3484
+ const isFirstLocal = state.isFirst;
3485
+ state.didColumnsChange = numColumnsProp !== state.props.numColumns;
3486
+ const didDataChangeLocal = state.props.dataVersion !== dataVersion || state.props.data !== dataProp && checkActualChange(state, dataProp, state.props.data);
3487
+ if (didDataChangeLocal) {
3488
+ state.dataChangeNeedsScrollUpdate = true;
3489
+ state.didDataChange = true;
3490
+ state.previousData = state.props.data;
3491
+ }
3492
+ const throttleScrollFn = scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp;
3398
3493
  state.props = {
3399
3494
  alignItemsAtEnd,
3400
3495
  data: dataProp,
3496
+ dataVersion,
3401
3497
  enableAverages,
3402
3498
  estimatedItemSize,
3403
3499
  getEstimatedItemSize,
@@ -3405,7 +3501,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3405
3501
  getItemType,
3406
3502
  horizontal: !!horizontal,
3407
3503
  initialContainerPoolRatio,
3408
- initialScroll,
3409
3504
  itemsAreEqual,
3410
3505
  keyExtractor,
3411
3506
  maintainScrollAtEnd,
@@ -3419,45 +3514,25 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3419
3514
  onScroll: throttleScrollFn,
3420
3515
  onStartReached,
3421
3516
  onStartReachedThreshold,
3517
+ onStickyHeaderChange,
3422
3518
  recycleItems: !!recycleItems,
3423
3519
  renderItem,
3424
3520
  scrollBuffer,
3425
3521
  snapToIndices,
3426
- stickyIndicesArr: stickyIndices != null ? stickyIndices : [],
3427
- stickyIndicesSet: useMemo(() => new Set(stickyIndices != null ? stickyIndices : []), [stickyIndices == null ? void 0 : stickyIndices.join(",")]),
3522
+ stickyIndicesArr: stickyHeaderIndices != null ? stickyHeaderIndices : [],
3523
+ stickyIndicesSet: useMemo(() => new Set(stickyHeaderIndices != null ? stickyHeaderIndices : []), [stickyHeaderIndices == null ? void 0 : stickyHeaderIndices.join(",")]),
3428
3524
  stylePaddingBottom: stylePaddingBottomState,
3429
3525
  stylePaddingTop: stylePaddingTopState,
3430
3526
  suggestEstimatedItemSize: !!suggestEstimatedItemSize
3431
3527
  };
3432
3528
  state.refScroller = refScroller;
3433
- const checkResetContainers = (isFirst2) => {
3434
- const state2 = refState.current;
3435
- if (state2) {
3436
- if (!isFirst2 && state2.props.data !== dataProp) {
3437
- updateAveragesOnDataChange(state2, state2.props.data, dataProp);
3438
- }
3439
- state2.props.data = dataProp;
3440
- if (!isFirst2) {
3441
- calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
3442
- const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
3443
- const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state2, false);
3444
- if (!didMaintainScrollAtEnd && dataProp.length > state2.props.data.length) {
3445
- state2.isEndReached = false;
3446
- }
3447
- if (!didMaintainScrollAtEnd) {
3448
- checkAtTop(state2);
3449
- checkAtBottom(ctx, state2);
3450
- }
3451
- }
3452
- }
3453
- };
3454
3529
  const memoizedLastItemKeys = useMemo(() => {
3455
3530
  if (!dataProp.length) return [];
3456
3531
  return Array.from(
3457
3532
  { length: Math.min(numColumnsProp, dataProp.length) },
3458
3533
  (_, i) => getId(state, dataProp.length - 1 - i)
3459
3534
  );
3460
- }, [dataProp, numColumnsProp]);
3535
+ }, [dataProp, dataVersion, numColumnsProp]);
3461
3536
  const initializeStateVars = () => {
3462
3537
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
3463
3538
  set$(ctx, "numColumns", numColumnsProp);
@@ -3465,44 +3540,70 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3465
3540
  setPaddingTop(ctx, state, { stylePaddingTop: stylePaddingTopState });
3466
3541
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
3467
3542
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
3468
- if (maintainVisibleContentPosition && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") {
3543
+ if (paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") {
3469
3544
  if (state.scroll < 0) {
3470
3545
  paddingDiff += state.scroll;
3471
3546
  }
3472
3547
  requestAdjust(ctx, state, paddingDiff);
3473
3548
  }
3474
3549
  };
3475
- if (isFirst) {
3550
+ if (isFirstLocal) {
3476
3551
  initializeStateVars();
3477
- updateAllPositions(ctx, state);
3552
+ updateItemPositions(
3553
+ ctx,
3554
+ state,
3555
+ /*dataChanged*/
3556
+ true
3557
+ );
3478
3558
  }
3479
3559
  const initialContentOffset = useMemo(() => {
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;
3560
+ var _a4, _b2;
3561
+ const { initialScroll } = refState.current;
3562
+ if (!initialScroll) {
3563
+ refState.current.initialAnchor = void 0;
3564
+ return 0;
3565
+ }
3566
+ if (initialScroll.index !== void 0 && (!refState.current.initialAnchor || ((_a4 = refState.current.initialAnchor) == null ? void 0 : _a4.index) !== initialScroll.index)) {
3567
+ refState.current.initialAnchor = {
3568
+ attempts: 0,
3569
+ index: initialScroll.index,
3570
+ settledTicks: 0,
3571
+ viewOffset: (_b2 = initialScroll.viewOffset) != null ? _b2 : 0,
3572
+ viewPosition: initialScroll.viewPosition
3573
+ };
3491
3574
  }
3492
- return 0;
3575
+ if (initialScroll.contentOffset !== void 0) {
3576
+ return initialScroll.contentOffset;
3577
+ }
3578
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, state, initialScroll.index) : 0;
3579
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, state, baseOffset, initialScroll);
3580
+ let clampedOffset = resolvedOffset;
3581
+ if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
3582
+ const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
3583
+ clampedOffset = Math.min(clampedOffset, maxOffset);
3584
+ }
3585
+ clampedOffset = Math.max(0, clampedOffset);
3586
+ const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3587
+ refState.current.initialScroll = updatedInitialScroll;
3588
+ state.initialScroll = updatedInitialScroll;
3589
+ refState.current.isStartReached = clampedOffset < refState.current.scrollLength * onStartReachedThreshold;
3590
+ return clampedOffset;
3493
3591
  }, [renderNum]);
3494
- if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
3495
- state.lastBatchingAction = Date.now();
3496
- if (!keyExtractorProp && !isFirst && didDataChange) {
3497
- __DEV__ && warnDevOnce(
3592
+ if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
3593
+ refState.current.lastBatchingAction = Date.now();
3594
+ if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
3595
+ IS_DEV && warnDevOnce(
3498
3596
  "keyExtractor",
3499
3597
  "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."
3500
3598
  );
3501
- state.sizes.clear();
3502
- state.positions.clear();
3599
+ refState.current.sizes.clear();
3600
+ refState.current.positions.clear();
3601
+ refState.current.totalSize = 0;
3602
+ set$(ctx, "totalSize", 0);
3503
3603
  }
3504
3604
  }
3505
3605
  const onLayoutHeader = useCallback((rect, fromLayoutEffect) => {
3606
+ const { initialScroll } = refState.current;
3506
3607
  const size = rect[horizontal ? "width" : "height"];
3507
3608
  set$(ctx, "headerSize", size);
3508
3609
  if ((initialScroll == null ? void 0 : initialScroll.index) !== void 0) {
@@ -3513,132 +3614,71 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3513
3614
  }
3514
3615
  }
3515
3616
  }, []);
3617
+ const doInitialScroll = useCallback(() => {
3618
+ var _a4;
3619
+ const initialScroll = state.initialScroll;
3620
+ if (initialScroll) {
3621
+ scrollTo(ctx, state, {
3622
+ animated: false,
3623
+ index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3624
+ isInitialScroll: true,
3625
+ offset: initialContentOffset,
3626
+ precomputedWithViewOffset: true
3627
+ });
3628
+ }
3629
+ }, [initialContentOffset]);
3630
+ const onLayoutChange = useCallback((layout) => {
3631
+ doInitialScroll();
3632
+ handleLayout(ctx, state, layout, setCanRender);
3633
+ }, []);
3634
+ const { onLayout } = useOnLayoutSync({
3635
+ onLayoutChange,
3636
+ onLayoutProp,
3637
+ ref: refScroller
3638
+ // the type of ScrollView doesn't include measure?
3639
+ });
3516
3640
  useLayoutEffect(() => {
3517
3641
  if (snapToIndices) {
3518
3642
  updateSnapToOffsets(ctx, state);
3519
3643
  }
3520
3644
  }, [snapToIndices]);
3521
3645
  useLayoutEffect(() => {
3522
- const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainersCallback();
3523
- if (!didAllocateContainers) {
3524
- checkResetContainers(
3525
- /*isFirst*/
3526
- isFirst
3527
- );
3528
- }
3529
- }, [dataProp, numColumnsProp]);
3646
+ const {
3647
+ didColumnsChange,
3648
+ didDataChange,
3649
+ isFirst,
3650
+ props: { data }
3651
+ } = state;
3652
+ const didAllocateContainers = data.length > 0 && doInitialAllocateContainers(ctx, state);
3653
+ if (!didAllocateContainers && !isFirst && (didDataChange || didColumnsChange)) {
3654
+ checkResetContainers(ctx, state, data);
3655
+ }
3656
+ state.didColumnsChange = false;
3657
+ state.didDataChange = false;
3658
+ state.isFirst = false;
3659
+ }, [dataProp, dataVersion, numColumnsProp]);
3530
3660
  useLayoutEffect(() => {
3531
3661
  set$(ctx, "extraData", extraData);
3532
3662
  }, [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
- });
3543
3663
  useLayoutEffect(initializeStateVars, [
3664
+ dataVersion,
3544
3665
  memoizedLastItemKeys.join(","),
3545
3666
  numColumnsProp,
3546
- stylePaddingTopState,
3547
- stylePaddingBottomState
3667
+ stylePaddingBottomState,
3668
+ stylePaddingTopState
3548
3669
  ]);
3549
- const doInitialAllocateContainersCallback = () => {
3550
- return doInitialAllocateContainers(ctx, state);
3551
- };
3552
- useImperativeHandle(forwardedRef, () => {
3553
- const scrollIndexIntoView = (options) => {
3554
- const state2 = refState.current;
3555
- if (state2) {
3556
- const { index, ...rest2 } = options;
3557
- const { startNoBuffer, endNoBuffer } = state2;
3558
- if (index < startNoBuffer || index > endNoBuffer) {
3559
- const viewPosition = index < startNoBuffer ? 0 : 1;
3560
- scrollToIndex(ctx, state2, {
3561
- ...rest2,
3562
- index,
3563
- viewPosition
3564
- });
3565
- }
3566
- }
3567
- };
3568
- return {
3569
- flashScrollIndicators: () => {
3570
- var _a, _b;
3571
- return (_b = (_a = refScroller.current) == null ? void 0 : _a.flashScrollIndicators) == null ? void 0 : _b.call(_a);
3572
- },
3573
- getNativeScrollRef: () => refScroller.current,
3574
- getScrollableNode: () => refScroller.current,
3575
- getScrollResponder: () => refScroller.current,
3576
- getState: () => {
3577
- const state2 = refState.current;
3578
- return state2 ? {
3579
- contentLength: state2.totalSize,
3580
- data: state2.props.data,
3581
- end: state2.endNoBuffer,
3582
- endBuffered: state2.endBuffered,
3583
- isAtEnd: state2.isAtEnd,
3584
- isAtStart: state2.isAtStart,
3585
- positionAtIndex: (index) => state2.positions.get(getId(state2, index)),
3586
- positions: state2.positions,
3587
- scroll: state2.scroll,
3588
- scrollLength: state2.scrollLength,
3589
- sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index)),
3590
- sizes: state2.sizesKnown,
3591
- start: state2.startNoBuffer,
3592
- startBuffered: state2.startBuffered
3593
- } : {};
3594
- },
3595
- scrollIndexIntoView,
3596
- scrollItemIntoView: ({ item, ...props2 }) => {
3597
- const data = refState.current.props.data;
3598
- const index = data.indexOf(item);
3599
- if (index !== -1) {
3600
- scrollIndexIntoView({ index, ...props2 });
3601
- }
3602
- },
3603
- scrollToEnd: (options) => {
3604
- const data = refState.current.props.data;
3605
- const stylePaddingBottom = refState.current.props.stylePaddingBottom;
3606
- const index = data.length - 1;
3607
- if (index !== -1) {
3608
- const paddingBottom = stylePaddingBottom || 0;
3609
- const footerSize = peek$(ctx, "footerSize") || 0;
3610
- scrollToIndex(ctx, state, {
3611
- index,
3612
- viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
3613
- viewPosition: 1,
3614
- ...options
3615
- });
3616
- }
3617
- },
3618
- scrollToIndex: (params) => scrollToIndex(ctx, state, params),
3619
- scrollToItem: ({ item, ...props2 }) => {
3620
- const data = refState.current.props.data;
3621
- const index = data.indexOf(item);
3622
- if (index !== -1) {
3623
- scrollToIndex(ctx, state, { index, ...props2 });
3624
- }
3625
- },
3626
- scrollToOffset: (params) => scrollTo(state, params),
3627
- setScrollProcessingEnabled: (enabled) => {
3628
- refState.current.scrollProcessingEnabled = enabled;
3629
- },
3630
- setVisibleContentAnchorOffset: (value) => {
3631
- const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
3632
- set$(ctx, "scrollAdjustUserOffset", val);
3633
- }
3634
- };
3635
- }, []);
3670
+ useEffect(() => {
3671
+ const viewability = setupViewability({
3672
+ onViewableItemsChanged,
3673
+ viewabilityConfig,
3674
+ viewabilityConfigCallbackPairs
3675
+ });
3676
+ state.viewabilityConfigCallbackPairs = viewability;
3677
+ state.enableScrollForNextCalculateItemsInView = !viewability;
3678
+ }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
3679
+ useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, state), []);
3636
3680
  {
3637
- useEffect(() => {
3638
- if (initialContentOffset) {
3639
- scrollTo(state, { animated: false, offset: initialContentOffset });
3640
- }
3641
- }, []);
3681
+ useEffect(doInitialScroll, []);
3642
3682
  }
3643
3683
  const fns = useMemo(
3644
3684
  () => ({
@@ -3648,7 +3688,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3648
3688
  }),
3649
3689
  []
3650
3690
  );
3651
- const onScrollHandler = useStickyScrollHandler(stickyIndices, horizontal, ctx, fns.onScroll);
3691
+ const onScrollHandler = useStickyScrollHandler(stickyHeaderIndices, horizontal, ctx, fns.onScroll);
3652
3692
  return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
3653
3693
  ListComponent,
3654
3694
  {
@@ -3667,7 +3707,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3667
3707
  onMomentumScrollEnd: (event) => {
3668
3708
  {
3669
3709
  requestAnimationFrame(() => {
3670
- finishScrollTo(refState.current);
3710
+ finishScrollTo(ctx, refState.current);
3671
3711
  });
3672
3712
  }
3673
3713
  if (onMomentumScrollEnd) {
@@ -3687,38 +3727,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3687
3727
  }
3688
3728
  ),
3689
3729
  refScrollView: combinedRef,
3690
- scrollAdjustHandler: state.scrollAdjustHandler,
3730
+ scrollAdjustHandler: (_b = refState.current) == null ? void 0 : _b.scrollAdjustHandler,
3731
+ scrollEventThrottle: 16 ,
3691
3732
  snapToIndices,
3692
- stickyIndices,
3733
+ stickyHeaderIndices,
3693
3734
  style,
3694
3735
  updateItemSize: fns.updateItemSize,
3695
3736
  waitForInitialLayout
3696
3737
  }
3697
- ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3.createElement(DebugView, { state: refState.current }));
3738
+ ), IS_DEV && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3.createElement(DebugView, { state: refState.current }));
3698
3739
  });
3699
- /*! Bundled license information:
3700
-
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
- */
3723
-
3724
- export { LegendList, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout2 as useSyncLayout, useViewability, useViewabilityAmount };
3740
+
3741
+ export { LegendList, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };