@legendapp/list 2.0.0-beta.3 → 2.0.0-beta.5

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
@@ -693,30 +693,33 @@ function useThrottleDebounce(mode) {
693
693
  timeoutRef.current = null;
694
694
  }
695
695
  };
696
- const execute = React3.useCallback((callback, delay, ...args) => {
697
- {
698
- const now = Date.now();
699
- lastArgsRef.current = args;
700
- if (now - lastCallTimeRef.current >= delay) {
701
- lastCallTimeRef.current = now;
702
- callback(...args);
703
- clearTimeoutRef();
704
- } else {
705
- clearTimeoutRef();
706
- timeoutRef.current = setTimeout(
707
- () => {
708
- if (lastArgsRef.current) {
709
- lastCallTimeRef.current = Date.now();
710
- callback(...lastArgsRef.current);
711
- timeoutRef.current = null;
712
- lastArgsRef.current = null;
713
- }
714
- },
715
- delay - (now - lastCallTimeRef.current)
716
- );
696
+ const execute = React3.useCallback(
697
+ (callback, delay, ...args) => {
698
+ {
699
+ const now = Date.now();
700
+ lastArgsRef.current = args;
701
+ if (now - lastCallTimeRef.current >= delay) {
702
+ lastCallTimeRef.current = now;
703
+ callback(...args);
704
+ clearTimeoutRef();
705
+ } else {
706
+ clearTimeoutRef();
707
+ timeoutRef.current = setTimeout(
708
+ () => {
709
+ if (lastArgsRef.current) {
710
+ lastCallTimeRef.current = Date.now();
711
+ callback(...lastArgsRef.current);
712
+ timeoutRef.current = null;
713
+ lastArgsRef.current = null;
714
+ }
715
+ },
716
+ delay - (now - lastCallTimeRef.current)
717
+ );
718
+ }
717
719
  }
718
- }
719
- }, [mode]);
720
+ },
721
+ [mode]
722
+ );
720
723
  return execute;
721
724
  }
722
725
 
@@ -912,7 +915,7 @@ function calculateOffsetForIndex(ctx, state, index) {
912
915
  }
913
916
 
914
917
  // src/utils/getItemSize.ts
