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

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.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var React4 = require('react');
3
+ var React3 = require('react');
4
4
  var shim = require('use-sync-external-store/shim');
5
5
  var reactDom = require('react-dom');
6
6
 
@@ -22,14 +22,14 @@ function _interopNamespace(e) {
22
22
  return Object.freeze(n);
23
23
  }
24
24
 
25
- var React4__namespace = /*#__PURE__*/_interopNamespace(React4);
25
+ var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
26
26
 
27
27
  // src/components/LegendList.tsx
28
- var AnimatedView = React4.forwardRef(function AnimatedView2(props, ref) {
29
- return /* @__PURE__ */ React4__namespace.createElement("div", { ref, ...props });
28
+ React3.forwardRef(function AnimatedView2(props, ref) {
29
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref, ...props });
30
30
  });
31
- var View = React4.forwardRef(function View2(props, ref) {
32
- return /* @__PURE__ */ React4__namespace.createElement("div", { ref, ...props });
31
+ var View = React3.forwardRef(function View2(props, ref) {
32
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref, ...props });
33
33
  });
34
34
  var Text = View;
35
35
 
@@ -37,9 +37,9 @@ var Text = View;
37
37
  var createAnimatedValue = (value) => value;
38
38
 
39
39
  // src/state/state.tsx
40
- var ContextState = React4__namespace.createContext(null);
40
+ var ContextState = React3__namespace.createContext(null);
41
41
  function StateProvider({ children }) {
42
- const [value] = React4__namespace.useState(() => ({
42
+ const [value] = React3__namespace.useState(() => ({
43
43
  animatedScrollY: createAnimatedValue(0),
44
44
  columnWrapperStyle: void 0,
45
45
  internalState: void 0,
@@ -54,14 +54,17 @@ function StateProvider({ children }) {
54
54
  ["stylePaddingTop", 0],
55
55
  ["headerSize", 0],
56
56
  ["numContainers", 0],
57
- ["totalSize", 0]
57
+ ["activeStickyIndex", void 0],
58
+ ["totalSize", 0],
59
+ ["scrollAdjustPending", 0],
60
+ ["scrollingTo", void 0]
58
61
  ]),
59
62
  viewRefs: /* @__PURE__ */ new Map()
60
63
  }));
61
- return /* @__PURE__ */ React4__namespace.createElement(ContextState.Provider, { value }, children);
64
+ return /* @__PURE__ */ React3__namespace.createElement(ContextState.Provider, { value }, children);
62
65
  }
63
66
  function useStateContext() {
64
- return React4__namespace.useContext(ContextState);
67
+ return React3__namespace.useContext(ContextState);
65
68
  }
66
69
  function createSelectorFunctionsArr(ctx, signalNames) {
67
70
  let lastValues = [];
@@ -131,23 +134,23 @@ function getContentSize(ctx) {
131
134
  return headerSize + footerSize + totalSize + stylePaddingTop;
132
135
  }
133
136
  function useArr$(signalNames) {
134
- const ctx = React4__namespace.useContext(ContextState);
135
- const { subscribe, get } = React4__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
137
+ const ctx = React3__namespace.useContext(ContextState);
138
+ const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
136
139
  const value = shim.useSyncExternalStore(subscribe, get);
137
140
  return value;
138
141
  }
139
142
  function useSelector$(signalName, selector) {
140
- const ctx = React4__namespace.useContext(ContextState);
141
- const { subscribe, get } = React4__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
143
+ const ctx = React3__namespace.useContext(ContextState);
144
+ const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
142
145
  const value = shim.useSyncExternalStore(subscribe, () => selector(get()[0]));
143
146
  return value;
144
147
  }
145
148
 
146
149
  // src/components/DebugView.tsx
147
150
  var DebugRow = ({ children }) => {
148
- return /* @__PURE__ */ React4__namespace.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
151
+ return /* @__PURE__ */ React3__namespace.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
149
152
  };
150
- var DebugView = React4__namespace.memo(function DebugView2({ state }) {
153
+ var DebugView = React3__namespace.memo(function DebugView2({ state }) {
151
154
  const ctx = useStateContext();
152
155
  const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
153
156
  "totalSize",
@@ -158,11 +161,11 @@ var DebugView = React4__namespace.memo(function DebugView2({ state }) {
158
161
  "numContainersPooled"
159
162
  ]);
160
163
  const contentSize = getContentSize(ctx);
161
- const [, forceUpdate] = React4.useReducer((x) => x + 1, 0);
164
+ const [, forceUpdate] = React3.useReducer((x) => x + 1, 0);
162
165
  useInterval(() => {
163
166
  forceUpdate();
164
167
  }, 100);
165
- return /* @__PURE__ */ React4__namespace.createElement(
168
+ return /* @__PURE__ */ React3__namespace.createElement(
166
169
  View,
167
170
  {
168
171
  pointerEvents: "none",
@@ -178,106 +181,35 @@ var DebugView = React4__namespace.memo(function DebugView2({ state }) {
178
181
  top: 0
179
182
  }
180
183
  },
181
- /* @__PURE__ */ React4__namespace.createElement(DebugRow, null, /* @__PURE__ */ React4__namespace.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React4__namespace.createElement(Text, null, totalSize.toFixed(2))),
182
- /* @__PURE__ */ React4__namespace.createElement(DebugRow, null, /* @__PURE__ */ React4__namespace.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React4__namespace.createElement(Text, null, contentSize.toFixed(2))),
183
- /* @__PURE__ */ React4__namespace.createElement(DebugRow, null, /* @__PURE__ */ React4__namespace.createElement(Text, null, "At end:"), /* @__PURE__ */ React4__namespace.createElement(Text, null, String(state.isAtEnd))),
184
- /* @__PURE__ */ React4__namespace.createElement(DebugRow, null, /* @__PURE__ */ React4__namespace.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React4__namespace.createElement(Text, null, scrollAdjust.toFixed(2))),
185
- /* @__PURE__ */ React4__namespace.createElement(DebugRow, null, /* @__PURE__ */ React4__namespace.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React4__namespace.createElement(Text, null, rawScroll.toFixed(2))),
186
- /* @__PURE__ */ React4__namespace.createElement(DebugRow, null, /* @__PURE__ */ React4__namespace.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React4__namespace.createElement(Text, null, scroll.toFixed(2)))
184
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, totalSize.toFixed(2))),
185
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, contentSize.toFixed(2))),
186
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "At end:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, String(state.isAtEnd))),
187
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, scrollAdjust.toFixed(2))),
188
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React3__namespace.createElement(Text, null, rawScroll.toFixed(2))),
189
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React3__namespace.createElement(Text, null, scroll.toFixed(2)))
187
190
  );
188
191
  });
189
192
  function useInterval(callback, delay) {
190
- React4.useEffect(() => {
193
+ React3.useEffect(() => {
191
194
  const interval = setInterval(callback, delay);
192
195
  return () => clearInterval(interval);
193
196
  }, [delay]);
194
197
  }
195
- var globalResizeObserver = null;
196
- function getGlobalResizeObserver() {
197
- if (!globalResizeObserver) {
198
- globalResizeObserver = new ResizeObserver((entries) => {
199
- for (const entry of entries) {
200
- const callbacks = callbackMap.get(entry.target);
201
- if (callbacks) {
202
- for (const callback of callbacks) {
203
- callback(entry);
204
- }
205
- }
206
- }
207
- });
208
- }
209
- return globalResizeObserver;
210
- }
211
- var callbackMap = /* @__PURE__ */ new WeakMap();
212
- function useResizeObserver(element, callback) {
213
- React4.useEffect(() => {
214
- if (!element) return;
215
- const observer = getGlobalResizeObserver();
216
- let callbacks = callbackMap.get(element);
217
- if (!callbacks) {
218
- callbacks = /* @__PURE__ */ new Set();
219
- callbackMap.set(element, callbacks);
220
- observer.observe(element);
221
- }
222
- callbacks.add(callback);
223
- return () => {
224
- const callbacks2 = callbackMap.get(element);
225
- if (callbacks2) {
226
- callbacks2.delete(callback);
227
- if (callbacks2.size === 0) {
228
- callbackMap.delete(element);
229
- observer.unobserve(element);
230
- }
231
- }
232
- };
233
- }, [element, callback]);
234
- }
235
-
236
- // src/hooks/useSyncLayout.tsx
237
- function useSyncLayout({
238
- ref,
239
- onLayoutChange
240
- }) {
241
- var _a, _b;
242
- useResizeObserver(
243
- ((_b = (_a = ref.current) == null ? void 0 : _a.getScrollableNode) == null ? void 0 : _b.call(_a)) || ref.current,
244
- React4.useCallback(
245
- (entry) => {
246
- onLayoutChange(entry.contentRect, false);
247
- },
248
- [onLayoutChange]
249
- )
250
- );
251
- React4.useLayoutEffect(() => {
252
- if (ref.current) {
253
- const rect = ref.current.getBoundingClientRect();
254
- onLayoutChange(
255
- {
256
- height: rect.height,
257
- width: rect.width,
258
- x: rect.left,
259
- y: rect.top
260
- },
261
- true
262
- );
263
- }
264
- }, []);
265
- return {};
266
- }
267
198
 
268
- // src/components/LayoutView.tsx
269
- var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
270
- const ref = refView != null ? refView : React4.useRef();
271
- useSyncLayout({ onLayoutChange, ref });
272
- return /* @__PURE__ */ React4__namespace.createElement("div", { ...rest, ref }, children);
273
- };
199
+ // src/utils/devEnvironment.ts
200
+ var metroDev = typeof __DEV__ !== "undefined" ? __DEV__ : void 0;
201
+ var _a;
202
+ var envMode = typeof process !== "undefined" && typeof process.env === "object" && process.env ? (_a = process.env.NODE_ENV) != null ? _a : process.env.MODE : void 0;
203
+ var processDev = typeof envMode === "string" ? envMode.toLowerCase() !== "production" : void 0;
204
+ var _a2;
205
+ var IS_DEV = (_a2 = metroDev != null ? metroDev : processDev) != null ? _a2 : false;
274
206
 
275
207
  // src/constants.ts
276
208
  var POSITION_OUT_OF_VIEW = -1e7;
277
- var ENABLE_DEVMODE = __DEV__ && false;
278
- var ENABLE_DEBUG_VIEW = __DEV__ && false;
279
- var typedForwardRef = React4.forwardRef;
280
- var typedMemo = React4.memo;
209
+ var ENABLE_DEVMODE = IS_DEV && false;
210
+ var ENABLE_DEBUG_VIEW = IS_DEV && false;
211
+ var typedForwardRef = React3.forwardRef;
212
+ var typedMemo = React3.memo;
281
213
 
282
214
  // src/components/PositionView.tsx
283
215
  var PositionViewState = typedMemo(function PositionView({
@@ -288,9 +220,12 @@ var PositionViewState = typedMemo(function PositionView({
288
220
  ...rest
289
221
  }) {
290
222
  const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
291
- const base = Array.isArray(style) ? Object.assign({}, ...style) : style;
292
- const combinedStyle = horizontal ? { ...base, left: position } : { ...base, top: position };
293
- return /* @__PURE__ */ React4__namespace.createElement(LayoutView, { refView, style: combinedStyle, ...rest });
223
+ const base = {
224
+ contain: "paint layout style"
225
+ };
226
+ const composed = Array.isArray(style) ? Object.assign({}, ...style) : style;
227
+ const combinedStyle = horizontal ? { ...base, ...composed, left: position } : { ...base, ...composed, top: position };
228
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: combinedStyle, ...rest });
294
229
  });
295
230
  var PositionViewSticky = typedMemo(function PositionViewSticky2({
296
231
  id,
@@ -298,38 +233,50 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
298
233
  style,
299
234
  refView,
300
235
  index,
236
+ stickyOffset,
237
+ animatedScrollY: _animatedScrollY,
238
+ children,
301
239
  ...rest
302
240
  }) {
303
- const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
304
- const viewStyle = React4__namespace.useMemo(() => {
305
- const base = Array.isArray(style) ? Object.assign({}, ...style) : style;
306
- const axisStyle = horizontal ? { transform: `translateX(${position}px)` } : { top: position };
307
- return {
308
- ...base,
309
- zIndex: index + 1e3,
310
- ...axisStyle
311
- };
312
- }, [style, position, horizontal, index]);
313
- return /* @__PURE__ */ React4__namespace.createElement(LayoutView, { refView, style: viewStyle, ...rest });
241
+ const [position = POSITION_OUT_OF_VIEW, headerSize = 0, activeStickyIndex] = useArr$([
242
+ `containerPosition${id}`,
243
+ "headerSize",
244
+ "activeStickyIndex"
245
+ ]);
246
+ const base = {
247
+ contain: "paint layout style"
248
+ };
249
+ const composed = React3__namespace.useMemo(
250
+ () => {
251
+ var _a3;
252
+ return (_a3 = Array.isArray(style) ? Object.assign({}, ...style) : style) != null ? _a3 : {};
253
+ },
254
+ [style]
255
+ );
256
+ const viewStyle = React3__namespace.useMemo(() => {
257
+ var _a3;
258
+ const styleBase = { ...base, ...composed };
259
+ delete styleBase.transform;
260
+ const offset = (_a3 = stickyOffset != null ? stickyOffset : headerSize) != null ? _a3 : 0;
261
+ const isActive = activeStickyIndex === index;
262
+ styleBase.position = isActive ? "sticky" : "absolute";
263
+ styleBase.zIndex = index + 1e3;
264
+ if (horizontal) {
265
+ styleBase.left = isActive ? offset : position;
266
+ } else {
267
+ styleBase.top = isActive ? offset : position;
268
+ }
269
+ return styleBase;
270
+ }, [composed, horizontal, position, index, stickyOffset, headerSize, activeStickyIndex]);
271
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: viewStyle, ...rest }, children);
314
272
  });
315
273
  var PositionView2 = PositionViewState;
316
- function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
317
- const [lastItemKeys] = useArr$(["lastItemKeys"]);
318
- const isALastItem = lastItemKeys.includes(itemKey);
319
- return isALastItem ? null : /* @__PURE__ */ React4__namespace.createElement(ItemSeparatorComponent, { leadingItem });
320
- }
321
274
 
322
275
  // src/constants-platform.ts
323
276
  var IsNewArchitecture = true;
324
-
325
- // src/platform/Platform.ts
326
- var Platform = {
327
- // Widen the type to avoid unreachable-branch lints in cross-platform code that compares against other OSes
328
- OS: "web"
329
- };
330
277
  var symbolFirst = Symbol();
