@jsenv/navi 0.29.448 → 0.29.450
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/dist/dev/jsenv_navi.js +184 -85
- package/dist/dev/jsenv_navi.js.map +4 -4
- package/dist/jsenv_navi.js +184 -85
- package/dist/jsenv_navi.js.map +4 -4
- package/docs/AI_INSTRUCTIONS.md +6 -4
- package/docs/list_refresh.md +10 -4
- package/docs/scroll.md +36 -4
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -4988,9 +4988,11 @@ const actionRunEffect = (
|
|
|
4988
4988
|
return params;
|
|
4989
4989
|
});
|
|
4990
4990
|
// Whether the getter asks for a run is read off what it returned, never off
|
|
4991
|
-
// the
|
|
4992
|
-
//
|
|
4993
|
-
//
|
|
4991
|
+
// the instances it moves between: an action handed here holding params of
|
|
4992
|
+
// its own (an instance, a binding) keeps them when the getter returns
|
|
4993
|
+
// nothing — and nothing must still run nothing; an instance reset under the
|
|
4994
|
+
// effect (a same-resource DELETE) reads as never run — and the next params
|
|
4995
|
+
// the getter asks for must still run.
|
|
4994
4996
|
let asking = Boolean(actionParamsSignal.peek());
|
|
4995
4997
|
const actionRunnedByThisEffect = action.bindParams(actionParamsSignal, {
|
|
4996
4998
|
debounce,
|
|
@@ -5017,11 +5019,7 @@ const actionRunEffect = (
|
|
|
5017
5019
|
return;
|
|
5018
5020
|
}
|
|
5019
5021
|
|
|
5020
|
-
if (
|
|
5021
|
-
actionTargetPrevious &&
|
|
5022
|
-
!actionTargetPrevious.isPrerun &&
|
|
5023
|
-
actionTarget
|
|
5024
|
-
) {
|
|
5022
|
+
if (actionTargetPrevious && actionTarget) {
|
|
5025
5023
|
// params changed
|
|
5026
5024
|
if (!asking) {
|
|
5027
5025
|
// falsy params, don't run
|
|
@@ -73699,6 +73697,9 @@ const createListItems = () => {
|
|
|
73699
73697
|
// what puts the view back once they have (see VirtualFiller).
|
|
73700
73698
|
captureAnchor: () => {},
|
|
73701
73699
|
holdViewStill: () => {},
|
|
73700
|
+
// The list has asked for a window no render has drawn yet: a run holding
|
|
73701
|
+
// the one before has nothing to ask for it (see useRequestMissing).
|
|
73702
|
+
windowOnItsWay: () => false,
|
|
73702
73703
|
horizontal: false,
|
|
73703
73704
|
virtualItemSizeSignal: null,
|
|
73704
73705
|
roomById,
|
|
@@ -75907,6 +75908,7 @@ const useListScrollSync = ({
|
|
|
75907
75908
|
const renderWindowRef = useRef(null);
|
|
75908
75909
|
// A window was asked for that no render has drawn yet (see settleWindow).
|
|
75909
75910
|
const windowAskedRef = useRef(false);
|
|
75911
|
+
listItems.windowOnItsWay = () => windowAskedRef.current;
|
|
75910
75912
|
const windowLeavesItemsOut = () => {
|
|
75911
75913
|
const renderWindow = renderWindowRef.current;
|
|
75912
75914
|
if (!renderWindow) {
|
|
@@ -77401,6 +77403,7 @@ const useListScrollSync = ({
|
|
|
77401
77403
|
}, [scrollerElResolved]);
|
|
77402
77404
|
holdWindow();
|
|
77403
77405
|
// Whatever was asked for until now is what this render draws.
|
|
77406
|
+
const windowWasAsked = windowAskedRef.current;
|
|
77404
77407
|
windowAskedRef.current = false;
|
|
77405
77408
|
const {
|
|
77406
77409
|
start: windowStart,
|
|
@@ -77416,13 +77419,15 @@ const useListScrollSync = ({
|
|
|
77416
77419
|
// column — started anywhere but on a line, every item drawn would sit in the
|
|
77417
77420
|
// column of another. Started on one, an item is in the column its place says
|
|
77418
77421
|
// whatever the window frames. The same object while the numbers hold, so the
|
|
77419
|
-
// runs are not told about a window that did not move
|
|
77422
|
+
// runs are not told about a window that did not move — except after a window
|
|
77423
|
+
// was asked for: a run waiting for it to ask (see useRequestMissing) must be
|
|
77424
|
+
// told, even when the window framed comes back to the same numbers.
|
|
77420
77425
|
const windowDrawnRef = useRef(null);
|
|
77421
77426
|
const drawnStart = windowStart - windowStart % itemsPerLine;
|
|
77422
77427
|
const endPastLine = windowEnd % itemsPerLine;
|
|
77423
77428
|
const drawnEnd = endPastLine === 0 ? windowEnd : windowEnd + itemsPerLine - endPastLine;
|
|
77424
77429
|
let windowDrawn = windowDrawnRef.current;
|
|
77425
|
-
if (!windowDrawn || windowDrawn.start !== drawnStart || windowDrawn.end !== drawnEnd || windowDrawn.itemsPerLine !== itemsPerLine) {
|
|
77430
|
+
if (!windowDrawn || windowWasAsked || windowDrawn.start !== drawnStart || windowDrawn.end !== drawnEnd || windowDrawn.itemsPerLine !== itemsPerLine) {
|
|
77426
77431
|
windowDrawn = {
|
|
77427
77432
|
start: drawnStart,
|
|
77428
77433
|
end: drawnEnd,
|
|
@@ -79661,6 +79666,15 @@ const VISIBILITY_HIDDEN_STYLE = {
|
|
|
79661
79666
|
* @param {(range: object) => any} [props.itemsAction]
|
|
79662
79667
|
* Where the items come from when the collection is read a slice at a time:
|
|
79663
79668
|
* a resource's range reader (`RESOURCE.GET_RANGE.bindParams(...)`).
|
|
79669
|
+
* @param {number} [props.count]
|
|
79670
|
+
* How many items the collection holds, when the app knows it before the
|
|
79671
|
+
* first answer: a total shown elsewhere, a profile saying how many there are.
|
|
79672
|
+
* The list is then as long as the collection from its first frame: it opens
|
|
79673
|
+
* where it is held, the scrollbar right, and asks for that window. Without
|
|
79674
|
+
* it, the run stands for skeletons up to the item the list opens on and a
|
|
79675
|
+
* page past it, until the first answer says how many there are. Not worth a
|
|
79676
|
+
* request of its own, since the first answer gives it (see docs/scroll.md,
|
|
79677
|
+
* "What a run knows when it opens").
|
|
79664
79678
|
* @param {number} [props.debounce]
|
|
79665
79679
|
* Milliseconds the reader must hold still before the run draws the
|
|
79666
79680
|
* collection it reads: params following a field as the user types
|
|
@@ -79776,6 +79790,7 @@ const ListItemsRun = ({
|
|
|
79776
79790
|
count,
|
|
79777
79791
|
itemsAction,
|
|
79778
79792
|
settling,
|
|
79793
|
+
pageSize: runProps.pageSize,
|
|
79779
79794
|
memoryBudget,
|
|
79780
79795
|
onRequestStateChange,
|
|
79781
79796
|
onCountChange
|
|
@@ -80044,9 +80059,17 @@ const useRunItems = (store, {
|
|
|
80044
80059
|
// A hole with nothing on either side (the scrollbar was thrown into
|
|
80045
80060
|
// territory never visited): grow it both ways around what is on
|
|
80046
80061
|
// screen.
|
|
80047
|
-
|
|
80048
|
-
|
|
80049
|
-
|
|
80062
|
+
askStart = missingStart - Math.floor((itemsPerPage - holeSize) / 2);
|
|
80063
|
+
askEnd = askStart + itemsPerPage - 1;
|
|
80064
|
+
// Cut by an edge of the run (the first page, the last one), the page
|
|
80065
|
+
// takes the room on the other side.
|
|
80066
|
+
if (askStart < runStart) {
|
|
80067
|
+
askEnd += runStart - askStart;
|
|
80068
|
+
askStart = runStart;
|
|
80069
|
+
} else if (askEnd > runEnd - 1) {
|
|
80070
|
+
askStart -= askEnd - (runEnd - 1);
|
|
80071
|
+
askEnd = runEnd - 1;
|
|
80072
|
+
}
|
|
80050
80073
|
}
|
|
80051
80074
|
}
|
|
80052
80075
|
if (askStart < runStart) {
|
|
@@ -80446,6 +80469,18 @@ const ListItemsFailure = ({
|
|
|
80446
80469
|
const ITEM_STORE_MAX_DEFAULT = 1000;
|
|
80447
80470
|
const ITEM_STORE_KEEP_AROUND = 250;
|
|
80448
80471
|
const COUNT_NOT_SAID = {};
|
|
80472
|
+
|
|
80473
|
+
// The index of the item the list is held at, when the hold names one: a number,
|
|
80474
|
+
// or a position remembered with its index (see placeWhereHeld).
|
|
80475
|
+
const readHeldIndex = scrolled => {
|
|
80476
|
+
if (typeof scrolled === "number") {
|
|
80477
|
+
return scrolled;
|
|
80478
|
+
}
|
|
80479
|
+
if (scrolled && typeof scrolled === "object" && typeof scrolled.index === "number") {
|
|
80480
|
+
return scrolled.index;
|
|
80481
|
+
}
|
|
80482
|
+
return null;
|
|
80483
|
+
};
|
|
80449
80484
|
const rangeIsSame = (a, b) => {
|
|
80450
80485
|
if (!a || !b) {
|
|
80451
80486
|
return a === b;
|
|
@@ -80463,6 +80498,7 @@ const useItemStore = ({
|
|
|
80463
80498
|
count,
|
|
80464
80499
|
itemsAction,
|
|
80465
80500
|
settling,
|
|
80501
|
+
pageSize,
|
|
80466
80502
|
memoryBudget,
|
|
80467
80503
|
onRequestStateChange,
|
|
80468
80504
|
onCountChange
|
|
@@ -80557,6 +80593,68 @@ const useItemStore = ({
|
|
|
80557
80593
|
if (staleRanksRef.current === null) {
|
|
80558
80594
|
staleRanksRef.current = restored ? new Set(pages.byIndex.keys()) : new Set();
|
|
80559
80595
|
}
|
|
80596
|
+
const takeInPage = ({
|
|
80597
|
+
pageItems,
|
|
80598
|
+
pageStart,
|
|
80599
|
+
pageCount
|
|
80600
|
+
}) => {
|
|
80601
|
+
// An item from before is gone from where it stood when the page puts
|
|
80602
|
+
// it at another rank (it would be drawn twice), or when its rank is
|
|
80603
|
+
// past the end of the collection.
|
|
80604
|
+
const staleRanks = staleRanksRef.current;
|
|
80605
|
+
const pageEnd = pageStart + pageItems.length;
|
|
80606
|
+
let dropped = false;
|
|
80607
|
+
if (staleRanks.size > 0) {
|
|
80608
|
+
const pageIds = new Set();
|
|
80609
|
+
for (const pageItem of pageItems) {
|
|
80610
|
+
if (pageItem && pageItem.id !== undefined) {
|
|
80611
|
+
pageIds.add(pageItem.id);
|
|
80612
|
+
}
|
|
80613
|
+
}
|
|
80614
|
+
for (const rank of staleRanks) {
|
|
80615
|
+
if (rank >= pageStart && rank < pageEnd) {
|
|
80616
|
+
continue;
|
|
80617
|
+
}
|
|
80618
|
+
const staleItem = pages.byIndex.get(rank);
|
|
80619
|
+
if (rank >= pageCount || staleItem && pageIds.has(staleItem.id)) {
|
|
80620
|
+
staleRanks.delete(rank);
|
|
80621
|
+
pages.byIndex.delete(rank);
|
|
80622
|
+
dropped = true;
|
|
80623
|
+
}
|
|
80624
|
+
}
|
|
80625
|
+
}
|
|
80626
|
+
let i = 0;
|
|
80627
|
+
while (i < pageItems.length) {
|
|
80628
|
+
pages.byIndex.set(pageStart + i, pageItems[i]);
|
|
80629
|
+
staleRanks.delete(pageStart + i);
|
|
80630
|
+
i++;
|
|
80631
|
+
}
|
|
80632
|
+
pages.count = pageCount;
|
|
80633
|
+
// Which rank holds which id, kept by the source so a list drawing
|
|
80634
|
+
// this collection again finds it drawn (see readComposition above).
|
|
80635
|
+
if (itemsAction.writeComposition) {
|
|
80636
|
+
itemsAction.writeComposition({
|
|
80637
|
+
byIndex: pages.byIndex,
|
|
80638
|
+
count: pageCount,
|
|
80639
|
+
replace: dropped
|
|
80640
|
+
});
|
|
80641
|
+
}
|
|
80642
|
+
};
|
|
80643
|
+
// The pages answered since the last render, taken in by the render and not
|
|
80644
|
+
// as they land: what the list reads of the run — how many items it stands for
|
|
80645
|
+
// (see listItems.take), where an item sits (its locator) — then moves in one
|
|
80646
|
+
// step. Taken in on landing, an item could be located past the count the list
|
|
80647
|
+
// still holds, and a list held on it would aim its window there at every
|
|
80648
|
+
// render, framed back each time.
|
|
80649
|
+
const pagesLandedRef = useRef([]);
|
|
80650
|
+
const pagesLanded = pagesLandedRef.current;
|
|
80651
|
+
const pagesTakenIn = pagesLanded.length > 0;
|
|
80652
|
+
if (pagesTakenIn) {
|
|
80653
|
+
pagesLandedRef.current = [];
|
|
80654
|
+
for (const page of pagesLanded) {
|
|
80655
|
+
takeInPage(page);
|
|
80656
|
+
}
|
|
80657
|
+
}
|
|
80560
80658
|
const [refreshing, setRefreshing] = useState(false);
|
|
80561
80659
|
// A source that says when what it reads has moved (a resource range reader
|
|
80562
80660
|
// does: see rerunOn.GET_RANGE) is heard here — a write deciding who belongs
|
|
@@ -80587,19 +80685,33 @@ const useItemStore = ({
|
|
|
80587
80685
|
const [failure, setFailure] = useState(null);
|
|
80588
80686
|
const listItems = useContext(ListItemsContext);
|
|
80589
80687
|
// The items are there, which is what the list waits for to place itself on the
|
|
80590
|
-
// item it is held at (see placeWhereHeld). Said from an effect
|
|
80591
|
-
// during this very render must not be written
|
|
80688
|
+
// item it is held at (see placeWhereHeld). Said from an effect, once the run
|
|
80689
|
+
// has drawn them: a signal read during this very render must not be written
|
|
80690
|
+
// during it.
|
|
80592
80691
|
useLayoutEffect(() => {
|
|
80593
|
-
if (
|
|
80692
|
+
if (inMemory) {
|
|
80693
|
+
if (itemsHeldRef.current) {
|
|
80694
|
+
return;
|
|
80695
|
+
}
|
|
80696
|
+
itemsHeldRef.current = true;
|
|
80697
|
+
} else if (!pagesTakenIn) {
|
|
80594
80698
|
return;
|
|
80595
80699
|
}
|
|
80596
|
-
itemsHeldRef.current = true;
|
|
80597
80700
|
listItems.pagesSignal.value = listItems.pagesSignal.peek() + 1;
|
|
80598
80701
|
});
|
|
80599
80702
|
// Before the first answer a run does not know how many items it stands for.
|
|
80600
80703
|
// It stands for a page of them: a list that is about to be filled looks
|
|
80601
|
-
// like items on their way, not like an empty list.
|
|
80602
|
-
|
|
80704
|
+
// like items on their way, not like an empty list. A list held on an item
|
|
80705
|
+
// (see placeWhereHeld) is about to be filled there: the run stands for the
|
|
80706
|
+
// items up to that one and a page past it, so the window frames the item
|
|
80707
|
+
// before any answer, and what the run asks for first is that window.
|
|
80708
|
+
const itemsPerPage = pageSize || listItems.pageSize;
|
|
80709
|
+
const countKnown = pages.count ?? count;
|
|
80710
|
+
let itemCount = countKnown;
|
|
80711
|
+
if (itemCount === undefined) {
|
|
80712
|
+
const heldIndex = readHeldIndex(listItems.scrolled);
|
|
80713
|
+
itemCount = heldIndex === null ? itemsPerPage : heldIndex + itemsPerPage;
|
|
80714
|
+
}
|
|
80603
80715
|
// The items drawn are from before while they are read again, and while the
|
|
80604
80716
|
// collection that replaces them waits for its params to hold still (see
|
|
80605
80717
|
// useSettledReader).
|
|
@@ -80618,7 +80730,6 @@ const useItemStore = ({
|
|
|
80618
80730
|
// say: the count the source answered or the caller gave, never the page the
|
|
80619
80731
|
// run stands for before it knows. Said by each run on its first commit, so a
|
|
80620
80732
|
// run drawing another collection takes back what the one before said.
|
|
80621
|
-
const countKnown = pages.count ?? count;
|
|
80622
80733
|
const onCountChangeRef = useRef(onCountChange);
|
|
80623
80734
|
onCountChangeRef.current = onCountChange;
|
|
80624
80735
|
const countSaidRef = useRef(COUNT_NOT_SAID);
|
|
@@ -80665,8 +80776,13 @@ const useItemStore = ({
|
|
|
80665
80776
|
};
|
|
80666
80777
|
// A list taken off the screen while it was asking leaves nothing ringing
|
|
80667
80778
|
// behind it: whoever is drawing "looking for items" has to stop.
|
|
80779
|
+
const mountedRef = useRef(false);
|
|
80780
|
+
// Which render's ask is the one to send (see useRequestMissing).
|
|
80781
|
+
const askTurnRef = useRef(0);
|
|
80668
80782
|
useLayoutEffect(() => {
|
|
80783
|
+
mountedRef.current = true;
|
|
80669
80784
|
return () => {
|
|
80785
|
+
mountedRef.current = false;
|
|
80670
80786
|
if (requestStateRef.current.busy && onRequestStateChangeRef.current) {
|
|
80671
80787
|
onRequestStateChangeRef.current({
|
|
80672
80788
|
busy: false,
|
|
@@ -80726,11 +80842,7 @@ const useItemStore = ({
|
|
|
80726
80842
|
// what it hands over (see rankOf). The one thing read from the list
|
|
80727
80843
|
// itself is where it is being held, which is a list item.
|
|
80728
80844
|
const rankOfIndex = itemIndex => itemIndex - runStart;
|
|
80729
|
-
|
|
80730
|
-
// how many items there are, so it asks for the items the list would open
|
|
80731
|
-
// on — counting back from the end when that is where it opens, the way
|
|
80732
|
-
// an HTTP range does.
|
|
80733
|
-
const budget = listItems.pageSize;
|
|
80845
|
+
const budget = itemsPerPage;
|
|
80734
80846
|
let start = missingStart;
|
|
80735
80847
|
let end = missingEnd;
|
|
80736
80848
|
let around;
|
|
@@ -80800,26 +80912,26 @@ const useItemStore = ({
|
|
|
80800
80912
|
around = firstStale.id;
|
|
80801
80913
|
}
|
|
80802
80914
|
} else if (pages.count === undefined) {
|
|
80915
|
+
// The very first ask is what the window misses, like any other: the
|
|
80916
|
+
// run stands for the items up to where the list opens (see
|
|
80917
|
+
// itemCount), so the window frames that place already.
|
|
80803
80918
|
const scrolled = listItems.scrolled;
|
|
80804
|
-
if (scrolled === "end") {
|
|
80805
|
-
//
|
|
80806
|
-
//
|
|
80807
|
-
// there are.
|
|
80919
|
+
if (scrolled === "end" && countKnown === undefined) {
|
|
80920
|
+
// Except the end, which no window can frame before the count is
|
|
80921
|
+
// known: counted back from, the way an HTTP range does.
|
|
80808
80922
|
start = -budget;
|
|
80809
80923
|
end = -1;
|
|
80810
|
-
} else if (
|
|
80811
|
-
//
|
|
80812
|
-
//
|
|
80813
|
-
|
|
80814
|
-
|
|
80815
|
-
|
|
80816
|
-
|
|
80817
|
-
|
|
80924
|
+
} else if (start === -1) {
|
|
80925
|
+
// The window does not reach the run yet: its first page is asked
|
|
80926
|
+
// for all the same, which says how many items it stands for.
|
|
80927
|
+
start = 0;
|
|
80928
|
+
end = budget - 1;
|
|
80929
|
+
}
|
|
80930
|
+
if (scrolled && scrolled.id !== undefined) {
|
|
80931
|
+
// Asked for by name too, since a place can have changed hands since
|
|
80932
|
+
// it was written down: the answer says where it really landed (see
|
|
80933
|
+
// the page's own `start`).
|
|
80818
80934
|
around = scrolled.id;
|
|
80819
|
-
} else {
|
|
80820
|
-
const first = typeof scrolled === "number" ? rankOfIndex(scrolled) - Math.floor(budget / 2) : 0;
|
|
80821
|
-
start = first < 0 ? 0 : first;
|
|
80822
|
-
end = start + budget - 1;
|
|
80823
80935
|
}
|
|
80824
80936
|
}
|
|
80825
80937
|
const ask = () => {
|
|
@@ -80833,6 +80945,12 @@ const useItemStore = ({
|
|
|
80833
80945
|
const debugAsk = outcome => {
|
|
80834
80946
|
debugScroll(`ask ${start}-${end}: ${outcome}`, `(revalidating=${revalidating} holdPending=${listItems.holdPending} count=${pages.count})`);
|
|
80835
80947
|
};
|
|
80948
|
+
if (listItems.windowOnItsWay()) {
|
|
80949
|
+
// The list moved its window after this render drew the one it had:
|
|
80950
|
+
// the run draws the new one in the list's next pass, and asks then.
|
|
80951
|
+
debugAsk("the list is moving its window");
|
|
80952
|
+
return;
|
|
80953
|
+
}
|
|
80836
80954
|
if (start === -1) {
|
|
80837
80955
|
// Nothing missing and nothing to revalidate: the run has what it
|
|
80838
80956
|
// draws.
|
|
@@ -80928,51 +81046,21 @@ const useItemStore = ({
|
|
|
80928
81046
|
const pageItems = Array.isArray(page) ? page : page.items;
|
|
80929
81047
|
const pageStart = Array.isArray(page) ? 0 : page.start ?? 0;
|
|
80930
81048
|
const pageCount = Array.isArray(page) ? pageItems.length : page.count ?? pageStart + pageItems.length;
|
|
81049
|
+
const pageLanded = {
|
|
81050
|
+
pageItems,
|
|
81051
|
+
pageStart,
|
|
81052
|
+
pageCount
|
|
81053
|
+
};
|
|
81054
|
+
if (!mountedRef.current) {
|
|
81055
|
+
// No render is coming to take it in, and the source still keeps
|
|
81056
|
+
// what came back for the next list drawing this collection.
|
|
81057
|
+
takeInPage(pageLanded);
|
|
81058
|
+
return;
|
|
81059
|
+
}
|
|
80931
81060
|
// Before the items land: what is on screen has to stay where it is,
|
|
80932
81061
|
// and the DOM still shows the state to hold onto.
|
|
80933
81062
|
listItems.captureAnchor();
|
|
80934
|
-
|
|
80935
|
-
// it at another rank (it would be drawn twice), or when its rank is
|
|
80936
|
-
// past the end of the collection.
|
|
80937
|
-
const staleRanksNow = staleRanksRef.current;
|
|
80938
|
-
const pageEnd = pageStart + pageItems.length;
|
|
80939
|
-
let dropped = false;
|
|
80940
|
-
if (staleRanksNow.size > 0) {
|
|
80941
|
-
const pageIds = new Set();
|
|
80942
|
-
for (const pageItem of pageItems) {
|
|
80943
|
-
if (pageItem && pageItem.id !== undefined) {
|
|
80944
|
-
pageIds.add(pageItem.id);
|
|
80945
|
-
}
|
|
80946
|
-
}
|
|
80947
|
-
for (const rank of staleRanksNow) {
|
|
80948
|
-
if (rank >= pageStart && rank < pageEnd) {
|
|
80949
|
-
continue;
|
|
80950
|
-
}
|
|
80951
|
-
const staleItem = pages.byIndex.get(rank);
|
|
80952
|
-
if (rank >= pageCount || staleItem && pageIds.has(staleItem.id)) {
|
|
80953
|
-
staleRanksNow.delete(rank);
|
|
80954
|
-
pages.byIndex.delete(rank);
|
|
80955
|
-
dropped = true;
|
|
80956
|
-
}
|
|
80957
|
-
}
|
|
80958
|
-
}
|
|
80959
|
-
let i = 0;
|
|
80960
|
-
while (i < pageItems.length) {
|
|
80961
|
-
pages.byIndex.set(pageStart + i, pageItems[i]);
|
|
80962
|
-
staleRanksNow.delete(pageStart + i);
|
|
80963
|
-
i++;
|
|
80964
|
-
}
|
|
80965
|
-
pages.count = pageCount;
|
|
80966
|
-
// Which rank holds which id, kept by the source so a list drawing
|
|
80967
|
-
// this collection again finds it drawn (see readComposition above).
|
|
80968
|
-
if (itemsAction.writeComposition) {
|
|
80969
|
-
itemsAction.writeComposition({
|
|
80970
|
-
byIndex: pages.byIndex,
|
|
80971
|
-
count: pageCount,
|
|
80972
|
-
replace: dropped
|
|
80973
|
-
});
|
|
80974
|
-
}
|
|
80975
|
-
listItems.pagesSignal.value = listItems.pagesSignal.peek() + 1;
|
|
81063
|
+
pagesLandedRef.current.push(pageLanded);
|
|
80976
81064
|
setPageVersion(version => version + 1);
|
|
80977
81065
|
};
|
|
80978
81066
|
const failed = error => {
|
|
@@ -81017,9 +81105,20 @@ const useItemStore = ({
|
|
|
81017
81105
|
done(result);
|
|
81018
81106
|
}
|
|
81019
81107
|
};
|
|
81108
|
+
// Asked once the commit is over rather than from the effect: the list
|
|
81109
|
+
// frames its window after its runs, in that same commit — sized on the
|
|
81110
|
+
// screen, aimed at the item it is held on — and what the run asks for is
|
|
81111
|
+
// the window the list settles on. A render coming meanwhile asks instead.
|
|
81020
81112
|
useLayoutEffect(() => {
|
|
81021
|
-
|
|
81022
|
-
|
|
81113
|
+
askTurnRef.current++;
|
|
81114
|
+
const turn = askTurnRef.current;
|
|
81115
|
+
queueMicrotask(() => {
|
|
81116
|
+
if (turn !== askTurnRef.current || !mountedRef.current) {
|
|
81117
|
+
return;
|
|
81118
|
+
}
|
|
81119
|
+
ask();
|
|
81120
|
+
publishRequestState();
|
|
81121
|
+
});
|
|
81023
81122
|
});
|
|
81024
81123
|
}
|
|
81025
81124
|
};
|