@legendapp/list 2.0.0-next.10 → 2.0.0-next.11

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.js CHANGED
@@ -28,6 +28,7 @@ var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
28
28
  var ContextState = React3__namespace.createContext(null);
29
29
  function StateProvider({ children }) {
30
30
  const [value] = React3__namespace.useState(() => ({
31
+ animatedScrollY: new reactNative.Animated.Value(0),
31
32
  columnWrapperStyle: void 0,
32
33
  listeners: /* @__PURE__ */ new Map(),
33
34
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
@@ -185,18 +186,130 @@ var LeanViewComponent = React3__namespace.forwardRef((props, ref) => {
185
186
  LeanViewComponent.displayName = "RCTView";
186
187
  var LeanView = reactNative.Platform.OS === "android" || reactNative.Platform.OS === "ios" ? LeanViewComponent : reactNative.View;
187
188
 
189
+ // src/constants.ts
190
+ var POSITION_OUT_OF_VIEW = -1e7;
191
+ var ENABLE_DEVMODE = __DEV__ && false;
192
+ var ENABLE_DEBUG_VIEW = __DEV__ && false;
193
+ var IsNewArchitecture = global.nativeFabricUIManager != null;
194
+ var useAnimatedValue = (initialValue) => {
195
+ return React3.useRef(new reactNative.Animated.Value(initialValue)).current;
196
+ };
197
+
198
+ // src/hooks/useValue$.ts
199
+ function useValue$(key, params) {
200
+ var _a;
201
+ const { getValue, delay } = params || {};
202
+ const ctx = useStateContext();
203
+ const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
204
+ React3.useMemo(() => {
205
+ let newValue;
206
+ let prevValue;
207
+ let didQueueTask = false;
208
+ listen$(ctx, key, (v) => {
209
+ newValue = getValue ? getValue(v) : v;
210
+ if (delay !== void 0) {
211
+ const fn = () => {
212
+ didQueueTask = false;
213
+ if (newValue !== void 0) {
214
+ animValue.setValue(newValue);
215
+ }
216
+ };
217
+ const delayValue = typeof delay === "function" ? delay(newValue, prevValue) : delay;
218
+ prevValue = newValue;
219
+ if (!didQueueTask) {
220
+ didQueueTask = true;
221
+ if (delayValue === 0) {
222
+ queueMicrotask(fn);
223
+ } else {
224
+ setTimeout(fn, delayValue);
225
+ }
226
+ }
227
+ } else {
228
+ animValue.setValue(newValue);
229
+ }
230
+ });
231
+ }, []);
232
+ return animValue;
233
+ }
234
+ var typedForwardRef = React3.forwardRef;
235
+ var typedMemo = React3.memo;
236
+
237
+ // src/components/PositionView.tsx
238
+ var PositionViewState = typedMemo(function PositionView({
239
+ id,
240
+ horizontal,
241
+ style,
242
+ refView,
243
+ ...rest
244
+ }) {
245
+ const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
246
+ return /* @__PURE__ */ React3__namespace.createElement(
247
+ LeanView,
248
+ {
249
+ ref: refView,
250
+ style: [
251
+ style,
252
+ horizontal ? { transform: [{ translateX: position }] } : { transform: [{ translateY: position }] }
253
+ ],
254
+ ...rest
255
+ }
256
+ );
257
+ });
258
+ var PositionViewAnimated = typedMemo(function PositionView2({
259
+ id,
260
+ horizontal,
261
+ style,
262
+ refView,
263
+ ...rest
264
+ }) {
265
+ const position$ = useValue$(`containerPosition${id}`, {
266
+ getValue: (v) => v != null ? v : POSITION_OUT_OF_VIEW
267
+ });
268
+ return /* @__PURE__ */ React3__namespace.createElement(
269
+ reactNative.Animated.View,
270
+ {
271
+ ref: refView,
272
+ style: [
273
+ style,
274
+ horizontal ? { transform: [{ translateX: position$ }] } : { transform: [{ translateY: position$ }] }
275
+ ],
276
+ ...rest
277
+ }
278
+ );
279
+ });
280
+ var PositionViewSticky = typedMemo(function PositionViewSticky2({
281
+ id,
282
+ horizontal,
283
+ style,
284
+ refView,
285
+ animatedScrollY,
286
+ stickyOffset,
287
+ index,
288
+ ...rest
289
+ }) {
290
+ const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
291
+ const transform = React3__namespace.useMemo(() => {
292
+ if (animatedScrollY && stickyOffset) {
293
+ const stickyPosition = animatedScrollY.interpolate({
294
+ extrapolate: "clamp",
295
+ inputRange: [position, position + 5e3],
296
+ outputRange: [position, position + 5e3]
297
+ });
298
+ return horizontal ? [{ translateX: stickyPosition }] : [{ translateY: stickyPosition }];
299
+ }
300
+ }, [position, horizontal, animatedScrollY, stickyOffset]);
301
+ console.log("index", index, position, transform);
302
+ const viewStyle = React3__namespace.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
303
+ return /* @__PURE__ */ React3__namespace.createElement(reactNative.Animated.View, { ref: refView, style: viewStyle, ...rest });
304
+ });
305
+ var PositionView3 = IsNewArchitecture ? PositionViewState : PositionViewAnimated;
306
+
188
307
  // src/components/Separator.tsx
189
308
  function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
190
309
  const [lastItemKeys] = useArr$(["lastItemKeys"]);
191
310
  const isALastItem = lastItemKeys.includes(itemKey);
192
311
  return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
193
312
  }
194
-
195
- // src/constants.ts
196
- var POSITION_OUT_OF_VIEW = -1e7;
197
- var ENABLE_DEVMODE = __DEV__ && false;
198
- var ENABLE_DEBUG_VIEW = __DEV__ && false;
199
- var IsNewArchitecture = global.nativeFabricUIManager != null;
200
313
  var symbolFirst = Symbol();
201
314
  function useInit(cb) {
202
315
  const refValue = React3.useRef(symbolFirst);
@@ -333,8 +446,6 @@ function useListScrollSize() {
333
446
  const [scrollSize] = useArr$(["scrollSize"]);
334
447
  return scrollSize;
335
448
  }
336
- var typedForwardRef = React3.forwardRef;
337
- var typedMemo = React3.memo;
338
449
 
339
450
  // src/components/Container.tsx
340
451
  var Container = typedMemo(function Container2({
@@ -346,14 +457,15 @@ var Container = typedMemo(function Container2({
346
457
  ItemSeparatorComponent
347
458
  }) {
348
459
  const ctx = useStateContext();
349
- const columnWrapperStyle = ctx.columnWrapperStyle;
350
- const [column = 0, data, itemKey, position = POSITION_OUT_OF_VIEW, numColumns, extraData] = useArr$([
460
+ const { columnWrapperStyle, animatedScrollY } = ctx;
461
+ const [column = 0, data, itemKey, numColumns, extraData, isSticky, stickyOffset] = useArr$([
351
462
  `containerColumn${id}`,
352
463
  `containerItemData${id}`,
353
464
  `containerItemKey${id}`,
354
- `containerPosition${id}`,
355
465
  "numColumns",
356
- "extraData"
466
+ "extraData",
467
+ `containerSticky${id}`,
468
+ `containerStickyOffset${id}`
357
469
  ]);
358
470
  const refLastSize = React3.useRef();
359
471
  const ref = React3.useRef(null);
@@ -361,36 +473,38 @@ var Container = typedMemo(function Container2({
361
473
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
362
474
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
363
475
  let didLayout = false;
364
- let paddingStyles;
365
- if (columnWrapperStyle) {
366
- const { columnGap, rowGap, gap } = columnWrapperStyle;
367
- if (horizontal) {
368
- paddingStyles = {
369
- paddingRight: columnGap || gap || void 0,
370
- paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
371
- };
372
- } else {
373
- paddingStyles = {
374
- paddingBottom: rowGap || gap || void 0,
375
- paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
376
- };
476
+ const style = React3.useMemo(() => {
477
+ let paddingStyles;
478
+ if (columnWrapperStyle) {
479
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
480
+ if (horizontal) {
481
+ paddingStyles = {
482
+ paddingRight: columnGap || gap || void 0,
483
+ paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
484
+ };
485
+ } else {
486
+ paddingStyles = {
487
+ paddingBottom: rowGap || gap || void 0,
488
+ paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
489
+ };
490
+ }
377
491
  }
378
- }
379
- const style = horizontal ? {
380
- flexDirection: ItemSeparatorComponent ? "row" : void 0,
381
- height: otherAxisSize,
382
- left: position,
383
- position: "absolute",
384
- top: otherAxisPos,
385
- ...paddingStyles || {}
386
- } : {
387
- left: otherAxisPos,
388
- position: "absolute",
389
- right: numColumns > 1 ? null : 0,
390
- top: position,
391
- width: otherAxisSize,
392
- ...paddingStyles || {}
393
- };
492
+ return horizontal ? {
493
+ flexDirection: ItemSeparatorComponent ? "row" : void 0,
494
+ height: otherAxisSize,
495
+ left: 0,
496
+ position: "absolute",
497
+ top: otherAxisPos,
498
+ ...paddingStyles || {}
499
+ } : {
500
+ left: otherAxisPos,
501
+ position: "absolute",
502
+ right: numColumns > 1 ? null : 0,
503
+ top: 0,
504
+ width: otherAxisSize,
505
+ ...paddingStyles || {}
506
+ };
507
+ }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
394
508
  const renderedItemInfo = React3.useMemo(
395
509
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
396
510
  [itemKey, data, extraData]
@@ -455,55 +569,30 @@ var Container = typedMemo(function Container2({
455
569
  }
456
570
  }, [itemKey]);
457
571
  }
458
- return /* @__PURE__ */ React3__namespace.createElement(LeanView, { key: recycleItems ? void 0 : itemKey, onLayout, ref, style }, /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(
459
- Separator,
572
+ const PositionComponent = isSticky ? PositionViewSticky : PositionView3;
573
+ return /* @__PURE__ */ React3__namespace.createElement(
574
+ PositionComponent,
460
575
  {
461
- ItemSeparatorComponent,
462
- itemKey,
463
- leadingItem: renderedItemInfo.item
464
- }
465
- )));
466
- });
467
- var useAnimatedValue = (initialValue) => {
468
- return React3.useRef(new reactNative.Animated.Value(initialValue)).current;
469
- };
470
-
471
- // src/hooks/useValue$.ts
472
- function useValue$(key, params) {
473
- var _a;
474
- const { getValue, delay } = params || {};
475
- const ctx = useStateContext();
476
- const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
477
- React3.useMemo(() => {
478
- let newValue;
479
- let prevValue;
480
- let didQueueTask = false;
481
- listen$(ctx, key, (v) => {
482
- newValue = getValue ? getValue(v) : v;
483
- if (delay !== void 0) {
484
- const fn = () => {
485
- didQueueTask = false;
486
- if (newValue !== void 0) {
487
- animValue.setValue(newValue);
488
- }
489
- };
490
- const delayValue = typeof delay === "function" ? delay(newValue, prevValue) : delay;
491
- prevValue = newValue;
492
- if (!didQueueTask) {
493
- didQueueTask = true;
494
- if (delayValue === 0) {
495
- queueMicrotask(fn);
496
- } else {
497
- setTimeout(fn, delayValue);
498
- }
499
- }
500
- } else {
501
- animValue.setValue(newValue);
576
+ animatedScrollY: isSticky ? animatedScrollY : void 0,
577
+ horizontal,
578
+ id,
579
+ index,
580
+ key: recycleItems ? void 0 : itemKey,
581
+ onLayout,
582
+ refView: ref,
583
+ stickyOffset: isSticky ? stickyOffset : void 0,
584
+ style
585
+ },
586
+ /* @__PURE__ */ React3__namespace.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3__namespace.createElement(
587
+ Separator,
588
+ {
589
+ ItemSeparatorComponent,
590
+ itemKey,
591
+ leadingItem: renderedItemInfo.item
502
592
  }
503
- });
504
- }, []);
505
- return animValue;
506
- }
593
+ ))
594
+ );
595
+ });
507
596
 
508
597
  // src/components/Containers.tsx
509
598
  var Containers = typedMemo(function Containers2({
@@ -663,6 +752,7 @@ var ListComponent = typedMemo(function ListComponent2({
663
752
  scrollAdjustHandler,
664
753
  onLayoutHeader,
665
754
  snapToIndices,
755
+ stickyIndices,
666
756
  ...rest
667
757
  }) {
668
758
  const ctx = useStateContext();
@@ -672,7 +762,7 @@ var ListComponent = typedMemo(function ListComponent2({
672
762
  const ScrollComponent = renderScrollComponent ? React3.useMemo(
673
763
  () => React3__namespace.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
674
764
  [renderScrollComponent]
675
- ) : reactNative.ScrollView;
765
+ ) : reactNative.Animated.ScrollView;
676
766
  React3__namespace.useEffect(() => {
677
767
  if (canRender) {
678
768
  setTimeout(() => {
@@ -725,9 +815,26 @@ var ListComponent = typedMemo(function ListComponent2({
725
815
  style: ListFooterComponentStyle
726
816
  },
727
817
  getComponent(ListFooterComponent)
728
- )
818
+ ),
819
+ __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React3__namespace.createElement(DevNumbers, null)
729
820
  );
730
821
  });
822
+ var DevNumbers = __DEV__ && React3__namespace.memo(function DevNumbers2() {
823
+ return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3__namespace.createElement(
824
+ reactNative.View,
825
+ {
826
+ key: index,
827
+ style: {
828
+ height: 100,
829
+ pointerEvents: "none",
830
+ position: "absolute",
831
+ top: index * 100,
832
+ width: "100%"
833
+ }
834
+ },
835
+ /* @__PURE__ */ React3__namespace.createElement(reactNative.Text, { style: { color: "red" } }, index * 100)
836
+ ));
837
+ });
731
838
 
732
839
  // src/utils/getId.ts
733
840
  function getId(state, index) {
@@ -759,20 +866,36 @@ function calculateOffsetForIndex(ctx, state, index) {
759
866
  }
760
867
 
761
868
  // src/utils/getItemSize.ts
762
- function getItemSize(state, key, index, data, useAverageSize) {
869
+ function getItemSize(state, key, index, data, useAverageSize, defaultAverageSize) {
870
+ var _a, _b;
763
871
  const {
764
872
  sizesKnown,
765
873
  sizes,
766
874
  scrollingTo,
767
- props: { estimatedItemSize, getEstimatedItemSize }
875
+ averageSizes,
876
+ props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
768
877
  } = state;
769
878
  const sizeKnown = sizesKnown.get(key);
770
879
  if (sizeKnown !== void 0) {
771
880
  return sizeKnown;
772
881
  }
773
882
  let size;
774
- if (useAverageSize !== void 0 && sizeKnown === void 0 && !getEstimatedItemSize && !scrollingTo) {
775
- size = useAverageSize;
883
+ const itemType = getItemType ? (_a = getItemType(data, index)) != null ? _a : "" : "";
884
+ if (getFixedItemSize) {
885
+ size = getFixedItemSize(index, data, itemType);
886
+ if (size !== void 0) {
887
+ sizesKnown.set(key, size);
888
+ }
889
+ }
890
+ if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
891
+ if (itemType === "") {
892
+ size = defaultAverageSize;
893
+ } else {
894
+ const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
895
+ if (averageSizeForType !== void 0) {
896
+ size = roundSize(averageSizeForType);
897
+ }
898
+ }
776
899
  }
777
900
  if (size === void 0) {
778
901
  size = sizes.get(key);
@@ -781,7 +904,7 @@ function getItemSize(state, key, index, data, useAverageSize) {
781
904
  }
782
905
  }
783
906
  if (size === void 0) {
784
- size = getEstimatedItemSize ? getEstimatedItemSize(index, data) : estimatedItemSize;
907
+ size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
785
908
  }
786
909
  sizes.set(key, size);
787
910
  return size;
@@ -800,6 +923,37 @@ function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
800
923
  return offset;
801
924
  }
802
925
 
926
+ // src/core/finishScrollTo.ts
927
+ var finishScrollTo = (state) => {
928
+ if (state) {
929
+ state.scrollingTo = void 0;
930
+ state.scrollHistory.length = 0;
931
+ }
932
+ };
933
+
934
+ // src/core/scrollTo.ts
935
+ function scrollTo(state, params = {}) {
936
+ var _a;
937
+ const { animated } = params;
938
+ const {
939
+ refScroller,
940
+ props: { horizontal }
941
+ } = state;
942
+ const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
943
+ state.scrollHistory.length = 0;
944
+ state.scrollingTo = params;
945
+ state.scrollPending = offset;
946
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
947
+ animated: !!animated,
948
+ x: horizontal ? offset : 0,
949
+ y: horizontal ? 0 : offset
950
+ });
951
+ if (!animated) {
952
+ state.scroll = offset;
953
+ setTimeout(() => finishScrollTo(state), 100);
954
+ }
955
+ }
956
+
803
957
  // src/utils/requestAdjust.ts
804
958
  function requestAdjust(ctx, state, positionDiff) {
805
959
  if (Math.abs(positionDiff) > 0.1) {
@@ -833,7 +987,7 @@ function requestAdjust(ctx, state, positionDiff) {
833
987
  }
834
988
 
835
989
  // src/core/prepareMVCP.ts
836
- function prepareMVCP(ctx, state) {
990
+ function prepareMVCP(ctx, state, dataChanged) {
837
991
  const {
838
992
  positions,
839
993
  scrollingTo,
@@ -862,7 +1016,13 @@ function prepareMVCP(ctx, state) {
862
1016
  if (newPosition !== void 0) {
863
1017
  const positionDiff = newPosition - prevPosition;
864
1018
  if (Math.abs(positionDiff) > 0.1) {
865
- requestAdjust(ctx, state, positionDiff);
1019
+ if (reactNative.Platform.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff) {
1020
+ scrollTo(state, {
1021
+ offset: state.scroll + positionDiff
1022
+ });
1023
+ } else {
1024
+ requestAdjust(ctx, state, positionDiff);
1025
+ }
866
1026
  }
867
1027
  }
868
1028
  }
@@ -1004,7 +1164,7 @@ function updateAllPositions(ctx, state, dataChanged) {
1004
1164
  firstFullyOnScreenIndex,
1005
1165
  idCache,
1006
1166
  sizesKnown,
1007
- props: { snapToIndices }
1167
+ props: { getEstimatedItemSize, snapToIndices }
1008
1168
  } = state;
1009
1169
  const data = state.props.data;
1010
1170
  const numColumns = peek$(ctx, "numColumns");
@@ -1014,6 +1174,7 @@ function updateAllPositions(ctx, state, dataChanged) {
1014
1174
  indexByKey.clear();
1015
1175
  idCache.clear();
1016
1176
  }
1177
+ const useAverageSize = !getEstimatedItemSize;
1017
1178
  const itemType = "";
1018
1179
  let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
1019
1180
  if (averageSize !== void 0) {
@@ -1029,7 +1190,7 @@ function updateAllPositions(ctx, state, dataChanged) {
1029
1190
  let bailout = false;
1030
1191
  for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
1031
1192
  const id = (_b = idCache.get(i)) != null ? _b : getId(state, i);
1032
- const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(state, id, i, data[i], averageSize);
1193
+ const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(state, id, i, data[i], useAverageSize, averageSize);
1033
1194
  const itemColumn = columns.get(id);
1034
1195
  maxSizeInRow2 = Math.max(maxSizeInRow2, size);
1035
1196
  if (itemColumn === 1) {
@@ -1056,7 +1217,7 @@ function updateAllPositions(ctx, state, dataChanged) {
1056
1217
  const dataLength = data.length;
1057
1218
  for (let i = 0; i < dataLength; i++) {
1058
1219
  const id = (_d = idCache.get(i)) != null ? _d : getId(state, i);
1059
- const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(state, id, i, data[i], averageSize);
1220
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(state, id, i, data[i], useAverageSize, averageSize);
1060
1221
  if (__DEV__ && needsIndexByKey) {
1061
1222
  if (indexByKeyForChecking.has(id)) {
1062
1223
  console.error(
@@ -1295,35 +1456,84 @@ function checkAllSizesKnown(state) {
1295
1456
  }
1296
1457
 
1297
1458
  // src/utils/findAvailableContainers.ts
1298
- function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
1459
+ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
1299
1460
  const numContainers = peek$(ctx, "numContainers");
1461
+ const { stickyIndicesSet } = state.props;
1300
1462
  const result = [];
1301
1463
  const availableContainers = [];
1302
- for (let u = 0; u < numContainers; u++) {
1303
- const key = peek$(ctx, `containerItemKey${u}`);
1304
- let isOk = key === void 0;
1305
- if (!isOk) {
1306
- const index = pendingRemoval.indexOf(u);
1307
- if (index !== -1) {
1308
- pendingRemoval.splice(index, 1);
1309
- isOk = true;
1464
+ const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
1465
+ const nonStickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => !stickyIndicesSet.has(index))) || [];
1466
+ const canReuseContainer = (containerIndex, requiredType) => {
1467
+ if (!requiredType) return true;
1468
+ const existingType = state.containerItemTypes.get(containerIndex);
1469
+ if (!existingType) return true;
1470
+ return existingType === requiredType;
1471
+ };
1472
+ const neededTypes = requiredItemTypes ? [...requiredItemTypes] : [];
1473
+ let typeIndex = 0;
1474
+ for (let i = 0; i < stickyItemIndices.length; i++) {
1475
+ const requiredType = neededTypes[typeIndex];
1476
+ let foundContainer = false;
1477
+ for (const containerIndex of state.stickyContainerPool) {
1478
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
1479
+ const isPendingRemoval = pendingRemoval.includes(containerIndex);
1480
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType)) {
1481
+ result.push(containerIndex);
1482
+ if (isPendingRemoval) {
1483
+ const index = pendingRemoval.indexOf(containerIndex);
1484
+ pendingRemoval.splice(index, 1);
1485
+ }
1486
+ foundContainer = true;
1487
+ if (requiredItemTypes) typeIndex++;
1488
+ break;
1310
1489
  }
1311
1490
  }
1312
- if (isOk) {
1313
- result.push(u);
1314
- if (result.length >= numNeeded) {
1315
- return result;
1491
+ if (!foundContainer) {
1492
+ const newContainerIndex = numContainers + result.filter((index) => index >= numContainers).length;
1493
+ result.push(newContainerIndex);
1494
+ state.stickyContainerPool.add(newContainerIndex);
1495
+ if (requiredItemTypes) typeIndex++;
1496
+ }
1497
+ }
1498
+ if (nonStickyItemIndices.length > 0) {
1499
+ for (let u = 0; u < numContainers; u++) {
1500
+ if (state.stickyContainerPool.has(u)) {
1501
+ continue;
1502
+ }
1503
+ const key = peek$(ctx, `containerItemKey${u}`);
1504
+ let isOk = key === void 0;
1505
+ if (!isOk) {
1506
+ const index = pendingRemoval.indexOf(u);
1507
+ if (index !== -1) {
1508
+ pendingRemoval.splice(index, 1);
1509
+ const requiredType = neededTypes[typeIndex];
1510
+ isOk = canReuseContainer(u, requiredType);
1511
+ }
1512
+ }
1513
+ if (isOk) {
1514
+ result.push(u);
1515
+ if (requiredItemTypes) {
1516
+ typeIndex++;
1517
+ }
1518
+ if (result.length >= numNeeded) {
1519
+ return result;
1520
+ }
1316
1521
  }
1317
1522
  }
1318
1523
  }
1319
1524
  for (let u = 0; u < numContainers; u++) {
1525
+ if (state.stickyContainerPool.has(u)) {
1526
+ continue;
1527
+ }
1320
1528
  const key = peek$(ctx, `containerItemKey${u}`);
1321
1529
  if (key === void 0) continue;
1322
1530
  const index = state.indexByKey.get(key);
1323
- if (index < startBuffered) {
1324
- availableContainers.push({ distance: startBuffered - index, index: u });
1325
- } else if (index > endBuffered) {
1326
- availableContainers.push({ distance: index - endBuffered, index: u });
1531
+ const isOutOfView = index < startBuffered || index > endBuffered;
1532
+ if (isOutOfView) {
1533
+ const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
1534
+ if (!requiredItemTypes || typeIndex < neededTypes.length && canReuseContainer(u, neededTypes[typeIndex])) {
1535
+ availableContainers.push({ distance, index: u });
1536
+ }
1327
1537
  }
1328
1538
  }
1329
1539
  const remaining = numNeeded - result.length;
@@ -1335,6 +1545,9 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1335
1545
  }
1336
1546
  for (const container of availableContainers) {
1337
1547
  result.push(container.index);
1548
+ if (requiredItemTypes) {
1549
+ typeIndex++;
1550
+ }
1338
1551
  }
1339
1552
  }
1340
1553
  const stillNeeded = numNeeded - result.length;
@@ -1363,37 +1576,6 @@ function comparatorByDistance(a, b) {
1363
1576
  return b.distance - a.distance;
1364
1577
  }
1365
1578
 
1366
- // src/core/finishScrollTo.ts
1367
- var finishScrollTo = (state) => {
1368
- if (state) {
1369
- state.scrollingTo = void 0;
1370
- state.scrollHistory.length = 0;
1371
- }
1372
- };
1373
-
1374
- // src/core/scrollTo.ts
1375
- function scrollTo(state, params = {}) {
1376
- var _a;
1377
- const { animated } = params;
1378
- const {
1379
- refScroller,
1380
- props: { horizontal }
1381
- } = state;
1382
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1383
- state.scrollHistory.length = 0;
1384
- state.scrollingTo = params;
1385
- state.scrollPending = offset;
1386
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1387
- animated: !!animated,
1388
- x: horizontal ? offset : 0,
1389
- y: horizontal ? 0 : offset
1390
- });
1391
- if (!animated) {
1392
- state.scroll = offset;
1393
- setTimeout(() => finishScrollTo(state), 100);
1394
- }
1395
- }
1396
-
1397
1579
  // src/core/scrollToIndex.ts
1398
1580
  function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1399
1581
  if (index >= state.props.data.length) {
@@ -1481,16 +1663,90 @@ function setDidLayout(ctx, state) {
1481
1663
  } = state;
1482
1664
  state.queuedInitialLayout = true;
1483
1665
  checkAtBottom(ctx, state);
1484
- if (!IsNewArchitecture && initialScroll) {
1485
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1486
- }
1487
- set$(ctx, "containersDidLayout", true);
1488
- if (onLoad) {
1489
- onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1666
+ const setIt = () => {
1667
+ set$(ctx, "containersDidLayout", true);
1668
+ if (onLoad) {
1669
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1670
+ }
1671
+ };
1672
+ if (reactNative.Platform.OS === "android" || !IsNewArchitecture) {
1673
+ if (initialScroll) {
1674
+ queueMicrotask(() => {
1675
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1676
+ requestAnimationFrame(() => {
1677
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1678
+ setIt();
1679
+ });
1680
+ });
1681
+ } else {
1682
+ queueMicrotask(setIt);
1683
+ }
1684
+ } else {
1685
+ setIt();
1490
1686
  }
1491
1687
  }
1492
1688
 
1493
1689
  // src/core/calculateItemsInView.ts
1690
+ function findCurrentStickyIndex(stickyArray, scroll, state) {
1691
+ var _a;
1692
+ for (let i = stickyArray.length - 1; i >= 0; i--) {
1693
+ const stickyId = (_a = state.idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
1694
+ const stickyPos = stickyId ? state.positions.get(stickyId) : void 0;
1695
+ if (stickyPos !== void 0 && scroll >= stickyPos) {
1696
+ return i;
1697
+ }
1698
+ }
1699
+ return -1;
1700
+ }
1701
+ function getActiveStickyIndices(ctx, state, stickyIndices) {
1702
+ return new Set(
1703
+ Array.from(state.stickyContainerPool).map((i) => peek$(ctx, `containerItemKey${i}`)).map((key) => key ? state.indexByKey.get(key) : void 0).filter((idx) => idx !== void 0 && stickyIndices.has(idx))
1704
+ );
1705
+ }
1706
+ function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll, needNewContainers, startBuffered, endBuffered) {
1707
+ var _a;
1708
+ const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
1709
+ const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1710
+ for (let offset = 0; offset <= 1; offset++) {
1711
+ const idx = currentStickyIdx - offset;
1712
+ if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
1713
+ const stickyIndex = stickyArray[idx];
1714
+ const stickyId = (_a = state.idCache.get(stickyIndex)) != null ? _a : getId(state, stickyIndex);
1715
+ if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered)) {
1716
+ needNewContainers.push(stickyIndex);
1717
+ }
1718
+ }
1719
+ }
1720
+ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pendingRemoval) {
1721
+ var _a, _b, _c;
1722
+ const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1723
+ for (const containerIndex of state.stickyContainerPool) {
1724
+ const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
1725
+ const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
1726
+ if (itemIndex === void 0) continue;
1727
+ const arrayIdx = stickyArray.indexOf(itemIndex);
1728
+ if (arrayIdx === -1) continue;
1729
+ const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
1730
+ if (isRecentSticky) continue;
1731
+ const nextIndex = stickyArray[arrayIdx + 1];
1732
+ let shouldRecycle = false;
1733
+ if (nextIndex) {
1734
+ const nextId = (_a = state.idCache.get(nextIndex)) != null ? _a : getId(state, nextIndex);
1735
+ const nextPos = nextId ? state.positions.get(nextId) : void 0;
1736
+ shouldRecycle = nextPos !== void 0 && scroll > nextPos + scrollBuffer * 2;
1737
+ } else {
1738
+ const currentId = (_b = state.idCache.get(itemIndex)) != null ? _b : getId(state, itemIndex);
1739
+ if (currentId) {
1740
+ const currentPos = state.positions.get(currentId);
1741
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
1742
+ shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
1743
+ }
1744
+ }
1745
+ if (shouldRecycle) {
1746
+ pendingRemoval.push(containerIndex);
1747
+ }
1748
+ }
1749
+ }
1494
1750
  function calculateItemsInView(ctx, state, params = {}) {
1495
1751
  reactNative.unstable_batchedUpdates(() => {
1496
1752
  var _a, _b, _c, _d, _e, _f, _g, _h;
@@ -1507,7 +1763,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1507
1763
  enableScrollForNextCalculateItemsInView,
1508
1764
  minIndexSizeChanged
1509
1765
  } = state;
1510
- const data = state.props.data;
1766
+ const { data, stickyIndicesArr, stickyIndicesSet } = state.props;
1511
1767
  const prevNumContainers = peek$(ctx, "numContainers");
1512
1768
  if (!data || scrollLength === 0 || !prevNumContainers) {
1513
1769
  return;
@@ -1519,7 +1775,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1519
1775
  const { dataChanged, doMVCP } = params;
1520
1776
  const speed = getScrollVelocity(state);
1521
1777
  if (doMVCP || dataChanged) {
1522
- const checkMVCP = doMVCP ? prepareMVCP(ctx, state) : void 0;
1778
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
1523
1779
  updateAllPositions(ctx, state, dataChanged);
1524
1780
  checkMVCP == null ? void 0 : checkMVCP();
1525
1781
  }
@@ -1669,14 +1925,23 @@ function calculateItemsInView(ctx, state, params = {}) {
1669
1925
  needNewContainers.push(i);
1670
1926
  }
1671
1927
  }
1928
+ if (stickyIndicesArr.length > 0) {
1929
+ handleStickyActivation(ctx, state, stickyIndicesSet, stickyIndicesArr, scroll, needNewContainers, startBuffered, endBuffered);
1930
+ }
1672
1931
  if (needNewContainers.length > 0) {
1932
+ const requiredItemTypes = state.props.getItemType ? needNewContainers.map((i) => {
1933
+ const itemType = state.props.getItemType(data[i], i);
1934
+ return itemType ? String(itemType) : "";
1935
+ }) : void 0;
1673
1936
  const availableContainers = findAvailableContainers(
1674
1937
  ctx,
1675
1938
  state,
1676
1939
  needNewContainers.length,
1677
1940
  startBuffered,
1678
1941
  endBuffered,
1679
- pendingRemoval
1942
+ pendingRemoval,
1943
+ requiredItemTypes,
1944
+ needNewContainers
1680
1945
  );
1681
1946
  for (let idx = 0; idx < needNewContainers.length; idx++) {
1682
1947
  const i = needNewContainers[idx];
@@ -1688,7 +1953,18 @@ function calculateItemsInView(ctx, state, params = {}) {
1688
1953
  }
1689
1954
  set$(ctx, `containerItemKey${containerIndex}`, id);
1690
1955
  set$(ctx, `containerItemData${containerIndex}`, data[i]);
1956
+ if (requiredItemTypes) {
1957
+ state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
1958
+ }
1691
1959
  containerItemKeys.add(id);
1960
+ if (stickyIndicesSet.has(i)) {
1961
+ set$(ctx, `containerSticky${containerIndex}`, true);
1962
+ const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1963
+ set$(ctx, `containerStickyOffset${containerIndex}`, new reactNative.Animated.Value(topPadding));
1964
+ state.stickyContainerPool.add(containerIndex);
1965
+ } else {
1966
+ state.stickyContainerPool.delete(containerIndex);
1967
+ }
1692
1968
  if (containerIndex >= numContainers2) {
1693
1969
  numContainers2 = containerIndex + 1;
1694
1970
  }
@@ -1701,12 +1977,21 @@ function calculateItemsInView(ctx, state, params = {}) {
1701
1977
  }
1702
1978
  }
1703
1979
  }
1980
+ if (stickyIndicesArr.length > 0) {
1981
+ handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, pendingRemoval);
1982
+ }
1704
1983
  for (let i = 0; i < numContainers; i++) {
1705
1984
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1706
1985
  if (pendingRemoval.includes(i)) {
1707
1986
  if (itemKey) {
1708
1987
  containerItemKeys.delete(itemKey);
1709
1988
  }
1989
+ state.containerItemTypes.delete(i);
1990
+ if (state.stickyContainerPool.has(i)) {
1991
+ set$(ctx, `containerSticky${i}`, false);
1992
+ set$(ctx, `containerStickyOffset${i}`, void 0);
1993
+ state.stickyContainerPool.delete(i);
1994
+ }
1710
1995
  set$(ctx, `containerItemKey${i}`, void 0);
1711
1996
  set$(ctx, `containerItemData${i}`, void 0);
1712
1997
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
@@ -1757,10 +2042,14 @@ function calculateItemsInView(ctx, state, params = {}) {
1757
2042
 
1758
2043
  // src/core/doInitialAllocateContainers.ts
1759
2044
  function doInitialAllocateContainers(ctx, state) {
1760
- const { scrollLength } = state;
2045
+ var _a;
2046
+ const {
2047
+ scrollLength,
2048
+ props: { getItemType }
2049
+ } = state;
1761
2050
  const data = state.props.data;
1762
2051
  if (scrollLength > 0 && data.length > 0 && !peek$(ctx, "numContainers")) {
1763
- const averageItemSize = state.props.getEstimatedItemSize ? state.props.getEstimatedItemSize(0, data[0]) : state.props.estimatedItemSize;
2052
+ const averageItemSize = state.props.getEstimatedItemSize ? state.props.getEstimatedItemSize(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "") : state.props.estimatedItemSize;
1764
2053
  const Extra = 1.5;
1765
2054
  const numContainers = Math.ceil(
1766
2055
  (scrollLength + state.props.scrollBuffer * 2) / averageItemSize * state.props.numColumns * Extra
@@ -1797,16 +2086,18 @@ function doMaintainScrollAtEnd(ctx, state, animated) {
1797
2086
  }
1798
2087
  requestAnimationFrame(() => {
1799
2088
  var _a;
1800
- state.maintainingScrollAtEnd = true;
1801
- (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
1802
- animated
1803
- });
1804
- setTimeout(
1805
- () => {
1806
- state.maintainingScrollAtEnd = false;
1807
- },
1808
- 0
1809
- );
2089
+ if (state == null ? void 0 : state.isAtEnd) {
2090
+ state.maintainingScrollAtEnd = true;
2091
+ (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
2092
+ animated
2093
+ });
2094
+ setTimeout(
2095
+ () => {
2096
+ state.maintainingScrollAtEnd = false;
2097
+ },
2098
+ 0
2099
+ );
2100
+ }
1810
2101
  });
1811
2102
  return true;
1812
2103
  }
@@ -2026,7 +2317,22 @@ function updateItemSizes(ctx, state, itemUpdates) {
2026
2317
  }
2027
2318
  }
2028
2319
  function updateItemSize(ctx, state, itemKey, sizeObj) {
2029
- const { queuedItemSizeUpdates, queuedItemSizeUpdatesWaiting } = state;
2320
+ var _a;
2321
+ const {
2322
+ queuedItemSizeUpdates,
2323
+ queuedItemSizeUpdatesWaiting,
2324
+ sizesKnown,
2325
+ props: { getFixedItemSize, getItemType }
2326
+ } = state;
2327
+ if (getFixedItemSize) {
2328
+ const index = state.indexByKey.get(itemKey);
2329
+ const itemData = state.props.data[index];
2330
+ const type = getItemType ? (_a = getItemType(itemData, index)) != null ? _a : "" : "";
2331
+ const size = getFixedItemSize(index, itemData, type);
2332
+ if (size !== void 0 && size === sizesKnown.get(itemKey)) {
2333
+ return;
2334
+ }
2335
+ }
2030
2336
  const containersDidLayout = peek$(ctx, "containersDidLayout");
2031
2337
  if (!containersDidLayout || !queuedItemSizeUpdatesWaiting) {
2032
2338
  updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
@@ -2043,25 +2349,28 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2043
2349
  }
2044
2350
  }
2045
2351
  function updateOneItemSize(state, itemKey, sizeObj) {
2352
+ var _a;
2046
2353
  const {
2047
2354
  sizes,
2048
2355
  indexByKey,
2049
2356
  sizesKnown,
2050
2357
  averageSizes,
2051
- props: { data, horizontal }
2358
+ props: { data, horizontal, getEstimatedItemSize, getItemType }
2052
2359
  } = state;
2053
2360
  if (!data) return 0;
2054
2361
  const index = indexByKey.get(itemKey);
2055
2362
  const prevSize = getItemSize(state, itemKey, index, data);
2056
2363
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2057
2364
  sizesKnown.set(itemKey, size);
2058
- const itemType = "";
2059
- let averages = averageSizes[itemType];
2060
- if (!averages) {
2061
- averages = averageSizes[itemType] = { avg: 0, num: 0 };
2365
+ if (!getEstimatedItemSize) {
2366
+ const itemType = getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : "";
2367
+ let averages = averageSizes[itemType];
2368
+ if (!averages) {
2369
+ averages = averageSizes[itemType] = { avg: 0, num: 0 };
2370
+ }
2371
+ averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2372
+ averages.num++;
2062
2373
  }
2063
- averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2064
- averages.num++;
2065
2374
  if (!prevSize || Math.abs(prevSize - size) > 0.1) {
2066
2375
  sizes.set(itemKey, size);
2067
2376
  return size - prevSize;
@@ -2099,12 +2408,13 @@ function createColumnWrapperStyle(contentContainerStyle) {
2099
2408
  }
2100
2409
  }
2101
2410
  function getRenderedItem(ctx, state, key) {
2411
+ var _a;
2102
2412
  if (!state) {
2103
2413
  return null;
2104
2414
  }
2105
2415
  const {
2106
2416
  indexByKey,
2107
- props: { data, renderItem: renderItem2 }
2417
+ props: { data, getItemType, renderItem: renderItem2 }
2108
2418
  } = state;
2109
2419
  const index = indexByKey.get(key);
2110
2420
  if (index === void 0) {
@@ -2115,7 +2425,8 @@ function getRenderedItem(ctx, state, key) {
2115
2425
  const itemProps = {
2116
2426
  extraData: peek$(ctx, "extraData"),
2117
2427
  index,
2118
- item: data[index]
2428
+ item: data[index],
2429
+ type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
2119
2430
  };
2120
2431
  renderedItem = React3__namespace.default.createElement(renderItem2, itemProps);
2121
2432
  }
@@ -2131,49 +2442,52 @@ var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
2131
2442
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
2132
2443
  var _a;
2133
2444
  const {
2445
+ alignItemsAtEnd = false,
2446
+ columnWrapperStyle,
2447
+ contentContainerStyle: contentContainerStyleProp,
2134
2448
  data: dataProp = [],
2449
+ drawDistance = 250,
2450
+ estimatedItemSize: estimatedItemSizeProp,
2451
+ estimatedListSize,
2452
+ extraData,
2453
+ getEstimatedItemSize,
2454
+ getFixedItemSize,
2455
+ getItemType,
2456
+ horizontal,
2457
+ initialContainerPoolRatio = 2,
2135
2458
  initialScrollIndex: initialScrollIndexProp,
2136
2459
  initialScrollOffset,
2137
- horizontal,
2138
- drawDistance = 250,
2139
- recycleItems = false,
2140
- onEndReachedThreshold = 0.5,
2141
- onStartReachedThreshold = 0.5,
2460
+ keyExtractor: keyExtractorProp,
2461
+ ListEmptyComponent,
2462
+ ListHeaderComponent,
2142
2463
  maintainScrollAtEnd = false,
2143
2464
  maintainScrollAtEndThreshold = 0.1,
2144
- alignItemsAtEnd = false,
2145
2465
  maintainVisibleContentPosition = false,
2146
- onScroll: onScrollProp,
2147
- onMomentumScrollEnd,
2148
2466
  numColumns: numColumnsProp = 1,
2149
- columnWrapperStyle,
2150
- keyExtractor: keyExtractorProp,
2151
- renderItem: renderItem2,
2152
- estimatedListSize,
2153
- estimatedItemSize: estimatedItemSizeProp,
2154
- getEstimatedItemSize,
2155
- suggestEstimatedItemSize,
2156
- ListHeaderComponent,
2157
- ListEmptyComponent,
2467
+ onEndReached,
2468
+ onEndReachedThreshold = 0.5,
2158
2469
  onItemSizeChanged,
2159
- refScrollView,
2160
- waitForInitialLayout = true,
2161
- extraData,
2162
- contentContainerStyle: contentContainerStyleProp,
2163
- style: styleProp,
2164
2470
  onLayout: onLayoutProp,
2471
+ onLoad,
2472
+ onMomentumScrollEnd,
2165
2473
  onRefresh,
2166
- refreshing,
2474
+ onScroll: onScrollProp,
2475
+ onStartReached,
2476
+ onStartReachedThreshold = 0.5,
2477
+ onViewableItemsChanged,
2167
2478
  progressViewOffset,
2479
+ recycleItems = false,
2168
2480
  refreshControl,
2169
- initialContainerPoolRatio = 2,
2481
+ refreshing,
2482
+ refScrollView,
2483
+ renderItem: renderItem2,
2484
+ snapToIndices,
2485
+ stickyIndices,
2486
+ style: styleProp,
2487
+ suggestEstimatedItemSize,
2170
2488
  viewabilityConfig,
2171
2489
  viewabilityConfigCallbackPairs,
2172
- snapToIndices,
2173
- onViewableItemsChanged,
2174
- onStartReached,
2175
- onEndReached,
2176
- onLoad,
2490
+ waitForInitialLayout = true,
2177
2491
  ...rest
2178
2492
  } = props;
2179
2493
  const [renderNum, setRenderNum] = React3.useState(0);
@@ -2195,9 +2509,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2195
2509
  if (!refState.current) {
2196
2510
  const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : reactNative.Dimensions.get("window"))[horizontal ? "width" : "height"];
2197
2511
  refState.current = {
2512
+ activeStickyIndex: void 0,
2198
2513
  averageSizes: {},
2199
2514
  columns: /* @__PURE__ */ new Map(),
2200
2515
  containerItemKeys: /* @__PURE__ */ new Set(),
2516
+ containerItemTypes: /* @__PURE__ */ new Map(),
2201
2517
  enableScrollForNextCalculateItemsInView: true,
2202
2518
  endBuffered: -1,
2203
2519
  endNoBuffer: -1,
@@ -2236,6 +2552,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2236
2552
  startBuffered: -1,
2237
2553
  startNoBuffer: -1,
2238
2554
  startReachedBlockedByTimer: false,
2555
+ stickyContainerPool: /* @__PURE__ */ new Set(),
2556
+ stickyContainers: /* @__PURE__ */ new Map(),
2239
2557
  timeoutSizeMessage: 0,
2240
2558
  timeouts: /* @__PURE__ */ new Set(),
2241
2559
  totalSize: 0,
@@ -2252,6 +2570,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2252
2570
  data: dataProp,
2253
2571
  estimatedItemSize,
2254
2572
  getEstimatedItemSize,
2573
+ getFixedItemSize,
2574
+ getItemType,
2255
2575
  horizontal: !!horizontal,
2256
2576
  initialContainerPoolRatio,
2257
2577
  initialScroll,
@@ -2267,9 +2587,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2267
2587
  onScroll: onScrollProp,
2268
2588
  onStartReached,
2269
2589
  onStartReachedThreshold,
2590
+ recycleItems: !!recycleItems,
2270
2591
  renderItem: renderItem2,
2271
2592
  scrollBuffer,
2272
2593
  snapToIndices,
2594
+ stickyIndicesArr: stickyIndices != null ? stickyIndices : [],
2595
+ stickyIndicesSet: React3.useMemo(() => new Set(stickyIndices), [stickyIndices]),
2273
2596
  stylePaddingBottom: stylePaddingBottomState,
2274
2597
  stylePaddingTop: stylePaddingTopState,
2275
2598
  suggestEstimatedItemSize: !!suggestEstimatedItemSize
@@ -2507,6 +2830,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2507
2830
  }),
2508
2831
  []
2509
2832
  );
2833
+ const animatedScrollHandler = React3.useMemo(() => {
2834
+ if (stickyIndices == null ? void 0 : stickyIndices.length) {
2835
+ const { animatedScrollY } = ctx;
2836
+ return reactNative.Animated.event([{ nativeEvent: { contentOffset: { [horizontal ? "x" : "y"]: animatedScrollY } } }], {
2837
+ listener: fns.onScroll,
2838
+ useNativeDriver: true
2839
+ });
2840
+ }
2841
+ return fns.onScroll;
2842
+ }, [stickyIndices, horizontal, onScroll]);
2510
2843
  return /* @__PURE__ */ React3__namespace.createElement(React3__namespace.Fragment, null, /* @__PURE__ */ React3__namespace.createElement(
2511
2844
  ListComponent,
2512
2845
  {
@@ -2523,14 +2856,20 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2523
2856
  onLayout,
2524
2857
  onLayoutHeader,
2525
2858
  onMomentumScrollEnd: (event) => {
2526
- requestAnimationFrame(() => {
2527
- finishScrollTo(refState.current);
2528
- });
2859
+ if (IsNewArchitecture) {
2860
+ requestAnimationFrame(() => {
2861
+ finishScrollTo(refState.current);
2862
+ });
2863
+ } else {
2864
+ setTimeout(() => {
2865
+ finishScrollTo(refState.current);
2866
+ }, 1e3);
2867
+ }
2529
2868
  if (onMomentumScrollEnd) {
2530
2869
  onMomentumScrollEnd(event);
2531
2870
  }
2532
2871
  },
2533
- onScroll: fns.onScroll,
2872
+ onScroll: animatedScrollHandler,
2534
2873
  recycleItems,
2535
2874
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3__namespace.cloneElement(refreshControl, {
2536
2875
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
@@ -2546,6 +2885,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2546
2885
  scrollAdjustHandler: (_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler,
2547
2886
  scrollEventThrottle: reactNative.Platform.OS === "web" ? 16 : void 0,
2548
2887
  snapToIndices,
2888
+ stickyIndices,
2549
2889
  style,
2550
2890
  updateItemSize: fns.updateItemSize,
2551
2891
  waitForInitialLayout