@legendapp/list 2.1.0-beta.7 → 2.1.0-beta.8

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.native.js CHANGED
@@ -303,7 +303,8 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
303
303
  const transform = React2__namespace.useMemo(() => {
304
304
  if (animatedScrollY && stickyOffset !== void 0) {
305
305
  const stickyPosition = animatedScrollY.interpolate({
306
- extrapolate: "clamp",
306
+ extrapolateLeft: "clamp",
307
+ extrapolateRight: "extend",
307
308
  inputRange: [position + headerSize, position + 5e3 + headerSize],
308
309
  outputRange: [position, position + 5e3]
309
310
  });
@@ -903,26 +904,6 @@ function calculateOffsetForIndex(ctx, state, index) {
903
904
  return position;
904
905
  }
905
906
 
906
- // src/core/checkActualChange.ts
907
- function checkActualChange(state, dataProp, previousData) {
908
- if (!previousData || !dataProp || dataProp.length !== previousData.length) {
909
- return true;
910
- }
911
- const {
912
- idCache,
913
- props: { keyExtractor }
914
- } = state;
915
- for (let i = 0; i < dataProp.length; i++) {
916
- if (dataProp[i] !== previousData[i]) {
917
- return true;
918
- }
919
- if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
920
- return true;
921
- }
922
- }
923
- return false;
924
- }
925
-
926
907
  // src/utils/setPaddingTop.ts
927
908
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
928
909
  if (stylePaddingTop !== void 0) {
@@ -1012,7 +993,7 @@ function setSize(ctx, state, itemKey, size) {
1012
993
  }
1013
994
 
1014
995
  // src/utils/getItemSize.ts
1015
- function getItemSize(ctx, state, key, index, data, useAverageSize) {
996
+ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedSize) {
1016
997
  var _a3, _b;
1017
998
  const {
1018
999
  sizesKnown,
@@ -1027,6 +1008,12 @@ function getItemSize(ctx, state, key, index, data, useAverageSize) {
1027
1008
  let size;
1028
1009
  const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1029
1010
  const scrollingTo = peek$(ctx, "scrollingTo");
1011
+ if (preferCachedSize) {
1012
+ const cachedSize = sizes.get(key);
1013
+ if (cachedSize !== void 0) {
1014
+ return cachedSize;
1015
+ }
1016
+ }
1030
1017
  if (getFixedItemSize) {
1031
1018
  size = getFixedItemSize(index, data, itemType);
1032
1019
  if (size !== void 0) {
@@ -1236,14 +1223,13 @@ function updateScroll(ctx, state, newScroll, forceUpdate) {
1236
1223
 
1237
1224
  // src/core/finishScrollTo.ts
1238
1225
  function finishScrollTo(ctx, state) {
1239
- var _a3;
1226
+ var _a3, _b;
1240
1227
  if (state) {
1241
1228
  state.scrollHistory.length = 0;
1242
1229
  state.initialScroll = void 0;
1243
- state.isOptimizingItemPositions = false;
1244
1230
  set$(ctx, "scrollingTo", void 0);
1245
1231
  if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1246
- calculateItemsInView(ctx, state, { forceFullItemPositions: true });
1232
+ (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1247
1233
  }
1248
1234
  }
1249
1235
  }
@@ -1253,14 +1239,14 @@ var Platform2 = reactNative.Platform;
1253
1239
  function scrollTo(ctx, state, params) {
1254
1240
  var _a3;
1255
1241
  const { noScrollingTo, ...scrollTarget } = params;
1256
- const { animated, isInitialScroll, offset: scrollTargetOffset } = scrollTarget;
1242
+ const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1257
1243
  const {
1258
1244
  refScroller,
1259
1245
  props: { horizontal }
1260
1246
  } = state;
1261
- let offset = calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1247
+ let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1262
1248
  if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
1263
- const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
1249
+ const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
1264
1250
  offset = Math.min(offset, maxOffset);
1265
1251
  }
1266
1252
  state.scrollHistory.length = 0;
@@ -1522,14 +1508,14 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1522
1508
  scrollBottomBuffered: -1,
1523
1509
  startIndex: 0
1524
1510
  }) {
1525
- var _a3, _b, _c, _d;
1511
+ var _a3, _b, _c, _d, _e;
1526
1512
  const {
1527
1513
  columns,
1528
1514
  indexByKey,
1529
1515
  positions,
1530
1516
  idCache,
1531
1517
  sizesKnown,
1532
- props: { getEstimatedItemSize, snapToIndices, enableAverages }
1518
+ props: { getEstimatedItemSize, snapToIndices, enableAverages, maintainVisibleContentPosition }
1533
1519
  } = state;
1534
1520
  const data = state.props.data;
1535
1521
  const dataLength = data.length;
@@ -1538,9 +1524,9 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1538
1524
  const hasColumns = numColumns > 1;
1539
1525
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1540
1526
  const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1541
- state.isOptimizingItemPositions = shouldOptimize;
1542
1527
  const maxVisibleArea = scrollBottomBuffered + 1e3;
1543
1528
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1529
+ const preferCachedSize = maintainVisibleContentPosition && (dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0);
1544
1530
  let currentRowTop = 0;
1545
1531
  let column = 1;
1546
1532
  let maxSizeInRow = 0;
@@ -1557,8 +1543,8 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1557
1543
  } else if (startIndex < dataLength) {
1558
1544
  const prevIndex = startIndex - 1;
1559
1545
  const prevId = getId(state, prevIndex);
1560
- const prevPosition = (_a3 = positions.get(prevId)) != null ? _a3 : 0;
1561
- const prevSize = (_b = sizesKnown.get(prevId)) != null ? _b : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize);
1546
+ const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1547
+ const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1562
1548
  currentRowTop = prevPosition + prevSize;
1563
1549
  }
1564
1550
  }
@@ -1574,8 +1560,8 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1574
1560
  const itemsPerRow = hasColumns ? numColumns : 1;
1575
1561
  breakAt = i + itemsPerRow + 10;
1576
1562
  }
1577
- const id = (_c = idCache[i]) != null ? _c : getId(state, i);
1578
- const size = (_d = sizesKnown.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i], useAverageSize);
1563
+ const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1564
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, state, id, i, data[i], useAverageSize, preferCachedSize);
1579
1565
  if (IS_DEV && needsIndexByKey) {
1580
1566
  if (indexByKeyForChecking.has(id)) {
1581
1567
  console.error(
@@ -2396,6 +2382,26 @@ function calculateItemsInView(ctx, state, params = {}) {
2396
2382
  });
2397
2383
  }
2398
2384
 
2385
+ // src/core/checkActualChange.ts
2386
+ function checkActualChange(state, dataProp, previousData) {
2387
+ if (!previousData || !dataProp || dataProp.length !== previousData.length) {
2388
+ return true;
2389
+ }
2390
+ const {
2391
+ idCache,
2392
+ props: { keyExtractor }
2393
+ } = state;
2394
+ for (let i = 0; i < dataProp.length; i++) {
2395
+ if (dataProp[i] !== previousData[i]) {
2396
+ return true;
2397
+ }
2398
+ if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
2399
+ return true;
2400
+ }
2401
+ }
2402
+ return false;
2403
+ }
2404
+
2399
2405
  // src/core/doMaintainScrollAtEnd.ts
2400
2406
  function doMaintainScrollAtEnd(ctx, state, animated) {
2401
2407
  const {
@@ -2930,6 +2936,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2930
2936
  columnWrapperStyle,
2931
2937
  contentContainerStyle: contentContainerStyleProp,
2932
2938
  data: dataProp = [],
2939
+ dataVersion,
2933
2940
  drawDistance = 250,
2934
2941
  enableAverages = true,
2935
2942
  estimatedItemSize: estimatedItemSizeProp,
@@ -2979,13 +2986,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2979
2986
  waitForInitialLayout = true,
2980
2987
  ...rest
2981
2988
  } = props;
2982
- const [renderNum, setRenderNum] = React2.useState(0);
2983
- const initialScrollProp = initialScrollAtEnd ? { index: dataProp.length - 1, viewOffset: 0 } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
2984
- const [canRender, setCanRender] = React2__namespace.useState(!IsNewArchitecture);
2985
2989
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
2986
2990
  const style = { ...StyleSheet.flatten(styleProp) };
2987
2991
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
2988
2992
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
2993
+ const [renderNum, setRenderNum] = React2.useState(0);
2994
+ const initialScrollProp = initialScrollAtEnd ? { index: dataProp.length - 1, viewOffset: -stylePaddingBottomState } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
2995
+ const [canRender, setCanRender] = React2__namespace.useState(!IsNewArchitecture);
2989
2996
  const ctx = useStateContext();
2990
2997
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
2991
2998
  const refScroller = React2.useRef(null);
@@ -3019,7 +3026,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3019
3026
  isAtStart: false,
3020
3027
  isEndReached: false,
3021
3028
  isFirst: true,
3022
- isOptimizingItemPositions: false,
3023
3029
  isStartReached: false,
3024
3030
  lastBatchingAction: Date.now(),
3025
3031
  lastLayout: void 0,
@@ -3052,6 +3058,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3052
3058
  totalSize: 0,
3053
3059
  viewabilityConfigCallbackPairs: void 0
3054
3060
  };
3061
+ const internalState = ctx.internalState;
3062
+ internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, internalState, params);
3055
3063
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
3056
3064
  set$(ctx, "extraData", extraData);
3057
3065
  }
