@legendapp/list 2.1.0-next.1 → 3.0.0-beta.1

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 = [];
@@ -123,31 +126,33 @@ function set$(ctx, signalName, value) {
123
126
  }
124
127
  }
125
128
  function getContentSize(ctx) {
126
- const { values } = ctx;
129
+ var _a3, _b;
130
+ const { values, internalState } = ctx;
127
131
  const stylePaddingTop = values.get("stylePaddingTop") || 0;
132
+ const stylePaddingBottom = (internalState == null ? void 0 : internalState.props.stylePaddingBottom) || 0;
128
133
  const headerSize = values.get("headerSize") || 0;
129
134
  const footerSize = values.get("footerSize") || 0;
130
- const totalSize = values.get("totalSize");
131
- return headerSize + footerSize + totalSize + stylePaddingTop;
135
+ const totalSize = (_b = (_a3 = ctx.internalState) == null ? void 0 : _a3.pendingTotalSize) != null ? _b : values.get("totalSize");
136
+ return headerSize + footerSize + totalSize + stylePaddingTop + stylePaddingBottom;
132
137
  }
133
138
  function useArr$(signalNames) {
134
- const ctx = React4__namespace.useContext(ContextState);
135
- const { subscribe, get } = React4__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
139
+ const ctx = React3__namespace.useContext(ContextState);
140
+ const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
136
141
  const value = shim.useSyncExternalStore(subscribe, get);
137
142
  return value;
138
143
  }
139
144
  function useSelector$(signalName, selector) {
140
- const ctx = React4__namespace.useContext(ContextState);
141
- const { subscribe, get } = React4__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
145
+ const ctx = React3__namespace.useContext(ContextState);
146
+ const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
142
147
  const value = shim.useSyncExternalStore(subscribe, () => selector(get()[0]));
143
148
  return value;
144
149
  }
145
150
 
146
151
  // src/components/DebugView.tsx
147
152
  var DebugRow = ({ children }) => {
148
- return /* @__PURE__ */ React4__namespace.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
153
+ return /* @__PURE__ */ React3__namespace.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
149
154
  };
150
- var DebugView = React4__namespace.memo(function DebugView2({ state }) {
155
+ var DebugView = React3__namespace.memo(function DebugView2({ state }) {
151
156
  const ctx = useStateContext();
152
157
  const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
153
158
  "totalSize",
@@ -158,11 +163,11 @@ var DebugView = React4__namespace.memo(function DebugView2({ state }) {
158
163
  "numContainersPooled"
159
164
  ]);
160
165
  const contentSize = getContentSize(ctx);
161
- const [, forceUpdate] = React4.useReducer((x) => x + 1, 0);
166
+ const [, forceUpdate] = React3.useReducer((x) => x + 1, 0);
162
167
  useInterval(() => {
163
168
  forceUpdate();
164
169
  }, 100);
165
- return /* @__PURE__ */ React4__namespace.createElement(
170
+ return /* @__PURE__ */ React3__namespace.createElement(
166
171
  View,
167
172
  {
168
173
  pointerEvents: "none",
@@ -178,107 +183,77 @@ var DebugView = React4__namespace.memo(function DebugView2({ state }) {
178
183
  top: 0
179
184
  }
180
185
  },
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)))
186
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, totalSize.toFixed(2))),
187
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, contentSize.toFixed(2))),
188
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "At end:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, String(state.isAtEnd))),
189
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, scrollAdjust.toFixed(2))),
190
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React3__namespace.createElement(Text, null, rawScroll.toFixed(2))),
191
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React3__namespace.createElement(Text, null, scroll.toFixed(2)))
187
192
  );
188
193
  });
189
194
  function useInterval(callback, delay) {
190
- React4.useEffect(() => {
195
+ React3.useEffect(() => {
191
196
  const interval = setInterval(callback, delay);
192
197
  return () => clearInterval(interval);
193
198
  }, [delay]);
194
199
  }
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
- });
200
+
201
+ // src/utils/devEnvironment.ts
202
+ var metroDev = typeof __DEV__ !== "undefined" ? __DEV__ : void 0;
203
+ var _a;
204
+ var envMode = typeof process !== "undefined" && typeof process.env === "object" && process.env ? (_a = process.env.NODE_ENV) != null ? _a : process.env.MODE : void 0;
205
+ var processDev = typeof envMode === "string" ? envMode.toLowerCase() !== "production" : void 0;
206
+ var _a2;
207
+ var IS_DEV = (_a2 = metroDev != null ? metroDev : processDev) != null ? _a2 : false;
208
+
209
+ // src/constants.ts
210
+ var POSITION_OUT_OF_VIEW = -1e7;
211
+ var ENABLE_DEVMODE = IS_DEV && false;
212
+ var ENABLE_DEBUG_VIEW = IS_DEV && false;
213
+ var typedForwardRef = React3.forwardRef;
214
+ var typedMemo = React3.memo;
215
+
216
+ // src/utils/helpers.ts
217
+ function isFunction(obj) {
218
+ return typeof obj === "function";
219
+ }
220
+ function isArray(obj) {
221
+ return Array.isArray(obj);
222
+ }
223
+ var warned = /* @__PURE__ */ new Set();
224
+ function warnDevOnce(id, text) {
225
+ if (IS_DEV && !warned.has(id)) {
226
+ warned.add(id);
227
+ console.warn(`[legend-list] ${text}`);
208
228
  }
209
- return globalResizeObserver;
210
229
  }
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]);
230
+ function roundSize(size) {
231
+ return Math.floor(size * 8) / 8;
234
232
  }
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
- );
233
+ function isNullOrUndefined(value) {
234
+ return value === null || value === void 0;
235
+ }
236
+ function comparatorDefault(a, b) {
237
+ return a - b;
238
+ }
239
+ function getPadding(s, type) {
240
+ var _a3, _b, _c;
241
+ return (_c = (_b = (_a3 = s[`padding${type}`]) != null ? _a3 : s.paddingVertical) != null ? _b : s.padding) != null ? _c : 0;
242
+ }
243
+ function extractPadding(style, contentContainerStyle, type) {
244
+ return getPadding(style, type) + getPadding(contentContainerStyle, type);
245
+ }
246
+ function findContainerId(ctx, key) {
247
+ const numContainers = peek$(ctx, "numContainers");
248
+ for (let i = 0; i < numContainers; i++) {
249
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
250
+ if (itemKey === key) {
251
+ return i;
263
252
  }
264
- }, []);
265
- return {};
253
+ }
254
+ return -1;
266
255
  }
267
256
 
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
- };
274
-
275
- // src/constants.ts
276
- 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;
281
-
282
257
  // src/components/PositionView.tsx
283
258
  var PositionViewState = typedMemo(function PositionView({
284
259
  id,
@@ -288,9 +263,12 @@ var PositionViewState = typedMemo(function PositionView({
288
263
  ...rest
289
264
  }) {
290
265
  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 });
266
+ const base = {
267
+ contain: "paint layout style"
268
+ };
269
+ const composed = isArray(style) ? Object.assign({}, ...style) : style;
270
+ const combinedStyle = horizontal ? { ...base, ...composed, left: position } : { ...base, ...composed, top: position };
271
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: combinedStyle, ...rest });
294
272
  });
295
273
  var PositionViewSticky = typedMemo(function PositionViewSticky2({
296
274
  id,
@@ -298,80 +276,61 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
298
276
  style,
299
277
  refView,
300
278
  index,
279
+ stickyOffset,
280
+ animatedScrollY: _animatedScrollY,
281
+ children,
301
282
  ...rest
302
283
  }) {
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 });
284
+ const [position = POSITION_OUT_OF_VIEW, headerSize = 0, activeStickyIndex] = useArr$([
285
+ `containerPosition${id}`,
286
+ "headerSize",
287
+ "activeStickyIndex"
288
+ ]);
289
+ const base = {
290
+ contain: "paint layout style"
291
+ };
292
+ const composed = React3__namespace.useMemo(
293
+ () => {
294
+ var _a3;
295
+ return (_a3 = isArray(style) ? Object.assign({}, ...style) : style) != null ? _a3 : {};
296
+ },
297
+ [style]
298
+ );
299
+ const viewStyle = React3__namespace.useMemo(() => {
300
+ var _a3;
301
+ const styleBase = { ...base, ...composed };
302
+ delete styleBase.transform;
303
+ const offset = (_a3 = stickyOffset != null ? stickyOffset : headerSize) != null ? _a3 : 0;
304
+ const isActive = activeStickyIndex === index;
305
+ styleBase.position = isActive ? "sticky" : "absolute";
306
+ styleBase.zIndex = index + 1e3;
307
+ if (horizontal) {
308
+ styleBase.left = isActive ? offset : position;
309
+ } else {
310
+ styleBase.top = isActive ? offset : position;
311
+ }
312
+ return styleBase;
313
+ }, [composed, horizontal, position, index, stickyOffset, headerSize, activeStickyIndex]);
314
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: viewStyle, ...rest }, children);
314
315
  });
315
316
  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
317
 
322
318
  // src/constants-platform.ts
323
319
  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
320
  var symbolFirst = Symbol();
331
321
  function useInit(cb) {
332
- const refValue = React4.useRef(symbolFirst);
322
+ const refValue = React3.useRef(symbolFirst);
333
323
  if (refValue.current === symbolFirst) {
334
324
  refValue.current = cb();
335
325
  }
336
326
  return refValue.current;
337
327
  }
338
328
 
339
- // src/utils/helpers.ts
340
- function isFunction(obj) {
341
- return typeof obj === "function";
342
- }
343
- function isArray(obj) {
344
- return Array.isArray(obj);
345
- }
346
- var warned = /* @__PURE__ */ new Set();
347
- function warnDevOnce(id, text) {
348
- if (__DEV__ && !warned.has(id)) {
349
- warned.add(id);
350
- console.warn(`[legend-list] ${text}`);
351
- }
352
- }
353
- function roundSize(size) {
354
- return Math.floor(size * 8) / 8;
355
- }
356
- function isNullOrUndefined(value) {
357
- return value === null || value === void 0;
358
- }
359
- function comparatorDefault(a, b) {
360
- return a - b;
361
- }
362
- 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;
365
- }
366
- function extractPadding(style, contentContainerStyle, type) {
367
- return getPadding(style, type) + getPadding(contentContainerStyle, type);
368
- }
369
-
370
329
  // src/state/ContextContainer.ts
