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