@@ -3060,7 +3068,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3060
3068
  const state = refState.current;
3061
3069
  const isFirstLocal = state.isFirst;
3062
3070
  state.didColumnsChange = numColumnsProp !== state.props.numColumns;
3063
- const didDataChangeLocal = state.props.data !== dataProp && checkActualChange(state, dataProp, state.props.data);
3071
+ const didDataChangeLocal = state.props.dataVersion !== dataVersion || state.props.data !== dataProp && checkActualChange(state, dataProp, state.props.data);
3064
3072
  if (didDataChangeLocal) {
3065
3073
  state.dataChangeNeedsScrollUpdate = true;
3066
3074
  state.didDataChange = true;
@@ -3070,6 +3078,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3070
3078
  state.props = {
3071
3079
  alignItemsAtEnd,
3072
3080
  data: dataProp,
3081
+ dataVersion,
3073
3082
  enableAverages,
3074
3083
  estimatedItemSize,
3075
3084
  getEstimatedItemSize,
@@ -3108,7 +3117,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3108
3117
  { length: Math.min(numColumnsProp, dataProp.length) },
3109
3118
  (_, i) => getId(state, dataProp.length - 1 - i)
3110
3119
  );
3111
- }, [dataProp, numColumnsProp]);
3120
+ }, [dataProp, dataVersion, numColumnsProp]);
3112
3121
  const initializeStateVars = () => {
3113
3122
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
3114
3123
  set$(ctx, "numColumns", numColumnsProp);
@@ -3134,17 +3143,26 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3134
3143
  }
