@legendapp/list 2.0.1 → 2.0.3

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,11 +345,6 @@ 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
- };
353
348
  averageSizes: Record<string, {
354
349
  num: number;
355
350
  avg: number;
@@ -413,17 +408,18 @@ interface LegendListRenderItemProps<ItemT, TItemType extends string | number | u
413
408
  extraData: any;
414
409
  }
415
410
  type ScrollState = {
411
+ activeStickyIndex: number | undefined;
416
412
  contentLength: number;
417
413
  data: readonly any[];
418
414
  end: number;
419
415
  endBuffered: number;
420
416
  isAtEnd: boolean;
421
417
  isAtStart: boolean;
422
- positionAtIndex: (index: number) => number | undefined;
418
+ positionAtIndex: (index: number) => number;
423
419
  positions: Map<string, number>;
424
420
  scroll: number;
425
421
  scrollLength: number;
426
- sizeAtIndex: (index: number) => number | undefined;
422
+ sizeAtIndex: (index: number) => number;
427
423
  sizes: Map<string, number>;
428
424
  start: number;
429
425
  startBuffered: number;
package/index.d.ts CHANGED
@@ -345,11 +345,6 @@ 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
- };
353
348
  averageSizes: Record<string, {
354
349
  num: number;
355
350
  avg: number;
@@ -413,17 +408,18 @@ interface LegendListRenderItemProps<ItemT, TItemType extends string | number | u
413
408
  extraData: any;
414
409
  }
415
410
  type ScrollState = {
411
+ activeStickyIndex: number | undefined;
416
412
  contentLength: number;
417
413
  data: readonly any[];
418
414
  end: number;
419
415
  endBuffered: number;
420
416
  isAtEnd: boolean;
421
417
  isAtStart: boolean;
422
- positionAtIndex: (index: number) => number | undefined;
418
+ positionAtIndex: (index: number) => number;
423
419
  positions: Map<string, number>;
424
420
  scroll: number;
425
421
  scrollLength: number;
426
- sizeAtIndex: (index: number) => number | undefined;
422
+ sizeAtIndex: (index: number) => number;
427
423
  sizes: Map<string, number>;
428
424
  start: number;
429
425
  startBuffered: number;
package/index.js CHANGED
@@ -897,6 +897,23 @@ 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
+
900
917
  // src/utils/getItemSize.ts
901
918
  function getItemSize(state, key, index, data, useAverageSize) {
902
919
  var _a, _b;
@@ -938,6 +955,152 @@ function getItemSize(state, key, index, data, useAverageSize) {
938
955
  return size;
939
956
  }
940
957
 
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
+
941
1104
  // src/utils/setPaddingTop.ts
942
1105
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
943
1106
  if (stylePaddingTop !== void 0) {
@@ -976,15 +1139,15 @@ function updateAlignItemsPaddingTop(ctx, state) {
976
1139
  // src/core/updateTotalSize.ts
977
1140
  function updateTotalSize(ctx, state) {
978
1141
  const {
1142
+ positions,
979
1143
  props: { data }
980
1144
  } = state;
981
1145
  if (data.length === 0) {
982
1146
  addTotalSize(ctx, state, null, 0);
983
1147
  } else {
984
- const lastIndex = data.length - 1;
985
- const lastId = getId(state, lastIndex);
1148
+ const lastId = getId(state, data.length - 1);
986
1149
  if (lastId !== void 0) {
987
- const lastPosition = getPositionByIndex(ctx, state, lastIndex);
1150
+ const lastPosition = positions.get(lastId);
988
1151
  if (lastPosition !== void 0) {
989
1152
  const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
990
1153
  if (lastSize !== void 0) {
@@ -1013,60 +1176,21 @@ function addTotalSize(ctx, state, key, add) {
1013
1176
  // src/utils/updateSnapToOffsets.ts
1014
1177
  function updateSnapToOffsets(ctx, state) {
1015
1178
  const {
1179
+ positions,
1016
1180
  props: { snapToIndices }
1017
1181
  } = state;
1018
1182
  const snapToOffsets = Array(snapToIndices.length);
1019
1183
  for (let i = 0; i < snapToIndices.length; i++) {
1020
1184
  const idx = snapToIndices[i];
1021
- snapToOffsets[i] = getPositionByIndex(ctx, state, idx) || 0;
1185
+ const key = getId(state, idx);
1186
+ snapToOffsets[i] = positions.get(key);
1022
1187
  }
1023
1188
  set$(ctx, "snapToOffsets", snapToOffsets);
1024
1189
  }
1025
1190
 
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;
1191
+ // src/core/updateAllPositions.ts
1192
+ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1193
+ var _a, _b, _c, _d, _e, _f;
1070
1194
  const {
1071
1195
  columns,
1072
1196
  indexByKey,
@@ -1098,11 +1222,6 @@ function updateItemPositions(ctx, state, dataChanged, startIndex = 0, endIndex)
1098
1222
  }
1099
1223
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1100
1224
  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;
1106
1225
  for (let i = startIndex; i < dataLength; i++) {
1107
1226
  const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1108
1227
  const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(state, id, i, data[i], useAverageSize);
@@ -1132,26 +1251,6 @@ function updateItemPositions(ctx, state, dataChanged, startIndex = 0, endIndex)
1132
1251
  } else {
1133
1252
  currentRowTop += size;
1134
1253
  }
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
- };
1155
1254
  }
1156
1255
  updateTotalSize(ctx, state);
1157
1256
  if (snapToIndices) {
@@ -1159,189 +1258,6 @@ function updateItemPositions(ctx, state, dataChanged, startIndex = 0, endIndex)
1159
1258
  }
1160
1259
  }
1161
1260
 
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
-
1345
1261
  // src/core/viewability.ts
1346
1262
  function ensureViewabilityState(ctx, configId) {
1347
1263
  let map = ctx.mapViewabilityConfigStates;
@@ -1843,6 +1759,7 @@ function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll,
1843
1759
  var _a;
1844
1760
  const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
1845
1761
  const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1762
+ state.activeStickyIndex = currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : void 0;
1846
1763
  for (let offset = 0; offset <= 1; offset++) {
1847
1764
  const idx = currentStickyIdx - offset;
1848
1765
  if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
@@ -1922,7 +1839,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1922
1839
  positions.clear();
1923
1840
  }
1924
1841
  const startIndex = dataChanged ? 0 : minIndexSizeChanged != null ? minIndexSizeChanged : 0;
1925
- updateItemPositions(ctx, state, dataChanged, startIndex);
1842
+ updateAllPositions(ctx, state, dataChanged, startIndex);
1926
1843
  if (minIndexSizeChanged !== void 0) {
1927
1844
  state.minIndexSizeChanged = void 0;
1928
1845
  }
@@ -2079,6 +1996,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2079
1996
  startBuffered,
2080
1997
  endBuffered
2081
1998
  );
1999
+ } else {
2000
+ state.activeStickyIndex = void 0;
2082
2001
  }
2083
2002
  if (needNewContainers.length > 0) {
2084
2003
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
@@ -2154,7 +2073,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2154
2073
  const item = data[itemIndex];
2155
2074
  if (item !== void 0) {
2156
2075
  const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
2157
- const position = getPositionById(ctx, state, id);
2076
+ const position = positions.get(id);
2158
2077
  if (position === void 0) {
2159
2078
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2160
2079
  } else {
@@ -2370,6 +2289,8 @@ function updateScroll(ctx, state, newScroll) {
2370
2289
  if (state.scrollHistory.length > 5) {
2371
2290
  state.scrollHistory.shift();
2372
2291
  }
2292
+ state.scrollPrev = state.scroll;
2293
+ state.scrollPrevTime = state.scrollTime;
2373
2294
  state.scroll = newScroll;
2374
2295
  state.scrollTime = currentTime;
2375
2296
  if (Math.abs(state.scroll - state.scrollPrev) > 2) {
@@ -2377,8 +2298,6 @@ function updateScroll(ctx, state, newScroll) {
2377
2298
  checkAtBottom(ctx, state);
2378
2299
  checkAtTop(state);
2379
2300
  }
2380
- state.scrollPrev = state.scroll;
2381
- state.scrollPrevTime = state.scrollTime;
2382
2301
  }
2383
2302
 
2384
2303
  // src/core/ScrollAdjustHandler.ts
@@ -2767,7 +2686,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2767
2686
  loadStartTime: Date.now(),
2768
2687
  minIndexSizeChanged: 0,
2769
2688
  nativeMarginTop: 0,
2770
- positionRange: { end: -1, start: -1, valid: false },
2771
2689
  positions: /* @__PURE__ */ new Map(),
2772
2690
  props: {},
2773
2691
  queuedCalculateItemsInView: 0,
@@ -2880,7 +2798,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2880
2798
  };
2881
2799
  if (isFirst) {
2882
2800
  initializeStateVars();
2883
- updateItemPositions(ctx, state);
2801
+ updateAllPositions(ctx, state);
2884
2802
  }
2885
2803
  const initialContentOffset = React3.useMemo(() => {
2886
2804
  if (initialScroll) {
@@ -3008,13 +2926,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
3008
2926
  getState: () => {
3009
2927
  const state2 = refState.current;
3010
2928
  return state2 ? {
2929
+ activeStickyIndex: state2.activeStickyIndex,
3011
2930
  contentLength: state2.totalSize,
3012
2931
  data: state2.props.data,
3013
2932
  end: state2.endNoBuffer,
3014
2933
  endBuffered: state2.endBuffered,
3015
2934
  isAtEnd: state2.isAtEnd,
3016
2935
  isAtStart: state2.isAtStart,
3017
- positionAtIndex: (index) => getPositionByIndex(ctx, state2, index),
2936
+ positionAtIndex: (index) => state2.positions.get(getId(state2, index)),
3018
2937
  positions: state2.positions,
3019
2938
  scroll: state2.scroll,
3020
2939
  scrollLength: state2.scrollLength,
package/index.mjs CHANGED
@@ -876,6 +876,23 @@ 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
+
879
896
  // src/utils/getItemSize.ts
880
897
  function getItemSize(state, key, index, data, useAverageSize) {
881
898
  var _a, _b;
@@ -917,6 +934,152 @@ function getItemSize(state, key, index, data, useAverageSize) {
917
934
  return size;
918
935
  }
919
936
 
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
+
920
1083
  // src/utils/setPaddingTop.ts
921
1084
  function setPaddingTop(ctx, state, { stylePaddingTop, alignItemsPaddingTop }) {
922
1085
  if (stylePaddingTop !== void 0) {
@@ -955,15 +1118,15 @@ function updateAlignItemsPaddingTop(ctx, state) {
955
1118
  // src/core/updateTotalSize.ts
956
1119
  function updateTotalSize(ctx, state) {
957
1120
  const {
1121
+ positions,
958
1122
  props: { data }
959
1123
  } = state;
960
1124
  if (data.length === 0) {
961
1125
  addTotalSize(ctx, state, null, 0);
962
1126
  } else {
963
- const lastIndex = data.length - 1;
964
- const lastId = getId(state, lastIndex);
1127
+ const lastId = getId(state, data.length - 1);
965
1128
  if (lastId !== void 0) {
966
- const lastPosition = getPositionByIndex(ctx, state, lastIndex);
1129
+ const lastPosition = positions.get(lastId);
967
1130
  if (lastPosition !== void 0) {
968
1131
  const lastSize = getItemSize(state, lastId, data.length - 1, data[data.length - 1]);
969
1132
  if (lastSize !== void 0) {
@@ -992,60 +1155,21 @@ function addTotalSize(ctx, state, key, add) {
992
1155
  // src/utils/updateSnapToOffsets.ts
993
1156
  function updateSnapToOffsets(ctx, state) {
994
1157
  const {
1158
+ positions,
995
1159
  props: { snapToIndices }
996
1160
  } = state;
997
1161
  const snapToOffsets = Array(snapToIndices.length);
998
1162
  for (let i = 0; i < snapToIndices.length; i++) {
999
1163
  const idx = snapToIndices[i];
1000
- snapToOffsets[i] = getPositionByIndex(ctx, state, idx) || 0;
1164
+ const key = getId(state, idx);
1165
+ snapToOffsets[i] = positions.get(key);
1001
1166
  }
1002
1167
  set$(ctx, "snapToOffsets", snapToOffsets);
1003
1168
  }
1004
1169
 
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;
1170
+ // src/core/updateAllPositions.ts
1171
+ function updateAllPositions(ctx, state, dataChanged, startIndex = 0) {
1172
+ var _a, _b, _c, _d, _e, _f;
1049
1173
  const {
1050
1174
  columns,
1051
1175
  indexByKey,
@@ -1077,11 +1201,6 @@ function updateItemPositions(ctx, state, dataChanged, startIndex = 0, endIndex)
1077
1201
  }
1078
1202
  const needsIndexByKey = dataChanged || indexByKey.size === 0;
1079
1203
  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;
1085
1204
  for (let i = startIndex; i < dataLength; i++) {
1086
1205
  const id = (_e = idCache.get(i)) != null ? _e : getId(state, i);
1087
1206
  const size = (_f = sizesKnown.get(id)) != null ? _f : getItemSize(state, id, i, data[i], useAverageSize);
@@ -1111,26 +1230,6 @@ function updateItemPositions(ctx, state, dataChanged, startIndex = 0, endIndex)
1111
1230
  } else {
1112
1231
  currentRowTop += size;
1113
1232
  }
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
- };
1134
1233
  }
1135
1234
  updateTotalSize(ctx, state);
1136
1235
  if (snapToIndices) {
@@ -1138,189 +1237,6 @@ function updateItemPositions(ctx, state, dataChanged, startIndex = 0, endIndex)
1138
1237
  }
1139
1238
  }
1140
1239
 
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
-
1324
1240
  // src/core/viewability.ts
1325
1241
  function ensureViewabilityState(ctx, configId) {
1326
1242
  let map = ctx.mapViewabilityConfigStates;
@@ -1822,6 +1738,7 @@ function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll,
1822
1738
  var _a;
1823
1739
  const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
1824
1740
  const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1741
+ state.activeStickyIndex = currentStickyIdx >= 0 ? stickyArray[currentStickyIdx] : void 0;
1825
1742
  for (let offset = 0; offset <= 1; offset++) {
1826
1743
  const idx = currentStickyIdx - offset;
1827
1744
  if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
@@ -1901,7 +1818,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1901
1818
  positions.clear();
1902
1819
  }
1903
1820
  const startIndex = dataChanged ? 0 : minIndexSizeChanged != null ? minIndexSizeChanged : 0;
1904
- updateItemPositions(ctx, state, dataChanged, startIndex);
1821
+ updateAllPositions(ctx, state, dataChanged, startIndex);
1905
1822
  if (minIndexSizeChanged !== void 0) {
1906
1823
  state.minIndexSizeChanged = void 0;
1907
1824
  }
@@ -2058,6 +1975,8 @@ function calculateItemsInView(ctx, state, params = {}) {
2058
1975
  startBuffered,
2059
1976
  endBuffered
2060
1977
  );
1978
+ } else {
1979
+ state.activeStickyIndex = void 0;
2061
1980
  }
2062
1981
  if (needNewContainers.length > 0) {
2063
1982
  const requiredItemTypes = getItemType ? needNewContainers.map((i) => {
@@ -2133,7 +2052,7 @@ function calculateItemsInView(ctx, state, params = {}) {
2133
2052
  const item = data[itemIndex];
2134
2053
  if (item !== void 0) {
2135
2054
  const id = (_h = idCache.get(itemIndex)) != null ? _h : getId(state, itemIndex);
2136
- const position = getPositionById(ctx, state, id);
2055
+ const position = positions.get(id);
2137
2056
  if (position === void 0) {
2138
2057
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
2139
2058
  } else {
@@ -2349,6 +2268,8 @@ function updateScroll(ctx, state, newScroll) {
2349
2268
  if (state.scrollHistory.length > 5) {
2350
2269
  state.scrollHistory.shift();
2351
2270
  }
2271
+ state.scrollPrev = state.scroll;
2272
+ state.scrollPrevTime = state.scrollTime;
2352
2273
  state.scroll = newScroll;
2353
2274
  state.scrollTime = currentTime;
2354
2275
  if (Math.abs(state.scroll - state.scrollPrev) > 2) {
@@ -2356,8 +2277,6 @@ function updateScroll(ctx, state, newScroll) {
2356
2277
  checkAtBottom(ctx, state);
2357
2278
  checkAtTop(state);
2358
2279
  }
2359
- state.scrollPrev = state.scroll;
2360
- state.scrollPrevTime = state.scrollTime;
2361
2280
  }
2362
2281
 
2363
2282
  // src/core/ScrollAdjustHandler.ts
@@ -2746,7 +2665,6 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2746
2665
  loadStartTime: Date.now(),
2747
2666
  minIndexSizeChanged: 0,
2748
2667
  nativeMarginTop: 0,
2749
- positionRange: { end: -1, start: -1, valid: false },
2750
2668
  positions: /* @__PURE__ */ new Map(),
2751
2669
  props: {},
2752
2670
  queuedCalculateItemsInView: 0,
@@ -2859,7 +2777,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2859
2777
  };
2860
2778
  if (isFirst) {
2861
2779
  initializeStateVars();
2862
- updateItemPositions(ctx, state);
2780
+ updateAllPositions(ctx, state);
2863
2781
  }
2864
2782
  const initialContentOffset = useMemo(() => {
2865
2783
  if (initialScroll) {
@@ -2987,13 +2905,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2987
2905
  getState: () => {
2988
2906
  const state2 = refState.current;
2989
2907
  return state2 ? {
2908
+ activeStickyIndex: state2.activeStickyIndex,
2990
2909
  contentLength: state2.totalSize,
2991
2910
  data: state2.props.data,
2992
2911
  end: state2.endNoBuffer,
2993
2912
  endBuffered: state2.endBuffered,
2994
2913
  isAtEnd: state2.isAtEnd,
2995
2914
  isAtStart: state2.isAtStart,
2996
- positionAtIndex: (index) => getPositionByIndex(ctx, state2, index),
2915
+ positionAtIndex: (index) => state2.positions.get(getId(state2, index)),
2997
2916
  positions: state2.positions,
2998
2917
  scroll: state2.scroll,
2999
2918
  scrollLength: state2.scrollLength,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legendapp/list",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
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,