@legendapp/list 3.3.0 → 3.3.2
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 +8 -1
- package/keyboard-legacy.d.ts +8 -1
- package/keyboard.d.ts +8 -1
- package/package.json +1 -1
- package/react-native.d.ts +8 -1
- package/react-native.js +330 -114
- package/react-native.mjs +330 -114
- package/react-native.web.d.ts +8 -1
- package/react-native.web.js +330 -114
- package/react-native.web.mjs +330 -114
- package/react.d.ts +8 -1
- package/react.js +330 -114
- package/react.mjs +330 -114
- package/reanimated.d.ts +8 -1
- package/section-list.d.ts +8 -1
package/react-native.web.mjs
CHANGED
|
@@ -127,6 +127,7 @@ var createAnimatedValue = (value) => value;
|
|
|
127
127
|
|
|
128
128
|
// src/state/state.tsx
|
|
129
129
|
var ContextState = React3.createContext(null);
|
|
130
|
+
var SIGNAL_NAMES_SEPARATOR = "\0";
|
|
130
131
|
var contextNum = 0;
|
|
131
132
|
function StateProvider({ children }) {
|
|
132
133
|
const [value] = React3.useState(() => ({
|
|
@@ -198,6 +199,12 @@ function createSelectorFunctionsArr(ctx, signalNames) {
|
|
|
198
199
|
}
|
|
199
200
|
};
|
|
200
201
|
}
|
|
202
|
+
function getSignalNamesKey(signalNames) {
|
|
203
|
+
return signalNames.length === 1 ? signalNames[0] : signalNames.join(SIGNAL_NAMES_SEPARATOR);
|
|
204
|
+
}
|
|
205
|
+
function getSignalNamesFromKey(signalNamesKey) {
|
|
206
|
+
return signalNamesKey.split(SIGNAL_NAMES_SEPARATOR);
|
|
207
|
+
}
|
|
201
208
|
function listen$(ctx, signalName, cb) {
|
|
202
209
|
const { listeners } = ctx;
|
|
203
210
|
let setListeners = listeners.get(signalName);
|
|
@@ -245,7 +252,11 @@ function notifyPosition$(ctx, key, value) {
|
|
|
245
252
|
}
|
|
246
253
|
function useArr$(signalNames) {
|
|
247
254
|
const ctx = React3.useContext(ContextState);
|
|
248
|
-
const
|
|
255
|
+
const signalNamesKey = getSignalNamesKey(signalNames);
|
|
256
|
+
const { subscribe, get } = React3.useMemo(
|
|
257
|
+
() => createSelectorFunctionsArr(ctx, getSignalNamesFromKey(signalNamesKey)),
|
|
258
|
+
[ctx, signalNamesKey]
|
|
259
|
+
);
|
|
249
260
|
const value = useSyncExternalStore(subscribe, get, get);
|
|
250
261
|
return value;
|
|
251
262
|
}
|
|
@@ -532,9 +543,22 @@ function useInit(cb) {
|
|
|
532
543
|
|
|
533
544
|
// src/state/ContextContainer.ts
|
|
534
545
|
var ContextContainer = createContext(null);
|
|
546
|
+
var NO_CONTAINER_ID = -1;
|
|
535
547
|
function useContextContainer() {
|
|
536
548
|
return useContext(ContextContainer);
|
|
537
549
|
}
|
|
550
|
+
function useContainerItemInfo(containerContext) {
|
|
551
|
+
var _a3;
|
|
552
|
+
const containerId = (_a3 = containerContext == null ? void 0 : containerContext.containerId) != null ? _a3 : NO_CONTAINER_ID;
|
|
553
|
+
const [itemInfo] = useArr$([`containerItemInfo${containerId}`]);
|
|
554
|
+
return containerContext ? itemInfo : void 0;
|
|
555
|
+
}
|
|
556
|
+
function useContainerItemKey(containerContext) {
|
|
557
|
+
var _a3;
|
|
558
|
+
const containerId = (_a3 = containerContext == null ? void 0 : containerContext.containerId) != null ? _a3 : NO_CONTAINER_ID;
|
|
559
|
+
const [itemKey] = useArr$([`containerItemKey${containerId}`]);
|
|
560
|
+
return containerContext ? itemKey : void 0;
|
|
561
|
+
}
|
|
538
562
|
function useAdaptiveRender() {
|
|
539
563
|
const [mode] = useArr$(["adaptiveRender"]);
|
|
540
564
|
return mode;
|
|
@@ -605,40 +629,35 @@ function useViewabilityAmount(callback) {
|
|
|
605
629
|
}
|
|
606
630
|
function useRecyclingEffect(effect) {
|
|
607
631
|
const containerContext = useContextContainer();
|
|
608
|
-
const
|
|
609
|
-
|
|
610
|
-
prevItem: void 0
|
|
611
|
-
});
|
|
632
|
+
const itemInfo = useContainerItemInfo(containerContext);
|
|
633
|
+
const prevInfo = useRef(void 0);
|
|
612
634
|
useEffect(() => {
|
|
613
|
-
if (!
|
|
635
|
+
if (!itemInfo) {
|
|
614
636
|
return;
|
|
615
637
|
}
|
|
616
|
-
const { index, value } = containerContext;
|
|
617
638
|
let ret;
|
|
618
|
-
if (
|
|
639
|
+
if (prevInfo.current) {
|
|
619
640
|
ret = effect({
|
|
620
|
-
index,
|
|
621
|
-
item: value,
|
|
622
|
-
prevIndex:
|
|
623
|
-
prevItem:
|
|
641
|
+
index: itemInfo.index,
|
|
642
|
+
item: itemInfo.value,
|
|
643
|
+
prevIndex: prevInfo.current.index,
|
|
644
|
+
prevItem: prevInfo.current.value
|
|
624
645
|
});
|
|
625
646
|
}
|
|
626
|
-
|
|
627
|
-
prevIndex: index,
|
|
628
|
-
prevItem: value
|
|
629
|
-
};
|
|
647
|
+
prevInfo.current = itemInfo;
|
|
630
648
|
return ret;
|
|
631
|
-
}, [effect,
|
|
649
|
+
}, [effect, itemInfo]);
|
|
632
650
|
}
|
|
633
651
|
function useRecyclingState(valueOrFun) {
|
|
634
|
-
var _a3
|
|
652
|
+
var _a3;
|
|
635
653
|
const containerContext = useContextContainer();
|
|
636
|
-
const
|
|
654
|
+
const itemInfo = useContainerItemInfo(containerContext);
|
|
655
|
+
const computeValue = (info) => {
|
|
637
656
|
if (isFunction(valueOrFun)) {
|
|
638
657
|
const initializer = valueOrFun;
|
|
639
|
-
return
|
|
640
|
-
index:
|
|
641
|
-
item:
|
|
658
|
+
return info ? initializer({
|
|
659
|
+
index: info.index,
|
|
660
|
+
item: info.value,
|
|
642
661
|
prevIndex: void 0,
|
|
643
662
|
prevItem: void 0
|
|
644
663
|
}) : initializer();
|
|
@@ -646,13 +665,12 @@ function useRecyclingState(valueOrFun) {
|
|
|
646
665
|
return valueOrFun;
|
|
647
666
|
};
|
|
648
667
|
const [stateValue, setStateValue] = useState(() => {
|
|
649
|
-
return computeValue(
|
|
668
|
+
return computeValue(itemInfo);
|
|
650
669
|
});
|
|
651
|
-
const prevItemKeyRef = useRef((_a3 =
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
setStateValue(computeValue(containerContext));
|
|
670
|
+
const prevItemKeyRef = useRef((_a3 = itemInfo == null ? void 0 : itemInfo.itemKey) != null ? _a3 : null);
|
|
671
|
+
if (itemInfo && prevItemKeyRef.current !== itemInfo.itemKey) {
|
|
672
|
+
prevItemKeyRef.current = itemInfo.itemKey;
|
|
673
|
+
setStateValue(computeValue(itemInfo));
|
|
656
674
|
}
|
|
657
675
|
const triggerLayout = containerContext == null ? void 0 : containerContext.triggerLayout;
|
|
658
676
|
const setState = useCallback(
|
|
@@ -671,12 +689,10 @@ function useRecyclingState(valueOrFun) {
|
|
|
671
689
|
}
|
|
672
690
|
function useIsLastItem() {
|
|
673
691
|
const containerContext = useContextContainer();
|
|
692
|
+
const itemKey = useContainerItemKey(containerContext);
|
|
674
693
|
const isLast = useSelector$("lastItemKeys", (lastItemKeys) => {
|
|
675
|
-
if (containerContext) {
|
|
676
|
-
|
|
677
|
-
if (!isNullOrUndefined(itemKey)) {
|
|
678
|
-
return (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false;
|
|
679
|
-
}
|
|
694
|
+
if (containerContext && !isNullOrUndefined(itemKey)) {
|
|
695
|
+
return (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false;
|
|
680
696
|
}
|
|
681
697
|
return false;
|
|
682
698
|
});
|
|
@@ -690,12 +706,7 @@ var noop = () => {
|
|
|
690
706
|
};
|
|
691
707
|
function useSyncLayout() {
|
|
692
708
|
const containerContext = useContextContainer();
|
|
693
|
-
|
|
694
|
-
const { triggerLayout: syncLayout } = containerContext;
|
|
695
|
-
return syncLayout;
|
|
696
|
-
} else {
|
|
697
|
-
return noop;
|
|
698
|
-
}
|
|
709
|
+
return containerContext ? containerContext.triggerLayout : noop;
|
|
699
710
|
}
|
|
700
711
|
|
|
701
712
|
// src/components/Separator.tsx
|
|
@@ -1463,6 +1474,7 @@ function finishScrollTo(ctx) {
|
|
|
1463
1474
|
const scrollingTo = state.scrollingTo;
|
|
1464
1475
|
state.scrollHistory.length = 0;
|
|
1465
1476
|
state.scrollingTo = void 0;
|
|
1477
|
+
state.scrollTargetPinnedRange = void 0;
|
|
1466
1478
|
if (state.pendingTotalSize !== void 0) {
|
|
1467
1479
|
addTotalSize(ctx, null, state.pendingTotalSize);
|
|
1468
1480
|
}
|
|
@@ -1956,6 +1968,8 @@ function prepareMVCP(ctx, dataChanged) {
|
|
|
1956
1968
|
}
|
|
1957
1969
|
|
|
1958
1970
|
// src/utils/getScrollVelocity.ts
|
|
1971
|
+
var MAX_SCROLL_VELOCITY_WINDOW_MS = 1e3;
|
|
1972
|
+
var SCROLL_VELOCITY_HALF_LIFE_MS = 200;
|
|
1959
1973
|
var getScrollVelocity = (state) => {
|
|
1960
1974
|
const { scrollHistory } = state;
|
|
1961
1975
|
const newestIndex = scrollHistory.length - 1;
|
|
@@ -1963,35 +1977,37 @@ var getScrollVelocity = (state) => {
|
|
|
1963
1977
|
return 0;
|
|
1964
1978
|
}
|
|
1965
1979
|
const newest = scrollHistory[newestIndex];
|
|
1966
|
-
|
|
1967
|
-
let direction = 0;
|
|
1968
|
-
for (let i = newestIndex; i > 0; i--) {
|
|
1969
|
-
const delta = scrollHistory[i].scroll - scrollHistory[i - 1].scroll;
|
|
1970
|
-
if (delta !== 0) {
|
|
1971
|
-
direction = Math.sign(delta);
|
|
1972
|
-
break;
|
|
1973
|
-
}
|
|
1974
|
-
}
|
|
1975
|
-
if (direction === 0) {
|
|
1980
|
+
if (Date.now() - newest.time > MAX_SCROLL_VELOCITY_WINDOW_MS) {
|
|
1976
1981
|
return 0;
|
|
1977
1982
|
}
|
|
1978
|
-
let
|
|
1979
|
-
|
|
1983
|
+
let direction = 0;
|
|
1984
|
+
let weightedVelocity = 0;
|
|
1985
|
+
let totalWeight = 0;
|
|
1986
|
+
for (let i = newestIndex; i > 0; i--) {
|
|
1980
1987
|
const current = scrollHistory[i];
|
|
1981
|
-
const
|
|
1982
|
-
const
|
|
1983
|
-
const
|
|
1984
|
-
|
|
1985
|
-
|
|
1988
|
+
const previous = scrollHistory[i - 1];
|
|
1989
|
+
const scrollDiff = current.scroll - previous.scroll;
|
|
1990
|
+
const timeDiff = current.time - previous.time;
|
|
1991
|
+
const deltaSign = Math.sign(scrollDiff);
|
|
1992
|
+
if (deltaSign !== 0) {
|
|
1993
|
+
if (direction === 0) {
|
|
1994
|
+
direction = deltaSign;
|
|
1995
|
+
} else if (deltaSign !== direction) {
|
|
1996
|
+
break;
|
|
1997
|
+
}
|
|
1986
1998
|
}
|
|
1987
|
-
if (
|
|
1999
|
+
if (newest.time - previous.time > MAX_SCROLL_VELOCITY_WINDOW_MS) {
|
|
1988
2000
|
break;
|
|
1989
2001
|
}
|
|
1990
|
-
|
|
2002
|
+
if (scrollDiff === 0 || timeDiff <= 0) {
|
|
2003
|
+
continue;
|
|
2004
|
+
}
|
|
2005
|
+
const age = newest.time - current.time;
|
|
2006
|
+
const weight = Math.exp(-age / SCROLL_VELOCITY_HALF_LIFE_MS);
|
|
2007
|
+
weightedVelocity += scrollDiff / timeDiff * weight;
|
|
2008
|
+
totalWeight += weight;
|
|
1991
2009
|
}
|
|
1992
|
-
|
|
1993
|
-
const timeDiff = newest.time - oldest.time;
|
|
1994
|
-
return timeDiff > 0 ? scrollDiff / timeDiff : 0;
|
|
2010
|
+
return totalWeight > 0 ? weightedVelocity / totalWeight : 0;
|
|
1995
2011
|
};
|
|
1996
2012
|
|
|
1997
2013
|
// src/core/updateScroll.ts
|
|
@@ -2108,8 +2124,93 @@ function syncInitialScrollNativeWatchdog(state, options) {
|
|
|
2108
2124
|
initialScrollWatchdog.clear(state);
|
|
2109
2125
|
}
|
|
2110
2126
|
}
|
|
2111
|
-
function
|
|
2127
|
+
function findPositionIndexAtOrBeforeOffset(ctx, offset) {
|
|
2128
|
+
const state = ctx.state;
|
|
2129
|
+
const dataLength = state.props.data.length;
|
|
2130
|
+
let low = 0;
|
|
2131
|
+
let high = dataLength - 1;
|
|
2132
|
+
let match;
|
|
2133
|
+
while (low <= high) {
|
|
2134
|
+
const mid = Math.floor((low + high) / 2);
|
|
2135
|
+
const top = state.positions[mid];
|
|
2136
|
+
if (top === void 0) {
|
|
2137
|
+
high = mid - 1;
|
|
2138
|
+
} else {
|
|
2139
|
+
if (top <= offset) {
|
|
2140
|
+
match = mid;
|
|
2141
|
+
low = mid + 1;
|
|
2142
|
+
} else {
|
|
2143
|
+
high = mid - 1;
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
return match;
|
|
2148
|
+
}
|
|
2149
|
+
function getItemBottom(ctx, index) {
|
|
2112
2150
|
var _a3;
|
|
2151
|
+
const top = ctx.state.positions[index];
|
|
2152
|
+
if (top === void 0) {
|
|
2153
|
+
return void 0;
|
|
2154
|
+
}
|
|
2155
|
+
const itemSize = (_a3 = getItemSizeAtIndex(ctx, index)) != null ? _a3 : 0;
|
|
2156
|
+
return top + (Number.isFinite(itemSize) ? itemSize : 0);
|
|
2157
|
+
}
|
|
2158
|
+
function getTargetViewportRenderRange(ctx, targetOffset, targetIndex) {
|
|
2159
|
+
const state = ctx.state;
|
|
2160
|
+
const dataLength = state.props.data.length;
|
|
2161
|
+
if (dataLength === 0) {
|
|
2162
|
+
return void 0;
|
|
2163
|
+
}
|
|
2164
|
+
const viewportStart = Math.max(0, targetOffset);
|
|
2165
|
+
const viewportEnd = Math.max(viewportStart, targetOffset + state.scrollLength);
|
|
2166
|
+
let start = targetIndex !== void 0 ? Math.max(0, Math.min(dataLength - 1, targetIndex)) : findPositionIndexAtOrBeforeOffset(ctx, viewportStart);
|
|
2167
|
+
if (start === void 0) {
|
|
2168
|
+
return void 0;
|
|
2169
|
+
}
|
|
2170
|
+
if (targetIndex !== void 0 && state.positions[start] === void 0) {
|
|
2171
|
+
return { end: start, start };
|
|
2172
|
+
}
|
|
2173
|
+
if (targetIndex === void 0) {
|
|
2174
|
+
const startBottom = getItemBottom(ctx, start);
|
|
2175
|
+
if (startBottom === void 0 || startBottom <= viewportStart) {
|
|
2176
|
+
return void 0;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
while (start > 0) {
|
|
2180
|
+
const top = state.positions[start];
|
|
2181
|
+
if (top === void 0 || top <= viewportStart || state.positions[start - 1] === void 0) {
|
|
2182
|
+
break;
|
|
2183
|
+
}
|
|
2184
|
+
start--;
|
|
2185
|
+
}
|
|
2186
|
+
while (start > 0) {
|
|
2187
|
+
const previousBottom = getItemBottom(ctx, start - 1);
|
|
2188
|
+
if (previousBottom === void 0 || previousBottom <= viewportStart) {
|
|
2189
|
+
break;
|
|
2190
|
+
}
|
|
2191
|
+
start--;
|
|
2192
|
+
}
|
|
2193
|
+
let end = start;
|
|
2194
|
+
while (end + 1 < dataLength) {
|
|
2195
|
+
const nextTop = state.positions[end + 1];
|
|
2196
|
+
if (nextTop === void 0 || nextTop > viewportEnd) {
|
|
2197
|
+
break;
|
|
2198
|
+
}
|
|
2199
|
+
end++;
|
|
2200
|
+
}
|
|
2201
|
+
return { end, start };
|
|
2202
|
+
}
|
|
2203
|
+
function pinScrollTargetRenderRange(ctx, targetOffset, targetIndex) {
|
|
2204
|
+
const range = getTargetViewportRenderRange(ctx, targetOffset, targetIndex);
|
|
2205
|
+
if (range) {
|
|
2206
|
+
ctx.state.scrollTargetPinnedRange = range;
|
|
2207
|
+
ctx.state.scrollForNextCalculateItemsInView = void 0;
|
|
2208
|
+
} else {
|
|
2209
|
+
ctx.state.scrollTargetPinnedRange = void 0;
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
function scrollTo(ctx, params) {
|
|
2213
|
+
var _a3, _b;
|
|
2113
2214
|
const state = ctx.state;
|
|
2114
2215
|
const { noScrollingTo, forceScroll, ...scrollTarget } = params;
|
|
2115
2216
|
const {
|
|
@@ -2144,11 +2245,20 @@ function scrollTo(ctx, params) {
|
|
|
2144
2245
|
targetOffset,
|
|
2145
2246
|
waitForInitialScrollCompletionFrame
|
|
2146
2247
|
};
|
|
2248
|
+
if (!isInitialScroll) {
|
|
2249
|
+
pinScrollTargetRenderRange(ctx, targetOffset, scrollTarget.index);
|
|
2250
|
+
}
|
|
2147
2251
|
}
|
|
2148
2252
|
state.scrollPending = targetOffset;
|
|
2149
2253
|
syncInitialScrollNativeWatchdog(state, { isInitialScroll, requestedOffset: offset, targetOffset });
|
|
2150
|
-
if (!
|
|
2151
|
-
|
|
2254
|
+
if (!isInitialScroll && !noScrollingTo && Math.abs(state.scroll - targetOffset) > 1) {
|
|
2255
|
+
if (animated) {
|
|
2256
|
+
if (state.scrollTargetPinnedRange) {
|
|
2257
|
+
(_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state);
|
|
2258
|
+
}
|
|
2259
|
+
} else {
|
|
2260
|
+
updateScroll(ctx, targetOffset, true, { markHasScrolled: false });
|
|
2261
|
+
}
|
|
2152
2262
|
}
|
|
2153
2263
|
if (forceScroll || !isInitialScroll || Platform.OS === "android") {
|
|
2154
2264
|
doScrollTo(ctx, { animated, horizontal, offset });
|
|
@@ -3236,22 +3346,28 @@ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
|
|
|
3236
3346
|
set$(ctx, `containerSpan${containerIndex}`, span);
|
|
3237
3347
|
}
|
|
3238
3348
|
}
|
|
3349
|
+
const prevItemInfo = peek$(ctx, `containerItemInfo${containerIndex}`);
|
|
3239
3350
|
const prevData = peek$(ctx, `containerItemData${containerIndex}`);
|
|
3351
|
+
let itemInfoValue = prevData;
|
|
3352
|
+
let didChangeItemInfo = (prevItemInfo == null ? void 0 : prevItemInfo.itemKey) !== itemKey || (prevItemInfo == null ? void 0 : prevItemInfo.index) !== itemIndex || (prevItemInfo == null ? void 0 : prevItemInfo.value) !== prevData;
|
|
3353
|
+
const updateData = () => {
|
|
3354
|
+
set$(ctx, `containerItemData${containerIndex}`, item);
|
|
3355
|
+
itemInfoValue = item;
|
|
3356
|
+
didChangeItemInfo = true;
|
|
3357
|
+
didRefreshData = true;
|
|
3358
|
+
};
|
|
3240
3359
|
if (prevData !== item) {
|
|
3241
3360
|
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;
|
|
3242
3361
|
const cachedComparison = (_g = pendingDataComparison == null ? void 0 : pendingDataComparison.byIndex[itemIndex]) != null ? _g : 0;
|
|
3243
3362
|
if (cachedComparison === 2) {
|
|
3244
|
-
|
|
3245
|
-
didRefreshData = true;
|
|
3363
|
+
updateData();
|
|
3246
3364
|
} else if (cachedComparison !== 1) {
|
|
3247
3365
|
const nextItemKey = (_h = peek$(ctx, `containerItemKey${containerIndex}`)) != null ? _h : itemKey;
|
|
3248
3366
|
const prevKey = keyExtractor == null ? void 0 : keyExtractor(prevData, itemIndex);
|
|
3249
3367
|
if (prevData === void 0 || !keyExtractor || prevKey !== nextItemKey) {
|
|
3250
|
-
|
|
3251
|
-
didRefreshData = true;
|
|
3368
|
+
updateData();
|
|
3252
3369
|
} else if (!itemsAreEqual) {
|
|
3253
|
-
|
|
3254
|
-
didRefreshData = true;
|
|
3370
|
+
updateData();
|
|
3255
3371
|
} else {
|
|
3256
3372
|
const isEqual = itemsAreEqual(prevData, item, itemIndex, data);
|
|
3257
3373
|
if (!state.pendingDataComparison || state.pendingDataComparison.previousData !== state.previousData || state.pendingDataComparison.nextData !== data) {
|
|
@@ -3267,12 +3383,18 @@ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
|
|
|
3267
3383
|
state.pendingDataComparison.byIndex[itemIndex] = isEqual ? 1 : 2;
|
|
3268
3384
|
}
|
|
3269
3385
|
if (!isEqual) {
|
|
3270
|
-
|
|
3271
|
-
didRefreshData = true;
|
|
3386
|
+
updateData();
|
|
3272
3387
|
}
|
|
3273
3388
|
}
|
|
3274
3389
|
}
|
|
3275
3390
|
}
|
|
3391
|
+
if (didChangeItemInfo) {
|
|
3392
|
+
set$(ctx, `containerItemInfo${containerIndex}`, {
|
|
3393
|
+
index: itemIndex,
|
|
3394
|
+
itemKey,
|
|
3395
|
+
value: itemInfoValue
|
|
3396
|
+
});
|
|
3397
|
+
}
|
|
3276
3398
|
return { didChangePosition, didRefreshData };
|
|
3277
3399
|
}
|
|
3278
3400
|
|
|
@@ -3965,6 +4087,32 @@ function setDidLayout(ctx) {
|
|
|
3965
4087
|
}
|
|
3966
4088
|
|
|
3967
4089
|
// src/core/calculateItemsInView.ts
|
|
4090
|
+
var RENDER_RANGE_PROJECTION_FULL_VELOCITY = 4;
|
|
4091
|
+
var RENDER_RANGE_PROJECTION_SETTLE_DELAY = 100;
|
|
4092
|
+
function getProjectedBufferAdjustment(scrollVelocity, trailingBuffer) {
|
|
4093
|
+
if (trailingBuffer <= 0) {
|
|
4094
|
+
return 0;
|
|
4095
|
+
}
|
|
4096
|
+
const velocityProgress = Math.min(1, Math.abs(scrollVelocity) / RENDER_RANGE_PROJECTION_FULL_VELOCITY);
|
|
4097
|
+
return Math.sign(scrollVelocity) * trailingBuffer * velocityProgress;
|
|
4098
|
+
}
|
|
4099
|
+
function scheduleRenderRangeProjectionSettle(ctx) {
|
|
4100
|
+
const state = ctx.state;
|
|
4101
|
+
const previousTimeout = state.timeoutRenderRangeProjectionSettle;
|
|
4102
|
+
if (previousTimeout !== void 0) {
|
|
4103
|
+
clearTimeout(previousTimeout);
|
|
4104
|
+
state.timeouts.delete(previousTimeout);
|
|
4105
|
+
}
|
|
4106
|
+
const timeout = setTimeout(() => {
|
|
4107
|
+
var _a3;
|
|
4108
|
+
state.timeoutRenderRangeProjectionSettle = void 0;
|
|
4109
|
+
state.timeouts.delete(timeout);
|
|
4110
|
+
state.scrollHistory.length = 0;
|
|
4111
|
+
(_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state);
|
|
4112
|
+
}, RENDER_RANGE_PROJECTION_SETTLE_DELAY);
|
|
4113
|
+
state.timeoutRenderRangeProjectionSettle = timeout;
|
|
4114
|
+
state.timeouts.add(timeout);
|
|
4115
|
+
}
|
|
3968
4116
|
function findCurrentStickyIndex(stickyArray, scroll, state) {
|
|
3969
4117
|
const positions = state.positions;
|
|
3970
4118
|
for (let i = stickyArray.length - 1; i >= 0; i--) {
|
|
@@ -4005,14 +4153,14 @@ function handleStickyActivation(ctx, stickyArray, currentStickyIdx, needNewConta
|
|
|
4005
4153
|
}
|
|
4006
4154
|
}
|
|
4007
4155
|
}
|
|
4008
|
-
function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentStickyIdx, pendingRemoval,
|
|
4156
|
+
function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentStickyIdx, pendingRemoval, isPinnedRenderIndex) {
|
|
4009
4157
|
var _a3, _b;
|
|
4010
4158
|
const state = ctx.state;
|
|
4011
4159
|
for (const containerIndex of state.stickyContainerPool) {
|
|
4012
4160
|
const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
|
|
4013
4161
|
const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
|
|
4014
4162
|
if (itemIndex === void 0) continue;
|
|
4015
|
-
if (
|
|
4163
|
+
if (isPinnedRenderIndex(itemIndex)) continue;
|
|
4016
4164
|
const arrayIdx = stickyArray.indexOf(itemIndex);
|
|
4017
4165
|
if (arrayIdx === -1) {
|
|
4018
4166
|
state.stickyContainerPool.delete(containerIndex);
|
|
@@ -4176,8 +4324,6 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4176
4324
|
const { data } = state.props;
|
|
4177
4325
|
const stickyHeaderIndicesArr = state.props.stickyHeaderIndicesArr || [];
|
|
4178
4326
|
const stickyHeaderIndicesSet = state.props.stickyHeaderIndicesSet || /* @__PURE__ */ new Set();
|
|
4179
|
-
const alwaysRenderArr = alwaysRenderIndicesArr || [];
|
|
4180
|
-
const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
|
|
4181
4327
|
const drawDistance = getEffectiveDrawDistance(ctx, params.drawDistanceMode);
|
|
4182
4328
|
const { dataChanged, doMVCP, forceFullItemPositions } = params;
|
|
4183
4329
|
const bootstrapInitialScrollState = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" ? state.initialScrollSession.bootstrap : void 0;
|
|
@@ -4244,14 +4390,19 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4244
4390
|
scrollBufferTop = drawDistance * 1.5;
|
|
4245
4391
|
scrollBufferBottom = drawDistance * 0.5;
|
|
4246
4392
|
}
|
|
4393
|
+
const shouldProjectRenderRange = !dataChanged && !forceFullItemPositions && !suppressInitialScrollSideEffects && !hasActiveInitialScroll(state) && !state.scrollingTo && !state.pendingNativeMVCPAdjust && !!peek$(ctx, "readyToRender");
|
|
4394
|
+
const projectedBufferAdjustment = shouldProjectRenderRange ? getProjectedBufferAdjustment(speed, Math.min(scrollBufferTop, scrollBufferBottom)) : 0;
|
|
4247
4395
|
const updateScrollRange = () => {
|
|
4248
4396
|
const scrollStart = Math.max(0, scroll);
|
|
4249
4397
|
const overscrollBeforeContent = Math.max(0, -nativeScrollState);
|
|
4250
|
-
scrollTopBuffered = scrollStart - scrollBufferTop;
|
|
4251
4398
|
scrollBottom = Math.max(scrollStart, scroll + scrollLength + overscrollBeforeContent);
|
|
4252
|
-
|
|
4399
|
+
scrollTopBuffered = scrollStart - scrollBufferTop + projectedBufferAdjustment;
|
|
4400
|
+
scrollBottomBuffered = scrollBottom + scrollBufferBottom + projectedBufferAdjustment;
|
|
4253
4401
|
};
|
|
4254
4402
|
updateScrollRange();
|
|
4403
|
+
if (projectedBufferAdjustment !== 0) {
|
|
4404
|
+
scheduleRenderRangeProjectionSettle(ctx);
|
|
4405
|
+
}
|
|
4255
4406
|
if (enableScrollForNextCalculateItemsInView && !suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
|
|
4256
4407
|
const { top, bottom } = scrollForNextCalculateItemsInView;
|
|
4257
4408
|
if (top === null && bottom === null) {
|
|
@@ -4409,9 +4560,34 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4409
4560
|
}
|
|
4410
4561
|
}
|
|
4411
4562
|
}
|
|
4563
|
+
const scrollTargetPinnedRange = state.scrollTargetPinnedRange;
|
|
4564
|
+
let scrollTargetPinnedStart = 0;
|
|
4565
|
+
let scrollTargetPinnedEnd = -1;
|
|
4566
|
+
if (scrollTargetPinnedRange) {
|
|
4567
|
+
scrollTargetPinnedStart = Math.max(0, Math.min(scrollTargetPinnedRange.start, scrollTargetPinnedRange.end));
|
|
4568
|
+
scrollTargetPinnedEnd = Math.min(
|
|
4569
|
+
dataLength - 1,
|
|
4570
|
+
Math.max(scrollTargetPinnedRange.start, scrollTargetPinnedRange.end)
|
|
4571
|
+
);
|
|
4572
|
+
}
|
|
4573
|
+
const hasScrollTargetPinnedRange = scrollTargetPinnedStart <= scrollTargetPinnedEnd;
|
|
4574
|
+
const isPinnedRenderIndex = (index) => alwaysRenderIndicesSet.has(index) || hasScrollTargetPinnedRange && index >= scrollTargetPinnedStart && index <= scrollTargetPinnedEnd;
|
|
4412
4575
|
if (startBuffered !== null && endBuffered !== null) {
|
|
4413
4576
|
const needNewContainers = [];
|
|
4414
4577
|
const needNewContainersSet = /* @__PURE__ */ new Set();
|
|
4578
|
+
const addPinnedIndex = (index) => {
|
|
4579
|
+
var _a4;
|
|
4580
|
+
if (index >= 0 && index < dataLength) {
|
|
4581
|
+
const id = (_a4 = idCache[index]) != null ? _a4 : getId(state, index);
|
|
4582
|
+
const containerIndex = containerItemKeys.get(id);
|
|
4583
|
+
if (containerIndex !== void 0) {
|
|
4584
|
+
state.stickyContainerPool.add(containerIndex);
|
|
4585
|
+
} else if (!isNullOrUndefined(id) && !needNewContainersSet.has(index)) {
|
|
4586
|
+
needNewContainersSet.add(index);
|
|
4587
|
+
needNewContainers.push(index);
|
|
4588
|
+
}
|
|
4589
|
+
}
|
|
4590
|
+
};
|
|
4415
4591
|
for (let i = startBuffered; i <= endBuffered; i++) {
|
|
4416
4592
|
const id = (_m = idCache[i]) != null ? _m : getId(state, i);
|
|
4417
4593
|
if (!containerItemKeys.has(id)) {
|
|
@@ -4419,21 +4595,19 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4419
4595
|
needNewContainers.push(i);
|
|
4420
4596
|
}
|
|
4421
4597
|
}
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
needNewContainers.push(index);
|
|
4429
|
-
}
|
|
4598
|
+
for (const index of alwaysRenderIndicesArr) {
|
|
4599
|
+
addPinnedIndex(index);
|
|
4600
|
+
}
|
|
4601
|
+
if (hasScrollTargetPinnedRange) {
|
|
4602
|
+
for (let index = scrollTargetPinnedStart; index <= scrollTargetPinnedEnd; index++) {
|
|
4603
|
+
addPinnedIndex(index);
|
|
4430
4604
|
}
|
|
4431
4605
|
}
|
|
4432
4606
|
if (stickyHeaderIndicesArr.length > 0) {
|
|
4433
4607
|
handleStickyActivation(
|
|
4434
4608
|
ctx,
|
|
4435
4609
|
stickyHeaderIndicesArr,
|
|
4436
|
-
(
|
|
4610
|
+
(_n = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _n : -1,
|
|
4437
4611
|
needNewContainers,
|
|
4438
4612
|
needNewContainersSet,
|
|
4439
4613
|
startBuffered,
|
|
@@ -4459,21 +4633,30 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4459
4633
|
for (const allocation of availableContainerAllocations) {
|
|
4460
4634
|
const i = allocation.itemIndex;
|
|
4461
4635
|
const containerIndex = allocation.containerIndex;
|
|
4462
|
-
const id = (
|
|
4636
|
+
const id = (_o = idCache[i]) != null ? _o : getId(state, i);
|
|
4463
4637
|
const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
|
|
4464
4638
|
if (oldKey && oldKey !== id) {
|
|
4465
4639
|
containerItemKeys.delete(oldKey);
|
|
4466
4640
|
}
|
|
4467
4641
|
set$(ctx, `containerItemKey${containerIndex}`, id);
|
|
4468
4642
|
set$(ctx, `containerItemData${containerIndex}`, data[i]);
|
|
4643
|
+
set$(ctx, `containerItemInfo${containerIndex}`, {
|
|
4644
|
+
index: i,
|
|
4645
|
+
itemKey: id,
|
|
4646
|
+
value: data[i]
|
|
4647
|
+
});
|
|
4469
4648
|
if (allocation.itemType !== void 0) {
|
|
4470
4649
|
state.containerItemTypes.set(containerIndex, allocation.itemType);
|
|
4471
4650
|
}
|
|
4472
4651
|
containerItemKeys.set(id, containerIndex);
|
|
4473
|
-
(
|
|
4652
|
+
(_p = state.userScrollAnchorReset) == null ? void 0 : _p.keys.add(id);
|
|
4653
|
+
{
|
|
4654
|
+
(_q = state.pendingLayoutEffectMeasurements) != null ? _q : state.pendingLayoutEffectMeasurements = /* @__PURE__ */ new Set();
|
|
4655
|
+
state.pendingLayoutEffectMeasurements.add(id);
|
|
4656
|
+
}
|
|
4474
4657
|
const containerSticky = `containerSticky${containerIndex}`;
|
|
4475
4658
|
const isSticky = stickyHeaderIndicesSet.has(i);
|
|
4476
|
-
const
|
|
4659
|
+
const isPinnedRender = isPinnedRenderIndex(i);
|
|
4477
4660
|
if (isSticky) {
|
|
4478
4661
|
set$(ctx, containerSticky, true);
|
|
4479
4662
|
state.stickyContainerPool.add(containerIndex);
|
|
@@ -4481,9 +4664,9 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4481
4664
|
if (peek$(ctx, containerSticky)) {
|
|
4482
4665
|
set$(ctx, containerSticky, false);
|
|
4483
4666
|
}
|
|
4484
|
-
if (
|
|
4667
|
+
if (isPinnedRender) {
|
|
4485
4668
|
state.stickyContainerPool.add(containerIndex);
|
|
4486
|
-
} else
|
|
4669
|
+
} else {
|
|
4487
4670
|
state.stickyContainerPool.delete(containerIndex);
|
|
4488
4671
|
}
|
|
4489
4672
|
}
|
|
@@ -4498,20 +4681,8 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4498
4681
|
}
|
|
4499
4682
|
}
|
|
4500
4683
|
}
|
|
4501
|
-
if (state.userScrollAnchorReset) {
|
|
4502
|
-
|
|
4503
|
-
state.userScrollAnchorReset = void 0;
|
|
4504
|
-
}
|
|
4505
|
-
}
|
|
4506
|
-
if (alwaysRenderArr.length > 0) {
|
|
4507
|
-
for (const index of alwaysRenderArr) {
|
|
4508
|
-
if (index < 0 || index >= dataLength) continue;
|
|
4509
|
-
const id = (_r = idCache[index]) != null ? _r : getId(state, index);
|
|
4510
|
-
const containerIndex = containerItemKeys.get(id);
|
|
4511
|
-
if (containerIndex !== void 0) {
|
|
4512
|
-
state.stickyContainerPool.add(containerIndex);
|
|
4513
|
-
}
|
|
4514
|
-
}
|
|
4684
|
+
if (((_r = state.userScrollAnchorReset) == null ? void 0 : _r.keys.size) === 0) {
|
|
4685
|
+
state.userScrollAnchorReset = void 0;
|
|
4515
4686
|
}
|
|
4516
4687
|
}
|
|
4517
4688
|
if (state.stickyContainerPool.size > 0) {
|
|
@@ -4522,7 +4693,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4522
4693
|
drawDistance,
|
|
4523
4694
|
(_s = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _s : -1,
|
|
4524
4695
|
pendingRemoval,
|
|
4525
|
-
|
|
4696
|
+
isPinnedRenderIndex
|
|
4526
4697
|
);
|
|
4527
4698
|
}
|
|
4528
4699
|
const pendingRemovalSet = pendingRemoval.length > 0 ? new Set(pendingRemoval) : void 0;
|
|
@@ -4540,6 +4711,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4540
4711
|
}
|
|
4541
4712
|
set$(ctx, `containerItemKey${i}`, void 0);
|
|
4542
4713
|
set$(ctx, `containerItemData${i}`, void 0);
|
|
4714
|
+
set$(ctx, `containerItemInfo${i}`, void 0);
|
|
4543
4715
|
set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
|
|
4544
4716
|
set$(ctx, `containerColumn${i}`, -1);
|
|
4545
4717
|
set$(ctx, `containerSpan${i}`, 1);
|
|
@@ -4681,6 +4853,36 @@ function mergeItemSizeUpdateResult(result, next) {
|
|
|
4681
4853
|
result.needsRecalculate || (result.needsRecalculate = next.needsRecalculate);
|
|
4682
4854
|
result.shouldMaintainScrollAtEnd || (result.shouldMaintainScrollAtEnd = next.shouldMaintainScrollAtEnd);
|
|
4683
4855
|
}
|
|
4856
|
+
var batchedItemSizeRecalculates = /* @__PURE__ */ new WeakMap();
|
|
4857
|
+
function flushBatchedItemSizeRecalculate(ctx, didFallback = false, expectedResult) {
|
|
4858
|
+
const result = batchedItemSizeRecalculates.get(ctx);
|
|
4859
|
+
if (!result || expectedResult && result !== expectedResult) {
|
|
4860
|
+
return;
|
|
4861
|
+
}
|
|
4862
|
+
batchedItemSizeRecalculates.delete(ctx);
|
|
4863
|
+
if (didFallback) {
|
|
4864
|
+
ctx.state.pendingLayoutEffectMeasurements = void 0;
|
|
4865
|
+
}
|
|
4866
|
+
flushItemSizeUpdates(ctx, result);
|
|
4867
|
+
}
|
|
4868
|
+
function queueItemSizeRecalculate(ctx, result) {
|
|
4869
|
+
var _a3, _b;
|
|
4870
|
+
const batch = batchedItemSizeRecalculates.get(ctx);
|
|
4871
|
+
if (batch) {
|
|
4872
|
+
mergeItemSizeUpdateResult(batch, result);
|
|
4873
|
+
} else {
|
|
4874
|
+
const nextBatch = { ...result };
|
|
4875
|
+
batchedItemSizeRecalculates.set(ctx, nextBatch);
|
|
4876
|
+
if ((_a3 = ctx.state.pendingLayoutEffectMeasurements) == null ? void 0 : _a3.size) {
|
|
4877
|
+
requestAnimationFrame(() => {
|
|
4878
|
+
flushBatchedItemSizeRecalculate(ctx, true, nextBatch);
|
|
4879
|
+
});
|
|
4880
|
+
}
|
|
4881
|
+
}
|
|
4882
|
+
if (!((_b = ctx.state.pendingLayoutEffectMeasurements) == null ? void 0 : _b.size)) {
|
|
4883
|
+
flushBatchedItemSizeRecalculate(ctx);
|
|
4884
|
+
}
|
|
4885
|
+
}
|
|
4684
4886
|
function flushItemSizeUpdates(ctx, result) {
|
|
4685
4887
|
var _a3;
|
|
4686
4888
|
const state = ctx.state;
|
|
@@ -4697,12 +4899,22 @@ function flushItemSizeUpdates(ctx, result) {
|
|
|
4697
4899
|
function updateItemSizes(ctx, measurement) {
|
|
4698
4900
|
var _a3, _b, _c, _d;
|
|
4699
4901
|
const state = ctx.state;
|
|
4902
|
+
let didDrainLayoutEffectMeasurements = false;
|
|
4903
|
+
if (measurement.fromLayoutEffect) {
|
|
4904
|
+
const pendingLayoutEffectMeasurements = state.pendingLayoutEffectMeasurements;
|
|
4905
|
+
if ((pendingLayoutEffectMeasurements == null ? void 0 : pendingLayoutEffectMeasurements.delete(measurement.itemKey)) && pendingLayoutEffectMeasurements.size === 0) {
|
|
4906
|
+
state.pendingLayoutEffectMeasurements = void 0;
|
|
4907
|
+
didDrainLayoutEffectMeasurements = true;
|
|
4908
|
+
}
|
|
4909
|
+
}
|
|
4700
4910
|
const pendingKeys = (_a3 = state.userScrollAnchorReset) == null ? void 0 : _a3.keys;
|
|
4701
4911
|
const shouldBatchPendingMeasurements = measurement.fromLayoutEffect && !!(pendingKeys == null ? void 0 : pendingKeys.size);
|
|
4912
|
+
const shouldQueueRecalculate = !!measurement.fromLayoutEffect;
|
|
4913
|
+
let result;
|
|
4702
4914
|
if (!shouldBatchPendingMeasurements) {
|
|
4703
|
-
|
|
4915
|
+
result = applyItemSize(ctx, measurement.itemKey, measurement.size);
|
|
4704
4916
|
} else {
|
|
4705
|
-
|
|
4917
|
+
result = {};
|
|
4706
4918
|
const updateContainerItemSize = (itemKey, containerId, size) => {
|
|
4707
4919
|
if (containerId !== void 0 && peek$(ctx, `containerItemKey${containerId}`) === itemKey) {
|
|
4708
4920
|
mergeItemSizeUpdateResult(result, applyItemSize(ctx, itemKey, size));
|
|
@@ -4720,8 +4932,15 @@ function updateItemSizes(ctx, measurement) {
|
|
|
4720
4932
|
});
|
|
4721
4933
|
}
|
|
4722
4934
|
}
|
|
4935
|
+
}
|
|
4936
|
+
if (shouldQueueRecalculate && result.needsRecalculate) {
|
|
4937
|
+
queueItemSizeRecalculate(ctx, result);
|
|
4938
|
+
} else {
|
|
4723
4939
|
flushItemSizeUpdates(ctx, result);
|
|
4724
4940
|
}
|
|
4941
|
+
if (didDrainLayoutEffectMeasurements) {
|
|
4942
|
+
flushBatchedItemSizeRecalculate(ctx);
|
|
4943
|
+
}
|
|
4725
4944
|
}
|
|
4726
4945
|
function applyItemSize(ctx, itemKey, sizeObj) {
|
|
4727
4946
|
var _a3;
|
|
@@ -5113,12 +5332,9 @@ var Container = typedMemo(function Container2({
|
|
|
5113
5332
|
ctx.viewRefs.set(id, ref);
|
|
5114
5333
|
return {
|
|
5115
5334
|
containerId: id,
|
|
5116
|
-
|
|
5117
|
-
itemKey,
|
|
5118
|
-
triggerLayout,
|
|
5119
|
-
value: data
|
|
5335
|
+
triggerLayout
|
|
5120
5336
|
};
|
|
5121
|
-
}, [id,
|
|
5337
|
+
}, [id, triggerLayout]);
|
|
5122
5338
|
useLayoutEffect(() => {
|
|
5123
5339
|
ctx.containerLayoutTriggers.set(id, triggerLayout);
|
|
5124
5340
|
return () => {
|