@jsenv/navi 0.29.4 → 0.29.5
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 +133 -45
- package/dist/jsenv_navi.js.map +8 -7
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -6422,6 +6422,16 @@ const applyOnTwoProps = (propA, propB) => {
|
|
|
6422
6422
|
};
|
|
6423
6423
|
};
|
|
6424
6424
|
|
|
6425
|
+
// How much of the free space an expanding item claims next to its siblings:
|
|
6426
|
+
// expand={30} between four expand={18} is the wide one in the middle. A bare
|
|
6427
|
+
// `expand` claims one share, like everyone else asking for their part.
|
|
6428
|
+
const expandWeight = (value) => {
|
|
6429
|
+
if (value === true || value === "") {
|
|
6430
|
+
return 1;
|
|
6431
|
+
}
|
|
6432
|
+
return value;
|
|
6433
|
+
};
|
|
6434
|
+
|
|
6425
6435
|
const LAYOUT_PROPS = {
|
|
6426
6436
|
// all are handled by navi-attributes
|
|
6427
6437
|
inline: () => {},
|
|
@@ -6529,7 +6539,7 @@ const DIMENSION_PROPS = {
|
|
|
6529
6539
|
return { flexGrow: 1 };
|
|
6530
6540
|
}
|
|
6531
6541
|
// Parent is flex-x: grow as flex item
|
|
6532
|
-
return { flexGrow:
|
|
6542
|
+
return { flexGrow: expandWeight(value), flexBasis: "0%" };
|
|
6533
6543
|
}
|
|
6534
6544
|
if (parentBoxFlow === "flex-y" || parentBoxFlow === "inline-flex-y") {
|
|
6535
6545
|
return {
|
|
@@ -6553,7 +6563,7 @@ const DIMENSION_PROPS = {
|
|
|
6553
6563
|
return { flexGrow: 1 };
|
|
6554
6564
|
}
|
|
6555
6565
|
// Parent is flex-y: grow as flex item
|
|
6556
|
-
return { flexGrow:
|
|
6566
|
+
return { flexGrow: expandWeight(value), flexBasis: "0%" };
|
|
6557
6567
|
}
|
|
6558
6568
|
if (parentBoxFlow === "flex-x" || parentBoxFlow === "inline-flex-x") {
|
|
6559
6569
|
return {
|
|
@@ -7834,6 +7844,11 @@ Object.assign(PSEUDO_CLASSES, {
|
|
|
7834
7844
|
":visited": {
|
|
7835
7845
|
attribute: "data-visited",
|
|
7836
7846
|
},
|
|
7847
|
+
// Written by whoever knows the current url — a Link from its href, a Button
|
|
7848
|
+
// from its route — so it lives here rather than with one of them.
|
|
7849
|
+
":-navi-href-current": {
|
|
7850
|
+
attribute: "data-href-current",
|
|
7851
|
+
},
|
|
7837
7852
|
});
|
|
7838
7853
|
const definePseudoClass = (pseudoClass, definition) => {
|
|
7839
7854
|
PSEUDO_CLASSES[pseudoClass] = definition;
|
|
@@ -30354,9 +30369,6 @@ Object.assign(PSEUDO_CLASSES, {
|
|
|
30354
30369
|
},
|
|
30355
30370
|
":-navi-href-anchor": {
|
|
30356
30371
|
attribute: "data-href-anchor"
|
|
30357
|
-
},
|
|
30358
|
-
":-navi-href-current": {
|
|
30359
|
-
attribute: "data-href-current"
|
|
30360
30372
|
}
|
|
30361
30373
|
});
|
|
30362
30374
|
|
|
@@ -31958,15 +31970,16 @@ installImportMetaCssBuild(import.meta);/**
|
|
|
31958
31970
|
* 2. **It gives its space back.** Being fixed it covers the content: without a
|
|
31959
31971
|
* reserve the end of a long page stays under it, unreachable. It publishes
|
|
31960
31972
|
* what it takes on <html> — see fixed_bar_space.js.
|
|
31961
|
-
* 3. **It reaches under the notch.** `env(safe-area-inset-*)`
|
|
31962
|
-
* content in while the background keeps running to the edge of
|
|
31963
|
-
*
|
|
31964
|
-
*
|
|
31965
|
-
*
|
|
31966
|
-
*
|
|
31967
|
-
*
|
|
31968
|
-
*
|
|
31969
|
-
* out of
|
|
31973
|
+
* 3. **It reaches under the notch.** `env(safe-area-inset-*)` is padding, so
|
|
31974
|
+
* the content is pushed in while the background keeps running to the edge of
|
|
31975
|
+
* the screen. Across the bar that inset is added to `width`/`height` too, so
|
|
31976
|
+
* the size asked for is the size the content gets whatever the device does;
|
|
31977
|
+
* along the bar it adds to the padding asked for. Note that every
|
|
31978
|
+
* `env(safe-area-inset-*)` is 0 unless the page asks for it:
|
|
31979
|
+
* `<meta name="viewport" content="…, viewport-fit=cover">`.
|
|
31980
|
+
* 4. **Its hairline is a box-shadow, not a border.** A real border would eat
|
|
31981
|
+
* into the size; a box-shadow draws the identical line and stays out of
|
|
31982
|
+
* layout.
|
|
31970
31983
|
*/
|
|
31971
31984
|
const css$M = /* css */`
|
|
31972
31985
|
@layer navi {
|
|
@@ -31977,11 +31990,11 @@ const css$M = /* css */`
|
|
|
31977
31990
|
--navi-fixed-bar-background: var(--navi-surface-color);
|
|
31978
31991
|
--navi-fixed-bar-border-width: 1px;
|
|
31979
31992
|
--navi-fixed-bar-border-color: var(--navi-separator-color-default);
|
|
31980
|
-
/* Along the bar only
|
|
31981
|
-
|
|
31982
|
-
|
|
31983
|
-
|
|
31984
|
-
--navi-fixed-bar-padding:
|
|
31993
|
+
/* Along the bar only — across it there is nothing to add, that direction
|
|
31994
|
+
is what the width/height prop names. None by default: a row of items
|
|
31995
|
+
sharing the whole strip is as common as a toolbar wanting air at its
|
|
31996
|
+
ends, and only the second can ask. */
|
|
31997
|
+
--navi-fixed-bar-padding: 0px;
|
|
31985
31998
|
}
|
|
31986
31999
|
}
|
|
31987
32000
|
|
|
@@ -31991,58 +32004,69 @@ const css$M = /* css */`
|
|
|
31991
32004
|
position: fixed;
|
|
31992
32005
|
z-index: 1;
|
|
31993
32006
|
display: flex;
|
|
31994
|
-
|
|
31995
|
-
stays bare and the safe-area padding adds OUTSIDE it, so a bar asked for
|
|
31996
|
-
56px still shows 56px of bar under the notch instead of 56px minus it. */
|
|
31997
|
-
box-sizing: content-box;
|
|
32007
|
+
box-sizing: border-box;
|
|
31998
32008
|
margin: auto;
|
|
31999
32009
|
align-items: center;
|
|
32000
32010
|
background: var(--navi-fixed-bar-background);
|
|
32001
32011
|
|
|
32012
|
+
/* Along the bar, the two insets that can bite into it there are added to
|
|
32013
|
+
the padding asked for: in landscape the notch is on a side, and a top bar
|
|
32014
|
+
whose padding ignored it would put its first item under it. */
|
|
32002
32015
|
&[data-area="top"],
|
|
32003
32016
|
&[data-area="bottom"] {
|
|
32004
32017
|
right: 0;
|
|
32005
32018
|
left: 0;
|
|
32006
32019
|
/* No width of its own: pinned to both edges, the used width absorbs the
|
|
32007
|
-
padding instead of being inflated by it
|
|
32008
|
-
|
|
32009
|
-
margins re-center it. */
|
|
32020
|
+
padding instead of being inflated by it. max-width then narrows it and
|
|
32021
|
+
the auto margins re-center it. */
|
|
32010
32022
|
max-width: var(--navi-fixed-bar-max-width);
|
|
32011
|
-
|
|
32012
|
-
|
|
32013
|
-
|
|
32023
|
+
padding-right: calc(
|
|
32024
|
+
var(--navi-fixed-bar-padding) + env(safe-area-inset-right)
|
|
32025
|
+
);
|
|
32026
|
+
padding-left: calc(
|
|
32027
|
+
var(--navi-fixed-bar-padding) + env(safe-area-inset-left)
|
|
32028
|
+
);
|
|
32014
32029
|
}
|
|
32015
32030
|
&[data-area="left"],
|
|
32016
32031
|
&[data-area="right"] {
|
|
32017
32032
|
top: 0;
|
|
32018
32033
|
bottom: 0;
|
|
32019
|
-
|
|
32020
|
-
|
|
32021
|
-
|
|
32034
|
+
padding-top: calc(
|
|
32035
|
+
var(--navi-fixed-bar-padding) + env(safe-area-inset-top)
|
|
32036
|
+
);
|
|
32037
|
+
padding-bottom: calc(
|
|
32038
|
+
var(--navi-fixed-bar-padding) + env(safe-area-inset-bottom)
|
|
32039
|
+
);
|
|
32022
32040
|
flex-direction: column;
|
|
32023
32041
|
}
|
|
32024
32042
|
|
|
32025
|
-
/*
|
|
32043
|
+
/* Across the bar, the inset of the edge it is pinned to is padding AND is
|
|
32044
|
+
added to the size: the background then runs under the notch while the
|
|
32045
|
+
content keeps the whole width/height asked for. */
|
|
32026
32046
|
&[data-area="top"] {
|
|
32027
32047
|
top: 0;
|
|
32048
|
+
height: calc(var(--navi-fixed-bar-height) + env(safe-area-inset-top));
|
|
32028
32049
|
padding-top: env(safe-area-inset-top);
|
|
32029
32050
|
box-shadow: 0 var(--navi-fixed-bar-border-width) 0
|
|
32030
32051
|
var(--navi-fixed-bar-border-color);
|
|
32031
32052
|
}
|
|
32032
32053
|
&[data-area="bottom"] {
|
|
32033
32054
|
bottom: 0;
|
|
32055
|
+
height: calc(var(--navi-fixed-bar-height) + env(safe-area-inset-bottom));
|
|
32034
32056
|
padding-bottom: env(safe-area-inset-bottom);
|
|
32035
32057
|
box-shadow: 0 calc(-1 * var(--navi-fixed-bar-border-width)) 0
|
|
32036
32058
|
var(--navi-fixed-bar-border-color);
|
|
32037
32059
|
}
|
|
32038
32060
|
&[data-area="left"] {
|
|
32039
32061
|
left: 0;
|
|
32062
|
+
width: calc(var(--navi-fixed-bar-width) + env(safe-area-inset-left));
|
|
32040
32063
|
padding-left: env(safe-area-inset-left);
|
|
32041
32064
|
box-shadow: var(--navi-fixed-bar-border-width) 0 0
|
|
32042
32065
|
var(--navi-fixed-bar-border-color);
|
|
32043
32066
|
}
|
|
32044
32067
|
&[data-area="right"] {
|
|
32045
32068
|
right: 0;
|
|
32069
|
+
width: calc(var(--navi-fixed-bar-width) + env(safe-area-inset-right));
|
|
32046
32070
|
padding-right: env(safe-area-inset-right);
|
|
32047
32071
|
box-shadow: calc(-1 * var(--navi-fixed-bar-border-width)) 0 0
|
|
32048
32072
|
var(--navi-fixed-bar-border-color);
|
|
@@ -32053,6 +32077,11 @@ const css$M = /* css */`
|
|
|
32053
32077
|
}
|
|
32054
32078
|
`;
|
|
32055
32079
|
const FixedBarStyleCSSVars = {
|
|
32080
|
+
// width/height go through the vars the size calc reads: written as plain
|
|
32081
|
+
// inline styles they would land on the border box and the safe-area inset
|
|
32082
|
+
// would eat into the size asked for.
|
|
32083
|
+
width: "--navi-fixed-bar-width",
|
|
32084
|
+
height: "--navi-fixed-bar-height",
|
|
32056
32085
|
maxWidth: "--navi-fixed-bar-max-width",
|
|
32057
32086
|
padding: "--navi-fixed-bar-padding",
|
|
32058
32087
|
background: "--navi-fixed-bar-background",
|
|
@@ -32076,8 +32105,8 @@ const FixedBarStyleCSSVars = {
|
|
|
32076
32105
|
* the window it is pinned to.
|
|
32077
32106
|
* @param {string|number} [props.height] - For a bar on the top or bottom
|
|
32078
32107
|
* @param {string|number} [props.width] - …and for one on a side. The safe-area
|
|
32079
|
-
* inset is NOT
|
|
32080
|
-
*
|
|
32108
|
+
* inset is NOT part of it: it is added on top, so the content keeps the size
|
|
32109
|
+
* asked for.
|
|
32081
32110
|
* @param {boolean} [props.border=true] - The hairline on the content side.
|
|
32082
32111
|
* Drawn with a box-shadow so it never eats into the size; give it a
|
|
32083
32112
|
* `borderWidth`/`borderColor`, or `border={false}` for none.
|
|
@@ -32095,10 +32124,10 @@ const FixedBar = ({
|
|
|
32095
32124
|
props.ref = props.ref || defaultRef;
|
|
32096
32125
|
// Whichever of width/height crosses the edge the bar sits on is what the
|
|
32097
32126
|
// content has to be given back — and the bar's border box already IS that:
|
|
32098
|
-
// the size it was given
|
|
32099
|
-
//
|
|
32100
|
-
//
|
|
32101
|
-
//
|
|
32127
|
+
// the size it was given plus the inset of that edge. Measured rather than
|
|
32128
|
+
// rebuilt as a calc() expression, so a size coming from anywhere — a prop, a
|
|
32129
|
+
// theme variable, the content itself — is reserved just the same, and each
|
|
32130
|
+
// `env()` inset stays the browser's business alone.
|
|
32102
32131
|
const vertical = area === "left" || area === "right";
|
|
32103
32132
|
const {
|
|
32104
32133
|
ref
|
|
@@ -35220,6 +35249,7 @@ const ButtonWithRoute = props => {
|
|
|
35220
35249
|
route,
|
|
35221
35250
|
routeParams,
|
|
35222
35251
|
children,
|
|
35252
|
+
pseudoState,
|
|
35223
35253
|
...rest
|
|
35224
35254
|
} = props;
|
|
35225
35255
|
const url = route.buildUrl(routeParams);
|
|
@@ -35228,9 +35258,15 @@ const ButtonWithRoute = props => {
|
|
|
35228
35258
|
} = useRouteStatus(route);
|
|
35229
35259
|
const paramsAreMatching = route.matchesParams(routeParams);
|
|
35230
35260
|
const linkMatching = matching && paramsAreMatching;
|
|
35261
|
+
|
|
35262
|
+
// Merged into whatever the caller already holds: a button can be forced into
|
|
35263
|
+
// a state for a demo and still learn its own current-ness from its route.
|
|
35231
35264
|
return jsx(Next, {
|
|
35232
35265
|
href: url,
|
|
35233
|
-
|
|
35266
|
+
pseudoState: {
|
|
35267
|
+
...pseudoState,
|
|
35268
|
+
":-navi-href-current": linkMatching
|
|
35269
|
+
},
|
|
35234
35270
|
...rest,
|
|
35235
35271
|
children: children || route.buildRelativeUrl(routeParams)
|
|
35236
35272
|
});
|
|
@@ -35272,6 +35308,11 @@ installImportMetaCssBuild(import.meta);const css$E = /* css */`
|
|
|
35272
35308
|
black
|
|
35273
35309
|
);
|
|
35274
35310
|
--button-color-hover: var(--button-color);
|
|
35311
|
+
/* Current: the button points at the page one is already on. Nothing by
|
|
35312
|
+
default — it is a nav item that wants to say so, not every button. */
|
|
35313
|
+
--button-border-color-current: var(--button-border-color);
|
|
35314
|
+
--button-background-color-current: var(--button-background-color);
|
|
35315
|
+
--button-color-current: var(--button-color);
|
|
35275
35316
|
/* Pressed */
|
|
35276
35317
|
--button-border-color-pressed: color-mix(
|
|
35277
35318
|
in srgb,
|
|
@@ -35315,6 +35356,13 @@ installImportMetaCssBuild(import.meta);const css$E = /* css */`
|
|
|
35315
35356
|
.navi_button {
|
|
35316
35357
|
--x-button-outline-offset: var(--button-outline-offset);
|
|
35317
35358
|
--x-button-border-color: var(--button-border-color);
|
|
35359
|
+
/* The shorthand wins over the parts when it is given, which is what makes
|
|
35360
|
+
border="none" remove the line: the parts alone can only ever describe
|
|
35361
|
+
a border, never the absence of one. */
|
|
35362
|
+
--x-button-border: var(
|
|
35363
|
+
--button-border,
|
|
35364
|
+
var(--button-border-width) solid var(--x-button-border-color)
|
|
35365
|
+
);
|
|
35318
35366
|
--x-button-background: var(--button-background);
|
|
35319
35367
|
--x-button-background-color: var(--button-background-color);
|
|
35320
35368
|
--x-button-color: var(--button-color);
|
|
@@ -35378,9 +35426,7 @@ installImportMetaCssBuild(import.meta);const css$E = /* css */`
|
|
|
35378
35426
|
--x-button-background-color,
|
|
35379
35427
|
var(--x-button-background)
|
|
35380
35428
|
);
|
|
35381
|
-
border
|
|
35382
|
-
border-style: solid;
|
|
35383
|
-
border-color: var(--x-button-border-color);
|
|
35429
|
+
border: var(--x-button-border);
|
|
35384
35430
|
border-radius: inherit;
|
|
35385
35431
|
outline-width: var(--button-outline-width);
|
|
35386
35432
|
outline-color: var(--button-outline-color);
|
|
@@ -35401,6 +35447,12 @@ installImportMetaCssBuild(import.meta);const css$E = /* css */`
|
|
|
35401
35447
|
}
|
|
35402
35448
|
}
|
|
35403
35449
|
|
|
35450
|
+
/* Current */
|
|
35451
|
+
&[data-href-current] {
|
|
35452
|
+
--x-button-border-color: var(--button-border-color-current);
|
|
35453
|
+
--x-button-background-color: var(--button-background-color-current);
|
|
35454
|
+
--x-button-color: var(--button-color-current);
|
|
35455
|
+
}
|
|
35404
35456
|
/* Hover */
|
|
35405
35457
|
&[data-hover] {
|
|
35406
35458
|
--x-button-border-color: var(--button-border-color-hover);
|
|
@@ -35547,6 +35599,21 @@ installImportMetaCssBuild(import.meta);const css$E = /* css */`
|
|
|
35547
35599
|
--x-button-background-color: transparent;
|
|
35548
35600
|
}
|
|
35549
35601
|
}
|
|
35602
|
+
/* Last word on the shrink, over whatever the variant decided: the variant
|
|
35603
|
+
guesses from how the button is drawn, and that guess is wrong as soon as
|
|
35604
|
+
the content is a box of its own — a discrete button holding a filled
|
|
35605
|
+
pill reads as a button being pressed, not as its content flinching. */
|
|
35606
|
+
&[data-press-effect="scale"][data-pressed] {
|
|
35607
|
+
.navi_button_content {
|
|
35608
|
+
transform: scale(0.9);
|
|
35609
|
+
}
|
|
35610
|
+
}
|
|
35611
|
+
&[data-press-effect="none"][data-pressed] {
|
|
35612
|
+
.navi_button_content {
|
|
35613
|
+
transform: none;
|
|
35614
|
+
}
|
|
35615
|
+
}
|
|
35616
|
+
|
|
35550
35617
|
&[data-icon] {
|
|
35551
35618
|
--button-padding: 0;
|
|
35552
35619
|
display: inline-flex;
|
|
@@ -35607,6 +35674,7 @@ const ButtonUI = props => {
|
|
|
35607
35674
|
rel,
|
|
35608
35675
|
// visual
|
|
35609
35676
|
variant,
|
|
35677
|
+
pressEffect,
|
|
35610
35678
|
icon,
|
|
35611
35679
|
cta,
|
|
35612
35680
|
spacing
|
|
@@ -35620,18 +35688,31 @@ const ButtonUI = props => {
|
|
|
35620
35688
|
children
|
|
35621
35689
|
} = buttonControlHostProps;
|
|
35622
35690
|
const loading = basePseudoState[":-navi-loading"];
|
|
35691
|
+
|
|
35692
|
+
// subscribe to document url to re-render and re-compute getHrefTargetInfo
|
|
35693
|
+
useDocumentUrl();
|
|
35623
35694
|
const isLink = href !== undefined;
|
|
35624
35695
|
let as = "button";
|
|
35625
35696
|
let innerTarget;
|
|
35626
35697
|
let innerRel;
|
|
35698
|
+
let innerCurrent;
|
|
35627
35699
|
if (isLink) {
|
|
35628
35700
|
as = "a";
|
|
35629
35701
|
const {
|
|
35630
|
-
isSameSite
|
|
35702
|
+
isSameSite,
|
|
35703
|
+
isCurrent
|
|
35631
35704
|
} = getHrefTargetInfo(href);
|
|
35632
35705
|
innerTarget = target === undefined ? isSameSite ? undefined : "_blank" : target;
|
|
35633
35706
|
innerRel = rel === undefined ? isSameSite ? undefined : "noopener noreferrer" : rel;
|
|
35707
|
+
innerCurrent = isCurrent;
|
|
35634
35708
|
}
|
|
35709
|
+
// For a button that has only an href: nothing else knows it points at the
|
|
35710
|
+
// page one is on. A route says so through `pseudoState`, which Box lays over
|
|
35711
|
+
// this one.
|
|
35712
|
+
buttonControlHostProps.basePseudoState = {
|
|
35713
|
+
...basePseudoState,
|
|
35714
|
+
":-navi-href-current": innerCurrent
|
|
35715
|
+
};
|
|
35635
35716
|
const visualSelector = ".navi_button_content";
|
|
35636
35717
|
useAccentColorAttributes(ref, null, {
|
|
35637
35718
|
elementSelector: visualSelector
|
|
@@ -35651,6 +35732,7 @@ const ButtonUI = props => {
|
|
|
35651
35732
|
type: "button",
|
|
35652
35733
|
spacing: undefined,
|
|
35653
35734
|
cta: undefined,
|
|
35735
|
+
pressEffect: undefined,
|
|
35654
35736
|
ref: ref,
|
|
35655
35737
|
as: as,
|
|
35656
35738
|
href: href,
|
|
@@ -35680,6 +35762,7 @@ const ButtonUI = props => {
|
|
|
35680
35762
|
e.preventDefault();
|
|
35681
35763
|
},
|
|
35682
35764
|
"data-variant": variant,
|
|
35765
|
+
"data-press-effect": pressEffect,
|
|
35683
35766
|
"data-icon": icon ? "" : undefined,
|
|
35684
35767
|
"data-cta": cta ? "" : undefined,
|
|
35685
35768
|
"data-callout-arrow-x": "center"
|
|
@@ -35741,6 +35824,11 @@ const ButtonStyleCSSVars = {
|
|
|
35741
35824
|
":-navi-pressed": {
|
|
35742
35825
|
borderColor: "--button-border-color-pressed"
|
|
35743
35826
|
},
|
|
35827
|
+
":-navi-href-current": {
|
|
35828
|
+
backgroundColor: "--button-background-color-current",
|
|
35829
|
+
borderColor: "--button-border-color-current",
|
|
35830
|
+
color: "--button-color-current"
|
|
35831
|
+
},
|
|
35744
35832
|
":read-only": {
|
|
35745
35833
|
backgroundColor: "--button-background-color-readonly",
|
|
35746
35834
|
borderColor: "--button-border-color-readonly",
|
|
@@ -35752,7 +35840,7 @@ const ButtonStyleCSSVars = {
|
|
|
35752
35840
|
color: "--button-color-disabled"
|
|
35753
35841
|
}
|
|
35754
35842
|
};
|
|
35755
|
-
const ButtonPseudoClasses = [":hover", ":active", ":-navi-pressed", ":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading"];
|
|
35843
|
+
const ButtonPseudoClasses = [":-navi-href-current", ":hover", ":active", ":-navi-pressed", ":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading"];
|
|
35756
35844
|
const ButtonPseudoElements = ["::-navi-loader"];
|
|
35757
35845
|
const ButtonShadow = () => {
|
|
35758
35846
|
return jsx("span", {
|