@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.
@@ -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 names as popups (see popup_content_mount.js):
43091
- * `mountWhenClosed` builds it right away, `unmountWhenClosed` throws it away
43092
- * once the collapse settles (so a closing animation still plays on real
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
- * mountWhenClosed?: boolean,
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 mountWhenClosed - Builds the content right away instead of on first
43294
- * expansion. In layout="column" it also gives the closed expandable its
43295
- * content's height (the content is kept laid out at its open width), so
43296
- * opening only reveals the width instead of changing the height too.
43297
- * @param unmountWhenClosed - Throws the content away once the collapse
43298
- * settles — after the closing animation, so it still plays on real content —
43299
- * and rebuilds it from scratch on every expansion.
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
- mountWhenClosed,
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 closedContentSized = Boolean(isColumn && mountWhenClosed);
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(() => Boolean(mountWhenClosed) || opened);
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 unmountWhenClosed waits for before emptying.
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 — unmountWhenClosed must not
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 && effectiveUnmountWhenClosed) {
43651
+ if (settled && !opened && mountedWhileOpened) {
43536
43652
  setContentMounted(false);
43537
43653
  }
43538
- }, [settled, opened, effectiveUnmountWhenClosed]);
43654
+ }, [settled, opened, mountedWhileOpened]);
43539
43655
  useLayoutEffect(() => {
43540
- if (mountWhenClosed) {
43656
+ if (mountedAlways) {
43541
43657
  setContentMounted(true);
43542
43658
  }
43543
- }, [mountWhenClosed]);
43659
+ }, [mountedAlways]);
43544
43660
 
43545
- // closedContentSized (column + mountWhenClosed): the closed content sizes
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 (`unmountWhenClosed`). Called from performClose above.
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 {boolean} [props.mountWhenClosed] - Builds `children` right away
55673
- * instead of waiting for the first open (see popup_content_mount.js). For
55674
- * content something depends on while the popup is still closed: a value read
55675
- * off it, fields a surrounding form collects on submit, a size measured from
55676
- * outside.
55677
- * @param {boolean} [props.unmountWhenClosed] - Throws `children` away once the
55678
- * popup has finished closing (see popup_content_mount.js). For content whose
55679
- * fresh state is its initial state: an uncontrolled field seeded from a
55680
- * `defaultValue` that changed while the popup was closed. Ignored when
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
- mountWhenClosed,
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
- mountWhenClosed,
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 {boolean} [props.mountWhenClosed] - Builds `children` right away
57143
- * instead of waiting for the first open (see popup_content_mount.js). For
57144
- * content something depends on while the popup is still closed: a value read
57145
- * off it, fields a surrounding form collects on submit, a size measured from
57146
- * outside.
57147
- * @param {boolean} [props.unmountWhenClosed] - Throws `children` away once the
57148
- * popup has finished closing (see popup_content_mount.js). For content whose
57149
- * fresh state is its initial state: an uncontrolled field seeded from a
57150
- * `defaultValue` that changed while the popup was closed. Ignored when
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
- mountWhenClosed,
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
- mountWhenClosed,
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 {boolean} [props.mountWhenClosed] - Builds `children` right away
58317
- * instead of waiting for the first open (see popup_content_mount.js). For
58318
- * content something depends on while the popup is still closed: a value read
58319
- * off it, fields a surrounding form collects on submit, a size measured from
58320
- * outside.
58321
- * @param {boolean} [props.unmountWhenClosed] - Throws `children` away once the
58322
- * popup has finished closing (see popup_content_mount.js). For content whose
58323
- * fresh state is its initial state: an uncontrolled field seeded from a
58324
- * `defaultValue` that changed while the popup was closed. Ignored when
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
- mountWhenClosed: props.mountWhenClosed ?? !isControlValueGivenByProps(props),
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
- mountWhenClosed: undefined,
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 `mountWhenClosed` keeps it. The element
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
- // mountWhenClosed in picker_custom.jsx).
59406
+ // the `mount` resolution in picker_custom.jsx).
59405
59407
  ,
59406
59408
 
59407
- mountWhenClosed: false,
59409
+ mount: MOUNT_DEFAULT,
59408
59410
  message: undefined,
59409
59411
  confirmLabel: undefined,
59410
59412
  cancelLabel: undefined,