915
- function getItemSize(state, key, index, data, useAverageSize, defaultAverageSize, preferRenderedCache) {
918
+ function getItemSize(state, key, index, data, useAverageSize) {
916
919
  var _a, _b;
917
920
  const {
918
921
  sizesKnown,
@@ -933,22 +936,17 @@ function getItemSize(state, key, index, data, useAverageSize, defaultAverageSize
933
936
  sizesKnown.set(key, size);
934
937
  }
935
938
  }
936
- const renderedSize = sizes.get(key);
937
- if (size === void 0 && preferRenderedCache && renderedSize !== void 0) {
938
- return renderedSize;
939
- }
940
- if (size === void 0 && useAverageSize && !scrollingTo) {
941
- if (itemType === "") {
942
- size = defaultAverageSize;
943
- } else {
944
- const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
945
- if (averageSizeForType !== void 0) {
946
- size = roundSize(averageSizeForType);
947
- }
939
+ if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
940
+ const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
941
+ if (averageSizeForType !== void 0) {
942
+ size = roundSize(averageSizeForType);
948
943
  }
949
944
  }
950
- if (size === void 0 && renderedSize !== void 0) {
951
- return renderedSize;
945
+ if (size === void 0) {
946
+ size = sizes.get(key);
947
+ if (size !== void 0) {
948
+ return size;
949
+ }
952
950
  }
953
951
  if (size === void 0) {
954
952
  size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
@@ -1175,44 +1173,6 @@ function addTotalSize(ctx, state, key, add) {
1175
1173
  }
1176
1174
  }
1177
1175
 
1178
- // src/utils/getScrollVelocity.ts
1179
- var getScrollVelocity = (state) => {
1180
- const { scrollHistory } = state;
1181
- let velocity = 0;
1182
- if (scrollHistory.length >= 1) {
1183
- const newest = scrollHistory[scrollHistory.length - 1];
1184
- let oldest;
1185
- let start = 0;
1186
- const now = Date.now();
1187
- for (let i = 0; i < scrollHistory.length - 1; i++) {
1188
- const entry = scrollHistory[i];
1189
- const nextEntry = scrollHistory[i + 1];
1190
- if (i > 0) {
1191
- const prevEntry = scrollHistory[i - 1];
1192
- const prevDirection = entry.scroll - prevEntry.scroll;
1193
- const currentDirection = nextEntry.scroll - entry.scroll;
1194
- if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1195
- start = i;
1196
- break;
1197
- }
1198
- }
1199
- }
1200
- for (let i = start; i < scrollHistory.length - 1; i++) {
1201
- const entry = scrollHistory[i];
1202
- if (now - entry.time <= 1e3) {
1203
- oldest = entry;
1204
- break;
1205
- }
1206
- }
1207
- if (oldest && oldest !== newest) {
1208
- const scrollDiff = newest.scroll - oldest.scroll;
1209
- const timeDiff = newest.time - oldest.time;
1210
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1211
- }
1212
- }
1213
- return velocity;
1214
- };
1215
-
1216
1176
  // src/utils/updateSnapToOffsets.ts
1217
1177
  function updateSnapToOffsets(ctx, state) {
1218
1178
  const {
@@ -1229,14 +1189,12 @@ function updateSnapToOffsets(ctx, state) {
1229
1189
  }
1230
1190
 
1231
1191
  // src/core/updateAllPositions.ts
1232
- function updateAllPositions(ctx, state, dataChanged) {
1233
- var _a, _b, _c, _d, _e;
1192
+ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1193
+ var _a, _b, _c, _d, _e, _f;
1234
1194
  const {
1235
- averageSizes,
1236
1195
  columns,
1237
1196
  indexByKey,
1238
1197
  positions,
1239
- firstFullyOnScreenIndex,
1240
1198
  idCache,
1241
1199
  sizesKnown,
1242
1200
  props: { getEstimatedItemSize, snapToIndices, enableAverages }
@@ -1244,69 +1202,29 @@ function updateAllPositions(ctx, state, dataChanged) {
1244
1202
  const data = state.props.data;
1245
1203
  const numColumns = peek$(ctx, "numColumns");
1246
1204
  const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1247
- const scrollVelocity = getScrollVelocity(state);
1248
1205
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1249
- const itemType = "";
1250
- let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
1251
- if (averageSize !== void 0) {
1252
- averageSize = roundSize(averageSize);
1253
- }
1254
- const shouldUseBackwards = !dataChanged && scrollVelocity < 0 && firstFullyOnScreenIndex > 5 && firstFullyOnScreenIndex < data.length;
1255
- if (shouldUseBackwards && firstFullyOnScreenIndex !== void 0) {
1256
- const anchorId = getId(state, firstFullyOnScreenIndex);
1257
- const anchorPosition = positions.get(anchorId);
1258
- if (anchorPosition !== void 0) {
1259
- let currentRowTop2 = anchorPosition;
1260
- let maxSizeInRow2 = 0;
1261
- let bailout = false;
1262
- for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
1263
- const id = (_b = idCache.get(i)) != null ? _b : getId(state, i);
1264
- const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(
1265
- state,
1266
- id,
1267
- i,
1268
- data[i],
1269
- useAverageSize,
1270
- averageSize,
1271
- /*preferRenderedCache*/
1272
- !!dataChanged
1273
- );
1274
- const itemColumn = columns.get(id);
1275
- maxSizeInRow2 = Math.max(maxSizeInRow2, size);
1276
- if (itemColumn === 1) {
1277
- currentRowTop2 -= maxSizeInRow2;
1278
- maxSizeInRow2 = 0;
1279
- }
1280
- if (currentRowTop2 < -2e3) {
1281
- bailout = true;
1282
- break;
1283
- }
1284
- positions.set(id, currentRowTop2);
1285
- }
1286
- if (!bailout) {
1287
- updateTotalSize(ctx, state);
1288
- return;
1289
- }
1290
- }
1291
- }
1292
1206
  let currentRowTop = 0;
1293
1207
  let column = 1;
1294
1208
  let maxSizeInRow = 0;
1295
1209
  const hasColumns = numColumns > 1;
1210
+ if (startIndex > 0) {
1211
+ const prevIndex = startIndex - 1;
1212
+ const prevId = (_a = idCache.get(prevIndex)) != null ? _a : getId(state, prevIndex);
1213
+ const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1214
+ if (hasColumns) {
1215
+ const prevColumn = (_c = columns.get(prevId)) != null ? _c : 1;
1216
+ currentRowTop = prevPosition;
1217
+ column = prevColumn % numColumns + 1;
1218
+ } else {
1219
+ const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(state, prevId, prevIndex, data[prevIndex], useAverageSize);
1220
+ currentRowTop = prevPosition + prevSize;
1221
+ }
1222
+ }
1296
1223
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1297
1224
  const dataLength = data.length;
1298
- for (let i = 0; i < dataLength; i++) {
1299
- const id = (_d = idCache.get(i)) != null ? _d : getId(state, i);
1300
- const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(
1301
- state,
1302
- id,
1303
- i,
1304
- data[i],
1305
- useAverageSize,
1306
- averageSize,
1307
- /*preferRenderedCache*/
1308
- !!dataChanged
1309
- );
1225
+ for (let i = startIndex; i < dataLength; i++) {
1226
+ const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1227
+ const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(state, id, i, data[i], useAverageSize);
1310
1228
  if (__DEV__ && needsIndexByKey) {
1311
1229
  if (indexByKeyForChecking.has(id)) {
1312
1230
  console.error(
@@ -1669,6 +1587,44 @@ function comparatorByDistance(a, b) {
1669
1587
  return b.distance - a.distance;
1670
1588
  }
1671
1589
 
1590
+ // src/utils/getScrollVelocity.ts
1591
+ var getScrollVelocity = (state) => {
1592
+ const { scrollHistory } = state;
1593
+ let velocity = 0;
1594
+ if (scrollHistory.length >= 1) {
1595
+ const newest = scrollHistory[scrollHistory.length - 1];
1596
+ let oldest;
1597
+ let start = 0;
1598
+ const now = Date.now();
1599
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
1600
+ const entry = scrollHistory[i];
1601
+ const nextEntry = scrollHistory[i + 1];
1602
+ if (i > 0) {
1603
+ const prevEntry = scrollHistory[i - 1];
1604
+ const prevDirection = entry.scroll - prevEntry.scroll;
1605
+ const currentDirection = nextEntry.scroll - entry.scroll;
1606
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1607
+ start = i;
1608
+ break;
1609
+ }
1610
+ }
1611
+ }
1612
+ for (let i = start; i < scrollHistory.length - 1; i++) {
1613
+ const entry = scrollHistory[i];
1614
+ if (now - entry.time <= 1e3) {
1615
+ oldest = entry;
1616
+ break;
1617
+ }
1618
+ }
1619
+ if (oldest && oldest !== newest) {
1620
+ const scrollDiff = newest.scroll - oldest.scroll;
1621
+ const timeDiff = newest.time - oldest.time;
1622
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1623
+ }
1624
+ }
1625
+ return velocity;
1626
+ };
1627
+
1672
1628
  // src/core/scrollToIndex.ts
1673
1629
  function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1674
1630
  if (index >= state.props.data.length) {
@@ -1880,7 +1836,11 @@ function calculateItemsInView(ctx, state, params = {}) {
1880
1836
  idCache.clear();
1881
1837
  positions.clear();
1882
1838
  }
1883
- updateAllPositions(ctx, state, dataChanged);
1839
+ const startIndex = dataChanged ? 0 : minIndexSizeChanged != null ? minIndexSizeChanged : 0;
1840
+ updateAllPositions(ctx, state, dataChanged, startIndex);
1841
+ if (minIndexSizeChanged !== void 0) {
1842
+ state.minIndexSizeChanged = void 0;
1843
+ }
1884
1844
  checkMVCP == null ? void 0 : checkMVCP();
1885
1845
  }
1886
1846
  const scrollExtra = 0;
@@ -1927,10 +1887,6 @@ function calculateItemsInView(ctx, state, params = {}) {
1927
1887
  let endNoBuffer = null;
1928
1888
  let endBuffered = null;
1929
1889
  let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1930
- if (minIndexSizeChanged !== void 0) {
1931
- loopStart = Math.min(minIndexSizeChanged, loopStart);
1932
- state.minIndexSizeChanged = void 0;
1933
- }
1934
1890
  for (let i = loopStart; i >= 0; i--) {
1935
1891
  const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
1936
1892
  const top = positions.get(id);
@@ -2149,10 +2105,30 @@ function doInitialAllocateContainers(ctx, state) {
2149
2105
  var _a;
2150
2106
  const {
2151
2107
  scrollLength,
2152
- props: { data, getEstimatedItemSize, getItemType, scrollBuffer, numColumns, estimatedItemSize }
2108
+ props: {
2109
+ data,
2110
+ getEstimatedItemSize,
2111
+ getFixedItemSize,
2112
+ getItemType,
2113
+ scrollBuffer,
2114
+ numColumns,
2115
+ estimatedItemSize
2116
+ }
2153
2117
  } = state;
2154
- if (scrollLength > 0 && data.length > 0 && !peek$(ctx, "numContainers")) {
2155
- const averageItemSize = getEstimatedItemSize ? getEstimatedItemSize(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "") : estimatedItemSize;
2118
+ const hasContainers = peek$(ctx, "numContainers");
2119
+ if (scrollLength > 0 && data.length > 0 && !hasContainers) {
2120
+ let averageItemSize;
2121
+ const fn = getFixedItemSize || getEstimatedItemSize;
2122
+ if (fn) {
2123
+ let totalSize = 0;
2124
+ const num = Math.min(20, data.length);
2125
+ for (let i = 0; i < num; i++) {
2126
+ totalSize += fn(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "");
2127
+ }
2128
+ averageItemSize = totalSize / num;
2129
+ } else {
2130
+ averageItemSize = estimatedItemSize;
2131
+ }
2156
2132
  const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize * numColumns);
2157
2133
  for (let i = 0; i < numContainers; i++) {
2158
2134
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
@@ -2160,13 +2136,13 @@ function doInitialAllocateContainers(ctx, state) {
2160
2136
  }
2161
2137
  set$(ctx, "numContainers", numContainers);
2162
2138
  set$(ctx, "numContainersPooled", numContainers * state.props.initialContainerPoolRatio);
2163
- if (!IsNewArchitecture) {
2139
+ if (!IsNewArchitecture || state.lastLayout) {
2164
2140
  if (state.props.initialScroll) {
2165
2141
  requestAnimationFrame(() => {
2166
- calculateItemsInView(ctx, state);
2142
+ calculateItemsInView(ctx, state, { dataChanged: true });
2167
2143
  });
2168
2144
  } else {
2169
- calculateItemsInView(ctx, state);
2145
+ calculateItemsInView(ctx, state, { dataChanged: true });
2170
2146
  }
2171
2147
  }
2172
2148
  return true;
@@ -2238,35 +2214,37 @@ function handleLayout(ctx, state, layout, setCanRender) {
2238
2214
  const otherAxisSize = layout[state.props.horizontal ? "height" : "width"];
2239
2215
  const needsCalculate = !state.lastLayout || scrollLength > state.scrollLength || state.lastLayout.x !== layout.x || state.lastLayout.y !== layout.y;
2240
2216
  state.lastLayout = layout;
2241
- const didChange = scrollLength !== state.scrollLength;
2242
2217
  const prevOtherAxisSize = state.otherAxisSize;
2243
- state.scrollLength = scrollLength;
2244
- state.otherAxisSize = otherAxisSize;
2245
- state.lastBatchingAction = Date.now();
2246
- state.scrollForNextCalculateItemsInView = void 0;
2247
- doInitialAllocateContainers(ctx, state);
2248
- if (needsCalculate) {
2249
- calculateItemsInView(ctx, state, { doMVCP: true });
2250
- }
2251
- if (didChange || otherAxisSize !== prevOtherAxisSize) {
2252
- set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
2253
- }
2254
- if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
2255
- doMaintainScrollAtEnd(ctx, state, false);
2256
- }
2257
- updateAlignItemsPaddingTop(ctx, state);
2258
- checkAtBottom(ctx, state);
2259
- checkAtTop(state);
2260
- if (state) {
2261
- state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2262
- }
2263
- if (__DEV__ && scrollLength === 0) {
2264
- warnDevOnce(
2265
- "height0",
2266
- `List ${state.props.horizontal ? "width" : "height"} is 0. You may need to set a style or \`flex: \` for the list, because children are absolutely positioned.`
2267
- );
2218
+ const didChange = scrollLength !== state.scrollLength || otherAxisSize !== prevOtherAxisSize;
2219
+ if (didChange) {
2220
+ state.scrollLength = scrollLength;
2221
+ state.otherAxisSize = otherAxisSize;
2222
+ state.lastBatchingAction = Date.now();
2223
+ state.scrollForNextCalculateItemsInView = void 0;
2224
+ doInitialAllocateContainers(ctx, state);
2225
+ if (needsCalculate) {
2226
+ calculateItemsInView(ctx, state, { doMVCP: true });
2227
+ }
2228
+ if (didChange || otherAxisSize !== prevOtherAxisSize) {
2229
+ set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
2230
+ }
2231
+ if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
2232
+ doMaintainScrollAtEnd(ctx, state, false);
2233
+ }
2234
+ updateAlignItemsPaddingTop(ctx, state);
2235
+ checkAtBottom(ctx, state);
2236
+ checkAtTop(state);
2237
+ if (state) {
2238
+ state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2239
+ }
2240
+ if (__DEV__ && scrollLength === 0) {
2241
+ warnDevOnce(
2242
+ "height0",
2243
+ `List ${state.props.horizontal ? "width" : "height"} is 0. You may need to set a style or \`flex: \` for the list, because children are absolutely positioned.`
2244
+ );
2245
+ }
2246
+ setCanRender(true);
2268
2247
  }
2269
- setCanRender(true);
2270
2248
  }
2271
2249
 
2272
2250
  // src/core/onScroll.ts
@@ -2300,7 +2278,8 @@ function updateScroll(ctx, state, newScroll) {
2300
2278
  state.lastBatchingAction = Date.now();
2301
2279
  const currentTime = Date.now();
2302
2280
  if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
2303
- state.scrollHistory.push({ scroll: newScroll, time: currentTime });
2281
+ const adjust = state.scrollAdjustHandler.getAdjust();
2282
+ state.scrollHistory.push({ scroll: newScroll - adjust, time: currentTime });
2304
2283
  }
2305
2284
  if (state.scrollHistory.length > 5) {
2306
2285
  state.scrollHistory.shift();
@@ -2336,13 +2315,19 @@ var ScrollAdjustHandler = class {
2336
2315
  setMounted() {
2337
2316
  this.mounted = true;
2338
2317
  }
2318
+ getAdjust() {
2319
+ return this.appliedAdjust;
2320
+ }
2339
2321
  };
2340
2322
 
2341
2323
  // src/core/updateItemSize.ts
2342
- function updateItemSizes(ctx, state, itemUpdates) {
2343
- var _a;
2324
+ function updateItemSize(ctx, state, itemKey, sizeObj) {
2325
+ var _a, _b;
2344
2326
  const {
2327
+ sizesKnown,
2345
2328
  props: {
2329
+ getFixedItemSize,
2330
+ getItemType,
2346
2331
  horizontal,
2347
2332
  maintainVisibleContentPosition,
2348
2333
  suggestEstimatedItemSize,
@@ -2352,47 +2337,60 @@ function updateItemSizes(ctx, state, itemUpdates) {
2352
2337
  }
2353
2338
  } = state;
2354
2339
  if (!data) return;
2340
+ if (getFixedItemSize) {
2341
+ const index2 = state.indexByKey.get(itemKey);
2342
+ if (index2 === void 0) {
2343
+ return;
2344
+ }
2345
+ const itemData = state.props.data[index2];
2346
+ if (itemData === void 0) {
2347
+ return;
2348
+ }
2349
+ const type = getItemType ? (_a = getItemType(itemData, index2)) != null ? _a : "" : "";
2350
+ const size2 = getFixedItemSize(index2, itemData, type);
2351
+ if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
2352
+ return;
2353
+ }
2354
+ }
2355
2355
  const containersDidLayout = peek$(ctx, "containersDidLayout");
2356
2356
  let needsRecalculate = !containersDidLayout;
2357
2357
  let shouldMaintainScrollAtEnd = false;
2358
2358
  let minIndexSizeChanged;
2359
2359
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2360
- for (const { itemKey, sizeObj } of itemUpdates) {
2361
- const index = state.indexByKey.get(itemKey);
2362
- const prevSizeKnown = state.sizesKnown.get(itemKey);
2363
- const diff = updateOneItemSize(state, itemKey, sizeObj);
2364
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2365
- if (diff !== 0) {
2366
- minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
2367
- if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
2368
- requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
2369
- }
2370
- const { startBuffered, endBuffered } = state;
2371
- needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2372
- if (!needsRecalculate) {
2373
- const numContainers = ctx.values.get("numContainers");
2374
- for (let i = 0; i < numContainers; i++) {
2375
- if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
2376
- needsRecalculate = true;
2377
- break;
2378
- }
2360
+ const index = state.indexByKey.get(itemKey);
2361
+ const prevSizeKnown = state.sizesKnown.get(itemKey);
2362
+ const diff = updateOneItemSize(state, itemKey, sizeObj);
2363
+ const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2364
+ if (diff !== 0) {
2365
+ minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
2366
+ if (((_b = state.scrollingTo) == null ? void 0 : _b.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
2367
+ requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
2368
+ }
2369
+ const { startBuffered, endBuffered } = state;
2370
+ needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2371
+ if (!needsRecalculate) {
2372
+ const numContainers = ctx.values.get("numContainers");
2373
+ for (let i = 0; i < numContainers; i++) {
2374
+ if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
2375
+ needsRecalculate = true;
2376
+ break;
2379
2377
  }
2380
2378
  }
2381
- if (state.needsOtherAxisSize) {
2382
- const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
2383
- maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
2384
- }
2385
- if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
2386
- shouldMaintainScrollAtEnd = true;
2387
- }
2388
- onItemSizeChanged == null ? void 0 : onItemSizeChanged({
2389
- index,
2390
- itemData: state.props.data[index],
2391
- itemKey,
2392
- previous: size - diff,
2393
- size
2394
- });
2395
2379
  }
2380
+ if (state.needsOtherAxisSize) {
2381
+ const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
2382
+ maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
2383
+ }
2384
+ if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
2385
+ shouldMaintainScrollAtEnd = true;
2386
+ }
2387
+ onItemSizeChanged == null ? void 0 : onItemSizeChanged({
2388
+ index,
2389
+ itemData: state.props.data[index],
2390
+ itemKey,
2391
+ previous: size - diff,
2392
+ size
2393
+ });
2396
2394
  }
2397
2395
  if (minIndexSizeChanged !== void 0) {
2398
2396
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
@@ -2425,45 +2423,6 @@ function updateItemSizes(ctx, state, itemUpdates) {
2425
2423
  }
2426
2424
  }
2427
2425
  }
2428
- function updateItemSize(ctx, state, itemKey, sizeObj) {
2429
- var _a;
2430
- const {
2431
- queuedItemSizeUpdates,
2432
- queuedItemSizeUpdatesWaiting,
2433
- sizesKnown,
2434
- props: { getFixedItemSize, getItemType }
2435
- } = state;
2436
- if (getFixedItemSize) {
2437
- const index = state.indexByKey.get(itemKey);
2438
- if (index === void 0) {
2439
- return;
2440
- }
2441
- const itemData = state.props.data[index];
2442
- if (itemData === void 0) {
2443
- return;
2444
- }
2445
- const type = getItemType ? (_a = getItemType(itemData, index)) != null ? _a : "" : "";
2446
- const size = getFixedItemSize(index, itemData, type);
2447
- if (size !== void 0 && size === sizesKnown.get(itemKey)) {
2448
- return;
2449
- }
2450
- }
2451
- const containersDidLayout = peek$(ctx, "containersDidLayout");
2452
- const speed = getScrollVelocity(state);
2453
- if (!containersDidLayout || !queuedItemSizeUpdatesWaiting || Math.abs(speed) < 1) {
2454
- updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
2455
- if (containersDidLayout) {
2456
- state.queuedItemSizeUpdatesWaiting = true;
2457
- requestAnimationFrame(() => {
2458
- state.queuedItemSizeUpdatesWaiting = false;
2459
- updateItemSizes(ctx, state, queuedItemSizeUpdates);
2460
- queuedItemSizeUpdates.length = 0;
2461
- });
2462
- }
2463
- } else {
2464
- queuedItemSizeUpdates.push({ itemKey, sizeObj });
2465
- }
2466
- }
2467
2426
  function updateOneItemSize(state, itemKey, sizeObj) {
2468
2427
  var _a;
2469
2428
  const {
@@ -2478,7 +2437,7 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2478
2437
  const prevSize = getItemSize(state, itemKey, index, data);
2479
2438
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2480
2439
  sizesKnown.set(itemKey, size);
2481
- if (!getEstimatedItemSize && !getFixedItemSize) {
2440
+ if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
2482
2441
  const itemType = getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : "";
2483
2442
  let averages = averageSizes[itemType];
2484
2443
  if (!averages) {
@@ -2551,11 +2510,9 @@ function getRenderedItem(ctx, state, key) {
2551
2510
  }
2552
2511
 
2553
2512
  // src/utils/throttledOnScroll.ts
2554
- function throttledOnScroll(originalHandler, scrollEventThrottle) {
2513
+ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
2555
2514
  const throttle = useThrottleDebounce("throttle");
2556
- return (event) => {
2557
- throttle(originalHandler, scrollEventThrottle, event);
2558
- };
2515
+ return (event) => throttle(originalHandler, scrollEventThrottle, { nativeEvent: event.nativeEvent });
2559
2516
  }
2560
2517
 
2561
2518
  // src/utils/updateAveragesOnDataChange.ts
@@ -2724,11 +2681,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2724
2681
  loadStartTime: Date.now(),
2725
2682
  minIndexSizeChanged: 0,
2726
2683
  nativeMarginTop: 0,
2727
- pendingAdjust: 0,
2728
2684
  positions: /* @__PURE__ */ new Map(),
2729
2685
  props: {},
2730
2686
  queuedCalculateItemsInView: 0,
2731
- queuedItemSizeUpdates: [],
2732
2687
  refScroller: void 0,
2733
2688
  scroll: 0,
2734
2689
  scrollAdjustHandler: new ScrollAdjustHandler(ctx),
@@ -2758,6 +2713,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2758
2713
  const state = refState.current;
2759
2714
  const isFirst = !state.props.renderItem;
2760
2715
  const didDataChange = state.props.data !== dataProp;
2716
+ const throttleScrollFn = scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp;
2761
2717
  state.props = {
2762
2718
  alignItemsAtEnd,
2763
2719
  data: dataProp,
@@ -2779,7 +2735,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2779
2735
  onEndReachedThreshold,
2780
2736
  onItemSizeChanged,
2781
2737
  onLoad,
2782
- onScroll: onScrollProp,
2738
+ onScroll: throttleScrollFn,
2783
2739
  onStartReached,
2784
2740
  onStartReachedThreshold,
2785
2741
  recycleItems: !!recycleItems,
@@ -2886,7 +2842,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2886
2842
  }
2887
2843
  }, [snapToIndices]);
2888
2844
  React3.useLayoutEffect(() => {
2889
- const didAllocateContainers = doInitialAllocateContainersCallback();
2845
+ const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainersCallback();
2890
2846
  if (!didAllocateContainers) {
2891
2847
  checkResetContainers(
2892
2848
  /*isFirst*/
@@ -3037,8 +2993,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3037
2993
  }),
3038
2994
  []
3039
2995
  );
3040
- const animatedScrollHandler = React3.useMemo(() => {
3041
- const onScrollFn = scrollEventThrottle && scrollEventThrottle > 0 ? throttledOnScroll(fns.onScroll, scrollEventThrottle) : fns.onScroll;
2996
+ const onScrollHandler = React3.useMemo(() => {
2997
+ const onScrollFn = fns.onScroll;
3042
2998
  if (stickyIndices == null ? void 0 : stickyIndices.length) {
3043
2999
  const { animatedScrollY } = ctx;
3044
3000
  return reactNative.Animated.event([{ nativeEvent: { contentOffset: { [horizontal ? "x" : "y"]: animatedScrollY } } }], {
@@ -3077,7 +3033,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3077
3033
  onMomentumScrollEnd(event);
3078
3034
  }
3079
3035
  },
3080
- onScroll: animatedScrollHandler,
3036
+ onScroll: onScrollHandler,
3081
3037
  recycleItems,
3082
3038
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
3083
3039
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState