@jsenv/navi 0.29.162 → 0.29.164
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/jsenv_navi.js +478 -112
- package/dist/jsenv_navi.js.map +11 -9
- package/docs/route_transitions.md +39 -5
- package/package.json +2 -2
package/dist/jsenv_navi.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { installImportMetaCssBuild, windowHeightSignal, windowWidthSignal, visualViewportHeightSignal, visualViewportWidthSignal, getAppHeight, getAppWidth, coarsePointerSignal, smallTouchScreenSignal } from "./jsenv_navi_side_effects.js";
|
|
6
6
|
export { disableVirtualKeyboardOverlay } from "./jsenv_navi_side_effects.js";
|
|
7
|
-
import { elementIsFocusable, createIterableWeakSet, dispatchInternalCustomEvent, dispatchCustomEvent, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, getElementSignature, createPubSub, findEvent, createValueEffect, findFocusDelegateTarget, findFocusable, allowWheelThrough, dispatchPublicCustomEvent, resolveCSSColor, ELEMENT_SIZE_CHANGE, findSelfOrAncestorFixedPosition, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, applyNewPosition, measureLongestVisualLineWidth, chainEvent, waitForPressHeld, suppressClickAfterGesture, startDragToTravel, markDragSource, startDragTo, createEventGroupLogger, getKeyboardEventDefaultAction, activeElementSignal, normalizeStyle, mergeOneStyle, getPositionedParent, normalizeStyles, createGroupTransitionController, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, watchWheelTravel, scrollRoomTowards, getScrollContainer, closestOpenableAncestor, isAncestorOpen, isDisplayedDespiteClosedAncestor, observeAncestorOpenState, getAncestorOpenType, findBefore, findAfter, resolveCSSSize, hasCSSSizeUnit, releaseWheelGesture, getScrollIntoViewScopedOffsets, wheelGestureIsTakenFrom, claimWheelGesture, scrollIntoViewScoped, initFocusGroup, stringifyStyle as stringifyStyle$1, resolveOklchLightness, contrastColor, isTouchDrivenEvent, parsePositionArea, snapToPixel, trapFocusInside, trapScrollInside, onAncestorReopen, canScroll, measureWidestChildRow, performTabNavigation, dragAfterIntent, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement } from "@jsenv/dom";
|
|
7
|
+
import { elementIsFocusable, createIterableWeakSet, dispatchInternalCustomEvent, dispatchCustomEvent, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, getElementSignature, createPubSub, findEvent, createValueEffect, findFocusDelegateTarget, findFocusable, allowWheelThrough, dispatchPublicCustomEvent, resolveCSSColor, ELEMENT_SIZE_CHANGE, findSelfOrAncestorFixedPosition, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, applyNewPosition, measureLongestVisualLineWidth, chainEvent, waitForPressHeld, suppressClickAfterGesture, startDragToTravel, markDragSource, startDragTo, createEventGroupLogger, getKeyboardEventDefaultAction, activeElementSignal, normalizeStyle, mergeOneStyle, getPositionedParent, normalizeStyles, createGroupTransitionController, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, watchWheelTravel, scrollRoomTowards, getScrollContainer, closestOpenableAncestor, isAncestorOpen, isDisplayedDespiteClosedAncestor, observeAncestorOpenState, getAncestorOpenType, findBefore, findAfter, resolveCSSSize, hasCSSSizeUnit, releaseWheelGesture, getScrollIntoViewScopedOffsets, wheelGestureIsTakenFrom, claimWheelGesture, scrollIntoViewScoped, initFocusGroup, stringifyStyle as stringifyStyle$1, resolveOklchLightness, contrastColor, isTouchDrivenEvent, parsePositionArea, snapToPixel, trapFocusInside, trapScrollInside, onAncestorReopen, isPressDisputedByDrag, canScroll, measureWidestChildRow, performTabNavigation, dragAfterIntent, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement } from "@jsenv/dom";
|
|
8
8
|
export { chainEvent, clickIsSuppressed, contrastColor, findEvent, startDragTo } from "@jsenv/dom";
|
|
9
9
|
import { signal, computed, effect, untracked, batch, useComputed, useSignal } from "@preact/signals";
|
|
10
10
|
import { isValidElement, h, Fragment, createContext, render, toChildArray, options, cloneElement } from "preact";
|
|
@@ -28064,6 +28064,21 @@ installImportMetaCssBuild(import.meta);/**
|
|
|
28064
28064
|
* the reverse of another, so B → A can be given a movement of its own, or
|
|
28065
28065
|
* silenced with "none", by writing it (see findRelation).
|
|
28066
28066
|
*
|
|
28067
|
+
* One shape of page has no pair to write: the one whose door is in the fixed
|
|
28068
|
+
* furniture — a gear in a top bar, a "+" in a tab bar — and which is therefore
|
|
28069
|
+
* opened from every screen and closed back onto whichever one the reader was
|
|
28070
|
+
* on. The relation is real and it is a single sentence; only the `from` is
|
|
28071
|
+
* missing, so it is left out:
|
|
28072
|
+
*
|
|
28073
|
+
* defineRouteTransition(null, SETTINGS_PAGE, "cover-top");
|
|
28074
|
+
*
|
|
28075
|
+
* Arriving there plays forward from wherever, leaving plays back to wherever,
|
|
28076
|
+
* and that is what lets the back button close it the way it opened — a
|
|
28077
|
+
* traversal carries no request, and nothing has to remember per history entry
|
|
28078
|
+
* what the press that created it had asked for. It is tried after every
|
|
28079
|
+
* written pair, and it is not defineRouteDefaultTransition: a default is about
|
|
28080
|
+
* every navigation nothing was said about, this is about ONE destination.
|
|
28081
|
+
*
|
|
28067
28082
|
* The relation says WHEN something plays and which way; the transition says
|
|
28068
28083
|
* WHAT plays — a movement navi ships, or a name the application defines in its
|
|
28069
28084
|
* own CSS (see the JSDoc below). Said without one, the relation plays the
|
|
@@ -28252,7 +28267,7 @@ const css$11 = /* css */`:root[data-navi-route-transition] [data-navi-route-tran
|
|
|
28252
28267
|
}
|
|
28253
28268
|
}
|
|
28254
28269
|
|
|
28255
|
-
&[data-navi-route-transition-type="cover-
|
|
28270
|
+
&[data-navi-route-transition-type="cover-right"] {
|
|
28256
28271
|
&[data-navi-route-transition="forward"] {
|
|
28257
28272
|
--navi-route-transition-leave: navi-route-transition-still;
|
|
28258
28273
|
--navi-route-transition-enter: navi-route-transition-enter-from-end;
|
|
@@ -28261,14 +28276,22 @@ const css$11 = /* css */`:root[data-navi-route-transition] [data-navi-route-tran
|
|
|
28261
28276
|
&[data-navi-route-transition="back"] {
|
|
28262
28277
|
--navi-route-transition-leave: navi-route-transition-leave-towards-end;
|
|
28263
28278
|
--navi-route-transition-enter: navi-route-transition-still;
|
|
28279
|
+
}
|
|
28280
|
+
}
|
|
28264
28281
|
|
|
28265
|
-
|
|
28266
|
-
|
|
28267
|
-
|
|
28282
|
+
&[data-navi-route-transition-type="cover-left"] {
|
|
28283
|
+
&[data-navi-route-transition="forward"] {
|
|
28284
|
+
--navi-route-transition-leave: navi-route-transition-still;
|
|
28285
|
+
--navi-route-transition-enter: navi-route-transition-enter-from-start;
|
|
28286
|
+
}
|
|
28287
|
+
|
|
28288
|
+
&[data-navi-route-transition="back"] {
|
|
28289
|
+
--navi-route-transition-leave: navi-route-transition-leave-towards-start;
|
|
28290
|
+
--navi-route-transition-enter: navi-route-transition-still;
|
|
28268
28291
|
}
|
|
28269
28292
|
}
|
|
28270
28293
|
|
|
28271
|
-
&[data-navi-route-transition-type="cover-
|
|
28294
|
+
&[data-navi-route-transition-type="cover-bottom"] {
|
|
28272
28295
|
&[data-navi-route-transition="forward"] {
|
|
28273
28296
|
--navi-route-transition-leave: navi-route-transition-still;
|
|
28274
28297
|
--navi-route-transition-enter: navi-route-transition-enter-from-bottom;
|
|
@@ -28277,7 +28300,23 @@ const css$11 = /* css */`:root[data-navi-route-transition] [data-navi-route-tran
|
|
|
28277
28300
|
&[data-navi-route-transition="back"] {
|
|
28278
28301
|
--navi-route-transition-leave: navi-route-transition-leave-towards-bottom;
|
|
28279
28302
|
--navi-route-transition-enter: navi-route-transition-still;
|
|
28303
|
+
}
|
|
28304
|
+
}
|
|
28305
|
+
|
|
28306
|
+
&[data-navi-route-transition-type="cover-top"] {
|
|
28307
|
+
&[data-navi-route-transition="forward"] {
|
|
28308
|
+
--navi-route-transition-leave: navi-route-transition-still;
|
|
28309
|
+
--navi-route-transition-enter: navi-route-transition-enter-from-top;
|
|
28310
|
+
}
|
|
28311
|
+
|
|
28312
|
+
&[data-navi-route-transition="back"] {
|
|
28313
|
+
--navi-route-transition-leave: navi-route-transition-leave-towards-top;
|
|
28314
|
+
--navi-route-transition-enter: navi-route-transition-still;
|
|
28315
|
+
}
|
|
28316
|
+
}
|
|
28280
28317
|
|
|
28318
|
+
&[data-navi-route-transition-type="cover-right"], &[data-navi-route-transition-type="cover-left"], &[data-navi-route-transition-type="cover-bottom"], &[data-navi-route-transition-type="cover-top"] {
|
|
28319
|
+
&[data-navi-route-transition="back"] {
|
|
28281
28320
|
&::view-transition-old(root), &::view-transition-old(navi-route-transition) {
|
|
28282
28321
|
z-index: 1;
|
|
28283
28322
|
}
|
|
@@ -28300,7 +28339,7 @@ const css$11 = /* css */`:root[data-navi-route-transition] [data-navi-route-tran
|
|
|
28300
28339
|
}
|
|
28301
28340
|
}
|
|
28302
28341
|
|
|
28303
|
-
&[data-navi-route-transition-type="slide-x"], &[data-navi-route-transition-type="slide-y"], &[data-navi-route-transition-type="cover-
|
|
28342
|
+
&[data-navi-route-transition-type="slide-x"], &[data-navi-route-transition-type="slide-y"], &[data-navi-route-transition-type="cover-right"], &[data-navi-route-transition-type="cover-left"], &[data-navi-route-transition-type="cover-bottom"], &[data-navi-route-transition-type="cover-top"], &[data-navi-route-transition-type="zoom"] {
|
|
28304
28343
|
&::view-transition-old(root), &::view-transition-old(navi-route-transition) {
|
|
28305
28344
|
animation-name: var(--navi-route-transition-leave);
|
|
28306
28345
|
}
|
|
@@ -28310,7 +28349,7 @@ const css$11 = /* css */`:root[data-navi-route-transition] [data-navi-route-tran
|
|
|
28310
28349
|
}
|
|
28311
28350
|
}
|
|
28312
28351
|
|
|
28313
|
-
&[data-navi-route-transition-type="slide-x"], &[data-navi-route-transition-type="slide-y"], &[data-navi-route-transition-type="cover-
|
|
28352
|
+
&[data-navi-route-transition-type="slide-x"], &[data-navi-route-transition-type="slide-y"], &[data-navi-route-transition-type="cover-right"], &[data-navi-route-transition-type="cover-left"], &[data-navi-route-transition-type="cover-bottom"], &[data-navi-route-transition-type="cover-top"] {
|
|
28314
28353
|
&::view-transition-old(root), &::view-transition-new(root), &::view-transition-old(navi-route-transition), &::view-transition-new(navi-route-transition) {
|
|
28315
28354
|
animation-timing-function: ease;
|
|
28316
28355
|
}
|
|
@@ -28435,10 +28474,17 @@ const RouteTransitionArea = ({
|
|
|
28435
28474
|
};
|
|
28436
28475
|
|
|
28437
28476
|
/**
|
|
28438
|
-
* Declare how a pair of routes moves against each other
|
|
28439
|
-
*
|
|
28440
|
-
*
|
|
28441
|
-
*
|
|
28477
|
+
* Declare how a pair of routes moves against each other — or how one route is
|
|
28478
|
+
* entered, from wherever its door happens to be.
|
|
28479
|
+
*
|
|
28480
|
+
* @param {object|null} from - a route, or `{ route, params }` when the page is
|
|
28481
|
+
* a param of a route rather than a route of its own. `null` says the page is
|
|
28482
|
+
* reached FROM ANYWHERE: its door is in the furniture (a gear in the top
|
|
28483
|
+
* bar, a "+" in the tab bar) rather than on a screen, so there is no pair to
|
|
28484
|
+
* write it on. Arriving at `to` from any page then plays forward and leaving
|
|
28485
|
+
* it for any page plays back, which is what makes the back button close it
|
|
28486
|
+
* the way it opened. Tried last, after every written pair: a pair naming the
|
|
28487
|
+
* same destination still owns its crossing.
|
|
28442
28488
|
* @param {object} to - same forms. Going from `from` to `to` plays forward,
|
|
28443
28489
|
* the reverse plays back — unless the reverse is written as a relation of
|
|
28444
28490
|
* its own, which then owns that way (a movement of its own, or `"none"` for
|
|
@@ -28452,8 +28498,11 @@ const RouteTransitionArea = ({
|
|
|
28452
28498
|
* Omitted, the browser's own cross-fade. Shipped with navi:
|
|
28453
28499
|
* - `"slide-x"`, `"slide-y"`: the two pages slide past each other, forward
|
|
28454
28500
|
* towards the start of the axis;
|
|
28455
|
-
* - `"cover-
|
|
28456
|
-
* not move, and slides off it
|
|
28501
|
+
* - `"cover-right"`, `"cover-left"`, `"cover-bottom"`, `"cover-top"`: the
|
|
28502
|
+
* page arriving slides in OVER one that does not move, and slides off it
|
|
28503
|
+
* on the way back. The edge named is the one it comes IN from, which is
|
|
28504
|
+
* where its door is: a page reached from a bottom bar covers from the
|
|
28505
|
+
* bottom, one pulled down from a top bar covers from the top;
|
|
28457
28506
|
* - `"zoom"`: the deeper page is the closer one — it lands from slightly too
|
|
28458
28507
|
* big, and grows away when left;
|
|
28459
28508
|
* - `"none"`: nothing, said out loud — written on one way of a pair, it cuts
|
|
@@ -28484,6 +28533,9 @@ const RouteTransitionArea = ({
|
|
|
28484
28533
|
const defineRouteTransition = (from, to, transition) => {
|
|
28485
28534
|
import.meta.css = [css$11, "@jsenv/navi/src/nav/route_transition.jsx"];
|
|
28486
28535
|
installTransitionWindowCss();
|
|
28536
|
+
if (!to) {
|
|
28537
|
+
throw new TypeError(`defineRouteTransition needs a destination: "to" is ${to}. The page reached from anywhere is written defineRouteTransition(null, THAT_PAGE, ...) — there is no relation the other way round, a page LEFT for anywhere being the back half of that one.`);
|
|
28538
|
+
}
|
|
28487
28539
|
const {
|
|
28488
28540
|
type,
|
|
28489
28541
|
duration
|
|
@@ -28652,13 +28704,15 @@ const rebuildWatcher = () => {
|
|
|
28652
28704
|
}
|
|
28653
28705
|
// Every page any relation mentions, each once: the position of the current
|
|
28654
28706
|
// page in this list is what turns "some signal moved" into "the document
|
|
28655
|
-
// went from page A to page B".
|
|
28707
|
+
// went from page A to page B". A relation written from anywhere mentions one
|
|
28708
|
+
// page only — the other end is whatever the reader was on, and -1 is how it
|
|
28709
|
+
// reads here.
|
|
28656
28710
|
const pages = [];
|
|
28657
28711
|
for (const {
|
|
28658
28712
|
from,
|
|
28659
28713
|
to
|
|
28660
28714
|
} of relations) {
|
|
28661
|
-
if (pageIndexOf$1(pages, from) === -1) {
|
|
28715
|
+
if (from && pageIndexOf$1(pages, from) === -1) {
|
|
28662
28716
|
pages.push(from);
|
|
28663
28717
|
}
|
|
28664
28718
|
if (pageIndexOf$1(pages, to) === -1) {
|
|
@@ -28678,10 +28732,15 @@ const rebuildWatcher = () => {
|
|
|
28678
28732
|
firstReading = false;
|
|
28679
28733
|
return;
|
|
28680
28734
|
}
|
|
28681
|
-
if (
|
|
28735
|
+
if (fromIndex === index) {
|
|
28682
28736
|
return;
|
|
28683
28737
|
}
|
|
28684
|
-
|
|
28738
|
+
// A page in no relation at all is a real end of the crossing, not a
|
|
28739
|
+
// missing one: it is the "anywhere" a page reached from the furniture is
|
|
28740
|
+
// opened over and closed back onto (see findRelation).
|
|
28741
|
+
const fromPage = fromIndex === -1 ? null : pages[fromIndex];
|
|
28742
|
+
const toPage = index === -1 ? null : pages[index];
|
|
28743
|
+
const found = findRelation(fromPage, toPage);
|
|
28685
28744
|
if (!found && !navigationRequest) {
|
|
28686
28745
|
// No relation says anything about these two and this navigation asked
|
|
28687
28746
|
// for nothing: they are side by side, and silence is the fact — not a
|
|
@@ -28700,7 +28759,7 @@ const rebuildWatcher = () => {
|
|
|
28700
28759
|
return;
|
|
28701
28760
|
}
|
|
28702
28761
|
beginTransition({
|
|
28703
|
-
page:
|
|
28762
|
+
page: toPage,
|
|
28704
28763
|
url: navigationUrl,
|
|
28705
28764
|
// Which way it plays: what the navigation itself said first — the link
|
|
28706
28765
|
// being pressed is where the way the app is being walked is known — then
|
|
@@ -28777,13 +28836,23 @@ observeAfterRouting(() => {
|
|
|
28777
28836
|
releaseRoutingRenderingHold();
|
|
28778
28837
|
});
|
|
28779
28838
|
|
|
28780
|
-
// The exact way travelled first, over the whole registry,
|
|
28781
|
-
//
|
|
28782
|
-
//
|
|
28783
|
-
//
|
|
28784
|
-
//
|
|
28839
|
+
// The exact way travelled first, over the whole registry, then the reverses,
|
|
28840
|
+
// and last the pages written from anywhere.
|
|
28841
|
+
//
|
|
28842
|
+
// A relation written B → A owns that way, and being the reverse of one written
|
|
28843
|
+
// A → B never outranks it. This is what makes reciprocity a default rather
|
|
28844
|
+
// than a decree — write the way back to give it a movement of its own, or
|
|
28845
|
+
// "none" to silence it.
|
|
28846
|
+
//
|
|
28847
|
+
// A page reached from anywhere is tried after every pair, so a pair naming the
|
|
28848
|
+
// same destination still owns its crossing — the map, where it was drawn, is
|
|
28849
|
+
// more precise than "from wherever". Arriving is read before leaving: between
|
|
28850
|
+
// two such pages, the one being opened says what plays.
|
|
28785
28851
|
const findRelation = (fromPage, toPage) => {
|
|
28786
28852
|
for (const relation of relations) {
|
|
28853
|
+
if (!relation.from) {
|
|
28854
|
+
continue;
|
|
28855
|
+
}
|
|
28787
28856
|
if (samePage$1(relation.from, fromPage) && samePage$1(relation.to, toPage)) {
|
|
28788
28857
|
return {
|
|
28789
28858
|
direction: "forward",
|
|
@@ -28792,6 +28861,9 @@ const findRelation = (fromPage, toPage) => {
|
|
|
28792
28861
|
}
|
|
28793
28862
|
}
|
|
28794
28863
|
for (const relation of relations) {
|
|
28864
|
+
if (!relation.from) {
|
|
28865
|
+
continue;
|
|
28866
|
+
}
|
|
28795
28867
|
if (samePage$1(relation.from, toPage) && samePage$1(relation.to, fromPage)) {
|
|
28796
28868
|
return {
|
|
28797
28869
|
direction: "back",
|
|
@@ -28799,6 +28871,28 @@ const findRelation = (fromPage, toPage) => {
|
|
|
28799
28871
|
};
|
|
28800
28872
|
}
|
|
28801
28873
|
}
|
|
28874
|
+
for (const relation of relations) {
|
|
28875
|
+
if (relation.from) {
|
|
28876
|
+
continue;
|
|
28877
|
+
}
|
|
28878
|
+
if (samePage$1(relation.to, toPage)) {
|
|
28879
|
+
return {
|
|
28880
|
+
direction: "forward",
|
|
28881
|
+
relation
|
|
28882
|
+
};
|
|
28883
|
+
}
|
|
28884
|
+
}
|
|
28885
|
+
for (const relation of relations) {
|
|
28886
|
+
if (relation.from) {
|
|
28887
|
+
continue;
|
|
28888
|
+
}
|
|
28889
|
+
if (samePage$1(relation.to, fromPage)) {
|
|
28890
|
+
return {
|
|
28891
|
+
direction: "back",
|
|
28892
|
+
relation
|
|
28893
|
+
};
|
|
28894
|
+
}
|
|
28895
|
+
}
|
|
28802
28896
|
return null;
|
|
28803
28897
|
};
|
|
28804
28898
|
|
|
@@ -28906,10 +29000,11 @@ const beginTransition = ({
|
|
|
28906
29000
|
// rendered has already resolved the wait by the next line.
|
|
28907
29001
|
releaseRendering();
|
|
28908
29002
|
if (page === null) {
|
|
28909
|
-
//
|
|
28910
|
-
//
|
|
28911
|
-
//
|
|
28912
|
-
//
|
|
29003
|
+
// Which page is arriving is unknown — a default transition, or a page
|
|
29004
|
+
// reached from anywhere being left for wherever — and some navigations
|
|
29005
|
+
// render no route at all (a search param bound to a signal): waited
|
|
29006
|
+
// on, those would freeze the page until the browser gives up. The wait
|
|
29007
|
+
// is raced with a short timer instead.
|
|
28913
29008
|
await Promise.race([renderWait.rendered, waitMs(50)]);
|
|
28914
29009
|
} else if (pageIsCurrent$1(page)) {
|
|
28915
29010
|
await renderWait.rendered;
|
|
@@ -29034,10 +29129,18 @@ const armRouteRenderWait$1 = () => {
|
|
|
29034
29129
|
};
|
|
29035
29130
|
};
|
|
29036
29131
|
const waitMs = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
29037
|
-
|
|
29038
|
-
|
|
29039
|
-
|
|
29040
|
-
|
|
29132
|
+
|
|
29133
|
+
// A page written as the route itself, and the page written nowhere: `from`
|
|
29134
|
+
// may be left out, which is a relation about arriving at `to` from anywhere.
|
|
29135
|
+
const normalizePage$1 = page => {
|
|
29136
|
+
if (!page) {
|
|
29137
|
+
return null;
|
|
29138
|
+
}
|
|
29139
|
+
return page.isRoute ? {
|
|
29140
|
+
route: page,
|
|
29141
|
+
params: undefined
|
|
29142
|
+
} : page;
|
|
29143
|
+
};
|
|
29041
29144
|
|
|
29042
29145
|
// Two pages are the same page when they select the same thing, not when they
|
|
29043
29146
|
// were written by the same hand.
|
|
@@ -30594,6 +30697,117 @@ const unnameAfterTravel = element => {
|
|
|
30594
30697
|
element.style.viewTransitionName = "";
|
|
30595
30698
|
};
|
|
30596
30699
|
|
|
30700
|
+
/**
|
|
30701
|
+
* What covers the box a route movement plays in, from INSIDE the document: a
|
|
30702
|
+
* sticky row of tabs above a `<RouteTravel>`, a header pinned to the top of a
|
|
30703
|
+
* scroller. The element says it is there, this measures what it takes and
|
|
30704
|
+
* publishes it under --navi-transition-cover-* — the slot transition_window.js
|
|
30705
|
+
* declares and explains, and which nothing but the element covering the box can
|
|
30706
|
+
* fill: the safe area answers for what is pinned to the WINDOW's edges, and a
|
|
30707
|
+
* sticky row is none of those.
|
|
30708
|
+
*
|
|
30709
|
+
* The pictures of a transition are drawn in the top layer, above every z-index
|
|
30710
|
+
* of the document, so a band left uncounted here is a band the pictures slide
|
|
30711
|
+
* over instead of being cut at.
|
|
30712
|
+
*
|
|
30713
|
+
* Same shape as the room a fixed bar gives back (layout/fixed_bar/
|
|
30714
|
+
* fixed_bar_space.js): measured rather than declared, and the largest of the
|
|
30715
|
+
* elements sharing an edge rather than their sum — during a route movement the
|
|
30716
|
+
* outgoing and the incoming row are both mounted, pinned to the same edge, one
|
|
30717
|
+
* over the other. Nothing takes its layout from these variables, though, so the
|
|
30718
|
+
* write happens where it is measured, with no frame to wait for.
|
|
30719
|
+
*/
|
|
30720
|
+
|
|
30721
|
+
|
|
30722
|
+
const sizeMapByEdge = new Map();
|
|
30723
|
+
// What is currently on <html> for each edge (absent = the variable is not set).
|
|
30724
|
+
// Several elements sharing an edge means most calls compute the same largest
|
|
30725
|
+
// size again, and a size that has not changed is a style recalculation of the
|
|
30726
|
+
// whole document for nothing.
|
|
30727
|
+
const writtenValueByEdge = new Map();
|
|
30728
|
+
|
|
30729
|
+
/**
|
|
30730
|
+
* @param {import("preact").RefObject<Element>} elementRef - The element
|
|
30731
|
+
* covering the box.
|
|
30732
|
+
* @param {"top"|"right"|"bottom"|"left"} [edge="top"] - Which side of the box
|
|
30733
|
+
* it covers. Its size across that edge is what gets published; the edge's own
|
|
30734
|
+
* band (the safe area, the fixed bars) is already counted, so an element
|
|
30735
|
+
* states its own size and nothing else.
|
|
30736
|
+
*/
|
|
30737
|
+
const useTransitionCover = (elementRef, edge = "top") => {
|
|
30738
|
+
installTransitionWindowCss();
|
|
30739
|
+
|
|
30740
|
+
const measureCover = (element) => {
|
|
30741
|
+
const { width, height } = element.getBoundingClientRect();
|
|
30742
|
+
return edge === "left" || edge === "right" ? width : height;
|
|
30743
|
+
};
|
|
30744
|
+
|
|
30745
|
+
// Anything a render can change — the row's content, a size prop, a theme
|
|
30746
|
+
// variable — is measured in that same commit: a movement starting on the
|
|
30747
|
+
// render that grew the row is cut at the row as it now is.
|
|
30748
|
+
useLayoutEffect(() => {
|
|
30749
|
+
const element = elementRef.current;
|
|
30750
|
+
if (!element) {
|
|
30751
|
+
return;
|
|
30752
|
+
}
|
|
30753
|
+
writeCover(edge, element, measureCover(element));
|
|
30754
|
+
});
|
|
30755
|
+
|
|
30756
|
+
// What no render caused: a font arriving late, content coming from outside, a
|
|
30757
|
+
// rotation.
|
|
30758
|
+
useLayoutEffect(() => {
|
|
30759
|
+
const element = elementRef.current;
|
|
30760
|
+
if (!element) {
|
|
30761
|
+
return undefined;
|
|
30762
|
+
}
|
|
30763
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
30764
|
+
writeCover(edge, element, measureCover(element));
|
|
30765
|
+
});
|
|
30766
|
+
resizeObserver.observe(element);
|
|
30767
|
+
return () => {
|
|
30768
|
+
resizeObserver.disconnect();
|
|
30769
|
+
writeCover(edge, element, null);
|
|
30770
|
+
};
|
|
30771
|
+
}, [edge]);
|
|
30772
|
+
};
|
|
30773
|
+
|
|
30774
|
+
const writeCover = (edge, element, size) => {
|
|
30775
|
+
let sizeMap = sizeMapByEdge.get(edge);
|
|
30776
|
+
if (!sizeMap) {
|
|
30777
|
+
sizeMap = new Map();
|
|
30778
|
+
sizeMapByEdge.set(edge, sizeMap);
|
|
30779
|
+
}
|
|
30780
|
+
if (size === null) {
|
|
30781
|
+
sizeMap.delete(element);
|
|
30782
|
+
} else {
|
|
30783
|
+
sizeMap.set(element, size);
|
|
30784
|
+
}
|
|
30785
|
+
let largestSize = 0;
|
|
30786
|
+
for (const coverSize of sizeMap.values()) {
|
|
30787
|
+
if (coverSize > largestSize) {
|
|
30788
|
+
largestSize = coverSize;
|
|
30789
|
+
}
|
|
30790
|
+
}
|
|
30791
|
+
const property = `--navi-transition-cover-${edge}`;
|
|
30792
|
+
const { style } = document.documentElement;
|
|
30793
|
+
if (sizeMap.size === 0) {
|
|
30794
|
+
// Back to the zero the sheet declares, rather than a zero written over it:
|
|
30795
|
+
// a page with no sticky row must read what navi says, not what the last one
|
|
30796
|
+
// left behind.
|
|
30797
|
+
if (writtenValueByEdge.has(edge)) {
|
|
30798
|
+
writtenValueByEdge.delete(edge);
|
|
30799
|
+
style.removeProperty(property);
|
|
30800
|
+
}
|
|
30801
|
+
return;
|
|
30802
|
+
}
|
|
30803
|
+
const value = `${largestSize}px`;
|
|
30804
|
+
if (writtenValueByEdge.get(edge) === value) {
|
|
30805
|
+
return;
|
|
30806
|
+
}
|
|
30807
|
+
writtenValueByEdge.set(edge, value);
|
|
30808
|
+
style.setProperty(property, value);
|
|
30809
|
+
};
|
|
30810
|
+
|
|
30597
30811
|
const routeAction = (
|
|
30598
30812
|
routeOrRoutes,
|
|
30599
30813
|
action,
|
|
@@ -39632,6 +39846,12 @@ const shouldInjectSpacingBetween = (left, right) => {
|
|
|
39632
39846
|
* An invisible placeholder rendered with those styles reserves the space; the
|
|
39633
39847
|
* real visible text is layered on top via `position: absolute`.
|
|
39634
39848
|
* Best combined with `noWrap` — does not work reliably on multi-line text.
|
|
39849
|
+
* The placeholder is a SECOND copy of the children: it is `aria-hidden`, so
|
|
39850
|
+
* the accessible name is right, but the text appears twice in `textContent`
|
|
39851
|
+
* — which is what a test asserting on the element's text reads. Where the
|
|
39852
|
+
* element's text must stay single (a tab, a label a test matches on), reserve
|
|
39853
|
+
* the space some other way; `Link`'s `currentEffectBold` paints the weight by
|
|
39854
|
+
* default and comes here only when asked to (`"hold-space"`).
|
|
39635
39855
|
*
|
|
39636
39856
|
* @param {boolean} [boldStable]
|
|
39637
39857
|
* Alternative to `holdSpaceForStyle` for multi-line text. Keeps a consistent
|
|
@@ -40131,6 +40351,7 @@ installImportMetaCssBuild(import.meta);const css$X = /* css */`@layer navi {
|
|
|
40131
40351
|
--link-text-decoration-hover: var(--link-text-decoration);
|
|
40132
40352
|
--link-cursor: pointer;
|
|
40133
40353
|
--link-outline-width: 2px;
|
|
40354
|
+
--link-current-effect-bold-thickness: .02em;
|
|
40134
40355
|
--link-current-indicator-size: 2px;
|
|
40135
40356
|
--link-current-indicator-spacing: 0;
|
|
40136
40357
|
--link-current-indicator-color: var(--navi-link-current-indicator-color);
|
|
@@ -40266,7 +40487,12 @@ installImportMetaCssBuild(import.meta);const css$X = /* css */`@layer navi {
|
|
|
40266
40487
|
--x-link-color: var(--link-color-current);
|
|
40267
40488
|
}
|
|
40268
40489
|
|
|
40269
|
-
&[data-current-effect-bold] {
|
|
40490
|
+
&[data-current-effect-bold="text-shadow"] {
|
|
40491
|
+
text-shadow: var(--link-current-effect-bold-thickness) 0 0 currentColor,
|
|
40492
|
+
calc(-1 * var(--link-current-effect-bold-thickness)) 0 0 currentColor;
|
|
40493
|
+
}
|
|
40494
|
+
|
|
40495
|
+
&[data-current-effect-bold="hold-space"] {
|
|
40270
40496
|
font-weight: bold;
|
|
40271
40497
|
}
|
|
40272
40498
|
|
|
@@ -40479,8 +40705,17 @@ Object.assign(PSEUDO_CLASSES, {
|
|
|
40479
40705
|
* `"tab"` renders a tab-like affordance.
|
|
40480
40706
|
* @param {boolean|"top"|"bottom"|"left"|"right"} [props.currentIndicator] - A
|
|
40481
40707
|
* bar drawn on the given edge (or bottom when `true`) while current.
|
|
40482
|
-
* @param {boolean} [props.currentEffectBold] - Bold
|
|
40483
|
-
*
|
|
40708
|
+
* @param {boolean|"text-shadow"|"hold-space"} [props.currentEffectBold] - Bold
|
|
40709
|
+
* the label while current, without its width changing — a row of tabs must
|
|
40710
|
+
* not jump when one becomes current. Which is a choice of two:
|
|
40711
|
+
* - `"text-shadow"` (what `true` means): the weight is PAINTED, the glyphs
|
|
40712
|
+
* drawn a hair to each side of themselves
|
|
40713
|
+
* (`--link-current-effect-bold-thickness`). The label stays one piece of
|
|
40714
|
+
* text, so `textContent` and anything reading it still see it once.
|
|
40715
|
+
* - `"hold-space"`: the real bold face, its width held by an invisible copy
|
|
40716
|
+
* of the label rendered bold underneath. True bold — and the label then
|
|
40717
|
+
* appears TWICE in `textContent`, which a test asserting on the element's
|
|
40718
|
+
* text reads (see `holdSpaceForStyle` in `text.jsx`).
|
|
40484
40719
|
* @param {boolean} [props.currentEffectShadow] - Inset-shadow effect while
|
|
40485
40720
|
* current (used with `variant="tab"`).
|
|
40486
40721
|
* @param {boolean|import("ignore:preact").ComponentChild} [props.startIcon] - Icon
|
|
@@ -40710,6 +40945,11 @@ const LinkPlain = props => {
|
|
|
40710
40945
|
const startIconEl = startIcon;
|
|
40711
40946
|
const endIconEl = innerEndIcon;
|
|
40712
40947
|
|
|
40948
|
+
// Bold by painting the glyphs unless asked for the bold face itself, because
|
|
40949
|
+
// that one costs a second copy of the label in the element's text (see the
|
|
40950
|
+
// css above).
|
|
40951
|
+
const currentEffectBoldTechnique = currentEffectBold === true ? "text-shadow" : currentEffectBold || undefined;
|
|
40952
|
+
|
|
40713
40953
|
// Where the bar goes: said here, or once for the whole row by the <Nav>
|
|
40714
40954
|
// around this link.
|
|
40715
40955
|
const currentIndicatorAsked = currentIndicator ?? nav?.currentIndicator;
|
|
@@ -40799,7 +41039,7 @@ const LinkPlain = props => {
|
|
|
40799
41039
|
onnavi_value: e => {
|
|
40800
41040
|
e.detail.setValue(value);
|
|
40801
41041
|
},
|
|
40802
|
-
holdSpaceForStyle:
|
|
41042
|
+
holdSpaceForStyle: currentEffectBoldTechnique === "hold-space" ? {
|
|
40803
41043
|
fontWeight: "bold"
|
|
40804
41044
|
} : undefined,
|
|
40805
41045
|
preventSpaceUnderlines: true
|
|
@@ -40813,7 +41053,7 @@ const LinkPlain = props => {
|
|
|
40813
41053
|
,
|
|
40814
41054
|
|
|
40815
41055
|
"data-variant": variant,
|
|
40816
|
-
"data-current-effect-bold":
|
|
41056
|
+
"data-current-effect-bold": currentEffectBoldTechnique,
|
|
40817
41057
|
"data-current-effect-shadow": currentEffectShadow ? "" : undefined,
|
|
40818
41058
|
"data-current-indicator-position": currentIndicatorPosition,
|
|
40819
41059
|
"data-anchor": anchor ? "" : undefined,
|
|
@@ -41051,6 +41291,10 @@ const css$W = /* css */`@layer navi {
|
|
|
41051
41291
|
--nav-current-indicator-size: 2px;
|
|
41052
41292
|
--nav-current-indicator-color: var(--navi-link-current-indicator-color);
|
|
41053
41293
|
}
|
|
41294
|
+
|
|
41295
|
+
.navi_nav .navi_link {
|
|
41296
|
+
--link-current-indicator-color: var(--nav-current-indicator-color);
|
|
41297
|
+
}
|
|
41054
41298
|
}
|
|
41055
41299
|
|
|
41056
41300
|
.navi_nav[data-nav-indicator] {
|
|
@@ -41061,8 +41305,14 @@ const css$W = /* css */`@layer navi {
|
|
|
41061
41305
|
var(--nav-indicator-position-delta));
|
|
41062
41306
|
--x-nav-indicator-length: calc(var(--nav-indicator-length) + var(--slide-travel-progress) *
|
|
41063
41307
|
var(--nav-indicator-length-delta));
|
|
41308
|
+
--x-nav-indicator-color: var(--nav-indicator-color, var(--nav-current-indicator-color));
|
|
41309
|
+
--x-nav-indicator-color-toward: var(--nav-indicator-color-toward, var(--x-nav-indicator-color));
|
|
41064
41310
|
z-index: 1;
|
|
41065
|
-
background:
|
|
41311
|
+
background: color-mix(in srgb,
|
|
41312
|
+
var(--x-nav-indicator-color-toward)
|
|
41313
|
+
calc(var(--slide-travel-progress) * var(--nav-indicator-toward-sign, 0) *
|
|
41314
|
+
100%),
|
|
41315
|
+
var(--x-nav-indicator-color));
|
|
41066
41316
|
pointer-events: none;
|
|
41067
41317
|
border-radius: .1px;
|
|
41068
41318
|
position: absolute;
|
|
@@ -41127,6 +41377,11 @@ const css$W = /* css */`@layer navi {
|
|
|
41127
41377
|
|
|
41128
41378
|
&[data-scrollable] {
|
|
41129
41379
|
max-width: 100%;
|
|
41380
|
+
|
|
41381
|
+
& .navi_link {
|
|
41382
|
+
white-space: nowrap;
|
|
41383
|
+
flex: none;
|
|
41384
|
+
}
|
|
41130
41385
|
}
|
|
41131
41386
|
|
|
41132
41387
|
&[data-scrollable][data-vertical] {
|
|
@@ -41162,13 +41417,13 @@ const css$W = /* css */`@layer navi {
|
|
|
41162
41417
|
&[data-expand-x] {
|
|
41163
41418
|
flex-grow: 1;
|
|
41164
41419
|
|
|
41165
|
-
&:not([data-vertical]) .navi_link {
|
|
41420
|
+
&:not([data-vertical]):not([data-scrollable]) .navi_link {
|
|
41166
41421
|
flex: 1;
|
|
41167
41422
|
justify-content: center;
|
|
41168
41423
|
}
|
|
41169
41424
|
}
|
|
41170
41425
|
|
|
41171
|
-
&[data-expand-y][data-vertical] {
|
|
41426
|
+
&[data-expand-y][data-vertical]:not([data-scrollable]) {
|
|
41172
41427
|
& .navi_link {
|
|
41173
41428
|
flex: 1;
|
|
41174
41429
|
}
|
|
@@ -41256,6 +41511,10 @@ const positionOfCurrentIndicator = (currentIndicator, vertical) => {
|
|
|
41256
41511
|
* @param {boolean|"top"|"bottom"|"left"|"right"} [props.currentIndicator] - the
|
|
41257
41512
|
* bar that says which tab one is on, said once here rather than on every
|
|
41258
41513
|
* `<Link>`. A link may still say otherwise for itself.
|
|
41514
|
+
* Its colour belongs to the tab it is under: `currentIndicatorColor` here is
|
|
41515
|
+
* what every tab inherits, and a tab declaring
|
|
41516
|
+
* `--nav-current-indicator-color` for itself is arrived at in its own colour
|
|
41517
|
+
* — the bar changes colour as it travels rather than once it lands.
|
|
41259
41518
|
* @param {boolean} [props.currentIndicatorSlides=true] - whether that bar
|
|
41260
41519
|
* travels from the tab it was under to the tab it is under now, instead of
|
|
41261
41520
|
* going out on one and coming back on the other. For a nav made of routes it
|
|
@@ -41334,11 +41593,11 @@ const Nav = ({
|
|
|
41334
41593
|
return navElement.querySelector(`[data-slide-target="${CSS.escape(towardArea)}"]`);
|
|
41335
41594
|
};
|
|
41336
41595
|
|
|
41337
|
-
// Where the trait is
|
|
41338
|
-
// CSS above interpolates between (see the .navi_nav_indicator
|
|
41339
|
-
// by hand rather than rendered: it is read off the row as it
|
|
41340
|
-
// travel it must agree with starts in the same frame the
|
|
41341
|
-
// it — a render would land after the movement had begun.
|
|
41596
|
+
// Where the trait is, where it is headed, and in which colour at each end —
|
|
41597
|
+
// the numbers the CSS above interpolates between (see the .navi_nav_indicator
|
|
41598
|
+
// rules). Written by hand rather than rendered: it is read off the row as it
|
|
41599
|
+
// stands, and the travel it must agree with starts in the same frame the
|
|
41600
|
+
// container publishes it — a render would land after the movement had begun.
|
|
41342
41601
|
const paintIndicatorGeometry = () => {
|
|
41343
41602
|
const navElement = navRef.current;
|
|
41344
41603
|
const containerElement = slideContainerElementRef.current;
|
|
@@ -41360,13 +41619,29 @@ const Nav = ({
|
|
|
41360
41619
|
position: tabElement.offsetLeft,
|
|
41361
41620
|
length: tabElement.offsetWidth
|
|
41362
41621
|
};
|
|
41622
|
+
// The colour a tab asks the bar to be under it. Read from the tab and not
|
|
41623
|
+
// from the row, so a tab that says nothing gives the row's value back —
|
|
41624
|
+
// it inherits it (see the css above) — and one that says something gives
|
|
41625
|
+
// its own. Empty when neither resolves to anything: the css then falls
|
|
41626
|
+
// back on its own, rather than being handed a colour that is not one.
|
|
41627
|
+
const colorOf = tabElement => getComputedStyle(tabElement).getPropertyValue("--link-current-indicator-color").trim();
|
|
41628
|
+
const writeColor = (property, color) => {
|
|
41629
|
+
if (color) {
|
|
41630
|
+
navElement.style.setProperty(property, color);
|
|
41631
|
+
} else {
|
|
41632
|
+
navElement.style.removeProperty(property);
|
|
41633
|
+
}
|
|
41634
|
+
};
|
|
41363
41635
|
const currentMeasure = measure(tabElements[currentIndex]);
|
|
41364
41636
|
const towardArea = containerElement.getAttribute("data-slide-travel-toward");
|
|
41365
41637
|
const towardIndex = tabElements.findIndex(tabElement => areaOf(tabElement) === towardArea);
|
|
41366
41638
|
let positionDelta = 0;
|
|
41367
41639
|
let lengthDelta = 0;
|
|
41640
|
+
let towardSign = 0;
|
|
41641
|
+
let towardColor = "";
|
|
41368
41642
|
if (towardIndex !== -1 && towardIndex !== currentIndex) {
|
|
41369
|
-
const
|
|
41643
|
+
const towardTabElement = tabElements[towardIndex];
|
|
41644
|
+
const towardMeasure = measure(towardTabElement);
|
|
41370
41645
|
// What one box of travel is worth in pixels of this row, signed so that
|
|
41371
41646
|
// the trait is exactly on the other tab when the progress is at its own
|
|
41372
41647
|
// end: the container counts +1 when the picture leans on a slide sitting
|
|
@@ -41374,6 +41649,8 @@ const Nav = ({
|
|
|
41374
41649
|
const sign = towardIndex > currentIndex ? -1 : 1;
|
|
41375
41650
|
positionDelta = (towardMeasure.position - currentMeasure.position) * sign;
|
|
41376
41651
|
lengthDelta = (towardMeasure.length - currentMeasure.length) * sign;
|
|
41652
|
+
towardSign = sign;
|
|
41653
|
+
towardColor = colorOf(towardTabElement);
|
|
41377
41654
|
}
|
|
41378
41655
|
const {
|
|
41379
41656
|
style
|
|
@@ -41382,6 +41659,9 @@ const Nav = ({
|
|
|
41382
41659
|
style.setProperty("--nav-indicator-length", currentMeasure.length);
|
|
41383
41660
|
style.setProperty("--nav-indicator-position-delta", positionDelta);
|
|
41384
41661
|
style.setProperty("--nav-indicator-length-delta", lengthDelta);
|
|
41662
|
+
style.setProperty("--nav-indicator-toward-sign", towardSign);
|
|
41663
|
+
writeColor("--nav-indicator-color", colorOf(tabElements[currentIndex]));
|
|
41664
|
+
writeColor("--nav-indicator-color-toward", towardColor);
|
|
41385
41665
|
navElement.setAttribute("data-nav-indicator-measured", "");
|
|
41386
41666
|
};
|
|
41387
41667
|
// Reached through a ref by everything watching the DOM below: those watchers
|
|
@@ -42857,7 +43137,15 @@ installImportMetaCssBuild(import.meta);/**
|
|
|
42857
43137
|
* keeps its bars against its own edges.
|
|
42858
43138
|
* 2. **It gives its space back.** Being fixed it covers the content: without a
|
|
42859
43139
|
* reserve the end of a long page stays under it, unreachable. It publishes
|
|
42860
|
-
* what it takes on <html> — see fixed_bar_space.js.
|
|
43140
|
+
* what it takes on <html> — see fixed_bar_space.js. An edge holds ONE bar:
|
|
43141
|
+
* bars sharing an edge are pinned to it one over the other, so the room
|
|
43142
|
+
* given back is the largest of them and never their sum — which is what the
|
|
43143
|
+
* two bars of a page transition need, and what makes a deliberately stacked
|
|
43144
|
+
* second bar unexpressible. A second strip under the first belongs to the
|
|
43145
|
+
* flow: `position: sticky` at `top: var(--navi-fixed-bar-space-top)`, which
|
|
43146
|
+
* puts it under whatever the bar of the moment is worth, and
|
|
43147
|
+
* `useTransitionCover` (nav/transition_cover.js) so the pictures of a route
|
|
43148
|
+
* movement are cut at it.
|
|
42861
43149
|
* 3. **It reaches under the notch.** `env(safe-area-inset-*)` is padding, so
|
|
42862
43150
|
* the content is pushed in while the background keeps running to the edge of
|
|
42863
43151
|
* the screen. Across the bar that inset is added to `width`/`height` too, so
|
|
@@ -42972,7 +43260,9 @@ const FixedBarStyleCSSVars = {
|
|
|
42972
43260
|
* borderColor?: string,
|
|
42973
43261
|
* }>}
|
|
42974
43262
|
* @param {"top"|"bottom"|"left"|"right"} [props.area="top"] - Which edge of
|
|
42975
|
-
* the window it is pinned to.
|
|
43263
|
+
* the window it is pinned to. One bar per edge: a second one does not stack
|
|
43264
|
+
* under the first, it sits on it (see this file's top comment for the strip
|
|
43265
|
+
* that does stack).
|
|
42976
43266
|
* @param {string|number} [props.height] - For a bar on the top or bottom
|
|
42977
43267
|
* @param {string|number} [props.width] - …and for one on a side. The safe-area
|
|
42978
43268
|
* inset is NOT part of it: it is added on top, so the content keeps the size
|
|
@@ -43945,23 +44235,34 @@ installImportMetaCssBuild(import.meta);/**
|
|
|
43945
44235
|
* Expandable: an in-flow disclosure — a UI part that reveals a content part.
|
|
43946
44236
|
* It covers the same ground as <Details> with structural differences:
|
|
43947
44237
|
*
|
|
43948
|
-
* - the two parts are explicit and
|
|
44238
|
+
* - the two parts are explicit, and are Boxes:
|
|
43949
44239
|
*
|
|
43950
44240
|
* <Expandable>
|
|
43951
44241
|
* <Expandable.UI>See more</Expandable.UI>
|
|
43952
44242
|
* <Expandable.Content>…</Expandable.Content>
|
|
43953
44243
|
* </Expandable>
|
|
43954
44244
|
*
|
|
43955
|
-
*
|
|
43956
|
-
*
|
|
43957
|
-
*
|
|
43958
|
-
*
|
|
43959
|
-
*
|
|
43960
|
-
*
|
|
44245
|
+
* `openDirection` decides where the content is revealed — down (the
|
|
44246
|
+
* <details> shape) or up, left or right in `layout="column"`, where the
|
|
44247
|
+
* parts sit side by side sharing their height. It places the parts too
|
|
44248
|
+
* (CSS `order`), so an expandable revealing upward can still be written UI
|
|
44249
|
+
* first, and an expandable with no UI part at all — driven from
|
|
44250
|
+
* `open`/`signal` by a toggle of the app's own — can say which way it
|
|
44251
|
+
* opens. The marker chevron follows: it points right while closed and
|
|
44252
|
+
* toward where the content went while open (down, up, or left). The common
|
|
44253
|
+
* shape has a shorthand: `ui` prop + children as content.
|
|
44254
|
+
*
|
|
43961
44255
|
* - the UI part is the focusable toggle itself (role button, Space/Enter,
|
|
43962
44256
|
* arrow keys) and accepts any markup: controls inside it keep their own
|
|
43963
44257
|
* behavior, the marker is purely decorative.
|
|
43964
44258
|
*
|
|
44259
|
+
* The root never looks at its children: which parts are there, in which order,
|
|
44260
|
+
* is none of its business. It publishes a context and the parts take what they
|
|
44261
|
+
* need from it — including WHEN to arm the reveal, which <Expandable.Content>
|
|
44262
|
+
* asks for from its own layout effect. That is what lets a part re-render
|
|
44263
|
+
* later than the root (a memoized subtree does exactly that): the measurement
|
|
44264
|
+
* runs in the commit that put the content in the DOM, whichever one that is.
|
|
44265
|
+
*
|
|
43965
44266
|
* Reach for it knowingly: expanding in-flow SHIFTS the layout — everything
|
|
43966
44267
|
* below (or beside) moves when it opens. A Popover, Dialog, Picker or Callout
|
|
43967
44268
|
* answers the same click on its own layer, moving nothing, which is usually
|
|
@@ -44001,6 +44302,10 @@ const css$Q = /* css */`.navi_expandable {
|
|
|
44001
44302
|
display: flex;
|
|
44002
44303
|
position: relative;
|
|
44003
44304
|
|
|
44305
|
+
&[data-open-direction="down"] > .navi_expandable_content_container, &[data-open-direction="right"] > .navi_expandable_content_container, &[data-open-direction="up"] > .navi_expandable_ui, &[data-open-direction="left"] > .navi_expandable_ui {
|
|
44306
|
+
order: 1;
|
|
44307
|
+
}
|
|
44308
|
+
|
|
44004
44309
|
& > .navi_expandable_ui {
|
|
44005
44310
|
cursor: pointer;
|
|
44006
44311
|
user-select: none;
|
|
@@ -44046,7 +44351,7 @@ const css$Q = /* css */`.navi_expandable {
|
|
|
44046
44351
|
grid-template-rows: 1fr;
|
|
44047
44352
|
}
|
|
44048
44353
|
|
|
44049
|
-
&[data-
|
|
44354
|
+
&[data-open-direction="up"] > .navi_expandable_content_container {
|
|
44050
44355
|
clip-path: inset(0 -9999px -9999px);
|
|
44051
44356
|
align-content: end;
|
|
44052
44357
|
|
|
@@ -44087,7 +44392,7 @@ const css$Q = /* css */`.navi_expandable {
|
|
|
44087
44392
|
grid-template-rows: none;
|
|
44088
44393
|
}
|
|
44089
44394
|
|
|
44090
|
-
&[data-
|
|
44395
|
+
&[data-open-direction="left"] > .navi_expandable_content_container {
|
|
44091
44396
|
clip-path: inset(-9999px -9999px 0 0);
|
|
44092
44397
|
justify-content: end;
|
|
44093
44398
|
|
|
@@ -44143,6 +44448,7 @@ const useExpandableContext = partName => {
|
|
|
44143
44448
|
* loading?: boolean,
|
|
44144
44449
|
* animation?: boolean,
|
|
44145
44450
|
* layout?: "row" | "column",
|
|
44451
|
+
* openDirection?: "down" | "up" | "right" | "left",
|
|
44146
44452
|
* autoFocus?: boolean,
|
|
44147
44453
|
* maxContentHeight?: string | number,
|
|
44148
44454
|
* mount?: "always" | "from-first-open" | "while-opened",
|
|
@@ -44175,6 +44481,12 @@ const useExpandableContext = partName => {
|
|
|
44175
44481
|
* @param layout - `"row"` (default): the parts stack, the content expands
|
|
44176
44482
|
* vertically. `"column"`: the parts sit side by side sharing their height,
|
|
44177
44483
|
* the content expands horizontally next to the UI part.
|
|
44484
|
+
* @param openDirection - Where the content is revealed: `"down"` (default) or
|
|
44485
|
+
* `"up"` in the stacked layout, `"right"` (default) or `"left"` in
|
|
44486
|
+
* `layout="column"`. It also places the parts, so the direction holds
|
|
44487
|
+
* whatever order they are written in — and an expandable with no
|
|
44488
|
+
* `<Expandable.UI>` at all, driven from `open`/`signal` by a toggle of the
|
|
44489
|
+
* app's own, can still say which way it opens.
|
|
44178
44490
|
* @param autoFocus - Off by default (the focus stays on the UI part when
|
|
44179
44491
|
* opening). `true` moves the focus into the content on open — the
|
|
44180
44492
|
* `[autofocus]` element if any, the first focusable otherwise. Whatever the
|
|
@@ -44204,6 +44516,7 @@ const Expandable = props => {
|
|
|
44204
44516
|
loading,
|
|
44205
44517
|
animation = false,
|
|
44206
44518
|
layout,
|
|
44519
|
+
openDirection,
|
|
44207
44520
|
autoFocus,
|
|
44208
44521
|
maxContentHeight,
|
|
44209
44522
|
mount = MOUNT_DEFAULT,
|
|
@@ -44345,30 +44658,44 @@ const Expandable = props => {
|
|
|
44345
44658
|
toggleTo(openRequested);
|
|
44346
44659
|
}, [openRequested]);
|
|
44347
44660
|
|
|
44348
|
-
// A state change: tell the world (the "toggle" event)
|
|
44349
|
-
//
|
|
44350
|
-
//
|
|
44351
|
-
//
|
|
44661
|
+
// A state change: tell the world (the "toggle" event) and take the keyboard
|
|
44662
|
+
// back if the closing content held it. Skipped on mount — nothing changed,
|
|
44663
|
+
// so no event exists (and a page must not have its focus stolen by an
|
|
44664
|
+
// expandable that was simply already open).
|
|
44352
44665
|
const isFirstOpenedRunRef = useRef(true);
|
|
44353
44666
|
useLayoutEffect(() => {
|
|
44354
44667
|
if (isFirstOpenedRunRef.current) {
|
|
44355
44668
|
isFirstOpenedRunRef.current = false;
|
|
44356
|
-
return
|
|
44669
|
+
return;
|
|
44357
44670
|
}
|
|
44358
44671
|
const root = rootRef.current;
|
|
44359
44672
|
root.dispatchEvent(createToggleEvent(opened));
|
|
44360
44673
|
if (opened) {
|
|
44361
|
-
|
|
44362
|
-
|
|
44363
|
-
|
|
44364
|
-
|
|
44365
|
-
|
|
44674
|
+
return;
|
|
44675
|
+
}
|
|
44676
|
+
const focusedBeforeClose = focusedBeforeCloseRef.current;
|
|
44677
|
+
focusedBeforeCloseRef.current = null;
|
|
44678
|
+
if (focusedBeforeClose && contentContainerRef.current && contentContainerRef.current.contains(focusedBeforeClose)) {
|
|
44679
|
+
const uiElement = uiRef.current;
|
|
44680
|
+
if (uiElement) {
|
|
44681
|
+
uiElement.focus();
|
|
44682
|
+
} else {
|
|
44683
|
+
// Nothing of the expandable's own can hold the keyboard (no UI part):
|
|
44684
|
+
// the focus only has to leave the content becoming inert.
|
|
44685
|
+
focusedBeforeClose.blur();
|
|
44366
44686
|
}
|
|
44367
|
-
}
|
|
44368
|
-
|
|
44369
|
-
|
|
44370
|
-
|
|
44371
|
-
|
|
44687
|
+
}
|
|
44688
|
+
}, [opened]);
|
|
44689
|
+
|
|
44690
|
+
// Everything a state change owes the content: the focus it may take, and the
|
|
44691
|
+
// reveal, which measures it. Ran by <Expandable.Content> from its own layout
|
|
44692
|
+
// effect — the commit where the content really is in the DOM — and returns
|
|
44693
|
+
// that effect's cleanup.
|
|
44694
|
+
const applyOpenedToContent = () => {
|
|
44695
|
+
if (opened && autoFocus) {
|
|
44696
|
+
const firstFocusableElement = findFirstFocusableInContent();
|
|
44697
|
+
if (firstFocusableElement) {
|
|
44698
|
+
firstFocusableElement.focus();
|
|
44372
44699
|
}
|
|
44373
44700
|
}
|
|
44374
44701
|
if (!animation) {
|
|
@@ -44380,9 +44707,9 @@ const Expandable = props => {
|
|
|
44380
44707
|
// The reveal needs the content at its final size before the track
|
|
44381
44708
|
// starts moving, and the final size only exists in the open state —
|
|
44382
44709
|
// the reflow trick (see instructions.md, CSS section), with transitions
|
|
44383
|
-
// suppressed BEFORE the first layout read: this
|
|
44384
|
-
//
|
|
44385
|
-
//
|
|
44710
|
+
// suppressed BEFORE the first layout read: this runs pre-paint, so any
|
|
44711
|
+
// earlier read would itself be the first recalc of the open state and
|
|
44712
|
+
// would start the track transition (see revealStartSizeRef).
|
|
44386
44713
|
contentContainer.style.transitionProperty = "none";
|
|
44387
44714
|
const finalRect = contentElement.getBoundingClientRect();
|
|
44388
44715
|
if (isColumn) {
|
|
@@ -44422,7 +44749,7 @@ const Expandable = props => {
|
|
|
44422
44749
|
setSettled(true);
|
|
44423
44750
|
});
|
|
44424
44751
|
return cancel;
|
|
44425
|
-
}
|
|
44752
|
+
};
|
|
44426
44753
|
useLayoutEffect(() => {
|
|
44427
44754
|
if (settled && !opened && mountedWhileOpened) {
|
|
44428
44755
|
setContentMounted(false);
|
|
@@ -44468,6 +44795,12 @@ const Expandable = props => {
|
|
|
44468
44795
|
if (!arrowKeyShortcuts) {
|
|
44469
44796
|
return;
|
|
44470
44797
|
}
|
|
44798
|
+
// The shortcuts all speak about the UI part — opening from it, stepping
|
|
44799
|
+
// into the content, stepping back to it. Without one the expandable is
|
|
44800
|
+
// driven from outside and the keys belong to whatever drives it.
|
|
44801
|
+
if (!uiRef.current) {
|
|
44802
|
+
return;
|
|
44803
|
+
}
|
|
44471
44804
|
// A nested expandable (deeper, so heard first) already answered this key.
|
|
44472
44805
|
if (keyboardEvent.defaultPrevented) {
|
|
44473
44806
|
return;
|
|
@@ -44549,22 +44882,21 @@ const Expandable = props => {
|
|
|
44549
44882
|
}
|
|
44550
44883
|
};
|
|
44551
44884
|
|
|
44552
|
-
//
|
|
44553
|
-
//
|
|
44554
|
-
|
|
44555
|
-
// the
|
|
44556
|
-
|
|
44557
|
-
|
|
44558
|
-
const
|
|
44559
|
-
const contentFirst = hasParts && firstPart.type === ExpandableContent;
|
|
44560
|
-
const openDirection = isColumn ? "left" : contentFirst ? "up" : "down";
|
|
44885
|
+
// Only the two directions the layout has room for: a column layout reveals
|
|
44886
|
+
// sideways, a stacked one vertically.
|
|
44887
|
+
const revealDirection = isColumn ? openDirection === "left" ? "left" : "right" : openDirection === "up" ? "up" : "down";
|
|
44888
|
+
// While open the marker points at the content, while closed always right.
|
|
44889
|
+
// In a column layout it points back toward the UI part whichever side the
|
|
44890
|
+
// content took, "right" being the closed direction already.
|
|
44891
|
+
const markerDirection = isColumn ? "left" : revealDirection;
|
|
44561
44892
|
const expandableContextValue = {
|
|
44562
44893
|
opened,
|
|
44563
44894
|
loading: loading || hasAction && actionLoading,
|
|
44564
44895
|
contentMounted,
|
|
44565
44896
|
hasAction,
|
|
44566
44897
|
effectiveAction,
|
|
44567
|
-
|
|
44898
|
+
markerDirection,
|
|
44899
|
+
applyOpenedToContent,
|
|
44568
44900
|
toggleTo,
|
|
44569
44901
|
onUIClick,
|
|
44570
44902
|
onUIPointerDown,
|
|
@@ -44574,12 +44906,9 @@ const Expandable = props => {
|
|
|
44574
44906
|
contentId
|
|
44575
44907
|
};
|
|
44576
44908
|
|
|
44577
|
-
//
|
|
44578
|
-
//
|
|
44579
|
-
|
|
44580
|
-
// their context subscription to re-render them asynchronously — after the
|
|
44581
|
-
// [opened] effect above, which measures the content they render.
|
|
44582
|
-
const body = hasParts ? childArray.map(child => child && (child.type === ExpandableUI || child.type === ExpandableContent) ? cloneElement(child) : child) : jsxs(Fragment$1, {
|
|
44909
|
+
// The `ui` prop is the shorthand for the common shape: it names the UI part
|
|
44910
|
+
// and children are the content. Without it the children ARE the parts.
|
|
44911
|
+
const body = ui === undefined ? children : jsxs(Fragment$1, {
|
|
44583
44912
|
children: [jsx(ExpandableUI, {
|
|
44584
44913
|
children: ui
|
|
44585
44914
|
}), jsx(ExpandableContent, {
|
|
@@ -44591,7 +44920,7 @@ const Expandable = props => {
|
|
|
44591
44920
|
baseClassName: "navi_expandable",
|
|
44592
44921
|
"aria-expanded": opened ? "true" : "false",
|
|
44593
44922
|
"data-layout": isColumn ? "column" : undefined,
|
|
44594
|
-
"data-
|
|
44923
|
+
"data-open-direction": revealDirection,
|
|
44595
44924
|
"data-animation": animation ? "" : undefined,
|
|
44596
44925
|
"data-settled": settled ? "" : undefined,
|
|
44597
44926
|
"data-content-scrolls": maxContentHeight === undefined ? undefined : "",
|
|
@@ -44631,22 +44960,25 @@ const Expandable = props => {
|
|
|
44631
44960
|
* The always-visible part that reveals the content: the focusable toggle
|
|
44632
44961
|
* itself (role button — click, Space/Enter, arrow keys), holding the marker
|
|
44633
44962
|
* plus whatever it is given — any markup, a function of `{ open }` included.
|
|
44634
|
-
* Controls inside it keep their own behavior and do not toggle.
|
|
44635
|
-
*
|
|
44636
|
-
* below/right; after it: content above/left).
|
|
44963
|
+
* Controls inside it keep their own behavior and do not toggle. A Box, so it
|
|
44964
|
+
* takes the layout and style props every Box takes.
|
|
44637
44965
|
*
|
|
44638
44966
|
* @type {import("ignore:preact").FunctionComponent<{
|
|
44967
|
+
* marker?: false | import("ignore:preact").ComponentChildren,
|
|
44639
44968
|
* children?: import("ignore:preact").ComponentChildren | ((state: { open: boolean }) => import("ignore:preact").ComponentChildren),
|
|
44640
44969
|
* }>}
|
|
44970
|
+
* @param marker - The chevron drawn before the label. `false` removes it (a UI
|
|
44971
|
+
* part that is already an icon has no room for one); any node replaces it.
|
|
44641
44972
|
*/
|
|
44642
44973
|
const ExpandableUI = ({
|
|
44974
|
+
marker,
|
|
44643
44975
|
children,
|
|
44644
44976
|
...rest
|
|
44645
44977
|
}) => {
|
|
44646
44978
|
const {
|
|
44647
44979
|
opened,
|
|
44648
44980
|
loading,
|
|
44649
|
-
|
|
44981
|
+
markerDirection,
|
|
44650
44982
|
toggleTo,
|
|
44651
44983
|
onUIClick,
|
|
44652
44984
|
onUIPointerDown,
|
|
@@ -44654,9 +44986,9 @@ const ExpandableUI = ({
|
|
|
44654
44986
|
uiRef,
|
|
44655
44987
|
contentId
|
|
44656
44988
|
} = useExpandableContext("UI");
|
|
44657
|
-
return jsxs(
|
|
44989
|
+
return jsxs(Box, {
|
|
44658
44990
|
ref: uiRef,
|
|
44659
|
-
|
|
44991
|
+
baseClassName: "navi_expandable_ui",
|
|
44660
44992
|
role: "button",
|
|
44661
44993
|
tabIndex: 0,
|
|
44662
44994
|
"aria-expanded": opened,
|
|
@@ -44681,14 +45013,14 @@ const ExpandableUI = ({
|
|
|
44681
45013
|
toggleTo(false);
|
|
44682
45014
|
},
|
|
44683
45015
|
...rest,
|
|
44684
|
-
children: [jsx("span", {
|
|
45016
|
+
children: [marker === false ? null : jsx("span", {
|
|
44685
45017
|
className: "navi_expandable_marker",
|
|
44686
45018
|
"aria-hidden": "true",
|
|
44687
|
-
children: jsx(SummaryMarker, {
|
|
45019
|
+
children: marker === undefined ? jsx(SummaryMarker, {
|
|
44688
45020
|
open: opened,
|
|
44689
45021
|
loading: loading,
|
|
44690
|
-
openDirection:
|
|
44691
|
-
})
|
|
45022
|
+
openDirection: markerDirection
|
|
45023
|
+
}) : marker
|
|
44692
45024
|
}), jsx("div", {
|
|
44693
45025
|
className: "navi_expandable_ui_label",
|
|
44694
45026
|
children: typeof children === "function" ? children({
|
|
@@ -44699,8 +45031,9 @@ const ExpandableUI = ({
|
|
|
44699
45031
|
};
|
|
44700
45032
|
|
|
44701
45033
|
/**
|
|
44702
|
-
* The revealed part. With an `action` on the
|
|
44703
|
-
* function `(data) => ui` or a branches object —
|
|
45034
|
+
* The revealed part, a Box like the UI part. With an `action` on the
|
|
45035
|
+
* Expandable, children may be a function `(data) => ui` or a branches object —
|
|
45036
|
+
* see ActionRenderer.
|
|
44704
45037
|
*
|
|
44705
45038
|
* @type {import("ignore:preact").FunctionComponent<{}>}
|
|
44706
45039
|
*/
|
|
@@ -44713,9 +45046,24 @@ const ExpandableContent = ({
|
|
|
44713
45046
|
contentMounted,
|
|
44714
45047
|
hasAction,
|
|
44715
45048
|
effectiveAction,
|
|
45049
|
+
applyOpenedToContent,
|
|
44716
45050
|
contentContainerRef,
|
|
44717
45051
|
contentId
|
|
44718
45052
|
} = useExpandableContext("Content");
|
|
45053
|
+
|
|
45054
|
+
// The focus move and the reveal are the root's, but they measure the content
|
|
45055
|
+
// and can only run once it is in the DOM — which is this commit, the one
|
|
45056
|
+
// that rendered it. Skipped on mount: nothing has changed yet, and an
|
|
45057
|
+
// expandable that was simply already open must neither animate nor take the
|
|
45058
|
+
// focus.
|
|
45059
|
+
const isFirstOpenedRunRef = useRef(true);
|
|
45060
|
+
useLayoutEffect(() => {
|
|
45061
|
+
if (isFirstOpenedRunRef.current) {
|
|
45062
|
+
isFirstOpenedRunRef.current = false;
|
|
45063
|
+
return undefined;
|
|
45064
|
+
}
|
|
45065
|
+
return applyOpenedToContent();
|
|
45066
|
+
}, [opened]);
|
|
44719
45067
|
let content = children;
|
|
44720
45068
|
if (hasAction) {
|
|
44721
45069
|
content = jsx(ActionRenderer, {
|
|
@@ -44723,10 +45071,10 @@ const ExpandableContent = ({
|
|
|
44723
45071
|
children: children
|
|
44724
45072
|
});
|
|
44725
45073
|
}
|
|
44726
|
-
return jsx(
|
|
45074
|
+
return jsx(Box, {
|
|
44727
45075
|
ref: contentContainerRef,
|
|
44728
45076
|
id: contentId,
|
|
44729
|
-
|
|
45077
|
+
baseClassName: "navi_expandable_content_container",
|
|
44730
45078
|
inert: opened ? undefined : true,
|
|
44731
45079
|
...rest,
|
|
44732
45080
|
children: jsx("div", {
|
|
@@ -59776,7 +60124,7 @@ const PickerCustom = props => {
|
|
|
59776
60124
|
// could then never form. So the picker steps back and opens on the click,
|
|
59777
60125
|
// which the browser only delivers if the press stayed a press (a gesture
|
|
59778
60126
|
// swallows the click it leaves behind).
|
|
59779
|
-
const
|
|
60127
|
+
const interactionsDispute = interactionsDisputeThePress(props.interactions);
|
|
59780
60128
|
Object.assign(pickerProps, {
|
|
59781
60129
|
eventReactionDefinitions: {
|
|
59782
60130
|
mouseDown: e => {
|
|
@@ -59795,7 +60143,14 @@ const PickerCustom = props => {
|
|
|
59795
60143
|
})
|
|
59796
60144
|
};
|
|
59797
60145
|
}
|
|
59798
|
-
|
|
60146
|
+
// The same dispute, said by a box AROUND the picker rather than
|
|
60147
|
+
// by the picker itself: a page that travels between tabs under the
|
|
60148
|
+
// finger, a panel that swipes closed, a card carried out of a
|
|
60149
|
+
// list. Asked of the DOM here rather than of the props at render,
|
|
60150
|
+
// because that is where such a box says what it travels by — and
|
|
60151
|
+
// asked at every press, since what the picker sits in is not the
|
|
60152
|
+
// picker's to know at mount.
|
|
60153
|
+
if (interactionsDispute || isPressDisputedByDrag(e.target)) {
|
|
59799
60154
|
return null;
|
|
59800
60155
|
}
|
|
59801
60156
|
return {
|
|
@@ -59814,7 +60169,7 @@ const PickerCustom = props => {
|
|
|
59814
60169
|
}
|
|
59815
60170
|
// When a label is clicked it transfers focus to the select
|
|
59816
60171
|
// in that case we want to open it (otherwise we have already opened on mousedown interaction)
|
|
59817
|
-
// And when a gesture disputes the press (see
|
|
60172
|
+
// And when a gesture disputes the press (see the two disputes
|
|
59818
60173
|
// above), this is where the picker opens for real.
|
|
59819
60174
|
return {
|
|
59820
60175
|
name: e.detail === 0 ? "click (keyboard or progammatic) to open picker" : "click to open picker",
|
|
@@ -68517,7 +68872,18 @@ const PickerInput = props => {
|
|
|
68517
68872
|
as: "input",
|
|
68518
68873
|
...props,
|
|
68519
68874
|
readOnly: readOnlyForced ? true : readOnly,
|
|
68520
|
-
"data-readonly-forced": readOnlyForced ? "" : undefined
|
|
68875
|
+
"data-readonly-forced": readOnlyForced ? "" : undefined
|
|
68876
|
+
// An <input> by tag and a door by nature: this one opens a popup on the
|
|
68877
|
+
// press and reads nothing at all as the pointer moves — no caret dragged
|
|
68878
|
+
// through it (the press selects the whole value and preventDefaults, see
|
|
68879
|
+
// useAutoSelectReadOnly), no content of its own to scroll. So the gesture
|
|
68880
|
+
// readers must not treat it as the field it looks like: without this, a
|
|
68881
|
+
// box that travels by drag refuses to travel from a picker, which is a
|
|
68882
|
+
// hole under the finger in the middle of a page (see PRESS_ONLY_ATTRIBUTE
|
|
68883
|
+
// in @jsenv/dom's drag_to_travel.js).
|
|
68884
|
+
,
|
|
68885
|
+
|
|
68886
|
+
"data-press-only": "",
|
|
68521
68887
|
ui: undefined,
|
|
68522
68888
|
className: "navi_picker_input",
|
|
68523
68889
|
pseudoClasses: PickerInputPseudoClasses,
|
|
@@ -80728,5 +81094,5 @@ const UserSvg = () => jsx("svg", {
|
|
|
80728
81094
|
})
|
|
80729
81095
|
});
|
|
80730
81096
|
|
|
80731
|
-
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, CalloutStatusIcon, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, ControlSwap, 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, OfflineError, 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, TimeRange, 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, isOfflineError, isRowSelected, isScrolling, isToday, languagesSignal, localStorageSignal, markErrorAsDisplayedBy, moveArrayItemByIndex, moveFocusTo, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, scrollActivitySignal, setBaseUrl, setNetworkPolicy, 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, useNetworkPolicyReason, useOrderedColumns, usePopupMode, useRouteStatus, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideContainer, useSlideValue, useStateArray, useTitleLevel, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
|
|
81097
|
+
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, CalloutStatusIcon, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, ControlSwap, 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, OfflineError, 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, TimeRange, 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, isOfflineError, isRowSelected, isScrolling, isToday, languagesSignal, localStorageSignal, markErrorAsDisplayedBy, moveArrayItemByIndex, moveFocusTo, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, scrollActivitySignal, setBaseUrl, setNetworkPolicy, 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, useNetworkPolicyReason, useOrderedColumns, usePopupMode, useRouteStatus, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideContainer, useSlideValue, useStateArray, useTitleLevel, useTransitionCover, useUrlSearchParam, useUrlTargetId, valueInLocalStorage, windowWidthSignal };
|
|
80732
81098
|
//# sourceMappingURL=jsenv_navi.js.map
|