@legendapp/list 3.0.0-beta.54 → 3.0.0-beta.55

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.native.js CHANGED
@@ -29,6 +29,111 @@ var ReactNative__namespace = /*#__PURE__*/_interopNamespace(ReactNative);
29
29
  ReactNative.Animated.View;
30
30
  var View = ReactNative.View;
31
31
  var Text = ReactNative.Text;
32
+ var Platform = ReactNative.Platform;
33
+ var PlatformAdjustBreaksScroll = Platform.OS === "android";
34
+
35
+ // src/utils/rtl.ts
36
+ function clampHorizontalOffset(offset, maxOffset) {
37
+ if (maxOffset === void 0) {
38
+ return offset;
39
+ }
40
+ return Math.max(0, Math.min(maxOffset, offset));
41
+ }
42
+ function getHorizontalMaxOffset(state, contentWidth) {
43
+ if (contentWidth === void 0 || !Number.isFinite(contentWidth) || !Number.isFinite(state.scrollLength) || contentWidth <= state.scrollLength) {
44
+ return contentWidth !== void 0 && Number.isFinite(contentWidth) && Number.isFinite(state.scrollLength) ? 0 : void 0;
45
+ }
46
+ return Math.max(0, contentWidth - state.scrollLength);
47
+ }
48
+ function getDefaultHorizontalRTLScrollType() {
49
+ return Platform.OS === "web" ? "normal" : "inverted";
50
+ }
51
+ function getNativeHorizontalRTLScrollType(state) {
52
+ var _a3;
53
+ return (_a3 = state == null ? void 0 : state.horizontalRTLScrollType) != null ? _a3 : getDefaultHorizontalRTLScrollType();
54
+ }
55
+ function isRTLProps(props) {
56
+ var _a3;
57
+ return (_a3 = props == null ? void 0 : props.rtl) != null ? _a3 : !!ReactNative.I18nManager.isRTL;
58
+ }
59
+ function isHorizontalRTL(state) {
60
+ return isHorizontalRTLProps(state == null ? void 0 : state.props);
61
+ }
62
+ function isHorizontalRTLProps(props) {
63
+ return !!(props == null ? void 0 : props.horizontal) && isRTLProps(props);
64
+ }
65
+ function getLogicalHorizontalMaxOffset(state, contentWidth) {
66
+ var _a3;
67
+ return (_a3 = getHorizontalMaxOffset(state, contentWidth)) != null ? _a3 : 0;
68
+ }
69
+ function getHorizontalInsetEnd(state, inset) {
70
+ if (!inset) {
71
+ return 0;
72
+ }
73
+ return (isHorizontalRTL(state) ? inset.left : inset.right) || 0;
74
+ }
75
+ function toPhysicalHorizontalItemPosition(state, logicalPosition, itemSize, listSize) {
76
+ if (!isHorizontalRTL(state) || listSize === void 0 || !Number.isFinite(listSize)) {
77
+ return logicalPosition;
78
+ }
79
+ return Math.max(0, listSize - logicalPosition - itemSize);
80
+ }
81
+ function toNativeHorizontalOffset(state, logicalOffset, contentWidth) {
82
+ if (!state || !isHorizontalRTL(state)) {
83
+ return logicalOffset;
84
+ }
85
+ const maxOffset = getHorizontalMaxOffset(state, contentWidth);
86
+ const clampedLogicalOffset = clampHorizontalOffset(logicalOffset, maxOffset);
87
+ const mode = getNativeHorizontalRTLScrollType(state);
88
+ if (mode === "negative") {
89
+ return clampedLogicalOffset === 0 ? 0 : -clampedLogicalOffset;
90
+ }
91
+ if (mode === "inverted") {
92
+ if (maxOffset === void 0) {
93
+ return clampedLogicalOffset;
94
+ }
95
+ return clampHorizontalOffset(maxOffset - clampedLogicalOffset, maxOffset);
96
+ }
97
+ return clampedLogicalOffset;
98
+ }
99
+ function toLogicalHorizontalOffset(state, rawOffset, contentWidth) {
100
+ if (!isHorizontalRTL(state)) {
101
+ state.horizontalRTLScrollType = void 0;
102
+ return rawOffset;
103
+ }
104
+ const maxOffset = getHorizontalMaxOffset(state, contentWidth);
105
+ if (rawOffset < 0) {
106
+ state.horizontalRTLScrollType = "negative";
107
+ return clampHorizontalOffset(-rawOffset, maxOffset);
108
+ }
109
+ if (maxOffset === void 0) {
110
+ return rawOffset;
111
+ }
112
+ const normalOffset = rawOffset;
113
+ const invertedOffset = maxOffset - rawOffset;
114
+ if (!Number.isFinite(invertedOffset)) {
115
+ state.horizontalRTLScrollType = "normal";
116
+ return normalOffset;
117
+ }
118
+ const previousMode = state.horizontalRTLScrollType;
119
+ if (previousMode === "inverted") {
120
+ return clampHorizontalOffset(invertedOffset, maxOffset);
121
+ }
122
+ if (previousMode === "normal") {
123
+ return clampHorizontalOffset(normalOffset, maxOffset);
124
+ }
125
+ if (!state.hasScrolled) {
126
+ const defaultMode = getDefaultHorizontalRTLScrollType();
127
+ state.horizontalRTLScrollType = defaultMode;
128
+ return clampHorizontalOffset(defaultMode === "inverted" ? invertedOffset : normalOffset, maxOffset);
129
+ }
130
+ const referenceScroll = state.scroll;
131
+ const distanceNormal = Math.abs(normalOffset - referenceScroll);
132
+ const distanceInverted = Math.abs(invertedOffset - referenceScroll);
133
+ const useInverted = distanceInverted + 0.5 < distanceNormal;
134
+ state.horizontalRTLScrollType = useInverted ? "inverted" : "normal";
135
+ return clampHorizontalOffset(useInverted ? invertedOffset : normalOffset, maxOffset);
136
+ }
32
137
  var createAnimatedValue = (value) => new ReactNative.Animated.Value(value);
