@legendapp/list 3.2.0 → 3.3.0

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.
@@ -1048,32 +1048,34 @@ function scheduleAdaptiveRenderExit(ctx, exitDelay) {
1048
1048
  const state = ctx.state;
1049
1049
  clearAdaptiveRenderExitTimeout(ctx);
1050
1050
  if (exitDelay <= 0) {
1051
- setAdaptiveRender(ctx, "normal");
1051
+ setAdaptiveRender(ctx, "normal", "scroll");
1052
1052
  } else {
1053
1053
  const timeout = setTimeout(() => {
1054
1054
  state.timeouts.delete(timeout);
1055
1055
  state.timeoutAdaptiveRender = void 0;
1056
- setAdaptiveRender(ctx, "normal");
1056
+ setAdaptiveRender(ctx, "normal", "scroll");
1057
1057
  }, exitDelay);
1058
1058
  state.timeoutAdaptiveRender = timeout;
1059
1059
  state.timeouts.add(timeout);
1060
1060
  }
1061
1061
  }
1062
- function setAdaptiveRender(ctx, mode) {
1062
+ function setAdaptiveRender(ctx, mode, reason) {
1063
1063
  var _a3, _b;
1064
1064
  const previousMode = peek$(ctx, "adaptiveRender");
1065
1065
  if (previousMode !== mode) {
1066
1066
  set$(ctx, "adaptiveRender", mode);
1067
- (_b = (_a3 = ctx.state.props.adaptiveRender) == null ? void 0 : _a3.onChange) == null ? void 0 : _b.call(_a3, mode);
1067
+ (_b = (_a3 = ctx.state.props.adaptiveRender) == null ? void 0 : _a3.onChange) == null ? void 0 : _b.call(_a3, mode, reason);
1068
1068
  }
1069
1069
  }
1070
1070
  function resetAdaptiveRender(ctx) {
1071
+ var _a3, _b;
1071
1072
  clearAdaptiveRenderExitTimeout(ctx);
1072
- if (peek$(ctx, "adaptiveRender") !== "normal") {
1073
- setAdaptiveRender(ctx, "normal");
1073
+ const mode = (_b = (_a3 = ctx.state.props.adaptiveRender) == null ? void 0 : _a3.initialMode) != null ? _b : "normal";
1074
+ if (peek$(ctx, "adaptiveRender") !== mode) {
1075
+ setAdaptiveRender(ctx, mode, "initial");
1074
1076
  }
1075
1077
  }
1076
- function updateAdaptiveRender(ctx, scrollVelocity) {
1078
+ function updateAdaptiveRender(ctx, scrollVelocity, options) {
1077
1079
  var _a3, _b, _c;
1078
1080
  const state = ctx.state;
1079
1081
  const adaptiveRender = state.props.adaptiveRender;
@@ -1084,11 +1086,11 @@ function updateAdaptiveRender(ctx, scrollVelocity) {
1084
1086
  const exitVelocity = (_b = adaptiveRender.exitVelocity) != null ? _b : DEFAULT_WEB_ADAPTIVE_RENDER_EXIT_VELOCITY ;
1085
1087
  const exitDelay = (_c = adaptiveRender.exitDelay) != null ? _c : DEFAULT_WEB_ADAPTIVE_RENDER_EXIT_DELAY ;
1086
1088
  const threshold = currentMode === "light" ? exitVelocity : enterVelocity;
1087
- const nextMode = Math.abs(scrollVelocity) > threshold ? "light" : "normal";
1089
+ const nextMode = (options == null ? void 0 : options.forceLight) || Math.abs(scrollVelocity) > threshold ? "light" : "normal";
1088
1090
  const previousMode = state.timeoutAdaptiveRender !== void 0 ? "normal" : currentMode;
1089
1091
  if (nextMode !== previousMode) {
1090
1092
  if (nextMode === "light") {
1091
- setAdaptiveRender(ctx, "light");
1093
+ setAdaptiveRender(ctx, "light", "scroll");
1092
1094
  scheduleAdaptiveRenderExit(ctx, exitDelay);
1093
1095
  } else if (currentMode === "light") {
1094
1096
  scheduleAdaptiveRenderExit(ctx, exitDelay);
@@ -1101,16 +1103,43 @@ function updateAdaptiveRender(ctx, scrollVelocity) {
1101
1103
  }
1102
1104
 
1103
1105
  // src/utils/getEffectiveDrawDistance.ts
1104
- var INITIAL_DRAW_DISTANCE = 100;
1105
- function getEffectiveDrawDistance(ctx) {
1106
+ var INITIAL_DRAW_DISTANCE = 50;
1107
+ function getEffectiveDrawDistance(ctx, mode) {
1106
1108
  var _a3;
1107
1109
  const drawDistance = ctx.state.props.drawDistance;
1108
1110
  const initialScroll = ctx.state.initialScroll;
1109
1111
  const needsFullInitialDrawDistance = initialScroll !== void 0 && ((_a3 = initialScroll.viewPosition) != null ? _a3 : 0) > 0;
1110
- return peek$(ctx, "readyToRender") || needsFullInitialDrawDistance ? drawDistance : Math.min(drawDistance, INITIAL_DRAW_DISTANCE);
1112
+ const shouldCapDrawDistance = mode === "visible-first" || mode !== "full" && !peek$(ctx, "readyToRender") && !needsFullInitialDrawDistance;
1113
+ return shouldCapDrawDistance ? Math.min(drawDistance, INITIAL_DRAW_DISTANCE) : drawDistance;
1114
+ }
1115
+ function scheduleFullDrawDistancePrewarm(ctx) {
1116
+ const { state } = ctx;
1117
+ if (state.props.drawDistance <= INITIAL_DRAW_DISTANCE || state.queuedFullDrawDistancePrewarm !== void 0) {
1118
+ return;
1119
+ }
1120
+ state.queuedFullDrawDistancePrewarm = requestAnimationFrame(() => {
1121
+ var _a3;
1122
+ state.queuedFullDrawDistancePrewarm = void 0;
1123
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state);
1124
+ });
1111
1125
  }
1112
1126
 
1113
1127
  // src/utils/setInitialRenderState.ts
1128
+ function resetInitialRenderState(ctx, {
1129
+ resetLayout,
1130
+ resetInitialScroll
1131
+ }) {
1132
+ const { state } = ctx;
1133
+ if (resetLayout) {
1134
+ state.didContainersLayout = false;
1135
+ state.queuedInitialLayout = false;
1136
+ }
1137
+ if (resetInitialScroll) {
1138
+ state.didFinishInitialScroll = false;
1139
+ }
1140
+ set$(ctx, "readyToRender", false);
1141
+ resetAdaptiveRender(ctx);
1142
+ }
1114
1143
  function setInitialRenderState(ctx, {
1115
1144
  didLayout,
1116
1145
  didInitialScroll
@@ -1129,15 +1158,15 @@ function setInitialRenderState(ctx, {
1129
1158
  const isReadyToRender = Boolean(state.didContainersLayout && state.didFinishInitialScroll);
1130
1159
  if (isReadyToRender && !peek$(ctx, "readyToRender")) {
1131
1160
  set$(ctx, "readyToRender", true);
1132
- setAdaptiveRender(ctx, "normal");
1161
+ setAdaptiveRender(ctx, "normal", "ready");
1133
1162
  if (state.props.drawDistance > INITIAL_DRAW_DISTANCE) {
1134
- requestAnimationFrame(() => {
1135
- var _a3;
1136
- (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state);
1137
- });
1163
+ scheduleFullDrawDistancePrewarm(ctx);
1138
1164
  }
1139
- if (onLoad) {
1140
- onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1165
+ if (!state.didLoad) {
1166
+ state.didLoad = true;
1167
+ if (onLoad) {
1168
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1169
+ }
1141
1170
  }
1142
1171
  }
1143
1172
  }
@@ -1561,8 +1590,8 @@ function doMaintainScrollAtEnd(ctx) {
1561
1590
  state.pendingMaintainScrollAtEnd = shouldMaintainScrollAtEnd;
1562
1591
  return false;
1563
1592
  }
1564
- state.pendingMaintainScrollAtEnd = false;
1565
1593
  if (shouldMaintainScrollAtEnd) {
1594
+ state.pendingMaintainScrollAtEnd = false;
1566
1595
  const contentSize = getContentSize(ctx);
1567
1596
  if (contentSize < state.scrollLength) {
1568
1597
  state.scroll = 0;
@@ -1593,6 +1622,9 @@ function doMaintainScrollAtEnd(ctx) {
1593
1622
  () => {
1594
1623
  if (state.maintainingScrollAtEnd === activeState) {
1595
1624
  state.maintainingScrollAtEnd = void 0;
1625
+ if (state.pendingMaintainScrollAtEnd) {
1626
+ doMaintainScrollAtEnd(ctx);
1627
+ }
1596
1628
  }
1597
1629
  },
1598
1630
  maintainScrollAtEnd.animated ? 500 : 0
@@ -1601,9 +1633,12 @@ function doMaintainScrollAtEnd(ctx) {
1601
1633
  state.maintainingScrollAtEnd = void 0;
1602
1634
  }
1603
1635
  });
1636
+ } else {
1637
+ state.pendingMaintainScrollAtEnd = true;
1604
1638
  }
1605
1639
  return true;
1606
1640
  }
1641
+ state.pendingMaintainScrollAtEnd = false;
1607
1642
  return false;
1608
1643
  }
1609
1644
 
@@ -1984,8 +2019,6 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
1984
2019
  if (scrollHistory.length > 5) {
1985
2020
  scrollHistory.shift();
1986
2021
  }
1987
- const scrollVelocity = getScrollVelocity(state);
1988
- updateAdaptiveRender(ctx, scrollVelocity);
1989
2022
  if (ignoreScrollFromMVCP && !scrollingTo) {
1990
2023
  const { lt, gt } = ignoreScrollFromMVCP;
1991
2024
  if (lt && newScroll < lt || gt && newScroll > gt) {
@@ -2000,6 +2033,9 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
2000
2033
  const scrollDelta = Math.abs(newScroll - prevScroll);
2001
2034
  const didResolvePendingNativeMVCPAdjust = resolvePendingNativeMVCPAdjust(ctx, newScroll);
2002
2035
  const scrollLength = state.scrollLength;
2036
+ const isLargeUserScrollJump = scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust;
2037
+ const scrollVelocity = getScrollVelocity(state);
2038
+ updateAdaptiveRender(ctx, scrollVelocity, { forceLight: isLargeUserScrollJump });
2003
2039
  const lastCalculated = state.scrollLastCalculate;
2004
2040
  const useAggressiveItemRecalculation = isInMVCPActiveMode(state);
2005
2041
  const shouldUpdate = useAggressiveItemRecalculation || didResolvePendingNativeMVCPAdjust || forceUpdate || lastCalculated === void 0 || Math.abs(state.scroll - lastCalculated) > 2;
@@ -2009,10 +2045,17 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
2009
2045
  state.lastScrollDelta = scrollDelta;
2010
2046
  const runCalculateItems = () => {
2011
2047
  var _a4;
2012
- (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, { doMVCP: scrollingTo !== void 0, scrollVelocity });
2048
+ const calculateItemsParams = {
2049
+ doMVCP: scrollingTo !== void 0,
2050
+ scrollVelocity
2051
+ };
2052
+ if (isLargeUserScrollJump) {
2053
+ calculateItemsParams.drawDistanceMode = "visible-first";
2054
+ }
2055
+ (_a4 = state.triggerCalculateItemsInView) == null ? void 0 : _a4.call(state, calculateItemsParams);
2013
2056
  checkThresholds(ctx);
2014
2057
  };
2015
- if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
2058
+ if (isLargeUserScrollJump) {
2016
2059
  state.mvcpAnchorLock = void 0;
2017
2060
  state.pendingNativeMVCPAdjust = void 0;
2018
2061
  state.userScrollAnchorReset = { keys: /* @__PURE__ */ new Set() };
@@ -2021,6 +2064,7 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
2021
2064
  state.queuedMVCPRecalculate = void 0;
2022
2065
  }
2023
2066
  flushSync(runCalculateItems);
2067
+ scheduleFullDrawDistancePrewarm(ctx);
2024
2068
  } else {
2025
2069
  runCalculateItems();
2026
2070
  }
@@ -2175,16 +2219,17 @@ function dispatchInitialScroll(ctx, params) {
2175
2219
  waitForInitialScrollCompletionFrame: waitForCompletionFrame
2176
2220
  });
2177
2221
  }
2178
- function setInitialScrollTarget(state, target, options) {
2222
+ function setInitialScrollTarget(ctx, target, options) {
2179
2223
  var _a3;
2224
+ const { state } = ctx;
2180
2225
  state.clearPreservedInitialScrollOnNextFinish = void 0;
2181
2226
  if (state.timeoutPreservedInitialScrollClear !== void 0) {
2182
2227
  clearTimeout(state.timeoutPreservedInitialScrollClear);
2183
2228
  state.timeoutPreservedInitialScrollClear = void 0;
2184
2229
  }
2185
2230
  state.initialScroll = target;
2186
- if ((options == null ? void 0 : options.resetDidFinish) && state.didFinishInitialScroll) {
2187
- state.didFinishInitialScroll = false;
2231
+ if (options == null ? void 0 : options.resetDidFinish) {
2232
+ resetInitialRenderState(ctx, { resetInitialScroll: true });
2188
2233
  }
2189
2234
  setInitialScrollSession(state, {
2190
2235
  kind: ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "offset" ? "offset" : "bootstrap"
@@ -2238,7 +2283,7 @@ function advanceMeasuredInitialScroll(ctx, options) {
2238
2283
  return false;
2239
2284
  }
2240
2285
  if (didOffsetChange && ((_b = state.initialScrollSession) == null ? void 0 : _b.kind) !== "offset") {
2241
- setInitialScrollTarget(state, { ...initialScroll, contentOffset: resolvedOffset });
2286
+ setInitialScrollTarget(ctx, { ...initialScroll, contentOffset: resolvedOffset });
2242
2287
  }
2243
2288
  const forceScroll = (_c = options == null ? void 0 : options.forceScroll) != null ? _c : !!queuedInitialLayout || isInitialScrollInProgress && didOffsetChange;
2244
2289
  dispatchInitialScroll(ctx, {
@@ -2511,7 +2556,6 @@ function areEquivalentBootstrapInitialScrollTargets(current, next) {
2511
2556
  }
2512
2557
  function clearPendingInitialScrollFooterLayout(ctx, options) {
2513
2558
  const { dataLength, stylePaddingBottom, target } = options;
2514
- const state = ctx.state;
2515
2559
  if (!shouldPreserveInitialScrollForFooterLayout(target)) {
2516
2560
  return;
2517
2561
  }
@@ -2521,7 +2565,7 @@ function clearPendingInitialScrollFooterLayout(ctx, options) {
2521
2565
  preserveForFooterLayout: void 0,
2522
2566
  stylePaddingBottom
2523
2567
  });
2524
- setInitialScrollTarget(state, clearedFooterTarget);
2568
+ setInitialScrollTarget(ctx, clearedFooterTarget);
2525
2569
  }
2526
2570
  function clearFinishedViewportRetargetableInitialScroll(state) {
2527
2571
  clearPreservedInitialScrollTarget(state);
@@ -2668,7 +2712,7 @@ function handleBootstrapInitialScrollDataChange(ctx, options) {
2668
2712
  return;
2669
2713
  }
2670
2714
  if (!areEquivalentBootstrapInitialScrollTargets(initialScroll, updatedInitialScroll) || !!bootstrapInitialScroll || shouldResetDidFinish || didDataChange) {
2671
- setInitialScrollTarget(state, updatedInitialScroll, {
2715
+ setInitialScrollTarget(ctx, updatedInitialScroll, {
2672
2716
  resetDidFinish: shouldResetDidFinish
2673
2717
  });
2674
2718
  rearmBootstrapInitialScroll(ctx, {
@@ -2683,7 +2727,7 @@ function handleBootstrapInitialScrollDataChange(ctx, options) {
2683
2727
  return;
2684
2728
  }
2685
2729
  if (bootstrapInitialScroll || shouldResetDidFinish) {
2686
- setInitialScrollTarget(state, initialScroll, {
2730
+ setInitialScrollTarget(ctx, initialScroll, {
2687
2731
  resetDidFinish: shouldResetDidFinish
2688
2732
  });
2689
2733
  rearmBootstrapInitialScroll(ctx, {
@@ -2729,7 +2773,7 @@ function handleBootstrapInitialScrollFooterLayout(ctx, options) {
2729
2773
  });
2730
2774
  } else {
2731
2775
  const didFinishInitialScroll = !!state.didFinishInitialScroll;
2732
- setInitialScrollTarget(state, updatedInitialScroll, {
2776
+ setInitialScrollTarget(ctx, updatedInitialScroll, {
2733
2777
  resetDidFinish: didFinishInitialScroll
2734
2778
  });
2735
2779
  rearmBootstrapInitialScroll(ctx, {
@@ -3063,7 +3107,7 @@ function initializeInitialScrollOnMount(ctx, options) {
3063
3107
  const resolvedInitialContentOffset = initialContentOffset != null ? initialContentOffset : 0;
3064
3108
  const preserveForFooterLayout = useBootstrapInitialScroll && initialScrollAtEnd && hasFooterComponent;
3065
3109
  if (initialScroll && (initialScroll.contentOffset === void 0 || !!initialScroll.preserveForFooterLayout !== preserveForFooterLayout && ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) !== "offset")) {
3066
- setInitialScrollTarget(state, {
3110
+ setInitialScrollTarget(ctx, {
3067
3111
  ...initialScroll,
3068
3112
  contentOffset: resolvedInitialContentOffset,
3069
3113
  preserveForFooterLayout
@@ -3092,6 +3136,7 @@ function handleInitialScrollDataChange(ctx, options) {
3092
3136
  const {
3093
3137
  dataLength,
3094
3138
  didDataChange,
3139
+ didStartFreshData,
3095
3140
  initialScrollAtEnd,
3096
3141
  latestInitialScroll,
3097
3142
  latestInitialScrollSessionKind,
@@ -3099,17 +3144,17 @@ function handleInitialScrollDataChange(ctx, options) {
3099
3144
  useBootstrapInitialScroll
3100
3145
  } = options;
3101
3146
  const state = ctx.state;
3102
- const previousDataLength = (_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.previousDataLength) != null ? _b : 0;
3103
- const isFirstNonEmptyData = !state.hasHadNonEmptyData && dataLength > 0;
3147
+ const previousInitialScrollDataLength = (_b = (_a3 = state.initialScrollSession) == null ? void 0 : _a3.previousDataLength) != null ? _b : 0;
3148
+ const shouldUseLatestInitialScroll = dataLength > 0 && (!state.hasHadNonEmptyData || didStartFreshData);
3104
3149
  if (dataLength > 0) {
3105
3150
  state.hasHadNonEmptyData = true;
3106
3151
  }
3107
- if (isFirstNonEmptyData) {
3152
+ if (shouldUseLatestInitialScroll) {
3108
3153
  if (latestInitialScroll) {
3109
- setInitialScrollTarget(state, latestInitialScroll);
3154
+ setInitialScrollTarget(ctx, latestInitialScroll);
3110
3155
  setInitialScrollSession(state, {
3111
3156
  kind: latestInitialScrollSessionKind,
3112
- previousDataLength
3157
+ previousDataLength: previousInitialScrollDataLength
3113
3158
  });
3114
3159
  } else {
3115
3160
  clearPreservedInitialScrollTarget(state);
@@ -3124,17 +3169,17 @@ function handleInitialScrollDataChange(ctx, options) {
3124
3169
  dataLength,
3125
3170
  didDataChange,
3126
3171
  initialScrollAtEnd,
3127
- previousDataLength,
3172
+ previousDataLength: previousInitialScrollDataLength,
3128
3173
  stylePaddingBottom
3129
3174
  });
3130
3175
  return;
3131
3176
  }
3132
- const shouldReplayFinishedOffsetInitialScroll = previousDataLength === 0 && dataLength > 0 && !!state.initialScroll && ((_c = ctx.state.initialScrollSession) == null ? void 0 : _c.kind) === "offset" && !!state.didFinishInitialScroll;
3133
- if (previousDataLength !== 0 || dataLength === 0 || !state.initialScroll || !state.queuedInitialLayout || state.didFinishInitialScroll && !shouldReplayFinishedOffsetInitialScroll) {
3177
+ const shouldReplayFinishedOffsetInitialScroll = previousInitialScrollDataLength === 0 && dataLength > 0 && !!state.initialScroll && ((_c = ctx.state.initialScrollSession) == null ? void 0 : _c.kind) === "offset" && !!state.didFinishInitialScroll;
3178
+ if (previousInitialScrollDataLength !== 0 || dataLength === 0 || !state.initialScroll || !state.queuedInitialLayout || state.didFinishInitialScroll && !shouldReplayFinishedOffsetInitialScroll) {
3134
3179
  return;
3135
3180
  }
3136
3181
  if (shouldReplayFinishedOffsetInitialScroll) {
3137
- state.didFinishInitialScroll = false;
3182
+ resetInitialRenderState(ctx, { resetInitialScroll: true });
3138
3183
  }
3139
3184
  advanceCurrentInitialScrollSession(ctx);
3140
3185
  }
@@ -4133,7 +4178,7 @@ function calculateItemsInView(ctx, params = {}) {
4133
4178
  const stickyHeaderIndicesSet = state.props.stickyHeaderIndicesSet || /* @__PURE__ */ new Set();
4134
4179
  const alwaysRenderArr = alwaysRenderIndicesArr || [];
4135
4180
  const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
4136
- const drawDistance = getEffectiveDrawDistance(ctx);
4181
+ const drawDistance = getEffectiveDrawDistance(ctx, params.drawDistanceMode);
4137
4182
  const { dataChanged, doMVCP, forceFullItemPositions } = params;
4138
4183
  const bootstrapInitialScrollState = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" ? state.initialScrollSession.bootstrap : void 0;
4139
4184
  const suppressInitialScrollSideEffects = !!bootstrapInitialScrollState;
@@ -7046,7 +7091,7 @@ var LegendList = typedMemo(
7046
7091
  })
7047
7092
  );
7048
7093
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
7049
- var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
7094
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
7050
7095
  const noopOnScroll = useCallback((_event) => {
7051
7096
  }, []);
7052
7097
  if (props.recycleItems === void 0) {
@@ -7063,6 +7108,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7063
7108
  contentContainerStyle: contentContainerStyleProp,
7064
7109
  contentInset,
7065
7110
  data: dataProp = [],
7111
+ dataKey,
7066
7112
  dataVersion,
7067
7113
  drawDistance = 250,
7068
7114
  contentInsetEndAdjustment,
@@ -7193,6 +7239,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7193
7239
  (_j = alwaysRender == null ? void 0 : alwaysRender.indices) == null ? void 0 : _j.join(","),
7194
7240
  (_k = alwaysRender == null ? void 0 : alwaysRender.keys) == null ? void 0 : _k.join(","),
7195
7241
  dataProp,
7242
+ dataKey,
7196
7243
  dataVersion,
7197
7244
  keyExtractor
7198
7245
  ]);
@@ -7215,6 +7262,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7215
7262
  dataChangeNeedsScrollUpdate: false,
7216
7263
  didColumnsChange: false,
7217
7264
  didDataChange: false,
7265
+ didLoad: false,
7218
7266
  enableScrollForNextCalculateItemsInView: true,
7219
7267
  endBuffered: -1,
7220
7268
  endNoBuffer: -1,
@@ -7244,6 +7292,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7244
7292
  positions: [],
7245
7293
  props: {},
7246
7294
  queuedCalculateItemsInView: 0,
7295
+ queuedFullDrawDistancePrewarm: void 0,
7247
7296
  refScroller: { current: null },
7248
7297
  scroll: 0,
7249
7298
  scrollAdjustHandler: new ScrollAdjustHandler(ctx),
@@ -7286,10 +7335,13 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7286
7335
  const didScrollAxisGapChange = !isFirstLocal && ctx.scrollAxisGap !== nextScrollAxisGap;
7287
7336
  ctx.scrollAxisGap = nextScrollAxisGap;
7288
7337
  state.didColumnsChange = numColumnsProp !== previousNumColumnsProp || didScrollAxisGapChange;
7338
+ const previousDataLength = (_n = (_m = state.props.data) == null ? void 0 : _m.length) != null ? _n : 0;
7289
7339
  const didDataReferenceChangeLocal = state.props.data !== dataProp;
7340
+ const didDataKeyChangeLocal = state.props.dataKey !== dataKey;
7290
7341
  const didDataVersionChangeLocal = state.props.dataVersion !== dataVersion;
7291
- const didDataChangeLocal = didDataVersionChangeLocal || didDataReferenceChangeLocal && checkStructuralDataChange(state, dataProp, state.props.data);
7292
- if (didDataChangeLocal && !initialScrollAtEnd && state.didFinishInitialScroll && ((_m = state.initialScroll) == null ? void 0 : _m.viewPosition) === 1 && state.props.data.length > 0) {
7342
+ const didDataChangeLocal = didDataKeyChangeLocal || didDataVersionChangeLocal || didDataReferenceChangeLocal && checkStructuralDataChange(state, dataProp, state.props.data);
7343
+ const shouldResetFreshDataLayout = !isFirstLocal && didDataChangeLocal && state.hasHadNonEmptyData && (didDataKeyChangeLocal || previousDataLength === 0) && dataProp.length > 0;
7344
+ if (didDataChangeLocal && !initialScrollAtEnd && state.didFinishInitialScroll && ((_o = state.initialScroll) == null ? void 0 : _o.viewPosition) === 1 && state.props.data.length > 0) {
7293
7345
  clearPreservedInitialScrollTarget(state);
7294
7346
  }
7295
7347
  if (didDataChangeLocal) {
@@ -7301,7 +7353,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7301
7353
  const throttledOnScroll = useThrottledOnScroll(onScrollProp != null ? onScrollProp : noopOnScroll, scrollEventThrottle != null ? scrollEventThrottle : 0);
7302
7354
  const throttleScrollFn = scrollEventThrottle && onScrollProp ? throttledOnScroll : onScrollProp;
7303
7355
  const anchoredEndSpaceResolved = anchoredEndSpace ? { ...anchoredEndSpace, includeInEndInset: true } : anchoredEndSpace;
7304
- const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_n = state.props.anchoredEndSpace) == null ? void 0 : _n.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
7356
+ const didAnchoredEndSpaceAnchorIndexChange = !isFirstLocal && !didDataChangeLocal && ((_p = state.props.anchoredEndSpace) == null ? void 0 : _p.anchorIndex) !== (anchoredEndSpaceResolved == null ? void 0 : anchoredEndSpaceResolved.anchorIndex);
7305
7357
  state.props = {
7306
7358
  adaptiveRender: experimental_adaptiveRender,
7307
7359
  alignItemsAtEnd,
@@ -7315,6 +7367,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7315
7367
  contentInset,
7316
7368
  contentInsetEndAdjustment: contentInsetEndAdjustmentResolved,
7317
7369
  data: dataProp,
7370
+ dataKey,
7318
7371
  dataVersion,
7319
7372
  drawDistance,
7320
7373
  estimatedItemSize,
@@ -7355,13 +7408,19 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7355
7408
  if (!isFirstLocal && previousAdaptiveRender && !experimental_adaptiveRender) {
7356
7409
  resetAdaptiveRender(ctx);
7357
7410
  }
7411
+ if (shouldResetFreshDataLayout) {
7412
+ resetInitialRenderState(ctx, {
7413
+ resetInitialScroll: !!initialScrollProp,
7414
+ resetLayout: true
7415
+ });
7416
+ }
7358
7417
  const memoizedLastItemKeys = useMemo(() => {
7359
7418
  if (!dataProp.length) return [];
7360
7419
  return Array.from(
7361
7420
  { length: Math.min(numColumnsProp, dataProp.length) },
7362
7421
  (_, i) => getId(state, dataProp.length - 1 - i)
7363
7422
  );
7364
- }, [dataProp, dataVersion, numColumnsProp]);
7423
+ }, [dataProp, dataKey, dataVersion, numColumnsProp]);
7365
7424
  const initializeStateVars = (shouldAdjustPadding) => {
7366
7425
  set$(ctx, "lastItemKeys", memoizedLastItemKeys);
7367
7426
  set$(ctx, "numColumns", numColumnsProp);
@@ -7416,13 +7475,22 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7416
7475
  handleInitialScrollDataChange(ctx, {
7417
7476
  dataLength: dataProp.length,
7418
7477
  didDataChange: didDataChangeLocal,
7478
+ didStartFreshData: shouldResetFreshDataLayout,
7419
7479
  initialScrollAtEnd,
7420
7480
  latestInitialScroll: initialScrollProp,
7421
7481
  latestInitialScrollSessionKind: initialScrollUsesOffsetOnly ? "offset" : "bootstrap",
7422
7482
  stylePaddingBottom: stylePaddingBottomState,
7423
7483
  useBootstrapInitialScroll: usesBootstrapInitialScroll
7424
7484
  });
7425
- }, [dataProp.length, didDataChangeLocal, initialScrollAtEnd, stylePaddingBottomState, usesBootstrapInitialScroll]);
7485
+ }, [
7486
+ dataProp.length,
7487
+ dataKey,
7488
+ didDataChangeLocal,
7489
+ shouldResetFreshDataLayout,
7490
+ initialScrollAtEnd,
7491
+ stylePaddingBottomState,
7492
+ usesBootstrapInitialScroll
7493
+ ]);
7426
7494
  useLayoutEffect(() => {
7427
7495
  var _a4;
7428
7496
  if (didAnchoredEndSpaceAnchorIndexChange) {
@@ -7490,6 +7558,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7490
7558
  useLayoutEffect(
7491
7559
  () => initializeStateVars(true),
7492
7560
  [
7561
+ dataKey,
7493
7562
  dataVersion,
7494
7563
  memoizedLastItemKeys.join(","),
7495
7564
  numColumnsProp,
@@ -7516,7 +7585,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7516
7585
  state.didColumnsChange = false;
7517
7586
  state.didDataChange = false;
7518
7587
  state.isFirst = false;
7519
- }, [dataProp, dataVersion, numColumnsProp, nextScrollAxisGap]);
7588
+ }, [dataProp, dataKey, dataVersion, numColumnsProp, nextScrollAxisGap]);
7520
7589
  useLayoutEffect(() => {
7521
7590
  var _a4;
7522
7591
  set$(ctx, "extraData", extraData);
@@ -7566,6 +7635,10 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7566
7635
  useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, scheduleImperativeScrollCommit), []);
7567
7636
  useEffect(() => {
7568
7637
  return () => {
7638
+ if (state.queuedFullDrawDistancePrewarm !== void 0) {
7639
+ cancelAnimationFrame(state.queuedFullDrawDistancePrewarm);
7640
+ state.queuedFullDrawDistancePrewarm = void 0;
7641
+ }
7569
7642
  for (const timeout of state.timeouts) {
7570
7643
  clearTimeout(timeout);
7571
7644
  }
@@ -7618,7 +7691,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7618
7691
  onScroll: onScrollHandler,
7619
7692
  recycleItems,
7620
7693
  refreshControl: refreshControlElement ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControlElement, {
7621
- progressViewOffset: ((_o = refreshControlElement.props.progressViewOffset) != null ? _o : 0) + stylePaddingTopState
7694
+ progressViewOffset: ((_q = refreshControlElement.props.progressViewOffset) != null ? _q : 0) + stylePaddingTopState
7622
7695
  }) : refreshControlElement : onRefresh && /* @__PURE__ */ React3.createElement(
7623
7696
  RefreshControl,
7624
7697
  {
@@ -7629,7 +7702,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
7629
7702
  ),
7630
7703
  refScrollView: combinedRef,
7631
7704
  renderScrollComponent,
7632
- scrollAdjustHandler: (_p = refState.current) == null ? void 0 : _p.scrollAdjustHandler,
7705
+ scrollAdjustHandler: (_r = refState.current) == null ? void 0 : _r.scrollAdjustHandler,
7633
7706
  scrollEventThrottle: 0,
7634
7707
  snapToIndices,
7635
7708
  stickyHeaderIndices,
package/react.d.ts CHANGED
@@ -115,6 +115,7 @@ interface NativeSyntheticEvent<T> {
115
115
  type ViewStyle = Record<string, unknown>;
116
116
  type StyleProp<T> = T | T[] | null | undefined | false;
117
117
  type AdaptiveRender = "normal" | "light";
118
+ type AdaptiveRenderChangeReason = "initial" | "ready" | "scroll";
118
119
  interface AdaptiveRenderConfig {
119
120
  /**
120
121
  * Mode to use before the list is ready to render.
@@ -139,7 +140,7 @@ interface AdaptiveRenderConfig {
139
140
  /**
140
141
  * Called when the list-level adaptive render changes.
141
142
  */
142
- onChange?: (mode: AdaptiveRender) => void;
143
+ onChange?: (mode: AdaptiveRender, reason: AdaptiveRenderChangeReason) => void;
143
144
  }
144
145
  type BaseScrollViewProps<TScrollView> = Omit<TScrollView, "contentOffset" | "maintainVisibleContentPosition" | "stickyHeaderIndices" | "removeClippedSubviews" | "children" | "onScroll">;
145
146
  interface DataModeProps<ItemT, TItemType extends string | undefined> {
@@ -181,6 +182,11 @@ interface LegendListSpecificProps<ItemT, TItemType extends string | undefined> {
181
182
  * Style applied to each column's wrapper view.
182
183
  */
183
184
  columnWrapperStyle?: ColumnWrapperStyle;
185
+ /**
186
+ * Identity token for the dataset represented by `data`.
187
+ * Change this when replacing the current dataset with a different logical dataset.
188
+ */
189
+ dataKey?: Key;
184
190
  /**
185
191
  * Version token that forces the list to treat data as updated even when the array reference is stable.
186
192
  * Increment or change this when mutating the data array in place.
@@ -826,4 +832,4 @@ declare function useSyncLayout(): () => void;
826
832
 
827
833
  declare const LegendList: LegendListComponent;
828
834
 
829
- export { type AdaptiveRender, type AdaptiveRenderConfig, type AlwaysRenderConfig, type AnchoredEndSpaceConfig, type ColumnWrapperStyle, type Insets, type LayoutRectangle, LegendList, type LegendListAverageItemSize, type LegendListComponent, type LegendListMetrics, type LegendListProps, type LegendListRecyclingState, type LegendListRef, type LegendListRenderItemProps, type LegendListState, type MaintainScrollAtEndOnOptions, type MaintainScrollAtEndOptions, type MaintainVisibleContentPositionConfig, type NativeScrollEvent, type NativeSyntheticEvent, type OnViewableItemsChanged, type OnViewableItemsChangedInfo, type ScrollIndexWithOffset, type ScrollIndexWithOffsetAndContentOffset, type ScrollIndexWithOffsetPosition, type StickyHeaderConfig, type StyleProp, type ViewAmountToken, type ViewStyle, type ViewToken, type ViewabilityAmountCallback, type ViewabilityCallback, type ViewabilityConfig, type ViewabilityConfigCallbackPair, type ViewabilityConfigCallbackPairs, useAdaptiveRender, useAdaptiveRenderChange, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };
835
+ export { type AdaptiveRender, type AdaptiveRenderChangeReason, type AdaptiveRenderConfig, type AlwaysRenderConfig, type AnchoredEndSpaceConfig, type ColumnWrapperStyle, type Insets, type LayoutRectangle, LegendList, type LegendListAverageItemSize, type LegendListComponent, type LegendListMetrics, type LegendListProps, type LegendListRecyclingState, type LegendListRef, type LegendListRenderItemProps, type LegendListState, type MaintainScrollAtEndOnOptions, type MaintainScrollAtEndOptions, type MaintainVisibleContentPositionConfig, type NativeScrollEvent, type NativeSyntheticEvent, type OnViewableItemsChanged, type OnViewableItemsChangedInfo, type ScrollIndexWithOffset, type ScrollIndexWithOffsetAndContentOffset, type ScrollIndexWithOffsetPosition, type StickyHeaderConfig, type StyleProp, type ViewAmountToken, type ViewStyle, type ViewToken, type ViewabilityAmountCallback, type ViewabilityCallback, type ViewabilityConfig, type ViewabilityConfigCallbackPair, type ViewabilityConfigCallbackPairs, useAdaptiveRender, useAdaptiveRenderChange, useIsLastItem, useListScrollSize, useRecyclingEffect, useRecyclingState, useSyncLayout, useViewability, useViewabilityAmount };