@jsenv/navi 0.29.45 → 0.29.47

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.
@@ -2,7 +2,8 @@
2
2
  * AI reading this file: read ../docs/AI_INSTRUCTIONS.md for context on
3
3
  * using @jsenv/navi as intended.
4
4
  */
5
- import { installImportMetaCssBuild, windowHeightSignal, windowWidthSignal, visualViewportHeightSignal, visualViewportWidthSignal, getAppHeight, getAppWidth, coarsePointerSignal } from "./jsenv_navi_side_effects.js";
5
+ import { installImportMetaCssBuild, windowHeightSignal, windowWidthSignal, visualViewportHeightSignal, visualViewportWidthSignal, getAppHeight, getAppWidth, smallTouchScreenSignal } from "./jsenv_navi_side_effects.js";
6
+ export { coarsePointerSignal } from "./jsenv_navi_side_effects.js";
6
7
  import { elementIsFocusable, createPubSub, dispatchInternalCustomEvent, dispatchCustomEvent, getElementSignature, findEvent, createValueEffect, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, findFocusDelegateTarget, findFocusable, allowWheelThrough, dispatchPublicCustomEvent, resolveCSSColor, ELEMENT_SIZE_CHANGE, findSelfOrAncestorFixedPosition, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, applyNewPosition, measureLongestVisualLineWidth, chainEvent, waitForPressHeld, suppressClickAfterGesture, startDragToTravel, markDragSource, startDragTo, createIterableWeakSet, createEventGroupLogger, getKeyboardEventDefaultAction, activeElementSignal, normalizeStyle, mergeOneStyle, getPositionedParent, mergeTwoStyles, normalizeStyles, resolveCSSSize, hasCSSSizeUnit, resolveOklchLightness, contrastColor, closestOpenableAncestor, isAncestorOpen, observeAncestorOpenState, getAncestorOpenType, parsePositionArea, snapToPixel, trapFocusInside, trapScrollInside, onAncestorReopen, createGroupTransitionController, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, watchWheelTravel, scrollRoomTowards, findBefore, findAfter, initFocusGroup, scrollIntoViewScoped, getScrollContainer, canScroll, measureWidestChildRow, performTabNavigation, wheelGestureIsTakenFrom, releaseWheelGesture, claimWheelGesture, dragAfterIntent, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement, stringifyStyle as stringifyStyle$1 } from "@jsenv/dom";
7
8
  export { contrastColor, findEvent, startDragTo } from "@jsenv/dom";
8
9
  import { signal, computed, effect, batch, useSignal } from "@preact/signals";
@@ -49,17 +50,28 @@ const css$10 = /* css */`
49
50
  --navi-z-index-control-focused: 2;
50
51
 
51
52
  /* Kept stuck while something scrolls under it: a list header, the head
52
- and foot of a side panel, a table's sticky cells. Above raised
53
- controls a control scrolling past must go under the header that
54
- pins the column it belongs to, never over it.
55
-
56
- "While stuck" is the whole condition, and a sticky element cannot read
57
- its own stuck state in CSS: List marks its parts with a navi-stuck
58
- attribute and applies this band only there (see --list-*-z-index in
59
- list.jsx). A
60
- sticky part at rest is a block in the flow with nothing passing under
61
- it; giving it this band anyway is what slices whatever a neighbouring
62
- row lets out of its box. */
53
+ and foot of a side panel, a table's sticky cells, the header and
54
+ footer of any scrolling Box. Above raised controls a control
55
+ scrolling past must go under the header that pins the column it
56
+ belongs to, never over it.
57
+
58
+ A sticky element is a positioned one, so it already wins against
59
+ everything in the flow — the band is what it takes to also win against
60
+ what the page positioned itself, which loses to DOM order otherwise
61
+ (a sticky part is written before what scrolls under it). Box applies
62
+ it by default, isolated, and lets a call site write auto back:
63
+ --box-header-z-index / --box-footer-z-index.
64
+
65
+ "While stuck" is the condition the name states, and it costs something
66
+ to ignore: a sticky part at rest is a block in the flow with nothing
67
+ passing under it, and the band there is what slices whatever a
68
+ neighbouring row lets out of its box. CSS cannot express the
69
+ condition — an element cannot read its own stuck state — so it takes
70
+ measuring, which List does (it marks its parts with a navi-stuck
71
+ attribute against its own scroller and applies the band only there,
72
+ see --list-*-z-index in list.jsx) and Box does not: a generic
73
+ scrolling area does not know what it was given to scroll, and dropping
74
+ to auto there loses to a single position: relative. */
63
75
  --navi-z-index-sticky: 10;
64
76
 
65
77
  /* Pinned to the viewport, over the whole page: FixedBar. A decade of its
@@ -19030,14 +19042,24 @@ import.meta.css = [/* css */`
19030
19042
 