33
138
 
34
139
  // src/state/state.tsx
@@ -170,7 +275,7 @@ function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
170
275
  const horizontal = props.horizontal;
171
276
  const contentInset = props.contentInset;
172
277
  const baseInset = contentInset != null ? contentInset : state.nativeContentInset;
173
- const baseEndInset = (horizontal ? baseInset == null ? void 0 : baseInset.right : baseInset == null ? void 0 : baseInset.bottom) || 0;
278
+ const baseEndInset = (horizontal ? getHorizontalInsetEnd(state, baseInset) : baseInset == null ? void 0 : baseInset.bottom) || 0;
174
279
  const contentInsetEndAdjustment = getContentInsetEndAdjustmentEnd(
175
280
  contentInsetEndAdjustmentOverride != null ? contentInsetEndAdjustmentOverride : props.contentInsetEndAdjustment
176
281
  );
@@ -179,9 +284,9 @@ function getContentInsetEnd(ctx, contentInsetEndAdjustmentOverride) {
179
284
  const overrideInset = (_b = state.contentInsetOverride) != null ? _b : void 0;
180
285
  const adjustedBaseEndInset = baseEndInset + contentInsetEndAdjustment;
181
286
  if (overrideInset) {
182
- const mergedInset = { bottom: 0, right: 0, ...baseInset, ...overrideInset };
287
+ const mergedInset = { bottom: 0, left: 0, right: 0, ...baseInset, ...overrideInset };
183
288
  return Math.max(
184
- ((horizontal ? mergedInset.right : mergedInset.bottom) || 0) + contentInsetEndAdjustment,
289
+ ((horizontal ? getHorizontalInsetEnd(state, mergedInset) : mergedInset.bottom) || 0) + contentInsetEndAdjustment,
185
290
  anchoredEndInset
186
291
  );
187
292
  }
@@ -461,7 +566,8 @@ function comparatorDefault(a, b) {
461
566
  }
462
567
  function getPadding(s, type) {
463
568
  var _a3, _b, _c;
464
- return (_c = (_b = (_a3 = s[`padding${type}`]) != null ? _a3 : s.paddingVertical) != null ? _b : s.padding) != null ? _c : 0;
569
+ const axisPadding = type === "Left" || type === "Right" ? s.paddingHorizontal : s.paddingVertical;
570
+ return (_c = (_b = (_a3 = s[`padding${type}`]) != null ? _a3 : axisPadding) != null ? _b : s.padding) != null ? _c : 0;
465
571
  }
466
572
  function extractPadding(style, contentContainerStyle, type) {
467
573
  return getPadding(style, type) + getPadding(contentContainerStyle, type);
@@ -668,8 +774,6 @@ function useOnLayoutSync({
668
774
  }
669
775
  return { onLayout };
670
776
  }
671
- var Platform = ReactNative.Platform;
672
- var PlatformAdjustBreaksScroll = Platform.OS === "android";
673
777
 
674
778
  // src/utils/isInMVCPActiveMode.native.ts
675
779
  function isInMVCPActiveMode(state) {
@@ -681,6 +785,7 @@ function getContainerPositionStyle({
681
785
  columnWrapperStyle,
682
786
  horizontal,
683
787
  hasItemSeparator,
788
+ isHorizontalRTLList,
684
789
  numColumns,
685
790
  otherAxisPos,
686
791
  otherAxisSize
@@ -704,6 +809,7 @@ function getContainerPositionStyle({
704
809
  }
705
810
  return horizontal ? {
706
811
  boxSizing: paddingStyles ? "border-box" : void 0,
812
+ direction: isHorizontalRTLList && Platform.OS === "web" ? "ltr" : void 0,
707
813
  flexDirection: hasItemSeparator ? "row" : void 0,
708
814
  height: otherAxisSize,
709
815
  left: 0,
@@ -732,6 +838,7 @@ var Container = typedMemo(function Container2({
732
838
  }) {
733
839
  const ctx = useStateContext();
734
840
  const { columnWrapperStyle, animatedScrollY } = ctx;
841
+ const isHorizontalRTLList = isHorizontalRTL(ctx.state);
735
842
  const positionComponentInternal = ctx.state.props.positionComponentInternal;
736
843
  const stickyPositionComponentInternal = ctx.state.props.stickyPositionComponentInternal;
737
844
  const [column = 0, span = 1, data, numColumns = 1, extraData, isSticky] = useArr$([
@@ -763,11 +870,20 @@ var Container = typedMemo(function Container2({
763
870
  columnWrapperStyle,
764
871
  hasItemSeparator: !!ItemSeparatorComponent,
765
872
  horizontal,
873
+ isHorizontalRTLList,
766
874
  numColumns,
767
875
  otherAxisPos,
768
876
  otherAxisSize
769
877
  }),
770
- [horizontal, otherAxisPos, otherAxisSize, columnWrapperStyle, numColumns, ItemSeparatorComponent]
878
+ [
879
+ horizontal,
880
+ isHorizontalRTLList,
881
+ otherAxisPos,
882
+ otherAxisSize,
883
+ columnWrapperStyle,
884
+ numColumns,
885
+ ItemSeparatorComponent
886
+ ]
771
887
  );
772
888
  const renderedItemInfo = React2.useMemo(
773
889
  () => itemKey !== void 0 ? getRenderedItem2(itemKey) : null,
@@ -920,9 +1036,13 @@ var ContainersLayer = typedMemo(function ContainersLayer2({ children, horizontal
920
1036
  const ctx = useStateContext();
921
1037
  const columnWrapperStyle = ctx.columnWrapperStyle;
922
1038
  const animSize = useValue$("totalSize");
923
- const otherAxisSize = useValue$("otherAxisSize");
924
- const [readyToRender, numColumns] = useArr$(["readyToRender", "numColumns"]);
925
- const style = horizontal ? { minHeight: otherAxisSize, opacity: readyToRender ? 1 : 0, width: animSize } : { height: animSize, minWidth: otherAxisSize, opacity: readyToRender ? 1 : 0 };
1039
+ const [readyToRender, numColumns, otherAxisSize = 0] = useArr$(["readyToRender", "numColumns", "otherAxisSize"]);
1040
+ const style = horizontal ? {
1041
+ height: otherAxisSize || "100%",
1042
+ minHeight: otherAxisSize,
1043
+ opacity: readyToRender ? 1 : 0,
1044
+ width: animSize
1045
+ } : { height: animSize, minWidth: otherAxisSize, opacity: readyToRender ? 1 : 0 };
926
1046
  if (columnWrapperStyle) {
927
1047
  const { columnGap, rowGap, gap } = columnWrapperStyle;
928
1048
  const gapX = columnGap || gap || 0;
@@ -975,6 +1095,18 @@ var Containers = typedMemo(function Containers2({
975
1095
  return /* @__PURE__ */ React2__namespace.createElement(ContainersLayer, { horizontal }, containers);
976
1096
  });
977
1097
  var ListComponentScrollView = ReactNative.Animated.ScrollView;
1098
+
1099
+ // src/components/listComponentStyles.ts
1100
+ function getAutoOtherAxisStyle({
1101
+ horizontal,
1102
+ needsOtherAxisSize,
1103
+ otherAxisSize
1104
+ }) {
1105
+ if (!needsOtherAxisSize || !otherAxisSize || otherAxisSize <= 0) {
1106
+ return void 0;
1107
+ }
1108
+ return horizontal ? { height: otherAxisSize } : { width: otherAxisSize };
1109
+ }
978
1110
  function ScrollAdjust() {
979
1111
  var _a3;
980
1112
  const ctx = useStateContext();
@@ -995,10 +1127,10 @@ function ScrollAdjust() {
995
1127
  }
996
1128
  );
997
1129
  }
998
- function SnapWrapper({ ScrollComponent, ...props }) {
1130
+ var SnapWrapper = React2__namespace.forwardRef(function SnapWrapperInner({ ScrollComponent, ...props }, ref) {
999
1131
  const [snapToOffsets] = useArr$(["snapToOffsets"]);
1000
- return /* @__PURE__ */ React2__namespace.createElement(ScrollComponent, { ...props, snapToOffsets });
1001
- }
1132
+ return /* @__PURE__ */ React2__namespace.createElement(ScrollComponent, { ...props, ref, snapToOffsets });
1133
+ });
1002
1134
  function WebAnchoredEndSpace({ horizontal }) {
1003
1135
  const ctx = useStateContext();
1004
1136
  const [anchoredEndSpaceSize] = useArr$(["anchoredEndSpaceSize"]);
@@ -1047,6 +1179,12 @@ var ListComponent = typedMemo(function ListComponent2({
1047
1179
  }) {
1048
1180
  const ctx = useStateContext();
1049
1181
  const maintainVisibleContentPosition = ctx.state.props.maintainVisibleContentPosition;
1182
+ const [otherAxisSize = 0] = useArr$(["otherAxisSize"]);
1183
+ const autoOtherAxisStyle = getAutoOtherAxisStyle({
1184
+ horizontal,
1185
+ needsOtherAxisSize: ctx.state.needsOtherAxisSize,
1186
+ otherAxisSize
1187
+ });
1050
1188
  const ScrollComponent = React2.useMemo(() => {
1051
1189
  if (!renderScrollComponent) {
1052
1190
  return ListComponentScrollView;
@@ -1085,10 +1223,10 @@ var ListComponent = typedMemo(function ListComponent2({
1085
1223
  ...rest,
1086
1224
  ...ScrollComponent === ListComponentScrollView ? { useWindowScroll } : {},
1087
1225
  contentContainerStyle: [
1088
- contentContainerStyle,
1089
1226
  horizontal ? {
1090
1227
  height: "100%"
1091
- } : {}
1228
+ } : {},
1229
+ contentContainerStyle
1092
1230
  ],
1093
1231
  contentOffset: initialContentOffset !== void 0 ? horizontal ? { x: initialContentOffset, y: 0 } : { x: 0, y: initialContentOffset } : void 0,
1094
1232
  horizontal,
@@ -1097,7 +1235,7 @@ var ListComponent = typedMemo(function ListComponent2({
1097
1235
  onScroll: onScroll2,
1098
1236
  ref: refScrollView,
1099
1237
  ScrollComponent: snapToIndices ? ScrollComponent : void 0,
1100
- style
1238
+ style: autoOtherAxisStyle ? [autoOtherAxisStyle, style] : style
1101
1239
  },
1102
1240
  /* @__PURE__ */ React2__namespace.createElement(ScrollAdjust, null),
1103
1241
  ListHeaderComponent && /* @__PURE__ */ React2__namespace.createElement(LayoutView, { onLayoutChange: onLayoutHeader, style: ListHeaderComponentStyle }, getComponent(ListHeaderComponent)),
@@ -1957,10 +2095,13 @@ function doScrollTo(ctx, params) {
1957
2095
  if (!scroller) {
1958
2096
  return;
1959
2097
  }
2098
+ const isHorizontal = !!horizontal;
2099
+ const contentSize = isHorizontal ? getContentSize(ctx) : void 0;
2100
+ const nativeOffset = toNativeHorizontalOffset(state, offset, contentSize);
1960
2101
  scroller.scrollTo({
1961
2102
  animated: isAnimated,
1962
- x: horizontal ? offset : 0,
1963
- y: horizontal ? 0 : offset
2103
+ x: isHorizontal ? nativeOffset : 0,
2104
+ y: isHorizontal ? 0 : offset
1964
2105
  });
1965
2106
  if (isInitialScroll) {
1966
2107
  initialScrollCompletion.markInitialScrollNativeDispatch(state);
@@ -2860,7 +3001,14 @@ function handleInitialScrollLayoutReady(ctx) {
2860
3001
  }
2861
3002
  function initializeInitialScrollOnMount(ctx, options) {
2862
3003
  var _a3, _b;
2863
- const { dataLength, hasFooterComponent, initialContentOffset, initialScrollAtEnd, useBootstrapInitialScroll } = options;
3004
+ const {
3005
+ alwaysDispatchInitialScroll,
3006
+ dataLength,
3007
+ hasFooterComponent,
3008
+ initialContentOffset,
3009
+ initialScrollAtEnd,
3010
+ useBootstrapInitialScroll
3011
+ } = options;
2864
3012
  const state = ctx.state;
2865
3013
  const initialScroll = state.initialScroll;
2866
3014
  const resolvedInitialContentOffset = initialContentOffset != null ? initialContentOffset : 0;
@@ -2880,7 +3028,7 @@ function initializeInitialScrollOnMount(ctx, options) {
2880
3028
  return;
2881
3029
  }
2882
3030
  const hasPendingDataDependentInitialScroll = !!initialScroll && dataLength === 0 && !(resolvedInitialContentOffset === 0 && !initialScrollAtEnd);
2883
- if (!resolvedInitialContentOffset && !hasPendingDataDependentInitialScroll) {
3031
+ if (!alwaysDispatchInitialScroll && !resolvedInitialContentOffset && !hasPendingDataDependentInitialScroll) {
2884
3032
  if (initialScroll && !initialScrollAtEnd) {
2885
3033
  finishInitialScroll(ctx, {
2886
3034
  resolvedOffset: resolvedInitialContentOffset
@@ -3211,9 +3359,18 @@ function prepareMVCP(ctx, dataChanged) {
3211
3359
  }
3212
3360
  }
3213
3361
 
3362
+ // src/core/resetLayoutCachesForDataChange.ts
3363
+ function resetLayoutCachesForDataChange(state) {
3364
+ state.indexByKey.clear();
3365
+ state.idCache.length = 0;
3366
+ state.positions.length = 0;
3367
+ state.columns.length = 0;
3368
+ state.columnSpans.length = 0;
3369
+ }
3370
+
3214
3371
  // src/core/syncMountedContainer.ts
3215
3372
  function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
3216
- var _a3, _b, _c, _d, _e, _f, _g, _h;
3373
+ var _a3, _b, _c, _d, _e, _f, _g, _h, _i;
3217
3374
  const state = ctx.state;
3218
3375
  const {
3219
3376
  columns,
@@ -3225,7 +3382,8 @@ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
3225
3382
  if (item === void 0) {
3226
3383
  return { didChangePosition: false, didRefreshData: false };
3227
3384
  }
3228
- const updateLayout = (_a3 = options == null ? void 0 : options.updateLayout) != null ? _a3 : true;
3385
+ const itemKey = (_a3 = state.idCache[itemIndex]) != null ? _a3 : getId(state, itemIndex);
3386
+ const updateLayout = (_b = options == null ? void 0 : options.updateLayout) != null ? _b : true;
3229
3387
  let didChangePosition = false;
3230
3388
  let didRefreshData = false;
3231
3389
  if (updateLayout) {
@@ -3234,7 +3392,9 @@ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
3234
3392
  set$(ctx, `containerPosition${containerIndex}`, POSITION_OUT_OF_VIEW);
3235
3393
  return { didChangePosition: false, didRefreshData: false };
3236
3394
  }
3237
- const position = (positionValue || 0) - ((_b = options == null ? void 0 : options.scrollAdjustPending) != null ? _b : 0);
3395
+ const logicalPosition = (positionValue || 0) - ((_c = options == null ? void 0 : options.scrollAdjustPending) != null ? _c : 0);
3396
+ const itemSize = (_d = state.sizes.get(itemKey)) != null ? _d : getItemSize(ctx, itemKey, itemIndex, item);
3397
+ const position = toPhysicalHorizontalItemPosition(state, logicalPosition, itemSize, peek$(ctx, "totalSize"));
3238
3398
  const column = columns[itemIndex] || 1;
3239
3399
  const span = columnSpans[itemIndex] || 1;
3240
3400
  const prevPos = peek$(ctx, `containerPosition${containerIndex}`);
@@ -3253,15 +3413,15 @@ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
3253
3413
  }
3254
3414
  const prevData = peek$(ctx, `containerItemData${containerIndex}`);
3255
3415
  if (prevData !== item) {
3256
- const pendingDataComparison = ((_c = state.pendingDataComparison) == null ? void 0 : _c.previousData) === state.previousData && ((_d = state.pendingDataComparison) == null ? void 0 : _d.nextData) === data ? state.pendingDataComparison : void 0;
3257
- const cachedComparison = (_e = pendingDataComparison == null ? void 0 : pendingDataComparison.byIndex[itemIndex]) != null ? _e : 0;
3416
+ const pendingDataComparison = ((_e = state.pendingDataComparison) == null ? void 0 : _e.previousData) === state.previousData && ((_f = state.pendingDataComparison) == null ? void 0 : _f.nextData) === data ? state.pendingDataComparison : void 0;
3417
+ const cachedComparison = (_g = pendingDataComparison == null ? void 0 : pendingDataComparison.byIndex[itemIndex]) != null ? _g : 0;
3258
3418
  if (cachedComparison === 2) {
3259
3419
  set$(ctx, `containerItemData${containerIndex}`, item);
3260
3420
  didRefreshData = true;
3261
3421
  } else if (cachedComparison !== 1) {
3262
- const itemKey = (_g = (_f = peek$(ctx, `containerItemKey${containerIndex}`)) != null ? _f : state.idCache[itemIndex]) != null ? _g : getId(state, itemIndex);
3422
+ const nextItemKey = (_h = peek$(ctx, `containerItemKey${containerIndex}`)) != null ? _h : itemKey;
3263
3423
  const prevKey = keyExtractor == null ? void 0 : keyExtractor(prevData, itemIndex);
3264
- if (prevData === void 0 || !keyExtractor || prevKey !== itemKey) {
3424
+ if (prevData === void 0 || !keyExtractor || prevKey !== nextItemKey) {
3265
3425
  set$(ctx, `containerItemData${containerIndex}`, item);
3266
3426
  didRefreshData = true;
3267
3427
  } else if (!itemsAreEqual) {
@@ -3278,7 +3438,7 @@ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
3278
3438
  };
3279
3439
  }
3280
3440
  }
3281
- if ((_h = state.pendingDataComparison) == null ? void 0 : _h.byIndex) {
3441
+ if ((_i = state.pendingDataComparison) == null ? void 0 : _i.byIndex) {
3282
3442
  state.pendingDataComparison.byIndex[itemIndex] = isEqual ? 1 : 2;
3283
3443
  }
3284
3444
  if (!isEqual) {
@@ -3443,11 +3603,13 @@ function updateSnapToOffsets(ctx) {
3443
3603
  const {
3444
3604
  props: { snapToIndices }
3445
3605
  } = state;
3606
+ const contentSize = state.props.horizontal ? getContentSize(ctx) : void 0;
3446
3607
  const snapToOffsets = Array(snapToIndices.length);
3447
3608
  for (let i = 0; i < snapToIndices.length; i++) {
3448
3609
  const idx = snapToIndices[i];
3449
3610
  getId(state, idx);
3450
- snapToOffsets[i] = state.positions[idx];
3611
+ const logicalOffset = state.positions[idx];
3612
+ snapToOffsets[i] = toNativeHorizontalOffset(state, logicalOffset, contentSize);
3451
3613
  }
3452
3614
  set$(ctx, "snapToOffsets", snapToOffsets);
3453
3615
  }
@@ -4056,7 +4218,6 @@ function calculateItemsInView(ctx, params = {}) {
4056
4218
  var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
4057
4219
  const {
4058
4220
  columns,
4059
- columnSpans,
4060
4221
  containerItemKeys,
4061
4222
  enableScrollForNextCalculateItemsInView,
4062
4223
  idCache,
@@ -4106,8 +4267,10 @@ function calculateItemsInView(ctx, params = {}) {
4106
4267
  let scrollTopBuffered = 0;
4107
4268
  let scrollBottom = 0;
4108
4269
  let scrollBottomBuffered = 0;
4270
+ let nativeScrollState = scrollState;
4109
4271
  const updateScroll2 = (nextScrollState) => {
4110
4272
  var _a4;
4273
+ nativeScrollState = nextScrollState;
4111
4274
  scrollAdjustPending = (_a4 = peek$(ctx, "scrollAdjustPending")) != null ? _a4 : 0;
4112
4275
  scrollAdjustPad = scrollAdjustPending - topPad;
4113
4276
  scroll = Math.round(nextScrollState + scrollExtra + scrollAdjustPad);
@@ -4119,9 +4282,17 @@ function calculateItemsInView(ctx, params = {}) {
4119
4282
  const previousStickyIndex = peek$(ctx, "activeStickyIndex");
4120
4283
  const currentStickyIdx = stickyIndicesArr.length > 0 ? findCurrentStickyIndex(stickyIndicesArr, scroll, state) : -1;
4121
4284
  const nextActiveStickyIndex = currentStickyIdx >= 0 ? stickyIndicesArr[currentStickyIdx] : -1;
4285
+ const stickyIndexDidChange = previousStickyIndex !== nextActiveStickyIndex;
4122
4286
  if (currentStickyIdx >= 0 || previousStickyIndex >= 0) {
4123
4287
  set$(ctx, "activeStickyIndex", nextActiveStickyIndex);
4124
4288
  }
4289
+ const shouldNotifyStickyHeaderChange = !!onStickyHeaderChange && stickyIndicesArr.length > 0 && stickyIndexDidChange;
4290
+ const finishCalculateItemsInView = shouldNotifyStickyHeaderChange ? () => {
4291
+ const item = data[nextActiveStickyIndex];
4292
+ if (item !== void 0) {
4293
+ onStickyHeaderChange == null ? void 0 : onStickyHeaderChange({ index: nextActiveStickyIndex, item });
4294
+ }
4295
+ } : void 0;
4125
4296
  let scrollBufferTop = drawDistance;
4126
4297
  let scrollBufferBottom = drawDistance;
4127
4298
  if (speed > 0 || speed === 0 && scroll < Math.max(50, drawDistance)) {
@@ -4132,8 +4303,10 @@ function calculateItemsInView(ctx, params = {}) {
4132
4303
  scrollBufferBottom = drawDistance * 0.5;
4133
4304
  }
4134
4305
  const updateScrollRange = () => {
4135
- scrollTopBuffered = scroll - scrollBufferTop;
4136
- scrollBottom = scroll + scrollLength + (scroll < 0 ? -scroll : 0);
4306
+ const scrollStart = Math.max(0, scroll);
4307
+ const overscrollBeforeContent = Math.max(0, -nativeScrollState);
4308
+ scrollTopBuffered = scrollStart - scrollBufferTop;
4309
+ scrollBottom = Math.max(scrollStart, scroll + scrollLength + overscrollBeforeContent);
4137
4310
  scrollBottomBuffered = scrollBottom + scrollBufferBottom;
4138
4311
  };
4139
4312
  updateScrollRange();
@@ -4143,17 +4316,14 @@ function calculateItemsInView(ctx, params = {}) {
4143
4316
  state.scrollForNextCalculateItemsInView = void 0;
4144
4317
  } else if ((top === null || scrollTopBuffered > top) && (bottom === null || scrollBottomBuffered < bottom)) {
4145
4318
  if (Platform.OS !== "web" || !isInMVCPActiveMode(state)) {
4319
+ finishCalculateItemsInView == null ? void 0 : finishCalculateItemsInView();
4146
4320
  return;
4147
4321
  }
4148
4322
  }
4149
4323
  }
4150
4324
  const checkMVCP = doMVCP && !suppressInitialScrollSideEffects ? prepareMVCP(ctx, dataChanged) : void 0;
4151
4325
  if (dataChanged) {
4152
- indexByKey.clear();
4153
- idCache.length = 0;
4154
- positions.length = 0;
4155
- columns.length = 0;
4156
- columnSpans.length = 0;
4326
+ resetLayoutCachesForDataChange(state);
4157
4327
  }
4158
4328
  const startIndex = forceFullItemPositions || dataChanged ? 0 : (_c = minIndexSizeChanged != null ? minIndexSizeChanged : state.startBuffered) != null ? _c : 0;
4159
4329
  const optimizeForVisibleWindow = !forceFullItemPositions && !dataChanged && numColumns > 1 && minIndexSizeChanged !== void 0;
@@ -4467,12 +4637,7 @@ function calculateItemsInView(ctx, params = {}) {
4467
4637
  );
4468
4638
  }
4469
4639
  }
4470
- if (onStickyHeaderChange && stickyIndicesArr.length > 0 && nextActiveStickyIndex !== void 0 && nextActiveStickyIndex !== previousStickyIndex) {
4471
- const item = data[nextActiveStickyIndex];
4472
- if (item !== void 0) {
4473
- onStickyHeaderChange({ index: nextActiveStickyIndex, item });
4474
- }
4475
- }
4640
+ finishCalculateItemsInView == null ? void 0 : finishCalculateItemsInView();
4476
4641
  });
4477
4642
  }
4478
4643
 
@@ -4500,11 +4665,22 @@ function doMaintainScrollAtEnd(ctx) {
4500
4665
  if (!state.maintainingScrollAtEnd) {
4501
4666
  state.maintainingScrollAtEnd = true;
4502
4667
  requestAnimationFrame(() => {
4503
- var _a3;
4504
4668
  if (peek$(ctx, "isWithinMaintainScrollAtEndThreshold")) {
4505
- (_a3 = refScroller.current) == null ? void 0 : _a3.scrollToEnd({
4506
- animated: maintainScrollAtEnd.animated
4507
- });
4669
+ const scroller = refScroller.current;
4670
+ if (state.props.horizontal && isHorizontalRTL(state)) {
4671
+ const currentContentSize = getContentSize(ctx);
4672
+ const logicalEndOffset = getLogicalHorizontalMaxOffset(state, currentContentSize);
4673
+ const nativeOffset = toNativeHorizontalOffset(state, logicalEndOffset, currentContentSize);
4674
+ scroller == null ? void 0 : scroller.scrollTo({
4675
+ animated: maintainScrollAtEnd.animated,
4676
+ x: nativeOffset,
4677
+ y: 0
4678
+ });
4679
+ } else {
4680
+ scroller == null ? void 0 : scroller.scrollToEnd({
4681
+ animated: maintainScrollAtEnd.animated
4682
+ });
4683
+ }
4508
4684
  setTimeout(
4509
4685
  () => {
4510
4686
  state.maintainingScrollAtEnd = false;
@@ -4700,7 +4876,8 @@ function handleLayout(ctx, layoutParam, setCanRender) {
4700
4876
  }
4701
4877
  checkThresholds(ctx);
4702
4878
  if (state) {
4703
- state.needsOtherAxisSize = otherAxisSize - (state.props.stylePaddingTop || 0) < 10;
4879
+ const crossAxisPadding = state.props.horizontal ? (state.props.stylePaddingTop || 0) + (state.props.stylePaddingBottom || 0) : (state.props.stylePaddingLeft || 0) + (state.props.stylePaddingRight || 0);
4880
+ state.needsOtherAxisSize = otherAxisSize - crossAxisPadding < 10;
4704
4881
  }
4705
4882
  if (IS_DEV && measuredLength === 0) {
4706
4883
  warnDevOnce(
@@ -4819,7 +4996,7 @@ function cloneScrollEvent(event) {
4819
4996
  };
4820
4997
  }
4821
4998
  function onScroll(ctx, event) {
4822
- var _a3, _b, _c, _d;
4999
+ var _a3, _b, _c, _d, _e;
4823
5000
  const state = ctx.state;
4824
5001
  const { scrollProcessingEnabled } = state;
4825
5002
  if (scrollProcessingEnabled === false) {
@@ -4838,6 +5015,9 @@ function onScroll(ctx, event) {
4838
5015
  }
4839
5016
  }
4840
5017
  let newScroll = event.nativeEvent.contentOffset[state.props.horizontal ? "x" : "y"];
5018
+ if (state.props.horizontal) {
5019
+ newScroll = toLogicalHorizontalOffset(state, newScroll, (_e = event.nativeEvent.contentSize) == null ? void 0 : _e.width);
5020
+ }
4841
5021
  if (state.scrollingTo && state.scrollingTo.offset >= newScroll) {
4842
5022
  const maxOffset = clampScrollOffset(ctx, newScroll, state.scrollingTo);
4843
5023
  if (newScroll !== maxOffset && Math.abs(newScroll - maxOffset) > 1) {
@@ -5011,6 +5191,16 @@ function runOrScheduleMVCPRecalculate(ctx) {
5011
5191
  calculateItemsInView(ctx, { doMVCP: true });
5012
5192
  }
5013
5193
  }
5194
+ function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
5195
+ const state = ctx.state;
5196
+ if (state.needsOtherAxisSize) {
5197
+ const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
5198
+ const currentOtherAxisSize = peek$(ctx, "otherAxisSize");
5199
+ if (!currentOtherAxisSize || otherAxisSize > currentOtherAxisSize) {
5200
+ set$(ctx, "otherAxisSize", otherAxisSize);
5201
+ }
5202
+ }
5203
+ }
5014
5204
  function updateItemSize(ctx, itemKey, sizeObj) {
5015
5205
  var _a3;
5016
5206
  const state = ctx.state;
@@ -5034,13 +5224,13 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5034
5224
  const type = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
5035
5225
  const size2 = getFixedItemSize(itemData, index, type);
5036
5226
  if (size2 !== void 0 && size2 === sizesKnown.get(itemKey)) {
5227
+ updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal);
5037
5228
  return;
5038
5229
  }
5039
5230
  }
5040
5231
  let needsRecalculate = !didContainersLayout;
5041
5232
  let shouldMaintainScrollAtEnd = false;
5042
5233
  let minIndexSizeChanged;
5043
- let maxOtherAxisSize = peek$(ctx, "otherAxisSize") || 0;
5044
5234
  const prevSizeKnown = state.sizesKnown.get(itemKey);
5045
5235
  const diff = updateOneItemSize(ctx, itemKey, sizeObj);
5046
5236
  const size = roundSize(horizontal ? sizeObj.width : sizeObj.height);
@@ -5051,10 +5241,6 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5051
5241
  if (!needsRecalculate && state.containerItemKeys.has(itemKey)) {
5052
5242
  needsRecalculate = true;
5053
5243
  }
5054
- if (state.needsOtherAxisSize) {
5055
- const otherAxisSize = horizontal ? sizeObj.height : sizeObj.width;
5056
- maxOtherAxisSize = Math.max(maxOtherAxisSize, otherAxisSize);
5057
- }
5058
5244
  if (prevSizeKnown !== void 0 && Math.abs(prevSizeKnown - size) > 5) {
5059
5245
  shouldMaintainScrollAtEnd = true;
5060
5246
  }
@@ -5070,10 +5256,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
5070
5256
  if (minIndexSizeChanged !== void 0) {
5071
5257
  state.minIndexSizeChanged = state.minIndexSizeChanged !== void 0 ? Math.min(state.minIndexSizeChanged, minIndexSizeChanged) : minIndexSizeChanged;
5072
5258
  }
5073
- const cur = peek$(ctx, "otherAxisSize");
5074
- if (!cur || maxOtherAxisSize > cur) {
5075
- set$(ctx, "otherAxisSize", maxOtherAxisSize);
5076
- }
5259
+ updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal);
5077
5260
  if (didContainersLayout || checkAllSizesKnown(state, getMountedBufferedIndices(state))) {
5078
5261
  if (needsRecalculate) {
5079
5262
  state.scrollForNextCalculateItemsInView = void 0;
@@ -5661,7 +5844,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5661
5844
  getFixedItemSize,
5662
5845
  getItemType,
5663
5846
  horizontal,
5847
+ rtl,
5664
5848
  initialContainerPoolRatio = 3,
5849
+ estimatedHeaderSize,
5665
5850
  initialScrollAtEnd = false,
5666
5851
  initialScrollIndex: initialScrollIndexProp,
5667
5852
  initialScrollOffset: initialScrollOffsetProp,
@@ -5729,13 +5914,16 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5729
5914
  const style = { ...StyleSheet.flatten(styleProp) };
5730
5915
  const stylePaddingTopState = extractPadding(style, contentContainerStyle, "Top");
5731
5916
  const stylePaddingBottomState = extractPadding(style, contentContainerStyle, "Bottom");
5917
+ const stylePaddingLeftState = extractPadding(style, contentContainerStyle, "Left");
5918
+ const stylePaddingRightState = extractPadding(style, contentContainerStyle, "Right");
5732
5919
  const maintainScrollAtEndConfig = normalizeMaintainScrollAtEnd(maintainScrollAtEnd);
5733
5920
  const maintainVisibleContentPositionConfig = normalizeMaintainVisibleContentPosition(
5734
5921
  maintainVisibleContentPositionProp
5735
5922
  );
5736
5923
  const hasInitialScrollIndex = initialScrollIndexProp !== void 0 && initialScrollIndexProp !== null;
5737
5924
  const hasInitialScrollOffset = initialScrollOffsetProp !== void 0 && initialScrollOffsetProp !== null;
5738
- const initialScrollUsesOffsetOnly = !initialScrollAtEnd && !hasInitialScrollIndex && hasInitialScrollOffset;
5925
+ const shouldInitializeHorizontalRTL = !initialScrollAtEnd && !hasInitialScrollIndex && !hasInitialScrollOffset && isHorizontalRTLProps({ horizontal, rtl });
5926
+ const initialScrollUsesOffsetOnly = !initialScrollAtEnd && !hasInitialScrollIndex && (hasInitialScrollOffset || shouldInitializeHorizontalRTL);
5739
5927
  const usesBootstrapInitialScroll = initialScrollAtEnd || hasInitialScrollIndex;
5740
5928
  const initialScrollProp = initialScrollAtEnd ? {
5741
5929
  index: Math.max(0, dataProp.length - 1),
@@ -5851,6 +6039,9 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5851
6039
  internalState.reprocessCurrentScroll = () => updateScroll(ctx, internalState.scroll, true);
5852
6040
  set$(ctx, "maintainVisibleContentPosition", maintainVisibleContentPositionConfig);
5853
6041
  set$(ctx, "extraData", extraData);
6042
+ if (estimatedHeaderSize !== void 0) {
6043
+ set$(ctx, "headerSize", estimatedHeaderSize);
6044
+ }
5854
6045
  }
5855
6046
  refState.current = ctx.state;
5856
6047
  }
@@ -5910,11 +6101,14 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5910
6101
  positionComponentInternal,
5911
6102
  recycleItems: !!recycleItems,
5912
6103
  renderItem,
6104
+ rtl,
5913
6105
  snapToIndices,
5914
6106
  stickyIndicesArr: stickyHeaderIndices != null ? stickyHeaderIndices : [],
5915
6107
  stickyIndicesSet: React2.useMemo(() => new Set(stickyHeaderIndices != null ? stickyHeaderIndices : []), [stickyHeaderIndices == null ? void 0 : stickyHeaderIndices.join(",")]),
5916
6108
  stickyPositionComponentInternal,
5917
6109
  stylePaddingBottom: stylePaddingBottomState,
6110
+ stylePaddingLeft: stylePaddingLeftState,
6111
+ stylePaddingRight: stylePaddingRightState,
5918
6112
  stylePaddingTop: stylePaddingTopState,
5919
6113
  useWindowScroll: useWindowScrollResolved
5920
6114
  };
@@ -5942,6 +6136,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5942
6136
  };
5943
6137
  if (isFirstLocal) {
5944
6138
  initializeStateVars(false);
6139
+ resetLayoutCachesForDataChange(state);
5945
6140
  updateItemPositions(
5946
6141
  ctx,
5947
6142
  /*dataChanged*/
@@ -5959,6 +6154,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
5959
6154
  }, [usesBootstrapInitialScroll]);
5960
6155
  React2.useLayoutEffect(() => {
5961
6156
  initializeInitialScrollOnMount(ctx, {
6157
+ alwaysDispatchInitialScroll: shouldInitializeHorizontalRTL,
5962
6158
  dataLength: dataProp.length,
5963
6159
  hasFooterComponent: !!ListFooterComponent,
5964
6160
  initialContentOffset,