@jsenv/navi 0.29.138 → 0.29.140
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/jsenv_navi.js +352 -54
- package/dist/jsenv_navi.js.map +43 -14
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -33367,6 +33367,34 @@ const isNamelessGrouping = (child, uiState) =>
|
|
|
33367
33367
|
typeof uiState === "object" &&
|
|
33368
33368
|
!Array.isArray(uiState);
|
|
33369
33369
|
|
|
33370
|
+
// Is this value the empty the child writes when it holds nothing? Reading it
|
|
33371
|
+
// back out of the object means the child holds nothing — which is `undefined`,
|
|
33372
|
+
// not the empty itself (see the object group's distributeChildUIState below).
|
|
33373
|
+
const uiStateIsChildEmpty = (uiState, child) => {
|
|
33374
|
+
const { emptyUIState } = child;
|
|
33375
|
+
if (emptyUIState === undefined) {
|
|
33376
|
+
return false;
|
|
33377
|
+
}
|
|
33378
|
+
if (uiState === emptyUIState) {
|
|
33379
|
+
return true;
|
|
33380
|
+
}
|
|
33381
|
+
// The empties are shapes, not identities: what comes back down went through
|
|
33382
|
+
// a restore, a signal or an action and is a different array/object than the
|
|
33383
|
+
// EMPTY_ARRAY/EMPTY_OBJECT that went up.
|
|
33384
|
+
if (Array.isArray(emptyUIState)) {
|
|
33385
|
+
return Array.isArray(uiState) && uiState.length === 0;
|
|
33386
|
+
}
|
|
33387
|
+
if (typeof emptyUIState === "object" && emptyUIState !== null) {
|
|
33388
|
+
return (
|
|
33389
|
+
uiState !== null &&
|
|
33390
|
+
typeof uiState === "object" &&
|
|
33391
|
+
!Array.isArray(uiState) &&
|
|
33392
|
+
Object.keys(uiState).length === 0
|
|
33393
|
+
);
|
|
33394
|
+
}
|
|
33395
|
+
return false;
|
|
33396
|
+
};
|
|
33397
|
+
|
|
33370
33398
|
const firstDefinedChildUIState = (children) => {
|
|
33371
33399
|
for (const child of children) {
|
|
33372
33400
|
const childUIState = child.uiState;
|
|
@@ -33504,7 +33532,19 @@ const GROUP_DEFAULTS = {
|
|
|
33504
33532
|
typeof newUIState === "object" &&
|
|
33505
33533
|
Object.prototype.hasOwnProperty.call(newUIState, childName)
|
|
33506
33534
|
) {
|
|
33507
|
-
|
|
33535
|
+
const childUIState = newUIState[childName];
|
|
33536
|
+
// The exact inverse of the empty aggregateChildStates wrote just
|
|
33537
|
+
// above: what a child holding nothing put into the object
|
|
33538
|
+
// must come back out as nothing. Handed back as-is it reads as a value
|
|
33539
|
+
// — a checkbox takes any state that is not `undefined` as checked,
|
|
33540
|
+
// `false` included (see the `checked` line in control_hooks'
|
|
33541
|
+
// toDomProps) — so restoring the object (a picker cancelling on Escape)
|
|
33542
|
+
// would check every box it contains, and the group would then re-derive
|
|
33543
|
+
// the `true` nobody said.
|
|
33544
|
+
if (uiStateIsChildEmpty(childUIState, child)) {
|
|
33545
|
+
return undefined;
|
|
33546
|
+
}
|
|
33547
|
+
return childUIState;
|
|
33508
33548
|
}
|
|
33509
33549
|
// Merged in on the way up (see above), so on the way down it takes the
|
|
33510
33550
|
// whole object and picks out its own keys — the same value it produced.
|
|
@@ -33732,6 +33772,15 @@ const useUIGroupStateController = (
|
|
|
33732
33772
|
// wheels nobody turned have settled nothing. Only the default shapes
|
|
33733
33773
|
// fall back to the empty of their type, where "no child says anything"
|
|
33734
33774
|
// and "the value is empty" are the same sentence.
|
|
33775
|
+
//
|
|
33776
|
+
// Not `fallbackState !== undefined`, tempting as it looks: `stateType`
|
|
33777
|
+
// is what the group's OWN shape would be, and a caller-supplied
|
|
33778
|
+
// aggregate is free to hold another one — TimeSpin and WheelTime are
|
|
33779
|
+
// "HH:MM" strings inside groups declared `stateType: "object"`, and
|
|
33780
|
+
// handing them `{}` for "unanswered" would empty a signal holding a
|
|
33781
|
+
// time. An aggregate that does want the empty of the declared type
|
|
33782
|
+
// takes it: it is handed `fallbackState` as its second argument (see
|
|
33783
|
+
// ListSelectable, which returns it for an emptied multiple list).
|
|
33735
33784
|
return stateShapeIsTheDefaultOne ? fallbackState : undefined;
|
|
33736
33785
|
};
|
|
33737
33786
|
|
|
@@ -61306,7 +61355,13 @@ const ListSelectable = props => {
|
|
|
61306
61355
|
if (selectionRef.current === undefined) {
|
|
61307
61356
|
selectionRef.current = Object.hasOwn(props, "value") ? props.value : props.defaultValue;
|
|
61308
61357
|
}
|
|
61309
|
-
|
|
61358
|
+
// `fallbackState` is the empty of the shape the list declared below
|
|
61359
|
+
// (`stateType`): `[]` for a multiple list, nothing for a single one. Taking
|
|
61360
|
+
// it is what lets an emptied list say "empty" — `undefined` is the word for
|
|
61361
|
+
// "unset", and a bound stateSignal reads that as "nothing decided here, go
|
|
61362
|
+
// back to the default" (see docs/control_value.md), which is how a list
|
|
61363
|
+
// emptied down to its last row puts that row back on reload.
|
|
61364
|
+
const aggregateChildStates = (children, fallbackState) => {
|
|
61310
61365
|
const kept = selectionRef.current;
|
|
61311
61366
|
if (multiple) {
|
|
61312
61367
|
const drawnValues = new Set(children.map(child => child.props.value));
|
|
@@ -61316,7 +61371,7 @@ const ListSelectable = props => {
|
|
|
61316
61371
|
stillSelected.push(child.uiState);
|
|
61317
61372
|
}
|
|
61318
61373
|
}
|
|
61319
|
-
const values = stillSelected.length === 0 ?
|
|
61374
|
+
const values = stillSelected.length === 0 ? fallbackState : stillSelected;
|
|
61320
61375
|
selectionRef.current = values;
|
|
61321
61376
|
return values;
|
|
61322
61377
|
}
|
|
@@ -61929,6 +61984,13 @@ const ListVirtualContext = createContext(null);
|
|
|
61929
61984
|
// that returning a component of one's own — instead of a bare <List.Item> —
|
|
61930
61985
|
// works the same way.
|
|
61931
61986
|
const ListRowContext = createContext(null);
|
|
61987
|
+
// The slot a child of the list stands in — which one it is, and where it sits
|
|
61988
|
+
// among its siblings (see ListDeclaredChildren). A row takes its place in the
|
|
61989
|
+
// collection by slot, and hears through this context that its slot moved: a
|
|
61990
|
+
// context subscriber is re-rendered even when preact skipped the component
|
|
61991
|
+
// that holds it, which is what lets a row nobody rebuilt follow the list all
|
|
61992
|
+
// the same.
|
|
61993
|
+
const ListSlotContext = createContext(null);
|
|
61932
61994
|
const css$x = /* css */`
|
|
61933
61995
|
@layer navi {
|
|
61934
61996
|
.navi_list_container {
|
|
@@ -62932,24 +62994,11 @@ const ListFirstResolver = props => {
|
|
|
62932
62994
|
props.ref = props.ref || refDefault;
|
|
62933
62995
|
const idDefault = useId();
|
|
62934
62996
|
props.id = props.id || idDefault;
|
|
62935
|
-
// A new pass every time the caller walks the children: they are about to
|
|
62936
|
-
// say again, in order, which rows of the collection they stand for. Decided
|
|
62937
|
-
// here, on the children as the caller gave them. Further down the chain a
|
|
62938
|
-
// resolver re-rendering on its own hands the rows down inside a vnode of its
|
|
62939
|
-
// own (ListSelectable wraps them in the group's contexts) — but the rows are
|
|
62940
|
-
// the very vnodes preact already holds, and it skips them: nothing is said
|
|
62941
|
-
// again, so nothing may be asked again either (see createListVirtual).
|
|
62942
62997
|
const virtualRef = useRef(null);
|
|
62943
62998
|
if (!virtualRef.current) {
|
|
62944
62999
|
virtualRef.current = createListVirtual();
|
|
62945
63000
|
}
|
|
62946
|
-
|
|
62947
|
-
const childrenPreviousRef = useRef(undefined);
|
|
62948
|
-
if (childrenPreviousRef.current !== props.children) {
|
|
62949
|
-
childrenPreviousRef.current = props.children;
|
|
62950
|
-
virtual.openPass();
|
|
62951
|
-
}
|
|
62952
|
-
props.virtual = virtual;
|
|
63001
|
+
props.virtual = virtualRef.current;
|
|
62953
63002
|
return jsx(Next, {
|
|
62954
63003
|
...props
|
|
62955
63004
|
});
|
|
@@ -64685,7 +64734,9 @@ const UnorderedList = ({
|
|
|
64685
64734
|
value: null,
|
|
64686
64735
|
children: jsx(ListColumnsContext.Provider, {
|
|
64687
64736
|
value: columns || null,
|
|
64688
|
-
children:
|
|
64737
|
+
children: jsx(ListDeclaredChildren, {
|
|
64738
|
+
children: children
|
|
64739
|
+
})
|
|
64689
64740
|
})
|
|
64690
64741
|
})
|
|
64691
64742
|
})
|
|
@@ -64896,6 +64947,9 @@ const ListItemUI = props => {
|
|
|
64896
64947
|
// registered the row, decided it is inside the render window, and placed its
|
|
64897
64948
|
// separator. All that is left here is to draw it.
|
|
64898
64949
|
const row = useContext(ListRowContext);
|
|
64950
|
+
// Where this row was declared, when it was declared one by one (see
|
|
64951
|
+
// ListDeclaredChildren).
|
|
64952
|
+
const slot = useContext(ListSlotContext);
|
|
64899
64953
|
// There is no standalone match/matchScore/highlight prop — participation
|
|
64900
64954
|
// in a matching system (search, filter…) only goes through `matchInfo`
|
|
64901
64955
|
// (e.g. useSearchText's getItemMatchInfo(item): { match, matchScore,
|
|
@@ -64919,12 +64973,22 @@ const ListItemUI = props => {
|
|
|
64919
64973
|
}
|
|
64920
64974
|
}
|
|
64921
64975
|
// Where a row sits is where it was declared, full stop: a list is written in
|
|
64922
|
-
// the order it reads.
|
|
64923
|
-
//
|
|
64924
|
-
// already knows its place; the run gave it.
|
|
64925
|
-
if (!row
|
|
64926
|
-
|
|
64976
|
+
// the order it reads. Its slot is what says that — a search that reorders
|
|
64977
|
+
// rows reorders the rows it declares, and the slots follow. A row drawn by a
|
|
64978
|
+
// run already knows its place; the run gave it.
|
|
64979
|
+
if (!row) {
|
|
64980
|
+
if (props.filtered) {
|
|
64981
|
+
virtual.drop(props.id);
|
|
64982
|
+
} else {
|
|
64983
|
+
props.index = virtual.take(props.id, 1, slot ? slot.id : props.id);
|
|
64984
|
+
}
|
|
64927
64985
|
}
|
|
64986
|
+
const rowId = props.id;
|
|
64987
|
+
useLayoutEffect(() => {
|
|
64988
|
+
return () => {
|
|
64989
|
+
virtual.drop(rowId);
|
|
64990
|
+
};
|
|
64991
|
+
}, []);
|
|
64928
64992
|
// Every row that is drawn registers itself, whether it was declared one by
|
|
64929
64993
|
// one or drawn by a run: what it says about itself (its value, whether it is
|
|
64930
64994
|
// selected) is written where it is drawn, in one place.
|
|
@@ -65281,12 +65345,19 @@ List.Item = ListItem;
|
|
|
65281
65345
|
// where each child's rows start.
|
|
65282
65346
|
//
|
|
65283
65347
|
// A child knows how many rows it stands for but not what was declared before
|
|
65284
|
-
// it,
|
|
65285
|
-
//
|
|
65286
|
-
//
|
|
65287
|
-
//
|
|
65288
|
-
//
|
|
65289
|
-
//
|
|
65348
|
+
// it, and it cannot deduce that from when it renders: a render is free to skip
|
|
65349
|
+
// it. A child that draws from signals and whose props are all referentially
|
|
65350
|
+
// === the previous ones does not render again (@preact/signals installs a
|
|
65351
|
+
// shouldComponentUpdate that says so), which is what any child nobody rebuilt
|
|
65352
|
+
// this frame is — and children numbered as they render would then slide up
|
|
65353
|
+
// into the place of the one that was skipped.
|
|
65354
|
+
//
|
|
65355
|
+
// So the places are read off the walk instead of off the renders: the list
|
|
65356
|
+
// names a slot for each of its children and declares them here, in order,
|
|
65357
|
+
// before any of them renders (see ListDeclaredChildren). A child then takes
|
|
65358
|
+
// its place BY SLOT and keeps it for as long as its slot stands — whether it
|
|
65359
|
+
// renders again or not — while a child whose slot the walk no longer names
|
|
65360
|
+
// loses its place in that same render, so nothing removed is ever counted.
|
|
65290
65361
|
const createListVirtual = () => {
|
|
65291
65362
|
const totalSignal = signal(0);
|
|
65292
65363
|
// Bumped whenever a run takes in rows. The list itself has to hear about it:
|
|
@@ -65298,10 +65369,101 @@ const createListVirtual = () => {
|
|
|
65298
65369
|
// an attribute: what is drawn is from before, and the app may want to say so
|
|
65299
65370
|
// without taking anything away.
|
|
65300
65371
|
const refreshingSignal = signal(0);
|
|
65372
|
+
// Where the walk put each slot: the slot it lives in (a group walks its own
|
|
65373
|
+
// rows, inside the slot the list gave the group) and its rank among the
|
|
65374
|
+
// slots declared with it.
|
|
65375
|
+
const slotById = new Map();
|
|
65376
|
+
// What stands in a slot once it has rendered: the row, or the run of rows,
|
|
65377
|
+
// that took the place, and how many rows of the collection it stands for.
|
|
65378
|
+
const ownerById = new Map();
|
|
65301
65379
|
const placeByOwner = new Map();
|
|
65380
|
+
// The owners in the order their slots put them, and how many rows they stand
|
|
65381
|
+
// for together: kept so that a child declared after all the others — a whole
|
|
65382
|
+
// first render, and anything the list gains at its end — is placed without
|
|
65383
|
+
// going over the others again.
|
|
65384
|
+
const orderedOwnerIds = [];
|
|
65385
|
+
let rowTotal = 0;
|
|
65302
65386
|
const locatorByOwner = new Map();
|
|
65303
|
-
|
|
65304
|
-
|
|
65387
|
+
const pathCache = new Map();
|
|
65388
|
+
// Tells two owners sharing a slot apart (several rows inside one child of
|
|
65389
|
+
// the list), in the order they first took a place.
|
|
65390
|
+
let sequence = 0;
|
|
65391
|
+
let placesStale = false;
|
|
65392
|
+
|
|
65393
|
+
// Whatever the slot held is gone with it, and so is whatever its own walk
|
|
65394
|
+
// declared inside it.
|
|
65395
|
+
const dropSlot = slotId => {
|
|
65396
|
+
slotById.delete(slotId);
|
|
65397
|
+
for (const [ownerId, owner] of ownerById) {
|
|
65398
|
+
if (owner.slotId === slotId) {
|
|
65399
|
+
ownerById.delete(ownerId);
|
|
65400
|
+
placeByOwner.delete(ownerId);
|
|
65401
|
+
}
|
|
65402
|
+
}
|
|
65403
|
+
for (const [otherSlotId, slot] of slotById) {
|
|
65404
|
+
if (slot.parentId === slotId) {
|
|
65405
|
+
dropSlot(otherSlotId);
|
|
65406
|
+
}
|
|
65407
|
+
}
|
|
65408
|
+
};
|
|
65409
|
+
// Where a slot sits, said as the ranks of the slots it lives in, outermost
|
|
65410
|
+
// first: comparing two of them keeps a group's rows inside their group and
|
|
65411
|
+
// the groups where the list declared them.
|
|
65412
|
+
const pathOf = slotId => {
|
|
65413
|
+
const pathCached = pathCache.get(slotId);
|
|
65414
|
+
if (pathCached) {
|
|
65415
|
+
return pathCached;
|
|
65416
|
+
}
|
|
65417
|
+
const slot = slotById.get(slotId);
|
|
65418
|
+
if (!slot) {
|
|
65419
|
+
return null;
|
|
65420
|
+
}
|
|
65421
|
+
let path;
|
|
65422
|
+
if (slot.parentId === null) {
|
|
65423
|
+
path = [slot.order];
|
|
65424
|
+
} else {
|
|
65425
|
+
const parentPath = pathOf(slot.parentId);
|
|
65426
|
+
path = parentPath === null ? [slot.order] : [...parentPath, slot.order];
|
|
65427
|
+
}
|
|
65428
|
+
pathCache.set(slotId, path);
|
|
65429
|
+
return path;
|
|
65430
|
+
};
|
|
65431
|
+
// The places, all of them, from the order the slots are in. Done in one go
|
|
65432
|
+
// rather than owner by owner: a place is a sum of what stands before it, so
|
|
65433
|
+
// there is nothing to hand out one at a time — and nothing changes it but a
|
|
65434
|
+
// slot moving or a child taking a different number of rows.
|
|
65435
|
+
const refreshPlaces = () => {
|
|
65436
|
+
placesStale = false;
|
|
65437
|
+
const owners = [...ownerById.entries()];
|
|
65438
|
+
owners.sort(([, leftOwner], [, rightOwner]) => {
|
|
65439
|
+
const comparison = comparePath(pathOf(leftOwner.slotId), pathOf(rightOwner.slotId));
|
|
65440
|
+
if (comparison !== 0) {
|
|
65441
|
+
return comparison;
|
|
65442
|
+
}
|
|
65443
|
+
return leftOwner.sequence - rightOwner.sequence;
|
|
65444
|
+
});
|
|
65445
|
+
orderedOwnerIds.length = 0;
|
|
65446
|
+
let index = 0;
|
|
65447
|
+
for (const [ownerId, owner] of owners) {
|
|
65448
|
+
orderedOwnerIds.push(ownerId);
|
|
65449
|
+
placeByOwner.set(ownerId, index);
|
|
65450
|
+
index += owner.rowCount;
|
|
65451
|
+
}
|
|
65452
|
+
rowTotal = index;
|
|
65453
|
+
totalSignal.value = rowTotal;
|
|
65454
|
+
};
|
|
65455
|
+
// Whether nothing that has taken a place stands after this one.
|
|
65456
|
+
const standsLast = owner => {
|
|
65457
|
+
if (orderedOwnerIds.length === 0) {
|
|
65458
|
+
return true;
|
|
65459
|
+
}
|
|
65460
|
+
const lastOwner = ownerById.get(orderedOwnerIds[orderedOwnerIds.length - 1]);
|
|
65461
|
+
const comparison = comparePath(pathOf(lastOwner.slotId), pathOf(owner.slotId));
|
|
65462
|
+
if (comparison !== 0) {
|
|
65463
|
+
return comparison < 0;
|
|
65464
|
+
}
|
|
65465
|
+
return lastOwner.sequence < owner.sequence;
|
|
65466
|
+
};
|
|
65305
65467
|
const virtual = {
|
|
65306
65468
|
totalSignal,
|
|
65307
65469
|
pagesSignal,
|
|
@@ -65322,14 +65484,41 @@ const createListVirtual = () => {
|
|
|
65322
65484
|
horizontal: false,
|
|
65323
65485
|
virtualItemSizeSignal: null,
|
|
65324
65486
|
renderSkeleton: undefined,
|
|
65325
|
-
//
|
|
65326
|
-
//
|
|
65327
|
-
//
|
|
65328
|
-
|
|
65329
|
-
|
|
65330
|
-
|
|
65331
|
-
|
|
65332
|
-
|
|
65487
|
+
// The children a walk stands over, in order — said in one call, before any
|
|
65488
|
+
// of them renders, so that what a child asks next is answered against the
|
|
65489
|
+
// whole picture and not against the children that happened to render first.
|
|
65490
|
+
declareSlots: (parentSlotId, slotIds) => {
|
|
65491
|
+
const slotIdSet = new Set(slotIds);
|
|
65492
|
+
for (const [slotId, slot] of slotById) {
|
|
65493
|
+
if (slot.parentId === parentSlotId && !slotIdSet.has(slotId)) {
|
|
65494
|
+
dropSlot(slotId);
|
|
65495
|
+
pathCache.clear();
|
|
65496
|
+
placesStale = true;
|
|
65497
|
+
}
|
|
65498
|
+
}
|
|
65499
|
+
let order = 0;
|
|
65500
|
+
for (const slotId of slotIds) {
|
|
65501
|
+
const slot = slotById.get(slotId);
|
|
65502
|
+
if (!slot) {
|
|
65503
|
+
// A slot nothing stands in yet moves nobody: the child that takes it
|
|
65504
|
+
// says so itself, when it renders.
|
|
65505
|
+
slotById.set(slotId, {
|
|
65506
|
+
parentId: parentSlotId,
|
|
65507
|
+
order
|
|
65508
|
+
});
|
|
65509
|
+
} else if (slot.order !== order) {
|
|
65510
|
+
slot.order = order;
|
|
65511
|
+
pathCache.clear();
|
|
65512
|
+
placesStale = true;
|
|
65513
|
+
}
|
|
65514
|
+
order++;
|
|
65515
|
+
}
|
|
65516
|
+
// Now, rather than when the first child asks: the walk has just said
|
|
65517
|
+
// where everything stands, so every place can be settled once instead of
|
|
65518
|
+
// once per child.
|
|
65519
|
+
if (placesStale) {
|
|
65520
|
+
refreshPlaces();
|
|
65521
|
+
}
|
|
65333
65522
|
},
|
|
65334
65523
|
// Whether any run of rows lives in this list: what makes a render window
|
|
65335
65524
|
// mean anything (see List's renderBudget).
|
|
@@ -65350,23 +65539,128 @@ const createListVirtual = () => {
|
|
|
65350
65539
|
}
|
|
65351
65540
|
return null;
|
|
65352
65541
|
},
|
|
65353
|
-
|
|
65354
|
-
|
|
65355
|
-
|
|
65356
|
-
|
|
65357
|
-
|
|
65358
|
-
const
|
|
65359
|
-
|
|
65360
|
-
|
|
65361
|
-
|
|
65362
|
-
|
|
65363
|
-
|
|
65364
|
-
|
|
65365
|
-
|
|
65542
|
+
// The place the slot's rows start at. Asked again on every render of the
|
|
65543
|
+
// child and answered with the same number for as long as nothing moved —
|
|
65544
|
+
// and answered at all for a child that does not ask again, which is the
|
|
65545
|
+
// point of taking by slot.
|
|
65546
|
+
take: (ownerId, rowCount, slotId) => {
|
|
65547
|
+
const previous = ownerById.get(ownerId);
|
|
65548
|
+
if (previous && previous.slotId === slotId && previous.rowCount === rowCount) {
|
|
65549
|
+
if (placesStale) {
|
|
65550
|
+
refreshPlaces();
|
|
65551
|
+
}
|
|
65552
|
+
return placeByOwner.get(ownerId);
|
|
65553
|
+
}
|
|
65554
|
+
const owner = {
|
|
65555
|
+
slotId,
|
|
65556
|
+
rowCount,
|
|
65557
|
+
sequence: previous ? previous.sequence : sequence++
|
|
65558
|
+
};
|
|
65559
|
+
ownerById.set(ownerId, owner);
|
|
65560
|
+
if (!previous && !placesStale && standsLast(owner)) {
|
|
65561
|
+
orderedOwnerIds.push(ownerId);
|
|
65562
|
+
placeByOwner.set(ownerId, rowTotal);
|
|
65563
|
+
rowTotal += rowCount;
|
|
65564
|
+
totalSignal.value = rowTotal;
|
|
65565
|
+
return placeByOwner.get(ownerId);
|
|
65566
|
+
}
|
|
65567
|
+
placesStale = true;
|
|
65568
|
+
refreshPlaces();
|
|
65569
|
+
return placeByOwner.get(ownerId);
|
|
65570
|
+
},
|
|
65571
|
+
// The child stands for no row of the collection any more: it was filtered
|
|
65572
|
+
// out by a search, or it is gone.
|
|
65573
|
+
drop: ownerId => {
|
|
65574
|
+
if (!ownerById.delete(ownerId)) {
|
|
65575
|
+
return;
|
|
65576
|
+
}
|
|
65577
|
+
placeByOwner.delete(ownerId);
|
|
65578
|
+
refreshPlaces();
|
|
65366
65579
|
}
|
|
65367
65580
|
};
|
|
65368
65581
|
return virtual;
|
|
65369
65582
|
};
|
|
65583
|
+
// The walk that gives the list's children their places. It names a slot for
|
|
65584
|
+
// each of them — after the child's key when it has one, after its position
|
|
65585
|
+
// otherwise, which is how preact itself tells unkeyed children apart — and says
|
|
65586
|
+
// the whole set to the list's virtual before any of them renders.
|
|
65587
|
+
//
|
|
65588
|
+
// Wrapping each child in its own provider is what makes a slot reach the row
|
|
65589
|
+
// inside it, however deep the caller buried it, and what wakes a row whose slot
|
|
65590
|
+
// moved: the value it holds is the same object for as long as the child stays
|
|
65591
|
+
// where it was.
|
|
65592
|
+
const ListDeclaredChildren = ({
|
|
65593
|
+
children
|
|
65594
|
+
}) => {
|
|
65595
|
+
const virtual = useContext(ListVirtualContext);
|
|
65596
|
+
const parentSlot = useContext(ListSlotContext);
|
|
65597
|
+
const parentSlotId = parentSlot ? parentSlot.id : null;
|
|
65598
|
+
const slotsRef = useRef(new Map());
|
|
65599
|
+
const slotsPrevious = slotsRef.current;
|
|
65600
|
+
const childArray = flattenChildren(children);
|
|
65601
|
+
const slots = new Map();
|
|
65602
|
+
const slotIds = [];
|
|
65603
|
+
let index = 0;
|
|
65604
|
+
for (const child of childArray) {
|
|
65605
|
+
const childKey = child && child.key !== undefined && child.key !== null ? `k${child.key}` : `i${index}`;
|
|
65606
|
+
let slotId = parentSlotId === null ? childKey : `${parentSlotId}/${childKey}`;
|
|
65607
|
+
if (slots.has(slotId)) {
|
|
65608
|
+
// Two children answering to the same key: preact cannot tell them apart
|
|
65609
|
+
// either, but a slot each is what keeps them both on screen.
|
|
65610
|
+
slotId = `${slotId}#${index}`;
|
|
65611
|
+
}
|
|
65612
|
+
const slotPrevious = slotsPrevious.get(slotId);
|
|
65613
|
+
slots.set(slotId, slotPrevious && slotPrevious.order === index ? slotPrevious : {
|
|
65614
|
+
id: slotId,
|
|
65615
|
+
order: index
|
|
65616
|
+
});
|
|
65617
|
+
slotIds.push(slotId);
|
|
65618
|
+
index++;
|
|
65619
|
+
}
|
|
65620
|
+
slotsRef.current = slots;
|
|
65621
|
+
virtual.declareSlots(parentSlotId, slotIds);
|
|
65622
|
+
return jsx(Fragment$1, {
|
|
65623
|
+
children: childArray.map((child, childIndex) => {
|
|
65624
|
+
const slotId = slotIds[childIndex];
|
|
65625
|
+
return jsx(ListSlotContext.Provider, {
|
|
65626
|
+
value: slots.get(slotId),
|
|
65627
|
+
children: child
|
|
65628
|
+
}, slotId);
|
|
65629
|
+
})
|
|
65630
|
+
});
|
|
65631
|
+
};
|
|
65632
|
+
// The children as preact will diff them: nested arrays flattened, and a child
|
|
65633
|
+
// that renders nothing still holding its position — a conditional child must
|
|
65634
|
+
// not move the ones after it as it comes and goes.
|
|
65635
|
+
const flattenChildren = (children, flat = []) => {
|
|
65636
|
+
if (Array.isArray(children)) {
|
|
65637
|
+
for (const child of children) {
|
|
65638
|
+
flattenChildren(child, flat);
|
|
65639
|
+
}
|
|
65640
|
+
return flat;
|
|
65641
|
+
}
|
|
65642
|
+
flat.push(children);
|
|
65643
|
+
return flat;
|
|
65644
|
+
};
|
|
65645
|
+
|
|
65646
|
+
// Two slots compared by where they sit (see pathOf). A slot no walk declared
|
|
65647
|
+
// sorts after them all: it stands nowhere the list knows of.
|
|
65648
|
+
const comparePath = (leftPath, rightPath) => {
|
|
65649
|
+
if (leftPath === null) {
|
|
65650
|
+
return rightPath === null ? 0 : 1;
|
|
65651
|
+
}
|
|
65652
|
+
if (rightPath === null) {
|
|
65653
|
+
return -1;
|
|
65654
|
+
}
|
|
65655
|
+
let depth = 0;
|
|
65656
|
+
while (depth < leftPath.length && depth < rightPath.length) {
|
|
65657
|
+
if (leftPath[depth] !== rightPath[depth]) {
|
|
65658
|
+
return leftPath[depth] - rightPath[depth];
|
|
65659
|
+
}
|
|
65660
|
+
depth++;
|
|
65661
|
+
}
|
|
65662
|
+
return leftPath.length - rightPath.length;
|
|
65663
|
+
};
|
|
65370
65664
|
const VISIBILITY_HIDDEN_STYLE = {
|
|
65371
65665
|
visibility: "hidden"
|
|
65372
65666
|
};
|
|
@@ -65501,6 +65795,7 @@ const ListItems = ({
|
|
|
65501
65795
|
}) => {
|
|
65502
65796
|
const ownerId = useId();
|
|
65503
65797
|
const virtual = useContext(ListVirtualContext);
|
|
65798
|
+
const slot = useContext(ListSlotContext);
|
|
65504
65799
|
const renderWindow = useContext(RenderWindowContext);
|
|
65505
65800
|
const separator = useContext(SeparatorContext);
|
|
65506
65801
|
const store = useItemStore({
|
|
@@ -65522,7 +65817,7 @@ const ListItems = ({
|
|
|
65522
65817
|
skeletonRow.rowMinHeight = `${virtualItemSize}px`;
|
|
65523
65818
|
}
|
|
65524
65819
|
}
|
|
65525
|
-
const runStart = virtual.take(ownerId, store.rowCount);
|
|
65820
|
+
const runStart = virtual.take(ownerId, store.rowCount, slot ? slot.id : ownerId);
|
|
65526
65821
|
const runEnd = runStart + store.rowCount;
|
|
65527
65822
|
const getItemAt = index => store.getItem(index);
|
|
65528
65823
|
const windowFrom = renderWindow.start > runStart ? renderWindow.start : runStart;
|
|
@@ -65549,6 +65844,7 @@ const ListItems = ({
|
|
|
65549
65844
|
useLayoutEffect(() => {
|
|
65550
65845
|
return () => {
|
|
65551
65846
|
virtual.dropRowLocator(ownerId);
|
|
65847
|
+
virtual.drop(ownerId);
|
|
65552
65848
|
};
|
|
65553
65849
|
}, []);
|
|
65554
65850
|
|
|
@@ -66334,7 +66630,9 @@ const ListItemGroup = ({
|
|
|
66334
66630
|
"aria-labelledby": groupId,
|
|
66335
66631
|
children: jsx(GroupItemTrackerContext.Provider, {
|
|
66336
66632
|
value: groupTracker,
|
|
66337
|
-
children:
|
|
66633
|
+
children: jsx(ListDeclaredChildren, {
|
|
66634
|
+
children: children
|
|
66635
|
+
})
|
|
66338
66636
|
})
|
|
66339
66637
|
})]
|
|
66340
66638
|
});
|