@jsenv/navi 0.29.119 → 0.29.121

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.
@@ -4256,6 +4256,53 @@ const findControlProxy = (el) => {
4256
4256
  return firstProxy;
4257
4257
  };
4258
4258
 
4259
+ /**
4260
+ * Typography reset shared by the surfaces a control opens: callout, popover,
4261
+ * dialog.
4262
+ *
4263
+ * A surface is painted on top of the page but lives in the DOM subtree of the
4264
+ * element it opens from, so every inherited text property of that element
4265
+ * reaches it. The ink an element chose for its own background — centered,
4266
+ * shadowed, uppercase, letter-spaced, kept on one line — arrives on paper that
4267
+ * has none of that background, and the caller discovers it as a symptom
4268
+ * (a blurred tooltip, a centered message) with nothing on screen pointing back
4269
+ * to the rule three elements up. A surface writes its own text, on its own
4270
+ * paper, in the document's terms.
4271
+ *
4272
+ * Every one of them is set to its initial value rather than `revert`: only
4273
+ * `color` and `background-color` are declared by the UA on a `[popover]`/
4274
+ * `<dialog>`, so `revert` on any of these would roll back to the inherited
4275
+ * value — the very thing to stop. `text-align: initial` is `start`, which
4276
+ * still reads the surface's own `direction`, so an RTL document keeps its
4277
+ * side.
4278
+ *
4279
+ * `font-family` is deliberately absent: a surface keeps the face of what
4280
+ * opened it, so a section written in a display font gets its tooltips in that
4281
+ * font. `color`, `font-size` and `font-weight` are absent too — each surface
4282
+ * answers those its own way (a popup writes in --navi-popup-color and follows
4283
+ * the size of what opened it; a callout reverts to the document's ink and
4284
+ * size).
4285
+ *
4286
+ * In `@layer navi` so an app that wants one of these back says so on the
4287
+ * surface and wins, without having to out-specify anything.
4288
+ */
4289
+ const surfaceTextCss = /* css */ `
4290
+ @layer navi {
4291
+ .navi_callout,
4292
+ .navi_popover,
4293
+ .navi_dialog {
4294
+ font-style: initial;
4295
+ text-align: initial;
4296
+ text-indent: initial;
4297
+ text-transform: initial;
4298
+ text-shadow: none;
4299
+ white-space: initial;
4300
+ word-spacing: initial;
4301
+ letter-spacing: initial;
4302
+ }
4303
+ }
4304
+ `;
4305
+
4259
4306
  const CalloutContext = createContext();
4260
4307
  const useCalloutRequestClose = () => {
4261
4308
  return useContext(CalloutContext)?.requestClose;
@@ -4601,7 +4648,6 @@ const css$11 = /* css */`
4601
4648
  box-sizing: border-box;
4602
4649
  box-decoration-break: clone;
4603
4650
  align-self: center;
4604
- white-space: normal; /* Override in case ancetor sets nowrap */
4605
4651
  word-break: break-word;
4606
4652
  overflow-wrap: anywhere;
4607
4653
 
@@ -4670,6 +4716,8 @@ const css$11 = /* css */`
4670
4716
  }
4671
4717
  }
4672
4718
  }
4719
+
4720
+ ${surfaceTextCss}
4673
4721
  `;
4674
4722
 
4675
4723
  /**
@@ -38845,7 +38893,6 @@ installImportMetaCssBuild(import.meta);const css$W = /* css */`
38845
38893
  --link-text-decoration: underline;
38846
38894
  --link-text-decoration-hover: var(--link-text-decoration);
38847
38895
  --link-cursor: pointer;
38848
- --link-loading-outline-size: 1px;
38849
38896
  --link-outline-width: 2px;
38850
38897
 
38851
38898
  --link-current-indicator-size: 2px;
