@jsenv/navi 0.29.149 → 0.29.150
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 +180 -178
- package/dist/jsenv_navi.js.map +17 -16
- package/docs/create_and_edit.md +1 -1
- package/docs/popup_open.md +16 -11
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -42834,6 +42834,34 @@ const DetailsFieldContent = ({
|
|
|
42834
42834
|
});
|
|
42835
42835
|
};
|
|
42836
42836
|
|
|
42837
|
+
/**
|
|
42838
|
+
* Runs `fn` and commits whatever it re-renders before returning, instead of
|
|
42839
|
+
* letting Preact batch it into the next microtask. Layout effects of what gets
|
|
42840
|
+
* mounted run inside the call too, exactly as they would on any other commit.
|
|
42841
|
+
*
|
|
42842
|
+
* For the caller that has to read the DOM it just asked for — measuring an
|
|
42843
|
+
* element whose content it mounts in the same breath — and cannot wait a tick
|
|
42844
|
+
* to do it, because what comes after is a browser event still in flight
|
|
42845
|
+
* (preventDefault, focus placement) that no longer accepts being answered late.
|
|
42846
|
+
*
|
|
42847
|
+
* `options.debounceRendering` is Preact's own hook for deciding *when* the
|
|
42848
|
+
* render queue drains; swapping it for "right now" for the duration of the call
|
|
42849
|
+
* is exactly how preact/compat implements React's flushSync. Reserve it for the
|
|
42850
|
+
* case above: rendering synchronously in the middle of an event gives up the
|
|
42851
|
+
* batching that makes several state changes one commit.
|
|
42852
|
+
*/
|
|
42853
|
+
const flushSyncRendering = (fn) => {
|
|
42854
|
+
const debounceRenderingPrevious = options.debounceRendering;
|
|
42855
|
+
options.debounceRendering = (drainRenderQueue) => {
|
|
42856
|
+
drainRenderQueue();
|
|
42857
|
+
};
|
|
42858
|
+
try {
|
|
42859
|
+
fn();
|
|
42860
|
+
} finally {
|
|
42861
|
+
options.debounceRendering = debounceRenderingPrevious;
|
|
42862
|
+
}
|
|
42863
|
+
};
|
|
42864
|
+
|
|
42837
42865
|
/**
|
|
42838
42866
|
* Small, renderer-agnostic helpers shared by Popover and Dialog's own custom
|
|
42839
42867
|
* (non-top-layer) renderers — operate on a plain DOM element, no knowledge
|
|
@@ -43047,6 +43075,96 @@ const resolveAutoAnimationKind = (anchor, parsedPositionArea) => {
|
|
|
43047
43075
|
return anchor || (yIsOverlapping && xIsOverlapping) ? "scaling" : "sliding";
|
|
43048
43076
|
};
|
|
43049
43077
|
|
|
43078
|
+
/**
|
|
43079
|
+
* When a popup builds what it holds, and when it throws it away.
|
|
43080
|
+
*
|
|
43081
|
+
* A closed popup shows nothing, focuses nothing, and answers nothing: what it
|
|
43082
|
+
* holds is out of reach until it opens. Building that content at mount time
|
|
43083
|
+
* means a page carrying a handful of closed popups pays, on the very render
|
|
43084
|
+
* that decides how fast it appears, for content nobody has asked for — and
|
|
43085
|
+
* pays again on every subsequent measurement, since each of those nodes makes
|
|
43086
|
+
* the document the rest of the page queries bigger.
|
|
43087
|
+
*
|
|
43088
|
+
* So the content is built when the popup first opens, and stays built from
|
|
43089
|
+
* then on: closing is not throwing away, and a reopened popup finds its scroll
|
|
43090
|
+
* position, its half-typed form and its list state where it left them.
|
|
43091
|
+
*
|
|
43092
|
+
* It is built synchronously, from inside `openController.open()` and before
|
|
43093
|
+
* `openEffect` runs (see open_controller.js), so the popup still measures real
|
|
43094
|
+
* content when it positions and animates itself, and so anything inside it
|
|
43095
|
+
* still observes the opening the way it always did — mounted while the popup
|
|
43096
|
+
* reads as closed, told it opened right after (see
|
|
43097
|
+
* use_displayed_layout_effect.js).
|
|
43098
|
+
*
|
|
43099
|
+
* The `mount` prop moves that line. "closed" is two states, not one — never
|
|
43100
|
+
* opened yet, and closed again after an opening — and the three values answer
|
|
43101
|
+
* both at once:
|
|
43102
|
+
*
|
|
43103
|
+
* | mount | before the first open | after a close |
|
|
43104
|
+
* | ----------------- | --------------------- | ------------- |
|
|
43105
|
+
* | "always" | mounted | mounted |
|
|
43106
|
+
* | "from-first-open" | not mounted | mounted |
|
|
43107
|
+
* | "while-opened" | not mounted | not mounted |
|
|
43108
|
+
*
|
|
43109
|
+
* "always" is for content something else depends on before any opening: a
|
|
43110
|
+
* value the popup's owner reads off its own children, fields a form around it
|
|
43111
|
+
* collects on submit, a size measured from outside.
|
|
43112
|
+
*
|
|
43113
|
+
* "while-opened" is the opposite end: content that must be rebuilt from
|
|
43114
|
+
* scratch every time, because what it shows is read once at build time and can
|
|
43115
|
+
* change while the popup is closed — an uncontrolled field seeded from a
|
|
43116
|
+
* `defaultValue`, a form whose fresh state is its initial state.
|
|
43117
|
+
*/
|
|
43118
|
+
|
|
43119
|
+
|
|
43120
|
+
const MOUNT_DEFAULT = "from-first-open";
|
|
43121
|
+
|
|
43122
|
+
const usePopupContentMount = (
|
|
43123
|
+
openController,
|
|
43124
|
+
ref,
|
|
43125
|
+
{ children, mount = MOUNT_DEFAULT },
|
|
43126
|
+
) => {
|
|
43127
|
+
const mountedAlways = mount === "always";
|
|
43128
|
+
const [contentMounted, setContentMounted] = useState(
|
|
43129
|
+
() => mountedAlways || openController.opened,
|
|
43130
|
+
);
|
|
43131
|
+
openController.mountContent = contentMounted
|
|
43132
|
+
? null
|
|
43133
|
+
: () => {
|
|
43134
|
+
flushSyncRendering(() => {
|
|
43135
|
+
setContentMounted(true);
|
|
43136
|
+
});
|
|
43137
|
+
};
|
|
43138
|
+
openController.unmountContent =
|
|
43139
|
+
mount === "while-opened"
|
|
43140
|
+
? () => {
|
|
43141
|
+
const element = ref?.current;
|
|
43142
|
+
if (!element) {
|
|
43143
|
+
setContentMounted(false);
|
|
43144
|
+
return;
|
|
43145
|
+
}
|
|
43146
|
+
// The popup is still on screen while it plays its exit transition;
|
|
43147
|
+
// emptying it right away would show that transition running on a
|
|
43148
|
+
// blank surface.
|
|
43149
|
+
whenTransitionSettles(element, () => {
|
|
43150
|
+
if (openController.opened) {
|
|
43151
|
+
// reopened while it was leaving — the content it holds is the
|
|
43152
|
+
// one that open just asked for
|
|
43153
|
+
return;
|
|
43154
|
+
}
|
|
43155
|
+
setContentMounted(false);
|
|
43156
|
+
});
|
|
43157
|
+
}
|
|
43158
|
+
: null;
|
|
43159
|
+
useLayoutEffect(() => {
|
|
43160
|
+
if (mountedAlways) {
|
|
43161
|
+
setContentMounted(true);
|
|
43162
|
+
}
|
|
43163
|
+
}, [mountedAlways]);
|
|
43164
|
+
|
|
43165
|
+
return contentMounted ? children : null;
|
|
43166
|
+
};
|
|
43167
|
+
|
|
43050
43168
|
installImportMetaCssBuild(import.meta);/**
|
|
43051
43169
|
* Expandable: an in-flow disclosure — a UI part that reveals a content part.
|
|
43052
43170
|
* It covers the same ground as <Details> with structural differences:
|
|
@@ -43087,10 +43205,9 @@ installImportMetaCssBuild(import.meta);/**
|
|
|
43087
43205
|
* events.
|
|
43088
43206
|
*
|
|
43089
43207
|
* Content is not built until the first expansion and stays built afterwards —
|
|
43090
|
-
* same policy, same prop
|
|
43091
|
-
* `
|
|
43092
|
-
*
|
|
43093
|
-
* content).
|
|
43208
|
+
* same policy, same `mount` prop as popups (see popup_content_mount.js):
|
|
43209
|
+
* `"always"` builds it right away, `"while-opened"` throws it away once the
|
|
43210
|
+
* collapse settles (so a closing animation still plays on real content).
|
|
43094
43211
|
*
|
|
43095
43212
|
* The animation is a REVEAL, not a resize: the expandable's own footprint
|
|
43096
43213
|
* grows/shrinks progressively (the content's grid track interpolates
|
|
@@ -43252,8 +43369,7 @@ const useExpandableContext = partName => {
|
|
|
43252
43369
|
* layout?: "row" | "column",
|
|
43253
43370
|
* autoFocus?: boolean,
|
|
43254
43371
|
* maxContentHeight?: string | number,
|
|
43255
|
-
*
|
|
43256
|
-
* unmountWhenClosed?: boolean,
|
|
43372
|
+
* mount?: "always" | "from-first-open" | "while-opened",
|
|
43257
43373
|
* arrowKeyShortcuts?: boolean,
|
|
43258
43374
|
* openKeyShortcut?: string,
|
|
43259
43375
|
* closeKeyShortcut?: string,
|
|
@@ -43290,13 +43406,15 @@ const useExpandableContext = partName => {
|
|
|
43290
43406
|
* the UI part (it would otherwise be lost to the closed, inert content).
|
|
43291
43407
|
* @param maxContentHeight - Caps the content height; taller content scrolls
|
|
43292
43408
|
* inside the expandable instead of growing it.
|
|
43293
|
-
* @param
|
|
43294
|
-
*
|
|
43295
|
-
*
|
|
43296
|
-
*
|
|
43297
|
-
*
|
|
43298
|
-
*
|
|
43299
|
-
*
|
|
43409
|
+
* @param mount - When the content is built and thrown away, same three values
|
|
43410
|
+
* as a popup's (see popup_content_mount.js). `"from-first-open"` (the
|
|
43411
|
+
* default) builds it on the first expansion and keeps it afterwards.
|
|
43412
|
+
* `"always"` builds it right away; in layout="column" it also gives the
|
|
43413
|
+
* closed expandable its content's height (the content is kept laid out at
|
|
43414
|
+
* its open width), so opening only reveals the width instead of changing the
|
|
43415
|
+
* height too. `"while-opened"` throws the content away once the collapse
|
|
43416
|
+
* settles — after the closing animation, so it still plays on real
|
|
43417
|
+
* content — and rebuilds it from scratch on every expansion.
|
|
43300
43418
|
*/
|
|
43301
43419
|
const Expandable = props => {
|
|
43302
43420
|
import.meta.css = [css$Q, "@jsenv/navi/src/control/expandable/expandable.jsx"];
|
|
@@ -43312,8 +43430,7 @@ const Expandable = props => {
|
|
|
43312
43430
|
layout,
|
|
43313
43431
|
autoFocus,
|
|
43314
43432
|
maxContentHeight,
|
|
43315
|
-
|
|
43316
|
-
unmountWhenClosed,
|
|
43433
|
+
mount = MOUNT_DEFAULT,
|
|
43317
43434
|
arrowKeyShortcuts = true,
|
|
43318
43435
|
openKeyShortcut = "ArrowRight",
|
|
43319
43436
|
closeKeyShortcut = "ArrowLeft",
|
|
@@ -43326,7 +43443,9 @@ const Expandable = props => {
|
|
|
43326
43443
|
const contentContainerRef = useRef();
|
|
43327
43444
|
const contentId = useId();
|
|
43328
43445
|
const isColumn = layout === "column";
|
|
43329
|
-
const
|
|
43446
|
+
const mountedAlways = mount === "always";
|
|
43447
|
+
const mountedWhileOpened = mount === "while-opened";
|
|
43448
|
+
const closedContentSized = isColumn && mountedAlways;
|
|
43330
43449
|
// Reading .value during render is what subscribes the expandable to it.
|
|
43331
43450
|
const openRequested = signal ? signal.value : open;
|
|
43332
43451
|
const [opened, setOpened] = useState(() => Boolean(openRequested === undefined ? defaultOpen : openRequested));
|
|
@@ -43337,13 +43456,10 @@ const Expandable = props => {
|
|
|
43337
43456
|
const {
|
|
43338
43457
|
loading: actionLoading
|
|
43339
43458
|
} = useActionStatus(effectiveAction);
|
|
43340
|
-
const [contentMounted, setContentMounted] = useState(() =>
|
|
43341
|
-
// Same exclusion as popup_content_mount.js: content that must exist while
|
|
43342
|
-
// closed cannot also be thrown away on close.
|
|
43343
|
-
const effectiveUnmountWhenClosed = unmountWhenClosed && !mountWhenClosed;
|
|
43459
|
+
const [contentMounted, setContentMounted] = useState(() => mountedAlways || opened);
|
|
43344
43460
|
|
|
43345
43461
|
// Fully open and no longer moving — what allows overflow to become visible
|
|
43346
|
-
// (see the CSS) and what
|
|
43462
|
+
// (see the CSS) and what mount="while-opened" waits for before emptying.
|
|
43347
43463
|
const [settled, setSettled] = useState(true);
|
|
43348
43464
|
|
|
43349
43465
|
// Read before the close touches the DOM: flipping the content to inert can
|
|
@@ -43410,7 +43526,7 @@ const Expandable = props => {
|
|
|
43410
43526
|
focusedAtPointerDownRef.current = null;
|
|
43411
43527
|
setOpened(nextOpen);
|
|
43412
43528
|
// Flipped here, before the closing/opening commit, so effects of that very
|
|
43413
|
-
// commit already see the movement as started —
|
|
43529
|
+
// commit already see the movement as started — mount="while-opened" must not
|
|
43414
43530
|
// read a stale "settled" and empty the content under a closing animation.
|
|
43415
43531
|
setSettled(!animation);
|
|
43416
43532
|
if (signal) {
|
|
@@ -43532,17 +43648,17 @@ const Expandable = props => {
|
|
|
43532
43648
|
return cancel;
|
|
43533
43649
|
}, [opened]);
|
|
43534
43650
|
useLayoutEffect(() => {
|
|
43535
|
-
if (settled && !opened &&
|
|
43651
|
+
if (settled && !opened && mountedWhileOpened) {
|
|
43536
43652
|
setContentMounted(false);
|
|
43537
43653
|
}
|
|
43538
|
-
}, [settled, opened,
|
|
43654
|
+
}, [settled, opened, mountedWhileOpened]);
|
|
43539
43655
|
useLayoutEffect(() => {
|
|
43540
|
-
if (
|
|
43656
|
+
if (mountedAlways) {
|
|
43541
43657
|
setContentMounted(true);
|
|
43542
43658
|
}
|
|
43543
|
-
}, [
|
|
43659
|
+
}, [mountedAlways]);
|
|
43544
43660
|
|
|
43545
|
-
// closedContentSized (column +
|
|
43661
|
+
// closedContentSized (column + mount="always"): the closed content sizes
|
|
43546
43662
|
// the height (see the CSS), which is only right if it lies at its OPEN
|
|
43547
43663
|
// width — at its natural closed width (a 0-wide track) it would wrap
|
|
43548
43664
|
// against nothing and stack word by word. So while closed, its width is
|
|
@@ -53902,7 +54018,7 @@ const createOpenController = (
|
|
|
53902
54018
|
// previous subject first.
|
|
53903
54019
|
onOpen: null,
|
|
53904
54020
|
// The counterpart, set only when the popup was told to throw its content
|
|
53905
|
-
// away on close (`
|
|
54021
|
+
// away on close (`mount="while-opened"`). Called from performClose above.
|
|
53906
54022
|
unmountContent: null,
|
|
53907
54023
|
// Told whenever `opened` actually changes, whatever asked for it — an
|
|
53908
54024
|
// interaction, a command, a prop — with the event that asked. What lets a
|
|
@@ -54374,111 +54490,6 @@ const getAvailableWidth = (layer, element) => {
|
|
|
54374
54490
|
return visualViewportWidthSignal.peek();
|
|
54375
54491
|
};
|
|
54376
54492
|
|
|
54377
|
-
/**
|
|
54378
|
-
* Runs `fn` and commits whatever it re-renders before returning, instead of
|
|
54379
|
-
* letting Preact batch it into the next microtask. Layout effects of what gets
|
|
54380
|
-
* mounted run inside the call too, exactly as they would on any other commit.
|
|
54381
|
-
*
|
|
54382
|
-
* For the caller that has to read the DOM it just asked for — measuring an
|
|
54383
|
-
* element whose content it mounts in the same breath — and cannot wait a tick
|
|
54384
|
-
* to do it, because what comes after is a browser event still in flight
|
|
54385
|
-
* (preventDefault, focus placement) that no longer accepts being answered late.
|
|
54386
|
-
*
|
|
54387
|
-
* `options.debounceRendering` is Preact's own hook for deciding *when* the
|
|
54388
|
-
* render queue drains; swapping it for "right now" for the duration of the call
|
|
54389
|
-
* is exactly how preact/compat implements React's flushSync. Reserve it for the
|
|
54390
|
-
* case above: rendering synchronously in the middle of an event gives up the
|
|
54391
|
-
* batching that makes several state changes one commit.
|
|
54392
|
-
*/
|
|
54393
|
-
const flushSyncRendering = (fn) => {
|
|
54394
|
-
const debounceRenderingPrevious = options.debounceRendering;
|
|
54395
|
-
options.debounceRendering = (drainRenderQueue) => {
|
|
54396
|
-
drainRenderQueue();
|
|
54397
|
-
};
|
|
54398
|
-
try {
|
|
54399
|
-
fn();
|
|
54400
|
-
} finally {
|
|
54401
|
-
options.debounceRendering = debounceRenderingPrevious;
|
|
54402
|
-
}
|
|
54403
|
-
};
|
|
54404
|
-
|
|
54405
|
-
/**
|
|
54406
|
-
* When a popup builds what it holds, and when it throws it away.
|
|
54407
|
-
*
|
|
54408
|
-
* A closed popup shows nothing, focuses nothing, and answers nothing: what it
|
|
54409
|
-
* holds is out of reach until it opens. Building that content at mount time
|
|
54410
|
-
* means a page carrying a handful of closed popups pays, on the very render
|
|
54411
|
-
* that decides how fast it appears, for content nobody has asked for — and
|
|
54412
|
-
* pays again on every subsequent measurement, since each of those nodes makes
|
|
54413
|
-
* the document the rest of the page queries bigger.
|
|
54414
|
-
*
|
|
54415
|
-
* So the content is built when the popup first opens, and stays built from
|
|
54416
|
-
* then on: closing is not throwing away, and a reopened popup finds its scroll
|
|
54417
|
-
* position, its half-typed form and its list state where it left them.
|
|
54418
|
-
*
|
|
54419
|
-
* It is built synchronously, from inside `openController.open()` and before
|
|
54420
|
-
* `openEffect` runs (see open_controller.js), so the popup still measures real
|
|
54421
|
-
* content when it positions and animates itself, and so anything inside it
|
|
54422
|
-
* still observes the opening the way it always did — mounted while the popup
|
|
54423
|
-
* reads as closed, told it opened right after (see
|
|
54424
|
-
* use_displayed_layout_effect.js).
|
|
54425
|
-
*
|
|
54426
|
-
* `mountWhenClosed` is for content something else depends on before any of
|
|
54427
|
-
* this: a value the popup's owner reads off its own children, fields a form
|
|
54428
|
-
* around it collects on submit, a size measured from outside.
|
|
54429
|
-
*
|
|
54430
|
-
* `unmountWhenClosed` is the opposite end: content that must be rebuilt from
|
|
54431
|
-
* scratch every time, because what it shows is read once at build time and can
|
|
54432
|
-
* change while the popup is closed — an uncontrolled field seeded from a
|
|
54433
|
-
* `defaultValue`, a form whose fresh state is its initial state.
|
|
54434
|
-
*/
|
|
54435
|
-
|
|
54436
|
-
|
|
54437
|
-
const usePopupContentMount = (
|
|
54438
|
-
openController,
|
|
54439
|
-
ref,
|
|
54440
|
-
{ children, mountWhenClosed, unmountWhenClosed },
|
|
54441
|
-
) => {
|
|
54442
|
-
const [contentMounted, setContentMounted] = useState(
|
|
54443
|
-
() => Boolean(mountWhenClosed) || openController.opened,
|
|
54444
|
-
);
|
|
54445
|
-
openController.mountContent = contentMounted
|
|
54446
|
-
? null
|
|
54447
|
-
: () => {
|
|
54448
|
-
flushSyncRendering(() => {
|
|
54449
|
-
setContentMounted(true);
|
|
54450
|
-
});
|
|
54451
|
-
};
|
|
54452
|
-
openController.unmountContent =
|
|
54453
|
-
unmountWhenClosed && !mountWhenClosed
|
|
54454
|
-
? () => {
|
|
54455
|
-
const element = ref?.current;
|
|
54456
|
-
if (!element) {
|
|
54457
|
-
setContentMounted(false);
|
|
54458
|
-
return;
|
|
54459
|
-
}
|
|
54460
|
-
// The popup is still on screen while it plays its exit transition;
|
|
54461
|
-
// emptying it right away would show that transition running on a
|
|
54462
|
-
// blank surface.
|
|
54463
|
-
whenTransitionSettles(element, () => {
|
|
54464
|
-
if (openController.opened) {
|
|
54465
|
-
// reopened while it was leaving — the content it holds is the
|
|
54466
|
-
// one that open just asked for
|
|
54467
|
-
return;
|
|
54468
|
-
}
|
|
54469
|
-
setContentMounted(false);
|
|
54470
|
-
});
|
|
54471
|
-
}
|
|
54472
|
-
: null;
|
|
54473
|
-
useLayoutEffect(() => {
|
|
54474
|
-
if (mountWhenClosed) {
|
|
54475
|
-
setContentMounted(true);
|
|
54476
|
-
}
|
|
54477
|
-
}, [mountWhenClosed]);
|
|
54478
|
-
|
|
54479
|
-
return contentMounted ? children : null;
|
|
54480
|
-
};
|
|
54481
|
-
|
|
54482
54493
|
/**
|
|
54483
54494
|
* Entry/exit animation CSS shared by Popover and Dialog.
|
|
54484
54495
|
*
|
|
@@ -55669,16 +55680,15 @@ const css$E = /* css */`
|
|
|
55669
55680
|
* open controller (see `open_controller.js`) for a caller that wants to
|
|
55670
55681
|
* drive open/close itself instead of `open`/`defaultOpen`/`onClose` (used
|
|
55671
55682
|
* by `picker_custom.jsx`).
|
|
55672
|
-
* @param {
|
|
55673
|
-
*
|
|
55674
|
-
*
|
|
55675
|
-
*
|
|
55676
|
-
*
|
|
55677
|
-
*
|
|
55678
|
-
* popup has finished closing
|
|
55679
|
-
* fresh state is its initial state: an uncontrolled field
|
|
55680
|
-
* `defaultValue` that changed while the popup was closed.
|
|
55681
|
-
* `mountWhenClosed` is set.
|
|
55683
|
+
* @param {"always"|"from-first-open"|"while-opened"} [props.mount] - When
|
|
55684
|
+
* `children` are built and thrown away (see popup_content_mount.js).
|
|
55685
|
+
* `"from-first-open"` (the default) builds them on the first open and keeps
|
|
55686
|
+
* them afterwards. `"always"` builds them right away, for content something
|
|
55687
|
+
* depends on while the popup is still closed: a value read off it, fields a
|
|
55688
|
+
* surrounding form collects on submit, a size measured from outside.
|
|
55689
|
+
* `"while-opened"` throws them away once the popup has finished closing, for
|
|
55690
|
+
* content whose fresh state is its initial state: an uncontrolled field
|
|
55691
|
+
* seeded from a `defaultValue` that changed while the popup was closed.
|
|
55682
55692
|
* @param {import("ignore:preact").ComponentChildren} props.children
|
|
55683
55693
|
*/
|
|
55684
55694
|
const Dialog = props => {
|
|
@@ -55915,8 +55925,7 @@ const useDialogProps = props => {
|
|
|
55915
55925
|
// openController.onOpen below).
|
|
55916
55926
|
onOpen,
|
|
55917
55927
|
children: childrenProp,
|
|
55918
|
-
|
|
55919
|
-
unmountWhenClosed,
|
|
55928
|
+
mount,
|
|
55920
55929
|
...rest
|
|
55921
55930
|
} = props;
|
|
55922
55931
|
// Assigned on every render, like openEffect below, so it always closes over
|
|
@@ -55925,8 +55934,7 @@ const useDialogProps = props => {
|
|
|
55925
55934
|
openController.onOpen = onOpen || null;
|
|
55926
55935
|
const children = usePopupContentMount(openController, props.ref, {
|
|
55927
55936
|
children: childrenProp,
|
|
55928
|
-
|
|
55929
|
-
unmountWhenClosed
|
|
55937
|
+
mount
|
|
55930
55938
|
});
|
|
55931
55939
|
const isModal = layer === "top";
|
|
55932
55940
|
const ref = props.ref;
|
|
@@ -57139,16 +57147,15 @@ const css$D = /* css */`
|
|
|
57139
57147
|
* open controller (see `open_controller.js`) for a caller that wants to
|
|
57140
57148
|
* drive open/close itself instead of `open`/`defaultOpen`/`onClose` (used
|
|
57141
57149
|
* by `picker_custom.jsx`/`side_panel.jsx`).
|
|
57142
|
-
* @param {
|
|
57143
|
-
*
|
|
57144
|
-
*
|
|
57145
|
-
*
|
|
57146
|
-
*
|
|
57147
|
-
*
|
|
57148
|
-
* popup has finished closing
|
|
57149
|
-
* fresh state is its initial state: an uncontrolled field
|
|
57150
|
-
* `defaultValue` that changed while the popup was closed.
|
|
57151
|
-
* `mountWhenClosed` is set.
|
|
57150
|
+
* @param {"always"|"from-first-open"|"while-opened"} [props.mount] - When
|
|
57151
|
+
* `children` are built and thrown away (see popup_content_mount.js).
|
|
57152
|
+
* `"from-first-open"` (the default) builds them on the first open and keeps
|
|
57153
|
+
* them afterwards. `"always"` builds them right away, for content something
|
|
57154
|
+
* depends on while the popup is still closed: a value read off it, fields a
|
|
57155
|
+
* surrounding form collects on submit, a size measured from outside.
|
|
57156
|
+
* `"while-opened"` throws them away once the popup has finished closing, for
|
|
57157
|
+
* content whose fresh state is its initial state: an uncontrolled field
|
|
57158
|
+
* seeded from a `defaultValue` that changed while the popup was closed.
|
|
57152
57159
|
* @param {import("ignore:preact").ComponentChildren} props.children
|
|
57153
57160
|
*/
|
|
57154
57161
|
const Popover = props => {
|
|
@@ -57363,8 +57370,7 @@ const usePopoverProps = props => {
|
|
|
57363
57370
|
// openController.onOpen below).
|
|
57364
57371
|
onOpen,
|
|
57365
57372
|
children: childrenProp,
|
|
57366
|
-
|
|
57367
|
-
unmountWhenClosed,
|
|
57373
|
+
mount,
|
|
57368
57374
|
...rest
|
|
57369
57375
|
} = props;
|
|
57370
57376
|
// Assigned on every render, like openEffect below, so it always closes over
|
|
@@ -57373,8 +57379,7 @@ const usePopoverProps = props => {
|
|
|
57373
57379
|
openController.onOpen = onOpen || null;
|
|
57374
57380
|
const children = usePopupContentMount(openController, props.ref, {
|
|
57375
57381
|
children: childrenProp,
|
|
57376
|
-
|
|
57377
|
-
unmountWhenClosed
|
|
57382
|
+
mount
|
|
57378
57383
|
});
|
|
57379
57384
|
const isTopLayer = layer === "top";
|
|
57380
57385
|
const ref = props.ref;
|
|
@@ -58313,16 +58318,15 @@ const css$C = /* css */`@layer navi {
|
|
|
58313
58318
|
* @param {string} [props.className] - Merged with the shared
|
|
58314
58319
|
* `"navi_popup"` class (see this file's own CSS) rather than replacing
|
|
58315
58320
|
* it.
|
|
58316
|
-
* @param {
|
|
58317
|
-
*
|
|
58318
|
-
*
|
|
58319
|
-
*
|
|
58320
|
-
*
|
|
58321
|
-
*
|
|
58322
|
-
* popup has finished closing
|
|
58323
|
-
* fresh state is its initial state: an uncontrolled field
|
|
58324
|
-
* `defaultValue` that changed while the popup was closed.
|
|
58325
|
-
* `mountWhenClosed` is set.
|
|
58321
|
+
* @param {"always"|"from-first-open"|"while-opened"} [props.mount] - When
|
|
58322
|
+
* `children` are built and thrown away (see popup_content_mount.js).
|
|
58323
|
+
* `"from-first-open"` (the default) builds them on the first open and keeps
|
|
58324
|
+
* them afterwards. `"always"` builds them right away, for content something
|
|
58325
|
+
* depends on while the popup is still closed: a value read off it, fields a
|
|
58326
|
+
* surrounding form collects on submit, a size measured from outside.
|
|
58327
|
+
* `"while-opened"` throws them away once the popup has finished closing, for
|
|
58328
|
+
* content whose fresh state is its initial state: an uncontrolled field
|
|
58329
|
+
* seeded from a `defaultValue` that changed while the popup was closed.
|
|
58326
58330
|
* @param {import("ignore:preact").ComponentChildren} props.children
|
|
58327
58331
|
*/
|
|
58328
58332
|
const Popup = props => {
|
|
@@ -58852,8 +58856,7 @@ const PickerCustom = props => {
|
|
|
58852
58856
|
// and pushes it down instead, leaving the popup free to build its
|
|
58853
58857
|
// content only when it is first opened (see popup_content_mount.js).
|
|
58854
58858
|
// A caller who knows better says so with the popup's own props.
|
|
58855
|
-
|
|
58856
|
-
unmountWhenClosed: props.unmountWhenClosed,
|
|
58859
|
+
mount: props.mount ?? (isControlValueGivenByProps(props) ? MOUNT_DEFAULT : "always"),
|
|
58857
58860
|
// Not on pickerProps (the trigger): commands.js's own
|
|
58858
58861
|
// resolveClosestExpandable() does `el.closest("[aria-expanded]")` to
|
|
58859
58862
|
// find where to dispatch navi_request_open/navi_request_close — and
|
|
@@ -59139,8 +59142,7 @@ const PickerContentInsidePopup = props => {
|
|
|
59139
59142
|
...rest,
|
|
59140
59143
|
// On popupProps already (see the picker's popup assembly); they mean
|
|
59141
59144
|
// nothing to the picker element.
|
|
59142
|
-
|
|
59143
|
-
unmountWhenClosed: undefined,
|
|
59145
|
+
mount: undefined,
|
|
59144
59146
|
onFocusOut: e => {
|
|
59145
59147
|
if (!isPopover || !closeOnFocusOut) {
|
|
59146
59148
|
return;
|
|
@@ -59222,7 +59224,7 @@ const PICKER_CALLOUT_CONTENT_TOKEN = createOpenToken();
|
|
|
59222
59224
|
* The content is rendered through a portal into an element this component
|
|
59223
59225
|
* owns, handed to the callout as its message (a Node, appended as-is). It is
|
|
59224
59226
|
* rendered whether the callout is open or not, so what the content holds
|
|
59225
|
-
* survives a close, the way a popup's `
|
|
59227
|
+
* survives a close, the way a popup's `mount="always"` keeps it. The element
|
|
59226
59228
|
* carries data-picker-content: the callout is appended inside the picker root,
|
|
59227
59229
|
* and a press in there must read as inside the popup, not on the trigger.
|
|
59228
59230
|
*/
|
|
@@ -59401,10 +59403,10 @@ const PickerConfirmResolver = props => {
|
|
|
59401
59403
|
onConfirm: onConfirm
|
|
59402
59404
|
// A question holds no value to read before it is asked: the popup is
|
|
59403
59405
|
// built on the first open, like that of a picker told its value (see
|
|
59404
|
-
//
|
|
59406
|
+
// the `mount` resolution in picker_custom.jsx).
|
|
59405
59407
|
,
|
|
59406
59408
|
|
|
59407
|
-
|
|
59409
|
+
mount: MOUNT_DEFAULT,
|
|
59408
59410
|
message: undefined,
|
|
59409
59411
|
confirmLabel: undefined,
|
|
59410
59412
|
cancelLabel: undefined,
|