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

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
  });
@@ -353,6 +354,16 @@ function getPadding(s, type) {
353
354
  function extractPadding(style, contentContainerStyle, type) {
354
355
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
355
356
  }
357
+ function findContainerId(ctx, key) {
358
+ const numContainers = peek$(ctx, "numContainers");
359
+ for (let i = 0; i < numContainers; i++) {
360
+ const itemKey = peek$(ctx, `containerItemKey${i}`);
361
+ if (itemKey === key) {
362
+ return i;
363
+ }
364
+ }
365
+ return -1;
366
+ }
356
367
 
357
368
  // src/state/ContextContainer.ts
358
369
  var ContextContainer = React2.createContext(null);
@@ -903,26 +914,6 @@ function calculateOffsetForIndex(ctx, state, index) {
903
914
  return position;
904
915
  }
905
916
 
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
917
  // src/utils/setPaddingTop.ts
927
918
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
928
919
  if (stylePaddingTop !== void 0) {
@@ -1012,7 +1003,7 @@ function setSize(ctx, state, itemKey, size) {
1012
1003
  }
1013
1004
 
1014
1005
  // src/utils/getItemSize.ts
1015
- function getItemSize(ctx, state, key, index, data, useAverageSize) {
1006
+ function getItemSize(ctx, state, key, index, data, useAverageSize, preferCachedSize) {
1016
1007
  var _a3, _b;
1017
1008
  const {
1018
1009
  sizesKnown,
@@ -1027,6 +1018,12 @@ function getItemSize(ctx, state, key, index, data, useAverageSize) {
1027
1018
  let size;
1028
1019
  const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
1029
1020
  const scrollingTo = peek$(ctx, "scrollingTo");
1021
+ if (preferCachedSize) {
1022
+ const cachedSize = sizes.get(key);
1023
+ if (cachedSize !== void 0) {
1024
+ return cachedSize;
1025
+ }
1026
+ }
1030
1027
  if (getFixedItemSize) {
1031
1028
  size = getFixedItemSize(index, data, itemType);
1032
1029
  if (size !== void 0) {
@@ -1236,14 +1233,13 @@ function updateScroll(ctx, state, newScroll, forceUpdate) {
1236
1233
 
1237
1234
  // src/core/finishScrollTo.ts
1238
1235
  function finishScrollTo(ctx, state) {
1239
- var _a3;
1236
+ var _a3, _b;
1240
1237
  if (state) {
1241
1238
  state.scrollHistory.length = 0;
1242
1239
  state.initialScroll = void 0;
1243
- state.isOptimizingItemPositions = false;
1244
1240
  set$(ctx, "scrollingTo", void 0);
1245
1241
  if ((_a3 = state.props) == null ? void 0 : _a3.data) {
1246
- calculateItemsInView(ctx, state, { forceFullItemPositions: true });
1242
+ (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state, { forceFullItemPositions: true });
1247
1243
  }
1248
1244
  }
1249
1245
  }
@@ -1253,14 +1249,14 @@ var Platform2 = reactNative.Platform;
1253
1249
  function scrollTo(ctx, state, params) {
1254
1250
  var _a3;
1255
1251
  const { noScrollingTo, ...scrollTarget } = params;
1256
- const { animated, isInitialScroll, offset: scrollTargetOffset } = scrollTarget;
1252
+ const { animated, isInitialScroll, offset: scrollTargetOffset, precomputedWithViewOffset } = scrollTarget;
1257
1253
  const {
1258
1254
  refScroller,
1259
1255
  props: { horizontal }
1260
1256
  } = state;
1261
- let offset = calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1257
+ let offset = precomputedWithViewOffset ? scrollTargetOffset : calculateOffsetWithOffsetPosition(ctx, state, scrollTargetOffset, scrollTarget);
1262
1258
  if (Number.isFinite(state.scrollLength) && Number.isFinite(state.totalSize)) {
1263
- const maxOffset = Math.max(0, state.totalSize - state.scrollLength);
1259
+ const maxOffset = Math.max(0, getContentSize(ctx) - state.scrollLength);
1264
1260
  offset = Math.min(offset, maxOffset);
1265
1261
  }
1266
1262
  state.scrollHistory.length = 0;
@@ -1522,14 +1518,14 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1522
1518
  scrollBottomBuffered: -1,
1523
1519
  startIndex: 0
1524
1520
  }) {
1525
- var _a3, _b, _c, _d;
1521
+ var _a3, _b, _c, _d, _e;
1526
1522
  const {
1527
1523
  columns,
1528
1524
  indexByKey,
1529
1525
  positions,
1530
1526
  idCache,
1531
1527
  sizesKnown,
1532
- props: { getEstimatedItemSize, snapToIndices, enableAverages }
1528
+ props: { getEstimatedItemSize, snapToIndices, enableAverages, maintainVisibleContentPosition }
1533
1529
  } = state;
1534
1530
  const data = state.props.data;
1535
1531
  const dataLength = data.length;
@@ -1538,9 +1534,9 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1538
1534
  const hasColumns = numColumns > 1;
1539
1535
  const indexByKeyForChecking = IS_DEV ? /* @__PURE__ */ new Map() : void 0;
1540
1536
  const shouldOptimize = !forceFullUpdate && !dataChanged && Math.abs(getScrollVelocity(state)) > 0;
1541
- state.isOptimizingItemPositions = shouldOptimize;
1542
1537
  const maxVisibleArea = scrollBottomBuffered + 1e3;
1543
1538
  const useAverageSize = enableAverages && !getEstimatedItemSize;
1539
+ const preferCachedSize = maintainVisibleContentPosition && (dataChanged || state.scrollAdjustHandler.getAdjust() !== 0 || ((_a3 = peek$(ctx, "scrollAdjustPending")) != null ? _a3 : 0) !== 0);
1544
1540
  let currentRowTop = 0;
1545
1541
  let column = 1;
1546
1542
  let maxSizeInRow = 0;
@@ -1557,8 +1553,8 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1557
1553
  } else if (startIndex < dataLength) {
1558
1554
  const prevIndex = startIndex - 1;
1559
1555
  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);
1556
+ const prevPosition = (_b = positions.get(prevId)) != null ? _b : 0;
1557
+ const prevSize = (_c = sizesKnown.get(prevId)) != null ? _c : getItemSize(ctx, state, prevId, prevIndex, data[prevIndex], useAverageSize, preferCachedSize);
1562
1558
  currentRowTop = prevPosition + prevSize;
1563
1559
  }
1564
1560
  }
@@ -1574,8 +1570,8 @@ function updateItemPositions(ctx, state, dataChanged, { startIndex, scrollBottom
1574
1570
  const itemsPerRow = hasColumns ? numColumns : 1;
1575
1571
  breakAt = i + itemsPerRow + 10;
1576
1572
  }
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);
1573
+ const id = (_d = idCache[i]) != null ? _d : getId(state, i);
1574
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(ctx, state, id, i, data[i], useAverageSize, preferCachedSize);
1579
1575
  if (IS_DEV && needsIndexByKey) {
1580
1576
  if (indexByKeyForChecking.has(id)) {
1581
1577
  console.error(
@@ -1793,16 +1789,6 @@ function isViewable(state, ctx, viewabilityConfig, containerId, key, scrollSize,
1793
1789
  const value = ctx.mapViewabilityAmountValues.get(containerId) || computeViewability(state, ctx, viewabilityConfig, containerId, key, scrollSize, item, index);
1794
1790
  return value.isViewable;
1795
1791
  }
1796
- function findContainerId(ctx, key) {
1797
- const numContainers = peek$(ctx, "numContainers");
1798
- for (let i = 0; i < numContainers; i++) {
1799
- const itemKey = peek$(ctx, `containerItemKey${i}`);
1800
- if (itemKey === key) {
1801
- return i;
1802
- }
1803
- }
1804
- return -1;
1805
- }
1806
1792
  function maybeUpdateViewabilityCallback(ctx, configId, containerId, viewToken) {
1807
1793
  const key = containerId + configId;
1808
1794
  ctx.mapViewabilityValues.set(key, viewToken);
@@ -2335,7 +2321,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2335
2321
  for (let i = 0; i < numContainers; i++) {
2336
2322
  const itemKey = peek$(ctx, `containerItemKey${i}`);
2337
2323
  if (pendingRemoval.includes(i)) {
2338
- if (itemKey) {
2324
+ if (itemKey !== void 0) {
2339
2325
  containerItemKeys.delete(itemKey);
2340
2326
  }
2341
2327
  state.containerItemTypes.delete(i);
@@ -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: Math.max(0, 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({
@@ -3258,6 +3283,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3258
3283
  activeStickyIndex: state2.activeStickyIndex,
3259
3284
  contentLength: state2.totalSize,
3260
3285
  data: state2.props.data,
3286
+ elementAtIndex: (index) => {
3287
+ var _a4;
3288
+ return (_a4 = ctx.viewRefs.get(findContainerId(ctx, getId(state2, index)))) == null ? void 0 : _a4.current;
3289
+ },
3261
3290
  end: state2.endNoBuffer,
3262
3291
  endBuffered: state2.endBuffered,
3263
3292
  isAtEnd: state2.isAtEnd,