@jsenv/navi 0.29.137 → 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 +508 -160
- package/dist/jsenv_navi.js.map +46 -17
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -27070,10 +27070,10 @@ const releaseTransitionDestination = (owner) => {
|
|
|
27070
27070
|
};
|
|
27071
27071
|
|
|
27072
27072
|
/**
|
|
27073
|
-
* The furniture around the pages — the fixed bars
|
|
27074
|
-
*
|
|
27075
|
-
*
|
|
27076
|
-
* in a frame.
|
|
27073
|
+
* The furniture around the pages — the fixed bars, and the popups standing
|
|
27074
|
+
* over them in the top layer — photographed with them for the length of a
|
|
27075
|
+
* route transition, so that a piece of it belonging to ONE of the two states
|
|
27076
|
+
* takes part in the movement instead of appearing or vanishing in a frame.
|
|
27077
27077
|
*
|
|
27078
27078
|
* Whether a bar is the frame or part of what changes is a fact about the PAIR
|
|
27079
27079
|
* of states, never about the bar: the top bar of a list is the frame while one
|
|
@@ -27088,7 +27088,15 @@ const releaseTransitionDestination = (owner) => {
|
|
|
27088
27088
|
* that has it, so it travels with that page — leaving by the keyframes the
|
|
27089
27089
|
* page being left leaves by, arriving by the ones the page arriving arrives
|
|
27090
27090
|
* by — instead of going out with the render. Under the pages, so a page
|
|
27091
|
-
* coming over it covers it
|
|
27091
|
+
* coming over it covers it — a popup over them instead, standing where it
|
|
27092
|
+
* stands in the document (see the z-order in route_transition.jsx).
|
|
27093
|
+
*
|
|
27094
|
+
* A popup shown in the top layer is furniture of the same kind, and its case
|
|
27095
|
+
* is the sharper one: it is a DOM descendant of the area, yet painted outside
|
|
27096
|
+
* the area's picture, so being captured on its own is the only way it is on
|
|
27097
|
+
* screen at all for those few hundred milliseconds (layout/popup_css.js). One
|
|
27098
|
+
* the two states share holds where it stands, one only a single state has
|
|
27099
|
+
* travels with that state's page — the same two outcomes, derived the same way.
|
|
27092
27100
|
*
|
|
27093
27101
|
* Which keyframes those are is published by the movement itself
|
|
27094
27102
|
* (--navi-route-transition-leave / -enter, see route_transition.jsx): a
|
|
@@ -27110,11 +27118,15 @@ const releaseTransitionDestination = (owner) => {
|
|
|
27110
27118
|
* both pages are pictures for those few hundred milliseconds anyway.
|
|
27111
27119
|
*/
|
|
27112
27120
|
|
|
27121
|
+
// The browser's top layer: painted above everything the document paints, so
|
|
27122
|
+
// outside the area's picture whatever the DOM says.
|
|
27123
|
+
const TOP_LAYER_SELECTOR = ":modal, :popover-open";
|
|
27113
27124
|
// What counts as furniture: what is pinned to an edge of the window and gives
|
|
27114
|
-
// its room back to the content (layout/fixed_bar/fixed_bar.jsx)
|
|
27115
|
-
//
|
|
27116
|
-
// part of the pages' own
|
|
27117
|
-
|
|
27125
|
+
// its room back to the content (layout/fixed_bar/fixed_bar.jsx), and what
|
|
27126
|
+
// stands over the pages in the top layer. A sticky row inside the pages needs
|
|
27127
|
+
// none of this — it lives in the area, so it is already part of the pages' own
|
|
27128
|
+
// picture, and so is a popup rendered with layer="local".
|
|
27129
|
+
const FURNITURE_SELECTOR = `.navi_fixed_bar, .navi_popover:is(${TOP_LAYER_SELECTOR}), .navi_dialog:is(${TOP_LAYER_SELECTOR})`;
|
|
27118
27130
|
// Worn by the root for the length of a route transition (route_transition.jsx
|
|
27119
27131
|
// owns it). Written out rather than imported: importing the module that owns
|
|
27120
27132
|
// it back into this one would close a cycle.
|
|
@@ -27183,8 +27195,10 @@ const nameFurnitureAround = (areaElement) => {
|
|
|
27183
27195
|
continue;
|
|
27184
27196
|
}
|
|
27185
27197
|
// Inside the area it is not furniture, it is the page: naming it would
|
|
27186
|
-
// punch a hole in the picture the movement is played on.
|
|
27187
|
-
|
|
27198
|
+
// punch a hole in the picture the movement is played on. Standing in the
|
|
27199
|
+
// top layer takes it out of that picture though, so there is no hole to
|
|
27200
|
+
// punch — which is exactly the case of a modal dialog rendered by a page.
|
|
27201
|
+
if (areaElement.contains(element) && !element.matches(TOP_LAYER_SELECTOR)) {
|
|
27188
27202
|
continue;
|
|
27189
27203
|
}
|
|
27190
27204
|
let name = nameByElement.get(element);
|
|
@@ -27640,24 +27654,118 @@ const css$10 = /* css */`
|
|
|
27640
27654
|
&[data-navi-route-transition-target="area"] {
|
|
27641
27655
|
view-transition-name: none;
|
|
27642
27656
|
|
|
27657
|
+
/* Where the pages are cut, and how far they travel — said on the root so
|
|
27658
|
+
that EVERY picture of the movement inherits them, not just the pages':
|
|
27659
|
+
a fixed bar or a popup travelling with the page it belongs to
|
|
27660
|
+
(transition_furniture.js) crosses the same window's worth of distance
|
|
27661
|
+
the pages do, whatever its own size. The pages are then cut with what
|
|
27662
|
+
is written here, on their group below.
|
|
27663
|
+
|
|
27664
|
+
The cut: the area's own box, and on top of it whatever covers the area.
|
|
27665
|
+
The pictures are drawn in the top layer, so they cover a fixed bar as
|
|
27666
|
+
easily as anything else — and the area runs UNDER the bars by design:
|
|
27667
|
+
that is what a fixed bar is for, and what the room it gives back is
|
|
27668
|
+
for. An area taller than the screen therefore ends below the bottom
|
|
27669
|
+
bar, and a scrolled one starts above the top bar, so the movement would
|
|
27670
|
+
be watched painting over them for its whole length.
|
|
27671
|
+
|
|
27672
|
+
Two bands are left free, and they answer for two different things: the
|
|
27673
|
+
app's own safe area (layout/safe_area.js), everything pinned to the
|
|
27674
|
+
WINDOW's edges, and --navi-transition-cover-* (transition_window.js),
|
|
27675
|
+
what covers the area from inside the document — a sticky header above
|
|
27676
|
+
the pages covers the top of the area exactly as a fixed bar covers the
|
|
27677
|
+
top of the screen. Both are read rather than asked for, so one that
|
|
27678
|
+
grows, shrinks or unmounts mid-transition is followed without anything
|
|
27679
|
+
being told.
|
|
27680
|
+
|
|
27681
|
+
Read live, though, they describe the state ARRIVING and nothing else,
|
|
27682
|
+
so the cut is taken at the smaller of that and the band the state
|
|
27683
|
+
being left kept free (--navi-transition-old-band-*, photographed while
|
|
27684
|
+
both still existed). Furniture standing in BOTH states is the frame:
|
|
27685
|
+
the pages move behind it and are cut at it. Furniture standing in one
|
|
27686
|
+
of them is part of what changes, and cutting the page being left at a
|
|
27687
|
+
bar it never had shows its own header being sliced instead of
|
|
27688
|
+
leaving. */
|
|
27689
|
+
--navi-route-transition-clip-top: max(
|
|
27690
|
+
0px,
|
|
27691
|
+
min(
|
|
27692
|
+
var(--navi-safe-area-inset-top) + var(--navi-transition-cover-top),
|
|
27693
|
+
var(--navi-transition-old-band-top)
|
|
27694
|
+
) - var(--navi-transition-window-top)
|
|
27695
|
+
);
|
|
27696
|
+
--navi-route-transition-clip-left: max(
|
|
27697
|
+
0px,
|
|
27698
|
+
min(
|
|
27699
|
+
var(--navi-safe-area-inset-left) + var(--navi-transition-cover-left),
|
|
27700
|
+
var(--navi-transition-old-band-left)
|
|
27701
|
+
) - var(--navi-transition-window-left)
|
|
27702
|
+
);
|
|
27703
|
+
--navi-route-transition-clip-bottom: max(
|
|
27704
|
+
0px,
|
|
27705
|
+
var(--navi-transition-window-top) +
|
|
27706
|
+
var(--navi-transition-window-height) +
|
|
27707
|
+
min(
|
|
27708
|
+
var(--navi-safe-area-inset-bottom) +
|
|
27709
|
+
var(--navi-transition-cover-bottom),
|
|
27710
|
+
var(--navi-transition-old-band-bottom)
|
|
27711
|
+
) -
|
|
27712
|
+
100dvh
|
|
27713
|
+
);
|
|
27714
|
+
--navi-route-transition-clip-right: max(
|
|
27715
|
+
0px,
|
|
27716
|
+
var(--navi-transition-window-left) +
|
|
27717
|
+
var(--navi-transition-window-width) +
|
|
27718
|
+
min(
|
|
27719
|
+
var(--navi-safe-area-inset-right) +
|
|
27720
|
+
var(--navi-transition-cover-right),
|
|
27721
|
+
var(--navi-transition-old-band-right)
|
|
27722
|
+
) -
|
|
27723
|
+
100dvw
|
|
27724
|
+
);
|
|
27725
|
+
|
|
27726
|
+
/* How far a page travels: the WINDOW it is seen through, not its own
|
|
27727
|
+
size. A page is as tall as its content — several screens of it — and a
|
|
27728
|
+
movement measured on the picture would send it thousands of pixels
|
|
27729
|
+
away, off screen for most of the transition and flying past at the
|
|
27730
|
+
end. What one page crossing another means is one window's worth of
|
|
27731
|
+
movement, whatever the pages are made of (see the keyframes). */
|
|
27732
|
+
--navi-route-transition-travel-x: calc(
|
|
27733
|
+
var(--navi-transition-window-width) - var(
|
|
27734
|
+
--navi-route-transition-clip-left
|
|
27735
|
+
) - var(--navi-route-transition-clip-right)
|
|
27736
|
+
);
|
|
27737
|
+
--navi-route-transition-travel-y: calc(
|
|
27738
|
+
var(--navi-transition-window-height) - var(
|
|
27739
|
+
--navi-route-transition-clip-top
|
|
27740
|
+
) - var(--navi-route-transition-clip-bottom)
|
|
27741
|
+
);
|
|
27742
|
+
|
|
27643
27743
|
/* The pages travel OVER the furniture. Everything else captured while an
|
|
27644
|
-
area is marked
|
|
27645
|
-
|
|
27646
|
-
|
|
27647
|
-
|
|
27648
|
-
|
|
27649
|
-
|
|
27744
|
+
area is marked wears a name of navi's own for the length of the
|
|
27745
|
+
movement (transition_furniture.js): a bar the two states share is one
|
|
27746
|
+
group the browser holds where it stands, and a bar only one of them
|
|
27747
|
+
has stands there too, with no counterpart to move to. Both belong
|
|
27748
|
+
under the pages — that is what lets a page come over a bar that is
|
|
27749
|
+
going away, and a page leaving uncover the bar arriving behind it.
|
|
27750
|
+
|
|
27751
|
+
An open popup is the one piece that goes the other way: it stands in
|
|
27752
|
+
the top layer, over everything the document paints, so its picture
|
|
27753
|
+
stands over the pages rather than under them — a page sliding under a
|
|
27754
|
+
dialog, not over it (the class comes from layout/popup_css.js).
|
|
27650
27755
|
|
|
27651
27756
|
Ordered here rather than left to the DOM, which decides it otherwise:
|
|
27652
27757
|
where an application puts its bars relative to the area is its own
|
|
27653
|
-
business. A name and \`*\` weigh the same, so the
|
|
27654
|
-
the order they are written. */
|
|
27758
|
+
business. A name, a class and \`*\` weigh the same, so the rules are
|
|
27759
|
+
read in the order they are written. */
|
|
27655
27760
|
&::view-transition-group(*) {
|
|
27656
27761
|
z-index: 0;
|
|
27657
27762
|
}
|
|
27658
27763
|
&::view-transition-group(navi-route-transition) {
|
|
27659
27764
|
z-index: 1;
|
|
27660
27765
|
}
|
|
27766
|
+
&::view-transition-group(.navi_popup) {
|
|
27767
|
+
z-index: 2;
|
|
27768
|
+
}
|
|
27661
27769
|
|
|
27662
27770
|
/* And on the transition's own clock, whatever was captured. How long the
|
|
27663
27771
|
movement lasts is a fact about the movement, not about the pages: a bar
|
|
@@ -27713,93 +27821,15 @@ const css$10 = /* css */`
|
|
|
27713
27821
|
);
|
|
27714
27822
|
width: var(--navi-transition-window-width);
|
|
27715
27823
|
height: var(--navi-transition-window-height);
|
|
27716
|
-
|
|
27717
|
-
|
|
27718
|
-
/* Cut at what covers the area, on top of being cut at the area's own
|
|
27719
|
-
box. The pictures are drawn in the top layer, so they cover a fixed bar
|
|
27720
|
-
as easily as anything else — and the area runs UNDER the bars by
|
|
27721
|
-
design: that is what a fixed bar is for, and what the room it gives
|
|
27722
|
-
back is for. An area taller than the screen therefore ends below the
|
|
27723
|
-
bottom bar, and a scrolled one starts above the top bar, so the
|
|
27724
|
-
movement would be watched painting over them for its whole length.
|
|
27725
|
-
|
|
27726
|
-
Two bands are left free, and they answer for two different things: the
|
|
27727
|
-
app's own safe area (layout/safe_area.js), everything pinned to the
|
|
27728
|
-
WINDOW's edges, and --navi-transition-cover-* (transition_window.js),
|
|
27729
|
-
what covers the area from inside the document — a sticky header above
|
|
27730
|
-
the pages covers the top of the area exactly as a fixed bar covers the
|
|
27731
|
-
top of the screen. Both are read rather than asked for, so one that
|
|
27732
|
-
grows, shrinks or unmounts mid-transition is followed without anything
|
|
27733
|
-
being told.
|
|
27734
|
-
|
|
27735
|
-
Read live, though, they describe the state ARRIVING and nothing else,
|
|
27736
|
-
so the cut is taken at the smaller of that and the band the state
|
|
27737
|
-
being left kept free (--navi-transition-old-band-*, photographed while
|
|
27738
|
-
both still existed). Furniture standing in BOTH states is the frame:
|
|
27739
|
-
the pages move behind it and are cut at it. Furniture standing in one
|
|
27740
|
-
of them is part of what changes, and cutting the page being left at a
|
|
27741
|
-
bar it never had shows its own header being sliced instead of
|
|
27742
|
-
leaving. */
|
|
27743
|
-
--navi-route-transition-clip-top: max(
|
|
27744
|
-
0px,
|
|
27745
|
-
min(
|
|
27746
|
-
var(--navi-safe-area-inset-top) + var(--navi-transition-cover-top),
|
|
27747
|
-
var(--navi-transition-old-band-top)
|
|
27748
|
-
) - var(--navi-transition-window-top)
|
|
27749
|
-
);
|
|
27750
|
-
--navi-route-transition-clip-left: max(
|
|
27751
|
-
0px,
|
|
27752
|
-
min(
|
|
27753
|
-
var(--navi-safe-area-inset-left) + var(--navi-transition-cover-left),
|
|
27754
|
-
var(--navi-transition-old-band-left)
|
|
27755
|
-
) - var(--navi-transition-window-left)
|
|
27756
|
-
);
|
|
27757
|
-
--navi-route-transition-clip-bottom: max(
|
|
27758
|
-
0px,
|
|
27759
|
-
var(--navi-transition-window-top) +
|
|
27760
|
-
var(--navi-transition-window-height) +
|
|
27761
|
-
min(
|
|
27762
|
-
var(--navi-safe-area-inset-bottom) +
|
|
27763
|
-
var(--navi-transition-cover-bottom),
|
|
27764
|
-
var(--navi-transition-old-band-bottom)
|
|
27765
|
-
) -
|
|
27766
|
-
100dvh
|
|
27767
|
-
);
|
|
27768
|
-
--navi-route-transition-clip-right: max(
|
|
27769
|
-
0px,
|
|
27770
|
-
var(--navi-transition-window-left) +
|
|
27771
|
-
var(--navi-transition-window-width) +
|
|
27772
|
-
min(
|
|
27773
|
-
var(--navi-safe-area-inset-right) +
|
|
27774
|
-
var(--navi-transition-cover-right),
|
|
27775
|
-
var(--navi-transition-old-band-right)
|
|
27776
|
-
) -
|
|
27777
|
-
100dvw
|
|
27778
|
-
);
|
|
27824
|
+
/* And cut at what covers the area, on top of that (the band is worked
|
|
27825
|
+
out on the root above). */
|
|
27779
27826
|
clip-path: inset(
|
|
27780
27827
|
var(--navi-route-transition-clip-top)
|
|
27781
27828
|
var(--navi-route-transition-clip-right)
|
|
27782
27829
|
var(--navi-route-transition-clip-bottom)
|
|
27783
27830
|
var(--navi-route-transition-clip-left)
|
|
27784
27831
|
);
|
|
27785
|
-
|
|
27786
|
-
/* How far a page travels: the WINDOW it is seen through, not its own
|
|
27787
|
-
size. A page is as tall as its content — several screens of it — and a
|
|
27788
|
-
movement measured on the picture would send it thousands of pixels
|
|
27789
|
-
away, off screen for most of the transition and flying past at the
|
|
27790
|
-
end. What one page crossing another means is one window's worth of
|
|
27791
|
-
movement, whatever the pages are made of. Inherited by the pictures,
|
|
27792
|
-
which is where it is used (see the keyframes). */
|
|
27793
|
-
--navi-route-transition-travel-x: calc(
|
|
27794
|
-
var(--navi-transition-window-width) - var(
|
|
27795
|
-
--navi-route-transition-clip-left
|
|
27796
|
-
) - var(--navi-route-transition-clip-right)
|
|
27797
|
-
);
|
|
27798
|
-
--navi-route-transition-travel-y: calc(
|
|
27799
|
-
var(--navi-transition-window-height) - var(
|
|
27800
|
-
--navi-route-transition-clip-top
|
|
27801
|
-
) - var(--navi-route-transition-clip-bottom)
|
|
27802
|
-
);
|
|
27832
|
+
animation-name: none;
|
|
27803
27833
|
}
|
|
27804
27834
|
/* Each picture at the corner its own state stood at, which is not the
|
|
27805
27835
|
window's: the window contains both states, and a state that is scrolled
|
|
@@ -33337,6 +33367,34 @@ const isNamelessGrouping = (child, uiState) =>
|
|
|
33337
33367
|
typeof uiState === "object" &&
|
|
33338
33368
|
!Array.isArray(uiState);
|
|
33339
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
|
+
|
|
33340
33398
|
const firstDefinedChildUIState = (children) => {
|
|
33341
33399
|
for (const child of children) {
|
|
33342
33400
|
const childUIState = child.uiState;
|
|
@@ -33474,7 +33532,19 @@ const GROUP_DEFAULTS = {
|
|
|
33474
33532
|
typeof newUIState === "object" &&
|
|
33475
33533
|
Object.prototype.hasOwnProperty.call(newUIState, childName)
|
|
33476
33534
|
) {
|
|
33477
|
-
|
|
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;
|
|
33478
33548
|
}
|
|
33479
33549
|
// Merged in on the way up (see above), so on the way down it takes the
|
|
33480
33550
|
// whole object and picks out its own keys — the same value it produced.
|
|
@@ -33702,6 +33772,15 @@ const useUIGroupStateController = (
|
|
|
33702
33772
|
// wheels nobody turned have settled nothing. Only the default shapes
|
|
33703
33773
|
// fall back to the empty of their type, where "no child says anything"
|
|
33704
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).
|
|
33705
33784
|
return stateShapeIsTheDefaultOne ? fallbackState : undefined;
|
|
33706
33785
|
};
|
|
33707
33786
|
|
|
@@ -55471,21 +55550,41 @@ const popupCss = /* css */ `
|
|
|
55471
55550
|
popup lives in the top layer too: uncaptured, it is simply covered for the
|
|
55472
55551
|
length of the movement, so it disappears the instant its page starts to
|
|
55473
55552
|
leave and lands abruptly when the arriving one settles. Captured, it is a
|
|
55474
|
-
group beside the pages, painted over them where it stands
|
|
55475
|
-
|
|
55476
|
-
|
|
55553
|
+
group beside the pages, painted over them where it stands.
|
|
55554
|
+
|
|
55555
|
+
The class is how navi reaches that picture afterwards: its clock below,
|
|
55556
|
+
and its place above the pages (the z-order in nav/route_transition.jsx). */
|
|
55557
|
+
:root[data-navi-route-transition] .navi_popover[aria-expanded="true"],
|
|
55558
|
+
:root[data-navi-route-transition] .navi_dialog[aria-expanded="true"],
|
|
55559
|
+
:root[data-navi-route-travel] .navi_popover[aria-expanded="true"],
|
|
55560
|
+
:root[data-navi-route-travel] .navi_dialog[aria-expanded="true"] {
|
|
55561
|
+
view-transition-class: navi_popup;
|
|
55562
|
+
}
|
|
55563
|
+
|
|
55564
|
+
/* The name, wherever nobody writes a better one. A movement played on an
|
|
55565
|
+
area names the popups standing over it itself, per element and in JS
|
|
55566
|
+
(nav/transition_furniture.js): only a real name tells the popup the two
|
|
55567
|
+
states SHARE — one element, one name, one group held where it stands —
|
|
55568
|
+
from the one a single state has, which belongs to that state's page and
|
|
55569
|
+
travels with it. A movement played on the whole document runs no such
|
|
55570
|
+
pass, so the popup takes an identity of its own and the browser fades it.
|
|
55477
55571
|
|
|
55478
55572
|
An identity of its own (match-element), never a shared name: two popups on
|
|
55479
55573
|
either side of a navigation are two different popups, and what is wanted is
|
|
55480
55574
|
precisely that one goes and the other comes. A browser with no
|
|
55481
55575
|
match-element takes no name and the pictures cover the popup. */
|
|
55482
55576
|
@supports (view-transition-name: match-element) {
|
|
55483
|
-
:root[data-navi-route-transition]
|
|
55484
|
-
|
|
55577
|
+
:root[data-navi-route-transition]:not(
|
|
55578
|
+
[data-navi-route-transition-target="area"]
|
|
55579
|
+
)
|
|
55580
|
+
.navi_popover[aria-expanded="true"],
|
|
55581
|
+
:root[data-navi-route-transition]:not(
|
|
55582
|
+
[data-navi-route-transition-target="area"]
|
|
55583
|
+
)
|
|
55584
|
+
.navi_dialog[aria-expanded="true"],
|
|
55485
55585
|
:root[data-navi-route-travel] .navi_popover[aria-expanded="true"],
|
|
55486
55586
|
:root[data-navi-route-travel] .navi_dialog[aria-expanded="true"] {
|
|
55487
55587
|
view-transition-name: match-element;
|
|
55488
|
-
view-transition-class: navi_popup;
|
|
55489
55588
|
}
|
|
55490
55589
|
}
|
|
55491
55590
|
|
|
@@ -61256,7 +61355,13 @@ const ListSelectable = props => {
|
|
|
61256
61355
|
if (selectionRef.current === undefined) {
|
|
61257
61356
|
selectionRef.current = Object.hasOwn(props, "value") ? props.value : props.defaultValue;
|
|
61258
61357
|
}
|
|
61259
|
-
|
|
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) => {
|
|
61260
61365
|
const kept = selectionRef.current;
|
|
61261
61366
|
if (multiple) {
|
|
61262
61367
|
const drawnValues = new Set(children.map(child => child.props.value));
|
|
@@ -61266,7 +61371,7 @@ const ListSelectable = props => {
|
|
|
61266
61371
|
stillSelected.push(child.uiState);
|
|
61267
61372
|
}
|
|
61268
61373
|
}
|
|
61269
|
-
const values = stillSelected.length === 0 ?
|
|
61374
|
+
const values = stillSelected.length === 0 ? fallbackState : stillSelected;
|
|
61270
61375
|
selectionRef.current = values;
|
|
61271
61376
|
return values;
|
|
61272
61377
|
}
|
|
@@ -61879,6 +61984,13 @@ const ListVirtualContext = createContext(null);
|
|
|
61879
61984
|
// that returning a component of one's own — instead of a bare <List.Item> —
|
|
61880
61985
|
// works the same way.
|
|
61881
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);
|
|
61882
61994
|
const css$x = /* css */`
|
|
61883
61995
|
@layer navi {
|
|
61884
61996
|
.navi_list_container {
|
|
@@ -62882,24 +62994,11 @@ const ListFirstResolver = props => {
|
|
|
62882
62994
|
props.ref = props.ref || refDefault;
|
|
62883
62995
|
const idDefault = useId();
|
|
62884
62996
|
props.id = props.id || idDefault;
|
|
62885
|
-
// A new pass every time the caller walks the children: they are about to
|
|
62886
|
-
// say again, in order, which rows of the collection they stand for. Decided
|
|
62887
|
-
// here, on the children as the caller gave them. Further down the chain a
|
|
62888
|
-
// resolver re-rendering on its own hands the rows down inside a vnode of its
|
|
62889
|
-
// own (ListSelectable wraps them in the group's contexts) — but the rows are
|
|
62890
|
-
// the very vnodes preact already holds, and it skips them: nothing is said
|
|
62891
|
-
// again, so nothing may be asked again either (see createListVirtual).
|
|
62892
62997
|
const virtualRef = useRef(null);
|
|
62893
62998
|
if (!virtualRef.current) {
|
|
62894
62999
|
virtualRef.current = createListVirtual();
|
|
62895
63000
|
}
|
|
62896
|
-
|
|
62897
|
-
const childrenPreviousRef = useRef(undefined);
|
|
62898
|
-
if (childrenPreviousRef.current !== props.children) {
|
|
62899
|
-
childrenPreviousRef.current = props.children;
|
|
62900
|
-
virtual.openPass();
|
|
62901
|
-
}
|
|
62902
|
-
props.virtual = virtual;
|
|
63001
|
+
props.virtual = virtualRef.current;
|
|
62903
63002
|
return jsx(Next, {
|
|
62904
63003
|
...props
|
|
62905
63004
|
});
|
|
@@ -64635,7 +64734,9 @@ const UnorderedList = ({
|
|
|
64635
64734
|
value: null,
|
|
64636
64735
|
children: jsx(ListColumnsContext.Provider, {
|
|
64637
64736
|
value: columns || null,
|
|
64638
|
-
children:
|
|
64737
|
+
children: jsx(ListDeclaredChildren, {
|
|
64738
|
+
children: children
|
|
64739
|
+
})
|
|
64639
64740
|
})
|
|
64640
64741
|
})
|
|
64641
64742
|
})
|
|
@@ -64846,6 +64947,9 @@ const ListItemUI = props => {
|
|
|
64846
64947
|
// registered the row, decided it is inside the render window, and placed its
|
|
64847
64948
|
// separator. All that is left here is to draw it.
|
|
64848
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);
|
|
64849
64953
|
// There is no standalone match/matchScore/highlight prop — participation
|
|
64850
64954
|
// in a matching system (search, filter…) only goes through `matchInfo`
|
|
64851
64955
|
// (e.g. useSearchText's getItemMatchInfo(item): { match, matchScore,
|
|
@@ -64869,12 +64973,22 @@ const ListItemUI = props => {
|
|
|
64869
64973
|
}
|
|
64870
64974
|
}
|
|
64871
64975
|
// Where a row sits is where it was declared, full stop: a list is written in
|
|
64872
|
-
// the order it reads.
|
|
64873
|
-
//
|
|
64874
|
-
// already knows its place; the run gave it.
|
|
64875
|
-
if (!row
|
|
64876
|
-
|
|
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
|
+
}
|
|
64877
64985
|
}
|
|
64986
|
+
const rowId = props.id;
|
|
64987
|
+
useLayoutEffect(() => {
|
|
64988
|
+
return () => {
|
|
64989
|
+
virtual.drop(rowId);
|
|
64990
|
+
};
|
|
64991
|
+
}, []);
|
|
64878
64992
|
// Every row that is drawn registers itself, whether it was declared one by
|
|
64879
64993
|
// one or drawn by a run: what it says about itself (its value, whether it is
|
|
64880
64994
|
// selected) is written where it is drawn, in one place.
|
|
@@ -65231,12 +65345,19 @@ List.Item = ListItem;
|
|
|
65231
65345
|
// where each child's rows start.
|
|
65232
65346
|
//
|
|
65233
65347
|
// A child knows how many rows it stands for but not what was declared before
|
|
65234
|
-
// it,
|
|
65235
|
-
//
|
|
65236
|
-
//
|
|
65237
|
-
//
|
|
65238
|
-
//
|
|
65239
|
-
//
|
|
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.
|
|
65240
65361
|
const createListVirtual = () => {
|
|
65241
65362
|
const totalSignal = signal(0);
|
|
65242
65363
|
// Bumped whenever a run takes in rows. The list itself has to hear about it:
|
|
@@ -65248,10 +65369,101 @@ const createListVirtual = () => {
|
|
|
65248
65369
|
// an attribute: what is drawn is from before, and the app may want to say so
|
|
65249
65370
|
// without taking anything away.
|
|
65250
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();
|
|
65251
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;
|
|
65252
65386
|
const locatorByOwner = new Map();
|
|
65253
|
-
|
|
65254
|
-
|
|
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
|
+
};
|
|
65255
65467
|
const virtual = {
|
|
65256
65468
|
totalSignal,
|
|
65257
65469
|
pagesSignal,
|
|
@@ -65272,14 +65484,41 @@ const createListVirtual = () => {
|
|
|
65272
65484
|
horizontal: false,
|
|
65273
65485
|
virtualItemSizeSignal: null,
|
|
65274
65486
|
renderSkeleton: undefined,
|
|
65275
|
-
//
|
|
65276
|
-
//
|
|
65277
|
-
//
|
|
65278
|
-
|
|
65279
|
-
|
|
65280
|
-
|
|
65281
|
-
|
|
65282
|
-
|
|
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
|
+
}
|
|
65283
65522
|
},
|
|
65284
65523
|
// Whether any run of rows lives in this list: what makes a render window
|
|
65285
65524
|
// mean anything (see List's renderBudget).
|
|
@@ -65300,23 +65539,128 @@ const createListVirtual = () => {
|
|
|
65300
65539
|
}
|
|
65301
65540
|
return null;
|
|
65302
65541
|
},
|
|
65303
|
-
|
|
65304
|
-
|
|
65305
|
-
|
|
65306
|
-
|
|
65307
|
-
|
|
65308
|
-
const
|
|
65309
|
-
|
|
65310
|
-
|
|
65311
|
-
|
|
65312
|
-
|
|
65313
|
-
|
|
65314
|
-
|
|
65315
|
-
|
|
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();
|
|
65316
65579
|
}
|
|
65317
65580
|
};
|
|
65318
65581
|
return virtual;
|
|
65319
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
|
+
};
|
|
65320
65664
|
const VISIBILITY_HIDDEN_STYLE = {
|
|
65321
65665
|
visibility: "hidden"
|
|
65322
65666
|
};
|
|
@@ -65451,6 +65795,7 @@ const ListItems = ({
|
|
|
65451
65795
|
}) => {
|
|
65452
65796
|
const ownerId = useId();
|
|
65453
65797
|
const virtual = useContext(ListVirtualContext);
|
|
65798
|
+
const slot = useContext(ListSlotContext);
|
|
65454
65799
|
const renderWindow = useContext(RenderWindowContext);
|
|
65455
65800
|
const separator = useContext(SeparatorContext);
|
|
65456
65801
|
const store = useItemStore({
|
|
@@ -65472,7 +65817,7 @@ const ListItems = ({
|
|
|
65472
65817
|
skeletonRow.rowMinHeight = `${virtualItemSize}px`;
|
|
65473
65818
|
}
|
|
65474
65819
|
}
|
|
65475
|
-
const runStart = virtual.take(ownerId, store.rowCount);
|
|
65820
|
+
const runStart = virtual.take(ownerId, store.rowCount, slot ? slot.id : ownerId);
|
|
65476
65821
|
const runEnd = runStart + store.rowCount;
|
|
65477
65822
|
const getItemAt = index => store.getItem(index);
|
|
65478
65823
|
const windowFrom = renderWindow.start > runStart ? renderWindow.start : runStart;
|
|
@@ -65499,6 +65844,7 @@ const ListItems = ({
|
|
|
65499
65844
|
useLayoutEffect(() => {
|
|
65500
65845
|
return () => {
|
|
65501
65846
|
virtual.dropRowLocator(ownerId);
|
|
65847
|
+
virtual.drop(ownerId);
|
|
65502
65848
|
};
|
|
65503
65849
|
}, []);
|
|
65504
65850
|
|
|
@@ -66284,7 +66630,9 @@ const ListItemGroup = ({
|
|
|
66284
66630
|
"aria-labelledby": groupId,
|
|
66285
66631
|
children: jsx(GroupItemTrackerContext.Provider, {
|
|
66286
66632
|
value: groupTracker,
|
|
66287
|
-
children:
|
|
66633
|
+
children: jsx(ListDeclaredChildren, {
|
|
66634
|
+
children: children
|
|
66635
|
+
})
|
|
66288
66636
|
})
|
|
66289
66637
|
})]
|
|
66290
66638
|
});
|