@@ -38904,12 +38951,7 @@ installImportMetaCssBuild(import.meta);const css$W = /* css */`
38904
38951
  aspect-ratio: inherit;
38905
38952
  padding-top: var(--x-link-padding-top);
38906
38953
  padding-right: var(--x-link-padding-right);
38907
- /* The loading underline is drawn inside the box: its own room is kept at
38908
- the bottom on top of whatever padding was asked for, so a link that
38909
- starts loading never reflows. */
38910
- padding-bottom: calc(
38911
- var(--x-link-padding-bottom) + var(--link-loading-outline-size)
38912
- );
38954
+ padding-bottom: var(--x-link-padding-bottom);
38913
38955
  padding-left: var(--x-link-padding-left);
38914
38956
  color: var(--x-link-color);
38915
38957
  text-decoration: var(--x-link-text-decoration);
@@ -39608,6 +39650,155 @@ const LinkCurrentIndicator = () => {
39608
39650
  };
39609
39651
  markAsOutsideTextFlow(LinkCurrentIndicator);
39610
39652
 
39653
+ /**
39654
+ * What a SlideContainer is doing, read from outside it.
39655
+ *
39656
+ * Only slides go in the box, so everything drawn AROUND the travel is written
39657
+ * around it — a chevron pinned to the edge of a full-screen viewer, a "3 / 8"
39658
+ * counter, a bar. Those need to know things the box alone knows: where one is,
39659
+ * and whether there is anywhere to go that way. A container driven by nobody
39660
+ * (no `current`, no `signal`) knows them and no one else does, so this is also
39661
+ * what keeps such a container usable without lifting its state out of it.
39662
+ *
39663
+ * Two channels, and they answer two different questions. The attributes the box
39664
+ * paints on itself are the STATE: they are there for whoever arrives later, and
39665
+ * CSS draws with them without any of this ([data-slide-ways~="right"]). The
39666
+ * event it dispatches is the NEWS: it says WHEN something changed, which no
39667
+ * attribute can say. So this reads the first and listens to the second.
39668
+ *
39669
+ * Not watching the DOM for it, which is the tempting third way and the wrong
39670
+ * one: a write is not a change. Under a finger the box writes where the picture
39671
+ * leans on every frame, with the same value in it more often than not, and a
39672
+ * watcher is woken for every one of them — while the box itself knows perfectly
39673
+ * well whether anything is different, and says so once.
39674
+ *
39675
+ * Nothing is told to the box in return, and nothing has to be wired: it
39676
+ * announces to itself and to its followers, so the thing doing the reading sits
39677
+ * anywhere on the page — in a fixed bar, in the frame around the box, in a
39678
+ * dialog holding it — and a container which never re-renders (a travel it drove
39679
+ * itself) is still followed.
39680
+ *
39681
+ * Reading only. Asking for a travel is what it always was: a command aimed at
39682
+ * the box (`commandFor={id}` + `--navi-right`, or triggerNaviCommand) — one way
39683
+ * of asking, wherever the asking is written.
39684
+ */
39685
+
39686
+
39687
+ // The vocabulary the box publishes, in one place: written by slide_container,
39688
+ // read here and by anything styling in CSS alone
39689
+ // ([data-slide-ways~="right"]).
39690
+ const SLIDE_CURRENT_ATTRIBUTE = "data-slide-current";
39691
+ const SLIDE_TOWARD_ATTRIBUTE = "data-slide-travel-toward";
39692
+ // Where a travel WOULD go right now: there is a slide that way and the one on
39693
+ // screen lets go of it.
39694
+ const SLIDE_WAYS_ATTRIBUTE = "data-slide-ways";
39695
+ // …and where there is a slide that way but the one on screen holds on to the
39696
+ // user (preventNav, or a `required` step still unanswered). Two facts, not one:
39697
+ // a way out leading nowhere is not there, while a way out being held is there
39698
+ // and says no — which is why it stays visible and explainable rather than
39699
+ // hidden.
39700
+ const SLIDE_HELD_ATTRIBUTE = "data-slide-held";
39701
+ // …and the one word said out loud, on the box and on every follower of it, when
39702
+ // any of the above has actually changed. It carries the whole state as its
39703
+ // detail, so `onnavi_slide_state` on the box is a way of hearing it too.
39704
+ const SLIDE_STATE_EVENT = "navi_slide_state";
39705
+
39706
+ const NO_WAYS = [];
39707
+ const NOTHING = {
39708
+ current: undefined,
39709
+ toward: undefined,
39710
+ areas: NO_WAYS,
39711
+ ways: NO_WAYS,
39712
+ held: NO_WAYS,
39713
+ };
39714
+
39715
+ const wordsOf = (element, attribute) => {
39716
+ const value = element.getAttribute(attribute);
39717
+ return value ? value.split(" ") : NO_WAYS;
39718
+ };
39719
+
39720
+ const readSlideContainerState = (element) => ({
39721
+ current: element.getAttribute(SLIDE_CURRENT_ATTRIBUTE) ?? undefined,
39722
+ toward: element.getAttribute(SLIDE_TOWARD_ATTRIBUTE) ?? undefined,
39723
+ // In DOM order, which is the order of the walk for a line and the order the
39724
+ // areas were written in for a map — the same order everything else reads
39725
+ // (see readMap).
39726
+ areas: Array.from(
39727
+ element.querySelectorAll(":scope > [data-slide-track] > [data-slide]"),
39728
+ (slideElement) =>
39729
+ slideElement.getAttribute("data-slide-area") || slideElement.id || "",
39730
+ ),
39731
+ ways: wordsOf(element, SLIDE_WAYS_ATTRIBUTE),
39732
+ held: wordsOf(element, SLIDE_HELD_ATTRIBUTE),
39733
+ });
39734
+
39735
+ const sameSlideContainerState = (a, b) =>
39736
+ a.current === b.current &&
39737
+ a.toward === b.toward &&
39738
+ a.areas.join(" ") === b.areas.join(" ") &&
39739
+ a.ways.join(" ") === b.ways.join(" ") &&
39740
+ a.held.join(" ") === b.held.join(" ");
39741
+
39742
+ /**
39743
+ * @param {string|Element|{current: Element}} [target] - the container: its id
39744
+ * (the way everything else addresses one), the element, or a ref to it. Not a
39745
+ * follower — a follower is painted for CSS to draw with, the box is what holds
39746
+ * the walk. Nothing at all is allowed and answers "no container": a component
39747
+ * that may or may not be wired to one calls this unconditionally, like every
39748
+ * hook.
39749
+ * @returns {{
39750
+ * current: string|undefined,
39751
+ * toward: string|undefined,
39752
+ * areas: string[],
39753
+ * can: (direction: "left"|"right"|"up"|"down") => boolean,
39754
+ * held: (direction: "left"|"right"|"up"|"down") => boolean,
39755
+ * }} where the box stands. `current` is the slide on screen — the one being
39756
+ * travelled TO while a travel plays, because that is what one is looking at;
39757
+ * `toward` is the other slide in the frame while the picture is between two,
39758
+ * and nothing at rest. `can` is "a travel that way would happen", `held` is
39759
+ * "there is a slide that way and this one says no" — a chevron is dead in
39760
+ * both cases and only the second is worth explaining.
39761
+ */
39762
+ const useSlideContainer = (target) => {
39763
+ const [state, setState] = useState(NOTHING);
39764
+
39765
+ useLayoutEffect(() => {
39766
+ const element =
39767
+ typeof target === "string"
39768
+ ? document.getElementById(target)
39769
+ : target && "current" in target
39770
+ ? target.current
39771
+ : target;
39772
+ if (!element) {
39773
+ setState(NOTHING);
39774
+ return undefined;
39775
+ }
39776
+ // Read off the DOM rather than taken from the event's detail, even though
39777
+ // the two say the same thing: the first read has no event to take it from
39778
+ // (the box was already standing somewhere when this mounted), and one way
39779
+ // of reading is one thing that can be wrong.
39780
+ const read = () => {
39781
+ const nextState = readSlideContainerState(element);
39782
+ setState((previous) =>
39783
+ sameSlideContainerState(previous, nextState) ? previous : nextState,
39784
+ );
39785
+ };
39786
+ read();
39787
+ element.addEventListener(SLIDE_STATE_EVENT, read);
39788
+ return () => {
39789
+ element.removeEventListener(SLIDE_STATE_EVENT, read);
39790
+ };
39791
+ }, [target]);
39792
+
39793
+ return {
39794
+ current: state.current,
39795
+ toward: state.toward,
39796
+ areas: state.areas,
39797
+ can: (direction) => state.ways.includes(direction),
39798
+ held: (direction) => state.held.includes(direction),
39799
+ };
39800
+ };
39801
+
39611
39802
  installImportMetaCssBuild(import.meta);/**
39612
39803
  * TabList component with support for horizontal and vertical layouts
39613
39804
  * https://dribbble.com/search/tabs
@@ -40006,19 +40197,17 @@ const Nav = ({
40006
40197
  }
40007
40198
  slideContainerElementRef.current = containerElement;
40008
40199
  const readContainer = () => {
40009
- setCurrentSlideArea(containerElement.getAttribute("data-slide-current") ?? undefined);
40200
+ setCurrentSlideArea(containerElement.getAttribute(SLIDE_CURRENT_ATTRIBUTE) ?? undefined);
40010
40201
  paintIndicatorGeometryRef.current();
40011
40202
  };
40012
40203
  readContainer();
40013
- // The container says where one is and what the picture leans on, and says
40014
- // it in the DOM: nothing here is told, everything is read which is what
40015
- // lets this row sit anywhere on the page (above the box, in a fixed bar)
40016
- // rather than inside it.
40017
- const attributeObserver = new MutationObserver(readContainer);
40018
- attributeObserver.observe(containerElement, {
40019
- attributes: true,
40020
- attributeFilter: ["data-slide-current", "data-slide-travel-toward"]
40021
- });
40204
+ // Where one is and what the picture leans on are written on the container,
40205
+ // and the container says out loud when either has changed: this row is not
40206
+ // in the box (it sits above it, in a fixed bar, anywhere), so it reads the
40207
+ // first and listens to the second. Listening rather than watching the DOM
40208
+ // because a write is not a change — the attribute the trait follows is
40209
+ // written on every frame of a gesture with the same value in it.
40210
+ containerElement.addEventListener(SLIDE_STATE_EVENT, readContainer);
40022
40211
  // A row whose tabs changed width — a badge count, a font that just
40023
40212
  // arrived, a window resized — is measured again: what was written is
40024
40213
  // pixels, and pixels go stale.
@@ -40027,7 +40216,7 @@ const Nav = ({
40027
40216
  });
40028
40217
  sizeObserver.observe(navRef.current);
40029
40218
  return () => {
40030
- attributeObserver.disconnect();
40219
+ containerElement.removeEventListener(SLIDE_STATE_EVENT, readContainer);
40031
40220
  sizeObserver.disconnect();
40032
40221
  slideContainerElementRef.current = null;
40033
40222
  };
@@ -49856,7 +50045,7 @@ const readArea = slideElement => slideElement.getAttribute("data-slide-area") ||
49856
50045
  * it says where one starts, not where one is — say `current` for that.
49857
50046
  * Without it the first slide is the one shown, the way a stack of pages opens
49858
50047
  * on its first page.
49859
- * @param {(area: string, detail: {cause: "drag"|"keyboard"|"command"|"code", event: Event}) => void|false|Promise<void|false>} [props.onCurrentChange]
50048
+ * @param {(area: string, detail: {cause: "drag"|"keyboard"|"command"|"code"|"url", event: Event}) => void|false|Promise<void|false>} [props.onCurrentChange]
49860
50049
  * - the slide being shown has changed. `cause` says what asked for it, which
49861
50050
  * is what tells a place browsed past from a place aimed at: a caller writing
49862
50051
  * this into the URL pushes a history entry for a tab that was pressed and
@@ -49866,6 +50055,8 @@ const readArea = slideElement => slideElement.getAttribute("data-slide-area") ||
49866
50055
  * from — a guard that says no, a session that is gone. A promise refuses it
49867
50056
  * late, once whatever it had to ask has answered; the travel plays meanwhile
49868
50057
  * and is undone if the answer is no.
50058
+ * `cause: "url"` is the address asking (see `urlParam`) — a load on a link, a
50059
+ * traversal — rather than anything done inside the box.
49869
50060
  * @param {"now"|"rest"} [props.commit="now"] - when the change is told.
49870
50061
  * "rest" waits for the travel to be over, and lets the container hold the
49871
50062
  * slide it is going to meanwhile: the picture moves with the finger and the
@@ -49883,6 +50074,33 @@ const readArea = slideElement => slideElement.getAttribute("data-slide-area") ||
49883
50074
  * one that just travelled there. Called once the travel is over, and in the
49884
50075
  * same render as the return to rest — anything later shows the old content
49885
50076
  * for a frame.
50077
+ * @param {string|{name: string, history?: "replace"|"push"}} [props.urlParam]
50078
+ * - the search param this container owns, and where it stands is written
50079
+ * into: `urlParam="step"` puts `?step=<area>` in the address on every travel,
50080
+ * and opens on the area it names on a load, a bookmark, a traversal, a link
50081
+ * from anywhere else in the application.
50082
+ * It is the answer to "the step should be readable and should survive a
50083
+ * reload" WITHOUT one route per slide: no route to declare, no route guard to
50084
+ * re-express the walk's own rules in, and no page transition — what travels
50085
+ * is the box, and the address is a label on where the box stands. Say it on a
50086
+ * container whose slides are places one may be sent to; a walk nobody links
50087
+ * into keeps its position to itself.
50088
+ * Written by REPLACEMENT: four steps that each stacked an entry would turn
50089
+ * one back-press into four, and the back arrow of a page means "leave this
50090
+ * page", not "one question back". `history: "push"` says the opposite for the
50091
+ * containers that mean it — slides that ARE places one came from, a gallery
50092
+ * one browses — and even there a slide reached by dragging replaces, so
50093
+ * swiping back and forth does not bury the way out.
50094
+ * The address is READ through the walk, not jumped to: it comes from outside
50095
+ * the box, so every slide between here and there is asked to let go the way a
50096
+ * key going that way would ask it, and the first one that holds
50097
+ * (`preventNav`, or a `required` step still unanswered) is where one stops —
50098
+ * `?step=done` cannot open a confirmation screen for something nobody sent.
50099
+ * Whatever comes of it, the address is then rewritten with the area actually
50100
+ * shown: it says where one IS, never where one asked to be. A step the app
50101
+ * knows is already answered on a reload is told so by its own `required`
50102
+ * (`required={!alreadyFilled}`) — the container remembers nothing across a
50103
+ * load, and cannot.
49886
50104
  * Each way of travelling can be shut off, or narrowed to one axis: `true`
49887
50105
  * (every axis the map has), `false`, `"x"`, `"y"`, `"xy"`.
49888
50106
  *
@@ -49893,6 +50111,13 @@ const readArea = slideElement => slideElement.getAttribute("data-slide-area") ||
49893
50111
  * screens are steps rather than places — so the keys keep the meaning the
49894
50112
  * content gives them, and travelling stays something one asks for (a button,
49895
50113
  * a command).
50114
+ * WHERE they are heard is a separate question, and it is not answered here: a
50115
+ * key only ever reaches what has the focus, so this box hears the ones pressed
50116
+ * inside it — and every follower of it hears the rest. A chevron pinned to the
50117
+ * edge of a full-screen surface is outside the box by necessity (only slides
50118
+ * go in it), so the surface says `data-slide-container-follows={id}` and the
50119
+ * arrows keep walking wherever the keyboard is in it. See the paragraph above
50120
+ * about what is drawn AROUND the travel.
49896
50121
  * @param {boolean|"x"|"y"|"xy"} [props.travelByDrag=true] - whether a pointer
49897
50122
  * dragging the slides travels. On by default: slides side by side are
49898
50123
  * something one expects to push around with a thumb. Off where the gesture
@@ -49928,6 +50153,7 @@ const SlideContainer = ({
49928
50153
  commit = "now",
49929
50154
  loop,
49930
50155
  onLoop,
50156
+ urlParam,
49931
50157
  travelByKeyboard = true,
49932
50158
  travelByDrag = true,
49933
50159
  travelByScroll = "x",
@@ -50023,6 +50249,51 @@ const SlideContainer = ({
50023
50249
  const followerElementsRef = useRef([]);
50024
50250
  const currentFromCaller = currentSignal ? currentSignal.value : currentProp;
50025
50251
  const current = rollingArea ?? provisionalArea ?? currentFromCaller ?? currentAreaState;
50252
+ // The search param this container owns, when it owns one: the name it is
50253
+ // written under, and whether going somewhere is somewhere one CAME from.
50254
+ const urlParamName = typeof urlParam === "string" ? urlParam : urlParam?.name;
50255
+ const urlParamHistory = urlParam?.history || "replace";
50256
+ // What the address says right now. Read from the signal rather than from
50257
+ // window.location so that a traversal — the browser's own back and forward —
50258
+ // is a render like any other: the address moved, and the slides follow it.
50259
+ // Read only when there is a param to read, so a container that owns none is
50260
+ // not re-rendered by every navigation in the application.
50261
+ const areaInUrl = urlParamName ? new URL(documentUrlSignal.value).searchParams.get(urlParamName) : null;
50262
+ // The last thing this container knows the address said, whether it wrote it
50263
+ // or read it. What makes a two-way binding stop turning: the address is only
50264
+ // an INSTRUCTION when it changed by itself (a load, a traversal, a link), and
50265
+ // what this container put there is not news. Without it, a container ahead of
50266
+ // its own URL (commit="rest", where the picture arrives before the address is
50267
+ // written) would read its own lateness as an order to go back.
50268
+ const areaInUrlSeenRef = useRef(undefined);
50269
+ // Where the container stands, said in the address. `replace` amends the entry
50270
+ // one is on: a walk of four steps must not turn one back-press into four, and
50271
+ // the back arrow of a page keeps meaning "leave this page". `push` is for
50272
+ // slides that ARE places one came from — and even there a slide reached by
50273
+ // DRAGGING replaces, because browsing back and forth with a thumb is not a
50274
+ // trail one wants to walk home along.
50275
+ const writeUrlParam = (area, cause, {
50276
+ replace = false
50277
+ } = {}) => {
50278
+ if (!urlParamName) {
50279
+ return;
50280
+ }
50281
+ areaInUrlSeenRef.current = area;
50282
+ const urlObject = new URL(window.location.href);
50283
+ if (urlObject.searchParams.get(urlParamName) === area) {
50284
+ return;
50285
+ }
50286
+ urlObject.searchParams.set(urlParamName, area);
50287
+ navTo(urlObject.href, {
50288
+ replace: replace || urlParamHistory !== "push" || cause === "drag" ||
50289
+ // The address already says it: reading it back is not a place one went.
50290
+ cause === "url",
50291
+ // What travels is the box, not the page: the address is a label on where
50292
+ // the box stands, and a route transition would move the whole document
50293
+ // for a slide that has already travelled by itself.
50294
+ routeTransition: "none"
50295
+ });
50296
+ };
50026
50297
  const vertical = layout === "column";
50027
50298
  // What the map has, and what each way of asking is allowed to use of it.
50028
50299
  const mapAxes = travelAxesOf(layout);
@@ -50167,7 +50438,7 @@ const SlideContainer = ({
50167
50438
  // there is nothing else for it to read — a slide the container holds by
50168
50439
  // itself is known to no one else.
50169
50440
  const paintCurrentArea = area => {
50170
- containerRef.current?.setAttribute("data-slide-current", area);
50441
+ containerRef.current?.setAttribute(SLIDE_CURRENT_ATTRIBUTE, area);
50171
50442
  };
50172
50443
  const markAnswered = area => {
50173
50444
  const order = readMap().slideElements.map(readArea);
@@ -50490,6 +50761,14 @@ const SlideContainer = ({
50490
50761
  if (!stageRef.current) {
50491
50762
  drawnAreaRef.current = currentArea;
50492
50763
  }
50764
+ // Said last, and after data-current has been written: what a travel would do
50765
+ // is read off the map from the slide that is now current, and off the locks
50766
+ // that slide is wearing in this very commit.
50767
+ paintWays(currentElement);
50768
+ // …and once everything this commit had to write is written, the box says so
50769
+ // — a single announcement for a render that may have changed several of the
50770
+ // facts at once.
50771
+ announceState();
50493
50772
  // The finger has the last word: everything above drew the map at rest, and
50494
50773
  // where the track actually is right now is where the gesture put it.
50495
50774
  paintDrag();
@@ -50625,7 +50904,7 @@ const SlideContainer = ({
50625
50904
  }
50626
50905
  const leftArea = readArea(currentElement);
50627
50906
  setCurrentAreaState(area);
50628
- if (!onCurrentChange && !currentSignal) {
50907
+ if (!onCurrentChange && !currentSignal && !urlParamName) {
50629
50908
  return true;
50630
50909
  }
50631
50910
  // What asked for this, read off the interaction rather than carried down
@@ -50660,6 +50939,12 @@ const SlideContainer = ({
50660
50939
  // `onCurrentChange` is called, in that order, so a caller reading the signal
50661
50940
  // from inside its own handler reads where it now is.
50662
50941
  const tellCurrentChange = (area, detail, leftArea) => {
50942
+ // The address first, because it is the one thing that must never disagree
50943
+ // with the picture — and it is told here rather than by the caller so that
50944
+ // it is told about the travels that HAPPENED and about no others: the ones
50945
+ // a lock refused never reach this point, and one refused late is written
50946
+ // back below (see goBackToRefusedArea).
50947
+ writeUrlParam(area, detail.cause);
50663
50948
  if (currentSignal) {
50664
50949
  currentSignal.value = area;
50665
50950
  }
@@ -50693,8 +50978,62 @@ const SlideContainer = ({
50693
50978
  if (currentSignal) {
50694
50979
  currentSignal.value = leftArea;
50695
50980
  }
50981
+ // Written over rather than stacked on, whatever this container does with
50982
+ // the history otherwise: the entry the refused travel wrote is the one
50983
+ // being corrected, and a refusal is not a place one was.
50984
+ writeUrlParam(leftArea, "code", {
50985
+ replace: true
50986
+ });
50696
50987
  };
50697
50988
 
50989
+ // The address asks for a slide. Read on every render it changes on rather
50990
+ // than at mount alone, because the browser's own arrows are exactly that —
50991
+ // the address moving by itself — and a link from elsewhere in the application
50992
+ // is too. What follows is a travel like any other: the slides move, the
50993
+ // caller is told, and the address ends up saying where the box actually
50994
+ // stands.
50995
+ useLayoutEffect(() => {
50996
+ if (!urlParamName) {
50997
+ return;
50998
+ }
50999
+ if (areaInUrl === areaInUrlSeenRef.current) {
51000
+ // Not news: either nothing moved, or this container is reading back what
51001
+ // it wrote itself.
51002
+ return;
51003
+ }
51004
+ areaInUrlSeenRef.current = areaInUrl;
51005
+ if (areaInUrl === null) {
51006
+ // An address that says nothing is not an address saying "the first
51007
+ // slide": a container opened without the param opens where it would have
51008
+ // opened anyway, and the param appears the first time one travels.
51009
+ return;
51010
+ }
51011
+ // Where the box IS, read off the DOM: `current` is undefined until someone
51012
+ // names a slide, and the container standing on its first one is a fact only
51013
+ // the map knows (see the layout effect that paints it).
51014
+ const areaOnScreen = containerRef.current?.getAttribute("data-slide-current");
51015
+ if (!areaOnScreen || areaInUrl === areaOnScreen) {
51016
+ return;
51017
+ }
51018
+ const reached = reachableTowards(areaOnScreen, areaInUrl);
51019
+ if (reached && reached !== areaOnScreen) {
51020
+ // Told rather than asked: the walk above has already put every lock on
51021
+ // the way the question goToArea would have put the first one, and this
51022
+ // travel has no interaction behind it to hand a focus to — the slide
51023
+ // arriving is handed the keyboard by the layout effect, the way it is for
51024
+ // any travel nobody pressed anything for.
51025
+ setCurrentAreaState(reached);
51026
+ tellCurrentChange(reached, {
51027
+ cause: "url"
51028
+ }, areaOnScreen);
51029
+ return;
51030
+ }
51031
+ // The param names nowhere this map knows, or somewhere the walk is not
51032
+ // allowed to reach: the address is put back on the slide one is actually
51033
+ // looking at, rather than left saying one is somewhere one is not.
51034
+ writeUrlParam(areaOnScreen, "url");
51035
+ }, [urlParamName, areaInUrl]);
51036
+
50698
51037
  // The press kept during a roll, taken once the window rests and the travel is
50699
51038
  // given back (noTravel off): by direction when there was one, so it is read
50700
51039
  // against the map as it is NOW — the content moved one step under the window
@@ -50788,20 +51127,25 @@ const SlideContainer = ({
50788
51127
  };
50789
51128
 
50790
51129
  /**
51130
+ * @param {number} dx
51131
+ * @param {number} dy
51132
+ * @param {string} [fromArea] - where to step from. The slide on screen when
51133
+ * nothing says otherwise; named only by a walk that is not standing there
51134
+ * (see reachableTowards).
50791
51135
  * @returns {string|undefined} the area one step that way, if there is one.
50792
51136
  * Nothing there means the direction is simply not offered — no wrapping, no
50793
51137
  * nearest-match: a map is read as a map, and a move landing nowhere would
50794
51138
  * break that reading. Walks over its own cells first, so a spanning area
50795
51139
  * leaves by its far edge rather than onto itself.
50796
51140
  */
50797
- const areaTowards = (dx, dy) => {
51141
+ const areaTowards = (dx, dy, fromArea) => {
50798
51142
  const {
50799
51143
  slideElements,
50800
51144
  areaAt,
50801
51145
  placeOf
50802
51146
  } = readMap();
50803
51147
  const currentElement = slideElements.find(slideElement => slideElement.hasAttribute("data-current")) || slideElements[0];
50804
- const currentArea = readArea(currentElement);
51148
+ const currentArea = fromArea ?? readArea(currentElement);
50805
51149
  let {
50806
51150
  x,
50807
51151
  y
@@ -50860,6 +51204,64 @@ const SlideContainer = ({
50860
51204
  const moveNext = (event, options) => vertical ? move(0, 1, event, options) || move(1, 0, event, options) : move(1, 0, event, options) || move(0, 1, event, options);
50861
51205
  const movePrevious = (event, options) => vertical ? move(0, -1, event, options) || move(-1, 0, event, options) : move(-1, 0, event, options) || move(0, -1, event, options);
50862
51206
 
51207
+ /**
51208
+ * How far the map lets one get towards an area, walking from where the
51209
+ * container stands.
51210
+ *
51211
+ * What the ADDRESS asks for goes through here rather than straight to
51212
+ * goToArea: a URL comes from OUTSIDE the walk — typed, shared, kept from a
51213
+ * session that has moved on — so every slide on the way is asked to let go,
51214
+ * exactly as a hand or a key going that way would ask it, and the first one
51215
+ * that holds is where one stops. Jumped to instead, an address would open the
51216
+ * one screen the walk itself cannot reach: the confirmation of something
51217
+ * nobody sent. Stopping short is not a failure either — a wizard reopens as
51218
+ * far along as it is allowed to, which is where the reader left off.
51219
+ *
51220
+ * @returns {string|undefined} the area one ends up on, undefined for a name
51221
+ * this map does not know.
51222
+ */
51223
+ const reachableTowards = (fromArea, targetArea) => {
51224
+ const {
51225
+ slideElements,
51226
+ placeOf
51227
+ } = readMap();
51228
+ const target = placeOf.get(targetArea);
51229
+ if (!target || !placeOf.has(fromArea)) {
51230
+ return undefined;
51231
+ }
51232
+ if (loop) {
51233
+ // A window has no walls to walk into: its slides are one endless line,
51234
+ // and what they show is whoever owns the content to place.
51235
+ return targetArea;
51236
+ }
51237
+ const holds = (area, forward) => {
51238
+ const slideElement = slideElements.find(slideElement => readArea(slideElement) === area);
51239
+ return slideElement?.hasAttribute(forward ? "data-prevent-nav-next" : "data-prevent-nav-previous");
51240
+ };
51241
+ let area = fromArea;
51242
+ // A walk crosses each slide at most once — beyond that a map is reading
51243
+ // itself in circles.
51244
+ let stepsLeft = slideElements.length;
51245
+ while (area !== targetArea && stepsLeft--) {
51246
+ const place = placeOf.get(area);
51247
+ // Along the row first, then down: the order a map is read in.
51248
+ const dx = Math.sign(target.x - place.x);
51249
+ const dy = dx ? 0 : Math.sign(target.y - place.y);
51250
+ if (!dx && !dy) {
51251
+ break;
51252
+ }
51253
+ if (holds(area, dx > 0 || dy > 0)) {
51254
+ break;
51255
+ }
51256
+ const next = areaTowards(dx, dy, area);
51257
+ if (!next) {
51258
+ break;
51259
+ }
51260
+ area = next;
51261
+ }
51262
+ return area;
51263
+ };
51264
+
50863
51265
  // Where the track is right now, as the gesture left it: the resting place of
50864
51266
  // the slide being dragged, plus what the pointer has pulled since.
50865
51267
  const paintDrag = () => {
@@ -50894,10 +51296,93 @@ const SlideContainer = ({
50894
51296
  const paintTravelToward = area => {
50895
51297
  for (const element of travelPainters()) {
50896
51298
  if (area) {
50897
- element.setAttribute("data-slide-travel-toward", area);
51299
+ element.setAttribute(SLIDE_TOWARD_ATTRIBUTE, area);
51300
+ } else {
51301
+ element.removeAttribute(SLIDE_TOWARD_ATTRIBUTE);
51302
+ }
51303
+ }
51304
+ // The one fact that changes without a render behind it: under a finger this
51305
+ // is written per frame, so the announcement is left to say whether any of
51306
+ // those writes was a change.
51307
+ announceState();
51308
+ };
51309
+
51310
+ // What a travel would do right now, said in two lists because they are two
51311
+ // different facts: `ways` is where one WOULD go — there is a slide that way
51312
+ // and the one on screen lets go of it — and `held` is where there is a slide
51313
+ // that way and this one holds on to the user (preventNav, a `required` step
51314
+ // still unanswered). A way out leading nowhere is not there; a way out being
51315
+ // held is there and says no, which is why it stays visible and explainable.
51316
+ //
51317
+ // Painted rather than rendered, and on the followers too: only slides go in
51318
+ // this box, so the chevrons, the counters and the bars that go with it are
51319
+ // written AROUND it — in CSS off these attributes
51320
+ // ([data-slide-ways~="right"]), or through useSlideContainer, which watches
51321
+ // them. Nothing is told, everything is read: it is what lets them sit
51322
+ // anywhere, and what lets a container nobody drives still be followed.
51323
+ const paintWays = currentElement => {
51324
+ const ways = [];
51325
+ const held = [];
51326
+ for (const direction of Object.keys(DIRECTIONS)) {
51327
+ const {
51328
+ dx,
51329
+ dy
51330
+ } = DIRECTIONS[direction];
51331
+ if (!mapAxes?.includes(dx ? "x" : "y")) {
51332
+ // Not an axis this map has: a row has no up and no down, and saying so
51333
+ // would be saying it about every row on the page.
51334
+ continue;
51335
+ }
51336
+ if (!areaTowards(dx, dy)) {
51337
+ continue;
51338
+ }
51339
+ const forward = dx > 0 || dy > 0;
51340
+ const isHeld = currentElement?.hasAttribute(forward ? "data-prevent-nav-next" : "data-prevent-nav-previous");
51341
+ (isHeld ? held : ways).push(direction);
51342
+ }
51343
+ for (const element of travelPainters()) {
51344
+ if (ways.length) {
51345
+ element.setAttribute(SLIDE_WAYS_ATTRIBUTE, ways.join(" "));
50898
51346
  } else {
50899
- element.removeAttribute("data-slide-travel-toward");
51347
+ element.removeAttribute(SLIDE_WAYS_ATTRIBUTE);
50900
51348
  }
51349
+ if (held.length) {
51350
+ element.setAttribute(SLIDE_HELD_ATTRIBUTE, held.join(" "));
51351
+ } else {
51352
+ element.removeAttribute(SLIDE_HELD_ATTRIBUTE);
51353
+ }
51354
+ }
51355
+ };
51356
+
51357
+ // The news, as opposed to the state. Everything painted above IS the state:
51358
+ // it is what anything arriving later reads, and what CSS draws with. What an
51359
+ // attribute cannot say is WHEN it changed — and watching it is the wrong way
51360
+ // to ask, because a write is not a change: `data-slide-travel-toward` is
51361
+ // written on every frame of a gesture with the same value in it, and every
51362
+ // watcher would be woken sixty times a second for nothing. So the box says it
51363
+ // itself, once, and only when something is actually different.
51364
+ //
51365
+ // Said to its followers as well as to itself, exactly as the painting is: a
51366
+ // frame drawn around the box hears what the box is doing without knowing its
51367
+ // id, and a row of tabs beside it listens on the box by id. Not bubbling, like
51368
+ // every other navi event — what is announced is about THIS box, and a box
51369
+ // inside another must not be heard as the one around it.
51370
+ const announcedRef = useRef(null);
51371
+ const announceState = () => {
51372
+ const containerEl = containerRef.current;
51373
+ if (!containerEl) {
51374
+ return;
51375
+ }
51376
+ const state = readSlideContainerState(containerEl);
51377
+ const announced = announcedRef.current;
51378
+ if (announced && sameSlideContainerState(announced, state)) {
51379
+ return;
51380
+ }
51381
+ announcedRef.current = state;
51382
+ for (const element of travelPainters()) {
51383
+ dispatchCustomEvent(element, SLIDE_STATE_EVENT, {
51384
+ ...state
51385
+ });
50901
51386
  }
50902
51387
  };
50903
51388
 
@@ -51113,8 +51598,8 @@ const SlideContainer = ({
51113
51598
  sign,
51114
51599
  target
51115
51600
  }) => {
51116
- const areaBack = axis === "x" ? areaTowards(-1, 0) : areaTowards(0, -1);
51117
- const areaOn = axis === "x" ? areaTowards(1, 0) : areaTowards(0, 1);
51601
+ let areaBack = axis === "x" ? areaTowards(-1, 0) : areaTowards(0, -1);
51602
+ let areaOn = axis === "x" ? areaTowards(1, 0) : areaTowards(0, 1);
51118
51603
  // Everything positional is read HERE rather than when the pointer
51119
51604
  // landed: the travel that was playing then may have arrived since, and
51120
51605
  // it is what the slides are doing at the moment the gesture takes them
@@ -51125,6 +51610,24 @@ const SlideContainer = ({
51125
51610
  placeOf
51126
51611
  } = readMap();
51127
51612
  const currentElement = slideElements.find(slideElement => slideElement.hasAttribute("data-current")) || slideElements[0];
51613
+ // The hold goToArea reads at the release, read again HERE, off the same
51614
+ // slide and the same attribute: a slide that will refuse the arrival
51615
+ // must not offer the journey. A locked direction simply has nowhere to
51616
+ // go for the length of this gesture — the one case the gesture already
51617
+ // knows, being the last slide of a walk. The hand then gets the wall it
51618
+ // can lean on and never walk through (see drag_to_travel), the slide
51619
+ // behind it stays offstage instead of being read on the way, and the
51620
+ // release has nothing left to refuse.
51621
+ // Nothing here about `released` (--navi-done): that is one particular
51622
+ // departure letting go, decided as it happens, and a gesture armed
51623
+ // before it has no such thing to read — the attribute as rendered is
51624
+ // what the hand is answered from.
51625
+ if (currentElement?.hasAttribute("data-prevent-nav-previous")) {
51626
+ areaBack = undefined;
51627
+ }
51628
+ if (currentElement?.hasAttribute("data-prevent-nav-next")) {
51629
+ areaOn = undefined;
51630
+ }
51128
51631
  const box = track.getBoundingClientRect();
51129
51632
  if (!areaBack && !areaOn || !currentElement || !box.width || !box.height ||
51130
51633
  // Something else with a better claim on the gesture: a scroller
@@ -51792,7 +52295,14 @@ const SlideMove = ({
51792
52295
  label
51793
52296
  } = DIRECTIONS[direction];
51794
52297
  const forward = dx > 0 || dy > 0;
51795
- const locked = forward ? locks?.preventNavNext : locks?.preventNavPrevious;
52298
+ // The same fact, read from wherever this way out is written. Inside a slide it
52299
+ // comes down as context — the slide holding the user is this button's
52300
+ // ancestor. Written AROUND the box (only slides go in it, so a chevron pinned
52301
+ // to the edge of a full-screen surface has to be), it is not, so it is read
52302
+ // off the box this button already names to ask for the travel: one prop, and
52303
+ // the way out behaves the same on either side of the box.
52304
+ const slides = useSlideContainer(rest.commandFor);
52305
+ const locked = (forward ? locks?.preventNavNext : locks?.preventNavPrevious) || slides.held(direction);
51796
52306
  return jsx(SlideNavButton, {
51797
52307
  command: command,
51798
52308
  locked: locked,
@@ -54345,6 +54855,7 @@ const css$E = /* css */`
54345
54855
  }