3135
3144
  const initialContentOffset = React2.useMemo(() => {
3136
3145
  const { initialScroll } = refState.current;
3137
- if (initialScroll) {
3138
- const { index, viewOffset } = initialScroll;
3139
- let initialContentOffset2 = viewOffset || 0;
3140
- if (index !== void 0) {
3141
- initialContentOffset2 += calculateOffsetForIndex(ctx, state, index);
3142
- }
3143
- refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
3144
- return initialContentOffset2;
3145
- }
3146
- return 0;
3147
- }, [renderNum]);
3146
+ if (!initialScroll) {
3147
+ return 0;
3148
+ }
3149
+ if (initialScroll.contentOffset !== void 0) {
3150
+ return initialScroll.contentOffset;
3151
+ }
3152
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, state, initialScroll.index) : 0;
3153
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, state, baseOffset, initialScroll);
3154
+ let clampedOffset = resolvedOffset;
3155
+ if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
3156
+ const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
3157
+ clampedOffset = Math.min(clampedOffset, maxOffset);
3158
+ }
3159
+ clampedOffset = Math.max(0, clampedOffset);
3160
+ const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3161
+ refState.current.initialScroll = updatedInitialScroll;
3162
+ state.initialScroll = updatedInitialScroll;
3163
+ refState.current.isStartReached = clampedOffset < refState.current.scrollLength * onStartReachedThreshold;
3164
+ return clampedOffset;
3165
+ }, [renderNum, state.initialScroll]);
3148
3166
  if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
3149
3167
  refState.current.lastBatchingAction = Date.now();
3150
3168
  if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
@@ -3173,9 +3191,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3173
3191
  }
3174
3192
  }, []);