19031
19043
  [data-scrollable] {
19032
19044
  overflow: var(--x-scrollable-overflow, auto);
19045
+ --box-header-z-index: var(--navi-z-index-sticky);
19046
+ --box-footer-z-index: var(--navi-z-index-sticky);
19047
+ /* The band stays inside this box: without a stacking context here, "in
19048
+ front of my body" would be read as "in front of everything on the page"
19049
+ and a header would reach past a bar or a popup — which is exactly what
19050
+ the decades in navi_z_indexes.js are there to prevent. See
19051
+ docs/z_index.md. */
19052
+ isolation: isolate;
19033
19053
 
19034
19054
  &[data-scrollable-overflow="scroll"] {
19035
19055
  --x-scrollable-overflow: scroll;
19036
19056
  }
19037
19057
 
19038
- /* box-shadow rather than a border: it draws the separation without taking
19039
- part in the layout, so a header keeps the exact height its content asks
19040
- for and nothing shifts by a pixel when the line appears. */
19058
+ /* A real border and not a box-shadow: a shadow is drawn outside the box, so
19059
+ it lands on top of whatever comes next in the painting order and loses to
19060
+ it a body painting its own background over the line that was meant to
19061
+ separate them. The border belongs to the part itself and is always
19062
+ visible; the pixel it adds shifts nothing, these parts never shrink. */
19041
19063
  /* The corners are the container's, not the part's: a header sitting at the
19042
19064
  top of a rounded box has to follow that curve or it paints square over
19043
19065
  it (a dark header in a rounded popup is where this shows). inherit and
@@ -19045,18 +19067,18 @@ import.meta.css = [/* css */`
19045
19067
  > [data-header] {
19046
19068
  position: sticky;
19047
19069
  top: 0;
19048
- z-index: 1;
19070
+ z-index: var(--box-header-z-index);
19071
+ border-bottom: 1px solid var(--navi-separator-color-default);
19049
19072
  border-top-left-radius: inherit;
19050
19073
  border-top-right-radius: inherit;
19051
- box-shadow: 0 1px 0 var(--navi-separator-color-default);
19052
19074
  }
19053
19075
  > [data-footer] {
19054
19076
  position: sticky;
19055
19077
  bottom: 0;
19056
- z-index: 1;
19078
+ z-index: var(--box-footer-z-index);
19079
+ border-top: 1px solid var(--navi-separator-color-default);
19057
19080
  border-bottom-right-radius: inherit;
19058
19081
  border-bottom-left-radius: inherit;
19059
- box-shadow: 0 -1px 0 var(--navi-separator-color-default);
19060
19082
  }
19061
19083
 
19062
19084
  &:has(> [data-body]) {
@@ -19070,8 +19092,11 @@ import.meta.css = [/* css */`
19070
19092
 
19071
19093
  > [data-header],
19072
19094
  > [data-footer] {
19095
+ /* Nothing scrolls under them here — the body does that, next to them —
19096
+ so they are back to being blocks in the flow, and stacking is not
19097
+ their business anymore. */
19073
19098
  position: static;
19074
- z-index: unset;
19099
+ z-index: auto;
19075
19100
  flex-shrink: 0;
19076
19101
  }
19077
19102
 
@@ -25441,6 +25466,13 @@ const useControlProps = (props, {
25441
25466
  const onButtonInteractionAllowed = e => {
25442
25467
  triggerUIAction(e);
25443
25468
  const control = ref.current;
25469
+ if (!control) {
25470
+ // What the button just did took the button away: a command that
25471
+ // navigates, a popup closing over it. There is no control left to
25472
+ // ask for an action, and nothing is lost by not asking — what the
25473
+ // press was for has already happened.
25474
+ return;
25475
+ }
25444
25476
  tryActionAfterInteractionAllowed(control, {
25445
25477
  event: e,
25446
25478
  action: boundAction,
@@ -26989,37 +27021,45 @@ installImportMetaCssBuild(import.meta);const css$W = /* css */`
26989
27021
  --x-button-border-color: var(--callout-color);
26990
27022
  }
26991
27023
 
27024
+ /* A variant states what the caller did NOT: the frameless ones below move
27025
+ the DEFAULTS (--button-*) and never the resolved values (--x-button-*),
27026
+ so a backgroundColor/background/borderColor prop — which lands inline on
27027
+ this same element — still wins. Two things come with that: the
27028
+ transparent default is written as a fallback of --button-background, so
27029
+ the background prop feeds --button-background-color through it; and the
27030
+ per-state defaults are re-pointed at the base one, otherwise the @layer
27031
+ formulas (hover = 5% black over the background, readonly = the same)
27032
+ would repaint a box the variant just took away. */
27033
+
26992
27034
  /* discrete: background on hover, and nothing else — no box at rest, and no
26993
27035
  shrink when pressed. What is drawn IS the content (a chevron, a number,
26994
27036
  a word), and shrinking it under the finger reads as the content itself
26995
27037
  flinching rather than as a button being pressed. */
26996
27038
  &[data-variant="discrete"] {
26997
27039
  --button-border-width: 0;
26998
- --x-button-background-color: transparent;
26999
- --x-button-border-color: transparent;
27040
+ --button-border-color: transparent;
27041
+ --button-border-color-hover: var(--button-border-color);
27042
+ --button-border-color-current: var(--button-border-color);
27043
+ --button-border-color-readonly: var(--button-border-color);
27044
+ --button-border-color-disabled: var(--button-border-color);
27045
+ --button-background-color: var(--button-background, transparent);
27046
+ /* The hover wash is mixed INTO the background instead of replacing it:
27047
+ over the transparent default it is exactly the 8% of currentColor it
27048
+ has always been, and over a backgroundColor the caller gave it darkens
27049
+ that color rather than erasing it. */
27050
+ --button-background-color-hover: color-mix(
27051
+ in srgb,
27052
+ currentColor 8%,
27053
+ var(--button-background-color)
27054
+ );
27055
+ --button-background-color-readonly: var(--button-background-color);
27056
+ --button-background-color-disabled: var(--button-background-color);
27000
27057
 
27001
27058
  &[data-pressed] {
27002
27059
  .navi_button_content {
27003
27060
  transform: none;
27004
27061
  }
27005
27062
  }
27006
-
27007
- &[data-hover] {
27008
- --x-button-border-color: transparent;
27009
- --x-button-background-color: color-mix(
27010
- in srgb,
27011
- currentColor 8%,
27012
- transparent
27013
- );
27014
- }
27015
- &[data-readonly] {
27016
- --x-button-border-color: transparent;
27017
- --x-button-background-color: transparent;
27018
- }
27019
- &[data-disabled] {
27020
- --x-button-border-color: transparent;
27021
- --x-button-background-color: transparent;
27022
- }
27023
27063
  }
27024
27064
  /* bare: discrete, minus the background on hover. For a control whose own
27025
27065
  drawing IS the button (a carousel bullet, a swatch), where a box lighting
@@ -27028,13 +27068,16 @@ installImportMetaCssBuild(import.meta);const css$W = /* css */`
27028
27068
  on focus, commandable. */
27029
27069
  &[data-variant="bare"] {
27030
27070
  --button-border-width: 0;
27031
- --x-button-background-color: transparent;
27032
- --x-button-border-color: transparent;
27071
+ --button-border-color: transparent;
27072
+ --button-border-color-hover: var(--button-border-color);
27073
+ --button-border-color-current: var(--button-border-color);
27074
+ --button-border-color-readonly: var(--button-border-color);
27075
+ --button-border-color-disabled: var(--button-border-color);
27076
+ --button-background-color: var(--button-background, transparent);
27077
+ --button-background-color-hover: var(--button-background-color);
27078
+ --button-background-color-readonly: var(--button-background-color);
27079
+ --button-background-color-disabled: var(--button-background-color);
27033
27080
 
27034
- &[data-hover] {
27035
- --x-button-background-color: transparent;
27036
- --x-button-border-color: transparent;
27037
- }
27038
27081
  &[data-pressed] {
27039
27082
  .navi_button_content {
27040
27083
  transform: none;
@@ -27043,36 +27086,34 @@ installImportMetaCssBuild(import.meta);const css$W = /* css */`
27043
27086
  }
27044
27087
  /* discrete-border: border on hover */
27045
27088
  &[data-variant="discrete-border"] {
27046
- --x-button-background-color: transparent;
27089
+ --button-background-color: var(--button-background, transparent);
27090
+ --button-background-color-hover: var(--button-background-color);
27091
+ --button-background-color-readonly: var(--button-background-color);
27092
+ --button-background-color-disabled: var(--button-background-color);
27093
+ /* The border is the whole point of this variant: it is absent at rest
27094
+ and drawn on hover, so only the resting color goes transparent — the
27095
+ hover one keeps the @layer formula, now mixed from whatever
27096
+ borderColor the caller gave. */
27047
27097
  --x-button-border-color: transparent;
27048
27098
 
27049
27099
  &[data-hover] {
27050
27100
  --x-button-border-color: var(--button-border-color-hover);
27051
27101
  }
27052
- &[data-readonly] {
27053
- --x-button-border-color: transparent;
27054
- }
27102
+ &[data-readonly],
27055
27103
  &[data-disabled] {
27056
27104
  --x-button-border-color: transparent;
27057
27105
  }
27058
27106
  }
27059
27107
  /* border variant: no background, border only */
27060
27108
  &[data-variant="border"] {
27061
- --x-button-background-color: transparent;
27062
-
27063
- &[data-hover] {
27064
- --x-button-background-color: color-mix(
27065
- in srgb,
27066
- currentColor 8%,
27067
- transparent
27068
- );
27069
- }
27070
- &[data-readonly] {
27071
- --x-button-background-color: transparent;
27072
- }
27073
- &[data-disabled] {
27074
- --x-button-background-color: transparent;
27075
- }
27109
+ --button-background-color: var(--button-background, transparent);
27110
+ --button-background-color-hover: color-mix(
27111
+ in srgb,
27112
+ currentColor 8%,
27113
+ var(--button-background-color)
27114
+ );
27115
+ --button-background-color-readonly: var(--button-background-color);
27116
+ --button-background-color-disabled: var(--button-background-color);
27076
27117
  }
27077
27118
  /* Last word on the shrink, over whatever the variant decided: the variant
27078
27119
  guesses from how the button is drawn, and that guess is wrong as soon as
@@ -29169,17 +29210,19 @@ const css$V = /* css */`
29169
29210
  * shown via the non-modal `.show()` instead, staying in normal document
29170
29211
  * flow inside its own positioned ancestor — confined to (and clipped by)
29171
29212
  * that container instead of the whole viewport.
29172
- * @param {boolean} [props.dockedOnTouch] - Turns the dialog into a bottom sheet
29173
- * (docked flush to the bottom edge, full width) when the pointer is coarse,
29174
- * and leaves it alone otherwise. For a dialog meant to be interacted with
29175
- * rather than merely read: under a finger the keyboard owns the bottom of
29176
- * the screen and a centered box ends up both cramped and out of thumb
29177
- * reach, while under a mouse the centered box is already the right shape
29178
- * hence a prop that only ever does something on touch. It supplies defaults
29179
- * for `positionArea`, `marginWithContainer`, `expandX` and `scrollCapture`,
29180
- * so any of them can still be pinned explicitly. Keyed off `(pointer: coarse)` (the
29181
- * input device, not a width breakpoint — a narrow desktop window is still a
29182
- * mouse) via `coarsePointerSignal`, so it re-resolves live.
29213
+ * @param {boolean} [props.dockedOnSmallTouchScreen] - Turns the dialog into a
29214
+ * bottom sheet (docked flush to the bottom edge, full width) on a small touch
29215
+ * screen, and leaves it alone otherwise. For a dialog meant to be interacted
29216
+ * with rather than merely read: on a phone the keyboard owns the bottom of
29217
+ * the screen and a centered box ends up both cramped and out of thumb reach,
29218
+ * while under a mouse the centered box is already the right shape. Both
29219
+ * halves of the name matter (`smallTouchScreenSignal`): touch alone would
29220
+ * dock a big touch screen — a tablet, a kiosk panel — a whole screen away
29221
+ * from where the finger just tapped, and size alone would dock a narrow
29222
+ * desktop window, which is still a mouse. It supplies defaults for
29223
+ * `positionArea`, `marginWithContainer`, `expandX` and `scrollCapture`, so
29224
+ * any of them can still be pinned explicitly. Re-resolves live as the pointer
29225
+ * type or the window size changes.
29183
29226
  * @param {string} [props.positionArea="center"] - Where to dock the dialog
29184
29227
  * within its container (the viewport for `layer="top"`, the positioned
29185
29228
  * ancestor for `layer="local"`) — Dialog is never anchored to a real
@@ -29192,8 +29235,8 @@ const css$V = /* css */`
29192
29235
  * `inset(top)`) for the overlapping variant.
29193
29236
  * @param {boolean} [props.expand] - Shorthand for both `expandX` and `expandY`.
29194
29237
  * @param {boolean} [props.expandX] - Stretches the dialog to the full width its
29195
- * container allows (`--dialog-maxmax-width`). Set by `dockedOnTouch` on a
29196
- * touch device.
29238
+ * container allows (`--dialog-maxmax-width`). Set by
29239
+ * `dockedOnSmallTouchScreen` on a small touch screen.
29197
29240
  * @param {boolean} [props.expandY] - Same, vertically
29198
29241
  * (`--dialog-maxmax-height`).
29199
29242
  * @param {string|number} [props.marginWithContainer="3appw"] - Minimum gap kept
@@ -29223,7 +29266,7 @@ const css$V = /* css */`
29223
29266
  * A `layer="local"` dialog always locks its own positioned ancestor's
29224
29267
  * scroll while open (its backdrop only covers the scrollport, so scrolling
29225
29268
  * there would reveal uncovered content); this prop extends the lock to the
29226
- * whole page. Defaults to `true` for a dialog docked by `dockedOnTouch`.
29269
+ * whole page. Defaults to `true` for a dialog docked by `dockedOnSmallTouchScreen`.
29227
29270
  * @param {boolean|"auto"|"fading"|"scaling"|"sliding"|`slide-from-${string}`} [props.animation]
29228
29271
  * - `true`/`"auto"` resolves to `"scaling"` for a centered `positionArea`,
29229
29272
  * or a concrete `"slide-from-*"` direction otherwise. Any other explicit
@@ -29406,10 +29449,10 @@ const DialogLocal = props => {
29406
29449
  * contentProps]` — `backdropProps` is `null` for the via-attribute renderer
29407
29450
  * (its own backdrop is native, not a real element).
29408
29451
  */
29409
- // What a dialog turns into under a finger. "bottom" is not a taste: it puts
29410
- // the dialog in the zone a handheld device is actually operated from — where
29411
- // the thumbs rest and where the virtual keyboard comes up — instead of the
29412
- // middle of the screen, which is the farthest point from both.
29452
+ // What a dialog turns into on a small touch screen. "bottom" is not a taste:
29453
+ // it puts the dialog in the zone a phone is actually operated from — where the
29454
+ // thumbs rest and where the virtual keyboard comes up — instead of the middle
29455
+ // of the screen, which is the farthest point from both.
29413
29456
  // Only defaults: an explicitly passed prop still wins, so the docked shape can
29414
29457
  // be adjusted one axis at a time instead of being all-or-nothing.
29415
29458
  const DOCKED = {
@@ -29447,7 +29490,7 @@ const useDialogProps = props => {
29447
29490
  // .show() instead, staying in normal document flow, position: absolute
29448
29491
  // relative to its own positioned ancestor. See this file's top comment.
29449
29492
  layer = "top",
29450
- dockedOnTouch,
29493
+ dockedOnSmallTouchScreen,
29451
29494
  // Same grammar as Popover's own positionArea — see this file's top
29452
29495
  // comment and popup_shared.js's parsePositionArea.
29453
29496
  positionArea: positionAreaProp,
@@ -29500,9 +29543,10 @@ const useDialogProps = props => {
29500
29543
  });
29501
29544
  const isModal = layer === "top";
29502
29545
  const ref = props.ref;
29503
- // Only touch changes anything: with a mouse a dialog already wants to be the
29504
- // centered box it is by default, so there is nothing to resolve there.
29505
- const isDocked = dockedOnTouch && coarsePointerSignal.value;
29546
+ // Only a small touch screen changes anything: on a mouse and on a touch
29547
+ // screen too big to reach the bottom edge of a dialog already wants to be
29548
+ // the centered box it is by default, so there is nothing to resolve.
29549
+ const isDocked = dockedOnSmallTouchScreen && smallTouchScreenSignal.value;
29506
29550
  const positionArea = positionAreaProp ?? (isDocked ? DOCKED.positionArea : "center");
29507
29551
  const marginWithContainer = marginWithContainerProp ?? (isDocked ? DOCKED.marginWithContainer :
29508
29552
  // A share of whatever holds the dialog: the app's own screen for a
@@ -31645,8 +31689,8 @@ const css$T = /* css */`
31645
31689
  * @property {"close"|"cancel"|"capture"|"none"} [pointerInteractionOutsideEffect]
31646
31690
  * - What a click outside does. `"capture"`/`"none"` force an explicit answer
31647
31691
  * by refusing to treat a click elsewhere as one.
31648
- * @property {boolean} [dockedOnTouch] - `"dialog"` mode only: turn the popup
31649
- * into a bottom sheet under a finger.
31692
+ * @property {boolean} [dockedOnSmallTouchScreen] - `"dialog"` mode only: turn
31693
+ * the popup into a bottom sheet on a small touch screen.
31650
31694
  * @property {(params: { message: import("ignore:preact").ComponentChildren }) => import("ignore:preact").ComponentChildren} [renderContent]
31651
31695
  * - Replaces the popup body — the question and the two buttons — for every
31652
31696
  * confirmation at once. The per-button `confirmPopupContent` prop is the same
@@ -31664,7 +31708,7 @@ const confirmPopupOptions = {
31664
31708
  animationDuration: undefined,
31665
31709
  positionArea: undefined,
31666
31710
  pointerInteractionOutsideEffect: "close",
31667
- dockedOnTouch: false,
31711
+ dockedOnSmallTouchScreen: false,
31668
31712
  renderContent: undefined
31669
31713
  };
31670
31714
 
@@ -31746,7 +31790,7 @@ const ConfirmPopup = ({
31746
31790
  animationDuration,
31747
31791
  positionArea,
31748
31792
  pointerInteractionOutsideEffect,
31749
- dockedOnTouch,
31793
+ dockedOnSmallTouchScreen,
31750
31794
  renderContent
31751
31795
  } = confirmPopupOptions;
31752
31796
 
@@ -31782,7 +31826,7 @@ const ConfirmPopup = ({
31782
31826
  if (mode === "dialog") {
31783
31827
  return jsx(Dialog, {
31784
31828
  className: "navi_confirm_popup",
31785
- dockedOnTouch: dockedOnTouch,
31829
+ dockedOnSmallTouchScreen: dockedOnSmallTouchScreen,
31786
31830
  ...popupProps,
31787
31831
  children: body
31788
31832
  });
@@ -32037,6 +32081,16 @@ const debounceSignal = (
32037
32081
  * The action will not fire while the user is actively changing filters; it fires once
32038
32082
  * they pause for half a second.
32039
32083
  */
32084
+ // The run is not awaited here, and a rejection nobody waits for is an unhandled
32085
+ // one — in dev, an error overlay thrown over a page that is already saying what
32086
+ // went wrong. Nothing is lost by dropping it: the failure is held by the action
32087
+ // itself, and whoever reads it (useAsyncData, <Button action>) is what shows it.
32088
+ const runUnwatched = (result) => {
32089
+ if (result && typeof result.catch === "function") {
32090
+ result.catch(() => {});
32091
+ }
32092
+ };
32093
+
32040
32094
  const actionRunEffect = (
32041
32095
  action,
32042
32096
  deriveActionParamsFromSignals,
@@ -32086,7 +32140,7 @@ const actionRunEffect = (
32086
32140
  // falsy params, don't run
32087
32141
  return;
32088
32142
  }
32089
- actionTarget.run({ reason: "truthy params first run" });
32143
+ runUnwatched(actionTarget.run({ reason: "truthy params first run" }));
32090
32144
  return;
32091
32145
  }
32092
32146
 
@@ -32103,16 +32157,20 @@ const actionRunEffect = (
32103
32157
  }
32104
32158
  if (!actionTargetPrevious.params) {
32105
32159
  // coming from falsy-params state: action may already be cached, avoid unnecessary rerun
32106
- actionTarget.run({ reason: "params restored from falsy state" });
32160
+ runUnwatched(
32161
+ actionTarget.run({ reason: "params restored from falsy state" }),
32162
+ );
32107
32163
  } else {
32108
- actionTarget.rerun({ reason: "params modified" });
32164
+ runUnwatched(actionTarget.rerun({ reason: "params modified" }));
32109
32165
  }
32110
32166
  }
32111
32167
  },
32112
32168
  ...options,
32113
32169
  });
32114
32170
  if (actionParamsSignal.peek()) {
32115
- actionRunnedByThisEffect.run({ reason: "initial truthy params" });
32171
+ runUnwatched(
32172
+ actionRunnedByThisEffect.run({ reason: "initial truthy params" }),
32173
+ );
32116
32174
  }
32117
32175
  return actionRunnedByThisEffect;
32118
32176
  };
@@ -35236,6 +35294,24 @@ const TYPE_CONVERTERS = {
35236
35294
  },
35237
35295
  };
35238
35296
 
35297
+ /**
35298
+ * A container has put its page on screen — or as much of it as it can.
35299
+ *
35300
+ * A route matching is a signal changing, and the page it selects reaches the
35301
+ * DOM only once Preact has rendered — an unknown number of passes later, in an
35302
+ * unknown number of microtasks. Anyone who needs the page as it IS rather than
35303
+ * as it has been decided (a travel about to have its picture taken by the
35304
+ * browser, see route_travel.jsx) waits for this instead of counting.
35305
+ *
35306
+ * A page waiting on data is announced too, by the boundary showing its loading
35307
+ * state (see Loading in use_async_data.jsx): what the container could put on
35308
+ * screen is what the browser is about to take a picture of, and a page that
35309
+ * cannot render yet would otherwise be waited on until the transition dies of
35310
+ * it. It lives in a module of its own for that: the async layer says it as much
35311
+ * as the router does, and neither can import the other.
35312
+ */
35313
+ const [publishRouteRender, observeRouteRender] = createPubSub();
35314
+
35239
35315
  const promiseStateWeakMap = new WeakMap();
35240
35316
  const usePromiseAsyncData = (
35241
35317
  promise,
@@ -35290,7 +35366,8 @@ const useForceRender = () => {
35290
35366
 
35291
35367
  const useAsyncData = (promiseOrAction, {
35292
35368
  loading = "delegate",
35293
- error = "delegate"
35369
+ error = "delegate",
35370
+ onLoad
35294
35371
  } = {}) => {
35295
35372
  const isAction = Boolean(promiseOrAction && promiseOrAction.isAction);
35296
35373
  if (loading === true) {
@@ -35302,7 +35379,8 @@ const useAsyncData = (promiseOrAction, {
35302
35379
  if (isAction) {
35303
35380
  return useActionAsyncData(promiseOrAction, {
35304
35381
  loadingEffect: loading,
35305
- errorEffect: error
35382
+ errorEffect: error,
35383
+ onLoad
35306
35384
  });
35307
35385
  }
35308
35386
  return usePromiseAsyncData(promiseOrAction, {
@@ -35319,12 +35397,14 @@ const dismissedActionWeakSet = new WeakSet();
35319
35397
  const dismissedActionPendingPromiseWeakMap = new WeakMap();
35320
35398
  const useActionAsyncData = (action, {
35321
35399
  loadingEffect,
35322
- errorEffect
35400
+ errorEffect,
35401
+ onLoad
35323
35402
  }) => {
35324
35403
  const loadingRef = useContext(LoadingContext);
35325
35404
  if (!loadingRef) {
35326
35405
  throw new Error("Missing <Loading>");
35327
35406
  }
35407
+ useOnLoad(action, onLoad);
35328
35408
 
35329
35409
  // Use peek() instead of .value to avoid subscribing this component to the signal.
35330
35410
  // Reading .value would make Preact re-render the component reactively when the state
@@ -35445,6 +35525,41 @@ const useActionAsyncData = (action, {
35445
35525
  throw pendingPromise;
35446
35526
  };
35447
35527
 
35528
+ // What a screen does with the data once, when it becomes known (see onLoad in
35529
+ // the JSDoc above). Kept apart because the two questions it answers are not the
35530
+ // ones the hook around it answers: WHEN — a layout effect, so a form taking its
35531
+ // reference in the same tick sees what was written; and HOW OFTEN — once per set
35532
+ // of params, which is the action's own answer to "is this another thing or the
35533
+ // same one again".
35534
+ const NOTHING_SEEDED = Symbol("nothing_seeded");
35535
+ const useOnLoad = (action, onLoad) => {
35536
+ const onLoadRef = useRef(onLoad);
35537
+ onLoadRef.current = onLoad;
35538
+ const paramsSeededRef = useRef(NOTHING_SEEDED);
35539
+ useLayoutEffect(() => {
35540
+ const callback = onLoadRef.current;
35541
+ if (!callback) {
35542
+ return;
35543
+ }
35544
+ if (action.runningStateSignal.peek() !== COMPLETED) {
35545
+ return;
35546
+ }
35547
+ const data = action.dataSignal.peek();
35548
+ if (data === undefined) {
35549
+ return;
35550
+ }
35551
+ const params = action.paramsSignal.peek();
35552
+ const paramsSeeded = paramsSeededRef.current;
35553
+ if (paramsSeeded !== NOTHING_SEEDED && compareTwoJsValues(params, paramsSeeded)) {
35554
+ return;
35555
+ }
35556
+ paramsSeededRef.current = params;
35557
+ callback(data, {
35558
+ params
35559
+ });
35560
+ });
35561
+ };
35562
+
35448
35563
  // ─── Loading ──────────────────────────────────────────────────────────────────
35449
35564
  // Wraps Suspense. Provides LoadingContext so useAction can write the suspension
35450
35565
  // reason. LoadingFallback reads that reason and subscribes to the action so it
@@ -35484,6 +35599,14 @@ const LoadingFallback = ({
35484
35599
  setTick(n => n + 1);
35485
35600
  });
35486
35601
  }, [action]);
35602
+ // A page that suspends never gets to say it is on screen — its own effects
35603
+ // are held with it — so this says it for it: what the document shows of the
35604
+ // page arriving is this. Anyone waiting for the page to be there before
35605
+ // moving (a travel about to have its picture taken, see route_travel.jsx)
35606
+ // would otherwise wait for a render that cannot happen until the data does.
35607
+ useLayoutEffect(() => {
35608
+ publishRouteRender();
35609
+ });
35487
35610
  if (loadingRef.current.reason !== "loading") {
35488
35611
  return null;
35489
35612
  }
@@ -36916,7 +37039,6 @@ const Head = ({
36916
37039
  * ```
36917
37040
  */
36918
37041
 
36919
- const [publishRouteRender, observeRouteRender] = createPubSub();
36920
37042
 
36921
37043
  /**
36922
37044
  * Keep every container showing the page it is showing, whatever the routes say.
@@ -37204,6 +37326,10 @@ installImportMetaCssBuild(import.meta);/**
37204
37326
  const CAN_KEEP_PICTURE = Boolean(document.startViewTransition && !document.startViewTransition.isPolyfill);
37205
37327
  const startViewTransition = ensureDocumentStartViewTransition();
37206
37328
  const TRAVEL_ATTRIBUTE = "data-navi-route-travel";
37329
+ // Which way the pages move, said on the document: the pictures of a transition
37330
+ // hang off the root, not off the box that travels, so the box's own `axis` has
37331
+ // to be lent to the document for the length of the travel.
37332
+ const TRAVEL_AXIS_ATTRIBUTE = "data-navi-route-travel-axis";
37207
37333
  // While a finger holds the travel: the pictures stand still and go exactly
37208
37334
  // where it says (see the CSS, and scrubTravel).
37209
37335
  const HOLD_ATTRIBUTE = "data-navi-route-travel-held";
@@ -37397,6 +37523,28 @@ const css$R = /* css */`
37397
37523
  }
37398
37524
  }
37399
37525
 
37526
+ /* The same four movements, along the axis the pages are laid out on: the
37527
+ start of a column is its top, so going forward there is the page rising and
37528
+ the next one coming up from below. */
37529
+ :root[${TRAVEL_AXIS_ATTRIBUTE}="y"] {
37530
+ &[${TRAVEL_ATTRIBUTE}="forward"] {
37531
+ &::view-transition-old(navi-route-travel) {
37532
+ animation-name: navi-route-travel-leave-towards-top;
37533
+ }
37534
+ &::view-transition-new(navi-route-travel) {
37535
+ animation-name: navi-route-travel-enter-from-bottom;
37536
+ }
37537
+ }
37538
+ &[${TRAVEL_ATTRIBUTE}="back"] {
37539
+ &::view-transition-old(navi-route-travel) {
37540
+ animation-name: navi-route-travel-leave-towards-bottom;
37541
+ }
37542
+ &::view-transition-new(navi-route-travel) {
37543
+ animation-name: navi-route-travel-enter-from-top;
37544
+ }
37545
+ }
37546
+ }
37547
+
37400
37548
  @keyframes navi-route-travel-leave-towards-start {
37401
37549
  from {
37402
37550
  translate: 0 0;
@@ -37429,6 +37577,38 @@ const css$R = /* css */`
37429
37577
  translate: 0 0;
37430
37578
  }
37431
37579
  }
37580
+ @keyframes navi-route-travel-leave-towards-top {
37581
+ from {
37582
+ translate: 0 0;
37583
+ }
37584
+ to {
37585
+ translate: 0 -100%;
37586
+ }
37587
+ }
37588
+ @keyframes navi-route-travel-enter-from-bottom {
37589
+ from {
37590
+ translate: 0 100%;
37591
+ }
37592
+ to {
37593
+ translate: 0 0;
37594
+ }
37595
+ }
37596
+ @keyframes navi-route-travel-leave-towards-bottom {
37597
+ from {
37598
+ translate: 0 0;
37599
+ }
37600
+ to {
37601
+ translate: 0 100%;
37602
+ }
37603
+ }
37604
+ @keyframes navi-route-travel-enter-from-top {
37605
+ from {
37606
+ translate: 0 -100%;
37607
+ }
37608
+ to {
37609
+ translate: 0 0;
37610
+ }
37611
+ }
37432
37612
  `;
37433
37613
 
37434
37614
  /**
@@ -37565,6 +37745,7 @@ const RouteTravel = ({
37565
37745
  // own for as long as it is the one travelling.
37566
37746
  nameForTravel(elementRef.current);
37567
37747
  document.documentElement.setAttribute(TRAVEL_ATTRIBUTE, direction);
37748
+ document.documentElement.setAttribute(TRAVEL_AXIS_ATTRIBUTE, axis);
37568
37749
  if (scrub) {
37569
37750
  holdPictures(travel);
37570
37751
  document.documentElement.setAttribute(DRAGGED_ATTRIBUTE, "");
@@ -37578,14 +37759,21 @@ const RouteTravel = ({
37578
37759
  const releaseRendering = renderingHeldForRouting || holdRendering();
37579
37760
  renderingHeldForRouting = null;
37580
37761
  // The picture the browser is about to take must be of the page that was
37581
- // asked for, and a route matching is not yet a page rendered.
37762
+ // asked for, and a route matching is not yet a page rendered. Watched from
37763
+ // here rather than from inside the callback below: the browser calls that
37764
+ // callback a frame later, and a navigation that has already been decided
37765
+ // (what follows a send, a command) renders its page in between. A wait
37766
+ // armed then waits for something that has already happened — until the
37767
+ // browser gives up on the transition, leaving the page it was leaving on
37768
+ // screen and an error nobody asked for.
37769
+ const renderWait = armRouteRenderWait();
37582
37770
  const viewTransition = startViewTransition(async () => {
37583
37771
  await whilePageRenders(page, async () => {
37584
37772
  releaseRendering();
37585
37773
  if (change) {
37586
37774
  await change();
37587
37775
  }
37588
- });
37776
+ }, renderWait);
37589
37777
  // The page arriving is in the DOM and the transition has not started
37590
37778
  // playing: the one moment both boxes can be known.
37591
37779
  holdTravelHeight(elementRef.current, heightBefore);
@@ -37610,6 +37798,7 @@ const RouteTravel = ({
37610
37798
  viewTransition.finished.catch(() => {
37611
37799
  // A transition that fails before it ever calls back leaves the page held:
37612
37800
  // whoever asked for the hold gives it back, here as everywhere else.
37801
+ renderWait.stop();
37613
37802
  releaseRendering();
37614
37803
  endTravel(travel);
37615
37804
  });
@@ -37913,6 +38102,7 @@ const RouteTravel = ({
37913
38102
  // rather than pick.
37914
38103
  unnameAfterTravel(elementRef.current);
37915
38104
  document.documentElement.removeAttribute(TRAVEL_ATTRIBUTE);
38105
+ document.documentElement.removeAttribute(TRAVEL_AXIS_ATTRIBUTE);
37916
38106
  document.documentElement.removeAttribute(DRAGGED_ATTRIBUTE);
37917
38107
  document.documentElement.removeAttribute(TURNED_ATTRIBUTE);
37918
38108
  releaseTravelHeight();
@@ -38475,20 +38665,30 @@ const scrubTravel = (travel, ratio) => {
38475
38665
  // inside the callback of a view transition: the browser has stopped rendering
38476
38666
  // and is waiting on this very promise to take its picture, so a wait that never
38477
38667
  // ends is a page frozen under a transition that never became ready.
38478
- const whilePageRenders = async (page, change) => {
38668
+ // Listening starts before the change, or a render landing while the change is
38669
+ // being awaited is a render nobody heard. Armed apart from the wait itself
38670
+ // because the two do not always happen at the same moment: a view transition
38671
+ // calls its update callback a frame after it is started, and the render can
38672
+ // land in that gap — see beginTravel, which arms this the moment the travel is
38673
+ // decided and hands it over.
38674
+ const armRouteRenderWait = () => {
38479
38675
  let stopListening;
38480
38676
  const rendered = new Promise(resolve => {
38481
- // Listened for before the change, or a render landing while the change is
38482
- // being awaited is a render nobody heard.
38483
38677
  stopListening = observeRouteRender(resolve);
38484
38678
  });
38679
+ return {
38680
+ rendered,
38681
+ stop: () => stopListening()
38682
+ };
38683
+ };
38684
+ const whilePageRenders = async (page, change, wait = armRouteRenderWait()) => {
38485
38685
  try {
38486
38686
  await change();
38487
38687
  if (pageIsCurrent(page)) {
38488
- await rendered;
38688
+ await wait.rendered;
38489
38689
  }
38490
38690
  } finally {
38491
- stopListening();
38691
+ wait.stop();
38492
38692
  }
38493
38693
  };
38494
38694
 
@@ -38536,12 +38736,20 @@ const pageIsCurrent = ({
38536
38736
  }
38537
38737
  return params ? route.matchesParams(params) : true;
38538
38738
  };
38539
- // Every page is read, never only up to the one that answers yes: a page that is
38540
- // not the current one today is the one that must wake the reader tomorrow.
38739
+ // The FIRST page that answers, as with the branches of a <Route>: several
38740
+ // routes match at once — a literal one and the parameterized one it is a case of
38741
+ // ("/games/new" is also a "/games/:gameId"), a section and the page inside it —
38742
+ // and the row has to be on the page the router is showing, which is the first
38743
+ // one written that matches.
38744
+ //
38745
+ // Every page is read all the same, never only up to the one that answers yes: a
38746
+ // page that is not the current one today is the one that must wake the reader
38747
+ // tomorrow.
38541
38748
  const currentPageIndex = pages => {
38542
38749
  let currentIndex = -1;
38543
38750
  for (let i = 0; i < pages.length; i++) {
38544
- if (pageIsCurrent(pages[i])) {
38751
+ const isCurrent = pageIsCurrent(pages[i]);
38752
+ if (isCurrent && currentIndex === -1) {
38545
38753
  currentIndex = i;
38546
38754
  }
38547
38755
  }
@@ -52361,7 +52569,7 @@ const PickerContentInsidePopup = props => {
52361
52569
  // above: those exist because "expand" already means something on the picker
52362
52570
  // itself, and this one does not. Popover ignores it, same as Dialog ignores
52363
52571
  // marginWithAnchor.
52364
- dockedOnTouch,
52572
+ dockedOnSmallTouchScreen,
52365
52573
  animation,
52366
52574
  ...rest
52367
52575
  } = props;
@@ -52409,7 +52617,7 @@ const PickerContentInsidePopup = props => {
52409
52617
  expand: isPopover ? undefined : dialogExpand,
52410
52618
  expandX: isPopover ? undefined : dialogExpandX,
52411
52619
  expandY: isPopover ? undefined : dialogExpandY,
52412
- dockedOnTouch: isPopover ? undefined : dockedOnTouch,
52620
+ dockedOnSmallTouchScreen: isPopover ? undefined : dockedOnSmallTouchScreen,
52413
52621
  children: jsx(PopupModeContext.Provider, {
52414
52622
  value: mode,
52415
52623
  children: children
@@ -54087,7 +54295,7 @@ const css$v = /* css */`
54087
54295
 
54088
54296
  /* Same reasoning, for the corners: a dialog squares off whatever corner
54089
54297
  lands on its container's own (see the data-flush-* rules in dialog.jsx —
54090
- a bottom sheet from dockedOnTouch squares its two bottom ones). A list
54298
+ a bottom sheet from dockedOnSmallTouchScreen squares its two bottom ones). A list
54091
54299
  drawn right against that corner has to square the same one, otherwise its
54092
54300
  own radius carves a notch out of the popup's square corner. Direct child
54093
54301
  only: any deeper and the list is presumably inset from the popup's edge,
@@ -59154,14 +59362,25 @@ installImportMetaCssBuild(import.meta);const css$r = /* css */`
59154
59362
  --x-picker-border-color: var(--callout-color);
59155
59363
  }
59156
59364
 
59365
+ /* A variant states what the caller did NOT: it moves the DEFAULTS
59366
+ (--picker-*) and never the resolved values (--x-picker-*), so a
59367
+ backgroundColor/borderColor/padding prop — which lands inline on this
59368
+ same element — still wins. The per-state defaults are re-pointed at the
59369
+ base one too, otherwise the @layer formulas (hover = 5% black over the
59370
+ background, disabled = 5% grey) would repaint a box the variant just
59371
+ took away. */
59157
59372
  &[data-variant="icon"] {
59158
- --x-picker-padding-top: 0;
59159
- --x-picker-padding-right: 0;
59160
- --x-picker-padding-bottom: 0;
59161
- --x-picker-padding-left: 0;
59373
+ --picker-padding-x-default: 0;
59374
+ --picker-padding-y-default: 0;
59162
59375
  --picker-border-width: 0px; /* must carry a unit (px) — used in calc() to offset the custom input overlay */
59163
- --x-picker-border-color: transparent;
59164
- --x-picker-background-color: transparent;
59376
+ --picker-border-color: transparent;
59377
+ --picker-border-color-hover: var(--picker-border-color);
59378
+ --picker-border-color-readonly: var(--picker-border-color);
59379
+ --picker-border-color-disabled: var(--picker-border-color);
59380
+ --picker-background-color: transparent;
59381
+ --picker-background-color-hover: var(--picker-background-color);
59382
+ --picker-background-color-readonly: var(--picker-background-color);
59383
+ --picker-background-color-disabled: var(--picker-background-color);
59165
59384
  --x-picker-icon-color: currentColor;
59166
59385
  }
59167
59386
  /* discrete: no box at rest, a background on hover — the same word Button
@@ -59169,31 +59388,35 @@ installImportMetaCssBuild(import.meta);const css$r = /* css */`
59169
59388
  around it; the chevron in the right slot is what still says it opens. */
59170
59389
  &[data-variant="discrete"] {
59171
59390
  --picker-border-width: 0px; /* must carry a unit (px) — used in calc() to offset the custom input overlay */
59172
- --x-picker-border-color: transparent;
59173
- --x-picker-background-color: transparent;
59174
-
59175
- &[data-hover] {
59176
- --x-picker-border-color: transparent;
59177
- --x-picker-background-color: color-mix(
59178
- in srgb,
59179
- currentColor 8%,
59180
- transparent
59181
- );
59182
- }
59183
- &[data-readonly],
59184
- &[data-disabled] {
59185
- --x-picker-border-color: transparent;
59186
- --x-picker-background-color: transparent;
59187
- }
59391
+ --picker-border-color: transparent;
59392
+ --picker-border-color-hover: var(--picker-border-color);
59393
+ --picker-border-color-readonly: var(--picker-border-color);
59394
+ --picker-border-color-disabled: var(--picker-border-color);
59395
+ --picker-background-color: transparent;
59396
+ /* The hover wash is mixed INTO the background instead of replacing it:
59397
+ over the transparent default it is exactly the 8% of currentColor it
59398
+ has always been, and over a backgroundColor the caller gave it darkens
59399
+ that color rather than erasing it. */
59400
+ --picker-background-color-hover: color-mix(
59401
+ in srgb,
59402
+ currentColor 8%,
59403
+ var(--picker-background-color)
59404
+ );
59405
+ --picker-background-color-readonly: var(--picker-background-color);
59406
+ --picker-background-color-disabled: var(--picker-background-color);
59188
59407
  }
59189
59408
  &[data-variant="headless"] {
59190
- --x-picker-padding-top: 0;
59191
- --x-picker-padding-right: 0;
59192
- --x-picker-padding-bottom: 0;
59193
- --x-picker-padding-left: 0;
59409
+ --picker-padding-x-default: 0;
59410
+ --picker-padding-y-default: 0;
59194
59411
  --picker-border-width: 0px; /* must carry a unit (px) — used in calc() to offset the custom input overlay */
59195
- --x-picker-border-color: transparent;
59196
- --x-picker-background-color: transparent;
59412
+ --picker-border-color: transparent;
59413
+ --picker-border-color-hover: var(--picker-border-color);
59414
+ --picker-border-color-readonly: var(--picker-border-color);
59415
+ --picker-border-color-disabled: var(--picker-border-color);
59416
+ --picker-background-color: transparent;
59417
+ --picker-background-color-hover: var(--picker-background-color);
59418
+ --picker-background-color-readonly: var(--picker-background-color);
59419
+ --picker-background-color-disabled: var(--picker-background-color);
59197
59420
  --x-picker-icon-color: currentColor;
59198
59421
 
59199
59422
  .navi_picker_box {
@@ -71079,5 +71302,5 @@ const UserSvg = () => jsx("svg", {
71079
71302
  })
71080
71303
  });
71081
71304
 
71082
- export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, InputDuration, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, ListItems, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, NumberSpin, Paragraph, Picker, Popover, Popup, Quantity, RadioGroup, Route, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, SpinGroup, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRangeSpin, TimeSpin, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, coarsePointerSignal, compareTwoJsValues, createAction, createAvailableConstraint, createI18n, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineNaviConfirmPopupOptions, detectHorizontalOverflow, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isScrolling, isToday, languagesSignal, localStorageSignal, moveArrayItemByIndex, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, scrollActivitySignal, setBaseUrl, setPreferredLanguage, setSupportedLanguages, setUrlTargetOptions, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, triggerNaviCommand, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutRequestClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useInputGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, usePopupMode, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideValue, useStateArray, useTitleLevel, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
71305
+ export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, InputDuration, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, ListItems, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, NumberSpin, Paragraph, Picker, Popover, Popup, Quantity, RadioGroup, Route, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, SpinGroup, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRangeSpin, TimeSpin, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, compareTwoJsValues, createAction, createAvailableConstraint, createI18n, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineNaviConfirmPopupOptions, detectHorizontalOverflow, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isScrolling, isToday, languagesSignal, localStorageSignal, moveArrayItemByIndex, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, scrollActivitySignal, setBaseUrl, setPreferredLanguage, setSupportedLanguages, setUrlTargetOptions, setupRoutes, smallTouchScreenSignal, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, triggerNaviCommand, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutRequestClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useInputGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, usePopupMode, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideValue, useStateArray, useTitleLevel, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
71083
71306
  //# sourceMappingURL=jsenv_navi.js.map