331
278
  function useInit(cb) {
332
- const refValue = React4.useRef(symbolFirst);
279
+ const refValue = React3.useRef(symbolFirst);
333
280
  if (refValue.current === symbolFirst) {
334
281
  refValue.current = cb();
335
282
  }
@@ -345,7 +292,7 @@ function isArray(obj) {
345
292
  }
346
293
  var warned = /* @__PURE__ */ new Set();
347
294
  function warnDevOnce(id, text) {
348
- if (__DEV__ && !warned.has(id)) {
295
+ if (IS_DEV && !warned.has(id)) {
349
296
  warned.add(id);
350
297
  console.warn(`[legend-list] ${text}`);
351
298
  }
@@ -360,18 +307,18 @@ function comparatorDefault(a, b) {
360
307
  return a - b;
361
308
  }
362
309
  function getPadding(s, type) {
363
- var _a, _b, _c;
364
- return (_c = (_b = (_a = s[`padding${type}`]) != null ? _a : s.paddingVertical) != null ? _b : s.padding) != null ? _c : 0;
310
+ var _a3, _b, _c;
311
+ return (_c = (_b = (_a3 = s[`padding${type}`]) != null ? _a3 : s.paddingVertical) != null ? _b : s.padding) != null ? _c : 0;
365
312
  }
366
313
  function extractPadding(style, contentContainerStyle, type) {
367
314
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
368
315
  }
369
316
 
370
317
  // src/state/ContextContainer.ts
371
- var ContextContainer = React4.createContext(null);
318
+ var ContextContainer = React3.createContext(null);
372
319
  function useViewability(callback, configId) {
373
320
  const ctx = useStateContext();
374
- const { containerId } = React4.useContext(ContextContainer);
321
+ const { containerId } = React3.useContext(ContextContainer);
375
322
  const key = containerId + (configId != null ? configId : "");
376
323
  useInit(() => {
377
324
  const value = ctx.mapViewabilityValues.get(key);
@@ -380,7 +327,7 @@ function useViewability(callback, configId) {
380
327
  }
381
328
  });
382
329
  ctx.mapViewabilityCallbacks.set(key, callback);
383
- React4.useEffect(
330
+ React3.useEffect(
384
331
  () => () => {
385
332
  ctx.mapViewabilityCallbacks.delete(key);
386
333
  },
@@ -389,7 +336,7 @@ function useViewability(callback, configId) {
389
336
  }
390
337
  function useViewabilityAmount(callback) {
391
338
  const ctx = useStateContext();
392
- const { containerId } = React4.useContext(ContextContainer);
339
+ const { containerId } = React3.useContext(ContextContainer);
393
340
  useInit(() => {
394
341
  const value = ctx.mapViewabilityAmountValues.get(containerId);
395
342
  if (value) {
@@ -397,7 +344,7 @@ function useViewabilityAmount(callback) {
397
344
  }
398
345
  });
399
346
  ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
400
- React4.useEffect(
347
+ React3.useEffect(
401
348
  () => () => {
402
349
  ctx.mapViewabilityAmountCallbacks.delete(containerId);
403
350
  },
@@ -405,12 +352,12 @@ function useViewabilityAmount(callback) {
405
352
  );
406
353
  }
407
354
  function useRecyclingEffect(effect) {
408
- const { index, value } = React4.useContext(ContextContainer);
409
- const prevValues = React4.useRef({
355
+ const { index, value } = React3.useContext(ContextContainer);
356
+ const prevValues = React3.useRef({
410
357
  prevIndex: void 0,
411
358
  prevItem: void 0
412
359
  });
413
- React4.useEffect(() => {
360
+ React3.useEffect(() => {
414
361
  let ret;
415
362
  if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
416
363
  ret = effect({
@@ -428,12 +375,12 @@ function useRecyclingEffect(effect) {
428
375
  }, [index, value, effect]);
429
376
  }
430
377
  function useRecyclingState(valueOrFun) {
431
- const { index, value, itemKey, triggerLayout } = React4.useContext(ContextContainer);
432
- const refState = React4.useRef({
378
+ const { index, value, itemKey, triggerLayout } = React3.useContext(ContextContainer);
379
+ const refState = React3.useRef({
433
380
  itemKey: null,
434
381
  value: null
435
382
  });
436
- const [_, setRenderNum] = React4.useState(0);
383
+ const [_, setRenderNum] = React3.useState(0);
437
384
  const state = refState.current;
438
385
  if (state.itemKey !== itemKey) {
439
386
  state.itemKey = itemKey;
@@ -444,7 +391,7 @@ function useRecyclingState(valueOrFun) {
444
391
  prevItem: void 0
445
392
  }) : valueOrFun;
446
393
  }
447
- const setState = React4.useCallback(
394
+ const setState = React3.useCallback(
448
395
  (newState) => {
449
396
  state.value = isFunction(newState) ? newState(state.value) : newState;
450
397
  setRenderNum((v) => v + 1);
@@ -455,7 +402,7 @@ function useRecyclingState(valueOrFun) {
455
402
  return [state.value, setState];
456
403
  }
457
404
  function useIsLastItem() {
458
- const { itemKey } = React4.useContext(ContextContainer);
405
+ const { itemKey } = React3.useContext(ContextContainer);
459
406
  const isLast = useSelector$("lastItemKeys", (lastItemKeys) => (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false);
460
407
  return isLast;
461
408
  }
@@ -463,13 +410,103 @@ function useListScrollSize() {
463
410
  const [scrollSize] = useArr$(["scrollSize"]);
464
411
  return scrollSize;
465
412
  }
466
- function useSyncLayout2() {
413
+ function useSyncLayout() {
467
414
  {
468
- const { triggerLayout: syncLayout } = React4.useContext(ContextContainer);
415
+ const { triggerLayout: syncLayout } = React3.useContext(ContextContainer);
469
416
  return syncLayout;
470
417
  }
471
418
  }
472
419
 
420
+ // src/components/Separator.tsx
421
+ function Separator({ ItemSeparatorComponent, leadingItem }) {
422
+ const isLastItem = useIsLastItem();
423
+ return isLastItem ? null : /* @__PURE__ */ React3__namespace.createElement(ItemSeparatorComponent, { leadingItem });
424
+ }
425
+
426
+ // src/hooks/createResizeObserver.ts
427
+ var globalResizeObserver = null;
428
+ function getGlobalResizeObserver() {
429
+ if (!globalResizeObserver) {
430
+ globalResizeObserver = new ResizeObserver((entries) => {
431
+ for (const entry of entries) {
432
+ const callbacks = callbackMap.get(entry.target);
433
+ if (callbacks) {
434
+ for (const callback of callbacks) {
435
+ callback(entry);
436
+ }
437
+ }
438
+ }
439
+ });
440
+ }
441
+ return globalResizeObserver;
442
+ }
443
+ var callbackMap = /* @__PURE__ */ new WeakMap();
444
+ function createResizeObserver(element, callback) {
445
+ if (!element) {
446
+ return () => {
447
+ };
448
+ }
449
+ const observer = getGlobalResizeObserver();
450
+ let callbacks = callbackMap.get(element);
451
+ if (!callbacks) {
452
+ callbacks = /* @__PURE__ */ new Set();
453
+ callbackMap.set(element, callbacks);
454
+ observer.observe(element);
455
+ }
456
+ callbacks.add(callback);
457
+ return () => {
458
+ const callbacks2 = callbackMap.get(element);
459
+ if (callbacks2) {
460
+ callbacks2.delete(callback);
461
+ if (callbacks2.size === 0) {
462
+ callbackMap.delete(element);
463
+ observer.unobserve(element);
464
+ }
465
+ }
466
+ };
467
+ }
468
+
469
+ // src/hooks/useOnLayoutSync.tsx
470
+ function useOnLayoutSync({
471
+ ref,
472
+ onLayoutProp,
473
+ onLayoutChange
474
+ }, deps) {
475
+ React3.useLayoutEffect(() => {
476
+ var _a3, _b;
477
+ const current = ref.current;
478
+ const scrollableNode = (_b = (_a3 = current == null ? void 0 : current.getScrollableNode) == null ? void 0 : _a3.call(current)) != null ? _b : null;
479
+ const element = scrollableNode || current;
480
+ if (!element || !(element instanceof HTMLElement)) {
481
+ return;
482
+ }
483
+ const emit = (layout, fromLayoutEffect) => {
484
+ if (layout.height === 0 && layout.width === 0) {
485
+ return;
486
+ }
487
+ onLayoutChange(layout, fromLayoutEffect);
488
+ onLayoutProp == null ? void 0 : onLayoutProp({ nativeEvent: { layout } });
489
+ };
490
+ const rect = element.getBoundingClientRect();
491
+ emit(toLayout(rect), true);
492
+ return createResizeObserver(element, (entry) => {
493
+ var _a4;
494
+ const target = entry.target instanceof HTMLElement ? entry.target : void 0;
495
+ const rect2 = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
496
+ emit(toLayout(rect2), false);
497
+ });
498
+ }, deps);
499
+ return {};
500
+ }
501
+ function toLayout(rect) {
502
+ return {
503
+ height: rect.height,
504
+ width: rect.width,
505
+ x: rect.left,
506
+ y: rect.top
507
+ };
508
+ }
509
+
473
510
  // src/components/Container.tsx
474
511
  var Container = typedMemo(function Container2({
475
512
  id,
@@ -480,37 +517,42 @@ var Container = typedMemo(function Container2({
480
517
  ItemSeparatorComponent
481
518
  }) {
482
519
  const ctx = useStateContext();
483
- const { columnWrapperStyle } = ctx;
484
- const [column = 0, data, itemKey, numColumns, extraData, isSticky] = useArr$([
520
+ const { columnWrapperStyle, animatedScrollY } = ctx;
521
+ const [column = 0, data, itemKey, numColumns, extraData, isSticky, stickyOffset] = useArr$([
485
522
  `containerColumn${id}`,
486
523
  `containerItemData${id}`,
487
524
  `containerItemKey${id}`,
488
525
  "numColumns",
489
526
  "extraData",
490
- `containerSticky${id}`
527
+ `containerSticky${id}`,
528
+ `containerStickyOffset${id}`
491
529
  ]);
492
- const refLastSize = React4.useRef();
493
- const ref = React4.useRef(null);
494
- const [_, forceLayoutRender] = React4.useState(0);
530
+ const itemLayoutRef = React3.useRef({
531
+ horizontal,
532
+ itemKey,
533
+ updateItemSize: updateItemSize2
534
+ });
535
+ itemLayoutRef.current.horizontal = horizontal;
536
+ itemLayoutRef.current.itemKey = itemKey;
537
+ itemLayoutRef.current.updateItemSize = updateItemSize2;
538
+ const ref = React3.useRef(null);
539
+ const [layoutRenderCount, forceLayoutRender] = React3.useState(0);
495
540
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
496
541
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
497
- const style = React4.useMemo(() => {
542
+ const didLayoutRef = React3.useRef(false);
543
+ const style = React3.useMemo(() => {
498
544
  let paddingStyles;
499
545
  if (columnWrapperStyle) {
500
546
  const { columnGap, rowGap, gap } = columnWrapperStyle;
501
547
  if (horizontal) {
502
- const py = numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0;
503
548
  paddingStyles = {
504
- paddingBottom: py,
505
549
  paddingRight: columnGap || gap || void 0,
506
- paddingTop: py
550
+ paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
507
551
  };
508
552
  } else {
509
- const px = numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0;
510
553
  paddingStyles = {
511
554
  paddingBottom: rowGap || gap || void 0,
512
- paddingLeft: px,
513
- paddingRight: px
555
+ paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
514
556
  };
515
557
  }
516
558
  }
@@ -524,18 +566,18 @@ var Container = typedMemo(function Container2({
524
566
  } : {
525
567
  left: otherAxisPos,
526
568
  position: "absolute",
527
- right: numColumns > 1 ? void 0 : 0,
569
+ right: numColumns > 1 ? null : 0,
528
570
  top: 0,
529
571
  width: otherAxisSize,
530
572
  ...paddingStyles || {}
531
573
  };
532
574
  }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
533
- const renderedItemInfo = React4.useMemo(
575
+ const renderedItemInfo = React3.useMemo(
534
576
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
535
577
  [itemKey, data, extraData]
536
578
  );
537
579
  const { index, renderedItem } = renderedItemInfo || {};
538
- const contextValue = React4.useMemo(() => {
580
+ const contextValue = React3.useMemo(() => {
539
581
  ctx.viewRefs.set(id, ref);
540
582
  return {
541
583
  containerId: id,
@@ -547,49 +589,64 @@ var Container = typedMemo(function Container2({
547
589
  value: data
548
590
  };
549
591
  }, [id, itemKey, index, data]);
550
- const onLayoutChange = (rectangle) => {
551
- if (!isNullOrUndefined(itemKey)) {
552
- let layout = rectangle;
553
- layout[horizontal ? "width" : "height"];
554
- const doUpdate = () => {
555
- refLastSize.current = { height: layout.height, width: layout.width };
556
- updateItemSize2(itemKey, layout);
557
- };
558
- {
559
- doUpdate();
560
- }
592
+ const onLayoutChange = React3.useCallback((rectangle) => {
593
+ const {
594
+ horizontal: currentHorizontal,
595
+ itemKey: currentItemKey,
596
+ updateItemSize: updateItemSizeFn
597
+ } = itemLayoutRef.current;
598
+ if (isNullOrUndefined(currentItemKey)) {
599
+ return;
561
600
  }
562
- };
601
+ didLayoutRef.current = true;
602
+ let layout = rectangle;
603
+ Math.floor(rectangle[currentHorizontal ? "width" : "height"] * 8) / 8;
604
+ const doUpdate = () => {
605
+ itemLayoutRef.current.lastSize = { height: layout.height, width: layout.width };
606
+ updateItemSizeFn(currentItemKey, layout);
607
+ didLayoutRef.current = true;
608
+ };
609
+ {
610
+ doUpdate();
611
+ }
612
+ }, []);
613
+ const { onLayout } = useOnLayoutSync(
614
+ {
615
+ onLayoutChange,
616
+ ref
617
+ },
618
+ [itemKey, layoutRenderCount]
619
+ );
563
620
  const PositionComponent = isSticky ? PositionViewSticky : PositionView2;
564
- return /* @__PURE__ */ React4__namespace.createElement(ContextContainer.Provider, { value: contextValue }, /* @__PURE__ */ React4__namespace.createElement(
621
+ return /* @__PURE__ */ React3__namespace.createElement(
565
622
  PositionComponent,
566
623
  {
624
+ animatedScrollY: isSticky ? animatedScrollY : void 0,
567
625
  horizontal,
568
626
  id,
569
627
  index,
570
628
  key: recycleItems ? void 0 : itemKey,
571
- onLayoutChange,
629
+ onLayout,
572
630
  refView: ref,
631
+ stickyOffset: isSticky ? stickyOffset : void 0,
573
632
  style
574
633
  },
575
- renderedItem,
576
- renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React4__namespace.createElement(
577
- Separator,
578
- {
579
- ItemSeparatorComponent,
580
- itemKey,
581
- leadingItem: renderedItemInfo.item
582
- }
583
- )
584
- ));
634
+ /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(Separator, { ItemSeparatorComponent, leadingItem: renderedItemInfo.item }))
635
+ );
585
636
  });
586
637
 
638
+ // src/platform/Platform.ts
639
+ var Platform = {
640
+ // Widen the type to avoid unreachable-branch lints in cross-platform code that compares against other OSes
641
+ OS: "web"
642
+ };
643
+
587
644
  // src/utils/reordering.ts
588
645
  var mapFn = (element) => {
589
646
  const indexStr = element.getAttribute("index");
590
647
  return [element, indexStr === null ? null : parseInt(indexStr)];
591
648
  };
592
- function sortDOMElementsPatience(container) {
649
+ function sortDOMElements(container) {
593
650
  const elements = Array.from(container.children);
594
651
  if (elements.length <= 1) return elements;
595
652
  const items = elements.map(mapFn);
@@ -671,8 +728,8 @@ function findLIS(arr) {
671
728
  // src/hooks/useDOMOrder.ts
672
729
  function useDOMOrder(ref) {
673
730
  const ctx = useStateContext();
674
- const debounceRef = React4.useRef(void 0);
675
- React4.useEffect(() => {
731
+ const debounceRef = React3.useRef(void 0);
732
+ React3.useEffect(() => {
676
733
  const unsubscribe = listen$(ctx, "lastPositionUpdate", () => {
677
734
  if (debounceRef.current !== void 0) {
678
735
  clearTimeout(debounceRef.current);
@@ -680,7 +737,7 @@ function useDOMOrder(ref) {
680
737
  debounceRef.current = setTimeout(() => {
681
738
  const parent = ref.current;
682
739
  if (parent) {
683
- sortDOMElementsPatience(parent);
740
+ sortDOMElements(parent);
684
741
  }
685
742
  debounceRef.current = void 0;
686
743
  }, 500);
@@ -696,7 +753,7 @@ function useDOMOrder(ref) {
696
753
 
697
754
  // src/components/Containers.tsx
698
755
  var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColumns, children }) {
699
- const ref = React4.useRef(null);
756
+ const ref = React3.useRef(null);
700
757
  const ctx = useStateContext();
701
758
  const columnWrapperStyle = ctx.columnWrapperStyle;
702
759
  const [totalSize, otherAxisSize] = useArr$(["totalSize", "otherAxisSize"]);
@@ -722,7 +779,7 @@ var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColum
722
779
  }
723
780
  }
724
781
  }
725
- return /* @__PURE__ */ React4__namespace.createElement("div", { ref, style }, children);
782
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref, style }, children);
726
783
  });
727
784
  var Containers = typedMemo(function Containers2({
728
785
  horizontal,
@@ -736,7 +793,7 @@ var Containers = typedMemo(function Containers2({
736
793
  const containers = [];
737
794
  for (let i = 0; i < numContainers; i++) {
738
795
  containers.push(
739
- /* @__PURE__ */ React4__namespace.createElement(
796
+ /* @__PURE__ */ React3__namespace.createElement(
740
797
  Container,
741
798
  {
742
799
  getRenderedItem: getRenderedItem2,
@@ -750,25 +807,41 @@ var Containers = typedMemo(function Containers2({
750
807
  )
751
808
  );
752
809
  }
753
- return /* @__PURE__ */ React4__namespace.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
754
- });
755
- var DevNumbers = __DEV__ && React4__namespace.memo(function DevNumbers2() {
756
- return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React4__namespace.createElement(
757
- View,
758
- {
759
- key: index,
760
- style: {
761
- height: 100,
762
- pointerEvents: "none",
763
- position: "absolute",
764
- top: index * 100,
765
- width: "100%"
766
- }
767
- },
768
- /* @__PURE__ */ React4__namespace.createElement(Text, { style: { color: "red" } }, index * 100)
769
- ));
810
+ return /* @__PURE__ */ React3__namespace.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
770
811
  });
771
- var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView2({
812
+ function DevNumbers() {
813
+ return IS_DEV && React3__namespace.memo(function DevNumbers2() {
814
+ return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3__namespace.createElement(
815
+ "div",
816
+ {
817
+ key: index,
818
+ style: {
819
+ height: 100,
820
+ pointerEvents: "none",
821
+ position: "absolute",
822
+ top: index * 100,
823
+ width: "100%"
824
+ }
825
+ },
826
+ /* @__PURE__ */ React3__namespace.createElement("div", { style: { color: "red" } }, index * 100)
827
+ ));
828
+ });
829
+ }
830
+
831
+ // src/platform/StyleSheet.tsx
832
+ function flattenStyles(styles) {
833
+ if (Array.isArray(styles)) {
834
+ return Object.assign({}, ...styles.filter(Boolean));
835
+ }
836
+ return styles;
837
+ }
838
+ var StyleSheet = {
839
+ create: (styles) => styles,
840
+ flatten: (style) => flattenStyles(style)
841
+ };
842
+
843
+ // src/components/ListComponentScrollView.tsx
844
+ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView2({
772
845
  children,
773
846
  style,
774
847
  contentContainerStyle,
@@ -781,25 +854,23 @@ var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView
781
854
  showsVerticalScrollIndicator = true,
782
855
  refreshControl,
783
856
  onLayout,
784
- ScrollComponent,
785
857
  ...props
786
858
  }, ref) {
787
- const scrollRef = React4.useRef(null);
788
- const contentRef = React4.useRef(null);
789
- const momentumTimeout = React4.useRef(null);
790
- React4.useImperativeHandle(ref, () => {
859
+ const scrollRef = React3.useRef(null);
860
+ const contentRef = React3.useRef(null);
861
+ const momentumTimeout = React3.useRef(null);
862
+ React3.useImperativeHandle(ref, () => {
791
863
  const api = {
792
864
  getBoundingClientRect: () => {
793
- var _a;
794
- return (_a = scrollRef.current) == null ? void 0 : _a.getBoundingClientRect();
865
+ var _a3;
866
+ return (_a3 = scrollRef.current) == null ? void 0 : _a3.getBoundingClientRect();
795
867
  },
796
868
  getScrollableNode: () => scrollRef.current,
797
869
  getScrollResponder: () => scrollRef.current,
798
- scrollBy: (options) => {
870
+ scrollBy: (x, y) => {
799
871
  const el = scrollRef.current;
800
872
  if (!el) return;
801
- const { x = 0, y = 0, animated = true } = options;
802
- el.scrollBy({ behavior: animated ? "smooth" : "auto", left: x, top: y });
873
+ el.scrollBy(x, y);
803
874
  },
804
875
  scrollTo: (options) => {
805
876
  const el = scrollRef.current;
@@ -830,7 +901,7 @@ var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView
830
901
  };
831
902
  return api;
832
903
  }, [horizontal]);
833
- const handleScroll = React4.useCallback(
904
+ const handleScroll = React3.useCallback(
834
905
  (event) => {
835
906
  if (!onScroll2 || !(event == null ? void 0 : event.target)) {
836
907
  return;
@@ -866,21 +937,25 @@ var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView
866
937
  },
867
938
  [onScroll2, onMomentumScrollEnd]
868
939
  );
869
- React4.useLayoutEffect(() => {
940
+ React3.useLayoutEffect(() => {
870
941
  const element = scrollRef.current;
871
942
  if (!element) return;
872
- element.addEventListener("scroll", handleScroll, { passive: true });
943
+ element.addEventListener("scroll", handleScroll);
873
944
  return () => {
874
945
  element.removeEventListener("scroll", handleScroll);
875
946
  };
876
947
  }, [handleScroll]);
877
- React4.useLayoutEffect(() => {
878
- if (contentOffset && scrollRef.current) {
879
- scrollRef.current.scrollLeft = contentOffset.x || 0;
880
- scrollRef.current.scrollTop = contentOffset.y || 0;
881
- }
882
- }, [contentOffset]);
883
- React4.useLayoutEffect(() => {
948
+ React3.useEffect(() => {
949
+ const doScroll = () => {
950
+ if (contentOffset && scrollRef.current) {
951
+ scrollRef.current.scrollLeft = contentOffset.x || 0;
952
+ scrollRef.current.scrollTop = contentOffset.y || 0;
953
+ }
954
+ };
955
+ doScroll();
956
+ requestAnimationFrame(doScroll);
957
+ }, [contentOffset == null ? void 0 : contentOffset.x, contentOffset == null ? void 0 : contentOffset.y]);
958
+ React3.useLayoutEffect(() => {
884
959
  if (!onLayout || !scrollRef.current) return;
885
960
  const element = scrollRef.current;
886
961
  const fireLayout = () => {
@@ -911,36 +986,57 @@ var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView
911
986
  // Ensure proper positioning context
912
987
  WebkitOverflowScrolling: "touch",
913
988
  // iOS momentum scrolling
914
- ...style
989
+ ...StyleSheet.flatten(style)
915
990
  };
916
991
  const contentStyle = {
917
992
  display: horizontal ? "flex" : "block",
918
993
  flexDirection: horizontal ? "row" : void 0,
919
994
  minHeight: horizontal ? void 0 : "100%",
920
995
  minWidth: horizontal ? "100%" : void 0,
921
- ...contentContainerStyle
996
+ ...StyleSheet.flatten(contentContainerStyle)
922
997
  };
923
- return /* @__PURE__ */ React4__namespace.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React4__namespace.createElement("div", { ref: contentRef, style: contentStyle }, children));
998
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React3__namespace.createElement("div", { ref: contentRef, style: contentStyle }, children));
924
999
  });
1000
+ function Padding() {
1001
+ const [paddingTop] = useArr$(["alignItemsPaddingTop"]);
1002
+ return /* @__PURE__ */ React3__namespace.createElement("div", { style: { paddingTop } });
1003
+ }
1004
+ function PaddingDevMode() {
1005
+ const [paddingTop] = useArr$(["alignItemsPaddingTop"]);
1006
+ return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement("div", { style: { paddingTop } }), /* @__PURE__ */ React3__namespace.createElement(
1007
+ "div",
1008
+ {
1009
+ style: {
1010
+ backgroundColor: "green",
1011
+ height: paddingTop,
1012
+ left: 0,
1013
+ position: "absolute",
1014
+ right: 0,
1015
+ top: 0
1016
+ }
1017
+ }
1018
+ ));
1019
+ }
925
1020
  function useValueListener$(key, callback) {
926
1021
  const ctx = useStateContext();
927
- React4.useLayoutEffect(() => {
928
- listen$(ctx, key, (value) => {
1022
+ React3.useLayoutEffect(() => {
1023
+ const unsubscribe = listen$(ctx, key, (value) => {
929
1024
  callback(value);
930
1025
  });
931
- }, []);
1026
+ return unsubscribe;
1027
+ }, [callback, ctx, key]);
932
1028
  }
933
1029
 
934
1030
  // src/components/ScrollAdjust.tsx
935
1031
  function ScrollAdjust() {
936
1032
  const ctx = useStateContext();
937
- const lastScrollOffsetRef = React4__namespace.useRef(0);
938
- const callback = React4__namespace.useCallback(() => {
939
- var _a;
1033
+ const lastScrollOffsetRef = React3__namespace.useRef(0);
1034
+ const callback = React3__namespace.useCallback(() => {
1035
+ var _a3;
940
1036
  const scrollAdjust = peek$(ctx, "scrollAdjust");
941
1037
  const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
942
1038
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
943
- const scrollView = (_a = ctx.internalState) == null ? void 0 : _a.refScroller.current;
1039
+ const scrollView = (_a3 = ctx.internalState) == null ? void 0 : _a3.refScroller.current;
944
1040
  if (scrollView && scrollOffset !== lastScrollOffsetRef.current) {
945
1041
  const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
946
1042
  if (scrollDelta !== 0) {
@@ -954,49 +1050,26 @@ function ScrollAdjust() {
954
1050
  useValueListener$("scrollAdjustUserOffset", callback);
955
1051
  return null;
956
1052
  }
957
-
958
- // src/components/SnapWrapper.tsx
959
1053
  function SnapWrapper({ ScrollComponent, ...props }) {
960
1054
  const [snapToOffsets] = useArr$(["snapToOffsets"]);
961
- return /* @__PURE__ */ React.createElement(ScrollComponent, { ...props, snapToOffsets });
962
- }
963
-
964
- // src/hooks/useValue$.ts
965
- function useValue$(key, params) {
966
- const [value] = useArr$([key]);
967
- return value;
1055
+ return /* @__PURE__ */ React3__namespace.createElement(ScrollComponent, { ...props, snapToOffsets });
968
1056
  }
1057
+ var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
1058
+ const ref = refView != null ? refView : React3.useRef();
1059
+ useOnLayoutSync({ onLayoutChange, ref });
1060
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ...rest, ref }, children);
1061
+ };
969
1062
 
970
1063
  // src/components/ListComponent.tsx
971
1064
  var getComponent = (Component) => {
972
- if (React4__namespace.isValidElement(Component)) {
1065
+ if (React3__namespace.isValidElement(Component)) {
973
1066
  return Component;
974
1067
  }
975
1068
  if (Component) {
976
- return /* @__PURE__ */ React4__namespace.createElement(Component, null);
1069
+ return /* @__PURE__ */ React3__namespace.createElement(Component, null);
977
1070
  }
978
1071
  return null;
979
1072
  };
980
- var Padding = () => {
981
- const animPaddingTop = useValue$("alignItemsPaddingTop");
982
- return /* @__PURE__ */ React4__namespace.createElement(AnimatedView, { style: { paddingTop: animPaddingTop } });
983
- };
984
- var PaddingDevMode = () => {
985
- const animPaddingTop = useValue$("alignItemsPaddingTop");
986
- return /* @__PURE__ */ React4__namespace.createElement(React4__namespace.Fragment, null, /* @__PURE__ */ React4__namespace.createElement(AnimatedView, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React4__namespace.createElement(
987
- AnimatedView,
988
- {
989
- style: {
990
- backgroundColor: "green",
991
- height: animPaddingTop,
992
- left: 0,
993
- position: "absolute",
994
- right: 0,
995
- top: 0
996
- }
997
- }
998
- ));
999
- };
1000
1073
  var ListComponent = typedMemo(function ListComponent2({
1001
1074
  canRender,
1002
1075
  style,
@@ -1026,12 +1099,11 @@ var ListComponent = typedMemo(function ListComponent2({
1026
1099
  ...rest
1027
1100
  }) {
1028
1101
  const ctx = useStateContext();
1029
- const refHeader = React4__namespace.useRef(null);
1030
- const ScrollComponent = renderScrollComponent ? React4.useMemo(
1031
- () => React4__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
1102
+ const ScrollComponent = renderScrollComponent ? React3.useMemo(
1103
+ () => React3__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
1032
1104
  [renderScrollComponent]
1033
1105
  ) : ListComponentScrollView;
1034
- React4__namespace.useEffect(() => {
1106
+ React3__namespace.useEffect(() => {
1035
1107
  if (canRender) {
1036
1108
  setTimeout(() => {
1037
1109
  scrollAdjustHandler.setMounted();
@@ -1039,39 +1111,30 @@ var ListComponent = typedMemo(function ListComponent2({
1039
1111
  }
1040
1112
  }, [canRender]);
1041
1113
  const SnapOrScroll = snapToIndices ? SnapWrapper : ScrollComponent;
1042
- const contentContainerStyleWeb = React4.useMemo(() => {
1043
- const base = contentContainerStyle || void 0;
1044
- if (!horizontal) return base;
1045
- if (base && base.height === "100%") return base;
1046
- return { ...base || {}, height: "100%" };
1047
- }, [horizontal, (contentContainerStyle == null ? void 0 : contentContainerStyle.height) === "100%" ? 1 : 0]);
1048
- return /* @__PURE__ */ React4__namespace.createElement(
1114
+ return /* @__PURE__ */ React3__namespace.createElement(
1049
1115
  SnapOrScroll,
1050
1116
  {
1051
1117
  ...rest,
1052
- contentContainerStyle: contentContainerStyleWeb,
1118
+ contentContainerStyle: [
1119
+ contentContainerStyle,
1120
+ horizontal ? {
1121
+ height: "100%"
1122
+ } : {}
1123
+ ],
1053
1124
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
1054
1125
  horizontal,
1055
- maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
1126
+ maintainVisibleContentPosition: maintainVisibleContentPosition ? { minIndexForVisible: 0 } : void 0,
1056
1127
  onLayout,
1057
1128
  onScroll: onScroll2,
1058
1129
  ref: refScrollView,
1059
1130
  ScrollComponent: snapToIndices ? ScrollComponent : void 0,
1060
1131
  style
1061
1132
  },
1062
- maintainVisibleContentPosition && /* @__PURE__ */ React4__namespace.createElement(ScrollAdjust, null),
1063
- ENABLE_DEVMODE ? /* @__PURE__ */ React4__namespace.createElement(PaddingDevMode, null) : /* @__PURE__ */ React4__namespace.createElement(Padding, null),
1064
- ListHeaderComponent && /* @__PURE__ */ React4__namespace.createElement(
1065
- LayoutView,
1066
- {
1067
- onLayoutChange: onLayoutHeader,
1068
- refView: refHeader,
1069
- style: ListHeaderComponentStyle
1070
- },
1071
- getComponent(ListHeaderComponent)
1072
- ),
1133
+ maintainVisibleContentPosition && /* @__PURE__ */ React3__namespace.createElement(ScrollAdjust, null),
1134
+ ENABLE_DEVMODE ? /* @__PURE__ */ React3__namespace.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3__namespace.createElement(Padding, null),
1135
+ ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1073
1136
  ListEmptyComponent && getComponent(ListEmptyComponent),
1074
- canRender && /* @__PURE__ */ React4__namespace.createElement(
1137
+ canRender && !ListEmptyComponent && /* @__PURE__ */ React3__namespace.createElement(
1075
1138
  Containers,
1076
1139
  {
1077
1140
  getRenderedItem: getRenderedItem2,
@@ -1082,7 +1145,7 @@ var ListComponent = typedMemo(function ListComponent2({
1082
1145
  waitForInitialLayout
1083
1146
  }
1084
1147
  ),
1085
- ListFooterComponent && /* @__PURE__ */ React4__namespace.createElement(
1148
+ ListFooterComponent && /* @__PURE__ */ React3__namespace.createElement(
1086
1149
  LayoutView,
1087
1150
  {
1088
1151
  onLayoutChange: (layout) => {
@@ -1093,7 +1156,7 @@ var ListComponent = typedMemo(function ListComponent2({
1093
1156
  },
1094
1157
  getComponent(ListFooterComponent)
1095
1158
  ),
1096
- __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React4__namespace.createElement(DevNumbers, null)
1159
+ IS_DEV && ENABLE_DEVMODE && /* @__PURE__ */ React3__namespace.createElement(DevNumbers, null)
1097
1160
  );
1098
1161
  });
1099
1162
 
@@ -1105,7 +1168,7 @@ function getId(state, index) {
1105
1168
  }
1106
1169
  const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
1107
1170
  const id = ret;
1108
- state.idCache.set(index, id);
1171
+ state.idCache[index] = id;
1109
1172
  return id;
1110
1173
  }
1111
1174
 
@@ -1127,12 +1190,11 @@ function calculateOffsetForIndex(ctx, state, index) {
1127
1190
  }
1128
1191
 
1129
1192
  // src/utils/getItemSize.ts
1130
- function getItemSize(state, key, index, data, useAverageSize) {
1131
- var _a, _b;
1193
+ function getItemSize(ctx, state, key, index, data, useAverageSize) {
1194
+ var _a3, _b;
1132
1195
  const {
1133
1196
  sizesKnown,
1134
1197
  sizes,
1135
- scrollingTo,
1136
1198
  averageSizes,
1137
1199
  props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
1138
1200
  } = state;
@@ -1141,7 +1203,8 @@ function getItemSize(state, key, index, data, useAverageSize) {
1141
1203
  return sizeKnown;
1142
1204
  }
1143
1205
  let size;
1144
- const itemType = getItemType ? (_a = getItemType(data, index)) != null ? _a : "" : "";
1206
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1207
+ const scrollingTo = peek$(ctx, "scrollingTo");
1145
1208
  if (getFixedItemSize) {
1146
1209
  size = getFixedItemSize(index, data, itemType);
1147
1210
  if (size !== void 0) {
@@ -1168,82 +1231,241 @@ function getItemSize(state, key, index, data, useAverageSize) {
1168
1231
  }
1169
1232
 
1170
1233
  // src/core/calculateOffsetWithOffsetPosition.ts
1171
- function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
1234
+ function calculateOffsetWithOffsetPosition(ctx, state, offsetParam, params) {
1172
1235
  const { index, viewOffset, viewPosition } = params;
1173
1236
  let offset = offsetParam;
1174
1237
  if (viewOffset) {
1175
1238
  offset -= viewOffset;
1176
1239
  }
1177
1240
  if (viewPosition !== void 0 && index !== void 0) {
1178
- offset -= viewPosition * (state.scrollLength - getItemSize(state, getId(state, index), index, state.props.data[index]));
1241
+ offset -= viewPosition * (state.scrollLength - getItemSize(ctx, state, getId(state, index), index, state.props.data[index]));
1179
1242
  }
1180
1243
  return offset;
1181
1244
  }
1182
1245
 
1183
- // src/core/finishScrollTo.ts
1184
- var finishScrollTo = (state) => {
1185
- if (state) {
1186
- state.scrollingTo = void 0;
1187
- state.scrollHistory.length = 0;
1246
+ // src/utils/checkThreshold.ts
1247
+ var HYSTERESIS_MULTIPLIER = 1.3;
1248
+ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
1249
+ const absDistance = Math.abs(distance);
1250
+ const within = atThreshold || threshold > 0 && absDistance <= threshold;
1251
+ const updateSnapshot = () => {
1252
+ setSnapshot == null ? void 0 : setSnapshot({
1253
+ atThreshold,
1254
+ contentSize: context.contentSize,
1255
+ dataLength: context.dataLength,
1256
+ scrollPosition: context.scrollPosition
1257
+ });
1258
+ };
1259
+ if (!wasReached) {
1260
+ if (!within) {
1261
+ return false;
1262
+ }
1263
+ onReached == null ? void 0 : onReached(distance);
1264
+ updateSnapshot();
1265
+ return true;
1266
+ }
1267
+ const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
1268
+ if (reset) {
1269
+ setSnapshot == null ? void 0 : setSnapshot(void 0);
1270
+ return false;
1271
+ }
1272
+ if (within) {
1273
+ const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
1274
+ if (changed) {
1275
+ onReached == null ? void 0 : onReached(distance);
1276
+ updateSnapshot();
1277
+ }
1188
1278
  }
1279
+ return true;
1189
1280
  };
1190
1281
 
1191
- // src/core/scrollTo.ts
1192
- function scrollTo(state, params = {}) {
1193
- var _a;
1194
- const { animated, noScrollingTo } = params;
1282
+ // src/utils/checkAtBottom.ts
1283
+ function checkAtBottom(ctx, state) {
1284
+ var _a3;
1285
+ if (!state) {
1286
+ return;
1287
+ }
1195
1288
  const {
1196
- refScroller,
1197
- props: { horizontal }
1289
+ queuedInitialLayout,
1290
+ scrollLength,
1291
+ scroll,
1292
+ maintainingScrollAtEnd,
1293
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1198
1294
  } = state;
1199
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1200
- state.scrollHistory.length = 0;
1201
- if (!noScrollingTo) {
1202
- state.scrollingTo = params;
1203
- }
1204
- state.scrollPending = offset;
1205
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1206
- animated: !!animated,
1207
- x: horizontal ? offset : 0,
1208
- y: horizontal ? 0 : offset
1209
- });
1210
- if (!animated) {
1211
- state.scroll = offset;
1212
- setTimeout(() => finishScrollTo(state), 100);
1295
+ const contentSize = getContentSize(ctx);
1296
+ if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1297
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1298
+ const isContentLess = contentSize < scrollLength;
1299
+ state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1300
+ state.isEndReached = checkThreshold(
1301
+ distanceFromEnd,
1302
+ isContentLess,
1303
+ onEndReachedThreshold * scrollLength,
1304
+ state.isEndReached,
1305
+ state.endReachedSnapshot,
1306
+ {
1307
+ contentSize,
1308
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1309
+ scrollPosition: scroll
1310
+ },
1311
+ (distance) => {
1312
+ var _a4, _b;
1313
+ return (_b = (_a4 = state.props).onEndReached) == null ? void 0 : _b.call(_a4, { distanceFromEnd: distance });
1314
+ },
1315
+ (snapshot) => {
1316
+ state.endReachedSnapshot = snapshot;
1317
+ }
1318
+ );
1213
1319
  }
1214
1320
  }
1215
1321
 
1216
- // src/utils/requestAdjust.ts
1217
- function requestAdjust(ctx, state, positionDiff, dataChanged) {
1218
- if (Math.abs(positionDiff) > 0.1) {
1219
- const doit = () => {
1220
- {
1221
- state.scrollAdjustHandler.requestAdjust(positionDiff);
1222
- }
1223
- };
1224
- state.scroll += positionDiff;
1225
- state.scrollForNextCalculateItemsInView = void 0;
1226
- const didLayout = peek$(ctx, "containersDidLayout");
1227
- if (didLayout) {
1228
- doit();
1229
- const threshold = state.scroll - positionDiff / 2;
1230
- if (!state.ignoreScrollFromMVCP) {
1231
- state.ignoreScrollFromMVCP = {};
1232
- }
1233
- if (positionDiff > 0) {
1234
- state.ignoreScrollFromMVCP.lt = threshold;
1235
- } else {
1236
- state.ignoreScrollFromMVCP.gt = threshold;
1237
- }
1238
- if (state.ignoreScrollFromMVCPTimeout) {
1239
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
1322
+ // src/utils/checkAtTop.ts
1323
+ function checkAtTop(state) {
1324
+ var _a3;
1325
+ if (!state) {
1326
+ return;
1327
+ }
1328
+ const {
1329
+ scrollLength,
1330
+ scroll,
1331
+ props: { onStartReachedThreshold }
1332
+ } = state;
1333
+ const distanceFromTop = scroll;
1334
+ state.isAtStart = distanceFromTop <= 0;
1335
+ state.isStartReached = checkThreshold(
1336
+ distanceFromTop,
1337
+ false,
1338
+ onStartReachedThreshold * scrollLength,
1339
+ state.isStartReached,
1340
+ state.startReachedSnapshot,
1341
+ {
1342
+ contentSize: state.totalSize,
1343
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1344
+ scrollPosition: scroll
1345
+ },
1346
+ (distance) => {
1347
+ var _a4, _b;
1348
+ return (_b = (_a4 = state.props).onStartReached) == null ? void 0 : _b.call(_a4, { distanceFromStart: distance });
1349
+ },
1350
+ (snapshot) => {
1351
+ state.startReachedSnapshot = snapshot;
1352
+ }
1353
+ );
1354
+ }
1355
+
1356
+ // src/core/onScroll.ts
1357
+ function onScroll(ctx, state, event) {
1358
+ var _a3, _b, _c;
1359
+ const {
1360
+ scrollProcessingEnabled,
1361
+ props: { onScroll: onScrollProp }
1362
+ } = state;
1363
+ if (scrollProcessingEnabled === false) {
1364
+ return;
1365
+ }
1366
+ 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) {
1367
+ return;
1368
+ }
1369
+ const newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
1370
+ state.scrollPending = newScroll;
1371
+ updateScroll(ctx, state, newScroll);
1372
+ onScrollProp == null ? void 0 : onScrollProp(event);
1373
+ }
1374
+ function updateScroll(ctx, state, newScroll, forceUpdate) {
1375
+ const scrollingTo = peek$(ctx, "scrollingTo");
1376
+ state.hasScrolled = true;
1377
+ state.lastBatchingAction = Date.now();
1378
+ const currentTime = Date.now();
1379
+ const adjust = state.scrollAdjustHandler.getAdjust();
1380
+ const lastHistoryAdjust = state.lastScrollAdjustForHistory;
1381
+ const adjustChanged = lastHistoryAdjust !== void 0 && Math.abs(adjust - lastHistoryAdjust) > 0.1;
1382
+ if (adjustChanged) {
1383
+ state.scrollHistory.length = 0;
1384
+ }
1385
+ state.lastScrollAdjustForHistory = adjust;
1386
+ if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
1387
+ if (!adjustChanged) {
1388
+ state.scrollHistory.push({ scroll: newScroll, time: currentTime });
1389
+ }
1390
+ }
1391
+ if (state.scrollHistory.length > 5) {
1392
+ state.scrollHistory.shift();
1393
+ }
1394
+ state.scrollPrev = state.scroll;
1395
+ state.scrollPrevTime = state.scrollTime;
1396
+ state.scroll = newScroll;
1397
+ state.scrollTime = currentTime;
1398
+ const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
1399
+ if (ignoreScrollFromMVCP && !scrollingTo) {
1400
+ const { lt, gt } = ignoreScrollFromMVCP;
1401
+ if (lt && newScroll < lt || gt && newScroll > gt) {
1402
+ state.ignoreScrollFromMVCPIgnored = true;
1403
+ return;
1404
+ }
1405
+ }
1406
+ if (state.dataChangeNeedsScrollUpdate || Math.abs(state.scroll - state.scrollPrev) > 2) {
1407
+ state.ignoreScrollFromMVCPIgnored = false;
1408
+ calculateItemsInView(ctx, state, { doMVCP: scrollingTo !== void 0 });
1409
+ checkAtBottom(ctx, state);
1410
+ checkAtTop(state);
1411
+ state.dataChangeNeedsScrollUpdate = false;
1412
+ }
1413
+ }
1414
+
1415
+ // src/core/finishScrollTo.ts
1416
+ function finishScrollTo(ctx, state) {
1417
+ if (state) {
1418
+ set$(ctx, "scrollingTo", void 0);
1419
+ state.scrollHistory.length = 0;
1420
+ }
1421
+ }
1422
+
1423
+ // src/core/scrollTo.ts
1424
+ function scrollTo(ctx, state, params) {
1425
+ var _a3;
1426
+ const { noScrollingTo, ...scrollTarget } = params;
1427
+ const { animated, isInitialScroll, offset: scrollTargetOffset } = scrollTarget;
1428
+ const {
1429
+ refScroller,
1430
+ props: { horizontal }
1431
+ } = state;
1432
+ const offset = calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1433
+ state.scrollHistory.length = 0;
1434
+ if (!noScrollingTo) {
1435
+ set$(ctx, "scrollingTo", scrollTarget);
1436
+ }
1437
+ state.scrollPending = offset;
1438
+ if (!isInitialScroll || Platform.OS === "android") {
1439
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollTo({
1440
+ animated: !!animated,
1441
+ x: horizontal ? offset : 0,
1442
+ y: horizontal ? 0 : offset
1443
+ });
1444
+ }
1445
+ if (!animated) {
1446
+ state.scroll = offset;
1447
+ setTimeout(() => finishScrollTo(ctx, state), 100);
1448
+ if (isInitialScroll) {
1449
+ setTimeout(() => {
1450
+ state.initialScroll = void 0;
1451
+ }, 500);
1452
+ }
1453
+ }
1454
+ }
1455
+
1456
+ // src/utils/requestAdjust.ts
1457
+ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1458
+ if (Math.abs(positionDiff) > 0.1) {
1459
+ const doit = () => {
1460
+ {
1461
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
1240
1462
  }
1241
- state.ignoreScrollFromMVCPTimeout = setTimeout(
1242
- () => {
1243
- state.ignoreScrollFromMVCP = void 0;
1244
- },
1245
- 100
1246
- );
1463
+ };
1464
+ state.scroll += positionDiff;
1465
+ state.scrollForNextCalculateItemsInView = void 0;
1466
+ const didLayout = peek$(ctx, "containersDidLayout");
1467
+ if (didLayout) {
1468
+ doit();
1247
1469
  } else {
1248
1470
  requestAnimationFrame(doit);
1249
1471
  }
@@ -1255,9 +1477,9 @@ function prepareMVCP(ctx, state, dataChanged) {
1255
1477
  const {
1256
1478
  idsInView,
1257
1479
  positions,
1258
- scrollingTo,
1259
1480
  props: { maintainVisibleContentPosition }
1260
1481
  } = state;
1482
+ const scrollingTo = peek$(ctx, "scrollingTo");
1261
1483
  let prevPosition;
1262
1484
  let targetId;
1263
1485
  const idsInViewWithPositions = [];
@@ -1298,7 +1520,16 @@ function prepareMVCP(ctx, state, dataChanged) {
1298
1520
  if (targetId !== void 0 && prevPosition !== void 0) {
1299
1521
  const newPosition = positions.get(targetId);
1300
1522
  if (newPosition !== void 0) {
1301
- positionDiff = newPosition - prevPosition;
1523
+ const totalSize = peek$(ctx, "totalSize");
1524
+ let diff = newPosition - prevPosition;
1525
+ if (diff !== 0 && state.scroll + state.scrollLength > totalSize) {
1526
+ if (diff > 0) {
1527
+ diff = Math.max(0, totalSize - state.scroll - state.scrollLength);
1528
+ } else {
1529
+ diff = 0;
1530
+ }
1531
+ }
1532
+ positionDiff = diff;
1302
1533
  }
1303
1534
  }
1304
1535
  if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
@@ -1307,6 +1538,68 @@ function prepareMVCP(ctx, state, dataChanged) {
1307
1538
  };
1308
1539
  }
1309
1540
 
1541
+ // src/core/prepareColumnStartState.ts
1542
+ function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1543
+ var _a3;
1544
+ const numColumns = peek$(ctx, "numColumns");
1545
+ let rowStartIndex = startIndex;
1546
+ const columnAtStart = state.columns.get(state.idCache[startIndex]);
1547
+ if (columnAtStart !== 1) {
1548
+ rowStartIndex = findRowStartIndex(state, numColumns, startIndex);
1549
+ }
1550
+ let currentRowTop = 0;
1551
+ const curId = state.idCache[rowStartIndex];
1552
+ const column = state.columns.get(curId);
1553
+ if (rowStartIndex > 0) {
1554
+ const prevIndex = rowStartIndex - 1;
1555
+ const prevId = state.idCache[prevIndex];
1556
+ const prevPosition = (_a3 = state.positions.get(prevId)) != null ? _a3 : 0;
1557
+ const prevRowStart = findRowStartIndex(state, numColumns, prevIndex);
1558
+ const prevRowHeight = calculateRowMaxSize(ctx, state, prevRowStart, prevIndex, useAverageSize);
1559
+ currentRowTop = prevPosition + prevRowHeight;
1560
+ }
1561
+ return {
1562
+ column,
1563
+ currentRowTop,
1564
+ startIndex: rowStartIndex
1565
+ };
1566
+ }
1567
+ function findRowStartIndex(state, numColumns, index) {
1568
+ if (numColumns <= 1) {
1569
+ return Math.max(0, index);
1570
+ }
1571
+ let rowStart = Math.max(0, index);
1572
+ while (rowStart > 0) {
1573
+ const columnForIndex = state.columns.get(state.idCache[rowStart]);
1574
+ if (columnForIndex === 1) {
1575
+ break;
1576
+ }
1577
+ rowStart--;
1578
+ }
1579
+ return rowStart;
1580
+ }
1581
+ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1582
+ if (endIndex < startIndex) {
1583
+ return 0;
1584
+ }
1585
+ const { data } = state.props;
1586
+ if (!data) {
1587
+ return 0;
1588
+ }
1589
+ let maxSize = 0;
1590
+ for (let i = startIndex; i <= endIndex; i++) {
1591
+ if (i < 0 || i >= data.length) {
1592
+ continue;
1593
+ }
1594
+ const id = state.idCache[i];
1595
+ const size = getItemSize(ctx, state, id, i, data[i], useAverageSize);
1596
+ if (size > maxSize) {
1597
+ maxSize = size;
1598
+ }
1599
+ }
1600
+ return maxSize;
1601
+ }
1602
+
1310
1603
  // src/utils/setPaddingTop.ts
1311
1604
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1312
1605
  if (stylePaddingTop !== void 0) {
@@ -1355,7 +1648,7 @@ function updateTotalSize(ctx, state) {
1355
1648
  if (lastId !== void 0) {
1356
1649
  const lastPosition = positions.get(lastId);
1357
1650
  if (lastPosition !== void 0) {
1358
- const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
1651
+ const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
1359
1652
  if (lastSize !== void 0) {
1360
1653
  const totalSize = lastPosition + lastSize;
1361
1654
  addTotalSize(ctx, state, null, totalSize);
@@ -1366,16 +1659,21 @@ function updateTotalSize(ctx, state) {
1366
1659
  }
1367
1660
  function addTotalSize(ctx, state, key, add) {
1368
1661
  const { alignItemsAtEnd } = state.props;
1369
- {
1662
+ const prevTotalSize = state.totalSize;
1663
+ if (key === null) {
1370
1664
  state.totalSize = add;
1371
1665
  if (state.timeoutSetPaddingTop) {
1372
1666
  clearTimeout(state.timeoutSetPaddingTop);
1373
1667
  state.timeoutSetPaddingTop = void 0;
1374
1668
  }
1669
+ } else {
1670
+ state.totalSize += add;
1375
1671
  }
1376
- set$(ctx, "totalSize", state.totalSize);
1377
- if (alignItemsAtEnd) {
1378
- updateAlignItemsPaddingTop(ctx, state);
1672
+ if (prevTotalSize !== state.totalSize) {
1673
+ set$(ctx, "totalSize", state.totalSize);
1674
+ if (alignItemsAtEnd) {
1675
+ updateAlignItemsPaddingTop(ctx, state);
1676
+ }
1379
1677
  }
1380
1678
  }
1381
1679
 
@@ -1394,9 +1692,9 @@ function updateSnapToOffsets(ctx, state) {
1394
1692
  set$(ctx, "snapToOffsets", snapToOffsets);
1395
1693
  }
1396
1694
 
1397
- // src/core/updateAllPositions.ts
1398
- function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1399
- var _a, _b, _c, _d, _e, _f;
1695
+ // src/core/updateItemPositions.ts
1696
+ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottomBuffered } = { scrollBottomBuffered: -1, startIndex: 0 }) {
1697
+ var _a3, _b, _c, _d;
1400
1698
  const {
1401
1699
  columns,
1402
1700
  indexByKey,
@@ -1406,32 +1704,49 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1406
1704
  props: { getEstimatedItemSize, snapToIndices, enableAverages }
1407
1705
  } = state;
1408
1706
  const data = state.props.data;
1707
+ const dataLength = data.length;
1409
1708
  const numColumns = peek$(ctx, "numColumns");
1410
- const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1709
+ const scrollingTo = peek$(ctx, "scrollingTo");
1710
+ const hasColumns = numColumns > 1;
1711
+ const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1712
+ const maxVisibleArea = scrollBottomBuffered + 1e3;
1411
1713
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1412
1714
  let currentRowTop = 0;
1413
1715
  let column = 1;
1414
1716
  let maxSizeInRow = 0;
1415
- const hasColumns = numColumns > 1;
1416
1717
  if (startIndex > 0) {
1417
- const prevIndex = startIndex - 1;
1418
- const prevId = (_a = idCache.get(prevIndex)) != null ? _a : getId(state, prevIndex);
1419
- const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1420
1718
  if (hasColumns) {
1421
- const prevColumn = (_c = columns.get(prevId)) != null ? _c : 1;
1422
- currentRowTop = prevPosition;
1423
- column = prevColumn % numColumns + 1;
1424
- } else {
1425
- const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(state, prevId, prevIndex, data[prevIndex], useAverageSize);
1719
+ const { startIndex: processedStartIndex, currentRowTop: initialRowTop } = prepareColumnStartState(
1720
+ ctx,
1721
+ state,
1722
+ startIndex,
1723
+ useAverageSize
1724
+ );
1725
+ startIndex = processedStartIndex;
1726
+ currentRowTop = initialRowTop;
1727
+ } else if (startIndex < dataLength) {
1728
+ const prevIndex = startIndex - 1;
1729
+ const prevId = getId(state, prevIndex);
1730
+ const prevPosition = (_a3 = positions.get(prevId)) != null ? _a3 : 0;
1731
+ const prevSize = (_b = sizesKnown.get(prevId)) != null ? _b : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize);
1426
1732
  currentRowTop = prevPosition + prevSize;
1427
1733
  }
1428
1734
  }
1429
1735
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1430
- const dataLength = data.length;
1736
+ let didBreakEarly = false;
1737
+ let breakAt;
1431
1738
  for (let i = startIndex; i < dataLength; i++) {
1432
- const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1433
- const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(state, id, i, data[i], useAverageSize);
1434
- if (__DEV__ && needsIndexByKey) {
1739
+ if (breakAt && i > breakAt) {
1740
+ didBreakEarly = true;
1741
+ break;
1742
+ }
1743
+ if (breakAt === void 0 && !scrollingTo && !dataChanged && currentRowTop > maxVisibleArea) {
1744
+ const itemsPerRow = hasColumns ? numColumns : 1;
1745
+ breakAt = i + itemsPerRow + 10;
1746
+ }
1747
+ const id = (_c = idCache[i]) != null ? _c : getId(state, i);
1748
+ const size = (_d = sizesKnown.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i], useAverageSize);
1749
+ if (IS_DEV && needsIndexByKey) {
1435
1750
  if (indexByKeyForChecking.has(id)) {
1436
1751
  console.error(
1437
1752
  `[legend-list] Error: Detected overlapping key (${id}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`
@@ -1458,7 +1773,9 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1458
1773
  currentRowTop += size;
1459
1774
  }
1460
1775
  }
1461
- updateTotalSize(ctx, state);
1776
+ if (!didBreakEarly) {
1777
+ updateTotalSize(ctx, state);
1778
+ }
1462
1779
  if (snapToIndices) {
1463
1780
  updateSnapToOffsets(ctx, state);
1464
1781
  }
@@ -1478,6 +1795,21 @@ function ensureViewabilityState(ctx, configId) {
1478
1795
  }
1479
1796
  return state;
1480
1797
  }
1798
+ function setupViewability(props) {
1799
+ let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
1800
+ if (viewabilityConfig || onViewableItemsChanged) {
1801
+ viewabilityConfigCallbackPairs = [
1802
+ ...viewabilityConfigCallbackPairs || [],
1803
+ {
1804
+ onViewableItemsChanged,
1805
+ viewabilityConfig: viewabilityConfig || {
1806
+ viewAreaCoveragePercentThreshold: 0
1807
+ }
1808
+ }
1809
+ ];
1810
+ }
1811
+ return viewabilityConfigCallbackPairs;
1812
+ }
1481
1813
  function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
1482
1814
  const {
1483
1815
  timeouts,
@@ -1649,9 +1981,12 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1649
1981
  }
1650
1982
 
1651
1983
  // src/utils/checkAllSizesKnown.ts
1984
+ function isNullOrUndefined2(value) {
1985
+ return value === null || value === void 0;
1986
+ }
1652
1987
  function checkAllSizesKnown(state) {
1653
1988
  const { startBuffered, endBuffered, sizesKnown } = state;
1654
- if (endBuffered !== null && startBuffered >= 0 && endBuffered >= 0) {
1989
+ if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
1655
1990
  let areAllKnown = true;
1656
1991
  for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1657
1992
  const key = getId(state, i);
@@ -1668,6 +2003,8 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1668
2003
  const { stickyContainerPool, containerItemTypes } = state;
1669
2004
  const result = [];
1670
2005
  const availableContainers = [];
2006
+ const pendingRemovalSet = new Set(pendingRemoval);
2007
+ let pendingRemovalChanged = false;
1671
2008
  const stickyIndicesSet = state.props.stickyIndicesSet;
1672
2009
  const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
1673
2010
  const canReuseContainer = (containerIndex, requiredType) => {
@@ -1683,12 +2020,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1683
2020
  let foundContainer = false;
1684
2021
  for (const containerIndex of stickyContainerPool) {
1685
2022
  const key = peek$(ctx, `containerItemKey${containerIndex}`);
1686
- const isPendingRemoval = pendingRemoval.includes(containerIndex);
2023
+ const isPendingRemoval = pendingRemovalSet.has(containerIndex);
1687
2024
  if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType)) {
1688
2025
  result.push(containerIndex);
1689
- if (isPendingRemoval) {
1690
- const index = pendingRemoval.indexOf(containerIndex);
1691
- pendingRemoval.splice(index, 1);
2026
+ if (isPendingRemoval && pendingRemovalSet.delete(containerIndex)) {
2027
+ pendingRemovalChanged = true;
1692
2028
  }
1693
2029
  foundContainer = true;
1694
2030
  if (requiredItemTypes) typeIndex++;
@@ -1708,13 +2044,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1708
2044
  }
1709
2045
  const key = peek$(ctx, `containerItemKey${u}`);
1710
2046
  let isOk = key === void 0;
1711
- if (!isOk) {
1712
- const index = pendingRemoval.indexOf(u);
1713
- if (index !== -1) {
1714
- pendingRemoval.splice(index, 1);
1715
- const requiredType = neededTypes[typeIndex];
1716
- isOk = canReuseContainer(u, requiredType);
1717
- }
2047
+ if (!isOk && pendingRemovalSet.has(u)) {
2048
+ pendingRemovalSet.delete(u);
2049
+ pendingRemovalChanged = true;
2050
+ const requiredType = neededTypes[typeIndex];
2051
+ isOk = canReuseContainer(u, requiredType);
1718
2052
  }
1719
2053
  if (isOk) {
1720
2054
  result.push(u);
@@ -1757,7 +2091,7 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1757
2091
  for (let i = 0; i < stillNeeded; i++) {
1758
2092
  result.push(numContainers + i);
1759
2093
  }
1760
- if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
2094
+ if (IS_DEV && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
1761
2095
  console.warn(
1762
2096
  "[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.",
1763
2097
  {
@@ -1772,6 +2106,12 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1772
2106
  }
1773
2107
  }
1774
2108
  }
2109
+ if (pendingRemovalChanged) {
2110
+ pendingRemoval.length = 0;
2111
+ for (const value of pendingRemovalSet) {
2112
+ pendingRemoval.push(value);
2113
+ }
2114
+ }
1775
2115
  return result.sort(comparatorDefault);
1776
2116
  }
1777
2117
  function comparatorByDistance(a, b) {
@@ -1828,72 +2168,16 @@ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, vie
1828
2168
  if (isLast && viewPosition === void 0) {
1829
2169
  viewPosition = 1;
1830
2170
  }
1831
- const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1832
2171
  state.scrollForNextCalculateItemsInView = void 0;
1833
- scrollTo(state, {
2172
+ scrollTo(ctx, state, {
1834
2173
  animated,
1835
2174
  index,
1836
- offset: firstIndexScrollPostion,
2175
+ offset: firstIndexOffset,
1837
2176
  viewOffset,
1838
2177
  viewPosition: viewPosition != null ? viewPosition : 0
1839
2178
  });
1840
2179
  }
1841
2180
 
1842
- // src/utils/checkThreshold.ts
1843
- var checkThreshold = (distance, atThreshold, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
1844
- const distanceAbs = Math.abs(distance);
1845
- const isAtThreshold = atThreshold || distanceAbs < threshold;
1846
- if (!isReached && !isBlockedByTimer) {
1847
- if (isAtThreshold) {
1848
- onReached == null ? void 0 : onReached(distance);
1849
- blockTimer == null ? void 0 : blockTimer(true);
1850
- setTimeout(() => {
1851
- blockTimer == null ? void 0 : blockTimer(false);
1852
- }, 700);
1853
- return true;
1854
- }
1855
- } else {
1856
- if (distance >= 1.3 * threshold) {
1857
- return false;
1858
- }
1859
- }
1860
- return isReached;
1861
- };
1862
-
1863
- // src/utils/checkAtBottom.ts
1864
- function checkAtBottom(ctx, state) {
1865
- if (!state) {
1866
- return;
1867
- }
1868
- const {
1869
- queuedInitialLayout,
1870
- scrollLength,
1871
- scroll,
1872
- maintainingScrollAtEnd,
1873
- props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1874
- } = state;
1875
- const contentSize = getContentSize(ctx);
1876
- if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1877
- const distanceFromEnd = contentSize - scroll - scrollLength;
1878
- const isContentLess = contentSize < scrollLength;
1879
- state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1880
- state.isEndReached = checkThreshold(
1881
- distanceFromEnd,
1882
- isContentLess,
1883
- onEndReachedThreshold * scrollLength,
1884
- state.isEndReached,
1885
- state.endReachedBlockedByTimer,
1886
- (distance) => {
1887
- var _a, _b;
1888
- return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
1889
- },
1890
- (block) => {
1891
- state.endReachedBlockedByTimer = block;
1892
- }
1893
- );
1894
- }
1895
- }
1896
-
1897
2181
  // src/utils/setDidLayout.ts
1898
2182
  function setDidLayout(ctx, state) {
1899
2183
  const {
@@ -1916,11 +2200,12 @@ function setDidLayout(ctx, state) {
1916
2200
 
1917
2201
  // src/core/calculateItemsInView.ts
1918
2202
  function findCurrentStickyIndex(stickyArray, scroll, state) {
1919
- var _a;
2203
+ var _a3;
1920
2204
  const idCache = state.idCache;
1921
2205
  const positions = state.positions;
1922
2206
  for (let i = stickyArray.length - 1; i >= 0; i--) {
1923
- const stickyId = (_a = idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
2207
+ const stickyIndex = stickyArray[i];
2208
+ const stickyId = (_a3 = idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
1924
2209
  const stickyPos = stickyId ? positions.get(stickyId) : void 0;
1925
2210
  if (stickyPos !== void 0 && scroll >= stickyPos) {
1926
2211
  return i;
@@ -1933,42 +2218,46 @@ function getActiveStickyIndices(ctx, state, stickyIndices) {
1933
2218
  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))
1934
2219
  );
1935
2220
  }
1936
- function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll, needNewContainers, startBuffered, endBuffered) {
1937
- var _a;
2221
+ function handleStickyActivation(ctx, state, stickyIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
2222
+ var _a3;
1938
2223
  const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
1939
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
2224
+ state.activeStickyIndex = currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : void 0;
1940
2225
  for (let offset = 0; offset <= 1; offset++) {
1941
2226
  const idx = currentStickyIdx - offset;
1942
2227
  if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
1943
2228
  const stickyIndex = stickyArray[idx];
1944
- const stickyId = (_a = state.idCache.get(stickyIndex)) != null ? _a : getId(state, stickyIndex);
2229
+ const stickyId = (_a3 = state.idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
1945
2230
  if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered)) {
1946
2231
  needNewContainers.push(stickyIndex);
1947
2232
  }
1948
2233
  }
1949
2234
  }
1950
- function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pendingRemoval) {
1951
- var _a, _b, _c;
1952
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
2235
+ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
2236
+ var _a3, _b, _c;
1953
2237
  for (const containerIndex of state.stickyContainerPool) {
1954
2238
  const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
1955
2239
  const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
1956
2240
  if (itemIndex === void 0) continue;
1957
2241
  const arrayIdx = stickyArray.indexOf(itemIndex);
1958
- if (arrayIdx === -1) continue;
2242
+ if (arrayIdx === -1) {
2243
+ state.stickyContainerPool.delete(containerIndex);
2244
+ set$(ctx, `containerSticky${containerIndex}`, false);
2245
+ set$(ctx, `containerStickyOffset${containerIndex}`, void 0);
2246
+ continue;
2247
+ }
1959
2248
  const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
1960
2249
  if (isRecentSticky) continue;
1961
2250
  const nextIndex = stickyArray[arrayIdx + 1];
1962
2251
  let shouldRecycle = false;
1963
2252
  if (nextIndex) {
1964
- const nextId = (_a = state.idCache.get(nextIndex)) != null ? _a : getId(state, nextIndex);
2253
+ const nextId = (_a3 = state.idCache[nextIndex]) != null ? _a3 : getId(state, nextIndex);
1965
2254
  const nextPos = nextId ? state.positions.get(nextId) : void 0;
1966
2255
  shouldRecycle = nextPos !== void 0 && scroll > nextPos + scrollBuffer * 2;
1967
2256
  } else {
1968
- const currentId = (_b = state.idCache.get(itemIndex)) != null ? _b : getId(state, itemIndex);
2257
+ const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
1969
2258
  if (currentId) {
1970
2259
  const currentPos = state.positions.get(currentId);
1971
- const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
2260
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, state, currentId, itemIndex, state.props.data[itemIndex]);
1972
2261
  shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
1973
2262
  }
1974
2263
  }
@@ -1979,7 +2268,7 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pe
1979
2268
  }
1980
2269
  function calculateItemsInView(ctx, state, params = {}) {
1981
2270
  reactDom.unstable_batchedUpdates(() => {
1982
- var _a, _b, _c, _d, _e, _f, _g, _h;
2271
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1983
2272
  const {
1984
2273
  columns,
1985
2274
  containerItemKeys,
@@ -1993,7 +2282,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1993
2282
  sizes,
1994
2283
  startBufferedId: startBufferedIdOrig,
1995
2284
  viewabilityConfigCallbackPairs,
1996
- props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, scrollBuffer }
2285
+ props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, onStickyHeaderChange, scrollBuffer }
1997
2286
  } = state;
1998
2287
  const { data } = state.props;
1999
2288
  const stickyIndicesArr = state.props.stickyIndicesArr || [];
@@ -2005,35 +2294,22 @@ function calculateItemsInView(ctx, state, params = {}) {
2005
2294
  const totalSize = peek$(ctx, "totalSize");
2006
2295
  const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
2007
2296
  const numColumns = peek$(ctx, "numColumns");
2008
- const previousScrollAdjust = 0;
2009
2297
  const { dataChanged, doMVCP } = params;
2010
2298
  const speed = getScrollVelocity(state);
2011
- if (doMVCP || dataChanged) {
2012
- const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
2013
- if (dataChanged) {
2014
- indexByKey.clear();
2015
- idCache.clear();
2016
- positions.clear();
2017
- }
2018
- const startIndex = dataChanged ? 0 : minIndexSizeChanged != null ? minIndexSizeChanged : 0;
2019
- updateAllPositions(ctx, state, dataChanged, startIndex);
2020
- if (minIndexSizeChanged !== void 0) {
2021
- state.minIndexSizeChanged = void 0;
2022
- }
2023
- checkMVCP == null ? void 0 : checkMVCP();
2024
- }
2025
2299
  const scrollExtra = 0;
2026
2300
  const { queuedInitialLayout } = state;
2027
2301
  let { scroll: scrollState } = state;
2028
2302
  if (!queuedInitialLayout && initialScroll) {
2029
2303
  const updatedOffset = calculateOffsetWithOffsetPosition(
2304
+ ctx,
2030
2305
  state,
2031
2306
  calculateOffsetForIndex(ctx, state, initialScroll.index),
2032
2307
  initialScroll
2033
2308
  );
2034
2309
  scrollState = updatedOffset;
2035
2310
  }
2036
- const scrollAdjustPad = -previousScrollAdjust - topPad;
2311
+ const scrollAdjustPending = (_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0;
2312
+ const scrollAdjustPad = scrollAdjustPending - topPad;
2037
2313
  let scroll = scrollState + scrollExtra + scrollAdjustPad;
2038
2314
  if (scroll + scrollLength > totalSize) {
2039
2315
  scroll = Math.max(0, totalSize - scrollLength);
@@ -2042,6 +2318,11 @@ function calculateItemsInView(ctx, state, params = {}) {
2042
2318
  set$(ctx, "debugRawScroll", scrollState);
2043
2319
  set$(ctx, "debugComputedScroll", scroll);
2044
2320
  }
2321
+ const previousStickyIndex = state.activeStickyIndex;
2322
+ const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
2323
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : void 0;
2324
+ state.activeStickyIndex = nextActiveStickyIndex;
2325
+ set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
2045
2326
  let scrollBufferTop = scrollBuffer;
2046
2327
  let scrollBufferBottom = scrollBuffer;
2047
2328
  if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
@@ -2054,22 +2335,34 @@ function calculateItemsInView(ctx, state, params = {}) {
2054
2335
  const scrollTopBuffered = scroll - scrollBufferTop;
2055
2336
  const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
2056
2337
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
2057
- if (scrollForNextCalculateItemsInView) {
2338
+ if (!dataChanged && scrollForNextCalculateItemsInView) {
2058
2339
  const { top, bottom } = scrollForNextCalculateItemsInView;
2059
2340
  if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
2060
2341
  return;
2061
2342
  }
2062
2343
  }
2344
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
2345
+ if (dataChanged) {
2346
+ indexByKey.clear();
2347
+ idCache.length = 0;
2348
+ positions.clear();
2349
+ }
2350
+ const startIndex = dataChanged ? 0 : (_b = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _b : 0;
2351
+ updateItemPositions(ctx, state, dataChanged, { scrollBottomBuffered, startIndex });
2352
+ if (minIndexSizeChanged !== void 0) {
2353
+ state.minIndexSizeChanged = void 0;
2354
+ }
2355
+ checkMVCP == null ? void 0 : checkMVCP();
2063
2356
  let startNoBuffer = null;
2064
2357
  let startBuffered = null;
2065
2358
  let startBufferedId = null;
2066
2359
  let endNoBuffer = null;
2067
2360
  let endBuffered = null;
2068
- let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2361
+ let loopStart = !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2069
2362
  for (let i = loopStart; i >= 0; i--) {
2070
- const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
2363
+ const id = (_c = idCache[i]) != null ? _c : getId(state, i);
2071
2364
  const top = positions.get(id);
2072
- const size = (_b = sizes.get(id)) != null ? _b : getItemSize(state, id, i, data[i]);
2365
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i]);
2073
2366
  const bottom = top + size;
2074
2367
  if (bottom > scroll - scrollBuffer) {
2075
2368
  loopStart = i;
@@ -2095,8 +2388,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2095
2388
  let firstFullyOnScreenIndex;
2096
2389
  const dataLength = data.length;
2097
2390
  for (let i = Math.max(0, loopStart); i < dataLength && (!foundEnd || i <= maxIndexRendered); i++) {
2098
- const id = (_c = idCache.get(i)) != null ? _c : getId(state, i);
2099
- const size = (_d = sizes.get(id)) != null ? _d : getItemSize(state, id, i, data[i]);
2391
+ const id = (_e = idCache[i]) != null ? _e : getId(state, i);
2392
+ const size = (_f = sizes.get(id)) != null ? _f : getItemSize(ctx, state, id, i, data[i]);
2100
2393
  const top = positions.get(id);
2101
2394
  if (!foundEnd) {
2102
2395
  if (startNoBuffer === null && top + size > scroll) {
@@ -2125,7 +2418,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2125
2418
  }
2126
2419
  const idsInView = [];
2127
2420
  for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
2128
- const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
2421
+ const id = (_g = idCache[i]) != null ? _g : getId(state, i);
2129
2422
  idsInView.push(id);
2130
2423
  }
2131
2424
  Object.assign(state, {
@@ -2157,7 +2450,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2157
2450
  let numContainers2 = prevNumContainers;
2158
2451
  const needNewContainers = [];
2159
2452
  for (let i = startBuffered; i <= endBuffered; i++) {
2160
- const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
2453
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
2161
2454
  if (!containerItemKeys.has(id)) {
2162
2455
  needNewContainers.push(i);
2163
2456
  }
@@ -2168,11 +2461,14 @@ function calculateItemsInView(ctx, state, params = {}) {
2168
2461
  state,
2169
2462
  stickyIndicesSet,
2170
2463
  stickyIndicesArr,
2171
- scroll,
2464
+ currentStickyIdx,
2172
2465
  needNewContainers,
2173
2466
  startBuffered,
2174
2467
  endBuffered
2175
2468
  );
2469
+ } else {
2470
+ state.activeStickyIndex = void 0;
2471
+ set$(ctx, "activeStickyIndex", void 0);
2176
2472
  }
2177
2473
  if (needNewContainers.length > 0) {
2178
2474
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
@@ -2192,7 +2488,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2192
2488
  for (let idx = 0; idx < needNewContainers.length; idx++) {
2193
2489
  const i = needNewContainers[idx];
2194
2490
  const containerIndex = availableContainers[idx];
2195
- const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
2491
+ const id = (_i = idCache[i]) != null ? _i : getId(state, i);
2196
2492
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
2197
2493
  if (oldKey && oldKey !== id) {
2198
2494
  containerItemKeys.delete(oldKey);
@@ -2206,9 +2502,10 @@ function calculateItemsInView(ctx, state, params = {}) {
2206
2502
  if (stickyIndicesSet.has(i)) {
2207
2503
  set$(ctx, `containerSticky${containerIndex}`, true);
2208
2504
  const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2209
- set$(ctx, `containerStickyOffset${containerIndex}`, createAnimatedValue(topPadding));
2505
+ set$(ctx, `containerStickyOffset${containerIndex}`, topPadding);
2210
2506
  state.stickyContainerPool.add(containerIndex);
2211
2507
  } else {
2508
+ set$(ctx, `containerSticky${containerIndex}`, false);
2212
2509
  state.stickyContainerPool.delete(containerIndex);
2213
2510
  }
2214
2511
  if (containerIndex >= numContainers2) {
@@ -2224,7 +2521,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2224
2521
  }
2225
2522
  }
2226
2523
  if (stickyIndicesArr.length > 0) {
2227
- handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, pendingRemoval);
2524
+ handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2228
2525
  }
2229
2526
  let didChangePositions = false;
2230
2527
  for (let i = 0; i < numContainers; i++) {
@@ -2247,11 +2544,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2247
2544
  const itemIndex = indexByKey.get(itemKey);
2248
2545
  const item = data[itemIndex];
2249
2546
  if (item !== void 0) {
2250
- const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
2251
- const position = positions.get(id);
2252
- if (position === void 0) {
2547
+ const id = (_j = idCache[itemIndex]) != null ? _j : getId(state, itemIndex);
2548
+ const positionValue = positions.get(id);
2549
+ if (positionValue === void 0) {
2253
2550
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2254
2551
  } else {
2552
+ const position = (positionValue || 0) - scrollAdjustPending;
2255
2553
  const column = columns.get(id) || 1;
2256
2554
  const prevPos = peek$(ctx, `containerPosition${i}`);
2257
2555
  const prevColumn = peek$(ctx, `containerColumn${i}`);
@@ -2264,7 +2562,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2264
2562
  set$(ctx, `containerColumn${i}`, column);
2265
2563
  }
2266
2564
  if (prevData !== item && (itemsAreEqual ? !itemsAreEqual(prevData, item, itemIndex, data) : true)) {
2267
- set$(ctx, `containerItemData${i}`, data[itemIndex]);
2565
+ set$(ctx, `containerItemData${i}`, item);
2268
2566
  }
2269
2567
  }
2270
2568
  }
@@ -2281,12 +2579,122 @@ function calculateItemsInView(ctx, state, params = {}) {
2281
2579
  if (viewabilityConfigCallbackPairs) {
2282
2580
  updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
2283
2581
  }
2582
+ if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
2583
+ const item = data[nextActiveStickyIndex];
2584
+ if (item !== void 0) {
2585
+ onStickyHeaderChange({ index: nextActiveStickyIndex, item });
2586
+ }
2587
+ }
2284
2588
  });
2285
2589
  }
2286
2590
 
2591
+ // src/core/doMaintainScrollAtEnd.ts
2592
+ function doMaintainScrollAtEnd(ctx, state, animated) {
2593
+ const {
2594
+ refScroller,
2595
+ props: { maintainScrollAtEnd }
2596
+ } = state;
2597
+ if ((state == null ? void 0 : state.isAtEnd) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
2598
+ const paddingTop = peek$(ctx, "alignItemsPaddingTop");
2599
+ if (paddingTop > 0) {
2600
+ state.scroll = 0;
2601
+ }
2602
+ requestAnimationFrame(() => {
2603
+ var _a3;
2604
+ if (state == null ? void 0 : state.isAtEnd) {
2605
+ state.maintainingScrollAtEnd = true;
2606
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
2607
+ animated
2608
+ });
2609
+ setTimeout(
2610
+ () => {
2611
+ state.maintainingScrollAtEnd = false;
2612
+ },
2613
+ 0
2614
+ );
2615
+ }
2616
+ });
2617
+ return true;
2618
+ }
2619
+ }
2620
+
2621
+ // src/utils/updateAveragesOnDataChange.ts
2622
+ function updateAveragesOnDataChange(state, oldData, newData) {
2623
+ var _a3;
2624
+ const {
2625
+ averageSizes,
2626
+ sizesKnown,
2627
+ indexByKey,
2628
+ props: { itemsAreEqual, getItemType, keyExtractor }
2629
+ } = state;
2630
+ if (!itemsAreEqual || !oldData.length || !newData.length) {
2631
+ for (const key in averageSizes) {
2632
+ delete averageSizes[key];
2633
+ }
2634
+ return;
2635
+ }
2636
+ const itemTypesToPreserve = {};
2637
+ const newDataLength = newData.length;
2638
+ const oldDataLength = oldData.length;
2639
+ for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
2640
+ const newItem = newData[newIndex];
2641
+ const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
2642
+ const oldIndex = indexByKey.get(id);
2643
+ if (oldIndex !== void 0 && oldIndex < oldDataLength) {
2644
+ const knownSize = sizesKnown.get(id);
2645
+ if (knownSize === void 0) continue;
2646
+ const oldItem = oldData[oldIndex];
2647
+ const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
2648
+ if (areEqual) {
2649
+ const itemType = getItemType ? (_a3 = getItemType(newItem, newIndex)) != null ? _a3 : "" : "";
2650
+ let typeData = itemTypesToPreserve[itemType];
2651
+ if (!typeData) {
2652
+ typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
2653
+ }
2654
+ typeData.totalSize += knownSize;
2655
+ typeData.count++;
2656
+ }
2657
+ }
2658
+ }
2659
+ for (const key in averageSizes) {
2660
+ delete averageSizes[key];
2661
+ }
2662
+ for (const itemType in itemTypesToPreserve) {
2663
+ const { totalSize, count } = itemTypesToPreserve[itemType];
2664
+ if (count > 0) {
2665
+ averageSizes[itemType] = {
2666
+ avg: totalSize / count,
2667
+ num: count
2668
+ };
2669
+ }
2670
+ }
2671
+ }
2672
+
2673
+ // src/core/checkResetContainers.ts
2674
+ function checkResetContainers(ctx, state, isFirst, dataProp) {
2675
+ if (state) {
2676
+ if (!isFirst && state.props.data !== dataProp) {
2677
+ updateAveragesOnDataChange(state, state.props.data, dataProp);
2678
+ }
2679
+ const { maintainScrollAtEnd } = state.props;
2680
+ if (!isFirst) {
2681
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2682
+ const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
2683
+ const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state, false);
2684
+ if (!didMaintainScrollAtEnd && dataProp.length > state.props.data.length) {
2685
+ state.isEndReached = false;
2686
+ }
2687
+ if (!didMaintainScrollAtEnd) {
2688
+ checkAtTop(state);
2689
+ checkAtBottom(ctx, state);
2690
+ }
2691
+ }
2692
+ }
2693
+ }
2694
+
2287
2695
  // src/core/doInitialAllocateContainers.ts
2288
2696
  function doInitialAllocateContainers(ctx, state) {
2289
- var _a;
2697
+ var _a3, _b, _c;
2290
2698
  const {
2291
2699
  scrollLength,
2292
2700
  props: {
@@ -2302,12 +2710,13 @@ function doInitialAllocateContainers(ctx, state) {
2302
2710
  const hasContainers = peek$(ctx, "numContainers");
2303
2711
  if (scrollLength > 0 && data.length > 0 && !hasContainers) {
2304
2712
  let averageItemSize;
2305
- const fn = getFixedItemSize || getEstimatedItemSize;
2306
- if (fn) {
2713
+ if (getFixedItemSize || getEstimatedItemSize) {
2307
2714
  let totalSize = 0;
2308
2715
  const num = Math.min(20, data.length);
2309
2716
  for (let i = 0; i < num; i++) {
2310
- totalSize += fn(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "");
2717
+ const item = data[i];
2718
+ const itemType = getItemType ? (_a3 = getItemType(item, i)) != null ? _a3 : "" : "";
2719
+ totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(i, item, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(i, item, itemType)) != null ? _c : estimatedItemSize;
2311
2720
  }
2312
2721
  averageItemSize = totalSize / num;
2313
2722
  } else {
@@ -2323,74 +2732,16 @@ function doInitialAllocateContainers(ctx, state) {
2323
2732
  if (state.lastLayout) {
2324
2733
  if (state.props.initialScroll) {
2325
2734
  requestAnimationFrame(() => {
2326
- calculateItemsInView(ctx, state, { dataChanged: true });
2735
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2327
2736
  });
2328
2737
  } else {
2329
- calculateItemsInView(ctx, state, { dataChanged: true });
2738
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2330
2739
  }
2331
2740
  }
2332
2741
  return true;
2333
2742
  }
2334
2743
  }
2335
2744
 
2336
- // src/core/doMaintainScrollAtEnd.ts
2337
- function doMaintainScrollAtEnd(ctx, state, animated) {
2338
- const {
2339
- refScroller,
2340
- props: { maintainScrollAtEnd }
2341
- } = state;
2342
- if ((state == null ? void 0 : state.isAtEnd) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
2343
- const paddingTop = peek$(ctx, "alignItemsPaddingTop");
2344
- if (paddingTop > 0) {
2345
- state.scroll = 0;
2346
- }
2347
- requestAnimationFrame(() => {
2348
- var _a;
2349
- if (state == null ? void 0 : state.isAtEnd) {
2350
- state.maintainingScrollAtEnd = true;
2351
- (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
2352
- animated
2353
- });
2354
- setTimeout(
2355
- () => {
2356
- state.maintainingScrollAtEnd = false;
2357
- },
2358
- 0
2359
- );
2360
- }
2361
- });
2362
- return true;
2363
- }
2364
- }
2365
-
2366
- // src/utils/checkAtTop.ts
2367
- function checkAtTop(state) {
2368
- if (!state) {
2369
- return;
2370
- }
2371
- const {
2372
- scrollLength,
2373
- scroll,
2374
- props: { onStartReachedThreshold }
2375
- } = state;
2376
- const distanceFromTop = scroll;
2377
- state.isAtStart = distanceFromTop <= 0;
2378
- state.isStartReached = checkThreshold(
2379
- distanceFromTop,
2380
- false,
2381
- onStartReachedThreshold * scrollLength,
2382
- state.isStartReached,
2383
- state.startReachedBlockedByTimer,
2384
- (distance) => {
2385
- var _a, _b;
2386
- return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
2387
- },
2388
- (block) => {
2389
- state.startReachedBlockedByTimer = block;
2390
- }
2391
- );
2392
- }
2393
-
2394
2745
  // src/core/handleLayout.ts
2395
2746
  function handleLayout(ctx, state, layout, setCanRender) {
2396
2747
  const { maintainScrollAtEnd } = state.props;
@@ -2425,87 +2776,55 @@ function handleLayout(ctx, state, layout, setCanRender) {
2425
2776
  if (state) {
2426
2777
  state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2427
2778
  }
2428
- if (__DEV__ && measuredLength === 0) {
2779
+ if (IS_DEV && measuredLength === 0) {
2429
2780
  warnDevOnce(
2430
2781
  "height0",
2431
2782
  `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.`
2432
2783
  );
2433
2784
  }
2434
- setCanRender(true);
2435
- }
2436
- }
2437
-
2438
- // src/core/onScroll.ts
2439
- function onScroll(ctx, state, event) {
2440
- var _a, _b, _c;
2441
- const {
2442
- scrollProcessingEnabled,
2443
- props: { onScroll: onScrollProp }
2444
- } = state;
2445
- if (scrollProcessingEnabled === false) {
2446
- return;
2447
- }
2448
- 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) {
2449
- return;
2450
- }
2451
- const newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
2452
- const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
2453
- if (ignoreScrollFromMVCP && !state.scrollingTo) {
2454
- const { lt, gt } = ignoreScrollFromMVCP;
2455
- if (lt && newScroll < lt || gt && newScroll > gt) {
2456
- return;
2457
- }
2458
- }
2459
- state.scrollPending = newScroll;
2460
- {
2461
- if (!state.onScrollRafScheduled) {
2462
- state.onScrollRafScheduled = true;
2463
- requestAnimationFrame(() => {
2464
- state.onScrollRafScheduled = false;
2465
- updateScroll(ctx, state, newScroll);
2466
- });
2467
- }
2468
- }
2469
- onScrollProp == null ? void 0 : onScrollProp(event);
2470
- }
2471
- function updateScroll(ctx, state, newScroll) {
2472
- const scrollingTo = state.scrollingTo;
2473
- state.hasScrolled = true;
2474
- state.lastBatchingAction = Date.now();
2475
- const currentTime = Date.now();
2476
- if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
2477
- const adjust = state.scrollAdjustHandler.getAdjust();
2478
- state.scrollHistory.push({ scroll: newScroll - adjust, time: currentTime });
2479
- }
2480
- if (state.scrollHistory.length > 5) {
2481
- state.scrollHistory.shift();
2482
- }
2483
- state.scrollPrev = state.scroll;
2484
- state.scrollPrevTime = state.scrollTime;
2485
- state.scroll = newScroll;
2486
- state.scrollTime = currentTime;
2487
- if (Math.abs(state.scroll - state.scrollPrev) > 2) {
2488
- calculateItemsInView(ctx, state);
2489
- checkAtBottom(ctx, state);
2490
- checkAtTop(state);
2491
2785
  }
2786
+ setCanRender(true);
2492
2787
  }
2493
2788
 
2494
2789
  // src/core/ScrollAdjustHandler.ts
2495
2790
  var ScrollAdjustHandler = class {
2496
2791
  constructor(ctx) {
2497
2792
  this.appliedAdjust = 0;
2793
+ this.pendingAdjust = 0;
2498
2794
  this.mounted = false;
2499
2795
  this.context = ctx;
2796
+ {
2797
+ const commitPendingAdjust = () => {
2798
+ const state = this.context.internalState;
2799
+ const pending = this.pendingAdjust;
2800
+ this.pendingAdjust = 0;
2801
+ this.appliedAdjust += pending;
2802
+ state.scroll += pending;
2803
+ state.scrollForNextCalculateItemsInView = void 0;
2804
+ set$(this.context, "scrollAdjustPending", 0);
2805
+ set$(this.context, "scrollAdjust", this.appliedAdjust);
2806
+ calculateItemsInView(this.context, this.context.internalState);
2807
+ };
2808
+ listen$(this.context, "scrollingTo", (value) => {
2809
+ if (value === void 0) {
2810
+ commitPendingAdjust();
2811
+ }
2812
+ });
2813
+ }
2500
2814
  }
2501
2815
  requestAdjust(add) {
2502
- const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
2503
- this.appliedAdjust = add + oldAdjustTop;
2504
- const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
2505
- if (this.mounted) {
2506
- set();
2816
+ const scrollingTo = peek$(this.context, "scrollingTo");
2817
+ if ((scrollingTo == null ? void 0 : scrollingTo.animated) && !scrollingTo.isInitialScroll) {
2818
+ this.pendingAdjust += add;
2819
+ set$(this.context, "scrollAdjustPending", this.pendingAdjust);
2507
2820
  } else {
2508
- requestAnimationFrame(set);
2821
+ this.appliedAdjust += add;
2822
+ const setter = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
2823
+ if (this.mounted) {
2824
+ setter();
2825
+ } else {
2826
+ requestAnimationFrame(setter);
2827
+ }
2509
2828
  }
2510
2829
  }
2511
2830
  setMounted() {
@@ -2518,14 +2837,13 @@ var ScrollAdjustHandler = class {
2518
2837
 
2519
2838
  // src/core/updateItemSize.ts
2520
2839
  function updateItemSize(ctx, state, itemKey, sizeObj) {
2521
- var _a, _b;
2840
+ var _a3;
2522
2841
  const {
2523
2842
  sizesKnown,
2524
2843
  props: {
2525
2844
  getFixedItemSize,
2526
2845
  getItemType,
2527
2846
  horizontal,
2528
- maintainVisibleContentPosition,
2529
2847
  suggestEstimatedItemSize,
2530
2848
  onItemSizeChanged,
2531
2849
  data,
@@ -2533,17 +2851,17 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2533
2851
  }
2534
2852
  } = state;
2535
2853
  if (!data) return;
2854
+ const index = state.indexByKey.get(itemKey);
2536
2855
  if (getFixedItemSize) {
2537
- const index2 = state.indexByKey.get(itemKey);
2538
- if (index2 === void 0) {
2856
+ if (index === void 0) {
2539
2857
  return;
2540
2858
  }
2541
- const itemData = state.props.data[index2];
2859
+ const itemData = state.props.data[index];
2542
2860
  if (itemData === void 0) {
2543
2861
  return;
2544
2862
  }
2545
- const type = getItemType ? (_a = getItemType(itemData, index2)) != null ? _a : "" : "";
2546
- const size2 = getFixedItemSize(index2, itemData, type);
2863
+ const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
2864
+ const size2 = getFixedItemSize(index, itemData, type);
2547
2865
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
2548
2866
  return;
2549
2867
  }
@@ -2553,15 +2871,11 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2553
2871
  let shouldMaintainScrollAtEnd = false;
2554
2872
  let minIndexSizeChanged;
2555
2873
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2556
- const index = state.indexByKey.get(itemKey);
2557
2874
  const prevSizeKnown = state.sizesKnown.get(itemKey);
2558
- const diff = updateOneItemSize(state, itemKey, sizeObj);
2875
+ const diff = updateOneItemSize(ctx, state, itemKey, sizeObj);
2559
2876
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2560
2877
  if (diff !== 0) {
2561
2878
  minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
2562
- if (((_b = state.scrollingTo) == null ? void 0 : _b.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
2563
- requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
2564
- }
2565
2879
  const { startBuffered, endBuffered } = state;
2566
2880
  needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2567
2881
  if (!needsRecalculate) {
@@ -2580,6 +2894,7 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2580
2894
  if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
2581
2895
  shouldMaintainScrollAtEnd = true;
2582
2896
  }
2897
+ addTotalSize(ctx, state, itemKey, diff);
2583
2898
  onItemSizeChanged == null ? void 0 : onItemSizeChanged({
2584
2899
  index,
2585
2900
  itemData: state.props.data[index],
@@ -2591,13 +2906,13 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2591
2906
  if (minIndexSizeChanged !== void 0) {
2592
2907
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
2593
2908
  }
2594
- if (__DEV__ && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
2909
+ if (IS_DEV && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
2595
2910
  if (state.timeoutSizeMessage) clearTimeout(state.timeoutSizeMessage);
2596
2911
  state.timeoutSizeMessage = setTimeout(() => {
2597
- var _a2;
2912
+ var _a4;
2598
2913
  state.timeoutSizeMessage = void 0;
2599
2914
  const num = state.sizesKnown.size;
2600
- const avg = (_a2 = state.averageSizes[""]) == null ? void 0 : _a2.avg;
2915
+ const avg = (_a4 = state.averageSizes[""]) == null ? void 0 : _a4.avg;
2601
2916
  console.warn(
2602
2917
  `[legend-list] Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`
2603
2918
  );
@@ -2619,8 +2934,8 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2619
2934
  }
2620
2935
  }
2621
2936
  }
2622
- function updateOneItemSize(state, itemKey, sizeObj) {
2623
- var _a;
2937
+ function updateOneItemSize(ctx, state, itemKey, sizeObj) {
2938
+ var _a3;
2624
2939
  const {
2625
2940
  sizes,
2626
2941
  indexByKey,
@@ -2630,12 +2945,12 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2630
2945
  } = state;
2631
2946
  if (!data) return 0;
2632
2947
  const index = indexByKey.get(itemKey);
2633
- const prevSize = getItemSize(state, itemKey, index, data);
2948
+ const prevSize = getItemSize(ctx, state, itemKey, index, data[index]);
2634
2949
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
2635
2950
  const size = Math.round(rawSize) ;
2636
2951
  sizesKnown.set(itemKey, size);
2637
2952
  if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
2638
- const itemType = getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : "";
2953
+ const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
2639
2954
  let averages = averageSizes[itemType];
2640
2955
  if (!averages) {
2641
2956
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -2650,7 +2965,7 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2650
2965
  return 0;
2651
2966
  }
2652
2967
  var useCombinedRef = (...refs) => {
2653
- const callback = React4.useCallback((element) => {
2968
+ const callback = React3.useCallback((element) => {
2654
2969
  for (const ref of refs) {
2655
2970
  if (!ref) {
2656
2971
  continue;
@@ -2666,24 +2981,12 @@ var useCombinedRef = (...refs) => {
2666
2981
  };
2667
2982
 
2668
2983
  // src/platform/RefreshControl.tsx
2669
- function RefreshControl(props) {
2984
+ function RefreshControl(_props) {
2670
2985
  return null;
2671
2986
  }
2672
2987
 
2673
- // src/platform/StyleSheet.tsx
2674
- function flattenStyles(styles) {
2675
- if (Array.isArray(styles)) {
2676
- return Object.assign({}, ...styles.filter(Boolean));
2677
- }
2678
- return styles;
2679
- }
2680
- var StyleSheet = {
2681
- create: (styles) => styles,
2682
- flatten: (style) => flattenStyles(style)
2683
- };
2684
-
2685
2988
  // src/platform/useStickyScrollHandler.ts
2686
- function useStickyScrollHandler(stickyIndices, horizontal, ctx, onScroll2) {
2989
+ function useStickyScrollHandler(_stickyIndices, _horizontal, _ctx, onScroll2) {
2687
2990
  return onScroll2;
2688
2991
  }
2689
2992
 
@@ -2702,7 +3005,7 @@ function createColumnWrapperStyle(contentContainerStyle) {
2702
3005
  }
2703
3006
  }
2704
3007
  function getRenderedItem(ctx, state, key) {
2705
- var _a;
3008
+ var _a3;
2706
3009
  if (!state) {
2707
3010
  return null;
2708
3011
  }
@@ -2715,29 +3018,31 @@ function getRenderedItem(ctx, state, key) {
2715
3018
  return null;
2716
3019
  }
2717
3020
  let renderedItem = null;
2718
- if (renderItem && data[index]) {
3021
+ const extraData = peek$(ctx, "extraData");
3022
+ const item = data[index];
3023
+ if (renderItem && !isNullOrUndefined(item)) {
2719
3024
  const itemProps = {
2720
3025
  data,
2721
- extraData: peek$(ctx, "extraData"),
3026
+ extraData,
2722
3027
  index,
2723
- item: data[index],
2724
- type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
3028
+ item,
3029
+ type: getItemType ? (_a3 = getItemType(item, index)) != null ? _a3 : "" : ""
2725
3030
  };
2726
- renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React4__namespace.default.createElement(renderItem, itemProps);
3031
+ renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React3__namespace.default.createElement(renderItem, itemProps);
2727
3032
  }
2728
3033
  return { index, item: data[index], renderedItem };
2729
3034
  }
2730
3035
  function useThrottleDebounce(mode) {
2731
- const timeoutRef = React4.useRef(null);
2732
- const lastCallTimeRef = React4.useRef(0);
2733
- const lastArgsRef = React4.useRef(null);
3036
+ const timeoutRef = React3.useRef(null);
3037
+ const lastCallTimeRef = React3.useRef(0);
3038
+ const lastArgsRef = React3.useRef(null);
2734
3039
  const clearTimeoutRef = () => {
2735
3040
  if (timeoutRef.current) {
2736
3041
  clearTimeout(timeoutRef.current);
2737
3042
  timeoutRef.current = null;
2738
3043
  }
2739
3044
  };
2740
- const execute = React4.useCallback(
3045
+ const execute = React3.useCallback(
2741
3046
  (callback, delay, ...args) => {
2742
3047
  {
2743
3048
  const now = Date.now();
@@ -2773,58 +3078,6 @@ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
2773
3078
  return (event) => throttle(originalHandler, scrollEventThrottle, { nativeEvent: event.nativeEvent });
2774
3079
  }
2775
3080
 
2776
- // src/utils/updateAveragesOnDataChange.ts
2777
- function updateAveragesOnDataChange(state, oldData, newData) {
2778
- var _a;
2779
- const {
2780
- averageSizes,
2781
- sizesKnown,
2782
- indexByKey,
2783
- props: { itemsAreEqual, getItemType, keyExtractor }
2784
- } = state;
2785
- if (!itemsAreEqual || !oldData.length || !newData.length) {
2786
- for (const key in averageSizes) {
2787
- delete averageSizes[key];
2788
- }
2789
- return;
2790
- }
2791
- const itemTypesToPreserve = {};
2792
- const newDataLength = newData.length;
2793
- const oldDataLength = oldData.length;
2794
- for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
2795
- const newItem = newData[newIndex];
2796
- const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
2797
- const oldIndex = indexByKey.get(id);
2798
- if (oldIndex !== void 0 && oldIndex < oldDataLength) {
2799
- const knownSize = sizesKnown.get(id);
2800
- if (knownSize === void 0) continue;
2801
- const oldItem = oldData[oldIndex];
2802
- const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
2803
- if (areEqual) {
2804
- const itemType = getItemType ? (_a = getItemType(newItem, newIndex)) != null ? _a : "" : "";
2805
- let typeData = itemTypesToPreserve[itemType];
2806
- if (!typeData) {
2807
- typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
2808
- }
2809
- typeData.totalSize += knownSize;
2810
- typeData.count++;
2811
- }
2812
- }
2813
- }
2814
- for (const key in averageSizes) {
2815
- delete averageSizes[key];
2816
- }
2817
- for (const itemType in itemTypesToPreserve) {
2818
- const { totalSize, count } = itemTypesToPreserve[itemType];
2819
- if (count > 0) {
2820
- averageSizes[itemType] = {
2821
- avg: totalSize / count,
2822
- num: count
2823
- };
2824
- }
2825
- }
2826
- }
2827
-
2828
3081
  // src/components/LegendList.tsx
2829
3082
  var DEFAULT_DRAW_DISTANCE = 250;
2830
3083
  var DEFAULT_ITEM_SIZE = 100;
@@ -2834,17 +3087,18 @@ var LegendList = typedMemo(
2834
3087
  const isChildrenMode = children !== void 0 && dataProp === void 0;
2835
3088
  const processedProps = isChildrenMode ? {
2836
3089
  ...restProps,
2837
- data: (isArray(children) ? children : React4__namespace.Children.toArray(children)).flat(1),
3090
+ data: (isArray(children) ? children : React3__namespace.Children.toArray(children)).flat(1),
2838
3091
  renderItem: ({ item }) => item
2839
3092
  } : {
2840
3093
  ...restProps,
2841
3094
  data: dataProp || [],
2842
3095
  renderItem: renderItemProp
2843
3096
  };
2844
- return /* @__PURE__ */ React4__namespace.createElement(StateProvider, null, /* @__PURE__ */ React4__namespace.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
3097
+ return /* @__PURE__ */ React3__namespace.createElement(StateProvider, null, /* @__PURE__ */ React3__namespace.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
2845
3098
  })
2846
3099
  );
2847
3100
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
3101
+ var _a3;
2848
3102
  const {
2849
3103
  alignItemsAtEnd = false,
2850
3104
  columnWrapperStyle,
@@ -2880,6 +3134,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2880
3134
  onScroll: onScrollProp,
2881
3135
  onStartReached,
2882
3136
  onStartReachedThreshold = 0.5,
3137
+ onStickyHeaderChange,
3138
+ onViewableItemsChanged,
2883
3139
  progressViewOffset,
2884
3140
  recycleItems = false,
2885
3141
  refreshControl,
@@ -2891,24 +3147,26 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2891
3147
  stickyIndices,
2892
3148
  style: styleProp,
2893
3149
  suggestEstimatedItemSize,
3150
+ viewabilityConfig,
3151
+ viewabilityConfigCallbackPairs,
2894
3152
  waitForInitialLayout = true,
2895
3153
  ...rest
2896
3154
  } = props;
2897
- const [renderNum, setRenderNum] = React4.useState(0);
3155
+ const [renderNum, setRenderNum] = React3.useState(0);
2898
3156
  const initialScroll = initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
2899
- const [canRender, setCanRender] = React4__namespace.useState(!IsNewArchitecture);
3157
+ const [canRender, setCanRender] = React3__namespace.useState(!IsNewArchitecture);
2900
3158
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
2901
3159
  const style = { ...StyleSheet.flatten(styleProp) };
2902
3160
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
2903
3161
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
2904
3162
  const ctx = useStateContext();
2905
3163
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
2906
- const refScroller = React4.useRef(null);
3164
+ const refScroller = React3.useRef(null);
2907
3165
  const combinedRef = useCombinedRef(refScroller, refScrollView);
2908
3166
  const estimatedItemSize = estimatedItemSizeProp != null ? estimatedItemSizeProp : DEFAULT_ITEM_SIZE;
2909
3167
  const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
2910
3168
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
2911
- const refState = React4.useRef();
3169
+ const refState = React3.useRef();
2912
3170
  if (!refState.current) {
2913
3171
  if (!ctx.internalState) {
2914
3172
  const initialScrollLength = (estimatedListSize != null ? estimatedListSize : { height: 0, width: 0 } )[horizontal ? "width" : "height"];
@@ -2918,12 +3176,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2918
3176
  columns: /* @__PURE__ */ new Map(),
2919
3177
  containerItemKeys: /* @__PURE__ */ new Set(),
2920
3178
  containerItemTypes: /* @__PURE__ */ new Map(),
3179
+ dataChangeNeedsScrollUpdate: false,
2921
3180
  enableScrollForNextCalculateItemsInView: true,
2922
3181
  endBuffered: -1,
2923
3182
  endNoBuffer: -1,
2924
- endReachedBlockedByTimer: false,
3183
+ endReachedSnapshot: void 0,
2925
3184
  firstFullyOnScreenIndex: -1,
2926
- idCache: /* @__PURE__ */ new Map(),
3185
+ idCache: [],
2927
3186
  idsInView: [],
2928
3187
  indexByKey: /* @__PURE__ */ new Map(),
2929
3188
  initialScroll,
@@ -2954,7 +3213,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2954
3213
  sizesKnown: /* @__PURE__ */ new Map(),
2955
3214
  startBuffered: -1,
2956
3215
  startNoBuffer: -1,
2957
- startReachedBlockedByTimer: false,
3216
+ startReachedSnapshot: void 0,
2958
3217
  stickyContainerPool: /* @__PURE__ */ new Set(),
2959
3218
  stickyContainers: /* @__PURE__ */ new Map(),
2960
3219
  timeoutSizeMessage: 0,
@@ -2970,10 +3229,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2970
3229
  const state = refState.current;
2971
3230
  const isFirst = !state.props.renderItem;
2972
3231
  const didDataChange = state.props.data !== dataProp;
2973
- const throttleScrollFn = (
2974
- // @ts-expect-error TODO Fix this
2975
- scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp
2976
- );
3232
+ if (didDataChange) {
3233
+ state.dataChangeNeedsScrollUpdate = true;
3234
+ }
3235
+ const throttleScrollFn = scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp;
2977
3236
  state.props = {
2978
3237
  alignItemsAtEnd,
2979
3238
  data: dataProp,
@@ -2998,39 +3257,19 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2998
3257
  onScroll: throttleScrollFn,
2999
3258
  onStartReached,
3000
3259
  onStartReachedThreshold,
3260
+ onStickyHeaderChange,
3001
3261
  recycleItems: !!recycleItems,
3002
3262
  renderItem,
3003
3263
  scrollBuffer,
3004
3264
  snapToIndices,
3005
3265
  stickyIndicesArr: stickyIndices != null ? stickyIndices : [],
3006
- stickyIndicesSet: React4.useMemo(() => new Set(stickyIndices != null ? stickyIndices : []), [stickyIndices == null ? void 0 : stickyIndices.join(",")]),
3266
+ stickyIndicesSet: React3.useMemo(() => new Set(stickyIndices != null ? stickyIndices : []), [stickyIndices == null ? void 0 : stickyIndices.join(",")]),
3007
3267
  stylePaddingBottom: stylePaddingBottomState,
3008
3268
  stylePaddingTop: stylePaddingTopState,
3009
3269
  suggestEstimatedItemSize: !!suggestEstimatedItemSize
3010
3270
  };
3011
3271
  state.refScroller = refScroller;
3012
- const checkResetContainers = (isFirst2) => {
3013
- const state2 = refState.current;
3014
- if (state2) {
3015
- if (!isFirst2 && state2.props.data !== dataProp) {
3016
- updateAveragesOnDataChange(state2, state2.props.data, dataProp);
3017
- }
3018
- state2.props.data = dataProp;
3019
- if (!isFirst2) {
3020
- calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
3021
- const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
3022
- const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state2, false);
3023
- if (!didMaintainScrollAtEnd && dataProp.length > state2.props.data.length) {
3024
- state2.isEndReached = false;
3025
- }
3026
- if (!didMaintainScrollAtEnd) {
3027
- checkAtTop(state2);
3028
- checkAtBottom(ctx, state2);
3029
- }
3030
- }
3031
- }
3032
- };
3033
- const memoizedLastItemKeys = React4.useMemo(() => {
3272
+ const memoizedLastItemKeys = React3.useMemo(() => {
3034
3273
  if (!dataProp.length) return [];
3035
3274
  return Array.from(
3036
3275
  { length: Math.min(numColumnsProp, dataProp.length) },
@@ -3053,9 +3292,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3053
3292
  };
3054
3293
  if (isFirst) {
3055
3294
  initializeStateVars();
3056
- updateAllPositions(ctx, state);
3295
+ updateItemPositions(
3296
+ ctx,
3297
+ state,
3298
+ /*dataChanged*/
3299
+ true
3300
+ );
3057
3301
  }
3058
- const initialContentOffset = React4.useMemo(() => {
3302
+ const initialContentOffset = React3.useMemo(() => {
3059
3303
  if (initialScroll) {
3060
3304
  const { index, viewOffset } = initialScroll;
3061
3305
  let initialContentOffset2 = viewOffset || 0;
@@ -3064,24 +3308,30 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3064
3308
  }
3065
3309
  refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
3066
3310
  if (initialContentOffset2 > 0) {
3067
- scrollTo(state, { animated: false, index, offset: initialContentOffset2 });
3311
+ scrollTo(ctx, state, {
3312
+ animated: false,
3313
+ index,
3314
+ isInitialScroll: true,
3315
+ offset: initialContentOffset2,
3316
+ viewPosition: index === dataProp.length - 1 ? 1 : 0
3317
+ });
3068
3318
  }
3069
3319
  return initialContentOffset2;
3070
3320
  }
3071
3321
  return 0;
3072
3322
  }, [renderNum]);
3073
3323
  if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
3074
- state.lastBatchingAction = Date.now();
3324
+ refState.current.lastBatchingAction = Date.now();
3075
3325
  if (!keyExtractorProp && !isFirst && didDataChange) {
3076
- __DEV__ && warnDevOnce(
3326
+ IS_DEV && warnDevOnce(
3077
3327
  "keyExtractor",
3078
3328
  "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."
3079
3329
  );
3080
- state.sizes.clear();
3081
- state.positions.clear();
3330
+ refState.current.sizes.clear();
3331
+ refState.current.positions.clear();
3082
3332
  }
3083
3333
  }
3084
- const onLayoutHeader = React4.useCallback((rect, fromLayoutEffect) => {
3334
+ const onLayoutHeader = React3.useCallback((rect, fromLayoutEffect) => {
3085
3335
  const size = rect[horizontal ? "width" : "height"];
3086
3336
  set$(ctx, "headerSize", size);
3087
3337
  if ((initialScroll == null ? void 0 : initialScroll.index) !== void 0) {
@@ -3092,43 +3342,51 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3092
3342
  }
3093
3343
  }
3094
3344
  }, []);
3095
- React4.useLayoutEffect(() => {
3345
+ React3.useLayoutEffect(() => {
3096
3346
  if (snapToIndices) {
3097
3347
  updateSnapToOffsets(ctx, state);
3098
3348
  }
3099
3349
  }, [snapToIndices]);
3100
- React4.useLayoutEffect(() => {
3101
- const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainersCallback();
3350
+ React3.useLayoutEffect(() => {
3351
+ const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainers(ctx, state);
3102
3352
  if (!didAllocateContainers) {
3103
3353
  checkResetContainers(
3354
+ ctx,
3355
+ state,
3104
3356
  /*isFirst*/
3105
- isFirst
3357
+ isFirst,
3358
+ dataProp
3106
3359
  );
3107
3360
  }
3108
3361
  }, [dataProp, numColumnsProp]);
3109
- React4.useLayoutEffect(() => {
3362
+ React3.useLayoutEffect(() => {
3110
3363
  set$(ctx, "extraData", extraData);
3111
3364
  }, [extraData]);
3112
- const { onLayout } = useSyncLayout({
3113
- onLayout: onLayoutProp,
3114
- onLayoutChange: React4.useCallback(
3115
- (rectangle) => {
3116
- handleLayout(ctx, state, rectangle, setCanRender);
3117
- },
3118
- [ctx, state, setCanRender]
3119
- ),
3120
- ref: refScroller
3121
- });
3122
- React4.useLayoutEffect(initializeStateVars, [
3365
+ React3.useLayoutEffect(initializeStateVars, [
3123
3366
  memoizedLastItemKeys.join(","),
3124
3367
  numColumnsProp,
3125
3368
  stylePaddingTopState,
3126
3369
  stylePaddingBottomState
3127
3370
  ]);
3128
- const doInitialAllocateContainersCallback = () => {
3129
- return doInitialAllocateContainers(ctx, state);
3130
- };
3131
- React4.useImperativeHandle(forwardedRef, () => {
3371
+ React3.useEffect(() => {
3372
+ const viewability = setupViewability({
3373
+ onViewableItemsChanged,
3374
+ viewabilityConfig,
3375
+ viewabilityConfigCallbackPairs
3376
+ });
3377
+ state.viewabilityConfigCallbackPairs = viewability;
3378
+ state.enableScrollForNextCalculateItemsInView = !viewability;
3379
+ }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
3380
+ const onLayoutChange = React3.useCallback((layout) => {
3381
+ handleLayout(ctx, state, layout, setCanRender);
3382
+ }, []);
3383
+ const { onLayout } = useOnLayoutSync({
3384
+ onLayoutChange,
3385
+ onLayoutProp,
3386
+ ref: refScroller
3387
+ // the type of ScrollView doesn't include measure?
3388
+ });
3389
+ React3.useImperativeHandle(forwardedRef, () => {
3132
3390
  const scrollIndexIntoView = (options) => {
3133
3391
  const state2 = refState.current;
3134
3392
  if (state2) {
@@ -3145,16 +3403,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3145
3403
  }
3146
3404
  };
3147
3405
  return {
3148
- flashScrollIndicators: () => {
3149
- var _a, _b;
3150
- return (_b = (_a = refScroller.current) == null ? void 0 : _a.flashScrollIndicators) == null ? void 0 : _b.call(_a);
3151
- },
3406
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
3152
3407
  getNativeScrollRef: () => refScroller.current,
3153
- getScrollableNode: () => refScroller.current,
3154
- getScrollResponder: () => refScroller.current,
3408
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
3409
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
3155
3410
  getState: () => {
3156
3411
  const state2 = refState.current;
3157
3412
  return state2 ? {
3413
+ activeStickyIndex: state2.activeStickyIndex,
3158
3414
  contentLength: state2.totalSize,
3159
3415
  data: state2.props.data,
3160
3416
  end: state2.endNoBuffer,
@@ -3202,7 +3458,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3202
3458
  scrollToIndex(ctx, state, { index, ...props2 });
3203
3459
  }
3204
3460
  },
3205
- scrollToOffset: (params) => scrollTo(state, params),
3461
+ scrollToOffset: (params) => scrollTo(ctx, state, params),
3206
3462
  setScrollProcessingEnabled: (enabled) => {
3207
3463
  refState.current.scrollProcessingEnabled = enabled;
3208
3464
  },
@@ -3213,13 +3469,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3213
3469
  };
3214
3470
  }, []);
3215
3471
  {
3216
- React4.useEffect(() => {
3472
+ React3.useEffect(() => {
3217
3473
  if (initialContentOffset) {
3218
- scrollTo(state, { animated: false, offset: initialContentOffset });
3474
+ scrollTo(ctx, state, { animated: false, offset: initialContentOffset, ...initialScroll || {} });
3219
3475
  }
3220
3476
  }, []);
3221
3477
  }
3222
- const fns = React4.useMemo(
3478
+ const fns = React3.useMemo(
3223
3479
  () => ({
3224
3480
  getRenderedItem: (key) => getRenderedItem(ctx, state, key),
3225
3481
  onScroll: (event) => onScroll(ctx, state, event),
@@ -3228,7 +3484,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3228
3484
  []
3229
3485
  );
3230
3486
  const onScrollHandler = useStickyScrollHandler(stickyIndices, horizontal, ctx, fns.onScroll);
3231
- return /* @__PURE__ */ React4__namespace.createElement(React4__namespace.Fragment, null, /* @__PURE__ */ React4__namespace.createElement(
3487
+ return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement(
3232
3488
  ListComponent,
3233
3489
  {
3234
3490
  ...rest,
@@ -3246,7 +3502,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3246
3502
  onMomentumScrollEnd: (event) => {
3247
3503
  {
3248
3504
  requestAnimationFrame(() => {
3249
- finishScrollTo(refState.current);
3505
+ finishScrollTo(ctx, refState.current);
3250
3506
  });
3251
3507
  }
3252
3508
  if (onMomentumScrollEnd) {
@@ -3255,9 +3511,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3255
3511
  },
3256
3512
  onScroll: onScrollHandler,
3257
3513
  recycleItems,
3258
- refreshControl: refreshControl ? stylePaddingTopState > 0 ? React4__namespace.cloneElement(refreshControl, {
3514
+ refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
3259
3515
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
3260
- }) : refreshControl : onRefresh && /* @__PURE__ */ React4__namespace.createElement(
3516
+ }) : refreshControl : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
3261
3517
  RefreshControl,
3262
3518
  {
3263
3519
  onRefresh,
@@ -3266,14 +3522,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3266
3522
  }
3267
3523
  ),
3268
3524
  refScrollView: combinedRef,
3269
- scrollAdjustHandler: state.scrollAdjustHandler,
3525
+ scrollAdjustHandler: (_a3 = refState.current) == null ? void 0 : _a3.scrollAdjustHandler,
3526
+ scrollEventThrottle: 16 ,
3270
3527
  snapToIndices,
3271
3528
  stickyIndices,
3272
3529
  style,
3273
3530
  updateItemSize: fns.updateItemSize,
3274
3531
  waitForInitialLayout
3275
3532
  }
3276
- ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React4__namespace.createElement(DebugView, { state: refState.current }));
3533
+ ), IS_DEV && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3__namespace.createElement(DebugView, { state: refState.current }));
3277
3534
  });
3278
3535
 
3279
3536
  exports.LegendList = LegendList;
@@ -3281,6 +3538,6 @@ exports.useIsLastItem = useIsLastItem;
3281
3538
  exports.useListScrollSize = useListScrollSize;
3282
3539
  exports.useRecyclingEffect = useRecyclingEffect;
3283
3540
  exports.useRecyclingState = useRecyclingState;
3284
- exports.useSyncLayout = useSyncLayout2;
3541
+ exports.useSyncLayout = useSyncLayout;
3285
3542
  exports.useViewability = useViewability;
3286
3543
  exports.useViewabilityAmount = useViewabilityAmount;