@legendapp/list 3.0.2 → 3.0.4
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/CHANGELOG.md +12 -0
- package/animated.d.ts +11 -4
- package/keyboard-legacy.d.ts +5 -4
- package/keyboard.d.ts +11 -4
- package/package.json +1 -1
- package/react-native.d.ts +11 -4
- package/react-native.js +211 -92
- package/react-native.mjs +212 -93
- package/react-native.web.d.ts +11 -4
- package/react-native.web.js +178 -88
- package/react-native.web.mjs +178 -88
- package/react.d.ts +11 -4
- package/react.js +178 -88
- package/react.mjs +178 -88
- package/reanimated.d.ts +11 -4
- package/section-list.d.ts +11 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 3.0.4
|
|
2
|
+
|
|
3
|
+
- Fix: scrollToEnd now waits for newly committed data before targeting the final item, improving chat-style append-and-scroll flows.
|
|
4
|
+
- Fix: Anchored end space waits for measured or fixed tail sizes before reporting readiness, avoiding stale end-space values during append flows.
|
|
5
|
+
- Feat: Add anchoredEndSpace.onReady to notify when the anchored tail has authoritative sizing.
|
|
6
|
+
|
|
7
|
+
## 3.0.3
|
|
8
|
+
|
|
9
|
+
- Fix: MVCP was getting batched to improve big jumps, but was making scroll worse
|
|
10
|
+
- Fix: On native, ignore one-physical-pixel layout measurement noise, preventing unnecessary item size updates from Fabric and native onLayout rounding differences.
|
|
11
|
+
- Fix: Average item sizes update correctly when getFixedItemSize returns undefined for only some item types.
|
|
12
|
+
|
|
1
13
|
## 3.0.2
|
|
2
14
|
|
|
3
15
|
- Fix: Using viewability was causing scrolling to end to sometimes not update items in view if the JS thread was slammed
|
package/animated.d.ts
CHANGED
|
@@ -388,12 +388,22 @@ interface MaintainVisibleContentPositionConfig<ItemT = any> {
|
|
|
388
388
|
size?: boolean;
|
|
389
389
|
shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
|
|
390
390
|
}
|
|
391
|
+
interface AnchoredEndSpaceReadyInfo {
|
|
392
|
+
anchorIndex: number | undefined;
|
|
393
|
+
anchorKey: string | undefined;
|
|
394
|
+
size: number;
|
|
395
|
+
}
|
|
396
|
+
interface ScrollToEndOptions {
|
|
397
|
+
animated?: boolean;
|
|
398
|
+
viewOffset?: number;
|
|
399
|
+
}
|
|
391
400
|
interface AnchoredEndSpaceConfig {
|
|
392
401
|
anchorIndex: number;
|
|
393
402
|
anchorOffset?: number;
|
|
394
403
|
anchorMaxSize?: number;
|
|
395
404
|
includeInEndInset?: boolean;
|
|
396
405
|
onSizeChanged?: (size: number) => void;
|
|
406
|
+
onReady?: (info: AnchoredEndSpaceReadyInfo) => void;
|
|
397
407
|
}
|
|
398
408
|
interface StickyHeaderConfig {
|
|
399
409
|
/**
|
|
@@ -525,10 +535,7 @@ type LegendListRef$1 = {
|
|
|
525
535
|
* @param options.animated - If true, animates the scroll. Default: true.
|
|
526
536
|
* @param options.viewOffset - Offset from the target position.
|
|
527
537
|
*/
|
|
528
|
-
scrollToEnd(options?:
|
|
529
|
-
animated?: boolean | undefined;
|
|
530
|
-
viewOffset?: number | undefined;
|
|
531
|
-
}): Promise<void>;
|
|
538
|
+
scrollToEnd(options?: ScrollToEndOptions): Promise<void>;
|
|
532
539
|
/**
|
|
533
540
|
* Scrolls to a specific index in the list.
|
|
534
541
|
* @param params - Parameters for scrolling.
|
package/keyboard-legacy.d.ts
CHANGED
|
@@ -63,6 +63,10 @@ interface Insets {
|
|
|
63
63
|
bottom: number;
|
|
64
64
|
right: number;
|
|
65
65
|
}
|
|
66
|
+
interface ScrollToEndOptions {
|
|
67
|
+
animated?: boolean;
|
|
68
|
+
viewOffset?: number;
|
|
69
|
+
}
|
|
66
70
|
interface LegendListAverageItemSize {
|
|
67
71
|
average: number;
|
|
68
72
|
count: number;
|
|
@@ -141,10 +145,7 @@ type LegendListRef$1 = {
|
|
|
141
145
|
* @param options.animated - If true, animates the scroll. Default: true.
|
|
142
146
|
* @param options.viewOffset - Offset from the target position.
|
|
143
147
|
*/
|
|
144
|
-
scrollToEnd(options?:
|
|
145
|
-
animated?: boolean | undefined;
|
|
146
|
-
viewOffset?: number | undefined;
|
|
147
|
-
}): Promise<void>;
|
|
148
|
+
scrollToEnd(options?: ScrollToEndOptions): Promise<void>;
|
|
148
149
|
/**
|
|
149
150
|
* Scrolls to a specific index in the list.
|
|
150
151
|
* @param params - Parameters for scrolling.
|
package/keyboard.d.ts
CHANGED
|
@@ -64,12 +64,22 @@ interface Insets {
|
|
|
64
64
|
bottom: number;
|
|
65
65
|
right: number;
|
|
66
66
|
}
|
|
67
|
+
interface AnchoredEndSpaceReadyInfo {
|
|
68
|
+
anchorIndex: number | undefined;
|
|
69
|
+
anchorKey: string | undefined;
|
|
70
|
+
size: number;
|
|
71
|
+
}
|
|
72
|
+
interface ScrollToEndOptions {
|
|
73
|
+
animated?: boolean;
|
|
74
|
+
viewOffset?: number;
|
|
75
|
+
}
|
|
67
76
|
interface AnchoredEndSpaceConfig$1 {
|
|
68
77
|
anchorIndex: number;
|
|
69
78
|
anchorOffset?: number;
|
|
70
79
|
anchorMaxSize?: number;
|
|
71
80
|
includeInEndInset?: boolean;
|
|
72
81
|
onSizeChanged?: (size: number) => void;
|
|
82
|
+
onReady?: (info: AnchoredEndSpaceReadyInfo) => void;
|
|
73
83
|
}
|
|
74
84
|
interface LegendListAverageItemSize {
|
|
75
85
|
average: number;
|
|
@@ -149,10 +159,7 @@ type LegendListRef$1 = {
|
|
|
149
159
|
* @param options.animated - If true, animates the scroll. Default: true.
|
|
150
160
|
* @param options.viewOffset - Offset from the target position.
|
|
151
161
|
*/
|
|
152
|
-
scrollToEnd(options?:
|
|
153
|
-
animated?: boolean | undefined;
|
|
154
|
-
viewOffset?: number | undefined;
|
|
155
|
-
}): Promise<void>;
|
|
162
|
+
scrollToEnd(options?: ScrollToEndOptions): Promise<void>;
|
|
156
163
|
/**
|
|
157
164
|
* Scrolls to a specific index in the list.
|
|
158
165
|
* @param params - Parameters for scrolling.
|
package/package.json
CHANGED
package/react-native.d.ts
CHANGED
|
@@ -394,12 +394,22 @@ interface MaintainVisibleContentPositionConfig<ItemT = any> {
|
|
|
394
394
|
size?: boolean;
|
|
395
395
|
shouldRestorePosition?: (item: ItemT, index: number, data: readonly ItemT[]) => boolean;
|
|
396
396
|
}
|
|
397
|
+
interface AnchoredEndSpaceReadyInfo {
|
|
398
|
+
anchorIndex: number | undefined;
|
|
399
|
+
anchorKey: string | undefined;
|
|
400
|
+
size: number;
|
|
401
|
+
}
|
|
402
|
+
interface ScrollToEndOptions {
|
|
403
|
+
animated?: boolean;
|
|
404
|
+
viewOffset?: number;
|
|
405
|
+
}
|
|
397
406
|
interface AnchoredEndSpaceConfig {
|
|
398
407
|
anchorIndex: number;
|
|
399
408
|
anchorOffset?: number;
|
|
400
409
|
anchorMaxSize?: number;
|
|
401
410
|
includeInEndInset?: boolean;
|
|
402
411
|
onSizeChanged?: (size: number) => void;
|
|
412
|
+
onReady?: (info: AnchoredEndSpaceReadyInfo) => void;
|
|
403
413
|
}
|
|
404
414
|
interface StickyHeaderConfig {
|
|
405
415
|
/**
|
|
@@ -531,10 +541,7 @@ type LegendListRef$1 = {
|
|
|
531
541
|
* @param options.animated - If true, animates the scroll. Default: true.
|
|
532
542
|
* @param options.viewOffset - Offset from the target position.
|
|
533
543
|
*/
|
|
534
|
-
scrollToEnd(options?:
|
|
535
|
-
animated?: boolean | undefined;
|
|
536
|
-
viewOffset?: number | undefined;
|
|
537
|
-
}): Promise<void>;
|
|
544
|
+
scrollToEnd(options?: ScrollToEndOptions): Promise<void>;
|
|
538
545
|
/**
|
|
539
546
|
* Scrolls to a specific index in the list.
|
|
540
547
|
* @param params - Parameters for scrolling.
|
package/react-native.js
CHANGED
|
@@ -743,6 +743,22 @@ function Separator({ ItemSeparatorComponent, leadingItem }) {
|
|
|
743
743
|
const isLastItem = useIsLastItem();
|
|
744
744
|
return isLastItem ? null : /* @__PURE__ */ React2__namespace.createElement(ItemSeparatorComponent, { leadingItem });
|
|
745
745
|
}
|
|
746
|
+
var PixelRatio = ReactNative.PixelRatio;
|
|
747
|
+
|
|
748
|
+
// src/utils/layoutMeasurement.ts
|
|
749
|
+
var FLOATING_POINT_SLACK = 0.01;
|
|
750
|
+
var NATIVE_LAYOUT_MEASUREMENT_EPSILON = 1 / PixelRatio.get() + FLOATING_POINT_SLACK;
|
|
751
|
+
function isWithinEpsilon(delta) {
|
|
752
|
+
return Math.abs(delta) <= NATIVE_LAYOUT_MEASUREMENT_EPSILON;
|
|
753
|
+
}
|
|
754
|
+
function isNativeLayoutNoise(delta) {
|
|
755
|
+
return isWithinEpsilon(delta);
|
|
756
|
+
}
|
|
757
|
+
function isNativeLayoutSizeNoise(heightDelta, widthDelta) {
|
|
758
|
+
return isWithinEpsilon(heightDelta) && isWithinEpsilon(widthDelta);
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// src/hooks/useOnLayoutSync.native.tsx
|
|
746
762
|
function useOnLayoutSync({
|
|
747
763
|
ref,
|
|
748
764
|
onLayoutProp,
|
|
@@ -751,11 +767,21 @@ function useOnLayoutSync({
|
|
|
751
767
|
const lastLayoutRef = React2.useRef(null);
|
|
752
768
|
const onLayout = React2.useCallback(
|
|
753
769
|
(event) => {
|
|
754
|
-
var _a3, _b;
|
|
755
770
|
const { layout } = event.nativeEvent;
|
|
756
|
-
|
|
771
|
+
const lastLayout = lastLayoutRef.current;
|
|
772
|
+
const didLayoutSizeChange = lastLayout && (layout.height !== lastLayout.height || layout.width !== lastLayout.width);
|
|
773
|
+
const isMeasuredLayoutNoise = !!didLayoutSizeChange && !!lastLayout.measuredLayout && isNativeLayoutSizeNoise(
|
|
774
|
+
layout.height - lastLayout.measuredLayout.height,
|
|
775
|
+
layout.width - lastLayout.measuredLayout.width
|
|
776
|
+
);
|
|
777
|
+
if (!lastLayout || didLayoutSizeChange && !isMeasuredLayoutNoise) {
|
|
757
778
|
onLayoutChange(layout, false);
|
|
758
|
-
|
|
779
|
+
}
|
|
780
|
+
if (!lastLayout || didLayoutSizeChange) {
|
|
781
|
+
lastLayoutRef.current = {
|
|
782
|
+
...layout,
|
|
783
|
+
measuredLayout: isMeasuredLayoutNoise ? lastLayout == null ? void 0 : lastLayout.measuredLayout : void 0
|
|
784
|
+
};
|
|
759
785
|
}
|
|
760
786
|
onLayoutProp == null ? void 0 : onLayoutProp(event);
|
|
761
787
|
},
|
|
@@ -766,7 +792,7 @@ function useOnLayoutSync({
|
|
|
766
792
|
if (ref.current) {
|
|
767
793
|
ref.current.measure((x, y, width, height) => {
|
|
768
794
|
const layout = { height, width, x, y };
|
|
769
|
-
lastLayoutRef.current = layout;
|
|
795
|
+
lastLayoutRef.current = { ...layout, measuredLayout: layout };
|
|
770
796
|
onLayoutChange(layout, true);
|
|
771
797
|
});
|
|
772
798
|
}
|
|
@@ -1805,17 +1831,42 @@ function setSize(ctx, itemKey, size, notifyTotalSize = true) {
|
|
|
1805
1831
|
}
|
|
1806
1832
|
|
|
1807
1833
|
// src/utils/getItemSize.ts
|
|
1834
|
+
function getKnownOrFixedSize(ctx, key, index, data) {
|
|
1835
|
+
var _a3;
|
|
1836
|
+
const state = ctx.state;
|
|
1837
|
+
const { getFixedItemSize, getItemType } = state.props;
|
|
1838
|
+
let size = key ? state.sizesKnown.get(key) : void 0;
|
|
1839
|
+
if (size === void 0 && key && getFixedItemSize) {
|
|
1840
|
+
const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
|
|
1841
|
+
size = getFixedItemSize(data, index, itemType);
|
|
1842
|
+
if (size !== void 0) {
|
|
1843
|
+
state.sizesKnown.set(key, size);
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
return size;
|
|
1847
|
+
}
|
|
1848
|
+
function getKnownOrFixedItemSize(ctx, index) {
|
|
1849
|
+
const key = getId(ctx.state, index);
|
|
1850
|
+
return getKnownOrFixedSize(ctx, key, index, ctx.state.props.data[index]);
|
|
1851
|
+
}
|
|
1852
|
+
function areKnownOrFixedItemSizesAvailable(ctx, startIndex, endIndex) {
|
|
1853
|
+
for (let index = startIndex; index <= endIndex; index++) {
|
|
1854
|
+
if (getKnownOrFixedItemSize(ctx, index) === void 0) {
|
|
1855
|
+
return false;
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
return true;
|
|
1859
|
+
}
|
|
1808
1860
|
function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, notifyTotalSize) {
|
|
1809
1861
|
var _a3, _b, _c;
|
|
1810
1862
|
const state = ctx.state;
|
|
1811
1863
|
const {
|
|
1812
|
-
sizesKnown,
|
|
1813
1864
|
sizes,
|
|
1814
1865
|
averageSizes,
|
|
1815
|
-
props: { estimatedItemSize,
|
|
1866
|
+
props: { estimatedItemSize, getItemType },
|
|
1816
1867
|
scrollingTo
|
|
1817
1868
|
} = state;
|
|
1818
|
-
const sizeKnown = sizesKnown.get(key);
|
|
1869
|
+
const sizeKnown = state.sizesKnown.get(key);
|
|
1819
1870
|
if (sizeKnown !== void 0) {
|
|
1820
1871
|
return sizeKnown;
|
|
1821
1872
|
}
|
|
@@ -1826,14 +1877,13 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
|
|
|
1826
1877
|
return renderedSize;
|
|
1827
1878
|
}
|
|
1828
1879
|
}
|
|
1829
|
-
|
|
1830
|
-
if (
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
sizesKnown.set(key, size);
|
|
1834
|
-
}
|
|
1880
|
+
size = getKnownOrFixedSize(ctx, key, index, data);
|
|
1881
|
+
if (size !== void 0) {
|
|
1882
|
+
setSize(ctx, key, size, notifyTotalSize);
|
|
1883
|
+
return size;
|
|
1835
1884
|
}
|
|
1836
|
-
|
|
1885
|
+
const itemType = getItemType ? (_a3 = getItemType(data, index)) != null ? _a3 : "" : "";
|
|
1886
|
+
if (useAverageSize && !scrollingTo) {
|
|
1837
1887
|
const averageSizeForType = (_b = averageSizes[itemType]) == null ? void 0 : _b.avg;
|
|
1838
1888
|
if (averageSizeForType !== void 0) {
|
|
1839
1889
|
size = roundSize(averageSizeForType);
|
|
@@ -1842,7 +1892,7 @@ function getItemSize(ctx, key, index, data, useAverageSize, preferCachedSize, no
|
|
|
1842
1892
|
if (size === void 0 && renderedSize !== void 0) {
|
|
1843
1893
|
return renderedSize;
|
|
1844
1894
|
}
|
|
1845
|
-
if (size === void 0 && useAverageSize &&
|
|
1895
|
+
if (size === void 0 && useAverageSize && scrollingTo) {
|
|
1846
1896
|
const averageSizeForType = (_c = scrollingTo.averageSizeSnapshot) == null ? void 0 : _c[itemType];
|
|
1847
1897
|
if (averageSizeForType !== void 0) {
|
|
1848
1898
|
size = roundSize(averageSizeForType);
|
|
@@ -2595,7 +2645,7 @@ function updateScroll(ctx, newScroll, forceUpdate, options) {
|
|
|
2595
2645
|
if (scrollLength > 0 && scrollingTo === void 0 && scrollDelta > scrollLength && !state.pendingNativeMVCPAdjust) {
|
|
2596
2646
|
state.mvcpAnchorLock = void 0;
|
|
2597
2647
|
state.pendingNativeMVCPAdjust = void 0;
|
|
2598
|
-
state.
|
|
2648
|
+
state.userScrollAnchorReset = { keys: /* @__PURE__ */ new Set() };
|
|
2599
2649
|
if (state.queuedMVCPRecalculate !== void 0) {
|
|
2600
2650
|
cancelAnimationFrame(state.queuedMVCPRecalculate);
|
|
2601
2651
|
state.queuedMVCPRecalculate = void 0;
|
|
@@ -4413,7 +4463,7 @@ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentSt
|
|
|
4413
4463
|
function calculateItemsInView(ctx, params = {}) {
|
|
4414
4464
|
const state = ctx.state;
|
|
4415
4465
|
batchedUpdates(() => {
|
|
4416
|
-
var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p
|
|
4466
|
+
var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
|
|
4417
4467
|
const {
|
|
4418
4468
|
columns,
|
|
4419
4469
|
containerItemKeys,
|
|
@@ -4727,7 +4777,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4727
4777
|
state.containerItemTypes.set(containerIndex, requiredItemTypes[idx]);
|
|
4728
4778
|
}
|
|
4729
4779
|
containerItemKeys.set(id, containerIndex);
|
|
4730
|
-
(_o = state.
|
|
4780
|
+
(_o = state.userScrollAnchorReset) == null ? void 0 : _o.keys.add(id);
|
|
4731
4781
|
const containerSticky = `containerSticky${containerIndex}`;
|
|
4732
4782
|
const isSticky = stickyHeaderIndicesSet.has(i);
|
|
4733
4783
|
const isAlwaysRender = alwaysRenderSet.has(i);
|
|
@@ -4755,13 +4805,17 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4755
4805
|
}
|
|
4756
4806
|
}
|
|
4757
4807
|
}
|
|
4758
|
-
if (
|
|
4759
|
-
state.
|
|
4808
|
+
if (state.userScrollAnchorReset) {
|
|
4809
|
+
if (state.userScrollAnchorReset.keys.size === 0) {
|
|
4810
|
+
state.userScrollAnchorReset = void 0;
|
|
4811
|
+
} else {
|
|
4812
|
+
state.userScrollAnchorReset.batchSize = state.userScrollAnchorReset.keys.size;
|
|
4813
|
+
}
|
|
4760
4814
|
}
|
|
4761
4815
|
if (alwaysRenderArr.length > 0) {
|
|
4762
4816
|
for (const index of alwaysRenderArr) {
|
|
4763
4817
|
if (index < 0 || index >= dataLength) continue;
|
|
4764
|
-
const id = (
|
|
4818
|
+
const id = (_p = idCache[index]) != null ? _p : getId(state, index);
|
|
4765
4819
|
const containerIndex = containerItemKeys.get(id);
|
|
4766
4820
|
if (containerIndex !== void 0) {
|
|
4767
4821
|
state.stickyContainerPool.add(containerIndex);
|
|
@@ -5159,22 +5213,27 @@ var ScrollAdjustHandler = class {
|
|
|
5159
5213
|
|
|
5160
5214
|
// src/core/updateAnchoredEndSpace.ts
|
|
5161
5215
|
function maybeUpdateAnchoredEndSpace(ctx) {
|
|
5162
|
-
var _a3;
|
|
5216
|
+
var _a3, _b;
|
|
5163
5217
|
const state = ctx.state;
|
|
5164
5218
|
const anchoredEndSpace = state.props.anchoredEndSpace;
|
|
5165
5219
|
const previousSize = peek$(ctx, "anchoredEndSpaceSize");
|
|
5220
|
+
const previousReadyAnchorIndex = state.anchoredEndSpaceReadyAnchorIndex;
|
|
5221
|
+
const previousReadyAnchorKey = state.anchoredEndSpaceReadyAnchorKey;
|
|
5222
|
+
const nextAnchorIndex = anchoredEndSpace == null ? void 0 : anchoredEndSpace.anchorIndex;
|
|
5223
|
+
let nextAnchorKey;
|
|
5224
|
+
let isReady = true;
|
|
5166
5225
|
let nextSize = 0;
|
|
5167
5226
|
if (anchoredEndSpace) {
|
|
5168
5227
|
const { anchorIndex, anchorMaxSize, anchorOffset = 0 } = anchoredEndSpace;
|
|
5169
5228
|
const { data } = state.props;
|
|
5170
5229
|
if (anchorIndex >= 0 && anchorIndex < data.length && state.scrollLength > 0) {
|
|
5230
|
+
nextAnchorKey = getId(state, anchorIndex);
|
|
5171
5231
|
let contentBelowAnchor = 0;
|
|
5172
5232
|
const footerSize = ctx.values.get("footerSize") || 0;
|
|
5173
5233
|
const stylePaddingBottom = state.props.stylePaddingBottom || 0;
|
|
5174
5234
|
let hasUnknownTailSize = false;
|
|
5175
5235
|
for (let index = anchorIndex; index < data.length; index++) {
|
|
5176
|
-
const
|
|
5177
|
-
const size = itemKey ? state.sizesKnown.get(itemKey) : void 0;
|
|
5236
|
+
const size = getKnownOrFixedItemSize(ctx, index);
|
|
5178
5237
|
const effectiveSize = index === anchorIndex && anchorMaxSize !== void 0 ? Math.min(size || 0, Math.max(0, anchorMaxSize)) : size;
|
|
5179
5238
|
if (size === void 0) {
|
|
5180
5239
|
hasUnknownTailSize = true;
|
|
@@ -5184,15 +5243,25 @@ function maybeUpdateAnchoredEndSpace(ctx) {
|
|
|
5184
5243
|
}
|
|
5185
5244
|
}
|
|
5186
5245
|
contentBelowAnchor += footerSize + stylePaddingBottom;
|
|
5246
|
+
isReady = !hasUnknownTailSize;
|
|
5187
5247
|
nextSize = hasUnknownTailSize ? previousSize || 0 : Math.max(0, state.scrollLength - contentBelowAnchor - anchorOffset);
|
|
5248
|
+
} else if (anchorIndex >= 0) {
|
|
5249
|
+
isReady = false;
|
|
5188
5250
|
}
|
|
5189
5251
|
}
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5252
|
+
const didSizeChange = previousSize !== nextSize;
|
|
5253
|
+
const didReadyAnchorChange = previousReadyAnchorIndex !== nextAnchorIndex || previousReadyAnchorKey !== nextAnchorKey;
|
|
5254
|
+
if (isReady && (didSizeChange || didReadyAnchorChange)) {
|
|
5255
|
+
state.anchoredEndSpaceReadyAnchorIndex = nextAnchorIndex;
|
|
5256
|
+
state.anchoredEndSpaceReadyAnchorKey = nextAnchorKey;
|
|
5257
|
+
if (didSizeChange) {
|
|
5258
|
+
set$(ctx, "anchoredEndSpaceSize", nextSize);
|
|
5259
|
+
(_a3 = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onSizeChanged) == null ? void 0 : _a3.call(anchoredEndSpace, nextSize);
|
|
5260
|
+
}
|
|
5261
|
+
if (didSizeChange && (anchoredEndSpace == null ? void 0 : anchoredEndSpace.includeInEndInset)) {
|
|
5194
5262
|
updateScroll(ctx, state.scroll, true);
|
|
5195
5263
|
}
|
|
5264
|
+
(_b = anchoredEndSpace == null ? void 0 : anchoredEndSpace.onReady) == null ? void 0 : _b.call(anchoredEndSpace, { anchorIndex: nextAnchorIndex, anchorKey: nextAnchorKey, size: nextSize });
|
|
5196
5265
|
}
|
|
5197
5266
|
return nextSize;
|
|
5198
5267
|
}
|
|
@@ -5215,37 +5284,42 @@ function updateContentInsetEndAdjustment(ctx, previousContentInsetEndAdjustment)
|
|
|
5215
5284
|
|
|
5216
5285
|
// src/core/updateItemSize.ts
|
|
5217
5286
|
function runOrScheduleMVCPRecalculate(ctx) {
|
|
5287
|
+
var _a3, _b;
|
|
5218
5288
|
const state = ctx.state;
|
|
5219
|
-
if (state.
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5289
|
+
if (state.userScrollAnchorReset !== void 0) {
|
|
5290
|
+
const replacementBatchSize = (_a3 = state.userScrollAnchorReset.batchSize) != null ? _a3 : state.userScrollAnchorReset.keys.size;
|
|
5291
|
+
const replacementMeasurementBatchThreshold = 3;
|
|
5292
|
+
const shouldBatchReplacementMeasurements = replacementBatchSize > replacementMeasurementBatchThreshold;
|
|
5293
|
+
if (shouldBatchReplacementMeasurements) {
|
|
5294
|
+
if (state.queuedMVCPRecalculate === void 0) {
|
|
5295
|
+
state.queuedMVCPRecalculate = requestAnimationFrame(() => {
|
|
5296
|
+
var _a4;
|
|
5297
|
+
state.queuedMVCPRecalculate = void 0;
|
|
5298
|
+
calculateItemsInView(ctx);
|
|
5299
|
+
if (((_a4 = state.userScrollAnchorReset) == null ? void 0 : _a4.keys.size) === 0) {
|
|
5300
|
+
state.userScrollAnchorReset = void 0;
|
|
5301
|
+
}
|
|
5302
|
+
});
|
|
5303
|
+
}
|
|
5304
|
+
} else {
|
|
5226
5305
|
calculateItemsInView(ctx);
|
|
5227
|
-
if (((
|
|
5228
|
-
state.
|
|
5306
|
+
if (((_b = state.userScrollAnchorReset) == null ? void 0 : _b.keys.size) === 0) {
|
|
5307
|
+
state.userScrollAnchorReset = void 0;
|
|
5229
5308
|
}
|
|
5230
|
-
}
|
|
5231
|
-
|
|
5232
|
-
}
|
|
5233
|
-
if (Platform.OS === "web") {
|
|
5309
|
+
}
|
|
5310
|
+
} else if (Platform.OS === "web") {
|
|
5234
5311
|
if (!state.mvcpAnchorLock) {
|
|
5235
5312
|
if (state.queuedMVCPRecalculate !== void 0) {
|
|
5236
5313
|
cancelAnimationFrame(state.queuedMVCPRecalculate);
|
|
5237
5314
|
state.queuedMVCPRecalculate = void 0;
|
|
5238
5315
|
}
|
|
5239
5316
|
calculateItemsInView(ctx, { doMVCP: true });
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5317
|
+
} else if (state.queuedMVCPRecalculate === void 0) {
|
|
5318
|
+
state.queuedMVCPRecalculate = requestAnimationFrame(() => {
|
|
5319
|
+
state.queuedMVCPRecalculate = void 0;
|
|
5320
|
+
calculateItemsInView(ctx, { doMVCP: true });
|
|
5321
|
+
});
|
|
5244
5322
|
}
|
|
5245
|
-
state.queuedMVCPRecalculate = requestAnimationFrame(() => {
|
|
5246
|
-
state.queuedMVCPRecalculate = void 0;
|
|
5247
|
-
calculateItemsInView(ctx, { doMVCP: true });
|
|
5248
|
-
});
|
|
5249
5323
|
} else {
|
|
5250
5324
|
calculateItemsInView(ctx, { doMVCP: true });
|
|
5251
5325
|
}
|
|
@@ -5263,8 +5337,8 @@ function updateOtherAxisSizeIfNeeded(ctx, sizeObj, horizontal) {
|
|
|
5263
5337
|
function updateItemSize(ctx, itemKey, sizeObj) {
|
|
5264
5338
|
var _a3;
|
|
5265
5339
|
const state = ctx.state;
|
|
5266
|
-
const
|
|
5267
|
-
const didMeasureUserScrollAnchorResetItem = !!(
|
|
5340
|
+
const userScrollAnchorReset = state.userScrollAnchorReset;
|
|
5341
|
+
const didMeasureUserScrollAnchorResetItem = !!(userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.delete(itemKey));
|
|
5268
5342
|
const {
|
|
5269
5343
|
didContainersLayout,
|
|
5270
5344
|
sizesKnown,
|
|
@@ -5320,8 +5394,8 @@ function updateItemSize(ctx, itemKey, sizeObj) {
|
|
|
5320
5394
|
if (needsRecalculate) {
|
|
5321
5395
|
state.scrollForNextCalculateItemsInView = void 0;
|
|
5322
5396
|
runOrScheduleMVCPRecalculate(ctx);
|
|
5323
|
-
} else if (didMeasureUserScrollAnchorResetItem && (
|
|
5324
|
-
state.
|
|
5397
|
+
} else if (didMeasureUserScrollAnchorResetItem && (userScrollAnchorReset == null ? void 0 : userScrollAnchorReset.keys.size) === 0) {
|
|
5398
|
+
state.userScrollAnchorReset = void 0;
|
|
5325
5399
|
}
|
|
5326
5400
|
if (shouldMaintainScrollAtEnd) {
|
|
5327
5401
|
if (maintainScrollAtEnd == null ? void 0 : maintainScrollAtEnd.onItemLayout) {
|
|
@@ -5331,7 +5405,7 @@ function updateItemSize(ctx, itemKey, sizeObj) {
|
|
|
5331
5405
|
}
|
|
5332
5406
|
}
|
|
5333
5407
|
function updateOneItemSize(ctx, itemKey, sizeObj) {
|
|
5334
|
-
var _a3;
|
|
5408
|
+
var _a3, _b;
|
|
5335
5409
|
const state = ctx.state;
|
|
5336
5410
|
const {
|
|
5337
5411
|
indexByKey,
|
|
@@ -5341,13 +5415,23 @@ function updateOneItemSize(ctx, itemKey, sizeObj) {
|
|
|
5341
5415
|
} = state;
|
|
5342
5416
|
if (!data) return 0;
|
|
5343
5417
|
const index = indexByKey.get(itemKey);
|
|
5344
|
-
const
|
|
5418
|
+
const itemData = data[index];
|
|
5419
|
+
let itemType;
|
|
5420
|
+
let fixedItemSize;
|
|
5421
|
+
if (getFixedItemSize) {
|
|
5422
|
+
itemType = getItemType ? (_a3 = getItemType(itemData, index)) != null ? _a3 : "" : "";
|
|
5423
|
+
fixedItemSize = getFixedItemSize(itemData, index, itemType);
|
|
5424
|
+
}
|
|
5425
|
+
const prevSize = getItemSize(ctx, itemKey, index, itemData);
|
|
5345
5426
|
const rawSize = horizontal ? sizeObj.width : sizeObj.height;
|
|
5346
|
-
const size = Platform.OS === "web" ? Math.round(rawSize) : roundSize(rawSize);
|
|
5347
5427
|
const prevSizeKnown = sizesKnown.get(itemKey);
|
|
5428
|
+
if (Platform.OS !== "web" && prevSizeKnown !== void 0 && isNativeLayoutNoise(rawSize - prevSizeKnown)) {
|
|
5429
|
+
return 0;
|
|
5430
|
+
}
|
|
5431
|
+
const size = Platform.OS === "web" ? Math.round(rawSize) : roundSize(rawSize);
|
|
5348
5432
|
sizesKnown.set(itemKey, size);
|
|
5349
|
-
if (
|
|
5350
|
-
|
|
5433
|
+
if (fixedItemSize === void 0 && size > 0) {
|
|
5434
|
+
itemType != null ? itemType : itemType = getItemType ? (_b = getItemType(itemData, index)) != null ? _b : "" : "";
|
|
5351
5435
|
let averages = averageSizes[itemType];
|
|
5352
5436
|
if (!averages) {
|
|
5353
5437
|
averages = averageSizes[itemType] = { avg: 0, num: 0 };
|
|
@@ -5428,6 +5512,25 @@ function createColumnWrapperStyle(contentContainerStyle) {
|
|
|
5428
5512
|
}
|
|
5429
5513
|
}
|
|
5430
5514
|
|
|
5515
|
+
// src/core/scrollToEnd.ts
|
|
5516
|
+
function scrollToEnd(ctx, options) {
|
|
5517
|
+
const state = ctx.state;
|
|
5518
|
+
const data = state.props.data;
|
|
5519
|
+
const index = data.length - 1;
|
|
5520
|
+
if (index === -1) {
|
|
5521
|
+
return false;
|
|
5522
|
+
}
|
|
5523
|
+
const paddingBottom = state.props.stylePaddingBottom || 0;
|
|
5524
|
+
const footerSize = peek$(ctx, "footerSize") || 0;
|
|
5525
|
+
scrollToIndex(ctx, {
|
|
5526
|
+
...options,
|
|
5527
|
+
index,
|
|
5528
|
+
viewOffset: -paddingBottom - footerSize + ((options == null ? void 0 : options.viewOffset) || 0),
|
|
5529
|
+
viewPosition: 1
|
|
5530
|
+
});
|
|
5531
|
+
return true;
|
|
5532
|
+
}
|
|
5533
|
+
|
|
5431
5534
|
// src/utils/createImperativeHandle.ts
|
|
5432
5535
|
var DEFAULT_AVERAGE_ITEM_SIZE_TYPE = "default";
|
|
5433
5536
|
function getAverageItemSizes(state) {
|
|
@@ -5443,7 +5546,7 @@ function getAverageItemSizes(state) {
|
|
|
5443
5546
|
}
|
|
5444
5547
|
return averageItemSizes;
|
|
5445
5548
|
}
|
|
5446
|
-
function createImperativeHandle(ctx) {
|
|
5549
|
+
function createImperativeHandle(ctx, scheduleImperativeScrollCommit) {
|
|
5447
5550
|
const state = ctx.state;
|
|
5448
5551
|
const IMPERATIVE_SCROLL_SETTLE_MAX_WAIT_MS = 800;
|
|
5449
5552
|
const IMPERATIVE_SCROLL_SETTLE_STABLE_FRAMES = 2;
|
|
@@ -5460,15 +5563,10 @@ function createImperativeHandle(ctx) {
|
|
|
5460
5563
|
if (targetIndex >= dataLength) {
|
|
5461
5564
|
return false;
|
|
5462
5565
|
}
|
|
5463
|
-
if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex
|
|
5566
|
+
if (anchorIndex === void 0 || anchorIndex < 0 || anchorIndex >= dataLength || targetIndex < anchorIndex) {
|
|
5464
5567
|
return true;
|
|
5465
5568
|
}
|
|
5466
|
-
|
|
5467
|
-
if (!state.sizesKnown.has(getId(state, index))) {
|
|
5468
|
-
return false;
|
|
5469
|
-
}
|
|
5470
|
-
}
|
|
5471
|
-
return true;
|
|
5569
|
+
return areKnownOrFixedItemSizesAvailable(ctx, anchorIndex, dataLength - 1);
|
|
5472
5570
|
};
|
|
5473
5571
|
const runWhenReady = (token, run, isReady) => {
|
|
5474
5572
|
const startedAt = Date.now();
|
|
@@ -5491,11 +5589,7 @@ function createImperativeHandle(ctx) {
|
|
|
5491
5589
|
};
|
|
5492
5590
|
requestAnimationFrame(check);
|
|
5493
5591
|
};
|
|
5494
|
-
const
|
|
5495
|
-
var _a3;
|
|
5496
|
-
const token = ++imperativeScrollToken;
|
|
5497
|
-
(_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
|
|
5498
|
-
state.pendingScrollResolve = resolve;
|
|
5592
|
+
const runScrollRequest = (token, resolve, run, isReady = () => true) => {
|
|
5499
5593
|
const runNow = () => {
|
|
5500
5594
|
if (token !== imperativeScrollToken) {
|
|
5501
5595
|
return;
|
|
@@ -5513,7 +5607,33 @@ function createImperativeHandle(ctx) {
|
|
|
5513
5607
|
} else {
|
|
5514
5608
|
runNow();
|
|
5515
5609
|
}
|
|
5610
|
+
};
|
|
5611
|
+
const startImperativeScroll = (resolve) => {
|
|
5612
|
+
var _a3;
|
|
5613
|
+
const token = ++imperativeScrollToken;
|
|
5614
|
+
state.pendingScrollToEnd = void 0;
|
|
5615
|
+
(_a3 = state.pendingScrollResolve) == null ? void 0 : _a3.call(state);
|
|
5616
|
+
state.pendingScrollResolve = resolve;
|
|
5617
|
+
return token;
|
|
5618
|
+
};
|
|
5619
|
+
const runScrollWithPromise = (run, isReady = () => true) => new Promise((resolve) => {
|
|
5620
|
+
const token = startImperativeScroll(resolve);
|
|
5621
|
+
runScrollRequest(token, resolve, run, isReady);
|
|
5516
5622
|
});
|
|
5623
|
+
state.runPendingScrollToEnd = () => {
|
|
5624
|
+
const pendingScroll = state.pendingScrollToEnd;
|
|
5625
|
+
if (pendingScroll) {
|
|
5626
|
+
state.pendingScrollToEnd = void 0;
|
|
5627
|
+
if (pendingScroll.token === imperativeScrollToken) {
|
|
5628
|
+
runScrollRequest(
|
|
5629
|
+
pendingScroll.token,
|
|
5630
|
+
pendingScroll.resolve,
|
|
5631
|
+
() => scrollToEnd(ctx, pendingScroll.options),
|
|
5632
|
+
() => isScrollToIndexReady(state.props.data.length - 1, true)
|
|
5633
|
+
);
|
|
5634
|
+
}
|
|
5635
|
+
}
|
|
5636
|
+
};
|
|
5517
5637
|
const scrollIndexIntoView = (options) => {
|
|
5518
5638
|
if (state) {
|
|
5519
5639
|
const { index, ...rest } = options;
|
|
@@ -5612,26 +5732,20 @@ function createImperativeHandle(ctx) {
|
|
|
5612
5732
|
}
|
|
5613
5733
|
return false;
|
|
5614
5734
|
}),
|
|
5615
|
-
scrollToEnd: (options) =>
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
return true;
|
|
5630
|
-
}
|
|
5631
|
-
return false;
|
|
5632
|
-
},
|
|
5633
|
-
() => isScrollToIndexReady(state.props.data.length - 1, true)
|
|
5634
|
-
),
|
|
5735
|
+
scrollToEnd: (options) => new Promise((resolve) => {
|
|
5736
|
+
var _a3;
|
|
5737
|
+
const token = startImperativeScroll(resolve);
|
|
5738
|
+
state.pendingScrollToEnd = {
|
|
5739
|
+
options,
|
|
5740
|
+
resolve,
|
|
5741
|
+
token
|
|
5742
|
+
};
|
|
5743
|
+
if (scheduleImperativeScrollCommit) {
|
|
5744
|
+
scheduleImperativeScrollCommit();
|
|
5745
|
+
} else {
|
|
5746
|
+
(_a3 = state.runPendingScrollToEnd) == null ? void 0 : _a3.call(state);
|
|
5747
|
+
}
|
|
5748
|
+
}),
|
|
5635
5749
|
scrollToIndex: (params) => {
|
|
5636
5750
|
return runScrollWithPromise(
|
|
5637
5751
|
() => {
|
|
@@ -6001,6 +6115,7 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
6001
6115
|
viewOffset: 0
|
|
6002
6116
|
} : void 0;
|
|
6003
6117
|
const [canRender, setCanRender] = React2__namespace.useState(!IsNewArchitecture);
|
|
6118
|
+
const [, scheduleImperativeScrollCommit] = React2__namespace.useReducer((value) => value + 1, 0);
|
|
6004
6119
|
const ctx = useStateContext();
|
|
6005
6120
|
ctx.columnWrapperStyle = columnWrapperStyle || (contentContainerStyle ? createColumnWrapperStyle(contentContainerStyle) : void 0);
|
|
6006
6121
|
const refScroller = React2.useRef(null);
|
|
@@ -6373,7 +6488,11 @@ var LegendListInner = typedForwardRef(function LegendListInner2(props, forwarded
|
|
|
6373
6488
|
doInitialAllocateContainers(ctx);
|
|
6374
6489
|
}
|
|
6375
6490
|
});
|
|
6376
|
-
React2.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx), []);
|
|
6491
|
+
React2.useImperativeHandle(forwardedRef, () => createImperativeHandle(ctx, scheduleImperativeScrollCommit), []);
|
|
6492
|
+
React2.useLayoutEffect(() => {
|
|
6493
|
+
var _a4;
|
|
6494
|
+
(_a4 = state.runPendingScrollToEnd) == null ? void 0 : _a4.call(state);
|
|
6495
|
+
});
|
|
6377
6496
|
React2.useEffect(() => {
|
|
6378
6497
|
if (Platform.OS !== "web" || usesBootstrapInitialScroll) {
|
|
6379
6498
|
return;
|