54346
54856
  }
54347
54857
 
54858
+ ${surfaceTextCss}
54348
54859
  ${popupCss}
54349
54860
  `;
54350
54861
 
@@ -55842,6 +56353,7 @@ const css$D = /* css */`
55842
56353
  }
55843
56354
  }
55844
56355
 
56356
+ ${surfaceTextCss}
55845
56357
  ${popupCss}
55846
56358
  `;
55847
56359
 
@@ -65962,6 +66474,20 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`
65962
66474
  pointer-events: none;
65963
66475
  user-select: none;
65964
66476
 
66477
+ /* The value the picker draws itself is the control's own text, at the
66478
+ control's font size: it keeps the control line, snapped to the pixel
66479
+ like the field around it. A caller's "ui" is the caller's own drawing
66480
+ of the control, and it is written on the page's line, as the number,
66481
+ so each text it holds keeps a line relative to its own size. The
66482
+ control line is a length (--navi-control-line-height), and inherited
66483
+ it would arrive as the control's pixels: a 14px label under an 18px
66484
+ picker's 23px line carries ~5px of leading above and below that no
66485
+ glyph occupies and nothing on screen explains. Same reason a popup
66486
+ takes the number — see .navi_popup in popup.jsx. */
66487
+ &[data-picker-facade] {
66488
+ line-height: var(--navi-line-height);
66489
+ }
66490
+
65965
66491
  &[navi-placeholder] {
65966
66492
  color: var(--picker-placeholder-color);
65967
66493
  font-style: var(--picker-placeholder-font-style);
@@ -66101,6 +66627,16 @@ installImportMetaCssBuild(import.meta);const css$t = /* css */`
66101
66627
  --x-corner-bottom-left-radius: initial;
66102
66628
 
66103
66629
  display: contents;
66630
+ /* What opens from a control is a page of its own, not part of that
66631
+ control's type scale: it is written at the control font by name,
66632
+ rather than by inheriting the size the picker itself is drawn at. A
66633
+ caller who sizes a picker to the façade it holds (so the padding, the
66634
+ corners and the chevron the picker draws in em land on the text the
66635
+ caller actually wrote) would otherwise take the popup down with it:
66636
+ its title, and everything in it that does not state a size of its
66637
+ own. Same reason the popup is written on the page's line rather than
66638
+ the control's — see .navi_popup in popup.jsx. */
66639
+ font-size: var(--navi-control-font-size);
66104
66640
  text-align: initial; /* Don't inherit picker text align */
66105
66641
  }
66106
66642
 
@@ -66504,6 +67040,12 @@ const PickerButton = props => {
66504
67040
  }
66505
67041
  }), variant === "headless" || ui === "default" ? null : jsx(Text, {
66506
67042
  className: "navi_picker_value"
67043
+ // Tells the caller's own drawing of the control from the value
67044
+ // the picker draws itself, so each is written on its own line
67045
+ // (see .navi_picker_value in the CSS above).
67046
+ ,
67047
+
67048
+ "data-picker-facade": ui === undefined ? undefined : ""
66507
67049
  // A button's label is not a placeholder, however empty the
66508
67050
  // picker behind it is.
66509
67051
  ,
@@ -78693,8 +79235,8 @@ const StepList = ({
78693
79235
  }
78694
79236
  const rootElement = rootRef.current;
78695
79237
  const read = () => {
78696
- const currentArea = containerElement.getAttribute("data-slide-current");
78697
- const towardArea = containerElement.getAttribute("data-slide-travel-toward");
79238
+ const currentArea = containerElement.getAttribute(SLIDE_CURRENT_ATTRIBUTE);
79239
+ const towardArea = containerElement.getAttribute(SLIDE_TOWARD_ATTRIBUTE);
78698
79240
  setContainerCurrent(currentArea ?? undefined);
78699
79241
  const currentIdx = currentArea === null ? -1 : indexOf(currentArea);
78700
79242
  if (currentIdx === -1) {
@@ -78718,13 +79260,12 @@ const StepList = ({
78718
79260
  rootElement.style.setProperty("--step-list-pos-dx", dx);
78719
79261
  };
78720
79262
  read();
78721
- const observer = new MutationObserver(read);
78722
- observer.observe(containerElement, {
78723
- attributes: true,
78724
- attributeFilter: ["data-slide-current", "data-slide-travel-toward"]
78725
- });
79263
+ // Read off the container, and re-read when it says something has changed:
79264
+ // a write is not a change, and the attribute the halo follows is written on
79265
+ // every frame of a gesture with the same value in it.
79266
+ containerElement.addEventListener(SLIDE_STATE_EVENT, read);
78726
79267
  return () => {
78727
- observer.disconnect();
79268
+ containerElement.removeEventListener(SLIDE_STATE_EVENT, read);
78728
79269
  };
78729
79270
  // width: the dots move when the room does, and the written positions are
78730
79271
  // pixels of those dots.
@@ -79555,5 +80096,5 @@ const UserSvg = () => jsx("svg", {
79555
80096
  })
79556
80097
  });
79557
80098
 
79558
- export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, CalloutStatusIcon, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, Expandable, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, InfoSvg, 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, RouteTransitionArea, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, SpinGroup, SplitButton, StarSvg, Step, StepList, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRangeSpin, TimeRangeWheel, TimeSpin, TimeWheel, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, canNavBackSignal, canNavForwardSignal, coarsePointerSignal, compareTwoJsValues, constraintFromValidityRule, createAction, createAvailableConstraint, createI18n, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineRouteDefaultTransition, defineRouteTransition, detectHorizontalOverflow, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, errorIsDisplayed, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isScrolling, isToday, languagesSignal, localStorageSignal, markErrorAsDisplayedBy, 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, useCalloutElement, useCalloutRequestClose, useCanNavBack, useCanNavForward, 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 };
80099
+ export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, CalloutStatusIcon, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, Expandable, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, InfoSvg, 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, RouteTransitionArea, RouteTravel, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, SpinGroup, SplitButton, StarSvg, Step, StepList, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, TimeRangeSpin, TimeRangeWheel, TimeSpin, TimeWheel, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, canNavBackSignal, canNavForwardSignal, coarsePointerSignal, compareTwoJsValues, constraintFromValidityRule, createAction, createAvailableConstraint, createI18n, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineInteractionDetector, defineRouteDefaultTransition, defineRouteTransition, detectHorizontalOverflow, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, errorIsDisplayed, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isScrolling, isToday, languagesSignal, localStorageSignal, markErrorAsDisplayedBy, 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, useCalloutElement, useCalloutRequestClose, useCanNavBack, useCanNavForward, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useInputGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, usePopupMode, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideContainer, useSlideValue, useStateArray, useTitleLevel, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
79559
80100
  //# sourceMappingURL=jsenv_navi.js.map