@legendapp/list 2.1.0-beta.0 → 2.1.0-beta.10

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,14 +1,14 @@
1
- import * as React4 from 'react';
2
- import React4__default, { forwardRef, useReducer, useEffect, createContext, useRef, useState, useMemo, useImperativeHandle, useCallback, useLayoutEffect, memo, useContext } from 'react';
1
+ import * as React3 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
4
  import { unstable_batchedUpdates } from 'react-dom';
5
5
 
6
6
  // src/components/LegendList.tsx
7
- var AnimatedView = forwardRef(function AnimatedView2(props, ref) {
8
- return /* @__PURE__ */ React4.createElement("div", { ref, ...props });
7
+ forwardRef(function AnimatedView2(props, ref) {
8
+ return /* @__PURE__ */ React3.createElement("div", { ref, ...props });
9
9
  });
10
10
  var View = forwardRef(function View2(props, ref) {
11
- return /* @__PURE__ */ React4.createElement("div", { ref, ...props });
11
+ return /* @__PURE__ */ React3.createElement("div", { ref, ...props });
12
12
  });
13
13
  var Text = View;
14
14
 
@@ -16,9 +16,9 @@ var Text = View;
16
16
  var createAnimatedValue = (value) => value;
17
17
 
18
18
  // src/state/state.tsx
19
- var ContextState = React4.createContext(null);
19
+ var ContextState = React3.createContext(null);
20
20
  function StateProvider({ children }) {
21
- const [value] = React4.useState(() => ({
21
+ const [value] = React3.useState(() => ({
22
22
  animatedScrollY: createAnimatedValue(0),
23
23
  columnWrapperStyle: void 0,
24
24
  internalState: void 0,
@@ -33,14 +33,17 @@ function StateProvider({ children }) {
33
33
  ["stylePaddingTop", 0],
34
34
  ["headerSize", 0],
35
35
  ["numContainers", 0],
36
- ["totalSize", 0]
36
+ ["activeStickyIndex", void 0],
37
+ ["totalSize", 0],
38
+ ["scrollAdjustPending", 0],
39
+ ["scrollingTo", void 0]
37
40
  ]),
38
41
  viewRefs: /* @__PURE__ */ new Map()
39
42
  }));
40
- return /* @__PURE__ */ React4.createElement(ContextState.Provider, { value }, children);
43
+ return /* @__PURE__ */ React3.createElement(ContextState.Provider, { value }, children);
41
44
  }
42
45
  function useStateContext() {
43
- return React4.useContext(ContextState);
46
+ return React3.useContext(ContextState);
44
47
  }
45
48
  function createSelectorFunctionsArr(ctx, signalNames) {
46
49
  let lastValues = [];
@@ -110,23 +113,23 @@ function getContentSize(ctx) {
110
113
  return headerSize + footerSize + totalSize + stylePaddingTop;
111
114
  }
112
115
  function useArr$(signalNames) {
113
- const ctx = React4.useContext(ContextState);
114
- const { subscribe, get } = React4.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
116
+ const ctx = React3.useContext(ContextState);
117
+ const { subscribe, get } = React3.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
115
118
  const value = useSyncExternalStore(subscribe, get);
116
119
  return value;
117
120
  }
118
121
  function useSelector$(signalName, selector) {
119
- const ctx = React4.useContext(ContextState);
120
- const { subscribe, get } = React4.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
122
+ const ctx = React3.useContext(ContextState);
123
+ const { subscribe, get } = React3.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
121
124
  const value = useSyncExternalStore(subscribe, () => selector(get()[0]));
122
125
  return value;
123
126
  }
124
127
 
125
128
  // src/components/DebugView.tsx
126
129
  var DebugRow = ({ children }) => {
127
- return /* @__PURE__ */ React4.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
130
+ return /* @__PURE__ */ React3.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
128
131
  };
129
- var DebugView = React4.memo(function DebugView2({ state }) {
132
+ var DebugView = React3.memo(function DebugView2({ state }) {
130
133
  const ctx = useStateContext();
131
134
  const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
132
135
  "totalSize",
@@ -141,7 +144,7 @@ var DebugView = React4.memo(function DebugView2({ state }) {
141
144
  useInterval(() => {
142
145
  forceUpdate();
143
146
  }, 100);
144
- return /* @__PURE__ */ React4.createElement(
147
+ return /* @__PURE__ */ React3.createElement(
145
148
  View,
146
149
  {
147
150
  pointerEvents: "none",
@@ -157,12 +160,12 @@ var DebugView = React4.memo(function DebugView2({ state }) {
157
160
  top: 0
158
161
  }
159
162
  },
160
- /* @__PURE__ */ React4.createElement(DebugRow, null, /* @__PURE__ */ React4.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React4.createElement(Text, null, totalSize.toFixed(2))),
161
- /* @__PURE__ */ React4.createElement(DebugRow, null, /* @__PURE__ */ React4.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React4.createElement(Text, null, contentSize.toFixed(2))),
162
- /* @__PURE__ */ React4.createElement(DebugRow, null, /* @__PURE__ */ React4.createElement(Text, null, "At end:"), /* @__PURE__ */ React4.createElement(Text, null, String(state.isAtEnd))),
163
- /* @__PURE__ */ React4.createElement(DebugRow, null, /* @__PURE__ */ React4.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React4.createElement(Text, null, scrollAdjust.toFixed(2))),
164
- /* @__PURE__ */ React4.createElement(DebugRow, null, /* @__PURE__ */ React4.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React4.createElement(Text, null, rawScroll.toFixed(2))),
165
- /* @__PURE__ */ React4.createElement(DebugRow, null, /* @__PURE__ */ React4.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React4.createElement(Text, null, scroll.toFixed(2)))
163
+ /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React3.createElement(Text, null, totalSize.toFixed(2))),
164
+ /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React3.createElement(Text, null, contentSize.toFixed(2))),
165
+ /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "At end:"), /* @__PURE__ */ React3.createElement(Text, null, String(state.isAtEnd))),
166
+ /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React3.createElement(Text, null, scrollAdjust.toFixed(2))),
167
+ /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React3.createElement(Text, null, rawScroll.toFixed(2))),
168
+ /* @__PURE__ */ React3.createElement(DebugRow, null, /* @__PURE__ */ React3.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React3.createElement(Text, null, scroll.toFixed(2)))
166
169
  );
167
170
  });
168
171
  function useInterval(callback, delay) {
@@ -171,93 +174,63 @@ function useInterval(callback, delay) {
171
174
  return () => clearInterval(interval);
172
175
  }, [delay]);
173
176
  }
174
- var globalResizeObserver = null;
175
- function getGlobalResizeObserver() {
176
- if (!globalResizeObserver) {
177
- globalResizeObserver = new ResizeObserver((entries) => {
178
- for (const entry of entries) {
179
- const callbacks = callbackMap.get(entry.target);
180
- if (callbacks) {
181
- for (const callback of callbacks) {
182
- callback(entry);
183
- }
184
- }
185
- }
186
- });
187
- }
188
- return globalResizeObserver;
189
- }
190
- var callbackMap = /* @__PURE__ */ new WeakMap();
191
- function useResizeObserver(element, callback) {
192
- useEffect(() => {
193
- if (!element) return;
194
- const observer = getGlobalResizeObserver();
195
- let callbacks = callbackMap.get(element);
196
- if (!callbacks) {
197
- callbacks = /* @__PURE__ */ new Set();
198
- callbackMap.set(element, callbacks);
199
- observer.observe(element);
200
- }
201
- callbacks.add(callback);
202
- return () => {
203
- const callbacks2 = callbackMap.get(element);
204
- if (callbacks2) {
205
- callbacks2.delete(callback);
206
- if (callbacks2.size === 0) {
207
- callbackMap.delete(element);
208
- observer.unobserve(element);
209
- }
210
- }
211
- };
212
- }, [element, callback]);
213
- }
214
-
215
- // src/hooks/useSyncLayout.tsx
216
- function useSyncLayout({
217
- ref,
218
- onLayoutChange
219
- }) {
220
- var _a, _b;
221
- useResizeObserver(
222
- ((_b = (_a = ref.current) == null ? void 0 : _a.getScrollableNode) == null ? void 0 : _b.call(_a)) || ref.current,
223
- useCallback(
224
- (entry) => {
225
- onLayoutChange(entry.contentRect, false);
226
- },
227
- [onLayoutChange]
228
- )
229
- );
230
- useLayoutEffect(() => {
231
- if (ref.current) {
232
- const rect = ref.current.getBoundingClientRect();
233
- onLayoutChange(
234
- {
235
- height: rect.height,
236
- width: rect.width,
237
- x: rect.left,
238
- y: rect.top
239
- },
240
- true
241
- );
242
- }
243
- }, []);
244
- return {};
245
- }
246
177
 
247
- // src/components/LayoutView.tsx
248
- var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
249
- const ref = refView != null ? refView : useRef();
250
- useSyncLayout({ onLayoutChange, ref });
251
- return /* @__PURE__ */ React4.createElement("div", { ...rest, ref }, children);
252
- };
178
+ // src/utils/devEnvironment.ts
179
+ var metroDev = typeof __DEV__ !== "undefined" ? __DEV__ : void 0;
180
+ var _a;
181
+ var envMode = typeof process !== "undefined" && typeof process.env === "object" && process.env ? (_a = process.env.NODE_ENV) != null ? _a : process.env.MODE : void 0;
182
+ var processDev = typeof envMode === "string" ? envMode.toLowerCase() !== "production" : void 0;
183
+ var _a2;
184
+ var IS_DEV = (_a2 = metroDev != null ? metroDev : processDev) != null ? _a2 : false;
253
185
 
254
186
  // src/constants.ts
255
187
  var POSITION_OUT_OF_VIEW = -1e7;
256
- var ENABLE_DEVMODE = __DEV__ && false;
257
- var ENABLE_DEBUG_VIEW = __DEV__ && false;
188
+ var ENABLE_DEVMODE = IS_DEV && false;
189
+ var ENABLE_DEBUG_VIEW = IS_DEV && false;
258
190
  var typedForwardRef = forwardRef;
259
191
  var typedMemo = memo;
260
192
 
193
+ // src/utils/helpers.ts
194
+ function isFunction(obj) {
195
+ return typeof obj === "function";
196
+ }
197
+ function isArray(obj) {
198
+ return Array.isArray(obj);
199
+ }
200
+ var warned = /* @__PURE__ */ new Set();
201
+ function warnDevOnce(id, text) {
202
+ if (IS_DEV && !warned.has(id)) {
203
+ warned.add(id);
204
+ console.warn(`[legend-list] ${text}`);
205
+ }
206
+ }
207
+ function roundSize(size) {
208
+ return Math.floor(size * 8) / 8;
209
+ }
210
+ function isNullOrUndefined(value) {
211
+ return value === null || value === void 0;
212
+ }
213
+ function comparatorDefault(a, b) {
214
+ return a - b;
215
+ }
216
+ function getPadding(s, type) {
217
+ var _a3, _b, _c;
218
+ return (_c = (_b = (_a3 = s[`padding${type}`]) != null ? _a3 : s.paddingVertical) != null ? _b : s.padding) != null ? _c : 0;
219
+ }
220
+ function extractPadding(style, contentContainerStyle, type) {
221
+ return getPadding(style, type) + getPadding(contentContainerStyle, type);
222
+ }
223
+ function findContainerId(ctx, key) {
224
+ const numContainers = peek$(ctx, "numContainers");
225
+ for (let i = 0; i < numContainers; i++) {
226
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
227
+ if (itemKey === key) {
228
+ return i;
229
+ }
230
+ }
231
+ return -1;
232
+ }
233
+
261
234
  // src/components/PositionView.tsx
262
235
  var PositionViewState = typedMemo(function PositionView({
263
236
  id,
@@ -267,9 +240,12 @@ var PositionViewState = typedMemo(function PositionView({
267
240
  ...rest
268
241
  }) {
269
242
  const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
270
- const base = Array.isArray(style) ? Object.assign({}, ...style) : style;
271
- const combinedStyle = horizontal ? { ...base, left: position } : { ...base, top: position };
272
- return /* @__PURE__ */ React4.createElement(LayoutView, { refView, style: combinedStyle, ...rest });
243
+ const base = {
244
+ contain: "paint layout style"
245
+ };
246
+ const composed = isArray(style) ? Object.assign({}, ...style) : style;
247
+ const combinedStyle = horizontal ? { ...base, ...composed, left: position } : { ...base, ...composed, top: position };
248
+ return /* @__PURE__ */ React3.createElement("div", { ref: refView, style: combinedStyle, ...rest });
273
249
  });
274
250
  var PositionViewSticky = typedMemo(function PositionViewSticky2({
275
251
  id,
@@ -277,35 +253,47 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
277
253
  style,
278
254
  refView,
279
255
  index,
256
+ stickyOffset,
257
+ animatedScrollY: _animatedScrollY,
258
+ children,
280
259
  ...rest
281
260
  }) {
282
- const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
283
- const viewStyle = React4.useMemo(() => {
284
- const base = Array.isArray(style) ? Object.assign({}, ...style) : style;
285
- const axisStyle = horizontal ? { transform: `translateX(${position}px)` } : { top: position };
286
- return {
287
- ...base,
288
- zIndex: index + 1e3,
289
- ...axisStyle
290
- };
291
- }, [style, position, horizontal, index]);
292
- return /* @__PURE__ */ React4.createElement(LayoutView, { refView, style: viewStyle, ...rest });
261
+ const [position = POSITION_OUT_OF_VIEW, headerSize = 0, activeStickyIndex] = useArr$([
262
+ `containerPosition${id}`,
263
+ "headerSize",
264
+ "activeStickyIndex"
265
+ ]);
266
+ const base = {
267
+ contain: "paint layout style"
268
+ };
269
+ const composed = React3.useMemo(
270
+ () => {
271
+ var _a3;
272
+ return (_a3 = isArray(style) ? Object.assign({}, ...style) : style) != null ? _a3 : {};
273
+ },
274
+ [style]
275
+ );
276
+ const viewStyle = React3.useMemo(() => {
277
+ var _a3;
278
+ const styleBase = { ...base, ...composed };
279
+ delete styleBase.transform;
280
+ const offset = (_a3 = stickyOffset != null ? stickyOffset : headerSize) != null ? _a3 : 0;
281
+ const isActive = activeStickyIndex === index;
282
+ styleBase.position = isActive ? "sticky" : "absolute";
283
+ styleBase.zIndex = index + 1e3;
284
+ if (horizontal) {
285
+ styleBase.left = isActive ? offset : position;
286
+ } else {
287
+ styleBase.top = isActive ? offset : position;
288
+ }
289
+ return styleBase;
290
+ }, [composed, horizontal, position, index, stickyOffset, headerSize, activeStickyIndex]);
291
+ return /* @__PURE__ */ React3.createElement("div", { ref: refView, style: viewStyle, ...rest }, children);
293
292
  });
294
293
  var PositionView2 = PositionViewState;
295
- function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
296
- const [lastItemKeys] = useArr$(["lastItemKeys"]);
297
- const isALastItem = lastItemKeys.includes(itemKey);
298
- return isALastItem ? null : /* @__PURE__ */ React4.createElement(ItemSeparatorComponent, { leadingItem });
299
- }
300
294
 
301
295
  // src/constants-platform.ts
302
296
  var IsNewArchitecture = true;
303
-
304
- // src/platform/Platform.ts
305
- var Platform = {
306
- // Widen the type to avoid unreachable-branch lints in cross-platform code that compares against other OSes
307
- OS: "web"
308
- };
309
297
  var symbolFirst = Symbol();
310
298
  function useInit(cb) {
311
299
  const refValue = useRef(symbolFirst);
@@ -315,37 +303,6 @@ function useInit(cb) {
315
303
  return refValue.current;
316
304
  }
317
305
 
318
- // src/utils/helpers.ts
319
- function isFunction(obj) {
320
- return typeof obj === "function";
321
- }
322
- function isArray(obj) {
323
- return Array.isArray(obj);
324
- }
325
- var warned = /* @__PURE__ */ new Set();
326
- function warnDevOnce(id, text) {
327
- if (__DEV__ && !warned.has(id)) {
328
- warned.add(id);
329
- console.warn(`[legend-list] ${text}`);
330
- }
331
- }
332
- function roundSize(size) {
333
- return Math.floor(size * 8) / 8;
334
- }
335
- function isNullOrUndefined(value) {
336
- return value === null || value === void 0;
337
- }
338
- function comparatorDefault(a, b) {
339
- return a - b;
340
- }
341
- function getPadding(s, type) {
342
- var _a, _b, _c;
343
- return (_c = (_b = (_a = s[`padding${type}`]) != null ? _a : s.paddingVertical) != null ? _b : s.padding) != null ? _c : 0;
344
- }
345
- function extractPadding(style, contentContainerStyle, type) {
346
- return getPadding(style, type) + getPadding(contentContainerStyle, type);
347
- }
348
-
349
306
  // src/state/ContextContainer.ts
350
307
  var ContextContainer = createContext(null);
351
308
  function useViewability(callback, configId) {
@@ -442,13 +399,110 @@ function useListScrollSize() {
442
399
  const [scrollSize] = useArr$(["scrollSize"]);
443
400
  return scrollSize;
444
401
  }
445
- function useSyncLayout2() {
402
+ function useSyncLayout() {
446
403
  {
447
404
  const { triggerLayout: syncLayout } = useContext(ContextContainer);
448
405
  return syncLayout;
449
406
  }
450
407
  }
451
408
 
409
+ // src/components/Separator.tsx
410
+ function Separator({ ItemSeparatorComponent, leadingItem }) {
411
+ const isLastItem = useIsLastItem();
412
+ return isLastItem ? null : /* @__PURE__ */ React3.createElement(ItemSeparatorComponent, { leadingItem });
413
+ }
414
+
415
+ // src/hooks/createResizeObserver.ts
416
+ var globalResizeObserver = null;
417
+ function getGlobalResizeObserver() {
418
+ if (!globalResizeObserver) {
419
+ globalResizeObserver = new ResizeObserver((entries) => {
420
+ for (const entry of entries) {
421
+ const callbacks = callbackMap.get(entry.target);
422
+ if (callbacks) {
423
+ for (const callback of callbacks) {
424
+ callback(entry);
425
+ }
426
+ }
427
+ }
428
+ });
429
+ }
430
+ return globalResizeObserver;
431
+ }
432
+ var callbackMap = /* @__PURE__ */ new WeakMap();
433
+ function createResizeObserver(element, callback) {
434
+ if (typeof ResizeObserver === "undefined") {
435
+ return () => {
436
+ };
437
+ }
438
+ if (!element) {
439
+ return () => {
440
+ };
441
+ }
442
+ const observer = getGlobalResizeObserver();
443
+ let callbacks = callbackMap.get(element);
444
+ if (!callbacks) {
445
+ callbacks = /* @__PURE__ */ new Set();
446
+ callbackMap.set(element, callbacks);
447
+ observer.observe(element);
448
+ }
449
+ callbacks.add(callback);
450
+ return () => {
451
+ const callbacks2 = callbackMap.get(element);
452
+ if (callbacks2) {
453
+ callbacks2.delete(callback);
454
+ if (callbacks2.size === 0) {
455
+ callbackMap.delete(element);
456
+ observer.unobserve(element);
457
+ }
458
+ }
459
+ };
460
+ }
461
+
462
+ // src/hooks/useOnLayoutSync.tsx
463
+ function useOnLayoutSync({
464
+ ref,
465
+ onLayoutProp,
466
+ onLayoutChange
467
+ }, deps) {
468
+ useLayoutEffect(() => {
469
+ var _a3, _b;
470
+ const current = ref.current;
471
+ const scrollableNode = (_b = (_a3 = current == null ? void 0 : current.getScrollableNode) == null ? void 0 : _a3.call(current)) != null ? _b : null;
472
+ const element = scrollableNode || current;
473
+ if (!element) {
474
+ return;
475
+ }
476
+ const emit = (layout, fromLayoutEffect) => {
477
+ if (layout.height === 0 && layout.width === 0) {
478
+ return;
479
+ }
480
+ onLayoutChange(layout, fromLayoutEffect);
481
+ onLayoutProp == null ? void 0 : onLayoutProp({ nativeEvent: { layout } });
482
+ };
483
+ const rect = element.getBoundingClientRect();
484
+ emit(toLayout(rect), true);
485
+ return createResizeObserver(element, (entry) => {
486
+ var _a4;
487
+ const target = entry.target instanceof HTMLElement ? entry.target : void 0;
488
+ const rect2 = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
489
+ emit(toLayout(rect2), false);
490
+ });
491
+ }, deps);
492
+ return {};
493
+ }
494
+ function toLayout(rect) {
495
+ if (!rect) {
496
+ return { height: 0, width: 0, x: 0, y: 0 };
497
+ }
498
+ return {
499
+ height: rect.height,
500
+ width: rect.width,
501
+ x: rect.left,
502
+ y: rect.top
503
+ };
504
+ }
505
+
452
506
  // src/components/Container.tsx
453
507
  var Container = typedMemo(function Container2({
454
508
  id,
@@ -459,37 +513,42 @@ var Container = typedMemo(function Container2({
459
513
  ItemSeparatorComponent
460
514
  }) {
461
515
  const ctx = useStateContext();
462
- const { columnWrapperStyle } = ctx;
463
- const [column = 0, data, itemKey, numColumns, extraData, isSticky] = useArr$([
516
+ const { columnWrapperStyle, animatedScrollY } = ctx;
517
+ const [column = 0, data, itemKey, numColumns, extraData, isSticky, stickyOffset] = useArr$([
464
518
  `containerColumn${id}`,
465
519
  `containerItemData${id}`,
466
520
  `containerItemKey${id}`,
467
521
  "numColumns",
468
522
  "extraData",
469
- `containerSticky${id}`
523
+ `containerSticky${id}`,
524
+ `containerStickyOffset${id}`
470
525
  ]);
471
- const refLastSize = useRef();
526
+ const itemLayoutRef = useRef({
527
+ horizontal,
528
+ itemKey,
529
+ updateItemSize: updateItemSize2
530
+ });
531
+ itemLayoutRef.current.horizontal = horizontal;
532
+ itemLayoutRef.current.itemKey = itemKey;
533
+ itemLayoutRef.current.updateItemSize = updateItemSize2;
472
534
  const ref = useRef(null);
473
- const [_, forceLayoutRender] = useState(0);
535
+ const [layoutRenderCount, forceLayoutRender] = useState(0);
474
536
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
475
537
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
538
+ const didLayoutRef = useRef(false);
476
539
  const style = useMemo(() => {
477
540
  let paddingStyles;
478
541
  if (columnWrapperStyle) {
479
542
  const { columnGap, rowGap, gap } = columnWrapperStyle;
480
543
  if (horizontal) {
481
- const py = numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0;
482
544
  paddingStyles = {
483
- paddingBottom: py,
484
545
  paddingRight: columnGap || gap || void 0,
485
- paddingTop: py
546
+ paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
486
547
  };
487
548
  } else {
488
- const px = numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0;
489
549
  paddingStyles = {
490
550
  paddingBottom: rowGap || gap || void 0,
491
- paddingLeft: px,
492
- paddingRight: px
551
+ paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
493
552
  };
494
553
  }
495
554
  }
@@ -503,7 +562,7 @@ var Container = typedMemo(function Container2({
503
562
  } : {
504
563
  left: otherAxisPos,
505
564
  position: "absolute",
506
- right: numColumns > 1 ? void 0 : 0,
565
+ right: numColumns > 1 ? null : 0,
507
566
  top: 0,
508
567
  width: otherAxisSize,
509
568
  ...paddingStyles || {}
@@ -526,49 +585,64 @@ var Container = typedMemo(function Container2({
526
585
  value: data
527
586
  };
528
587
  }, [id, itemKey, index, data]);
529
- const onLayoutChange = (rectangle) => {
530
- if (!isNullOrUndefined(itemKey)) {
531
- let layout = rectangle;
532
- layout[horizontal ? "width" : "height"];
533
- const doUpdate = () => {
534
- refLastSize.current = { height: layout.height, width: layout.width };
535
- updateItemSize2(itemKey, layout);
536
- };
537
- {
538
- doUpdate();
539
- }
588
+ const onLayoutChange = useCallback((rectangle) => {
589
+ const {
590
+ horizontal: currentHorizontal,
591
+ itemKey: currentItemKey,
592
+ updateItemSize: updateItemSizeFn
593
+ } = itemLayoutRef.current;
594
+ if (isNullOrUndefined(currentItemKey)) {
595
+ return;
540
596
  }
541
- };
597
+ didLayoutRef.current = true;
598
+ let layout = rectangle;
599
+ roundSize(rectangle[currentHorizontal ? "width" : "height"]);
600
+ const doUpdate = () => {
601
+ itemLayoutRef.current.lastSize = { height: layout.height, width: layout.width };
602
+ updateItemSizeFn(currentItemKey, layout);
603
+ didLayoutRef.current = true;
604
+ };
605
+ {
606
+ doUpdate();
607
+ }
608
+ }, []);
609
+ const { onLayout } = useOnLayoutSync(
610
+ {
611
+ onLayoutChange,
612
+ ref
613
+ },
614
+ [itemKey, layoutRenderCount]
615
+ );
542
616
  const PositionComponent = isSticky ? PositionViewSticky : PositionView2;
543
- return /* @__PURE__ */ React4.createElement(ContextContainer.Provider, { value: contextValue }, /* @__PURE__ */ React4.createElement(
617
+ return /* @__PURE__ */ React3.createElement(
544
618
  PositionComponent,
545
619
  {
620
+ animatedScrollY: isSticky ? animatedScrollY : void 0,
546
621
  horizontal,
547
622
  id,
548
623
  index,
549
624
  key: recycleItems ? void 0 : itemKey,
550
- onLayoutChange,
625
+ onLayout,
551
626
  refView: ref,
627
+ stickyOffset: isSticky ? stickyOffset : void 0,
552
628
  style
553
629
  },
554
- renderedItem,
555
- renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React4.createElement(
556
- Separator,
557
- {
558
- ItemSeparatorComponent,
559
- itemKey,
560
- leadingItem: renderedItemInfo.item
561
- }
562
- )
563
- ));
630
+ /* @__PURE__ */ React3.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3.createElement(Separator, { ItemSeparatorComponent, leadingItem: renderedItemInfo.item }))
631
+ );
564
632
  });
565
633
 
634
+ // src/platform/Platform.ts
635
+ var Platform = {
636
+ // Widen the type to avoid unreachable-branch lints in cross-platform code that compares against other OSes
637
+ OS: "web"
638
+ };
639
+
566
640
  // src/utils/reordering.ts
567
641
  var mapFn = (element) => {
568
642
  const indexStr = element.getAttribute("index");
569
643
  return [element, indexStr === null ? null : parseInt(indexStr)];
570
644
  };
571
- function sortDOMElementsPatience(container) {
645
+ function sortDOMElements(container) {
572
646
  const elements = Array.from(container.children);
573
647
  if (elements.length <= 1) return elements;
574
648
  const items = elements.map(mapFn);
@@ -659,7 +733,7 @@ function useDOMOrder(ref) {
659
733
  debounceRef.current = setTimeout(() => {
660
734
  const parent = ref.current;
661
735
  if (parent) {
662
- sortDOMElementsPatience(parent);
736
+ sortDOMElements(parent);
663
737
  }
664
738
  debounceRef.current = void 0;
665
739
  }, 500);
@@ -680,7 +754,7 @@ var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColum
680
754
  const columnWrapperStyle = ctx.columnWrapperStyle;
681
755
  const [totalSize, otherAxisSize] = useArr$(["totalSize", "otherAxisSize"]);
682
756
  useDOMOrder(ref);
683
- const style = horizontal ? { minHeight: otherAxisSize, width: totalSize } : { height: totalSize, minWidth: otherAxisSize };
757
+ const style = horizontal ? { minHeight: otherAxisSize, position: "relative", width: totalSize } : { height: totalSize, minWidth: otherAxisSize, position: "relative" };
684
758
  if (columnWrapperStyle && numColumns > 1) {
685
759
  const { columnGap, rowGap, gap } = columnWrapperStyle;
686
760
  const gapX = columnGap || gap || 0;
@@ -701,7 +775,7 @@ var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColum
701
775
  }
702
776
  }
703
777
  }
704
- return /* @__PURE__ */ React4.createElement("div", { ref, style }, children);
778
+ return /* @__PURE__ */ React3.createElement("div", { ref, style }, children);
705
779
  });
706
780
  var Containers = typedMemo(function Containers2({
707
781
  horizontal,
@@ -715,7 +789,7 @@ var Containers = typedMemo(function Containers2({
715
789
  const containers = [];
716
790
  for (let i = 0; i < numContainers; i++) {
717
791
  containers.push(
718
- /* @__PURE__ */ React4.createElement(
792
+ /* @__PURE__ */ React3.createElement(
719
793
  Container,
720
794
  {
721
795
  getRenderedItem: getRenderedItem2,
@@ -729,24 +803,40 @@ var Containers = typedMemo(function Containers2({
729
803
  )
730
804
  );
731
805
  }
732
- return /* @__PURE__ */ React4.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
733
- });
734
- var DevNumbers = __DEV__ && React4.memo(function DevNumbers2() {
735
- return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React4.createElement(
736
- View,
737
- {
738
- key: index,
739
- style: {
740
- height: 100,
741
- pointerEvents: "none",
742
- position: "absolute",
743
- top: index * 100,
744
- width: "100%"
745
- }
746
- },
747
- /* @__PURE__ */ React4.createElement(Text, { style: { color: "red" } }, index * 100)
748
- ));
806
+ return /* @__PURE__ */ React3.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
749
807
  });
808
+ function DevNumbers() {
809
+ return IS_DEV && React3.memo(function DevNumbers2() {
810
+ return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3.createElement(
811
+ "div",
812
+ {
813
+ key: index,
814
+ style: {
815
+ height: 100,
816
+ pointerEvents: "none",
817
+ position: "absolute",
818
+ top: index * 100,
819
+ width: "100%"
820
+ }
821
+ },
822
+ /* @__PURE__ */ React3.createElement("div", { style: { color: "red" } }, index * 100)
823
+ ));
824
+ });
825
+ }
826
+
827
+ // src/platform/StyleSheet.tsx
828
+ function flattenStyles(styles) {
829
+ if (isArray(styles)) {
830
+ return Object.assign({}, ...styles.filter(Boolean));
831
+ }
832
+ return styles;
833
+ }
834
+ var StyleSheet = {
835
+ create: (styles) => styles,
836
+ flatten: (style) => flattenStyles(style)
837
+ };
838
+
839
+ // src/components/ListComponentScrollView.tsx
750
840
  var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
751
841
  children,
752
842
  style,
@@ -760,7 +850,6 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
760
850
  showsVerticalScrollIndicator = true,
761
851
  refreshControl,
762
852
  onLayout,
763
- ScrollComponent,
764
853
  ...props
765
854
  }, ref) {
766
855
  const scrollRef = useRef(null);
@@ -769,16 +858,15 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
769
858
  useImperativeHandle(ref, () => {
770
859
  const api = {
771
860
  getBoundingClientRect: () => {
772
- var _a;
773
- return (_a = scrollRef.current) == null ? void 0 : _a.getBoundingClientRect();
861
+ var _a3;
862
+ return (_a3 = scrollRef.current) == null ? void 0 : _a3.getBoundingClientRect();
774
863
  },
775
864
  getScrollableNode: () => scrollRef.current,
776
865
  getScrollResponder: () => scrollRef.current,
777
- scrollBy: (options) => {
866
+ scrollBy: (x, y) => {
778
867
  const el = scrollRef.current;
779
868
  if (!el) return;
780
- const { x = 0, y = 0, animated = true } = options;
781
- el.scrollBy({ behavior: animated ? "smooth" : "auto", left: x, top: y });
869
+ el.scrollBy(x, y);
782
870
  },
783
871
  scrollTo: (options) => {
784
872
  const el = scrollRef.current;
@@ -848,17 +936,21 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
848
936
  useLayoutEffect(() => {
849
937
  const element = scrollRef.current;
850
938
  if (!element) return;
851
- element.addEventListener("scroll", handleScroll, { passive: true });
939
+ element.addEventListener("scroll", handleScroll);
852
940
  return () => {
853
941
  element.removeEventListener("scroll", handleScroll);
854
942
  };
855
943
  }, [handleScroll]);
856
- useLayoutEffect(() => {
857
- if (contentOffset && scrollRef.current) {
858
- scrollRef.current.scrollLeft = contentOffset.x || 0;
859
- scrollRef.current.scrollTop = contentOffset.y || 0;
860
- }
861
- }, [contentOffset]);
944
+ useEffect(() => {
945
+ const doScroll = () => {
946
+ if (contentOffset && scrollRef.current) {
947
+ scrollRef.current.scrollLeft = contentOffset.x || 0;
948
+ scrollRef.current.scrollTop = contentOffset.y || 0;
949
+ }
950
+ };
951
+ doScroll();
952
+ requestAnimationFrame(doScroll);
953
+ }, [contentOffset == null ? void 0 : contentOffset.x, contentOffset == null ? void 0 : contentOffset.y]);
862
954
  useLayoutEffect(() => {
863
955
  if (!onLayout || !scrollRef.current) return;
864
956
  const element = scrollRef.current;
@@ -890,36 +982,57 @@ var ListComponentScrollView = forwardRef(function ListComponentScrollView2({
890
982
  // Ensure proper positioning context
891
983
  WebkitOverflowScrolling: "touch",
892
984
  // iOS momentum scrolling
893
- ...style
985
+ ...StyleSheet.flatten(style)
894
986
  };
895
987
  const contentStyle = {
896
988
  display: horizontal ? "flex" : "block",
897
989
  flexDirection: horizontal ? "row" : void 0,
898
990
  minHeight: horizontal ? void 0 : "100%",
899
991
  minWidth: horizontal ? "100%" : void 0,
900
- ...contentContainerStyle
992
+ ...StyleSheet.flatten(contentContainerStyle)
901
993
  };
902
- return /* @__PURE__ */ React4.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React4.createElement("div", { ref: contentRef, style: contentStyle }, children));
994
+ return /* @__PURE__ */ React3.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React3.createElement("div", { ref: contentRef, style: contentStyle }, children));
903
995
  });
996
+ function Padding() {
997
+ const [paddingTop] = useArr$(["alignItemsPaddingTop"]);
998
+ return /* @__PURE__ */ React3.createElement("div", { style: { paddingTop } });
999
+ }
1000
+ function PaddingDevMode() {
1001
+ const [paddingTop] = useArr$(["alignItemsPaddingTop"]);
1002
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("div", { style: { paddingTop } }), /* @__PURE__ */ React3.createElement(
1003
+ "div",
1004
+ {
1005
+ style: {
1006
+ backgroundColor: "green",
1007
+ height: paddingTop,
1008
+ left: 0,
1009
+ position: "absolute",
1010
+ right: 0,
1011
+ top: 0
1012
+ }
1013
+ }
1014
+ ));
1015
+ }
904
1016
  function useValueListener$(key, callback) {
905
1017
  const ctx = useStateContext();
906
1018
  useLayoutEffect(() => {
907
- listen$(ctx, key, (value) => {
1019
+ const unsubscribe = listen$(ctx, key, (value) => {
908
1020
  callback(value);
909
1021
  });
910
- }, []);
1022
+ return unsubscribe;
1023
+ }, [callback, ctx, key]);
911
1024
  }
912
1025
 
913
1026
  // src/components/ScrollAdjust.tsx
914
1027
  function ScrollAdjust() {
915
1028
  const ctx = useStateContext();
916
- const lastScrollOffsetRef = React4.useRef(0);
917
- const callback = React4.useCallback(() => {
918
- var _a;
1029
+ const lastScrollOffsetRef = React3.useRef(0);
1030
+ const callback = React3.useCallback(() => {
1031
+ var _a3;
919
1032
  const scrollAdjust = peek$(ctx, "scrollAdjust");
920
1033
  const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
921
1034
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
922
- const scrollView = (_a = ctx.internalState) == null ? void 0 : _a.refScroller.current;
1035
+ const scrollView = (_a3 = ctx.internalState) == null ? void 0 : _a3.refScroller.current;
923
1036
  if (scrollView && scrollOffset !== lastScrollOffsetRef.current) {
924
1037
  const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
925
1038
  if (scrollDelta !== 0) {
@@ -933,49 +1046,26 @@ function ScrollAdjust() {
933
1046
  useValueListener$("scrollAdjustUserOffset", callback);
934
1047
  return null;
935
1048
  }
936
-
937
- // src/components/SnapWrapper.tsx
938
1049
  function SnapWrapper({ ScrollComponent, ...props }) {
939
1050
  const [snapToOffsets] = useArr$(["snapToOffsets"]);
940
- return /* @__PURE__ */ React.createElement(ScrollComponent, { ...props, snapToOffsets });
941
- }
942
-
943
- // src/hooks/useValue$.ts
944
- function useValue$(key, params) {
945
- const [value] = useArr$([key]);
946
- return value;
1051
+ return /* @__PURE__ */ React3.createElement(ScrollComponent, { ...props, snapToOffsets });
947
1052
  }
1053
+ var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
1054
+ const ref = refView != null ? refView : useRef();
1055
+ useOnLayoutSync({ onLayoutChange, ref });
1056
+ return /* @__PURE__ */ React3.createElement("div", { ...rest, ref }, children);
1057
+ };
948
1058
 
949
1059
  // src/components/ListComponent.tsx
950
1060
  var getComponent = (Component) => {
951
- if (React4.isValidElement(Component)) {
1061
+ if (React3.isValidElement(Component)) {
952
1062
  return Component;
953
1063
  }
954
1064
  if (Component) {
955
- return /* @__PURE__ */ React4.createElement(Component, null);
1065
+ return /* @__PURE__ */ React3.createElement(Component, null);
956
1066
  }
957
1067
  return null;
958
1068
  };
959
- var Padding = () => {
960
- const animPaddingTop = useValue$("alignItemsPaddingTop");
961
- return /* @__PURE__ */ React4.createElement(AnimatedView, { style: { paddingTop: animPaddingTop } });
962
- };
963
- var PaddingDevMode = () => {
964
- const animPaddingTop = useValue$("alignItemsPaddingTop");
965
- return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(AnimatedView, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React4.createElement(
966
- AnimatedView,
967
- {
968
- style: {
969
- backgroundColor: "green",
970
- height: animPaddingTop,
971
- left: 0,
972
- position: "absolute",
973
- right: 0,
974
- top: 0
975
- }
976
- }
977
- ));
978
- };
979
1069
  var ListComponent = typedMemo(function ListComponent2({
980
1070
  canRender,
981
1071
  style,
@@ -1005,12 +1095,11 @@ var ListComponent = typedMemo(function ListComponent2({
1005
1095
  ...rest
1006
1096
  }) {
1007
1097
  const ctx = useStateContext();
1008
- const refHeader = React4.useRef(null);
1009
1098
  const ScrollComponent = renderScrollComponent ? useMemo(
1010
- () => React4.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
1099
+ () => React3.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
1011
1100
  [renderScrollComponent]
1012
1101
  ) : ListComponentScrollView;
1013
- React4.useEffect(() => {
1102
+ React3.useEffect(() => {
1014
1103
  if (canRender) {
1015
1104
  setTimeout(() => {
1016
1105
  scrollAdjustHandler.setMounted();
@@ -1018,39 +1107,30 @@ var ListComponent = typedMemo(function ListComponent2({
1018
1107
  }
1019
1108
  }, [canRender]);
1020
1109
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1021
- const contentContainerStyleWeb = useMemo(() => {
1022
- const base = contentContainerStyle || void 0;
1023
- if (!horizontal) return base;
1024
- if (base && base.height === "100%") return base;
1025
- return { ...base || {}, height: "100%" };
1026
- }, [horizontal, (contentContainerStyle == null ? void 0 : contentContainerStyle.height) === "100%" ? 1 : 0]);
1027
- return /* @__PURE__ */ React4.createElement(
1110
+ return /* @__PURE__ */ React3.createElement(
1028
1111
  SnapOrScroll,
1029
1112
  {
1030
1113
  ...rest,
1031
- contentContainerStyle: contentContainerStyleWeb,
1114
+ contentContainerStyle: [
1115
+ contentContainerStyle,
1116
+ horizontal ? {
1117
+ height: "100%"
1118
+ } : {}
1119
+ ],
1032
1120
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
1033
1121
  horizontal,
1034
- maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
1122
+ maintainVisibleContentPosition: maintainVisibleContentPosition ? { minIndexForVisible: 0 } : void 0,
1035
1123
  onLayout,
1036
1124
  onScroll: onScroll2,
1037
1125
  ref: refScrollView,
1038
1126
  ScrollComponent: snapToIndices ? ScrollComponent : void 0,
1039
1127
  style
1040
1128
  },
1041
- maintainVisibleContentPosition && /* @__PURE__ */ React4.createElement(ScrollAdjust, null),
1042
- ENABLE_DEVMODE ? /* @__PURE__ */ React4.createElement(PaddingDevMode, null) : /* @__PURE__ */ React4.createElement(Padding, null),
1043
- ListHeaderComponent && /* @__PURE__ */ React4.createElement(
1044
- LayoutView,
1045
- {
1046
- onLayoutChange: onLayoutHeader,
1047
- refView: refHeader,
1048
- style: ListHeaderComponentStyle
1049
- },
1050
- getComponent(ListHeaderComponent)
1051
- ),
1129
+ maintainVisibleContentPosition && /* @__PURE__ */ React3.createElement(ScrollAdjust, null),
1130
+ ENABLE_DEVMODE ? /* @__PURE__ */ React3.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3.createElement(Padding, null),
1131
+ ListHeaderComponent && /* @__PURE__ */ React3.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1052
1132
  ListEmptyComponent && getComponent(ListEmptyComponent),
1053
- canRender && /* @__PURE__ */ React4.createElement(
1133
+ canRender && !ListEmptyComponent && /* @__PURE__ */ React3.createElement(
1054
1134
  Containers,
1055
1135
  {
1056
1136
  getRenderedItem: getRenderedItem2,
@@ -1061,7 +1141,7 @@ var ListComponent = typedMemo(function ListComponent2({
1061
1141
  waitForInitialLayout
1062
1142
  }
1063
1143
  ),
1064
- ListFooterComponent && /* @__PURE__ */ React4.createElement(
1144
+ ListFooterComponent && /* @__PURE__ */ React3.createElement(
1065
1145
  LayoutView,
1066
1146
  {
1067
1147
  onLayoutChange: (layout) => {
@@ -1072,7 +1152,7 @@ var ListComponent = typedMemo(function ListComponent2({
1072
1152
  },
1073
1153
  getComponent(ListFooterComponent)
1074
1154
  ),
1075
- __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React4.createElement(DevNumbers, null)
1155
+ IS_DEV && ENABLE_DEVMODE && /* @__PURE__ */ React3.createElement(DevNumbers, null)
1076
1156
  );
1077
1157
  });
1078
1158
 
@@ -1084,7 +1164,7 @@ function getId(state, index) {
1084
1164
  }
1085
1165
  const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
1086
1166
  const id = ret;
1087
- state.idCache.set(index, id);
1167
+ state.idCache[index] = id;
1088
1168
  return id;
1089
1169
  }
1090
1170
 
@@ -1105,13 +1185,100 @@ function calculateOffsetForIndex(ctx, state, index) {
1105
1185
  return position;
1106
1186
  }
1107
1187
 
1188
+ // src/utils/setPaddingTop.ts
1189
+ function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1190
+ if (stylePaddingTop !== void 0) {
1191
+ const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1192
+ if (stylePaddingTop < prevStylePaddingTop) {
1193
+ let prevTotalSize = peek$(ctx, "totalSize") || 0;
1194
+ set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
1195
+ state.timeoutSetPaddingTop = setTimeout(() => {
1196
+ prevTotalSize = peek$(ctx, "totalSize") || 0;
1197
+ set$(ctx, "totalSize", prevTotalSize - prevStylePaddingTop);
1198
+ }, 16);
1199
+ }
1200
+ set$(ctx, "stylePaddingTop", stylePaddingTop);
1201
+ }
1202
+ if (alignItemsPaddingTop !== void 0) {
1203
+ set$(ctx, "alignItemsPaddingTop", alignItemsPaddingTop);
1204
+ }
1205
+ }
1206
+
1207
+ // src/utils/updateAlignItemsPaddingTop.ts
1208
+ function updateAlignItemsPaddingTop(ctx, state) {
1209
+ const {
1210
+ scrollLength,
1211
+ props: { alignItemsAtEnd, data }
1212
+ } = state;
1213
+ if (alignItemsAtEnd) {
1214
+ let alignItemsPaddingTop = 0;
1215
+ if ((data == null ? void 0 : data.length) > 0) {
1216
+ const contentSize = getContentSize(ctx);
1217
+ alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1218
+ }
1219
+ setPaddingTop(ctx, state, { alignItemsPaddingTop });
1220
+ }
1221
+ }
1222
+
1223
+ // src/core/updateTotalSize.ts
1224
+ function updateTotalSize(ctx, state) {
1225
+ const {
1226
+ positions,
1227
+ props: { data }
1228
+ } = state;
1229
+ if (data.length === 0) {
1230
+ addTotalSize(ctx, state, null, 0);
1231
+ } else {
1232
+ const lastId = getId(state, data.length - 1);
1233
+ if (lastId !== void 0) {
1234
+ const lastPosition = positions.get(lastId);
1235
+ if (lastPosition !== void 0) {
1236
+ const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
1237
+ if (lastSize !== void 0) {
1238
+ const totalSize = lastPosition + lastSize;
1239
+ addTotalSize(ctx, state, null, totalSize);
1240
+ }
1241
+ }
1242
+ }
1243
+ }
1244
+ }
1245
+ function addTotalSize(ctx, state, key, add) {
1246
+ const { alignItemsAtEnd } = state.props;
1247
+ const prevTotalSize = state.totalSize;
1248
+ if (key === null) {
1249
+ state.totalSize = add;
1250
+ if (state.timeoutSetPaddingTop) {
1251
+ clearTimeout(state.timeoutSetPaddingTop);
1252
+ state.timeoutSetPaddingTop = void 0;
1253
+ }
1254
+ } else {
1255
+ state.totalSize += add;
1256
+ }
1257
+ if (prevTotalSize !== state.totalSize) {
1258
+ set$(ctx, "totalSize", state.totalSize);
1259
+ if (alignItemsAtEnd) {
1260
+ updateAlignItemsPaddingTop(ctx, state);
1261
+ }
1262
+ }
1263
+ }
1264
+
1265
+ // src/core/setSize.ts
1266
+ function setSize(ctx, state, itemKey, size) {
1267
+ const { sizes } = state;
1268
+ const previousSize = sizes.get(itemKey);
1269
+ const diff = previousSize !== void 0 ? size - previousSize : size;
1270
+ if (diff !== 0) {
1271
+ addTotalSize(ctx, state, itemKey, diff);
1272
+ }
1273
+ sizes.set(itemKey, size);
1274
+ }
1275
+
1108
1276
  // src/utils/getItemSize.ts
1109
- function getItemSize(state, key, index, data, useAverageSize) {
1110
- var _a, _b;
1277
+ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedSize) {
1278
+ var _a3, _b;
1111
1279
  const {
1112
1280
  sizesKnown,
1113
1281
  sizes,
1114
- scrollingTo,
1115
1282
  averageSizes,
1116
1283
  props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
1117
1284
  } = state;
@@ -1120,7 +1287,14 @@ function getItemSize(state, key, index, data, useAverageSize) {
1120
1287
  return sizeKnown;
1121
1288
  }
1122
1289
  let size;
1123
- const itemType = getItemType ? (_a = getItemType(data, index)) != null ? _a : "" : "";
1290
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1291
+ const scrollingTo = peek$(ctx, "scrollingTo");
1292
+ if (preferCachedSize) {
1293
+ const cachedSize = sizes.get(key);
1294
+ if (cachedSize !== void 0) {
1295
+ return cachedSize;
1296
+ }
1297
+ }
1124
1298
  if (getFixedItemSize) {
1125
1299
  size = getFixedItemSize(index, data, itemType);
1126
1300
  if (size !== void 0) {
@@ -1142,53 +1316,239 @@ function getItemSize(state, key, index, data, useAverageSize) {
1142
1316
  if (size === void 0) {
1143
1317
  size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
1144
1318
  }
1145
- sizes.set(key, size);
1319
+ setSize(ctx, state, key, size);
1146
1320
  return size;
1147
1321
  }
1148
1322
 
1149
1323
  // src/core/calculateOffsetWithOffsetPosition.ts
1150
- function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
1324
+ function calculateOffsetWithOffsetPosition(ctx, state, offsetParam, params) {
1151
1325
  const { index, viewOffset, viewPosition } = params;
1152
1326
  let offset = offsetParam;
1153
1327
  if (viewOffset) {
1154
1328
  offset -= viewOffset;
1155
1329
  }
1156
1330
  if (viewPosition !== void 0 && index !== void 0) {
1157
- offset -= viewPosition * (state.scrollLength - getItemSize(state, getId(state, index), index, state.props.data[index]));
1331
+ offset -= viewPosition * (state.scrollLength - getItemSize(ctx, state, getId(state, index), index, state.props.data[index]));
1158
1332
  }
1159
1333
  return offset;
1160
1334
  }
1161
1335
 
1336
+ // src/utils/checkThreshold.ts
1337
+ var HYSTERESIS_MULTIPLIER = 1.3;
1338
+ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
1339
+ const absDistance = Math.abs(distance);
1340
+ const within = atThreshold || threshold > 0 && absDistance <= threshold;
1341
+ const updateSnapshot = () => {
1342
+ setSnapshot == null ? void 0 : setSnapshot({
1343
+ atThreshold,
1344
+ contentSize: context.contentSize,
1345
+ dataLength: context.dataLength,
1346
+ scrollPosition: context.scrollPosition
1347
+ });
1348
+ };
1349
+ if (!wasReached) {
1350
+ if (!within) {
1351
+ return false;
1352
+ }
1353
+ onReached == null ? void 0 : onReached(distance);
1354
+ updateSnapshot();
1355
+ return true;
1356
+ }
1357
+ const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
1358
+ if (reset) {
1359
+ setSnapshot == null ? void 0 : setSnapshot(void 0);
1360
+ return false;
1361
+ }
1362
+ if (within) {
1363
+ const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
1364
+ if (changed) {
1365
+ onReached == null ? void 0 : onReached(distance);
1366
+ updateSnapshot();
1367
+ }
1368
+ }
1369
+ return true;
1370
+ };
1371
+
1372
+ // src/utils/checkAtBottom.ts
1373
+ function checkAtBottom(ctx, state) {
1374
+ var _a3;
1375
+ if (!state) {
1376
+ return;
1377
+ }
1378
+ const {
1379
+ queuedInitialLayout,
1380
+ scrollLength,
1381
+ scroll,
1382
+ maintainingScrollAtEnd,
1383
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1384
+ } = state;
1385
+ const contentSize = getContentSize(ctx);
1386
+ if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1387
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1388
+ const isContentLess = contentSize < scrollLength;
1389
+ state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1390
+ state.isEndReached = checkThreshold(
1391
+ distanceFromEnd,
1392
+ isContentLess,
1393
+ onEndReachedThreshold * scrollLength,
1394
+ state.isEndReached,
1395
+ state.endReachedSnapshot,
1396
+ {
1397
+ contentSize,
1398
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1399
+ scrollPosition: scroll
1400
+ },
1401
+ (distance) => {
1402
+ var _a4, _b;
1403
+ return (_b = (_a4 = state.props).onEndReached) == null ? void 0 : _b.call(_a4, { distanceFromEnd: distance });
1404
+ },
1405
+ (snapshot) => {
1406
+ state.endReachedSnapshot = snapshot;
1407
+ }
1408
+ );
1409
+ }
1410
+ }
1411
+
1412
+ // src/utils/checkAtTop.ts
1413
+ function checkAtTop(state) {
1414
+ var _a3;
1415
+ if (!state) {
1416
+ return;
1417
+ }
1418
+ const {
1419
+ scrollLength,
1420
+ scroll,
1421
+ props: { onStartReachedThreshold }
1422
+ } = state;
1423
+ const distanceFromTop = scroll;
1424
+ state.isAtStart = distanceFromTop <= 0;
1425
+ state.isStartReached = checkThreshold(
1426
+ distanceFromTop,
1427
+ false,
1428
+ onStartReachedThreshold * scrollLength,
1429
+ state.isStartReached,
1430
+ state.startReachedSnapshot,
1431
+ {
1432
+ contentSize: state.totalSize,
1433
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1434
+ scrollPosition: scroll
1435
+ },
1436
+ (distance) => {
1437
+ var _a4, _b;
1438
+ return (_b = (_a4 = state.props).onStartReached) == null ? void 0 : _b.call(_a4, { distanceFromStart: distance });
1439
+ },
1440
+ (snapshot) => {
1441
+ state.startReachedSnapshot = snapshot;
1442
+ }
1443
+ );
1444
+ }
1445
+
1446
+ // src/core/onScroll.ts
1447
+ function onScroll(ctx, state, event) {
1448
+ var _a3, _b, _c;
1449
+ const {
1450
+ scrollProcessingEnabled,
1451
+ props: { onScroll: onScrollProp }
1452
+ } = state;
1453
+ if (scrollProcessingEnabled === false) {
1454
+ return;
1455
+ }
1456
+ 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) {
1457
+ return;
1458
+ }
1459
+ const newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
1460
+ state.scrollPending = newScroll;
1461
+ updateScroll(ctx, state, newScroll);
1462
+ onScrollProp == null ? void 0 : onScrollProp(event);
1463
+ }
1464
+ function updateScroll(ctx, state, newScroll, forceUpdate) {
1465
+ const scrollingTo = peek$(ctx, "scrollingTo");
1466
+ state.hasScrolled = true;
1467
+ state.lastBatchingAction = Date.now();
1468
+ const currentTime = Date.now();
1469
+ const adjust = state.scrollAdjustHandler.getAdjust();
1470
+ const lastHistoryAdjust = state.lastScrollAdjustForHistory;
1471
+ const adjustChanged = lastHistoryAdjust !== void 0 && Math.abs(adjust - lastHistoryAdjust) > 0.1;
1472
+ if (adjustChanged) {
1473
+ state.scrollHistory.length = 0;
1474
+ }
1475
+ state.lastScrollAdjustForHistory = adjust;
1476
+ if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
1477
+ if (!adjustChanged) {
1478
+ state.scrollHistory.push({ scroll: newScroll, time: currentTime });
1479
+ }
1480
+ }
1481
+ if (state.scrollHistory.length > 5) {
1482
+ state.scrollHistory.shift();
1483
+ }
1484
+ state.scrollPrev = state.scroll;
1485
+ state.scrollPrevTime = state.scrollTime;
1486
+ state.scroll = newScroll;
1487
+ state.scrollTime = currentTime;
1488
+ const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
1489
+ if (ignoreScrollFromMVCP && !scrollingTo) {
1490
+ const { lt, gt } = ignoreScrollFromMVCP;
1491
+ if (lt && newScroll < lt || gt && newScroll > gt) {
1492
+ state.ignoreScrollFromMVCPIgnored = true;
1493
+ return;
1494
+ }
1495
+ }
1496
+ if (state.dataChangeNeedsScrollUpdate || Math.abs(state.scroll - state.scrollPrev) > 2) {
1497
+ state.ignoreScrollFromMVCPIgnored = false;
1498
+ calculateItemsInView(ctx, state, { doMVCP: scrollingTo !== void 0 });
1499
+ checkAtBottom(ctx, state);
1500
+ checkAtTop(state);
1501
+ state.dataChangeNeedsScrollUpdate = false;
1502
+ }
1503
+ }
1504
+
1162
1505
  // src/core/finishScrollTo.ts
1163
- var finishScrollTo = (state) => {
1506
+ function finishScrollTo(ctx, state) {
1507
+ var _a3, _b;
1164
1508
  if (state) {
1165
- state.scrollingTo = void 0;
1166
1509
  state.scrollHistory.length = 0;
1510
+ state.initialScroll = void 0;
1511
+ set$(ctx, "scrollingTo", void 0);
1512
+ if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1513
+ (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1514
+ }
1167
1515
  }
1168
- };
1516
+ }
1169
1517
 
1170
1518
  // src/core/scrollTo.ts
1171
- function scrollTo(state, params = {}) {
1172
- var _a;
1173
- const { animated, noScrollingTo } = params;
1519
+ function scrollTo(ctx, state, params) {
1520
+ var _a3;
1521
+ const { noScrollingTo, ...scrollTarget } = params;
1522
+ const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1174
1523
  const {
1175
1524
  refScroller,
1176
1525
  props: { horizontal }
1177
1526
  } = state;
1178
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1527
+ let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1528
+ if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
1529
+ const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
1530
+ offset = Math.min(offset, maxOffset);
1531
+ }
1179
1532
  state.scrollHistory.length = 0;
1180
1533
  if (!noScrollingTo) {
1181
- state.scrollingTo = params;
1534
+ set$(ctx, "scrollingTo", scrollTarget);
1182
1535
  }
1183
1536
  state.scrollPending = offset;
1184
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1185
- animated: !!animated,
1186
- x: horizontal ? offset : 0,
1187
- y: horizontal ? 0 : offset
1188
- });
1537
+ if (!isInitialScroll || Platform.OS === "android") {
1538
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollTo({
1539
+ animated: !!animated,
1540
+ x: horizontal ? offset : 0,
1541
+ y: horizontal ? 0 : offset
1542
+ });
1543
+ }
1189
1544
  if (!animated) {
1190
1545
  state.scroll = offset;
1191
- setTimeout(() => finishScrollTo(state), 100);
1546
+ setTimeout(() => finishScrollTo(ctx, state), 100);
1547
+ if (isInitialScroll) {
1548
+ setTimeout(() => {
1549
+ state.initialScroll = void 0;
1550
+ }, 500);
1551
+ }
1192
1552
  }
1193
1553
  }
1194
1554
 
@@ -1205,24 +1565,6 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1205
1565
  const didLayout = peek$(ctx, "containersDidLayout");
1206
1566
  if (didLayout) {
1207
1567
  doit();
1208
- const threshold = state.scroll - positionDiff / 2;
1209
- if (!state.ignoreScrollFromMVCP) {
1210
- state.ignoreScrollFromMVCP = {};
1211
- }
1212
- if (positionDiff > 0) {
1213
- state.ignoreScrollFromMVCP.lt = threshold;
1214
- } else {
1215
- state.ignoreScrollFromMVCP.gt = threshold;
1216
- }
1217
- if (state.ignoreScrollFromMVCPTimeout) {
1218
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
1219
- }
1220
- state.ignoreScrollFromMVCPTimeout = setTimeout(
1221
- () => {
1222
- state.ignoreScrollFromMVCP = void 0;
1223
- },
1224
- 100
1225
- );
1226
1568
  } else {
1227
1569
  requestAnimationFrame(doit);
1228
1570
  }
@@ -1234,9 +1576,9 @@ function prepareMVCP(ctx, state, dataChanged) {
1234
1576
  const {
1235
1577
  idsInView,
1236
1578
  positions,
1237
- scrollingTo,
1238
1579
  props: { maintainVisibleContentPosition }
1239
1580
  } = state;
1581
+ const scrollingTo = peek$(ctx, "scrollingTo");
1240
1582
  let prevPosition;
1241
1583
  let targetId;
1242
1584
  const idsInViewWithPositions = [];
@@ -1277,7 +1619,16 @@ function prepareMVCP(ctx, state, dataChanged) {
1277
1619
  if (targetId !== void 0 && prevPosition !== void 0) {
1278
1620
  const newPosition = positions.get(targetId);
1279
1621
  if (newPosition !== void 0) {
1280
- positionDiff = newPosition - prevPosition;
1622
+ const totalSize = peek$(ctx, "totalSize");
1623
+ let diff = newPosition - prevPosition;
1624
+ if (diff !== 0 && state.scroll + state.scrollLength > totalSize) {
1625
+ if (diff > 0) {
1626
+ diff = Math.max(0, totalSize - state.scroll - state.scrollLength);
1627
+ } else {
1628
+ diff = 0;
1629
+ }
1630
+ }
1631
+ positionDiff = diff;
1281
1632
  }
1282
1633
  }
1283
1634
  if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
@@ -1286,77 +1637,105 @@ function prepareMVCP(ctx, state, dataChanged) {
1286
1637
  };
1287
1638
  }
1288
1639
 
1289
- // src/utils/setPaddingTop.ts
1290
- function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1291
- if (stylePaddingTop !== void 0) {
1292
- const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1293
- if (stylePaddingTop < prevStylePaddingTop) {
1294
- let prevTotalSize = peek$(ctx, "totalSize") || 0;
1295
- set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
1296
- state.timeoutSetPaddingTop = setTimeout(() => {
1297
- prevTotalSize = peek$(ctx, "totalSize") || 0;
1298
- set$(ctx, "totalSize", prevTotalSize - prevStylePaddingTop);
1299
- }, 16);
1300
- }
1301
- set$(ctx, "stylePaddingTop", stylePaddingTop);
1640
+ // src/core/prepareColumnStartState.ts
1641
+ function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1642
+ var _a3;
1643
+ const numColumns = peek$(ctx, "numColumns");
1644
+ let rowStartIndex = startIndex;
1645
+ const columnAtStart = state.columns.get(state.idCache[startIndex]);
1646
+ if (columnAtStart !== 1) {
1647
+ rowStartIndex = findRowStartIndex(state, numColumns, startIndex);
1302
1648
  }
1303
- if (alignItemsPaddingTop !== void 0) {
1304
- set$(ctx, "alignItemsPaddingTop", alignItemsPaddingTop);
1649
+ let currentRowTop = 0;
1650
+ const curId = state.idCache[rowStartIndex];
1651
+ const column = state.columns.get(curId);
1652
+ if (rowStartIndex > 0) {
1653
+ const prevIndex = rowStartIndex - 1;
1654
+ const prevId = state.idCache[prevIndex];
1655
+ const prevPosition = (_a3 = state.positions.get(prevId)) != null ? _a3 : 0;
1656
+ const prevRowStart = findRowStartIndex(state, numColumns, prevIndex);
1657
+ const prevRowHeight = calculateRowMaxSize(ctx, state, prevRowStart, prevIndex, useAverageSize);
1658
+ currentRowTop = prevPosition + prevRowHeight;
1305
1659
  }
1660
+ return {
1661
+ column,
1662
+ currentRowTop,
1663
+ startIndex: rowStartIndex
1664
+ };
1306
1665
  }
1307
-
1308
- // src/utils/updateAlignItemsPaddingTop.ts
1309
- function updateAlignItemsPaddingTop(ctx, state) {
1310
- const {
1311
- scrollLength,
1312
- props: { alignItemsAtEnd, data }
1313
- } = state;
1314
- if (alignItemsAtEnd) {
1315
- let alignItemsPaddingTop = 0;
1316
- if ((data == null ? void 0 : data.length) > 0) {
1317
- const contentSize = getContentSize(ctx);
1318
- alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1666
+ function findRowStartIndex(state, numColumns, index) {
1667
+ if (numColumns <= 1) {
1668
+ return Math.max(0, index);
1669
+ }
1670
+ let rowStart = Math.max(0, index);
1671
+ while (rowStart > 0) {
1672
+ const columnForIndex = state.columns.get(state.idCache[rowStart]);
1673
+ if (columnForIndex === 1) {
1674
+ break;
1675
+ }
1676
+ rowStart--;
1677
+ }
1678
+ return rowStart;
1679
+ }
1680
+ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1681
+ if (endIndex < startIndex) {
1682
+ return 0;
1683
+ }
1684
+ const { data } = state.props;
1685
+ if (!data) {
1686
+ return 0;
1687
+ }
1688
+ let maxSize = 0;
1689
+ for (let i = startIndex; i <= endIndex; i++) {
1690
+ if (i < 0 || i >= data.length) {
1691
+ continue;
1692
+ }
1693
+ const id = state.idCache[i];
1694
+ const size = getItemSize(ctx, state, id, i, data[i], useAverageSize);
1695
+ if (size > maxSize) {
1696
+ maxSize = size;
1319
1697
  }
1320
- setPaddingTop(ctx, state, { alignItemsPaddingTop });
1321
1698
  }
1699
+ return maxSize;
1322
1700
  }
1323
1701
 
1324
- // src/core/updateTotalSize.ts
1325
- function updateTotalSize(ctx, state) {
1326
- const {
1327
- positions,
1328
- props: { data }
1329
- } = state;
1330
- if (data.length === 0) {
1331
- addTotalSize(ctx, state, null, 0);
1332
- } else {
1333
- const lastId = getId(state, data.length - 1);
1334
- if (lastId !== void 0) {
1335
- const lastPosition = positions.get(lastId);
1336
- if (lastPosition !== void 0) {
1337
- const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
1338
- if (lastSize !== void 0) {
1339
- const totalSize = lastPosition + lastSize;
1340
- addTotalSize(ctx, state, null, totalSize);
1702
+ // src/utils/getScrollVelocity.ts
1703
+ var getScrollVelocity = (state) => {
1704
+ const { scrollHistory } = state;
1705
+ let velocity = 0;
1706
+ if (scrollHistory.length >= 1) {
1707
+ const newest = scrollHistory[scrollHistory.length - 1];
1708
+ let oldest;
1709
+ let start = 0;
1710
+ const now = Date.now();
1711
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
1712
+ const entry = scrollHistory[i];
1713
+ const nextEntry = scrollHistory[i + 1];
1714
+ if (i > 0) {
1715
+ const prevEntry = scrollHistory[i - 1];
1716
+ const prevDirection = entry.scroll - prevEntry.scroll;
1717
+ const currentDirection = nextEntry.scroll - entry.scroll;
1718
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1719
+ start = i;
1720
+ break;
1341
1721
  }
1342
1722
  }
1343
1723
  }
1344
- }
1345
- }
1346
- function addTotalSize(ctx, state, key, add) {
1347
- const { alignItemsAtEnd } = state.props;
1348
- {
1349
- state.totalSize = add;
1350
- if (state.timeoutSetPaddingTop) {
1351
- clearTimeout(state.timeoutSetPaddingTop);
1352
- state.timeoutSetPaddingTop = void 0;
1724
+ for (let i = start; i < scrollHistory.length - 1; i++) {
1725
+ const entry = scrollHistory[i];
1726
+ if (now - entry.time <= 1e3) {
1727
+ oldest = entry;
1728
+ break;
1729
+ }
1730
+ }
1731
+ if (oldest && oldest !== newest) {
1732
+ const scrollDiff = newest.scroll - oldest.scroll;
1733
+ const timeDiff = newest.time - oldest.time;
1734
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1353
1735
  }
1354
1736
  }
1355
- set$(ctx, "totalSize", state.totalSize);
1356
- if (alignItemsAtEnd) {
1357
- updateAlignItemsPaddingTop(ctx, state);
1358
- }
1359
- }
1737
+ return velocity;
1738
+ };
1360
1739
 
1361
1740
  // src/utils/updateSnapToOffsets.ts
1362
1741
  function updateSnapToOffsets(ctx, state) {
@@ -1373,44 +1752,67 @@ function updateSnapToOffsets(ctx, state) {
1373
1752
  set$(ctx, "snapToOffsets", snapToOffsets);
1374
1753
  }
1375
1754
 
1376
- // src/core/updateAllPositions.ts
1377
- function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1378
- var _a, _b, _c, _d, _e, _f;
1755
+ // src/core/updateItemPositions.ts
1756
+ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false } = {
1757
+ forceFullUpdate: false,
1758
+ scrollBottomBuffered: -1,
1759
+ startIndex: 0
1760
+ }) {
1761
+ var _a3, _b, _c, _d, _e;
1379
1762
  const {
1380
1763
  columns,
1381
1764
  indexByKey,
1382
1765
  positions,
1383
1766
  idCache,
1384
1767
  sizesKnown,
1385
- props: { getEstimatedItemSize, snapToIndices, enableAverages }
1768
+ props: { getEstimatedItemSize, snapToIndices, enableAverages, maintainVisibleContentPosition }
1386
1769
  } = state;
1387
1770
  const data = state.props.data;
1771
+ const dataLength = data.length;
1388
1772
  const numColumns = peek$(ctx, "numColumns");
1389
- const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1773
+ const scrollingTo = peek$(ctx, "scrollingTo");
1774
+ const hasColumns = numColumns > 1;
1775
+ const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1776
+ const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1777
+ const maxVisibleArea = scrollBottomBuffered + 1e3;
1390
1778
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1779
+ const preferCachedSize = maintainVisibleContentPosition && (dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0);
1391
1780
  let currentRowTop = 0;
1392
1781
  let column = 1;
1393
1782
  let maxSizeInRow = 0;
1394
- const hasColumns = numColumns > 1;
1395
1783
  if (startIndex > 0) {
1396
- const prevIndex = startIndex - 1;
1397
- const prevId = (_a = idCache.get(prevIndex)) != null ? _a : getId(state, prevIndex);
1398
- const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1399
1784
  if (hasColumns) {
1400
- const prevColumn = (_c = columns.get(prevId)) != null ? _c : 1;
1401
- currentRowTop = prevPosition;
1402
- column = prevColumn % numColumns + 1;
1403
- } else {
1404
- const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(state, prevId, prevIndex, data[prevIndex], useAverageSize);
1785
+ const { startIndex: processedStartIndex, currentRowTop: initialRowTop } = prepareColumnStartState(
1786
+ ctx,
1787
+ state,
1788
+ startIndex,
1789
+ useAverageSize
1790
+ );
1791
+ startIndex = processedStartIndex;
1792
+ currentRowTop = initialRowTop;
1793
+ } else if (startIndex < dataLength) {
1794
+ const prevIndex = startIndex - 1;
1795
+ const prevId = getId(state, prevIndex);
1796
+ const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1797
+ const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1405
1798
  currentRowTop = prevPosition + prevSize;
1406
1799
  }
1407
1800
  }
1408
1801
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1409
- const dataLength = data.length;
1802
+ let didBreakEarly = false;
1803
+ let breakAt;
1410
1804
  for (let i = startIndex; i < dataLength; i++) {
1411
- const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1412
- const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(state, id, i, data[i], useAverageSize);
1413
- if (__DEV__ && needsIndexByKey) {
1805
+ if (shouldOptimize && breakAt !== void 0 && i > breakAt) {
1806
+ didBreakEarly = true;
1807
+ break;
1808
+ }
1809
+ if (shouldOptimize && breakAt === void 0 && !scrollingTo && !dataChanged && currentRowTop > maxVisibleArea) {
1810
+ const itemsPerRow = hasColumns ? numColumns : 1;
1811
+ breakAt = i + itemsPerRow + 10;
1812
+ }
1813
+ const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1814
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, state, id, i, data[i], useAverageSize, preferCachedSize);
1815
+ if (IS_DEV && needsIndexByKey) {
1414
1816
  if (indexByKeyForChecking.has(id)) {
1415
1817
  console.error(
1416
1818
  `[legend-list] Error: Detected overlapping key (${id}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`
@@ -1437,7 +1839,9 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1437
1839
  currentRowTop += size;
1438
1840
  }
1439
1841
  }
1440
- updateTotalSize(ctx, state);
1842
+ if (!didBreakEarly) {
1843
+ updateTotalSize(ctx, state);
1844
+ }
1441
1845
  if (snapToIndices) {
1442
1846
  updateSnapToOffsets(ctx, state);
1443
1847
  }
@@ -1457,6 +1861,21 @@ function ensureViewabilityState(ctx, configId) {
1457
1861
  }
1458
1862
  return state;
1459
1863
  }
1864
+ function setupViewability(props) {
1865
+ let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
1866
+ if (viewabilityConfig || onViewableItemsChanged) {
1867
+ viewabilityConfigCallbackPairs = [
1868
+ ...viewabilityConfigCallbackPairs || [],
1869
+ {
1870
+ onViewableItemsChanged,
1871
+ viewabilityConfig: viewabilityConfig || {
1872
+ viewAreaCoveragePercentThreshold: 0
1873
+ }
1874
+ }
1875
+ ];
1876
+ }
1877
+ return viewabilityConfigCallbackPairs;
1878
+ }
1460
1879
  function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
1461
1880
  const {
1462
1881
  timeouts,
@@ -1610,16 +2029,6 @@ function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize,
1610
2029
  const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
1611
2030
  return value.isViewable;
1612
2031
  }
1613
- function findContainerId(ctx, key) {
1614
- const numContainers = peek$(ctx, "numContainers");
1615
- for (let i = 0; i < numContainers; i++) {
1616
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1617
- if (itemKey === key) {
1618
- return i;
1619
- }
1620
- }
1621
- return -1;
1622
- }
1623
2032
  function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1624
2033
  const key = containerId + configId;
1625
2034
  ctx.mapViewabilityValues.set(key, viewToken);
@@ -1628,9 +2037,12 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1628
2037
  }
1629
2038
 
1630
2039
  // src/utils/checkAllSizesKnown.ts
2040
+ function isNullOrUndefined2(value) {
2041
+ return value === null || value === void 0;
2042
+ }
1631
2043
  function checkAllSizesKnown(state) {
1632
2044
  const { startBuffered, endBuffered, sizesKnown } = state;
1633
- if (endBuffered !== null && startBuffered >= 0 && endBuffered >= 0) {
2045
+ if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
1634
2046
  let areAllKnown = true;
1635
2047
  for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1636
2048
  const key = getId(state, i);
@@ -1647,6 +2059,8 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1647
2059
  const { stickyContainerPool, containerItemTypes } = state;
1648
2060
  const result = [];
1649
2061
  const availableContainers = [];
2062
+ const pendingRemovalSet = new Set(pendingRemoval);
2063
+ let pendingRemovalChanged = false;
1650
2064
  const stickyIndicesSet = state.props.stickyIndicesSet;
1651
2065
  const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
1652
2066
  const canReuseContainer = (containerIndex, requiredType) => {
@@ -1662,12 +2076,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1662
2076
  let foundContainer = false;
1663
2077
  for (const containerIndex of stickyContainerPool) {
1664
2078
  const key = peek$(ctx, `containerItemKey${containerIndex}`);
1665
- const isPendingRemoval = pendingRemoval.includes(containerIndex);
1666
- if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType)) {
2079
+ const isPendingRemoval = pendingRemovalSet.has(containerIndex);
2080
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType) && !result.includes(containerIndex)) {
1667
2081
  result.push(containerIndex);
1668
- if (isPendingRemoval) {
1669
- const index = pendingRemoval.indexOf(containerIndex);
1670
- pendingRemoval.splice(index, 1);
2082
+ if (isPendingRemoval && pendingRemovalSet.delete(containerIndex)) {
2083
+ pendingRemovalChanged = true;
1671
2084
  }
1672
2085
  foundContainer = true;
1673
2086
  if (requiredItemTypes) typeIndex++;
@@ -1687,13 +2100,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1687
2100
  }
1688
2101
  const key = peek$(ctx, `containerItemKey${u}`);
1689
2102
  let isOk = key === void 0;
1690
- if (!isOk) {
1691
- const index = pendingRemoval.indexOf(u);
1692
- if (index !== -1) {
1693
- pendingRemoval.splice(index, 1);
1694
- const requiredType = neededTypes[typeIndex];
1695
- isOk = canReuseContainer(u, requiredType);
1696
- }
2103
+ if (!isOk && pendingRemovalSet.has(u)) {
2104
+ pendingRemovalSet.delete(u);
2105
+ pendingRemovalChanged = true;
2106
+ const requiredType = neededTypes[typeIndex];
2107
+ isOk = canReuseContainer(u, requiredType);
1697
2108
  }
1698
2109
  if (isOk) {
1699
2110
  result.push(u);
@@ -1736,7 +2147,7 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1736
2147
  for (let i = 0; i < stillNeeded; i++) {
1737
2148
  result.push(numContainers + i);
1738
2149
  }
1739
- if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
2150
+ if (IS_DEV && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
1740
2151
  console.warn(
1741
2152
  "[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.",
1742
2153
  {
@@ -1751,50 +2162,18 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1751
2162
  }
1752
2163
  }
1753
2164
  }
2165
+ if (pendingRemovalChanged) {
2166
+ pendingRemoval.length = 0;
2167
+ for (const value of pendingRemovalSet) {
2168
+ pendingRemoval.push(value);
2169
+ }
2170
+ }
1754
2171
  return result.sort(comparatorDefault);
1755
2172
  }
1756
2173
  function comparatorByDistance(a, b) {
1757
2174
  return b.distance - a.distance;
1758
2175
  }
1759
2176
 
1760
- // src/utils/getScrollVelocity.ts
1761
- var getScrollVelocity = (state) => {
1762
- const { scrollHistory } = state;
1763
- let velocity = 0;
1764
- if (scrollHistory.length >= 1) {
1765
- const newest = scrollHistory[scrollHistory.length - 1];
1766
- let oldest;
1767
- let start = 0;
1768
- const now = Date.now();
1769
- for (let i = 0; i < scrollHistory.length - 1; i++) {
1770
- const entry = scrollHistory[i];
1771
- const nextEntry = scrollHistory[i + 1];
1772
- if (i > 0) {
1773
- const prevEntry = scrollHistory[i - 1];
1774
- const prevDirection = entry.scroll - prevEntry.scroll;
1775
- const currentDirection = nextEntry.scroll - entry.scroll;
1776
- if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1777
- start = i;
1778
- break;
1779
- }
1780
- }
1781
- }
1782
- for (let i = start; i < scrollHistory.length - 1; i++) {
1783
- const entry = scrollHistory[i];
1784
- if (now - entry.time <= 1e3) {
1785
- oldest = entry;
1786
- break;
1787
- }
1788
- }
1789
- if (oldest && oldest !== newest) {
1790
- const scrollDiff = newest.scroll - oldest.scroll;
1791
- const timeDiff = newest.time - oldest.time;
1792
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1793
- }
1794
- }
1795
- return velocity;
1796
- };
1797
-
1798
2177
  // src/core/scrollToIndex.ts
1799
2178
  function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1800
2179
  if (index >= state.props.data.length) {
@@ -1807,72 +2186,16 @@ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, vie
1807
2186
  if (isLast && viewPosition === void 0) {
1808
2187
  viewPosition = 1;
1809
2188
  }
1810
- const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1811
2189
  state.scrollForNextCalculateItemsInView = void 0;
1812
- scrollTo(state, {
2190
+ scrollTo(ctx, state, {
1813
2191
  animated,
1814
2192
  index,
1815
- offset: firstIndexScrollPostion,
2193
+ offset: firstIndexOffset,
1816
2194
  viewOffset,
1817
2195
  viewPosition: viewPosition != null ? viewPosition : 0
1818
2196
  });
1819
2197
  }
1820
2198
 
1821
- // src/utils/checkThreshold.ts
1822
- var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
1823
- const distanceAbs = Math.abs(distance);
1824
- const isAtThreshold = atThreshold || distanceAbs < threshold;
1825
- if (!isReached && !isBlockedByTimer) {
1826
- if (isAtThreshold) {
1827
- onReached == null ? void 0 : onReached(distance);
1828
- blockTimer == null ? void 0 : blockTimer(true);
1829
- setTimeout(() => {
1830
- blockTimer == null ? void 0 : blockTimer(false);
1831
- }, 700);
1832
- return true;
1833
- }
1834
- } else {
1835
- if (distance >= 1.3 * threshold) {
1836
- return false;
1837
- }
1838
- }
1839
- return isReached;
1840
- };
1841
-
1842
- // src/utils/checkAtBottom.ts
1843
- function checkAtBottom(ctx, state) {
1844
- if (!state) {
1845
- return;
1846
- }
1847
- const {
1848
- queuedInitialLayout,
1849
- scrollLength,
1850
- scroll,
1851
- maintainingScrollAtEnd,
1852
- props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1853
- } = state;
1854
- const contentSize = getContentSize(ctx);
1855
- if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1856
- const distanceFromEnd = contentSize - scroll - scrollLength;
1857
- const isContentLess = contentSize < scrollLength;
1858
- state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1859
- state.isEndReached = checkThreshold(
1860
- distanceFromEnd,
1861
- isContentLess,
1862
- onEndReachedThreshold * scrollLength,
1863
- state.isEndReached,
1864
- state.endReachedBlockedByTimer,
1865
- (distance) => {
1866
- var _a, _b;
1867
- return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1868
- },
1869
- (block) => {
1870
- state.endReachedBlockedByTimer = block;
1871
- }
1872
- );
1873
- }
1874
- }
1875
-
1876
2199
  // src/utils/setDidLayout.ts
1877
2200
  function setDidLayout(ctx, state) {
1878
2201
  const {
@@ -1895,11 +2218,12 @@ function setDidLayout(ctx, state) {
1895
2218
 
1896
2219
  // src/core/calculateItemsInView.ts
1897
2220
  function findCurrentStickyIndex(stickyArray, scroll, state) {
1898
- var _a;
2221
+ var _a3;
1899
2222
  const idCache = state.idCache;
1900
2223
  const positions = state.positions;
1901
2224
  for (let i = stickyArray.length - 1; i >= 0; i--) {
1902
- const stickyId = (_a = idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
2225
+ const stickyIndex = stickyArray[i];
2226
+ const stickyId = (_a3 = idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
1903
2227
  const stickyPos = stickyId ? positions.get(stickyId) : void 0;
1904
2228
  if (stickyPos !== void 0 && scroll >= stickyPos) {
1905
2229
  return i;
@@ -1912,42 +2236,46 @@ function getActiveStickyIndices(ctx, state, stickyIndices) {
1912
2236
  Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyIndices.has(idx))
1913
2237
  );
1914
2238
  }
1915
- function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll, needNewContainers, startBuffered, endBuffered) {
1916
- var _a;
2239
+ function handleStickyActivation(ctx, state, stickyIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
2240
+ var _a3;
1917
2241
  const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
1918
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
2242
+ state.activeStickyIndex = currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : void 0;
1919
2243
  for (let offset = 0; offset <= 1; offset++) {
1920
2244
  const idx = currentStickyIdx - offset;
1921
2245
  if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
1922
2246
  const stickyIndex = stickyArray[idx];
1923
- const stickyId = (_a = state.idCache.get(stickyIndex)) != null ? _a : getId(state, stickyIndex);
2247
+ const stickyId = (_a3 = state.idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
1924
2248
  if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered)) {
1925
2249
  needNewContainers.push(stickyIndex);
1926
2250
  }
1927
2251
  }
1928
2252
  }
1929
- function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pendingRemoval) {
1930
- var _a, _b, _c;
1931
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
2253
+ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
2254
+ var _a3, _b, _c;
1932
2255
  for (const containerIndex of state.stickyContainerPool) {
1933
2256
  const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
1934
2257
  const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
1935
2258
  if (itemIndex === void 0) continue;
1936
2259
  const arrayIdx = stickyArray.indexOf(itemIndex);
1937
- if (arrayIdx === -1) continue;
2260
+ if (arrayIdx === -1) {
2261
+ state.stickyContainerPool.delete(containerIndex);
2262
+ set$(ctx, `containerSticky${containerIndex}`, false);
2263
+ set$(ctx, `containerStickyOffset${containerIndex}`, void 0);
2264
+ continue;
2265
+ }
1938
2266
  const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
1939
2267
  if (isRecentSticky) continue;
1940
2268
  const nextIndex = stickyArray[arrayIdx + 1];
1941
2269
  let shouldRecycle = false;
1942
2270
  if (nextIndex) {
1943
- const nextId = (_a = state.idCache.get(nextIndex)) != null ? _a : getId(state, nextIndex);
2271
+ const nextId = (_a3 = state.idCache[nextIndex]) != null ? _a3 : getId(state, nextIndex);
1944
2272
  const nextPos = nextId ? state.positions.get(nextId) : void 0;
1945
2273
  shouldRecycle = nextPos !== void 0 && scroll > nextPos + scrollBuffer * 2;
1946
2274
  } else {
1947
- const currentId = (_b = state.idCache.get(itemIndex)) != null ? _b : getId(state, itemIndex);
2275
+ const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
1948
2276
  if (currentId) {
1949
2277
  const currentPos = state.positions.get(currentId);
1950
- const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
2278
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, state, currentId, itemIndex, state.props.data[itemIndex]);
1951
2279
  shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
1952
2280
  }
1953
2281
  }
@@ -1958,21 +2286,22 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pe
1958
2286
  }
1959
2287
  function calculateItemsInView(ctx, state, params = {}) {
1960
2288
  unstable_batchedUpdates(() => {
1961
- var _a, _b, _c, _d, _e, _f, _g, _h;
2289
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1962
2290
  const {
1963
2291
  columns,
1964
2292
  containerItemKeys,
1965
2293
  enableScrollForNextCalculateItemsInView,
1966
2294
  idCache,
1967
2295
  indexByKey,
2296
+ initialScroll,
1968
2297
  minIndexSizeChanged,
1969
2298
  positions,
2299
+ props: { getItemType, itemsAreEqual, keyExtractor, onStickyHeaderChange, scrollBuffer },
1970
2300
  scrollForNextCalculateItemsInView,
1971
2301
  scrollLength,
1972
2302
  sizes,
1973
2303
  startBufferedId: startBufferedIdOrig,
1974
- viewabilityConfigCallbackPairs,
1975
- props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, scrollBuffer }
2304
+ viewabilityConfigCallbackPairs
1976
2305
  } = state;
1977
2306
  const { data } = state.props;
1978
2307
  const stickyIndicesArr = state.props.stickyIndicesArr || [];
@@ -1984,35 +2313,22 @@ function calculateItemsInView(ctx, state, params = {}) {
1984
2313
  const totalSize = peek$(ctx, "totalSize");
1985
2314
  const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
1986
2315
  const numColumns = peek$(ctx, "numColumns");
1987
- const previousScrollAdjust = 0;
1988
- const { dataChanged, doMVCP } = params;
2316
+ const { dataChanged, doMVCP, forceFullItemPositions } = params;
1989
2317
  const speed = getScrollVelocity(state);
1990
- if (doMVCP || dataChanged) {
1991
- const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
1992
- if (dataChanged) {
1993
- indexByKey.clear();
1994
- idCache.clear();
1995
- positions.clear();
1996
- }
1997
- const startIndex = dataChanged ? 0 : minIndexSizeChanged != null ? minIndexSizeChanged : 0;
1998
- updateAllPositions(ctx, state, dataChanged, startIndex);
1999
- if (minIndexSizeChanged !== void 0) {
2000
- state.minIndexSizeChanged = void 0;
2001
- }
2002
- checkMVCP == null ? void 0 : checkMVCP();
2003
- }
2004
2318
  const scrollExtra = 0;
2005
2319
  const { queuedInitialLayout } = state;
2006
2320
  let { scroll: scrollState } = state;
2007
2321
  if (!queuedInitialLayout && initialScroll) {
2008
2322
  const updatedOffset = calculateOffsetWithOffsetPosition(
2323
+ ctx,
2009
2324
  state,
2010
2325
  calculateOffsetForIndex(ctx, state, initialScroll.index),
2011
2326
  initialScroll
2012
2327
  );
2013
2328
  scrollState = updatedOffset;
2014
2329
  }
2015
- const scrollAdjustPad = -previousScrollAdjust - topPad;
2330
+ const scrollAdjustPending = (_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0;
2331
+ const scrollAdjustPad = scrollAdjustPending - topPad;
2016
2332
  let scroll = scrollState + scrollExtra + scrollAdjustPad;
2017
2333
  if (scroll + scrollLength > totalSize) {
2018
2334
  scroll = Math.max(0, totalSize - scrollLength);
@@ -2021,6 +2337,11 @@ function calculateItemsInView(ctx, state, params = {}) {
2021
2337
  set$(ctx, "debugRawScroll", scrollState);
2022
2338
  set$(ctx, "debugComputedScroll", scroll);
2023
2339
  }
2340
+ const previousStickyIndex = state.activeStickyIndex;
2341
+ const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
2342
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : void 0;
2343
+ state.activeStickyIndex = nextActiveStickyIndex;
2344
+ set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
2024
2345
  let scrollBufferTop = scrollBuffer;
2025
2346
  let scrollBufferBottom = scrollBuffer;
2026
2347
  if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
@@ -2033,22 +2354,38 @@ function calculateItemsInView(ctx, state, params = {}) {
2033
2354
  const scrollTopBuffered = scroll - scrollBufferTop;
2034
2355
  const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
2035
2356
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
2036
- if (scrollForNextCalculateItemsInView) {
2357
+ if (!dataChanged && scrollForNextCalculateItemsInView) {
2037
2358
  const { top, bottom } = scrollForNextCalculateItemsInView;
2038
2359
  if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
2039
2360
  return;
2040
2361
  }
2041
2362
  }
2363
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
2364
+ if (dataChanged) {
2365
+ indexByKey.clear();
2366
+ idCache.length = 0;
2367
+ positions.clear();
2368
+ }
2369
+ const startIndex = dataChanged ? 0 : (_b = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _b : 0;
2370
+ updateItemPositions(ctx, state, dataChanged, {
2371
+ forceFullUpdate: !!forceFullItemPositions,
2372
+ scrollBottomBuffered,
2373
+ startIndex
2374
+ });
2375
+ if (minIndexSizeChanged !== void 0) {
2376
+ state.minIndexSizeChanged = void 0;
2377
+ }
2378
+ checkMVCP == null ? void 0 : checkMVCP();
2042
2379
  let startNoBuffer = null;
2043
2380
  let startBuffered = null;
2044
2381
  let startBufferedId = null;
2045
2382
  let endNoBuffer = null;
2046
2383
  let endBuffered = null;
2047
- let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2384
+ let loopStart = !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2048
2385
  for (let i = loopStart; i >= 0; i--) {
2049
- const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
2386
+ const id = (_c = idCache[i]) != null ? _c : getId(state, i);
2050
2387
  const top = positions.get(id);
2051
- const size = (_b = sizes.get(id)) != null ? _b : getItemSize(state, id, i, data[i]);
2388
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i]);
2052
2389
  const bottom = top + size;
2053
2390
  if (bottom > scroll - scrollBuffer) {
2054
2391
  loopStart = i;
@@ -2074,8 +2411,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2074
2411
  let firstFullyOnScreenIndex;
2075
2412
  const dataLength = data.length;
2076
2413
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
2077
- const id = (_c = idCache.get(i)) != null ? _c : getId(state, i);
2078
- const size = (_d = sizes.get(id)) != null ? _d : getItemSize(state, id, i, data[i]);
2414
+ const id = (_e = idCache[i]) != null ? _e : getId(state, i);
2415
+ const size = (_f = sizes.get(id)) != null ? _f : getItemSize(ctx, state, id, i, data[i]);
2079
2416
  const top = positions.get(id);
2080
2417
  if (!foundEnd) {
2081
2418
  if (startNoBuffer === null && top + size > scroll) {
@@ -2104,7 +2441,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2104
2441
  }
2105
2442
  const idsInView = [];
2106
2443
  for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
2107
- const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
2444
+ const id = (_g = idCache[i]) != null ? _g : getId(state, i);
2108
2445
  idsInView.push(id);
2109
2446
  }
2110
2447
  Object.assign(state, {
@@ -2136,7 +2473,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2136
2473
  let numContainers2 = prevNumContainers;
2137
2474
  const needNewContainers = [];
2138
2475
  for (let i = startBuffered; i <= endBuffered; i++) {
2139
- const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
2476
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
2140
2477
  if (!containerItemKeys.has(id)) {
2141
2478
  needNewContainers.push(i);
2142
2479
  }
@@ -2147,11 +2484,14 @@ function calculateItemsInView(ctx, state, params = {}) {
2147
2484
  state,
2148
2485
  stickyIndicesSet,
2149
2486
  stickyIndicesArr,
2150
- scroll,
2487
+ currentStickyIdx,
2151
2488
  needNewContainers,
2152
2489
  startBuffered,
2153
2490
  endBuffered
2154
2491
  );
2492
+ } else {
2493
+ state.activeStickyIndex = void 0;
2494
+ set$(ctx, "activeStickyIndex", void 0);
2155
2495
  }
2156
2496
  if (needNewContainers.length > 0) {
2157
2497
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
@@ -2171,7 +2511,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2171
2511
  for (let idx = 0; idx < needNewContainers.length; idx++) {
2172
2512
  const i = needNewContainers[idx];
2173
2513
  const containerIndex = availableContainers[idx];
2174
- const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
2514
+ const id = (_i = idCache[i]) != null ? _i : getId(state, i);
2175
2515
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
2176
2516
  if (oldKey && oldKey !== id) {
2177
2517
  containerItemKeys.delete(oldKey);
@@ -2185,9 +2525,10 @@ function calculateItemsInView(ctx, state, params = {}) {
2185
2525
  if (stickyIndicesSet.has(i)) {
2186
2526
  set$(ctx, `containerSticky${containerIndex}`, true);
2187
2527
  const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2188
- set$(ctx, `containerStickyOffset${containerIndex}`, createAnimatedValue(topPadding));
2528
+ set$(ctx, `containerStickyOffset${containerIndex}`, topPadding);
2189
2529
  state.stickyContainerPool.add(containerIndex);
2190
2530
  } else {
2531
+ set$(ctx, `containerSticky${containerIndex}`, false);
2191
2532
  state.stickyContainerPool.delete(containerIndex);
2192
2533
  }
2193
2534
  if (containerIndex >= numContainers2) {
@@ -2203,13 +2544,13 @@ function calculateItemsInView(ctx, state, params = {}) {
2203
2544
  }
2204
2545
  }
2205
2546
  if (stickyIndicesArr.length > 0) {
2206
- handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, pendingRemoval);
2547
+ handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2207
2548
  }
2208
2549
  let didChangePositions = false;
2209
2550
  for (let i = 0; i < numContainers; i++) {
2210
2551
  const itemKey = peek$(ctx, `containerItemKey${i}`);
2211
2552
  if (pendingRemoval.includes(i)) {
2212
- if (itemKey) {
2553
+ if (itemKey !== void 0) {
2213
2554
  containerItemKeys.delete(itemKey);
2214
2555
  }
2215
2556
  state.containerItemTypes.delete(i);
@@ -2226,11 +2567,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2226
2567
  const itemIndex = indexByKey.get(itemKey);
2227
2568
  const item = data[itemIndex];
2228
2569
  if (item !== void 0) {
2229
- const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
2230
- const position = positions.get(id);
2231
- if (position === void 0) {
2570
+ const id = (_j = idCache[itemIndex]) != null ? _j : getId(state, itemIndex);
2571
+ const positionValue = positions.get(id);
2572
+ if (positionValue === void 0) {
2232
2573
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2233
2574
  } else {
2575
+ const position = (positionValue || 0) - scrollAdjustPending;
2234
2576
  const column = columns.get(id) || 1;
2235
2577
  const prevPos = peek$(ctx, `containerPosition${i}`);
2236
2578
  const prevColumn = peek$(ctx, `containerColumn${i}`);
@@ -2243,7 +2585,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2243
2585
  set$(ctx, `containerColumn${i}`, column);
2244
2586
  }
2245
2587
  if (prevData !== item && (itemsAreEqual ? !itemsAreEqual(prevData, item, itemIndex, data) : true)) {
2246
- set$(ctx, `containerItemData${i}`, data[itemIndex]);
2588
+ set$(ctx, `containerItemData${i}`, item);
2247
2589
  }
2248
2590
  }
2249
2591
  }
@@ -2260,12 +2602,140 @@ function calculateItemsInView(ctx, state, params = {}) {
2260
2602
  if (viewabilityConfigCallbackPairs) {
2261
2603
  updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
2262
2604
  }
2263
- });
2605
+ if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
2606
+ const item = data[nextActiveStickyIndex];
2607
+ if (item !== void 0) {
2608
+ onStickyHeaderChange({ index: nextActiveStickyIndex, item });
2609
+ }
2610
+ }
2611
+ });
2612
+ }
2613
+
2614
+ // src/core/checkActualChange.ts
2615
+ function checkActualChange(state, dataProp, previousData) {
2616
+ if (!previousData || !dataProp || dataProp.length !== previousData.length) {
2617
+ return true;
2618
+ }
2619
+ const {
2620
+ idCache,
2621
+ props: { keyExtractor }
2622
+ } = state;
2623
+ for (let i = 0; i < dataProp.length; i++) {
2624
+ if (dataProp[i] !== previousData[i]) {
2625
+ return true;
2626
+ }
2627
+ if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
2628
+ return true;
2629
+ }
2630
+ }
2631
+ return false;
2632
+ }
2633
+
2634
+ // src/core/doMaintainScrollAtEnd.ts
2635
+ function doMaintainScrollAtEnd(ctx, state, animated) {
2636
+ const {
2637
+ refScroller,
2638
+ props: { maintainScrollAtEnd }
2639
+ } = state;
2640
+ if ((state == null ? void 0 : state.isAtEnd) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
2641
+ const paddingTop = peek$(ctx, "alignItemsPaddingTop");
2642
+ if (paddingTop > 0) {
2643
+ state.scroll = 0;
2644
+ }
2645
+ requestAnimationFrame(() => {
2646
+ var _a3;
2647
+ if (state == null ? void 0 : state.isAtEnd) {
2648
+ state.maintainingScrollAtEnd = true;
2649
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
2650
+ animated
2651
+ });
2652
+ setTimeout(
2653
+ () => {
2654
+ state.maintainingScrollAtEnd = false;
2655
+ },
2656
+ 0
2657
+ );
2658
+ }
2659
+ });
2660
+ return true;
2661
+ }
2662
+ }
2663
+
2664
+ // src/utils/updateAveragesOnDataChange.ts
2665
+ function updateAveragesOnDataChange(state, oldData, newData) {
2666
+ var _a3;
2667
+ const {
2668
+ averageSizes,
2669
+ sizesKnown,
2670
+ indexByKey,
2671
+ props: { itemsAreEqual, getItemType, keyExtractor }
2672
+ } = state;
2673
+ if (!itemsAreEqual || !oldData.length || !newData.length) {
2674
+ for (const key in averageSizes) {
2675
+ delete averageSizes[key];
2676
+ }
2677
+ return;
2678
+ }
2679
+ const itemTypesToPreserve = {};
2680
+ const newDataLength = newData.length;
2681
+ const oldDataLength = oldData.length;
2682
+ for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
2683
+ const newItem = newData[newIndex];
2684
+ const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
2685
+ const oldIndex = indexByKey.get(id);
2686
+ if (oldIndex !== void 0 && oldIndex < oldDataLength) {
2687
+ const knownSize = sizesKnown.get(id);
2688
+ if (knownSize === void 0) continue;
2689
+ const oldItem = oldData[oldIndex];
2690
+ const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
2691
+ if (areEqual) {
2692
+ const itemType = getItemType ? (_a3 = getItemType(newItem, newIndex)) != null ? _a3 : "" : "";
2693
+ let typeData = itemTypesToPreserve[itemType];
2694
+ if (!typeData) {
2695
+ typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
2696
+ }
2697
+ typeData.totalSize += knownSize;
2698
+ typeData.count++;
2699
+ }
2700
+ }
2701
+ }
2702
+ for (const key in averageSizes) {
2703
+ delete averageSizes[key];
2704
+ }
2705
+ for (const itemType in itemTypesToPreserve) {
2706
+ const { totalSize, count } = itemTypesToPreserve[itemType];
2707
+ if (count > 0) {
2708
+ averageSizes[itemType] = {
2709
+ avg: totalSize / count,
2710
+ num: count
2711
+ };
2712
+ }
2713
+ }
2714
+ }
2715
+
2716
+ // src/core/checkResetContainers.ts
2717
+ function checkResetContainers(ctx, state, dataProp) {
2718
+ const { previousData } = state;
2719
+ if (previousData) {
2720
+ updateAveragesOnDataChange(state, previousData, dataProp);
2721
+ }
2722
+ const { maintainScrollAtEnd } = state.props;
2723
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2724
+ const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
2725
+ const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state, false);
2726
+ if (!didMaintainScrollAtEnd && previousData && dataProp.length > previousData.length) {
2727
+ state.isEndReached = false;
2728
+ }
2729
+ if (!didMaintainScrollAtEnd) {
2730
+ checkAtTop(state);
2731
+ checkAtBottom(ctx, state);
2732
+ }
2733
+ delete state.previousData;
2264
2734
  }
2265
2735
 
2266
2736
  // src/core/doInitialAllocateContainers.ts
2267
2737
  function doInitialAllocateContainers(ctx, state) {
2268
- var _a;
2738
+ var _a3, _b, _c;
2269
2739
  const {
2270
2740
  scrollLength,
2271
2741
  props: {
@@ -2281,12 +2751,13 @@ function doInitialAllocateContainers(ctx, state) {
2281
2751
  const hasContainers = peek$(ctx, "numContainers");
2282
2752
  if (scrollLength > 0 && data.length > 0 && !hasContainers) {
2283
2753
  let averageItemSize;
2284
- const fn = getFixedItemSize || getEstimatedItemSize;
2285
- if (fn) {
2754
+ if (getFixedItemSize || getEstimatedItemSize) {
2286
2755
  let totalSize = 0;
2287
2756
  const num = Math.min(20, data.length);
2288
2757
  for (let i = 0; i < num; i++) {
2289
- totalSize += fn(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "");
2758
+ const item = data[i];
2759
+ const itemType = getItemType ? (_a3 = getItemType(item, i)) != null ? _a3 : "" : "";
2760
+ totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(i, item, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(i, item, itemType)) != null ? _c : estimatedItemSize;
2290
2761
  }
2291
2762
  averageItemSize = totalSize / num;
2292
2763
  } else {
@@ -2300,76 +2771,18 @@ function doInitialAllocateContainers(ctx, state) {
2300
2771
  set$(ctx, "numContainers", numContainers);
2301
2772
  set$(ctx, "numContainersPooled", numContainers * state.props.initialContainerPoolRatio);
2302
2773
  if (state.lastLayout) {
2303
- if (state.props.initialScroll) {
2774
+ if (state.initialScroll) {
2304
2775
  requestAnimationFrame(() => {
2305
- calculateItemsInView(ctx, state, { dataChanged: true });
2776
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2306
2777
  });
2307
2778
  } else {
2308
- calculateItemsInView(ctx, state, { dataChanged: true });
2779
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2309
2780
  }
2310
2781
  }
2311
2782
  return true;
2312
2783
  }
2313
2784
  }
2314
2785
 
2315
- // src/core/doMaintainScrollAtEnd.ts
2316
- function doMaintainScrollAtEnd(ctx, state, animated) {
2317
- const {
2318
- refScroller,
2319
- props: { maintainScrollAtEnd }
2320
- } = state;
2321
- if ((state == null ? void 0 : state.isAtEnd) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
2322
- const paddingTop = peek$(ctx, "alignItemsPaddingTop");
2323
- if (paddingTop > 0) {
2324
- state.scroll = 0;
2325
- }
2326
- requestAnimationFrame(() => {
2327
- var _a;
2328
- if (state == null ? void 0 : state.isAtEnd) {
2329
- state.maintainingScrollAtEnd = true;
2330
- (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
2331
- animated
2332
- });
2333
- setTimeout(
2334
- () => {
2335
- state.maintainingScrollAtEnd = false;
2336
- },
2337
- 0
2338
- );
2339
- }
2340
- });
2341
- return true;
2342
- }
2343
- }
2344
-
2345
- // src/utils/checkAtTop.ts
2346
- function checkAtTop(state) {
2347
- if (!state) {
2348
- return;
2349
- }
2350
- const {
2351
- scrollLength,
2352
- scroll,
2353
- props: { onStartReachedThreshold }
2354
- } = state;
2355
- const distanceFromTop = scroll;
2356
- state.isAtStart = distanceFromTop <= 0;
2357
- state.isStartReached = checkThreshold(
2358
- distanceFromTop,
2359
- false,
2360
- onStartReachedThreshold * scrollLength,
2361
- state.isStartReached,
2362
- state.startReachedBlockedByTimer,
2363
- (distance) => {
2364
- var _a, _b;
2365
- return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
2366
- },
2367
- (block) => {
2368
- state.startReachedBlockedByTimer = block;
2369
- }
2370
- );
2371
- }
2372
-
2373
2786
  // src/core/handleLayout.ts
2374
2787
  function handleLayout(ctx, state, layout, setCanRender) {
2375
2788
  const { maintainScrollAtEnd } = state.props;
@@ -2404,87 +2817,57 @@ function handleLayout(ctx, state, layout, setCanRender) {
2404
2817
  if (state) {
2405
2818
  state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2406
2819
  }
2407
- if (__DEV__ && measuredLength === 0) {
2820
+ if (IS_DEV && measuredLength === 0) {
2408
2821
  warnDevOnce(
2409
2822
  "height0",
2410
2823
  `List ${state.props.horizontal ? "width" : "height"} is 0. You may need to set a style or \`flex: \` for the list, because children are absolutely positioned.`
2411
2824
  );
2412
2825
  }
2413
- setCanRender(true);
2414
- }
2415
- }
2416
-
2417
- // src/core/onScroll.ts
2418
- function onScroll(ctx, state, event) {
2419
- var _a, _b, _c;
2420
- const {
2421
- scrollProcessingEnabled,
2422
- props: { onScroll: onScrollProp }
2423
- } = state;
2424
- if (scrollProcessingEnabled === false) {
2425
- return;
2426
- }
2427
- if (((_b = (_a = event.nativeEvent) == null ? void 0 : _a.contentSize) == null ? void 0 : _b.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
2428
- return;
2429
- }
2430
- const newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
2431
- const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
2432
- if (ignoreScrollFromMVCP && !state.scrollingTo) {
2433
- const { lt, gt } = ignoreScrollFromMVCP;
2434
- if (lt && newScroll < lt || gt && newScroll > gt) {
2435
- return;
2436
- }
2437
- }
2438
- state.scrollPending = newScroll;
2439
- {
2440
- if (!state.onScrollRafScheduled) {
2441
- state.onScrollRafScheduled = true;
2442
- requestAnimationFrame(() => {
2443
- state.onScrollRafScheduled = false;
2444
- updateScroll(ctx, state, newScroll);
2445
- });
2446
- }
2447
- }
2448
- onScrollProp == null ? void 0 : onScrollProp(event);
2449
- }
2450
- function updateScroll(ctx, state, newScroll) {
2451
- const scrollingTo = state.scrollingTo;
2452
- state.hasScrolled = true;
2453
- state.lastBatchingAction = Date.now();
2454
- const currentTime = Date.now();
2455
- if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
2456
- const adjust = state.scrollAdjustHandler.getAdjust();
2457
- state.scrollHistory.push({ scroll: newScroll - adjust, time: currentTime });
2458
- }
2459
- if (state.scrollHistory.length > 5) {
2460
- state.scrollHistory.shift();
2461
- }
2462
- state.scrollPrev = state.scroll;
2463
- state.scrollPrevTime = state.scrollTime;
2464
- state.scroll = newScroll;
2465
- state.scrollTime = currentTime;
2466
- if (Math.abs(state.scroll - state.scrollPrev) > 2) {
2467
- calculateItemsInView(ctx, state);
2468
- checkAtBottom(ctx, state);
2469
- checkAtTop(state);
2470
2826
  }
2827
+ setCanRender(true);
2471
2828
  }
2472
2829
 
2473
2830
  // src/core/ScrollAdjustHandler.ts
2474
2831
  var ScrollAdjustHandler = class {
2475
2832
  constructor(ctx) {
2476
2833
  this.appliedAdjust = 0;
2834
+ this.pendingAdjust = 0;
2477
2835
  this.mounted = false;
2478
2836
  this.context = ctx;
2837
+ {
2838
+ const commitPendingAdjust = () => {
2839
+ const state = this.context.internalState;
2840
+ const pending = this.pendingAdjust;
2841
+ if (pending !== 0) {
2842
+ this.pendingAdjust = 0;
2843
+ this.appliedAdjust += pending;
2844
+ state.scroll += pending;
2845
+ state.scrollForNextCalculateItemsInView = void 0;
2846
+ set$(this.context, "scrollAdjustPending", 0);
2847
+ set$(this.context, "scrollAdjust", this.appliedAdjust);
2848
+ calculateItemsInView(this.context, this.context.internalState);
2849
+ }
2850
+ };
2851
+ listen$(this.context, "scrollingTo", (value) => {
2852
+ if (value === void 0) {
2853
+ commitPendingAdjust();
2854
+ }
2855
+ });
2856
+ }
2479
2857
  }
2480
2858
  requestAdjust(add) {
2481
- const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
2482
- this.appliedAdjust = add + oldAdjustTop;
2483
- const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
2484
- if (this.mounted) {
2485
- set();
2859
+ const scrollingTo = peek$(this.context, "scrollingTo");
2860
+ if ((scrollingTo == null ? void 0 : scrollingTo.animated) && !scrollingTo.isInitialScroll) {
2861
+ this.pendingAdjust += add;
2862
+ set$(this.context, "scrollAdjustPending", this.pendingAdjust);
2486
2863
  } else {
2487
- requestAnimationFrame(set);
2864
+ this.appliedAdjust += add;
2865
+ const setter = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
2866
+ if (this.mounted) {
2867
+ setter();
2868
+ } else {
2869
+ requestAnimationFrame(setter);
2870
+ }
2488
2871
  }
2489
2872
  }
2490
2873
  setMounted() {
@@ -2497,14 +2880,13 @@ var ScrollAdjustHandler = class {
2497
2880
 
2498
2881
  // src/core/updateItemSize.ts
2499
2882
  function updateItemSize(ctx, state, itemKey, sizeObj) {
2500
- var _a, _b;
2883
+ var _a3;
2501
2884
  const {
2502
2885
  sizesKnown,
2503
2886
  props: {
2504
2887
  getFixedItemSize,
2505
2888
  getItemType,
2506
2889
  horizontal,
2507
- maintainVisibleContentPosition,
2508
2890
  suggestEstimatedItemSize,
2509
2891
  onItemSizeChanged,
2510
2892
  data,
@@ -2512,17 +2894,17 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2512
2894
  }
2513
2895
  } = state;
2514
2896
  if (!data) return;
2897
+ const index = state.indexByKey.get(itemKey);
2515
2898
  if (getFixedItemSize) {
2516
- const index2 = state.indexByKey.get(itemKey);
2517
- if (index2 === void 0) {
2899
+ if (index === void 0) {
2518
2900
  return;
2519
2901
  }
2520
- const itemData = state.props.data[index2];
2902
+ const itemData = state.props.data[index];
2521
2903
  if (itemData === void 0) {
2522
2904
  return;
2523
2905
  }
2524
- const type = getItemType ? (_a = getItemType(itemData, index2)) != null ? _a : "" : "";
2525
- const size2 = getFixedItemSize(index2, itemData, type);
2906
+ const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
2907
+ const size2 = getFixedItemSize(index, itemData, type);
2526
2908
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
2527
2909
  return;
2528
2910
  }
@@ -2532,15 +2914,11 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2532
2914
  let shouldMaintainScrollAtEnd = false;
2533
2915
  let minIndexSizeChanged;
2534
2916
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2535
- const index = state.indexByKey.get(itemKey);
2536
2917
  const prevSizeKnown = state.sizesKnown.get(itemKey);
2537
- const diff = updateOneItemSize(state, itemKey, sizeObj);
2538
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2918
+ const diff = updateOneItemSize(ctx, state, itemKey, sizeObj);
2919
+ const size = roundSize(horizontal ? sizeObj.width : sizeObj.height);
2539
2920
  if (diff !== 0) {
2540
2921
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
2541
- if (((_b = state.scrollingTo) == null ? void 0 : _b.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
2542
- requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
2543
- }
2544
2922
  const { startBuffered, endBuffered } = state;
2545
2923
  needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2546
2924
  if (!needsRecalculate) {
@@ -2570,13 +2948,13 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2570
2948
  if (minIndexSizeChanged !== void 0) {
2571
2949
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
2572
2950
  }
2573
- if (__DEV__ && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
2951
+ if (IS_DEV && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
2574
2952
  if (state.timeoutSizeMessage) clearTimeout(state.timeoutSizeMessage);
2575
2953
  state.timeoutSizeMessage = setTimeout(() => {
2576
- var _a2;
2954
+ var _a4;
2577
2955
  state.timeoutSizeMessage = void 0;
2578
2956
  const num = state.sizesKnown.size;
2579
- const avg = (_a2 = state.averageSizes[""]) == null ? void 0 : _a2.avg;
2957
+ const avg = (_a4 = state.averageSizes[""]) == null ? void 0 : _a4.avg;
2580
2958
  console.warn(
2581
2959
  `[legend-list] Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`
2582
2960
  );
@@ -2598,8 +2976,8 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2598
2976
  }
2599
2977
  }
2600
2978
  }
2601
- function updateOneItemSize(state, itemKey, sizeObj) {
2602
- var _a;
2979
+ function updateOneItemSize(ctx, state, itemKey, sizeObj) {
2980
+ var _a3;
2603
2981
  const {
2604
2982
  sizes,
2605
2983
  indexByKey,
@@ -2609,12 +2987,12 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2609
2987
  } = state;
2610
2988
  if (!data) return 0;
2611
2989
  const index = indexByKey.get(itemKey);
2612
- const prevSize = getItemSize(state, itemKey, index, data);
2990
+ const prevSize = getItemSize(ctx, state, itemKey, index, data[index]);
2613
2991
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
2614
2992
  const size = Math.round(rawSize) ;
2615
2993
  sizesKnown.set(itemKey, size);
2616
2994
  if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
2617
- const itemType = getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : "";
2995
+ const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
2618
2996
  let averages = averageSizes[itemType];
2619
2997
  if (!averages) {
2620
2998
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -2623,7 +3001,7 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2623
3001
  averages.num++;
2624
3002
  }
2625
3003
  if (!prevSize || Math.abs(prevSize - size) > 0.1) {
2626
- sizes.set(itemKey, size);
3004
+ setSize(ctx, state, itemKey, size);
2627
3005
  return size - prevSize;
2628
3006
  }
2629
3007
  return 0;
@@ -2645,24 +3023,12 @@ var useCombinedRef = (...refs) => {
2645
3023
  };
2646
3024
 
2647
3025
  // src/platform/RefreshControl.tsx
2648
- function RefreshControl(props) {
3026
+ function RefreshControl(_props) {
2649
3027
  return null;
2650
3028
  }
2651
3029
 
2652
- // src/platform/StyleSheet.tsx
2653
- function flattenStyles(styles) {
2654
- if (Array.isArray(styles)) {
2655
- return Object.assign({}, ...styles.filter(Boolean));
2656
- }
2657
- return styles;
2658
- }
2659
- var StyleSheet = {
2660
- create: (styles) => styles,
2661
- flatten: (style) => flattenStyles(style)
2662
- };
2663
-
2664
3030
  // src/platform/useStickyScrollHandler.ts
2665
- function useStickyScrollHandler(stickyIndices, horizontal, ctx, onScroll2) {
3031
+ function useStickyScrollHandler(_stickyIndices, _horizontal, _ctx, onScroll2) {
2666
3032
  return onScroll2;
2667
3033
  }
2668
3034
 
@@ -2680,8 +3046,93 @@ function createColumnWrapperStyle(contentContainerStyle) {
2680
3046
  };
2681
3047
  }
2682
3048
  }
3049
+
3050
+ // src/utils/createImperativeHandle.ts
3051
+ function createImperativeHandle(ctx, state) {
3052
+ const scrollIndexIntoView = (options) => {
3053
+ if (state) {
3054
+ const { index, ...rest } = options;
3055
+ const { startNoBuffer, endNoBuffer } = state;
3056
+ if (index < startNoBuffer || index > endNoBuffer) {
3057
+ const viewPosition = index < startNoBuffer ? 0 : 1;
3058
+ scrollToIndex(ctx, state, {
3059
+ ...rest,
3060
+ index,
3061
+ viewPosition
3062
+ });
3063
+ }
3064
+ }
3065
+ };
3066
+ const refScroller = state.refScroller;
3067
+ return {
3068
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
3069
+ getNativeScrollRef: () => refScroller.current,
3070
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
3071
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
3072
+ getState: () => ({
3073
+ activeStickyIndex: state.activeStickyIndex,
3074
+ contentLength: state.totalSize,
3075
+ data: state.props.data,
3076
+ elementAtIndex: (index) => {
3077
+ var _a3;
3078
+ return (_a3 = ctx.viewRefs.get(findContainerId(ctx, getId(state, index)))) == null ? void 0 : _a3.current;
3079
+ },
3080
+ end: state.endNoBuffer,
3081
+ endBuffered: state.endBuffered,
3082
+ isAtEnd: state.isAtEnd,
3083
+ isAtStart: state.isAtStart,
3084
+ positionAtIndex: (index) => state.positions.get(getId(state, index)),
3085
+ positions: state.positions,
3086
+ scroll: state.scroll,
3087
+ scrollLength: state.scrollLength,
3088
+ sizeAtIndex: (index) => state.sizesKnown.get(getId(state, index)),
3089
+ sizes: state.sizesKnown,
3090
+ start: state.startNoBuffer,
3091
+ startBuffered: state.startBuffered
3092
+ }),
3093
+ scrollIndexIntoView,
3094
+ scrollItemIntoView: ({ item, ...props }) => {
3095
+ const data = state.props.data;
3096
+ const index = data.indexOf(item);
3097
+ if (index !== -1) {
3098
+ scrollIndexIntoView({ index, ...props });
3099
+ }
3100
+ },
3101
+ scrollToEnd: (options) => {
3102
+ const data = state.props.data;
3103
+ const stylePaddingBottom = state.props.stylePaddingBottom;
3104
+ const index = data.length - 1;
3105
+ if (index !== -1) {
3106
+ const paddingBottom = stylePaddingBottom || 0;
3107
+ const footerSize = peek$(ctx, "footerSize") || 0;
3108
+ scrollToIndex(ctx, state, {
3109
+ index,
3110
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
3111
+ viewPosition: 1,
3112
+ ...options
3113
+ });
3114
+ }
3115
+ },
3116
+ scrollToIndex: (params) => scrollToIndex(ctx, state, params),
3117
+ scrollToItem: ({ item, ...props }) => {
3118
+ const data = state.props.data;
3119
+ const index = data.indexOf(item);
3120
+ if (index !== -1) {
3121
+ scrollToIndex(ctx, state, { index, ...props });
3122
+ }
3123
+ },
3124
+ scrollToOffset: (params) => scrollTo(ctx, state, params),
3125
+ setScrollProcessingEnabled: (enabled) => {
3126
+ state.scrollProcessingEnabled = enabled;
3127
+ },
3128
+ setVisibleContentAnchorOffset: (value) => {
3129
+ const val = isFunction(value) ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
3130
+ set$(ctx, "scrollAdjustUserOffset", val);
3131
+ }
3132
+ };
3133
+ }
2683
3134
  function getRenderedItem(ctx, state, key) {
2684
- var _a;
3135
+ var _a3;
2685
3136
  if (!state) {
2686
3137
  return null;
2687
3138
  }
@@ -2694,15 +3145,17 @@ function getRenderedItem(ctx, state, key) {
2694
3145
  return null;
2695
3146
  }
2696
3147
  let renderedItem = null;
2697
- if (renderItem && data[index]) {
3148
+ const extraData = peek$(ctx, "extraData");
3149
+ const item = data[index];
3150
+ if (renderItem && !isNullOrUndefined(item)) {
2698
3151
  const itemProps = {
2699
3152
  data,
2700
- extraData: peek$(ctx, "extraData"),
3153
+ extraData,
2701
3154
  index,
2702
- item: data[index],
2703
- type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
3155
+ item,
3156
+ type: getItemType ? (_a3 = getItemType(item, index)) != null ? _a3 : "" : ""
2704
3157
  };
2705
- renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React4__default.createElement(renderItem, itemProps);
3158
+ renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React3__default.createElement(renderItem, itemProps);
2706
3159
  }
2707
3160
  return { index, item: data[index], renderedItem };
2708
3161
  }
@@ -2752,58 +3205,6 @@ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
2752
3205
  return (event) => throttle(originalHandler, scrollEventThrottle, { nativeEvent: event.nativeEvent });
2753
3206
  }
2754
3207
 
2755
- // src/utils/updateAveragesOnDataChange.ts
2756
- function updateAveragesOnDataChange(state, oldData, newData) {
2757
- var _a;
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 ? (_a = getItemType(newItem, newIndex)) != null ? _a : "" : "";
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
- };
2803
- }
2804
- }
2805
- }
2806
-
2807
3208
  // src/components/LegendList.tsx
2808
3209
  var DEFAULT_DRAW_DISTANCE = 250;
2809
3210
  var DEFAULT_ITEM_SIZE = 100;
@@ -2813,22 +3214,24 @@ var LegendList = typedMemo(
2813
3214
  const isChildrenMode = children !== void 0 && dataProp === void 0;
2814
3215
  const processedProps = isChildrenMode ? {
2815
3216
  ...restProps,
2816
- data: (isArray(children) ? children : React4.Children.toArray(children)).flat(1),
3217
+ data: (isArray(children) ? children : React3.Children.toArray(children)).flat(1),
2817
3218
  renderItem: ({ item }) => item
2818
3219
  } : {
2819
3220
  ...restProps,
2820
3221
  data: dataProp || [],
2821
3222
  renderItem: renderItemProp
2822
3223
  };
2823
- return /* @__PURE__ */ React4.createElement(StateProvider, null, /* @__PURE__ */ React4.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
3224
+ return /* @__PURE__ */ React3.createElement(StateProvider, null, /* @__PURE__ */ React3.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
2824
3225
  })
2825
3226
  );
2826
3227
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
3228
+ var _a3;
2827
3229
  const {
2828
3230
  alignItemsAtEnd = false,
2829
3231
  columnWrapperStyle,
2830
3232
  contentContainerStyle: contentContainerStyleProp,
2831
3233
  data: dataProp = [],
3234
+ dataVersion,
2832
3235
  drawDistance = 250,
2833
3236
  enableAverages = true,
2834
3237
  estimatedItemSize: estimatedItemSizeProp,
@@ -2839,6 +3242,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2839
3242
  getItemType,
2840
3243
  horizontal,
2841
3244
  initialContainerPoolRatio = 2,
3245
+ initialScrollAtEnd = false,
2842
3246
  initialScrollIndex: initialScrollIndexProp,
2843
3247
  initialScrollOffset: initialScrollOffsetProp,
2844
3248
  itemsAreEqual,
@@ -2859,6 +3263,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2859
3263
  onScroll: onScrollProp,
2860
3264
  onStartReached,
2861
3265
  onStartReachedThreshold = 0.5,
3266
+ onStickyHeaderChange,
3267
+ onViewableItemsChanged,
2862
3268
  progressViewOffset,
2863
3269
  recycleItems = false,
2864
3270
  refreshControl,
@@ -2870,16 +3276,18 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2870
3276
  stickyIndices,
2871
3277
  style: styleProp,
2872
3278
  suggestEstimatedItemSize,
3279
+ viewabilityConfig,
3280
+ viewabilityConfigCallbackPairs,
2873
3281
  waitForInitialLayout = true,
2874
3282
  ...rest
2875
3283
  } = props;
2876
- const [renderNum, setRenderNum] = useState(0);
2877
- const initialScroll = initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
2878
- const [canRender, setCanRender] = React4.useState(!IsNewArchitecture);
2879
3284
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
2880
3285
  const style = { ...StyleSheet.flatten(styleProp) };
2881
3286
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
2882
3287
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
3288
+ const [renderNum, setRenderNum] = useState(0);
3289
+ 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;
3290
+ const [canRender, setCanRender] = React3.useState(!IsNewArchitecture);
2883
3291
  const ctx = useStateContext();
2884
3292
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
2885
3293
  const refScroller = useRef(null);
@@ -2897,18 +3305,22 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2897
3305
  columns: /* @__PURE__ */ new Map(),
2898
3306
  containerItemKeys: /* @__PURE__ */ new Set(),
2899
3307
  containerItemTypes: /* @__PURE__ */ new Map(),
3308
+ dataChangeNeedsScrollUpdate: false,
3309
+ didColumnsChange: false,
3310
+ didDataChange: false,
2900
3311
  enableScrollForNextCalculateItemsInView: true,
2901
3312
  endBuffered: -1,
2902
3313
  endNoBuffer: -1,
2903
- endReachedBlockedByTimer: false,
3314
+ endReachedSnapshot: void 0,
2904
3315
  firstFullyOnScreenIndex: -1,
2905
- idCache: /* @__PURE__ */ new Map(),
3316
+ idCache: [],
2906
3317
  idsInView: [],
2907
3318
  indexByKey: /* @__PURE__ */ new Map(),
2908
- initialScroll,
3319
+ initialScroll: initialScrollProp,
2909
3320
  isAtEnd: false,
2910
3321
  isAtStart: false,
2911
3322
  isEndReached: false,
3323
+ isFirst: true,
2912
3324
  isStartReached: false,
2913
3325
  lastBatchingAction: Date.now(),
2914
3326
  lastLayout: void 0,
@@ -2933,7 +3345,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2933
3345
  sizesKnown: /* @__PURE__ */ new Map(),
2934
3346
  startBuffered: -1,
2935
3347
  startNoBuffer: -1,
2936
- startReachedBlockedByTimer: false,
3348
+ startReachedSnapshot: void 0,
2937
3349
  stickyContainerPool: /* @__PURE__ */ new Set(),
2938
3350
  stickyContainers: /* @__PURE__ */ new Map(),
2939
3351
  timeoutSizeMessage: 0,
@@ -2941,21 +3353,27 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2941
3353
  totalSize: 0,
2942
3354
  viewabilityConfigCallbackPairs: void 0
2943
3355
  };
3356
+ const internalState = ctx.internalState;
3357
+ internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, internalState, params);
2944
3358
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2945
3359
  set$(ctx, "extraData", extraData);
2946
3360
  }
2947
3361
  refState.current = ctx.internalState;
2948
3362
  }
2949
3363
  const state = refState.current;
2950
- const isFirst = !state.props.renderItem;
2951
- const didDataChange = state.props.data !== dataProp;
2952
- const throttleScrollFn = (
2953
- // @ts-expect-error TODO Fix this
2954
- scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp
2955
- );
3364
+ const isFirstLocal = state.isFirst;
3365
+ state.didColumnsChange = numColumnsProp !== state.props.numColumns;
3366
+ const didDataChangeLocal = state.props.dataVersion !== dataVersion || state.props.data !== dataProp && checkActualChange(state, dataProp, state.props.data);
3367
+ if (didDataChangeLocal) {
3368
+ state.dataChangeNeedsScrollUpdate = true;
3369
+ state.didDataChange = true;
3370
+ state.previousData = state.props.data;
3371
+ }
3372
+ const throttleScrollFn = scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp;
2956
3373
  state.props = {
2957
3374
  alignItemsAtEnd,
2958
3375
  data: dataProp,
3376
+ dataVersion,
2959
3377
  enableAverages,
2960
3378
  estimatedItemSize,
2961
3379
  getEstimatedItemSize,
@@ -2963,7 +3381,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2963
3381
  getItemType,
2964
3382
  horizontal: !!horizontal,
2965
3383
  initialContainerPoolRatio,
2966
- initialScroll,
2967
3384
  itemsAreEqual,
2968
3385
  keyExtractor,
2969
3386
  maintainScrollAtEnd,
@@ -2977,6 +3394,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2977
3394
  onScroll: throttleScrollFn,
2978
3395
  onStartReached,
2979
3396
  onStartReachedThreshold,
3397
+ onStickyHeaderChange,
2980
3398
  recycleItems: !!recycleItems,
2981
3399
  renderItem,
2982
3400
  scrollBuffer,
@@ -2988,34 +3406,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2988
3406
  suggestEstimatedItemSize: !!suggestEstimatedItemSize
2989
3407
  };
2990
3408
  state.refScroller = refScroller;
2991
- const checkResetContainers = (isFirst2) => {
2992
- const state2 = refState.current;
2993
- if (state2) {
2994
- if (!isFirst2 && state2.props.data !== dataProp) {
2995
- updateAveragesOnDataChange(state2, state2.props.data, dataProp);
2996
- }
2997
- state2.props.data = dataProp;
2998
- if (!isFirst2) {
2999
- calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
3000
- const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
3001
- const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state2, false);
3002
- if (!didMaintainScrollAtEnd && dataProp.length > state2.props.data.length) {
3003
- state2.isEndReached = false;
3004
- }
3005
- if (!didMaintainScrollAtEnd) {
3006
- checkAtTop(state2);
3007
- checkAtBottom(ctx, state2);
3008
- }
3009
- }
3010
- }
3011
- };
3012
3409
  const memoizedLastItemKeys = useMemo(() => {
3013
3410
  if (!dataProp.length) return [];
3014
3411
  return Array.from(
3015
3412
  { length: Math.min(numColumnsProp, dataProp.length) },
3016
3413
  (_, i) => getId(state, dataProp.length - 1 - i)
3017
3414
  );
3018
- }, [dataProp, numColumnsProp]);
3415
+ }, [dataProp, dataVersion, numColumnsProp]);
3019
3416
  const initializeStateVars = () => {
3020
3417
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
3021
3418
  set$(ctx, "numColumns", numColumnsProp);
@@ -3030,37 +3427,52 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3030
3427
  requestAdjust(ctx, state, paddingDiff);
3031
3428
  }
3032
3429
  };
3033
- if (isFirst) {
3430
+ if (isFirstLocal) {
3034
3431
  initializeStateVars();
3035
- updateAllPositions(ctx, state);
3432
+ updateItemPositions(
3433
+ ctx,
3434
+ state,
3435
+ /*dataChanged*/
3436
+ true
3437
+ );
3036
3438
  }
3037
3439
  const initialContentOffset = useMemo(() => {
3038
- if (initialScroll) {
3039
- const { index, viewOffset } = initialScroll;
3040
- let initialContentOffset2 = viewOffset || 0;
3041
- if (index !== void 0) {
3042
- initialContentOffset2 += calculateOffsetForIndex(ctx, state, index);
3043
- }
3044
- refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
3045
- if (initialContentOffset2 > 0) {
3046
- scrollTo(state, { animated: false, index, offset: initialContentOffset2 });
3047
- }
3048
- return initialContentOffset2;
3049
- }
3050
- return 0;
3051
- }, [renderNum]);
3052
- if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
3053
- state.lastBatchingAction = Date.now();
3054
- if (!keyExtractorProp && !isFirst && didDataChange) {
3055
- __DEV__ && warnDevOnce(
3440
+ const { initialScroll } = refState.current;
3441
+ if (!initialScroll) {
3442
+ return 0;
3443
+ }
3444
+ if (initialScroll.contentOffset !== void 0) {
3445
+ return initialScroll.contentOffset;
3446
+ }
3447
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, state, initialScroll.index) : 0;
3448
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, state, baseOffset, initialScroll);
3449
+ let clampedOffset = resolvedOffset;
3450
+ if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
3451
+ const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
3452
+ clampedOffset = Math.min(clampedOffset, maxOffset);
3453
+ }
3454
+ clampedOffset = Math.max(0, clampedOffset);
3455
+ const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3456
+ refState.current.initialScroll = updatedInitialScroll;
3457
+ state.initialScroll = updatedInitialScroll;
3458
+ refState.current.isStartReached = clampedOffset < refState.current.scrollLength * onStartReachedThreshold;
3459
+ return clampedOffset;
3460
+ }, [renderNum, state.initialScroll]);
3461
+ if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
3462
+ refState.current.lastBatchingAction = Date.now();
3463
+ if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
3464
+ IS_DEV && warnDevOnce(
3056
3465
  "keyExtractor",
3057
3466
  "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."
3058
3467
  );
3059
- state.sizes.clear();
3060
- state.positions.clear();
3468
+ refState.current.sizes.clear();
3469
+ refState.current.positions.clear();
3470
+ refState.current.totalSize = 0;
3471
+ set$(ctx, "totalSize", 0);
3061
3472
  }
3062
3473
  }
3063
3474
  const onLayoutHeader = useCallback((rect, fromLayoutEffect) => {
3475
+ const { initialScroll } = refState.current;
3064
3476
  const size = rect[horizontal ? "width" : "height"];
3065
3477
  set$(ctx, "headerSize", size);
3066
3478
  if ((initialScroll == null ? void 0 : initialScroll.index) !== void 0) {
@@ -3071,132 +3483,70 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3071
3483
  }
3072
3484
  }
3073
3485
  }, []);
3486
+ const doInitialScroll = useCallback(() => {
3487
+ var _a4;
3488
+ const initialScroll = state.initialScroll;
3489
+ if (initialScroll) {
3490
+ scrollTo(ctx, state, {
3491
+ animated: false,
3492
+ index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3493
+ offset: initialContentOffset,
3494
+ precomputedWithViewOffset: true
3495
+ });
3496
+ }
3497
+ }, [initialContentOffset, state.initialScroll]);
3498
+ const onLayoutChange = useCallback((layout) => {
3499
+ doInitialScroll();
3500
+ handleLayout(ctx, state, layout, setCanRender);
3501
+ }, []);
3502
+ const { onLayout } = useOnLayoutSync({
3503
+ onLayoutChange,
3504
+ onLayoutProp,
3505
+ ref: refScroller
3506
+ // the type of ScrollView doesn't include measure?
3507
+ });
3074
3508
  useLayoutEffect(() => {
3075
3509
  if (snapToIndices) {
3076
3510
  updateSnapToOffsets(ctx, state);
3077
3511
  }
3078
3512
  }, [snapToIndices]);
3079
3513
  useLayoutEffect(() => {
3080
- const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainersCallback();
3081
- if (!didAllocateContainers) {
3082
- checkResetContainers(
3083
- /*isFirst*/
3084
- isFirst
3085
- );
3086
- }
3087
- }, [dataProp, numColumnsProp]);
3514
+ const {
3515
+ didColumnsChange,
3516
+ didDataChange,
3517
+ isFirst,
3518
+ props: { data }
3519
+ } = state;
3520
+ const didAllocateContainers = data.length > 0 && doInitialAllocateContainers(ctx, state);
3521
+ if (!didAllocateContainers && !isFirst && (didDataChange || didColumnsChange)) {
3522
+ checkResetContainers(ctx, state, data);
3523
+ }
3524
+ state.didColumnsChange = false;
3525
+ state.didDataChange = false;
3526
+ state.isFirst = false;
3527
+ }, [dataProp, dataVersion, numColumnsProp]);
3088
3528
  useLayoutEffect(() => {
3089
3529
  set$(ctx, "extraData", extraData);
3090
3530
  }, [extraData]);
3091
- const { onLayout } = useSyncLayout({
3092
- onLayout: onLayoutProp,
3093
- onLayoutChange: useCallback(
3094
- (rectangle) => {
3095
- handleLayout(ctx, state, rectangle, setCanRender);
3096
- },
3097
- [ctx, state, setCanRender]
3098
- ),
3099
- ref: refScroller
3100
- });
3101
3531
  useLayoutEffect(initializeStateVars, [
3532
+ dataVersion,
3102
3533
  memoizedLastItemKeys.join(","),
3103
3534
  numColumnsProp,
3104
- stylePaddingTopState,
3105
- stylePaddingBottomState
3535
+ stylePaddingBottomState,
3536
+ stylePaddingTopState
3106
3537
  ]);
3107
- const doInitialAllocateContainersCallback = () => {
3108
- return doInitialAllocateContainers(ctx, state);
3109
- };
3110
- useImperativeHandle(forwardedRef, () => {
3111
- const scrollIndexIntoView = (options) => {
3112
- const state2 = refState.current;
3113
- if (state2) {
3114
- const { index, ...rest2 } = options;
3115
- const { startNoBuffer, endNoBuffer } = state2;
3116
- if (index < startNoBuffer || index > endNoBuffer) {
3117
- const viewPosition = index < startNoBuffer ? 0 : 1;
3118
- scrollToIndex(ctx, state2, {
3119
- ...rest2,
3120
- index,
3121
- viewPosition
3122
- });
3123
- }
3124
- }
3125
- };
3126
- return {
3127
- flashScrollIndicators: () => {
3128
- var _a, _b;
3129
- return (_b = (_a = refScroller.current) == null ? void 0 : _a.flashScrollIndicators) == null ? void 0 : _b.call(_a);
3130
- },
3131
- getNativeScrollRef: () => refScroller.current,
3132
- getScrollableNode: () => refScroller.current,
3133
- getScrollResponder: () => refScroller.current,
3134
- getState: () => {
3135
- const state2 = refState.current;
3136
- return state2 ? {
3137
- contentLength: state2.totalSize,
3138
- data: state2.props.data,
3139
- end: state2.endNoBuffer,
3140
- endBuffered: state2.endBuffered,
3141
- isAtEnd: state2.isAtEnd,
3142
- isAtStart: state2.isAtStart,
3143
- positionAtIndex: (index) => state2.positions.get(getId(state2, index)),
3144
- positions: state2.positions,
3145
- scroll: state2.scroll,
3146
- scrollLength: state2.scrollLength,
3147
- sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index)),
3148
- sizes: state2.sizesKnown,
3149
- start: state2.startNoBuffer,
3150
- startBuffered: state2.startBuffered
3151
- } : {};
3152
- },
3153
- scrollIndexIntoView,
3154
- scrollItemIntoView: ({ item, ...props2 }) => {
3155
- const data = refState.current.props.data;
3156
- const index = data.indexOf(item);
3157
- if (index !== -1) {
3158
- scrollIndexIntoView({ index, ...props2 });
3159
- }
3160
- },
3161
- scrollToEnd: (options) => {
3162
- const data = refState.current.props.data;
3163
- const stylePaddingBottom = refState.current.props.stylePaddingBottom;
3164
- const index = data.length - 1;
3165
- if (index !== -1) {
3166
- const paddingBottom = stylePaddingBottom || 0;
3167
- const footerSize = peek$(ctx, "footerSize") || 0;
3168
- scrollToIndex(ctx, state, {
3169
- index,
3170
- viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
3171
- viewPosition: 1,
3172
- ...options
3173
- });
3174
- }
3175
- },
3176
- scrollToIndex: (params) => scrollToIndex(ctx, state, params),
3177
- scrollToItem: ({ item, ...props2 }) => {
3178
- const data = refState.current.props.data;
3179
- const index = data.indexOf(item);
3180
- if (index !== -1) {
3181
- scrollToIndex(ctx, state, { index, ...props2 });
3182
- }
3183
- },
3184
- scrollToOffset: (params) => scrollTo(state, params),
3185
- setScrollProcessingEnabled: (enabled) => {
3186
- refState.current.scrollProcessingEnabled = enabled;
3187
- },
3188
- setVisibleContentAnchorOffset: (value) => {
3189
- const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
3190
- set$(ctx, "scrollAdjustUserOffset", val);
3191
- }
3192
- };
3193
- }, []);
3538
+ useEffect(() => {
3539
+ const viewability = setupViewability({
3540
+ onViewableItemsChanged,
3541
+ viewabilityConfig,
3542
+ viewabilityConfigCallbackPairs
3543
+ });
3544
+ state.viewabilityConfigCallbackPairs = viewability;
3545
+ state.enableScrollForNextCalculateItemsInView = !viewability;
3546
+ }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
3547
+ useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, state), []);
3194
3548
  {
3195
- useEffect(() => {
3196
- if (initialContentOffset) {
3197
- scrollTo(state, { animated: false, offset: initialContentOffset });
3198
- }
3199
- }, []);
3549
+ useEffect(doInitialScroll, []);
3200
3550
  }
3201
3551
  const fns = useMemo(
3202
3552
  () => ({
@@ -3207,7 +3557,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3207
3557
  []
3208
3558
  );
3209
3559
  const onScrollHandler = useStickyScrollHandler(stickyIndices, horizontal, ctx, fns.onScroll);
3210
- return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(
3560
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
3211
3561
  ListComponent,
3212
3562
  {
3213
3563
  ...rest,
@@ -3225,7 +3575,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3225
3575
  onMomentumScrollEnd: (event) => {
3226
3576
  {
3227
3577
  requestAnimationFrame(() => {
3228
- finishScrollTo(refState.current);
3578
+ finishScrollTo(ctx, refState.current);
3229
3579
  });
3230
3580
  }
3231
3581
  if (onMomentumScrollEnd) {
@@ -3234,9 +3584,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3234
3584
  },
3235
3585
  onScroll: onScrollHandler,
3236
3586
  recycleItems,
3237
- refreshControl: refreshControl ? stylePaddingTopState > 0 ? React4.cloneElement(refreshControl, {
3587
+ refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControl, {
3238
3588
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
3239
- }) : refreshControl : onRefresh && /* @__PURE__ */ React4.createElement(
3589
+ }) : refreshControl : onRefresh && /* @__PURE__ */ React3.createElement(
3240
3590
  RefreshControl,
3241
3591
  {
3242
3592
  onRefresh,
@@ -3245,14 +3595,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3245
3595
  }
3246
3596
  ),
3247
3597
  refScrollView: combinedRef,
3248
- scrollAdjustHandler: state.scrollAdjustHandler,
3598
+ scrollAdjustHandler: (_a3 = refState.current) == null ? void 0 : _a3.scrollAdjustHandler,
3599
+ scrollEventThrottle: 16 ,
3249
3600
  snapToIndices,
3250
3601
  stickyIndices,
3251
3602
  style,
3252
3603
  updateItemSize: fns.updateItemSize,
3253
3604
  waitForInitialLayout
3254
3605
  }
3255
- ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React4.createElement(DebugView, { state: refState.current }));
3606
+ ), IS_DEV && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3.createElement(DebugView, { state: refState.current }));
3256
3607
  });
3257
3608
 
3258
- export { LegendList, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout2 as useSyncLayout, useViewability, useViewabilityAmount };
3609
+ export { LegendList, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };