@jsenv/navi 0.29.427 → 0.29.429
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 +187 -65
- package/dist/dev/jsenv_navi.js.map +5 -5
- package/dist/jsenv_navi.js +179 -59
- package/dist/jsenv_navi.js.map +5 -5
- package/docs/list_refresh.md +5 -4
- package/docs/scroll.md +4 -1
- package/package.json +2 -2
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -26867,10 +26867,11 @@ const createRangeReader = (
|
|
|
26867
26867
|
});
|
|
26868
26868
|
return { byIndex, count: composition.count };
|
|
26869
26869
|
};
|
|
26870
|
-
// `replace`
|
|
26871
|
-
//
|
|
26872
|
-
// so two lists reading the same
|
|
26873
|
-
// to one composition instead of
|
|
26870
|
+
// `replace` says the list dropped ranks it held (an item the collection moved
|
|
26871
|
+
// elsewhere, ranks past its end): kept here, they would come back at the next
|
|
26872
|
+
// mount. Otherwise the ranks are merged, so two lists reading the same
|
|
26873
|
+
// collection through their own windows add up to one composition instead of
|
|
26874
|
+
// taking turns erasing each other.
|
|
26874
26875
|
readRange.writeComposition = ({ byIndex, count, replace }) => {
|
|
26875
26876
|
const params = currentParams();
|
|
26876
26877
|
let composition = findComposition(params);
|
|
@@ -39813,6 +39814,16 @@ const resolveAfterSend = (target, requester) => {
|
|
|
39813
39814
|
}
|
|
39814
39815
|
return undefined;
|
|
39815
39816
|
};
|
|
39817
|
+
// What follows a send is caused by the send, not by the gesture: the send
|
|
39818
|
+
// answered the gesture and may have prevented it (an Enter must not also click
|
|
39819
|
+
// the submit button, nor activate the trigger of the popup it closed), and a
|
|
39820
|
+
// follow-up judged on that event is refused as a gesture someone cancelled.
|
|
39821
|
+
// Chained, so the gesture stays readable behind it.
|
|
39822
|
+
const createSentEvent = (event) => {
|
|
39823
|
+
const sentEvent = new CustomEvent("sent", { detail: {} });
|
|
39824
|
+
chainEvent(sentEvent, event);
|
|
39825
|
+
return sentEvent;
|
|
39826
|
+
};
|
|
39816
39827
|
|
|
39817
39828
|
registerNaviCommand("--navi-send", (source, event, { requester }) => {
|
|
39818
39829
|
const expandable = resolveExpandableAround(source);
|
|
@@ -39845,7 +39856,9 @@ registerNaviCommand("--navi-send", (source, event, { requester }) => {
|
|
|
39845
39856
|
source.getAttribute("data-after-send") ||
|
|
39846
39857
|
target.getAttribute("data-after-send");
|
|
39847
39858
|
if (afterSend) {
|
|
39848
|
-
triggerNaviCommand(target, afterSend, event, {
|
|
39859
|
+
triggerNaviCommand(target, afterSend, createSentEvent(event), {
|
|
39860
|
+
optional: true,
|
|
39861
|
+
});
|
|
39849
39862
|
}
|
|
39850
39863
|
return result;
|
|
39851
39864
|
},
|
|
@@ -39889,7 +39902,9 @@ registerNaviCommand("--navi-send", (source, event, { requester }) => {
|
|
|
39889
39902
|
if (!afterSend) {
|
|
39890
39903
|
return;
|
|
39891
39904
|
}
|
|
39892
|
-
triggerNaviCommand(source, afterSend, event, {
|
|
39905
|
+
triggerNaviCommand(source, afterSend, createSentEvent(event), {
|
|
39906
|
+
optional: true,
|
|
39907
|
+
});
|
|
39893
39908
|
};
|
|
39894
39909
|
const {
|
|
39895
39910
|
result: sent,
|
|
@@ -74110,9 +74125,12 @@ const useListScrollSync = ({
|
|
|
74110
74125
|
};
|
|
74111
74126
|
const [renderWindow, setRenderWindow] = useState(() => {
|
|
74112
74127
|
// Opening somewhere else than the beginning starts by framing there: the
|
|
74113
|
-
// items the list will draw are the items it will ask for.
|
|
74128
|
+
// items the list will draw are the items it will ask for. A named item is
|
|
74129
|
+
// framed where it stood when it was written down, which is where holdWindow
|
|
74130
|
+
// aims before anyone can say where it is.
|
|
74114
74131
|
const openAt = scrolled ?? defaultScrolled;
|
|
74115
|
-
const
|
|
74132
|
+
const openIndex = typeof openAt === "number" ? openAt : openAt && typeof openAt === "object" && typeof openAt.index === "number" ? openAt.index : null;
|
|
74133
|
+
const start = openIndex === null ? 0 : openIndex - itemsAboveOpening(openAt, firstWindowItemCount);
|
|
74116
74134
|
const startClamped = start < 0 ? 0 : start;
|
|
74117
74135
|
return {
|
|
74118
74136
|
start: startClamped,
|
|
@@ -74239,14 +74257,11 @@ const useListScrollSync = ({
|
|
|
74239
74257
|
if (wantedStart < 0) {
|
|
74240
74258
|
wantedStart = 0;
|
|
74241
74259
|
}
|
|
74242
|
-
|
|
74243
|
-
|
|
74244
|
-
|
|
74245
|
-
|
|
74246
|
-
|
|
74247
|
-
start: wantedStart,
|
|
74248
|
-
end: wantedStart + windowSize
|
|
74249
|
-
};
|
|
74260
|
+
// The window the hold frames goes into the state, not into this render
|
|
74261
|
+
// alone: the next render starts from the state, and once the item stands
|
|
74262
|
+
// inside the window the hold stops framing it — a window left where the
|
|
74263
|
+
// state had it would draw around another place.
|
|
74264
|
+
updateRenderWindow(wantedStart, wantedStart + windowSize, `held on item ${heldItem}`);
|
|
74250
74265
|
listItems.holdPending = false;
|
|
74251
74266
|
};
|
|
74252
74267
|
const pendingScrollRef = useRef();
|
|
@@ -74395,6 +74410,13 @@ const useListScrollSync = ({
|
|
|
74395
74410
|
return;
|
|
74396
74411
|
}
|
|
74397
74412
|
hasBeenDisplayedRef.current = true;
|
|
74413
|
+
const place = startPlaceRef.current;
|
|
74414
|
+
if (!place.userTookOver && place.wanted !== "start" && place.wanted !== undefined) {
|
|
74415
|
+
// Held somewhere: where the list opens is the hold's to say (see
|
|
74416
|
+
// placeWhereHeld). Scrolled here too, the list would go to the top or
|
|
74417
|
+
// the selected item for as long as the hold takes to put it back.
|
|
74418
|
+
return;
|
|
74419
|
+
}
|
|
74398
74420
|
const items = listItems.itemsSignal.peek();
|
|
74399
74421
|
const firstSelected = items.find(i => {
|
|
74400
74422
|
if (i.selected) {
|
|
@@ -75097,12 +75119,14 @@ const useListScrollSync = ({
|
|
|
75097
75119
|
const spare = budget > screen ? budget - screen : 0;
|
|
75098
75120
|
const behindSize = countsItems ? Math.floor(spare / 4) : spare / 4;
|
|
75099
75121
|
const aheadSize = spare - behindSize;
|
|
75100
|
-
|
|
75101
|
-
|
|
75102
|
-
|
|
75103
|
-
|
|
75104
|
-
|
|
75105
|
-
|
|
75122
|
+
// Said only when the budget holds nothing past the screen: the blank is
|
|
75123
|
+
// then certain. Past the screen, whether a fling outruns the window is
|
|
75124
|
+
// what the device and the rest of the main thread's work decide, and a
|
|
75125
|
+
// number of items cannot tell it — two one-line items are 76 px, two
|
|
75126
|
+
// cards a whole screen. That is measured on the list, not guessed here.
|
|
75127
|
+
if (stage === "steady" && !budgetWarnedRef.current && bandEnd > bandStart && spare === 0) {
|
|
75128
|
+
budgetWarnedRef.current = true;
|
|
75129
|
+
console.warn(`List: renderBudget=${renderBudget.value}${renderBudget.unit} holds no more than what the screen shows (${bandEnd - bandStart} items on it): the screen goes blank past it as soon as the list scrolls. Give it more than a screen — "150%" of the box that scrolls it, say.`);
|
|
75106
75130
|
}
|
|
75107
75131
|
if (!force) {
|
|
75108
75132
|
const roomAround = readRoomAround({
|
|
@@ -77673,19 +77697,57 @@ const useRunItems = (store, {
|
|
|
77673
77697
|
// rebuilt as the window slides — a group holds the items of its day that are
|
|
77674
77698
|
// currently drawn, which is exactly the span its label has to survive.
|
|
77675
77699
|
let group = null;
|
|
77700
|
+
// Two groups can still share a key (a failure band standing mid-group, data
|
|
77701
|
+
// not sorted by group): the later ones are told apart by their rank among
|
|
77702
|
+
// them, so the first keeps its element. A group keyed by where it starts
|
|
77703
|
+
// would lose its element each time the window slides past its first item.
|
|
77704
|
+
const groupCountByKey = new Map();
|
|
77676
77705
|
const closeGroup = () => {
|
|
77677
77706
|
if (!group) {
|
|
77678
77707
|
return;
|
|
77679
77708
|
}
|
|
77709
|
+
const groupCount = (groupCountByKey.get(group.key) || 0) + 1;
|
|
77710
|
+
groupCountByKey.set(group.key, groupCount);
|
|
77680
77711
|
nodes.push(jsx(ListItemGroup, {
|
|
77681
77712
|
label: group.label,
|
|
77682
77713
|
labelProps: group.labelProps,
|
|
77683
77714
|
children: group.children
|
|
77684
|
-
}, `${ownerId}_group_${group.key}`));
|
|
77715
|
+
}, groupCount === 1 ? `${ownerId}_group_${group.key}` : `${ownerId}_group_${group.key}_${groupCount}`));
|
|
77685
77716
|
group = null;
|
|
77686
77717
|
};
|
|
77718
|
+
// An item not held has no group of its own. Between two items of the open
|
|
77719
|
+
// group it is a line of that group whose content has not arrived: drawn
|
|
77720
|
+
// outside, it would cut the group in two and show its label twice. A hole at
|
|
77721
|
+
// a group's edge stays outside — nothing says which side it belongs to.
|
|
77722
|
+
let holeTo = -1;
|
|
77723
|
+
let holeGroupKey;
|
|
77724
|
+
const groupKeyOfHole = itemIndex => {
|
|
77725
|
+
if (itemIndex < holeTo) {
|
|
77726
|
+
return holeGroupKey;
|
|
77727
|
+
}
|
|
77728
|
+
holeTo = itemIndex + 1;
|
|
77729
|
+
while (holeTo < windowTo && holeTo !== failureFrom && getItemAt(holeTo) === undefined) {
|
|
77730
|
+
holeTo++;
|
|
77731
|
+
}
|
|
77732
|
+
holeGroupKey = undefined;
|
|
77733
|
+
if (group && holeTo < windowTo && holeTo !== failureFrom) {
|
|
77734
|
+
const keyAfterHole = groupBy(getItemAt(holeTo), holeTo);
|
|
77735
|
+
if (keyAfterHole === group.key) {
|
|
77736
|
+
holeGroupKey = keyAfterHole;
|
|
77737
|
+
}
|
|
77738
|
+
}
|
|
77739
|
+
return holeGroupKey;
|
|
77740
|
+
};
|
|
77687
77741
|
// Which group an item belongs to, or undefined when it belongs to none.
|
|
77688
|
-
const groupKeyOf = (item, itemIndex) =>
|
|
77742
|
+
const groupKeyOf = (item, itemIndex) => {
|
|
77743
|
+
if (!groupBy) {
|
|
77744
|
+
return undefined;
|
|
77745
|
+
}
|
|
77746
|
+
if (item === undefined) {
|
|
77747
|
+
return groupKeyOfHole(itemIndex);
|
|
77748
|
+
}
|
|
77749
|
+
return groupBy(item, itemIndex);
|
|
77750
|
+
};
|
|
77689
77751
|
const pushItem = (itemNode, item, itemIndex, groupKey) => {
|
|
77690
77752
|
if (groupKey === undefined) {
|
|
77691
77753
|
closeGroup();
|
|
@@ -78022,10 +78084,15 @@ const useItemStore = ({
|
|
|
78022
78084
|
}
|
|
78023
78085
|
const pages = pagesRef.current;
|
|
78024
78086
|
const [, setPageVersion] = useState(0);
|
|
78025
|
-
// The
|
|
78026
|
-
//
|
|
78027
|
-
//
|
|
78028
|
-
|
|
78087
|
+
// The ranks whose item is from before: the run came back to the screen, or
|
|
78088
|
+
// the source said the collection moved. They stay drawn until a page confirms
|
|
78089
|
+
// or replaces them, rank by rank. A page covers what the window framed when it
|
|
78090
|
+
// was asked for, and the window keeps growing meanwhile: dropping what the
|
|
78091
|
+
// page did not cover empties items on screen.
|
|
78092
|
+
const staleRanksRef = useRef(null);
|
|
78093
|
+
if (staleRanksRef.current === null) {
|
|
78094
|
+
staleRanksRef.current = restored ? new Set(pages.byIndex.keys()) : new Set();
|
|
78095
|
+
}
|
|
78029
78096
|
const [refreshing, setRefreshing] = useState(false);
|
|
78030
78097
|
// A source that says when what it reads has moved (a resource range reader
|
|
78031
78098
|
// does: see rerunOn.GET_RANGE) is heard here — a write deciding who belongs
|
|
@@ -78036,7 +78103,7 @@ const useItemStore = ({
|
|
|
78036
78103
|
const invalidationRef = useRef(invalidation);
|
|
78037
78104
|
if (invalidationRef.current !== invalidation) {
|
|
78038
78105
|
invalidationRef.current = invalidation;
|
|
78039
|
-
|
|
78106
|
+
staleRanksRef.current = new Set(pages.byIndex.keys());
|
|
78040
78107
|
}
|
|
78041
78108
|
// The one request in flight, with the means to call it off: a page asked for
|
|
78042
78109
|
// a window the list has left is work the server and the browser are doing for
|
|
@@ -78069,11 +78136,6 @@ const useItemStore = ({
|
|
|
78069
78136
|
// It stands for a page of them: a list that is about to be filled looks
|
|
78070
78137
|
// like items on their way, not like an empty list.
|
|
78071
78138
|
const itemCount = pages.count ?? count ?? listItems.pageSize;
|
|
78072
|
-
// A run that never received anything has nothing to keep on screen: asking
|
|
78073
|
-
// again is its first ask, not a refresh.
|
|
78074
|
-
if (staleRef.current && pages.count === undefined) {
|
|
78075
|
-
staleRef.current = false;
|
|
78076
|
-
}
|
|
78077
78139
|
useLayoutEffect(() => {
|
|
78078
78140
|
if (!refreshing) {
|
|
78079
78141
|
return null;
|
|
@@ -78146,9 +78208,11 @@ const useItemStore = ({
|
|
|
78146
78208
|
const keepFrom = windowFrom - ITEM_STORE_KEEP_AROUND;
|
|
78147
78209
|
const keepTo = windowTo + ITEM_STORE_KEEP_AROUND;
|
|
78148
78210
|
if (pages.byIndex.size > budget) {
|
|
78211
|
+
const staleRanks = staleRanksRef.current;
|
|
78149
78212
|
for (const index of pages.byIndex.keys()) {
|
|
78150
78213
|
if (index < keepFrom || index > keepTo) {
|
|
78151
78214
|
pages.byIndex.delete(index);
|
|
78215
|
+
staleRanks.delete(index);
|
|
78152
78216
|
}
|
|
78153
78217
|
}
|
|
78154
78218
|
}
|
|
@@ -78183,10 +78247,24 @@ const useItemStore = ({
|
|
|
78183
78247
|
let start = missingStart;
|
|
78184
78248
|
let end = missingEnd;
|
|
78185
78249
|
let around;
|
|
78186
|
-
//
|
|
78187
|
-
//
|
|
78188
|
-
|
|
78189
|
-
|
|
78250
|
+
// The window draws items from before: they are asked for again, and stay
|
|
78251
|
+
// drawn meanwhile.
|
|
78252
|
+
const staleRanks = staleRanksRef.current;
|
|
78253
|
+
let staleFrom = -1;
|
|
78254
|
+
let staleTo = -1;
|
|
78255
|
+
if (staleRanks.size > 0) {
|
|
78256
|
+
let rank = windowFrom;
|
|
78257
|
+
while (rank < windowTo) {
|
|
78258
|
+
if (staleRanks.has(rank)) {
|
|
78259
|
+
if (staleFrom === -1) {
|
|
78260
|
+
staleFrom = rank;
|
|
78261
|
+
}
|
|
78262
|
+
staleTo = rank;
|
|
78263
|
+
}
|
|
78264
|
+
rank++;
|
|
78265
|
+
}
|
|
78266
|
+
}
|
|
78267
|
+
const revalidating = staleFrom !== -1;
|
|
78190
78268
|
// The list is held on an item nothing on screen leads to: the items it holds
|
|
78191
78269
|
// do not contain it, so no window it could draw will ever bring it. Only
|
|
78192
78270
|
// asking for it by name does.
|
|
@@ -78203,18 +78281,36 @@ const useItemStore = ({
|
|
|
78203
78281
|
start = from < 0 ? 0 : from;
|
|
78204
78282
|
end = start + budget - 1;
|
|
78205
78283
|
} else if (revalidating) {
|
|
78206
|
-
|
|
78207
|
-
|
|
78208
|
-
if (
|
|
78209
|
-
|
|
78210
|
-
|
|
78211
|
-
|
|
78212
|
-
|
|
78213
|
-
|
|
78214
|
-
|
|
78215
|
-
|
|
78216
|
-
|
|
78217
|
-
|
|
78284
|
+
// The items from before that the window draws, and the missing ones
|
|
78285
|
+
// with them: one ask.
|
|
78286
|
+
if (start === -1 || staleFrom < start) {
|
|
78287
|
+
start = staleFrom;
|
|
78288
|
+
}
|
|
78289
|
+
if (staleTo > end) {
|
|
78290
|
+
end = staleTo;
|
|
78291
|
+
}
|
|
78292
|
+
// Grown over the items from before on either side, up to a page: the
|
|
78293
|
+
// window grows past its first picture right after it is painted, and
|
|
78294
|
+
// what it grows onto would otherwise be asked for once more.
|
|
78295
|
+
while (end - start + 1 < budget) {
|
|
78296
|
+
const staleBefore = staleRanks.has(start - 1);
|
|
78297
|
+
const staleAfter = staleRanks.has(end + 1);
|
|
78298
|
+
if (!staleBefore && !staleAfter) {
|
|
78299
|
+
break;
|
|
78300
|
+
}
|
|
78301
|
+
if (staleBefore) {
|
|
78302
|
+
start--;
|
|
78303
|
+
}
|
|
78304
|
+
if (staleAfter && end - start + 1 < budget) {
|
|
78305
|
+
end++;
|
|
78306
|
+
}
|
|
78307
|
+
}
|
|
78308
|
+
// Anchored on the first item from before on screen: a source
|
|
78309
|
+
// paginating by cursor gets an item to count from, and the reading
|
|
78310
|
+
// position is what must survive.
|
|
78311
|
+
const firstStale = pages.byIndex.get(staleFrom);
|
|
78312
|
+
if (firstStale && firstStale.id !== undefined) {
|
|
78313
|
+
around = firstStale.id;
|
|
78218
78314
|
}
|
|
78219
78315
|
} else if (pages.count === undefined) {
|
|
78220
78316
|
const scrolled = listItems.scrolled;
|
|
@@ -78268,7 +78364,8 @@ const useItemStore = ({
|
|
|
78268
78364
|
debugAsk("already revalidating");
|
|
78269
78365
|
return;
|
|
78270
78366
|
}
|
|
78271
|
-
// A page for
|
|
78367
|
+
// A page asked for before the items went stale answers for the
|
|
78368
|
+
// collection as it was.
|
|
78272
78369
|
request.controller?.abort();
|
|
78273
78370
|
request.busy = false;
|
|
78274
78371
|
}
|
|
@@ -78289,11 +78386,11 @@ const useItemStore = ({
|
|
|
78289
78386
|
request.controller?.abort();
|
|
78290
78387
|
request.busy = false;
|
|
78291
78388
|
}
|
|
78292
|
-
const held = pages.byIndex.size;
|
|
78293
78389
|
// Asking again for a range that was already asked for, having received
|
|
78294
|
-
// nothing since, can only produce the same answer
|
|
78295
|
-
//
|
|
78296
|
-
|
|
78390
|
+
// nothing since, can only produce the same answer — unless the
|
|
78391
|
+
// collection moved since, which is what an invalidation says.
|
|
78392
|
+
const held = `${pages.byIndex.size}/${staleRanks.size}/${invalidation}`;
|
|
78393
|
+
if (request.start === start && request.end === end && request.held === held) {
|
|
78297
78394
|
debugAsk("this range was asked for already");
|
|
78298
78395
|
return;
|
|
78299
78396
|
}
|
|
@@ -78329,7 +78426,6 @@ const useItemStore = ({
|
|
|
78329
78426
|
request.revalidating = false;
|
|
78330
78427
|
setFailure(null);
|
|
78331
78428
|
if (revalidating) {
|
|
78332
|
-
staleRef.current = false;
|
|
78333
78429
|
setRefreshing(false);
|
|
78334
78430
|
}
|
|
78335
78431
|
publishRequestState();
|
|
@@ -78348,15 +78444,35 @@ const useItemStore = ({
|
|
|
78348
78444
|
// Before the items land: what is on screen has to stay where it is,
|
|
78349
78445
|
// and the DOM still shows the state to hold onto.
|
|
78350
78446
|
listItems.captureAnchor();
|
|
78351
|
-
|
|
78352
|
-
|
|
78353
|
-
|
|
78354
|
-
|
|
78355
|
-
|
|
78447
|
+
// An item from before is gone from where it stood when the page puts
|
|
78448
|
+
// it at another rank (it would be drawn twice), or when its rank is
|
|
78449
|
+
// past the end of the collection.
|
|
78450
|
+
const staleRanksNow = staleRanksRef.current;
|
|
78451
|
+
const pageEnd = pageStart + pageItems.length;
|
|
78452
|
+
let dropped = false;
|
|
78453
|
+
if (staleRanksNow.size > 0) {
|
|
78454
|
+
const pageIds = new Set();
|
|
78455
|
+
for (const pageItem of pageItems) {
|
|
78456
|
+
if (pageItem && pageItem.id !== undefined) {
|
|
78457
|
+
pageIds.add(pageItem.id);
|
|
78458
|
+
}
|
|
78459
|
+
}
|
|
78460
|
+
for (const rank of staleRanksNow) {
|
|
78461
|
+
if (rank >= pageStart && rank < pageEnd) {
|
|
78462
|
+
continue;
|
|
78463
|
+
}
|
|
78464
|
+
const staleItem = pages.byIndex.get(rank);
|
|
78465
|
+
if (rank >= pageCount || staleItem && pageIds.has(staleItem.id)) {
|
|
78466
|
+
staleRanksNow.delete(rank);
|
|
78467
|
+
pages.byIndex.delete(rank);
|
|
78468
|
+
dropped = true;
|
|
78469
|
+
}
|
|
78470
|
+
}
|
|
78356
78471
|
}
|
|
78357
78472
|
let i = 0;
|
|
78358
78473
|
while (i < pageItems.length) {
|
|
78359
78474
|
pages.byIndex.set(pageStart + i, pageItems[i]);
|
|
78475
|
+
staleRanksNow.delete(pageStart + i);
|
|
78360
78476
|
i++;
|
|
78361
78477
|
}
|
|
78362
78478
|
pages.count = pageCount;
|
|
@@ -78366,7 +78482,7 @@ const useItemStore = ({
|
|
|
78366
78482
|
itemsAction.writeComposition({
|
|
78367
78483
|
byIndex: pages.byIndex,
|
|
78368
78484
|
count: pageCount,
|
|
78369
|
-
replace:
|
|
78485
|
+
replace: dropped
|
|
78370
78486
|
});
|
|
78371
78487
|
}
|
|
78372
78488
|
listItems.pagesSignal.value = listItems.pagesSignal.peek() + 1;
|
|
@@ -78381,9 +78497,14 @@ const useItemStore = ({
|
|
|
78381
78497
|
request.revalidating = false;
|
|
78382
78498
|
publishRequestState();
|
|
78383
78499
|
if (revalidating) {
|
|
78384
|
-
// The items from before stay
|
|
78500
|
+
// The items from before stay, and are not asked for again until the
|
|
78501
|
+
// source says the collection moved: a revalidation that failed has
|
|
78385
78502
|
// nothing better to put in their place.
|
|
78386
|
-
|
|
78503
|
+
let rank = start;
|
|
78504
|
+
while (rank <= end) {
|
|
78505
|
+
staleRanksRef.current.delete(rank);
|
|
78506
|
+
rank++;
|
|
78507
|
+
}
|
|
78387
78508
|
setRefreshing(false);
|
|
78388
78509
|
return;
|
|
78389
78510
|
}
|
|
@@ -78700,7 +78821,8 @@ const ListResolved = /*#__PURE__*/createComponentResolver([ListFirstResolver, Li
|
|
|
78700
78821
|
* "Many rows"). The window keeps three quarters of what the screen leaves of
|
|
78701
78822
|
* it ahead of the scroll, and moves once that falls under half a screen; it
|
|
78702
78823
|
* has to hold more than the screen shows, with room for that lookahead — the
|
|
78703
|
-
* list warns when it
|
|
78824
|
+
* list warns when it holds no more than the screen. How much more is
|
|
78825
|
+
* measured: fling the list on the slowest device it runs on.
|
|
78704
78826
|
*
|
|
78705
78827
|
* `{ initial, after }` for a list whose first picture is taken as it is
|
|
78706
78828
|
* built — drawn in the click that opens a popup, or in the update callback
|