3175
3193
  const doInitialScroll = React2.useCallback(() => {
3194
+ var _a4;
3176
3195
  const initialScroll = state.initialScroll;
3177
3196
  if (initialScroll) {
3178
- scrollTo(ctx, state, { animated: false, offset: initialContentOffset, ...state.initialScroll || {} });
3197
+ scrollTo(ctx, state, {
3198
+ animated: false,
3199
+ index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3200
+ offset: initialContentOffset,
3201
+ precomputedWithViewOffset: true
3202
+ });
3179
3203
  }
3180
3204
  }, [initialContentOffset, state.initialScroll]);
3181
3205
  const onLayoutChange = React2.useCallback((layout) => {
@@ -3207,15 +3231,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3207
3231
  state.didColumnsChange = false;
3208
3232
  state.didDataChange = false;
3209
3233
  state.isFirst = false;
3210
- }, [dataProp, numColumnsProp]);
3234
+ }, [dataProp, dataVersion, numColumnsProp]);
3211
3235
  React2.useLayoutEffect(() => {
3212
3236
  set$(ctx, "extraData", extraData);
3213
3237
  }, [extraData]);
3214
3238
  React2.useLayoutEffect(initializeStateVars, [
3239
+ dataVersion,
3215
3240
  memoizedLastItemKeys.join(","),
3216
3241
  numColumnsProp,
3217
- stylePaddingTopState,
3218
- stylePaddingBottomState
3242
+ stylePaddingBottomState,
3243
+ stylePaddingTopState
3219
3244
  ]);
3220
3245
  React2.useEffect(() => {
3221
3246
  const viewability = setupViewability({
package/index.native.mjs CHANGED
@@ -282,7 +282,8 @@ var PositionViewSticky = typedMemo(function PositionViewSticky2({
282
282
  const transform = React2.useMemo(() => {
283
283
  if (animatedScrollY && stickyOffset !== void 0) {
284
284
  const stickyPosition = animatedScrollY.interpolate({
285
- extrapolate: "clamp",
285
+ extrapolateLeft: "clamp",
286
+ extrapolateRight: "extend",
286
287
  inputRange: [position + headerSize, position + 5e3 + headerSize],
287
288
  outputRange: [position, position + 5e3]
288
289
  });
@@ -882,26 +883,6 @@ function calculateOffsetForIndex(ctx, state, index) {
882
883
  return position;
883
884
  }
884
885
 
885
- // src/core/checkActualChange.ts
886
- function checkActualChange(state, dataProp, previousData) {
887
- if (!previousData || !dataProp || dataProp.length !== previousData.length) {
888
- return true;
889
- }
890
- const {
891
- idCache,
892
- props: { keyExtractor }
893
- } = state;
894
- for (let i = 0; i < dataProp.length; i++) {
895
- if (dataProp[i] !== previousData[i]) {
896
- return true;
897
- }
898
- if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
899
- return true;
900
- }
901
- }
902
- return false;
903
- }
904
-
905
886
  // src/utils/setPaddingTop.ts
906
887
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
907
888
  if (stylePaddingTop !== void 0) {
@@ -991,7 +972,7 @@ function setSize(ctx, state, itemKey, size) {
991
972
  }
992
973
 
993
974
  // src/utils/getItemSize.ts
994
- function getItemSize(ctx, state, key, index, data, useAverageSize) {
975
+ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedSize) {
995
976
  var _a3, _b;
996
977
  const {
997
978
  sizesKnown,
@@ -1006,6 +987,12 @@ function getItemSize(ctx, state, key, index, data, useAverageSize) {
1006
987
  let size;
1007
988
  const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1008
989
  const scrollingTo = peek$(ctx, "scrollingTo");
990
+ if (preferCachedSize) {
991
+ const cachedSize = sizes.get(key);
992
+ if (cachedSize !== void 0) {
993
+ return cachedSize;
994
+ }
995
+ }
1009
996
  if (getFixedItemSize) {
1010
997
  size = getFixedItemSize(index, data, itemType);
1011
998
  if (size !== void 0) {
@@ -1215,14 +1202,13 @@ function updateScroll(ctx, state, newScroll, forceUpdate) {
1215
1202
 
1216
1203
  // src/core/finishScrollTo.ts
1217
1204
  function finishScrollTo(ctx, state) {
1218
- var _a3;
1205
+ var _a3, _b;
1219
1206
  if (state) {
1220
1207
  state.scrollHistory.length = 0;
1221
1208
  state.initialScroll = void 0;
1222
- state.isOptimizingItemPositions = false;
1223
1209
  set$(ctx, "scrollingTo", void 0);
1224
1210
  if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1225
- calculateItemsInView(ctx, state, { forceFullItemPositions: true });
1211
+ (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1226
1212
  }
1227
1213
  }
1228
1214
  }
@@ -1232,14 +1218,14 @@ var Platform2 = Platform;
1232
1218
  function scrollTo(ctx, state, params) {
1233
1219
  var _a3;
1234
1220
  const { noScrollingTo, ...scrollTarget } = params;
1235
- const { animated, isInitialScroll, offset: scrollTargetOffset } = scrollTarget;
1221
+ const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1236
1222
  const {
1237
1223
  refScroller,
1238
1224
  props: { horizontal }
1239
1225
  } = state;
1240
- let offset = calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1226
+ let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1241
1227
  if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
1242
- const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
1228
+ const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
1243
1229
  offset = Math.min(offset, maxOffset);
1244
1230
  }
1245
1231
  state.scrollHistory.length = 0;
@@ -1501,14 +1487,14 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1501
1487
  scrollBottomBuffered: -1,
1502
1488
  startIndex: 0
1503
1489
  }) {
1504
- var _a3, _b, _c, _d;
1490
+ var _a3, _b, _c, _d, _e;
1505
1491
  const {
1506
1492
  columns,
1507
1493
  indexByKey,
1508
1494
  positions,
1509
1495
  idCache,
1510
1496
  sizesKnown,
1511
- props: { getEstimatedItemSize, snapToIndices, enableAverages }
1497
+ props: { getEstimatedItemSize, snapToIndices, enableAverages, maintainVisibleContentPosition }
1512
1498
  } = state;
1513
1499
  const data = state.props.data;
1514
1500
  const dataLength = data.length;
@@ -1517,9 +1503,9 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1517
1503
  const hasColumns = numColumns > 1;
1518
1504
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1519
1505
  const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1520
- state.isOptimizingItemPositions = shouldOptimize;
1521
1506
  const maxVisibleArea = scrollBottomBuffered + 1e3;
1522
1507
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1508
+ const preferCachedSize = maintainVisibleContentPosition && (dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0);
1523
1509
  let currentRowTop = 0;
1524
1510
  let column = 1;
1525
1511
  let maxSizeInRow = 0;
@@ -1536,8 +1522,8 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1536
1522
  } else if (startIndex < dataLength) {
1537
1523
  const prevIndex = startIndex - 1;
1538
1524
  const prevId = getId(state, prevIndex);
1539
- const prevPosition = (_a3 = positions.get(prevId)) != null ? _a3 : 0;
1540
- const prevSize = (_b = sizesKnown.get(prevId)) != null ? _b : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize);
1525
+ const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1526
+ const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1541
1527
  currentRowTop = prevPosition + prevSize;
1542
1528
  }
1543
1529
  }
@@ -1553,8 +1539,8 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1553
1539
  const itemsPerRow = hasColumns ? numColumns : 1;
1554
1540
  breakAt = i + itemsPerRow + 10;
1555
1541
  }
1556
- const id = (_c = idCache[i]) != null ? _c : getId(state, i);
1557
- const size = (_d = sizesKnown.get(id)) != null ? _d : getItemSize(ctx, state, id, i, data[i], useAverageSize);
1542
+ const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1543
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, state, id, i, data[i], useAverageSize, preferCachedSize);
1558
1544
  if (IS_DEV && needsIndexByKey) {
1559
1545
  if (indexByKeyForChecking.has(id)) {
1560
1546
  console.error(
@@ -2375,6 +2361,26 @@ function calculateItemsInView(ctx, state, params = {}) {
2375
2361
  });
2376
2362
  }
2377
2363
 
2364
+ // src/core/checkActualChange.ts
2365
+ function checkActualChange(state, dataProp, previousData) {
2366
+ if (!previousData || !dataProp || dataProp.length !== previousData.length) {
2367
+ return true;
2368
+ }
2369
+ const {
2370
+ idCache,
2371
+ props: { keyExtractor }
2372
+ } = state;
2373
+ for (let i = 0; i < dataProp.length; i++) {
2374
+ if (dataProp[i] !== previousData[i]) {
2375
+ return true;
2376
+ }
2377
+ if (keyExtractor ? idCache[i] !== keyExtractor(previousData[i], i) : dataProp[i] !== previousData[i]) {
2378
+ return true;
2379
+ }
2380
+ }
2381
+ return false;
2382
+ }
2383
+
2378
2384
  // src/core/doMaintainScrollAtEnd.ts
2379
2385
  function doMaintainScrollAtEnd(ctx, state, animated) {
2380
2386
  const {
@@ -2909,6 +2915,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2909
2915
  columnWrapperStyle,
2910
2916
  contentContainerStyle: contentContainerStyleProp,
2911
2917
  data: dataProp = [],
2918
+ dataVersion,
2912
2919
  drawDistance = 250,
2913
2920
  enableAverages = true,
2914
2921
  estimatedItemSize: estimatedItemSizeProp,
@@ -2958,13 +2965,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2958
2965
  waitForInitialLayout = true,
2959
2966
  ...rest
2960
2967
  } = props;
2961
- const [renderNum, setRenderNum] = useState(0);
2962
- const initialScrollProp = initialScrollAtEnd ? { index: dataProp.length - 1, viewOffset: 0 } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
2963
- const [canRender, setCanRender] = React2.useState(!IsNewArchitecture);
2964
2968
  const contentContainerStyle = { ...StyleSheet.flatten(contentContainerStyleProp) };
2965
2969
  const style = { ...StyleSheet.flatten(styleProp) };
2966
2970
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
2967
2971
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
2972
+ const [renderNum, setRenderNum] = useState(0);
2973
+ const initialScrollProp = initialScrollAtEnd ? { index: dataProp.length - 1, viewOffset: -stylePaddingBottomState } : initialScrollIndexProp || initialScrollOffsetProp ? typeof initialScrollIndexProp === "object" ? { index: initialScrollIndexProp.index || 0, viewOffset: initialScrollIndexProp.viewOffset || 0 } : { index: initialScrollIndexProp || 0, viewOffset: initialScrollOffsetProp || 0 } : void 0;
2974
+ const [canRender, setCanRender] = React2.useState(!IsNewArchitecture);
2968
2975
  const ctx = useStateContext();
2969
2976
  ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
2970
2977
  const refScroller = useRef(null);
@@ -2998,7 +3005,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2998
3005
  isAtStart: false,
2999
3006
  isEndReached: false,
3000
3007
  isFirst: true,
3001
- isOptimizingItemPositions: false,
3002
3008
  isStartReached: false,
3003
3009
  lastBatchingAction: Date.now(),
3004
3010
  lastLayout: void 0,
@@ -3031,6 +3037,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3031
3037
  totalSize: 0,
3032
3038
  viewabilityConfigCallbackPairs: void 0
3033
3039
  };
3040
+ const internalState = ctx.internalState;
3041
+ internalState.triggerCalculateItemsInView = (params) => calculateItemsInView(ctx, internalState, params);
3034
3042
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPosition);
3035
3043
  set$(ctx, "extraData", extraData);
3036
3044
  }
@@ -3039,7 +3047,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3039
3047
  const state = refState.current;
3040
3048
  const isFirstLocal = state.isFirst;
3041
3049
  state.didColumnsChange = numColumnsProp !== state.props.numColumns;
3042
- const didDataChangeLocal = state.props.data !== dataProp && checkActualChange(state, dataProp, state.props.data);
3050
+ const didDataChangeLocal = state.props.dataVersion !== dataVersion || state.props.data !== dataProp && checkActualChange(state, dataProp, state.props.data);
3043
3051
  if (didDataChangeLocal) {
3044
3052
  state.dataChangeNeedsScrollUpdate = true;
3045
3053
  state.didDataChange = true;
@@ -3049,6 +3057,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3049
3057
  state.props = {
3050
3058
  alignItemsAtEnd,
3051
3059
  data: dataProp,
3060
+ dataVersion,
3052
3061
  enableAverages,
3053
3062
  estimatedItemSize,
3054
3063
  getEstimatedItemSize,
@@ -3087,7 +3096,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3087
3096
  { length: Math.min(numColumnsProp, dataProp.length) },
3088
3097
  (_, i) => getId(state, dataProp.length - 1 - i)
3089
3098
  );
3090
- }, [dataProp, numColumnsProp]);
3099
+ }, [dataProp, dataVersion, numColumnsProp]);
3091
3100
  const initializeStateVars = () => {
3092
3101
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
3093
3102
  set$(ctx, "numColumns", numColumnsProp);
@@ -3113,17 +3122,26 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3113
3122
  }
3114
3123
  const initialContentOffset = useMemo(() => {
3115
3124
  const { initialScroll } = refState.current;
3116
- if (initialScroll) {
3117
- const { index, viewOffset } = initialScroll;
3118
- let initialContentOffset2 = viewOffset || 0;
3119
- if (index !== void 0) {
3120
- initialContentOffset2 += calculateOffsetForIndex(ctx, state, index);
3121
- }
3122
- refState.current.isStartReached = initialContentOffset2 < refState.current.scrollLength * onStartReachedThreshold;
3123
- return initialContentOffset2;
3124
- }
3125
- return 0;
3126
- }, [renderNum]);
3125
+ if (!initialScroll) {
3126
+ return 0;
3127
+ }
3128
+ if (initialScroll.contentOffset !== void 0) {
3129
+ return initialScroll.contentOffset;
3130
+ }
3131
+ const baseOffset = initialScroll.index !== void 0 ? calculateOffsetForIndex(ctx, state, initialScroll.index) : 0;
3132
+ const resolvedOffset = calculateOffsetWithOffsetPosition(ctx, state, baseOffset, initialScroll);
3133
+ let clampedOffset = resolvedOffset;
3134
+ if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
3135
+ const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
3136
+ clampedOffset = Math.min(clampedOffset, maxOffset);
3137
+ }
3138
+ clampedOffset = Math.max(0, clampedOffset);
3139
+ const updatedInitialScroll = { ...initialScroll, contentOffset: clampedOffset };
3140
+ refState.current.initialScroll = updatedInitialScroll;
3141
+ state.initialScroll = updatedInitialScroll;
3142
+ refState.current.isStartReached = clampedOffset < refState.current.scrollLength * onStartReachedThreshold;
3143
+ return clampedOffset;
3144
+ }, [renderNum, state.initialScroll]);
3127
3145
  if (isFirstLocal || didDataChangeLocal || numColumnsProp !== peek$(ctx, "numColumns")) {
3128
3146
  refState.current.lastBatchingAction = Date.now();
3129
3147
  if (!keyExtractorProp && !isFirstLocal && didDataChangeLocal) {
@@ -3152,9 +3170,15 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3152
3170
  }
3153
3171
  }, []);
3154
3172
  const doInitialScroll = useCallback(() => {
3173
+ var _a4;
3155
3174
  const initialScroll = state.initialScroll;
3156
3175
  if (initialScroll) {
3157
- scrollTo(ctx, state, { animated: false, offset: initialContentOffset, ...state.initialScroll || {} });
3176
+ scrollTo(ctx, state, {
3177
+ animated: false,
3178
+ index: (_a4 = state.initialScroll) == null ? void 0 : _a4.index,
3179
+ offset: initialContentOffset,
3180
+ precomputedWithViewOffset: true
3181
+ });
3158
3182
  }
3159
3183
  }, [initialContentOffset, state.initialScroll]);
3160
3184
  const onLayoutChange = useCallback((layout) => {
@@ -3186,15 +3210,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3186
3210
  state.didColumnsChange = false;
3187
3211
  state.didDataChange = false;
3188
3212
  state.isFirst = false;
3189
- }, [dataProp, numColumnsProp]);
3213
+ }, [dataProp, dataVersion, numColumnsProp]);
3190
3214
  useLayoutEffect(() => {
3191
3215
  set$(ctx, "extraData", extraData);
3192
3216
  }, [extraData]);
3193
3217
  useLayoutEffect(initializeStateVars, [
3218
+ dataVersion,
3194
3219
  memoizedLastItemKeys.join(","),
3195
3220
  numColumnsProp,
3196
- stylePaddingTopState,
3197
- stylePaddingBottomState
3221
+ stylePaddingBottomState,
3222
+ stylePaddingTopState
3198
3223
  ]);
3199
3224
  useEffect(() => {
3200
3225
  const viewability = setupViewability({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "2.1.0-beta.7",
3
+ "version": "2.1.0-beta.8",
4
4
  "description": "Legend List is a drop-in replacement for FlatList with much better performance and supporting dynamically sized items.",
5
5
  "sideEffects": false,
6
6
  "private": false,