@legendapp/list 2.1.0-beta.0 → 2.1.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,
@@ -58,10 +58,10 @@ function StateProvider({ children }) {
58
58
  ]),
59
59
  viewRefs: /* @__PURE__ */ new Map()
60
60
  }));
61
- return /* @__PURE__ */ React4__namespace.createElement(ContextState.Provider, { value }, children);
61
+ return /* @__PURE__ */ React3__namespace.createElement(ContextState.Provider, { value }, children);
62
62
  }
63
63
  function useStateContext() {
64
- return React4__namespace.useContext(ContextState);
64
+ return React3__namespace.useContext(ContextState);
65
65
  }
66
66
  function createSelectorFunctionsArr(ctx, signalNames) {
67
67
  let lastValues = [];
@@ -131,23 +131,23 @@ function getContentSize(ctx) {
131
131
  return headerSize + footerSize + totalSize + stylePaddingTop;
132
132
  }
133
133
  function useArr$(signalNames) {
134
- const ctx = React4__namespace.useContext(ContextState);
135
- const { subscribe, get } = React4__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
134
+ const ctx = React3__namespace.useContext(ContextState);
135
+ const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, signalNames), [ctx, signalNames]);
136
136
  const value = shim.useSyncExternalStore(subscribe, get);
137
137
  return value;
138
138
  }
139
139
  function useSelector$(signalName, selector) {
140
- const ctx = React4__namespace.useContext(ContextState);
141
- const { subscribe, get } = React4__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
140
+ const ctx = React3__namespace.useContext(ContextState);
141
+ const { subscribe, get } = React3__namespace.useMemo(() => createSelectorFunctionsArr(ctx, [signalName]), [ctx, signalName]);
142
142
  const value = shim.useSyncExternalStore(subscribe, () => selector(get()[0]));
143
143
  return value;
144
144
  }
145
145
 
146
146
  // src/components/DebugView.tsx
147
147
  var DebugRow = ({ children }) => {
148
- return /* @__PURE__ */ React4__namespace.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
148
+ return /* @__PURE__ */ React3__namespace.createElement(View, { style: { alignItems: "center", flexDirection: "row", justifyContent: "space-between" } }, children);
149
149
  };
150
- var DebugView = React4__namespace.memo(function DebugView2({ state }) {
150
+ var DebugView = React3__namespace.memo(function DebugView2({ state }) {
151
151
  const ctx = useStateContext();
152
152
  const [totalSize = 0, scrollAdjust = 0, rawScroll = 0, scroll = 0, _numContainers = 0, _numContainersPooled = 0] = useArr$([
153
153
  "totalSize",
@@ -158,11 +158,11 @@ var DebugView = React4__namespace.memo(function DebugView2({ state }) {
158
158
  "numContainersPooled"
159
159
  ]);
160
160
  const contentSize = getContentSize(ctx);
161
- const [, forceUpdate] = React4.useReducer((x) => x + 1, 0);
161
+ const [, forceUpdate] = React3.useReducer((x) => x + 1, 0);
162
162
  useInterval(() => {
163
163
  forceUpdate();
164
164
  }, 100);
165
- return /* @__PURE__ */ React4__namespace.createElement(
165
+ return /* @__PURE__ */ React3__namespace.createElement(
166
166
  View,
167
167
  {
168
168
  pointerEvents: "none",
@@ -178,106 +178,35 @@ var DebugView = React4__namespace.memo(function DebugView2({ state }) {
178
178
  top: 0
179
179
  }
180
180
  },
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)))
181
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "TotalSize:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, totalSize.toFixed(2))),
182
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ContentSize:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, contentSize.toFixed(2))),
183
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "At end:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, String(state.isAtEnd))),
184
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ScrollAdjust:"), /* @__PURE__ */ React3__namespace.createElement(Text, null, scrollAdjust.toFixed(2))),
185
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "RawScroll: "), /* @__PURE__ */ React3__namespace.createElement(Text, null, rawScroll.toFixed(2))),
186
+ /* @__PURE__ */ React3__namespace.createElement(DebugRow, null, /* @__PURE__ */ React3__namespace.createElement(Text, null, "ComputedScroll: "), /* @__PURE__ */ React3__namespace.createElement(Text, null, scroll.toFixed(2)))
187
187
  );
188
188
  });
