@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/react-native.mjs CHANGED
@@ -1513,6 +1513,7 @@ function finishScrollTo(ctx) {
1513
1513
  const scrollingTo = state.scrollingTo;
1514
1514
  state.scrollHistory.length = 0;
1515
1515
  state.scrollingTo = void 0;
1516
+ state.scrollTargetPinnedRange = void 0;
1516
1517
  if (state.pendingTotalSize !== void 0) {
1517
1518
  addTotalSize(ctx, null, state.pendingTotalSize);
1518
1519
  }
@@ -2152,6 +2153,8 @@ var flushSync = (fn) => {
2152
2153
  };
2153
2154
 
2154
2155
  // src/utils/getScrollVelocity.ts
2156
+ var MAX_SCROLL_VELOCITY_WINDOW_MS = 1e3;
2157
+ var SCROLL_VELOCITY_HALF_LIFE_MS = 200;
2155
2158
  var getScrollVelocity = (state) => {
2156
2159
  const { scrollHistory } = state;
2157
2160
  const newestIndex = scrollHistory.length - 1;
@@ -2159,35 +2162,37 @@ var getScrollVelocity = (state) => {
2159
2162
  return 0;
2160
2163
  }
2161
2164
  const newest = scrollHistory[newestIndex];
2162
- const now = Date.now();
2163
- let direction = 0;
2164
- for (let i = newestIndex; i > 0; i--) {
2165
- const delta = scrollHistory[i].scroll - scrollHistory[i - 1].scroll;
2166
- if (delta !== 0) {
2167
- direction = Math.sign(delta);
2168
- break;
2169
- }
2170
- }
2171
- if (direction === 0) {
2165
+ if (Date.now() - newest.time > MAX_SCROLL_VELOCITY_WINDOW_MS) {
2172
2166
  return 0;
2173
2167
  }
2174
- let oldest = newest;
2175
- for (let i = newestIndex - 1; i >= 0; i--) {
2168
+ let direction = 0;
2169
+ let weightedVelocity = 0;
2170
+ let totalWeight = 0;
2171
+ for (let i = newestIndex; i > 0; i--) {
2176
2172
  const current = scrollHistory[i];
2177
- const next = scrollHistory[i + 1];
2178
- const delta = next.scroll - current.scroll;
2179
- const deltaSign = Math.sign(delta);
2180
- if (deltaSign !== 0 && deltaSign !== direction) {
2181
- break;
2173
+ const previous = scrollHistory[i - 1];
2174
+ const scrollDiff = current.scroll - previous.scroll;
2175
+ const timeDiff = current.time - previous.time;
2176
+ const deltaSign = Math.sign(scrollDiff);
2177
+ if (deltaSign !== 0) {
2178
+ if (direction === 0) {
2179
+ direction = deltaSign;
2180
+ } else if (deltaSign !== direction) {
2181
+ break;
2182
+ }
2182
2183
  }
2183
- if (now - current.time > 1e3) {
2184
+ if (newest.time - previous.time > MAX_SCROLL_VELOCITY_WINDOW_MS) {
2184
2185
  break;
2185
2186
  }
2186
- oldest = current;
2187
+ if (scrollDiff === 0 || timeDiff <= 0) {
2188
+ continue;
2189
+ }
2190
+ const age = newest.time - current.time;
2191
+ const weight = Math.exp(-age / SCROLL_VELOCITY_HALF_LIFE_MS);
2192
+ weightedVelocity += scrollDiff / timeDiff * weight;
2193
+ totalWeight += weight;
2187
2194
  }
2188
- const scrollDiff = newest.scroll - oldest.scroll;
2189
- const timeDiff = newest.time - oldest.time;
2190
- return timeDiff > 0 ? scrollDiff / timeDiff : 0;
2195
+ return totalWeight > 0 ? weightedVelocity / totalWeight : 0;
2191
2196
  };
2192
2197
 
2193
2198
  // src/core/updateScroll.ts
@@ -2304,8 +2309,93 @@ function syncInitialScrollNativeWatchdog(state, options) {
2304
2309
  initialScrollWatchdog.clear(state);
2305
2310
  }
2306
2311
  }
2307
- function scrollTo(ctx, params) {
2312
+ function findPositionIndexAtOrBeforeOffset(ctx, offset) {
2313
+ const state = ctx.state;
2314
+ const dataLength = state.props.data.length;
2315
+ let low = 0;
2316
+ let high = dataLength - 1;
2317
+ let match;
2318
+ while (low <= high) {
2319
+ const mid = Math.floor((low + high) / 2);
2320
+ const top = state.positions[mid];
2321
+ if (top === void 0) {
2322
+ high = mid - 1;
2323
+ } else {
2324
+ if (top <= offset) {
2325
+ match = mid;
2326
+ low = mid + 1;
2327
+ } else {
2328
+ high = mid - 1;
2329
+ }
2330
+ }
2331
+ }
2332
+ return match;
2333
+ }
2334
+ function getItemBottom(ctx, index) {
2308
2335
  var _a3;
2336
+ const top = ctx.state.positions[index];
2337
+ if (top === void 0) {
2338
+ return void 0;
2339
+ }
2340
+ const itemSize = (_a3 = getItemSizeAtIndex(ctx, index)) != null ? _a3 : 0;
2341
+ return top + (Number.isFinite(itemSize) ? itemSize : 0);
2342
+ }
2343
+ function getTargetViewportRenderRange(ctx, targetOffset, targetIndex) {
2344
+ const state = ctx.state;
2345
+ const dataLength = state.props.data.length;
2346
+ if (dataLength === 0) {
2347
+ return void 0;
2348
+ }
2349
+ const viewportStart = Math.max(0, targetOffset);
2350
+ const viewportEnd = Math.max(viewportStart, targetOffset + state.scrollLength);
2351
+ let start = targetIndex !== void 0 ? Math.max(0, Math.min(dataLength - 1, targetIndex)) : findPositionIndexAtOrBeforeOffset(ctx, viewportStart);
2352
+ if (start === void 0) {
2353
+ return void 0;
2354
+ }
2355
+ if (targetIndex !== void 0 && state.positions[start] === void 0) {
2356
+ return { end: start, start };
2357
+ }
2358
+ if (targetIndex === void 0) {
2359
+ const startBottom = getItemBottom(ctx, start);
2360
+ if (startBottom === void 0 || startBottom <= viewportStart) {
2361
+ return void 0;
2362
+ }
2363
+ }
2364
+ while (start > 0) {
2365
+ const top = state.positions[start];
2366
+ if (top === void 0 || top <= viewportStart || state.positions[start - 1] === void 0) {
2367
+ break;
2368
+ }
2369
+ start--;
2370
+ }
2371
+ while (start > 0) {
2372
+ const previousBottom = getItemBottom(ctx, start - 1);
2373
+ if (previousBottom === void 0 || previousBottom <= viewportStart) {
2374
+ break;
2375
+ }
2376
+ start--;
2377
+ }
2378
+ let end = start;
2379
+ while (end + 1 < dataLength) {
2380
+ const nextTop = state.positions[end + 1];
2381
+ if (nextTop === void 0 || nextTop > viewportEnd) {
2382
+ break;
2383
+ }
2384
+ end++;
2385
+ }
2386
+ return { end, start };
2387
+ }
2388
+ function pinScrollTargetRenderRange(ctx, targetOffset, targetIndex) {
2389
+ const range = getTargetViewportRenderRange(ctx, targetOffset, targetIndex);
2390
+ if (range) {
2391
+ ctx.state.scrollTargetPinnedRange = range;
2392
+ ctx.state.scrollForNextCalculateItemsInView = void 0;
2393
+ } else {
2394
+ ctx.state.scrollTargetPinnedRange = void 0;
2395
+ }
2396
+ }
2397
+ function scrollTo(ctx, params) {
2398
+ var _a3, _b;
2309
2399
  const state = ctx.state;
2310
2400
  const { noScrollingTo, forceScroll, ...scrollTarget } = params;
2311
2401
  const {
@@ -2340,11 +2430,20 @@ function scrollTo(ctx, params) {
2340
2430
  targetOffset,
2341
2431
  waitForInitialScrollCompletionFrame
2342
2432
  };
2433
+ if (!isInitialScroll) {
2434
+ pinScrollTargetRenderRange(ctx, targetOffset, scrollTarget.index);
2435
+ }
2343
2436
  }
2344
2437
  state.scrollPending = targetOffset;
2345
2438
  syncInitialScrollNativeWatchdog(state, { isInitialScroll, requestedOffset: offset, targetOffset });
2346
- if (!animated && !isInitialScroll && !noScrollingTo && Math.abs(state.scroll - targetOffset) > 1) {
2347
- updateScroll(ctx, targetOffset, false, { markHasScrolled: false });
2439
+ if (!isInitialScroll && !noScrollingTo && Math.abs(state.scroll - targetOffset) > 1) {
2440
+ if (animated) {
2441
+ if (state.scrollTargetPinnedRange) {
2442
+ (_b = state.triggerCalculateItemsInView) == null ? void 0 : _b.call(state);
2443
+ }
2444
+ } else {
2445
+ updateScroll(ctx, targetOffset, true, { markHasScrolled: false });
2446
+ }
2348
2447
  }
2349
2448
  if (forceScroll || !isInitialScroll || Platform.OS === "android") {
2350
2449
  doScrollTo(ctx, { animated, horizontal, isInitialScroll, offset });
@@ -4016,6 +4115,32 @@ function setDidLayout(ctx) {
4016
4115
  }
4017
4116
 
4018
4117
  // src/core/calculateItemsInView.ts
4118
+ var RENDER_RANGE_PROJECTION_FULL_VELOCITY = 4;
4119
+ var RENDER_RANGE_PROJECTION_SETTLE_DELAY = 100;
4120
+ function getProjectedBufferAdjustment(scrollVelocity, trailingBuffer) {
4121
+ if (trailingBuffer <= 0) {
4122
+ return 0;
4123
+ }
4124
+ const velocityProgress = Math.min(1, Math.abs(scrollVelocity) / RENDER_RANGE_PROJECTION_FULL_VELOCITY);
4125
+ return Math.sign(scrollVelocity) * trailingBuffer * velocityProgress;
4126
+ }
4127
+ function scheduleRenderRangeProjectionSettle(ctx) {
4128
+ const state = ctx.state;
4129
+ const previousTimeout = state.timeoutRenderRangeProjectionSettle;
4130
+ if (previousTimeout !== void 0) {
4131
+ clearTimeout(previousTimeout);
4132
+ state.timeouts.delete(previousTimeout);
4133
+ }
4134
+ const timeout = setTimeout(() => {
4135
+ var _a3;
4136
+ state.timeoutRenderRangeProjectionSettle = void 0;
4137
+ state.timeouts.delete(timeout);
4138
+ state.scrollHistory.length = 0;
4139
+ (_a3 = state.triggerCalculateItemsInView) == null ? void 0 : _a3.call(state);
4140
+ }, RENDER_RANGE_PROJECTION_SETTLE_DELAY);
4141
+ state.timeoutRenderRangeProjectionSettle = timeout;
4142
+ state.timeouts.add(timeout);
4143
+ }
4019
4144
  function findCurrentStickyIndex(stickyArray, scroll, state) {
4020
4145
  const positions = state.positions;
4021
4146
  for (let i = stickyArray.length - 1; i >= 0; i--) {
@@ -4056,14 +4181,14 @@ function handleStickyActivation(ctx, stickyArray, currentStickyIdx, needNewConta
4056
4181
  }
4057
4182
  }
4058
4183
  }
4059
- function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentStickyIdx, pendingRemoval, alwaysRenderIndicesSet) {
4184
+ function handleStickyRecycling(ctx, stickyArray, scroll, drawDistance, currentStickyIdx, pendingRemoval, isPinnedRenderIndex) {
4060
4185
  var _a3, _b;
4061
4186
  const state = ctx.state;
4062
4187
  for (const containerIndex of state.stickyContainerPool) {
4063
4188
  const itemKey = peek$(ctx, `containerItemKey${containerIndex}`);
4064
4189
  const itemIndex = itemKey ? state.indexByKey.get(itemKey) : void 0;
4065
4190
  if (itemIndex === void 0) continue;
4066
- if (alwaysRenderIndicesSet.has(itemIndex)) continue;
4191
+ if (isPinnedRenderIndex(itemIndex)) continue;
4067
4192
  const arrayIdx = stickyArray.indexOf(itemIndex);
4068
4193
  if (arrayIdx === -1) {
4069
4194
  state.stickyContainerPool.delete(containerIndex);
@@ -4227,8 +4352,6 @@ function calculateItemsInView(ctx, params = {}) {
4227
4352
  const { data } = state.props;
4228
4353
  const stickyHeaderIndicesArr = state.props.stickyHeaderIndicesArr || [];
4229
4354
  const stickyHeaderIndicesSet = state.props.stickyHeaderIndicesSet || /* @__PURE__ */ new Set();
4230
- const alwaysRenderArr = alwaysRenderIndicesArr || [];
4231
- const alwaysRenderSet = alwaysRenderIndicesSet || /* @__PURE__ */ new Set();
4232
4355
  const drawDistance = getEffectiveDrawDistance(ctx, params.drawDistanceMode);
4233
4356
  const { dataChanged, doMVCP, forceFullItemPositions } = params;
4234
4357
  const bootstrapInitialScrollState = ((_a3 = state.initialScrollSession) == null ? void 0 : _a3.kind) === "bootstrap" ? state.initialScrollSession.bootstrap : void 0;
@@ -4295,14 +4418,19 @@ function calculateItemsInView(ctx, params = {}) {
4295
4418
  scrollBufferTop = drawDistance * 1.5;
4296
4419
  scrollBufferBottom = drawDistance * 0.5;
4297
4420
  }
4421
+ const shouldProjectRenderRange = !dataChanged && !forceFullItemPositions && !suppressInitialScrollSideEffects && !hasActiveInitialScroll(state) && !state.scrollingTo && !state.pendingNativeMVCPAdjust && !!peek$(ctx, "readyToRender");
4422
+ const projectedBufferAdjustment = shouldProjectRenderRange ? getProjectedBufferAdjustment(speed, Math.min(scrollBufferTop, scrollBufferBottom)) : 0;
4298
4423
  const updateScrollRange = () => {
4299
4424
  const scrollStart = Math.max(0, scroll);
4300
4425
  const overscrollBeforeContent = Math.max(0, -nativeScrollState);
4301
- scrollTopBuffered = scrollStart - scrollBufferTop;
4302
4426
  scrollBottom = Math.max(scrollStart, scroll + scrollLength + overscrollBeforeContent);
4303
- scrollBottomBuffered = scrollBottom + scrollBufferBottom;
4427
+ scrollTopBuffered = scrollStart - scrollBufferTop + projectedBufferAdjustment;
4428
+ scrollBottomBuffered = scrollBottom + scrollBufferBottom + projectedBufferAdjustment;
4304
4429
  };
4305
4430
  updateScrollRange();
4431
+ if (projectedBufferAdjustment !== 0) {
4432
+ scheduleRenderRangeProjectionSettle(ctx);
4433
+ }
4306
4434
  if (enableScrollForNextCalculateItemsInView && !suppressInitialScrollSideEffects && !dataChanged && !forceFullItemPositions && scrollForNextCalculateItemsInView) {
4307
4435
  const { top, bottom } = scrollForNextCalculateItemsInView;
4308
4436
  if (top === null && bottom === null) {
@@ -4460,9 +4588,34 @@ function calculateItemsInView(ctx, params = {}) {
4460
4588
  }
4461
4589
  }
4462
4590
  }
4591
+ const scrollTargetPinnedRange = state.scrollTargetPinnedRange;
4592
+ let scrollTargetPinnedStart = 0;
4593
+ let scrollTargetPinnedEnd = -1;
4594
+ if (scrollTargetPinnedRange) {
4595
+ scrollTargetPinnedStart = Math.max(0, Math.min(scrollTargetPinnedRange.start, scrollTargetPinnedRange.end));
4596
+ scrollTargetPinnedEnd = Math.min(
4597
+ dataLength - 1,
4598
+ Math.max(scrollTargetPinnedRange.start, scrollTargetPinnedRange.end)
4599
+ );
4600
+ }
4601
+ const hasScrollTargetPinnedRange = scrollTargetPinnedStart <= scrollTargetPinnedEnd;
4602
+ const isPinnedRenderIndex = (index) => alwaysRenderIndicesSet.has(index) || hasScrollTargetPinnedRange && index >= scrollTargetPinnedStart && index <= scrollTargetPinnedEnd;
4463
4603
  if (startBuffered !== null && endBuffered !== null) {
4464
4604
  const needNewContainers = [];
4465
4605
  const needNewContainersSet = /* @__PURE__ */ new Set();
4606
+ const addPinnedIndex = (index) => {
4607
+ var _a4;
4608
+ if (index >= 0 && index < dataLength) {
4609
+ const id = (_a4 = idCache[index]) != null ? _a4 : getId(state, index);
4610
+ const containerIndex = containerItemKeys.get(id);
4611
+ if (containerIndex !== void 0) {
4612
+ state.stickyContainerPool.add(containerIndex);
4613
+ } else if (!isNullOrUndefined(id) && !needNewContainersSet.has(index)) {
4614
+ needNewContainersSet.add(index);
4615
+ needNewContainers.push(index);
4616
+ }
4617
+ }
4618
+ };
4466
4619
  for (let i = startBuffered; i <= endBuffered; i++) {
4467
4620
  const id = (_m = idCache[i]) != null ? _m : getId(state, i);
4468
4621
  if (!containerItemKeys.has(id)) {
@@ -4470,21 +4623,19 @@ function calculateItemsInView(ctx, params = {}) {
4470
4623
  needNewContainers.push(i);
4471
4624
  }
4472
4625
  }
4473
- if (alwaysRenderArr.length > 0) {
4474
- for (const index of alwaysRenderArr) {
4475
- if (index < 0 || index >= dataLength) continue;
4476
- const id = (_n = idCache[index]) != null ? _n : getId(state, index);
4477
- if (id && !containerItemKeys.has(id) && !needNewContainersSet.has(index)) {
4478
- needNewContainersSet.add(index);
4479
- needNewContainers.push(index);
4480
- }
4626
+ for (const index of alwaysRenderIndicesArr) {
4627
+ addPinnedIndex(index);
4628
+ }
4629
+ if (hasScrollTargetPinnedRange) {
4630
+ for (let index = scrollTargetPinnedStart; index <= scrollTargetPinnedEnd; index++) {
4631
+ addPinnedIndex(index);
4481
4632
  }
4482
4633
  }
4483
4634
  if (stickyHeaderIndicesArr.length > 0) {
4484
4635
  handleStickyActivation(
4485
4636
  ctx,
4486
4637
  stickyHeaderIndicesArr,
4487
- (_o = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _o : -1,
4638
+ (_n = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _n : -1,
4488
4639
  needNewContainers,
4489
4640
  needNewContainersSet,
4490
4641
  startBuffered,
@@ -4510,7 +4661,7 @@ function calculateItemsInView(ctx, params = {}) {
4510
4661
  for (const allocation of availableContainerAllocations) {
4511
4662
  const i = allocation.itemIndex;
4512
4663
  const containerIndex = allocation.containerIndex;
4513
- const id = (_p = idCache[i]) != null ? _p : getId(state, i);
4664
+ const id = (_o = idCache[i]) != null ? _o : getId(state, i);
4514
4665
  const oldKey = peek$(ctx, `containerItemKey${containerIndex}`);
4515
4666
  if (oldKey && oldKey !== id) {
4516
4667
  containerItemKeys.delete(oldKey);
@@ -4521,10 +4672,14 @@ function calculateItemsInView(ctx, params = {}) {
4521
4672
  state.containerItemTypes.set(containerIndex, allocation.itemType);
4522
4673
  }
4523
4674
  containerItemKeys.set(id, containerIndex);
4524
- (_q = state.userScrollAnchorReset) == null ? void 0 : _q.keys.add(id);
4675
+ (_p = state.userScrollAnchorReset) == null ? void 0 : _p.keys.add(id);
4676
+ if (IsNewArchitecture) {
4677
+ (_q = state.pendingLayoutEffectMeasurements) != null ? _q : state.pendingLayoutEffectMeasurements = /* @__PURE__ */ new Set();
4678
+ state.pendingLayoutEffectMeasurements.add(id);
4679
+ }
4525
4680
  const containerSticky = `containerSticky${containerIndex}`;
4526
4681
  const isSticky = stickyHeaderIndicesSet.has(i);
4527
- const isAlwaysRender = alwaysRenderSet.has(i);
4682
+ const isPinnedRender = isPinnedRenderIndex(i);
4528
4683
  if (isSticky) {
4529
4684
  set$(ctx, containerSticky, true);
4530
4685
  state.stickyContainerPool.add(containerIndex);
@@ -4532,9 +4687,9 @@ function calculateItemsInView(ctx, params = {}) {
4532
4687
  if (peek$(ctx, containerSticky)) {
4533
4688
  set$(ctx, containerSticky, false);
4534
4689
  }
4535
- if (isAlwaysRender) {
4690
+ if (isPinnedRender) {
4536
4691
  state.stickyContainerPool.add(containerIndex);
4537
- } else if (state.stickyContainerPool.has(containerIndex)) {
4692
+ } else {
4538
4693
  state.stickyContainerPool.delete(containerIndex);
4539
4694
  }
4540
4695
  }
@@ -4549,20 +4704,8 @@ function calculateItemsInView(ctx, params = {}) {
4549
4704
  }
4550
4705
  }
4551
4706
  }
4552
- if (state.userScrollAnchorReset) {
4553
- if (state.userScrollAnchorReset.keys.size === 0) {
4554
- state.userScrollAnchorReset = void 0;
4555
- }
4556
- }
4557
- if (alwaysRenderArr.length > 0) {
4558
- for (const index of alwaysRenderArr) {
4559
- if (index < 0 || index >= dataLength) continue;
4560
- const id = (_r = idCache[index]) != null ? _r : getId(state, index);
4561
- const containerIndex = containerItemKeys.get(id);
4562
- if (containerIndex !== void 0) {
4563
- state.stickyContainerPool.add(containerIndex);
4564
- }
4565
- }
4707
+ if (((_r = state.userScrollAnchorReset) == null ? void 0 : _r.keys.size) === 0) {
4708
+ state.userScrollAnchorReset = void 0;
4566
4709
  }
4567
4710
  }
4568
4711
  if (state.stickyContainerPool.size > 0) {
@@ -4573,7 +4716,7 @@ function calculateItemsInView(ctx, params = {}) {
4573
4716
  drawDistance,
4574
4717
  (_s = stickyState == null ? void 0 : stickyState.currentStickyIdx) != null ? _s : -1,
4575
4718
  pendingRemoval,
4576
- alwaysRenderSet
4719
+ isPinnedRenderIndex
4577
4720
  );
4578
4721
  }
4579
4722
  const pendingRemovalSet = pendingRemoval.length > 0 ? new Set(pendingRemoval) : void 0;
@@ -4745,6 +4888,36 @@ function mergeItemSizeUpdateResult(result, next) {
4745
4888
  result.needsRecalculate || (result.needsRecalculate = next.needsRecalculate);
4746
4889
  result.shouldMaintainScrollAtEnd || (result.shouldMaintainScrollAtEnd = next.shouldMaintainScrollAtEnd);
4747
4890
  }
4891
+ var batchedItemSizeRecalculates = /* @__PURE__ */ new WeakMap();
4892
+ function flushBatchedItemSizeRecalculate(ctx, didFallback = false, expectedResult) {
4893
+ const result = batchedItemSizeRecalculates.get(ctx);
4894
+ if (!result || expectedResult && result !== expectedResult) {
4895
+ return;
4896
+ }
4897
+ batchedItemSizeRecalculates.delete(ctx);
4898
+ if (didFallback) {
4899
+ ctx.state.pendingLayoutEffectMeasurements = void 0;
4900
+ }
4901
+ flushItemSizeUpdates(ctx, result);
4902
+ }
4903
+ function queueItemSizeRecalculate(ctx, result) {
4904
+ var _a3, _b;
4905
+ const batch = batchedItemSizeRecalculates.get(ctx);
4906
+ if (batch) {
4907
+ mergeItemSizeUpdateResult(batch, result);
4908
+ } else {
4909
+ const nextBatch = { ...result };
4910
+ batchedItemSizeRecalculates.set(ctx, nextBatch);
4911
+ if ((_a3 = ctx.state.pendingLayoutEffectMeasurements) == null ? void 0 : _a3.size) {
4912
+ requestAnimationFrame(() => {
4913
+ flushBatchedItemSizeRecalculate(ctx, true, nextBatch);
4914
+ });
4915
+ }
4916
+ }
4917
+ if (!((_b = ctx.state.pendingLayoutEffectMeasurements) == null ? void 0 : _b.size)) {
4918
+ flushBatchedItemSizeRecalculate(ctx);
4919
+ }
4920
+ }
4748
4921
  function flushItemSizeUpdates(ctx, result) {
4749
4922
  var _a3;
4750
4923
  const state = ctx.state;
@@ -4761,12 +4934,22 @@ function flushItemSizeUpdates(ctx, result) {
4761
4934
  function updateItemSizes(ctx, measurement) {
4762
4935
  var _a3, _b, _c, _d;
4763
4936
  const state = ctx.state;
4937
+ let didDrainLayoutEffectMeasurements = false;
4938
+ if (IsNewArchitecture && measurement.fromLayoutEffect) {
4939
+ const pendingLayoutEffectMeasurements = state.pendingLayoutEffectMeasurements;
4940
+ if ((pendingLayoutEffectMeasurements == null ? void 0 : pendingLayoutEffectMeasurements.delete(measurement.itemKey)) && pendingLayoutEffectMeasurements.size === 0) {
4941
+ state.pendingLayoutEffectMeasurements = void 0;
4942
+ didDrainLayoutEffectMeasurements = true;
4943
+ }
4944
+ }
4764
4945
  const pendingKeys = (_a3 = state.userScrollAnchorReset) == null ? void 0 : _a3.keys;
4765
4946
  const shouldBatchPendingMeasurements = IsNewArchitecture && measurement.fromLayoutEffect && !!(pendingKeys == null ? void 0 : pendingKeys.size);
4947
+ const shouldQueueRecalculate = IsNewArchitecture && !!measurement.fromLayoutEffect;
4948
+ let result;
4766
4949
  if (!shouldBatchPendingMeasurements) {
4767
- flushItemSizeUpdates(ctx, applyItemSize(ctx, measurement.itemKey, measurement.size));
4950
+ result = applyItemSize(ctx, measurement.itemKey, measurement.size);
4768
4951
  } else {
4769
- const result = {};
4952
+ result = {};
4770
4953
  const updateContainerItemSize = (itemKey, containerId, size) => {
4771
4954
  if (containerId !== void 0 && peek$(ctx, `containerItemKey${containerId}`) === itemKey) {
4772
4955
  mergeItemSizeUpdateResult(result, applyItemSize(ctx, itemKey, size));
@@ -4784,8 +4967,15 @@ function updateItemSizes(ctx, measurement) {
4784
4967
  });
4785
4968
  }
4786
4969
  }
4970
+ }
4971
+ if (shouldQueueRecalculate && result.needsRecalculate) {
4972
+ queueItemSizeRecalculate(ctx, result);
4973
+ } else {
4787
4974
  flushItemSizeUpdates(ctx, result);
4788
4975
  }
4976
+ if (didDrainLayoutEffectMeasurements) {
4977
+ flushBatchedItemSizeRecalculate(ctx);
4978
+ }
4789
4979
  }
4790
4980
  function applyItemSize(ctx, itemKey, sizeObj) {
4791
4981
  var _a3;