@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.js
CHANGED
|
@@ -148,6 +148,7 @@ var createAnimatedValue = (value) => value;
|
|
|
148
148
|
|
|
149
149
|
// src/state/state.tsx
|
|
150
150
|
var ContextState = React3__namespace.createContext(null);
|
|
151
|
+
var SIGNAL_NAMES_SEPARATOR = "\0";
|
|
151
152
|
var contextNum = 0;
|
|
152
153
|
function StateProvider({ children }) {
|
|
153
154
|
const [value] = React3__namespace.useState(() => ({
|
|
@@ -219,6 +220,12 @@ function createSelectorFunctionsArr(ctx, signalNames) {
|
|
|
219
220
|
}
|
|
220
221
|
};
|
|
221
222
|
}
|
|
223
|
+
function getSignalNamesKey(signalNames) {
|
|
224
|
+
return signalNames.length === 1 ? signalNames[0] : signalNames.join(SIGNAL_NAMES_SEPARATOR);
|
|
225
|
+
}
|
|
226
|
+
function getSignalNamesFromKey(signalNamesKey) {
|
|
227
|
+
return signalNamesKey.split(SIGNAL_NAMES_SEPARATOR);
|
|
228
|
+
}
|
|
222
229
|
function listen$(ctx, signalName, cb) {
|
|
223
230
|
const { listeners } = ctx;
|
|
224
231
|
let setListeners = listeners.get(signalName);
|
|
@@ -266,7 +273,11 @@ function notifyPosition$(ctx, key, value) {
|
|
|
266
273
|
}
|
|
267
274
|
function useArr$(signalNames) {
|
|
268
275
|
const ctx = React3__namespace.useContext(ContextState);
|
|
269
|
-
const
|
|
276
|
+
const signalNamesKey = getSignalNamesKey(signalNames);
|
|
277
|
+
const { subscribe, get } = React3__namespace.useMemo(
|
|
278
|
+
() => createSelectorFunctionsArr(ctx, getSignalNamesFromKey(signalNamesKey)),
|
|
279
|
+
[ctx, signalNamesKey]
|
|
280
|
+
);
|
|
270
281
|
const value = shim.useSyncExternalStore(subscribe, get, get);
|
|
271
282
|
return value;
|
|
272
283
|
}
|
|
@@ -553,9 +564,22 @@ function useInit(cb) {
|
|
|
553
564
|
|
|
554
565
|
// src/state/ContextContainer.ts
|
|
555
566
|
var ContextContainer = React3.createContext(null);
|
|
567
|
+
var NO_CONTAINER_ID = -1;
|
|
556
568
|
function useContextContainer() {
|
|
557
569
|
return React3.useContext(ContextContainer);
|
|
558
570
|
}
|
|
571
|
+
function useContainerItemInfo(containerContext) {
|
|
572
|
+
var _a3;
|
|
573
|
+
const containerId = (_a3 = containerContext == null ? void 0 : containerContext.containerId) != null ? _a3 : NO_CONTAINER_ID;
|
|
574
|
+
const [itemInfo] = useArr$([`containerItemInfo${containerId}`]);
|
|
575
|
+
return containerContext ? itemInfo : void 0;
|
|
576
|
+
}
|
|
577
|
+
function useContainerItemKey(containerContext) {
|
|
578
|
+
var _a3;
|
|
579
|
+
const containerId = (_a3 = containerContext == null ? void 0 : containerContext.containerId) != null ? _a3 : NO_CONTAINER_ID;
|
|
580
|
+
const [itemKey] = useArr$([`containerItemKey${containerId}`]);
|
|
581
|
+
return containerContext ? itemKey : void 0;
|
|
582
|
+
}
|
|
559
583
|
function useAdaptiveRender() {
|
|
560
584
|
const [mode] = useArr$(["adaptiveRender"]);
|
|
561
585
|
return mode;
|
|
@@ -626,40 +650,35 @@ function useViewabilityAmount(callback) {
|
|
|
626
650
|
}
|
|
627
651
|
function useRecyclingEffect(effect) {
|
|
628
652
|
const containerContext = useContextContainer();
|
|
629
|
-
const
|
|
630
|
-
|
|
631
|
-
prevItem: void 0
|
|
632
|
-
});
|
|
653
|
+
const itemInfo = useContainerItemInfo(containerContext);
|
|
654
|
+
const prevInfo = React3.useRef(void 0);
|
|
633
655
|
React3.useEffect(() => {
|
|
634
|
-
if (!
|
|
656
|
+
if (!itemInfo) {
|
|
635
657
|
return;
|
|
636
658
|
}
|
|
637
|
-
const { index, value } = containerContext;
|
|
638
659
|
let ret;
|
|
639
|
-
if (
|
|
660
|
+
if (prevInfo.current) {
|
|
640
661
|
ret = effect({
|
|
641
|
-
index,
|
|
642
|
-
item: value,
|
|
643
|
-
prevIndex:
|
|
644
|
-
prevItem:
|
|
662
|
+
index: itemInfo.index,
|
|
663
|
+
item: itemInfo.value,
|
|
664
|
+
prevIndex: prevInfo.current.index,
|
|
665
|
+
prevItem: prevInfo.current.value
|
|
645
666
|
});
|
|
646
667
|
}
|
|
647
|
-
|
|
648
|
-
prevIndex: index,
|
|
649
|
-
prevItem: value
|
|
650
|
-
};
|
|
668
|
+
prevInfo.current = itemInfo;
|
|
651
669
|
return ret;
|
|
652
|
-
}, [effect,
|
|
670
|
+
}, [effect, itemInfo]);
|
|
653
671
|
}
|
|
654
672
|
function useRecyclingState(valueOrFun) {
|
|
655
|
-
var _a3
|
|
673
|
+
var _a3;
|
|
656
674
|
const containerContext = useContextContainer();
|
|
657
|
-
const
|
|
675
|
+
const itemInfo = useContainerItemInfo(containerContext);
|
|
676
|
+
const computeValue = (info) => {
|
|
658
677
|
if (isFunction(valueOrFun)) {
|
|
659
678
|
const initializer = valueOrFun;
|
|
660
|
-
return
|
|
661
|
-
index:
|
|
662
|
-
item:
|
|
679
|
+
return info ? initializer({
|
|
680
|
+
index: info.index,
|
|
681
|
+
item: info.value,
|
|
663
682
|
prevIndex: void 0,
|
|
664
683
|
prevItem: void 0
|
|
665
684
|
}) : initializer();
|
|
@@ -667,13 +686,12 @@ function useRecyclingState(valueOrFun) {
|
|
|
667
686
|
return valueOrFun;
|
|
668
687
|
};
|
|
669
688
|
const [stateValue, setStateValue] = React3.useState(() => {
|
|
670
|
-
return computeValue(
|
|
689
|
+
return computeValue(itemInfo);
|
|
671
690
|
});
|
|
672
|
-
const prevItemKeyRef = React3.useRef((_a3 =
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
setStateValue(computeValue(containerContext));
|
|
691
|
+
const prevItemKeyRef = React3.useRef((_a3 = itemInfo == null ? void 0 : itemInfo.itemKey) != null ? _a3 : null);
|
|
692
|
+
if (itemInfo && prevItemKeyRef.current !== itemInfo.itemKey) {
|
|
693
|
+
prevItemKeyRef.current = itemInfo.itemKey;
|
|
694
|
+
setStateValue(computeValue(itemInfo));
|
|
677
695
|
}
|
|
678
696
|
const triggerLayout = containerContext == null ? void 0 : containerContext.triggerLayout;
|
|
679
697
|
const setState = React3.useCallback(
|
|
@@ -692,12 +710,10 @@ function useRecyclingState(valueOrFun) {
|
|
|
692
710
|
}
|
|
693
711
|
function useIsLastItem() {
|
|
694
712
|
const containerContext = useContextContainer();
|
|
713
|
+
const itemKey = useContainerItemKey(containerContext);
|
|
695
714
|
const isLast = useSelector$("lastItemKeys", (lastItemKeys) => {
|
|
696
|
-
if (containerContext) {
|
|
697
|
-
|
|
698
|
-
if (!isNullOrUndefined(itemKey)) {
|
|
699
|
-
return (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false;
|
|
700
|
-
}
|
|
715
|
+
if (containerContext && !isNullOrUndefined(itemKey)) {
|
|
716
|
+
return (lastItemKeys == null ? void 0 : lastItemKeys.includes(itemKey)) || false;
|
|
701
717
|
}
|
|
702
718
|
return false;
|
|
703
719
|
});
|
|
@@ -711,12 +727,7 @@ var noop = () => {
|
|
|
711
727
|
};
|
|
712
728
|
function useSyncLayout() {
|
|
713
729
|
const containerContext = useContextContainer();
|
|
714
|
-
|
|
715
|
-
const { triggerLayout: syncLayout } = containerContext;
|
|
716
|
-
return syncLayout;
|
|
717
|
-
} else {
|
|
718
|
-
return noop;
|
|
719
|
-
}
|
|
730
|
+
return containerContext ? containerContext.triggerLayout : noop;
|
|
720
731
|
}
|
|
721
732
|
|
|
722
733
|
// src/components/Separator.tsx
|
|
@@ -1484,6 +1495,7 @@ function finishScrollTo(ctx) {
|
|
|
1484
1495
|
const scrollingTo = state.scrollingTo;
|
|
1485
1496
|
state.scrollHistory.length = 0;
|
|
1486
1497
|
state.scrollingTo = void 0;
|
|
1498
|
+
state.scrollTargetPinnedRange = void 0;
|
|
1487
1499
|
if (state.pendingTotalSize !== void 0) {
|
|
1488
1500
|
addTotalSize(ctx, null, state.pendingTotalSize);
|
|
1489
1501
|
}
|
|
@@ -1977,6 +1989,8 @@ function prepareMVCP(ctx, dataChanged) {
|
|
|
1977
1989
|
}
|
|
1978
1990
|
|
|
1979
1991
|
// src/utils/getScrollVelocity.ts
|
|
1992
|
+
var MAX_SCROLL_VELOCITY_WINDOW_MS = 1e3;
|
|
1993
|
+
var SCROLL_VELOCITY_HALF_LIFE_MS = 200;
|
|
1980
1994
|
var getScrollVelocity = (state) => {
|
|
1981
1995
|
const { scrollHistory } = state;
|
|
1982
1996
|
const newestIndex = scrollHistory.length - 1;
|
|
@@ -1984,35 +1998,37 @@ var getScrollVelocity = (state) => {
|
|
|
1984
1998
|
return 0;
|
|
1985
1999
|
}
|
|
1986
2000
|
const newest = scrollHistory[newestIndex];
|
|
1987
|
-
|
|
1988
|
-
let direction = 0;
|
|
1989
|
-
for (let i = newestIndex; i > 0; i--) {
|
|
1990
|
-
const delta = scrollHistory[i].scroll - scrollHistory[i - 1].scroll;
|
|
1991
|
-
if (delta !== 0) {
|
|
1992
|
-
direction = Math.sign(delta);
|
|
1993
|
-
break;
|
|
1994
|
-
}
|
|
1995
|
-
}
|
|
1996
|
-
if (direction === 0) {
|
|
2001
|
+
if (Date.now() - newest.time > MAX_SCROLL_VELOCITY_WINDOW_MS) {
|
|
1997
2002
|
return 0;
|
|
1998
2003
|
}
|
|
1999
|
-
let
|
|
2000
|
-
|
|
2004
|
+
let direction = 0;
|
|
2005
|
+
let weightedVelocity = 0;
|
|
2006
|
+
let totalWeight = 0;
|
|
2007
|
+
for (let i = newestIndex; i > 0; i--) {
|
|
2001
2008
|
const current = scrollHistory[i];
|
|
2002
|
-
const
|
|
2003
|
-
const
|
|
2004
|
-
const
|
|
2005
|
-
|
|
2006
|
-
|
|
2009
|
+
const previous = scrollHistory[i - 1];
|
|
2010
|
+
const scrollDiff = current.scroll - previous.scroll;
|
|
2011
|
+
const timeDiff = current.time - previous.time;
|
|
2012
|
+
const deltaSign = Math.sign(scrollDiff);
|
|
2013
|
+
if (deltaSign !== 0) {
|
|
2014
|
+
if (direction === 0) {
|
|
2015
|
+
direction = deltaSign;
|
|
2016
|
+
} else if (deltaSign !== direction) {
|
|
2017
|
+
break;
|
|
2018
|
+
}
|
|
2007
2019
|
}
|
|
2008
|
-
if (
|
|
2020
|
+
if (newest.time - previous.time > MAX_SCROLL_VELOCITY_WINDOW_MS) {
|
|
2009
2021
|
break;
|
|
2010
2022
|
}
|
|
2011
|
-
|
|
2023
|
+
if (scrollDiff === 0 || timeDiff <= 0) {
|
|
2024
|
+
continue;
|
|
2025
|
+
}
|
|
2026
|
+
const age = newest.time - current.time;
|
|
2027
|
+
const weight = Math.exp(-age / SCROLL_VELOCITY_HALF_LIFE_MS);
|
|
2028
|
+
weightedVelocity += scrollDiff / timeDiff * weight;
|
|
2029
|
+
totalWeight += weight;
|
|
2012
2030
|
}
|
|
2013
|
-
|
|
2014
|
-
const timeDiff = newest.time - oldest.time;
|
|
2015
|
-
return timeDiff > 0 ? scrollDiff / timeDiff : 0;
|
|
2031
|
+
return totalWeight > 0 ? weightedVelocity / totalWeight : 0;
|
|
2016
2032
|
};
|
|
2017
2033
|
|
|
2018
2034
|
// src/core/updateScroll.ts
|
|
@@ -2129,8 +2145,93 @@ function syncInitialScrollNativeWatchdog(state, options) {
|
|
|
2129
2145
|
initialScrollWatchdog.clear(state);
|
|
2130
2146
|
}
|
|
2131
2147
|
}
|
|
2132
|
-
function
|
|
2148
|
+
function findPositionIndexAtOrBeforeOffset(ctx, offset) {
|
|
2149
|
+
const state = ctx.state;
|
|
2150
|
+
const dataLength = state.props.data.length;
|
|
2151
|
+
let low = 0;
|
|
2152
|
+
let high = dataLength - 1;
|
|
2153
|
+
let match;
|
|
2154
|
+
while (low <= high) {
|
|
2155
|
+
const mid = Math.floor((low + high) / 2);
|
|
2156
|
+
const top = state.positions[mid];
|
|
2157
|
+
if (top === void 0) {
|
|
2158
|
+
high = mid - 1;
|
|
2159
|
+
} else {
|
|
2160
|
+
if (top <= offset) {
|
|
2161
|
+
match = mid;
|
|
2162
|
+
low = mid + 1;
|
|
2163
|
+
} else {
|
|
2164
|
+
high = mid - 1;
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
return match;
|
|
2169
|
+
}
|
|
2170
|
+
function getItemBottom(ctx, index) {
|
|
2133
2171
|
var _a3;
|
|
2172
|
+
const top = ctx.state.positions[index];
|
|
2173
|
+
if (top === void 0) {
|
|
2174
|
+
return void 0;
|
|
2175
|
+
}
|
|
2176
|
+
const itemSize = (_a3 = getItemSizeAtIndex(ctx, index)) != null ? _a3 : 0;
|
|
2177
|
+
return top + (Number.isFinite(itemSize) ? itemSize : 0);
|
|
2178
|
+
}
|
|
2179
|
+
function getTargetViewportRenderRange(ctx, targetOffset, targetIndex) {
|
|
2180
|
+
const state = ctx.state;
|
|
2181
|
+
const dataLength = state.props.data.length;
|
|
2182
|
+
if (dataLength === 0) {
|
|
2183
|
+
return void 0;
|
|
2184
|
+
}
|
|
2185
|
+
const viewportStart = Math.max(0, targetOffset);
|
|
2186
|
+
const viewportEnd = Math.max(viewportStart, targetOffset + state.scrollLength);
|
|
2187
|
+
let start = targetIndex !== void 0 ? Math.max(0, Math.min(dataLength - 1, targetIndex)) : findPositionIndexAtOrBeforeOffset(ctx, viewportStart);
|
|
2188
|
+
if (start === void 0) {
|
|
2189
|
+
return void 0;
|
|
2190
|
+
}
|
|
2191
|
+
if (targetIndex !== void 0 && state.positions[start] === void 0) {
|
|
2192
|
+
return { end: start, start };
|
|
2193
|
+
}
|
|
2194
|
+
if (targetIndex === void 0) {
|
|
2195
|
+
const startBottom = getItemBottom(ctx, start);
|
|
2196
|
+
if (startBottom === void 0 || startBottom <= viewportStart) {
|
|
2197
|
+
return void 0;
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
while (start > 0) {
|
|
2201
|
+
const top = state.positions[start];
|
|
2202
|
+
if (top === void 0 || top <= viewportStart || state.positions[start - 1] === void 0) {
|
|
2203
|
+
break;
|
|
2204
|
+
}
|
|
2205
|
+
start--;
|
|
2206
|
+
}
|
|
2207
|
+
while (start > 0) {
|
|
2208
|
+
const previousBottom = getItemBottom(ctx, start - 1);
|
|
2209
|
+
if (previousBottom === void 0 || previousBottom <= viewportStart) {
|
|
2210
|
+
break;
|
|
2211
|
+
}
|
|
2212
|
+
start--;
|
|
2213
|
+
}
|
|
2214
|
+
let end = start;
|
|
2215
|
+
while (end + 1 < dataLength) {
|
|
2216
|
+
const nextTop = state.positions[end + 1];
|
|
2217
|
+
if (nextTop === void 0 || nextTop > viewportEnd) {
|
|
2218
|
+
break;
|
|
2219
|
+
}
|
|
2220
|
+
end++;
|
|
2221
|
+
}
|
|
2222
|
+
return { end, start };
|
|
2223
|
+
}
|
|
2224
|
+
function pinScrollTargetRenderRange(ctx, targetOffset, targetIndex) {
|
|
2225
|
+
const range = getTargetViewportRenderRange(ctx, targetOffset, targetIndex);
|
|
2226
|
+
if (range) {
|
|
2227
|
+
ctx.state.scrollTargetPinnedRange = range;
|
|
2228
|
+
ctx.state.scrollForNextCalculateItemsInView = void 0;
|
|
2229
|
+
} else {
|
|
2230
|
+
ctx.state.scrollTargetPinnedRange = void 0;
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
function scrollTo(ctx, params) {
|
|
2234
|
+
var _a3, _b;
|
|
2134
2235
|
const state = ctx.state;
|
|
2135
2236
|
const { noScrollingTo, forceScroll, ...scrollTarget } = params;
|
|
2136
2237
|
const {
|
|
@@ -2165,11 +2266,20 @@ function scrollTo(ctx, params) {
|
|
|
2165
2266
|
targetOffset,
|
|
2166
2267
|
waitForInitialScrollCompletionFrame
|
|
2167
2268
|
};
|
|
2269
|
+
if (!isInitialScroll) {
|
|
2270
|
+
pinScrollTargetRenderRange(ctx, targetOffset, scrollTarget.index);
|
|
2271
|
+
}
|
|
2168
2272
|
}
|
|
2169
2273
|
state.scrollPending = targetOffset;
|
|
2170
2274
|
syncInitialScrollNativeWatchdog(state, { isInitialScroll, requestedOffset: offset, targetOffset });
|
|
2171
|
-
if (!
|
|
2172
|
-
|
|
2275
|
+
if (!isInitialScroll && !noScrollingTo && Math.abs(state.scroll - targetOffset) > 1) {
|
|
2276
|
+
if (animated) {
|
|
2277
|
+
if (state.scrollTargetPinnedRange) {
|
|
2278
|
+
(_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state);
|
|
2279
|
+
}
|
|
2280
|
+
} else {
|
|
2281
|
+
updateScroll(ctx, targetOffset, true, { markHasScrolled: false });
|
|
2282
|
+
}
|
|
2173
2283
|
}
|
|
2174
2284
|
if (forceScroll || !isInitialScroll || Platform.OS === "android") {
|
|
2175
2285
|
doScrollTo(ctx, { animated, horizontal, offset });
|
|
@@ -3257,22 +3367,28 @@ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
|
|
|
3257
3367
|
set$(ctx, `containerSpan${containerIndex}`, span);
|
|
3258
3368
|
}
|
|
3259
3369
|
}
|
|
3370
|
+
const prevItemInfo = peek$(ctx, `containerItemInfo${containerIndex}`);
|
|
3260
3371
|
const prevData = peek$(ctx, `containerItemData${containerIndex}`);
|
|
3372
|
+
let itemInfoValue = prevData;
|
|
3373
|
+
let didChangeItemInfo = (prevItemInfo == null ? void 0 : prevItemInfo.itemKey) !== itemKey || (prevItemInfo == null ? void 0 : prevItemInfo.index) !== itemIndex || (prevItemInfo == null ? void 0 : prevItemInfo.value) !== prevData;
|
|
3374
|
+
const updateData = () => {
|
|
3375
|
+
set$(ctx, `containerItemData${containerIndex}`, item);
|
|
3376
|
+
itemInfoValue = item;
|
|
3377
|
+
didChangeItemInfo = true;
|
|
3378
|
+
didRefreshData = true;
|
|
3379
|
+
};
|
|
3261
3380
|
if (prevData !== item) {
|
|
3262
3381
|
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;
|
|
3263
3382
|
const cachedComparison = (_g = pendingDataComparison == null ? void 0 : pendingDataComparison.byIndex[itemIndex]) != null ? _g : 0;
|
|
3264
3383
|
if (cachedComparison === 2) {
|
|
3265
|
-
|
|
3266
|
-
didRefreshData = true;
|
|
3384
|
+
updateData();
|
|
3267
3385
|
} else if (cachedComparison !== 1) {
|
|
3268
3386
|
const nextItemKey = (_h = peek$(ctx, `containerItemKey${containerIndex}`)) != null ? _h : itemKey;
|
|
3269
3387
|
const prevKey = keyExtractor == null ? void 0 : keyExtractor(prevData, itemIndex);
|
|
3270
3388
|
if (prevData === void 0 || !keyExtractor || prevKey !== nextItemKey) {
|
|
3271
|
-
|
|
3272
|
-
didRefreshData = true;
|
|
3389
|
+
updateData();
|
|
3273
3390
|
} else if (!itemsAreEqual) {
|
|
3274
|
-
|
|
3275
|
-
didRefreshData = true;
|
|
3391
|
+
updateData();
|
|
3276
3392
|
} else {
|
|
3277
3393
|
const isEqual = itemsAreEqual(prevData, item, itemIndex, data);
|
|
3278
3394
|
if (!state.pendingDataComparison || state.pendingDataComparison.previousData !== state.previousData || state.pendingDataComparison.nextData !== data) {
|
|
@@ -3288,12 +3404,18 @@ function syncMountedContainer(ctx, containerIndex, itemIndex, options) {
|
|
|
3288
3404
|
state.pendingDataComparison.byIndex[itemIndex] = isEqual ? 1 : 2;
|
|
3289
3405
|
}
|
|
3290
3406
|
if (!isEqual) {
|
|
3291
|
-
|
|
3292
|
-
didRefreshData = true;
|
|
3407
|
+
updateData();
|
|
3293
3408
|
}
|
|
3294
3409
|
}
|
|
3295
3410
|
}
|
|
3296
3411
|
}
|
|
3412
|
+
if (didChangeItemInfo) {
|
|
3413
|
+
set$(ctx, `containerItemInfo${containerIndex}`, {
|
|
3414
|
+
index: itemIndex,
|
|
3415
|
+
itemKey,
|
|
3416
|
+
value: itemInfoValue
|
|
3417
|
+
});
|
|
3418
|
+
}
|
|
3297
3419
|
return { didChangePosition, didRefreshData };
|
|
3298
3420
|
}
|
|
3299
3421
|
|
|
@@ -3986,6 +4108,32 @@ function setDidLayout(ctx) {
|
|
|
3986
4108
|
}
|
|
3987
4109
|
|
|
3988
4110
|
// src/core/calculateItemsInView.ts
|
|
4111
|
+
var RENDER_RANGE_PROJECTION_FULL_VELOCITY = 4;
|
|
4112
|
+
var RENDER_RANGE_PROJECTION_SETTLE_DELAY = 100;
|
|
4113
|
+
function getProjectedBufferAdjustment(scrollVelocity, trailingBuffer) {
|
|
4114
|
+
if (trailingBuffer <= 0) {
|
|
4115
|
+
return 0;
|
|
4116
|
+
}
|
|
4117
|
+
const velocityProgress = Math.min(1, Math.abs(scrollVelocity) / RENDER_RANGE_PROJECTION_FULL_VELOCITY);
|
|
4118
|
+
return Math.sign(scrollVelocity) * trailingBuffer * velocityProgress;
|
|
4119
|
+
}
|
|
4120
|
+
function scheduleRenderRangeProjectionSettle(ctx) {
|
|
4121
|
+
const state = ctx.state;
|
|
4122
|
+
const previousTimeout = state.timeoutRenderRangeProjectionSettle;
|
|
4123
|
+
if (previousTimeout !== void 0) {
|
|
4124
|
+
clearTimeout(previousTimeout);
|
|
4125
|
+
state.timeouts.delete(previousTimeout);
|
|
4126
|
+
}
|
|
4127
|
+
const timeout = setTimeout(() => {
|
|
4128
|
+
var _a3;
|
|
4129
|
+
state.timeoutRenderRangeProjectionSettle = void 0;
|
|
4130
|
+
state.timeouts.delete(timeout);
|
|
4131
|
+
state.scrollHistory.length = 0;
|
|
4132
|
+
(_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state);
|
|
4133
|
+
}, RENDER_RANGE_PROJECTION_SETTLE_DELAY);
|
|
4134
|
+
state.timeoutRenderRangeProjectionSettle = timeout;
|
|
4135
|
+
state.timeouts.add(timeout);
|
|
4136
|
+
}
|
|
3989
4137
|
function findCurrentStickyIndex(stickyArray, scroll, state) {
|
|
3990
4138
|
const positions = state.positions;
|
|
3991
4139
|
for (let i = stickyArray.length - 1; i >= 0; i--) {
|
|
@@ -4026,14 +4174,14 @@ function handleStickyActivation(ctx, stickyArray, currentStickyIdx, needNewConta
|
|
|
4026
4174
|
}
|
|
4027
4175
|
}
|
|
4028
4176
|
}
|
|
4029
|
-
function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentStickyIdx, pendingRemoval,
|
|
4177
|
+
function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentStickyIdx, pendingRemoval, isPinnedRenderIndex) {
|
|
4030
4178
|
var _a3, _b;
|
|
4031
4179
|
const state = ctx.state;
|
|
4032
4180
|
for (const containerIndex of state.stickyContainerPool) {
|
|
4033
4181
|
const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
|
|
4034
4182
|
const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
|
|
4035
4183
|
if (itemIndex === void 0) continue;
|
|
4036
|
-
if (
|
|
4184
|
+
if (isPinnedRenderIndex(itemIndex)) continue;
|
|
4037
4185
|
const arrayIdx = stickyArray.indexOf(itemIndex);
|
|
4038
4186
|
if (arrayIdx === -1) {
|
|
4039
4187
|
state.stickyContainerPool.delete(containerIndex);
|
|
@@ -4197,8 +4345,6 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4197
4345
|
const { data } = state.props;
|
|
4198
4346
|
const stickyHeaderIndicesArr = state.props.stickyHeaderIndicesArr || [];
|
|
4199
4347
|
const stickyHeaderIndicesSet = state.props.stickyHeaderIndicesSet || /* @__PURE__ */ new Set();
|
|
4200
|
-
const alwaysRenderArr = alwaysRenderIndicesArr || [];
|
|
4201
|
-
const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
|
|
4202
4348
|
const drawDistance = getEffectiveDrawDistance(ctx, params.drawDistanceMode);
|
|
4203
4349
|
const { dataChanged, doMVCP, forceFullItemPositions } = params;
|
|
4204
4350
|
const bootstrapInitialScrollState = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" ? state.initialScrollSession.bootstrap : void 0;
|
|
@@ -4265,14 +4411,19 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4265
4411
|
scrollBufferTop = drawDistance * 1.5;
|
|
4266
4412
|
scrollBufferBottom = drawDistance * 0.5;
|
|
4267
4413
|
}
|
|
4414
|
+
const shouldProjectRenderRange = !dataChanged && !forceFullItemPositions && !suppressInitialScrollSideEffects && !hasActiveInitialScroll(state) && !state.scrollingTo && !state.pendingNativeMVCPAdjust && !!peek$(ctx, "readyToRender");
|
|
4415
|
+
const projectedBufferAdjustment = shouldProjectRenderRange ? getProjectedBufferAdjustment(speed, Math.min(scrollBufferTop, scrollBufferBottom)) : 0;
|
|
4268
4416
|
const updateScrollRange = () => {
|
|
4269
4417
|
const scrollStart = Math.max(0, scroll);
|
|
4270
4418
|
const overscrollBeforeContent = Math.max(0, -nativeScrollState);
|
|
4271
|
-
scrollTopBuffered = scrollStart - scrollBufferTop;
|
|
4272
4419
|
scrollBottom = Math.max(scrollStart, scroll + scrollLength + overscrollBeforeContent);
|
|
4273
|
-
|
|
4420
|
+
scrollTopBuffered = scrollStart - scrollBufferTop + projectedBufferAdjustment;
|
|
4421
|
+
scrollBottomBuffered = scrollBottom + scrollBufferBottom + projectedBufferAdjustment;
|
|
4274
4422
|
};
|
|
4275
4423
|
updateScrollRange();
|
|
4424
|
+
if (projectedBufferAdjustment !== 0) {
|
|
4425
|
+
scheduleRenderRangeProjectionSettle(ctx);
|
|
4426
|
+
}
|
|
4276
4427
|
if (enableScrollForNextCalculateItemsInView && !suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
|
|
4277
4428
|
const { top, bottom } = scrollForNextCalculateItemsInView;
|
|
4278
4429
|
if (top === null && bottom === null) {
|
|
@@ -4430,9 +4581,34 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4430
4581
|
}
|
|
4431
4582
|
}
|
|
4432
4583
|
}
|
|
4584
|
+
const scrollTargetPinnedRange = state.scrollTargetPinnedRange;
|
|
4585
|
+
let scrollTargetPinnedStart = 0;
|
|
4586
|
+
let scrollTargetPinnedEnd = -1;
|
|
4587
|
+
if (scrollTargetPinnedRange) {
|
|
4588
|
+
scrollTargetPinnedStart = Math.max(0, Math.min(scrollTargetPinnedRange.start, scrollTargetPinnedRange.end));
|
|
4589
|
+
scrollTargetPinnedEnd = Math.min(
|
|
4590
|
+
dataLength - 1,
|
|
4591
|
+
Math.max(scrollTargetPinnedRange.start, scrollTargetPinnedRange.end)
|
|
4592
|
+
);
|
|
4593
|
+
}
|
|
4594
|
+
const hasScrollTargetPinnedRange = scrollTargetPinnedStart <= scrollTargetPinnedEnd;
|
|
4595
|
+
const isPinnedRenderIndex = (index) => alwaysRenderIndicesSet.has(index) || hasScrollTargetPinnedRange && index >= scrollTargetPinnedStart && index <= scrollTargetPinnedEnd;
|
|
4433
4596
|
if (startBuffered !== null && endBuffered !== null) {
|
|
4434
4597
|
const needNewContainers = [];
|
|
4435
4598
|
const needNewContainersSet = /* @__PURE__ */ new Set();
|
|
4599
|
+
const addPinnedIndex = (index) => {
|
|
4600
|
+
var _a4;
|
|
4601
|
+
if (index >= 0 && index < dataLength) {
|
|
4602
|
+
const id = (_a4 = idCache[index]) != null ? _a4 : getId(state, index);
|
|
4603
|
+
const containerIndex = containerItemKeys.get(id);
|
|
4604
|
+
if (containerIndex !== void 0) {
|
|
4605
|
+
state.stickyContainerPool.add(containerIndex);
|
|
4606
|
+
} else if (!isNullOrUndefined(id) && !needNewContainersSet.has(index)) {
|
|
4607
|
+
needNewContainersSet.add(index);
|
|
4608
|
+
needNewContainers.push(index);
|
|
4609
|
+
}
|
|
4610
|
+
}
|
|
4611
|
+
};
|
|
4436
4612
|
for (let i = startBuffered; i <= endBuffered; i++) {
|
|
4437
4613
|
const id = (_m = idCache[i]) != null ? _m : getId(state, i);
|
|
4438
4614
|
if (!containerItemKeys.has(id)) {
|
|
@@ -4440,21 +4616,19 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4440
4616
|
needNewContainers.push(i);
|
|
4441
4617
|
}
|
|
4442
4618
|
}
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
needNewContainers.push(index);
|
|
4450
|
-
}
|
|
4619
|
+
for (const index of alwaysRenderIndicesArr) {
|
|
4620
|
+
addPinnedIndex(index);
|
|
4621
|
+
}
|
|
4622
|
+
if (hasScrollTargetPinnedRange) {
|
|
4623
|
+
for (let index = scrollTargetPinnedStart; index <= scrollTargetPinnedEnd; index++) {
|
|
4624
|
+
addPinnedIndex(index);
|
|
4451
4625
|
}
|
|
4452
4626
|
}
|
|
4453
4627
|
if (stickyHeaderIndicesArr.length > 0) {
|
|
4454
4628
|
handleStickyActivation(
|
|
4455
4629
|
ctx,
|
|
4456
4630
|
stickyHeaderIndicesArr,
|
|
4457
|
-
(
|
|
4631
|
+
(_n = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _n : -1,
|
|
4458
4632
|
needNewContainers,
|
|
4459
4633
|
needNewContainersSet,
|
|
4460
4634
|
startBuffered,
|
|
@@ -4480,21 +4654,30 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4480
4654
|
for (const allocation of availableContainerAllocations) {
|
|
4481
4655
|
const i = allocation.itemIndex;
|
|
4482
4656
|
const containerIndex = allocation.containerIndex;
|
|
4483
|
-
const id = (
|
|
4657
|
+
const id = (_o = idCache[i]) != null ? _o : getId(state, i);
|
|
4484
4658
|
const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
|
|
4485
4659
|
if (oldKey && oldKey !== id) {
|
|
4486
4660
|
containerItemKeys.delete(oldKey);
|
|
4487
4661
|
}
|
|
4488
4662
|
set$(ctx, `containerItemKey${containerIndex}`, id);
|
|
4489
4663
|
set$(ctx, `containerItemData${containerIndex}`, data[i]);
|
|
4664
|
+
set$(ctx, `containerItemInfo${containerIndex}`, {
|
|
4665
|
+
index: i,
|
|
4666
|
+
itemKey: id,
|
|
4667
|
+
value: data[i]
|
|
4668
|
+
});
|
|
4490
4669
|
if (allocation.itemType !== void 0) {
|
|
4491
4670
|
state.containerItemTypes.set(containerIndex, allocation.itemType);
|
|
4492
4671
|
}
|
|
4493
4672
|
containerItemKeys.set(id, containerIndex);
|
|
4494
|
-
(
|
|
4673
|
+
(_p = state.userScrollAnchorReset) == null ? void 0 : _p.keys.add(id);
|
|
4674
|
+
{
|
|
4675
|
+
(_q = state.pendingLayoutEffectMeasurements) != null ? _q : state.pendingLayoutEffectMeasurements = /* @__PURE__ */ new Set();
|
|
4676
|
+
state.pendingLayoutEffectMeasurements.add(id);
|
|
4677
|
+
}
|
|
4495
4678
|
const containerSticky = `containerSticky${containerIndex}`;
|
|
4496
4679
|
const isSticky = stickyHeaderIndicesSet.has(i);
|
|
4497
|
-
const
|
|
4680
|
+
const isPinnedRender = isPinnedRenderIndex(i);
|
|
4498
4681
|
if (isSticky) {
|
|
4499
4682
|
set$(ctx, containerSticky, true);
|
|
4500
4683
|
state.stickyContainerPool.add(containerIndex);
|
|
@@ -4502,9 +4685,9 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4502
4685
|
if (peek$(ctx, containerSticky)) {
|
|
4503
4686
|
set$(ctx, containerSticky, false);
|
|
4504
4687
|
}
|
|
4505
|
-
if (
|
|
4688
|
+
if (isPinnedRender) {
|
|
4506
4689
|
state.stickyContainerPool.add(containerIndex);
|
|
4507
|
-
} else
|
|
4690
|
+
} else {
|
|
4508
4691
|
state.stickyContainerPool.delete(containerIndex);
|
|
4509
4692
|
}
|
|
4510
4693
|
}
|
|
@@ -4519,20 +4702,8 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4519
4702
|
}
|
|
4520
4703
|
}
|
|
4521
4704
|
}
|
|
4522
|
-
if (state.userScrollAnchorReset) {
|
|
4523
|
-
|
|
4524
|
-
state.userScrollAnchorReset = void 0;
|
|
4525
|
-
}
|
|
4526
|
-
}
|
|
4527
|
-
if (alwaysRenderArr.length > 0) {
|
|
4528
|
-
for (const index of alwaysRenderArr) {
|
|
4529
|
-
if (index < 0 || index >= dataLength) continue;
|
|
4530
|
-
const id = (_r = idCache[index]) != null ? _r : getId(state, index);
|
|
4531
|
-
const containerIndex = containerItemKeys.get(id);
|
|
4532
|
-
if (containerIndex !== void 0) {
|
|
4533
|
-
state.stickyContainerPool.add(containerIndex);
|
|
4534
|
-
}
|
|
4535
|
-
}
|
|
4705
|
+
if (((_r = state.userScrollAnchorReset) == null ? void 0 : _r.keys.size) === 0) {
|
|
4706
|
+
state.userScrollAnchorReset = void 0;
|
|
4536
4707
|
}
|
|
4537
4708
|
}
|
|
4538
4709
|
if (state.stickyContainerPool.size > 0) {
|
|
@@ -4543,7 +4714,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4543
4714
|
drawDistance,
|
|
4544
4715
|
(_s = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _s : -1,
|
|
4545
4716
|
pendingRemoval,
|
|
4546
|
-
|
|
4717
|
+
isPinnedRenderIndex
|
|
4547
4718
|
);
|
|
4548
4719
|
}
|
|
4549
4720
|
const pendingRemovalSet = pendingRemoval.length > 0 ? new Set(pendingRemoval) : void 0;
|
|
@@ -4561,6 +4732,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4561
4732
|
}
|
|
4562
4733
|
set$(ctx, `containerItemKey${i}`, void 0);
|
|
4563
4734
|
set$(ctx, `containerItemData${i}`, void 0);
|
|
4735
|
+
set$(ctx, `containerItemInfo${i}`, void 0);
|
|
4564
4736
|
set$(ctx, `containerPosition${i}`, POSITION_OUT_OF_VIEW);
|
|
4565
4737
|
set$(ctx, `containerColumn${i}`, -1);
|
|
4566
4738
|
set$(ctx, `containerSpan${i}`, 1);
|
|
@@ -4702,6 +4874,36 @@ function mergeItemSizeUpdateResult(result, next) {
|
|
|
4702
4874
|
result.needsRecalculate || (result.needsRecalculate = next.needsRecalculate);
|
|
4703
4875
|
result.shouldMaintainScrollAtEnd || (result.shouldMaintainScrollAtEnd = next.shouldMaintainScrollAtEnd);
|
|
4704
4876
|
}
|
|
4877
|
+
var batchedItemSizeRecalculates = /* @__PURE__ */ new WeakMap();
|
|
4878
|
+
function flushBatchedItemSizeRecalculate(ctx, didFallback = false, expectedResult) {
|
|
4879
|
+
const result = batchedItemSizeRecalculates.get(ctx);
|
|
4880
|
+
if (!result || expectedResult && result !== expectedResult) {
|
|
4881
|
+
return;
|
|
4882
|
+
}
|
|
4883
|
+
batchedItemSizeRecalculates.delete(ctx);
|
|
4884
|
+
if (didFallback) {
|
|
4885
|
+
ctx.state.pendingLayoutEffectMeasurements = void 0;
|
|
4886
|
+
}
|
|
4887
|
+
flushItemSizeUpdates(ctx, result);
|
|
4888
|
+
}
|
|
4889
|
+
function queueItemSizeRecalculate(ctx, result) {
|
|
4890
|
+
var _a3, _b;
|
|
4891
|
+
const batch = batchedItemSizeRecalculates.get(ctx);
|
|
4892
|
+
if (batch) {
|
|
4893
|
+
mergeItemSizeUpdateResult(batch, result);
|
|
4894
|
+
} else {
|
|
4895
|
+
const nextBatch = { ...result };
|
|
4896
|
+
batchedItemSizeRecalculates.set(ctx, nextBatch);
|
|
4897
|
+
if ((_a3 = ctx.state.pendingLayoutEffectMeasurements) == null ? void 0 : _a3.size) {
|
|
4898
|
+
requestAnimationFrame(() => {
|
|
4899
|
+
flushBatchedItemSizeRecalculate(ctx, true, nextBatch);
|
|
4900
|
+
});
|
|
4901
|
+
}
|
|
4902
|
+
}
|
|
4903
|
+
if (!((_b = ctx.state.pendingLayoutEffectMeasurements) == null ? void 0 : _b.size)) {
|
|
4904
|
+
flushBatchedItemSizeRecalculate(ctx);
|
|
4905
|
+
}
|
|
4906
|
+
}
|
|
4705
4907
|
function flushItemSizeUpdates(ctx, result) {
|
|
4706
4908
|
var _a3;
|
|
4707
4909
|
const state = ctx.state;
|
|
@@ -4718,12 +4920,22 @@ function flushItemSizeUpdates(ctx, result) {
|
|
|
4718
4920
|
function updateItemSizes(ctx, measurement) {
|
|
4719
4921
|
var _a3, _b, _c, _d;
|
|
4720
4922
|
const state = ctx.state;
|
|
4923
|
+
let didDrainLayoutEffectMeasurements = false;
|
|
4924
|
+
if (measurement.fromLayoutEffect) {
|
|
4925
|
+
const pendingLayoutEffectMeasurements = state.pendingLayoutEffectMeasurements;
|
|
4926
|
+
if ((pendingLayoutEffectMeasurements == null ? void 0 : pendingLayoutEffectMeasurements.delete(measurement.itemKey)) && pendingLayoutEffectMeasurements.size === 0) {
|
|
4927
|
+
state.pendingLayoutEffectMeasurements = void 0;
|
|
4928
|
+
didDrainLayoutEffectMeasurements = true;
|
|
4929
|
+
}
|
|
4930
|
+
}
|
|
4721
4931
|
const pendingKeys = (_a3 = state.userScrollAnchorReset) == null ? void 0 : _a3.keys;
|
|
4722
4932
|
const shouldBatchPendingMeasurements = measurement.fromLayoutEffect && !!(pendingKeys == null ? void 0 : pendingKeys.size);
|
|
4933
|
+
const shouldQueueRecalculate = !!measurement.fromLayoutEffect;
|
|
4934
|
+
let result;
|
|
4723
4935
|
if (!shouldBatchPendingMeasurements) {
|
|
4724
|
-
|
|
4936
|
+
result = applyItemSize(ctx, measurement.itemKey, measurement.size);
|
|
4725
4937
|
} else {
|
|
4726
|
-
|
|
4938
|
+
result = {};
|
|
4727
4939
|
const updateContainerItemSize = (itemKey, containerId, size) => {
|
|
4728
4940
|
if (containerId !== void 0 && peek$(ctx, `containerItemKey${containerId}`) === itemKey) {
|
|
4729
4941
|
mergeItemSizeUpdateResult(result, applyItemSize(ctx, itemKey, size));
|
|
@@ -4741,8 +4953,15 @@ function updateItemSizes(ctx, measurement) {
|
|
|
4741
4953
|
});
|
|
4742
4954
|
}
|
|
4743
4955
|
}
|
|
4956
|
+
}
|
|
4957
|
+
if (shouldQueueRecalculate && result.needsRecalculate) {
|
|
4958
|
+
queueItemSizeRecalculate(ctx, result);
|
|
4959
|
+
} else {
|
|
4744
4960
|
flushItemSizeUpdates(ctx, result);
|
|
4745
4961
|
}
|
|
4962
|
+
if (didDrainLayoutEffectMeasurements) {
|
|
4963
|
+
flushBatchedItemSizeRecalculate(ctx);
|
|
4964
|
+
}
|
|
4746
4965
|
}
|
|
4747
4966
|
function applyItemSize(ctx, itemKey, sizeObj) {
|
|
4748
4967
|
var _a3;
|
|
@@ -5134,12 +5353,9 @@ var Container = typedMemo(function Container2({
|
|
|
5134
5353
|
ctx.viewRefs.set(id, ref);
|
|
5135
5354
|
return {
|
|
5136
5355
|
containerId: id,
|
|
5137
|
-
|
|
5138
|
-
itemKey,
|
|
5139
|
-
triggerLayout,
|
|
5140
|
-
value: data
|
|
5356
|
+
triggerLayout
|
|
5141
5357
|
};
|
|
5142
|
-
}, [id,
|
|
5358
|
+
}, [id, triggerLayout]);
|
|
5143
5359
|
React3.useLayoutEffect(() => {
|
|
5144
5360
|
ctx.containerLayoutTriggers.set(id, triggerLayout);
|
|
5145
5361
|
return () => {
|