@legendapp/list 3.3.0 → 3.3.1
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 +7 -0
- package/package.json +1 -1
- package/react-native.js +252 -62
- package/react-native.mjs +252 -62
- package/react-native.web.js +252 -62
- package/react-native.web.mjs +252 -62
- package/react.js +252 -62
- package/react.mjs +252 -62
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## 3.3.1
|
|
2
|
+
|
|
3
|
+
- Perf: Animated `scrollToIndex` and `scrollToOffset` calls now mount the destination rows before native scrolling starts, so long programmatic jumps are less likely to show blank space at the target.
|
|
4
|
+
- Perf: Fast scrolling shifts more of the render buffer in the direction of travel and settles back after scrolling stops, so rows ahead of the user are ready sooner without keeping the buffer displaced afterward.
|
|
5
|
+
- Perf: Scroll velocity favors recent movement and ignores stale samples, preventing old scroll events from keeping the render buffer pointed in the wrong direction after scrolling slows or stops.
|
|
6
|
+
- Perf: On Fabric, row measurements wait for all expected layout-effect measurements before recalculating positions, reducing the number of computations while scrolling quickly.
|
|
7
|
+
|
|
1
8
|
## 3.3.0
|
|
2
9
|
|
|
3
10
|
- Feat: Add `dataKey` so apps can tell the list when the current array represents a different dataset, such as switching conversations or feeds without remounting `LegendList`.
|
package/package.json
CHANGED
package/react-native.js
CHANGED
|
@@ -1534,6 +1534,7 @@ function finishScrollTo(ctx) {
|
|
|
1534
1534
|
const scrollingTo = state.scrollingTo;
|
|
1535
1535
|
state.scrollHistory.length = 0;
|
|
1536
1536
|
state.scrollingTo = void 0;
|
|
1537
|
+
state.scrollTargetPinnedRange = void 0;
|
|
1537
1538
|
if (state.pendingTotalSize !== void 0) {
|
|
1538
1539
|
addTotalSize(ctx, null, state.pendingTotalSize);
|
|
1539
1540
|
}
|
|
@@ -2173,6 +2174,8 @@ var flushSync = (fn) => {
|
|
|
2173
2174
|
};
|
|
2174
2175
|
|
|
2175
2176
|
// src/utils/getScrollVelocity.ts
|
|
2177
|
+
var MAX_SCROLL_VELOCITY_WINDOW_MS = 1e3;
|
|
2178
|
+
var SCROLL_VELOCITY_HALF_LIFE_MS = 200;
|
|
2176
2179
|
var getScrollVelocity = (state) => {
|
|
2177
2180
|
const { scrollHistory } = state;
|
|
2178
2181
|
const newestIndex = scrollHistory.length - 1;
|
|
@@ -2180,35 +2183,37 @@ var getScrollVelocity = (state) => {
|
|
|
2180
2183
|
return 0;
|
|
2181
2184
|
}
|
|
2182
2185
|
const newest = scrollHistory[newestIndex];
|
|
2183
|
-
|
|
2184
|
-
let direction = 0;
|
|
2185
|
-
for (let i = newestIndex; i > 0; i--) {
|
|
2186
|
-
const delta = scrollHistory[i].scroll - scrollHistory[i - 1].scroll;
|
|
2187
|
-
if (delta !== 0) {
|
|
2188
|
-
direction = Math.sign(delta);
|
|
2189
|
-
break;
|
|
2190
|
-
}
|
|
2191
|
-
}
|
|
2192
|
-
if (direction === 0) {
|
|
2186
|
+
if (Date.now() - newest.time > MAX_SCROLL_VELOCITY_WINDOW_MS) {
|
|
2193
2187
|
return 0;
|
|
2194
2188
|
}
|
|
2195
|
-
let
|
|
2196
|
-
|
|
2189
|
+
let direction = 0;
|
|
2190
|
+
let weightedVelocity = 0;
|
|
2191
|
+
let totalWeight = 0;
|
|
2192
|
+
for (let i = newestIndex; i > 0; i--) {
|
|
2197
2193
|
const current = scrollHistory[i];
|
|
2198
|
-
const
|
|
2199
|
-
const
|
|
2200
|
-
const
|
|
2201
|
-
|
|
2202
|
-
|
|
2194
|
+
const previous = scrollHistory[i - 1];
|
|
2195
|
+
const scrollDiff = current.scroll - previous.scroll;
|
|
2196
|
+
const timeDiff = current.time - previous.time;
|
|
2197
|
+
const deltaSign = Math.sign(scrollDiff);
|
|
2198
|
+
if (deltaSign !== 0) {
|
|
2199
|
+
if (direction === 0) {
|
|
2200
|
+
direction = deltaSign;
|
|
2201
|
+
} else if (deltaSign !== direction) {
|
|
2202
|
+
break;
|
|
2203
|
+
}
|
|
2203
2204
|
}
|
|
2204
|
-
if (
|
|
2205
|
+
if (newest.time - previous.time > MAX_SCROLL_VELOCITY_WINDOW_MS) {
|
|
2205
2206
|
break;
|
|
2206
2207
|
}
|
|
2207
|
-
|
|
2208
|
+
if (scrollDiff === 0 || timeDiff <= 0) {
|
|
2209
|
+
continue;
|
|
2210
|
+
}
|
|
2211
|
+
const age = newest.time - current.time;
|
|
2212
|
+
const weight = Math.exp(-age / SCROLL_VELOCITY_HALF_LIFE_MS);
|
|
2213
|
+
weightedVelocity += scrollDiff / timeDiff * weight;
|
|
2214
|
+
totalWeight += weight;
|
|
2208
2215
|
}
|
|
2209
|
-
|
|
2210
|
-
const timeDiff = newest.time - oldest.time;
|
|
2211
|
-
return timeDiff > 0 ? scrollDiff / timeDiff : 0;
|
|
2216
|
+
return totalWeight > 0 ? weightedVelocity / totalWeight : 0;
|
|
2212
2217
|
};
|
|
2213
2218
|
|
|
2214
2219
|
// src/core/updateScroll.ts
|
|
@@ -2325,8 +2330,93 @@ function syncInitialScrollNativeWatchdog(state, options) {
|
|
|
2325
2330
|
initialScrollWatchdog.clear(state);
|
|
2326
2331
|
}
|
|
2327
2332
|
}
|
|
2328
|
-
function
|
|
2333
|
+
function findPositionIndexAtOrBeforeOffset(ctx, offset) {
|
|
2334
|
+
const state = ctx.state;
|
|
2335
|
+
const dataLength = state.props.data.length;
|
|
2336
|
+
let low = 0;
|
|
2337
|
+
let high = dataLength - 1;
|
|
2338
|
+
let match;
|
|
2339
|
+
while (low <= high) {
|
|
2340
|
+
const mid = Math.floor((low + high) / 2);
|
|
2341
|
+
const top = state.positions[mid];
|
|
2342
|
+
if (top === void 0) {
|
|
2343
|
+
high = mid - 1;
|
|
2344
|
+
} else {
|
|
2345
|
+
if (top <= offset) {
|
|
2346
|
+
match = mid;
|
|
2347
|
+
low = mid + 1;
|
|
2348
|
+
} else {
|
|
2349
|
+
high = mid - 1;
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
return match;
|
|
2354
|
+
}
|
|
2355
|
+
function getItemBottom(ctx, index) {
|
|
2329
2356
|
var _a3;
|
|
2357
|
+
const top = ctx.state.positions[index];
|
|
2358
|
+
if (top === void 0) {
|
|
2359
|
+
return void 0;
|
|
2360
|
+
}
|
|
2361
|
+
const itemSize = (_a3 = getItemSizeAtIndex(ctx, index)) != null ? _a3 : 0;
|
|
2362
|
+
return top + (Number.isFinite(itemSize) ? itemSize : 0);
|
|
2363
|
+
}
|
|
2364
|
+
function getTargetViewportRenderRange(ctx, targetOffset, targetIndex) {
|
|
2365
|
+
const state = ctx.state;
|
|
2366
|
+
const dataLength = state.props.data.length;
|
|
2367
|
+
if (dataLength === 0) {
|
|
2368
|
+
return void 0;
|
|
2369
|
+
}
|
|
2370
|
+
const viewportStart = Math.max(0, targetOffset);
|
|
2371
|
+
const viewportEnd = Math.max(viewportStart, targetOffset + state.scrollLength);
|
|
2372
|
+
let start = targetIndex !== void 0 ? Math.max(0, Math.min(dataLength - 1, targetIndex)) : findPositionIndexAtOrBeforeOffset(ctx, viewportStart);
|
|
2373
|
+
if (start === void 0) {
|
|
2374
|
+
return void 0;
|
|
2375
|
+
}
|
|
2376
|
+
if (targetIndex !== void 0 && state.positions[start] === void 0) {
|
|
2377
|
+
return { end: start, start };
|
|
2378
|
+
}
|
|
2379
|
+
if (targetIndex === void 0) {
|
|
2380
|
+
const startBottom = getItemBottom(ctx, start);
|
|
2381
|
+
if (startBottom === void 0 || startBottom <= viewportStart) {
|
|
2382
|
+
return void 0;
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
while (start > 0) {
|
|
2386
|
+
const top = state.positions[start];
|
|
2387
|
+
if (top === void 0 || top <= viewportStart || state.positions[start - 1] === void 0) {
|
|
2388
|
+
break;
|
|
2389
|
+
}
|
|
2390
|
+
start--;
|
|
2391
|
+
}
|
|
2392
|
+
while (start > 0) {
|
|
2393
|
+
const previousBottom = getItemBottom(ctx, start - 1);
|
|
2394
|
+
if (previousBottom === void 0 || previousBottom <= viewportStart) {
|
|
2395
|
+
break;
|
|
2396
|
+
}
|
|
2397
|
+
start--;
|
|
2398
|
+
}
|
|
2399
|
+
let end = start;
|
|
2400
|
+
while (end + 1 < dataLength) {
|
|
2401
|
+
const nextTop = state.positions[end + 1];
|
|
2402
|
+
if (nextTop === void 0 || nextTop > viewportEnd) {
|
|
2403
|
+
break;
|
|
2404
|
+
}
|
|
2405
|
+
end++;
|
|
2406
|
+
}
|
|
2407
|
+
return { end, start };
|
|
2408
|
+
}
|
|
2409
|
+
function pinScrollTargetRenderRange(ctx, targetOffset, targetIndex) {
|
|
2410
|
+
const range = getTargetViewportRenderRange(ctx, targetOffset, targetIndex);
|
|
2411
|
+
if (range) {
|
|
2412
|
+
ctx.state.scrollTargetPinnedRange = range;
|
|
2413
|
+
ctx.state.scrollForNextCalculateItemsInView = void 0;
|
|
2414
|
+
} else {
|
|
2415
|
+
ctx.state.scrollTargetPinnedRange = void 0;
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
function scrollTo(ctx, params) {
|
|
2419
|
+
var _a3, _b;
|
|
2330
2420
|
const state = ctx.state;
|
|
2331
2421
|
const { noScrollingTo, forceScroll, ...scrollTarget } = params;
|
|
2332
2422
|
const {
|
|
@@ -2361,11 +2451,20 @@ function scrollTo(ctx, params) {
|
|
|
2361
2451
|
targetOffset,
|
|
2362
2452
|
waitForInitialScrollCompletionFrame
|
|
2363
2453
|
};
|
|
2454
|
+
if (!isInitialScroll) {
|
|
2455
|
+
pinScrollTargetRenderRange(ctx, targetOffset, scrollTarget.index);
|
|
2456
|
+
}
|
|
2364
2457
|
}
|
|
2365
2458
|
state.scrollPending = targetOffset;
|
|
2366
2459
|
syncInitialScrollNativeWatchdog(state, { isInitialScroll, requestedOffset: offset, targetOffset });
|
|
2367
|
-
if (!
|
|
2368
|
-
|
|
2460
|
+
if (!isInitialScroll && !noScrollingTo && Math.abs(state.scroll - targetOffset) > 1) {
|
|
2461
|
+
if (animated) {
|
|
2462
|
+
if (state.scrollTargetPinnedRange) {
|
|
2463
|
+
(_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state);
|
|
2464
|
+
}
|
|
2465
|
+
} else {
|
|
2466
|
+
updateScroll(ctx, targetOffset, true, { markHasScrolled: false });
|
|
2467
|
+
}
|
|
2369
2468
|
}
|
|
2370
2469
|
if (forceScroll || !isInitialScroll || Platform.OS === "android") {
|
|
2371
2470
|
doScrollTo(ctx, { animated, horizontal, isInitialScroll, offset });
|
|
@@ -4037,6 +4136,32 @@ function setDidLayout(ctx) {
|
|
|
4037
4136
|
}
|
|
4038
4137
|
|
|
4039
4138
|
// src/core/calculateItemsInView.ts
|
|
4139
|
+
var RENDER_RANGE_PROJECTION_FULL_VELOCITY = 4;
|
|
4140
|
+
var RENDER_RANGE_PROJECTION_SETTLE_DELAY = 100;
|
|
4141
|
+
function getProjectedBufferAdjustment(scrollVelocity, trailingBuffer) {
|
|
4142
|
+
if (trailingBuffer <= 0) {
|
|
4143
|
+
return 0;
|
|
4144
|
+
}
|
|
4145
|
+
const velocityProgress = Math.min(1, Math.abs(scrollVelocity) / RENDER_RANGE_PROJECTION_FULL_VELOCITY);
|
|
4146
|
+
return Math.sign(scrollVelocity) * trailingBuffer * velocityProgress;
|
|
4147
|
+
}
|
|
4148
|
+
function scheduleRenderRangeProjectionSettle(ctx) {
|
|
4149
|
+
const state = ctx.state;
|
|
4150
|
+
const previousTimeout = state.timeoutRenderRangeProjectionSettle;
|
|
4151
|
+
if (previousTimeout !== void 0) {
|
|
4152
|
+
clearTimeout(previousTimeout);
|
|
4153
|
+
state.timeouts.delete(previousTimeout);
|
|
4154
|
+
}
|
|
4155
|
+
const timeout = setTimeout(() => {
|
|
4156
|
+
var _a3;
|
|
4157
|
+
state.timeoutRenderRangeProjectionSettle = void 0;
|
|
4158
|
+
state.timeouts.delete(timeout);
|
|
4159
|
+
state.scrollHistory.length = 0;
|
|
4160
|
+
(_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state);
|
|
4161
|
+
}, RENDER_RANGE_PROJECTION_SETTLE_DELAY);
|
|
4162
|
+
state.timeoutRenderRangeProjectionSettle = timeout;
|
|
4163
|
+
state.timeouts.add(timeout);
|
|
4164
|
+
}
|
|
4040
4165
|
function findCurrentStickyIndex(stickyArray, scroll, state) {
|
|
4041
4166
|
const positions = state.positions;
|
|
4042
4167
|
for (let i = stickyArray.length - 1; i >= 0; i--) {
|
|
@@ -4077,14 +4202,14 @@ function handleStickyActivation(ctx, stickyArray, currentStickyIdx, needNewConta
|
|
|
4077
4202
|
}
|
|
4078
4203
|
}
|
|
4079
4204
|
}
|
|
4080
|
-
function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentStickyIdx, pendingRemoval,
|
|
4205
|
+
function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentStickyIdx, pendingRemoval, isPinnedRenderIndex) {
|
|
4081
4206
|
var _a3, _b;
|
|
4082
4207
|
const state = ctx.state;
|
|
4083
4208
|
for (const containerIndex of state.stickyContainerPool) {
|
|
4084
4209
|
const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
|
|
4085
4210
|
const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
|
|
4086
4211
|
if (itemIndex === void 0) continue;
|
|
4087
|
-
if (
|
|
4212
|
+
if (isPinnedRenderIndex(itemIndex)) continue;
|
|
4088
4213
|
const arrayIdx = stickyArray.indexOf(itemIndex);
|
|
4089
4214
|
if (arrayIdx === -1) {
|
|
4090
4215
|
state.stickyContainerPool.delete(containerIndex);
|
|
@@ -4248,8 +4373,6 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4248
4373
|
const { data } = state.props;
|
|
4249
4374
|
const stickyHeaderIndicesArr = state.props.stickyHeaderIndicesArr || [];
|
|
4250
4375
|
const stickyHeaderIndicesSet = state.props.stickyHeaderIndicesSet || /* @__PURE__ */ new Set();
|
|
4251
|
-
const alwaysRenderArr = alwaysRenderIndicesArr || [];
|
|
4252
|
-
const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
|
|
4253
4376
|
const drawDistance = getEffectiveDrawDistance(ctx, params.drawDistanceMode);
|
|
4254
4377
|
const { dataChanged, doMVCP, forceFullItemPositions } = params;
|
|
4255
4378
|
const bootstrapInitialScrollState = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" ? state.initialScrollSession.bootstrap : void 0;
|
|
@@ -4316,14 +4439,19 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4316
4439
|
scrollBufferTop = drawDistance * 1.5;
|
|
4317
4440
|
scrollBufferBottom = drawDistance * 0.5;
|
|
4318
4441
|
}
|
|
4442
|
+
const shouldProjectRenderRange = !dataChanged && !forceFullItemPositions && !suppressInitialScrollSideEffects && !hasActiveInitialScroll(state) && !state.scrollingTo && !state.pendingNativeMVCPAdjust && !!peek$(ctx, "readyToRender");
|
|
4443
|
+
const projectedBufferAdjustment = shouldProjectRenderRange ? getProjectedBufferAdjustment(speed, Math.min(scrollBufferTop, scrollBufferBottom)) : 0;
|
|
4319
4444
|
const updateScrollRange = () => {
|
|
4320
4445
|
const scrollStart = Math.max(0, scroll);
|
|
4321
4446
|
const overscrollBeforeContent = Math.max(0, -nativeScrollState);
|
|
4322
|
-
scrollTopBuffered = scrollStart - scrollBufferTop;
|
|
4323
4447
|
scrollBottom = Math.max(scrollStart, scroll + scrollLength + overscrollBeforeContent);
|
|
4324
|
-
|
|
4448
|
+
scrollTopBuffered = scrollStart - scrollBufferTop + projectedBufferAdjustment;
|
|
4449
|
+
scrollBottomBuffered = scrollBottom + scrollBufferBottom + projectedBufferAdjustment;
|
|
4325
4450
|
};
|
|
4326
4451
|
updateScrollRange();
|
|
4452
|
+
if (projectedBufferAdjustment !== 0) {
|
|
4453
|
+
scheduleRenderRangeProjectionSettle(ctx);
|
|
4454
|
+
}
|
|
4327
4455
|
if (enableScrollForNextCalculateItemsInView && !suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
|
|
4328
4456
|
const { top, bottom } = scrollForNextCalculateItemsInView;
|
|
4329
4457
|
if (top === null && bottom === null) {
|
|
@@ -4481,9 +4609,34 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4481
4609
|
}
|
|
4482
4610
|
}
|
|
4483
4611
|
}
|
|
4612
|
+
const scrollTargetPinnedRange = state.scrollTargetPinnedRange;
|
|
4613
|
+
let scrollTargetPinnedStart = 0;
|
|
4614
|
+
let scrollTargetPinnedEnd = -1;
|
|
4615
|
+
if (scrollTargetPinnedRange) {
|
|
4616
|
+
scrollTargetPinnedStart = Math.max(0, Math.min(scrollTargetPinnedRange.start, scrollTargetPinnedRange.end));
|
|
4617
|
+
scrollTargetPinnedEnd = Math.min(
|
|
4618
|
+
dataLength - 1,
|
|
4619
|
+
Math.max(scrollTargetPinnedRange.start, scrollTargetPinnedRange.end)
|
|
4620
|
+
);
|
|
4621
|
+
}
|
|
4622
|
+
const hasScrollTargetPinnedRange = scrollTargetPinnedStart <= scrollTargetPinnedEnd;
|
|
4623
|
+
const isPinnedRenderIndex = (index) => alwaysRenderIndicesSet.has(index) || hasScrollTargetPinnedRange && index >= scrollTargetPinnedStart && index <= scrollTargetPinnedEnd;
|
|
4484
4624
|
if (startBuffered !== null && endBuffered !== null) {
|
|
4485
4625
|
const needNewContainers = [];
|
|
4486
4626
|
const needNewContainersSet = /* @__PURE__ */ new Set();
|
|
4627
|
+
const addPinnedIndex = (index) => {
|
|
4628
|
+
var _a4;
|
|
4629
|
+
if (index >= 0 && index < dataLength) {
|
|
4630
|
+
const id = (_a4 = idCache[index]) != null ? _a4 : getId(state, index);
|
|
4631
|
+
const containerIndex = containerItemKeys.get(id);
|
|
4632
|
+
if (containerIndex !== void 0) {
|
|
4633
|
+
state.stickyContainerPool.add(containerIndex);
|
|
4634
|
+
} else if (!isNullOrUndefined(id) && !needNewContainersSet.has(index)) {
|
|
4635
|
+
needNewContainersSet.add(index);
|
|
4636
|
+
needNewContainers.push(index);
|
|
4637
|
+
}
|
|
4638
|
+
}
|
|
4639
|
+
};
|
|
4487
4640
|
for (let i = startBuffered; i <= endBuffered; i++) {
|
|
4488
4641
|
const id = (_m = idCache[i]) != null ? _m : getId(state, i);
|
|
4489
4642
|
if (!containerItemKeys.has(id)) {
|
|
@@ -4491,21 +4644,19 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4491
4644
|
needNewContainers.push(i);
|
|
4492
4645
|
}
|
|
4493
4646
|
}
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
needNewContainers.push(index);
|
|
4501
|
-
}
|
|
4647
|
+
for (const index of alwaysRenderIndicesArr) {
|
|
4648
|
+
addPinnedIndex(index);
|
|
4649
|
+
}
|
|
4650
|
+
if (hasScrollTargetPinnedRange) {
|
|
4651
|
+
for (let index = scrollTargetPinnedStart; index <= scrollTargetPinnedEnd; index++) {
|
|
4652
|
+
addPinnedIndex(index);
|
|
4502
4653
|
}
|
|
4503
4654
|
}
|
|
4504
4655
|
if (stickyHeaderIndicesArr.length > 0) {
|
|
4505
4656
|
handleStickyActivation(
|
|
4506
4657
|
ctx,
|
|
4507
4658
|
stickyHeaderIndicesArr,
|
|
4508
|
-
(
|
|
4659
|
+
(_n = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _n : -1,
|
|
4509
4660
|
needNewContainers,
|
|
4510
4661
|
needNewContainersSet,
|
|
4511
4662
|
startBuffered,
|
|
@@ -4531,7 +4682,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4531
4682
|
for (const allocation of availableContainerAllocations) {
|
|
4532
4683
|
const i = allocation.itemIndex;
|
|
4533
4684
|
const containerIndex = allocation.containerIndex;
|
|
4534
|
-
const id = (
|
|
4685
|
+
const id = (_o = idCache[i]) != null ? _o : getId(state, i);
|
|
4535
4686
|
const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
|
|
4536
4687
|
if (oldKey && oldKey !== id) {
|
|
4537
4688
|
containerItemKeys.delete(oldKey);
|
|
@@ -4542,10 +4693,14 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4542
4693
|
state.containerItemTypes.set(containerIndex, allocation.itemType);
|
|
4543
4694
|
}
|
|
4544
4695
|
containerItemKeys.set(id, containerIndex);
|
|
4545
|
-
(
|
|
4696
|
+
(_p = state.userScrollAnchorReset) == null ? void 0 : _p.keys.add(id);
|
|
4697
|
+
if (IsNewArchitecture) {
|
|
4698
|
+
(_q = state.pendingLayoutEffectMeasurements) != null ? _q : state.pendingLayoutEffectMeasurements = /* @__PURE__ */ new Set();
|
|
4699
|
+
state.pendingLayoutEffectMeasurements.add(id);
|
|
4700
|
+
}
|
|
4546
4701
|
const containerSticky = `containerSticky${containerIndex}`;
|
|
4547
4702
|
const isSticky = stickyHeaderIndicesSet.has(i);
|
|
4548
|
-
const
|
|
4703
|
+
const isPinnedRender = isPinnedRenderIndex(i);
|
|
4549
4704
|
if (isSticky) {
|
|
4550
4705
|
set$(ctx, containerSticky, true);
|
|
4551
4706
|
state.stickyContainerPool.add(containerIndex);
|
|
@@ -4553,9 +4708,9 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4553
4708
|
if (peek$(ctx, containerSticky)) {
|
|
4554
4709
|
set$(ctx, containerSticky, false);
|
|
4555
4710
|
}
|
|
4556
|
-
if (
|
|
4711
|
+
if (isPinnedRender) {
|
|
4557
4712
|
state.stickyContainerPool.add(containerIndex);
|
|
4558
|
-
} else
|
|
4713
|
+
} else {
|
|
4559
4714
|
state.stickyContainerPool.delete(containerIndex);
|
|
4560
4715
|
}
|
|
4561
4716
|
}
|
|
@@ -4570,20 +4725,8 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4570
4725
|
}
|
|
4571
4726
|
}
|
|
4572
4727
|
}
|
|
4573
|
-
if (state.userScrollAnchorReset) {
|
|
4574
|
-
|
|
4575
|
-
state.userScrollAnchorReset = void 0;
|
|
4576
|
-
}
|
|
4577
|
-
}
|
|
4578
|
-
if (alwaysRenderArr.length > 0) {
|
|
4579
|
-
for (const index of alwaysRenderArr) {
|
|
4580
|
-
if (index < 0 || index >= dataLength) continue;
|
|
4581
|
-
const id = (_r = idCache[index]) != null ? _r : getId(state, index);
|
|
4582
|
-
const containerIndex = containerItemKeys.get(id);
|
|
4583
|
-
if (containerIndex !== void 0) {
|
|
4584
|
-
state.stickyContainerPool.add(containerIndex);
|
|
4585
|
-
}
|
|
4586
|
-
}
|
|
4728
|
+
if (((_r = state.userScrollAnchorReset) == null ? void 0 : _r.keys.size) === 0) {
|
|
4729
|
+
state.userScrollAnchorReset = void 0;
|
|
4587
4730
|
}
|
|
4588
4731
|
}
|
|
4589
4732
|
if (state.stickyContainerPool.size > 0) {
|
|
@@ -4594,7 +4737,7 @@ function calculateItemsInView(ctx, params = {}) {
|
|
|
4594
4737
|
drawDistance,
|
|
4595
4738
|
(_s = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _s : -1,
|
|
4596
4739
|
pendingRemoval,
|
|
4597
|
-
|
|
4740
|
+
isPinnedRenderIndex
|
|
4598
4741
|
);
|
|
4599
4742
|
}
|
|
4600
4743
|
const pendingRemovalSet = pendingRemoval.length > 0 ? new Set(pendingRemoval) : void 0;
|
|
@@ -4766,6 +4909,36 @@ function mergeItemSizeUpdateResult(result, next) {
|
|
|
4766
4909
|
result.needsRecalculate || (result.needsRecalculate = next.needsRecalculate);
|
|
4767
4910
|
result.shouldMaintainScrollAtEnd || (result.shouldMaintainScrollAtEnd = next.shouldMaintainScrollAtEnd);
|
|
4768
4911
|
}
|
|
4912
|
+
var batchedItemSizeRecalculates = /* @__PURE__ */ new WeakMap();
|
|
4913
|
+
function flushBatchedItemSizeRecalculate(ctx, didFallback = false, expectedResult) {
|
|
4914
|
+
const result = batchedItemSizeRecalculates.get(ctx);
|
|
4915
|
+
if (!result || expectedResult && result !== expectedResult) {
|
|
4916
|
+
return;
|
|
4917
|
+
}
|
|
4918
|
+
batchedItemSizeRecalculates.delete(ctx);
|
|
4919
|
+
if (didFallback) {
|
|
4920
|
+
ctx.state.pendingLayoutEffectMeasurements = void 0;
|
|
4921
|
+
}
|
|
4922
|
+
flushItemSizeUpdates(ctx, result);
|
|
4923
|
+
}
|
|
4924
|
+
function queueItemSizeRecalculate(ctx, result) {
|
|
4925
|
+
var _a3, _b;
|
|
4926
|
+
const batch = batchedItemSizeRecalculates.get(ctx);
|
|
4927
|
+
if (batch) {
|
|
4928
|
+
mergeItemSizeUpdateResult(batch, result);
|
|
4929
|
+
} else {
|
|
4930
|
+
const nextBatch = { ...result };
|
|
4931
|
+
batchedItemSizeRecalculates.set(ctx, nextBatch);
|
|
4932
|
+
if ((_a3 = ctx.state.pendingLayoutEffectMeasurements) == null ? void 0 : _a3.size) {
|
|
4933
|
+
requestAnimationFrame(() => {
|
|
4934
|
+
flushBatchedItemSizeRecalculate(ctx, true, nextBatch);
|
|
4935
|
+
});
|
|
4936
|
+
}
|
|
4937
|
+
}
|
|
4938
|
+
if (!((_b = ctx.state.pendingLayoutEffectMeasurements) == null ? void 0 : _b.size)) {
|
|
4939
|
+
flushBatchedItemSizeRecalculate(ctx);
|
|
4940
|
+
}
|
|
4941
|
+
}
|
|
4769
4942
|
function flushItemSizeUpdates(ctx, result) {
|
|
4770
4943
|
var _a3;
|
|
4771
4944
|
const state = ctx.state;
|
|
@@ -4782,12 +4955,22 @@ function flushItemSizeUpdates(ctx, result) {
|
|
|
4782
4955
|
function updateItemSizes(ctx, measurement) {
|
|
4783
4956
|
var _a3, _b, _c, _d;
|
|
4784
4957
|
const state = ctx.state;
|
|
4958
|
+
let didDrainLayoutEffectMeasurements = false;
|
|
4959
|
+
if (IsNewArchitecture && measurement.fromLayoutEffect) {
|
|
4960
|
+
const pendingLayoutEffectMeasurements = state.pendingLayoutEffectMeasurements;
|
|
4961
|
+
if ((pendingLayoutEffectMeasurements == null ? void 0 : pendingLayoutEffectMeasurements.delete(measurement.itemKey)) && pendingLayoutEffectMeasurements.size === 0) {
|
|
4962
|
+
state.pendingLayoutEffectMeasurements = void 0;
|
|
4963
|
+
didDrainLayoutEffectMeasurements = true;
|
|
4964
|
+
}
|
|
4965
|
+
}
|
|
4785
4966
|
const pendingKeys = (_a3 = state.userScrollAnchorReset) == null ? void 0 : _a3.keys;
|
|
4786
4967
|
const shouldBatchPendingMeasurements = IsNewArchitecture && measurement.fromLayoutEffect && !!(pendingKeys == null ? void 0 : pendingKeys.size);
|
|
4968
|
+
const shouldQueueRecalculate = IsNewArchitecture && !!measurement.fromLayoutEffect;
|
|
4969
|
+
let result;
|
|
4787
4970
|
if (!shouldBatchPendingMeasurements) {
|
|
4788
|
-
|
|
4971
|
+
result = applyItemSize(ctx, measurement.itemKey, measurement.size);
|
|
4789
4972
|
} else {
|
|
4790
|
-
|
|
4973
|
+
result = {};
|
|
4791
4974
|
const updateContainerItemSize = (itemKey, containerId, size) => {
|
|
4792
4975
|
if (containerId !== void 0 && peek$(ctx, `containerItemKey${containerId}`) === itemKey) {
|
|
4793
4976
|
mergeItemSizeUpdateResult(result, applyItemSize(ctx, itemKey, size));
|
|
@@ -4805,8 +4988,15 @@ function updateItemSizes(ctx, measurement) {
|
|
|
4805
4988
|
});
|
|
4806
4989
|
}
|
|
4807
4990
|
}
|
|
4991
|
+
}
|
|
4992
|
+
if (shouldQueueRecalculate && result.needsRecalculate) {
|
|
4993
|
+
queueItemSizeRecalculate(ctx, result);
|
|
4994
|
+
} else {
|
|
4808
4995
|
flushItemSizeUpdates(ctx, result);
|
|
4809
4996
|
}
|
|
4997
|
+
if (didDrainLayoutEffectMeasurements) {
|
|
4998
|
+
flushBatchedItemSizeRecalculate(ctx);
|
|
4999
|
+
}
|
|
4810
5000
|
}
|
|
4811
5001
|
function applyItemSize(ctx, itemKey, sizeObj) {
|
|
4812
5002
|
var _a3;
|