@legendapp/list 2.0.0 → 2.0.1

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.d.mts CHANGED
@@ -345,6 +345,11 @@ interface InternalState {
345
345
  animated?: boolean;
346
346
  } | undefined;
347
347
  needsOtherAxisSize?: boolean;
348
+ positionRange: {
349
+ start: number;
350
+ end: number;
351
+ valid: boolean;
352
+ };
348
353
  averageSizes: Record<string, {
349
354
  num: number;
350
355
  avg: number;
@@ -414,11 +419,11 @@ type ScrollState = {
414
419
  endBuffered: number;
415
420
  isAtEnd: boolean;
416
421
  isAtStart: boolean;
417
- positionAtIndex: (index: number) => number;
422
+ positionAtIndex: (index: number) => number | undefined;
418
423
  positions: Map<string, number>;
419
424
  scroll: number;
420
425
  scrollLength: number;
421
- sizeAtIndex: (index: number) => number;
426
+ sizeAtIndex: (index: number) => number | undefined;
422
427
  sizes: Map<string, number>;
423
428
  start: number;
424
429
  startBuffered: number;
package/index.d.ts CHANGED
@@ -345,6 +345,11 @@ interface InternalState {
345
345
  animated?: boolean;
346
346
  } | undefined;
347
347
  needsOtherAxisSize?: boolean;
348
+ positionRange: {
349
+ start: number;
350
+ end: number;
351
+ valid: boolean;
352
+ };
348
353
  averageSizes: Record<string, {
349
354
  num: number;
350
355
  avg: number;
@@ -414,11 +419,11 @@ type ScrollState = {
414
419
  endBuffered: number;
415
420
  isAtEnd: boolean;
416
421
  isAtStart: boolean;
417
- positionAtIndex: (index: number) => number;
422
+ positionAtIndex: (index: number) => number | undefined;
418
423
  positions: Map<string, number>;
419
424
  scroll: number;
420
425
  scrollLength: number;
421
- sizeAtIndex: (index: number) => number;
426
+ sizeAtIndex: (index: number) => number | undefined;
422
427
  sizes: Map<string, number>;
423
428
  start: number;
424
429
  startBuffered: number;
package/index.js CHANGED
@@ -897,23 +897,6 @@ function getId(state, index) {
897
897
  return id;
898
898
  }
899
899
 
900
- // src/core/calculateOffsetForIndex.ts
901
- function calculateOffsetForIndex(ctx, state, index) {
902
- let position = 0;
903
- if (index !== void 0) {
904
- position = (state == null ? void 0 : state.positions.get(getId(state, index))) || 0;
905
- const paddingTop = peek$(ctx, "stylePaddingTop");
906
- if (paddingTop) {
907
- position += paddingTop;
908
- }
909
- const headerSize = peek$(ctx, "headerSize");
910
- if (headerSize) {
911
- position += headerSize;
912
- }
913
- }
914
- return position;
915
- }
916
-
917
900
  // src/utils/getItemSize.ts
918
901
  function getItemSize(state, key, index, data, useAverageSize) {
919
902
  var _a, _b;
@@ -955,152 +938,6 @@ function getItemSize(state, key, index, data, useAverageSize) {
955
938
  return size;
956
939
  }
957
940
 
958
- // src/core/calculateOffsetWithOffsetPosition.ts
959
- function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
960
- const { index, viewOffset, viewPosition } = params;
961
- let offset = offsetParam;
962
- if (viewOffset) {
963
- offset -= viewOffset;
964
- }
965
- if (viewPosition !== void 0 && index !== void 0) {
966
- offset -= viewPosition * (state.scrollLength - getItemSize(state, getId(state, index), index, state.props.data[index]));
967
- }
968
- return offset;
969
- }
970
-
971
- // src/core/finishScrollTo.ts
972
- var finishScrollTo = (state) => {
973
- if (state) {
974
- state.scrollingTo = void 0;
975
- state.scrollHistory.length = 0;
976
- }
977
- };
978
-
979
- // src/core/scrollTo.ts
980
- function scrollTo(state, params = {}) {
981
- var _a;
982
- const { animated, noScrollingTo } = params;
983
- const {
984
- refScroller,
985
- props: { horizontal }
986
- } = state;
987
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
988
- state.scrollHistory.length = 0;
989
- if (!noScrollingTo) {
990
- state.scrollingTo = params;
991
- }
992
- state.scrollPending = offset;
993
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
994
- animated: !!animated,
995
- x: horizontal ? offset : 0,
996
- y: horizontal ? 0 : offset
997
- });
998
- if (!animated) {
999
- state.scroll = offset;
1000
- setTimeout(() => finishScrollTo(state), 100);
1001
- }
1002
- }
1003
-
1004
- // src/utils/requestAdjust.ts
1005
- function requestAdjust(ctx, state, positionDiff, dataChanged) {
1006
- if (Math.abs(positionDiff) > 0.1) {
1007
- const needsScrollWorkaround = reactNative.Platform.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
1008
- const doit = () => {
1009
- if (needsScrollWorkaround) {
1010
- scrollTo(state, {
1011
- noScrollingTo: true,
1012
- offset: state.scroll
1013
- });
1014
- } else {
1015
- state.scrollAdjustHandler.requestAdjust(positionDiff);
1016
- }
1017
- };
1018
- state.scroll += positionDiff;
1019
- state.scrollForNextCalculateItemsInView = void 0;
1020
- const didLayout = peek$(ctx, "containersDidLayout");
1021
- if (didLayout) {
1022
- doit();
1023
- const threshold = state.scroll - positionDiff / 2;
1024
- if (!state.ignoreScrollFromMVCP) {
1025
- state.ignoreScrollFromMVCP = {};
1026
- }
1027
- if (positionDiff > 0) {
1028
- state.ignoreScrollFromMVCP.lt = threshold;
1029
- } else {
1030
- state.ignoreScrollFromMVCP.gt = threshold;
1031
- }
1032
- if (state.ignoreScrollFromMVCPTimeout) {
1033
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
1034
- }
1035
- state.ignoreScrollFromMVCPTimeout = setTimeout(
1036
- () => {
1037
- state.ignoreScrollFromMVCP = void 0;
1038
- },
1039
- needsScrollWorkaround ? 250 : 100
1040
- );
1041
- } else {
1042
- requestAnimationFrame(doit);
1043
- }
1044
- }
1045
- }
1046
-
1047
- // src/core/mvcp.ts
1048
- function prepareMVCP(ctx, state, dataChanged) {
1049
- const {
1050
- idsInView,
1051
- positions,
1052
- scrollingTo,
1053
- props: { maintainVisibleContentPosition }
1054
- } = state;
1055
- let prevPosition;
1056
- let targetId;
1057
- const idsInViewWithPositions = [];
1058
- const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1059
- if (maintainVisibleContentPosition) {
1060
- const indexByKey = state.indexByKey;
1061
- if (scrollTarget !== void 0) {
1062
- targetId = getId(state, scrollTarget);
1063
- } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1064
- if (dataChanged) {
1065
- for (let i = 0; i < idsInView.length; i++) {
1066
- const id = idsInView[i];
1067
- const index = indexByKey.get(id);
1068
- if (index !== void 0) {
1069
- idsInViewWithPositions.push({ id, position: positions.get(id) });
1070
- }
1071
- }
1072
- } else {
1073
- targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
1074
- }
1075
- }
1076
- if (targetId !== void 0) {
1077
- prevPosition = positions.get(targetId);
1078
- }
1079
- }
1080
- return () => {
1081
- let positionDiff;
1082
- if (dataChanged && targetId === void 0) {
1083
- for (let i = 0; i < idsInViewWithPositions.length; i++) {
1084
- const { id, position } = idsInViewWithPositions[i];
1085
- const newPosition = positions.get(id);
1086
- if (newPosition !== void 0) {
1087
- positionDiff = newPosition - position;
1088
- break;
1089
- }
1090
- }
1091
- }
1092
- if (targetId !== void 0 && prevPosition !== void 0) {
1093
- const newPosition = positions.get(targetId);
1094
- if (newPosition !== void 0) {
1095
- positionDiff = newPosition - prevPosition;
1096
- }
1097
- }
1098
- if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1099
- requestAdjust(ctx, state, positionDiff, dataChanged);
1100
- }
1101
- };
1102
- }
1103
-
1104
941
  // src/utils/setPaddingTop.ts
1105
942
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1106
943
  if (stylePaddingTop !== void 0) {
@@ -1139,15 +976,15 @@ function updateAlignItemsPaddingTop(ctx, state) {
1139
976
  // src/core/updateTotalSize.ts
1140
977
  function updateTotalSize(ctx, state) {
1141
978
  const {
1142
- positions,
1143
979
  props: { data }
1144
980
  } = state;
1145
981
  if (data.length === 0) {
1146
982
  addTotalSize(ctx, state, null, 0);
1147
983
  } else {
1148
- const lastId = getId(state, data.length - 1);
984
+ const lastIndex = data.length - 1;
985
+ const lastId = getId(state, lastIndex);
1149
986
  if (lastId !== void 0) {
1150
- const lastPosition = positions.get(lastId);
987
+ const lastPosition = getPositionByIndex(ctx, state, lastIndex);
1151
988
  if (lastPosition !== void 0) {
1152
989
  const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
1153
990
  if (lastSize !== void 0) {
@@ -1176,21 +1013,60 @@ function addTotalSize(ctx, state, key, add) {
1176
1013
  // src/utils/updateSnapToOffsets.ts
1177
1014
  function updateSnapToOffsets(ctx, state) {
1178
1015
  const {
1179
- positions,
1180
1016
  props: { snapToIndices }
1181
1017
  } = state;
1182
1018
  const snapToOffsets = Array(snapToIndices.length);
1183
1019
  for (let i = 0; i < snapToIndices.length; i++) {
1184
1020
  const idx = snapToIndices[i];
1185
- const key = getId(state, idx);
1186
- snapToOffsets[i] = positions.get(key);
1021
+ snapToOffsets[i] = getPositionByIndex(ctx, state, idx) || 0;
1187
1022
  }
1188
1023
  set$(ctx, "snapToOffsets", snapToOffsets);
1189
1024
  }
1190
1025
 
1191
- // src/core/updateAllPositions.ts
1192
- function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1193
- var _a, _b, _c, _d, _e, _f;
1026
+ // src/core/updateItemPositions.ts
1027
+ function getRequiredRange(_ctx, state) {
1028
+ var _a;
1029
+ const bufferSize = 10;
1030
+ const dataLength = state.props.data.length;
1031
+ let minIndex = 0;
1032
+ let maxIndex = dataLength - 1;
1033
+ if (dataLength < 500) {
1034
+ return { end: maxIndex, start: 0 };
1035
+ }
1036
+ const hasVisibleRange = state.startBuffered >= 0 && state.endBuffered >= 0;
1037
+ if (hasVisibleRange) {
1038
+ minIndex = state.startBuffered;
1039
+ maxIndex = state.endBuffered;
1040
+ }
1041
+ if (((_a = state.scrollingTo) == null ? void 0 : _a.index) !== void 0) {
1042
+ if (hasVisibleRange) {
1043
+ minIndex = Math.min(minIndex, state.scrollingTo.index);
1044
+ maxIndex = Math.max(maxIndex, state.scrollingTo.index);
1045
+ } else {
1046
+ minIndex = state.scrollingTo.index;
1047
+ maxIndex = state.scrollingTo.index;
1048
+ }
1049
+ }
1050
+ minIndex = Math.max(0, minIndex - bufferSize);
1051
+ maxIndex = Math.min(dataLength - 1, maxIndex + bufferSize);
1052
+ return { end: maxIndex, start: minIndex };
1053
+ }
1054
+ function ensurePositionCalculated(ctx, state, index) {
1055
+ if (!state.positionRange) {
1056
+ state.positionRange = { end: -1, start: 0, valid: false };
1057
+ }
1058
+ if (state.positionRange.valid && index >= state.positionRange.start && index <= state.positionRange.end) {
1059
+ return;
1060
+ }
1061
+ const newStart = state.positionRange.valid ? Math.min(state.positionRange.start, index) : 0;
1062
+ const newEnd = Math.min(
1063
+ state.props.data.length - 1,
1064
+ Math.max(state.positionRange.valid ? state.positionRange.end : 0, index + 50)
1065
+ );
1066
+ updateItemPositions(ctx, state, false, newStart, newEnd);
1067
+ }
1068
+ function updateItemPositions(ctx, state, dataChanged, startIndex = 0, endIndex) {
1069
+ var _a, _b, _c, _d, _e, _f, _g;
1194
1070
  const {
1195
1071
  columns,
1196
1072
  indexByKey,
@@ -1222,6 +1098,11 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1222
1098
  }
1223
1099
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1224
1100
  const dataLength = data.length;
1101
+ const requiredRange = getRequiredRange(ctx, state);
1102
+ const shouldOptimize = dataLength >= 500;
1103
+ const optimizedEndIndex = shouldOptimize ? Math.min(dataLength - 1, requiredRange.end) : dataLength - 1;
1104
+ const actualEndIndex = endIndex !== void 0 ? Math.min(endIndex, dataLength - 1) : optimizedEndIndex;
1105
+ let actualEndReached = startIndex;
1225
1106
  for (let i = startIndex; i < dataLength; i++) {
1226
1107
  const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1227
1108
  const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(state, id, i, data[i], useAverageSize);
@@ -1251,6 +1132,26 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1251
1132
  } else {
1252
1133
  currentRowTop += size;
1253
1134
  }
1135
+ actualEndReached = i;
1136
+ if (shouldOptimize && i >= actualEndIndex && (!((_g = state.scrollingTo) == null ? void 0 : _g.index) || i >= state.scrollingTo.index)) {
1137
+ break;
1138
+ }
1139
+ }
1140
+ if (!state.positionRange) {
1141
+ state.positionRange = { end: -1, start: 0, valid: false };
1142
+ }
1143
+ if (dataChanged) {
1144
+ state.positionRange = {
1145
+ end: actualEndReached,
1146
+ start: startIndex,
1147
+ valid: true
1148
+ };
1149
+ } else {
1150
+ state.positionRange = {
1151
+ end: Math.max(state.positionRange.valid ? state.positionRange.end : actualEndReached, actualEndReached),
1152
+ start: Math.min(state.positionRange.valid ? state.positionRange.start : startIndex, startIndex),
1153
+ valid: true
1154
+ };
1254
1155
  }
1255
1156
  updateTotalSize(ctx, state);
1256
1157
  if (snapToIndices) {
@@ -1258,6 +1159,189 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1258
1159
  }
1259
1160
  }
1260
1161
 
1162
+ // src/utils/getPosition.ts
1163
+ function getPositionByIndex(ctx, state, index) {
1164
+ ensurePositionCalculated(ctx, state, index);
1165
+ const id = getId(state, index);
1166
+ return id ? state.positions.get(id) : void 0;
1167
+ }
1168
+ function getPositionById(ctx, state, id) {
1169
+ const index = state.indexByKey.get(id);
1170
+ if (index === void 0) {
1171
+ return state.positions.get(id);
1172
+ }
1173
+ ensurePositionCalculated(ctx, state, index);
1174
+ return state.positions.get(id);
1175
+ }
1176
+
1177
+ // src/core/calculateOffsetForIndex.ts
1178
+ function calculateOffsetForIndex(ctx, state, index) {
1179
+ let position = 0;
1180
+ if (index !== void 0) {
1181
+ position = getPositionByIndex(ctx, state, index) || 0;
1182
+ const paddingTop = peek$(ctx, "stylePaddingTop");
1183
+ if (paddingTop) {
1184
+ position += paddingTop;
1185
+ }
1186
+ const headerSize = peek$(ctx, "headerSize");
1187
+ if (headerSize) {
1188
+ position += headerSize;
1189
+ }
1190
+ }
1191
+ return position;
1192
+ }
1193
+
1194
+ // src/core/calculateOffsetWithOffsetPosition.ts
1195
+ function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
1196
+ const { index, viewOffset, viewPosition } = params;
1197
+ let offset = offsetParam;
1198
+ if (viewOffset) {
1199
+ offset -= viewOffset;
1200
+ }
1201
+ if (viewPosition !== void 0 && index !== void 0) {
1202
+ offset -= viewPosition * (state.scrollLength - getItemSize(state, getId(state, index), index, state.props.data[index]));
1203
+ }
1204
+ return offset;
1205
+ }
1206
+
1207
+ // src/core/finishScrollTo.ts
1208
+ var finishScrollTo = (state) => {
1209
+ if (state) {
1210
+ state.scrollingTo = void 0;
1211
+ state.scrollHistory.length = 0;
1212
+ }
1213
+ };
1214
+
1215
+ // src/core/scrollTo.ts
1216
+ function scrollTo(state, params = {}) {
1217
+ var _a;
1218
+ const { animated, noScrollingTo } = params;
1219
+ const {
1220
+ refScroller,
1221
+ props: { horizontal }
1222
+ } = state;
1223
+ const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1224
+ state.scrollHistory.length = 0;
1225
+ if (!noScrollingTo) {
1226
+ state.scrollingTo = params;
1227
+ }
1228
+ state.scrollPending = offset;
1229
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1230
+ animated: !!animated,
1231
+ x: horizontal ? offset : 0,
1232
+ y: horizontal ? 0 : offset
1233
+ });
1234
+ if (!animated) {
1235
+ state.scroll = offset;
1236
+ setTimeout(() => finishScrollTo(state), 100);
1237
+ }
1238
+ }
1239
+
1240
+ // src/utils/requestAdjust.ts
1241
+ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1242
+ if (Math.abs(positionDiff) > 0.1) {
1243
+ const needsScrollWorkaround = reactNative.Platform.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
1244
+ const doit = () => {
1245
+ if (needsScrollWorkaround) {
1246
+ scrollTo(state, {
1247
+ noScrollingTo: true,
1248
+ offset: state.scroll
1249
+ });
1250
+ } else {
1251
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
1252
+ }
1253
+ };
1254
+ state.scroll += positionDiff;
1255
+ state.scrollForNextCalculateItemsInView = void 0;
1256
+ const didLayout = peek$(ctx, "containersDidLayout");
1257
+ if (didLayout) {
1258
+ doit();
1259
+ const threshold = state.scroll - positionDiff / 2;
1260
+ if (!state.ignoreScrollFromMVCP) {
1261
+ state.ignoreScrollFromMVCP = {};
1262
+ }
1263
+ if (positionDiff > 0) {
1264
+ state.ignoreScrollFromMVCP.lt = threshold;
1265
+ } else {
1266
+ state.ignoreScrollFromMVCP.gt = threshold;
1267
+ }
1268
+ if (state.ignoreScrollFromMVCPTimeout) {
1269
+ clearTimeout(state.ignoreScrollFromMVCPTimeout);
1270
+ }
1271
+ state.ignoreScrollFromMVCPTimeout = setTimeout(
1272
+ () => {
1273
+ state.ignoreScrollFromMVCP = void 0;
1274
+ },
1275
+ needsScrollWorkaround ? 250 : 100
1276
+ );
1277
+ } else {
1278
+ requestAnimationFrame(doit);
1279
+ }
1280
+ }
1281
+ }
1282
+
1283
+ // src/core/mvcp.ts
1284
+ function prepareMVCP(ctx, state, dataChanged) {
1285
+ const {
1286
+ idsInView,
1287
+ scrollingTo,
1288
+ props: { maintainVisibleContentPosition }
1289
+ } = state;
1290
+ let prevPosition;
1291
+ let targetId;
1292
+ const idsInViewWithPositions = [];
1293
+ const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1294
+ if (maintainVisibleContentPosition) {
1295
+ const indexByKey = state.indexByKey;
1296
+ if (scrollTarget !== void 0) {
1297
+ targetId = getId(state, scrollTarget);
1298
+ } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1299
+ if (dataChanged) {
1300
+ for (let i = 0; i < idsInView.length; i++) {
1301
+ const id = idsInView[i];
1302
+ const index = indexByKey.get(id);
1303
+ if (index !== void 0) {
1304
+ const position = getPositionById(ctx, state, id);
1305
+ if (position !== void 0) {
1306
+ idsInViewWithPositions.push({ id, position });
1307
+ }
1308
+ }
1309
+ }
1310
+ } else {
1311
+ targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
1312
+ }
1313
+ }
1314
+ if (targetId !== void 0) {
1315
+ const pos = getPositionById(ctx, state, targetId);
1316
+ if (pos !== void 0) {
1317
+ prevPosition = pos;
1318
+ }
1319
+ }
1320
+ }
1321
+ return () => {
1322
+ let positionDiff;
1323
+ if (dataChanged && targetId === void 0) {
1324
+ for (let i = 0; i < idsInViewWithPositions.length; i++) {
1325
+ const { id, position } = idsInViewWithPositions[i];
1326
+ const newPosition = getPositionById(ctx, state, id);
1327
+ if (newPosition !== void 0) {
1328
+ positionDiff = newPosition - position;
1329
+ break;
1330
+ }
1331
+ }
1332
+ }
1333
+ if (targetId !== void 0 && prevPosition !== void 0) {
1334
+ const newPosition = getPositionById(ctx, state, targetId);
1335
+ if (newPosition !== void 0) {
1336
+ positionDiff = newPosition - prevPosition;
1337
+ }
1338
+ }
1339
+ if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1340
+ requestAdjust(ctx, state, positionDiff, dataChanged);
1341
+ }
1342
+ };
1343
+ }
1344
+
1261
1345
  // src/core/viewability.ts
1262
1346
  function ensureViewabilityState(ctx, configId) {
1263
1347
  let map = ctx.mapViewabilityConfigStates;
@@ -1838,7 +1922,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1838
1922
  positions.clear();
1839
1923
  }
1840
1924
  const startIndex = dataChanged ? 0 : minIndexSizeChanged != null ? minIndexSizeChanged : 0;
1841
- updateAllPositions(ctx, state, dataChanged, startIndex);
1925
+ updateItemPositions(ctx, state, dataChanged, startIndex);
1842
1926
  if (minIndexSizeChanged !== void 0) {
1843
1927
  state.minIndexSizeChanged = void 0;
1844
1928
  }
@@ -2070,7 +2154,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2070
2154
  const item = data[itemIndex];
2071
2155
  if (item !== void 0) {
2072
2156
  const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
2073
- const position = positions.get(id);
2157
+ const position = getPositionById(ctx, state, id);
2074
2158
  if (position === void 0) {
2075
2159
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2076
2160
  } else {
@@ -2286,8 +2370,6 @@ function updateScroll(ctx, state, newScroll) {
2286
2370
  if (state.scrollHistory.length > 5) {
2287
2371
  state.scrollHistory.shift();
2288
2372
  }
2289
- state.scrollPrev = state.scroll;
2290
- state.scrollPrevTime = state.scrollTime;
2291
2373
  state.scroll = newScroll;
2292
2374
  state.scrollTime = currentTime;
2293
2375
  if (Math.abs(state.scroll - state.scrollPrev) > 2) {
@@ -2295,6 +2377,8 @@ function updateScroll(ctx, state, newScroll) {
2295
2377
  checkAtBottom(ctx, state);
2296
2378
  checkAtTop(state);
2297
2379
  }
2380
+ state.scrollPrev = state.scroll;
2381
+ state.scrollPrevTime = state.scrollTime;
2298
2382
  }
2299
2383
 
2300
2384
  // src/core/ScrollAdjustHandler.ts
@@ -2683,6 +2767,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2683
2767
  loadStartTime: Date.now(),
2684
2768
  minIndexSizeChanged: 0,
2685
2769
  nativeMarginTop: 0,
2770
+ positionRange: { end: -1, start: -1, valid: false },
2686
2771
  positions: /* @__PURE__ */ new Map(),
2687
2772
  props: {},
2688
2773
  queuedCalculateItemsInView: 0,
@@ -2795,7 +2880,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2795
2880
  };
2796
2881
  if (isFirst) {
2797
2882
  initializeStateVars();
2798
- updateAllPositions(ctx, state);
2883
+ updateItemPositions(ctx, state);
2799
2884
  }
2800
2885
  const initialContentOffset = React3.useMemo(() => {
2801
2886
  if (initialScroll) {
@@ -2929,7 +3014,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2929
3014
  endBuffered: state2.endBuffered,
2930
3015
  isAtEnd: state2.isAtEnd,
2931
3016
  isAtStart: state2.isAtStart,
2932
- positionAtIndex: (index) => state2.positions.get(getId(state2, index)),
3017
+ positionAtIndex: (index) => getPositionByIndex(ctx, state2, index),
2933
3018
  positions: state2.positions,
2934
3019
  scroll: state2.scroll,
2935
3020
  scrollLength: state2.scrollLength,
package/index.mjs CHANGED
@@ -876,23 +876,6 @@ function getId(state, index) {
876
876
  return id;
877
877
  }
878
878
 
879
- // src/core/calculateOffsetForIndex.ts
880
- function calculateOffsetForIndex(ctx, state, index) {
881
- let position = 0;
882
- if (index !== void 0) {
883
- position = (state == null ? void 0 : state.positions.get(getId(state, index))) || 0;
884
- const paddingTop = peek$(ctx, "stylePaddingTop");
885
- if (paddingTop) {
886
- position += paddingTop;
887
- }
888
- const headerSize = peek$(ctx, "headerSize");
889
- if (headerSize) {
890
- position += headerSize;
891
- }
892
- }
893
- return position;
894
- }
895
-
896
879
  // src/utils/getItemSize.ts
897
880
  function getItemSize(state, key, index, data, useAverageSize) {
898
881
  var _a, _b;
@@ -934,152 +917,6 @@ function getItemSize(state, key, index, data, useAverageSize) {
934
917
  return size;
935
918
  }
936
919
 
937
- // src/core/calculateOffsetWithOffsetPosition.ts
938
- function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
939
- const { index, viewOffset, viewPosition } = params;
940
- let offset = offsetParam;
941
- if (viewOffset) {
942
- offset -= viewOffset;
943
- }
944
- if (viewPosition !== void 0 && index !== void 0) {
945
- offset -= viewPosition * (state.scrollLength - getItemSize(state, getId(state, index), index, state.props.data[index]));
946
- }
947
- return offset;
948
- }
949
-
950
- // src/core/finishScrollTo.ts
951
- var finishScrollTo = (state) => {
952
- if (state) {
953
- state.scrollingTo = void 0;
954
- state.scrollHistory.length = 0;
955
- }
956
- };
957
-
958
- // src/core/scrollTo.ts
959
- function scrollTo(state, params = {}) {
960
- var _a;
961
- const { animated, noScrollingTo } = params;
962
- const {
963
- refScroller,
964
- props: { horizontal }
965
- } = state;
966
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
967
- state.scrollHistory.length = 0;
968
- if (!noScrollingTo) {
969
- state.scrollingTo = params;
970
- }
971
- state.scrollPending = offset;
972
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
973
- animated: !!animated,
974
- x: horizontal ? offset : 0,
975
- y: horizontal ? 0 : offset
976
- });
977
- if (!animated) {
978
- state.scroll = offset;
979
- setTimeout(() => finishScrollTo(state), 100);
980
- }
981
- }
982
-
983
- // src/utils/requestAdjust.ts
984
- function requestAdjust(ctx, state, positionDiff, dataChanged) {
985
- if (Math.abs(positionDiff) > 0.1) {
986
- const needsScrollWorkaround = Platform.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
987
- const doit = () => {
988
- if (needsScrollWorkaround) {
989
- scrollTo(state, {
990
- noScrollingTo: true,
991
- offset: state.scroll
992
- });
993
- } else {
994
- state.scrollAdjustHandler.requestAdjust(positionDiff);
995
- }
996
- };
997
- state.scroll += positionDiff;
998
- state.scrollForNextCalculateItemsInView = void 0;
999
- const didLayout = peek$(ctx, "containersDidLayout");
1000
- if (didLayout) {
1001
- doit();
1002
- const threshold = state.scroll - positionDiff / 2;
1003
- if (!state.ignoreScrollFromMVCP) {
1004
- state.ignoreScrollFromMVCP = {};
1005
- }
1006
- if (positionDiff > 0) {
1007
- state.ignoreScrollFromMVCP.lt = threshold;
1008
- } else {
1009
- state.ignoreScrollFromMVCP.gt = threshold;
1010
- }
1011
- if (state.ignoreScrollFromMVCPTimeout) {
1012
- clearTimeout(state.ignoreScrollFromMVCPTimeout);
1013
- }
1014
- state.ignoreScrollFromMVCPTimeout = setTimeout(
1015
- () => {
1016
- state.ignoreScrollFromMVCP = void 0;
1017
- },
1018
- needsScrollWorkaround ? 250 : 100
1019
- );
1020
- } else {
1021
- requestAnimationFrame(doit);
1022
- }
1023
- }
1024
- }
1025
-
1026
- // src/core/mvcp.ts
1027
- function prepareMVCP(ctx, state, dataChanged) {
1028
- const {
1029
- idsInView,
1030
- positions,
1031
- scrollingTo,
1032
- props: { maintainVisibleContentPosition }
1033
- } = state;
1034
- let prevPosition;
1035
- let targetId;
1036
- const idsInViewWithPositions = [];
1037
- const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1038
- if (maintainVisibleContentPosition) {
1039
- const indexByKey = state.indexByKey;
1040
- if (scrollTarget !== void 0) {
1041
- targetId = getId(state, scrollTarget);
1042
- } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1043
- if (dataChanged) {
1044
- for (let i = 0; i < idsInView.length; i++) {
1045
- const id = idsInView[i];
1046
- const index = indexByKey.get(id);
1047
- if (index !== void 0) {
1048
- idsInViewWithPositions.push({ id, position: positions.get(id) });
1049
- }
1050
- }
1051
- } else {
1052
- targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
1053
- }
1054
- }
1055
- if (targetId !== void 0) {
1056
- prevPosition = positions.get(targetId);
1057
- }
1058
- }
1059
- return () => {
1060
- let positionDiff;
1061
- if (dataChanged && targetId === void 0) {
1062
- for (let i = 0; i < idsInViewWithPositions.length; i++) {
1063
- const { id, position } = idsInViewWithPositions[i];
1064
- const newPosition = positions.get(id);
1065
- if (newPosition !== void 0) {
1066
- positionDiff = newPosition - position;
1067
- break;
1068
- }
1069
- }
1070
- }
1071
- if (targetId !== void 0 && prevPosition !== void 0) {
1072
- const newPosition = positions.get(targetId);
1073
- if (newPosition !== void 0) {
1074
- positionDiff = newPosition - prevPosition;
1075
- }
1076
- }
1077
- if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1078
- requestAdjust(ctx, state, positionDiff, dataChanged);
1079
- }
1080
- };
1081
- }
1082
-
1083
920
  // src/utils/setPaddingTop.ts
1084
921
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
1085
922
  if (stylePaddingTop !== void 0) {
@@ -1118,15 +955,15 @@ function updateAlignItemsPaddingTop(ctx, state) {
1118
955
  // src/core/updateTotalSize.ts
1119
956
  function updateTotalSize(ctx, state) {
1120
957
  const {
1121
- positions,
1122
958
  props: { data }
1123
959
  } = state;
1124
960
  if (data.length === 0) {
1125
961
  addTotalSize(ctx, state, null, 0);
1126
962
  } else {
1127
- const lastId = getId(state, data.length - 1);
963
+ const lastIndex = data.length - 1;
964
+ const lastId = getId(state, lastIndex);
1128
965
  if (lastId !== void 0) {
1129
- const lastPosition = positions.get(lastId);
966
+ const lastPosition = getPositionByIndex(ctx, state, lastIndex);
1130
967
  if (lastPosition !== void 0) {
1131
968
  const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
1132
969
  if (lastSize !== void 0) {
@@ -1155,21 +992,60 @@ function addTotalSize(ctx, state, key, add) {
1155
992
  // src/utils/updateSnapToOffsets.ts
1156
993
  function updateSnapToOffsets(ctx, state) {
1157
994
  const {
1158
- positions,
1159
995
  props: { snapToIndices }
1160
996
  } = state;
1161
997
  const snapToOffsets = Array(snapToIndices.length);
1162
998
  for (let i = 0; i < snapToIndices.length; i++) {
1163
999
  const idx = snapToIndices[i];
1164
- const key = getId(state, idx);
1165
- snapToOffsets[i] = positions.get(key);
1000
+ snapToOffsets[i] = getPositionByIndex(ctx, state, idx) || 0;
1166
1001
  }
1167
1002
  set$(ctx, "snapToOffsets", snapToOffsets);
1168
1003
  }
1169
1004
 
1170
- // src/core/updateAllPositions.ts
1171
- function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1172
- var _a, _b, _c, _d, _e, _f;
1005
+ // src/core/updateItemPositions.ts
1006
+ function getRequiredRange(_ctx, state) {
1007
+ var _a;
1008
+ const bufferSize = 10;
1009
+ const dataLength = state.props.data.length;
1010
+ let minIndex = 0;
1011
+ let maxIndex = dataLength - 1;
1012
+ if (dataLength < 500) {
1013
+ return { end: maxIndex, start: 0 };
1014
+ }
1015
+ const hasVisibleRange = state.startBuffered >= 0 && state.endBuffered >= 0;
1016
+ if (hasVisibleRange) {
1017
+ minIndex = state.startBuffered;
1018
+ maxIndex = state.endBuffered;
1019
+ }
1020
+ if (((_a = state.scrollingTo) == null ? void 0 : _a.index) !== void 0) {
1021
+ if (hasVisibleRange) {
1022
+ minIndex = Math.min(minIndex, state.scrollingTo.index);
1023
+ maxIndex = Math.max(maxIndex, state.scrollingTo.index);
1024
+ } else {
1025
+ minIndex = state.scrollingTo.index;
1026
+ maxIndex = state.scrollingTo.index;
1027
+ }
1028
+ }
1029
+ minIndex = Math.max(0, minIndex - bufferSize);
1030
+ maxIndex = Math.min(dataLength - 1, maxIndex + bufferSize);
1031
+ return { end: maxIndex, start: minIndex };
1032
+ }
1033
+ function ensurePositionCalculated(ctx, state, index) {
1034
+ if (!state.positionRange) {
1035
+ state.positionRange = { end: -1, start: 0, valid: false };
1036
+ }
1037
+ if (state.positionRange.valid && index >= state.positionRange.start && index <= state.positionRange.end) {
1038
+ return;
1039
+ }
1040
+ const newStart = state.positionRange.valid ? Math.min(state.positionRange.start, index) : 0;
1041
+ const newEnd = Math.min(
1042
+ state.props.data.length - 1,
1043
+ Math.max(state.positionRange.valid ? state.positionRange.end : 0, index + 50)
1044
+ );
1045
+ updateItemPositions(ctx, state, false, newStart, newEnd);
1046
+ }
1047
+ function updateItemPositions(ctx, state, dataChanged, startIndex = 0, endIndex) {
1048
+ var _a, _b, _c, _d, _e, _f, _g;
1173
1049
  const {
1174
1050
  columns,
1175
1051
  indexByKey,
@@ -1201,6 +1077,11 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1201
1077
  }
1202
1078
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1203
1079
  const dataLength = data.length;
1080
+ const requiredRange = getRequiredRange(ctx, state);
1081
+ const shouldOptimize = dataLength >= 500;
1082
+ const optimizedEndIndex = shouldOptimize ? Math.min(dataLength - 1, requiredRange.end) : dataLength - 1;
1083
+ const actualEndIndex = endIndex !== void 0 ? Math.min(endIndex, dataLength - 1) : optimizedEndIndex;
1084
+ let actualEndReached = startIndex;
1204
1085
  for (let i = startIndex; i < dataLength; i++) {
1205
1086
  const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1206
1087
  const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(state, id, i, data[i], useAverageSize);
@@ -1230,6 +1111,26 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1230
1111
  } else {
1231
1112
  currentRowTop += size;
1232
1113
  }
1114
+ actualEndReached = i;
1115
+ if (shouldOptimize && i >= actualEndIndex && (!((_g = state.scrollingTo) == null ? void 0 : _g.index) || i >= state.scrollingTo.index)) {
1116
+ break;
1117
+ }
1118
+ }
1119
+ if (!state.positionRange) {
1120
+ state.positionRange = { end: -1, start: 0, valid: false };
1121
+ }
1122
+ if (dataChanged) {
1123
+ state.positionRange = {
1124
+ end: actualEndReached,
1125
+ start: startIndex,
1126
+ valid: true
1127
+ };
1128
+ } else {
1129
+ state.positionRange = {
1130
+ end: Math.max(state.positionRange.valid ? state.positionRange.end : actualEndReached, actualEndReached),
1131
+ start: Math.min(state.positionRange.valid ? state.positionRange.start : startIndex, startIndex),
1132
+ valid: true
1133
+ };
1233
1134
  }
1234
1135
  updateTotalSize(ctx, state);
1235
1136
  if (snapToIndices) {
@@ -1237,6 +1138,189 @@ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1237
1138
  }
1238
1139
  }
1239
1140
 
1141
+ // src/utils/getPosition.ts
1142
+ function getPositionByIndex(ctx, state, index) {
1143
+ ensurePositionCalculated(ctx, state, index);
1144
+ const id = getId(state, index);
1145
+ return id ? state.positions.get(id) : void 0;
1146
+ }
1147
+ function getPositionById(ctx, state, id) {
1148
+ const index = state.indexByKey.get(id);
1149
+ if (index === void 0) {
1150
+ return state.positions.get(id);
1151
+ }
1152
+ ensurePositionCalculated(ctx, state, index);
1153
+ return state.positions.get(id);
1154
+ }
1155
+
1156
+ // src/core/calculateOffsetForIndex.ts
1157
+ function calculateOffsetForIndex(ctx, state, index) {
1158
+ let position = 0;
1159
+ if (index !== void 0) {
1160
+ position = getPositionByIndex(ctx, state, index) || 0;
1161
+ const paddingTop = peek$(ctx, "stylePaddingTop");
1162
+ if (paddingTop) {
1163
+ position += paddingTop;
1164
+ }
1165
+ const headerSize = peek$(ctx, "headerSize");
1166
+ if (headerSize) {
1167
+ position += headerSize;
1168
+ }
1169
+ }
1170
+ return position;
1171
+ }
1172
+
1173
+ // src/core/calculateOffsetWithOffsetPosition.ts
1174
+ function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
1175
+ const { index, viewOffset, viewPosition } = params;
1176
+ let offset = offsetParam;
1177
+ if (viewOffset) {
1178
+ offset -= viewOffset;
1179
+ }
1180
+ if (viewPosition !== void 0 && index !== void 0) {
1181
+ offset -= viewPosition * (state.scrollLength - getItemSize(state, getId(state, index), index, state.props.data[index]));
1182
+ }
1183
+ return offset;
1184
+ }
1185
+
1186
+ // src/core/finishScrollTo.ts
1187
+ var finishScrollTo = (state) => {
1188
+ if (state) {
1189
+ state.scrollingTo = void 0;
1190
+ state.scrollHistory.length = 0;
1191
+ }
1192
+ };
1193
+
1194
+ // src/core/scrollTo.ts
1195
+ function scrollTo(state, params = {}) {
1196
+ var _a;
1197
+ const { animated, noScrollingTo } = params;
1198
+ const {
1199
+ refScroller,
1200
+ props: { horizontal }
1201
+ } = state;
1202
+ const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1203
+ state.scrollHistory.length = 0;
1204
+ if (!noScrollingTo) {
1205
+ state.scrollingTo = params;
1206
+ }
1207
+ state.scrollPending = offset;
1208
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1209
+ animated: !!animated,
1210
+ x: horizontal ? offset : 0,
1211
+ y: horizontal ? 0 : offset
1212
+ });
1213
+ if (!animated) {
1214
+ state.scroll = offset;
1215
+ setTimeout(() => finishScrollTo(state), 100);
1216
+ }
1217
+ }
1218
+
1219
+ // src/utils/requestAdjust.ts
1220
+ function requestAdjust(ctx, state, positionDiff, dataChanged) {
1221
+ if (Math.abs(positionDiff) > 0.1) {
1222
+ const needsScrollWorkaround = Platform.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff;
1223
+ const doit = () => {
1224
+ if (needsScrollWorkaround) {
1225
+ scrollTo(state, {
1226
+ noScrollingTo: true,
1227
+ offset: state.scroll
1228
+ });
1229
+ } else {
1230
+ state.scrollAdjustHandler.requestAdjust(positionDiff);
1231
+ }
1232
+ };
1233
+ state.scroll += positionDiff;
1234
+ state.scrollForNextCalculateItemsInView = void 0;
1235
+ const didLayout = peek$(ctx, "containersDidLayout");
1236
+ if (didLayout) {
1237
+ doit();
1238
+ const threshold = state.scroll - positionDiff / 2;
1239
+ if (!state.ignoreScrollFromMVCP) {
1240
+ state.ignoreScrollFromMVCP = {};
1241
+ }
1242
+ if (positionDiff > 0) {
1243
+ state.ignoreScrollFromMVCP.lt = threshold;
1244
+ } else {
1245
+ state.ignoreScrollFromMVCP.gt = threshold;
1246
+ }
1247
+ if (state.ignoreScrollFromMVCPTimeout) {
1248
+ clearTimeout(state.ignoreScrollFromMVCPTimeout);
1249
+ }
1250
+ state.ignoreScrollFromMVCPTimeout = setTimeout(
1251
+ () => {
1252
+ state.ignoreScrollFromMVCP = void 0;
1253
+ },
1254
+ needsScrollWorkaround ? 250 : 100
1255
+ );
1256
+ } else {
1257
+ requestAnimationFrame(doit);
1258
+ }
1259
+ }
1260
+ }
1261
+
1262
+ // src/core/mvcp.ts
1263
+ function prepareMVCP(ctx, state, dataChanged) {
1264
+ const {
1265
+ idsInView,
1266
+ scrollingTo,
1267
+ props: { maintainVisibleContentPosition }
1268
+ } = state;
1269
+ let prevPosition;
1270
+ let targetId;
1271
+ const idsInViewWithPositions = [];
1272
+ const scrollTarget = scrollingTo == null ? void 0 : scrollingTo.index;
1273
+ if (maintainVisibleContentPosition) {
1274
+ const indexByKey = state.indexByKey;
1275
+ if (scrollTarget !== void 0) {
1276
+ targetId = getId(state, scrollTarget);
1277
+ } else if (idsInView.length > 0 && peek$(ctx, "containersDidLayout")) {
1278
+ if (dataChanged) {
1279
+ for (let i = 0; i < idsInView.length; i++) {
1280
+ const id = idsInView[i];
1281
+ const index = indexByKey.get(id);
1282
+ if (index !== void 0) {
1283
+ const position = getPositionById(ctx, state, id);
1284
+ if (position !== void 0) {
1285
+ idsInViewWithPositions.push({ id, position });
1286
+ }
1287
+ }
1288
+ }
1289
+ } else {
1290
+ targetId = state.idsInView.find((id) => indexByKey.get(id) !== void 0);
1291
+ }
1292
+ }
1293
+ if (targetId !== void 0) {
1294
+ const pos = getPositionById(ctx, state, targetId);
1295
+ if (pos !== void 0) {
1296
+ prevPosition = pos;
1297
+ }
1298
+ }
1299
+ }
1300
+ return () => {
1301
+ let positionDiff;
1302
+ if (dataChanged && targetId === void 0) {
1303
+ for (let i = 0; i < idsInViewWithPositions.length; i++) {
1304
+ const { id, position } = idsInViewWithPositions[i];
1305
+ const newPosition = getPositionById(ctx, state, id);
1306
+ if (newPosition !== void 0) {
1307
+ positionDiff = newPosition - position;
1308
+ break;
1309
+ }
1310
+ }
1311
+ }
1312
+ if (targetId !== void 0 && prevPosition !== void 0) {
1313
+ const newPosition = getPositionById(ctx, state, targetId);
1314
+ if (newPosition !== void 0) {
1315
+ positionDiff = newPosition - prevPosition;
1316
+ }
1317
+ }
1318
+ if (positionDiff !== void 0 && Math.abs(positionDiff) > 0.1) {
1319
+ requestAdjust(ctx, state, positionDiff, dataChanged);
1320
+ }
1321
+ };
1322
+ }
1323
+
1240
1324
  // src/core/viewability.ts
1241
1325
  function ensureViewabilityState(ctx, configId) {
1242
1326
  let map = ctx.mapViewabilityConfigStates;
@@ -1817,7 +1901,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1817
1901
  positions.clear();
1818
1902
  }
1819
1903
  const startIndex = dataChanged ? 0 : minIndexSizeChanged != null ? minIndexSizeChanged : 0;
1820
- updateAllPositions(ctx, state, dataChanged, startIndex);
1904
+ updateItemPositions(ctx, state, dataChanged, startIndex);
1821
1905
  if (minIndexSizeChanged !== void 0) {
1822
1906
  state.minIndexSizeChanged = void 0;
1823
1907
  }
@@ -2049,7 +2133,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2049
2133
  const item = data[itemIndex];
2050
2134
  if (item !== void 0) {
2051
2135
  const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
2052
- const position = positions.get(id);
2136
+ const position = getPositionById(ctx, state, id);
2053
2137
  if (position === void 0) {
2054
2138
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2055
2139
  } else {
@@ -2265,8 +2349,6 @@ function updateScroll(ctx, state, newScroll) {
2265
2349
  if (state.scrollHistory.length > 5) {
2266
2350
  state.scrollHistory.shift();
2267
2351
  }
2268
- state.scrollPrev = state.scroll;
2269
- state.scrollPrevTime = state.scrollTime;
2270
2352
  state.scroll = newScroll;
2271
2353
  state.scrollTime = currentTime;
2272
2354
  if (Math.abs(state.scroll - state.scrollPrev) > 2) {
@@ -2274,6 +2356,8 @@ function updateScroll(ctx, state, newScroll) {
2274
2356
  checkAtBottom(ctx, state);
2275
2357
  checkAtTop(state);
2276
2358
  }
2359
+ state.scrollPrev = state.scroll;
2360
+ state.scrollPrevTime = state.scrollTime;
2277
2361
  }
2278
2362
 
2279
2363
  // src/core/ScrollAdjustHandler.ts
@@ -2662,6 +2746,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2662
2746
  loadStartTime: Date.now(),
2663
2747
  minIndexSizeChanged: 0,
2664
2748
  nativeMarginTop: 0,
2749
+ positionRange: { end: -1, start: -1, valid: false },
2665
2750
  positions: /* @__PURE__ */ new Map(),
2666
2751
  props: {},
2667
2752
  queuedCalculateItemsInView: 0,
@@ -2774,7 +2859,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2774
2859
  };
2775
2860
  if (isFirst) {
2776
2861
  initializeStateVars();
2777
- updateAllPositions(ctx, state);
2862
+ updateItemPositions(ctx, state);
2778
2863
  }
2779
2864
  const initialContentOffset = useMemo(() => {
2780
2865
  if (initialScroll) {
@@ -2908,7 +2993,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2908
2993
  endBuffered: state2.endBuffered,
2909
2994
  isAtEnd: state2.isAtEnd,
2910
2995
  isAtStart: state2.isAtStart,
2911
- positionAtIndex: (index) => state2.positions.get(getId(state2, index)),
2996
+ positionAtIndex: (index) => getPositionByIndex(ctx, state2, index),
2912
2997
  positions: state2.positions,
2913
2998
  scroll: state2.scroll,
2914
2999
  scrollLength: state2.scrollLength,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
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,