@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.mjs CHANGED
@@ -672,30 +672,33 @@ function useThrottleDebounce(mode) {
672
672
  timeoutRef.current = null;
673
673
  }
674
674
  };
675
- const execute = useCallback((callback, delay, ...args) => {
676
- {
677
- const now = Date.now();
678
- lastArgsRef.current = args;
679
- if (now - lastCallTimeRef.current >= delay) {
680
- lastCallTimeRef.current = now;
681
- callback(...args);
682
- clearTimeoutRef();
683
- } else {
684
- clearTimeoutRef();
685
- timeoutRef.current = setTimeout(
686
- () => {
687
- if (lastArgsRef.current) {
688
- lastCallTimeRef.current = Date.now();
689
- callback(...lastArgsRef.current);
690
- timeoutRef.current = null;
691
- lastArgsRef.current = null;
692
- }
693
- },
694
- delay - (now - lastCallTimeRef.current)
695
- );
675
+ const execute = useCallback(
676
+ (callback, delay, ...args) => {
677
+ {
678
+ const now = Date.now();
679
+ lastArgsRef.current = args;
680
+ if (now - lastCallTimeRef.current >= delay) {
681
+ lastCallTimeRef.current = now;
682
+ callback(...args);
683
+ clearTimeoutRef();
684
+ } else {
685
+ clearTimeoutRef();
686
+ timeoutRef.current = setTimeout(
687
+ () => {
688
+ if (lastArgsRef.current) {
689
+ lastCallTimeRef.current = Date.now();
690
+ callback(...lastArgsRef.current);
691
+ timeoutRef.current = null;
692
+ lastArgsRef.current = null;
693
+ }
694
+ },
695
+ delay - (now - lastCallTimeRef.current)
696
+ );
697
+ }
696
698
  }
697
- }
698
- }, [mode]);
699
+ },
700
+ [mode]
701
+ );
699
702
  return execute;
700
703
  }
701
704
 
@@ -891,7 +894,7 @@ function calculateOffsetForIndex(ctx, state, index) {
891
894
  }
892
895
 
893
896
  // src/utils/getItemSize.ts
