@legendapp/list 1.0.0-beta.2 → 1.0.0-beta.20

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 React6 = require('react');
4
4
  var reactNative = require('react-native');
5
5
 
6
6
  function _interopNamespace(e) {
@@ -21,23 +21,24 @@ function _interopNamespace(e) {
21
21
  return Object.freeze(n);
22
22
  }
23
23
 
24
- var React4__namespace = /*#__PURE__*/_interopNamespace(React4);
24
+ var React6__namespace = /*#__PURE__*/_interopNamespace(React6);
25
25
 
26
26
  // src/LegendList.tsx
27
- var ContextState = React4__namespace.createContext(null);
27
+ var ContextState = React6__namespace.createContext(null);
28
28
  function StateProvider({ children }) {
29
- const [value] = React4__namespace.useState(() => ({
29
+ const [value] = React6__namespace.useState(() => ({
30
30
  listeners: /* @__PURE__ */ new Map(),
31
31
  values: /* @__PURE__ */ new Map(),
32
32
  mapViewabilityCallbacks: /* @__PURE__ */ new Map(),
33
33
  mapViewabilityValues: /* @__PURE__ */ new Map(),
34
34
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
35
- mapViewabilityAmountValues: /* @__PURE__ */ new Map()
35
+ mapViewabilityAmountValues: /* @__PURE__ */ new Map(),
36
+ columnWrapperStyle: void 0
36
37
  }));
37
- return /* @__PURE__ */ React4__namespace.createElement(ContextState.Provider, { value }, children);
38
+ return /* @__PURE__ */ React6__namespace.createElement(ContextState.Provider, { value }, children);
38
39
  }
39
40
  function useStateContext() {
40
- return React4__namespace.useContext(ContextState);
41
+ return React6__namespace.useContext(ContextState);
41
42
  }
42
43
  function createSelectorFunctions(ctx, signalName) {
43
44
  return {
@@ -46,9 +47,9 @@ function createSelectorFunctions(ctx, signalName) {
46
47
  };
47
48
  }
48
49
  function use$(signalName) {
49
- const ctx = React4__namespace.useContext(ContextState);
50
- const { subscribe, get } = React4__namespace.useMemo(() => createSelectorFunctions(ctx, signalName), []);
51
- const value = React4.useSyncExternalStore(subscribe, get);
50
+ const ctx = React6__namespace.useContext(ContextState);
51
+ const { subscribe, get } = React6__namespace.useMemo(() => createSelectorFunctions(ctx, signalName), []);
52
+ const value = React6.useSyncExternalStore(subscribe, get);
52
53
  return value;
53
54
  }
54
55
  function listen$(ctx, signalName, cb) {
@@ -77,76 +78,278 @@ function set$(ctx, signalName, value) {
77
78
  }
78
79
  }
79
80
  }
81
+ function getContentSize(ctx) {
82
+ const { values } = ctx;
83
+ const stylePaddingTop = values.get("stylePaddingTop") || 0;
84
+ const headerSize = values.get("headerSize") || 0;
85
+ const footerSize = values.get("footerSize") || 0;
86
+ const totalSize = values.get("totalSize") || 0;
87
+ return headerSize + footerSize + totalSize + stylePaddingTop;
88
+ }
89
+ var symbolFirst = Symbol();
90
+ function useInit(cb) {
91
+ const refValue = React6.useRef(symbolFirst);
92
+ if (refValue.current === symbolFirst) {
93
+ refValue.current = cb();
94
+ }
95
+ return refValue.current;
96
+ }
97
+
98
+ // src/ContextContainer.ts
99
+ var ContextContainer = React6.createContext(null);
100
+ function useViewability(configId, callback) {
101
+ const ctx = useStateContext();
102
+ const { containerId } = React6.useContext(ContextContainer);
103
+ const key = containerId + configId;
104
+ useInit(() => {
105
+ const value = ctx.mapViewabilityValues.get(key);
106
+ if (value) {
107
+ callback(value);
108
+ }
109
+ });
110
+ ctx.mapViewabilityCallbacks.set(key, callback);
111
+ React6.useEffect(
112
+ () => () => {
113
+ ctx.mapViewabilityCallbacks.delete(key);
114
+ },
115
+ []
116
+ );
117
+ }
118
+ function useViewabilityAmount(callback) {
119
+ const ctx = useStateContext();
120
+ const { containerId } = React6.useContext(ContextContainer);
121
+ useInit(() => {
122
+ const value = ctx.mapViewabilityAmountValues.get(containerId);
123
+ if (value) {
124
+ callback(value);
125
+ }
126
+ });
127
+ ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
128
+ React6.useEffect(
129
+ () => () => {
130
+ ctx.mapViewabilityAmountCallbacks.delete(containerId);
131
+ },
132
+ []
133
+ );
134
+ }
135
+ function useRecyclingEffect(effect) {
136
+ const { index, value } = React6.useContext(ContextContainer);
137
+ const prevValues = React6.useRef({
138
+ prevIndex: void 0,
139
+ prevItem: void 0
140
+ });
141
+ React6.useEffect(() => {
142
+ let ret = void 0;
143
+ if (prevValues.current.prevIndex !== void 0 && prevValues.current.prevItem !== void 0) {
144
+ ret = effect({
145
+ index,
146
+ item: value,
147
+ prevIndex: prevValues.current.prevIndex,
148
+ prevItem: prevValues.current.prevItem
149
+ });
150
+ }
151
+ prevValues.current = {
152
+ prevIndex: index,
153
+ prevItem: value
154
+ };
155
+ return ret;
156
+ }, [index, value]);
157
+ }
158
+ function useRecyclingState(valueOrFun) {
159
+ const { index, value } = React6.useContext(ContextContainer);
160
+ const stateInfo = React6.useState(
161
+ () => typeof valueOrFun === "function" ? valueOrFun({
162
+ index,
163
+ item: value,
164
+ prevIndex: void 0,
165
+ prevItem: void 0
166
+ }) : valueOrFun
167
+ );
168
+ useRecyclingEffect((state) => {
169
+ const newState = typeof valueOrFun === "function" ? valueOrFun(state) : valueOrFun;
170
+ stateInfo[1](newState);
171
+ });
172
+ return stateInfo;
173
+ }
174
+ var DebugView = React6.memo(function DebugView2({ state }) {
175
+ const ctx = useStateContext();
176
+ const totalSize = use$("totalSize");
177
+ const contentSize = getContentSize(ctx);
178
+ const [, forceUpdate] = React6.useReducer((x) => x + 1, 0);
179
+ useInterval(() => {
180
+ forceUpdate();
181
+ }, 100);
182
+ return /* @__PURE__ */ React6__namespace.createElement(
183
+ reactNative.View,
184
+ {
185
+ style: {
186
+ position: "absolute",
187
+ top: 0,
188
+ right: 0,
189
+ paddingLeft: 4,
190
+ paddingBottom: 4,
191
+ // height: 100,
192
+ backgroundColor: "#FFFFFFCC"
193
+ }
194
+ },
195
+ /* @__PURE__ */ React6__namespace.createElement(reactNative.Text, null, "TotalSize: ", totalSize),
196
+ /* @__PURE__ */ React6__namespace.createElement(reactNative.Text, null, "ContentSize: ", contentSize),
197
+ /* @__PURE__ */ React6__namespace.createElement(reactNative.Text, null, "At end: ", String(state.isAtBottom))
198
+ );
199
+ });
200
+ function useInterval(callback, delay) {
201
+ React6.useEffect(() => {
202
+ const interval = setInterval(callback, delay);
203
+ return () => clearInterval(interval);
204
+ }, [delay]);
205
+ }
206
+ var LeanViewComponent = React6__namespace.forwardRef((props, ref) => {
207
+ return React6__namespace.createElement("RCTView", { ...props, ref });
208
+ });
209
+ LeanViewComponent.displayName = "RCTView";
210
+ var LeanView = reactNative.Platform.OS === "android" || reactNative.Platform.OS === "ios" ? LeanViewComponent : reactNative.View;
211
+
212
+ // src/constants.ts
213
+ var POSITION_OUT_OF_VIEW = -1e7;
214
+ var ANCHORED_POSITION_OUT_OF_VIEW = {
215
+ type: "top",
216
+ relativeCoordinate: POSITION_OUT_OF_VIEW,
217
+ top: POSITION_OUT_OF_VIEW
218
+ };
219
+ var ENABLE_DEVMODE = __DEV__ && false;
220
+ var ENABLE_DEBUG_VIEW = __DEV__ && false;
80
221
 
81
222
  // src/Container.tsx
223
+ var isNewArchitecture = global.nativeFabricUIManager != null;
82
224
  var Container = ({
83
225
  id,
84
226
  recycleItems,
85
227
  horizontal,
86
- waitForInitialLayout,
87
228
  getRenderedItem,
88
229
  updateItemSize,
89
230
  ItemSeparatorComponent
90
231
  }) => {
91
232
  const ctx = useStateContext();
92
- const position = use$(`containerPosition${id}`);
233
+ const columnWrapperStyle = ctx.columnWrapperStyle;
234
+ const maintainVisibleContentPosition = use$("maintainVisibleContentPosition");
235
+ const position = use$(`containerPosition${id}`) || ANCHORED_POSITION_OUT_OF_VIEW;
93
236
  const column = use$(`containerColumn${id}`) || 0;
94
237
  const numColumns = use$("numColumns");
238
+ const lastItemKeys = use$("lastItemKeys");
239
+ const itemKey = use$(`containerItemKey${id}`);
240
+ const data = use$(`containerItemData${id}`);
241
+ const extraData = use$("extraData");
95
242
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
96
243
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
244
+ let verticalPaddingStyles;
245
+ if (columnWrapperStyle && !horizontal && numColumns > 1) {
246
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
247
+ verticalPaddingStyles = {
248
+ paddingBottom: !lastItemKeys.has(itemKey) ? rowGap || gap || void 0 : void 0,
249
+ // Apply horizontal padding based on column position (first, middle, or last)
250
+ paddingLeft: column > 1 ? (columnGap || gap || 0) / 2 : void 0,
251
+ paddingRight: column < numColumns ? (columnGap || gap || 0) / 2 : void 0
252
+ };
253
+ }
97
254
  const style = horizontal ? {
98
- flexDirection: "row",
255
+ flexDirection: ItemSeparatorComponent ? "row" : void 0,
99
256
  position: "absolute",
100
257
  top: otherAxisPos,
101
258
  bottom: numColumns > 1 ? null : 0,
102
259
  height: otherAxisSize,
103
- left: position
260
+ left: position.relativeCoordinate
104
261
  } : {
105
262
  position: "absolute",
106
263
  left: otherAxisPos,
107
264
  right: numColumns > 1 ? null : 0,
108
265
  width: otherAxisSize,
109
- top: position
266
+ top: position.relativeCoordinate,
267
+ ...verticalPaddingStyles || {}
110
268
  };
111
- if (waitForInitialLayout) {
112
- const visible = use$(`containerDidLayout${id}`);
113
- style.opacity = visible ? 1 : 0;
114
- }
115
- const lastItemKey = use$("lastItemKey");
116
- const itemKey = use$(`containerItemKey${id}`);
117
- const data = use$(`containerItemData${id}`);
118
- const extraData = use$("extraData");
119
- const renderedItem = React4.useMemo(() => itemKey !== void 0 && getRenderedItem(itemKey, id), [itemKey, data, extraData]);
120
- return /* @__PURE__ */ React4__namespace.default.createElement(
121
- reactNative.View,
122
- {
123
- style,
124
- onLayout: (event) => {
125
- const key = peek$(ctx, `containerItemKey${id}`);
126
- if (key !== void 0) {
127
- const size = Math.floor(event.nativeEvent.layout[horizontal ? "width" : "height"] * 8) / 8;
128
- updateItemSize(id, key, size);
269
+ const renderedItemInfo = React6.useMemo(
270
+ () => itemKey !== void 0 ? getRenderedItem(itemKey) : null,
271
+ [itemKey, data, extraData]
272
+ );
273
+ const { index, renderedItem } = renderedItemInfo || {};
274
+ const onLayout = (event) => {
275
+ if (itemKey !== void 0) {
276
+ const layout = event.nativeEvent.layout;
277
+ const size = Math.floor(layout[horizontal ? "width" : "height"] * 8) / 8;
278
+ if (size === 0) {
279
+ if (layout.x !== POSITION_OUT_OF_VIEW && layout.y !== POSITION_OUT_OF_VIEW) {
280
+ console.log(
281
+ "[WARN] Container 0 height reported, possible bug in LegendList",
282
+ id,
283
+ itemKey,
284
+ event.nativeEvent
285
+ );
129
286
  }
287
+ return;
130
288
  }
131
- },
132
- /* @__PURE__ */ React4__namespace.default.createElement(React4__namespace.default.Fragment, { key: recycleItems ? void 0 : itemKey }, renderedItem, renderedItem && ItemSeparatorComponent && itemKey !== lastItemKey && ItemSeparatorComponent)
289
+ updateItemSize(id, itemKey, size);
290
+ }
291
+ };
292
+ const ref = React6.useRef(null);
293
+ if (isNewArchitecture) {
294
+ React6.useLayoutEffect(() => {
295
+ var _a, _b;
296
+ if (itemKey !== void 0) {
297
+ const measured = (_b = (_a = ref.current) == null ? void 0 : _a.unstable_getBoundingClientRect) == null ? void 0 : _b.call(_a);
298
+ if (measured) {
299
+ const size = Math.floor(measured[horizontal ? "width" : "height"] * 8) / 8;
300
+ if (size) {
301
+ updateItemSize(id, itemKey, size);
302
+ }
303
+ }
304
+ }
305
+ }, [itemKey]);
306
+ }
307
+ const contextValue = React6.useMemo(
308
+ () => ({ containerId: id, itemKey, index, value: data }),
309
+ [id, itemKey, index, data]
133
310
  );
311
+ const contentFragment = /* @__PURE__ */ React6__namespace.default.createElement(React6__namespace.default.Fragment, { key: recycleItems ? void 0 : itemKey }, /* @__PURE__ */ React6__namespace.default.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && !lastItemKeys.has(itemKey) && /* @__PURE__ */ React6__namespace.default.createElement(ItemSeparatorComponent, { leadingItem: renderedItemInfo.item })));
312
+ if (maintainVisibleContentPosition) {
313
+ const anchorStyle = position.type === "top" ? { position: "absolute", top: 0, left: 0, right: 0 } : { position: "absolute", bottom: 0, left: 0, right: 0 };
314
+ if (ENABLE_DEVMODE) {
315
+ anchorStyle.borderColor = position.type === "top" ? "red" : "blue";
316
+ anchorStyle.borderWidth = 1;
317
+ }
318
+ return /* @__PURE__ */ React6__namespace.default.createElement(LeanView, { style }, /* @__PURE__ */ React6__namespace.default.createElement(LeanView, { style: anchorStyle, onLayout, ref }, contentFragment, ENABLE_DEVMODE && /* @__PURE__ */ React6__namespace.default.createElement(reactNative.Text, { style: { position: "absolute", top: 0, left: 0, zIndex: 1e3 } }, position.top)));
319
+ }
320
+ return /* @__PURE__ */ React6__namespace.default.createElement(LeanView, { style, onLayout, ref }, contentFragment);
134
321
  };
135
- var useAnimatedValue = reactNative.useAnimatedValue || ((initialValue) => {
136
- return React4.useRef(new reactNative.Animated.Value(initialValue)).current;
137
- });
138
- function useValue$(key, getValue, key2) {
322
+ var typedForwardRef = React6.forwardRef;
323
+ var typedMemo = React6.memo;
324
+ var useAnimatedValue = (initialValue) => {
325
+ return React6.useRef(new reactNative.Animated.Value(initialValue)).current;
326
+ };
327
+
328
+ // src/useValue$.ts
329
+ function useValue$(key, getValue, useMicrotask) {
139
330
  var _a;
140
331
  const ctx = useStateContext();
141
- const animValue = useAnimatedValue((_a = peek$(ctx, key)) != null ? _a : 0);
142
- React4.useMemo(() => {
143
- listen$(ctx, key, (v) => animValue.setValue(v));
332
+ const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
333
+ React6.useMemo(() => {
334
+ let newValue = void 0;
335
+ listen$(ctx, key, (v) => {
336
+ if (useMicrotask && newValue === void 0) {
337
+ queueMicrotask(() => {
338
+ animValue.setValue(newValue);
339
+ newValue = void 0;
340
+ });
341
+ }
342
+ newValue = getValue ? getValue(v) : v;
343
+ if (!useMicrotask) {
344
+ animValue.setValue(newValue);
345
+ }
346
+ });
144
347
  }, []);
145
348
  return animValue;
146
349
  }
147
350
 
148
351
  // src/Containers.tsx
149
- var Containers = React4__namespace.memo(function Containers2({
352
+ var Containers = typedMemo(function Containers2({
150
353
  horizontal,
151
354
  recycleItems,
152
355
  ItemSeparatorComponent,
@@ -155,18 +358,23 @@ var Containers = React4__namespace.memo(function Containers2({
155
358
  getRenderedItem
156
359
  }) {
157
360
  const numContainers = use$("numContainersPooled");
158
- const animSize = useValue$("totalSize");
361
+ const animSize = useValue$(
362
+ "totalSizeWithScrollAdjust",
363
+ void 0,
364
+ /*useMicrotask*/
365
+ true
366
+ );
367
+ const animOpacity = waitForInitialLayout ? useValue$("containersDidLayout", (value) => value ? 1 : 0) : void 0;
159
368
  const containers = [];
160
369
  for (let i = 0; i < numContainers; i++) {
161
370
  containers.push(
162
- /* @__PURE__ */ React4__namespace.createElement(
371
+ /* @__PURE__ */ React6__namespace.createElement(
163
372
  Container,
164
373
  {
165
374
  id: i,
166
375
  key: i,
167
376
  recycleItems,
168
377
  horizontal,
169
- waitForInitialLayout,
170
378
  getRenderedItem,
171
379
  updateItemSize,
172
380
  ItemSeparatorComponent
@@ -174,21 +382,72 @@ var Containers = React4__namespace.memo(function Containers2({
174
382
  )
175
383
  );
176
384
  }
177
- const style = horizontal ? { width: animSize } : { height: animSize };
178
- return /* @__PURE__ */ React4__namespace.createElement(reactNative.Animated.View, { style }, containers);
385
+ const style = horizontal ? { width: animSize, opacity: animOpacity } : { height: animSize, opacity: animOpacity };
386
+ return /* @__PURE__ */ React6__namespace.createElement(reactNative.Animated.View, { style }, containers);
179
387
  });
180
388
 
181
389
  // src/ListComponent.tsx
182
390
  var getComponent = (Component) => {
183
- if (React4__namespace.isValidElement(Component)) {
391
+ if (React6__namespace.isValidElement(Component)) {
184
392
  return Component;
185
393
  }
186
394
  if (Component) {
187
- return /* @__PURE__ */ React4__namespace.createElement(Component, null);
395
+ return /* @__PURE__ */ React6__namespace.createElement(Component, null);
188
396
  }
189
397
  return null;
190
398
  };
191
- var ListComponent = React4__namespace.memo(function ListComponent2({
399
+ var PaddingAndAdjust = () => {
400
+ const animPaddingTop = useValue$("paddingTop", (v) => v, true);
401
+ const animScrollAdjust = useValue$("scrollAdjust", (v) => v, true);
402
+ const additionalSize = { marginTop: animScrollAdjust, paddingTop: animPaddingTop };
403
+ return /* @__PURE__ */ React6__namespace.createElement(reactNative.Animated.View, { style: additionalSize });
404
+ };
405
+ var PaddingAndAdjustDevMode = () => {
406
+ const animPaddingTop = useValue$("paddingTop", (v) => v, true);
407
+ const animScrollAdjust = useValue$("scrollAdjust", (v) => v, true);
408
+ return /* @__PURE__ */ React6__namespace.createElement(React6__namespace.Fragment, null, /* @__PURE__ */ React6__namespace.createElement(reactNative.Animated.View, { style: { marginTop: animScrollAdjust } }), /* @__PURE__ */ React6__namespace.createElement(reactNative.Animated.View, { style: { paddingTop: animPaddingTop } }), /* @__PURE__ */ React6__namespace.createElement(
409
+ reactNative.Animated.View,
410
+ {
411
+ style: {
412
+ position: "absolute",
413
+ top: reactNative.Animated.add(animScrollAdjust, reactNative.Animated.multiply(animScrollAdjust, -1)),
414
+ height: animPaddingTop,
415
+ left: 0,
416
+ right: 0,
417
+ backgroundColor: "green"
418
+ }
419
+ }
420
+ ), /* @__PURE__ */ React6__namespace.createElement(
421
+ reactNative.Animated.View,
422
+ {
423
+ style: {
424
+ position: "absolute",
425
+ top: animPaddingTop,
426
+ height: animScrollAdjust,
427
+ left: -16,
428
+ right: -16,
429
+ backgroundColor: "lightblue"
430
+ }
431
+ }
432
+ ), /* @__PURE__ */ React6__namespace.createElement(
433
+ reactNative.Animated.View,
434
+ {
435
+ style: {
436
+ position: "absolute",
437
+ top: animPaddingTop,
438
+ height: reactNative.Animated.multiply(animScrollAdjust, -1),
439
+ width: 8,
440
+ right: 4,
441
+ borderStyle: "dashed",
442
+ borderColor: "blue",
443
+ borderWidth: 1,
444
+ backgroundColor: "lightblue"
445
+ //backgroundColor: "blue",
446
+ }
447
+ }
448
+ ));
449
+ };
450
+ var ListComponent = typedMemo(function ListComponent2({
192
451
  style,
193
452
  contentContainerStyle,
194
453
  horizontal,
@@ -204,28 +463,27 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
204
463
  ListFooterComponent,
205
464
  ListFooterComponentStyle,
206
465
  ListEmptyComponent,
207
- ListEmptyComponentStyle,
208
466
  getRenderedItem,
209
467
  updateItemSize,
210
468
  refScrollView,
211
469
  maintainVisibleContentPosition,
212
470
  renderScrollComponent,
471
+ onRefresh,
472
+ refreshing,
473
+ progressViewOffset,
213
474
  ...rest
214
475
  }) {
215
476
  const ctx = useStateContext();
216
- const animPaddingTop = useValue$("paddingTop");
217
- const animScrollAdjust = useValue$("scrollAdjust");
218
- const ScrollComponent = renderScrollComponent ? React4.useMemo(
219
- () => React4__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
477
+ const ScrollComponent = renderScrollComponent ? React6.useMemo(
478
+ () => React6__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
220
479
  [renderScrollComponent]
221
480
  ) : reactNative.ScrollView;
222
- const additionalSize = { marginTop: animScrollAdjust, paddingTop: animPaddingTop };
223
- return /* @__PURE__ */ React4__namespace.createElement(
481
+ return /* @__PURE__ */ React6__namespace.createElement(
224
482
  ScrollComponent,
225
483
  {
226
484
  ...rest,
227
485
  style,
228
- maintainVisibleContentPosition: maintainVisibleContentPosition ? { minIndexForVisible: 0 } : void 0,
486
+ maintainVisibleContentPosition: maintainVisibleContentPosition && !ListEmptyComponent ? { minIndexForVisible: 0 } : void 0,
229
487
  contentContainerStyle: [
230
488
  contentContainerStyle,
231
489
  horizontal ? {
@@ -238,34 +496,41 @@ var ListComponent = React4__namespace.memo(function ListComponent2({
238
496
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
239
497
  ref: refScrollView
240
498
  },
241
- /* @__PURE__ */ React4__namespace.createElement(reactNative.Animated.View, { style: additionalSize }),
242
- ListHeaderComponent && /* @__PURE__ */ React4__namespace.createElement(
243
- reactNative.Animated.View,
499
+ ENABLE_DEVMODE ? /* @__PURE__ */ React6__namespace.createElement(PaddingAndAdjustDevMode, null) : /* @__PURE__ */ React6__namespace.createElement(PaddingAndAdjust, null),
500
+ ListHeaderComponent && /* @__PURE__ */ React6__namespace.createElement(
501
+ reactNative.View,
244
502
  {
245
503
  style: ListHeaderComponentStyle,
246
504
  onLayout: (event) => {
247
505
  const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
248
- const prevSize = peek$(ctx, "headerSize") || 0;
249
- if (size !== prevSize) {
250
- set$(ctx, "headerSize", size);
251
- }
506
+ set$(ctx, "headerSize", size);
252
507
  }
253
508
  },
254
509
  getComponent(ListHeaderComponent)
255
510
  ),
256
- ListEmptyComponent && /* @__PURE__ */ React4__namespace.createElement(reactNative.Animated.View, { style: ListEmptyComponentStyle }, getComponent(ListEmptyComponent)),
257
- /* @__PURE__ */ React4__namespace.createElement(
511
+ ListEmptyComponent && getComponent(ListEmptyComponent),
512
+ /* @__PURE__ */ React6__namespace.createElement(
258
513
  Containers,
259
514
  {
260
515
  horizontal,
261
516
  recycleItems,
262
517
  waitForInitialLayout,
263
518
  getRenderedItem,
264
- ItemSeparatorComponent: ItemSeparatorComponent && getComponent(ItemSeparatorComponent),
519
+ ItemSeparatorComponent,
265
520
  updateItemSize
266
521
  }
267
522
  ),
268
- ListFooterComponent && /* @__PURE__ */ React4__namespace.createElement(reactNative.View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
523
+ ListFooterComponent && /* @__PURE__ */ React6__namespace.createElement(
524
+ reactNative.View,
525
+ {
526
+ style: ListFooterComponentStyle,
527
+ onLayout: (event) => {
528
+ const size = event.nativeEvent.layout[horizontal ? "width" : "height"];
529
+ set$(ctx, "footerSize", size);
530
+ }
531
+ },
532
+ getComponent(ListFooterComponent)
533
+ )
269
534
  );
270
535
  });
271
536
 
@@ -274,45 +539,57 @@ var ScrollAdjustHandler = class {
274
539
  constructor(ctx) {
275
540
  this.ctx = ctx;
276
541
  this.appliedAdjust = 0;
277
- this.pendingAdjust = 0;
278
542
  this.busy = false;
279
- this.firstAdjust = true;
543
+ this.isPaused = false;
280
544
  this.context = ctx;
281
545
  }
546
+ doAjdust() {
547
+ set$(this.context, "scrollAdjust", this.appliedAdjust);
548
+ this.busy = false;
549
+ }
282
550
  requestAdjust(adjust, onAdjusted) {
283
551
  const oldAdjustTop = peek$(this.context, "scrollAdjust");
284
552
  if (oldAdjustTop === adjust) {
285
553
  return;
286
554
  }
287
555
  this.appliedAdjust = adjust;
288
- this.pendingAdjust = adjust;
289
- const doAjdust = () => {
290
- set$(this.context, "scrollAdjust", this.pendingAdjust);
291
- onAdjusted(oldAdjustTop - this.pendingAdjust);
292
- this.busy = false;
293
- };
294
- if (!this.busy) {
556
+ if (!this.busy && !this.isPaused) {
295
557
  this.busy = true;
296
- if (this.firstAdjust) {
297
- this.firstAdjust = false;
298
- setTimeout(doAjdust, 50);
299
- } else {
300
- doAjdust();
301
- }
558
+ this.doAjdust();
559
+ onAdjusted(oldAdjustTop - adjust);
302
560
  }
303
561
  }
304
562
  getAppliedAdjust() {
305
563
  return this.appliedAdjust;
306
564
  }
307
- };
308
- var symbolFirst = Symbol();
309
- function useInit(cb) {
310
- const refValue = React4.useRef(symbolFirst);
311
- if (refValue.current === symbolFirst) {
312
- refValue.current = cb();
565
+ pauseAdjust() {
566
+ this.isPaused = true;
313
567
  }
314
- return refValue.current;
315
- }
568
+ // return true if it was paused
569
+ unPauseAdjust() {
570
+ if (this.isPaused) {
571
+ this.isPaused = false;
572
+ this.doAjdust();
573
+ return true;
574
+ }
575
+ return false;
576
+ }
577
+ };
578
+ var useCombinedRef = (...refs) => {
579
+ const callback = React6.useCallback((element) => {
580
+ for (const ref of refs) {
581
+ if (!ref) {
582
+ continue;
583
+ }
584
+ if (typeof ref === "function") {
585
+ ref(element);
586
+ } else {
587
+ ref.current = element;
588
+ }
589
+ }
590
+ }, refs);
591
+ return callback;
592
+ };
316
593
 
317
594
  // src/viewability.ts
318
595
  var mapViewabilityConfigCallbackPairs = /* @__PURE__ */ new Map();
@@ -463,15 +740,14 @@ function maybeUpdateViewabilityCallback(ctx, configId, viewToken) {
463
740
 
464
741
  // src/LegendList.tsx
465
742
  var DEFAULT_DRAW_DISTANCE = 250;
466
- var POSITION_OUT_OF_VIEW = -1e7;
467
743
  var DEFAULT_ITEM_SIZE = 100;
468
- var LegendList = React4.forwardRef(function LegendList2(props, forwardedRef) {
469
- return /* @__PURE__ */ React4__namespace.createElement(StateProvider, null, /* @__PURE__ */ React4__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
744
+ var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
745
+ return /* @__PURE__ */ React6__namespace.createElement(StateProvider, null, /* @__PURE__ */ React6__namespace.createElement(LegendListInner, { ...props, ref: forwardedRef }));
470
746
  });
471
- var LegendListInner = React4.forwardRef(function LegendListInner2(props, forwardedRef) {
747
+ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
472
748
  var _a, _b, _c, _d;
473
749
  const {
474
- data,
750
+ data: dataProp,
475
751
  initialScrollIndex,
476
752
  initialScrollOffset,
477
753
  horizontal,
@@ -484,51 +760,73 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
484
760
  alignItemsAtEnd = false,
485
761
  maintainVisibleContentPosition = false,
486
762
  onScroll: onScrollProp,
763
+ onMomentumScrollEnd,
487
764
  numColumns: numColumnsProp = 1,
765
+ columnWrapperStyle,
488
766
  keyExtractor: keyExtractorProp,
489
767
  renderItem,
490
768
  estimatedItemSize,
491
769
  getEstimatedItemSize,
492
- onEndReached,
493
- onStartReached,
494
770
  ListEmptyComponent,
495
771
  onItemSizeChanged,
496
772
  scrollEventThrottle,
497
773
  refScrollView,
774
+ waitForInitialLayout = true,
498
775
  extraData,
776
+ onLayout: onLayoutProp,
777
+ onRefresh,
778
+ refreshing,
779
+ progressViewOffset,
780
+ refreshControl,
499
781
  ...rest
500
782
  } = props;
501
783
  const { style, contentContainerStyle } = props;
784
+ const callbacks = React6.useRef({
785
+ onStartReached: rest.onStartReached,
786
+ onEndReached: rest.onEndReached
787
+ });
788
+ callbacks.current.onStartReached = rest.onStartReached;
789
+ callbacks.current.onEndReached = rest.onEndReached;
502
790
  const ctx = useStateContext();
503
- const refScroller = React4.useRef(null);
791
+ ctx.columnWrapperStyle = columnWrapperStyle;
792
+ const refScroller = React6.useRef(null);
793
+ const combinedRef = useCombinedRef(refScroller, refScrollView);
504
794
  const scrollBuffer = drawDistance != null ? drawDistance : DEFAULT_DRAW_DISTANCE;
505
795
  const keyExtractor = keyExtractorProp != null ? keyExtractorProp : (item, index) => index.toString();
506
- const refState = React4.useRef();
796
+ const refState = React6.useRef();
507
797
  const getId = (index) => {
508
798
  var _a2;
509
- const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
510
- if (!data2) {
799
+ const data = (_a2 = refState.current) == null ? void 0 : _a2.data;
800
+ if (!data) {
511
801
  return "";
512
802
  }
513
- const ret = index < data2.length ? keyExtractor ? keyExtractor(data2[index], index) : index : null;
803
+ const ret = index < data.length ? keyExtractor ? keyExtractor(data[index], index) : index : null;
514
804
  return `${ret}`;
515
805
  };
516
- const getItemSize = (key, index, data2) => {
806
+ const getItemSize = (key, index, data) => {
517
807
  var _a2;
518
808
  const sizeKnown = refState.current.sizes.get(key);
519
809
  if (sizeKnown !== void 0) {
520
810
  return sizeKnown;
521
811
  }
522
- const size = (_a2 = getEstimatedItemSize ? getEstimatedItemSize(index, data2) : estimatedItemSize) != null ? _a2 : DEFAULT_ITEM_SIZE;
812
+ const size = (_a2 = getEstimatedItemSize ? getEstimatedItemSize(index, data) : estimatedItemSize) != null ? _a2 : DEFAULT_ITEM_SIZE;
523
813
  refState.current.sizes.set(key, size);
524
814
  return size;
525
815
  };
526
- const calculateInitialOffset = (index = initialScrollIndex) => {
816
+ const calculateOffsetForIndex = (index = initialScrollIndex) => {
817
+ const data = dataProp;
527
818
  if (index) {
528
819
  let offset = 0;
529
- if (getEstimatedItemSize) {
820
+ const canGetSize = !!refState.current;
821
+ if (canGetSize || getEstimatedItemSize) {
822
+ const sizeFn = (index2) => {
823
+ if (canGetSize) {
824
+ return getItemSize(getId(index2), index2, data[index2]);
825
+ }
826
+ return getEstimatedItemSize(index2, data[index2]);
827
+ };
530
828
  for (let i = 0; i < index; i++) {
531
- offset += getEstimatedItemSize(i, data[i]);
829
+ offset += sizeFn(i);
532
830
  }
533
831
  } else if (estimatedItemSize) {
534
832
  offset = index * estimatedItemSize;
@@ -537,7 +835,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
537
835
  }
538
836
  return 0;
539
837
  };
540
- const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React4.useMemo(calculateInitialOffset, []);
838
+ const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : React6.useMemo(calculateOffsetForIndex, []);
541
839
  if (!refState.current) {
542
840
  const initialScrollLength = reactNative.Dimensions.get("window")[horizontal ? "width" : "height"];
543
841
  refState.current = {
@@ -545,13 +843,11 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
545
843
  positions: /* @__PURE__ */ new Map(),
546
844
  columns: /* @__PURE__ */ new Map(),
547
845
  pendingAdjust: 0,
548
- animFrameLayout: null,
549
846
  isStartReached: initialContentOffset < initialScrollLength * onStartReachedThreshold,
550
847
  isEndReached: false,
551
848
  isAtBottom: false,
552
849
  isAtTop: false,
553
- data,
554
- idsInFirstRender: void 0,
850
+ data: dataProp,
555
851
  hasScrolled: false,
556
852
  scrollLength: initialScrollLength,
557
853
  startBuffered: 0,
@@ -578,18 +874,19 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
578
874
  belowAnchorElementPositions: void 0,
579
875
  rowHeights: /* @__PURE__ */ new Map(),
580
876
  startReachedBlockedByTimer: false,
581
- layoutsPending: /* @__PURE__ */ new Set(),
877
+ endReachedBlockedByTimer: false,
582
878
  scrollForNextCalculateItemsInView: void 0,
583
- enableScrollForNextCalculateItemsInView: true
879
+ enableScrollForNextCalculateItemsInView: true,
880
+ minIndexSizeChanged: 0,
881
+ numPendingInitialLayout: 0
584
882
  };
585
- refState.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
586
883
  if (maintainVisibleContentPosition) {
587
884
  if (initialScrollIndex) {
588
885
  refState.current.anchorElement = {
589
886
  coordinate: initialContentOffset,
590
887
  id: getId(initialScrollIndex)
591
888
  };
592
- } else if (data.length) {
889
+ } else if (dataProp.length) {
593
890
  refState.current.anchorElement = {
594
891
  coordinate: initialContentOffset,
595
892
  id: getId(0)
@@ -599,8 +896,11 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
599
896
  }
600
897
  }
601
898
  set$(ctx, "scrollAdjust", 0);
899
+ set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
602
900
  set$(ctx, "extraData", extraData);
603
901
  }
902
+ const didDataChange = refState.current.data !== dataProp;
903
+ refState.current.data = dataProp;
604
904
  const getAnchorElementIndex = () => {
605
905
  const state = refState.current;
606
906
  if (state.anchorElement) {
@@ -609,16 +909,16 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
609
909
  }
610
910
  return void 0;
611
911
  };
612
- const addTotalSize = React4.useCallback((key, add, totalSizeBelowAnchor) => {
912
+ const addTotalSize = React6.useCallback((key, add, totalSizeBelowAnchor) => {
613
913
  const state = refState.current;
614
- const index = key === null ? 0 : state.indexByKey.get(key);
914
+ const { indexByKey, anchorElement } = state;
915
+ const index = key === null ? 0 : indexByKey.get(key);
615
916
  let isAboveAnchor = false;
616
917
  if (maintainVisibleContentPosition) {
617
- if (state.anchorElement && index < getAnchorElementIndex()) {
918
+ if (anchorElement && index < getAnchorElementIndex()) {
618
919
  isAboveAnchor = true;
619
920
  }
620
921
  }
621
- state.totalSize;
622
922
  if (key === null) {
623
923
  state.totalSize = add;
624
924
  state.totalSizeBelowAnchor = totalSizeBelowAnchor;
@@ -628,28 +928,28 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
628
928
  state.totalSizeBelowAnchor += add;
629
929
  }
630
930
  }
631
- let applyAdjustValue = void 0;
632
- if (maintainVisibleContentPosition) {
633
- const newAdjust = state.anchorElement.coordinate - state.totalSizeBelowAnchor;
931
+ let applyAdjustValue = 0;
932
+ let resultSize = state.totalSize;
933
+ if (maintainVisibleContentPosition && anchorElement !== void 0) {
934
+ const newAdjust = anchorElement.coordinate - state.totalSizeBelowAnchor;
634
935
  applyAdjustValue = -newAdjust;
635
936
  state.belowAnchorElementPositions = buildElementPositionsBelowAnchor();
636
937
  state.rowHeights.clear();
938
+ if (applyAdjustValue !== void 0) {
939
+ resultSize -= applyAdjustValue;
940
+ refState.current.scrollAdjustHandler.requestAdjust(applyAdjustValue, (diff) => {
941
+ state.scroll -= diff;
942
+ });
943
+ }
637
944
  }
638
- const totalSize = state.totalSize;
639
- let resultSize = totalSize;
640
- if (applyAdjustValue !== void 0) {
641
- resultSize -= applyAdjustValue;
642
- refState.current.scrollAdjustHandler.requestAdjust(applyAdjustValue, (diff) => {
643
- state.scroll -= diff;
644
- });
645
- }
646
- set$(ctx, "totalSize", resultSize);
945
+ set$(ctx, "totalSize", state.totalSize);
946
+ set$(ctx, "totalSizeWithScrollAdjust", resultSize);
647
947
  if (alignItemsAtEnd) {
648
948
  doUpdatePaddingTop();
649
949
  }
650
950
  }, []);
651
951
  const getRowHeight = (n) => {
652
- const { rowHeights } = refState.current;
952
+ const { rowHeights, data } = refState.current;
653
953
  if (numColumnsProp === 1) {
654
954
  const id = getId(n);
655
955
  return getItemSize(id, n, data[n]);
@@ -689,39 +989,47 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
689
989
  return map;
690
990
  };
691
991
  const getElementPositionBelowAchor = (id) => {
992
+ var _a2;
692
993
  const state = refState.current;
693
994
  if (!refState.current.belowAnchorElementPositions) {
694
995
  state.belowAnchorElementPositions = buildElementPositionsBelowAnchor();
695
996
  }
696
997
  const res = state.belowAnchorElementPositions.get(id);
697
998
  if (res === void 0) {
698
- throw new Error("Undefined position below achor");
999
+ console.warn(`Undefined position below achor ${id} ${(_a2 = state.anchorElement) == null ? void 0 : _a2.id}`);
1000
+ return 0;
699
1001
  }
700
1002
  return res;
701
1003
  };
702
- const calculateItemsInView = React4.useCallback((speed) => {
1004
+ const calculateItemsInView = React6.useCallback((speed) => {
1005
+ var _a2;
703
1006
  const state = refState.current;
704
1007
  const {
705
- data: data2,
1008
+ data,
706
1009
  scrollLength,
707
1010
  scroll: scrollState,
708
1011
  startBufferedId: startBufferedIdOrig,
709
1012
  positions,
710
1013
  columns,
711
- scrollAdjustHandler,
712
- layoutsPending
1014
+ scrollAdjustHandler
713
1015
  } = state;
714
- if (state.animFrameLayout) {
715
- cancelAnimationFrame(state.animFrameLayout);
716
- state.animFrameLayout = null;
717
- }
718
- if (!data2) {
1016
+ if (!data || scrollLength === 0) {
719
1017
  return;
720
1018
  }
721
1019
  const topPad = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
722
1020
  const previousScrollAdjust = scrollAdjustHandler.getAppliedAdjust();
723
1021
  const scrollExtra = Math.max(-16, Math.min(16, speed)) * 16;
724
- const scroll = scrollState - previousScrollAdjust - topPad - scrollExtra;
1022
+ const scroll = scrollState - previousScrollAdjust - topPad;
1023
+ let scrollBufferTop = scrollBuffer;
1024
+ let scrollBufferBottom = scrollBuffer;
1025
+ if (scrollExtra > 8) {
1026
+ scrollBufferTop = 0;
1027
+ scrollBufferBottom = scrollBuffer + scrollExtra;
1028
+ }
1029
+ if (scrollExtra < -8) {
1030
+ scrollBufferTop = scrollBuffer - scrollExtra;
1031
+ scrollBufferBottom = 0;
1032
+ }
725
1033
  if (state.scrollForNextCalculateItemsInView) {
726
1034
  const { top: top2, bottom } = state.scrollForNextCalculateItemsInView;
727
1035
  if (scroll > top2 && scroll < bottom) {
@@ -734,8 +1042,11 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
734
1042
  let startBufferedId = null;
735
1043
  let endNoBuffer = null;
736
1044
  let endBuffered = null;
737
- const originalStartId = startBufferedIdOrig && state.indexByKey.get(startBufferedIdOrig);
738
- let loopStart = originalStartId || 0;
1045
+ let loopStart = startBufferedIdOrig ? state.indexByKey.get(startBufferedIdOrig) || 0 : 0;
1046
+ if (state.minIndexSizeChanged !== void 0) {
1047
+ loopStart = Math.min(state.minIndexSizeChanged, loopStart);
1048
+ state.minIndexSizeChanged = void 0;
1049
+ }
739
1050
  const anchorElementIndex = getAnchorElementIndex();
740
1051
  for (let i = loopStart; i >= 0; i--) {
741
1052
  const id = getId(i);
@@ -748,7 +1059,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
748
1059
  }
749
1060
  const top2 = newPosition || positions.get(id);
750
1061
  if (top2 !== void 0) {
751
- const size = getItemSize(id, i, data2[i]);
1062
+ const size = getItemSize(id, i, data[i]);
752
1063
  const bottom = top2 + size;
753
1064
  if (bottom > scroll - scrollBuffer) {
754
1065
  loopStart = i;
@@ -766,22 +1077,22 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
766
1077
  let column = 1;
767
1078
  let maxSizeInRow = 0;
768
1079
  const getInitialTop = (i) => {
769
- var _a2;
1080
+ var _a3;
770
1081
  const id = getId(i);
771
1082
  let topOffset = 0;
772
1083
  if (positions.get(id)) {
773
1084
  topOffset = positions.get(id);
774
1085
  }
775
- if (id === ((_a2 = state.anchorElement) == null ? void 0 : _a2.id)) {
776
- topOffset = initialContentOffset || 0;
1086
+ if (id === ((_a3 = state.anchorElement) == null ? void 0 : _a3.id)) {
1087
+ topOffset = state.anchorElement.coordinate;
777
1088
  }
778
1089
  return topOffset;
779
1090
  };
780
- for (let i = loopStart; i < data2.length; i++) {
1091
+ for (let i = loopStart; i < data.length; i++) {
781
1092
  const id = getId(i);
782
- const size = getItemSize(id, i, data2[i]);
1093
+ const size = getItemSize(id, i, data[i]);
783
1094
  maxSizeInRow = Math.max(maxSizeInRow, size);
784
- if (top === void 0) {
1095
+ if (top === void 0 || id === ((_a2 = state.anchorElement) == null ? void 0 : _a2.id)) {
785
1096
  top = getInitialTop(i);
786
1097
  }
787
1098
  if (positions.get(id) !== top) {
@@ -793,7 +1104,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
793
1104
  if (startNoBuffer === null && top + size > scroll) {
794
1105
  startNoBuffer = i;
795
1106
  }
796
- if (startBuffered === null && top + size > scroll - scrollBuffer) {
1107
+ if (startBuffered === null && top + size > scroll - scrollBufferTop) {
797
1108
  startBuffered = i;
798
1109
  startBufferedId = id;
799
1110
  }
@@ -801,7 +1112,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
801
1112
  if (top <= scrollBottom) {
802
1113
  endNoBuffer = i;
803
1114
  }
804
- if (top <= scrollBottom + scrollBuffer) {
1115
+ if (top <= scrollBottom + scrollBufferBottom) {
805
1116
  endBuffered = i;
806
1117
  } else {
807
1118
  break;
@@ -855,7 +1166,7 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
855
1166
  break;
856
1167
  }
857
1168
  const index = state.indexByKey.get(key);
858
- const pos = peek$(ctx, `containerPosition${u}`);
1169
+ const pos = peek$(ctx, `containerPosition${u}`).top;
859
1170
  if (index < startBuffered || index > endBuffered) {
860
1171
  const distance = Math.abs(pos - top2);
861
1172
  if (index < 0 || distance > furthestDistance) {
@@ -867,14 +1178,14 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
867
1178
  if (furthestIndex >= 0) {
868
1179
  set$(ctx, `containerItemKey${furthestIndex}`, id);
869
1180
  const index = state.indexByKey.get(id);
870
- set$(ctx, `containerItemData${furthestIndex}`, data2[index]);
1181
+ set$(ctx, `containerItemData${furthestIndex}`, data[index]);
871
1182
  } else {
872
1183
  const containerId = numContainers;
873
1184
  numContainers++;
874
1185
  set$(ctx, `containerItemKey${containerId}`, id);
875
1186
  const index = state.indexByKey.get(id);
876
- set$(ctx, `containerItemData${containerId}`, data2[index]);
877
- set$(ctx, `containerPosition${containerId}`, POSITION_OUT_OF_VIEW);
1187
+ set$(ctx, `containerItemData${containerId}`, data[index]);
1188
+ set$(ctx, `containerPosition${containerId}`, ANCHORED_POSITION_OUT_OF_VIEW);
878
1189
  set$(ctx, `containerColumn${containerId}`, -1);
879
1190
  if (__DEV__ && numContainers > peek$(ctx, "numContainersPooled")) {
880
1191
  console.warn(
@@ -894,40 +1205,49 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
894
1205
  for (let i = 0; i < numContainers; i++) {
895
1206
  const itemKey = peek$(ctx, `containerItemKey${i}`);
896
1207
  const itemIndex = state.indexByKey.get(itemKey);
897
- const item = data2[itemIndex];
1208
+ const item = data[itemIndex];
898
1209
  if (item) {
899
1210
  const id = getId(itemIndex);
900
1211
  if (itemKey !== id || itemIndex < startBuffered || itemIndex > endBuffered) {
901
- const prevPos = peek$(ctx, `containerPosition${i}`);
1212
+ const prevPos = peek$(ctx, `containerPosition${i}`).top;
902
1213
  const pos = positions.get(id) || 0;
903
- const size = getItemSize(id, itemIndex, data2[i]);
1214
+ const size = getItemSize(id, itemIndex, data[i]);
904
1215
  if (pos + size >= scroll && pos <= scrollBottom || prevPos + size >= scroll && prevPos <= scrollBottom) {
905
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1216
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
906
1217
  }
907
1218
  } else {
908
- const pos = positions.get(id) || 0;
1219
+ const pos = {
1220
+ type: "top",
1221
+ relativeCoordinate: positions.get(id) || 0,
1222
+ top: positions.get(id) || 0
1223
+ };
909
1224
  const column2 = columns.get(id) || 1;
1225
+ if (maintainVisibleContentPosition && itemIndex < anchorElementIndex) {
1226
+ const currentRow = Math.floor(itemIndex / numColumnsProp);
1227
+ const rowHeight = getRowHeight(currentRow);
1228
+ const elementHeight = getItemSize(id, itemIndex, data[i]);
1229
+ const diff = rowHeight - elementHeight;
1230
+ pos.relativeCoordinate = pos.top + getRowHeight(currentRow) - diff;
1231
+ pos.type = "bottom";
1232
+ }
910
1233
  const prevPos = peek$(ctx, `containerPosition${i}`);
911
1234
  const prevColumn = peek$(ctx, `containerColumn${i}`);
912
1235
  const prevData = peek$(ctx, `containerItemData${i}`);
913
- if (pos > POSITION_OUT_OF_VIEW && pos !== prevPos) {
1236
+ if (pos.relativeCoordinate > POSITION_OUT_OF_VIEW && pos.top !== prevPos.top) {
914
1237
  set$(ctx, `containerPosition${i}`, pos);
915
1238
  }
916
1239
  if (column2 >= 0 && column2 !== prevColumn) {
917
1240
  set$(ctx, `containerColumn${i}`, column2);
918
1241
  }
919
1242
  if (prevData !== item) {
920
- set$(ctx, `containerItemData${i}`, data2[itemIndex]);
1243
+ set$(ctx, `containerItemData${i}`, data[itemIndex]);
921
1244
  }
922
1245
  }
923
1246
  }
924
1247
  }
925
1248
  }
926
- if (layoutsPending.size > 0) {
927
- for (const containerId of layoutsPending) {
928
- set$(ctx, `containerDidLayout${containerId}`, true);
929
- }
930
- layoutsPending.clear();
1249
+ if (state.numPendingInitialLayout === 0) {
1250
+ state.numPendingInitialLayout = state.endBuffered - state.startBuffered + 1;
931
1251
  }
932
1252
  if (state.viewabilityConfigCallbackPairs) {
933
1253
  updateViewableItems(
@@ -943,16 +1263,19 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
943
1263
  }, []);
944
1264
  const doUpdatePaddingTop = () => {
945
1265
  if (alignItemsAtEnd) {
946
- const { scrollLength, totalSize } = refState.current;
947
- const listPaddingTop = peek$(ctx, "stylePaddingTop") || 0;
948
- const paddingTop = Math.max(0, Math.floor(scrollLength - totalSize - listPaddingTop));
1266
+ const { scrollLength } = refState.current;
1267
+ const contentSize = getContentSize(ctx);
1268
+ const paddingTop = Math.max(0, Math.floor(scrollLength - contentSize));
949
1269
  set$(ctx, "paddingTop", paddingTop);
950
1270
  }
951
1271
  };
952
1272
  const doMaintainScrollAtEnd = (animated) => {
953
1273
  const state = refState.current;
954
1274
  if ((state == null ? void 0 : state.isAtBottom) && maintainScrollAtEnd) {
955
- state.scroll = state.totalSize - state.scrollLength + peek$(ctx, "paddingTop");
1275
+ const paddingTop = peek$(ctx, "paddingTop") || 0;
1276
+ if (paddingTop > 0) {
1277
+ state.scroll = 0;
1278
+ }
956
1279
  requestAnimationFrame(() => {
957
1280
  var _a2;
958
1281
  (_a2 = refScroller.current) == null ? void 0 : _a2.scrollToEnd({
@@ -962,28 +1285,48 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
962
1285
  return true;
963
1286
  }
964
1287
  };
1288
+ const checkThreshold = (distance, threshold, isReached, isBlockedByTimer, onReached, blockTimer) => {
1289
+ const distanceAbs = Math.abs(distance);
1290
+ const isAtThreshold = distanceAbs < threshold;
1291
+ if (!isReached && !isBlockedByTimer) {
1292
+ if (isAtThreshold) {
1293
+ onReached == null ? void 0 : onReached(distance);
1294
+ blockTimer == null ? void 0 : blockTimer(true);
1295
+ setTimeout(() => {
1296
+ blockTimer == null ? void 0 : blockTimer(false);
1297
+ }, 700);
1298
+ return true;
1299
+ }
1300
+ } else {
1301
+ if (distance >= 1.3 * threshold) {
1302
+ return false;
1303
+ }
1304
+ }
1305
+ return isReached;
1306
+ };
965
1307
  const checkAtBottom = () => {
966
1308
  if (!refState.current) {
967
1309
  return;
968
1310
  }
969
- const { scrollLength, scroll, totalSize } = refState.current;
970
- if (totalSize > 0) {
971
- const distanceFromEnd = totalSize - scroll - scrollLength;
972
- if (refState.current) {
973
- refState.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
974
- }
975
- if (onEndReached) {
976
- if (!refState.current.isEndReached) {
977
- if (distanceFromEnd < onEndReachedThreshold * scrollLength) {
978
- refState.current.isEndReached = true;
979
- onEndReached({ distanceFromEnd });
980
- }
981
- } else {
982
- if (distanceFromEnd >= onEndReachedThreshold * scrollLength) {
983
- refState.current.isEndReached = false;
984
- }
1311
+ const { scrollLength, scroll, hasScrolled } = refState.current;
1312
+ const contentSize = getContentSize(ctx);
1313
+ if (contentSize > 0 && hasScrolled) {
1314
+ const distanceFromEnd = contentSize - scroll - scrollLength;
1315
+ const distanceFromEndAbs = Math.abs(distanceFromEnd);
1316
+ refState.current.isAtBottom = distanceFromEndAbs < scrollLength * maintainScrollAtEndThreshold;
1317
+ refState.current.isEndReached = checkThreshold(
1318
+ distanceFromEnd,
1319
+ onEndReachedThreshold * scrollLength,
1320
+ refState.current.isEndReached,
1321
+ refState.current.endReachedBlockedByTimer,
1322
+ (distance) => {
1323
+ var _a2, _b2;
1324
+ return (_b2 = (_a2 = callbacks.current).onEndReached) == null ? void 0 : _b2.call(_a2, { distanceFromEnd: distance });
1325
+ },
1326
+ (block) => {
1327
+ refState.current.endReachedBlockedByTimer = block;
985
1328
  }
986
- }
1329
+ );
987
1330
  }
988
1331
  };
989
1332
  const checkAtTop = () => {
@@ -992,74 +1335,114 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
992
1335
  }
993
1336
  const { scrollLength, scroll } = refState.current;
994
1337
  const distanceFromTop = scroll;
995
- refState.current.isAtTop = distanceFromTop < 0;
996
- if (onStartReached) {
997
- if (!refState.current.isStartReached && !refState.current.startReachedBlockedByTimer) {
998
- if (distanceFromTop < onStartReachedThreshold * scrollLength) {
999
- refState.current.isStartReached = true;
1000
- onStartReached({ distanceFromStart: scroll });
1001
- refState.current.startReachedBlockedByTimer = true;
1002
- setTimeout(() => {
1003
- refState.current.startReachedBlockedByTimer = false;
1004
- }, 700);
1005
- }
1006
- } else {
1007
- if (distanceFromTop >= 1.3 * onStartReachedThreshold * scrollLength) {
1008
- refState.current.isStartReached = false;
1009
- }
1338
+ const distanceFromTopAbs = Math.abs(distanceFromTop);
1339
+ refState.current.isAtTop = distanceFromTopAbs < 0;
1340
+ refState.current.isStartReached = checkThreshold(
1341
+ distanceFromTop,
1342
+ onStartReachedThreshold * scrollLength,
1343
+ refState.current.isStartReached,
1344
+ refState.current.startReachedBlockedByTimer,
1345
+ (distance) => {
1346
+ var _a2, _b2;
1347
+ return (_b2 = (_a2 = callbacks.current).onStartReached) == null ? void 0 : _b2.call(_a2, { distanceFromStart: distance });
1348
+ },
1349
+ (block) => {
1350
+ refState.current.startReachedBlockedByTimer = block;
1010
1351
  }
1011
- }
1352
+ );
1012
1353
  };
1013
- const checkResetContainers = (reset) => {
1354
+ const checkResetContainers = (isFirst2) => {
1014
1355
  const state = refState.current;
1015
1356
  if (state) {
1016
- state.data = data;
1017
- if (reset) {
1357
+ state.data = dataProp;
1358
+ if (!isFirst2) {
1018
1359
  refState.current.scrollForNextCalculateItemsInView = void 0;
1019
1360
  const numContainers = peek$(ctx, "numContainers");
1020
1361
  for (let i = 0; i < numContainers; i++) {
1021
1362
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1022
1363
  if (!keyExtractorProp || itemKey && state.indexByKey.get(itemKey) === void 0) {
1023
1364
  set$(ctx, `containerItemKey${i}`, void 0);
1024
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1365
+ set$(ctx, `containerItemData${i}`, void 0);
1366
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1025
1367
  set$(ctx, `containerColumn${i}`, -1);
1026
1368
  }
1027
1369
  }
1028
1370
  if (!keyExtractorProp) {
1029
- state.sizes.clear();
1030
- state.positions;
1371
+ state.positions.clear();
1031
1372
  }
1032
1373
  calculateItemsInView(state.scrollVelocity);
1374
+ const didMaintainScrollAtEnd = doMaintainScrollAtEnd(false);
1375
+ if (!didMaintainScrollAtEnd && dataProp.length > state.data.length) {
1376
+ state.isEndReached = false;
1377
+ }
1378
+ checkAtTop();
1379
+ checkAtBottom();
1033
1380
  }
1034
- const didMaintainScrollAtEnd = doMaintainScrollAtEnd(false);
1035
- if (!didMaintainScrollAtEnd && data.length > state.data.length) {
1036
- state.isEndReached = false;
1037
- }
1038
- checkAtTop();
1039
- checkAtBottom();
1040
1381
  }
1041
1382
  };
1042
- const isFirst = !refState.current.renderItem;
1043
- if (isFirst || data !== refState.current.data || numColumnsProp !== peek$(ctx, "numColumns")) {
1044
- if (!keyExtractorProp && !isFirst && data !== refState.current.data) {
1045
- refState.current.sizes.clear();
1046
- refState.current.positions.clear();
1047
- }
1048
- refState.current.data = data;
1383
+ const calcTotalSizesAndPositions = ({ forgetPositions = false }) => {
1384
+ var _a2, _b2, _c2;
1049
1385
  let totalSize = 0;
1050
1386
  let totalSizeBelowIndex = 0;
1051
1387
  const indexByKey = /* @__PURE__ */ new Map();
1388
+ const newPositions = /* @__PURE__ */ new Map();
1052
1389
  let column = 1;
1053
1390
  let maxSizeInRow = 0;
1054
- for (let i = 0; i < data.length; i++) {
1391
+ if (!refState.current) {
1392
+ return;
1393
+ }
1394
+ for (let i = 0; i < dataProp.length; i++) {
1055
1395
  const key = getId(i);
1396
+ if (__DEV__) {
1397
+ if (indexByKey.has(key)) {
1398
+ console.error(
1399
+ `[legend-list] Error: Detected overlapping key (${key}) which causes missing items and gaps and other terrrible things. Check that keyExtractor returns unique values.`
1400
+ );
1401
+ }
1402
+ }
1056
1403
  indexByKey.set(key, i);
1404
+ if (!forgetPositions && refState.current.positions.get(key) != null && refState.current.indexByKey.get(key) === i) {
1405
+ newPositions.set(key, refState.current.positions.get(key));
1406
+ }
1057
1407
  }
1058
1408
  refState.current.indexByKey = indexByKey;
1409
+ refState.current.positions = newPositions;
1410
+ if (!forgetPositions && !isFirst) {
1411
+ if (maintainVisibleContentPosition) {
1412
+ if (refState.current.anchorElement == null || indexByKey.get(refState.current.anchorElement.id) == null) {
1413
+ if (dataProp.length) {
1414
+ const newAnchorElement = {
1415
+ coordinate: 0,
1416
+ id: getId(0)
1417
+ };
1418
+ refState.current.anchorElement = newAnchorElement;
1419
+ (_a2 = refState.current.belowAnchorElementPositions) == null ? void 0 : _a2.clear();
1420
+ (_b2 = refScroller.current) == null ? void 0 : _b2.scrollTo({ x: 0, y: 0, animated: false });
1421
+ setTimeout(() => {
1422
+ calculateItemsInView(0);
1423
+ }, 0);
1424
+ } else {
1425
+ refState.current.startBufferedId = void 0;
1426
+ }
1427
+ }
1428
+ } else {
1429
+ if (refState.current.startBufferedId != null && newPositions.get(refState.current.startBufferedId) == null) {
1430
+ if (dataProp.length) {
1431
+ refState.current.startBufferedId = getId(0);
1432
+ } else {
1433
+ refState.current.startBufferedId = void 0;
1434
+ }
1435
+ (_c2 = refScroller.current) == null ? void 0 : _c2.scrollTo({ x: 0, y: 0, animated: false });
1436
+ setTimeout(() => {
1437
+ calculateItemsInView(0);
1438
+ }, 0);
1439
+ }
1440
+ }
1441
+ }
1059
1442
  const anchorElementIndex = getAnchorElementIndex();
1060
- for (let i = 0; i < data.length; i++) {
1443
+ for (let i = 0; i < dataProp.length; i++) {
1061
1444
  const key = getId(i);
1062
- const size = getItemSize(key, i, data[i]);
1445
+ const size = getItemSize(key, i, dataProp[i]);
1063
1446
  maxSizeInRow = Math.max(maxSizeInRow, size);
1064
1447
  column++;
1065
1448
  if (column > numColumnsProp) {
@@ -1075,170 +1458,134 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1075
1458
  totalSize += maxSizeInRow;
1076
1459
  }
1077
1460
  addTotalSize(null, totalSize, totalSizeBelowIndex);
1461
+ };
1462
+ const isFirst = !refState.current.renderItem;
1463
+ if (isFirst || didDataChange || numColumnsProp !== peek$(ctx, "numColumns")) {
1464
+ if (!keyExtractorProp && !isFirst && didDataChange) {
1465
+ refState.current.sizes.clear();
1466
+ refState.current.positions.clear();
1467
+ }
1468
+ calcTotalSizesAndPositions({ forgetPositions: false });
1078
1469
  }
1079
- React4.useEffect(() => {
1470
+ React6.useEffect(() => {
1080
1471
  checkResetContainers(
1081
- /*reset*/
1082
- !isFirst
1472
+ /*isFirst*/
1473
+ isFirst
1083
1474
  );
1084
- }, [isFirst, data, numColumnsProp]);
1085
- React4.useEffect(() => {
1475
+ }, [isFirst, dataProp, numColumnsProp]);
1476
+ React6.useEffect(() => {
1086
1477
  set$(ctx, "extraData", extraData);
1087
1478
  }, [extraData]);
1088
1479
  refState.current.renderItem = renderItem;
1089
- const lastItemKey = getId(data[data.length - 1]);
1480
+ const memoizedLastItemKeys = React6.useMemo(() => {
1481
+ if (!dataProp.length) return [];
1482
+ return new Set(
1483
+ Array.from({ length: Math.min(numColumnsProp, dataProp.length) }, (_, i) => getId(dataProp.length - 1 - i))
1484
+ );
1485
+ }, [dataProp.length, numColumnsProp, dataProp.slice(-numColumnsProp).toString()]);
1090
1486
  const stylePaddingTop = (_d = (_c = (_a = reactNative.StyleSheet.flatten(style)) == null ? void 0 : _a.paddingTop) != null ? _c : (_b = reactNative.StyleSheet.flatten(contentContainerStyle)) == null ? void 0 : _b.paddingTop) != null ? _d : 0;
1091
1487
  const initalizeStateVars = () => {
1092
- set$(ctx, "lastItemKey", lastItemKey);
1488
+ set$(ctx, "lastItemKeys", memoizedLastItemKeys);
1093
1489
  set$(ctx, "numColumns", numColumnsProp);
1094
1490
  set$(ctx, "stylePaddingTop", stylePaddingTop);
1095
1491
  };
1096
1492
  if (isFirst) {
1097
1493
  initalizeStateVars();
1098
1494
  }
1099
- React4.useEffect(initalizeStateVars, [lastItemKey, numColumnsProp, stylePaddingTop]);
1100
- const getRenderedItem = React4.useCallback((key, containerId) => {
1495
+ React6.useEffect(initalizeStateVars, [memoizedLastItemKeys, numColumnsProp, stylePaddingTop]);
1496
+ const getRenderedItem = React6.useCallback((key) => {
1101
1497
  var _a2, _b2;
1102
1498
  const state = refState.current;
1103
1499
  if (!state) {
1104
1500
  return null;
1105
1501
  }
1106
- const { data: data2, indexByKey } = state;
1502
+ const { data, indexByKey } = state;
1107
1503
  const index = indexByKey.get(key);
1108
1504
  if (index === void 0) {
1109
1505
  return null;
1110
1506
  }
1111
- const useViewability = (configId, callback) => {
1112
- const key2 = containerId + configId;
1113
- useInit(() => {
1114
- const value = ctx.mapViewabilityValues.get(key2);
1115
- if (value) {
1116
- callback(value);
1117
- }
1118
- });
1119
- ctx.mapViewabilityCallbacks.set(key2, callback);
1120
- React4.useEffect(
1121
- () => () => {
1122
- ctx.mapViewabilityCallbacks.delete(key2);
1123
- },
1124
- []
1125
- );
1507
+ const useViewability2 = (configId, callback) => {
1508
+ useViewability(configId, callback);
1126
1509
  };
1127
- const useViewabilityAmount = (callback) => {
1128
- useInit(() => {
1129
- const value = ctx.mapViewabilityAmountValues.get(containerId);
1130
- if (value) {
1131
- callback(value);
1132
- }
1133
- });
1134
- ctx.mapViewabilityAmountCallbacks.set(containerId, callback);
1135
- React4.useEffect(
1136
- () => () => {
1137
- ctx.mapViewabilityAmountCallbacks.delete(containerId);
1138
- },
1139
- []
1140
- );
1510
+ const useViewabilityAmount2 = (callback) => {
1511
+ useViewabilityAmount(callback);
1141
1512
  };
1142
- const useRecyclingEffect = (effect) => {
1143
- React4.useEffect(() => {
1144
- const state2 = refState.current;
1145
- let prevIndex = index;
1146
- let prevItem = state2.data[index];
1147
- const signal = `containerItemKey${containerId}`;
1148
- const run = () => {
1149
- const data3 = state2.data;
1150
- if (data3) {
1151
- const newKey = peek$(ctx, signal);
1152
- const newIndex = state2.indexByKey.get(newKey);
1153
- const newItem = data3[newIndex];
1154
- if (newItem) {
1155
- effect({
1156
- index: newIndex,
1157
- item: newItem,
1158
- prevIndex,
1159
- prevItem
1160
- });
1161
- }
1162
- prevIndex = newIndex;
1163
- prevItem = newItem;
1164
- }
1165
- };
1166
- run();
1167
- return listen$(ctx, signal, run);
1168
- }, []);
1513
+ const useRecyclingEffect2 = (effect) => {
1514
+ useRecyclingEffect(effect);
1169
1515
  };
1170
- const useRecyclingState = (valueOrFun) => {
1171
- const stateInfo = React4.useState(
1172
- () => typeof valueOrFun === "function" ? valueOrFun({
1173
- index,
1174
- item: refState.current.data[index],
1175
- prevIndex: void 0,
1176
- prevItem: void 0
1177
- }) : valueOrFun
1178
- );
1179
- useRecyclingEffect((state2) => {
1180
- const newState = typeof valueOrFun === "function" ? valueOrFun(state2) : valueOrFun;
1181
- stateInfo[1](newState);
1182
- });
1183
- return stateInfo;
1516
+ const useRecyclingState2 = (valueOrFun) => {
1517
+ return useRecyclingState(valueOrFun);
1184
1518
  };
1185
1519
  const renderedItem = (_b2 = (_a2 = refState.current).renderItem) == null ? void 0 : _b2.call(_a2, {
1186
- item: data2[index],
1520
+ item: data[index],
1187
1521
  index,
1188
- useViewability,
1189
- useViewabilityAmount,
1190
- useRecyclingEffect,
1191
- useRecyclingState
1522
+ useViewability: useViewability2,
1523
+ useViewabilityAmount: useViewabilityAmount2,
1524
+ useRecyclingEffect: useRecyclingEffect2,
1525
+ useRecyclingState: useRecyclingState2
1192
1526
  });
1193
- return renderedItem;
1527
+ return { index, item: data[index], renderedItem };
1194
1528
  }, []);
1195
- useInit(() => {
1529
+ const doInitialAllocateContainers = () => {
1196
1530
  var _a2;
1531
+ const state = refState.current;
1532
+ const scrollLength = state.scrollLength;
1533
+ if (scrollLength > 0 && !peek$(ctx, "numContainers")) {
1534
+ const averageItemSize = (_a2 = estimatedItemSize != null ? estimatedItemSize : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(0, dataProp[0])) != null ? _a2 : DEFAULT_ITEM_SIZE;
1535
+ const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) * numColumnsProp;
1536
+ for (let i = 0; i < numContainers; i++) {
1537
+ set$(ctx, `containerPosition${i}`, ANCHORED_POSITION_OUT_OF_VIEW);
1538
+ set$(ctx, `containerColumn${i}`, -1);
1539
+ }
1540
+ set$(ctx, "numContainers", numContainers);
1541
+ set$(ctx, "numContainersPooled", numContainers * 2);
1542
+ if (initialScrollIndex) {
1543
+ requestAnimationFrame(() => {
1544
+ calculateItemsInView(state.scrollVelocity);
1545
+ });
1546
+ } else {
1547
+ calculateItemsInView(state.scrollVelocity);
1548
+ }
1549
+ }
1550
+ };
1551
+ useInit(() => {
1197
1552
  const state = refState.current;
1198
1553
  const viewability = setupViewability(props);
1199
1554
  state.viewabilityConfigCallbackPairs = viewability;
1200
1555
  state.enableScrollForNextCalculateItemsInView = !viewability;
1201
- const scrollLength = state.scrollLength;
1202
- const averageItemSize = (_a2 = estimatedItemSize != null ? estimatedItemSize : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(0, data[0])) != null ? _a2 : DEFAULT_ITEM_SIZE;
1203
- const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) * numColumnsProp;
1204
- for (let i = 0; i < numContainers; i++) {
1205
- set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
1206
- set$(ctx, `containerColumn${i}`, -1);
1207
- }
1208
- set$(ctx, "numContainers", numContainers);
1209
- set$(ctx, "numContainersPooled", numContainers * 2);
1210
- calculateItemsInView(state.scrollVelocity);
1556
+ doInitialAllocateContainers();
1211
1557
  });
1212
- const updateItemSize = React4.useCallback((containerId, itemKey, size) => {
1213
- var _a2;
1214
- const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
1215
- if (!data2) {
1558
+ const updateItemSize = React6.useCallback((containerId, itemKey, size) => {
1559
+ const state = refState.current;
1560
+ const { sizes, indexByKey, sizesLaidOut, data, rowHeights } = state;
1561
+ if (!data) {
1216
1562
  return;
1217
1563
  }
1218
- const state = refState.current;
1219
- const { sizes, indexByKey, idsInFirstRender, columns, sizesLaidOut } = state;
1220
1564
  const index = indexByKey.get(itemKey);
1221
1565
  const numColumns = peek$(ctx, "numColumns");
1222
- const row = Math.floor(index / numColumns);
1223
- const prevSize = getRowHeight(row);
1224
- const measured = peek$(ctx, `containerDidLayout${containerId}`);
1225
- if (!measured) {
1226
- state.layoutsPending.add(containerId);
1566
+ state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, index) : index;
1567
+ const prevSize = getItemSize(itemKey, index, data);
1568
+ let needsCalculate = false;
1569
+ if (state.numPendingInitialLayout > 0) {
1570
+ state.numPendingInitialLayout--;
1571
+ if (state.numPendingInitialLayout === 0) {
1572
+ needsCalculate = true;
1573
+ state.numPendingInitialLayout = -1;
1574
+ queueMicrotask(() => {
1575
+ set$(ctx, "containersDidLayout", true);
1576
+ });
1577
+ }
1227
1578
  }
1228
1579
  if (!prevSize || Math.abs(prevSize - size) > 0.5) {
1229
1580
  let diff;
1581
+ needsCalculate = true;
1230
1582
  if (numColumns > 1) {
1231
- const prevMaxSizeInRow = getRowHeight(row);
1583
+ const rowNumber = Math.floor(index / numColumnsProp);
1584
+ const prevSizeInRow = getRowHeight(rowNumber);
1232
1585
  sizes.set(itemKey, size);
1233
- const column = columns.get(itemKey);
1234
- const loopStart = index - (column - 1);
1235
- let nextMaxSizeInRow = 0;
1236
- for (let i = loopStart; i < loopStart + numColumns && i < data2.length; i++) {
1237
- const id = getId(i);
1238
- const size2 = getItemSize(id, i, data2[i]);
1239
- nextMaxSizeInRow = Math.max(nextMaxSizeInRow, size2);
1240
- }
1241
- diff = nextMaxSizeInRow - prevMaxSizeInRow;
1586
+ rowHeights.delete(rowNumber);
1587
+ const sizeInRow = getRowHeight(rowNumber);
1588
+ diff = sizeInRow - prevSizeInRow;
1242
1589
  } else {
1243
1590
  sizes.set(itemKey, size);
1244
1591
  diff = size - prevSize;
@@ -1265,36 +1612,41 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1265
1612
  refState.current.scrollForNextCalculateItemsInView = void 0;
1266
1613
  addTotalSize(itemKey, diff, 0);
1267
1614
  doMaintainScrollAtEnd(true);
1268
- const scrollVelocity = state.scrollVelocity;
1269
- if (!state.animFrameLayout && (Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1)) {
1270
- if (!peek$(ctx, `containerDidLayout${containerId}`)) {
1271
- state.animFrameLayout = requestAnimationFrame(() => {
1272
- state.animFrameLayout = null;
1273
- calculateItemsInView(state.scrollVelocity);
1274
- });
1275
- } else {
1276
- calculateItemsInView(state.scrollVelocity);
1277
- }
1278
- }
1279
1615
  if (onItemSizeChanged) {
1280
- onItemSizeChanged({ size, previous: prevSize, index, itemKey, itemData: data2[index] });
1616
+ onItemSizeChanged({
1617
+ size,
1618
+ previous: prevSize,
1619
+ index,
1620
+ itemKey,
1621
+ itemData: data[index]
1622
+ });
1623
+ }
1624
+ }
1625
+ if (needsCalculate) {
1626
+ const scrollVelocity = state.scrollVelocity;
1627
+ if ((Number.isNaN(scrollVelocity) || Math.abs(scrollVelocity) < 1) && (!waitForInitialLayout || state.numPendingInitialLayout < 0)) {
1628
+ calculateItemsInView(state.scrollVelocity);
1281
1629
  }
1282
- } else {
1283
- set$(ctx, `containerDidLayout${containerId}`, true);
1284
1630
  }
1285
1631
  }, []);
1286
- const handleScrollDebounced = React4.useCallback((velocity) => {
1632
+ const handleScrollDebounced = React6.useCallback((velocity) => {
1287
1633
  calculateItemsInView(velocity);
1288
1634
  checkAtBottom();
1289
1635
  checkAtTop();
1290
1636
  }, []);
1291
- const onLayout = React4.useCallback((event) => {
1637
+ const onLayout = React6.useCallback((event) => {
1292
1638
  const scrollLength = event.nativeEvent.layout[horizontal ? "width" : "height"];
1639
+ const didChange = scrollLength !== refState.current.scrollLength;
1640
+ refState.current.scrollLength;
1293
1641
  refState.current.scrollLength = scrollLength;
1642
+ doInitialAllocateContainers();
1294
1643
  doMaintainScrollAtEnd(false);
1295
1644
  doUpdatePaddingTop();
1296
1645
  checkAtBottom();
1297
1646
  checkAtTop();
1647
+ if (didChange) {
1648
+ calculateItemsInView(0);
1649
+ }
1298
1650
  if (__DEV__) {
1299
1651
  const isWidthZero = event.nativeEvent.layout.width === 0;
1300
1652
  const isHeightZero = event.nativeEvent.layout.height === 0;
@@ -1304,8 +1656,11 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1304
1656
  );
1305
1657
  }
1306
1658
  }
1659
+ if (onLayoutProp) {
1660
+ onLayoutProp(event);
1661
+ }
1307
1662
  }, []);
1308
- const handleScroll = React4.useCallback(
1663
+ const handleScroll = React6.useCallback(
1309
1664
  (event, fromSelf) => {
1310
1665
  var _a2, _b2, _c2;
1311
1666
  if (((_b2 = (_a2 = event.nativeEvent) == null ? void 0 : _a2.contentSize) == null ? void 0 : _b2.height) === 0 && ((_c2 = event.nativeEvent.contentSize) == null ? void 0 : _c2.width) === 0) {
@@ -1347,63 +1702,111 @@ var LegendListInner = React4.forwardRef(function LegendListInner2(props, forward
1347
1702
  },
1348
1703
  []
1349
1704
  );
1350
- React4.useImperativeHandle(
1705
+ React6.useImperativeHandle(
1351
1706
  forwardedRef,
1352
1707
  () => {
1353
- const scrollToIndex = ({ index, animated }) => {
1354
- const offsetObj = calculateInitialOffset(index);
1355
- const offset = horizontal ? { x: offsetObj, y: 0 } : { x: 0, y: offsetObj };
1356
- refScroller.current.scrollTo({ ...offset, animated });
1708
+ const scrollToIndex = ({ index, animated = true }) => {
1709
+ var _a2;
1710
+ const state = refState.current;
1711
+ const firstIndexOffset = calculateOffsetForIndex(index);
1712
+ let firstIndexScrollPostion = firstIndexOffset;
1713
+ if (maintainVisibleContentPosition) {
1714
+ const id = getId(index);
1715
+ state.anchorElement = { id, coordinate: firstIndexOffset };
1716
+ (_a2 = state.belowAnchorElementPositions) == null ? void 0 : _a2.clear();
1717
+ state.positions.clear();
1718
+ calcTotalSizesAndPositions({ forgetPositions: true });
1719
+ state.scrollForNextCalculateItemsInView = void 0;
1720
+ state.startBufferedId = id;
1721
+ state.minIndexSizeChanged = index;
1722
+ firstIndexScrollPostion = firstIndexOffset + state.scrollAdjustHandler.getAppliedAdjust();
1723
+ state.scrollAdjustHandler.pauseAdjust();
1724
+ setTimeout(
1725
+ () => {
1726
+ const wasAdjusted = state.scrollAdjustHandler.unPauseAdjust();
1727
+ if (wasAdjusted) {
1728
+ refState.current.scrollVelocity = 0;
1729
+ refState.current.scrollHistory = [];
1730
+ calculateItemsInView(0);
1731
+ }
1732
+ },
1733
+ animated ? 1e3 : 50
1734
+ );
1735
+ }
1736
+ const offset = horizontal ? { x: firstIndexScrollPostion, y: 0 } : { x: 0, y: firstIndexScrollPostion };
1737
+ if (maintainVisibleContentPosition) {
1738
+ setTimeout(() => {
1739
+ refScroller.current.scrollTo({ ...offset, animated });
1740
+ }, 50);
1741
+ } else {
1742
+ refScroller.current.scrollTo({ ...offset, animated });
1743
+ }
1357
1744
  };
1358
1745
  return {
1359
1746
  getNativeScrollRef: () => refScroller.current,
1360
- getScrollableNode: refScroller.current.getScrollableNode,
1361
- getScrollResponder: refScroller.current.getScrollResponder,
1362
- flashScrollIndicators: refScroller.current.flashScrollIndicators,
1747
+ getScrollableNode: () => refScroller.current.getScrollableNode(),
1748
+ getScrollResponder: () => refScroller.current.getScrollResponder(),
1749
+ flashScrollIndicators: () => refScroller.current.flashScrollIndicators(),
1363
1750
  scrollToIndex,
1364
1751
  scrollToOffset: ({ offset, animated }) => {
1365
1752
  const offsetObj = horizontal ? { x: offset, y: 0 } : { x: 0, y: offset };
1366
1753
  refScroller.current.scrollTo({ ...offsetObj, animated });
1367
1754
  },
1368
1755
  scrollToItem: ({ item, animated }) => {
1756
+ const { data } = refState.current;
1369
1757
  const index = data.indexOf(item);
1370
1758
  if (index !== -1) {
1371
1759
  scrollToIndex({ index, animated });
1372
1760
  }
1373
1761
  },
1374
- scrollToEnd: refScroller.current.scrollToEnd
1762
+ scrollToEnd: (options) => refScroller.current.scrollToEnd(options)
1375
1763
  };
1376
1764
  },
1377
1765
  []
1378
1766
  );
1379
- return /* @__PURE__ */ React4__namespace.createElement(
1767
+ return /* @__PURE__ */ React6__namespace.createElement(React6__namespace.Fragment, null, /* @__PURE__ */ React6__namespace.createElement(
1380
1768
  ListComponent,
1381
1769
  {
1382
1770
  ...rest,
1383
1771
  horizontal,
1384
- refScrollView: (r) => {
1385
- refScroller.current = r;
1386
- if (refScrollView) {
1387
- if (typeof refScrollView === "function") {
1388
- refScrollView(r);
1389
- } else {
1390
- refScrollView.current = r;
1391
- }
1392
- }
1393
- },
1772
+ refScrollView: combinedRef,
1394
1773
  initialContentOffset,
1395
1774
  getRenderedItem,
1396
1775
  updateItemSize,
1397
1776
  handleScroll,
1777
+ onMomentumScrollEnd: (event) => {
1778
+ const wasPaused = refState.current.scrollAdjustHandler.unPauseAdjust();
1779
+ if (wasPaused) {
1780
+ refState.current.scrollVelocity = 0;
1781
+ refState.current.scrollHistory = [];
1782
+ calculateItemsInView(0);
1783
+ }
1784
+ if (onMomentumScrollEnd) {
1785
+ onMomentumScrollEnd(event);
1786
+ }
1787
+ },
1398
1788
  onLayout,
1399
1789
  recycleItems,
1400
1790
  alignItemsAtEnd,
1401
- ListEmptyComponent: data.length === 0 ? ListEmptyComponent : void 0,
1791
+ ListEmptyComponent: dataProp.length === 0 ? ListEmptyComponent : void 0,
1402
1792
  maintainVisibleContentPosition,
1403
1793
  scrollEventThrottle: scrollEventThrottle != null ? scrollEventThrottle : reactNative.Platform.OS === "web" ? 16 : void 0,
1794
+ waitForInitialLayout,
1795
+ refreshControl: refreshControl != null ? refreshControl : onRefresh && /* @__PURE__ */ React6__namespace.createElement(
1796
+ reactNative.RefreshControl,
1797
+ {
1798
+ refreshing: !!refreshing,
1799
+ onRefresh,
1800
+ progressViewOffset
1801
+ }
1802
+ ),
1404
1803
  style
1405
1804
  }
1406
- );
1805
+ ), __DEV__ && ENABLE_DEBUG_VIEW && /* @__PURE__ */ React6__namespace.createElement(DebugView, { state: refState.current }));
1407
1806
  });
1408
1807
 
1409
1808
  exports.LegendList = LegendList;
1809
+ exports.useRecyclingEffect = useRecyclingEffect;
1810
+ exports.useRecyclingState = useRecyclingState;
1811
+ exports.useViewability = useViewability;
1812
+ exports.useViewabilityAmount = useViewabilityAmount;