189
189
  function useInterval(callback, delay) {
190
- React4.useEffect(() => {
190
+ React3.useEffect(() => {
191
191
  const interval = setInterval(callback, delay);
192
192
  return () => clearInterval(interval);
193
193
  }, [delay]);
194
194
  }
195
- var globalResizeObserver = null;
196
- function getGlobalResizeObserver() {
197
- if (!globalResizeObserver) {
198
- globalResizeObserver = new ResizeObserver((entries) => {
199
- for (const entry of entries) {
200
- const callbacks = callbackMap.get(entry.target);
201
- if (callbacks) {
202
- for (const callback of callbacks) {
203
- callback(entry);
204
- }
205
- }
206
- }
207
- });
208
- }
209
- return globalResizeObserver;
210
- }
211
- var callbackMap = /* @__PURE__ */ new WeakMap();
212
- function useResizeObserver(element, callback) {
213
- React4.useEffect(() => {
214
- if (!element) return;
215
- const observer = getGlobalResizeObserver();
216
- let callbacks = callbackMap.get(element);
217
- if (!callbacks) {
218
- callbacks = /* @__PURE__ */ new Set();
219
- callbackMap.set(element, callbacks);
220
- observer.observe(element);
221
- }
222
- callbacks.add(callback);
223
- return () => {
224
- const callbacks2 = callbackMap.get(element);
225
- if (callbacks2) {
226
- callbacks2.delete(callback);
227
- if (callbacks2.size === 0) {
228
- callbackMap.delete(element);
229
- observer.unobserve(element);
230
- }
231
- }
232
- };
233
- }, [element, callback]);
234
- }
235
-
236
- // src/hooks/useSyncLayout.tsx
237
- function useSyncLayout({
238
- ref,
239
- onLayoutChange
240
- }) {
241
- var _a, _b;
242
- useResizeObserver(
243
- ((_b = (_a = ref.current) == null ? void 0 : _a.getScrollableNode) == null ? void 0 : _b.call(_a)) || ref.current,
244
- React4.useCallback(
245
- (entry) => {
246
- onLayoutChange(entry.contentRect, false);
247
- },
248
- [onLayoutChange]
249
- )
250
- );
251
- React4.useLayoutEffect(() => {
252
- if (ref.current) {
253
- const rect = ref.current.getBoundingClientRect();
254
- onLayoutChange(
255
- {
256
- height: rect.height,
257
- width: rect.width,
258
- x: rect.left,
259
- y: rect.top
260
- },
261
- true
262
- );
263
- }
264
- }, []);
265
- return {};
266
- }
267
195
 
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
- };
196
+ // src/utils/devEnvironment.ts
197
+ var metroDev = typeof __DEV__ !== "undefined" ? __DEV__ : void 0;
198
+ var _a;
199
+ var envMode = typeof process !== "undefined" && typeof process.env === "object" && process.env ? (_a = process.env.NODE_ENV) != null ? _a : process.env.MODE : void 0;
200
+ var processDev = typeof envMode === "string" ? envMode.toLowerCase() !== "production" : void 0;
201
+ var _a2;
202
+ var IS_DEV = (_a2 = metroDev != null ? metroDev : processDev) != null ? _a2 : false;
274
203
 
275
204
  // src/constants.ts
276
205
  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;
206
+ var ENABLE_DEVMODE = IS_DEV && false;
207
+ var ENABLE_DEBUG_VIEW = IS_DEV && false;
208
+ var typedForwardRef = React3.forwardRef;
209
+ var typedMemo = React3.memo;
281
210
 
282
211
  // src/components/PositionView.tsx
283
212
  var PositionViewState = typedMemo(function PositionView({
@@ -290,7 +219,7 @@ var PositionViewState = typedMemo(function PositionView({
290
219
  const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
291
220
  const base = Array.isArray(style) ? Object.assign({}, ...style) : style;
292
221
  const combinedStyle = horizontal ? { ...base, left: position } : { ...base, top: position };
293
- return /* @__PURE__ */ React4__namespace.createElement(LayoutView, { refView, style: combinedStyle, ...rest });
222
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: combinedStyle, ...rest });
294
223
  });
295
224
  var PositionViewSticky = typedMemo(function PositionViewSticky2({
296
225
  id,
@@ -300,8 +229,8 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
300
229
  index,
301
230
  ...rest
302
231
  }) {
303
- const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
304
- const viewStyle = React4__namespace.useMemo(() => {
232
+ const [position = POSITION_OUT_OF_VIEW, _headerSize] = useArr$([`containerPosition${id}`, "headerSize"]);
233
+ const viewStyle = React3__namespace.useMemo(() => {
305
234
  const base = Array.isArray(style) ? Object.assign({}, ...style) : style;
306
235
  const axisStyle = horizontal ? { transform: `translateX(${position}px)` } : { top: position };
307
236
  return {
@@ -310,26 +239,15 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
310
239
  ...axisStyle
311
240
  };
312
241
  }, [style, position, horizontal, index]);
313
- return /* @__PURE__ */ React4__namespace.createElement(LayoutView, { refView, style: viewStyle, ...rest });
242
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: refView, style: viewStyle, ...rest });
314
243
  });
315
244
  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
245
 
322
246
  // src/constants-platform.ts
323
247
  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
248
  var symbolFirst = Symbol();
331
249
  function useInit(cb) {
332
- const refValue = React4.useRef(symbolFirst);
250
+ const refValue = React3.useRef(symbolFirst);
333
251
  if (refValue.current === symbolFirst) {
334
252
  refValue.current = cb();
335
253
  }
@@ -345,7 +263,7 @@ function isArray(obj) {
345
263
  }
346
264
  var warned = /* @__PURE__ */ new Set();
347
265
  function warnDevOnce(id, text) {
348
- if (__DEV__ && !warned.has(id)) {
266
+ if (IS_DEV && !warned.has(id)) {
349
267
  warned.add(id);
350
268
  console.warn(`[legend-list] ${text}`);
351
269
  }
@@ -360,18 +278,18 @@ function comparatorDefault(a, b) {
360
278
  return a - b;
361
279
  }
362
280
  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;
281
+ var _a3, _b, _c;
282
+ return (_c = (_b = (_a3 = s[`padding${type}`]) != null ? _a3 : s.paddingVertical) != null ? _b : s.padding) != null ? _c : 0;
365
283
  }
366
284
  function extractPadding(style, contentContainerStyle, type) {
367
285
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
368
286
  }
369
287
 
370
288
  // src/state/ContextContainer.ts
371
- var ContextContainer = React4.createContext(null);
289
+ var ContextContainer = React3.createContext(null);
372
290
  function useViewability(callback, configId) {
373
291
  const ctx = useStateContext();
374
- const { containerId } = React4.useContext(ContextContainer);
292
+ const { containerId } = React3.useContext(ContextContainer);
375
293
  const key = containerId + (configId != null ? configId : "");
376
294
  useInit(() => {
377
295
  const value = ctx.mapViewabilityValues.get(key);
@@ -380,7 +298,7 @@ function useViewability(callback, configId) {
380
298
  }
381
299
  });
382
300
  ctx.mapViewabilityCallbacks.set(key, callback);
383
- React4.useEffect(
301
+ React3.useEffect(
384
302
  () => () => {
385
303
  ctx.mapViewabilityCallbacks.delete(key);
386
304
  },
@@ -389,7 +307,7 @@ function useViewability(callback, configId) {
389
307
  }
390
308
  function useViewabilityAmount(callback) {
391
309
  const ctx = useStateContext();
392
- const { containerId } = React4.useContext(ContextContainer);
310
+ const { containerId } = React3.useContext(ContextContainer);
393
311
  useInit(() => {
394
312
  const value = ctx.mapViewabilityAmountValues.get(containerId);
395
313
  if (value) {
@@ -397,7 +315,7 @@ function useViewabilityAmount(callback) {
397
315
  }
398
316
  });
399
317
  ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
400
- React4.useEffect(
318
+ React3.useEffect(
401
319
  () => () => {
402
320
  ctx.mapViewabilityAmountCallbacks.delete(containerId);
403
321
  },
@@ -405,12 +323,12 @@ function useViewabilityAmount(callback) {
405
323
  );
406
324
  }
407
325
  function useRecyclingEffect(effect) {
408
- const { index, value } = React4.useContext(ContextContainer);
409
- const prevValues = React4.useRef({
326
+ const { index, value } = React3.useContext(ContextContainer);
327
+ const prevValues = React3.useRef({
410
328
  prevIndex: void 0,
411
329
  prevItem: void 0
412
330
  });
413
- React4.useEffect(() => {
331
+ React3.useEffect(() => {
414
332
  let ret;
415
333
  if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
416
334
  ret = effect({
@@ -428,12 +346,12 @@ function useRecyclingEffect(effect) {
428
346
  }, [index, value, effect]);
429
347
  }
430
348
  function useRecyclingState(valueOrFun) {
431
- const { index, value, itemKey, triggerLayout } = React4.useContext(ContextContainer);
432
- const refState = React4.useRef({
349
+ const { index, value, itemKey, triggerLayout } = React3.useContext(ContextContainer);
350
+ const refState = React3.useRef({
433
351
  itemKey: null,
434
352
  value: null
435
353
  });
436
- const [_, setRenderNum] = React4.useState(0);
354
+ const [_, setRenderNum] = React3.useState(0);
437
355
  const state = refState.current;
438
356
  if (state.itemKey !== itemKey) {
439
357
  state.itemKey = itemKey;
@@ -444,7 +362,7 @@ function useRecyclingState(valueOrFun) {
444
362
  prevItem: void 0
445
363
  }) : valueOrFun;
446
364
  }
447
- const setState = React4.useCallback(
365
+ const setState = React3.useCallback(
448
366
  (newState) => {
449
367
  state.value = isFunction(newState) ? newState(state.value) : newState;
450
368
  setRenderNum((v) => v + 1);
@@ -455,7 +373,7 @@ function useRecyclingState(valueOrFun) {
455
373
  return [state.value, setState];
456
374
  }
457
375
  function useIsLastItem() {
458
- const { itemKey } = React4.useContext(ContextContainer);
376
+ const { itemKey } = React3.useContext(ContextContainer);
459
377
  const isLast = useSelector$("lastItemKeys", (lastItemKeys) => (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false);
460
378
  return isLast;
461
379
  }
@@ -463,13 +381,103 @@ function useListScrollSize() {
463
381
  const [scrollSize] = useArr$(["scrollSize"]);
464
382
  return scrollSize;
465
383
  }
466
- function useSyncLayout2() {
384
+ function useSyncLayout() {
467
385
  {
468
- const { triggerLayout: syncLayout } = React4.useContext(ContextContainer);
386
+ const { triggerLayout: syncLayout } = React3.useContext(ContextContainer);
469
387
  return syncLayout;
470
388
  }
471
389
  }
472
390
 
391
+ // src/components/Separator.tsx
392
+ function Separator({ ItemSeparatorComponent, leadingItem }) {
393
+ const isLastItem = useIsLastItem();
394
+ return isLastItem ? null : /* @__PURE__ */ React3__namespace.createElement(ItemSeparatorComponent, { leadingItem });
395
+ }
396
+
397
+ // src/hooks/createResizeObserver.ts
398
+ var globalResizeObserver = null;
399
+ function getGlobalResizeObserver() {
400
+ if (!globalResizeObserver) {
401
+ globalResizeObserver = new ResizeObserver((entries) => {
402
+ for (const entry of entries) {
403
+ const callbacks = callbackMap.get(entry.target);
404
+ if (callbacks) {
405
+ for (const callback of callbacks) {
406
+ callback(entry);
407
+ }
408
+ }
409
+ }
410
+ });
411
+ }
412
+ return globalResizeObserver;
413
+ }
414
+ var callbackMap = /* @__PURE__ */ new WeakMap();
415
+ function createResizeObserver(element, callback) {
416
+ if (!element) {
417
+ return () => {
418
+ };
419
+ }
420
+ const observer = getGlobalResizeObserver();
421
+ let callbacks = callbackMap.get(element);
422
+ if (!callbacks) {
423
+ callbacks = /* @__PURE__ */ new Set();
424
+ callbackMap.set(element, callbacks);
425
+ observer.observe(element);
426
+ }
427
+ callbacks.add(callback);
428
+ return () => {
429
+ const callbacks2 = callbackMap.get(element);
430
+ if (callbacks2) {
431
+ callbacks2.delete(callback);
432
+ if (callbacks2.size === 0) {
433
+ callbackMap.delete(element);
434
+ observer.unobserve(element);
435
+ }
436
+ }
437
+ };
438
+ }
439
+
440
+ // src/hooks/useOnLayoutSync.tsx
441
+ function useOnLayoutSync({
442
+ ref,
443
+ onLayoutProp,
444
+ onLayoutChange
445
+ }, deps) {
446
+ React3.useLayoutEffect(() => {
447
+ var _a3, _b;
448
+ const current = ref.current;
449
+ const scrollableNode = (_b = (_a3 = current == null ? void 0 : current.getScrollableNode) == null ? void 0 : _a3.call(current)) != null ? _b : null;
450
+ const element = scrollableNode || current;
451
+ if (!element || !(element instanceof HTMLElement)) {
452
+ return;
453
+ }
454
+ const emit = (layout, fromLayoutEffect) => {
455
+ if (layout.height === 0 && layout.width === 0) {
456
+ return;
457
+ }
458
+ onLayoutChange(layout, fromLayoutEffect);
459
+ onLayoutProp == null ? void 0 : onLayoutProp({ nativeEvent: { layout } });
460
+ };
461
+ const rect = element.getBoundingClientRect();
462
+ emit(toLayout(rect), true);
463
+ return createResizeObserver(element, (entry) => {
464
+ var _a4;
465
+ const target = entry.target instanceof HTMLElement ? entry.target : void 0;
466
+ const rect2 = (_a4 = entry.contentRect) != null ? _a4 : target == null ? void 0 : target.getBoundingClientRect();
467
+ emit(toLayout(rect2), false);
468
+ });
469
+ }, deps);
470
+ return {};
471
+ }
472
+ function toLayout(rect) {
473
+ return {
474
+ height: rect.height,
475
+ width: rect.width,
476
+ x: rect.left,
477
+ y: rect.top
478
+ };
479
+ }
480
+
473
481
  // src/components/Container.tsx
474
482
  var Container = typedMemo(function Container2({
475
483
  id,
@@ -480,37 +488,42 @@ var Container = typedMemo(function Container2({
480
488
  ItemSeparatorComponent
481
489
  }) {
482
490
  const ctx = useStateContext();
483
- const { columnWrapperStyle } = ctx;
484
- const [column = 0, data, itemKey, numColumns, extraData, isSticky] = useArr$([
491
+ const { columnWrapperStyle, animatedScrollY } = ctx;
492
+ const [column = 0, data, itemKey, numColumns, extraData, isSticky, stickyOffset] = useArr$([
485
493
  `containerColumn${id}`,
486
494
  `containerItemData${id}`,
487
495
  `containerItemKey${id}`,
488
496
  "numColumns",
489
497
  "extraData",
490
- `containerSticky${id}`
498
+ `containerSticky${id}`,
499
+ `containerStickyOffset${id}`
491
500
  ]);
492
- const refLastSize = React4.useRef();
493
- const ref = React4.useRef(null);
494
- const [_, forceLayoutRender] = React4.useState(0);
501
+ const itemLayoutRef = React3.useRef({
502
+ horizontal,
503
+ itemKey,
504
+ updateItemSize: updateItemSize2
505
+ });
506
+ itemLayoutRef.current.horizontal = horizontal;
507
+ itemLayoutRef.current.itemKey = itemKey;
508
+ itemLayoutRef.current.updateItemSize = updateItemSize2;
509
+ const ref = React3.useRef(null);
510
+ const [layoutRenderCount, forceLayoutRender] = React3.useState(0);
495
511
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
496
512
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
497
- const style = React4.useMemo(() => {
513
+ const didLayoutRef = React3.useRef(false);
514
+ const style = React3.useMemo(() => {
498
515
  let paddingStyles;
499
516
  if (columnWrapperStyle) {
500
517
  const { columnGap, rowGap, gap } = columnWrapperStyle;
501
518
  if (horizontal) {
502
- const py = numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0;
503
519
  paddingStyles = {
504
- paddingBottom: py,
505
520
  paddingRight: columnGap || gap || void 0,
506
- paddingTop: py
521
+ paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
507
522
  };
508
523
  } else {
509
- const px = numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0;
510
524
  paddingStyles = {
511
525
  paddingBottom: rowGap || gap || void 0,
512
- paddingLeft: px,
513
- paddingRight: px
526
+ paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
514
527
  };
515
528
  }
516
529
  }
@@ -524,18 +537,18 @@ var Container = typedMemo(function Container2({
524
537
  } : {
525
538
  left: otherAxisPos,
526
539
  position: "absolute",
527
- right: numColumns > 1 ? void 0 : 0,
540
+ right: numColumns > 1 ? null : 0,
528
541
  top: 0,
529
542
  width: otherAxisSize,
530
543
  ...paddingStyles || {}
531
544
  };
532
545
  }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
533
- const renderedItemInfo = React4.useMemo(
546
+ const renderedItemInfo = React3.useMemo(
534
547
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
535
548
  [itemKey, data, extraData]
536
549
  );
537
550
  const { index, renderedItem } = renderedItemInfo || {};
538
- const contextValue = React4.useMemo(() => {
551
+ const contextValue = React3.useMemo(() => {
539
552
  ctx.viewRefs.set(id, ref);
540
553
  return {
541
554
  containerId: id,
@@ -547,49 +560,64 @@ var Container = typedMemo(function Container2({
547
560
  value: data
548
561
  };
549
562
  }, [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
- }
563
+ const onLayoutChange = React3.useCallback((rectangle) => {
564
+ const {
565
+ horizontal: currentHorizontal,
566
+ itemKey: currentItemKey,
567
+ updateItemSize: updateItemSizeFn
568
+ } = itemLayoutRef.current;
569
+ if (isNullOrUndefined(currentItemKey)) {
570
+ return;
561
571
  }
562
- };
572
+ didLayoutRef.current = true;
573
+ let layout = rectangle;
574
+ Math.floor(rectangle[currentHorizontal ? "width" : "height"] * 8) / 8;
575
+ const doUpdate = () => {
576
+ itemLayoutRef.current.lastSize = { height: layout.height, width: layout.width };
577
+ updateItemSizeFn(currentItemKey, layout);
578
+ didLayoutRef.current = true;
579
+ };
580
+ {
581
+ doUpdate();
582
+ }
583
+ }, []);
584
+ const { onLayout } = useOnLayoutSync(
585
+ {
586
+ onLayoutChange,
587
+ ref
588
+ },
589
+ [itemKey, layoutRenderCount]
590
+ );
563
591
  const PositionComponent = isSticky ? PositionViewSticky : PositionView2;
564
- return /* @__PURE__ */ React4__namespace.createElement(ContextContainer.Provider, { value: contextValue }, /* @__PURE__ */ React4__namespace.createElement(
592
+ return /* @__PURE__ */ React3__namespace.createElement(
565
593
  PositionComponent,
566
594
  {
595
+ animatedScrollY: isSticky ? animatedScrollY : void 0,
567
596
  horizontal,
568
597
  id,
569
598
  index,
570
599
  key: recycleItems ? void 0 : itemKey,
571
- onLayoutChange,
600
+ onLayout,
572
601
  refView: ref,
602
+ stickyOffset: isSticky ? stickyOffset : void 0,
573
603
  style
574
604
  },
575
- renderedItem,
576
- renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React4__namespace.createElement(
577
- Separator,
578
- {
579
- ItemSeparatorComponent,
580
- itemKey,
581
- leadingItem: renderedItemInfo.item
582
- }
583
- )
584
- ));
605
+ /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(Separator, { ItemSeparatorComponent, leadingItem: renderedItemInfo.item }))
606
+ );
585
607
  });
586
608
 
609
+ // src/platform/Platform.ts
610
+ var Platform = {
611
+ // Widen the type to avoid unreachable-branch lints in cross-platform code that compares against other OSes
612
+ OS: "web"
613
+ };
614
+
587
615
  // src/utils/reordering.ts
588
616
  var mapFn = (element) => {
589
617
  const indexStr = element.getAttribute("index");
590
618
  return [element, indexStr === null ? null : parseInt(indexStr)];
591
619
  };
592
- function sortDOMElementsPatience(container) {
620
+ function sortDOMElements(container) {
593
621
  const elements = Array.from(container.children);
594
622
  if (elements.length <= 1) return elements;
595
623
  const items = elements.map(mapFn);
@@ -671,8 +699,8 @@ function findLIS(arr) {
671
699
  // src/hooks/useDOMOrder.ts
672
700
  function useDOMOrder(ref) {
673
701
  const ctx = useStateContext();
674
- const debounceRef = React4.useRef(void 0);
675
- React4.useEffect(() => {
702
+ const debounceRef = React3.useRef(void 0);
703
+ React3.useEffect(() => {
676
704
  const unsubscribe = listen$(ctx, "lastPositionUpdate", () => {
677
705
  if (debounceRef.current !== void 0) {
678
706
  clearTimeout(debounceRef.current);
@@ -680,7 +708,7 @@ function useDOMOrder(ref) {
680
708
  debounceRef.current = setTimeout(() => {
681
709
  const parent = ref.current;
682
710
  if (parent) {
683
- sortDOMElementsPatience(parent);
711
+ sortDOMElements(parent);
684
712
  }
685
713
  debounceRef.current = void 0;
686
714
  }, 500);
@@ -696,7 +724,7 @@ function useDOMOrder(ref) {
696
724
 
697
725
  // src/components/Containers.tsx
698
726
  var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColumns, children }) {
699
- const ref = React4.useRef(null);
727
+ const ref = React3.useRef(null);
700
728
  const ctx = useStateContext();
701
729
  const columnWrapperStyle = ctx.columnWrapperStyle;
702
730
  const [totalSize, otherAxisSize] = useArr$(["totalSize", "otherAxisSize"]);
@@ -722,7 +750,7 @@ var ContainersInner = typedMemo(function ContainersInner2({ horizontal, numColum
722
750
  }
723
751
  }
724
752
  }
725
- return /* @__PURE__ */ React4__namespace.createElement("div", { ref, style }, children);
753
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref, style }, children);
726
754
  });
727
755
  var Containers = typedMemo(function Containers2({
728
756
  horizontal,
@@ -736,7 +764,7 @@ var Containers = typedMemo(function Containers2({
736
764
  const containers = [];
737
765
  for (let i = 0; i < numContainers; i++) {
738
766
  containers.push(
739
- /* @__PURE__ */ React4__namespace.createElement(
767
+ /* @__PURE__ */ React3__namespace.createElement(
740
768
  Container,
741
769
  {
742
770
  getRenderedItem: getRenderedItem2,
@@ -750,25 +778,41 @@ var Containers = typedMemo(function Containers2({
750
778
  )
751
779
  );
752
780
  }
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
- ));
781
+ return /* @__PURE__ */ React3__namespace.createElement(ContainersInner, { horizontal, numColumns, waitForInitialLayout }, containers);
770
782
  });
771
- var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView2({
783
+ function DevNumbers() {
784
+ return IS_DEV && React3__namespace.memo(function DevNumbers2() {
785
+ return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3__namespace.createElement(
786
+ "div",
787
+ {
788
+ key: index,
789
+ style: {
790
+ height: 100,
791
+ pointerEvents: "none",
792
+ position: "absolute",
793
+ top: index * 100,
794
+ width: "100%"
795
+ }
796
+ },
797
+ /* @__PURE__ */ React3__namespace.createElement("div", { style: { color: "red" } }, index * 100)
798
+ ));
799
+ });
800
+ }
801
+
802
+ // src/platform/StyleSheet.tsx
803
+ function flattenStyles(styles) {
804
+ if (Array.isArray(styles)) {
805
+ return Object.assign({}, ...styles.filter(Boolean));
806
+ }
807
+ return styles;
808
+ }
809
+ var StyleSheet = {
810
+ create: (styles) => styles,
811
+ flatten: (style) => flattenStyles(style)
812
+ };
813
+
814
+ // src/components/ListComponentScrollView.tsx
815
+ var ListComponentScrollView = React3.forwardRef(function ListComponentScrollView2({
772
816
  children,
773
817
  style,
774
818
  contentContainerStyle,
@@ -781,25 +825,23 @@ var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView
781
825
  showsVerticalScrollIndicator = true,
782
826
  refreshControl,
783
827
  onLayout,
784
- ScrollComponent,
785
828
  ...props
786
829
  }, ref) {
787
- const scrollRef = React4.useRef(null);
788
- const contentRef = React4.useRef(null);
789
- const momentumTimeout = React4.useRef(null);
790
- React4.useImperativeHandle(ref, () => {
830
+ const scrollRef = React3.useRef(null);
831
+ const contentRef = React3.useRef(null);
832
+ const momentumTimeout = React3.useRef(null);
833
+ React3.useImperativeHandle(ref, () => {
791
834
  const api = {
792
835
  getBoundingClientRect: () => {
793
- var _a;
794
- return (_a = scrollRef.current) == null ? void 0 : _a.getBoundingClientRect();
836
+ var _a3;
837
+ return (_a3 = scrollRef.current) == null ? void 0 : _a3.getBoundingClientRect();
795
838
  },
796
839
  getScrollableNode: () => scrollRef.current,
797
840
  getScrollResponder: () => scrollRef.current,
798
- scrollBy: (options) => {
841
+ scrollBy: (x, y) => {
799
842
  const el = scrollRef.current;
800
843
  if (!el) return;
801
- const { x = 0, y = 0, animated = true } = options;
802
- el.scrollBy({ behavior: animated ? "smooth" : "auto", left: x, top: y });
844
+ el.scrollBy(x, y);
803
845
  },
804
846
  scrollTo: (options) => {
805
847
  const el = scrollRef.current;
@@ -830,7 +872,7 @@ var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView
830
872
  };
831
873
  return api;
832
874
  }, [horizontal]);
833
- const handleScroll = React4.useCallback(
875
+ const handleScroll = React3.useCallback(
834
876
  (event) => {
835
877
  if (!onScroll2 || !(event == null ? void 0 : event.target)) {
836
878
  return;
@@ -866,21 +908,25 @@ var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView
866
908
  },
867
909
  [onScroll2, onMomentumScrollEnd]
868
910
  );
869
- React4.useLayoutEffect(() => {
911
+ React3.useLayoutEffect(() => {
870
912
  const element = scrollRef.current;
871
913
  if (!element) return;
872
- element.addEventListener("scroll", handleScroll, { passive: true });
914
+ element.addEventListener("scroll", handleScroll);
873
915
  return () => {
874
916
  element.removeEventListener("scroll", handleScroll);
875
917
  };
876
918
  }, [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(() => {
919
+ React3.useEffect(() => {
920
+ const doScroll = () => {
921
+ if (contentOffset && scrollRef.current) {
922
+ scrollRef.current.scrollLeft = contentOffset.x || 0;
923
+ scrollRef.current.scrollTop = contentOffset.y || 0;
924
+ }
925
+ };
926
+ doScroll();
927
+ requestAnimationFrame(doScroll);
928
+ }, [contentOffset == null ? void 0 : contentOffset.x, contentOffset == null ? void 0 : contentOffset.y]);
929
+ React3.useLayoutEffect(() => {
884
930
  if (!onLayout || !scrollRef.current) return;
885
931
  const element = scrollRef.current;
886
932
  const fireLayout = () => {
@@ -911,20 +957,40 @@ var ListComponentScrollView = React4.forwardRef(function ListComponentScrollView
911
957
  // Ensure proper positioning context
912
958
  WebkitOverflowScrolling: "touch",
913
959
  // iOS momentum scrolling
914
- ...style
960
+ ...StyleSheet.flatten(style)
915
961
  };
916
962
  const contentStyle = {
917
963
  display: horizontal ? "flex" : "block",
918
964
  flexDirection: horizontal ? "row" : void 0,
919
965
  minHeight: horizontal ? void 0 : "100%",
920
966
  minWidth: horizontal ? "100%" : void 0,
921
- ...contentContainerStyle
967
+ ...StyleSheet.flatten(contentContainerStyle)
922
968
  };
923
- return /* @__PURE__ */ React4__namespace.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React4__namespace.createElement("div", { ref: contentRef, style: contentStyle }, children));
969
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ref: scrollRef, style: scrollViewStyle, ...props }, refreshControl, /* @__PURE__ */ React3__namespace.createElement("div", { ref: contentRef, style: contentStyle }, children));
924
970
  });
971
+ function Padding() {
972
+ const [paddingTop] = useArr$(["alignItemsPaddingTop"]);
973
+ return /* @__PURE__ */ React3__namespace.createElement("div", { style: { paddingTop } });
974
+ }
975
+ function PaddingDevMode() {
976
+ const [paddingTop] = useArr$(["alignItemsPaddingTop"]);
977
+ return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement("div", { style: { paddingTop } }), /* @__PURE__ */ React3__namespace.createElement(
978
+ "div",
979
+ {
980
+ style: {
981
+ backgroundColor: "green",
982
+ height: paddingTop,
983
+ left: 0,
984
+ position: "absolute",
985
+ right: 0,
986
+ top: 0
987
+ }
988
+ }
989
+ ));
990
+ }
925
991
  function useValueListener$(key, callback) {
926
992
  const ctx = useStateContext();
927
- React4.useLayoutEffect(() => {
993
+ React3.useLayoutEffect(() => {
928
994
  listen$(ctx, key, (value) => {
929
995
  callback(value);
930
996
  });
@@ -934,13 +1000,13 @@ function useValueListener$(key, callback) {
934
1000
  // src/components/ScrollAdjust.tsx
935
1001
  function ScrollAdjust() {
936
1002
  const ctx = useStateContext();
937
- const lastScrollOffsetRef = React4__namespace.useRef(0);
938
- const callback = React4__namespace.useCallback(() => {
939
- var _a;
1003
+ const lastScrollOffsetRef = React3__namespace.useRef(0);
1004
+ const callback = React3__namespace.useCallback(() => {
1005
+ var _a3;
940
1006
  const scrollAdjust = peek$(ctx, "scrollAdjust");
941
1007
  const scrollAdjustUserOffset = peek$(ctx, "scrollAdjustUserOffset");
942
1008
  const scrollOffset = (scrollAdjust || 0) + (scrollAdjustUserOffset || 0);
943
- const scrollView = (_a = ctx.internalState) == null ? void 0 : _a.refScroller.current;
1009
+ const scrollView = (_a3 = ctx.internalState) == null ? void 0 : _a3.refScroller.current;
944
1010
  if (scrollView && scrollOffset !== lastScrollOffsetRef.current) {
945
1011
  const scrollDelta = scrollOffset - lastScrollOffsetRef.current;
946
1012
  if (scrollDelta !== 0) {
@@ -954,49 +1020,26 @@ function ScrollAdjust() {
954
1020
  useValueListener$("scrollAdjustUserOffset", callback);
955
1021
  return null;
956
1022
  }
957
-
958
- // src/components/SnapWrapper.tsx
959
1023
  function SnapWrapper({ ScrollComponent, ...props }) {
960
1024
  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;
1025
+ return /* @__PURE__ */ React3__namespace.createElement(ScrollComponent, { ...props, snapToOffsets });
968
1026
  }
1027
+ var LayoutView = ({ onLayoutChange, refView, children, ...rest }) => {
1028
+ const ref = refView != null ? refView : React3.useRef();
1029
+ useOnLayoutSync({ onLayoutChange, ref });
1030
+ return /* @__PURE__ */ React3__namespace.createElement("div", { ...rest, ref }, children);
1031
+ };
969
1032
 
970
1033
  // src/components/ListComponent.tsx
971
1034
  var getComponent = (Component) => {
972
- if (React4__namespace.isValidElement(Component)) {
1035
+ if (React3__namespace.isValidElement(Component)) {
973
1036
  return Component;
974
1037
  }
975
1038
  if (Component) {
976
- return /* @__PURE__ */ React4__namespace.createElement(Component, null);
1039
+ return /* @__PURE__ */ React3__namespace.createElement(Component, null);
977
1040
  }
978
1041
  return null;
979
1042
  };
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
1043
  var ListComponent = typedMemo(function ListComponent2({
1001
1044
  canRender,
1002
1045
  style,
@@ -1026,12 +1069,11 @@ var ListComponent = typedMemo(function ListComponent2({
1026
1069
  ...rest
1027
1070
  }) {
1028
1071
  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 })),
1072
+ const ScrollComponent = renderScrollComponent ? React3.useMemo(
1073
+ () => React3__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
1032
1074
  [renderScrollComponent]
1033
1075
  ) : ListComponentScrollView;
1034
- React4__namespace.useEffect(() => {
1076
+ React3__namespace.useEffect(() => {
1035
1077
  if (canRender) {
1036
1078
  setTimeout(() => {
1037
1079
  scrollAdjustHandler.setMounted();
@@ -1039,39 +1081,30 @@ var ListComponent = typedMemo(function ListComponent2({
1039
1081
  }
1040
1082
  }, [canRender]);
1041
1083
  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(
1084
+ return /* @__PURE__ */ React3__namespace.createElement(
1049
1085
  SnapOrScroll,
1050
1086
  {
1051
1087
  ...rest,
1052
- contentContainerStyle: contentContainerStyleWeb,
1088
+ contentContainerStyle: [
1089
+ contentContainerStyle,
1090
+ horizontal ? {
1091
+ height: "100%"
1092
+ } : {}
1093
+ ],
1053
1094
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
1054
1095
  horizontal,
1055
- maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
1096
+ maintainVisibleContentPosition: maintainVisibleContentPosition ? { minIndexForVisible: 0 } : void 0,
1056
1097
  onLayout,
1057
1098
  onScroll: onScroll2,
1058
1099
  ref: refScrollView,
1059
1100
  ScrollComponent: snapToIndices ? ScrollComponent : void 0,
1060
1101
  style
1061
1102
  },
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
- ),
1103
+ maintainVisibleContentPosition && /* @__PURE__ */ React3__namespace.createElement(ScrollAdjust, null),
1104
+ ENABLE_DEVMODE ? /* @__PURE__ */ React3__namespace.createElement(PaddingDevMode, null) : /* @__PURE__ */ React3__namespace.createElement(Padding, null),
1105
+ ListHeaderComponent && /* @__PURE__ */ React3__namespace.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
1073
1106
  ListEmptyComponent && getComponent(ListEmptyComponent),
1074
- canRender && /* @__PURE__ */ React4__namespace.createElement(
1107
+ canRender && !ListEmptyComponent && /* @__PURE__ */ React3__namespace.createElement(
1075
1108
  Containers,
1076
1109
  {
1077
1110
  getRenderedItem: getRenderedItem2,
@@ -1082,7 +1115,7 @@ var ListComponent = typedMemo(function ListComponent2({
1082
1115
  waitForInitialLayout
1083
1116
  }
1084
1117
  ),
1085
- ListFooterComponent && /* @__PURE__ */ React4__namespace.createElement(
1118
+ ListFooterComponent && /* @__PURE__ */ React3__namespace.createElement(
1086
1119
  LayoutView,
1087
1120
  {
1088
1121
  onLayoutChange: (layout) => {
@@ -1093,7 +1126,7 @@ var ListComponent = typedMemo(function ListComponent2({
1093
1126
  },
1094
1127
  getComponent(ListFooterComponent)
1095
1128
  ),
1096
- __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React4__namespace.createElement(DevNumbers, null)
1129
+ IS_DEV && ENABLE_DEVMODE && /* @__PURE__ */ React3__namespace.createElement(DevNumbers, null)
1097
1130
  );
1098
1131
  });
1099
1132
 
@@ -1105,7 +1138,7 @@ function getId(state, index) {
1105
1138
  }
1106
1139
  const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
1107
1140
  const id = ret;
1108
- state.idCache.set(index, id);
1141
+ state.idCache[index] = id;
1109
1142
  return id;
1110
1143
  }
1111
1144
 
@@ -1128,7 +1161,7 @@ function calculateOffsetForIndex(ctx, state, index) {
1128
1161
 
1129
1162
  // src/utils/getItemSize.ts
1130
1163
  function getItemSize(state, key, index, data, useAverageSize) {
1131
- var _a, _b;
1164
+ var _a3, _b;
1132
1165
  const {
1133
1166
  sizesKnown,
1134
1167
  sizes,
@@ -1141,7 +1174,7 @@ function getItemSize(state, key, index, data, useAverageSize) {
1141
1174
  return sizeKnown;
1142
1175
  }
1143
1176
  let size;
1144
- const itemType = getItemType ? (_a = getItemType(data, index)) != null ? _a : "" : "";
1177
+ const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1145
1178
  if (getFixedItemSize) {
1146
1179
  size = getFixedItemSize(index, data, itemType);
1147
1180
  if (size !== void 0) {
@@ -1190,8 +1223,8 @@ var finishScrollTo = (state) => {
1190
1223
 
1191
1224
  // src/core/scrollTo.ts
1192
1225
  function scrollTo(state, params = {}) {
1193
- var _a;
1194
- const { animated, noScrollingTo } = params;
1226
+ var _a3;
1227
+ const { animated, noScrollingTo, isInitialScroll } = params;
1195
1228
  const {
1196
1229
  refScroller,
1197
1230
  props: { horizontal }
@@ -1202,14 +1235,21 @@ function scrollTo(state, params = {}) {
1202
1235
  state.scrollingTo = params;
1203
1236
  }
1204
1237
  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
- });
1238
+ if (!params.isInitialScroll || Platform.OS === "android") {
1239
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollTo({
1240
+ animated: !!animated,
1241
+ x: horizontal ? offset : 0,
1242
+ y: horizontal ? 0 : offset
1243
+ });
1244
+ }
1210
1245
  if (!animated) {
1211
1246
  state.scroll = offset;
1212
1247
  setTimeout(() => finishScrollTo(state), 100);
1248
+ if (isInitialScroll) {
1249
+ setTimeout(() => {
1250
+ state.initialScroll = void 0;
1251
+ }, 500);
1252
+ }
1213
1253
  }
1214
1254
  }
1215
1255
 
@@ -1298,7 +1338,16 @@ function prepareMVCP(ctx, state, dataChanged) {
1298
1338
  if (targetId !== void 0 && prevPosition !== void 0) {
1299
1339
  const newPosition = positions.get(targetId);
1300
1340
  if (newPosition !== void 0) {
1301
- positionDiff = newPosition - prevPosition;
1341
+ const totalSize = peek$(ctx, "totalSize");
1342
+ let diff = newPosition - prevPosition;
1343
+ if (diff !== 0 && state.scroll + state.scrollLength > totalSize) {
1344
+ if (diff > 0) {
1345
+ diff = Math.max(0, totalSize - state.scroll - state.scrollLength);
1346
+ } else {
1347
+ diff = 0;
1348
+ }
1349
+ }
1350
+ positionDiff = diff;
1302
1351
  }
1303
1352
  }
1304
1353
  if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
@@ -1307,6 +1356,68 @@ function prepareMVCP(ctx, state, dataChanged) {
1307
1356
  };
1308
1357
  }
1309
1358
 
1359
+ // src/core/prepareColumnStartState.ts
1360
+ function prepareColumnStartState(ctx, state, startIndex, useAverageSize) {
1361
+ var _a3;
1362
+ const numColumns = peek$(ctx, "numColumns");
1363
+ let rowStartIndex = startIndex;
1364
+ const columnAtStart = state.columns.get(state.idCache[startIndex]);
1365
+ if (columnAtStart !== 1) {
1366
+ rowStartIndex = findRowStartIndex(state, numColumns, startIndex);
1367
+ }
1368
+ let currentRowTop = 0;
1369
+ const curId = state.idCache[rowStartIndex];
1370
+ const column = state.columns.get(curId);
1371
+ if (rowStartIndex > 0) {
1372
+ const prevIndex = rowStartIndex - 1;
1373
+ const prevId = state.idCache[prevIndex];
1374
+ const prevPosition = (_a3 = state.positions.get(prevId)) != null ? _a3 : 0;
1375
+ const prevRowStart = findRowStartIndex(state, numColumns, prevIndex);
1376
+ const prevRowHeight = calculateRowMaxSize(state, prevRowStart, prevIndex, useAverageSize);
1377
+ currentRowTop = prevPosition + prevRowHeight;
1378
+ }
1379
+ return {
1380
+ column,
1381
+ currentRowTop,
1382
+ startIndex: rowStartIndex
1383
+ };
1384
+ }
1385
+ function findRowStartIndex(state, numColumns, index) {
1386
+ if (numColumns <= 1) {
1387
+ return Math.max(0, index);
1388
+ }
1389
+ let rowStart = Math.max(0, index);
1390
+ while (rowStart > 0) {
1391
+ const columnForIndex = state.columns.get(state.idCache[rowStart]);
1392
+ if (columnForIndex === 1) {
1393
+ break;
1394
+ }
1395
+ rowStart--;
1396
+ }
1397
+ return rowStart;
1398
+ }
1399
+ function calculateRowMaxSize(state, startIndex, endIndex, useAverageSize) {
1400
+ if (endIndex < startIndex) {
1401
+ return 0;
1402
+ }
1403
+ const { data } = state.props;
1404
+ if (!data) {
1405
+ return 0;
1406
+ }
1407
+ let maxSize = 0;
1408
+ for (let i = startIndex; i <= endIndex; i++) {
1409
+ if (i < 0 || i >= data.length) {
1410
+ continue;
1411
+ }
1412
+ const id = state.idCache[i];
1413
+ const size = getItemSize(state, id, i, data[i], useAverageSize);
1414
+ if (size > maxSize) {
1415
+ maxSize = size;
1416
+ }
1417
+ }
1418
+ return maxSize;
1419
+ }
1420
+
1310
1421
  // src/utils/setPaddingTop.ts
1311
1422
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1312
1423
  if (stylePaddingTop !== void 0) {
@@ -1366,16 +1477,21 @@ function updateTotalSize(ctx, state) {
1366
1477
  }
1367
1478
  function addTotalSize(ctx, state, key, add) {
1368
1479
  const { alignItemsAtEnd } = state.props;
1369
- {
1480
+ const prevTotalSize = state.totalSize;
1481
+ if (key === null) {
1370
1482
  state.totalSize = add;
1371
1483
  if (state.timeoutSetPaddingTop) {
1372
1484
  clearTimeout(state.timeoutSetPaddingTop);
1373
1485
  state.timeoutSetPaddingTop = void 0;
1374
1486
  }
1487
+ } else {
1488
+ state.totalSize += add;
1375
1489
  }
1376
- set$(ctx, "totalSize", state.totalSize);
1377
- if (alignItemsAtEnd) {
1378
- updateAlignItemsPaddingTop(ctx, state);
1490
+ if (prevTotalSize !== state.totalSize) {
1491
+ set$(ctx, "totalSize", state.totalSize);
1492
+ if (alignItemsAtEnd) {
1493
+ updateAlignItemsPaddingTop(ctx, state);
1494
+ }
1379
1495
  }
1380
1496
  }
1381
1497
 
@@ -1394,9 +1510,9 @@ function updateSnapToOffsets(ctx, state) {
1394
1510
  set$(ctx, "snapToOffsets", snapToOffsets);
1395
1511
  }
1396
1512
 
1397
- // src/core/updateAllPositions.ts
1398
- function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1399
- var _a, _b, _c, _d, _e, _f;
1513
+ // src/core/updateItemPositions.ts
1514
+ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottomBuffered } = { scrollBottomBuffered: -1, startIndex: 0 }) {
1515
+ var _a3, _b, _c, _d;
1400
1516
  const {
1401
1517
  columns,
1402
1518
  indexByKey,
@@ -1406,32 +1522,48 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1406
1522
  props: { getEstimatedItemSize, snapToIndices, enableAverages }
1407
1523
  } = state;
1408
1524
  const data = state.props.data;
1525
+ const dataLength = data.length;
1409
1526
  const numColumns = peek$(ctx, "numColumns");
1410
- const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1527
+ const hasColumns = numColumns > 1;
1528
+ const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1529
+ const maxVisibleArea = scrollBottomBuffered + 1e3;
1411
1530
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1412
1531
  let currentRowTop = 0;
1413
1532
  let column = 1;
1414
1533
  let maxSizeInRow = 0;
1415
- const hasColumns = numColumns > 1;
1416
1534
  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
1535
  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);
1536
+ const { startIndex: processedStartIndex, currentRowTop: initialRowTop } = prepareColumnStartState(
1537
+ ctx,
1538
+ state,
1539
+ startIndex,
1540
+ useAverageSize
1541
+ );
1542
+ startIndex = processedStartIndex;
1543
+ currentRowTop = initialRowTop;
1544
+ } else if (startIndex < dataLength) {
1545
+ const prevIndex = startIndex - 1;
1546
+ const prevId = getId(state, prevIndex);
1547
+ const prevPosition = (_a3 = positions.get(prevId)) != null ? _a3 : 0;
1548
+ const prevSize = (_b = sizesKnown.get(prevId)) != null ? _b : getItemSize(state, prevId, prevIndex, data[prevIndex], useAverageSize);
1426
1549
  currentRowTop = prevPosition + prevSize;
1427
1550
  }
1428
1551
  }
1429
1552
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1430
- const dataLength = data.length;
1553
+ let didBreakEarly = false;
1554
+ let breakAt;
1431
1555
  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) {
1556
+ if (breakAt && i > breakAt) {
1557
+ didBreakEarly = true;
1558
+ break;
1559
+ }
1560
+ if (breakAt === void 0 && !dataChanged && currentRowTop > maxVisibleArea) {
1561
+ const itemsPerRow = hasColumns ? numColumns : 1;
1562
+ breakAt = i + itemsPerRow + 10;
1563
+ }
1564
+ const id = (_c = idCache[i]) != null ? _c : getId(state, i);
1565
+ const size = (_d = sizesKnown.get(id)) != null ? _d : getItemSize(state, id, i, data[i], useAverageSize);
1566
+ if (IS_DEV && needsIndexByKey) {
1435
1567
  if (indexByKeyForChecking.has(id)) {
1436
1568
  console.error(
1437
1569
  `[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 +1590,9 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1458
1590
  currentRowTop += size;
1459
1591
  }
1460
1592
  }
1461
- updateTotalSize(ctx, state);
1593
+ if (!didBreakEarly) {
1594
+ updateTotalSize(ctx, state);
1595
+ }
1462
1596
  if (snapToIndices) {
1463
1597
  updateSnapToOffsets(ctx, state);
1464
1598
  }
@@ -1478,6 +1612,21 @@ function ensureViewabilityState(ctx, configId) {
1478
1612
  }
1479
1613
  return state;
1480
1614
  }
1615
+ function setupViewability(props) {
1616
+ let { viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged } = props;
1617
+ if (viewabilityConfig || onViewableItemsChanged) {
1618
+ viewabilityConfigCallbackPairs = [
1619
+ ...viewabilityConfigCallbackPairs || [],
1620
+ {
1621
+ onViewableItemsChanged,
1622
+ viewabilityConfig: viewabilityConfig || {
1623
+ viewAreaCoveragePercentThreshold: 0
1624
+ }
1625
+ }
1626
+ ];
1627
+ }
1628
+ return viewabilityConfigCallbackPairs;
1629
+ }
1481
1630
  function updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollSize, start, end) {
1482
1631
  const {
1483
1632
  timeouts,
@@ -1649,9 +1798,12 @@ function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1649
1798
  }
1650
1799
 
1651
1800
  // src/utils/checkAllSizesKnown.ts
1801
+ function isNullOrUndefined2(value) {
1802
+ return value === null || value === void 0;
1803
+ }
1652
1804
  function checkAllSizesKnown(state) {
1653
1805
  const { startBuffered, endBuffered, sizesKnown } = state;
1654
- if (endBuffered !== null && startBuffered >= 0 && endBuffered >= 0) {
1806
+ if (!isNullOrUndefined2(endBuffered) && !isNullOrUndefined2(startBuffered) && startBuffered >= 0 && endBuffered >= 0) {
1655
1807
  let areAllKnown = true;
1656
1808
  for (let i = startBuffered; areAllKnown && i <= endBuffered; i++) {
1657
1809
  const key = getId(state, i);
@@ -1668,6 +1820,8 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1668
1820
  const { stickyContainerPool, containerItemTypes } = state;
1669
1821
  const result = [];
1670
1822
  const availableContainers = [];
1823
+ const pendingRemovalSet = new Set(pendingRemoval);
1824
+ let pendingRemovalChanged = false;
1671
1825
  const stickyIndicesSet = state.props.stickyIndicesSet;
1672
1826
  const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
1673
1827
  const canReuseContainer = (containerIndex, requiredType) => {
@@ -1683,12 +1837,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1683
1837
  let foundContainer = false;
1684
1838
  for (const containerIndex of stickyContainerPool) {
1685
1839
  const key = peek$(ctx, `containerItemKey${containerIndex}`);
1686
- const isPendingRemoval = pendingRemoval.includes(containerIndex);
1840
+ const isPendingRemoval = pendingRemovalSet.has(containerIndex);
1687
1841
  if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType)) {
1688
1842
  result.push(containerIndex);
1689
- if (isPendingRemoval) {
1690
- const index = pendingRemoval.indexOf(containerIndex);
1691
- pendingRemoval.splice(index, 1);
1843
+ if (isPendingRemoval && pendingRemovalSet.delete(containerIndex)) {
1844
+ pendingRemovalChanged = true;
1692
1845
  }
1693
1846
  foundContainer = true;
1694
1847
  if (requiredItemTypes) typeIndex++;
@@ -1708,13 +1861,11 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1708
1861
  }
1709
1862
  const key = peek$(ctx, `containerItemKey${u}`);
1710
1863
  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
- }
1864
+ if (!isOk && pendingRemovalSet.has(u)) {
1865
+ pendingRemovalSet.delete(u);
1866
+ pendingRemovalChanged = true;
1867
+ const requiredType = neededTypes[typeIndex];
1868
+ isOk = canReuseContainer(u, requiredType);
1718
1869
  }
1719
1870
  if (isOk) {
1720
1871
  result.push(u);
@@ -1757,7 +1908,7 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1757
1908
  for (let i = 0; i < stillNeeded; i++) {
1758
1909
  result.push(numContainers + i);
1759
1910
  }
1760
- if (__DEV__ && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
1911
+ if (IS_DEV && numContainers + stillNeeded > peek$(ctx, "numContainersPooled")) {
1761
1912
  console.warn(
1762
1913
  "[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
1914
  {
@@ -1772,6 +1923,12 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1772
1923
  }
1773
1924
  }
1774
1925
  }
1926
+ if (pendingRemovalChanged) {
1927
+ pendingRemoval.length = 0;
1928
+ for (const value of pendingRemovalSet) {
1929
+ pendingRemoval.push(value);
1930
+ }
1931
+ }
1775
1932
  return result.sort(comparatorDefault);
1776
1933
  }
1777
1934
  function comparatorByDistance(a, b) {
@@ -1828,40 +1985,55 @@ function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, vie
1828
1985
  if (isLast && viewPosition === void 0) {
1829
1986
  viewPosition = 1;
1830
1987
  }
1831
- const firstIndexScrollPostion = firstIndexOffset - viewOffset;
1832
1988
  state.scrollForNextCalculateItemsInView = void 0;
1833
1989
  scrollTo(state, {
1834
1990
  animated,
1835
1991
  index,
1836
- offset: firstIndexScrollPostion,
1992
+ offset: firstIndexOffset,
1837
1993
  viewOffset,
1838
1994
  viewPosition: viewPosition != null ? viewPosition : 0
1839
1995
  });
1840
1996
  }
1841
1997
 
1842
1998
  // 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) {
1999
+ var HYSTERESIS_MULTIPLIER = 1.3;
2000
+ var checkThreshold = (distance, atThreshold, threshold, wasReached, snapshot, context, onReached, setSnapshot) => {
2001
+ const absDistance = Math.abs(distance);
2002
+ const within = atThreshold || threshold > 0 && absDistance <= threshold;
2003
+ const updateSnapshot = () => {
2004
+ setSnapshot == null ? void 0 : setSnapshot({
2005
+ atThreshold,
2006
+ contentSize: context.contentSize,
2007
+ dataLength: context.dataLength,
2008
+ scrollPosition: context.scrollPosition
2009
+ });
2010
+ };
2011
+ if (!wasReached) {
2012
+ if (!within) {
1857
2013
  return false;
1858
2014
  }
2015
+ onReached == null ? void 0 : onReached(distance);
2016
+ updateSnapshot();
2017
+ return true;
2018
+ }
2019
+ const reset = !atThreshold && threshold > 0 && absDistance >= threshold * HYSTERESIS_MULTIPLIER || !atThreshold && threshold <= 0 && absDistance > 0;
2020
+ if (reset) {
2021
+ setSnapshot == null ? void 0 : setSnapshot(void 0);
2022
+ return false;
2023
+ }
2024
+ if (within) {
2025
+ const changed = !snapshot || snapshot.atThreshold !== atThreshold || snapshot.contentSize !== context.contentSize || snapshot.dataLength !== context.dataLength;
2026
+ if (changed) {
2027
+ onReached == null ? void 0 : onReached(distance);
2028
+ updateSnapshot();
2029
+ }
1859
2030
  }
1860
- return isReached;
2031
+ return true;
1861
2032
  };
1862
2033
 
1863
2034
  // src/utils/checkAtBottom.ts
1864
2035
  function checkAtBottom(ctx, state) {
2036
+ var _a3;
1865
2037
  if (!state) {
1866
2038
  return;
1867
2039
  }
@@ -1882,13 +2054,18 @@ function checkAtBottom(ctx, state) {
1882
2054
  isContentLess,
1883
2055
  onEndReachedThreshold * scrollLength,
1884
2056
  state.isEndReached,
1885
- state.endReachedBlockedByTimer,
2057
+ state.endReachedSnapshot,
2058
+ {
2059
+ scrollPosition: scroll,
2060
+ contentSize,
2061
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length
2062
+ },
1886
2063
  (distance) => {
1887
- var _a, _b;
1888
- return (_b = (_a = state.props).onEndReached) == null ? void 0 : _b.call(_a, { distanceFromEnd: distance });
2064
+ var _a4, _b;
2065
+ return (_b = (_a4 = state.props).onEndReached) == null ? void 0 : _b.call(_a4, { distanceFromEnd: distance });
1889
2066
  },
1890
- (block) => {
1891
- state.endReachedBlockedByTimer = block;
2067
+ (snapshot) => {
2068
+ state.endReachedSnapshot = snapshot;
1892
2069
  }
1893
2070
  );
1894
2071
  }
@@ -1916,11 +2093,12 @@ function setDidLayout(ctx, state) {
1916
2093
 
1917
2094
  // src/core/calculateItemsInView.ts
1918
2095
  function findCurrentStickyIndex(stickyArray, scroll, state) {
1919
- var _a;
2096
+ var _a3;
1920
2097
  const idCache = state.idCache;
1921
2098
  const positions = state.positions;
1922
2099
  for (let i = stickyArray.length - 1; i >= 0; i--) {
1923
- const stickyId = (_a = idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
2100
+ const stickyIndex = stickyArray[i];
2101
+ const stickyId = (_a3 = idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
1924
2102
  const stickyPos = stickyId ? positions.get(stickyId) : void 0;
1925
2103
  if (stickyPos !== void 0 && scroll >= stickyPos) {
1926
2104
  return i;
@@ -1933,39 +2111,43 @@ function getActiveStickyIndices(ctx, state, stickyIndices) {
1933
2111
  Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyIndices.has(idx))
1934
2112
  );
1935
2113
  }
1936
- function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll, needNewContainers, startBuffered, endBuffered) {
1937
- var _a;
2114
+ function handleStickyActivation(ctx, state, stickyIndices, stickyArray, currentStickyIdx, needNewContainers, startBuffered, endBuffered) {
2115
+ var _a3;
1938
2116
  const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
1939
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
2117
+ state.activeStickyIndex = currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : void 0;
1940
2118
  for (let offset = 0; offset <= 1; offset++) {
1941
2119
  const idx = currentStickyIdx - offset;
1942
2120
  if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
1943
2121
  const stickyIndex = stickyArray[idx];
1944
- const stickyId = (_a = state.idCache.get(stickyIndex)) != null ? _a : getId(state, stickyIndex);
2122
+ const stickyId = (_a3 = state.idCache[stickyIndex]) != null ? _a3 : getId(state, stickyIndex);
1945
2123
  if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered)) {
1946
2124
  needNewContainers.push(stickyIndex);
1947
2125
  }
1948
2126
  }
1949
2127
  }
1950
- function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pendingRemoval) {
1951
- var _a, _b, _c;
1952
- const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
2128
+ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, currentStickyIdx, pendingRemoval) {
2129
+ var _a3, _b, _c;
1953
2130
  for (const containerIndex of state.stickyContainerPool) {
1954
2131
  const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
1955
2132
  const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
1956
2133
  if (itemIndex === void 0) continue;
1957
2134
  const arrayIdx = stickyArray.indexOf(itemIndex);
1958
- if (arrayIdx === -1) continue;
2135
+ if (arrayIdx === -1) {
2136
+ state.stickyContainerPool.delete(containerIndex);
2137
+ set$(ctx, `containerSticky${containerIndex}`, false);
2138
+ set$(ctx, `containerStickyOffset${containerIndex}`, void 0);
2139
+ continue;
2140
+ }
1959
2141
  const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
1960
2142
  if (isRecentSticky) continue;
1961
2143
  const nextIndex = stickyArray[arrayIdx + 1];
1962
2144
  let shouldRecycle = false;
1963
2145
  if (nextIndex) {
1964
- const nextId = (_a = state.idCache.get(nextIndex)) != null ? _a : getId(state, nextIndex);
2146
+ const nextId = (_a3 = state.idCache[nextIndex]) != null ? _a3 : getId(state, nextIndex);
1965
2147
  const nextPos = nextId ? state.positions.get(nextId) : void 0;
1966
2148
  shouldRecycle = nextPos !== void 0 && scroll > nextPos + scrollBuffer * 2;
1967
2149
  } else {
1968
- const currentId = (_b = state.idCache.get(itemIndex)) != null ? _b : getId(state, itemIndex);
2150
+ const currentId = (_b = state.idCache[itemIndex]) != null ? _b : getId(state, itemIndex);
1969
2151
  if (currentId) {
1970
2152
  const currentPos = state.positions.get(currentId);
1971
2153
  const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
@@ -1979,7 +2161,7 @@ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pe
1979
2161
  }
1980
2162
  function calculateItemsInView(ctx, state, params = {}) {
1981
2163
  reactDom.unstable_batchedUpdates(() => {
1982
- var _a, _b, _c, _d, _e, _f, _g, _h;
2164
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i;
1983
2165
  const {
1984
2166
  columns,
1985
2167
  containerItemKeys,
@@ -1993,7 +2175,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1993
2175
  sizes,
1994
2176
  startBufferedId: startBufferedIdOrig,
1995
2177
  viewabilityConfigCallbackPairs,
1996
- props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, scrollBuffer }
2178
+ props: { getItemType, initialScroll, itemsAreEqual, keyExtractor, onStickyHeaderChange, scrollBuffer }
1997
2179
  } = state;
1998
2180
  const { data } = state.props;
1999
2181
  const stickyIndicesArr = state.props.stickyIndicesArr || [];
@@ -2005,23 +2187,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2005
2187
  const totalSize = peek$(ctx, "totalSize");
2006
2188
  const topPad = peek$(ctx, "stylePaddingTop") + peek$(ctx, "headerSize");
2007
2189
  const numColumns = peek$(ctx, "numColumns");
2008
- const previousScrollAdjust = 0;
2009
2190
  const { dataChanged, doMVCP } = params;
2010
2191
  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
2192
  const scrollExtra = 0;
2026
2193
  const { queuedInitialLayout } = state;
2027
2194
  let { scroll: scrollState } = state;
@@ -2033,7 +2200,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2033
2200
  );
2034
2201
  scrollState = updatedOffset;
2035
2202
  }
2036
- const scrollAdjustPad = -previousScrollAdjust - topPad;
2203
+ const scrollAdjustPad = -topPad;
2037
2204
  let scroll = scrollState + scrollExtra + scrollAdjustPad;
2038
2205
  if (scroll + scrollLength > totalSize) {
2039
2206
  scroll = Math.max(0, totalSize - scrollLength);
@@ -2042,6 +2209,10 @@ function calculateItemsInView(ctx, state, params = {}) {
2042
2209
  set$(ctx, "debugRawScroll", scrollState);
2043
2210
  set$(ctx, "debugComputedScroll", scroll);
2044
2211
  }
2212
+ const previousStickyIndex = state.activeStickyIndex;
2213
+ const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
2214
+ const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : void 0;
2215
+ state.activeStickyIndex = nextActiveStickyIndex;
2045
2216
  let scrollBufferTop = scrollBuffer;
2046
2217
  let scrollBufferBottom = scrollBuffer;
2047
2218
  if (speed > 0 || speed === 0 && scroll < Math.max(50, scrollBuffer)) {
@@ -2054,22 +2225,34 @@ function calculateItemsInView(ctx, state, params = {}) {
2054
2225
  const scrollTopBuffered = scroll - scrollBufferTop;
2055
2226
  const scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
2056
2227
  const scrollBottomBuffered = scrollBottom + scrollBufferBottom;
2057
- if (scrollForNextCalculateItemsInView) {
2228
+ if (!dataChanged && scrollForNextCalculateItemsInView) {
2058
2229
  const { top, bottom } = scrollForNextCalculateItemsInView;
2059
2230
  if (scrollTopBuffered > top && scrollBottomBuffered < bottom) {
2060
2231
  return;
2061
2232
  }
2062
2233
  }
2234
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
2235
+ if (dataChanged) {
2236
+ indexByKey.clear();
2237
+ idCache.length = 0;
2238
+ positions.clear();
2239
+ }
2240
+ const startIndex = dataChanged ? 0 : (_a3 = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _a3 : 0;
2241
+ updateItemPositions(ctx, state, dataChanged, { scrollBottomBuffered, startIndex });
2242
+ if (minIndexSizeChanged !== void 0) {
2243
+ state.minIndexSizeChanged = void 0;
2244
+ }
2245
+ checkMVCP == null ? void 0 : checkMVCP();
2063
2246
  let startNoBuffer = null;
2064
2247
  let startBuffered = null;
2065
2248
  let startBufferedId = null;
2066
2249
  let endNoBuffer = null;
2067
2250
  let endBuffered = null;
2068
- let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2251
+ let loopStart = !dataChanged && startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
2069
2252
  for (let i = loopStart; i >= 0; i--) {
2070
- const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
2253
+ const id = (_b = idCache[i]) != null ? _b : getId(state, i);
2071
2254
  const top = positions.get(id);
2072
- const size = (_b = sizes.get(id)) != null ? _b : getItemSize(state, id, i, data[i]);
2255
+ const size = (_c = sizes.get(id)) != null ? _c : getItemSize(state, id, i, data[i]);
2073
2256
  const bottom = top + size;
2074
2257
  if (bottom > scroll - scrollBuffer) {
2075
2258
  loopStart = i;
@@ -2095,8 +2278,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2095
2278
  let firstFullyOnScreenIndex;
2096
2279
  const dataLength = data.length;
2097
2280
  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]);
2281
+ const id = (_d = idCache[i]) != null ? _d : getId(state, i);
2282
+ const size = (_e = sizes.get(id)) != null ? _e : getItemSize(state, id, i, data[i]);
2100
2283
  const top = positions.get(id);
2101
2284
  if (!foundEnd) {
2102
2285
  if (startNoBuffer === null && top + size > scroll) {
@@ -2125,7 +2308,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2125
2308
  }
2126
2309
  const idsInView = [];
2127
2310
  for (let i = firstFullyOnScreenIndex; i <= endNoBuffer; i++) {
2128
- const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
2311
+ const id = (_f = idCache[i]) != null ? _f : getId(state, i);
2129
2312
  idsInView.push(id);
2130
2313
  }
2131
2314
  Object.assign(state, {
@@ -2157,7 +2340,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2157
2340
  let numContainers2 = prevNumContainers;
2158
2341
  const needNewContainers = [];
2159
2342
  for (let i = startBuffered; i <= endBuffered; i++) {
2160
- const id = (_f = idCache.get(i)) != null ? _f : getId(state, i);
2343
+ const id = (_g = idCache[i]) != null ? _g : getId(state, i);
2161
2344
  if (!containerItemKeys.has(id)) {
2162
2345
  needNewContainers.push(i);
2163
2346
  }
@@ -2168,11 +2351,13 @@ function calculateItemsInView(ctx, state, params = {}) {
2168
2351
  state,
2169
2352
  stickyIndicesSet,
2170
2353
  stickyIndicesArr,
2171
- scroll,
2354
+ currentStickyIdx,
2172
2355
  needNewContainers,
2173
2356
  startBuffered,
2174
2357
  endBuffered
2175
2358
  );
2359
+ } else {
2360
+ state.activeStickyIndex = void 0;
2176
2361
  }
2177
2362
  if (needNewContainers.length > 0) {
2178
2363
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
@@ -2192,7 +2377,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2192
2377
  for (let idx = 0; idx < needNewContainers.length; idx++) {
2193
2378
  const i = needNewContainers[idx];
2194
2379
  const containerIndex = availableContainers[idx];
2195
- const id = (_g = idCache.get(i)) != null ? _g : getId(state, i);
2380
+ const id = (_h = idCache[i]) != null ? _h : getId(state, i);
2196
2381
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
2197
2382
  if (oldKey && oldKey !== id) {
2198
2383
  containerItemKeys.delete(oldKey);
@@ -2206,9 +2391,10 @@ function calculateItemsInView(ctx, state, params = {}) {
2206
2391
  if (stickyIndicesSet.has(i)) {
2207
2392
  set$(ctx, `containerSticky${containerIndex}`, true);
2208
2393
  const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
2209
- set$(ctx, `containerStickyOffset${containerIndex}`, createAnimatedValue(topPadding));
2394
+ set$(ctx, `containerStickyOffset${containerIndex}`, topPadding);
2210
2395
  state.stickyContainerPool.add(containerIndex);
2211
2396
  } else {
2397
+ set$(ctx, `containerSticky${containerIndex}`, false);
2212
2398
  state.stickyContainerPool.delete(containerIndex);
2213
2399
  }
2214
2400
  if (containerIndex >= numContainers2) {
@@ -2224,7 +2410,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2224
2410
  }
2225
2411
  }
2226
2412
  if (stickyIndicesArr.length > 0) {
2227
- handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, pendingRemoval);
2413
+ handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, currentStickyIdx, pendingRemoval);
2228
2414
  }
2229
2415
  let didChangePositions = false;
2230
2416
  for (let i = 0; i < numContainers; i++) {
@@ -2247,7 +2433,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2247
2433
  const itemIndex = indexByKey.get(itemKey);
2248
2434
  const item = data[itemIndex];
2249
2435
  if (item !== void 0) {
2250
- const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
2436
+ const id = (_i = idCache[itemIndex]) != null ? _i : getId(state, itemIndex);
2251
2437
  const position = positions.get(id);
2252
2438
  if (position === void 0) {
2253
2439
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
@@ -2264,7 +2450,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2264
2450
  set$(ctx, `containerColumn${i}`, column);
2265
2451
  }
2266
2452
  if (prevData !== item && (itemsAreEqual ? !itemsAreEqual(prevData, item, itemIndex, data) : true)) {
2267
- set$(ctx, `containerItemData${i}`, data[itemIndex]);
2453
+ set$(ctx, `containerItemData${i}`, item);
2268
2454
  }
2269
2455
  }
2270
2456
  }
@@ -2281,56 +2467,13 @@ function calculateItemsInView(ctx, state, params = {}) {
2281
2467
  if (viewabilityConfigCallbackPairs) {
2282
2468
  updateViewableItems(state, ctx, viewabilityConfigCallbackPairs, scrollLength, startNoBuffer, endNoBuffer);
2283
2469
  }
2284
- });
2285
- }
2286
-
2287
- // src/core/doInitialAllocateContainers.ts
2288
- function doInitialAllocateContainers(ctx, state) {
2289
- var _a;
2290
- const {
2291
- scrollLength,
2292
- props: {
2293
- data,
2294
- getEstimatedItemSize,
2295
- getFixedItemSize,
2296
- getItemType,
2297
- scrollBuffer,
2298
- numColumns,
2299
- estimatedItemSize
2300
- }
2301
- } = state;
2302
- const hasContainers = peek$(ctx, "numContainers");
2303
- if (scrollLength > 0 && data.length > 0 && !hasContainers) {
2304
- let averageItemSize;
2305
- const fn = getFixedItemSize || getEstimatedItemSize;
2306
- if (fn) {
2307
- let totalSize = 0;
2308
- const num = Math.min(20, data.length);
2309
- for (let i = 0; i < num; i++) {
2310
- totalSize += fn(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "");
2311
- }
2312
- averageItemSize = totalSize / num;
2313
- } else {
2314
- averageItemSize = estimatedItemSize;
2315
- }
2316
- const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize * numColumns);
2317
- for (let i = 0; i < numContainers; i++) {
2318
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2319
- set$(ctx, `containerColumn${i}`, -1);
2320
- }
2321
- set$(ctx, "numContainers", numContainers);
2322
- set$(ctx, "numContainersPooled", numContainers * state.props.initialContainerPoolRatio);
2323
- if (state.lastLayout) {
2324
- if (state.props.initialScroll) {
2325
- requestAnimationFrame(() => {
2326
- calculateItemsInView(ctx, state, { dataChanged: true });
2327
- });
2328
- } else {
2329
- calculateItemsInView(ctx, state, { dataChanged: true });
2470
+ if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
2471
+ const item = data[nextActiveStickyIndex];
2472
+ if (item !== void 0) {
2473
+ onStickyHeaderChange({ index: nextActiveStickyIndex, item });
2330
2474
  }
2331
2475
  }
2332
- return true;
2333
- }
2476
+ });
2334
2477
  }
2335
2478
 
2336
2479
  // src/core/doMaintainScrollAtEnd.ts
@@ -2345,10 +2488,10 @@ function doMaintainScrollAtEnd(ctx, state, animated) {
2345
2488
  state.scroll = 0;
2346
2489
  }
2347
2490
  requestAnimationFrame(() => {
2348
- var _a;
2491
+ var _a3;
2349
2492
  if (state == null ? void 0 : state.isAtEnd) {
2350
2493
  state.maintainingScrollAtEnd = true;
2351
- (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
2494
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
2352
2495
  animated
2353
2496
  });
2354
2497
  setTimeout(
@@ -2365,6 +2508,7 @@ function doMaintainScrollAtEnd(ctx, state, animated) {
2365
2508
 
2366
2509
  // src/utils/checkAtTop.ts
2367
2510
  function checkAtTop(state) {
2511
+ var _a3;
2368
2512
  if (!state) {
2369
2513
  return;
2370
2514
  }
@@ -2380,17 +2524,146 @@ function checkAtTop(state) {
2380
2524
  false,
2381
2525
  onStartReachedThreshold * scrollLength,
2382
2526
  state.isStartReached,
2383
- state.startReachedBlockedByTimer,
2527
+ state.startReachedSnapshot,
2528
+ {
2529
+ scrollPosition: scroll,
2530
+ contentSize: state.totalSize,
2531
+ dataLength: (_a3 = state.props.data) == null ? void 0 : _a3.length
2532
+ },
2384
2533
  (distance) => {
2385
- var _a, _b;
2386
- return (_b = (_a = state.props).onStartReached) == null ? void 0 : _b.call(_a, { distanceFromStart: distance });
2534
+ var _a4, _b;
2535
+ return (_b = (_a4 = state.props).onStartReached) == null ? void 0 : _b.call(_a4, { distanceFromStart: distance });
2387
2536
  },
2388
- (block) => {
2389
- state.startReachedBlockedByTimer = block;
2537
+ (snapshot) => {
2538
+ state.startReachedSnapshot = snapshot;
2390
2539
  }
2391
2540
  );
2392
2541
  }
2393
2542
 
2543
+ // src/utils/updateAveragesOnDataChange.ts
2544
+ function updateAveragesOnDataChange(state, oldData, newData) {
2545
+ var _a3;
2546
+ const {
2547
+ averageSizes,
2548
+ sizesKnown,
2549
+ indexByKey,
2550
+ props: { itemsAreEqual, getItemType, keyExtractor }
2551
+ } = state;
2552
+ if (!itemsAreEqual || !oldData.length || !newData.length) {
2553
+ for (const key in averageSizes) {
2554
+ delete averageSizes[key];
2555
+ }
2556
+ return;
2557
+ }
2558
+ const itemTypesToPreserve = {};
2559
+ const newDataLength = newData.length;
2560
+ const oldDataLength = oldData.length;
2561
+ for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
2562
+ const newItem = newData[newIndex];
2563
+ const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
2564
+ const oldIndex = indexByKey.get(id);
2565
+ if (oldIndex !== void 0 && oldIndex < oldDataLength) {
2566
+ const knownSize = sizesKnown.get(id);
2567
+ if (knownSize === void 0) continue;
2568
+ const oldItem = oldData[oldIndex];
2569
+ const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
2570
+ if (areEqual) {
2571
+ const itemType = getItemType ? (_a3 = getItemType(newItem, newIndex)) != null ? _a3 : "" : "";
2572
+ let typeData = itemTypesToPreserve[itemType];
2573
+ if (!typeData) {
2574
+ typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
2575
+ }
2576
+ typeData.totalSize += knownSize;
2577
+ typeData.count++;
2578
+ }
2579
+ }
2580
+ }
2581
+ for (const key in averageSizes) {
2582
+ delete averageSizes[key];
2583
+ }
2584
+ for (const itemType in itemTypesToPreserve) {
2585
+ const { totalSize, count } = itemTypesToPreserve[itemType];
2586
+ if (count > 0) {
2587
+ averageSizes[itemType] = {
2588
+ avg: totalSize / count,
2589
+ num: count
2590
+ };
2591
+ }
2592
+ }
2593
+ }
2594
+
2595
+ // src/core/checkResetContainers.ts
2596
+ function checkResetContainers(ctx, state, isFirst, dataProp) {
2597
+ if (state) {
2598
+ if (!isFirst && state.props.data !== dataProp) {
2599
+ updateAveragesOnDataChange(state, state.props.data, dataProp);
2600
+ }
2601
+ const { maintainScrollAtEnd } = state.props;
2602
+ if (!isFirst) {
2603
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2604
+ const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
2605
+ const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state, false);
2606
+ if (!didMaintainScrollAtEnd && dataProp.length > state.props.data.length) {
2607
+ state.isEndReached = false;
2608
+ }
2609
+ if (!didMaintainScrollAtEnd) {
2610
+ checkAtTop(state);
2611
+ checkAtBottom(ctx, state);
2612
+ }
2613
+ }
2614
+ }
2615
+ }
2616
+
2617
+ // src/core/doInitialAllocateContainers.ts
2618
+ function doInitialAllocateContainers(ctx, state) {
2619
+ var _a3, _b, _c;
2620
+ const {
2621
+ scrollLength,
2622
+ props: {
2623
+ data,
2624
+ getEstimatedItemSize,
2625
+ getFixedItemSize,
2626
+ getItemType,
2627
+ scrollBuffer,
2628
+ numColumns,
2629
+ estimatedItemSize
2630
+ }
2631
+ } = state;
2632
+ const hasContainers = peek$(ctx, "numContainers");
2633
+ if (scrollLength > 0 && data.length > 0 && !hasContainers) {
2634
+ let averageItemSize;
2635
+ if (getFixedItemSize || getEstimatedItemSize) {
2636
+ let totalSize = 0;
2637
+ const num = Math.min(20, data.length);
2638
+ for (let i = 0; i < num; i++) {
2639
+ const item = data[i];
2640
+ const itemType = getItemType ? (_a3 = getItemType(item, i)) != null ? _a3 : "" : "";
2641
+ totalSize += (_c = (_b = getFixedItemSize == null ? void 0 : getFixedItemSize(i, item, itemType)) != null ? _b : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(i, item, itemType)) != null ? _c : estimatedItemSize;
2642
+ }
2643
+ averageItemSize = totalSize / num;
2644
+ } else {
2645
+ averageItemSize = estimatedItemSize;
2646
+ }
2647
+ const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize * numColumns);
2648
+ for (let i = 0; i < numContainers; i++) {
2649
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2650
+ set$(ctx, `containerColumn${i}`, -1);
2651
+ }
2652
+ set$(ctx, "numContainers", numContainers);
2653
+ set$(ctx, "numContainersPooled", numContainers * state.props.initialContainerPoolRatio);
2654
+ if (state.lastLayout) {
2655
+ if (state.props.initialScroll) {
2656
+ requestAnimationFrame(() => {
2657
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2658
+ });
2659
+ } else {
2660
+ calculateItemsInView(ctx, state, { dataChanged: true, doMVCP: true });
2661
+ }
2662
+ }
2663
+ return true;
2664
+ }
2665
+ }
2666
+
2394
2667
  // src/core/handleLayout.ts
2395
2668
  function handleLayout(ctx, state, layout, setCanRender) {
2396
2669
  const { maintainScrollAtEnd } = state.props;
@@ -2425,19 +2698,19 @@ function handleLayout(ctx, state, layout, setCanRender) {
2425
2698
  if (state) {
2426
2699
  state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2427
2700
  }
2428
- if (__DEV__ && measuredLength === 0) {
2701
+ if (IS_DEV && measuredLength === 0) {
2429
2702
  warnDevOnce(
2430
2703
  "height0",
2431
2704
  `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
2705
  );
2433
2706
  }
2434
- setCanRender(true);
2435
2707
  }
2708
+ setCanRender(true);
2436
2709
  }
2437
2710
 
2438
2711
  // src/core/onScroll.ts
2439
2712
  function onScroll(ctx, state, event) {
2440
- var _a, _b, _c;
2713
+ var _a3, _b, _c;
2441
2714
  const {
2442
2715
  scrollProcessingEnabled,
2443
2716
  props: { onScroll: onScrollProp }
@@ -2445,27 +2718,12 @@ function onScroll(ctx, state, event) {
2445
2718
  if (scrollProcessingEnabled === false) {
2446
2719
  return;
2447
2720
  }
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) {
2721
+ 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
2722
  return;
2450
2723
  }
2451
2724
  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
2725
  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
- }
2726
+ updateScroll(ctx, state, newScroll);
2469
2727
  onScrollProp == null ? void 0 : onScrollProp(event);
2470
2728
  }
2471
2729
  function updateScroll(ctx, state, newScroll) {
@@ -2473,9 +2731,17 @@ function updateScroll(ctx, state, newScroll) {
2473
2731
  state.hasScrolled = true;
2474
2732
  state.lastBatchingAction = Date.now();
2475
2733
  const currentTime = Date.now();
2734
+ const adjust = state.scrollAdjustHandler.getAdjust();
2735
+ const lastHistoryAdjust = state.lastScrollAdjustForHistory;
2736
+ const adjustChanged = lastHistoryAdjust !== void 0 && Math.abs(adjust - lastHistoryAdjust) > 0.1;
2737
+ if (adjustChanged) {
2738
+ state.scrollHistory.length = 0;
2739
+ }
2740
+ state.lastScrollAdjustForHistory = adjust;
2476
2741
  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 });
2742
+ if (!adjustChanged) {
2743
+ state.scrollHistory.push({ scroll: newScroll, time: currentTime });
2744
+ }
2479
2745
  }
2480
2746
  if (state.scrollHistory.length > 5) {
2481
2747
  state.scrollHistory.shift();
@@ -2484,10 +2750,18 @@ function updateScroll(ctx, state, newScroll) {
2484
2750
  state.scrollPrevTime = state.scrollTime;
2485
2751
  state.scroll = newScroll;
2486
2752
  state.scrollTime = currentTime;
2487
- if (Math.abs(state.scroll - state.scrollPrev) > 2) {
2488
- calculateItemsInView(ctx, state);
2753
+ const ignoreScrollFromMVCP = state.ignoreScrollFromMVCP;
2754
+ if (ignoreScrollFromMVCP && !state.scrollingTo) {
2755
+ const { lt, gt } = ignoreScrollFromMVCP;
2756
+ if (lt && newScroll < lt || gt && newScroll > gt) {
2757
+ return;
2758
+ }
2759
+ }
2760
+ if (state.dataChangeNeedsScrollUpdate || Math.abs(state.scroll - state.scrollPrev) > 2) {
2761
+ calculateItemsInView(ctx, state, { doMVCP: state.scrollingTo !== void 0 });
2489
2762
  checkAtBottom(ctx, state);
2490
2763
  checkAtTop(state);
2764
+ state.dataChangeNeedsScrollUpdate = false;
2491
2765
  }
2492
2766
  }
2493
2767
 
@@ -2499,7 +2773,7 @@ var ScrollAdjustHandler = class {
2499
2773
  this.context = ctx;
2500
2774
  }
2501
2775
  requestAdjust(add) {
2502
- const oldAdjustTop = peek$(this.context, "scrollAdjust") || 0;
2776
+ const oldAdjustTop = this.appliedAdjust;
2503
2777
  this.appliedAdjust = add + oldAdjustTop;
2504
2778
  const set = () => set$(this.context, "scrollAdjust", this.appliedAdjust);
2505
2779
  if (this.mounted) {
@@ -2518,14 +2792,13 @@ var ScrollAdjustHandler = class {
2518
2792
 
2519
2793
  // src/core/updateItemSize.ts
2520
2794
  function updateItemSize(ctx, state, itemKey, sizeObj) {
2521
- var _a, _b;
2795
+ var _a3;
2522
2796
  const {
2523
2797
  sizesKnown,
2524
2798
  props: {
2525
2799
  getFixedItemSize,
2526
2800
  getItemType,
2527
2801
  horizontal,
2528
- maintainVisibleContentPosition,
2529
2802
  suggestEstimatedItemSize,
2530
2803
  onItemSizeChanged,
2531
2804
  data,
@@ -2533,17 +2806,17 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2533
2806
  }
2534
2807
  } = state;
2535
2808
  if (!data) return;
2809
+ const index = state.indexByKey.get(itemKey);
2536
2810
  if (getFixedItemSize) {
2537
- const index2 = state.indexByKey.get(itemKey);
2538
- if (index2 === void 0) {
2811
+ if (index === void 0) {
2539
2812
  return;
2540
2813
  }
2541
- const itemData = state.props.data[index2];
2814
+ const itemData = state.props.data[index];
2542
2815
  if (itemData === void 0) {
2543
2816
  return;
2544
2817
  }
2545
- const type = getItemType ? (_a = getItemType(itemData, index2)) != null ? _a : "" : "";
2546
- const size2 = getFixedItemSize(index2, itemData, type);
2818
+ const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
2819
+ const size2 = getFixedItemSize(index, itemData, type);
2547
2820
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
2548
2821
  return;
2549
2822
  }
@@ -2553,15 +2826,11 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2553
2826
  let shouldMaintainScrollAtEnd = false;
2554
2827
  let minIndexSizeChanged;
2555
2828
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2556
- const index = state.indexByKey.get(itemKey);
2557
2829
  const prevSizeKnown = state.sizesKnown.get(itemKey);
2558
2830
  const diff = updateOneItemSize(state, itemKey, sizeObj);
2559
2831
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2560
2832
  if (diff !== 0) {
2561
2833
  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
2834
  const { startBuffered, endBuffered } = state;
2566
2835
  needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2567
2836
  if (!needsRecalculate) {
@@ -2580,6 +2849,7 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2580
2849
  if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
2581
2850
  shouldMaintainScrollAtEnd = true;
2582
2851
  }
2852
+ addTotalSize(ctx, state, itemKey, diff);
2583
2853
  onItemSizeChanged == null ? void 0 : onItemSizeChanged({
2584
2854
  index,
2585
2855
  itemData: state.props.data[index],
@@ -2591,13 +2861,13 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2591
2861
  if (minIndexSizeChanged !== void 0) {
2592
2862
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
2593
2863
  }
2594
- if (__DEV__ && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
2864
+ if (IS_DEV && suggestEstimatedItemSize && minIndexSizeChanged !== void 0) {
2595
2865
  if (state.timeoutSizeMessage) clearTimeout(state.timeoutSizeMessage);
2596
2866
  state.timeoutSizeMessage = setTimeout(() => {
2597
- var _a2;
2867
+ var _a4;
2598
2868
  state.timeoutSizeMessage = void 0;
2599
2869
  const num = state.sizesKnown.size;
2600
- const avg = (_a2 = state.averageSizes[""]) == null ? void 0 : _a2.avg;
2870
+ const avg = (_a4 = state.averageSizes[""]) == null ? void 0 : _a4.avg;
2601
2871
  console.warn(
2602
2872
  `[legend-list] Based on the ${num} items rendered so far, the optimal estimated size is ${avg}.`
2603
2873
  );
@@ -2620,7 +2890,7 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2620
2890
  }
2621
2891
  }
2622
2892
  function updateOneItemSize(state, itemKey, sizeObj) {
2623
- var _a;
2893
+ var _a3;
2624
2894
  const {
2625
2895
  sizes,
2626
2896
  indexByKey,
@@ -2630,12 +2900,12 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2630
2900
  } = state;
2631
2901
  if (!data) return 0;
2632
2902
  const index = indexByKey.get(itemKey);
2633
- const prevSize = getItemSize(state, itemKey, index, data);
2903
+ const prevSize = getItemSize(state, itemKey, index, data[index]);
2634
2904
  const rawSize = horizontal ? sizeObj.width : sizeObj.height;
2635
2905
  const size = Math.round(rawSize) ;
2636
2906
  sizesKnown.set(itemKey, size);
2637
2907
  if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
2638
- const itemType = getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : "";
2908
+ const itemType = getItemType ? (_a3 = getItemType(data[index], index)) != null ? _a3 : "" : "";
2639
2909
  let averages = averageSizes[itemType];
2640
2910
  if (!averages) {
2641
2911
  averages = averageSizes[itemType] = { avg: 0, num: 0 };
@@ -2650,7 +2920,7 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2650
2920
  return 0;
2651
2921
  }
2652
2922
  var useCombinedRef = (...refs) => {
2653
- const callback = React4.useCallback((element) => {
2923
+ const callback = React3.useCallback((element) => {
2654
2924
  for (const ref of refs) {
2655
2925
  if (!ref) {
2656
2926
  continue;
@@ -2666,24 +2936,12 @@ var useCombinedRef = (...refs) => {
2666
2936
  };
2667
2937
 
2668
2938
  // src/platform/RefreshControl.tsx
2669
- function RefreshControl(props) {
2939
+ function RefreshControl(_props) {
2670
2940
  return null;
2671
2941
  }
2672
2942
 
2673
- // src/platform/StyleSheet.tsx
2674
- function flattenStyles(styles) {
2675
- if (Array.isArray(styles)) {
2676
- return Object.assign({}, ...styles.filter(Boolean));
2677
- }
2678
- return styles;
2679
- }
2680
- var StyleSheet = {
2681
- create: (styles) => styles,
2682
- flatten: (style) => flattenStyles(style)
2683
- };
2684
-
2685
2943
  // src/platform/useStickyScrollHandler.ts
2686
- function useStickyScrollHandler(stickyIndices, horizontal, ctx, onScroll2) {
2944
+ function useStickyScrollHandler(_stickyIndices, _horizontal, _ctx, onScroll2) {
2687
2945
  return onScroll2;
2688
2946
  }
2689
2947
 
@@ -2702,7 +2960,7 @@ function createColumnWrapperStyle(contentContainerStyle) {
2702
2960
  }
2703
2961
  }
2704
2962
  function getRenderedItem(ctx, state, key) {
2705
- var _a;
2963
+ var _a3;
2706
2964
  if (!state) {
2707
2965
  return null;
2708
2966
  }
@@ -2715,29 +2973,31 @@ function getRenderedItem(ctx, state, key) {
2715
2973
  return null;
2716
2974
  }
2717
2975
  let renderedItem = null;
2718
- if (renderItem && data[index]) {
2976
+ const extraData = peek$(ctx, "extraData");
2977
+ const item = data[index];
2978
+ if (renderItem && !isNullOrUndefined(item)) {
2719
2979
  const itemProps = {
2720
2980
  data,
2721
- extraData: peek$(ctx, "extraData"),
2981
+ extraData,
2722
2982
  index,
2723
- item: data[index],
2724
- type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
2983
+ item,
2984
+ type: getItemType ? (_a3 = getItemType(item, index)) != null ? _a3 : "" : ""
2725
2985
  };
2726
- renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React4__namespace.default.createElement(renderItem, itemProps);
2986
+ renderedItem = isFunction(renderItem) ? renderItem(itemProps) : React3__namespace.default.createElement(renderItem, itemProps);
2727
2987
  }
2728
2988
  return { index, item: data[index], renderedItem };
2729
2989
  }
2730
2990
  function useThrottleDebounce(mode) {
2731
- const timeoutRef = React4.useRef(null);
2732
- const lastCallTimeRef = React4.useRef(0);
2733
- const lastArgsRef = React4.useRef(null);
2991
+ const timeoutRef = React3.useRef(null);
2992
+ const lastCallTimeRef = React3.useRef(0);
2993
+ const lastArgsRef = React3.useRef(null);
2734
2994
  const clearTimeoutRef = () => {
2735
2995
  if (timeoutRef.current) {
2736
2996
  clearTimeout(timeoutRef.current);
2737
2997
  timeoutRef.current = null;
2738
2998
  }
2739
2999
  };
2740
- const execute = React4.useCallback(
3000
+ const execute = React3.useCallback(
2741
3001
  (callback, delay, ...args) => {
2742
3002
  {
2743
3003
  const now = Date.now();
@@ -2773,58 +3033,6 @@ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
2773
3033
  return (event) => throttle(originalHandler, scrollEventThrottle, { nativeEvent: event.nativeEvent });
2774
3034
  }
2775
3035
 
2776
- // src/utils/updateAveragesOnDataChange.ts
2777
- function updateAveragesOnDataChange(state, oldData, newData) {
2778
- var _a;
2779
- const {
2780
- averageSizes,
2781
- sizesKnown,
2782
- indexByKey,
2783
- props: { itemsAreEqual, getItemType, keyExtractor }
2784
- } = state;
2785
- if (!itemsAreEqual || !oldData.length || !newData.length) {
2786
- for (const key in averageSizes) {
2787
- delete averageSizes[key];
2788
- }
2789
- return;
2790
- }
2791
- const itemTypesToPreserve = {};
2792
- const newDataLength = newData.length;
2793
- const oldDataLength = oldData.length;
2794
- for (let newIndex = 0; newIndex < newDataLength; newIndex++) {
2795
- const newItem = newData[newIndex];
2796
- const id = keyExtractor ? keyExtractor(newItem, newIndex) : String(newIndex);
2797
- const oldIndex = indexByKey.get(id);
2798
- if (oldIndex !== void 0 && oldIndex < oldDataLength) {
2799
- const knownSize = sizesKnown.get(id);
2800
- if (knownSize === void 0) continue;
2801
- const oldItem = oldData[oldIndex];
2802
- const areEqual = itemsAreEqual(oldItem, newItem, newIndex, newData);
2803
- if (areEqual) {
2804
- const itemType = getItemType ? (_a = getItemType(newItem, newIndex)) != null ? _a : "" : "";
2805
- let typeData = itemTypesToPreserve[itemType];
2806
- if (!typeData) {
2807
- typeData = itemTypesToPreserve[itemType] = { count: 0, totalSize: 0 };
2808
- }
2809
- typeData.totalSize += knownSize;
2810
- typeData.count++;
2811
- }
2812
- }
2813
- }
2814
- for (const key in averageSizes) {
2815
- delete averageSizes[key];
2816
- }
2817
- for (const itemType in itemTypesToPreserve) {
2818
- const { totalSize, count } = itemTypesToPreserve[itemType];
2819
- if (count > 0) {
2820
- averageSizes[itemType] = {
2821
- avg: totalSize / count,
2822
- num: count
2823
- };
2824
- }
2825
- }
2826
- }
2827
-
2828
3036
  // src/components/LegendList.tsx
2829
3037
  var DEFAULT_DRAW_DISTANCE = 250;
2830
3038
  var DEFAULT_ITEM_SIZE = 100;
@@ -2834,17 +3042,18 @@ var LegendList = typedMemo(
2834
3042
  const isChildrenMode = children !== void 0 && dataProp === void 0;
2835
3043
  const processedProps = isChildrenMode ? {
2836
3044
  ...restProps,
2837
- data: (isArray(children) ? children : React4__namespace.Children.toArray(children)).flat(1),
3045
+ data: (isArray(children) ? children : React3__namespace.Children.toArray(children)).flat(1),
2838
3046
  renderItem: ({ item }) => item
2839
3047
  } : {
2840
3048
  ...restProps,
2841
3049
  data: dataProp || [],
2842
3050
  renderItem: renderItemProp
2843
3051
  };
2844
- return /* @__PURE__ */ React4__namespace.createElement(StateProvider, null, /* @__PURE__ */ React4__namespace.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
3052
+ return /* @__PURE__ */ React3__namespace.createElement(StateProvider, null, /* @__PURE__ */ React3__namespace.createElement(LegendListInner, { ...processedProps, ref: forwardedRef }));
2845
3053
  })
2846
3054
  );
2847
3055
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
3056
+ var _a3;
2848
3057
  const {
2849
3058
  alignItemsAtEnd = false,
2850
3059
  columnWrapperStyle,
@@ -2880,6 +3089,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2880
3089
  onScroll: onScrollProp,
2881
3090
  onStartReached,
2882
3091
  onStartReachedThreshold = 0.5,
3092
+ onStickyHeaderChange,
3093
+ onViewableItemsChanged,
2883
3094
  progressViewOffset,
2884
3095
  recycleItems = false,
2885
3096
  refreshControl,
@@ -2891,24 +3102,26 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2891
3102
  stickyIndices,
2892
3103
  style: styleProp,
2893
3104
  suggestEstimatedItemSize,
3105
+ viewabilityConfig,
3106
+ viewabilityConfigCallbackPairs,
2894
3107
  waitForInitialLayout = true,
2895
3108
  ...rest
2896
3109
  } = props;
2897
- const [renderNum, setRenderNum] = React4.useState(0);
3110
+ const [renderNum, setRenderNum] = React3.useState(0);
2898
3111
  const initialScroll = initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
2899
- const [canRender, setCanRender] = React4__namespace.useState(!IsNewArchitecture);
3112
+ const [canRender, setCanRender] = React3__namespace.useState(!IsNewArchitecture);
2900
3113
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
2901
3114
  const style = { ...StyleSheet.flatten(styleProp) };
2902
3115
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
2903
3116
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
2904
3117
  const ctx = useStateContext();
2905
3118
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
2906
- const refScroller = React4.useRef(null);
3119
+ const refScroller = React3.useRef(null);
2907
3120
  const combinedRef = useCombinedRef(refScroller, refScrollView);
2908
3121
  const estimatedItemSize = estimatedItemSizeProp != null ? estimatedItemSizeProp : DEFAULT_ITEM_SIZE;
2909
3122
  const scrollBuffer = (drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE) || 1;
2910
3123
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (_item, index) => index.toString();
2911
- const refState = React4.useRef();
3124
+ const refState = React3.useRef();
2912
3125
  if (!refState.current) {
2913
3126
  if (!ctx.internalState) {
2914
3127
  const initialScrollLength = (estimatedListSize != null ? estimatedListSize : { height: 0, width: 0 } )[horizontal ? "width" : "height"];
@@ -2918,12 +3131,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2918
3131
  columns: /* @__PURE__ */ new Map(),
2919
3132
  containerItemKeys: /* @__PURE__ */ new Set(),
2920
3133
  containerItemTypes: /* @__PURE__ */ new Map(),
3134
+ dataChangeNeedsScrollUpdate: false,
2921
3135
  enableScrollForNextCalculateItemsInView: true,
2922
3136
  endBuffered: -1,
2923
3137
  endNoBuffer: -1,
2924
- endReachedBlockedByTimer: false,
3138
+ endReachedSnapshot: void 0,
2925
3139
  firstFullyOnScreenIndex: -1,
2926
- idCache: /* @__PURE__ */ new Map(),
3140
+ idCache: [],
2927
3141
  idsInView: [],
2928
3142
  indexByKey: /* @__PURE__ */ new Map(),
2929
3143
  initialScroll,
@@ -2954,7 +3168,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2954
3168
  sizesKnown: /* @__PURE__ */ new Map(),
2955
3169
  startBuffered: -1,
2956
3170
  startNoBuffer: -1,
2957
- startReachedBlockedByTimer: false,
3171
+ startReachedSnapshot: void 0,
2958
3172
  stickyContainerPool: /* @__PURE__ */ new Set(),
2959
3173
  stickyContainers: /* @__PURE__ */ new Map(),
2960
3174
  timeoutSizeMessage: 0,
@@ -2970,10 +3184,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2970
3184
  const state = refState.current;
2971
3185
  const isFirst = !state.props.renderItem;
2972
3186
  const didDataChange = state.props.data !== dataProp;
2973
- const throttleScrollFn = (
2974
- // @ts-expect-error TODO Fix this
2975
- scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp
2976
- );
3187
+ if (didDataChange) {
3188
+ state.dataChangeNeedsScrollUpdate = true;
3189
+ }
3190
+ const throttleScrollFn = scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp;
2977
3191
  state.props = {
2978
3192
  alignItemsAtEnd,
2979
3193
  data: dataProp,
@@ -2998,39 +3212,19 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2998
3212
  onScroll: throttleScrollFn,
2999
3213
  onStartReached,
3000
3214
  onStartReachedThreshold,
3215
+ onStickyHeaderChange,
3001
3216
  recycleItems: !!recycleItems,
3002
3217
  renderItem,
3003
3218
  scrollBuffer,
3004
3219
  snapToIndices,
3005
3220
  stickyIndicesArr: stickyIndices != null ? stickyIndices : [],
3006
- stickyIndicesSet: React4.useMemo(() => new Set(stickyIndices != null ? stickyIndices : []), [stickyIndices == null ? void 0 : stickyIndices.join(",")]),
3221
+ stickyIndicesSet: React3.useMemo(() => new Set(stickyIndices != null ? stickyIndices : []), [stickyIndices == null ? void 0 : stickyIndices.join(",")]),
3007
3222
  stylePaddingBottom: stylePaddingBottomState,
3008
3223
  stylePaddingTop: stylePaddingTopState,
3009
3224
  suggestEstimatedItemSize: !!suggestEstimatedItemSize
3010
3225
  };
3011
3226
  state.refScroller = refScroller;
3012
- const checkResetContainers = (isFirst2) => {
3013
- const state2 = refState.current;
3014
- if (state2) {
3015
- if (!isFirst2 && state2.props.data !== dataProp) {
3016
- updateAveragesOnDataChange(state2, state2.props.data, dataProp);
3017
- }
3018
- state2.props.data = dataProp;
3019
- if (!isFirst2) {
3020
- calculateItemsInView(ctx, state2, { dataChanged: true, doMVCP: true });
3021
- const shouldMaintainScrollAtEnd = maintainScrollAtEnd === true || maintainScrollAtEnd.onDataChange;
3022
- const didMaintainScrollAtEnd = shouldMaintainScrollAtEnd && doMaintainScrollAtEnd(ctx, state2, false);
3023
- if (!didMaintainScrollAtEnd && dataProp.length > state2.props.data.length) {
3024
- state2.isEndReached = false;
3025
- }
3026
- if (!didMaintainScrollAtEnd) {
3027
- checkAtTop(state2);
3028
- checkAtBottom(ctx, state2);
3029
- }
3030
- }
3031
- }
3032
- };
3033
- const memoizedLastItemKeys = React4.useMemo(() => {
3227
+ const memoizedLastItemKeys = React3.useMemo(() => {
3034
3228
  if (!dataProp.length) return [];
3035
3229
  return Array.from(
3036
3230
  { length: Math.min(numColumnsProp, dataProp.length) },
@@ -3053,9 +3247,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3053
3247
  };
3054
3248
  if (isFirst) {
3055
3249
  initializeStateVars();
3056
- updateAllPositions(ctx, state);
3250
+ updateItemPositions(
3251
+ ctx,
3252
+ state,
3253
+ /*dataChanged*/
3254
+ true
3255
+ );
3057
3256
  }
3058
- const initialContentOffset = React4.useMemo(() => {
3257
+ const initialContentOffset = React3.useMemo(() => {
3059
3258
  if (initialScroll) {
3060
3259
  const { index, viewOffset } = initialScroll;
3061
3260
  let initialContentOffset2 = viewOffset || 0;
@@ -3064,24 +3263,30 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3064
3263
  }
3065
3264
  refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
3066
3265
  if (initialContentOffset2 > 0) {
3067
- scrollTo(state, { animated: false, index, offset: initialContentOffset2 });
3266
+ scrollTo(state, {
3267
+ animated: false,
3268
+ index,
3269
+ isInitialScroll: true,
3270
+ offset: initialContentOffset2,
3271
+ viewPosition: index === dataProp.length - 1 ? 1 : 0
3272
+ });
3068
3273
  }
3069
3274
  return initialContentOffset2;
3070
3275
  }
3071
3276
  return 0;
3072
3277
  }, [renderNum]);
3073
3278
  if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
3074
- state.lastBatchingAction = Date.now();
3279
+ refState.current.lastBatchingAction = Date.now();
3075
3280
  if (!keyExtractorProp && !isFirst && didDataChange) {
3076
- __DEV__ && warnDevOnce(
3281
+ IS_DEV && warnDevOnce(
3077
3282
  "keyExtractor",
3078
3283
  "Changing data without a keyExtractor can cause slow performance and resetting scroll. If your list data can change you should use a keyExtractor with a unique id for best performance and behavior."
3079
3284
  );
3080
- state.sizes.clear();
3081
- state.positions.clear();
3285
+ refState.current.sizes.clear();
3286
+ refState.current.positions.clear();
3082
3287
  }
3083
3288
  }
3084
- const onLayoutHeader = React4.useCallback((rect, fromLayoutEffect) => {
3289
+ const onLayoutHeader = React3.useCallback((rect, fromLayoutEffect) => {
3085
3290
  const size = rect[horizontal ? "width" : "height"];
3086
3291
  set$(ctx, "headerSize", size);
3087
3292
  if ((initialScroll == null ? void 0 : initialScroll.index) !== void 0) {
@@ -3092,43 +3297,51 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3092
3297
  }
3093
3298
  }
3094
3299
  }, []);
3095
- React4.useLayoutEffect(() => {
3300
+ React3.useLayoutEffect(() => {
3096
3301
  if (snapToIndices) {
3097
3302
  updateSnapToOffsets(ctx, state);
3098
3303
  }
3099
3304
  }, [snapToIndices]);
3100
- React4.useLayoutEffect(() => {
3101
- const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainersCallback();
3305
+ React3.useLayoutEffect(() => {
3306
+ const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainers(ctx, state);
3102
3307
  if (!didAllocateContainers) {
3103
3308
  checkResetContainers(
3309
+ ctx,
3310
+ state,
3104
3311
  /*isFirst*/
3105
- isFirst
3312
+ isFirst,
3313
+ dataProp
3106
3314
  );
3107
3315
  }
3108
3316
  }, [dataProp, numColumnsProp]);
3109
- React4.useLayoutEffect(() => {
3317
+ React3.useLayoutEffect(() => {
3110
3318
  set$(ctx, "extraData", extraData);
3111
3319
  }, [extraData]);
3112
- const { onLayout } = useSyncLayout({
3113
- onLayout: onLayoutProp,
3114
- onLayoutChange: React4.useCallback(
3115
- (rectangle) => {
3116
- handleLayout(ctx, state, rectangle, setCanRender);
3117
- },
3118
- [ctx, state, setCanRender]
3119
- ),
3120
- ref: refScroller
3121
- });
3122
- React4.useLayoutEffect(initializeStateVars, [
3320
+ React3.useLayoutEffect(initializeStateVars, [
3123
3321
  memoizedLastItemKeys.join(","),
3124
3322
  numColumnsProp,
3125
3323
  stylePaddingTopState,
3126
3324
  stylePaddingBottomState
3127
3325
  ]);
3128
- const doInitialAllocateContainersCallback = () => {
3129
- return doInitialAllocateContainers(ctx, state);
3130
- };
3131
- React4.useImperativeHandle(forwardedRef, () => {
3326
+ React3.useEffect(() => {
3327
+ const viewability = setupViewability({
3328
+ onViewableItemsChanged,
3329
+ viewabilityConfig,
3330
+ viewabilityConfigCallbackPairs
3331
+ });
3332
+ state.viewabilityConfigCallbackPairs = viewability;
3333
+ state.enableScrollForNextCalculateItemsInView = !viewability;
3334
+ }, [viewabilityConfig, viewabilityConfigCallbackPairs, onViewableItemsChanged]);
3335
+ const onLayoutChange = React3.useCallback((layout) => {
3336
+ handleLayout(ctx, state, layout, setCanRender);
3337
+ }, []);
3338
+ const { onLayout } = useOnLayoutSync({
3339
+ onLayoutChange,
3340
+ onLayoutProp,
3341
+ ref: refScroller
3342
+ // the type of ScrollView doesn't include measure?
3343
+ });
3344
+ React3.useImperativeHandle(forwardedRef, () => {
3132
3345
  const scrollIndexIntoView = (options) => {
3133
3346
  const state2 = refState.current;
3134
3347
  if (state2) {
@@ -3145,16 +3358,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3145
3358
  }
3146
3359
  };
3147
3360
  return {
3148
- flashScrollIndicators: () => {
3149
- var _a, _b;
3150
- return (_b = (_a = refScroller.current) == null ? void 0 : _a.flashScrollIndicators) == null ? void 0 : _b.call(_a);
3151
- },
3361
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
3152
3362
  getNativeScrollRef: () => refScroller.current,
3153
- getScrollableNode: () => refScroller.current,
3154
- getScrollResponder: () => refScroller.current,
3363
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
3364
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
3155
3365
  getState: () => {
3156
3366
  const state2 = refState.current;
3157
3367
  return state2 ? {
3368
+ activeStickyIndex: state2.activeStickyIndex,
3158
3369
  contentLength: state2.totalSize,
3159
3370
  data: state2.props.data,
3160
3371
  end: state2.endNoBuffer,
@@ -3213,13 +3424,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3213
3424
  };
3214
3425
  }, []);
3215
3426
  {
3216
- React4.useEffect(() => {
3427
+ React3.useEffect(() => {
3217
3428
  if (initialContentOffset) {
3218
- scrollTo(state, { animated: false, offset: initialContentOffset });
3429
+ scrollTo(state, { animated: false, offset: initialContentOffset, ...initialScroll || {} });
3219
3430
  }
3220
3431
  }, []);
3221
3432
  }
3222
- const fns = React4.useMemo(
3433
+ const fns = React3.useMemo(
3223
3434
  () => ({
3224
3435
  getRenderedItem: (key) => getRenderedItem(ctx, state, key),
3225
3436
  onScroll: (event) => onScroll(ctx, state, event),
@@ -3228,7 +3439,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3228
3439
  []
3229
3440
  );
3230
3441
  const onScrollHandler = useStickyScrollHandler(stickyIndices, horizontal, ctx, fns.onScroll);
3231
- return /* @__PURE__ */ React4__namespace.createElement(React4__namespace.Fragment, null, /* @__PURE__ */ React4__namespace.createElement(
3442
+ return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement(
3232
3443
  ListComponent,
3233
3444
  {
3234
3445
  ...rest,
@@ -3255,9 +3466,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3255
3466
  },
3256
3467
  onScroll: onScrollHandler,
3257
3468
  recycleItems,
3258
- refreshControl: refreshControl ? stylePaddingTopState > 0 ? React4__namespace.cloneElement(refreshControl, {
3469
+ refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
3259
3470
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
3260
- }) : refreshControl : onRefresh && /* @__PURE__ */ React4__namespace.createElement(
3471
+ }) : refreshControl : onRefresh && /* @__PURE__ */ React3__namespace.createElement(
3261
3472
  RefreshControl,
3262
3473
  {
3263
3474
  onRefresh,
@@ -3266,14 +3477,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3266
3477
  }
3267
3478
  ),
3268
3479
  refScrollView: combinedRef,
3269
- scrollAdjustHandler: state.scrollAdjustHandler,
3480
+ scrollAdjustHandler: (_a3 = refState.current) == null ? void 0 : _a3.scrollAdjustHandler,
3481
+ scrollEventThrottle: 16 ,
3270
3482
  snapToIndices,
3271
3483
  stickyIndices,
3272
3484
  style,
3273
3485
  updateItemSize: fns.updateItemSize,
3274
3486
  waitForInitialLayout
3275
3487
  }
3276
- ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React4__namespace.createElement(DebugView, { state: refState.current }));
3488
+ ), IS_DEV && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React3__namespace.createElement(DebugView, { state: refState.current }));
3277
3489
  });
3278
3490
 
3279
3491
  exports.LegendList = LegendList;
@@ -3281,6 +3493,6 @@ exports.useIsLastItem = useIsLastItem;
3281
3493
  exports.useListScrollSize = useListScrollSize;
3282
3494
  exports.useRecyclingEffect = useRecyclingEffect;
3283
3495
  exports.useRecyclingState = useRecyclingState;
3284
- exports.useSyncLayout = useSyncLayout2;
3496
+ exports.useSyncLayout = useSyncLayout;
3285
3497
  exports.useViewability = useViewability;
3286
3498
  exports.useViewabilityAmount = useViewabilityAmount;