894
- function getItemSize(state, key, index, data, useAverageSize, defaultAverageSize, preferRenderedCache) {
897
+ function getItemSize(state, key, index, data, useAverageSize) {
895
898
  var _a, _b;
896
899
  const {
897
900
  sizesKnown,
@@ -912,22 +915,17 @@ function getItemSize(state, key, index, data, useAverageSize, defaultAverageSize
912
915
  sizesKnown.set(key, size);
913
916
  }
914
917
  }
915
- const renderedSize = sizes.get(key);
916
- if (size === void 0 && preferRenderedCache && renderedSize !== void 0) {
917
- return renderedSize;
918
- }
919
- if (size === void 0 && useAverageSize && !scrollingTo) {
920
- if (itemType === "") {
921
- size = defaultAverageSize;
922
- } else {
923
- const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
924
- if (averageSizeForType !== void 0) {
925
- size = roundSize(averageSizeForType);
926
- }
918
+ if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
919
+ const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
920
+ if (averageSizeForType !== void 0) {
921
+ size = roundSize(averageSizeForType);
927
922
  }
928
923
  }
929
- if (size === void 0 && renderedSize !== void 0) {
930
- return renderedSize;
924
+ if (size === void 0) {
925
+ size = sizes.get(key);
926
+ if (size !== void 0) {
927
+ return size;
928
+ }
931
929
  }
932
930
  if (size === void 0) {
933
931
  size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
@@ -1154,44 +1152,6 @@ function addTotalSize(ctx, state, key, add) {
1154
1152
  }
1155
1153
  }
1156
1154
 
1157
- // src/utils/getScrollVelocity.ts
1158
- var getScrollVelocity = (state) => {
1159
- const { scrollHistory } = state;
1160
- let velocity = 0;
1161
- if (scrollHistory.length >= 1) {
1162
- const newest = scrollHistory[scrollHistory.length - 1];
1163
- let oldest;
1164
- let start = 0;
1165
- const now = Date.now();
1166
- for (let i = 0; i < scrollHistory.length - 1; i++) {
1167
- const entry = scrollHistory[i];
1168
- const nextEntry = scrollHistory[i + 1];
1169
- if (i > 0) {
1170
- const prevEntry = scrollHistory[i - 1];
1171
- const prevDirection = entry.scroll - prevEntry.scroll;
1172
- const currentDirection = nextEntry.scroll - entry.scroll;
1173
- if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1174
- start = i;
1175
- break;
1176
- }
1177
- }
1178
- }
1179
- for (let i = start; i < scrollHistory.length - 1; i++) {
1180
- const entry = scrollHistory[i];
1181
- if (now - entry.time <= 1e3) {
1182
- oldest = entry;
1183
- break;
1184
- }
1185
- }
1186
- if (oldest && oldest !== newest) {
1187
- const scrollDiff = newest.scroll - oldest.scroll;
1188
- const timeDiff = newest.time - oldest.time;
1189
- velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1190
- }
1191
- }
1192
- return velocity;
1193
- };
1194
-
1195
1155
  // src/utils/updateSnapToOffsets.ts
1196
1156
  function updateSnapToOffsets(ctx, state) {
1197
1157
  const {
@@ -1208,14 +1168,12 @@ function updateSnapToOffsets(ctx, state) {
1208
1168
  }
1209
1169
 
1210
1170
  // src/core/updateAllPositions.ts
1211
- function updateAllPositions(ctx, state, dataChanged) {
1212
- var _a, _b, _c, _d, _e;
1171
+ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1172
+ var _a, _b, _c, _d, _e, _f;
1213
1173
  const {
1214
- averageSizes,
1215
1174
  columns,
1216
1175
  indexByKey,
1217
1176
  positions,
1218
- firstFullyOnScreenIndex,
1219
1177
  idCache,
1220
1178
  sizesKnown,
1221
1179
  props: { getEstimatedItemSize, snapToIndices, enableAverages }
@@ -1223,69 +1181,29 @@ function updateAllPositions(ctx, state, dataChanged) {
1223
1181
  const data = state.props.data;
1224
1182
  const numColumns = peek$(ctx, "numColumns");
1225
1183
  const indexByKeyForChecking = __DEV__ ? /* @__PURE__ */ new Map() : void 0;
1226
- const scrollVelocity = getScrollVelocity(state);
1227
1184
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1228
- const itemType = "";
1229
- let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
1230
- if (averageSize !== void 0) {
1231
- averageSize = roundSize(averageSize);
1232
- }
1233
- const shouldUseBackwards = !dataChanged && scrollVelocity < 0 && firstFullyOnScreenIndex > 5 && firstFullyOnScreenIndex < data.length;
1234
- if (shouldUseBackwards && firstFullyOnScreenIndex !== void 0) {
1235
- const anchorId = getId(state, firstFullyOnScreenIndex);
1236
- const anchorPosition = positions.get(anchorId);
1237
- if (anchorPosition !== void 0) {
1238
- let currentRowTop2 = anchorPosition;
1239
- let maxSizeInRow2 = 0;
1240
- let bailout = false;
1241
- for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
1242
- const id = (_b = idCache.get(i)) != null ? _b : getId(state, i);
1243
- const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(
1244
- state,
1245
- id,
1246
- i,
1247
- data[i],
1248
- useAverageSize,
1249
- averageSize,
1250
- /*preferRenderedCache*/
1251
- !!dataChanged
1252
- );
1253
- const itemColumn = columns.get(id);
1254
- maxSizeInRow2 = Math.max(maxSizeInRow2, size);
1255
- if (itemColumn === 1) {
1256
- currentRowTop2 -= maxSizeInRow2;
1257
- maxSizeInRow2 = 0;
1258
- }
1259
- if (currentRowTop2 < -2e3) {
1260
- bailout = true;
1261
- break;
1262
- }
1263
- positions.set(id, currentRowTop2);
1264
- }
1265
- if (!bailout) {
1266
- updateTotalSize(ctx, state);
1267
- return;
1268
- }
1269
- }
1270
- }
1271
1185
  let currentRowTop = 0;
1272
1186
  let column = 1;
1273
1187
  let maxSizeInRow = 0;
1274
1188
  const hasColumns = numColumns > 1;
1189
+ if (startIndex > 0) {
1190
+ const prevIndex = startIndex - 1;
1191
+ const prevId = (_a = idCache.get(prevIndex)) != null ? _a : getId(state, prevIndex);
1192
+ const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1193
+ if (hasColumns) {
1194
+ const prevColumn = (_c = columns.get(prevId)) != null ? _c : 1;
1195
+ currentRowTop = prevPosition;
1196
+ column = prevColumn % numColumns + 1;
1197
+ } else {
1198
+ const prevSize = (_d = sizesKnown.get(prevId)) != null ? _d : getItemSize(state, prevId, prevIndex, data[prevIndex], useAverageSize);
1199
+ currentRowTop = prevPosition + prevSize;
1200
+ }
1201
+ }
1275
1202
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1276
1203
  const dataLength = data.length;
1277
- for (let i = 0; i < dataLength; i++) {
1278
- const id = (_d = idCache.get(i)) != null ? _d : getId(state, i);
1279
- const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(
1280
- state,
1281
- id,
1282
- i,
1283
- data[i],
1284
- useAverageSize,
1285
- averageSize,
1286
- /*preferRenderedCache*/
1287
- !!dataChanged
1288
- );
1204
+ for (let i = startIndex; i < dataLength; i++) {
1205
+ const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1206
+ const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(state, id, i, data[i], useAverageSize);
1289
1207
  if (__DEV__ && needsIndexByKey) {
1290
1208
  if (indexByKeyForChecking.has(id)) {
1291
1209
  console.error(
@@ -1648,6 +1566,44 @@ function comparatorByDistance(a, b) {
1648
1566
  return b.distance - a.distance;
1649
1567
  }
1650
1568
 
1569
+ // src/utils/getScrollVelocity.ts
1570
+ var getScrollVelocity = (state) => {
1571
+ const { scrollHistory } = state;
1572
+ let velocity = 0;
1573
+ if (scrollHistory.length >= 1) {
1574
+ const newest = scrollHistory[scrollHistory.length - 1];
1575
+ let oldest;
1576
+ let start = 0;
1577
+ const now = Date.now();
1578
+ for (let i = 0; i < scrollHistory.length - 1; i++) {
1579
+ const entry = scrollHistory[i];
1580
+ const nextEntry = scrollHistory[i + 1];
1581
+ if (i > 0) {
1582
+ const prevEntry = scrollHistory[i - 1];
1583
+ const prevDirection = entry.scroll - prevEntry.scroll;
1584
+ const currentDirection = nextEntry.scroll - entry.scroll;
1585
+ if (prevDirection > 0 && currentDirection < 0 || prevDirection < 0 && currentDirection > 0) {
1586
+ start = i;
1587
+ break;
1588
+ }
1589
+ }
1590
+ }
1591
+ for (let i = start; i < scrollHistory.length - 1; i++) {
1592
+ const entry = scrollHistory[i];
1593
+ if (now - entry.time <= 1e3) {
1594
+ oldest = entry;
1595
+ break;
1596
+ }
1597
+ }
1598
+ if (oldest && oldest !== newest) {
1599
+ const scrollDiff = newest.scroll - oldest.scroll;
1600
+ const timeDiff = newest.time - oldest.time;
1601
+ velocity = timeDiff > 0 ? scrollDiff / timeDiff : 0;
1602
+ }
1603
+ }
1604
+ return velocity;
1605
+ };
1606
+
1651
1607
  // src/core/scrollToIndex.ts
1652
1608
  function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1653
1609
  if (index >= state.props.data.length) {
@@ -1859,7 +1815,11 @@ function calculateItemsInView(ctx, state, params = {}) {
1859
1815
  idCache.clear();
1860
1816
  positions.clear();
1861
1817
  }
1862
- updateAllPositions(ctx, state, dataChanged);
1818
+ const startIndex = dataChanged ? 0 : minIndexSizeChanged != null ? minIndexSizeChanged : 0;
1819
+ updateAllPositions(ctx, state, dataChanged, startIndex);
1820
+ if (minIndexSizeChanged !== void 0) {
1821
+ state.minIndexSizeChanged = void 0;
1822
+ }
1863
1823
  checkMVCP == null ? void 0 : checkMVCP();
1864
1824
  }
1865
1825
  const scrollExtra = 0;
@@ -1906,10 +1866,6 @@ function calculateItemsInView(ctx, state, params = {}) {
1906
1866
  let endNoBuffer = null;
1907
1867
  let endBuffered = null;
1908
1868
  let loopStart = startBufferedIdOrig ? indexByKey.get(startBufferedIdOrig) || 0 : 0;
1909
- if (minIndexSizeChanged !== void 0) {
1910
- loopStart = Math.min(minIndexSizeChanged, loopStart);
1911
- state.minIndexSizeChanged = void 0;
1912
- }
1913
1869
  for (let i = loopStart; i >= 0; i--) {
1914
1870
  const id = (_a = idCache.get(i)) != null ? _a : getId(state, i);
1915
1871
  const top = positions.get(id);
@@ -2128,10 +2084,30 @@ function doInitialAllocateContainers(ctx, state) {
2128
2084
  var _a;
2129
2085
  const {
2130
2086
  scrollLength,
2131
- props: { data, getEstimatedItemSize, getItemType, scrollBuffer, numColumns, estimatedItemSize }
2087
+ props: {
2088
+ data,
2089
+ getEstimatedItemSize,
2090
+ getFixedItemSize,
2091
+ getItemType,
2092
+ scrollBuffer,
2093
+ numColumns,
2094
+ estimatedItemSize
2095
+ }
2132
2096
  } = state;
2133
- if (scrollLength > 0 && data.length > 0 && !peek$(ctx, "numContainers")) {
2134
- const averageItemSize = getEstimatedItemSize ? getEstimatedItemSize(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "") : estimatedItemSize;
2097
+ const hasContainers = peek$(ctx, "numContainers");
2098
+ if (scrollLength > 0 && data.length > 0 && !hasContainers) {
2099
+ let averageItemSize;
2100
+ const fn = getFixedItemSize || getEstimatedItemSize;
2101
+ if (fn) {
2102
+ let totalSize = 0;
2103
+ const num = Math.min(20, data.length);
2104
+ for (let i = 0; i < num; i++) {
2105
+ totalSize += fn(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "");
2106
+ }
2107
+ averageItemSize = totalSize / num;
2108
+ } else {
2109
+ averageItemSize = estimatedItemSize;
2110
+ }
2135
2111
  const numContainers = Math.ceil((scrollLength + scrollBuffer * 2) / averageItemSize * numColumns);
2136
2112
  for (let i = 0; i < numContainers; i++) {
2137
2113
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
@@ -2139,13 +2115,13 @@ function doInitialAllocateContainers(ctx, state) {
2139
2115
  }
2140
2116
  set$(ctx, "numContainers", numContainers);
2141
2117
  set$(ctx, "numContainersPooled", numContainers * state.props.initialContainerPoolRatio);
2142
- if (!IsNewArchitecture) {
2118
+ if (!IsNewArchitecture || state.lastLayout) {
2143
2119
  if (state.props.initialScroll) {
2144
2120
  requestAnimationFrame(() => {
2145
- calculateItemsInView(ctx, state);
2121
+ calculateItemsInView(ctx, state, { dataChanged: true });
2146
2122
  });
2147
2123
  } else {
2148
- calculateItemsInView(ctx, state);
2124
+ calculateItemsInView(ctx, state, { dataChanged: true });
2149
2125
  }
2150
2126
  }
2151
2127
  return true;
@@ -2217,35 +2193,37 @@ function handleLayout(ctx, state, layout, setCanRender) {
2217
2193
  const otherAxisSize = layout[state.props.horizontal ? "height" : "width"];
2218
2194
  const needsCalculate = !state.lastLayout || scrollLength > state.scrollLength || state.lastLayout.x !== layout.x || state.lastLayout.y !== layout.y;
2219
2195
  state.lastLayout = layout;
2220
- const didChange = scrollLength !== state.scrollLength;
2221
2196
  const prevOtherAxisSize = state.otherAxisSize;
2222
- state.scrollLength = scrollLength;
2223
- state.otherAxisSize = otherAxisSize;
2224
- state.lastBatchingAction = Date.now();
2225
- state.scrollForNextCalculateItemsInView = void 0;
2226
- doInitialAllocateContainers(ctx, state);
2227
- if (needsCalculate) {
2228
- calculateItemsInView(ctx, state, { doMVCP: true });
2229
- }
2230
- if (didChange || otherAxisSize !== prevOtherAxisSize) {
2231
- set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
2232
- }
2233
- if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
2234
- doMaintainScrollAtEnd(ctx, state, false);
2235
- }
2236
- updateAlignItemsPaddingTop(ctx, state);
2237
- checkAtBottom(ctx, state);
2238
- checkAtTop(state);
2239
- if (state) {
2240
- state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2241
- }
2242
- if (__DEV__ && scrollLength === 0) {
2243
- warnDevOnce(
2244
- "height0",
2245
- `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.`
2246
- );
2197
+ const didChange = scrollLength !== state.scrollLength || otherAxisSize !== prevOtherAxisSize;
2198
+ if (didChange) {
2199
+ state.scrollLength = scrollLength;
2200
+ state.otherAxisSize = otherAxisSize;
2201
+ state.lastBatchingAction = Date.now();
2202
+ state.scrollForNextCalculateItemsInView = void 0;
2203
+ doInitialAllocateContainers(ctx, state);
2204
+ if (needsCalculate) {
2205
+ calculateItemsInView(ctx, state, { doMVCP: true });
2206
+ }
2207
+ if (didChange || otherAxisSize !== prevOtherAxisSize) {
2208
+ set$(ctx, "scrollSize", { height: layout.height, width: layout.width });
2209
+ }
2210
+ if (maintainScrollAtEnd === true || maintainScrollAtEnd.onLayout) {
2211
+ doMaintainScrollAtEnd(ctx, state, false);
2212
+ }
2213
+ updateAlignItemsPaddingTop(ctx, state);
2214
+ checkAtBottom(ctx, state);
2215
+ checkAtTop(state);
2216
+ if (state) {
2217
+ state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
2218
+ }
2219
+ if (__DEV__ && scrollLength === 0) {
2220
+ warnDevOnce(
2221
+ "height0",
2222
+ `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.`
2223
+ );
2224
+ }
2225
+ setCanRender(true);
2247
2226
  }
2248
- setCanRender(true);
2249
2227
  }
2250
2228
 
2251
2229
  // src/core/onScroll.ts
@@ -2279,7 +2257,8 @@ function updateScroll(ctx, state, newScroll) {
2279
2257
  state.lastBatchingAction = Date.now();
2280
2258
  const currentTime = Date.now();
2281
2259
  if (scrollingTo === void 0 && !(state.scrollHistory.length === 0 && newScroll === state.scroll)) {
2282
- state.scrollHistory.push({ scroll: newScroll, time: currentTime });
2260
+ const adjust = state.scrollAdjustHandler.getAdjust();
2261
+ state.scrollHistory.push({ scroll: newScroll - adjust, time: currentTime });
2283
2262
  }
2284
2263
  if (state.scrollHistory.length > 5) {
2285
2264
  state.scrollHistory.shift();
@@ -2315,13 +2294,19 @@ var ScrollAdjustHandler = class {
2315
2294
  setMounted() {
2316
2295
  this.mounted = true;
2317
2296
  }
2297
+ getAdjust() {
2298
+ return this.appliedAdjust;
2299
+ }
2318
2300
  };
2319
2301
 
2320
2302
  // src/core/updateItemSize.ts
2321
- function updateItemSizes(ctx, state, itemUpdates) {
2322
- var _a;
2303
+ function updateItemSize(ctx, state, itemKey, sizeObj) {
2304
+ var _a, _b;
2323
2305
  const {
2306
+ sizesKnown,
2324
2307
  props: {
2308
+ getFixedItemSize,
2309
+ getItemType,
2325
2310
  horizontal,
2326
2311
  maintainVisibleContentPosition,
2327
2312
  suggestEstimatedItemSize,
@@ -2331,47 +2316,60 @@ function updateItemSizes(ctx, state, itemUpdates) {
2331
2316
  }
2332
2317
  } = state;
2333
2318
  if (!data) return;
2319
+ if (getFixedItemSize) {
2320
+ const index2 = state.indexByKey.get(itemKey);
2321
+ if (index2 === void 0) {
2322
+ return;
2323
+ }
2324
+ const itemData = state.props.data[index2];
2325
+ if (itemData === void 0) {
2326
+ return;
2327
+ }
2328
+ const type = getItemType ? (_a = getItemType(itemData, index2)) != null ? _a : "" : "";
2329
+ const size2 = getFixedItemSize(index2, itemData, type);
2330
+ if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
2331
+ return;
2332
+ }
2333
+ }
2334
2334
  const containersDidLayout = peek$(ctx, "containersDidLayout");
2335
2335
  let needsRecalculate = !containersDidLayout;
2336
2336
  let shouldMaintainScrollAtEnd = false;
2337
2337
  let minIndexSizeChanged;
2338
2338
  let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
2339
- for (const { itemKey, sizeObj } of itemUpdates) {
2340
- const index = state.indexByKey.get(itemKey);
2341
- const prevSizeKnown = state.sizesKnown.get(itemKey);
2342
- const diff = updateOneItemSize(state, itemKey, sizeObj);
2343
- const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2344
- if (diff !== 0) {
2345
- minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
2346
- if (((_a = state.scrollingTo) == null ? void 0 : _a.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
2347
- requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
2348
- }
2349
- const { startBuffered, endBuffered } = state;
2350
- needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2351
- if (!needsRecalculate) {
2352
- const numContainers = ctx.values.get("numContainers");
2353
- for (let i = 0; i < numContainers; i++) {
2354
- if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
2355
- needsRecalculate = true;
2356
- break;
2357
- }
2339
+ const index = state.indexByKey.get(itemKey);
2340
+ const prevSizeKnown = state.sizesKnown.get(itemKey);
2341
+ const diff = updateOneItemSize(state, itemKey, sizeObj);
2342
+ const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2343
+ if (diff !== 0) {
2344
+ minIndexSizeChanged = minIndexSizeChanged !== void 0 ? Math.min(minIndexSizeChanged, index) : index;
2345
+ if (((_b = state.scrollingTo) == null ? void 0 : _b.viewPosition) && maintainVisibleContentPosition && index === state.scrollingTo.index && diff > 0) {
2346
+ requestAdjust(ctx, state, diff * state.scrollingTo.viewPosition);
2347
+ }
2348
+ const { startBuffered, endBuffered } = state;
2349
+ needsRecalculate || (needsRecalculate = index >= startBuffered && index <= endBuffered);
2350
+ if (!needsRecalculate) {
2351
+ const numContainers = ctx.values.get("numContainers");
2352
+ for (let i = 0; i < numContainers; i++) {
2353
+ if (peek$(ctx, `containerItemKey${i}`) === itemKey) {
2354
+ needsRecalculate = true;
2355
+ break;
2358
2356
  }
2359
2357
  }
2360
- if (state.needsOtherAxisSize) {
2361
- const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
2362
- maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
2363
- }
2364
- if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
2365
- shouldMaintainScrollAtEnd = true;
2366
- }
2367
- onItemSizeChanged == null ? void 0 : onItemSizeChanged({
2368
- index,
2369
- itemData: state.props.data[index],
2370
- itemKey,
2371
- previous: size - diff,
2372
- size
2373
- });
2374
2358
  }
2359
+ if (state.needsOtherAxisSize) {
2360
+ const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
2361
+ maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
2362
+ }
2363
+ if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
2364
+ shouldMaintainScrollAtEnd = true;
2365
+ }
2366
+ onItemSizeChanged == null ? void 0 : onItemSizeChanged({
2367
+ index,
2368
+ itemData: state.props.data[index],
2369
+ itemKey,
2370
+ previous: size - diff,
2371
+ size
2372
+ });
2375
2373
  }
2376
2374
  if (minIndexSizeChanged !== void 0) {
2377
2375
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
@@ -2404,45 +2402,6 @@ function updateItemSizes(ctx, state, itemUpdates) {
2404
2402
  }
2405
2403
  }
2406
2404
  }
2407
- function updateItemSize(ctx, state, itemKey, sizeObj) {
2408
- var _a;
2409
- const {
2410
- queuedItemSizeUpdates,
2411
- queuedItemSizeUpdatesWaiting,
2412
- sizesKnown,
2413
- props: { getFixedItemSize, getItemType }
2414
- } = state;
2415
- if (getFixedItemSize) {
2416
- const index = state.indexByKey.get(itemKey);
2417
- if (index === void 0) {
2418
- return;
2419
- }
2420
- const itemData = state.props.data[index];
2421
- if (itemData === void 0) {
2422
- return;
2423
- }
2424
- const type = getItemType ? (_a = getItemType(itemData, index)) != null ? _a : "" : "";
2425
- const size = getFixedItemSize(index, itemData, type);
2426
- if (size !== void 0 && size === sizesKnown.get(itemKey)) {
2427
- return;
2428
- }
2429
- }
2430
- const containersDidLayout = peek$(ctx, "containersDidLayout");
2431
- const speed = getScrollVelocity(state);
2432
- if (!containersDidLayout || !queuedItemSizeUpdatesWaiting || Math.abs(speed) < 1) {
2433
- updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
2434
- if (containersDidLayout) {
2435
- state.queuedItemSizeUpdatesWaiting = true;
2436
- requestAnimationFrame(() => {
2437
- state.queuedItemSizeUpdatesWaiting = false;
2438
- updateItemSizes(ctx, state, queuedItemSizeUpdates);
2439
- queuedItemSizeUpdates.length = 0;
2440
- });
2441
- }
2442
- } else {
2443
- queuedItemSizeUpdates.push({ itemKey, sizeObj });
2444
- }
2445
- }
2446
2405
  function updateOneItemSize(state, itemKey, sizeObj) {
2447
2406
  var _a;
2448
2407
  const {
@@ -2457,7 +2416,7 @@ function updateOneItemSize(state, itemKey, sizeObj) {
2457
2416
  const prevSize = getItemSize(state, itemKey, index, data);
2458
2417
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2459
2418
  sizesKnown.set(itemKey, size);
2460
- if (!getEstimatedItemSize && !getFixedItemSize) {
2419
+ if (!getEstimatedItemSize && !getFixedItemSize && size > 0) {
2461
2420
  const itemType = getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : "";
2462
2421
  let averages = averageSizes[itemType];
2463
2422
  if (!averages) {
@@ -2530,11 +2489,9 @@ function getRenderedItem(ctx, state, key) {
2530
2489
  }
2531
2490
 
2532
2491
  // src/utils/throttledOnScroll.ts
2533
- function throttledOnScroll(originalHandler, scrollEventThrottle) {
2492
+ function useThrottledOnScroll(originalHandler, scrollEventThrottle) {
2534
2493
  const throttle = useThrottleDebounce("throttle");
2535
- return (event) => {
2536
- throttle(originalHandler, scrollEventThrottle, event);
2537
- };
2494
+ return (event) => throttle(originalHandler, scrollEventThrottle, { nativeEvent: event.nativeEvent });
2538
2495
  }
2539
2496
 
2540
2497
  // src/utils/updateAveragesOnDataChange.ts
@@ -2703,11 +2660,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2703
2660
  loadStartTime: Date.now(),
2704
2661
  minIndexSizeChanged: 0,
2705
2662
  nativeMarginTop: 0,
2706
- pendingAdjust: 0,
2707
2663
  positions: /* @__PURE__ */ new Map(),
2708
2664
  props: {},
2709
2665
  queuedCalculateItemsInView: 0,
2710
- queuedItemSizeUpdates: [],
2711
2666
  refScroller: void 0,
2712
2667
  scroll: 0,
2713
2668
  scrollAdjustHandler: new ScrollAdjustHandler(ctx),
@@ -2737,6 +2692,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2737
2692
  const state = refState.current;
2738
2693
  const isFirst = !state.props.renderItem;
2739
2694
  const didDataChange = state.props.data !== dataProp;
2695
+ const throttleScrollFn = scrollEventThrottle && onScrollProp ? useThrottledOnScroll(onScrollProp, scrollEventThrottle) : onScrollProp;
2740
2696
  state.props = {
2741
2697
  alignItemsAtEnd,
2742
2698
  data: dataProp,
@@ -2758,7 +2714,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2758
2714
  onEndReachedThreshold,
2759
2715
  onItemSizeChanged,
2760
2716
  onLoad,
2761
- onScroll: onScrollProp,
2717
+ onScroll: throttleScrollFn,
2762
2718
  onStartReached,
2763
2719
  onStartReachedThreshold,
2764
2720
  recycleItems: !!recycleItems,
@@ -2865,7 +2821,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2865
2821
  }
2866
2822
  }, [snapToIndices]);
2867
2823
  useLayoutEffect(() => {
2868
- const didAllocateContainers = doInitialAllocateContainersCallback();
2824
+ const didAllocateContainers = dataProp.length > 0 && doInitialAllocateContainersCallback();
2869
2825
  if (!didAllocateContainers) {
2870
2826
  checkResetContainers(
2871
2827
  /*isFirst*/
@@ -3016,8 +2972,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3016
2972
  }),
3017
2973
  []
3018
2974
  );
3019
- const animatedScrollHandler = useMemo(() => {
3020
- const onScrollFn = scrollEventThrottle && scrollEventThrottle > 0 ? throttledOnScroll(fns.onScroll, scrollEventThrottle) : fns.onScroll;
2975
+ const onScrollHandler = useMemo(() => {
2976
+ const onScrollFn = fns.onScroll;
3021
2977
  if (stickyIndices == null ? void 0 : stickyIndices.length) {
3022
2978
  const { animatedScrollY } = ctx;
3023
2979
  return Animated.event([{ nativeEvent: { contentOffset: { [horizontal ? "x" : "y"]: animatedScrollY } } }], {
@@ -3056,7 +3012,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3056
3012
  onMomentumScrollEnd(event);
3057
3013
  }
3058
3014
  },
3059
- onScroll: animatedScrollHandler,
3015
+ onScroll: onScrollHandler,
3060
3016
  recycleItems,
3061
3017
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControl, {
3062
3018
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState