@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.mjs CHANGED
@@ -1,12 +1,13 @@
1
1
  import * as React3 from 'react';
2
- import React3__default, { useReducer, useEffect, createContext, useRef, useState, useMemo, useLayoutEffect, useCallback, useImperativeHandle, useContext, forwardRef, memo } from 'react';
3
- import { View, Text, Platform, Animated, ScrollView, StyleSheet, Dimensions, RefreshControl, unstable_batchedUpdates } from 'react-native';
2
+ import React3__default, { useReducer, useEffect, createContext, useRef, useState, useMemo, useLayoutEffect, useCallback, useImperativeHandle, forwardRef, memo, useContext } from 'react';
3
+ import { View, Text, Platform, Animated, StyleSheet, Dimensions, RefreshControl, unstable_batchedUpdates } from 'react-native';
4
4
  import { useSyncExternalStore } from 'use-sync-external-store/shim';
5
5
 
6
6
  // src/components/LazyLegendList.tsx
7
7
  var ContextState = React3.createContext(null);
8
8
  function StateProvider({ children }) {
9
9
  const [value] = React3.useState(() => ({
10
+ animatedScrollY: new Animated.Value(0),
10
11
  columnWrapperStyle: void 0,
11
12
  listeners: /* @__PURE__ */ new Map(),
12
13
  mapViewabilityAmountCallbacks: /* @__PURE__ */ new Map(),
@@ -164,18 +165,130 @@ var LeanViewComponent = React3.forwardRef((props, ref) => {
164
165
  LeanViewComponent.displayName = "RCTView";
165
166
  var LeanView = Platform.OS === "android" || Platform.OS === "ios" ? LeanViewComponent : View;
166
167
 
168
+ // src/constants.ts
169
+ var POSITION_OUT_OF_VIEW = -1e7;
170
+ var ENABLE_DEVMODE = __DEV__ && false;
171
+ var ENABLE_DEBUG_VIEW = __DEV__ && false;
172
+ var IsNewArchitecture = global.nativeFabricUIManager != null;
173
+ var useAnimatedValue = (initialValue) => {
174
+ return useRef(new Animated.Value(initialValue)).current;
175
+ };
176
+
177
+ // src/hooks/useValue$.ts
178
+ function useValue$(key, params) {
179
+ var _a;
180
+ const { getValue, delay } = params || {};
181
+ const ctx = useStateContext();
182
+ const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
183
+ useMemo(() => {
184
+ let newValue;
185
+ let prevValue;
186
+ let didQueueTask = false;
187
+ listen$(ctx, key, (v) => {
188
+ newValue = getValue ? getValue(v) : v;
189
+ if (delay !== void 0) {
190
+ const fn = () => {
191
+ didQueueTask = false;
192
+ if (newValue !== void 0) {
193
+ animValue.setValue(newValue);
194
+ }
195
+ };
196
+ const delayValue = typeof delay === "function" ? delay(newValue, prevValue) : delay;
197
+ prevValue = newValue;
198
+ if (!didQueueTask) {
199
+ didQueueTask = true;
200
+ if (delayValue === 0) {
201
+ queueMicrotask(fn);
202
+ } else {
203
+ setTimeout(fn, delayValue);
204
+ }
205
+ }
206
+ } else {
207
+ animValue.setValue(newValue);
208
+ }
209
+ });
210
+ }, []);
211
+ return animValue;
212
+ }
213
+ var typedForwardRef = forwardRef;
214
+ var typedMemo = memo;
215
+
216
+ // src/components/PositionView.tsx
217
+ var PositionViewState = typedMemo(function PositionView({
218
+ id,
219
+ horizontal,
220
+ style,
221
+ refView,
222
+ ...rest
223
+ }) {
224
+ const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
225
+ return /* @__PURE__ */ React3.createElement(
226
+ LeanView,
227
+ {
228
+ ref: refView,
229
+ style: [
230
+ style,
231
+ horizontal ? { transform: [{ translateX: position }] } : { transform: [{ translateY: position }] }
232
+ ],
233
+ ...rest
234
+ }
235
+ );
236
+ });
237
+ var PositionViewAnimated = typedMemo(function PositionView2({
238
+ id,
239
+ horizontal,
240
+ style,
241
+ refView,
242
+ ...rest
243
+ }) {
244
+ const position$ = useValue$(`containerPosition${id}`, {
245
+ getValue: (v) => v != null ? v : POSITION_OUT_OF_VIEW
246
+ });
247
+ return /* @__PURE__ */ React3.createElement(
248
+ Animated.View,
249
+ {
250
+ ref: refView,
251
+ style: [
252
+ style,
253
+ horizontal ? { transform: [{ translateX: position$ }] } : { transform: [{ translateY: position$ }] }
254
+ ],
255
+ ...rest
256
+ }
257
+ );
258
+ });
259
+ var PositionViewSticky = typedMemo(function PositionViewSticky2({
260
+ id,
261
+ horizontal,
262
+ style,
263
+ refView,
264
+ animatedScrollY,
265
+ stickyOffset,
266
+ index,
267
+ ...rest
268
+ }) {
269
+ const [position = POSITION_OUT_OF_VIEW] = useArr$([`containerPosition${id}`]);
270
+ const transform = React3.useMemo(() => {
271
+ if (animatedScrollY && stickyOffset) {
272
+ const stickyPosition = animatedScrollY.interpolate({
273
+ extrapolate: "clamp",
274
+ inputRange: [position, position + 5e3],
275
+ outputRange: [position, position + 5e3]
276
+ });
277
+ return horizontal ? [{ translateX: stickyPosition }] : [{ translateY: stickyPosition }];
278
+ }
279
+ }, [position, horizontal, animatedScrollY, stickyOffset]);
280
+ console.log("index", index, position, transform);
281
+ const viewStyle = React3.useMemo(() => [style, { zIndex: index + 1e3 }, { transform }], [style, transform]);
282
+ return /* @__PURE__ */ React3.createElement(Animated.View, { ref: refView, style: viewStyle, ...rest });
283
+ });
284
+ var PositionView3 = IsNewArchitecture ? PositionViewState : PositionViewAnimated;
285
+
167
286
  // src/components/Separator.tsx
168
287
  function Separator({ ItemSeparatorComponent, itemKey, leadingItem }) {
169
288
  const [lastItemKeys] = useArr$(["lastItemKeys"]);
170
289
  const isALastItem = lastItemKeys.includes(itemKey);
171
290
  return isALastItem ? null : /* @__PURE__ */ React.createElement(ItemSeparatorComponent, { leadingItem });
172
291
  }
173
-
174
- // src/constants.ts
175
- var POSITION_OUT_OF_VIEW = -1e7;
176
- var ENABLE_DEVMODE = __DEV__ && false;
177
- var ENABLE_DEBUG_VIEW = __DEV__ && false;
178
- var IsNewArchitecture = global.nativeFabricUIManager != null;
179
292
  var symbolFirst = Symbol();
180
293
  function useInit(cb) {
181
294
  const refValue = useRef(symbolFirst);
@@ -312,8 +425,6 @@ function useListScrollSize() {
312
425
  const [scrollSize] = useArr$(["scrollSize"]);
313
426
  return scrollSize;
314
427
  }
315
- var typedForwardRef = forwardRef;
316
- var typedMemo = memo;
317
428
 
318
429
  // src/components/Container.tsx
319
430
  var Container = typedMemo(function Container2({
@@ -325,14 +436,15 @@ var Container = typedMemo(function Container2({
325
436
  ItemSeparatorComponent
326
437
  }) {
327
438
  const ctx = useStateContext();
328
- const columnWrapperStyle = ctx.columnWrapperStyle;
329
- const [column = 0, data, itemKey, position = POSITION_OUT_OF_VIEW, numColumns, extraData] = useArr$([
439
+ const { columnWrapperStyle, animatedScrollY } = ctx;
440
+ const [column = 0, data, itemKey, numColumns, extraData, isSticky, stickyOffset] = useArr$([
330
441
  `containerColumn${id}`,
331
442
  `containerItemData${id}`,
332
443
  `containerItemKey${id}`,
333
- `containerPosition${id}`,
334
444
  "numColumns",
335
- "extraData"
445
+ "extraData",
446
+ `containerSticky${id}`,
447
+ `containerStickyOffset${id}`
336
448
  ]);
337
449
  const refLastSize = useRef();
338
450
  const ref = useRef(null);
@@ -340,36 +452,38 @@ var Container = typedMemo(function Container2({
340
452
  const otherAxisPos = numColumns > 1 ? `${(column - 1) / numColumns * 100}%` : 0;
341
453
  const otherAxisSize = numColumns > 1 ? `${1 / numColumns * 100}%` : void 0;
342
454
  let didLayout = false;
343
- let paddingStyles;
344
- if (columnWrapperStyle) {
345
- const { columnGap, rowGap, gap } = columnWrapperStyle;
346
- if (horizontal) {
347
- paddingStyles = {
348
- paddingRight: columnGap || gap || void 0,
349
- paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
350
- };
351
- } else {
352
- paddingStyles = {
353
- paddingBottom: rowGap || gap || void 0,
354
- paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
355
- };
455
+ const style = useMemo(() => {
456
+ let paddingStyles;
457
+ if (columnWrapperStyle) {
458
+ const { columnGap, rowGap, gap } = columnWrapperStyle;
459
+ if (horizontal) {
460
+ paddingStyles = {
461
+ paddingRight: columnGap || gap || void 0,
462
+ paddingVertical: numColumns > 1 ? (rowGap || gap || 0) / 2 : void 0
463
+ };
464
+ } else {
465
+ paddingStyles = {
466
+ paddingBottom: rowGap || gap || void 0,
467
+ paddingHorizontal: numColumns > 1 ? (columnGap || gap || 0) / 2 : void 0
468
+ };
469
+ }
356
470
  }
357
- }
358
- const style = horizontal ? {
359
- flexDirection: ItemSeparatorComponent ? "row" : void 0,
360
- height: otherAxisSize,
361
- left: position,
362
- position: "absolute",
363
- top: otherAxisPos,
364
- ...paddingStyles || {}
365
- } : {
366
- left: otherAxisPos,
367
- position: "absolute",
368
- right: numColumns > 1 ? null : 0,
369
- top: position,
370
- width: otherAxisSize,
371
- ...paddingStyles || {}
372
- };
471
+ return horizontal ? {
472
+ flexDirection: ItemSeparatorComponent ? "row" : void 0,
473
+ height: otherAxisSize,
474
+ left: 0,
475
+ position: "absolute",
476
+ top: otherAxisPos,
477
+ ...paddingStyles || {}
478
+ } : {
479
+ left: otherAxisPos,
480
+ position: "absolute",
481
+ right: numColumns > 1 ? null : 0,
482
+ top: 0,
483
+ width: otherAxisSize,
484
+ ...paddingStyles || {}
485
+ };
486
+ }, [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns]);
373
487
  const renderedItemInfo = useMemo(
374
488
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
375
489
  [itemKey, data, extraData]
@@ -434,55 +548,30 @@ var Container = typedMemo(function Container2({
434
548
  }
435
549
  }, [itemKey]);
436
550
  }
437
- return /* @__PURE__ */ React3.createElement(LeanView, { key: recycleItems ? void 0 : itemKey, onLayout, ref, style }, /* @__PURE__ */ React3.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3.createElement(
438
- Separator,
551
+ const PositionComponent = isSticky ? PositionViewSticky : PositionView3;
552
+ return /* @__PURE__ */ React3.createElement(
553
+ PositionComponent,
439
554
  {
440
- ItemSeparatorComponent,
441
- itemKey,
442
- leadingItem: renderedItemInfo.item
443
- }
444
- )));
445
- });
446
- var useAnimatedValue = (initialValue) => {
447
- return useRef(new Animated.Value(initialValue)).current;
448
- };
449
-
450
- // src/hooks/useValue$.ts
451
- function useValue$(key, params) {
452
- var _a;
453
- const { getValue, delay } = params || {};
454
- const ctx = useStateContext();
455
- const animValue = useAnimatedValue((_a = getValue ? getValue(peek$(ctx, key)) : peek$(ctx, key)) != null ? _a : 0);
456
- useMemo(() => {
457
- let newValue;
458
- let prevValue;
459
- let didQueueTask = false;
460
- listen$(ctx, key, (v) => {
461
- newValue = getValue ? getValue(v) : v;
462
- if (delay !== void 0) {
463
- const fn = () => {
464
- didQueueTask = false;
465
- if (newValue !== void 0) {
466
- animValue.setValue(newValue);
467
- }
468
- };
469
- const delayValue = typeof delay === "function" ? delay(newValue, prevValue) : delay;
470
- prevValue = newValue;
471
- if (!didQueueTask) {
472
- didQueueTask = true;
473
- if (delayValue === 0) {
474
- queueMicrotask(fn);
475
- } else {
476
- setTimeout(fn, delayValue);
477
- }
478
- }
479
- } else {
480
- animValue.setValue(newValue);
555
+ animatedScrollY: isSticky ? animatedScrollY : void 0,
556
+ horizontal,
557
+ id,
558
+ index,
559
+ key: recycleItems ? void 0 : itemKey,
560
+ onLayout,
561
+ refView: ref,
562
+ stickyOffset: isSticky ? stickyOffset : void 0,
563
+ style
564
+ },
565
+ /* @__PURE__ */ React3.createElement(ContextContainer.Provider, { value: contextValue }, renderedItem, renderedItemInfo && ItemSeparatorComponent && /* @__PURE__ */ React3.createElement(
566
+ Separator,
567
+ {
568
+ ItemSeparatorComponent,
569
+ itemKey,
570
+ leadingItem: renderedItemInfo.item
481
571
  }
482
- });
483
- }, []);
484
- return animValue;
485
- }
572
+ ))
573
+ );
574
+ });
486
575
 
487
576
  // src/components/Containers.tsx
488
577
  var Containers = typedMemo(function Containers2({
@@ -642,6 +731,7 @@ var ListComponent = typedMemo(function ListComponent2({
642
731
  scrollAdjustHandler,
643
732
  onLayoutHeader,
644
733
  snapToIndices,
734
+ stickyIndices,
645
735
  ...rest
646
736
  }) {
647
737
  const ctx = useStateContext();
@@ -651,7 +741,7 @@ var ListComponent = typedMemo(function ListComponent2({
651
741
  const ScrollComponent = renderScrollComponent ? useMemo(
652
742
  () => React3.forwardRef((props, ref) => renderScrollComponent({ ...props, ref })),
653
743
  [renderScrollComponent]
654
- ) : ScrollView;
744
+ ) : Animated.ScrollView;
655
745
  React3.useEffect(() => {
656
746
  if (canRender) {
657
747
  setTimeout(() => {
@@ -704,9 +794,26 @@ var ListComponent = typedMemo(function ListComponent2({
704
794
  style: ListFooterComponentStyle
705
795
  },
706
796
  getComponent(ListFooterComponent)
707
- )
797
+ ),
798
+ __DEV__ && ENABLE_DEVMODE && /* @__PURE__ */ React3.createElement(DevNumbers, null)
708
799
  );
709
800
  });
801
+ var DevNumbers = __DEV__ && React3.memo(function DevNumbers2() {
802
+ return Array.from({ length: 100 }).map((_, index) => /* @__PURE__ */ React3.createElement(
803
+ View,
804
+ {
805
+ key: index,
806
+ style: {
807
+ height: 100,
808
+ pointerEvents: "none",
809
+ position: "absolute",
810
+ top: index * 100,
811
+ width: "100%"
812
+ }
813
+ },
814
+ /* @__PURE__ */ React3.createElement(Text, { style: { color: "red" } }, index * 100)
815
+ ));
816
+ });
710
817
 
711
818
  // src/utils/getId.ts
712
819
  function getId(state, index) {
@@ -738,20 +845,36 @@ function calculateOffsetForIndex(ctx, state, index) {
738
845
  }
739
846
 
740
847
  // src/utils/getItemSize.ts
741
- function getItemSize(state, key, index, data, useAverageSize) {
848
+ function getItemSize(state, key, index, data, useAverageSize, defaultAverageSize) {
849
+ var _a, _b;
742
850
  const {
743
851
  sizesKnown,
744
852
  sizes,
745
853
  scrollingTo,
746
- props: { estimatedItemSize, getEstimatedItemSize }
854
+ averageSizes,
855
+ props: { estimatedItemSize, getEstimatedItemSize, getFixedItemSize, getItemType }
747
856
  } = state;
748
857
  const sizeKnown = sizesKnown.get(key);
749
858
  if (sizeKnown !== void 0) {
750
859
  return sizeKnown;
751
860
  }
752
861
  let size;
753
- if (useAverageSize !== void 0 && sizeKnown === void 0 && !getEstimatedItemSize && !scrollingTo) {
754
- size = useAverageSize;
862
+ const itemType = getItemType ? (_a = getItemType(data, index)) != null ? _a : "" : "";
863
+ if (getFixedItemSize) {
864
+ size = getFixedItemSize(index, data, itemType);
865
+ if (size !== void 0) {
866
+ sizesKnown.set(key, size);
867
+ }
868
+ }
869
+ if (size === void 0 && useAverageSize && sizeKnown === void 0 && !scrollingTo) {
870
+ if (itemType === "") {
871
+ size = defaultAverageSize;
872
+ } else {
873
+ const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
874
+ if (averageSizeForType !== void 0) {
875
+ size = roundSize(averageSizeForType);
876
+ }
877
+ }
755
878
  }
756
879
  if (size === void 0) {
757
880
  size = sizes.get(key);
@@ -760,7 +883,7 @@ function getItemSize(state, key, index, data, useAverageSize) {
760
883
  }
761
884
  }
762
885
  if (size === void 0) {
763
- size = getEstimatedItemSize ? getEstimatedItemSize(index, data) : estimatedItemSize;
886
+ size = getEstimatedItemSize ? getEstimatedItemSize(index, data, itemType) : estimatedItemSize;
764
887
  }
765
888
  sizes.set(key, size);
766
889
  return size;
@@ -779,6 +902,37 @@ function calculateOffsetWithOffsetPosition(state, offsetParam, params) {
779
902
  return offset;
780
903
  }
781
904
 
905
+ // src/core/finishScrollTo.ts
906
+ var finishScrollTo = (state) => {
907
+ if (state) {
908
+ state.scrollingTo = void 0;
909
+ state.scrollHistory.length = 0;
910
+ }
911
+ };
912
+
913
+ // src/core/scrollTo.ts
914
+ function scrollTo(state, params = {}) {
915
+ var _a;
916
+ const { animated } = params;
917
+ const {
918
+ refScroller,
919
+ props: { horizontal }
920
+ } = state;
921
+ const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
922
+ state.scrollHistory.length = 0;
923
+ state.scrollingTo = params;
924
+ state.scrollPending = offset;
925
+ (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
926
+ animated: !!animated,
927
+ x: horizontal ? offset : 0,
928
+ y: horizontal ? 0 : offset
929
+ });
930
+ if (!animated) {
931
+ state.scroll = offset;
932
+ setTimeout(() => finishScrollTo(state), 100);
933
+ }
934
+ }
935
+
782
936
  // src/utils/requestAdjust.ts
783
937
  function requestAdjust(ctx, state, positionDiff) {
784
938
  if (Math.abs(positionDiff) > 0.1) {
@@ -812,7 +966,7 @@ function requestAdjust(ctx, state, positionDiff) {
812
966
  }
813
967
 
814
968
  // src/core/prepareMVCP.ts
815
- function prepareMVCP(ctx, state) {
969
+ function prepareMVCP(ctx, state, dataChanged) {
816
970
  const {
817
971
  positions,
818
972
  scrollingTo,
@@ -841,7 +995,13 @@ function prepareMVCP(ctx, state) {
841
995
  if (newPosition !== void 0) {
842
996
  const positionDiff = newPosition - prevPosition;
843
997
  if (Math.abs(positionDiff) > 0.1) {
844
- requestAdjust(ctx, state, positionDiff);
998
+ if (Platform.OS === "android" && !IsNewArchitecture && dataChanged && state.scroll <= positionDiff) {
999
+ scrollTo(state, {
1000
+ offset: state.scroll + positionDiff
1001
+ });
1002
+ } else {
1003
+ requestAdjust(ctx, state, positionDiff);
1004
+ }
845
1005
  }
846
1006
  }
847
1007
  }
@@ -983,7 +1143,7 @@ function updateAllPositions(ctx, state, dataChanged) {
983
1143
  firstFullyOnScreenIndex,
984
1144
  idCache,
985
1145
  sizesKnown,
986
- props: { snapToIndices }
1146
+ props: { getEstimatedItemSize, snapToIndices }
987
1147
  } = state;
988
1148
  const data = state.props.data;
989
1149
  const numColumns = peek$(ctx, "numColumns");
@@ -993,6 +1153,7 @@ function updateAllPositions(ctx, state, dataChanged) {
993
1153
  indexByKey.clear();
994
1154
  idCache.clear();
995
1155
  }
1156
+ const useAverageSize = !getEstimatedItemSize;
996
1157
  const itemType = "";
997
1158
  let averageSize = (_a = averageSizes[itemType]) == null ? void 0 : _a.avg;
998
1159
  if (averageSize !== void 0) {
@@ -1008,7 +1169,7 @@ function updateAllPositions(ctx, state, dataChanged) {
1008
1169
  let bailout = false;
1009
1170
  for (let i = firstFullyOnScreenIndex - 1; i >= 0; i--) {
1010
1171
  const id = (_b = idCache.get(i)) != null ? _b : getId(state, i);
1011
- const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(state, id, i, data[i], averageSize);
1172
+ const size = (_c = sizesKnown.get(id)) != null ? _c : getItemSize(state, id, i, data[i], useAverageSize, averageSize);
1012
1173
  const itemColumn = columns.get(id);
1013
1174
  maxSizeInRow2 = Math.max(maxSizeInRow2, size);
1014
1175
  if (itemColumn === 1) {
@@ -1035,7 +1196,7 @@ function updateAllPositions(ctx, state, dataChanged) {
1035
1196
  const dataLength = data.length;
1036
1197
  for (let i = 0; i < dataLength; i++) {
1037
1198
  const id = (_d = idCache.get(i)) != null ? _d : getId(state, i);
1038
- const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(state, id, i, data[i], averageSize);
1199
+ const size = (_e = sizesKnown.get(id)) != null ? _e : getItemSize(state, id, i, data[i], useAverageSize, averageSize);
1039
1200
  if (__DEV__ && needsIndexByKey) {
1040
1201
  if (indexByKeyForChecking.has(id)) {
1041
1202
  console.error(
@@ -1274,35 +1435,84 @@ function checkAllSizesKnown(state) {
1274
1435
  }
1275
1436
 
1276
1437
  // src/utils/findAvailableContainers.ts
1277
- function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval) {
1438
+ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffered, pendingRemoval, requiredItemTypes, needNewContainers) {
1278
1439
  const numContainers = peek$(ctx, "numContainers");
1440
+ const { stickyIndicesSet } = state.props;
1279
1441
  const result = [];
1280
1442
  const availableContainers = [];
1281
- for (let u = 0; u < numContainers; u++) {
1282
- const key = peek$(ctx, `containerItemKey${u}`);
1283
- let isOk = key === void 0;
1284
- if (!isOk) {
1285
- const index = pendingRemoval.indexOf(u);
1286
- if (index !== -1) {
1287
- pendingRemoval.splice(index, 1);
1288
- isOk = true;
1443
+ const stickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => stickyIndicesSet.has(index))) || [];
1444
+ const nonStickyItemIndices = (needNewContainers == null ? void 0 : needNewContainers.filter((index) => !stickyIndicesSet.has(index))) || [];
1445
+ const canReuseContainer = (containerIndex, requiredType) => {
1446
+ if (!requiredType) return true;
1447
+ const existingType = state.containerItemTypes.get(containerIndex);
1448
+ if (!existingType) return true;
1449
+ return existingType === requiredType;
1450
+ };
1451
+ const neededTypes = requiredItemTypes ? [...requiredItemTypes] : [];
1452
+ let typeIndex = 0;
1453
+ for (let i = 0; i < stickyItemIndices.length; i++) {
1454
+ const requiredType = neededTypes[typeIndex];
1455
+ let foundContainer = false;
1456
+ for (const containerIndex of state.stickyContainerPool) {
1457
+ const key = peek$(ctx, `containerItemKey${containerIndex}`);
1458
+ const isPendingRemoval = pendingRemoval.includes(containerIndex);
1459
+ if ((key === void 0 || isPendingRemoval) && canReuseContainer(containerIndex, requiredType)) {
1460
+ result.push(containerIndex);
1461
+ if (isPendingRemoval) {
1462
+ const index = pendingRemoval.indexOf(containerIndex);
1463
+ pendingRemoval.splice(index, 1);
1464
+ }
1465
+ foundContainer = true;
1466
+ if (requiredItemTypes) typeIndex++;
1467
+ break;
1289
1468
  }
1290
1469
  }
1291
- if (isOk) {
1292
- result.push(u);
1293
- if (result.length >= numNeeded) {
1294
- return result;
1470
+ if (!foundContainer) {
1471
+ const newContainerIndex = numContainers + result.filter((index) => index >= numContainers).length;
1472
+ result.push(newContainerIndex);
1473
+ state.stickyContainerPool.add(newContainerIndex);
1474
+ if (requiredItemTypes) typeIndex++;
1475
+ }
1476
+ }
1477
+ if (nonStickyItemIndices.length > 0) {
1478
+ for (let u = 0; u < numContainers; u++) {
1479
+ if (state.stickyContainerPool.has(u)) {
1480
+ continue;
1481
+ }
1482
+ const key = peek$(ctx, `containerItemKey${u}`);
1483
+ let isOk = key === void 0;
1484
+ if (!isOk) {
1485
+ const index = pendingRemoval.indexOf(u);
1486
+ if (index !== -1) {
1487
+ pendingRemoval.splice(index, 1);
1488
+ const requiredType = neededTypes[typeIndex];
1489
+ isOk = canReuseContainer(u, requiredType);
1490
+ }
1491
+ }
1492
+ if (isOk) {
1493
+ result.push(u);
1494
+ if (requiredItemTypes) {
1495
+ typeIndex++;
1496
+ }
1497
+ if (result.length >= numNeeded) {
1498
+ return result;
1499
+ }
1295
1500
  }
1296
1501
  }
1297
1502
  }
1298
1503
  for (let u = 0; u < numContainers; u++) {
1504
+ if (state.stickyContainerPool.has(u)) {
1505
+ continue;
1506
+ }
1299
1507
  const key = peek$(ctx, `containerItemKey${u}`);
1300
1508
  if (key === void 0) continue;
1301
1509
  const index = state.indexByKey.get(key);
1302
- if (index < startBuffered) {
1303
- availableContainers.push({ distance: startBuffered - index, index: u });
1304
- } else if (index > endBuffered) {
1305
- availableContainers.push({ distance: index - endBuffered, index: u });
1510
+ const isOutOfView = index < startBuffered || index > endBuffered;
1511
+ if (isOutOfView) {
1512
+ const distance = index < startBuffered ? startBuffered - index : index - endBuffered;
1513
+ if (!requiredItemTypes || typeIndex < neededTypes.length && canReuseContainer(u, neededTypes[typeIndex])) {
1514
+ availableContainers.push({ distance, index: u });
1515
+ }
1306
1516
  }
1307
1517
  }
1308
1518
  const remaining = numNeeded - result.length;
@@ -1314,6 +1524,9 @@ function findAvailableContainers(ctx, state, numNeeded, startBuffered, endBuffer
1314
1524
  }
1315
1525
  for (const container of availableContainers) {
1316
1526
  result.push(container.index);
1527
+ if (requiredItemTypes) {
1528
+ typeIndex++;
1529
+ }
1317
1530
  }
1318
1531
  }
1319
1532
  const stillNeeded = numNeeded - result.length;
@@ -1342,37 +1555,6 @@ function comparatorByDistance(a, b) {
1342
1555
  return b.distance - a.distance;
1343
1556
  }
1344
1557
 
1345
- // src/core/finishScrollTo.ts
1346
- var finishScrollTo = (state) => {
1347
- if (state) {
1348
- state.scrollingTo = void 0;
1349
- state.scrollHistory.length = 0;
1350
- }
1351
- };
1352
-
1353
- // src/core/scrollTo.ts
1354
- function scrollTo(state, params = {}) {
1355
- var _a;
1356
- const { animated } = params;
1357
- const {
1358
- refScroller,
1359
- props: { horizontal }
1360
- } = state;
1361
- const offset = calculateOffsetWithOffsetPosition(state, params.offset, params);
1362
- state.scrollHistory.length = 0;
1363
- state.scrollingTo = params;
1364
- state.scrollPending = offset;
1365
- (_a = refScroller.current) == null ? void 0 : _a.scrollTo({
1366
- animated: !!animated,
1367
- x: horizontal ? offset : 0,
1368
- y: horizontal ? 0 : offset
1369
- });
1370
- if (!animated) {
1371
- state.scroll = offset;
1372
- setTimeout(() => finishScrollTo(state), 100);
1373
- }
1374
- }
1375
-
1376
1558
  // src/core/scrollToIndex.ts
1377
1559
  function scrollToIndex(ctx, state, { index, viewOffset = 0, animated = true, viewPosition }) {
1378
1560
  if (index >= state.props.data.length) {
@@ -1460,16 +1642,90 @@ function setDidLayout(ctx, state) {
1460
1642
  } = state;
1461
1643
  state.queuedInitialLayout = true;
1462
1644
  checkAtBottom(ctx, state);
1463
- if (!IsNewArchitecture && initialScroll) {
1464
- scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1465
- }
1466
- set$(ctx, "containersDidLayout", true);
1467
- if (onLoad) {
1468
- onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1645
+ const setIt = () => {
1646
+ set$(ctx, "containersDidLayout", true);
1647
+ if (onLoad) {
1648
+ onLoad({ elapsedTimeInMs: Date.now() - loadStartTime });
1649
+ }
1650
+ };
1651
+ if (Platform.OS === "android" || !IsNewArchitecture) {
1652
+ if (initialScroll) {
1653
+ queueMicrotask(() => {
1654
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1655
+ requestAnimationFrame(() => {
1656
+ scrollToIndex(ctx, state, { ...initialScroll, animated: false });
1657
+ setIt();
1658
+ });
1659
+ });
1660
+ } else {
1661
+ queueMicrotask(setIt);
1662
+ }
1663
+ } else {
1664
+ setIt();
1469
1665
  }
1470
1666
  }
1471
1667
 
1472
1668
  // src/core/calculateItemsInView.ts
1669
+ function findCurrentStickyIndex(stickyArray, scroll, state) {
1670
+ var _a;
1671
+ for (let i = stickyArray.length - 1; i >= 0; i--) {
1672
+ const stickyId = (_a = state.idCache.get(stickyArray[i])) != null ? _a : getId(state, stickyArray[i]);
1673
+ const stickyPos = stickyId ? state.positions.get(stickyId) : void 0;
1674
+ if (stickyPos !== void 0 && scroll >= stickyPos) {
1675
+ return i;
1676
+ }
1677
+ }
1678
+ return -1;
1679
+ }
1680
+ function getActiveStickyIndices(ctx, state, stickyIndices) {
1681
+ return new Set(
1682
+ 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))
1683
+ );
1684
+ }
1685
+ function handleStickyActivation(ctx, state, stickyIndices, stickyArray, scroll, needNewContainers, startBuffered, endBuffered) {
1686
+ var _a;
1687
+ const activeIndices = getActiveStickyIndices(ctx, state, stickyIndices);
1688
+ const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1689
+ for (let offset = 0; offset <= 1; offset++) {
1690
+ const idx = currentStickyIdx - offset;
1691
+ if (idx < 0 || activeIndices.has(stickyArray[idx])) continue;
1692
+ const stickyIndex = stickyArray[idx];
1693
+ const stickyId = (_a = state.idCache.get(stickyIndex)) != null ? _a : getId(state, stickyIndex);
1694
+ if (stickyId && !state.containerItemKeys.has(stickyId) && (stickyIndex < startBuffered || stickyIndex > endBuffered)) {
1695
+ needNewContainers.push(stickyIndex);
1696
+ }
1697
+ }
1698
+ }
1699
+ function handleStickyRecycling(ctx, state, stickyArray, scroll, scrollBuffer, pendingRemoval) {
1700
+ var _a, _b, _c;
1701
+ const currentStickyIdx = findCurrentStickyIndex(stickyArray, scroll, state);
1702
+ for (const containerIndex of state.stickyContainerPool) {
1703
+ const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
1704
+ const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
1705
+ if (itemIndex === void 0) continue;
1706
+ const arrayIdx = stickyArray.indexOf(itemIndex);
1707
+ if (arrayIdx === -1) continue;
1708
+ const isRecentSticky = arrayIdx >= currentStickyIdx - 1 && arrayIdx <= currentStickyIdx + 1;
1709
+ if (isRecentSticky) continue;
1710
+ const nextIndex = stickyArray[arrayIdx + 1];
1711
+ let shouldRecycle = false;
1712
+ if (nextIndex) {
1713
+ const nextId = (_a = state.idCache.get(nextIndex)) != null ? _a : getId(state, nextIndex);
1714
+ const nextPos = nextId ? state.positions.get(nextId) : void 0;
1715
+ shouldRecycle = nextPos !== void 0 && scroll > nextPos + scrollBuffer * 2;
1716
+ } else {
1717
+ const currentId = (_b = state.idCache.get(itemIndex)) != null ? _b : getId(state, itemIndex);
1718
+ if (currentId) {
1719
+ const currentPos = state.positions.get(currentId);
1720
+ const currentSize = (_c = state.sizes.get(currentId)) != null ? _c : getItemSize(state, currentId, itemIndex, state.props.data[itemIndex]);
1721
+ shouldRecycle = currentPos !== void 0 && scroll > currentPos + currentSize + scrollBuffer * 3;
1722
+ }
1723
+ }
1724
+ if (shouldRecycle) {
1725
+ pendingRemoval.push(containerIndex);
1726
+ }
1727
+ }
1728
+ }
1473
1729
  function calculateItemsInView(ctx, state, params = {}) {
1474
1730
  unstable_batchedUpdates(() => {
1475
1731
  var _a, _b, _c, _d, _e, _f, _g, _h;
@@ -1486,7 +1742,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1486
1742
  enableScrollForNextCalculateItemsInView,
1487
1743
  minIndexSizeChanged
1488
1744
  } = state;
1489
- const data = state.props.data;
1745
+ const { data, stickyIndicesArr, stickyIndicesSet } = state.props;
1490
1746
  const prevNumContainers = peek$(ctx, "numContainers");
1491
1747
  if (!data || scrollLength === 0 || !prevNumContainers) {
1492
1748
  return;
@@ -1498,7 +1754,7 @@ function calculateItemsInView(ctx, state, params = {}) {
1498
1754
  const { dataChanged, doMVCP } = params;
1499
1755
  const speed = getScrollVelocity(state);
1500
1756
  if (doMVCP || dataChanged) {
1501
- const checkMVCP = doMVCP ? prepareMVCP(ctx, state) : void 0;
1757
+ const checkMVCP = doMVCP ? prepareMVCP(ctx, state, dataChanged) : void 0;
1502
1758
  updateAllPositions(ctx, state, dataChanged);
1503
1759
  checkMVCP == null ? void 0 : checkMVCP();
1504
1760
  }
@@ -1648,14 +1904,23 @@ function calculateItemsInView(ctx, state, params = {}) {
1648
1904
  needNewContainers.push(i);
1649
1905
  }
1650
1906
  }
1907
+ if (stickyIndicesArr.length > 0) {
1908
+ handleStickyActivation(ctx, state, stickyIndicesSet, stickyIndicesArr, scroll, needNewContainers, startBuffered, endBuffered);
1909
+ }
1651
1910
  if (needNewContainers.length > 0) {
1911
+ const requiredItemTypes = state.props.getItemType ? needNewContainers.map((i) => {
1912
+ const itemType = state.props.getItemType(data[i], i);
1913
+ return itemType ? String(itemType) : "";
1914
+ }) : void 0;
1652
1915
  const availableContainers = findAvailableContainers(
1653
1916
  ctx,
1654
1917
  state,
1655
1918
  needNewContainers.length,
1656
1919
  startBuffered,
1657
1920
  endBuffered,
1658
- pendingRemoval
1921
+ pendingRemoval,
1922
+ requiredItemTypes,
1923
+ needNewContainers
1659
1924
  );
1660
1925
  for (let idx = 0; idx < needNewContainers.length; idx++) {
1661
1926
  const i = needNewContainers[idx];
@@ -1667,7 +1932,18 @@ function calculateItemsInView(ctx, state, params = {}) {
1667
1932
  }
1668
1933
  set$(ctx, `containerItemKey${containerIndex}`, id);
1669
1934
  set$(ctx, `containerItemData${containerIndex}`, data[i]);
1935
+ if (requiredItemTypes) {
1936
+ state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
1937
+ }
1670
1938
  containerItemKeys.add(id);
1939
+ if (stickyIndicesSet.has(i)) {
1940
+ set$(ctx, `containerSticky${containerIndex}`, true);
1941
+ const topPadding = (peek$(ctx, "stylePaddingTop") || 0) + (peek$(ctx, "headerSize") || 0);
1942
+ set$(ctx, `containerStickyOffset${containerIndex}`, new Animated.Value(topPadding));
1943
+ state.stickyContainerPool.add(containerIndex);
1944
+ } else {
1945
+ state.stickyContainerPool.delete(containerIndex);
1946
+ }
1671
1947
  if (containerIndex >= numContainers2) {
1672
1948
  numContainers2 = containerIndex + 1;
1673
1949
  }
@@ -1680,12 +1956,21 @@ function calculateItemsInView(ctx, state, params = {}) {
1680
1956
  }
1681
1957
  }
1682
1958
  }
1959
+ if (stickyIndicesArr.length > 0) {
1960
+ handleStickyRecycling(ctx, state, stickyIndicesArr, scroll, scrollBuffer, pendingRemoval);
1961
+ }
1683
1962
  for (let i = 0; i < numContainers; i++) {
1684
1963
  const itemKey = peek$(ctx, `containerItemKey${i}`);
1685
1964
  if (pendingRemoval.includes(i)) {
1686
1965
  if (itemKey) {
1687
1966
  containerItemKeys.delete(itemKey);
1688
1967
  }
1968
+ state.containerItemTypes.delete(i);
1969
+ if (state.stickyContainerPool.has(i)) {
1970
+ set$(ctx, `containerSticky${i}`, false);
1971
+ set$(ctx, `containerStickyOffset${i}`, void 0);
1972
+ state.stickyContainerPool.delete(i);
1973
+ }
1689
1974
  set$(ctx, `containerItemKey${i}`, void 0);
1690
1975
  set$(ctx, `containerItemData${i}`, void 0);
1691
1976
  set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
@@ -1736,10 +2021,14 @@ function calculateItemsInView(ctx, state, params = {}) {
1736
2021
 
1737
2022
  // src/core/doInitialAllocateContainers.ts
1738
2023
  function doInitialAllocateContainers(ctx, state) {
1739
- const { scrollLength } = state;
2024
+ var _a;
2025
+ const {
2026
+ scrollLength,
2027
+ props: { getItemType }
2028
+ } = state;
1740
2029
  const data = state.props.data;
1741
2030
  if (scrollLength > 0 && data.length > 0 && !peek$(ctx, "numContainers")) {
1742
- const averageItemSize = state.props.getEstimatedItemSize ? state.props.getEstimatedItemSize(0, data[0]) : state.props.estimatedItemSize;
2031
+ const averageItemSize = state.props.getEstimatedItemSize ? state.props.getEstimatedItemSize(0, data[0], getItemType ? (_a = getItemType(data[0], 0)) != null ? _a : "" : "") : state.props.estimatedItemSize;
1743
2032
  const Extra = 1.5;
1744
2033
  const numContainers = Math.ceil(
1745
2034
  (scrollLength + state.props.scrollBuffer * 2) / averageItemSize * state.props.numColumns * Extra
@@ -1776,16 +2065,18 @@ function doMaintainScrollAtEnd(ctx, state, animated) {
1776
2065
  }
1777
2066
  requestAnimationFrame(() => {
1778
2067
  var _a;
1779
- state.maintainingScrollAtEnd = true;
1780
- (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
1781
- animated
1782
- });
1783
- setTimeout(
1784
- () => {
1785
- state.maintainingScrollAtEnd = false;
1786
- },
1787
- 0
1788
- );
2068
+ if (state == null ? void 0 : state.isAtEnd) {
2069
+ state.maintainingScrollAtEnd = true;
2070
+ (_a = refScroller.current) == null ? void 0 : _a.scrollToEnd({
2071
+ animated
2072
+ });
2073
+ setTimeout(
2074
+ () => {
2075
+ state.maintainingScrollAtEnd = false;
2076
+ },
2077
+ 0
2078
+ );
2079
+ }
1789
2080
  });
1790
2081
  return true;
1791
2082
  }
@@ -2005,7 +2296,22 @@ function updateItemSizes(ctx, state, itemUpdates) {
2005
2296
  }
2006
2297
  }
2007
2298
  function updateItemSize(ctx, state, itemKey, sizeObj) {
2008
- const { queuedItemSizeUpdates, queuedItemSizeUpdatesWaiting } = state;
2299
+ var _a;
2300
+ const {
2301
+ queuedItemSizeUpdates,
2302
+ queuedItemSizeUpdatesWaiting,
2303
+ sizesKnown,
2304
+ props: { getFixedItemSize, getItemType }
2305
+ } = state;
2306
+ if (getFixedItemSize) {
2307
+ const index = state.indexByKey.get(itemKey);
2308
+ const itemData = state.props.data[index];
2309
+ const type = getItemType ? (_a = getItemType(itemData, index)) != null ? _a : "" : "";
2310
+ const size = getFixedItemSize(index, itemData, type);
2311
+ if (size !== void 0 && size === sizesKnown.get(itemKey)) {
2312
+ return;
2313
+ }
2314
+ }
2009
2315
  const containersDidLayout = peek$(ctx, "containersDidLayout");
2010
2316
  if (!containersDidLayout || !queuedItemSizeUpdatesWaiting) {
2011
2317
  updateItemSizes(ctx, state, [{ itemKey, sizeObj }]);
@@ -2022,25 +2328,28 @@ function updateItemSize(ctx, state, itemKey, sizeObj) {
2022
2328
  }
2023
2329
  }
2024
2330
  function updateOneItemSize(state, itemKey, sizeObj) {
2331
+ var _a;
2025
2332
  const {
2026
2333
  sizes,
2027
2334
  indexByKey,
2028
2335
  sizesKnown,
2029
2336
  averageSizes,
2030
- props: { data, horizontal }
2337
+ props: { data, horizontal, getEstimatedItemSize, getItemType }
2031
2338
  } = state;
2032
2339
  if (!data) return 0;
2033
2340
  const index = indexByKey.get(itemKey);
2034
2341
  const prevSize = getItemSize(state, itemKey, index, data);
2035
2342
  const size = Math.floor((horizontal ? sizeObj.width : sizeObj.height) * 8) / 8;
2036
2343
  sizesKnown.set(itemKey, size);
2037
- const itemType = "";
2038
- let averages = averageSizes[itemType];
2039
- if (!averages) {
2040
- averages = averageSizes[itemType] = { avg: 0, num: 0 };
2344
+ if (!getEstimatedItemSize) {
2345
+ const itemType = getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : "";
2346
+ let averages = averageSizes[itemType];
2347
+ if (!averages) {
2348
+ averages = averageSizes[itemType] = { avg: 0, num: 0 };
2349
+ }
2350
+ averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2351
+ averages.num++;
2041
2352
  }
2042
- averages.avg = (averages.avg * averages.num + size) / (averages.num + 1);
2043
- averages.num++;
2044
2353
  if (!prevSize || Math.abs(prevSize - size) > 0.1) {
2045
2354
  sizes.set(itemKey, size);
2046
2355
  return size - prevSize;
@@ -2078,12 +2387,13 @@ function createColumnWrapperStyle(contentContainerStyle) {
2078
2387
  }
2079
2388
  }
2080
2389
  function getRenderedItem(ctx, state, key) {
2390
+ var _a;
2081
2391
  if (!state) {
2082
2392
  return null;
2083
2393
  }
2084
2394
  const {
2085
2395
  indexByKey,
2086
- props: { data, renderItem: renderItem2 }
2396
+ props: { data, getItemType, renderItem: renderItem2 }
2087
2397
  } = state;
2088
2398
  const index = indexByKey.get(key);
2089
2399
  if (index === void 0) {
@@ -2094,7 +2404,8 @@ function getRenderedItem(ctx, state, key) {
2094
2404
  const itemProps = {
2095
2405
  extraData: peek$(ctx, "extraData"),
2096
2406
  index,
2097
- item: data[index]
2407
+ item: data[index],
2408
+ type: getItemType ? (_a = getItemType(data[index], index)) != null ? _a : "" : ""
2098
2409
  };
2099
2410
  renderedItem = React3__default.createElement(renderItem2, itemProps);
2100
2411
  }
@@ -2110,49 +2421,52 @@ var LegendList = typedForwardRef(function LegendList2(props, forwardedRef) {
2110
2421
  var LegendListInner = typedForwardRef(function LegendListInner2(props, forwardedRef) {
2111
2422
  var _a;
2112
2423
  const {
2424
+ alignItemsAtEnd = false,
2425
+ columnWrapperStyle,
2426
+ contentContainerStyle: contentContainerStyleProp,
2113
2427
  data: dataProp = [],
2428
+ drawDistance = 250,
2429
+ estimatedItemSize: estimatedItemSizeProp,
2430
+ estimatedListSize,
2431
+ extraData,
2432
+ getEstimatedItemSize,
2433
+ getFixedItemSize,
2434
+ getItemType,
2435
+ horizontal,
2436
+ initialContainerPoolRatio = 2,
2114
2437
  initialScrollIndex: initialScrollIndexProp,
2115
2438
  initialScrollOffset,
2116
- horizontal,
2117
- drawDistance = 250,
2118
- recycleItems = false,
2119
- onEndReachedThreshold = 0.5,
2120
- onStartReachedThreshold = 0.5,
2439
+ keyExtractor: keyExtractorProp,
2440
+ ListEmptyComponent,
2441
+ ListHeaderComponent,
2121
2442
  maintainScrollAtEnd = false,
2122
2443
  maintainScrollAtEndThreshold = 0.1,
2123
- alignItemsAtEnd = false,
2124
2444
  maintainVisibleContentPosition = false,
2125
- onScroll: onScrollProp,
2126
- onMomentumScrollEnd,
2127
2445
  numColumns: numColumnsProp = 1,
2128
- columnWrapperStyle,
2129
- keyExtractor: keyExtractorProp,
2130
- renderItem: renderItem2,
2131
- estimatedListSize,
2132
- estimatedItemSize: estimatedItemSizeProp,
2133
- getEstimatedItemSize,
2134
- suggestEstimatedItemSize,
2135
- ListHeaderComponent,
2136
- ListEmptyComponent,
2446
+ onEndReached,
2447
+ onEndReachedThreshold = 0.5,
2137
2448
  onItemSizeChanged,
2138
- refScrollView,
2139
- waitForInitialLayout = true,
2140
- extraData,
2141
- contentContainerStyle: contentContainerStyleProp,
2142
- style: styleProp,
2143
2449
  onLayout: onLayoutProp,
2450
+ onLoad,
2451
+ onMomentumScrollEnd,
2144
2452
  onRefresh,
2145
- refreshing,
2453
+ onScroll: onScrollProp,
2454
+ onStartReached,
2455
+ onStartReachedThreshold = 0.5,
2456
+ onViewableItemsChanged,
2146
2457
  progressViewOffset,
2458
+ recycleItems = false,
2147
2459
  refreshControl,
2148
- initialContainerPoolRatio = 2,
2460
+ refreshing,
2461
+ refScrollView,
2462
+ renderItem: renderItem2,
2463
+ snapToIndices,
2464
+ stickyIndices,
2465
+ style: styleProp,
2466
+ suggestEstimatedItemSize,
2149
2467
  viewabilityConfig,
2150
2468
  viewabilityConfigCallbackPairs,
2151
- snapToIndices,
2152
- onViewableItemsChanged,
2153
- onStartReached,
2154
- onEndReached,
2155
- onLoad,
2469
+ waitForInitialLayout = true,
2156
2470
  ...rest
2157
2471
  } = props;
2158
2472
  const [renderNum, setRenderNum] = useState(0);
@@ -2174,9 +2488,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2174
2488
  if (!refState.current) {
2175
2489
  const initialScrollLength = (estimatedListSize != null ? estimatedListSize : IsNewArchitecture ? { height: 0, width: 0 } : Dimensions.get("window"))[horizontal ? "width" : "height"];
2176
2490
  refState.current = {
2491
+ activeStickyIndex: void 0,
2177
2492
  averageSizes: {},
2178
2493
  columns: /* @__PURE__ */ new Map(),
2179
2494
  containerItemKeys: /* @__PURE__ */ new Set(),
2495
+ containerItemTypes: /* @__PURE__ */ new Map(),
2180
2496
  enableScrollForNextCalculateItemsInView: true,
2181
2497
  endBuffered: -1,
2182
2498
  endNoBuffer: -1,
@@ -2215,6 +2531,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2215
2531
  startBuffered: -1,
2216
2532
  startNoBuffer: -1,
2217
2533
  startReachedBlockedByTimer: false,
2534
+ stickyContainerPool: /* @__PURE__ */ new Set(),
2535
+ stickyContainers: /* @__PURE__ */ new Map(),
2218
2536
  timeoutSizeMessage: 0,
2219
2537
  timeouts: /* @__PURE__ */ new Set(),
2220
2538
  totalSize: 0,
@@ -2231,6 +2549,8 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2231
2549
  data: dataProp,
2232
2550
  estimatedItemSize,
2233
2551
  getEstimatedItemSize,
2552
+ getFixedItemSize,
2553
+ getItemType,
2234
2554
  horizontal: !!horizontal,
2235
2555
  initialContainerPoolRatio,
2236
2556
  initialScroll,
@@ -2246,9 +2566,12 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2246
2566
  onScroll: onScrollProp,
2247
2567
  onStartReached,
2248
2568
  onStartReachedThreshold,
2569
+ recycleItems: !!recycleItems,
2249
2570
  renderItem: renderItem2,
2250
2571
  scrollBuffer,
2251
2572
  snapToIndices,
2573
+ stickyIndicesArr: stickyIndices != null ? stickyIndices : [],
2574
+ stickyIndicesSet: useMemo(() => new Set(stickyIndices), [stickyIndices]),
2252
2575
  stylePaddingBottom: stylePaddingBottomState,
2253
2576
  stylePaddingTop: stylePaddingTopState,
2254
2577
  suggestEstimatedItemSize: !!suggestEstimatedItemSize
@@ -2486,6 +2809,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2486
2809
  }),
2487
2810
  []
2488
2811
  );
2812
+ const animatedScrollHandler = useMemo(() => {
2813
+ if (stickyIndices == null ? void 0 : stickyIndices.length) {
2814
+ const { animatedScrollY } = ctx;
2815
+ return Animated.event([{ nativeEvent: { contentOffset: { [horizontal ? "x" : "y"]: animatedScrollY } } }], {
2816
+ listener: fns.onScroll,
2817
+ useNativeDriver: true
2818
+ });
2819
+ }
2820
+ return fns.onScroll;
2821
+ }, [stickyIndices, horizontal, onScroll]);
2489
2822
  return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(
2490
2823
  ListComponent,
2491
2824
  {
@@ -2502,14 +2835,20 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2502
2835
  onLayout,
2503
2836
  onLayoutHeader,
2504
2837
  onMomentumScrollEnd: (event) => {
2505
- requestAnimationFrame(() => {
2506
- finishScrollTo(refState.current);
2507
- });
2838
+ if (IsNewArchitecture) {
2839
+ requestAnimationFrame(() => {
2840
+ finishScrollTo(refState.current);
2841
+ });
2842
+ } else {
2843
+ setTimeout(() => {
2844
+ finishScrollTo(refState.current);
2845
+ }, 1e3);
2846
+ }
2508
2847
  if (onMomentumScrollEnd) {
2509
2848
  onMomentumScrollEnd(event);
2510
2849
  }
2511
2850
  },
2512
- onScroll: fns.onScroll,
2851
+ onScroll: animatedScrollHandler,
2513
2852
  recycleItems,
2514
2853
  refreshControl: refreshControl ? stylePaddingTopState > 0 ? React3.cloneElement(refreshControl, {
2515
2854
  progressViewOffset: (refreshControl.props.progressViewOffset || 0) + stylePaddingTopState
@@ -2525,6 +2864,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
2525
2864
  scrollAdjustHandler: (_a = refState.current) == null ? void 0 : _a.scrollAdjustHandler,
2526
2865
  scrollEventThrottle: Platform.OS === "web" ? 16 : void 0,
2527
2866
  snapToIndices,
2867
+ stickyIndices,
2528
2868
  style,
2529
2869
  updateItemSize: fns.updateItemSize,
2530
2870
  waitForInitialLayout