371
- var ContextContainer = React4.createContext(null);
330
+ var ContextContainer = React3.createContext(null);
372
331
  function useViewability(callback, configId) {
373
332
  const ctx = useStateContext();
374
- const { containerId } = React4.useContext(ContextContainer);
333
+ const { containerId } = React3.useContext(ContextContainer);
375
334
  const key = containerId + (configId != null ? configId : "");
376
335
  useInit(() => {
377
336
  const value = ctx.mapViewabilityValues.get(key);
@@ -380,7 +339,7 @@ function useViewability(callback, configId) {
380
339
  }
381
340
  });
382
341
  ctx.mapViewabilityCallbacks.set(key, callback);
383
- React4.useEffect(
342
+ React3.useEffect(
384
343
  () => () => {
385
344
  ctx.mapViewabilityCallbacks.delete(key);
386
345
  },
@@ -389,7 +348,7 @@ function useViewability(callback, configId) {
389
348
  }
390
349
  function useViewabilityAmount(callback) {
391
350
  const ctx = useStateContext();
392
- const { containerId } = React4.useContext(ContextContainer);
351
+ const { containerId } = React3.useContext(ContextContainer);
393
352
  useInit(() => {
394
353
  const value = ctx.mapViewabilityAmountValues.get(containerId);
395
354
  if (value) {
@@ -397,7 +356,7 @@ function useViewabilityAmount(callback) {
397
356
  }
398
357
  });
399
358
  ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
400
- React4.useEffect(
359
+ React3.useEffect(
401
360
  () => () => {
402
361
  ctx.mapViewabilityAmountCallbacks.delete(containerId);
403
362
  },
@@ -405,12 +364,12 @@ function useViewabilityAmount(callback) {
405
364
  );
406
365
  }
407
366
  function useRecyclingEffect(effect) {
408
- const { index, value } = React4.useContext(ContextContainer);
409
- const prevValues = React4.useRef({
367
+ const { index, value } = React3.useContext(ContextContainer);
368
+ const prevValues = React3.useRef({
410
369
  prevIndex: void 0,
411
370
  prevItem: void 0
412
371
  });
413
- React4.useEffect(() => {
372
+ React3.useEffect(() => {
414
373
  let ret;
415
374
  if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
416
375
  ret = effect({
@@ -428,12 +387,12 @@ function useRecyclingEffect(effect) {
428
387
  }, [index, value, effect]);
429
388
  }
430
389
  function useRecyclingState(valueOrFun) {
431
- const { index, value, itemKey, triggerLayout } = React4.useContext(ContextContainer);
432
- const refState = React4.useRef({
390
+ const { index, value, itemKey, triggerLayout } = React3.useContext(ContextContainer);
391
+ const refState = React3.useRef({
433
392
  itemKey: null,
434
393
  value: null
435
394
  });
436
- const [_, setRenderNum] = React4.useState(0);
395
+ const [_, setRenderNum] = React3.useState(0);
437
396
  const state = refState.current;
438
397
  if (state.itemKey !== itemKey) {
439
398
  state.itemKey = itemKey;
@@ -444,7 +403,7 @@ function useRecyclingState(valueOrFun) {
444
403
  prevItem: void 0
445
404
  }) : valueOrFun;
446
405
  }
447
- const setState = React4.useCallback(
406
+ const setState = React3.useCallback(
448
407
  (newState) => {
449
408
  state.value = isFunction(newState) ? newState(state.value) : newState;
450
409
  setRenderNum((v) => v + 1);
@@ -455,7 +414,7 @@ function useRecyclingState(valueOrFun) {
455
414
  return [state.value, setState];
456
415
  }
457
416
  function useIsLastItem() {
458
- const { itemKey } = React4.useContext(ContextContainer);
417
+ const { itemKey } = React3.useContext(ContextContainer);
459
418
  const isLast = useSelector$("lastItemKeys", (lastItemKeys) => (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false);
460
419
  return isLast;
461
420
  }
@@ -463,13 +422,114 @@ function useListScrollSize() {
463
422
  const [scrollSize] = useArr$(["scrollSize"]);
464
423
  return scrollSize;
465
424
  }
466
- function useSyncLayout2() {
425
+ function useSyncLayout() {
467
426
  {
468
- const { triggerLayout: syncLayout } = React4.useContext(ContextContainer);
427
+ const { triggerLayout: syncLayout } = React3.useContext(ContextContainer);
469
428
  return syncLayout;
470
429
  }
471
430
  }
472
431
 
432
+ // src/components/Separator.tsx
433
+ function Separator({ ItemSeparatorComponent, leadingItem }) {
434
+ const isLastItem = useIsLastItem();
435
+ return isLastItem ? null : /* @__PURE__ */ React3__namespace.createElement(ItemSeparatorComponent, { leadingItem });
436
+ }
437
+
438
+ // src/hooks/createResizeObserver.ts
439
+ var globalResizeObserver = null;
440
+ function getGlobalResizeObserver() {
441
+ if (!globalResizeObserver) {
442
+ globalResizeObserver = new ResizeObserver((entries) => {
443
+ for (const entry of entries) {
444
+ const callbacks = callbackMap.get(entry.target);
445
+ if (callbacks) {
446
+ for (const callback of callbacks) {
447
+ callback(entry);
448
+ }
449
+ }
450
+ }
451
+ });
452
+ }
453
+ return globalResizeObserver;
454
+ }
455
+ var callbackMap = /* @__PURE__ */ new WeakMap();
456
+ function createResizeObserver(element, callback) {
457
+ if (typeof ResizeObserver === "undefined") {
458
+ return () => {
459
+ };
460
+ }
461
+ if (!element) {
462
+ return () => {
463
+ };
464
+ }
465
+ const observer = getGlobalResizeObserver();
466
+ let callbacks = callbackMap.get(element);
467
+ if (!callbacks) {
468
+ callbacks = /* @__PURE__ */ new Set();
469
+ callbackMap.set(element, callbacks);
470
+ observer.observe(element);
471
+ }
472
+ callbacks.add(callback);
473
+ return () => {
474
+ const callbacks2 = callbackMap.get(element);
475
+ if (callbacks2) {
476
+ callbacks2.delete(callback);
477
+ if (callbacks2.size === 0) {
478
+ callbackMap.delete(element);
479
+ observer.unobserve(element);
480
+ }
481
+ }
482
+ };
483
+ }
484
+
485
+ // src/hooks/useOnLayoutSync.tsx
486
+ function useOnLayoutSync({
487
+ ref,
488
+ onLayoutProp,
489
+ onLayoutChange
490
+ }, deps) {
491
+ React3.useLayoutEffect(() => {
492
+ var _a3, _b;
493
+ const current = ref.current;
494
+ const scrollableNode = (_b = (_a3 = current == null ? void 0 : current.getScrollableNode) == null ? void 0 : _a3.call(current)) != null ? _b : null;
495
+ const element = scrollableNode || current;
496
+ if (!element) {
497
+ return;
498
+ }
499
+ const emit = (layout, fromLayoutEffect) => {
500
+ if (layout.height === 0 && layout.width === 0) {
501
+ return;
502
+ }
503
+ onLayoutChange(layout, fromLayoutEffect);
504
+ onLayoutProp == null ? void 0 : onLayoutProp({ nativeEvent: { layout } });
505
+ };
506
+ const rect = element.getBoundingClientRect();
507
+ emit(toLayout(rect), true);
508
+ let prevRect = rect;
509
+ return createResizeObserver(element, (entry) => {
510
+ var _a4;
511
+ const target = entry.target instanceof HTMLElement ? entry.target : void 0;
512
+ const rect2 = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
513
+ if (rect2.width !== prevRect.width || rect2.height !== prevRect.height) {
514
+ prevRect = rect2;
515
+ emit(toLayout(rect2), false);
516
+ }
517
+ });
518
+ }, deps || []);
519
+ return {};
520
+ }
521
+ function toLayout(rect) {
522
+ if (!rect) {
523
+ return { height: 0, width: 0, x: 0, y: 0 };
524
+ }
525
+ return {
526
+ height: rect.height,
527
+ width: rect.width,
528
+ x: rect.left,
529
+ y: rect.top
530
+ };
531
+ }
532
+
473
533
  // src/components/Container.tsx
474
534
  var Container = typedMemo(function Container2({
475
535
  id,
@@ -480,37 +540,42 @@ var Container = typedMemo(function Container2({
480
540
  ItemSeparatorComponent
481
541
  }) {
482
542
  const ctx = useStateContext();
483
- const { columnWrapperStyle } = ctx;
484
- const [column = 0, data, itemKey, numColumns, extraData, isSticky] = useArr$([
543
+ const { columnWrapperStyle, animatedScrollY } = ctx;
544
+ const [column = 0, data, itemKey, numColumns, extraData, isSticky, stickyOffset] = useArr$([
485
545
  `containerColumn${id}`,
486
546
  `containerItemData${id}`,
487
547
  `containerItemKey${id}`,
488
548
  "numColumns",
489
549
  "extraData",
490
- `containerSticky${id}`
550
+ `containerSticky${id}`,
551
+ `containerStickyOffset${id}`
491
552
  ]);
492
- const refLastSize = React4.useRef();
493
- const ref = React4.useRef(null);
494
- const [_, forceLayoutRender] = React4.useState(0);
553
+ const itemLayoutRef = React3.useRef({
554
+ horizontal,
555
+ itemKey,
556
+ updateItemSize: updateItemSize2
557
+ });
558
+ itemLayoutRef.current.horizontal = horizontal;
559
+ itemLayoutRef.current.itemKey = itemKey;
560
+ itemLayoutRef.current.updateItemSize = updateItemSize2;
561
+ const ref = React3.useRef(null);
562
+ const [layoutRenderCount, forceLayoutRender] = React3.useState(0);
495
563
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
496
564
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
497
- const style = React4.useMemo(() => {
565
+ const didLayoutRef = React3.useRef(false);
566
+ const style = React3.useMemo(() => {
498
567
  let paddingStyles;
499
568
  if (columnWrapperStyle) {
500
569
  const { columnGap, rowGap, gap } = columnWrapperStyle;
501
570
  if (horizontal) {
502
- const py = numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0;
503
571
  paddingStyles = {
504
- paddingBottom: py,
505
572
  paddingRight: columnGap || gap || void 0,
506
- paddingTop: py
573
+ paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
507
574
  };
508
575
  } else {
509
- const px = numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0;
510
576
  paddingStyles = {
511
577
  paddingBottom: rowGap || gap || void 0,
512
- paddingLeft: px,
513
- paddingRight: px
578
+ paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
514
579
  };
515
580
  }
516
581
  }
@@ -524,18 +589,18 @@ var Container = typedMemo(function Container2({
524
589
  } : {
525
590
  left: otherAxisPos,
526
591
  position: "absolute",
527
- right: numColumns > 1 ? void 0 : 0,
592
+ right: numColumns > 1 ? null : 0,
528
593
  top: 0,
529
594
  width: otherAxisSize,
530
595
  ...paddingStyles || {}
531
596
  };
532
597
  }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
533
- const renderedItemInfo = React4.useMemo(
598
+ const renderedItemInfo = React3.useMemo(
534
599
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
535
600
  [itemKey, data, extraData]
536
601
  );
537
602
  const { index, renderedItem } = renderedItemInfo || {};
538
- const contextValue = React4.useMemo(() => {
603
+ const contextValue = React3.useMemo(() => {
539
604
  ctx.viewRefs.set(id, ref);
540
605
  return {
541
606
  containerId: id,
@@ -547,49 +612,64 @@ var Container = typedMemo(function Container2({
547
612
  value: data
548
613
  };
549
614
  }, [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
- }
615
+ const onLayoutChange = React3.useCallback((rectangle) => {
616
+ const {
617
+ horizontal: currentHorizontal,
618
+ itemKey: currentItemKey,
619
+ updateItemSize: updateItemSizeFn
620
+ } = itemLayoutRef.current;
621
+ if (isNullOrUndefined(currentItemKey)) {
622
+ return;
561
623
  }
562
- };
624
+ didLayoutRef.current = true;
625
+ let layout = rectangle;
626
+ roundSize(rectangle[currentHorizontal ? "width" : "height"]);
627
+ const doUpdate = () => {
628
+ itemLayoutRef.current.lastSize = { height: layout.height, width: layout.width };
629
+ updateItemSizeFn(currentItemKey, layout);
630
+ didLayoutRef.current = true;
631
+ };
632
+ {
633
+ doUpdate();
634
+ }
635
+ }, []);
636
+ const { onLayout } = useOnLayoutSync(
637
+ {
638
+ onLayoutChange,
639
+ ref
640
+ },
641
+ [itemKey, layoutRenderCount]
642
+ );
563
643
  const PositionComponent = isSticky ? PositionViewSticky : PositionView2;
564
- return /* @__PURE__ */ React4__namespace.createElement(ContextContainer.Provider, { value: contextValue }, /* @__PURE__ */ React4__namespace.createElement(
644
+ return /* @__PURE__ */ React3__namespace.createElement(
565
645
  PositionComponent,
566
646
  {
647
+ animatedScrollY: isSticky ? animatedScrollY : void 0,
567
648
  horizontal,
568
649
  id,
569
650
  index,
570
651
  key: recycleItems ? void 0 : itemKey,
571
- onLayoutChange,
652
+ onLayout,
572
653
  refView: ref,
654
+ stickyOffset: isSticky ? stickyOffset : void 0,
573
655
  style
574
656
  },
575
- renderedItem,
576
- renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React4__namespace.createElement(
577
- Separator,
578
- {
579
- ItemSeparatorComponent,
580
- itemKey,
581
- leadingItem: renderedItemInfo.item
582
- }
583
- )
584
- ));
657
+ /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(Separator, { ItemSeparatorComponent, leadingItem: renderedItemInfo.item }))
658
+ );
585
659
  });
586
660
 
661
+ // src/platform/Platform.ts
662
+ var Platform = {
663
+ // Widen the type to avoid unreachable-branch lints in cross-platform code that compares against other OSes
664
+ OS: "web"
665
+ };
666
+
587
667
  // src/utils/reordering.ts
588
668
  var mapFn = (element) => {
589
669
  const indexStr = element.getAttribute("index");
590
670
  return [element, indexStr === null ? null : parseInt(indexStr)];
591
671
  };
592
- function sortDOMElementsPatience(container) {
672
+ function sortDOMElements(container) {
593
673
  const elements = Array.from(container.children);
594
674
  if (elements.length <= 1) return elements;
595
675
  const items = elements.map(mapFn);
@@ -671,8 +751,8 @@ function findLIS(arr) {
671
751
  // src/hooks/useDOMOrder.ts
672
752
  function useDOMOrder(ref) {
673
753
  const ctx = useStateContext();
674
- const debounceRef = React4.useRef(void 0);
675
- React4.useEffect(() => {
754
+ const debounceRef = React3.useRef(void 0);
755
+ React3.useEffect(() => {
676
756
  const unsubscribe = listen$(ctx, "lastPositionUpdate", () => {
677
757
  if (debounceRef.current !== void 0) {
678
758
  clearTimeout(debounceRef.current);
@@ -680,7 +760,7 @@ function useDOMOrder(ref) {
680
760
  debounceRef.current = setTimeout(() => {
681
761
  const parent = ref.current;
682
762
  if (parent) {
683
- sortDOMElementsPatience(parent);
763
+ sortDOMElements(parent);
684
764
  }
685
765
  debounceRef.current = void 0;
686
766
  }, 500);
@@ -696,12 +776,12 @@ function useDOMOrder(ref) {
696
776
 
697
777
  // src/components/Containers.tsx
698
778
  var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColumns, children }) {
699
- const ref = React4.useRef(null);
779
+ const ref = React3.useRef(null);
700
780
  const ctx = useStateContext();
701
781
  const columnWrapperStyle = ctx.columnWrapperStyle;
702
782
  const [totalSize, otherAxisSize] = useArr$(["totalSize", "otherAxisSize"]);
703
783
  useDOMOrder(ref);
704
- const style = horizontal ? { minHeight: otherAxisSize, width: totalSize } : { height: totalSize, minWidth: otherAxisSize };
784
+ const style = horizontal ? { minHeight: otherAxisSize, position: "relative", width: totalSize } : { height: totalSize, minWidth: otherAxisSize, position: "relative" };
705
785
  if (columnWrapperStyle && numColumns > 1) {
706
786
  const { columnGap, rowGap, gap } = columnWrapperStyle;
707
787
  const gapX = columnGap || gap || 0;
@@ -722,7 +802,7 @@ var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColum
722
802
  }
723
803
  }
724
804
  }
725
- return /* @__PURE__ */ React4__namespace.createElement("div", { ref, style }, children);
805
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref, style }, children);
726
806
  });
727
807
  var Containers = typedMemo(function Containers2({
728
808
  horizontal,
@@ -736,7 +816,7 @@ var Containers = typedMemo(function Containers2({
736
816
  const containers = [];
737
817
  for (let i = 0; i < numContainers; i++) {
738
818
  containers.push(
739
- /* @__PURE__ */ React4__namespace.createElement(
819
+ /* @__PURE__ */ React3__namespace.createElement(
740
820
  Container,
741
821
  {
742
822
  getRenderedItem: getRenderedItem2,
@@ -750,25 +830,41 @@ var Containers = typedMemo(function Containers2({
750
830
  )
751
831
  );
752
832
  }
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
- ));
833
+ return /* @__PURE__ */ React3__namespace.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
770
834
  });
771
- var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView2({
835
+ function DevNumbers() {
836
+ return IS_DEV && React3__namespace.memo(function DevNumbers2() {
837
+ return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3__namespace.createElement(
838
+ "div",
839
+ {
840
+ key: index,
841
+ style: {
842
+ height: 100,
843
+ pointerEvents: "none",
844
+ position: "absolute",
845
+ top: index * 100,
846
+ width: "100%"
847
+ }
848
+ },
849
+ /* @__PURE__ */ React3__namespace.createElement("div", { style: { color: "red" } }, index * 100)
850
+ ));
851
+ });
852
+ }
853
+
854
+ // src/platform/StyleSheet.tsx
855
+ function flattenStyles(styles) {
856
+ if (isArray(styles)) {
857
+ return Object.assign({}, ...styles.filter(Boolean));
858
+ }
859
+ return styles;
860
+ }
861
+ var StyleSheet = {
862
+ create: (styles) => styles,
863
+ flatten: (style) => flattenStyles(style)
864
+ };
865
+
866
+ // src/components/ListComponentScrollView.tsx
867
+ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView2({
772
868
  children,
773
869
  style,
774
870
  contentContainerStyle,
@@ -781,25 +877,23 @@ var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView
781
877
  showsVerticalScrollIndicator = true,
782
878
  refreshControl,
783
879
  onLayout,
784
- ScrollComponent,
785
880
  ...props
786
881
  }, ref) {
787
- const scrollRef = React4.useRef(null);
788
- const contentRef = React4.useRef(null);
789
- const momentumTimeout = React4.useRef(null);
790
- React4.useImperativeHandle(ref, () => {
882
+ const scrollRef = React3.useRef(null);
883
+ const contentRef = React3.useRef(null);
884
+ const momentumTimeout = React3.useRef(null);
885
+ React3.useImperativeHandle(ref, () => {
791
886
  const api = {
792
887
  getBoundingClientRect: () => {
793
- var _a;
794
- return (_a = scrollRef.current) == null ? void 0 : _a.getBoundingClientRect();
888
+ var _a3;
889
+ return (_a3 = scrollRef.current) == null ? void 0 : _a3.getBoundingClientRect();
795
890
  },
796
891
  getScrollableNode: () => scrollRef.current,
797
892
  getScrollResponder: () => scrollRef.current,
798
- scrollBy: (options) => {
893
+ scrollBy: (x, y) => {
799
894
  const el = scrollRef.current;
800
895
  if (!el) return;
801
- const { x = 0, y = 0, animated = true } = options;
802
- el.scrollBy({ behavior: animated ? "smooth" : "auto", left: x, top: y });
896
+ el.scrollBy(x, y);
803
897
  },
804
898
  scrollTo: (options) => {
805
899
  const el = scrollRef.current;
@@ -830,7 +924,7 @@ var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView
830
924
  };
831
925
  return api;
832
926
  }, [horizontal]);
833
- const handleScroll = React4.useCallback(
927
+ const handleScroll = React3.useCallback(
834
928
  (event) => {
835
929
  if (!onScroll2 || !(event == null ? void 0 : event.target)) {
836
930
  return;
@@ -866,21 +960,25 @@ var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView
866
960
  },
867
961
  [onScroll2, onMomentumScrollEnd]
868
962
  );
869
- React4.useLayoutEffect(() => {
963
+ React3.useLayoutEffect(() => {
870
964
  const element = scrollRef.current;
871
965
  if (!element) return;
872
- element.addEventListener("scroll", handleScroll, { passive: true });
966
+ element.addEventListener("scroll", handleScroll);
873
967
  return () => {
874
968
  element.removeEventListener("scroll", handleScroll);
875
969
  };
876
970
  }, [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(() => {
971
+ React3.useEffect(() => {
972
+ const doScroll = () => {
973
+ if (contentOffset && scrollRef.current) {
974
+ scrollRef.current.scrollLeft = contentOffset.x || 0;
975
+ scrollRef.current.scrollTop = contentOffset.y || 0;
976
+ }
977
+ };
978
+ doScroll();
979
+ requestAnimationFrame(doScroll);
980
+ }, [contentOffset == null ? void 0 : contentOffset.x, contentOffset == null ? void 0 : contentOffset.y]);
981
+ React3.useLayoutEffect(() => {
884
982
  if (!onLayout || !scrollRef.current) return;
885
983
  const element = scrollRef.current;
886
984
  const fireLayout = () => {
@@ -911,41 +1009,80 @@ var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView
911
1009
  // Ensure proper positioning context
912
1010
  WebkitOverflowScrolling: "touch",
913
1011
  // iOS momentum scrolling
914
- ...style
1012
+ ...StyleSheet.flatten(style)
915
1013
  };
916
1014
  const contentStyle = {
917
1015
  display: horizontal ? "flex" : "block",
918
1016
  flexDirection: horizontal ? "row" : void 0,
919
1017
  minHeight: horizontal ? void 0 : "100%",
920
1018
  minWidth: horizontal ? "100%" : void 0,
921
- ...contentContainerStyle
1019
+ ...StyleSheet.flatten(contentContainerStyle)
922
1020
  };
923
- return /* @__PURE__ */ React4__namespace.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React4__namespace.createElement("div", { ref: contentRef, style: contentStyle }, children));
1021
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React3__namespace.createElement("div", { ref: contentRef, style: contentStyle }, children));
924
1022
  });
1023
+ function Padding() {
1024
+ const [paddingTop] = useArr$(["alignItemsPaddingTop"]);
1025
+ return /* @__PURE__ */ React3__namespace.createElement("div", { style: { paddingTop } });
1026
+ }
1027
+ function PaddingDevMode() {
1028
+ const [paddingTop] = useArr$(["alignItemsPaddingTop"]);
1029
+ return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement("div", { style: { paddingTop } }), /* @__PURE__ */ React3__namespace.createElement(
1030
+ "div",
1031
+ {
1032
+ style: {
1033
+ backgroundColor: "green",
1034
+ height: paddingTop,
1035
+ left: 0,
1036
+ position: "absolute",
1037
+ right: 0,
1038
+ top: 0
1039
+ }
1040
+ }
1041
+ ));
1042
+ }
925
1043
  function useValueListener$(key, callback) {
926
1044
  const ctx = useStateContext();
927
- React4.useLayoutEffect(() => {
928
- listen$(ctx, key, (value) => {
1045
+ React3.useLayoutEffect(() => {
1046
+ const unsubscribe = listen$(ctx, key, (value) => {
929
1047
  callback(value);
930
1048
  });
931
- }, []);
1049
+ return unsubscribe;
1050
+ }, [callback, ctx, key]);
932
1051
  }
933
1052
 
934
1053
  // src/components/ScrollAdjust.tsx
935
1054
  function ScrollAdjust() {
936
1055
  const ctx = useStateContext();
937
- const lastScrollOffsetRef = React4__namespace.useRef(0);
938
- const callback = React4__namespace.useCallback(() => {
939
- var _a;
1056
+ const lastScrollOffsetRef = React3__namespace.useRef(0);
1057
+ const callback = React3__namespace.useCallback(() => {
1058
+ var _a3;
940
1059
  const scrollAdjust = peek$(ctx, "scrollAdjust");
941
1060
  const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
942
1061
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
943
- const scrollView = (_a = ctx.internalState) == null ? void 0 : _a.refScroller.current;
1062
+ const scrollView = (_a3 = ctx.internalState) == null ? void 0 : _a3.refScroller.current;
944
1063
  if (scrollView && scrollOffset !== lastScrollOffsetRef.current) {
945
1064
  const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
946
1065
  if (scrollDelta !== 0) {
947
- scrollView.scrollBy(0, scrollDelta);
948
- console.log("ScrollAdjust (web scrollBy)", scrollDelta, "total offset:", scrollOffset);
1066
+ const el = scrollView.getScrollableNode();
1067
+ const prevScroll = el.scrollTop;
1068
+ const nextScroll = prevScroll + scrollDelta;
1069
+ const totalSize = el.scrollHeight;
1070
+ if (scrollDelta > 0 && !ctx.internalState.adjustingFromInitialMount && totalSize < nextScroll + el.clientHeight) {
1071
+ const child = el.firstElementChild;
1072
+ const prevPaddingBottom = child.style.paddingBottom;
1073
+ const pad = (nextScroll + el.clientHeight - totalSize) * 2;
1074
+ child.style.paddingBottom = `${pad}px`;
1075
+ void el.offsetHeight;
1076
+ scrollView.scrollBy(0, scrollDelta);
1077
+ setTimeout(() => {
1078
+ child.style.paddingBottom = prevPaddingBottom;
1079
+ }, 100);
1080
+ } else {
1081
+ scrollView.scrollBy(0, scrollDelta);
1082
+ }
1083
+ if (IS_DEV) {
1084
+ console.log("ScrollAdjust (web scrollBy)", scrollDelta, "total offset:", scrollOffset);
1085
+ }
949
1086
  }
950
1087
  lastScrollOffsetRef.current = scrollOffset;
951
1088
  }
@@ -954,49 +1091,26 @@ function ScrollAdjust() {
954
1091
  useValueListener$("scrollAdjustUserOffset", callback);
955
1092
  return null;
956
1093
  }
957
-
958
- // src/components/SnapWrapper.tsx
959
1094
  function SnapWrapper({ ScrollComponent, ...props }) {
960
1095
  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;
1096
+ return /* @__PURE__ */ React3__namespace.createElement(ScrollComponent, { ...props, snapToOffsets });
968
1097
  }
1098
+ var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
1099
+ const ref = refView != null ? refView : React3.useRef();
1100
+ useOnLayoutSync({ onLayoutChange, ref });
1101
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ...rest, ref }, children);
1102
+ };
969
1103
 
970
1104
  // src/components/ListComponent.tsx
971
1105
  var getComponent = (Component) => {
972
- if (React4__namespace.isValidElement(Component)) {
1106
+ if (React3__namespace.isValidElement(Component)) {
973
1107
  return Component;
974
1108
  }
975
1109
  if (Component) {
976
- return /* @__PURE__ */ React4__namespace.createElement(Component, null);
1110
+ return /* @__PURE__ */ React3__namespace.createElement(Component, null);
977
1111
  }
978
1112
  return null;
979
1113
  };
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
1114
  var ListComponent = typedMemo(function ListComponent2({
1001
1115
  canRender,
1002
1116
  style,
@@ -1022,16 +1136,15 @@ var ListComponent = typedMemo(function ListComponent2({
1022
1136
  scrollAdjustHandler,
1023
1137
  onLayoutHeader,
1024
1138
  snapToIndices,
1025
- stickyIndices,
1139
+ stickyHeaderIndices,
1026
1140
  ...rest
1027
1141
  }) {
1028
1142
  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 })),
1143
+ const ScrollComponent = renderScrollComponent ? React3.useMemo(
1144
+ () => React3__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
1032
1145
  [renderScrollComponent]
1033
1146
  ) : ListComponentScrollView;
1034
- React4__namespace.useEffect(() => {
1147
+ React3__namespace.useEffect(() => {
1035
1148
  if (canRender) {
1036
1149
  setTimeout(() => {
1037
1150
  scrollAdjustHandler.setMounted();
@@ -1039,39 +1152,30 @@ var ListComponent = typedMemo(function ListComponent2({
1039
1152
  }
1040
1153
  }, [canRender]);
1041
1154
  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(
1155
+ return /* @__PURE__ */ React3__namespace.createElement(
1049
1156
  SnapOrScroll,
1050
1157
  {
1051
1158
  ...rest,
1052
- contentContainerStyle: contentContainerStyleWeb,
1159
+ contentContainerStyle: [
1160
+ contentContainerStyle,
1161
+ horizontal ? {
1162
+ height: "100%"
1163
+ } : {}
1164
+ ],
1053
1165
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
1054
1166
  horizontal,
1055
- maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
1167
+ maintainVisibleContentPosition: maintainVisibleContentPosition ? { minIndexForVisible: 0 } : void 0,
1056
1168
  onLayout,
1057
1169
  onScroll: onScroll2,
1058
1170
  ref: refScrollView,
1059
1171
  ScrollComponent: snapToIndices ? ScrollComponent : void 0,
1060
1172
  style
1061
1173
  },
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
- ),
1174
+ /* @__PURE__ */ React3__namespace.createElement(ScrollAdjust, null),
1175
+ ENABLE_DEVMODE ? /* @__PURE__ */ React3__namespace.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3__namespace.createElement(Padding, null),
1176
+ ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1073
1177
  ListEmptyComponent && getComponent(ListEmptyComponent),
1074
- canRender && /* @__PURE__ */ React4__namespace.createElement(
1178
+ canRender && !ListEmptyComponent && /* @__PURE__ */ React3__namespace.createElement(
1075
1179
  Containers,
1076
1180
  {
1077
1181
  getRenderedItem: getRenderedItem2,
@@ -1082,7 +1186,7 @@ var ListComponent = typedMemo(function ListComponent2({
1082
1186
  waitForInitialLayout
1083
1187
  }
1084
1188
  ),
1085
- ListFooterComponent && /* @__PURE__ */ React4__namespace.createElement(
1189
+ ListFooterComponent && /* @__PURE__ */ React3__namespace.createElement(
1086
1190
  LayoutView,
1087
1191
  {
1088
1192
  onLayoutChange: (layout) => {
@@ -1093,7 +1197,7 @@ var ListComponent = typedMemo(function ListComponent2({
1093
1197
  },
1094
1198
  getComponent(ListFooterComponent)
1095
1199
  ),
1096
- __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React4__namespace.createElement(DevNumbers, null)
1200
+ IS_DEV && ENABLE_DEVMODE && /* @__PURE__ */ React3__namespace.createElement(DevNumbers, null)
1097
1201
  );
1098
1202
  });
1099
1203
 
@@ -1105,7 +1209,7 @@ function getId(state, index) {
1105
1209
  }
1106
1210
  const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
1107
1211
  const id = ret;
1108
- state.idCache.set(index, id);
1212
+ state.idCache[index] = id;
1109
1213
  return id;
1110
1214
  }
1111
1215
 
@@ -1126,13 +1230,84 @@ function calculateOffsetForIndex(ctx, state, index) {
1126
1230
  return position;
1127
1231
  }
1128
1232
 
1233
+ // src/utils/setPaddingTop.ts
1234
+ function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1235
+ if (stylePaddingTop !== void 0) {
1236
+ const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1237
+ if (stylePaddingTop < prevStylePaddingTop) {
1238
+ let prevTotalSize = peek$(ctx, "totalSize") || 0;
1239
+ set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
1240
+ state.timeoutSetPaddingTop = setTimeout(() => {
1241
+ prevTotalSize = peek$(ctx, "totalSize") || 0;
1242
+ set$(ctx, "totalSize", prevTotalSize - prevStylePaddingTop);
1243
+ }, 16);
1244
+ }
1245
+ set$(ctx, "stylePaddingTop", stylePaddingTop);
1246
+ }
1247
+ if (alignItemsPaddingTop !== void 0) {
1248
+ set$(ctx, "alignItemsPaddingTop", alignItemsPaddingTop);
1249
+ }
1250
+ }
1251
+
1252
+ // src/utils/updateAlignItemsPaddingTop.ts
1253
+ function updateAlignItemsPaddingTop(ctx, state) {
1254
+ const {
1255
+ scrollLength,
1256
+ props: { alignItemsAtEnd, data }
1257
+ } = state;
1258
+ if (alignItemsAtEnd) {
1259
+ let alignItemsPaddingTop = 0;
1260
+ if ((data == null ? void 0 : data.length) > 0) {
1261
+ const contentSize = getContentSize(ctx);
1262
+ alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1263
+ }
1264
+ setPaddingTop(ctx, state, { alignItemsPaddingTop });
1265
+ }
1266
+ }
1267
+
1268
+ // src/core/addTotalSize.ts
1269
+ function addTotalSize(ctx, state, key, add) {
1270
+ const { alignItemsAtEnd } = state.props;
1271
+ const prevTotalSize = state.totalSize;
1272
+ let totalSize = state.totalSize;
1273
+ if (key === null) {
1274
+ totalSize = add;
1275
+ if (state.timeoutSetPaddingTop) {
1276
+ clearTimeout(state.timeoutSetPaddingTop);
1277
+ state.timeoutSetPaddingTop = void 0;
1278
+ }
1279
+ } else {
1280
+ totalSize += add;
1281
+ }
1282
+ if (prevTotalSize !== totalSize) {
1283
+ {
1284
+ state.pendingTotalSize = void 0;
1285
+ state.totalSize = totalSize;
1286
+ set$(ctx, "totalSize", totalSize);
1287
+ if (alignItemsAtEnd) {
1288
+ updateAlignItemsPaddingTop(ctx, state);
1289
+ }
1290
+ }
1291
+ }
1292
+ }
1293
+
1294
+ // src/core/setSize.ts
1295
+ function setSize(ctx, state, itemKey, size) {
1296
+ const { sizes } = state;
1297
+ const previousSize = sizes.get(itemKey);
1298
+ const diff = previousSize !== void 0 ? size - previousSize : size;
1299
+ if (diff !== 0) {
1300
+ addTotalSize(ctx, state, itemKey, diff);
1301
+ }
1302
+ sizes.set(itemKey, size);
1303
+ }
1304
+
1129
1305
  // src/utils/getItemSize.ts
1130
- function getItemSize(state, key, index, data, useAverageSize) {
1131
- var _a, _b;
1306
+ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedSize) {
1307
+ var _a3, _b;
1132
1308
  const {
1133
1309
  sizesKnown,
1134
1310
  sizes,
1135
- scrollingTo,
1136
1311
  averageSizes,
1137
1312
  props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
1138
1313
  } = state;
@@ -1141,7 +1316,14 @@ function getItemSize(state, key, index, data, useAverageSize) {
1141
1316
  return sizeKnown;
1142
1317
  }
1143
1318
  let size;
1144
- const itemType = getItemType ? (_a = getItemType(data, index)) != null ? _a : "" : "";
1319
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1320
+ const scrollingTo = peek$(ctx, "scrollingTo");
1321
+ if (preferCachedSize) {
1322
+ const cachedSize = sizes.get(key);
1323
+ if (cachedSize !== void 0) {
1324
+ return cachedSize;
1325
+ }
1326
+ }
1145
1327
  if (getFixedItemSize) {
1146
1328
  size = getFixedItemSize(index, data, itemType);
1147
1329
  if (size !== void 0) {
@@ -1163,53 +1345,234 @@ function getItemSize(state, key, index, data, useAverageSize) {
1163
1345
  if (size === void 0) {
1164
1346
  size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
1165
1347
  }
1166
- sizes.set(key, size);
1348
+ setSize(ctx, state, key, size);
1167
1349
  return size;
1168
1350
  }
1169
1351
 
1170
1352
  // src/core/calculateOffsetWithOffsetPosition.ts
1171
- function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
1353
+ function calculateOffsetWithOffsetPosition(ctx, state, offsetParam, params) {
1172
1354
  const { index, viewOffset, viewPosition } = params;
1173
1355
  let offset = offsetParam;
1174
1356
  if (viewOffset) {
1175
1357
  offset -= viewOffset;
1176
1358
  }
1177
1359
  if (viewPosition !== void 0 && index !== void 0) {
1178
- offset -= viewPosition * (state.scrollLength - getItemSize(state, getId(state, index), index, state.props.data[index]));
1360
+ offset -= viewPosition * (state.scrollLength - getItemSize(ctx, state, getId(state, index), index, state.props.data[index]));
1179
1361
  }
1180
1362
  return offset;
1181
1363
  }
1182
1364
 
1183
1365
  // src/core/finishScrollTo.ts
1184
- var finishScrollTo = (state) => {
1366
+ function finishScrollTo(ctx, state) {
1367
+ var _a3, _b;
1185
1368
  if (state) {
1186
- state.scrollingTo = void 0;
1187
1369
  state.scrollHistory.length = 0;
1370
+ state.initialScroll = void 0;
1371
+ state.initialAnchor = void 0;
1372
+ set$(ctx, "scrollingTo", void 0);
1373
+ if (state.pendingTotalSize !== void 0) {
1374
+ addTotalSize(ctx, state, null, state.pendingTotalSize);
1375
+ }
1376
+ if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1377
+ (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1378
+ }
1188
1379
  }
1189
- };
1380
+ }
1190
1381
 
1191
1382
  // src/core/scrollTo.ts
1192
- function scrollTo(state, params = {}) {
1193
- var _a;
1194
- const { animated, noScrollingTo } = params;
1383
+ function scrollTo(ctx, state, params) {
1384
+ var _a3;
1385
+ const { noScrollingTo, ...scrollTarget } = params;
1386
+ const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1195
1387
  const {
1196
1388
  refScroller,
1197
1389
  props: { horizontal }
1198
1390
  } = state;
1199
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1391
+ let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1392
+ if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
1393
+ const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
1394
+ offset = Math.min(offset, maxOffset);
1395
+ }
1200
1396
  state.scrollHistory.length = 0;
1201
1397
  if (!noScrollingTo) {
1202
- state.scrollingTo = params;
1398
+ set$(ctx, "scrollingTo", scrollTarget);
1203
1399
  }
1204
1400
  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
- });
1401
+ if (!isInitialScroll || Platform.OS === "android") {
1402
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollTo({
1403
+ animated: !!animated,
1404
+ x: horizontal ? offset : 0,
1405
+ y: horizontal ? 0 : offset
1406
+ });
1407
+ }
1210
1408
  if (!animated) {
1211
1409
  state.scroll = offset;
1212
- setTimeout(() => finishScrollTo(state), 100);
1410
+ {
1411
+ const unlisten = listen$(ctx, "containersDidLayout", (value) => {
1412
+ if (value && peek$(ctx, "scrollingTo")) {
1413
+ finishScrollTo(ctx, state);
1414
+ unlisten();
1415
+ }
1416
+ });
1417
+ }
1418
+ if (isInitialScroll) {
1419
+ setTimeout(() => {
1420
+ state.initialScroll = void 0;
1421
+ }, 500);
1422
+ }
1423
+ }
1424
+ }
1425
+
1426
+ // src/utils/checkThreshold.ts
1427
+ var HYSTERESIS_MULTIPLIER = 1.3;
1428
+ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
1429
+ const absDistance = Math.abs(distance);
1430
+ const within = atThreshold || threshold > 0 && absDistance <= threshold;
1431
+ const updateSnapshot = () => {
1432
+ setSnapshot == null ? void 0 : setSnapshot({
1433
+ atThreshold,
1434
+ contentSize: context.contentSize,
1435
+ dataLength: context.dataLength,
1436
+ scrollPosition: context.scrollPosition
1437
+ });
1438
+ };
1439
+ if (!wasReached) {
1440
+ if (!within) {
1441
+ return false;
1442
+ }
1443
+ onReached == null ? void 0 : onReached(distance);
1444
+ updateSnapshot();
1445
+ return true;
1446
+ }
1447
+ const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
1448
+ if (reset) {
1449
+ setSnapshot == null ? void 0 : setSnapshot(void 0);
1450
+ return false;
1451
+ }
1452
+ if (within) {
1453
+ const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
1454
+ if (changed) {
1455
+ onReached == null ? void 0 : onReached(distance);
1456
+ updateSnapshot();
1457
+ }
1458
+ }
1459
+ return true;
1460
+ };
1461
+
1462
+ // src/utils/checkAtBottom.ts
1463
+ function checkAtBottom(ctx, state) {
1464
+ var _a3;
1465
+ if (!state) {
1466
+ return;
1467
+ }
1468
+ const {
1469
+ queuedInitialLayout,
1470
+ scrollLength,
1471
+ scroll,
1472
+ maintainingScrollAtEnd,
1473
+ props: { maintainScrollAtEndThreshold, onEndReachedThreshold }
1474
+ } = state;
1475
+ const contentSize = getContentSize(ctx);
1476
+ if (contentSize > 0 && queuedInitialLayout && !maintainingScrollAtEnd) {
1477
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1478
+ const isContentLess = contentSize < scrollLength;
1479
+ state.isAtEnd = isContentLess || distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
1480
+ state.isEndReached = checkThreshold(
1481
+ distanceFromEnd,
1482
+ isContentLess,
1483
+ onEndReachedThreshold * scrollLength,
1484
+ state.isEndReached,
1485
+ state.endReachedSnapshot,
1486
+ {
1487
+ contentSize,
1488
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1489
+ scrollPosition: scroll
1490
+ },
1491
+ (distance) => {
1492
+ var _a4, _b;
1493
+ return (_b = (_a4 = state.props).onEndReached) == null ? void 0 : _b.call(_a4, { distanceFromEnd: distance });
1494
+ },
1495
+ (snapshot) => {
1496
+ state.endReachedSnapshot = snapshot;
1497
+ }
1498
+ );
1499
+ }
1500
+ }
1501
+
1502
+ // src/utils/checkAtTop.ts
1503
+ function checkAtTop(state) {
1504
+ var _a3;
1505
+ if (!state) {
1506
+ return;
1507
+ }
1508
+ const {
1509
+ scrollLength,
1510
+ scroll,
1511
+ props: { onStartReachedThreshold }
1512
+ } = state;
1513
+ const distanceFromTop = scroll;
1514
+ state.isAtStart = distanceFromTop <= 0;
1515
+ state.isStartReached = checkThreshold(
1516
+ distanceFromTop,
1517
+ false,
1518
+ onStartReachedThreshold * scrollLength,
1519
+ state.isStartReached,
1520
+ state.startReachedSnapshot,
1521
+ {
1522
+ contentSize: state.totalSize,
1523
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length,
1524
+ scrollPosition: scroll
1525
+ },
1526
+ (distance) => {
1527
+ var _a4, _b;
1528
+ return (_b = (_a4 = state.props).onStartReached) == null ? void 0 : _b.call(_a4, { distanceFromStart: distance });
1529
+ },
1530
+ (snapshot) => {
1531
+ state.startReachedSnapshot = snapshot;
1532
+ }
1533
+ );
1534
+ }
1535
+
1536
+ // src/core/updateScroll.ts
1537
+ function updateScroll(ctx, state, newScroll, forceUpdate) {
1538
+ var _a3;
1539
+ const scrollingTo = peek$(ctx, "scrollingTo");
1540
+ state.hasScrolled = true;
1541
+ state.lastBatchingAction = Date.now();
1542
+ const currentTime = Date.now();
1543
+ const adjust = state.scrollAdjustHandler.getAdjust();
1544
+ const lastHistoryAdjust = state.lastScrollAdjustForHistory;
1545
+ const adjustChanged = lastHistoryAdjust !== void 0 && Math.abs(adjust - lastHistoryAdjust) > 0.1;
1546
+ if (adjustChanged) {
1547
+ state.scrollHistory.length = 0;
1548
+ }
1549
+ state.lastScrollAdjustForHistory = adjust;
1550
+ if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
1551
+ if (!adjustChanged) {
1552
+ state.scrollHistory.push({ scroll: newScroll, time: currentTime });
1553
+ }
1554
+ }
1555
+ if (state.scrollHistory.length > 5) {
1556
+ state.scrollHistory.shift();
1557
+ }
1558
+ state.scrollPrev = state.scroll;
1559
+ state.scrollPrevTime = state.scrollTime;
1560
+ state.scroll = newScroll;
1561
+ state.scrollTime = currentTime;
1562
+ const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
1563
+ if (ignoreScrollFromMVCP && !scrollingTo) {
1564
+ const { lt, gt } = ignoreScrollFromMVCP;
1565
+ if (lt && newScroll < lt || gt && newScroll > gt) {
1566
+ state.ignoreScrollFromMVCPIgnored = true;
1567
+ return;
1568
+ }
1569
+ }
1570
+ if (state.dataChangeNeedsScrollUpdate || Math.abs(state.scroll - state.scrollPrev) > 2) {
1571
+ state.ignoreScrollFromMVCPIgnored = false;
1572
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state, { doMVCP: scrollingTo !== void 0 });
1573
+ checkAtBottom(ctx, state);
1574
+ checkAtTop(state);
1575
+ state.dataChangeNeedsScrollUpdate = false;
1213
1576
  }
1214
1577
  }
1215
1578
 
@@ -1219,6 +1582,9 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1219
1582
  const doit = () => {
1220
1583
  {
1221
1584
  state.scrollAdjustHandler.requestAdjust(positionDiff);
1585
+ if (state.adjustingFromInitialMount) {
1586
+ state.adjustingFromInitialMount--;
1587
+ }
1222
1588
  }
1223
1589
  };
1224
1590
  state.scroll += positionDiff;
@@ -1226,44 +1592,77 @@ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1226
1592
  const didLayout = peek$(ctx, "containersDidLayout");
1227
1593
  if (didLayout) {
1228
1594
  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);
1240
- }
1241
- state.ignoreScrollFromMVCPTimeout = setTimeout(
1242
- () => {
1243
- state.ignoreScrollFromMVCP = void 0;
1244
- },
1245
- 100
1246
- );
1247
1595
  } else {
1596
+ state.adjustingFromInitialMount = (state.adjustingFromInitialMount || 0) + 1;
1248
1597
  requestAnimationFrame(doit);
1249
1598
  }
1250
1599
  }
1251
1600
  }
1252
1601
 
1602
+ // src/core/ensureInitialAnchor.ts
1603
+ var INITIAL_ANCHOR_TOLERANCE = 0.5;
1604
+ var INITIAL_ANCHOR_MAX_ATTEMPTS = 4;
1605
+ var INITIAL_ANCHOR_SETTLED_TICKS = 2;
1606
+ function ensureInitialAnchor(ctx, state) {
1607
+ var _a3, _b, _c, _d, _e;
1608
+ const anchor = state.initialAnchor;
1609
+ const item = state.props.data[anchor.index];
1610
+ const containersDidLayout = peek$(ctx, "containersDidLayout");
1611
+ if (!containersDidLayout) {
1612
+ return;
1613
+ }
1614
+ const id = getId(state, anchor.index);
1615
+ if (state.positions.get(id) === void 0) {
1616
+ return;
1617
+ }
1618
+ const size = getItemSize(ctx, state, id, anchor.index, item, true, true);
1619
+ if (size === void 0) {
1620
+ return;
1621
+ }
1622
+ const availableSpace = Math.max(0, state.scrollLength - size);
1623
+ const desiredOffset = calculateOffsetForIndex(ctx, state, anchor.index) - ((_a3 = anchor.viewOffset) != null ? _a3 : 0) - ((_b = anchor.viewPosition) != null ? _b : 0) * availableSpace;
1624
+ const contentSize = getContentSize(ctx);
1625
+ const maxOffset = Math.max(0, contentSize - state.scrollLength);
1626
+ const clampedDesiredOffset = Math.max(0, Math.min(desiredOffset, maxOffset));
1627
+ const delta = clampedDesiredOffset - state.scroll;
1628
+ if (Math.abs(delta) <= INITIAL_ANCHOR_TOLERANCE) {
1629
+ const settledTicks = ((_c = anchor.settledTicks) != null ? _c : 0) + 1;
1630
+ if (settledTicks >= INITIAL_ANCHOR_SETTLED_TICKS) {
1631
+ state.initialAnchor = void 0;
1632
+ } else {
1633
+ anchor.settledTicks = settledTicks;
1634
+ }
1635
+ return;
1636
+ }
1637
+ if (((_d = anchor.attempts) != null ? _d : 0) >= INITIAL_ANCHOR_MAX_ATTEMPTS) {
1638
+ state.initialAnchor = void 0;
1639
+ return;
1640
+ }
1641
+ const lastDelta = anchor.lastDelta;
1642
+ if (lastDelta !== void 0 && Math.abs(delta) >= Math.abs(lastDelta)) {
1643
+ state.initialAnchor = void 0;
1644
+ return;
1645
+ }
1646
+ Object.assign(anchor, {
1647
+ attempts: ((_e = anchor.attempts) != null ? _e : 0) + 1,
1648
+ lastDelta: delta,
1649
+ settledTicks: 0
1650
+ });
1651
+ requestAdjust(ctx, state, delta);
1652
+ }
1653
+
1253
1654
  // src/core/mvcp.ts
1254
1655
  function prepareMVCP(ctx, state, dataChanged) {
1255
- const {
1256
- idsInView,
1257
- positions,
1258
- scrollingTo,
1259
- props: { maintainVisibleContentPosition }
1260
- } = state;
1656
+ const { idsInView, positions, props } = state;
1657
+ const { maintainVisibleContentPosition } = props;
1658
+ const scrollingTo = peek$(ctx, "scrollingTo");
1261
1659
  let prevPosition;
1262
1660
  let targetId;
1263
1661
  const idsInViewWithPositions = [];
1264
1662
  const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1265
- if (maintainVisibleContentPosition) {
1266
- const indexByKey = state.indexByKey;
1663
+ const shouldMVCP = !dataChanged || maintainVisibleContentPosition;
1664
+ const indexByKey = state.indexByKey;
1665
+ if (shouldMVCP) {
1267
1666
  if (scrollTarget !== void 0) {
1268
1667
  targetId = getId(state, scrollTarget);
1269
1668
  } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
@@ -1276,70 +1675,106 @@ function prepareMVCP(ctx, state, dataChanged) {
1276
1675
  }
1277
1676
  }
1278
1677
  } else {
1279
- targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
1678
+ targetId = idsInView.find((id) => indexByKey.get(id) !== void 0);
1280
1679
  }
1281
1680
  }
1282
1681
  if (targetId !== void 0) {
1283
1682
  prevPosition = positions.get(targetId);
1284
1683
  }
1285
- }
1286
- return () => {
1287
- let positionDiff;
1288
- if (dataChanged && targetId === void 0) {
1289
- for (let i = 0; i < idsInViewWithPositions.length; i++) {
1290
- const { id, position } = idsInViewWithPositions[i];
1291
- const newPosition = positions.get(id);
1684
+ return () => {
1685
+ let positionDiff;
1686
+ if (dataChanged && targetId === void 0 && maintainVisibleContentPosition) {
1687
+ for (let i = 0; i < idsInViewWithPositions.length; i++) {
1688
+ const { id, position } = idsInViewWithPositions[i];
1689
+ const newPosition = positions.get(id);
1690
+ if (newPosition !== void 0) {
1691
+ positionDiff = newPosition - position;
1692
+ break;
1693
+ }
1694
+ }
1695
+ }
1696
+ if (targetId !== void 0 && prevPosition !== void 0) {
1697
+ const newPosition = positions.get(targetId);
1292
1698
  if (newPosition !== void 0) {
1293
- positionDiff = newPosition - position;
1294
- break;
1699
+ const totalSize = getContentSize(ctx);
1700
+ let diff = newPosition - prevPosition;
1701
+ if (diff !== 0 && state.scroll + state.scrollLength > totalSize) {
1702
+ if (diff > 0) {
1703
+ diff = Math.max(0, totalSize - state.scroll - state.scrollLength);
1704
+ } else {
1705
+ diff = 0;
1706
+ }
1707
+ }
1708
+ positionDiff = diff;
1295
1709
  }
1296
1710
  }
1297
- }
1298
- if (targetId !== void 0 && prevPosition !== void 0) {
1299
- const newPosition = positions.get(targetId);
1300
- if (newPosition !== void 0) {
1301
- positionDiff = newPosition - prevPosition;
1711
+ if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1712
+ requestAdjust(ctx, state, positionDiff);
1302
1713
  }
1303
- }
1304
- if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1305
- requestAdjust(ctx, state, positionDiff);
1306
- }
1307
- };
1714
+ };
1715
+ }
1308
1716
  }
1309
1717
 
1310
- // src/utils/setPaddingTop.ts
1311
- function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1312
- if (stylePaddingTop !== void 0) {
1313
- const prevStylePaddingTop = peek$(ctx, "stylePaddingTop") || 0;
1314
- if (stylePaddingTop < prevStylePaddingTop) {
1315
- let prevTotalSize = peek$(ctx, "totalSize") || 0;
1316
- set$(ctx, "totalSize", prevTotalSize + prevStylePaddingTop);
1317
- state.timeoutSetPaddingTop = setTimeout(() => {
1318
- prevTotalSize = peek$(ctx, "totalSize") || 0;
1319
- set$(ctx, "totalSize", prevTotalSize - prevStylePaddingTop);
1320
- }, 16);
1321
- }
1322
- set$(ctx, "stylePaddingTop", stylePaddingTop);
1718
+ // src/core/prepareColumnStartState.ts
1719
+ function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1720
+ var _a3;
1721
+ const numColumns = peek$(ctx, "numColumns");
1722
+ let rowStartIndex = startIndex;
1723
+ const columnAtStart = state.columns.get(state.idCache[startIndex]);
1724
+ if (columnAtStart !== 1) {
1725
+ rowStartIndex = findRowStartIndex(state, numColumns, startIndex);
1323
1726
  }
1324
- if (alignItemsPaddingTop !== void 0) {
1325
- set$(ctx, "alignItemsPaddingTop", alignItemsPaddingTop);
1727
+ let currentRowTop = 0;
1728
+ const curId = state.idCache[rowStartIndex];
1729
+ const column = state.columns.get(curId);
1730
+ if (rowStartIndex > 0) {
1731
+ const prevIndex = rowStartIndex - 1;
1732
+ const prevId = state.idCache[prevIndex];
1733
+ const prevPosition = (_a3 = state.positions.get(prevId)) != null ? _a3 : 0;
1734
+ const prevRowStart = findRowStartIndex(state, numColumns, prevIndex);
1735
+ const prevRowHeight = calculateRowMaxSize(ctx, state, prevRowStart, prevIndex, useAverageSize);
1736
+ currentRowTop = prevPosition + prevRowHeight;
1326
1737
  }
1738
+ return {
1739
+ column,
1740
+ currentRowTop,
1741
+ startIndex: rowStartIndex
1742
+ };
1327
1743
  }
1328
-
1329
- // src/utils/updateAlignItemsPaddingTop.ts
1330
- function updateAlignItemsPaddingTop(ctx, state) {
1331
- const {
1332
- scrollLength,
1333
- props: { alignItemsAtEnd, data }
1334
- } = state;
1335
- if (alignItemsAtEnd) {
1336
- let alignItemsPaddingTop = 0;
1337
- if ((data == null ? void 0 : data.length) > 0) {
1338
- const contentSize = getContentSize(ctx);
1339
- alignItemsPaddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
1744
+ function findRowStartIndex(state, numColumns, index) {
1745
+ if (numColumns <= 1) {
1746
+ return Math.max(0, index);
1747
+ }
1748
+ let rowStart = Math.max(0, index);
1749
+ while (rowStart > 0) {
1750
+ const columnForIndex = state.columns.get(state.idCache[rowStart]);
1751
+ if (columnForIndex === 1) {
1752
+ break;
1753
+ }
1754
+ rowStart--;
1755
+ }
1756
+ return rowStart;
1757
+ }
1758
+ function calculateRowMaxSize(ctx, state, startIndex, endIndex, useAverageSize) {
1759
+ if (endIndex < startIndex) {
1760
+ return 0;
1761
+ }
1762
+ const { data } = state.props;
1763
+ if (!data) {
1764
+ return 0;
1765
+ }
1766
+ let maxSize = 0;
1767
+ for (let i = startIndex; i <= endIndex; i++) {
1768
+ if (i < 0 || i >= data.length) {
1769
+ continue;
1770
+ }
1771
+ const id = state.idCache[i];
1772
+ const size = getItemSize(ctx, state, id, i, data[i], useAverageSize);
1773
+ if (size > maxSize) {
1774
+ maxSize = size;
1340
1775
  }
1341
- setPaddingTop(ctx, state, { alignItemsPaddingTop });
1342
1776
  }
1777
+ return maxSize;
1343
1778
  }
1344
1779
 
1345
1780
  // src/core/updateTotalSize.ts
@@ -1355,7 +1790,7 @@ function updateTotalSize(ctx, state) {
1355
1790
  if (lastId !== void 0) {
1356
1791
  const lastPosition = positions.get(lastId);
1357
1792
  if (lastPosition !== void 0) {
1358
- const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
1793
+ const lastSize = getItemSize(ctx, state, lastId, data.length - 1, data[data.length - 1]);
1359
1794
  if (lastSize !== void 0) {
1360
1795
  const totalSize = lastPosition + lastSize;
1361
1796
  addTotalSize(ctx, state, null, totalSize);
@@ -1364,20 +1799,44 @@ function updateTotalSize(ctx, state) {
1364
1799
  }
1365
1800
  }
1366
1801
  }
1367
- function addTotalSize(ctx, state, key, add) {
1368
- const { alignItemsAtEnd } = state.props;
1369
- {
1370
- state.totalSize = add;
1371
- if (state.timeoutSetPaddingTop) {
1372
- clearTimeout(state.timeoutSetPaddingTop);
1373
- state.timeoutSetPaddingTop = void 0;
1802
+
1803
+ // src/utils/getScrollVelocity.ts
1804
+ var getScrollVelocity = (state) => {
1805
+ const { scrollHistory } = state;
1806
+ let velocity = 0;
1807
+ if (scrollHistory.length >= 1) {
1808
+ const newest = scrollHistory[scrollHistory.length - 1];
1809
+ let oldest;
1810
+ let start = 0;
1811
+ const now = Date.now();
1812
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
1813
+ const entry = scrollHistory[i];
1814
+ const nextEntry = scrollHistory[i + 1];
1815
+ if (i > 0) {
1816
+ const prevEntry = scrollHistory[i - 1];
1817
+ const prevDirection = entry.scroll - prevEntry.scroll;
1818
+ const currentDirection = nextEntry.scroll - entry.scroll;
1819
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1820
+ start = i;
1821
+ break;
1822
+ }
1823
+ }
1824
+ }
1825
+ for (let i = start; i < scrollHistory.length - 1; i++) {
1826
+ const entry = scrollHistory[i];
1827
+ if (now - entry.time <= 1e3) {
1828
+ oldest = entry;
1829
+ break;
1830
+ }
1831
+ }
1832
+ if (oldest && oldest !== newest) {
1833
+ const scrollDiff = newest.scroll - oldest.scroll;
1834
+ const timeDiff = newest.time - oldest.time;
1835
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1374
1836
  }
1375
1837
  }
1376
- set$(ctx, "totalSize", state.totalSize);
1377
- if (alignItemsAtEnd) {
1378
- updateAlignItemsPaddingTop(ctx, state);
1379
- }
1380
- }
1838
+ return velocity;
1839
+ };
1381
1840
 
1382
1841
  // src/utils/updateSnapToOffsets.ts
1383
1842
  function updateSnapToOffsets(ctx, state) {
@@ -1394,9 +1853,14 @@ function updateSnapToOffsets(ctx, state) {
1394
1853
  set$(ctx, "snapToOffsets", snapToOffsets);
1395
1854
  }
1396
1855
 
1397
- // src/core/updateAllPositions.ts
1398
- function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1399
- var _a, _b, _c, _d, _e, _f;
1856
+ // src/core/updateItemPositions.ts
1857
+ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottomBuffered, forceFullUpdate = false, doMVCP } = {
1858
+ doMVCP: false,
1859
+ forceFullUpdate: false,
1860
+ scrollBottomBuffered: -1,
1861
+ startIndex: 0
1862
+ }) {
1863
+ var _a3, _b, _c, _d, _e;
1400
1864
  const {
1401
1865
  columns,
1402
1866
  indexByKey,
@@ -1406,32 +1870,51 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1406
1870
  props: { getEstimatedItemSize, snapToIndices, enableAverages }
1407
1871
  } = state;
1408
1872
  const data = state.props.data;
1873
+ const dataLength = data.length;
1409
1874
  const numColumns = peek$(ctx, "numColumns");
1410
- const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1875
+ const scrollingTo = peek$(ctx, "scrollingTo");
1876
+ const hasColumns = numColumns > 1;
1877
+ const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1878
+ const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1879
+ const maxVisibleArea = scrollBottomBuffered + 1e3;
1411
1880
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1881
+ const preferCachedSize = !doMVCP || dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0;
1412
1882
  let currentRowTop = 0;
1413
1883
  let column = 1;
1414
1884
  let maxSizeInRow = 0;
1415
- const hasColumns = numColumns > 1;
1416
1885
  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
1886
  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);
1887
+ const { startIndex: processedStartIndex, currentRowTop: initialRowTop } = prepareColumnStartState(
1888
+ ctx,
1889
+ state,
1890
+ startIndex,
1891
+ useAverageSize
1892
+ );
1893
+ startIndex = processedStartIndex;
1894
+ currentRowTop = initialRowTop;
1895
+ } else if (startIndex < dataLength) {
1896
+ const prevIndex = startIndex - 1;
1897
+ const prevId = getId(state, prevIndex);
1898
+ const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1899
+ const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1426
1900
  currentRowTop = prevPosition + prevSize;
1427
1901
  }
1428
1902
  }
1429
1903
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1430
- const dataLength = data.length;
1904
+ let didBreakEarly = false;
1905
+ let breakAt;
1431
1906
  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) {
1907
+ if (shouldOptimize && breakAt !== void 0 && i > breakAt) {
1908
+ didBreakEarly = true;
1909
+ break;
1910
+ }
1911
+ if (shouldOptimize && breakAt === void 0 && !scrollingTo && !dataChanged && currentRowTop > maxVisibleArea) {
1912
+ const itemsPerRow = hasColumns ? numColumns : 1;
1913
+ breakAt = i + itemsPerRow + 10;
1914
+ }
1915
+ const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1916
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, state, id, i, data[i], useAverageSize, preferCachedSize);
1917
+ if (IS_DEV && needsIndexByKey) {
1435
1918
  if (indexByKeyForChecking.has(id)) {
1436
1919
  console.error(
1437
1920
  `[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 +1941,9 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1458
1941
  currentRowTop += size;
1459
1942
  }
1460
1943
  }
1461
- updateTotalSize(ctx, state);
1944
+ if (!didBreakEarly) {
1945
+ updateTotalSize(ctx, state);
1946
+ }
1462
1947
  if (snapToIndices) {
1463
1948
  updateSnapToOffsets(ctx, state);
1464
1949
  }
@@ -1478,6 +1963,21 @@ function ensureViewabilityState(ctx, configId) {
1478
1963
  }
1479
1964
  return state;
1480
1965
  }
1966
+ function setupViewability(props) {
1967
+ let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
1968
+ if (viewabilityConfig || onViewableItemsChanged) {
1969
+ viewabilityConfigCallbackPairs = [
1970
+ ...viewabilityConfigCallbackPairs || [],
1971
+ {
1972
+ onViewableItemsChanged,
1973
+ viewabilityConfig: viewabilityConfig || {
1974
+ viewAreaCoveragePercentThreshold: 0
1975
+ }
1976
+ }
1977
+ ];
1978
+ }
1979
+ return viewabilityConfigCallbackPairs;
1980
+ }
1481
1981
  function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
1482
1982
  const {
1483
1983
  timeouts,
@@ -1631,16 +2131,6 @@ function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize,
1631
2131
  const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
1632
2132
  return value.isViewable;
1633
2133
  }
1634
- function findContainerId(ctx, key) {
1635
- const numContainers = peek$(ctx, "numContainers");
1636
- for (let i = 0; i < numContainers; i++) {
1637
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1638
- if (itemKey === key) {
1639
- return i;
1640
- }
1641
- }
1642
- return -1;
1643
- }
1644
2134
  function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1645
2135
  const key = containerId + configId;
1646
2136
  ctx.mapViewabilityValues.set(key, viewToken);
@@ -1649,9 +2139,12 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1649
2139
  }
1650
2140
 
1651
2141
  // src/utils/checkAllSizesKnown.ts
2142
+ function isNullOrUndefined2(value) {
2143
+ return value === null || value === void 0;
2144
+ }
1652
2145
  function checkAllSizesKnown(state) {
1653
2146
  const { startBuffered, endBuffered, sizesKnown } = state;
1654
- if (endBuffered !== null && startBuffered >= 0 && endBuffered >= 0) {
2147
+ if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
1655
2148
  let areAllKnown = true;
1656
2149
  for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1657
2150
  const key = getId(state, i);
@@ -1668,6 +2161,8 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1668
2161
  const { stickyContainerPool, containerItemTypes } = state;
1669
2162
  const result = [];
1670
2163
  const availableContainers = [];
2164
+ const pendingRemovalSet = new Set(pendingRemoval);
2165
+ let pendingRemovalChanged = false;
1671
2166
  const stickyIndicesSet = state.props.stickyIndicesSet;
1672
2167
  const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
1673
2168
  const canReuseContainer = (containerIndex, requiredType) => {
@@ -1683,12 +2178,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1683
2178
  let foundContainer = false;
1684
2179
  for (const containerIndex of stickyContainerPool) {
1685
2180
  const key = peek$(ctx, `containerItemKey${containerIndex}`);
1686
- const isPendingRemoval = pendingRemoval.includes(containerIndex);
1687
- if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType)) {
2181
+ const isPendingRemoval = pendingRemovalSet.has(containerIndex);
2182
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType) && !result.includes(containerIndex)) {
1688
2183
  result.push(containerIndex);
1689
- if (isPendingRemoval) {
1690
- const index = pendingRemoval.indexOf(containerIndex);
1691
- pendingRemoval.splice(index, 1);
2184
+ if (isPendingRemoval && pendingRemovalSet.delete(containerIndex)) {
2185
+ pendingRemovalChanged = true;
1692
2186
  }
1693
2187
  foundContainer = true;
1694
2188
  if (requiredItemTypes) typeIndex++;
@@ -1708,13 +2202,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1708
2202
  }
1709
2203
  const key = peek$(ctx, `containerItemKey${u}`);
1710
2204
  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
- }
2205
+ if (!isOk && pendingRemovalSet.has(u)) {
2206
+ pendingRemovalSet.delete(u);
2207
+ pendingRemovalChanged = true;
2208
+ const requiredType = neededTypes[typeIndex];
2209
+ isOk = canReuseContainer(u, requiredType);
1718
2210
  }
1719
2211
  if (isOk) {
1720
2212
  result.push(u);
@@ -1757,7 +2249,7 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1757
2249
  for (let i = 0; i < stillNeeded; i++) {
1758
2250
  result.push(numContainers + i);
1759
2251
  }
1760
- if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
2252
+ if (IS_DEV && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
1761
2253
  console.warn(
1762
2254
  "[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
2255
  {
@@ -1772,50 +2264,18 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1772
2264
  }
1773
2265
  }
1774
2266
  }
2267
+ if (pendingRemovalChanged) {
2268
+ pendingRemoval.length = 0;
2269
+ for (const value of pendingRemovalSet) {
2270
+ pendingRemoval.push(value);
2271
+ }
2272
+ }
1775
2273
  return result.sort(comparatorDefault);
1776
2274
  }
1777
2275
  function comparatorByDistance(a, b) {
1778
2276
  return b.distance - a.distance;
1779
2277
  }
1780
2278
 
1781
- // src/utils/getScrollVelocity.ts
1782
- var getScrollVelocity = (state) => {
1783
- const { scrollHistory } = state;
1784
- let velocity = 0;
1785
- if (scrollHistory.length >= 1) {
1786
- const newest = scrollHistory[scrollHistory.length - 1];
1787
- let oldest;
1788
- let start = 0;
1789
- const now = Date.now();
1790
- for (let i = 0; i < scrollHistory.length - 1; i++) {
1791
- const entry = scrollHistory[i];
1792
- const nextEntry = scrollHistory[i + 1];
1793
- if (i > 0) {
1794
- const prevEntry = scrollHistory[i - 1];
1795
- const prevDirection = entry.scroll - prevEntry.scroll;
1796
- const currentDirection = nextEntry.scroll - entry.scroll;
1797
- if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1798
- start = i;
1799
- break;
1800
- }
1801
- }
1802
- }
1803
- for (let i = start; i < scrollHistory.length - 1; i++) {
1804
- const entry = scrollHistory[i];
1805
- if (now - entry.time <= 1e3) {
1806
- oldest = entry;
1807
- break;
1808
- }
1809
- }
1810
- if (oldest && oldest !== newest) {
1811
- const scrollDiff = newest.scroll - oldest.scroll;
1812
- const timeDiff = newest.time - oldest.time;
1813
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1814
- }
1815
- }
1816
- return velocity;
1817
- };
1818
-
1819
2279
  // src/core/scrollToIndex.ts
1820
2280
  function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1821
2281
  if (index >= state.props.data.length) {
@@ -1828,72 +2288,16 @@ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, vie
1828
2288
  if (isLast && viewPosition === void 0) {
1829
2289
  viewPosition = 1;
1830
2290
  }
1831
- const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1832
2291
  state.scrollForNextCalculateItemsInView = void 0;
1833
- scrollTo(state, {
2292
+ scrollTo(ctx, state, {
1834
2293
  animated,
1835
2294
  index,
1836
- offset: firstIndexScrollPostion,
2295
+ offset: firstIndexOffset,
1837
2296
  viewOffset,
1838
2297
  viewPosition: viewPosition != null ? viewPosition : 0
1839
2298
  });
1840
2299
  }
1841
2300
 
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
2301
  // src/utils/setDidLayout.ts
1898
2302
  function setDidLayout(ctx, state) {
1899
2303
  const {
@@ -1916,11 +2320,12 @@ function setDidLayout(ctx, state) {
1916
2320
 
1917
2321
  // src/core/calculateItemsInView.ts
1918
2322
  function findCurrentStickyIndex(stickyArray, scroll, state) {
1919
- var _a;
2323
+ var _a3;
1920
2324
  const idCache = state.idCache;
1921
2325
  const positions = state.positions;
1922
2326
  for (let i = stickyArray.length - 1; i >= 0; i--) {
1923
- const stickyId = (_a = idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
2327
+ const stickyIndex = stickyArray[i];
2328
+ const stickyId = (_a3 = idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
1924
2329
  const stickyPos = stickyId ? positions.get(stickyId) : void 0;
1925
2330
  if (stickyPos !== void 0 && scroll >= stickyPos) {
1926
2331
  return i;
@@ -1928,47 +2333,51 @@ function findCurrentStickyIndex(stickyArray, scroll, state) {
1928
2333
  }
1929
2334
  return -1;
1930
2335
  }
1931
- function getActiveStickyIndices(ctx, state, stickyIndices) {
2336
+ function getActiveStickyIndices(ctx, state, stickyHeaderIndices) {
1932
2337
  return new Set(
1933
- 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))
2338
+ Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyHeaderIndices.has(idx))
1934
2339
  );
1935
2340
  }
1936
- function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll, needNewContainers, startBuffered, endBuffered) {
1937
- var _a;
1938
- const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
1939
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
2341
+ function handleStickyActivation(ctx, state, stickyHeaderIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
2342
+ var _a3;
2343
+ const activeIndices = getActiveStickyIndices(ctx, state, stickyHeaderIndices);
2344
+ state.activeStickyIndex = currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : void 0;
1940
2345
  for (let offset = 0; offset <= 1; offset++) {
1941
2346
  const idx = currentStickyIdx - offset;
1942
2347
  if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
1943
2348
  const stickyIndex = stickyArray[idx];
1944
- const stickyId = (_a = state.idCache.get(stickyIndex)) != null ? _a : getId(state, stickyIndex);
2349
+ const stickyId = (_a3 = state.idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
1945
2350
  if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered)) {
1946
2351
  needNewContainers.push(stickyIndex);
1947
2352
  }
1948
2353
  }
1949
2354
  }
1950
- function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pendingRemoval) {
1951
- var _a, _b, _c;
1952
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
2355
+ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
2356
+ var _a3, _b, _c;
1953
2357
  for (const containerIndex of state.stickyContainerPool) {
1954
2358
  const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
1955
2359
  const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
1956
2360
  if (itemIndex === void 0) continue;
1957
2361
  const arrayIdx = stickyArray.indexOf(itemIndex);
1958
- if (arrayIdx === -1) continue;
2362
+ if (arrayIdx === -1) {
2363
+ state.stickyContainerPool.delete(containerIndex);
2364
+ set$(ctx, `containerSticky${containerIndex}`, false);
2365
+ set$(ctx, `containerStickyOffset${containerIndex}`, void 0);
2366
+ continue;
2367
+ }
1959
2368
  const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
1960
2369
  if (isRecentSticky) continue;
1961
2370
  const nextIndex = stickyArray[arrayIdx + 1];
1962
2371
  let shouldRecycle = false;
1963
2372
  if (nextIndex) {
1964
- const nextId = (_a = state.idCache.get(nextIndex)) != null ? _a : getId(state, nextIndex);
2373
+ const nextId = (_a3 = state.idCache[nextIndex]) != null ? _a3 : getId(state, nextIndex);
1965
2374
  const nextPos = nextId ? state.positions.get(nextId) : void 0;
1966
2375
  shouldRecycle = nextPos !== void 0 && scroll > nextPos + scrollBuffer * 2;
1967
2376
  } else {
1968
- const currentId = (_b = state.idCache.get(itemIndex)) != null ? _b : getId(state, itemIndex);
2377
+ const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
1969
2378
  if (currentId) {
1970
2379
  const currentPos = state.positions.get(currentId);
1971
- const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
2380
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(ctx, state, currentId, itemIndex, state.props.data[itemIndex]);
1972
2381
  shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
1973
2382
  }
1974
2383
  }
@@ -1979,61 +2388,52 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pe
1979
2388
  }
1980
2389
  function calculateItemsInView(ctx, state, params = {}) {
1981
2390
  reactDom.unstable_batchedUpdates(() => {
1982
- var _a, _b, _c, _d, _e, _f, _g, _h;
2391
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
1983
2392
  const {
1984
2393
  columns,
1985
2394
  containerItemKeys,
1986
2395
  enableScrollForNextCalculateItemsInView,
1987
2396
  idCache,
1988
2397
  indexByKey,
2398
+ initialScroll,
1989
2399
  minIndexSizeChanged,
1990
2400
  positions,
2401
+ props: { getItemType, itemsAreEqual, keyExtractor, onStickyHeaderChange, scrollBuffer },
1991
2402
  scrollForNextCalculateItemsInView,
1992
2403
  scrollLength,
1993
2404
  sizes,
1994
2405
  startBufferedId: startBufferedIdOrig,
1995
- viewabilityConfigCallbackPairs,
1996
- props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, scrollBuffer }
2406
+ viewabilityConfigCallbackPairs
1997
2407
  } = state;
1998
2408
  const { data } = state.props;
1999
2409
  const stickyIndicesArr = state.props.stickyIndicesArr || [];
2000
2410
  const stickyIndicesSet = state.props.stickyIndicesSet || /* @__PURE__ */ new Set();
2001
2411
  const prevNumContainers = peek$(ctx, "numContainers");
2002
2412
  if (!data || scrollLength === 0 || !prevNumContainers) {
2413
+ if (state.initialAnchor) {
2414
+ ensureInitialAnchor(ctx, state);
2415
+ }
2003
2416
  return;
2004
2417
  }
2005
- const totalSize = peek$(ctx, "totalSize");
2418
+ const totalSize = getContentSize(ctx);
2006
2419
  const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
2007
2420
  const numColumns = peek$(ctx, "numColumns");
2008
- const previousScrollAdjust = 0;
2009
- const { dataChanged, doMVCP } = params;
2421
+ const { dataChanged, doMVCP, forceFullItemPositions } = params;
2010
2422
  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
2423
  const scrollExtra = 0;
2026
2424
  const { queuedInitialLayout } = state;
2027
2425
  let { scroll: scrollState } = state;
2028
2426
  if (!queuedInitialLayout && initialScroll) {
2029
2427
  const updatedOffset = calculateOffsetWithOffsetPosition(
2428
+ ctx,
2030
2429
  state,
2031
2430
  calculateOffsetForIndex(ctx, state, initialScroll.index),
2032
2431
  initialScroll
2033
2432
  );
2034
2433
  scrollState = updatedOffset;
2035
2434
  }
2036
- const scrollAdjustPad = -previousScrollAdjust - topPad;
2435
+ const scrollAdjustPending = (_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0;
2436
+ const scrollAdjustPad = scrollAdjustPending - topPad;
2037
2437
  let scroll = scrollState + scrollExtra + scrollAdjustPad;
2038
2438
  if (scroll + scrollLength > totalSize) {
2039
2439
  scroll = Math.max(0, totalSize - scrollLength);
@@ -2042,6 +2442,11 @@ function calculateItemsInView(ctx, state, params = {}) {
2042
2442
  set$(ctx, "debugRawScroll", scrollState);
2043
2443
  set$(ctx, "debugComputedScroll", scroll);
2044
2444
  }
2445
+ const previousStickyIndex = state.activeStickyIndex;
2446
+ const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
2447
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : void 0;
2448
+ state.activeStickyIndex = nextActiveStickyIndex;
2449
+ set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
2045
2450
  let scrollBufferTop = scrollBuffer;
2046
2451
  let scrollBufferBottom = scrollBuffer;
2047
2452
  if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
@@ -2054,22 +2459,42 @@ function calculateItemsInView(ctx, state, params = {}) {
2054
2459
  const scrollTopBuffered = scroll - scrollBufferTop;
2055
2460
  const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
2056
2461
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
2057
- if (scrollForNextCalculateItemsInView) {
2462
+ if (!dataChanged && scrollForNextCalculateItemsInView) {
2058
2463
  const { top, bottom } = scrollForNextCalculateItemsInView;
2059
2464
  if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
2465
+ if (state.initialAnchor) {
2466
+ ensureInitialAnchor(ctx, state);
2467
+ }
2060
2468
  return;
2061
2469
  }
2062
2470
  }
2471
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
2472
+ if (dataChanged) {
2473
+ indexByKey.clear();
2474
+ idCache.length = 0;
2475
+ positions.clear();
2476
+ }
2477
+ const startIndex = dataChanged ? 0 : (_b = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _b : 0;
2478
+ updateItemPositions(ctx, state, dataChanged, {
2479
+ doMVCP,
2480
+ forceFullUpdate: !!forceFullItemPositions,
2481
+ scrollBottomBuffered,
2482
+ startIndex
2483
+ });
2484
+ if (minIndexSizeChanged !== void 0) {
2485
+ state.minIndexSizeChanged = void 0;
2486
+ }
2487
+ checkMVCP == null ? void 0 : checkMVCP();
2063
2488
  let startNoBuffer = null;
2064
2489
  let startBuffered = null;
2065
2490
  let startBufferedId = null;
2066
2491
  let endNoBuffer = null;
2067
2492
  let endBuffered = null;
2068
- let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2493
+ let loopStart = !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2069
2494
  for (let i = loopStart; i >= 0; i--) {
2070
- const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
2495
+ const id = (_c = idCache[i]) != null ? _c : getId(state, i);
2071
2496
  const top = positions.get(id);
2072
- const size = (_b = sizes.get(id)) != null ? _b : getItemSize(state, id, i, data[i]);
2497
+ const size = (_d = sizes.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i]);
2073
2498
  const bottom = top + size;
2074
2499
  if (bottom > scroll - scrollBuffer) {
2075
2500
  loopStart = i;
@@ -2095,8 +2520,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2095
2520
  let firstFullyOnScreenIndex;
2096
2521
  const dataLength = data.length;
2097
2522
  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]);
2523
+ const id = (_e = idCache[i]) != null ? _e : getId(state, i);
2524
+ const size = (_f = sizes.get(id)) != null ? _f : getItemSize(ctx, state, id, i, data[i]);
2100
2525
  const top = positions.get(id);
2101
2526
  if (!foundEnd) {
2102
2527
  if (startNoBuffer === null && top + size > scroll) {
@@ -2125,7 +2550,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2125
2550
  }
2126
2551
  const idsInView = [];
2127
2552
  for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
2128
- const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
2553
+ const id = (_g = idCache[i]) != null ? _g : getId(state, i);
2129
2554
  idsInView.push(id);
2130
2555
  }
2131
2556
  Object.assign(state, {
@@ -2157,7 +2582,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2157
2582
  let numContainers2 = prevNumContainers;
2158
2583
  const needNewContainers = [];
2159
2584
  for (let i = startBuffered; i <= endBuffered; i++) {
2160
- const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
2585
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
2161
2586
  if (!containerItemKeys.has(id)) {
2162
2587
  needNewContainers.push(i);
2163
2588
  }
@@ -2168,11 +2593,14 @@ function calculateItemsInView(ctx, state, params = {}) {
2168
2593
  state,
2169
2594
  stickyIndicesSet,
2170
2595
  stickyIndicesArr,
2171
- scroll,
2596
+ currentStickyIdx,
2172
2597
  needNewContainers,
2173
2598
  startBuffered,
2174
2599
  endBuffered
2175
2600
  );
2601
+ } else {
2602
+ state.activeStickyIndex = void 0;
2603
+ set$(ctx, "activeStickyIndex", void 0);
2176
2604
  }
2177
2605
  if (needNewContainers.length > 0) {
2178
2606
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
@@ -2192,7 +2620,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2192
2620
  for (let idx = 0; idx < needNewContainers.length; idx++) {
2193
2621
  const i = needNewContainers[idx];
2194
2622
  const containerIndex = availableContainers[idx];
2195
- const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
2623
+ const id = (_i = idCache[i]) != null ? _i : getId(state, i);
2196
2624
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
2197
2625
  if (oldKey && oldKey !== id) {
2198
2626
  containerItemKeys.delete(oldKey);
@@ -2206,9 +2634,10 @@ function calculateItemsInView(ctx, state, params = {}) {
2206
2634
  if (stickyIndicesSet.has(i)) {
2207
2635
  set$(ctx, `containerSticky${containerIndex}`, true);
2208
2636
  const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2209
- set$(ctx, `containerStickyOffset${containerIndex}`, createAnimatedValue(topPadding));
2637
+ set$(ctx, `containerStickyOffset${containerIndex}`, topPadding);
2210
2638
  state.stickyContainerPool.add(containerIndex);
2211
2639
  } else {
2640
+ set$(ctx, `containerSticky${containerIndex}`, false);
2212
2641
  state.stickyContainerPool.delete(containerIndex);
2213
2642
  }
2214
2643
  if (containerIndex >= numContainers2) {
@@ -2224,13 +2653,13 @@ function calculateItemsInView(ctx, state, params = {}) {
2224
2653
  }
2225
2654
  }
2226
2655
  if (stickyIndicesArr.length > 0) {
2227
- handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, pendingRemoval);
2656
+ handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2228
2657
  }
2229
2658
  let didChangePositions = false;
2230
2659
  for (let i = 0; i < numContainers; i++) {
2231
2660
  const itemKey = peek$(ctx, `containerItemKey${i}`);
2232
2661
  if (pendingRemoval.includes(i)) {
2233
- if (itemKey) {
2662
+ if (itemKey !== void 0) {
2234
2663
  containerItemKeys.delete(itemKey);
2235
2664
  }
2236
2665
  state.containerItemTypes.delete(i);
@@ -2247,11 +2676,12 @@ function calculateItemsInView(ctx, state, params = {}) {
2247
2676
  const itemIndex = indexByKey.get(itemKey);
2248
2677
  const item = data[itemIndex];
2249
2678
  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) {
2679
+ const id = (_j = idCache[itemIndex]) != null ? _j : getId(state, itemIndex);
2680
+ const positionValue = positions.get(id);
2681
+ if (positionValue === void 0) {
2253
2682
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2254
2683
  } else {
2684
+ const position = (positionValue || 0) - scrollAdjustPending;
2255
2685
  const column = columns.get(id) || 1;
2256
2686
  const prevPos = peek$(ctx, `containerPosition${i}`);
2257
2687
  const prevColumn = peek$(ctx, `containerColumn${i}`);
@@ -2264,29 +2694,161 @@ function calculateItemsInView(ctx, state, params = {}) {
2264
2694
  set$(ctx, `containerColumn${i}`, column);
2265
2695
  }
2266
2696
  if (prevData !== item && (itemsAreEqual ? !itemsAreEqual(prevData, item, itemIndex, data) : true)) {
2267
- set$(ctx, `containerItemData${i}`, data[itemIndex]);
2697
+ set$(ctx, `containerItemData${i}`, item);
2268
2698
  }
2269
2699
  }
2270
2700
  }
2271
2701
  }
2272
2702
  }
2273
- if (didChangePositions) {
2274
- set$(ctx, "lastPositionUpdate", Date.now());
2275
- }
2276
- if (!queuedInitialLayout && endBuffered !== null) {
2277
- if (checkAllSizesKnown(state)) {
2278
- setDidLayout(ctx, state);
2279
- }
2280
- }
2281
- if (viewabilityConfigCallbackPairs) {
2282
- updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
2703
+ if (didChangePositions) {
2704
+ set$(ctx, "lastPositionUpdate", Date.now());
2705
+ }
2706
+ if (!queuedInitialLayout && endBuffered !== null) {
2707
+ if (checkAllSizesKnown(state)) {
2708
+ setDidLayout(ctx, state);
2709
+ }
2710
+ }
2711
+ if (viewabilityConfigCallbackPairs) {
2712
+ updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
2713
+ }
2714
+ if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
2715
+ const item = data[nextActiveStickyIndex];
2716
+ if (item !== void 0) {
2717
+ onStickyHeaderChange({ index: nextActiveStickyIndex, item });
2718
+ }
2719
+ }
2720
+ });
2721
+ if (state.initialAnchor) {
2722
+ ensureInitialAnchor(ctx, state);
2723
+ }
2724
+ }
2725
+
2726
+ // src/core/checkActualChange.ts
2727
+ function checkActualChange(state, dataProp, previousData) {
2728
+ if (!previousData || !dataProp || dataProp.length !== previousData.length) {
2729
+ return true;
2730
+ }
2731
+ const {
2732
+ idCache,
2733
+ props: { keyExtractor }
2734
+ } = state;
2735
+ for (let i = 0; i < dataProp.length; i++) {
2736
+ if (dataProp[i] !== previousData[i]) {
2737
+ return true;
2738
+ }
2739
+ if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
2740
+ return true;
2741
+ }
2742
+ }
2743
+ return false;
2744
+ }
2745
+
2746
+ // src/core/doMaintainScrollAtEnd.ts
2747
+ function doMaintainScrollAtEnd(ctx, state, animated) {
2748
+ const {
2749
+ refScroller,
2750
+ props: { maintainScrollAtEnd }
2751
+ } = state;
2752
+ if ((state == null ? void 0 : state.isAtEnd) && maintainScrollAtEnd && peek$(ctx, "containersDidLayout")) {
2753
+ const paddingTop = peek$(ctx, "alignItemsPaddingTop");
2754
+ if (paddingTop > 0) {
2755
+ state.scroll = 0;
2756
+ }
2757
+ requestAnimationFrame(() => {
2758
+ var _a3;
2759
+ if (state == null ? void 0 : state.isAtEnd) {
2760
+ state.maintainingScrollAtEnd = true;
2761
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
2762
+ animated
2763
+ });
2764
+ setTimeout(
2765
+ () => {
2766
+ state.maintainingScrollAtEnd = false;
2767
+ },
2768
+ 0
2769
+ );
2770
+ }
2771
+ });
2772
+ return true;
2773
+ }
2774
+ return false;
2775
+ }
2776
+
2777
+ // src/utils/updateAveragesOnDataChange.ts
2778
+ function updateAveragesOnDataChange(state, oldData, newData) {
2779
+ var _a3;
2780
+ const {
2781
+ averageSizes,
2782
+ sizesKnown,
2783
+ indexByKey,
2784
+ props: { itemsAreEqual, getItemType, keyExtractor }
2785
+ } = state;
2786
+ if (!itemsAreEqual || !oldData.length || !newData.length) {
2787
+ for (const key in averageSizes) {
2788
+ delete averageSizes[key];
2789
+ }
2790
+ return;
2791
+ }
2792
+ const itemTypesToPreserve = {};
2793
+ const newDataLength = newData.length;
2794
+ const oldDataLength = oldData.length;
2795
+ for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
2796
+ const newItem = newData[newIndex];
2797
+ const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
2798
+ const oldIndex = indexByKey.get(id);
2799
+ if (oldIndex !== void 0 && oldIndex < oldDataLength) {
2800
+ const knownSize = sizesKnown.get(id);
2801
+ if (knownSize === void 0) continue;
2802
+ const oldItem = oldData[oldIndex];
2803
+ const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
2804
+ if (areEqual) {
2805
+ const itemType = getItemType ? (_a3 = getItemType(newItem, newIndex)) != null ? _a3 : "" : "";
2806
+ let typeData = itemTypesToPreserve[itemType];
2807
+ if (!typeData) {
2808
+ typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
2809
+ }
2810
+ typeData.totalSize += knownSize;
2811
+ typeData.count++;
2812
+ }
2813
+ }
2814
+ }
2815
+ for (const key in averageSizes) {
2816
+ delete averageSizes[key];
2817
+ }
2818
+ for (const itemType in itemTypesToPreserve) {
2819
+ const { totalSize, count } = itemTypesToPreserve[itemType];
2820
+ if (count > 0) {
2821
+ averageSizes[itemType] = {
2822
+ avg: totalSize / count,
2823
+ num: count
2824
+ };
2283
2825
  }
2284
- });
2826
+ }
2827
+ }
2828
+
2829
+ // src/core/checkResetContainers.ts
2830
+ function checkResetContainers(ctx, state, dataProp) {
2831
+ const { previousData } = state;
2832
+ if (previousData) {
2833
+ updateAveragesOnDataChange(state, previousData, dataProp);
2834
+ }
2835
+ const { maintainScrollAtEnd } = state.props;
2836
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2837
+ const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
2838
+ const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state, false);
2839
+ if (!didMaintainScrollAtEnd && previousData && dataProp.length > previousData.length) {
2840
+ state.isEndReached = false;
2841
+ }
2842
+ if (!didMaintainScrollAtEnd) {
2843
+ checkAtTop(state);
2844
+ checkAtBottom(ctx, state);
2845
+ }
2846
+ delete state.previousData;
2285
2847
  }
2286
2848
 
2287
2849
  // src/core/doInitialAllocateContainers.ts
2288
2850
  function doInitialAllocateContainers(ctx, state) {
2289
- var _a;
2851
+ var _a3, _b, _c;
2290
2852
  const {
2291
2853
  scrollLength,
2292
2854
  props: {
@@ -2302,12 +2864,13 @@ function doInitialAllocateContainers(ctx, state) {
2302
2864
  const hasContainers = peek$(ctx, "numContainers");
2303
2865
  if (scrollLength > 0 && data.length > 0 && !hasContainers) {
2304
2866
  let averageItemSize;
2305
- const fn = getFixedItemSize || getEstimatedItemSize;
2306
- if (fn) {
2867
+ if (getFixedItemSize || getEstimatedItemSize) {
2307
2868
  let totalSize = 0;
2308
2869
  const num = Math.min(20, data.length);
2309
2870
  for (let i = 0; i < num; i++) {
2310
- totalSize += fn(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "");
2871
+ const item = data[i];
2872
+ const itemType = getItemType ? (_a3 = getItemType(item, i)) != null ? _a3 : "" : "";
2873
+ 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
2874
  }
2312
2875
  averageItemSize = totalSize / num;
2313
2876
  } else {
@@ -2321,76 +2884,18 @@ function doInitialAllocateContainers(ctx, state) {
2321
2884
  set$(ctx, "numContainers", numContainers);
2322
2885
  set$(ctx, "numContainersPooled", numContainers * state.props.initialContainerPoolRatio);
2323
2886
  if (state.lastLayout) {
2324
- if (state.props.initialScroll) {
2887
+ if (state.initialScroll) {
2325
2888
  requestAnimationFrame(() => {
2326
- calculateItemsInView(ctx, state, { dataChanged: true });
2889
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2327
2890
  });
2328
2891
  } else {
2329
- calculateItemsInView(ctx, state, { dataChanged: true });
2892
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2330
2893
  }
2331
2894
  }
2332
2895
  return true;
2333
2896
  }
2334
2897
  }
2335
2898
 
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
2899
  // src/core/handleLayout.ts
2395
2900
  function handleLayout(ctx, state, layout, setCanRender) {
2396
2901
  const { maintainScrollAtEnd } = state.props;
@@ -2425,19 +2930,19 @@ function handleLayout(ctx, state, layout, setCanRender) {
2425
2930
  if (state) {
2426
2931
  state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2427
2932
  }
2428
- if (__DEV__ && measuredLength === 0) {
2933
+ if (IS_DEV && measuredLength === 0) {
2429
2934
  warnDevOnce(
2430
2935
  "height0",
2431
2936
  `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
2937
  );
2433
2938
  }
2434
- setCanRender(true);
2435
2939
  }
2940
+ setCanRender(true);
2436
2941
  }
2437
2942
 
2438
2943
  // src/core/onScroll.ts
2439
2944
  function onScroll(ctx, state, event) {
2440
- var _a, _b, _c;
2945
+ var _a3, _b, _c;
2441
2946
  const {
2442
2947
  scrollProcessingEnabled,
2443
2948
  props: { onScroll: onScrollProp }
@@ -2445,67 +2950,51 @@ function onScroll(ctx, state, event) {
2445
2950
  if (scrollProcessingEnabled === false) {
2446
2951
  return;
2447
2952
  }
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) {
2953
+ 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) {
2449
2954
  return;
2450
2955
  }
2451
2956
  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
2957
  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
- }
2958
+ updateScroll(ctx, state, newScroll);
2469
2959
  onScrollProp == null ? void 0 : onScrollProp(event);
2470
2960
  }
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
- }
2492
- }
2493
2961
 
2494
2962
  // src/core/ScrollAdjustHandler.ts
2495
2963
  var ScrollAdjustHandler = class {
2496
2964
  constructor(ctx) {
2497
2965
  this.appliedAdjust = 0;
2966
+ this.pendingAdjust = 0;
2498
2967
  this.mounted = false;
2499
2968
  this.context = ctx;
2969
+ {
2970
+ const commitPendingAdjust = () => {
2971
+ const state = this.context.internalState;
2972
+ const pending = this.pendingAdjust;
2973
+ if (pending !== 0) {
2974
+ this.pendingAdjust = 0;
2975
+ this.appliedAdjust += pending;
2976
+ state.scroll += pending;
2977
+ state.scrollForNextCalculateItemsInView = void 0;
2978
+ set$(this.context, "scrollAdjustPending", 0);
2979
+ set$(this.context, "scrollAdjust", this.appliedAdjust);
2980
+ calculateItemsInView(this.context, this.context.internalState);
2981
+ }
2982
+ };
2983
+ listen$(this.context, "scrollingTo", (value) => {
2984
+ if (value === void 0) {
2985
+ commitPendingAdjust();
2986
+ }
2987
+ });
2988
+ }
2500
2989
  }
2501
2990
  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();
2991
+ const scrollingTo = peek$(this.context, "scrollingTo");
2992
+ if ((scrollingTo == null ? void 0 : scrollingTo.animated) && !scrollingTo.isInitialScroll) {
2993
+ this.pendingAdjust += add;
2994
+ set$(this.context, "scrollAdjustPending", this.pendingAdjust);
2507
2995
  } else {
2508
- requestAnimationFrame(set);
2996
+ this.appliedAdjust += add;
2997
+ set$(this.context, "scrollAdjust", this.appliedAdjust);
2509
2998
  }
2510
2999
  }
2511
3000
  setMounted() {
@@ -2518,14 +3007,13 @@ var ScrollAdjustHandler = class {
2518
3007
 
2519
3008
  // src/core/updateItemSize.ts
2520
3009
  function updateItemSize(ctx, state, itemKey, sizeObj) {
2521
- var _a, _b;
3010
+ var _a3;
2522
3011
  const {
2523
3012
  sizesKnown,
2524
3013
  props: {
2525
3014
  getFixedItemSize,
2526
3015
  getItemType,
2527
3016
  horizontal,
2528
- maintainVisibleContentPosition,
2529
3017
  suggestEstimatedItemSize,
2530
3018
  onItemSizeChanged,
2531
3019
  data,
@@ -2533,17 +3021,17 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2533
3021
  }
2534
3022
  } = state;
2535
3023
  if (!data) return;
3024
+ const index = state.indexByKey.get(itemKey);
2536
3025
  if (getFixedItemSize) {
2537
- const index2 = state.indexByKey.get(itemKey);
2538
- if (index2 === void 0) {
3026
+ if (index === void 0) {
2539
3027
  return;
2540
3028
  }
2541
- const itemData = state.props.data[index2];
3029
+ const itemData = state.props.data[index];
2542
3030
  if (itemData === void 0) {
2543
3031
  return;
2544
3032
  }
2545
- const type = getItemType ? (_a = getItemType(itemData, index2)) != null ? _a : "" : "";
2546
- const size2 = getFixedItemSize(index2, itemData, type);
3033
+ const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
3034
+ const size2 = getFixedItemSize(index, itemData, type);
2547
3035
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
2548
3036
  return;
2549
3037
  }
@@ -2553,15 +3041,11 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2553
3041
  let shouldMaintainScrollAtEnd = false;
2554
3042
  let minIndexSizeChanged;
2555
3043
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2556
- const index = state.indexByKey.get(itemKey);
2557
3044
  const prevSizeKnown = state.sizesKnown.get(itemKey);
2558
- const diff = updateOneItemSize(state, itemKey, sizeObj);
2559
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
3045
+ const diff = updateOneItemSize(ctx, state, itemKey, sizeObj);
3046
+ const size = roundSize(horizontal ? sizeObj.width : sizeObj.height);
2560
3047
  if (diff !== 0) {
2561
3048
  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
3049
  const { startBuffered, endBuffered } = state;
2566
3050
  needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2567
3051
  if (!needsRecalculate) {
@@ -2591,13 +3075,13 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2591
3075
  if (minIndexSizeChanged !== void 0) {
2592
3076
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
2593
3077
  }
2594
- if (__DEV__ && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
3078
+ if (IS_DEV && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
2595
3079
  if (state.timeoutSizeMessage) clearTimeout(state.timeoutSizeMessage);
2596
3080
  state.timeoutSizeMessage = setTimeout(() => {
2597
- var _a2;
3081
+ var _a4;
2598
3082
  state.timeoutSizeMessage = void 0;
2599
3083
  const num = state.sizesKnown.size;
2600
- const avg = (_a2 = state.averageSizes[""]) == null ? void 0 : _a2.avg;
3084
+ const avg = (_a4 = state.averageSizes[""]) == null ? void 0 : _a4.avg;
2601
3085
  console.warn(
2602
3086
  `[legend-list] Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`
2603
3087
  );
@@ -2619,8 +3103,8 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2619
3103
  }
2620
3104
  }
2621
3105
  }
2622
- function updateOneItemSize(state, itemKey, sizeObj) {
2623
- var _a;
3106
+ function updateOneItemSize(ctx, state, itemKey, sizeObj) {
3107
+ var _a3;
2624
3108
  const {
2625
3109
  sizes,
2626
3110
  indexByKey,
@@ -2630,12 +3114,12 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2630
3114
  } = state;
2631
3115
  if (!data) return 0;
2632
3116
  const index = indexByKey.get(itemKey);
2633
- const prevSize = getItemSize(state, itemKey, index, data);
3117
+ const prevSize = getItemSize(ctx, state, itemKey, index, data[index]);
2634
3118
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
2635
3119
  const size = Math.round(rawSize) ;
2636
3120
  sizesKnown.set(itemKey, size);
2637
3121
  if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
2638
- const itemType = getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : "";
3122
+ const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
2639
3123
  let averages = averageSizes[itemType];
2640
3124
  if (!averages) {
2641
3125
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -2644,13 +3128,13 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2644
3128
  averages.num++;
2645
3129
  }
2646
3130
  if (!prevSize || Math.abs(prevSize - size) > 0.1) {
2647
- sizes.set(itemKey, size);
3131
+ setSize(ctx, state, itemKey, size);
2648
3132
  return size - prevSize;
2649
3133
  }
2650
3134
  return 0;
2651
3135
  }
2652
3136
  var useCombinedRef = (...refs) => {
2653
- const callback = React4.useCallback((element) => {
3137
+ const callback = React3.useCallback((element) => {
2654
3138
  for (const ref of refs) {
2655
3139
  if (!ref) {
2656
3140
  continue;
@@ -2666,18 +3150,12 @@ var useCombinedRef = (...refs) => {
2666
3150
  };
2667
3151
 
2668
3152
  // src/platform/RefreshControl.tsx
2669
- function RefreshControl(props) {
3153
+ function RefreshControl(_props) {
2670
3154
  return null;
2671
3155
  }
2672
3156
 
2673
- // src/platform/StyleSheet.tsx
2674
- var StyleSheet = {
2675
- create: (styles) => styles,
2676
- flatten: (style) => style
2677
- };
2678
-
2679
3157
  // src/platform/useStickyScrollHandler.ts
2680
- function useStickyScrollHandler(stickyIndices, horizontal, ctx, onScroll2) {
3158
+ function useStickyScrollHandler(_stickyHeaderIndices, _horizontal, _ctx, onScroll2) {
2681
3159
  return onScroll2;
2682
3160
  }
2683
3161
 
@@ -2695,8 +3173,93 @@ function createColumnWrapperStyle(contentContainerStyle) {
2695
3173
  };
2696
3174
  }
2697
3175
  }
3176
+
3177
+ // src/utils/createImperativeHandle.ts
3178
+ function createImperativeHandle(ctx, state) {
3179
+ const scrollIndexIntoView = (options) => {
3180
+ if (state) {
3181
+ const { index, ...rest } = options;
3182
+ const { startNoBuffer, endNoBuffer } = state;
3183
+ if (index < startNoBuffer || index > endNoBuffer) {
3184
+ const viewPosition = index < startNoBuffer ? 0 : 1;
3185
+ scrollToIndex(ctx, state, {
3186
+ ...rest,
3187
+ index,
3188
+ viewPosition
3189
+ });
3190
+ }
3191
+ }
3192
+ };
3193
+ const refScroller = state.refScroller;
3194
+ return {
3195
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
3196
+ getNativeScrollRef: () => refScroller.current,
3197
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
3198
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
3199
+ getState: () => ({
3200
+ activeStickyIndex: state.activeStickyIndex,
3201
+ contentLength: state.totalSize,
3202
+ data: state.props.data,
3203
+ elementAtIndex: (index) => {
3204
+ var _a3;
3205
+ return (_a3 = ctx.viewRefs.get(findContainerId(ctx, getId(state, index)))) == null ? void 0 : _a3.current;
3206
+ },
3207
+ end: state.endNoBuffer,
3208
+ endBuffered: state.endBuffered,
3209
+ isAtEnd: state.isAtEnd,
3210
+ isAtStart: state.isAtStart,
3211
+ positionAtIndex: (index) => state.positions.get(getId(state, index)),
3212
+ positions: state.positions,
3213
+ scroll: state.scroll,
3214
+ scrollLength: state.scrollLength,
3215
+ sizeAtIndex: (index) => state.sizesKnown.get(getId(state, index)),
3216
+ sizes: state.sizesKnown,
3217
+ start: state.startNoBuffer,
3218
+ startBuffered: state.startBuffered
3219
+ }),
3220
+ scrollIndexIntoView,
3221
+ scrollItemIntoView: ({ item, ...props }) => {
3222
+ const data = state.props.data;
3223
+ const index = data.indexOf(item);
3224
+ if (index !== -1) {
3225
+ scrollIndexIntoView({ index, ...props });
3226
+ }
3227
+ },
3228
+ scrollToEnd: (options) => {
3229
+ const data = state.props.data;
3230
+ const stylePaddingBottom = state.props.stylePaddingBottom;
3231
+ const index = data.length - 1;
3232
+ if (index !== -1) {
3233
+ const paddingBottom = stylePaddingBottom || 0;
3234
+ const footerSize = peek$(ctx, "footerSize") || 0;
3235
+ scrollToIndex(ctx, state, {
3236
+ index,
3237
+ viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
3238
+ viewPosition: 1,
3239
+ ...options
3240
+ });
3241
+ }
3242
+ },
3243
+ scrollToIndex: (params) => scrollToIndex(ctx, state, params),
3244
+ scrollToItem: ({ item, ...props }) => {
3245
+ const data = state.props.data;
3246
+ const index = data.indexOf(item);
3247
+ if (index !== -1) {
3248
+ scrollToIndex(ctx, state, { index, ...props });
3249
+ }
3250
+ },
3251
+ scrollToOffset: (params) => scrollTo(ctx, state, params),
3252
+ setScrollProcessingEnabled: (enabled) => {
3253
+ state.scrollProcessingEnabled = enabled;
3254
+ },
3255
+ setVisibleContentAnchorOffset: (value) => {
3256
+ const val = isFunction(value) ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
3257
+ set$(ctx, "scrollAdjustUserOffset", val);
3258
+ }
3259
+ };
3260
+ }
2698
3261
  function getRenderedItem(ctx, state, key) {
2699
- var _a;
3262
+ var _a3;
2700
3263
  if (!state) {
2701
3264
  return null;
2702
3265
  }
@@ -2709,29 +3272,31 @@ function getRenderedItem(ctx, state, key) {
2709
3272
  return null;
2710
3273
  }
2711
3274
  let renderedItem = null;
2712
- if (renderItem && data[index]) {
3275
+ const extraData = peek$(ctx, "extraData");
3276
+ const item = data[index];
3277
+ if (renderItem && !isNullOrUndefined(item)) {
2713
3278
  const itemProps = {
2714
3279
  data,
2715
- extraData: peek$(ctx, "extraData"),
3280
+ extraData,
2716
3281
  index,
2717
- item: data[index],
2718
- type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
3282
+ item,
3283
+ type: getItemType ? (_a3 = getItemType(item, index)) != null ? _a3 : "" : ""
2719
3284
  };
2720
- renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React4__namespace.default.createElement(renderItem, itemProps);
3285
+ renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React3__namespace.default.createElement(renderItem, itemProps);
2721
3286
  }
2722
3287
  return { index, item: data[index], renderedItem };
2723
3288
  }
2724
3289
  function useThrottleDebounce(mode) {
2725
- const timeoutRef = React4.useRef(null);
2726
- const lastCallTimeRef = React4.useRef(0);
2727
- const lastArgsRef = React4.useRef(null);
3290
+ const timeoutRef = React3.useRef(null);
3291
+ const lastCallTimeRef = React3.useRef(0);
3292
+ const lastArgsRef = React3.useRef(null);
2728
3293
  const clearTimeoutRef = () => {
2729
3294
  if (timeoutRef.current) {
2730
3295
  clearTimeout(timeoutRef.current);
2731
3296
  timeoutRef.current = null;
2732
3297
  }
2733
3298
  };
2734
- const execute = React4.useCallback(
3299
+ const execute = React3.useCallback(
2735
3300
  (callback, delay, ...args) => {
2736
3301
  {
2737
3302
  const now = Date.now();
@@ -2767,58 +3332,6 @@ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
2767
3332
  return (event) => throttle(originalHandler, scrollEventThrottle, { nativeEvent: event.nativeEvent });
2768
3333
  }
2769
3334
 
2770
- // src/utils/updateAveragesOnDataChange.ts
2771
- function updateAveragesOnDataChange(state, oldData, newData) {
2772
- var _a;
2773
- const {
2774
- averageSizes,
2775
- sizesKnown,
2776
- indexByKey,
2777
- props: { itemsAreEqual, getItemType, keyExtractor }
2778
- } = state;
2779
- if (!itemsAreEqual || !oldData.length || !newData.length) {
2780
- for (const key in averageSizes) {
2781
- delete averageSizes[key];
2782
- }
2783
- return;
2784
- }
2785
- const itemTypesToPreserve = {};
2786
- const newDataLength = newData.length;
2787
- const oldDataLength = oldData.length;
2788
- for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
2789
- const newItem = newData[newIndex];
2790
- const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
2791
- const oldIndex = indexByKey.get(id);
2792
- if (oldIndex !== void 0 && oldIndex < oldDataLength) {
2793
- const knownSize = sizesKnown.get(id);
2794
- if (knownSize === void 0) continue;
2795
- const oldItem = oldData[oldIndex];
2796
- const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
2797
- if (areEqual) {
2798
- const itemType = getItemType ? (_a = getItemType(newItem, newIndex)) != null ? _a : "" : "";
2799
- let typeData = itemTypesToPreserve[itemType];
2800
- if (!typeData) {
2801
- typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
2802
- }
2803
- typeData.totalSize += knownSize;
2804
- typeData.count++;
2805
- }
2806
- }
2807
- }
2808
- for (const key in averageSizes) {
2809
- delete averageSizes[key];
2810
- }
2811
- for (const itemType in itemTypesToPreserve) {
2812
- const { totalSize, count } = itemTypesToPreserve[itemType];
2813
- if (count > 0) {
2814
- averageSizes[itemType] = {
2815
- avg: totalSize / count,
2816
- num: count
2817
- };
2818
- }
2819
- }
2820
- }
2821
-
2822
3335
  // src/components/LegendList.tsx
2823
3336
  var DEFAULT_DRAW_DISTANCE = 250;
2824
3337
  var DEFAULT_ITEM_SIZE = 100;
@@ -2828,22 +3341,24 @@ var LegendList = typedMemo(
2828
3341
  const isChildrenMode = children !== void 0 && dataProp === void 0;
2829
3342
  const processedProps = isChildrenMode ? {
2830
3343
  ...restProps,
2831
- data: (isArray(children) ? children : React4__namespace.Children.toArray(children)).flat(1),
3344
+ data: (isArray(children) ? children : React3__namespace.Children.toArray(children)).flat(1),
2832
3345
  renderItem: ({ item }) => item
2833
3346
  } : {
2834
3347
  ...restProps,
2835
3348
  data: dataProp || [],
2836
3349
  renderItem: renderItemProp
2837
3350
  };
2838
- return /* @__PURE__ */ React4__namespace.createElement(StateProvider, null, /* @__PURE__ */ React4__namespace.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
3351
+ return /* @__PURE__ */ React3__namespace.createElement(StateProvider, null, /* @__PURE__ */ React3__namespace.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
2839
3352
  })
2840
3353
  );
2841
3354
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
3355
+ var _a3, _b;
2842
3356
  const {
2843
3357
  alignItemsAtEnd = false,
2844
3358
  columnWrapperStyle,
2845
3359
  contentContainerStyle: contentContainerStyleProp,
2846
3360
  data: dataProp = [],
3361
+ dataVersion,
2847
3362
  drawDistance = 250,
2848
3363
  enableAverages = true,
2849
3364
  estimatedItemSize: estimatedItemSizeProp,
@@ -2854,6 +3369,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2854
3369
  getItemType,
2855
3370
  horizontal,
2856
3371
  initialContainerPoolRatio = 2,
3372
+ initialScrollAtEnd = false,
2857
3373
  initialScrollIndex: initialScrollIndexProp,
2858
3374
  initialScrollOffset: initialScrollOffsetProp,
2859
3375
  itemsAreEqual,
@@ -2862,7 +3378,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2862
3378
  ListHeaderComponent,
2863
3379
  maintainScrollAtEnd = false,
2864
3380
  maintainScrollAtEndThreshold = 0.1,
2865
- maintainVisibleContentPosition = true,
3381
+ maintainVisibleContentPosition = false,
2866
3382
  numColumns: numColumnsProp = 1,
2867
3383
  onEndReached,
2868
3384
  onEndReachedThreshold = 0.5,
@@ -2874,6 +3390,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2874
3390
  onScroll: onScrollProp,
2875
3391
  onStartReached,
2876
3392
  onStartReachedThreshold = 0.5,
3393
+ onStickyHeaderChange,
3394
+ onViewableItemsChanged,
2877
3395
  progressViewOffset,
2878
3396
  recycleItems = false,
2879
3397
  refreshControl,
@@ -2882,27 +3400,37 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2882
3400
  renderItem,
2883
3401
  scrollEventThrottle,
2884
3402
  snapToIndices,
2885
- stickyIndices,
3403
+ stickyHeaderIndices: stickyHeaderIndicesProp,
3404
+ stickyIndices: stickyIndicesDeprecated,
2886
3405
  style: styleProp,
2887
3406
  suggestEstimatedItemSize,
3407
+ viewabilityConfig,
3408
+ viewabilityConfigCallbackPairs,
2888
3409
  waitForInitialLayout = true,
2889
3410
  ...rest
2890
3411
  } = props;
2891
- const [renderNum, setRenderNum] = React4.useState(0);
2892
- const initialScroll = initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
2893
- const [canRender, setCanRender] = React4__namespace.useState(!IsNewArchitecture);
2894
3412
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
2895
3413
  const style = { ...StyleSheet.flatten(styleProp) };
2896
3414
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
2897
3415
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
3416
+ const [renderNum, setRenderNum] = React3.useState(0);
3417
+ const initialScrollProp = initialScrollAtEnd ? { index: Math.max(0, dataProp.length - 1), viewOffset: -stylePaddingBottomState } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
3418
+ const [canRender, setCanRender] = React3__namespace.useState(!IsNewArchitecture);
2898
3419
  const ctx = useStateContext();
2899
3420
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
2900
- const refScroller = React4.useRef(null);
3421
+ const refScroller = React3.useRef(null);
2901
3422
  const combinedRef = useCombinedRef(refScroller, refScrollView);
2902
3423
  const estimatedItemSize = estimatedItemSizeProp != null ? estimatedItemSizeProp : DEFAULT_ITEM_SIZE;
2903
3424
  const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
2904
3425
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
2905
- const refState = React4.useRef();
3426
+ const stickyHeaderIndices = stickyHeaderIndicesProp != null ? stickyHeaderIndicesProp : stickyIndicesDeprecated;
3427
+ if (IS_DEV && stickyIndicesDeprecated && !stickyHeaderIndicesProp) {
3428
+ warnDevOnce(
3429
+ "stickyIndices",
3430
+ "stickyIndices has been renamed to stickyHeaderIndices. Please update your props to use stickyHeaderIndices."
3431
+ );
3432
+ }
3433
+ const refState = React3.useRef();
2906
3434
  if (!refState.current) {
2907
3435
  if (!ctx.internalState) {
2908
3436
  const initialScrollLength = (estimatedListSize != null ? estimatedListSize : { height: 0, width: 0 } )[horizontal ? "width" : "height"];
@@ -2912,18 +3440,29 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2912
3440
  columns: /* @__PURE__ */ new Map(),
2913
3441
  containerItemKeys: /* @__PURE__ */ new Set(),
2914
3442
  containerItemTypes: /* @__PURE__ */ new Map(),
3443
+ dataChangeNeedsScrollUpdate: false,
3444
+ didColumnsChange: false,
3445
+ didDataChange: false,
2915
3446
  enableScrollForNextCalculateItemsInView: true,
2916
3447
  endBuffered: -1,
2917
3448
  endNoBuffer: -1,
2918
- endReachedBlockedByTimer: false,
3449
+ endReachedSnapshot: void 0,
2919
3450
  firstFullyOnScreenIndex: -1,
2920
- idCache: /* @__PURE__ */ new Map(),
3451
+ idCache: [],
2921
3452
  idsInView: [],
2922
3453
  indexByKey: /* @__PURE__ */ new Map(),
2923
- initialScroll,
3454
+ initialAnchor: (initialScrollProp == null ? void 0 : initialScrollProp.index) !== void 0 && (initialScrollProp == null ? void 0 : initialScrollProp.viewPosition) !== void 0 ? {
3455
+ attempts: 0,
3456
+ index: initialScrollProp.index,
3457
+ settledTicks: 0,
3458
+ viewOffset: (_a3 = initialScrollProp.viewOffset) != null ? _a3 : 0,
3459
+ viewPosition: initialScrollProp.viewPosition
3460
+ } : void 0,
3461
+ initialScroll: initialScrollProp,
2924
3462
  isAtEnd: false,
2925
3463
  isAtStart: false,
2926
3464
  isEndReached: false,
3465
+ isFirst: true,
2927
3466
  isStartReached: false,
2928
3467
  lastBatchingAction: Date.now(),
2929
3468
  lastLayout: void 0,
@@ -2948,7 +3487,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2948
3487
  sizesKnown: /* @__PURE__ */ new Map(),
2949
3488
  startBuffered: -1,
2950
3489
  startNoBuffer: -1,
2951
- startReachedBlockedByTimer: false,
3490
+ startReachedSnapshot: void 0,
2952
3491
  stickyContainerPool: /* @__PURE__ */ new Set(),
2953
3492
  stickyContainers: /* @__PURE__ */ new Map(),
2954
3493
  timeoutSizeMessage: 0,
@@ -2956,21 +3495,27 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2956
3495
  totalSize: 0,
2957
3496
  viewabilityConfigCallbackPairs: void 0
2958
3497
  };
3498
+ const internalState = ctx.internalState;
3499
+ internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, internalState, params);
2959
3500
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
2960
3501
  set$(ctx, "extraData", extraData);
2961
3502
  }
2962
3503
  refState.current = ctx.internalState;
2963
3504
  }
2964
3505
  const state = refState.current;
2965
- const isFirst = !state.props.renderItem;
2966
- const didDataChange = state.props.data !== dataProp;
2967
- const throttleScrollFn = (
2968
- // @ts-expect-error TODO Fix this
2969
- scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp
2970
- );
3506
+ const isFirstLocal = state.isFirst;
3507
+ state.didColumnsChange = numColumnsProp !== state.props.numColumns;
3508
+ const didDataChangeLocal = state.props.dataVersion !== dataVersion || state.props.data !== dataProp && checkActualChange(state, dataProp, state.props.data);
3509
+ if (didDataChangeLocal) {
3510
+ state.dataChangeNeedsScrollUpdate = true;
3511
+ state.didDataChange = true;
3512
+ state.previousData = state.props.data;
3513
+ }
3514
+ const throttleScrollFn = scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp;
2971
3515
  state.props = {
2972
3516
  alignItemsAtEnd,
2973
3517
  data: dataProp,
3518
+ dataVersion,
2974
3519
  enableAverages,
2975
3520
  estimatedItemSize,
2976
3521
  getEstimatedItemSize,
@@ -2978,7 +3523,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2978
3523
  getItemType,
2979
3524
  horizontal: !!horizontal,
2980
3525
  initialContainerPoolRatio,
2981
- initialScroll,
2982
3526
  itemsAreEqual,
2983
3527
  keyExtractor,
2984
3528
  maintainScrollAtEnd,
@@ -2992,45 +3536,25 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2992
3536
  onScroll: throttleScrollFn,
2993
3537
  onStartReached,
2994
3538
  onStartReachedThreshold,
3539
+ onStickyHeaderChange,
2995
3540
  recycleItems: !!recycleItems,
2996
3541
  renderItem,
2997
3542
  scrollBuffer,
2998
3543
  snapToIndices,
2999
- stickyIndicesArr: stickyIndices != null ? stickyIndices : [],
3000
- stickyIndicesSet: React4.useMemo(() => new Set(stickyIndices != null ? stickyIndices : []), [stickyIndices == null ? void 0 : stickyIndices.join(",")]),
3544
+ stickyIndicesArr: stickyHeaderIndices != null ? stickyHeaderIndices : [],
3545
+ stickyIndicesSet: React3.useMemo(() => new Set(stickyHeaderIndices != null ? stickyHeaderIndices : []), [stickyHeaderIndices == null ? void 0 : stickyHeaderIndices.join(",")]),
3001
3546
  stylePaddingBottom: stylePaddingBottomState,
3002
3547
  stylePaddingTop: stylePaddingTopState,
3003
3548
  suggestEstimatedItemSize: !!suggestEstimatedItemSize
3004
3549
  };
3005
3550
  state.refScroller = refScroller;
3006
- const checkResetContainers = (isFirst2) => {
3007
- const state2 = refState.current;
3008
- if (state2) {
3009
- if (!isFirst2 && state2.props.data !== dataProp) {
3010
- updateAveragesOnDataChange(state2, state2.props.data, dataProp);
3011
- }
3012
- state2.props.data = dataProp;
3013
- if (!isFirst2) {
3014
- calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
3015
- const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
3016
- const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state2, false);
3017
- if (!didMaintainScrollAtEnd && dataProp.length > state2.props.data.length) {
3018
- state2.isEndReached = false;
3019
- }
3020
- if (!didMaintainScrollAtEnd) {
3021
- checkAtTop(state2);
3022
- checkAtBottom(ctx, state2);
3023
- }
3024
- }
3025
- }
3026
- };
3027
- const memoizedLastItemKeys = React4.useMemo(() => {
3551
+ const memoizedLastItemKeys = React3.useMemo(() => {
3028
3552
  if (!dataProp.length) return [];
3029
3553
  return Array.from(
3030
3554
  { length: Math.min(numColumnsProp, dataProp.length) },
3031
3555
  (_, i) => getId(state, dataProp.length - 1 - i)
3032
3556
  );
3033
- }, [dataProp, numColumnsProp]);
3557
+ }, [dataProp, dataVersion, numColumnsProp]);
3034
3558
  const initializeStateVars = () => {
3035
3559
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
3036
3560
  set$(ctx, "numColumns", numColumnsProp);
@@ -3038,44 +3562,70 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3038
3562
  setPaddingTop(ctx, state, { stylePaddingTop: stylePaddingTopState });
3039
3563
  refState.current.props.stylePaddingBottom = stylePaddingBottomState;
3040
3564
  let paddingDiff = stylePaddingTopState - prevPaddingTop;
3041
- if (maintainVisibleContentPosition && paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") {
3565
+ if (paddingDiff && prevPaddingTop !== void 0 && Platform.OS === "ios") {
3042
3566
  if (state.scroll < 0) {
3043
3567
  paddingDiff += state.scroll;
3044
3568
  }
3045
3569
  requestAdjust(ctx, state, paddingDiff);
3046
3570
  }
3047
3571
  };
3048
- if (isFirst) {
3572
+ if (isFirstLocal) {
3049
3573
  initializeStateVars();
3050
- updateAllPositions(ctx, state);
3574
+ updateItemPositions(
3575
+ ctx,
3576
+ state,
3577
+ /*dataChanged*/
3578
+ true
3579
+ );
3051
3580
  }
3052
- const initialContentOffset = React4.useMemo(() => {
3053
- if (initialScroll) {
3054
- const { index, viewOffset } = initialScroll;
3055
- let initialContentOffset2 = viewOffset || 0;
3056
- if (index !== void 0) {
3057
- initialContentOffset2 += calculateOffsetForIndex(ctx, state, index);
3058
- }
3059
- refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
3060
- if (initialContentOffset2 > 0) {
3061
- scrollTo(state, { animated: false, index, offset: initialContentOffset2 });
3062
- }
3063
- return initialContentOffset2;
3581
+ const initialContentOffset = React3.useMemo(() => {
3582
+ var _a4, _b2;
3583
+ const { initialScroll } = refState.current;
3584
+ if (!initialScroll) {
3585
+ refState.current.initialAnchor = void 0;
3586
+ return 0;
3587
+ }
3588
+ if (initialScroll.index !== void 0 && (!refState.current.initialAnchor || ((_a4 = refState.current.initialAnchor) == null ? void 0 : _a4.index) !== initialScroll.index)) {
3589
+ refState.current.initialAnchor = {
3590
+ attempts: 0,
3591
+ index: initialScroll.index,
3592
+ settledTicks: 0,
3593
+ viewOffset: (_b2 = initialScroll.viewOffset) != null ? _b2 : 0,
3594
+ viewPosition: initialScroll.viewPosition
3595
+ };
3064
3596
  }
3065
- return 0;
3597
+ if (initialScroll.contentOffset !== void 0) {
3598
+ return initialScroll.contentOffset;
3599
+ }
3600
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, state, initialScroll.index) : 0;
3601
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, state, baseOffset, initialScroll);
3602
+ let clampedOffset = resolvedOffset;
3603
+ if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
3604
+ const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
3605
+ clampedOffset = Math.min(clampedOffset, maxOffset);
3606
+ }
3607
+ clampedOffset = Math.max(0, clampedOffset);
3608
+ const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3609
+ refState.current.initialScroll = updatedInitialScroll;
3610
+ state.initialScroll = updatedInitialScroll;
3611
+ refState.current.isStartReached = clampedOffset < refState.current.scrollLength * onStartReachedThreshold;
3612
+ return clampedOffset;
3066
3613
  }, [renderNum]);
3067
- if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
3068
- state.lastBatchingAction = Date.now();
3069
- if (!keyExtractorProp && !isFirst && didDataChange) {
3070
- __DEV__ && warnDevOnce(
3614
+ if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
3615
+ refState.current.lastBatchingAction = Date.now();
3616
+ if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
3617
+ IS_DEV && warnDevOnce(
3071
3618
  "keyExtractor",
3072
3619
  "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."
3073
3620
  );
3074
- state.sizes.clear();
3075
- state.positions.clear();
3621
+ refState.current.sizes.clear();
3622
+ refState.current.positions.clear();
3623
+ refState.current.totalSize = 0;
3624
+ set$(ctx, "totalSize", 0);
3076
3625
  }
3077
3626
  }
3078
- const onLayoutHeader = React4.useCallback((rect, fromLayoutEffect) => {
3627
+ const onLayoutHeader = React3.useCallback((rect, fromLayoutEffect) => {
3628
+ const { initialScroll } = refState.current;
3079
3629
  const size = rect[horizontal ? "width" : "height"];
3080
3630
  set$(ctx, "headerSize", size);
3081
3631
  if ((initialScroll == null ? void 0 : initialScroll.index) !== void 0) {
@@ -3086,134 +3636,73 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3086
3636
  }
3087
3637
  }
3088
3638
  }, []);
3089
- React4.useLayoutEffect(() => {
3639
+ const doInitialScroll = React3.useCallback(() => {
3640
+ var _a4;
3641
+ const initialScroll = state.initialScroll;
3642
+ if (initialScroll) {
3643
+ scrollTo(ctx, state, {
3644
+ animated: false,
3645
+ index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3646
+ isInitialScroll: true,
3647
+ offset: initialContentOffset,
3648
+ precomputedWithViewOffset: true
3649
+ });
3650
+ }
3651
+ }, [initialContentOffset]);
3652
+ const onLayoutChange = React3.useCallback((layout) => {
3653
+ doInitialScroll();
3654
+ handleLayout(ctx, state, layout, setCanRender);
3655
+ }, []);
3656
+ const { onLayout } = useOnLayoutSync({
3657
+ onLayoutChange,
3658
+ onLayoutProp,
3659
+ ref: refScroller
3660
+ // the type of ScrollView doesn't include measure?
3661
+ });
3662
+ React3.useLayoutEffect(() => {
3090
3663
  if (snapToIndices) {
3091
3664
  updateSnapToOffsets(ctx, state);
3092
3665
  }
3093
3666
  }, [snapToIndices]);
3094
- React4.useLayoutEffect(() => {
3095
- const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainersCallback();
3096
- if (!didAllocateContainers) {
3097
- checkResetContainers(
3098
- /*isFirst*/
3099
- isFirst
3100
- );
3101
- }
3102
- }, [dataProp, numColumnsProp]);
3103
- React4.useLayoutEffect(() => {
3667
+ React3.useLayoutEffect(() => {
3668
+ const {
3669
+ didColumnsChange,
3670
+ didDataChange,
3671
+ isFirst,
3672
+ props: { data }
3673
+ } = state;
3674
+ const didAllocateContainers = data.length > 0 && doInitialAllocateContainers(ctx, state);
3675
+ if (!didAllocateContainers && !isFirst && (didDataChange || didColumnsChange)) {
3676
+ checkResetContainers(ctx, state, data);
3677
+ }
3678
+ state.didColumnsChange = false;
3679
+ state.didDataChange = false;
3680
+ state.isFirst = false;
3681
+ }, [dataProp, dataVersion, numColumnsProp]);
3682
+ React3.useLayoutEffect(() => {
3104
3683
  set$(ctx, "extraData", extraData);
3105
3684
  }, [extraData]);
3106
- const { onLayout } = useSyncLayout({
3107
- onLayout: onLayoutProp,
3108
- onLayoutChange: React4.useCallback(
3109
- (rectangle) => {
3110
- handleLayout(ctx, state, rectangle, setCanRender);
3111
- },
3112
- [ctx, state, setCanRender]
3113
- ),
3114
- ref: refScroller
3115
- });
3116
- React4.useLayoutEffect(initializeStateVars, [
3685
+ React3.useLayoutEffect(initializeStateVars, [
3686
+ dataVersion,
3117
3687
  memoizedLastItemKeys.join(","),
3118
3688
  numColumnsProp,
3119
- stylePaddingTopState,
3120
- stylePaddingBottomState
3689
+ stylePaddingBottomState,
3690
+ stylePaddingTopState
3121
3691
  ]);
3122
- const doInitialAllocateContainersCallback = () => {
3123
- return doInitialAllocateContainers(ctx, state);
3124
- };
3125
- React4.useImperativeHandle(forwardedRef, () => {
3126
- const scrollIndexIntoView = (options) => {
3127
- const state2 = refState.current;
3128
- if (state2) {
3129
- const { index, ...rest2 } = options;
3130
- const { startNoBuffer, endNoBuffer } = state2;
3131
- if (index < startNoBuffer || index > endNoBuffer) {
3132
- const viewPosition = index < startNoBuffer ? 0 : 1;
3133
- scrollToIndex(ctx, state2, {
3134
- ...rest2,
3135
- index,
3136
- viewPosition
3137
- });
3138
- }
3139
- }
3140
- };
3141
- return {
3142
- flashScrollIndicators: () => {
3143
- var _a, _b;
3144
- return (_b = (_a = refScroller.current) == null ? void 0 : _a.flashScrollIndicators) == null ? void 0 : _b.call(_a);
3145
- },
3146
- getNativeScrollRef: () => refScroller.current,
3147
- getScrollableNode: () => refScroller.current,
3148
- getScrollResponder: () => refScroller.current,
3149
- getState: () => {
3150
- const state2 = refState.current;
3151
- return state2 ? {
3152
- contentLength: state2.totalSize,
3153
- data: state2.props.data,
3154
- end: state2.endNoBuffer,
3155
- endBuffered: state2.endBuffered,
3156
- isAtEnd: state2.isAtEnd,
3157
- isAtStart: state2.isAtStart,
3158
- positionAtIndex: (index) => state2.positions.get(getId(state2, index)),
3159
- positions: state2.positions,
3160
- scroll: state2.scroll,
3161
- scrollLength: state2.scrollLength,
3162
- sizeAtIndex: (index) => state2.sizesKnown.get(getId(state2, index)),
3163
- sizes: state2.sizesKnown,
3164
- start: state2.startNoBuffer,
3165
- startBuffered: state2.startBuffered
3166
- } : {};
3167
- },
3168
- scrollIndexIntoView,
3169
- scrollItemIntoView: ({ item, ...props2 }) => {
3170
- const data = refState.current.props.data;
3171
- const index = data.indexOf(item);
3172
- if (index !== -1) {
3173
- scrollIndexIntoView({ index, ...props2 });
3174
- }
3175
- },
3176
- scrollToEnd: (options) => {
3177
- const data = refState.current.props.data;
3178
- const stylePaddingBottom = refState.current.props.stylePaddingBottom;
3179
- const index = data.length - 1;
3180
- if (index !== -1) {
3181
- const paddingBottom = stylePaddingBottom || 0;
3182
- const footerSize = peek$(ctx, "footerSize") || 0;
3183
- scrollToIndex(ctx, state, {
3184
- index,
3185
- viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
3186
- viewPosition: 1,
3187
- ...options
3188
- });
3189
- }
3190
- },
3191
- scrollToIndex: (params) => scrollToIndex(ctx, state, params),
3192
- scrollToItem: ({ item, ...props2 }) => {
3193
- const data = refState.current.props.data;
3194
- const index = data.indexOf(item);
3195
- if (index !== -1) {
3196
- scrollToIndex(ctx, state, { index, ...props2 });
3197
- }
3198
- },
3199
- scrollToOffset: (params) => scrollTo(state, params),
3200
- setScrollProcessingEnabled: (enabled) => {
3201
- refState.current.scrollProcessingEnabled = enabled;
3202
- },
3203
- setVisibleContentAnchorOffset: (value) => {
3204
- const val = typeof value === "function" ? value(peek$(ctx, "scrollAdjustUserOffset") || 0) : value;
3205
- set$(ctx, "scrollAdjustUserOffset", val);
3206
- }
3207
- };
3208
- }, []);
3692
+ React3.useEffect(() => {
3693
+ const viewability = setupViewability({
3694
+ onViewableItemsChanged,
3695
+ viewabilityConfig,
3696
+ viewabilityConfigCallbackPairs
3697
+ });
3698
+ state.viewabilityConfigCallbackPairs = viewability;
3699
+ state.enableScrollForNextCalculateItemsInView = !viewability;
3700
+ }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
3701
+ React3.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, state), []);
3209
3702
  {
3210
- React4.useEffect(() => {
3211
- if (initialContentOffset) {
3212
- scrollTo(state, { animated: false, offset: initialContentOffset });
3213
- }
3214
- }, []);
3703
+ React3.useEffect(doInitialScroll, []);
3215
3704
  }
3216
- const fns = React4.useMemo(
3705
+ const fns = React3.useMemo(
3217
3706
  () => ({
3218
3707
  getRenderedItem: (key) => getRenderedItem(ctx, state, key),
3219
3708
  onScroll: (event) => onScroll(ctx, state, event),
@@ -3221,8 +3710,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3221
3710
  }),
3222
3711
  []
3223
3712
  );
3224
- const onScrollHandler = useStickyScrollHandler(stickyIndices, horizontal, ctx, fns.onScroll);
3225
- return /* @__PURE__ */ React4__namespace.createElement(React4__namespace.Fragment, null, /* @__PURE__ */ React4__namespace.createElement(
3713
+ const onScrollHandler = useStickyScrollHandler(stickyHeaderIndices, horizontal, ctx, fns.onScroll);
3714
+ return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement(
3226
3715
  ListComponent,
3227
3716
  {
3228
3717
  ...rest,
@@ -3240,7 +3729,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3240
3729
  onMomentumScrollEnd: (event) => {
3241
3730
  {
3242
3731
  requestAnimationFrame(() => {
3243
- finishScrollTo(refState.current);
3732
+ finishScrollTo(ctx, refState.current);
3244
3733
  });
3245
3734
  }
3246
3735
  if (onMomentumScrollEnd) {
@@ -3249,9 +3738,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3249
3738
  },
3250
3739
  onScroll: onScrollHandler,
3251
3740
  recycleItems,
3252
- refreshControl: refreshControl ? stylePaddingTopState > 0 ? React4__namespace.cloneElement(refreshControl, {
3741
+ refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
3253
3742
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
3254
- }) : refreshControl : onRefresh && /* @__PURE__ */ React4__namespace.createElement(
3743
+ }) : refreshControl : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
3255
3744
  RefreshControl,
3256
3745
  {
3257
3746
  onRefresh,
@@ -3260,14 +3749,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3260
3749
  }
3261
3750
  ),
3262
3751
  refScrollView: combinedRef,
3263
- scrollAdjustHandler: state.scrollAdjustHandler,
3752
+ scrollAdjustHandler: (_b = refState.current) == null ? void 0 : _b.scrollAdjustHandler,
3753
+ scrollEventThrottle: 16 ,
3264
3754
  snapToIndices,
3265
- stickyIndices,
3755
+ stickyHeaderIndices,
3266
3756
  style,
3267
3757
  updateItemSize: fns.updateItemSize,
3268
3758
  waitForInitialLayout
3269
3759
  }
3270
- ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React4__namespace.createElement(DebugView, { state: refState.current }));
3760
+ ), IS_DEV && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3__namespace.createElement(DebugView, { state: refState.current }));
3271
3761
  });
3272
3762
 
3273
3763
  exports.LegendList = LegendList;
@@ -3275,6 +3765,6 @@ exports.useIsLastItem = useIsLastItem;
3275
3765
  exports.useListScrollSize = useListScrollSize;
3276
3766
  exports.useRecyclingEffect = useRecyclingEffect;
3277
3767
  exports.useRecyclingState = useRecyclingState;
3278
- exports.useSyncLayout = useSyncLayout2;
3768
+ exports.useSyncLayout = useSyncLayout;
3279
3769
  exports.useViewability = useViewability;
3280
3770
  exports.useViewabilityAmount = useViewabilityAmount;