@legendapp/list 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.mjs CHANGED
@@ -1,39 +1,36 @@
1
- import * as React2 from 'react';
2
- import { forwardRef, useRef, useMemo, useCallback, useEffect } from 'react';
3
- import { ScrollView, View, StyleSheet, Dimensions } from 'react-native';
1
+ import * as React6 from 'react';
2
+ import { forwardRef, useRef, useMemo, useCallback } from 'react';
3
+ import { ScrollView, View, StyleSheet, Dimensions, unstable_batchedUpdates } from 'react-native';
4
4
 
5
5
  // src/LegendList.tsx
6
- var LeanView = React2.forwardRef((props, ref) => {
7
- return React2.createElement("RCTView", { ...props, ref });
6
+ var LeanView = React6.forwardRef((props, ref) => {
7
+ return React6.createElement("RCTView", { ...props, ref });
8
8
  });
9
9
  LeanView.displayName = "RCTView";
10
- var ContextListener = React2.createContext(null);
10
+ var ContextListener = React6.createContext(null);
11
11
  function StateProvider({ children }) {
12
- const [value] = React2.useState(() => ({
12
+ const [value] = React6.useState(() => ({
13
13
  listeners: /* @__PURE__ */ new Map(),
14
14
  values: /* @__PURE__ */ new Map()
15
15
  }));
16
- return /* @__PURE__ */ React2.createElement(ContextListener.Provider, { value }, children);
16
+ return /* @__PURE__ */ React6.createElement(ContextListener.Provider, { value }, children);
17
17
  }
18
18
  function useStateContext() {
19
- return React2.useContext(ContextListener);
19
+ return React6.useContext(ContextListener);
20
20
  }
21
21
  function use$(signalName) {
22
- const { listeners, values } = React2.useContext(ContextListener);
23
- const [_, setState] = React2.useState(0);
24
- React2.useMemo(() => {
25
- const render = () => setState((prev) => prev > 1e4 ? 0 : prev + 1);
26
- listeners.set(signalName, render);
27
- }, []);
22
+ const { listeners, values } = React6.useContext(ContextListener);
23
+ const [, forceUpdate] = React6.useReducer((x) => x + 1, 0);
24
+ listeners.set(signalName, forceUpdate);
28
25
  return values.get(signalName);
29
26
  }
30
- function peek$(signalName, ctx) {
31
- const { values } = ctx || React2.useContext(ContextListener);
27
+ function peek$(ctx, signalName) {
28
+ const { values } = ctx;
32
29
  return values.get(signalName);
33
30
  }
34
- function set$(signalName, ctx, value) {
31
+ function set$(ctx, signalName, value) {
35
32
  var _a;
36
- const { listeners, values } = ctx || React2.useContext(ContextListener);
33
+ const { listeners, values } = ctx;
37
34
  if (values.get(signalName) !== value) {
38
35
  values.set(signalName, value);
39
36
  (_a = listeners.get(signalName)) == null ? void 0 : _a();
@@ -44,7 +41,7 @@ function set$(signalName, ctx, value) {
44
41
  function $View({ $key, $style, ...rest }) {
45
42
  use$($key);
46
43
  const style = $style();
47
- return /* @__PURE__ */ React2.createElement(LeanView, { style, ...rest });
44
+ return /* @__PURE__ */ React6.createElement(LeanView, { style, ...rest });
48
45
  }
49
46
  function InnerContainer({ id, getRenderedItem, recycleItems, ItemSeparatorComponent }) {
50
47
  const itemIndex = use$(`containerIndex${id}`);
@@ -53,7 +50,7 @@ function InnerContainer({ id, getRenderedItem, recycleItems, ItemSeparatorCompon
53
50
  return null;
54
51
  }
55
52
  const renderedItem = getRenderedItem(itemIndex);
56
- return /* @__PURE__ */ React2.createElement(React2.Fragment, { key: recycleItems ? void 0 : itemIndex }, renderedItem, ItemSeparatorComponent && itemIndex < numItems - 1 && ItemSeparatorComponent);
53
+ return /* @__PURE__ */ React6.createElement(React6.Fragment, { key: recycleItems ? void 0 : itemIndex }, renderedItem, ItemSeparatorComponent && itemIndex < numItems - 1 && ItemSeparatorComponent);
57
54
  }
58
55
  var Container = ({
59
56
  id,
@@ -65,7 +62,7 @@ var Container = ({
65
62
  }) => {
66
63
  const ctx = useStateContext();
67
64
  const createStyle = () => {
68
- const position = peek$(`containerPosition${id}`, ctx);
65
+ const position = peek$(ctx, `containerPosition${id}`);
69
66
  return horizontal ? {
70
67
  flexDirection: "row",
71
68
  position: "absolute",
@@ -81,20 +78,20 @@ var Container = ({
81
78
  opacity: position < 0 ? 0 : 1
82
79
  };
83
80
  };
84
- return /* @__PURE__ */ React2.createElement(
81
+ return /* @__PURE__ */ React6.createElement(
85
82
  $View,
86
83
  {
87
84
  $key: `containerPosition${id}`,
88
85
  $style: createStyle,
89
86
  onLayout: (event) => {
90
- const index = peek$(`containerIndex${id}`, ctx);
87
+ const index = peek$(ctx, `containerIndex${id}`);
91
88
  if (index >= 0) {
92
89
  const length = Math.round(event.nativeEvent.layout[horizontal ? "width" : "height"]);
93
90
  onLayout(index, length);
94
91
  }
95
92
  }
96
93
  },
97
- /* @__PURE__ */ React2.createElement(
94
+ /* @__PURE__ */ React6.createElement(
98
95
  InnerContainer,
99
96
  {
100
97
  id,
@@ -107,11 +104,11 @@ var Container = ({
107
104
  };
108
105
 
109
106
  // src/Containers.tsx
110
- var Containers = React2.memo(function Containers2({
107
+ var Containers = React6.memo(function Containers2({
111
108
  horizontal,
112
109
  recycleItems,
113
110
  ItemSeparatorComponent,
114
- updateItemLength,
111
+ updateItemSize,
115
112
  getRenderedItem
116
113
  }) {
117
114
  const ctx = useStateContext();
@@ -119,7 +116,7 @@ var Containers = React2.memo(function Containers2({
119
116
  const containers = [];
120
117
  for (let i = 0; i < numContainers; i++) {
121
118
  containers.push(
122
- /* @__PURE__ */ React2.createElement(
119
+ /* @__PURE__ */ React6.createElement(
123
120
  Container,
124
121
  {
125
122
  id: i,
@@ -127,20 +124,20 @@ var Containers = React2.memo(function Containers2({
127
124
  recycleItems,
128
125
  horizontal,
129
126
  getRenderedItem,
130
- onLayout: updateItemLength,
127
+ onLayout: updateItemSize,
131
128
  ItemSeparatorComponent
132
129
  }
133
130
  )
134
131
  );
135
132
  }
136
- return /* @__PURE__ */ React2.createElement(
133
+ return /* @__PURE__ */ React6.createElement(
137
134
  $View,
138
135
  {
139
136
  $key: "totalLength",
140
137
  $style: () => horizontal ? {
141
- width: peek$("totalLength", ctx)
138
+ width: peek$(ctx, "totalLength")
142
139
  } : {
143
- height: peek$("totalLength", ctx)
140
+ height: peek$(ctx, "totalLength")
144
141
  }
145
142
  },
146
143
  containers
@@ -149,15 +146,15 @@ var Containers = React2.memo(function Containers2({
149
146
 
150
147
  // src/ListComponent.tsx
151
148
  var getComponent = (Component) => {
152
- if (React2.isValidElement(Component)) {
149
+ if (React6.isValidElement(Component)) {
153
150
  return Component;
154
151
  }
155
152
  if (Component) {
156
- return /* @__PURE__ */ React2.createElement(Component, null);
153
+ return /* @__PURE__ */ React6.createElement(Component, null);
157
154
  }
158
155
  return null;
159
156
  };
160
- var ListComponent = React2.memo(function ListComponent2({
157
+ var ListComponent = React6.memo(function ListComponent2({
161
158
  style,
162
159
  contentContainerStyle,
163
160
  horizontal,
@@ -172,12 +169,12 @@ var ListComponent = React2.memo(function ListComponent2({
172
169
  ListFooterComponent,
173
170
  ListFooterComponentStyle,
174
171
  getRenderedItem,
175
- updateItemLength,
172
+ updateItemSize,
176
173
  refScroller,
177
174
  ...rest
178
175
  }) {
179
176
  const ctx = useStateContext();
180
- return /* @__PURE__ */ React2.createElement(
177
+ return /* @__PURE__ */ React6.createElement(
181
178
  ScrollView,
182
179
  {
183
180
  ...rest,
@@ -190,24 +187,23 @@ var ListComponent = React2.memo(function ListComponent2({
190
187
  ],
191
188
  onScroll: handleScroll,
192
189
  onLayout,
193
- scrollEventThrottle: 32,
194
190
  horizontal,
195
191
  contentOffset: initialContentOffset ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
196
192
  ref: refScroller
197
193
  },
198
- alignItemsAtEnd && /* @__PURE__ */ React2.createElement($View, { $key: "paddingTop", $style: () => ({ height: peek$("paddingTop", ctx) }) }),
199
- ListHeaderComponent && /* @__PURE__ */ React2.createElement(View, { style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
200
- /* @__PURE__ */ React2.createElement(
194
+ alignItemsAtEnd && /* @__PURE__ */ React6.createElement($View, { $key: "paddingTop", $style: () => ({ height: peek$(ctx, "paddingTop") }) }),
195
+ ListHeaderComponent && /* @__PURE__ */ React6.createElement(View, { style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
196
+ /* @__PURE__ */ React6.createElement(
201
197
  Containers,
202
198
  {
203
199
  horizontal,
204
200
  recycleItems,
205
201
  getRenderedItem,
206
202
  ItemSeparatorComponent: ItemSeparatorComponent && getComponent(ItemSeparatorComponent),
207
- updateItemLength
203
+ updateItemSize
208
204
  }
209
205
  ),
210
- ListFooterComponent && /* @__PURE__ */ React2.createElement(View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
206
+ ListFooterComponent && /* @__PURE__ */ React6.createElement(View, { style: ListFooterComponentStyle }, getComponent(ListFooterComponent))
211
207
  );
212
208
  });
213
209
 
@@ -215,10 +211,11 @@ var ListComponent = React2.memo(function ListComponent2({
215
211
  var DEFAULT_SCROLL_BUFFER = 0;
216
212
  var POSITION_OUT_OF_VIEW = -1e4;
217
213
  var LegendList = forwardRef(function LegendList2(props, forwardedRef) {
218
- return /* @__PURE__ */ React2.createElement(StateProvider, null, /* @__PURE__ */ React2.createElement(LegendListInner, { ...props, ref: forwardedRef }));
214
+ return /* @__PURE__ */ React6.createElement(StateProvider, null, /* @__PURE__ */ React6.createElement(LegendListInner, { ...props, ref: forwardedRef }));
219
215
  });
220
216
  var LegendListInner = forwardRef(
221
217
  function LegendListInner2(props, forwardedRef) {
218
+ var _a, _b;
222
219
  const {
223
220
  data,
224
221
  initialScrollIndex,
@@ -226,7 +223,7 @@ var LegendListInner = forwardRef(
226
223
  horizontal,
227
224
  style: styleProp,
228
225
  contentContainerStyle: contentContainerStyleProp,
229
- initialContainers,
226
+ initialNumContainers,
230
227
  drawDistance,
231
228
  recycleItems = true,
232
229
  onEndReachedThreshold = 0.5,
@@ -236,7 +233,8 @@ var LegendListInner = forwardRef(
236
233
  onScroll: onScrollProp,
237
234
  keyExtractor,
238
235
  renderItem,
239
- estimatedItemLength,
236
+ estimatedItemSize,
237
+ getEstimatedItemSize,
240
238
  onEndReached,
241
239
  onViewableRangeChanged,
242
240
  ...rest
@@ -254,20 +252,39 @@ var LegendListInner = forwardRef(
254
252
  );
255
253
  const refState = useRef();
256
254
  const getId = (index) => {
257
- var _a;
258
- const data2 = (_a = refState.current) == null ? void 0 : _a.data;
255
+ var _a2;
256
+ const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
259
257
  if (!data2) {
260
258
  return "";
261
259
  }
262
260
  const ret = index < data2.length ? keyExtractor ? keyExtractor(data2[index], index) : index : null;
263
261
  return ret + "";
264
262
  };
263
+ const getItemLength = (index, data2) => {
264
+ return getEstimatedItemSize ? getEstimatedItemSize(index, data2) : estimatedItemSize;
265
+ };
266
+ const calculateInitialOffset = () => {
267
+ if (initialScrollIndex) {
268
+ if (getEstimatedItemSize) {
269
+ let offset = 0;
270
+ for (let i = 0; i < initialScrollIndex; i++) {
271
+ offset += getEstimatedItemSize(i, data[i]);
272
+ }
273
+ return offset;
274
+ } else if (estimatedItemSize) {
275
+ return initialScrollIndex * estimatedItemSize;
276
+ }
277
+ }
278
+ return void 0;
279
+ };
280
+ const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : useMemo(calculateInitialOffset, [initialScrollIndex, estimatedItemSize]);
265
281
  if (!refState.current) {
266
282
  refState.current = {
267
283
  lengths: /* @__PURE__ */ new Map(),
268
284
  positions: /* @__PURE__ */ new Map(),
269
285
  pendingAdjust: 0,
270
- animFrame: null,
286
+ animFrameScroll: null,
287
+ animFrameLayout: null,
271
288
  isStartReached: false,
272
289
  isEndReached: false,
273
290
  isAtBottom: false,
@@ -279,35 +296,36 @@ var LegendListInner = forwardRef(
279
296
  startNoBuffer: 0,
280
297
  endBuffered: 0,
281
298
  endNoBuffer: 0,
282
- scroll: 0,
283
- topPad: 0
299
+ scroll: initialContentOffset || 0
284
300
  };
285
301
  refState.current.idsInFirstRender = new Set(data.map((_, i) => getId(i)));
286
302
  }
287
303
  refState.current.data = data;
288
- set$(`numItems`, ctx, data.length);
289
- const initialContentOffset = initialScrollOffset != null ? initialScrollOffset : initialScrollIndex ? initialScrollIndex * estimatedItemLength(initialScrollIndex) : void 0;
290
- const setTotalLength = (length) => {
291
- set$(`totalLength`, ctx, length);
304
+ set$(ctx, `numItems`, data.length);
305
+ set$(ctx, `stylePaddingTop`, (_b = (_a = styleFlattened == null ? void 0 : styleFlattened.paddingTop) != null ? _a : contentContainerStyleFlattened == null ? void 0 : contentContainerStyleFlattened.paddingTop) != null ? _b : 0);
306
+ const addTotalSize = (add) => {
307
+ const length = (peek$(ctx, `totalLength`) || 0) + add;
308
+ set$(ctx, `totalLength`, length);
292
309
  const screenLength = refState.current.scrollLength;
293
310
  if (alignItemsAtEnd) {
294
- const listPaddingTop = ((style == null ? void 0 : style.paddingTop) || 0) + ((contentContainerStyle == null ? void 0 : contentContainerStyle.paddingTop) || 0);
295
- set$(`paddingTop`, ctx, Math.max(0, screenLength - length - listPaddingTop));
311
+ const listPaddingTop = peek$(ctx, `stylePaddingTop`);
312
+ set$(ctx, `paddingTop`, Math.max(0, screenLength - length - listPaddingTop));
296
313
  }
297
314
  };
298
315
  const allocateContainers = useCallback(() => {
299
316
  const scrollLength = refState.current.scrollLength;
300
- const numContainers = initialContainers || Math.ceil((scrollLength + scrollBuffer * 2) / estimatedItemLength(0)) + 4;
317
+ const averageItemSize = estimatedItemSize != null ? estimatedItemSize : getEstimatedItemSize == null ? void 0 : getEstimatedItemSize(0, data[0]);
318
+ const numContainers = initialNumContainers || Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize) + 4;
301
319
  for (let i = 0; i < numContainers; i++) {
302
- set$(`containerIndex${i}`, ctx, -1);
303
- set$(`containerPosition${i}`, ctx, POSITION_OUT_OF_VIEW);
320
+ set$(ctx, `containerIndex${i}`, -1);
321
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
304
322
  }
305
- set$(`numContainers`, ctx, numContainers);
323
+ set$(ctx, `numContainers`, numContainers);
306
324
  }, []);
307
325
  const getRenderedItem = useCallback(
308
326
  (index) => {
309
- var _a;
310
- const data2 = (_a = refState.current) == null ? void 0 : _a.data;
327
+ var _a2;
328
+ const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
311
329
  if (!data2) {
312
330
  return null;
313
331
  }
@@ -320,146 +338,164 @@ var LegendListInner = forwardRef(
320
338
  [renderItem]
321
339
  );
322
340
  const calculateItemsInView = useCallback(() => {
323
- var _a, _b;
324
- const {
325
- data: data2,
326
- scrollLength,
327
- scroll: scrollState,
328
- topPad,
329
- startNoBuffer: startNoBufferState,
330
- startBuffered: startBufferedState,
331
- endNoBuffer: endNoBufferState,
332
- endBuffered: endBufferedState
333
- } = refState.current;
334
- if (!data2) {
335
- return;
336
- }
337
- const scroll = scrollState - topPad;
338
- const { lengths, positions } = refState.current;
339
- let top = 0;
340
- let startNoBuffer = null;
341
- let startBuffered = null;
342
- let endNoBuffer = null;
343
- let endBuffered = null;
344
- for (let i = 0; i < data2.length; i++) {
345
- const id = getId(i);
346
- const length = (_a = lengths.get(id)) != null ? _a : estimatedItemLength(i);
347
- if (positions.get(id) !== top) {
348
- positions.set(id, top);
349
- }
350
- if (startNoBuffer === null && top + length > scroll) {
351
- startNoBuffer = i;
341
+ unstable_batchedUpdates(() => {
342
+ var _a2, _b2, _c;
343
+ const {
344
+ data: data2,
345
+ scrollLength,
346
+ scroll: scrollState,
347
+ startNoBuffer: startNoBufferState,
348
+ startBuffered: startBufferedState,
349
+ endNoBuffer: endNoBufferState,
350
+ endBuffered: endBufferedState
351
+ } = refState.current;
352
+ if (!data2) {
353
+ return;
352
354
  }
353
- if (startBuffered === null && top + length > scroll - scrollBuffer) {
354
- startBuffered = i;
355
+ const topPad = (peek$(ctx, `stylePaddingTop`) || 0) + (peek$(ctx, `headerSize`) || 0);
356
+ const scroll = scrollState - topPad;
357
+ const { lengths, positions } = refState.current;
358
+ let startNoBuffer = null;
359
+ let startBuffered = null;
360
+ let endNoBuffer = null;
361
+ let endBuffered = null;
362
+ let loopStart = startBufferedState || 0;
363
+ if (startBufferedState) {
364
+ for (let i = startBufferedState; i >= 0; i--) {
365
+ const id = getId(i);
366
+ const top2 = positions.get(id);
367
+ if (top2 !== void 0) {
368
+ const length = (_a2 = lengths.get(id)) != null ? _a2 : getItemLength(i, data2[i]);
369
+ const bottom = top2 + length;
370
+ if (bottom > scroll - scrollBuffer) {
371
+ loopStart = i;
372
+ } else {
373
+ break;
374
+ }
375
+ }
376
+ }
355
377
  }
356
- if (startNoBuffer !== null) {
357
- if (top <= scroll + scrollLength) {
358
- endNoBuffer = i;
378
+ let top = loopStart > 0 ? positions.get(getId(loopStart)) : 0;
379
+ for (let i = loopStart; i < data2.length; i++) {
380
+ const id = getId(i);
381
+ const length = (_b2 = lengths.get(id)) != null ? _b2 : getItemLength(i, data2[i]);
382
+ if (positions.get(id) !== top) {
383
+ positions.set(id, top);
359
384
  }
360
- if (top <= scroll + scrollLength + scrollBuffer) {
361
- endBuffered = i;
362
- } else {
363
- break;
385
+ if (startNoBuffer === null && top + length > scroll) {
386
+ startNoBuffer = i;
364
387
  }
365
- }
366
- top += length;
367
- }
368
- Object.assign(refState.current, {
369
- startBuffered,
370
- startNoBuffer,
371
- endBuffered,
372
- endNoBuffer
373
- });
374
- if (startBuffered !== null && endBuffered !== null) {
375
- const prevNumContainers = ctx.values.get("numContainers");
376
- let numContainers = prevNumContainers;
377
- for (let i = startBuffered; i <= endBuffered; i++) {
378
- let isContained = false;
379
- for (let j = 0; j < numContainers; j++) {
380
- const index = peek$(`containerIndex${j}`, ctx);
381
- if (index === i) {
382
- isContained = true;
388
+ if (startBuffered === null && top + length > scroll - scrollBuffer) {
389
+ startBuffered = i;
390
+ }
391
+ if (startNoBuffer !== null) {
392
+ if (top <= scroll + scrollLength) {
393
+ endNoBuffer = i;
394
+ }
395
+ if (top <= scroll + scrollLength + scrollBuffer) {
396
+ endBuffered = i;
397
+ } else {
383
398
  break;
384
399
  }
385
400
  }
386
- if (!isContained) {
387
- let didRecycle = false;
388
- for (let u = 0; u < numContainers; u++) {
389
- const index = peek$(`containerIndex${u}`, ctx);
390
- if (index < startBuffered || index > endBuffered) {
391
- set$(`containerIndex${u}`, ctx, i);
392
- didRecycle = true;
401
+ top += length;
402
+ }
403
+ Object.assign(refState.current, {
404
+ startBuffered,
405
+ startNoBuffer,
406
+ endBuffered,
407
+ endNoBuffer
408
+ });
409
+ if (startBuffered !== null && endBuffered !== null) {
410
+ const prevNumContainers = ctx.values.get("numContainers");
411
+ let numContainers = prevNumContainers;
412
+ for (let i = startBuffered; i <= endBuffered; i++) {
413
+ let isContained = false;
414
+ for (let j = 0; j < numContainers; j++) {
415
+ const index = peek$(ctx, `containerIndex${j}`);
416
+ if (index === i) {
417
+ isContained = true;
393
418
  break;
394
419
  }
395
420
  }
396
- if (!didRecycle) {
397
- if (__DEV__) {
398
- console.warn(
399
- "[legend-list] No container to recycle, consider increasing initialContainers or estimatedItemLength",
400
- i
401
- );
421
+ if (!isContained) {
422
+ let didRecycle = false;
423
+ for (let u = 0; u < numContainers; u++) {
424
+ const index = peek$(ctx, `containerIndex${u}`);
425
+ if (index < startBuffered || index > endBuffered) {
426
+ set$(ctx, `containerIndex${u}`, i);
427
+ didRecycle = true;
428
+ break;
429
+ }
430
+ }
431
+ if (!didRecycle) {
432
+ if (__DEV__) {
433
+ console.warn(
434
+ "[legend-list] No container to recycle, consider increasing initialContainers or estimatedItemSize",
435
+ i
436
+ );
437
+ }
438
+ const id = numContainers;
439
+ numContainers++;
440
+ set$(ctx, `containerIndex${id}`, i);
441
+ set$(ctx, `containerPosition${id}`, POSITION_OUT_OF_VIEW);
402
442
  }
403
- const id = numContainers;
404
- numContainers++;
405
- set$(`containerIndex${id}`, ctx, i);
406
- set$(`containerPosition${id}`, ctx, POSITION_OUT_OF_VIEW);
407
443
  }
408
444
  }
409
- }
410
- if (numContainers !== prevNumContainers) {
411
- set$(`numContainers`, ctx, numContainers);
412
- }
413
- for (let i = 0; i < numContainers; i++) {
414
- const itemIndex = peek$(`containerIndex${i}`, ctx);
415
- const item = data2[itemIndex];
416
- if (item) {
417
- const id = getId(itemIndex);
418
- if (itemIndex < startBuffered || itemIndex > endBuffered) {
419
- set$(`containerPosition${i}`, ctx, POSITION_OUT_OF_VIEW);
420
- } else {
421
- const pos = (_b = positions.get(id)) != null ? _b : -1;
422
- const prevPos = peek$(`containerPosition${i}`, ctx);
423
- if (pos >= 0 && pos !== prevPos) {
424
- set$(`containerPosition${i}`, ctx, pos);
445
+ if (numContainers !== prevNumContainers) {
446
+ set$(ctx, `numContainers`, numContainers);
447
+ }
448
+ for (let i = 0; i < numContainers; i++) {
449
+ const itemIndex = peek$(ctx, `containerIndex${i}`);
450
+ const item = data2[itemIndex];
451
+ if (item) {
452
+ const id = getId(itemIndex);
453
+ if (itemIndex < startBuffered || itemIndex > endBuffered) {
454
+ set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
455
+ } else {
456
+ const pos = (_c = positions.get(id)) != null ? _c : -1;
457
+ const prevPos = peek$(ctx, `containerPosition${i}`);
458
+ if (pos >= 0 && pos !== prevPos) {
459
+ set$(ctx, `containerPosition${i}`, pos);
460
+ }
425
461
  }
426
462
  }
427
463
  }
428
- }
429
- if (onViewableRangeChanged) {
430
- if (startNoBuffer !== startNoBufferState || startBuffered !== startBufferedState || endNoBuffer !== endNoBufferState || endBuffered !== endBufferedState) {
431
- onViewableRangeChanged({
432
- start: startNoBuffer,
433
- startBuffered,
434
- end: endNoBuffer,
435
- endBuffered,
436
- items: data2.slice(startNoBuffer, endNoBuffer + 1)
437
- });
464
+ if (onViewableRangeChanged) {
465
+ if (startNoBuffer !== startNoBufferState || startBuffered !== startBufferedState || endNoBuffer !== endNoBufferState || endBuffered !== endBufferedState) {
466
+ onViewableRangeChanged({
467
+ start: startNoBuffer,
468
+ startBuffered,
469
+ end: endNoBuffer,
470
+ endBuffered,
471
+ items: data2.slice(startNoBuffer, endNoBuffer + 1)
472
+ });
473
+ }
438
474
  }
439
475
  }
440
- }
476
+ });
441
477
  }, [data]);
442
478
  useMemo(() => {
443
- var _a, _b;
479
+ var _a2, _b2;
444
480
  allocateContainers();
445
481
  calculateItemsInView();
446
- const lengths = (_a = refState.current) == null ? void 0 : _a.lengths;
482
+ const lengths = (_a2 = refState.current) == null ? void 0 : _a2.lengths;
447
483
  let totalLength = 0;
448
484
  for (let i = 0; i < data.length; i++) {
449
485
  const id = getId(i);
450
- totalLength += (_b = lengths.get(id)) != null ? _b : estimatedItemLength(i);
486
+ totalLength += (_b2 = lengths.get(id)) != null ? _b2 : getItemLength(i, data[i]);
451
487
  }
452
- setTotalLength(totalLength);
488
+ addTotalSize(totalLength);
453
489
  }, []);
454
490
  const checkAtBottom = () => {
455
- var _a;
491
+ var _a2;
456
492
  const { scrollLength, scroll } = refState.current;
457
- const totalLength = peek$("totalLength", ctx);
493
+ const totalLength = peek$(ctx, "totalLength");
458
494
  const distanceFromEnd = totalLength - scroll - scrollLength;
459
495
  if (refState.current) {
460
496
  refState.current.isAtBottom = distanceFromEnd < scrollLength * maintainScrollAtEndThreshold;
461
497
  }
462
- if (onEndReached && !((_a = refState.current) == null ? void 0 : _a.isEndReached)) {
498
+ if (onEndReached && !((_a2 = refState.current) == null ? void 0 : _a2.isEndReached)) {
463
499
  if (distanceFromEnd < onEndReachedThreshold * scrollLength) {
464
500
  if (refState.current) {
465
501
  refState.current.isEndReached = true;
@@ -475,30 +511,33 @@ var LegendListInner = forwardRef(
475
511
  calculateItemsInView();
476
512
  checkAtBottom();
477
513
  }, [data]);
478
- const updateItemLength = useCallback((index, length) => {
479
- var _a, _b, _c, _d, _e;
480
- const data2 = (_a = refState.current) == null ? void 0 : _a.data;
514
+ const updateItemSize = useCallback((index, length) => {
515
+ var _a2, _b2, _c, _d;
516
+ const data2 = (_a2 = refState.current) == null ? void 0 : _a2.data;
481
517
  if (!data2) {
482
518
  return;
483
519
  }
484
- const lengths = (_b = refState.current) == null ? void 0 : _b.lengths;
520
+ const lengths = (_b2 = refState.current) == null ? void 0 : _b2.lengths;
485
521
  const id = getId(index);
486
522
  const wasInFirstRender = (_c = refState.current) == null ? void 0 : _c.idsInFirstRender.has(id);
487
- const prevLength = lengths.get(id) || (wasInFirstRender ? estimatedItemLength(index) : 0);
523
+ const prevLength = lengths.get(id) || (wasInFirstRender ? getItemLength(index, data2[index]) : 0);
488
524
  if (!prevLength || prevLength !== length) {
489
525
  lengths.set(id, length);
490
- const totalLength = peek$("totalLength", ctx);
491
- setTotalLength(totalLength + (length - prevLength));
526
+ addTotalSize(length - prevLength);
492
527
  if (((_d = refState.current) == null ? void 0 : _d.isAtBottom) && maintainScrollAtEnd) {
493
528
  requestAnimationFrame(() => {
494
- var _a2;
495
- (_a2 = refScroller.current) == null ? void 0 : _a2.scrollToEnd({
529
+ var _a3;
530
+ (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
496
531
  animated: true
497
532
  });
498
533
  });
499
534
  }
500
- if (!((_e = refState.current) == null ? void 0 : _e.animFrame)) {
501
- calculateItemsInView();
535
+ const state = refState.current;
536
+ if (!state.animFrameScroll && !state.animFrameLayout) {
537
+ state.animFrameLayout = requestAnimationFrame(() => {
538
+ state.animFrameLayout = null;
539
+ calculateItemsInView();
540
+ });
502
541
  }
503
542
  }
504
543
  }, []);
@@ -506,7 +545,7 @@ var LegendListInner = forwardRef(
506
545
  calculateItemsInView();
507
546
  checkAtBottom();
508
547
  if (refState.current) {
509
- refState.current.animFrame = null;
548
+ refState.current.animFrameScroll = null;
510
549
  }
511
550
  }, []);
512
551
  const onLayout = useCallback((event) => {
@@ -515,11 +554,15 @@ var LegendListInner = forwardRef(
515
554
  }, []);
516
555
  const handleScroll = useCallback(
517
556
  (event, fromSelf) => {
557
+ var _a2, _b2, _c;
558
+ if (((_b2 = (_a2 = event.nativeEvent) == null ? void 0 : _a2.contentSize) == null ? void 0 : _b2.height) === 0 && ((_c = event.nativeEvent.contentSize) == null ? void 0 : _c.width) === 0) {
559
+ return;
560
+ }
518
561
  refState.current.hasScrolled = true;
519
562
  const newScroll = event.nativeEvent.contentOffset[horizontal ? "x" : "y"];
520
563
  refState.current.scroll = newScroll;
521
- if (refState.current && !refState.current.animFrame) {
522
- refState.current.animFrame = requestAnimationFrame(handleScrollDebounced);
564
+ if (refState.current && !refState.current.animFrameScroll) {
565
+ refState.current.animFrameScroll = requestAnimationFrame(handleScrollDebounced);
523
566
  }
524
567
  if (!fromSelf) {
525
568
  onScrollProp == null ? void 0 : onScrollProp(event);
@@ -527,20 +570,7 @@ var LegendListInner = forwardRef(
527
570
  },
528
571
  []
529
572
  );
530
- useEffect(() => {
531
- if (initialContentOffset) {
532
- const offset = horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset };
533
- handleScroll(
534
- {
535
- nativeEvent: { contentOffset: offset }
536
- },
537
- /*fromSelf*/
538
- true
539
- );
540
- calculateItemsInView();
541
- }
542
- }, []);
543
- return /* @__PURE__ */ React2.createElement(
573
+ return /* @__PURE__ */ React6.createElement(
544
574
  ListComponent,
545
575
  {
546
576
  ...rest,
@@ -550,7 +580,7 @@ var LegendListInner = forwardRef(
550
580
  refScroller,
551
581
  initialContentOffset,
552
582
  getRenderedItem,
553
- updateItemLength,
583
+ updateItemSize,
554
584
  handleScroll,
555
585
  onLayout,
556
586
  recycleItems,