staffa 0.14.0 → 0.15.0
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/README.md +2 -2
- package/dist/components/dialog.js +1 -3
- package/dist/components/main.js +2 -47
- package/dist/components/menu.js +12 -13
- package/dist/components/panels.d.ts +11 -0
- package/dist/components/panels.js +30 -15
- package/dist/components/tabs.js +2 -5
- package/dist/components/toast.js +1 -3
- package/dist/components/tooltip.js +6 -12
- package/dist/core.d.ts +0 -15
- package/dist/core.js +0 -17
- package/dist/staffa.esm.js +1 -1
- package/package.json +1 -1
- package/src/components/dialog.ts +1 -3
- package/src/components/main.ts +2 -47
- package/src/components/menu.ts +11 -12
- package/src/components/panels.ts +34 -15
- package/src/components/tabs.ts +2 -5
- package/src/components/toast.ts +1 -3
- package/src/components/tooltip.ts +6 -12
- package/src/core.ts +0 -19
package/README.md
CHANGED
|
@@ -182,7 +182,7 @@ Navigating faster than the shell can settle is fine: closing travels through the
|
|
|
182
182
|
|
|
183
183
|
**The content area is the window**, minus the nav sidebar — or, when `S.main({ maxWidth })` says so, that much of it, centred. Either way it is the same width whatever is open, so the sidebar, the top bar and the footer never move.
|
|
184
184
|
|
|
185
|
-
The shell divides that area into columns: the narrowest whole number of them that keeps each one at least **360px** wide, and no column ever wider than **540**. A 1080px content area is three columns of 360; a 1520px one is four of 380; below 720px there is a single column — of at most 540, centred. `$panel.maxWidth` counts in those columns:
|
|
185
|
+
The shell divides that area into columns: the narrowest whole number of them that keeps each one at least **360px** wide, and no column ever wider than **540**. (A content area narrower than 360 still gets one column — just a narrower one.) A 1080px content area is three columns of 360; a 1520px one is four of 380; below 720px there is a single column — of at most 540, centred. `$panel.maxWidth` counts in those columns:
|
|
186
186
|
|
|
187
187
|
| `maxWidth` | How wide the panel gets | Good for |
|
|
188
188
|
| --- | --- | --- |
|
|
@@ -191,7 +191,7 @@ The shell divides that area into columns: the narrowest whole number of them tha
|
|
|
191
191
|
| `"large"` | Three columns — never above 1620px. | wide tables, dense forms |
|
|
192
192
|
| `"none"` | The whole content area, unbounded. | boards, dashboards |
|
|
193
193
|
|
|
194
|
-
The ask is a promise
|
|
194
|
+
The ask is a promise about the top end: the shell never draws a panel wider than its column count × 540px, and every size is also capped at the content area — so a draw function never has to look right past its own ceiling. At the bottom end there is no promise, because a window can be any width: aim your layout at **360px**, which is about the narrowest phone still in common use, and let it degrade gracefully below that (`min-width` on a fixed-size block, a table that has to scroll) rather than assuming a floor.
|
|
195
195
|
|
|
196
196
|
A column's width depends only on the size of the window, never on what else is open. So opening or closing a panel never resizes the ones already on screen, and never reflows what someone was reading. As many columns as fit are shown, ending at the current panel; when they don't fill the content area they sit centred in it, so an arriving column nudges the others over to share the room.
|
|
197
197
|
|
|
@@ -14,9 +14,7 @@ A.insertGlobalCss({
|
|
|
14
14
|
"&": "position:fixed z-index:200 top:50% left:50% " +
|
|
15
15
|
"display:flex flex-direction:column " +
|
|
16
16
|
"transform:translate(-50%,-50%) " +
|
|
17
|
-
|
|
18
|
-
// zoom (see `watchScale` in main.ts), and these caps mean the window.
|
|
19
|
-
"min-width:20rem max-width:min(calc(90vw/var(--s-zoom,1)),44rem) max-height:min(calc(88vh/var(--s-zoom,1)),800px) " +
|
|
17
|
+
"min-width:min(20rem,90vw) max-width:min(90vw,44rem) max-height:min(88vh,800px) " +
|
|
20
18
|
"r: $s-radius-lg; overflow:hidden " +
|
|
21
19
|
"transition: opacity 0.2s ease-out, transform 0.2s ease-out;",
|
|
22
20
|
"> header": "display:flex align-items:center gap:$2 padding: $2 $3; " +
|
package/dist/components/main.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import A from "aberdeen";
|
|
2
2
|
import { current as currentRoute } from "aberdeen/route";
|
|
3
|
-
import { drawSlot, focusFirst, NARROW_PX
|
|
3
|
+
import { drawSlot, focusFirst, NARROW_PX } from "../core.js";
|
|
4
4
|
import { drawMenu, isFloatingMenuOpen, consumeBranchNav, anyCurrent } from "./menu.js";
|
|
5
5
|
// The shell's own chrome glyphs, from the same Lucide set an app draws with —
|
|
6
6
|
// so a nav trigger sits beside app icons as an equal. Named imports, so a
|
|
@@ -14,9 +14,7 @@ const NAV_W = 200;
|
|
|
14
14
|
A.insertGlobalCss({
|
|
15
15
|
".s-main": {
|
|
16
16
|
// container-type so @container queries below can respond to shell width.
|
|
17
|
-
|
|
18
|
-
// zoom (see `watchScale`), and this height means the window.
|
|
19
|
-
"&": "display:flex flex-direction:column min-height:calc(100vh/var(--s-zoom,1)) max-height:calc(100vh/var(--s-zoom,1)) container-type:inline-size",
|
|
17
|
+
"&": "display:flex flex-direction:column min-height:100vh max-height:100vh container-type:inline-size",
|
|
20
18
|
// <body> carries a default $3 padding; when the shell is a direct child of it,
|
|
21
19
|
// cancel that padding with matching negative margins so the chrome still spans
|
|
22
20
|
// edge to edge (and the 100vh sizing stays exact).
|
|
@@ -336,7 +334,6 @@ export function main(opts = {}) {
|
|
|
336
334
|
});
|
|
337
335
|
});
|
|
338
336
|
watchNarrow(root, $shell);
|
|
339
|
-
watchScale();
|
|
340
337
|
// Escape peels back a panel of UI, and finally jumps to the navigation: into
|
|
341
338
|
// the sidebar's current item when the sidebar is showing, or — when it has
|
|
342
339
|
// collapsed to the ☰ — open the full-page nav, which focuses its current item.
|
|
@@ -468,48 +465,6 @@ function taglineFits(ctl, nav, $shell) {
|
|
|
468
465
|
return false;
|
|
469
466
|
return anyCurrent(nav.items);
|
|
470
467
|
}
|
|
471
|
-
/** How many mounted shells are watching the window; the listener is one per page. */
|
|
472
|
-
let scaleShells = 0;
|
|
473
|
-
/** Lay the page out at a virtual {@link MIN_PX} and zoom it down to the window. */
|
|
474
|
-
function applyScale() {
|
|
475
|
-
// The real window width: <html> is never zoomed, so this stays unscaled.
|
|
476
|
-
const w = document.documentElement.clientWidth;
|
|
477
|
-
const f = w && w < MIN_PX ? w / MIN_PX : 0;
|
|
478
|
-
document.body.style.zoom = f ? String(f) : "";
|
|
479
|
-
// Published for the vh/vw lengths in the library's CSS, which zoom shrinks
|
|
480
|
-
// and a `/var(--s-zoom,1)` restores to meaning the window.
|
|
481
|
-
if (f)
|
|
482
|
-
document.body.style.setProperty("--s-zoom", String(f));
|
|
483
|
-
else
|
|
484
|
-
document.body.style.removeProperty("--s-zoom");
|
|
485
|
-
}
|
|
486
|
-
/**
|
|
487
|
-
* Below {@link MIN_PX} of window the shell stops squeezing and starts scaling:
|
|
488
|
-
* the page keeps its {@link MIN_PX} layout and CSS `zoom` shrinks it to fit,
|
|
489
|
-
* so a 180px window shows the 360px layout at half size. The zoom goes on
|
|
490
|
-
* `<body>`, so the overlays that portal there — dialogs, menus, toasts,
|
|
491
|
-
* tooltips — scale with the shell. `zoom` rather than `transform:scale`,
|
|
492
|
-
* because zoom keeps layout, container queries and the top layer in one
|
|
493
|
-
* system; what it splits instead is coordinate spaces — window-space rects
|
|
494
|
-
* against element-space lengths — which the few places mixing those bridge
|
|
495
|
-
* with {@link cssZoom}, and vh/vw lengths with `--s-zoom` (see `applyScale`).
|
|
496
|
-
* Browsers that predate `currentCSSZoom` (mid-2024) keep the squeeze.
|
|
497
|
-
*/
|
|
498
|
-
function watchScale() {
|
|
499
|
-
if (typeof window === "undefined" || !("currentCSSZoom" in document.documentElement))
|
|
500
|
-
return;
|
|
501
|
-
if (++scaleShells === 1) {
|
|
502
|
-
window.addEventListener("resize", applyScale);
|
|
503
|
-
applyScale();
|
|
504
|
-
}
|
|
505
|
-
A.clean(() => {
|
|
506
|
-
if (--scaleShells === 0) {
|
|
507
|
-
window.removeEventListener("resize", applyScale);
|
|
508
|
-
document.body.style.zoom = "";
|
|
509
|
-
document.body.style.removeProperty("--s-zoom");
|
|
510
|
-
}
|
|
511
|
-
});
|
|
512
|
-
}
|
|
513
468
|
/**
|
|
514
469
|
* Track whether the shell is narrow, for everything that has to agree about it.
|
|
515
470
|
*
|
package/dist/components/menu.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import A from "aberdeen";
|
|
2
2
|
import { matchCurrent, current as currentRoute, go } from "aberdeen/route";
|
|
3
|
-
import {
|
|
3
|
+
import { drawSlot, mountPortal, focusFirst } from "../core.js";
|
|
4
4
|
import { menu as menuIcon, chevronRight, externalLink as newTabIcon, link as linkIcon } from "../icons.js";
|
|
5
5
|
import { button } from "./button.js";
|
|
6
6
|
import { toast } from "./toast.js";
|
|
@@ -17,7 +17,11 @@ A.insertGlobalCss({
|
|
|
17
17
|
// invisible yet still hittable by tests and read by assistive tech.
|
|
18
18
|
".s-menu-list": "position:fixed z-index:350 min-width:10rem display:flex flex-direction:column p:$1 " +
|
|
19
19
|
"r:$s-radius-lg " +
|
|
20
|
-
|
|
20
|
+
// The 16px off max-width is the 8px gap `positionMenu` leaves at either
|
|
21
|
+
// window edge: in a window too narrow for the menu, it narrows rather
|
|
22
|
+
// than hanging off the screen. (A `min-width` from the caller still wins,
|
|
23
|
+
// as CSS says it must — that ask is the app's to keep sensible.)
|
|
24
|
+
"max-width: calc(100vw - 16px); overflow-y:auto max-height:min(80vh,28rem) " +
|
|
21
25
|
"transition: opacity 0.15s, transform 0.15s, visibility 0.15s;",
|
|
22
26
|
".s-menu-list.hidden": "opacity:0 pointer-events:none transform:translateY(-6px) visibility:hidden",
|
|
23
27
|
// One class for both the `<a>` (link) and `<button>` forms — they look
|
|
@@ -396,20 +400,15 @@ export function closeFloatingMenu(anchor) {
|
|
|
396
400
|
closeFloating();
|
|
397
401
|
}
|
|
398
402
|
function positionMenu(menuEl, rect) {
|
|
399
|
-
// The rect arrives in window coordinates (an anchor's rect, or a pointer
|
|
400
|
-
// position); the left/top set below live in the menu's own space. The two
|
|
401
|
-
// differ when the shell has zoomed the page (see `watchScale` in main.ts),
|
|
402
|
-
// so everything is brought into the menu's space first.
|
|
403
|
-
const z = cssZoom(menuEl);
|
|
404
403
|
const mw = menuEl.offsetWidth, mh = menuEl.offsetHeight;
|
|
405
|
-
const vw = window.innerWidth
|
|
404
|
+
const vw = window.innerWidth, vh = window.innerHeight;
|
|
406
405
|
const gap = 4;
|
|
407
|
-
let x = rect.left
|
|
406
|
+
let x = rect.left;
|
|
408
407
|
if (x + mw > vw - 8)
|
|
409
|
-
x = Math.max(8, rect.right
|
|
410
|
-
let y = rect.bottom
|
|
411
|
-
if (y + mh > vh - 8 && rect.top
|
|
412
|
-
y = rect.top
|
|
408
|
+
x = Math.max(8, rect.right - mw);
|
|
409
|
+
let y = rect.bottom + gap;
|
|
410
|
+
if (y + mh > vh - 8 && rect.top - mh - gap >= 8)
|
|
411
|
+
y = rect.top - mh - gap;
|
|
413
412
|
menuEl.style.left = Math.max(8, x) + "px";
|
|
414
413
|
menuEl.style.top = Math.max(8, y) + "px";
|
|
415
414
|
}
|
|
@@ -184,6 +184,10 @@ export interface Panel<P = Record<string, string | number | string[]>> {
|
|
|
184
184
|
* window, never on what else is open, so opening or closing a panel never
|
|
185
185
|
* resizes another — the run of columns just recentres in the area.
|
|
186
186
|
*
|
|
187
|
+
* The ask is a ceiling only; there is no matching floor, since the window can
|
|
188
|
+
* be any width. Aim your layout at 360px — about the narrowest phone still in
|
|
189
|
+
* common use — and let it degrade gracefully below that.
|
|
190
|
+
*
|
|
187
191
|
* Ask only for what your content can actually use: a panel that would cap
|
|
188
192
|
* its own content narrower than its ask is holding room that would have
|
|
189
193
|
* let another column fit beside it.
|
|
@@ -734,6 +738,13 @@ export declare class PanelStackController implements PanelStack {
|
|
|
734
738
|
*/
|
|
735
739
|
private drawActions;
|
|
736
740
|
scheduleLayout(): void;
|
|
741
|
+
/**
|
|
742
|
+
* Run the pending layout pass now, rather than on the frame it is waiting
|
|
743
|
+
* for. For the callers that have to *read* what only the pass knows —
|
|
744
|
+
* `$panel.visible`, `$panel.width` — at a moment when waiting isn't an
|
|
745
|
+
* option. Does nothing when no pass is owed.
|
|
746
|
+
*/
|
|
747
|
+
private flushLayout;
|
|
737
748
|
/**
|
|
738
749
|
* Measure the content area, and with it the width a panel of each size gets.
|
|
739
750
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import A, { OPAQUE } from "aberdeen";
|
|
2
2
|
import * as route from "aberdeen/route";
|
|
3
|
-
import { drawSlot
|
|
3
|
+
import { drawSlot } from "../core.js";
|
|
4
4
|
import { circle as dotIcon, pin as pinIcon, pinOff as pinOffIcon, slash as sepIcon, x as closeIcon, } from "../icons.js";
|
|
5
5
|
import { PANEL_SHEEN } from "../theme.js";
|
|
6
6
|
import { addContextMenu } from "./menu.js";
|
|
@@ -122,13 +122,15 @@ const PAGE_MS = 250;
|
|
|
122
122
|
/** How long a freshly pushed `loading` panel holds its enter animation. */
|
|
123
123
|
const LOADING_HOLD_MS = 300;
|
|
124
124
|
/**
|
|
125
|
-
* The bounds of a column. At least 360px — the phone
|
|
126
|
-
*
|
|
127
|
-
* never reaches (`area / floor(area /
|
|
128
|
-
* lone column of a 540–720px area to it
|
|
129
|
-
* makes an ask's ceiling uniform: never
|
|
125
|
+
* The bounds of a column. At least 360px — about the narrowest phone still in
|
|
126
|
+
* common use, so it is where a panel's layout is aimed. And at most 540: that
|
|
127
|
+
* is the width the multi-column regime never reaches (`area / floor(area /
|
|
128
|
+
* 360)` stays under it), so capping the lone column of a 540–720px area to it
|
|
129
|
+
* too — centred, rather than stretched — makes an ask's ceiling uniform: never
|
|
130
|
+
* wider than its column count × 540. A content area narrower than 360 still
|
|
131
|
+
* gets its single column, just narrower than the minimum.
|
|
130
132
|
*/
|
|
131
|
-
const SMALL_MIN_PX =
|
|
133
|
+
const SMALL_MIN_PX = 360;
|
|
132
134
|
export const SMALL_MAX_PX = 540;
|
|
133
135
|
/**
|
|
134
136
|
* Panels are layered by their depth in the stack, two `z-index` steps per panel:
|
|
@@ -1190,6 +1192,13 @@ export class PanelStackController {
|
|
|
1190
1192
|
// otherwise. A confirmed leave unloads the document before any of it
|
|
1191
1193
|
// is seen; the history entry the move makes is then where a back
|
|
1192
1194
|
// navigation returns to, which is right: the panel that held the tab.
|
|
1195
|
+
// `visible` is written by the layout pass, which waits for an animation
|
|
1196
|
+
// frame — and the frame owed to the navigation that parked this panel
|
|
1197
|
+
// may not have landed, all the more so in a tab on its way out, which
|
|
1198
|
+
// may never paint again. Settle it first, or a panel parked a moment
|
|
1199
|
+
// ago still reads as on screen and the guard skips the very move it
|
|
1200
|
+
// exists to make.
|
|
1201
|
+
this.flushLayout();
|
|
1193
1202
|
if (!dirty.$panel.visible)
|
|
1194
1203
|
void this.focusAt(this.intended().stack.indexOf(dirty.path));
|
|
1195
1204
|
};
|
|
@@ -1326,10 +1335,19 @@ export class PanelStackController {
|
|
|
1326
1335
|
if (this.layoutQueued)
|
|
1327
1336
|
return;
|
|
1328
1337
|
this.layoutQueued = true;
|
|
1329
|
-
requestAnimationFrame(() =>
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1338
|
+
requestAnimationFrame(() => this.flushLayout());
|
|
1339
|
+
}
|
|
1340
|
+
/**
|
|
1341
|
+
* Run the pending layout pass now, rather than on the frame it is waiting
|
|
1342
|
+
* for. For the callers that have to *read* what only the pass knows —
|
|
1343
|
+
* `$panel.visible`, `$panel.width` — at a moment when waiting isn't an
|
|
1344
|
+
* option. Does nothing when no pass is owed.
|
|
1345
|
+
*/
|
|
1346
|
+
flushLayout() {
|
|
1347
|
+
if (!this.layoutQueued)
|
|
1348
|
+
return;
|
|
1349
|
+
this.layoutQueued = false;
|
|
1350
|
+
this.layout();
|
|
1333
1351
|
}
|
|
1334
1352
|
/**
|
|
1335
1353
|
* Measure the content area, and with it the width a panel of each size gets.
|
|
@@ -1356,10 +1374,7 @@ export class PanelStackController {
|
|
|
1356
1374
|
*/
|
|
1357
1375
|
measure() {
|
|
1358
1376
|
const el = this.containerEl;
|
|
1359
|
-
|
|
1360
|
-
// back as CSS lengths, which live in the region's own space — different
|
|
1361
|
-
// spaces when the shell has zoomed the page (see `watchScale` in main.ts).
|
|
1362
|
-
const area = el ? el.getBoundingClientRect().width / cssZoom(el) : 0;
|
|
1377
|
+
const area = el ? el.getBoundingClientRect().width : 0;
|
|
1363
1378
|
if (!area)
|
|
1364
1379
|
return undefined;
|
|
1365
1380
|
const small = Math.min(area / Math.max(1, Math.floor(area / SMALL_MIN_PX)), SMALL_MAX_PX);
|
package/dist/components/tabs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import A from "aberdeen";
|
|
2
|
-
import {
|
|
2
|
+
import { drawSlot, uniqueId } from "../core.js";
|
|
3
3
|
import { mk } from "../icons-helpers.js";
|
|
4
4
|
// Chevrons for the scroll buttons, as inline SVG (the icon set's own helper, so
|
|
5
5
|
// no icon data comes along) rather than `‹`/`›` characters — matching Lucide's
|
|
@@ -97,11 +97,8 @@ export function revealInStrip(el) {
|
|
|
97
97
|
// The overlays are 2.4em wide; clearing a little more than that keeps the
|
|
98
98
|
// revealed item from sitting right against one.
|
|
99
99
|
const pad = parseFloat(getComputedStyle(row).fontSize) * 2.6;
|
|
100
|
-
// The rects are in window coordinates while `scrollBy` counts in the row's
|
|
101
|
-
// own space; their difference scales over by the row's zoom (see `cssZoom`).
|
|
102
|
-
const z = cssZoom(row);
|
|
103
100
|
const box = el.getBoundingClientRect(), strip = row.getBoundingClientRect();
|
|
104
|
-
const left =
|
|
101
|
+
const left = box.left - strip.left, right = box.right - strip.right;
|
|
105
102
|
if (left < pad)
|
|
106
103
|
row.scrollBy({ left: left - pad, behavior: "smooth" });
|
|
107
104
|
else if (right > -pad)
|
package/dist/components/toast.js
CHANGED
|
@@ -4,9 +4,7 @@ import { drawSlot, mountPortal } from "../core.js";
|
|
|
4
4
|
A.insertGlobalCss({
|
|
5
5
|
".s-toasts": "position:fixed bottom:$3 right:$3 z-index:400 " +
|
|
6
6
|
"display:flex flex-direction:column gap:$2 " +
|
|
7
|
-
|
|
8
|
-
// zoom (see `watchScale` in main.ts), and this cap means the window.
|
|
9
|
-
"pointer-events:none max-width:min(calc(90vw/var(--s-zoom,1)),24rem) w:24rem",
|
|
7
|
+
"pointer-events:none max-width:min(90vw,24rem) w:24rem",
|
|
10
8
|
".s-toast": {
|
|
11
9
|
"&": "display:flex align-items:flex-start gap:$2 " +
|
|
12
10
|
"padding: $3; " +
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import A from "aberdeen";
|
|
2
|
-
import {
|
|
2
|
+
import { drawSlot, mountPortal } from "../core.js";
|
|
3
3
|
// The tip is a `.s-s.neutral.shadow` surface (it portals to <body>, so it renders at
|
|
4
4
|
// the page's next neutral shade), which provides its background, ink, border,
|
|
5
5
|
// radius and elevation.
|
|
@@ -20,12 +20,10 @@ let hideTimer = null;
|
|
|
20
20
|
if (typeof window !== "undefined") {
|
|
21
21
|
window.addEventListener("scroll", () => { $ttActive.value = undefined; }, { capture: true, passive: true });
|
|
22
22
|
}
|
|
23
|
-
function computePos(rect, tipW, tipH, placement
|
|
24
|
-
// `rect` is handed over already in the tip's own coordinate space; the
|
|
25
|
-
// window's size has to be brought into it too (see `cssZoom`).
|
|
23
|
+
function computePos(rect, tipW, tipH, placement) {
|
|
26
24
|
const gap = 7;
|
|
27
|
-
const vw = window.innerWidth
|
|
28
|
-
const vh = window.innerHeight
|
|
25
|
+
const vw = window.innerWidth;
|
|
26
|
+
const vh = window.innerHeight;
|
|
29
27
|
let x = 0, y = 0;
|
|
30
28
|
if (placement === "bottom") {
|
|
31
29
|
x = rect.left + (rect.width - tipW) / 2;
|
|
@@ -89,12 +87,8 @@ mountPortal(() => {
|
|
|
89
87
|
requestAnimationFrame(() => {
|
|
90
88
|
if (!document.body.contains(tipEl))
|
|
91
89
|
return;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const z = cssZoom(tipEl);
|
|
95
|
-
const r = anchor.getBoundingClientRect();
|
|
96
|
-
const rect = new DOMRect(r.x / z, r.y / z, r.width / z, r.height / z);
|
|
97
|
-
const { x, y } = computePos(rect, tipEl.offsetWidth, tipEl.offsetHeight, placement, z);
|
|
90
|
+
const rect = anchor.getBoundingClientRect();
|
|
91
|
+
const { x, y } = computePos(rect, tipEl.offsetWidth, tipEl.offsetHeight, placement);
|
|
98
92
|
tipEl.style.left = x + "px";
|
|
99
93
|
tipEl.style.top = y + "px";
|
|
100
94
|
tipEl.style.visibility = "";
|
package/dist/core.d.ts
CHANGED
|
@@ -56,21 +56,6 @@ export interface ContentOptions {
|
|
|
56
56
|
* that do the switching and by the JS that has to agree with them.
|
|
57
57
|
*/
|
|
58
58
|
export declare const NARROW_PX = 640;
|
|
59
|
-
/**
|
|
60
|
-
* The narrowest layout the library is designed for. A panel must work at this
|
|
61
|
-
* width (panels.ts sizes its columns from it), and a window narrower than this
|
|
62
|
-
* is shown the 360px layout scaled down to fit rather than squeezed further
|
|
63
|
-
* (see `watchScale` in main.ts).
|
|
64
|
-
*/
|
|
65
|
-
export declare const MIN_PX = 360;
|
|
66
|
-
/**
|
|
67
|
-
* `el`'s effective CSS zoom: the factor between its own coordinate space and
|
|
68
|
-
* the window's — 1 wherever `zoom` isn't in play, or in browsers that predate
|
|
69
|
-
* it. A `getBoundingClientRect()` or pointer coordinate is in window space;
|
|
70
|
-
* divide it by this before using it as a length or scroll offset, which live
|
|
71
|
-
* in the element's own space. (`offsetWidth` and friends already do.)
|
|
72
|
-
*/
|
|
73
|
-
export declare function cssZoom(el: Element): number;
|
|
74
59
|
/** Generates a process-unique id, used to wire `<label for>` to its control. */
|
|
75
60
|
export declare function uniqueId(prefix?: string): string;
|
|
76
61
|
/**
|
package/dist/core.js
CHANGED
|
@@ -6,23 +6,6 @@ import A from "aberdeen";
|
|
|
6
6
|
* that do the switching and by the JS that has to agree with them.
|
|
7
7
|
*/
|
|
8
8
|
export const NARROW_PX = 640;
|
|
9
|
-
/**
|
|
10
|
-
* The narrowest layout the library is designed for. A panel must work at this
|
|
11
|
-
* width (panels.ts sizes its columns from it), and a window narrower than this
|
|
12
|
-
* is shown the 360px layout scaled down to fit rather than squeezed further
|
|
13
|
-
* (see `watchScale` in main.ts).
|
|
14
|
-
*/
|
|
15
|
-
export const MIN_PX = 360;
|
|
16
|
-
/**
|
|
17
|
-
* `el`'s effective CSS zoom: the factor between its own coordinate space and
|
|
18
|
-
* the window's — 1 wherever `zoom` isn't in play, or in browsers that predate
|
|
19
|
-
* it. A `getBoundingClientRect()` or pointer coordinate is in window space;
|
|
20
|
-
* divide it by this before using it as a length or scroll offset, which live
|
|
21
|
-
* in the element's own space. (`offsetWidth` and friends already do.)
|
|
22
|
-
*/
|
|
23
|
-
export function cssZoom(el) {
|
|
24
|
-
return el.currentCSSZoom ?? 1;
|
|
25
|
-
}
|
|
26
9
|
let idCounter = 0;
|
|
27
10
|
/** Generates a process-unique id, used to wire `<label for>` to its control. */
|
|
28
11
|
export function uniqueId(prefix = "s") {
|
package/dist/staffa.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import E from"aberdeen";var I1=t=>`background: linear-gradient(${t}, color-mix(in oklab, $s-bg, white 9%), color-mix(in oklab, $s-bg, black 9%));`,B1=I1("170deg"),f1=I1("180deg"),y1="staffa:darkMode",F1=E.proxy({value:v2()});function v2(){try{let t=localStorage.getItem(y1);if(t==="dark")return!0;if(t==="light")return!1}catch{}}function m2(t){F1.value=t;try{t===void 0?localStorage.removeItem(y1):localStorage.setItem(y1,t?"dark":"light")}catch{}}function U1(t=!1){let a=F1.value;return a===void 0&&!t?E.darkMode():a}E(()=>{U1()?E.insertGlobalCss({":root, .s-s.neutral":"--s-bg:#0e0f12 --s-text:#e9eaec",".s-s.neutral":"--s-bg:#191b1f --s-text:#e9eaec",".s-s.neutral .s-s.neutral":"--s-bg:#23262b"}):E.insertGlobalCss({":root, .s-s.neutral":"--s-bg:#eef0f3 --s-text:#1d1f24",".s-s.neutral, .s-s.neutral":"--s-bg:#ffffff --s-text:#1d1f24",".s-s.neutral .s-s.neutral":"--s-bg:#f6f7f9"})});E.setSpacingCssVars(1.1);E.insertGlobalCss({"*, *::before, *::after":"box-sizing:border-box",html:"text-size-adjust:100%",body:"m:0 p:$3 line-height:1.5 font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; -webkit-font-smoothing:antialiased background-color:$s-bg text:$s-text",a:"color: $s-link-fg; text-decoration:underline text-underline-offset:2px; transition: color 0.12s, filter 0.12s;","a:hover":"filter: brightness(1.15)","input, button, textarea, select, optgroup":"font:inherit color:inherit","input:where(:not([type=checkbox],[type=radio],[type=range],[type=file],[type=color],[type=image],[type=submit],[type=button],[type=reset],[type=hidden])), textarea, select":"background:$s-bg border: 1px solid $s-faint; r:$s-radius-sm padding: 0.45em 0.65em; max-width:100%","input:where([type=checkbox],[type=radio])":"width:1.15em height:1.15em cursor:pointer","input[type=range]":"appearance:none background:transparent cursor:pointer vertical-align:middle","input[type=range]::-webkit-slider-runnable-track":"height:4px r:99px background:$s-faint","input[type=range]::-moz-range-track":"height:4px r:99px background:$s-faint","input[type=range]::-moz-range-progress":"height:4px r:99px background:$s-accent","input[type=range]::-webkit-slider-thumb":"appearance:none width:16px height:16px margin-top:-6px r:50% background:$s-accent","input[type=range]::-moz-range-thumb":"width:16px height:16px border:0 r:50% background:$s-accent","input[type=file]":"cursor:pointer",progress:"appearance:none border:0 height:6px r:99px background:$s-faint overflow:hidden vertical-align:middle","progress::-webkit-progress-bar":"background:$s-faint r:99px","progress::-webkit-progress-value":"background:$s-accent r:99px","progress::-moz-progress-bar":"background:$s-accent r:99px",meter:"vertical-align:middle",fieldset:"border: 1px solid $s-faint; r:$s-radius-sm padding:$2 min-width:0",legend:"padding: 0 $1; font-weight:600","code, kbd, samp, pre":"font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;",code:"background: color-mix(in oklab, $s-text, $s-bg 86%); padding: 0.12em 0.34em; r:4px font-size:0.9em",pre:"background: color-mix(in oklab, $s-text, $s-bg 92%); p:$3 r: $s-radius; overflow:auto","pre code":"background:transparent p:0","img, svg, video, canvas":"max-width:100% h:auto",hr:"border:0 border-top: 1px solid $s-faint;","::placeholder":"color: $s-muted; opacity:1",":focus-visible":"outline: 2px solid $s-focus; outline-offset:2px",small:"color:$s-muted font-size:0.9em","@media (prefers-reduced-motion: reduce)":{"*, *::before, *::after":"transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; scroll-behavior: auto !important;"},":root":"--s-primary:#00a884 --s-danger:#dc5b41 --s-success:#00a884 --s-warning:#ef6b00 --s-link:#3f8cd8 --s-radius-sm:6px --s-radius:12px --s-radius-lg:18px --s-focus: color-mix(in srgb, $s-primary 38%, transparent); --s-gradient: linear-gradient(135deg, color-mix(in oklab, $s-primary, white 16%), color-mix(in oklab, $s-primary, black 14%));",":root, .s-s.neutral":"--s-accent:$s-primary --s-link-fg:$s-link",".s-s:not(.neutral)":"--s-bg:$s-primary border:0 --s-text:#eee --s-accent:#fff --s-link-fg:#eef --s-muted: color-mix(in srgb, #fff 70%, transparent); --s-faint: color-mix(in srgb, #fff 30%, transparent);",".s-s.danger":"--s-bg:$s-danger",".s-s.success":"--s-bg:$s-success",".s-s.warning":"--s-bg:$s-warning",".s-s.link":"--s-bg:$s-link",".s-s.primary":"--s-bg:$s-primary",":root, .s-s":"--s-muted: color-mix(in oklab, $s-text, $s-bg 42%); --s-faint: color-mix(in oklab, $s-text, $s-bg 80%); color:$s-text accent-color:$s-accent scrollbar-width:thin scrollbar-color: $s-faint transparent;",".s-s, body":B1,".s-s":"r:$s-radius",":where(.s-s.neutral)":"border: 1px solid $s-faint;",".s-s::-webkit-scrollbar, .s-s ::-webkit-scrollbar":"width:10px height:10px",".s-s::-webkit-scrollbar-track, .s-s ::-webkit-scrollbar-track":"background:transparent",".s-s::-webkit-scrollbar-thumb, .s-s ::-webkit-scrollbar-thumb":"background:$s-faint border-radius:99px border: 2px solid transparent; background-clip:padding-box",".s-s.shadow.neutral:not(.s-btn)":"box-shadow: 0 4px 14px rgba(0,0,0,0.13);",".s-s.extra-shadow.neutral:not(.s-btn)":"box-shadow: 0 18px 50px rgba(0,0,0,0.28);",".s-s.shadow:not(.neutral):not(.tonal):not(.outlined)":"box-shadow: 0 4px 14px color-mix(in srgb, $s-bg 30%, transparent);",".s-s.extra-shadow:not(.neutral):not(.tonal):not(.outlined)":"box-shadow: 0 14px 40px color-mix(in srgb, $s-bg 40%, transparent);",".s-s.no-shadow":"box-shadow: none !important;",".s-s:not(.neutral).tonal, .s-s:not(.neutral).outlined":"--s-text:$s-bg --s-accent:$s-bg --s-link-fg:$s-bg --s-faint: color-mix(in srgb, $s-bg 30%, transparent); --s-muted: color-mix(in srgb, $s-bg 70%, transparent);",".s-s:not(.neutral).tonal":"background: color-mix(in srgb, $s-bg 15%, transparent); border: 1px solid $s-faint;",".s-s:not(.neutral).outlined":"background: transparent; border: 1px solid color-mix(in srgb, $s-bg 45%, transparent);",".s-s:not(.neutral) .s-s.tonal, .s-s:not(.neutral) .s-s.outlined":"--s-text:#fff --s-accent:#fff --s-link-fg:#fff "+B1+" border-color: transparent;"});E.insertGlobalCss({".s-preload, .s-preload *, .s-preload *::before, .s-preload *::after":"transition: none !important; animation: none !important;"});if(typeof document<"u"&&typeof requestAnimationFrame=="function"){let t=document.documentElement;t.classList.add("s-preload"),requestAnimationFrame(()=>requestAnimationFrame(()=>t.classList.remove("s-preload")))}E.insertGlobalCss({":disabled, [aria-disabled=true]":"opacity:0.45 filter:saturate(0.6) user-select:none",":disabled, [aria-disabled=true], :disabled *, [aria-disabled=true] *":"pointer-events:none cursor:not-allowed"});var u2="p, ul, ol, dl, blockquote, pre, table, figure, hr, h1, h2, h3, h4, h5, h6";E.insertGlobalCss({[`${u2}`]:{"&":"margin:0","&:not(:first-child)":"margin-top:$3"},"h1, h2, h3, h4, h5, h6":{"&":"line-height:1.15 font-weight:700 text-wrap:balance","&:not(:first-child)":"margin-top:1.4em"},h1:"font-size:2em font-weight:800 letter-spacing:-0.022em",h2:"font-size:1.55em letter-spacing:-0.018em",h3:"font-size:1.3em letter-spacing:-0.011em",h4:"font-size:1.1em",h5:"font-size:0.95em letter-spacing:0.005em",h6:"font-size:0.8em fg:$s-muted text-transform:uppercase letter-spacing:0.07em","ul, ol":{"&":"padding-left:1.5em","> li:not(:first-child), li > &:not(:first-child)":"margin-top:$1"},blockquote:"border-left: 3px solid $s-faint; padding-left: $3; fg: $s-muted",table:"border-collapse:collapse","th, td":"text-align:left padding: $1 $2; border-bottom: 1px solid $s-faint; vertical-align:top",th:"font-weight:600","thead th":"border-bottom: 2px solid $s-faint;",dt:"font-weight:600",dd:"margin-left: 1.5em",figcaption:"fg:$s-muted font-size:0.9em margin-top:$1 text-align:center"});import M from"aberdeen";import N1 from"aberdeen";var o1=640,t1=360;function B(t){return t.currentCSSZoom??1}var y2=0;function I(t="s"){return`${t}-${++y2}`}function v(t,...a){t!=null&&(typeof t=="function"?t(...a):N1("rich=",t))}var f2="a[href], button, input, select, textarea, [tabindex]";function _(t,a){let h=p=>p instanceof HTMLElement&&!p.hasAttribute("disabled")&&p.getAttribute("aria-disabled")!=="true"&&p.tabIndex>=0&&p.getClientRects().length>0,e=(a?[...t.querySelectorAll(a)].find(h):void 0)??[...t.querySelectorAll(f2)].find(h);return e?.focus(),e!=null}function F(t){queueMicrotask(()=>N1(t))}import L from"aberdeen";L.insertGlobalCss({".s-field":{"&":"display:flex flex-direction:column gap:$1","> label":"font-weight:600 font-size:0.9em fg:$s-text user-select:none"},".s-req":"fg:$s-danger margin-left:2px",".s-help":"font-size:0.82em fg:$s-muted",".s-error":"font-size:0.82em fg:$s-danger",".s-input":{"&":"w:100% background: color-mix(in oklab, $s-bg, $s-text 4%); color:$s-text border: 1px solid $s-faint; r:$s-radius padding: 0.55em 0.7em; transition: border-color 0.15s, box-shadow 0.15s;","&:hover:not(:disabled)":"border-color: color-mix(in oklab, $s-text, $s-bg 55%);","&:focus-visible":"border-color:$s-accent box-shadow: 0 0 0 3px $s-focus; outline:none","&[aria-invalid=true]":"border-color:$s-danger"}});function U(t,a){let h=t.id??I("field"),e=()=>!!t.error;L("div.s-field",t.attrs,()=>{L(()=>{t.label!=null&&L("label for=",h,()=>{v(t.label),t.required&&L("span.s-req aria-hidden=true #*")})}),a(h,e),L(()=>{t.help!=null&&!t.error&&L("div.s-help",()=>v(t.help))}),L(()=>{t.error&&L("div.s-error role=alert #",t.error)})})}function Q(t,a,h,e){L("id=",a),t.name&&L("name=",t.name),L(()=>{t.disabled&&L("disabled=true")}),L(()=>{t.required&&L("aria-required=true")}),L(()=>L("aria-invalid=",h()?"true":"false")),e&&L("bind=",e)}M.insertGlobalCss({".s-ac":{"&":"position:relative","> .s-control":"display:flex flex-wrap:wrap align-items:center gap:$1 background: color-mix(in oklab, $s-bg, $s-text 4%); color:$s-text border: 1px solid $s-faint; r:$s-radius padding: 0.3em 0.4em; cursor:text; transition: border-color 0.15s, box-shadow 0.15s;","> .s-control:hover":"border-color: color-mix(in oklab, $s-text, $s-bg 55%);","> .s-control:focus-within":"border-color:$s-accent box-shadow: 0 0 0 3px $s-focus;","&[aria-invalid=true] > .s-control":"border-color:$s-danger",".s-chip":"display:inline-flex align-items:center gap:$1 font-size:0.85em background: color-mix(in oklab, $s-bg, $s-text 10%); border: 1px solid $s-faint; r:$s-radius padding: 0.1em 0.2em 0.1em 0.5em;",".s-chip > button":"cursor:pointer border:0 background:transparent fg:$s-muted font-size:1.1em line-height:1 padding: 0 0.2em; r:4px",".s-chip > button:hover":"fg:$s-text background:$s-faint",input:"flex:1 min-width:6ch border:0 background:transparent color:inherit outline:none padding:0.25em","> .s-menu":"position:absolute top:100% left:0 right:0 z-index:20 margin-top:4px max-height:15rem overflow-y:auto list-style:none p:$1 margin-bottom:0","> .s-menu li":"margin:0",".s-option":"padding: 0.45em 0.6em; r:6px cursor:pointer transition: background 0.1s;",".s-option[aria-selected=true]":"background: color-mix(in srgb, $s-text 10%, transparent);",".s-add":"fg:$s-accent font-style:italic",".s-empty":"padding: 0.45em 0.6em; fg:$s-muted"}});function g2(t){return typeof t=="string"?{value:t,label:t}:{value:t.value,label:t.label??t.value}}function b2(t){let a=I("ac-menu"),h=M.proxy({query:"",open:!1,active:0}),e=()=>(typeof t.options=="function"?t.options():t.options).map(g2),p=()=>{let i=t.bind?.value;return i==null||i===""?[]:Array.isArray(i)?i:[i]},r=i=>e().find(m=>m.value===i)?.label??i;if(!t.multi){let i=t.bind?M.peek(t.bind,"value"):void 0;typeof i=="string"&&i&&(h.query=M.peek(()=>r(i)))}let d=()=>{let i=new Set(p()),m=e();t.multi&&(m=m.filter(b=>!i.has(b.value)));let g=h.query.trim().toLowerCase();return g&&(m=m.filter(b=>b.label.toLowerCase().includes(g))),m},o=(i,m)=>{if(t.multi){let g=Array.isArray(t.bind?.value)?[...t.bind.value]:[];g.includes(i)||g.push(i),t.bind&&(t.bind.value=g),h.query=""}else t.bind&&(t.bind.value=i),h.query=r(i),h.open=!1;h.active=0,m?.focus()},n=i=>{if(!t.bind)return;let m=t.bind.value??[];t.bind.value=m.filter(g=>g!==i)};U(t,(i,m)=>{M("div.s-ac",t.inputAttrs,()=>{M(()=>M("aria-invalid=",m()?"true":"false"));let g;M("div.s-control",()=>{M("click=",()=>g?.focus()),M(()=>{if(t.multi)for(let b of p())M("span.s-chip",()=>{M("span #",M.peek(()=>r(b))),M("button type=button aria-label=",`Remove ${b}`,()=>{M("#\xD7"),M("click=",l=>{l.stopPropagation(),n(b),g?.focus()})})})}),g=M("input type=text role=combobox autocomplete=off",()=>{M("id=",i,`aria-controls=${a} aria-autocomplete=list`),t.placeholder!=null&&M("placeholder=",t.placeholder),t.disabled&&M("disabled=true"),t.required&&M("aria-required=true"),M("bind=",M.ref(h,"query")),M(()=>M("aria-expanded=",h.open?"true":"false")),M(()=>{let l=d()[h.active];M("aria-activedescendant=",h.open&&l?`${a}-opt-${h.active}`:"")}),M("input=",()=>{h.open=!0,h.active=0}),M("focus=",()=>{h.open=!0}),M("blur=",()=>{setTimeout(()=>u(),150)}),M("keydown=",b=>c(b,g))})}),M(()=>{if(!h.open)return;let b=d(),l=h.query.trim(),f=t.allowCustom!==!1&&l!==""&&!b.some(C=>C.label.toLowerCase()===l.toLowerCase());M("ul.s-menu.s-s.neutral.shadow role=listbox",`id=${a}`,()=>{b.forEach((C,z)=>{M("li.s-option role=option",`id=${a}-opt-${z}`,()=>{M(()=>M("aria-selected=",h.active===z?"true":"false")),M("#",C.label),M("mousedown=",d1=>d1.preventDefault()),M("click=",()=>o(C.value,g)),M("mousemove=",()=>{h.active=z})})}),f&&M("li.s-option.s-add role=option",()=>{M("#",`Add "${l}"`),M("mousedown=",C=>C.preventDefault()),M("click=",()=>o(l,g))}),b.length===0&&!f&&M("li.s-empty #No matches")})}),M(()=>{if(t.name)if(t.multi)for(let b of p())M("input type=hidden",()=>{M("name=",t.name),M("value=",b)});else M("input type=hidden",()=>{M("name=",t.name),M("value=",p()[0]??"")})})})});function c(i,m){let g=d(),b=g.length-1;if(i.key==="ArrowDown")i.preventDefault(),h.open=!0,h.active=Math.min(b,h.active+1);else if(i.key==="ArrowUp")i.preventDefault(),h.active=Math.max(0,h.active-1);else if(i.key==="Enter"){i.preventDefault();let l=g[h.active];l?o(l.value,m):t.allowCustom!==!1&&h.query.trim()?o(h.query.trim(),m):h.open&&(h.open=!1)}else if(i.key==="Escape")h.open&&(i.preventDefault(),h.open=!1,t.multi||(h.query=r(p()[0]??"")));else if(i.key==="Backspace"&&t.multi&&h.query===""){let l=p();l.length&&n(l[l.length-1])}}function u(){h.open=!1,t.multi?h.query="":t.allowCustom!==!1&&h.query.trim()?o(h.query.trim()):h.query=r(p()[0]??"")}}import W from"aberdeen";import w2 from"aberdeen";var a1={size:24,color:"currentColor",strokeWidth:2,cap:"round",join:"round"};function H2(t,a){let h=a.size??a1.size,e=w2('svg.s-icon aria-hidden=true viewBox="0 0 24 24" fill=none',"width=",h,"height=",h,"stroke=",a.color??a1.color,"stroke-width=",a.strokeWidth??a1.strokeWidth,"stroke-linecap=",a.cap??a1.cap,"stroke-linejoin=",a.join??a1.join,a.attrs);e.innerHTML=t}function S(t){return(a={})=>H2(t,a)}var W1=S('<path d="m9 18 6-6-6-6" />');var X1=S('<circle cx="12" cy="12" r="10" />');var G1=S('<path d="M15 3h6v6" /><path d="M10 14 21 3" /><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />');var K1=S('<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />');var c1=S('<path d="M4 5h16" /><path d="M4 12h16" /><path d="M4 19h16" />');var j1=S('<path d="M12 17v5" /><path d="M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89" /><path d="m2 2 20 20" /><path d="M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11" />'),g1=S('<path d="M12 17v5" /><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z" />');var _1=S('<path d="M22 2 2 22" />');var J=S('<path d="M18 6 6 18" /><path d="m6 6 12 12" />');import P from"aberdeen";P.insertGlobalCss({".s-btn":{"&":"display:inline-flex align-items:center justify-content:center gap:$2 font-weight:450 line-height:1.1 white-space:nowrap cursor:pointer text-decoration:none padding: $m2 $m3; transition: background 0.15s, border-color 0.15s, color 0.15s, filter 0.15s, box-shadow 0.15s, transform 0.08s;","&:focus-visible":"outline: 3px solid $s-focus; outline-offset: 1px;","&:hover":"filter: brightness(1.06)","&.tonal:hover, &.outlined:hover":"background: color-mix(in srgb, $s-bg 24%, transparent);","&.neutral:hover":"filter:none background: color-mix(in srgb, $s-text 8%, $s-bg);","> svg":"width:1.25em height:1.25em","&:active:not(:disabled)":"transform: translateY(1px)","&.small, .small > &":"padding: $m1 $m2; font-size:0.85em border-radius:$s-radius-sm","&.large, .large > &":"font-size:1.4em border-radius:$s-radius-lg"},".s-icon-btn":{"&":"display:inline-flex align-items:center justify-content:center flex-shrink:0 width:2rem height:2rem p:0 border:0 background:transparent cursor:pointer fg:$s-muted r:$s-radius-sm line-height:1 font-size:1rem text-decoration:none transition: color 0.12s, background 0.12s;","> svg":"width:1.25em height:1.25em","&:hover:not(:disabled):not([aria-disabled=true])":"fg:$s-text background: color-mix(in srgb, $s-text 10%, transparent);","&:focus-visible":"outline: 3px solid $s-focus; outline-offset:1px","&.small, .small > &":"width:1.6rem height:1.6rem font-size:0.8rem","&.large, .large > &":"width:2.4rem height:2.4rem font-size:1.2rem"}});function h1(t){let a=t.href!=null?"a":"button";P(`${a}.s-icon-btn`,t.attrs,()=>{Q1(t),P("aria-label=",t.ariaLabel),v(t.icon)})}function Q1(t){t.href!=null?(P("role=button"),t.disabled?P("aria-disabled=true"):P("href=",t.href)):(P("type=",t.type??"button"),t.disabled&&P("disabled=true")),t.click&&!t.disabled&&P("click=",t.click)}function O(t={}){let a=typeof t=="string"||typeof t=="function"?{content:t}:t,h=a.href!=null?"a":"button";P(`${h}.s-btn.s-s.shadow`,a.attrs,()=>{Q1(a),a.ariaLabel&&P("aria-label=",a.ariaLabel),v(a.icon),v(a.content)})}W.insertGlobalCss({".s-box":{"&":"display:flex flex-direction:column overflow:hidden r: $s-radius-lg; position:relative","&:not(:first-child)":"margin-top: $3","> header":"display:flex align-items:center gap:$2 padding: $2 $3; border:0 border-bottom: 1px solid $s-faint; r:0 font-weight:600","> footer":"display:flex align-items:center justify-content:flex-end gap:$2 padding: $2 $3; border:0 border-top: 1px solid $s-faint; r:0","> div":"p:$3 gap:$3","> header > .s-box-close":"margin-left:auto","> .s-box-close":"position:absolute top:$2 right:$2 z-index:1"}});function A2(t={}){let a=typeof t=="string"||typeof t=="function"?{content:t}:t;W("section.s-box.s-s.neutral.shadow",a.attrs,()=>{W(()=>{a.header!=null?W("header.s-s.neutral",a.headerAttrs,()=>{v(a.header),typeof a.close=="function"&&J1(a.close)}):typeof a.close=="function"&&J1(a.close)}),W("div",a.contentAttrs,()=>{v(a.content)}),W(()=>{a.footer!=null&&W("footer.s-s.neutral",a.footerAttrs,()=>v(a.footer))})})}function J1(t){h1({icon:J,ariaLabel:"Close",click:t,attrs:".s-box-close"})}import b1 from"aberdeen";import Y1 from"aberdeen";Y1.insertGlobalCss({".s-bgroup":{"&":"display:inline-flex align-items:stretch","&.s-spaced":"gap:$2 flex-wrap:wrap","&.s-vertical":"flex-direction:column","&.s-attached":"gap:0","&.s-attached:not(.s-vertical) > .s-btn:not(:first-child)":"margin-left:-1px","&.s-attached:not(.s-vertical) > .s-btn:not(:first-child):not(:last-child)":"r:0","&.s-attached:not(.s-vertical) > .s-btn:first-child:not(:last-child)":"border-top-right-radius:0 border-bottom-right-radius:0","&.s-attached:not(.s-vertical) > .s-btn:last-child:not(:first-child)":"border-top-left-radius:0 border-bottom-left-radius:0","&.s-attached.s-vertical > .s-btn:not(:first-child)":"margin-top:-1px","&.s-attached.s-vertical > .s-btn:not(:first-child):not(:last-child)":"r:0","&.s-attached.s-vertical > .s-btn:first-child:not(:last-child)":"border-bottom-left-radius:0 border-bottom-right-radius:0","&.s-attached.s-vertical > .s-btn:last-child:not(:first-child)":"border-top-left-radius:0 border-top-right-radius:0","&.s-attached > .s-btn:hover, &.s-attached > .s-btn:focus-visible":"z-index:1"}});function X(t={}){let h=`.s-${t.layout??"attached"}${t.vertical?".s-vertical":""}`;Y1(`div.s-bgroup${h} role=group`,t.attrs,()=>{if(t.buttons)for(let e of t.buttons)O(e);v(t.content)})}function V2(t){b1(()=>{let a=t.bind.value;X({attrs:t.attrs,buttons:Object.entries(t.options).map(([h,e])=>({content:e,ariaLabel:typeof e=="function"?h:void 0,attrs:a===h?".primary":".neutral",click:()=>{t.bind.value=t.allowDeselect&&a===h?void 0:h}}))})}),t.name&&b1(()=>b1("input type=hidden name=",t.name,"value=",t.bind.value??""))}import k from"aberdeen";k.insertGlobalCss({".s-check":{"&":"display:flex flex-direction:column gap:$1","> label":"display:flex align-items:center gap:$2 cursor:pointer user-select:none","> label:has(input:disabled)":"cursor:not-allowed opacity:0.45 filter:saturate(0.6)",input:"cursor:inherit m:0"}});function k2(t={}){let a=t.id??I("check");k("div.s-check",t.attrs,()=>{k("label for=",a,()=>{k("input type=checkbox",t.inputAttrs,()=>{k("id=",a),t.name&&k("name=",t.name),t.checked&&!t.bind&&k("checked=true"),t.change&&k("change=",t.change),k(()=>{t.disabled&&k("disabled=true")}),k(()=>{t.required&&k("aria-required=true")}),t.bind&&k("bind=",t.bind)}),k(()=>{t.label!=null&&v(t.label),t.required&&k("span.s-req aria-hidden=true #*")})}),k(()=>{t.help!=null&&!t.error&&k("div.s-help",()=>v(t.help))}),k(()=>{t.error&&k("div.s-error role=alert #",t.error)})})}import G from"aberdeen";G.insertGlobalCss({".s-form":{"&":"display:flex flex-direction:column gap:$3","&.grid":"display:grid grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap:$3","&.grid > .s-wide, &.grid > footer":"grid-column: 1 / -1;","> footer":"display:flex align-items:center justify-content:flex-end gap:$2 flex-wrap:wrap margin-top:$1"}});function L2(t={}){let a=typeof t=="string"||typeof t=="function"?{content:t}:t;G("form.s-form",a.attrs,()=>{G(()=>{G(".grid=",a.layout==="grid")}),G("submit=",h=>{if(h.preventDefault(),a.submit){let e=new FormData(h.target),p={};for(let r of new Set(e.keys())){let d=e.getAll(r);p[r]=d.length===1?d[0]:d}a.submit(p,h)}}),v(a.content),G(()=>{a.actions&&G("footer",a.actionsAttrs,()=>v(a.actions))})})}import x from"aberdeen";import{current as T1}from"aberdeen/route";import y from"aberdeen";import{matchCurrent as $2,current as i1,go as P2}from"aberdeen/route";import V from"aberdeen";import{grow as C2,shrink as z2}from"aberdeen/transitions";V.insertGlobalCss({".s-toasts":"position:fixed bottom:$3 right:$3 z-index:400 display:flex flex-direction:column gap:$2 pointer-events:none max-width:min(calc(90vw/var(--s-zoom,1)),24rem) w:24rem",".s-toast":{"&":"display:flex align-items:flex-start gap:$2 padding: $3; pointer-events:auto position:relative overflow:hidden",".s-toast-body":"display:flex flex-direction:column gap:$1 flex:1 min-width:0",".s-toast-title":"font-weight:700 line-height:1.3",".s-toast-close":"cursor:pointer border:0 background:transparent fg:$s-muted font-size:1.1em line-height:1 padding: 0 0.15em; r:4px flex-shrink:0 align-self:flex-start",".s-toast-close:hover":"fg:$s-text",".s-toast-close:focus-visible":"outline:none box-shadow: 0 0 0 3px $s-focus; fg:$s-text",".s-toast-progress":"position:absolute bottom:0 left:0 right:0 height:2px background:$s-accent width:100%"}});var S2=0,e1=V.proxy({});F(()=>{V.peek(()=>V.isEmpty(e1))&&V.isEmpty(e1)||V("div.s-toasts",()=>{V.onEach(e1,t=>{let{opts:a,id:h}=t,e=a.type==="danger"||a.type==="warning"?"alert":"status",p=a.type==null||a.type==="neutral"?"neutral":a.type,r=a.duration??6e3,d,o=null,n=()=>{clearTimeout(d),o&&(o.style.transition="none",o.style.width="100%",o.offsetWidth,o.style.transition=`width ${r}ms linear`,o.style.width="0%"),d=setTimeout(()=>w1(h),r)},c=()=>{clearTimeout(d),d=void 0,o&&(o.style.transition="none",o.style.width="100%")};V.clean(()=>clearTimeout(d)),V(`div.s-toast.s-s.${p}.extra-shadow aria-live=polite role=${e}`,"create=",C2,"destroy=",z2,a.attrs,()=>{r>0&&(V("mouseenter=",c),V("mouseleave=",n)),V("div.s-toast-body",()=>{V(()=>{a.title!=null&&V("div.s-toast-title",()=>v(a.title))}),V("div.s-toast-msg",()=>v(a.message))}),V(()=>{a.dismissible!==!1&&V("button.s-toast-close type=button aria-label=Dismiss",()=>{V("#\xD7"),V("click=",()=>w1(h))})}),r>0&&(o=V("div.s-toast-progress"))}),r>0&&requestAnimationFrame(n)})})});function w1(t){delete e1[t]}function n1(t){let a=++S2;return e1[a]={id:a,opts:t},()=>w1(a)}y.insertGlobalCss({".s-menu-list":"position:fixed z-index:350 min-width:10rem display:flex flex-direction:column p:$1 r:$s-radius-lg overflow-y:auto max-height:min(calc(80vh/var(--s-zoom,1)),28rem) transition: opacity 0.15s, transform 0.15s, visibility 0.15s;",".s-menu-list.hidden":"opacity:0 pointer-events:none transform:translateY(-6px) visibility:hidden",".s-menu-item":"display:flex align-items:center gap:$2 w:100% outline:0 scroll-margin:$2 padding: $m2 0; line-height:1.1 r:$s-radius cursor:pointer text-align:left font-weight:450 font-size:0.9em border:0 background:transparent fg:$s-text text-decoration:none transition: color 0.12s, transform 0.12s, text-shadow 0.12s;",".s-menu-item:focus-visible:not([aria-current=page]), .s-menu-item:hover:not([aria-disabled=true]):not([aria-current=page])":"filter:none color: color-mix(in lab, $s-primary 33%, $s-text);",".s-menu-item[aria-current=page]":"color:$s-accent filter:none",".s-menu-list .s-menu-item":"padding-inline:$2",".s-menu-item[aria-disabled=true]":"opacity:0.45 cursor:not-allowed pointer-events:none",".s-menu-icon":"flex-shrink:0",".s-menu-list .s-menu-icon":"display:flex",".s-menu-list .s-menu-icon > svg":"width:1.25em height:1.25em","hr.s-menu-sep":"border:0 height:1px margin: $1 0.6rem; background: linear-gradient(to right, transparent, $s-faint 18%, $s-faint 82%, transparent);",".s-menu-chevron":"margin-left:auto flex-shrink:0 display:flex transition: transform 0.15s ease;",".s-menu-chevron > svg":"width:1em height:1em",".s-menu-details":{"> summary":"list-style:none","> summary::-webkit-details-marker":"display:none","&::details-content":"interpolate-size:allow-keywords block-size:0 overflow-y:clip transition: block-size 0.15s ease, content-visibility 0.15s allow-discrete;","&[open]::details-content":"block-size:auto","&[open] > summary .s-menu-chevron":"transform:rotate(90deg)"},".s-menu-sub":"display:flex flex-direction:column gap:$1 padding-left:$3",".s-menu-inline":"display:flex flex-direction:column gap:$1"});function p1(t,a){y("keydown=",e=>{if(e.key==="Enter"&&e.target.tagName==="A"){queueMicrotask(()=>a?.());return}if(e.key!=="ArrowDown"&&e.key!=="ArrowUp"&&e.key!=="Home"&&e.key!=="End")return;e.preventDefault();let r=[...e.currentTarget.querySelectorAll(".s-menu-item")].filter(c=>c.getAttribute("aria-disabled")!=="true"&&!q2(c));if(!r.length)return;let d=r.indexOf(document.activeElement),o=e.key==="ArrowUp"?-1:1,n=e.key==="Home"?0:e.key==="End"?r.length-1:d<0?o>0?0:r.length-1:(d+o+r.length)%r.length;r[n].focus()});let h=y.derive(()=>H1(t));a2(t,a,h)}function a2(t,a,h){for(let e of t){if(typeof e=="string"||typeof e=="function"){v(e);continue}if("separator"in e){y("hr.s-menu-sep");continue}e.items?E2(e,a,h):O2(e,a)}}function O2(t,a){let h=!1,e=y(t.href?"a.s-menu-item data-panel=open":"button.s-menu-item type=button",t.attrs,()=>{t.href&&(y("href=",t.href),t.target&&y("target=",t.target),y(()=>{let p=!h;h=!0,A1(t)&&(y("aria-current=page"),requestAnimationFrame(()=>e.scrollIntoView({block:"nearest",behavior:p?"instant":"smooth"})))})),t.disabled&&y("aria-disabled=true"),y("click=",p=>{if(t.disabled){p.preventDefault();return}a?.(),t.click?.(p)}),t.icon&&y("span.s-menu-icon",()=>v(t.icon)),v(t.label)})}var h2=new Map;function t2(t,a){return h2.set(t,a),a}function E2(t,a,h){let e=t.href??e2(t.items),p=e!=null?y.derive(()=>V1(t)?t2(e,!0):h==null||h.value?t2(e,!1):h2.get(e)??!1):null;y("details.s-menu-details",()=>{p&&y(()=>{p.value&&y("open=true")}),y("summary.s-menu-item.s-menu-branch",t.attrs,()=>{t.disabled&&y("aria-disabled=true"),y(()=>{A1(t)&&y("aria-current=page")}),y("click=",r=>{if(t.disabled){r.preventDefault();return}e!=null&&(r.preventDefault(),T2(e),P2(e)),t.click?.(r)}),t.icon&&y("span.s-menu-icon",()=>v(t.icon)),v(t.label),y("span.s-menu-chevron aria-hidden=true",()=>W1())}),y("div.s-menu-sub",()=>a2(t.items,a,h))})}function q2(t){for(let a=t.closest("details");a;a=a.parentElement&&a.parentElement.closest("details"))if(!a.open&&t.closest("summary")?.parentElement!==a)return!0;return!1}function H1(t){return t.some(a=>typeof a!="string"&&typeof a!="function"&&!("separator"in a)&&V1(a))}function A1(t){if(t.href!=null&&$2(t.href))return!0;let a=t.match;if(a==null)return!1;let h=i1.path;if(typeof a=="function")return a(h);let e=a.replace(/\/+$/,"")||"/";return h===e||h.startsWith(e==="/"?"/":e+"/")}function V1(t){if(A1(t))return!0;for(let a of t.items??[])if(!(typeof a=="string"||typeof a=="function"||"separator"in a)&&V1(a))return!0;return!1}function e2(t){for(let a of t){if(typeof a=="string"||typeof a=="function"||"separator"in a)continue;let h=a.href??(a.items?e2(a.items):void 0);if(h!=null)return h}}var s1=null;function T2(t){try{s1=new URL(t,location.href).pathname.replace(/\/+$/,"")||"/"}catch{s1=null}}function k1(t){return s1!==t?!1:(s1=null,!0)}var N=y.proxy({opts:null});function Z(){let t=N.opts?.anchor;N.opts=null,t?.focus()}function l1(t){let a=N.opts;return a!=null&&(t==null||a.anchor===t)}function D2(t){l1(t)&&Z()}function R2(t,a){let h=B(t),e=t.offsetWidth,p=t.offsetHeight,r=window.innerWidth/h,d=window.innerHeight/h,o=4,n=a.left/h;n+e>r-8&&(n=Math.max(8,a.right/h-e));let c=a.bottom/h+o;c+p>d-8&&a.top/h-p-o>=8&&(c=a.top/h-p-o),t.style.left=Math.max(8,n)+"px",t.style.top=Math.max(8,c)+"px"}function Z2(t){return[{label:"Open in new tab",icon:G1,click:()=>{window.open(t,"_blank","noopener")}},{label:"Copy link",icon:K1,click:()=>{B2(t)}}]}async function B2(t){let a=new URL(t,location.href).href;try{await navigator.clipboard.writeText(a),n1({message:"Link copied."})}catch{n1({message:"Couldn't copy the link.",type:"danger"})}}F(()=>{let t=N.opts;if(!t)return;let a=y("div.s-menu-list.s-s.neutral.shadow create=hidden destroy=hidden",t.dropdownAttrs,()=>{p1(t.link!=null?[...Z2(t.link),{separator:!0},...t.items]:t.items,Z)}),h=r=>{let d=r.target;!a.contains(d)&&(t.closeOnAnchorClick||!t.anchor.contains(d))&&Z()},e=r=>{(r.key==="Escape"||r.key==="Tab")&&(r.preventDefault(),Z())},p=y.peek(i1,"path");y(()=>{i1.path!==p&&!k1(i1.path)&&Z()}),document.addEventListener("click",h,!0),document.addEventListener("keydown",e,!0),y.clean(()=>{document.removeEventListener("click",h,!0),document.removeEventListener("keydown",e,!0)}),requestAnimationFrame(()=>{if(!document.body.contains(a))return;let r=t.at?{left:t.at.x,right:t.at.x,top:t.at.y,bottom:t.at.y}:t.anchor.getBoundingClientRect();R2(a,r),_(a,".s-menu-item[aria-current=page]")})});function I2(t){y("nav.s-menu-inline",t.attrs,()=>p1(t.items,t.onLeafSelect))}function L1(t){return N.opts=t,Z}function C1(t){let a=null;y.clean(()=>{N.opts?.anchor===a&&Z()}),y("contextmenu=",h=>{h.preventDefault(),a=h.currentTarget,L1({...t,anchor:a,at:{x:h.clientX,y:h.clientY},closeOnAnchorClick:!0})})}function F2(t){let a=null;y.clean(()=>{N.opts?.anchor===a&&Z()}),O({icon:c1,...t.button?.content==null?{ariaLabel:"Open menu"}:null,attrs:".neutral",...t.button,click:h=>{if(a=h.currentTarget,N.opts?.anchor===a){Z();return}L1({items:t.items,anchor:a,dropdownAttrs:t.dropdownAttrs})}})}import w from"aberdeen";import K from"aberdeen";function z1(t={}){U(t,(a,h)=>{K("input.s-input",t.inputAttrs,()=>{K("type=",t.type??"text"),t.placeholder!=null&&K("placeholder=",t.placeholder),t.autocomplete!=null&&K("autocomplete=",t.autocomplete),t.value!=null&&!t.bind&&K("value=",t.value),t.input&&K("input=",t.input),t.change&&K("change=",t.change),Q(t,a,h,t.bind)})})}w.insertGlobalCss({".s-backdrop":{"&":"position:fixed inset:0 z-index:200 display:block background: rgba(0,0,0,0.55); transition: opacity 0.4s ease-in-out;","&.hidden":"opacity:0 pointer-events:none"},".s-dialog":{"&":"position:fixed z-index:200 top:50% left:50% display:flex flex-direction:column transform:translate(-50%,-50%) min-width:20rem max-width:min(calc(90vw/var(--s-zoom,1)),44rem) max-height:min(calc(88vh/var(--s-zoom,1)),800px) r: $s-radius-lg; overflow:hidden transition: opacity 0.2s ease-out, transform 0.2s ease-out;","> header":"display:flex align-items:center gap:$2 padding: $2 $3; border:0 border-bottom: 1px solid $s-faint; r:0 font-weight:600 flex-shrink:0","> footer":"display:flex align-items:center justify-content:flex-end gap:$2 padding: $2 $3; border:0 border-top: 1px solid $s-faint; r:0 flex-shrink:0","> div":"p:$3 gap:$3 display:flex flex-direction:column overflow-y:auto flex:1 min-height:0","&.hidden":"opacity:0 pointer-events:none transform: translate(-50%, calc(-50% + 20px)); pointer-events:none"}});var j=w.proxy({}),S1=0,p2=w.derive(()=>{let t=Object.keys(j);if(t.length)return t[t.length-1]});function $1(){return p2.value!=null}F(()=>{w.onEach(j,({resolve:t,opts:a},h)=>{let e=()=>{delete j[h]};w.clean(()=>{a.onClose?.(),t()});let p=w.derive(()=>p2.value!=h);w("div.s-backdrop create=hidden destroy=hidden .hidden=",p,"click=",()=>{a.allowCancel!==!1&&e()});let r=w("div.s-dialog.neutral.s-s.extra-shadow create=hidden destroy=hidden",a.attrs,()=>{w(()=>{a.header!=null&&w("header.s-s.neutral",a.headerAttrs,()=>v(a.header))}),w("div",a.contentAttrs,()=>{v(a.content,e)}),w(()=>{a.footer!=null&&w("footer.s-s.neutral",a.footerAttrs,()=>v(a.footer))})});requestAnimationFrame(()=>{document.body.contains(r)&&_(r)})})});function M1(t){S1||document.addEventListener("keydown",h=>{if(h.key!=="Escape"||h.defaultPrevented)return;let e=w.unproxy(j);for(let p=S1;p>0;p--)if(e[p]){h.preventDefault(),e[p].opts.allowCancel!==!1&&delete j[p];break}});let a=++S1;return t.cancelWithScope!==!1&&w.clean(()=>{delete j[a]}),new Promise(h=>{j[a]={resolve:h,opts:t}})}function U2(t,a={}){return M1({header:"Alert",allowCancel:!0,content:h=>{w("p",()=>{w("#",t)}),X({layout:"spaced",attrs:"align-self:flex-end",content:()=>{O({content:"OK",click:h})}})},...a})}function N2(t,a={}){return new Promise(h=>{let e=!1;M1({header:"Confirm",allowCancel:!0,content:p=>{w("p",()=>{w("#",t)}),X({layout:"spaced",attrs:"align-self:flex-end",content:()=>{O({content:"Cancel",attrs:".neutral",click:p}),O({content:"OK",click:()=>{e=!0,p()}})}})},...a,onClose:()=>{h(e),a.onClose?.()}})})}function W2(t,a="",h={}){return new Promise(e=>{let p=null;M1({header:"Input",allowCancel:!0,content:r=>{w("p",()=>{w("#",t)});let d=w.proxy({value:a});w("form display:contents",()=>{w("submit=",o=>{o.preventDefault(),p=d.value,r()}),z1({bind:w.ref(d,"value")}),X({layout:"spaced",attrs:"align-self:flex-end",content:()=>{O({content:"Cancel",attrs:".neutral",type:"button",click:r}),O({content:"OK",type:"submit"})}})})},...h,onClose:()=>{e(p),h.onClose?.()}})})}import s,{OPAQUE as d2}from"aberdeen";import*as H from"aberdeen/route";import A from"aberdeen";var X2=S('<path d="m15 18-6-6 6-6"/>'),G2=S('<path d="m9 18 6-6-6-6"/>');A.insertGlobalCss({".s-strip":{"&":"position:relative display:flex min-width:0","> .s-strip-row":"display:flex align-items:center flex:1 min-width:0 overflow-x:auto overflow-y:hidden scrollbar-width:none scroll-behavior:smooth","> .s-strip-row::-webkit-scrollbar":"display:none","> .s-strip-btn":"position:absolute top:0 bottom:0 z-index:1 display:none align-items:center justify-content:center width:2.4em border:0 padding:0 cursor:pointer fg:$s-muted transition: color 0.15s;","> .s-strip-btn:hover":"fg:$s-text","> .s-strip-btn-left":"left:0 justify-content:flex-start background: linear-gradient(to right, $s-bg 45%, transparent)","> .s-strip-btn-right":"right:0 justify-content:flex-end background: linear-gradient(to left, $s-bg 45%, transparent)","&.s-can-left > .s-strip-btn-left, &.s-can-right > .s-strip-btn-right":"display:flex"},".s-tabs":{"&":"display:flex flex-direction:column gap:$3",".s-tabbar":"border-bottom: 1px solid $s-faint;",".s-tablist":"gap:$1 align-items:stretch margin-bottom:-1px",".s-tab":"display:inline-flex align-items:center gap:$2 cursor:pointer background:transparent border:0 color: $s-muted; font-weight:600 padding: 0.6em 0.9em; white-space:nowrap border-bottom: 3px solid transparent; transition: color 0.15s, background 0.15s, border-color 0.15s;",".s-tab:hover:not(:disabled), .s-tab[aria-selected=true]":"color: $s-text;",".s-tab:focus-visible":"outline:none box-shadow: inset 0 0 0 2px $s-focus; r: $s-radius;",".s-tab[aria-selected=true]":"border-image: $s-gradient 1;",".s-tabpanel":"display:block"}});function x1(t){A("div.s-strip",t.attrs,()=>{let a=A("div.s-strip-row",t.stripAttrs,()=>v(t.content));r2(a,-1),r2(a,1),j2(a)})}function v1(t){let a=t.parentElement;if(!a||!t.isConnected)return;let h=parseFloat(getComputedStyle(a).fontSize)*2.6,e=B(a),p=t.getBoundingClientRect(),r=a.getBoundingClientRect(),d=(p.left-r.left)/e,o=(p.right-r.right)/e;d<h?a.scrollBy({left:d-h,behavior:"smooth"}):o>-h&&a.scrollBy({left:o+h,behavior:"smooth"})}function K2(t){let a=I("tabs"),h=(r,d)=>r.id??String(d),e=t.bind??A.proxy(h(t.tabs[0]??{label:""},0));t.tabs.length>0&&!t.tabs.some((r,d)=>h(r,d)===A.peek(()=>e.value))&&(e.value=h(t.tabs[0],0));let p=(r,d)=>{r.disabled||(e.value=h(r,d))};A("div.s-tabs",t.attrs,()=>{x1({attrs:".s-tabbar",stripAttrs:".s-tablist role=tablist",content:()=>{t.tabs.forEach((r,d)=>{let o=h(r,d),n=A("button.s-tab type=button role=tab",()=>{A("id=",`${a}-tab-${o}`,"aria-controls=",`${a}-panel-${o}`),A(()=>{let c=e.value===o;A("aria-selected=",c?"true":"false"),A("tabindex=",c?"0":"-1"),c&&requestAnimationFrame(()=>v1(n))}),r.disabled&&A("disabled=true"),A("click=",()=>p(r,d)),A("keydown=",c=>_2(c,t.tabs,d,p)),v(r.icon),v(r.label)})})}}),A("div.s-tabpanel role=tabpanel",t.contentAttrs,()=>{A(()=>{let r=e.value,d=t.tabs.findIndex((n,c)=>h(n,c)===r),o=t.tabs[d]??t.tabs[0];o&&(A("id=",`${a}-panel-${h(o,d)}`,"aria-labelledby=",`${a}-tab-${h(o,d)}`),v(o.content))})})})}function r2(t,a){A(`button.s-strip-btn.s-strip-btn-${a<0?"left":"right"} type=button`,()=>{A("tabindex=-1 aria-hidden=true"),A("click=",()=>t.scrollBy({left:a*t.clientWidth*.8,behavior:"smooth"})),(a<0?X2:G2)({size:"1.1em"})})}function j2(t){let a=t.parentElement;if(!a||typeof ResizeObserver>"u")return;let h=()=>{let r=t.scrollWidth-t.clientWidth;a.classList.toggle("s-can-left",t.scrollLeft>1),a.classList.toggle("s-can-right",t.scrollLeft<r-1)};t.addEventListener("scroll",h,{passive:!0});let e=new ResizeObserver(h);e.observe(t);let p=typeof MutationObserver>"u"?void 0:new MutationObserver(r=>{for(let d of r){for(let o of d.addedNodes)o instanceof Element&&e.observe(o);for(let o of d.removedNodes)o instanceof Element&&e.unobserve(o)}h()});p?.observe(t,{childList:!0});for(let r of Array.from(t.children))e.observe(r);h(),A.clean(()=>{t.removeEventListener("scroll",h),e.disconnect(),p?.disconnect()})}function _2(t,a,h,e){let p=h;if(t.key==="ArrowRight"||t.key==="ArrowDown")p=(h+1)%a.length;else if(t.key==="ArrowLeft"||t.key==="ArrowUp")p=(h-1+a.length)%a.length;else if(t.key==="Home")p=0;else if(t.key==="End")p=a.length-1;else return;t.preventDefault();let r=p>=h?1:-1;for(let d=0;d<a.length;d++){let o=a[p];if(o&&!o.disabled){e(o,p),t.currentTarget?.parentElement?.children[p]?.focus();return}p=(p+r+a.length)%a.length}}var E1={integer(t){if(!/^(0|-?[1-9]\d*)$/.test(t))return;let a=Number(t);return Number.isSafeInteger(a)?a:void 0}};function q(t){let a=String(t).replace(/\/+$/,"");return a.startsWith("/")||(a=`/${a}`),a}function r1(t){let a=q(t);return a==="/"?[]:a.slice(1).split("/")}function o2(t){let a=r1(t),h=a.map((e,p)=>{if(!e.startsWith("[")||!e.endsWith("]"))return{kind:"lit",value:e};let r=/^\[\.\.\.([A-Za-z_$][\w$]*)\]$/.exec(e);if(r){if(p!==a.length-1)throw new Error(`Staffa: "${e}" must be the last segment of route "${t}"`);return{kind:"rest",name:r[1]}}let d=/^\[([A-Za-z_$][\w$]*)(?:=([A-Za-z_$][\w$]*))?\]$/.exec(e);if(!d)throw new Error(`Staffa: malformed param "${e}" in route "${t}"`);let[,o,n]=d;if(n&&!(n in E1))throw new Error(`Staffa: unknown matcher "${n}" in route "${t}" (known: ${Object.keys(E1).join(", ")})`);return{kind:"param",name:o,matcher:n}});return{key:t,segs:h}}function Q2(t){try{return decodeURIComponent(t)}catch{return t}}function P1(t,a){let h={};for(let e=0;e<t.segs.length;e++){let p=t.segs[e];if(p.kind==="rest")return e>=a.length?null:(h[p.name]=a.slice(e).join("/"),h);if(e>=a.length)return null;let r=a[e];if(p.kind==="lit"){if(r!==p.value)return null}else if(p.matcher){let d=E1[p.matcher](r);if(d===void 0)return null;h[p.name]=d}else h[p.name]=Q2(r)}return t.segs.length===a.length?h:null}var i2=250,J2=300,Y2=t1,q1=540,c2=2;s.insertGlobalCss({":root":`--s-panel-ms:${i2}ms`,".s-panels":"flex:1 min-width:0 min-height:0 position:relative overflow:clip isolation:isolate "+f1,".s-panel":{"&":"position:absolute top:0 bottom:0 left:0 display:flex flex-direction:column "+f1+" visibility:visible transition: left var(--s-panel-ms) ease, transform var(--s-panel-ms) ease-out, opacity var(--s-panel-ms) linear, visibility 0s;","&.s-panel-sep::before":"content:'' position:absolute left:0 top:0.6rem bottom:0.6rem width:1px z-index:1 background: linear-gradient(to bottom, transparent, $s-faint 18%, $s-faint 82%, transparent);","&.s-panel-enter":"opacity:0 transition:none transform: translateX(8cqw);","&.s-panel-closing":"opacity:0 pointer-events:none transform: translateX(8cqw);","&.s-panel-hidden, &.s-panel-parked":"opacity:0 visibility:hidden transition: left var(--s-panel-ms) ease, transform var(--s-panel-ms) ease-out, opacity var(--s-panel-ms) linear, visibility var(--s-panel-ms);","&.s-panel-hidden":"transform: translateX(-8cqw);","&.s-panel-parked":"transform: translateX(8cqw);"},".s-panel > .s-content":"flex:1 min-height:0 overflow-y:auto overflow-x:hidden p:$3",".s-panel-actions":"display:flex align-items:center justify-content:flex-end gap:$1 flex-shrink:0 padding: $3 $3 0;",".s-crumbs > .s-strip-row":"gap:$m1",".s-crumb":{"&":"flex: 1 0 4rem; font-size:0.85em line-height:1.5 fg:$s-muted text-decoration:none white-space:nowrap max-width:max-content overflow:hidden text-overflow:ellipsis transition: color 0.12s;","&.s-crumb-on":"font-weight:600 fg:$s-text","a&:hover":"filter:none color: color-mix(in lab, $s-primary 33%, $s-text);","svg.s-crumb-pin":"vertical-align:-0.12em margin-right:0.3em opacity:0.8 fill:currentColor","svg.s-crumb-unsaved":"vertical-align:0.08em margin-right:0.3em fill:currentColor"},"svg.s-crumb-sep":"flex-shrink:0 opacity:0.4",".s-main.s-shell-snap .s-panel":"transition:none",".s-panel-loading":{"&":"position:absolute inset:0 display:flex align-items:center justify-content:center gap:$1 pointer-events:none",i:"width:0.5rem height:0.5rem r:50% background:$s-muted opacity:0.45 animation: s-panel-pulse 1s ease-in-out infinite;","i:nth-child(2)":"animation-delay:0.15s","i:nth-child(3)":"animation-delay:0.3s"},"@keyframes s-panel-pulse":{"0%, 100%":"opacity:0.25 transform:scale(0.8)","50%":"opacity:0.7 transform:scale(1)"}});var O1=!1,m1=class{[d2]=!0;compiled;ancestors;opts;$state=s.proxy({live:[],focus:0});$open=s.proxy({});nextOrder=0;containerEl;geom;lastGeom;layoutQueued=!1;timers=new Set;intent=null;settling=null;lastSeen=null;queued=null;constructor(a){if(O1)throw new Error("Staffa: only one routed S.main() (one with `routes`) can be active at a time");O1=!0,this.opts=a,this.compiled=Object.entries(a.routes).map(([h,e])=>({...o2(h),draw:e})),this.ancestors=Object.entries(a.ancestors??{}).filter(h=>h[1]!=null).map(([h,e])=>({...o2(h),fn:e})),s(()=>{let h=this.computeTarget(),e={...H.current.search},p=H.current.hash;s.peek(()=>{let r=this.lastSeen;if(r&&r.path!==H.current.path){let d=this.$state.live.find(o=>o.path===r.path);d&&(d.search=r.search,d.hash=r.hash)}this.lastSeen={path:H.current.path,search:e,hash:p},this.propose(h),Array.isArray(H.current.state.panels)||Object.assign(H.current.state,this.stateFor({stack:this.paths(),focus:this.$state.focus}))})}),this.interceptLinks(),this.watchTitle(),this.guardTabClose(),s.clean(()=>{for(let h of this.timers)clearTimeout(h);this.timers.clear(),this.queued?.settle(!1),this.queued=null,O1=!1})}resolve(a){let h=r1(a);for(let e of this.compiled){let p=P1(e,h);if(p)return{draw:e.draw,params:p}}return{draw:this.opts.notFound??h0,params:{}}}matches(a){let h=r1(a);return this.compiled.some(e=>P1(e,h)!=null)}deriveStack(a){let h=q(a),e=this.askAncestors(h),p=e?e.map(q):this.prefixesOf(h),r=[];for(let d of p)d!==h&&!r.includes(d)&&this.matches(d)&&r.push(d);return r.push(h),r}askAncestors(a){let h=r1(a);for(let e of this.ancestors){let p=P1(e,h);if(p)return e.fn(p,a)??void 0}}prefixesOf(a){let h=r1(a),e=[];for(let p=1;p<h.length;p++)e.push("/"+h.slice(0,p).join("/"));return e}pinnedIn(a,h){return a.filter(e=>h.includes(e)?!1:this.$state.live.find(p=>p.path===e)?.$panel.pinned===!0)}unsavedAt(a){return this.$state.live.find(h=>h.path===a)?.$panel.unsaved===!0}targetFor(a,h){let e=Array.isArray(h?.panels)?h.panels.map(String):null;if(e){let p=Array.isArray(h.parked)?h.parked.map(String):[],r=q(a),d=new Set([r]),o=c=>c.map(q).filter(u=>!d.has(u)&&!!d.add(u)),n=o(e);return{stack:[...n,r,...o(p)],focus:n.length}}return s.peek(()=>{let p=this.deriveStack(a).slice(0,-1),r=[...p,...this.pinnedIn(this.paths(),[...p,q(a)]),q(a)];return{stack:r,focus:r.length-1}})}computeTarget(){return this.targetFor(H.current.path,H.current.state)}paths(){return this.$state.live.map(a=>a.path)}propose(a){let h=this.$state.live.filter(e=>!a.stack.includes(e.path)&&e.$panel.unsaved).map(e=>e.path);h.length&&(a={stack:[...a.stack,...h],focus:a.focus}),!(n2(this.paths(),a.stack)&&a.focus===this.$state.focus)&&this.commit(a,H.current.nav)}commit(a,h){this.geom=void 0;let e=H.current.state.pinned,p=new Set(Array.isArray(e)?e.map(String):[]),r=new Map(this.$state.live.map(o=>[o.path,o])),d=[];for(let o of a.stack){let n=r.get(o);if(n){r.delete(o),d.push(n);continue}let c=this.createEntry(o,d.length<=a.focus,p.has(o));h!=="load"&&h!=="back"&&(c.enter=!0),d.push(c),this.$open[o]=c}for(let o of r.values())this.beginClose(o);this.$state.live=d,this.$state.focus=Math.min(a.focus,d.length-1),this.scheduleLayout()}createEntry(a,h,e){let{draw:p,params:r}=this.resolve(a),d={[d2]:!0,order:this.nextOrder++,path:a,draw:p,$ui:s.proxy({holding:!1}),maxWidth:"medium",width:0};return d.$panel=s.proxy({stack:this,params:r,path:a,width:0,visible:h,pinned:e||void 0,close:()=>this.closePath(d.path),open:(o,n)=>this.navigate(o,{from:d.path,how:n})}),d}beginClose(a){a.closing=!0,a.$panel.visible=!1,a.el&&(a.el.style.zIndex=String(c2*this.$state.live.indexOf(a))),delete this.$open[a.path]}playExit(a,h){if(!a.closing){h.remove();return}h.classList.add("s-panel-closing"),h.setAttribute("inert","");let e=()=>{clearTimeout(p),this.timers.delete(p),h.remove()};h.addEventListener("transitionend",r=>{r.target===h&&r.propertyName==="opacity"&&e()});let p=setTimeout(e,i2+80);this.timers.add(p)}intended(){return this.intent??{stack:this.paths(),focus:this.$state.focus}}stateFor(a){return{panels:a.stack.slice(0,a.focus),parked:a.stack.slice(a.focus+1),pinned:this.pinnedPaths()}}pinnedPaths(){return this.$state.live.filter(a=>a.$panel.pinned).map(a=>a.path)}issue(a,h){return this.intent=a,this.settling?(this.queued?.settle(!1),new Promise(e=>{this.queued={run:h,settle:e}})):this.start(h)}start(a){let h=p=>{this.settling=null;let r=this.queued;return this.queued=null,p&&r?this.start(r.run).then(r.settle,()=>r.settle(!1)):(this.intent=null,r?.settle(!1)),p},e=Promise.resolve(a()).then(h,p=>(console.error(p),h(!1)));return this.settling=e,e}focusAt(a){let h=this.intended();if(a<0||a>=h.stack.length||a===h.focus)return Promise.resolve(!1);let e={stack:h.stack,focus:a},p=h.stack[a];return this.issue(e,()=>{let r=this.$state.live.find(d=>d.path===p);return H.go({path:p,search:r?.search,hash:r?.hash,state:this.stateFor(e)})})}back(){return s.peek(()=>{let a=this.intended();return a.focus===a.stack.length-1&&!this.unsavedAt(a.stack[a.focus])?this.closePath(a.stack[a.focus]??""):a.focus===0?Promise.resolve(!1):this.focusAt(a.focus-1)})}closePath(a){return s.peek(()=>{let h=this.intended(),e=h.stack.indexOf(q(a));if(e<0||h.stack.length<2||this.unsavedAt(h.stack[e]))return Promise.resolve(!1);let p=h.stack.filter((c,u)=>u!==e),r=e===h.focus?Math.max(0,e-1):h.focus-(e<h.focus?1:0),d={stack:p,focus:r};if(e===h.focus&&e===h.stack.length-1){let c=this.$state.live.find(m=>m.path===p[r]),u={};c?.search&&(u.search=c.search),c?.hash&&(u.hash=c.hash);let i=p.filter(m=>this.$state.live.find(g=>g.path===m)?.$panel.pinned===!0);return this.issue(d,()=>Promise.resolve(H.back({path:p[r],state:{panels:p.slice(0,r),parked:[]}},u)).then(m=>(m&&(H.current.state.pinned=i),m)))}let o=p[r],n=o!==h.stack[h.focus];return this.issue(d,()=>{let c=n?this.$state.live.find(u=>u.path===o):void 0;return H.go({path:o,search:n?c?.search:{...H.current.search},hash:n?c?.hash:H.current.hash,state:this.stateFor(d)})})})}navigate(a,{from:h,how:e,beneath:p}={}){let r=e??this.opts.linkNavigation,d=r==="open"?null:h??null,o=r==="replace";return s.peek(()=>{let n;try{n=new URL(a,location.href)}catch{return Promise.resolve(!1)}let c=q(n.pathname),u=this.intended(),i=p?-1:u.stack.indexOf(c),m;if(i>=0&&r!=="replace"&&r!=="open"){let f=this.pinnedIn(u.stack.slice(i+1),[]);m={stack:[...u.stack.slice(0,i+1),...f],focus:i}}else{let f=d==null?-1:u.stack.indexOf(d),z=(p?p.map(q):f<0?this.deriveStack(c).slice(0,-1):u.stack.slice(0,o?f:f+1)).filter((Z1,M2,x2)=>Z1!==c&&x2.indexOf(Z1)===M2),d1=[...z,...this.pinnedIn(u.stack,[...z,c,o?d:null])];m={stack:[...d1,c],focus:d1.length}}let g=i>=0?this.$state.live.find(f=>f.path===c):void 0,b=n.search?Object.fromEntries(new URLSearchParams(n.search)):g?.search??{},l=n.hash||g?.hash||"";return m.focus===u.focus&&n2(m.stack,u.stack)&&n.search===location.search&&(n.hash||"")===(location.hash||"")?Promise.resolve(!0):this.issue(m,()=>H.go({path:c,search:b,hash:l,state:this.stateFor(m)}))})}pushPath(a,h){return s.peek(()=>{let e=this.intended();return this.navigate(a,{from:e.stack[e.focus],how:h?"replace":"push"})})}interceptLinks(){H.interceptLinks((a,h)=>{let e=h.getAttribute("data-panel")??void 0,p=h.closest(".s-panel"),r=p?this.$state.live.find(d=>d.el===p):h.closest(".s-panel-origin")?this.$state.live[this.$state.focus]:void 0;return this.navigate(a.href,{from:r?.path,how:e}),!0})}get currentPanel(){return this.$state.live[this.$state.focus]?.$panel}get panels(){return this.$state.live.map(a=>a.$panel)}get currentPanelIndex(){return this.$state.focus}pushPanel(a){return this.pushPath(a,!1)}replacePanel(a){return this.pushPath(a,!0)}openPanelStack(a,h){return this.navigate(a,{how:"open",beneath:h})}closePanel(a){return s.peek(()=>{let h=this.intended();return this.closePath(a??h.stack[h.focus]??"")})}setColumns(a){this.opts.columns!==a&&(this.opts.columns=a,this.scheduleLayout())}setLinkNavigation(a){this.opts.linkNavigation=a}drawCrumbs(){x1({attrs:".s-crumbs role=navigation aria-label=Breadcrumbs",content:()=>{s(()=>{let a=this.panels.map(p=>p.path),h=this.currentPanelIndex,e;for(let p=0;p<a.length;p++){p&&_1({size:"0.85em",attrs:".s-crumb-sep"});let r=this.drawCrumb(a[p],p,p===h);p===h&&(e=r)}requestAnimationFrame(()=>{e&&v1(e)})})}})}drawCrumb(a,h,e){let p=this.$state.live[h];return s(e?"span.s-crumb aria-current=page":"a.s-crumb",()=>{e||s("href=",a),s(()=>{p?.$panel.visible&&s(".s-crumb-on")}),s(()=>{p?.$panel.unsaved&&X1({size:"0.45em",attrs:".s-crumb-unsaved"})}),s(()=>{p?.$panel.pinned&&g1({size:"0.85em",attrs:".s-crumb-pin"})}),s(()=>{s("#",p?.$panel.title??p?.$ui.fallback??(a.split("/").pop()||a))}),C1({link:a,items:[{label:()=>{s(()=>{s("#",p?.$panel.pinned?"Unpin":"Pin")})},icon:()=>{s(()=>{(p?.$panel.pinned?j1:g1)()})},click:()=>{p&&this.togglePin(p)}},{label:"Close",icon:J,disabled:p?.$panel.unsaved===!0,click:()=>{this.closePath(a)}}]})})}togglePin(a){a.$panel.pinned=!a.$panel.pinned||void 0,H.current.state.pinned=this.pinnedPaths()}watchTitle(){let a=document.title;s(()=>{let h=this.$state.live[this.$state.focus],e=h?.$panel.title??h?.$ui.fallback,p=typeof this.opts.title=="string"?this.opts.title:void 0,r=this.$state.live.some(o=>o.$panel.unsaved),d=e&&p?`${e} \xB7 ${p}`:e||p;d&&(document.title=(r?"\u2022 ":"")+d)}),s.clean(()=>{document.title=a})}guardTabClose(){if(typeof window>"u")return;let a=h=>{let e=this.$state.live.find(p=>p.$panel.unsaved);e&&(h.preventDefault(),h.returnValue=!0,e.$panel.visible||this.focusAt(this.intended().stack.indexOf(e.path)))};s(()=>{this.$state.live.some(h=>h.$panel.unsaved)&&(window.addEventListener("beforeunload",a),s.clean(()=>window.removeEventListener("beforeunload",a)))})}drawColumns(){let a=s("div.s-panels role=main",()=>{this.containerEl=s(),s.onEach(this.$open,h=>this.drawPanel(h),h=>h.order)});if(typeof ResizeObserver<"u"){let h=new ResizeObserver(()=>this.layout());h.observe(a),s.clean(()=>h.disconnect())}s.clean(()=>{this.containerEl===a&&(this.containerEl=void 0)}),this.scheduleLayout()}drawPanel(a){let h;s(()=>{let e=a.$panel.maxWidth;a.maxWidth=e==="small"||e==="large"||e==="none"?e:"medium";let p=this.roomFor(a.maxWidth);p&&(a.width=p,s.peek(a.$panel,"width")!==p&&(a.$panel.width=p),h&&(h.style.width=`${p}px`,this.scheduleLayout()))}),h=s(`section.s-panel${a.width?` w:${a.width}px`:""}`,"destroy=",e=>this.playExit(a,e),()=>{s(()=>this.drawActions(a)),s("div.s-content",()=>{if(a.draw(a.$panel),H.persistScroll(a.path),s.peek(a.$panel,"title")==null){let e=a0(s());e&&s.peek(a.$ui,"fallback")!==e&&(a.$ui.fallback=e)}}),s(()=>{!a.$panel.loading||a.$ui.holding||s("div.s-panel-loading aria-hidden=true",()=>{s("i"),s("i"),s("i")})})}),a.el=h,a.placed=!1,h.style.transition="none",s.clean(()=>{a.el===h&&(a.el=void 0)}),s(()=>{a.$panel.loading,this.scheduleLayout()}),this.scheduleLayout()}drawActions(a){this.opts.$shell.narrow||a.$panel.actions==null||s("div.s-panel-actions",()=>v(a.$panel.actions))}scheduleLayout(){this.layoutQueued||(this.layoutQueued=!0,requestAnimationFrame(()=>{this.layoutQueued=!1,this.layout()}))}measure(){let a=this.containerEl,h=a?a.getBoundingClientRect().width/B(a):0;if(!h)return;let e=Math.min(h/Math.max(1,Math.floor(h/Y2)),q1),p=r=>Math.min(r*e,h);return{area:h,size:{small:e,medium:p(2),large:p(3),none:h}}}geometry(){return this.geom??=this.measure()}roomFor(a){return this.geometry()?.size[a]??0}layout(){let a=this.containerEl,h=a?.closest(".s-main");if(!a||!h)return;let e=this.$state.live,p=e.length;if(!p||e.some(l=>!l.el))return;this.geom=void 0;let r=this.geometry();if(!r)return;let d=this.opts.columns==="single",o=this.lastGeom?.area!==r.area;o&&(this.lastGeom=r,h.classList.add("s-shell-snap"));let n=l=>r.size[l.maxWidth],c=Math.min(this.$state.focus,p-1),u=c,i=n(e[c]);if(!d)for(let l=c-1;l>=0;l--){let f=i+n(e[l]);if(f>r.area)break;i=f,u=l}let m=(r.area-i)/2;for(let l=u;l<=c;l++)e[l].width=n(e[l]);for(let l of e)l.width||(l.width=n(l));let g=[],b=m;for(let l=0;l<p;l++){let f=e[l],C=f.el,z=l>=u&&l<=c;t0(C,z?b:l>c?m+i:m,f.width,c2*l+1),f.$panel.visible!==z&&(f.$panel.visible=z),f.$panel.width!==f.width&&(f.$panel.width=f.width),z&&(b+=f.width),C.classList.toggle("s-panel-sep",z&&l>u),C.classList.toggle("s-panel-hidden",l<u),C.classList.toggle("s-panel-parked",l>c),C.toggleAttribute("inert",!z),!f.placed&&(g.push(f),!f.$panel.loading||f.holdDone?f.$ui.holding=!1:f.$ui.holding||(f.$ui.holding=!0,this.holdEnter(f)),f.enter&&z&&C.classList.add("s-panel-enter"))}(g.length||o)&&a.offsetWidth,o&&h.classList.remove("s-shell-snap");for(let l of g)l.$ui.holding||(l.el.style.transition="",l.el.classList.remove("s-panel-enter"),l.enter=!1,l.placed=!0)}holdEnter(a){let h=setTimeout(()=>{this.timers.delete(h),a.holdDone=!0,a.$ui.holding&&(a.$ui.holding=!1,this.scheduleLayout())},J2);this.timers.add(h)}};function t0(t,a,h,e){t.style.left=`${a}px`,t.style.width=`${h}px`,t.style.zIndex=String(e)}function n2(t,a){return t.length===a.length&&t.every((h,e)=>h===a[e])}function a0(t){let a=document.createTreeWalker(t,NodeFilter.SHOW_TEXT);for(let h=a.nextNode();h;h=a.nextNode()){let e=h.textContent.trim();if(e)return e.length>48?`${e.slice(0,47).trimEnd()}\u2026`:e}}function h0(t){s("p fg:$s-muted",()=>s("#",`No panel at ${t.path}`))}var e0=200;x.insertGlobalCss({".s-main":{"&":"display:flex flex-direction:column min-height:calc(100vh/var(--s-zoom,1)) max-height:calc(100vh/var(--s-zoom,1)) container-type:inline-size","body > &":"margin: calc(-1 * $3)","> header":"border:0 border-bottom: 1px solid $s-faint; r:0 position:sticky top:0 z-index:10","> footer":"border-top: 1px solid $s-faint; fg:$s-muted","> header > .s-bar, > footer > .s-bar":"display:flex align-items:center width:100% margin-inline:auto gap:$3 padding: $2 $3;","> header .s-logo, > header .s-nav-trigger":"display:flex align-items:center flex-shrink:0","> header .s-nav-trigger":"margin-left:-0.375rem","> header .s-logo":"font-size:1.4em background: $s-gradient; -webkit-background-clip:text; background-clip:text; color:transparent;","> header .s-titles":"display:flex flex-direction:column min-width:5rem flex: 0 1 auto;","> header .s-subtitle":"fg:$s-muted font-size:0.85em line-height:1.5 overflow:hidden text-overflow:ellipsis white-space:nowrap","> header .s-title":"font-weight:800 font-size:1.1em line-height:1.2 overflow:hidden text-overflow:ellipsis white-space:nowrap letter-spacing:-0.01em background: $s-gradient; -webkit-background-clip:text; background-clip:text; color:transparent; width:fit-content max-width:100%","> header a.s-logo, > header a.s-title":"text-decoration:none filter:none cursor:pointer","> header .s-menu":"display:flex align-items:center justify-content:flex-end gap:$2 flex: 1 0.1 auto; min-width:0",".s-body":"flex:1 overflow:clip display:flex flex-direction:row min-height:0 justify-content:center position:relative",".s-body-inner":"flex:1 min-width:0 display:flex flex-direction:row min-height:0","&.s-nav-right .s-body-inner":"flex-direction:row-reverse",".s-nav-sep":"width:1px flex-shrink:0 align-self:stretch margin: 0.6rem 0; border:0 background: linear-gradient(to bottom, transparent, $s-faint 18%, $s-faint 82%, transparent);",".s-body main":"flex:1 min-width:0 min-height:0 overflow-x:hidden overflow-y:auto display:flex flex-direction:column transition: transform var(--s-panel-ms) ease;",".s-body main.s-slide-in":"transform: translateX(100%); transition:none",".s-body main > .s-content":"width:100% flex:1 p:$3",".s-body main.s-scroll-y":"margin-right:$3"},".s-nav-panel":{"&":"display:flex flex-direction:column overflow-y:auto flex-shrink:0 width: calc(var(--s-nav-w) - 1px); padding:$3 gap:$1"},".s-nav-page":{"&":"position:absolute inset:0 z-index:5 display:flex flex-direction:column overflow-y:auto overscroll-behavior:contain border:0 r:0 padding:$2 gap:$1 transition: transform var(--s-panel-ms) ease, visibility var(--s-panel-ms);","&.s-nav-page-off":"transform:translateX(-100%) pointer-events:none visibility:hidden",".s-menu-item":"padding: $2 $3; min-height:3rem font-size:1.05em gap:$3"},[`@container (max-width: ${o1}px)`]:{".s-main .s-nav-panel, .s-main .s-nav-sep":"display:none",".s-main > header > .s-bar":"gap:$1 padding: $1 $2;",".s-main .s-body main.s-scroll-y":"margin-right:0"},[`@container (max-width: ${q1}px)`]:{".s-content > .s-box":"margin-inline: calc(-1 * $3); r:0 border-inline:0"}});function p0(t={}){let a=t.nav,h=t.navPosition??"left",e=x.proxy({open:!1}),p=x.proxy({narrow:typeof document<"u"&&document.documentElement.clientWidth<=o1}),r=t.routes;if(r!=null&&t.content!=null)throw new Error("Staffa: S.main() takes either `content` or `routes`, not both");let d=r?new m1({routes:r,notFound:t.notFound,ancestors:t.ancestors,title:t.title,$shell:p}):null;d&&(x(()=>d.setColumns(t.columns)),x(()=>d.setLinkNavigation(t.linkNavigation)));let o=d&&t.home!==null?t.home??"/":null,n=()=>{t.maxWidth!=null&&x("max-width:",t.maxWidth)},c=x("div.s-main",t.attrs,()=>{x(()=>{a==null||!a.items.length?x("--s-nav-w: 0px"):x(`.s-nav-${h}`,`--s-nav-w: ${t.navWidth??e0}px`)}),x(()=>{(d!=null||t.title!=null||t.subtitle!=null||t.logo!=null||t.menu!=null||a!=null&&a.items.length>0)&&x("header.s-s.neutral",t.topbarAttrs,()=>{x("div.s-bar",()=>{x(n),x(()=>{if(p.narrow&&a!=null&&a.items.length){x("div.s-nav-trigger",()=>i0(a,e));return}t.logo!=null&&x(o!=null?"a.s-logo aria-label=Home":"div.s-logo",()=>{o!=null&&x("href=",o),v(t.logo)})}),x("div.s-titles",()=>{x(()=>{t.title!=null&&x(o!=null?"a.s-title":"div.s-title",()=>{o!=null&&x("href=",o),v(t.title)})}),d0(t,d,a,p)}),x(()=>{let i=p.narrow?d?.currentPanel?.actions:void 0,m=i??t.menu;m!=null&&x(`div.s-menu${i!=null?".s-panel-origin":""}`,()=>v(m))})})})}),x("div.s-body",()=>{x("div.s-body-inner",()=>{x(n),x(()=>{a==null||!a.items.length||(x(`nav.s-nav-panel.s-nav-${h}`,t.navAttrs,()=>{p1(a.items)}),x("div.s-nav-sep aria-hidden=true"))}),M0(t,d)}),x(()=>{a!=null&&a.items.length&&e.open&&s0(a,t.navPageAttrs,e,p)})}),x(()=>{t.footer!=null&&x("footer",()=>{x("div.s-bar",()=>{x(n),v(t.footer)})})})});if(n0(c,p),c0(),a!=null||d){let u=i=>{if(i.key!=="Escape"||i.defaultPrevented||$1()||l1())return;let m=c.querySelector(".s-nav-trigger button");if(e.open){i.preventDefault(),e.open=!1,m?.focus();return}if(d&&d.currentPanelIndex>0){i.preventDefault(),d.back();return}let g=c.querySelector(".s-nav-panel");if(g?.offsetParent!=null){let b=g.querySelector("[aria-current=page]")??g.querySelector(".s-menu-item:not([aria-disabled=true])");b&&(i.preventDefault(),b.focus());return}m&&(i.preventDefault(),m.click())};document.addEventListener("keydown",u),x.clean(()=>document.removeEventListener("keydown",u))}return d??void 0}var u1=null;function r0(){u1?.()}function d0(t,a,h,e){x(()=>{if(t.subtitle!=null&&(a==null||o0(a,h,e))){x("div.s-subtitle",()=>v(t.subtitle));return}a?.drawCrumbs()})}function o0(t,a,h){return h.narrow||a==null||t.panels.length>1?!1:H1(a.items)}var s2=0;function D1(){let t=document.documentElement.clientWidth,a=t&&t<t1?t/t1:0;document.body.style.zoom=a?String(a):"",a?document.body.style.setProperty("--s-zoom",String(a)):document.body.style.removeProperty("--s-zoom")}function c0(){typeof window>"u"||!("currentCSSZoom"in document.documentElement)||(++s2===1&&(window.addEventListener("resize",D1),D1()),x.clean(()=>{--s2===0&&(window.removeEventListener("resize",D1),document.body.style.zoom="",document.body.style.removeProperty("--s-zoom"))}))}function n0(t,a){if(typeof ResizeObserver>"u")return;let h=new ResizeObserver(e=>{let p=e[0]?.contentBoxSize?.[0],r=p?p.inlineSize:e[0]?.contentRect.width;r!=null&&(a.narrow=r<=o1)});h.observe(t),x.clean(()=>h.disconnect())}function i0(t,a){h1({icon:t.button?.icon??(()=>x(()=>(a.open?J:c1)())),ariaLabel:t.button?.ariaLabel??"Open navigation",attrs:t.button?.attrs,click:()=>{a.open=!a.open}})}function s0(t,a,h,e){let p=!1,r=()=>{p=!0,h.open=!1},d=x("nav.s-nav-page.s-s.neutral aria-label=Navigation create=s-nav-page-off destroy=s-nav-page-off",a,()=>p1(t.items,r));u1=r,x.clean(()=>{u1===r&&(u1=null)});let o=x.peek(T1,"path");x(()=>{T1.path!==o&&!k1(T1.path)&&r()});let n=d.closest(".s-main"),c=d.parentElement?.querySelector(":scope > .s-body-inner"),u=c?.querySelector(":scope > main");c?.setAttribute("inert",""),x(()=>{e.narrow||(h.open=!1)}),x.clean(()=>{c?.removeAttribute("inert"),p&&(u&&l0(u),n?.querySelector(".s-nav-trigger button")?.focus())}),requestAnimationFrame(()=>{document.body.contains(d)&&_(d,".s-menu-item[aria-current=page]")})}function l0(t){t.classList.add("s-slide-in"),t.offsetWidth,t.classList.remove("s-slide-in")}function M0(t,a){if(a){a.drawColumns();return}let h=x("main",()=>{x("div.s-content",t.contentAttrs,()=>{v(t.content)})});x0(h)}function x0(t){if(typeof ResizeObserver>"u")return;let a=()=>t.classList.toggle("s-scroll-y",t.offsetWidth>t.clientWidth),h=new ResizeObserver(a);h.observe(t),t.firstElementChild&&h.observe(t.firstElementChild),a(),x.clean(()=>h.disconnect())}import $ from"aberdeen";$.insertGlobalCss({".s-select_wrap":{"&":"position:relative display:block",select:"w:100% cursor:pointer padding-right:2.2em; appearance:none","&::after":"content: '\u25BE'; position:absolute right:0.7em top:50%; transform: translateY(-50%); pointer-events:none fg:$s-muted font-size:0.85em"}});function v0(t){U(t,(a,h)=>{$("div.s-select_wrap",()=>{$("select.s-input",t.inputAttrs,()=>{Q(t,a,h),$("change=",e=>{t.bind&&(t.bind.value=e.target.value)}),$(()=>{let e=typeof t.options=="function"?t.options():t.options,p=t.bind?.value??"";t.placeholder!=null&&$("option",()=>{$("value= disabled=true hidden=true"),p||$("selected=true"),$("#",t.placeholder)});for(let r of e){let d=typeof r=="string"?{value:r,label:r}:{value:r.value,label:r.label??r.value};$("option",()=>{$("value=",d.value),d.value===p&&$("selected=true"),$("#",d.label)})}})})})})}import T from"aberdeen";T.insertGlobalCss({"textarea.s-input":"resize:vertical min-height:3em line-height:1.45","textarea.s-input.s-autoGrow":"resize:none min-height:2.5em overflow-y:hidden"});function m0(t={}){let a=t.autoGrow!==!1;U(t,(h,e)=>{let p=T("textarea.s-input",t.inputAttrs,()=>{a?(T(".s-autoGrow"),T("input=",r=>{l2(r.currentTarget),t.input&&t.input(r)})):(T("rows=",t.rows??4),T("resize:",t.resize??"vertical"),t.input&&T("input=",t.input)),t.placeholder!=null&&T("placeholder=",t.placeholder),t.value!=null&&!t.bind&&T("value=",t.value),t.change&&T("change=",t.change),Q(t,h,e,t.bind)});a&&requestAnimationFrame(()=>l2(p))})}function l2(t){t.style.height="auto",t.style.height=`${t.scrollHeight}px`}import D from"aberdeen";D.insertGlobalCss({".s-tt-tip":{"&":"position:fixed z-index:500 max-width:20rem w:max-content padding: 0.3em 0.65em; font-size:0.85em line-height:1.4 pointer-events:none"}});var Y=D.proxy(void 0),R=null;typeof window<"u"&&window.addEventListener("scroll",()=>{Y.value=void 0},{capture:!0,passive:!0});function u0(t,a,h,e,p){let d=window.innerWidth/p,o=window.innerHeight/p,n=0,c=0;return e==="bottom"?(n=t.left+(t.width-a)/2,c=t.bottom+7,c+h>o-8&&(c=t.top-h-7)):e==="left"?(n=t.left-a-7,c=t.top+(t.height-h)/2,n<8&&(n=t.right+7)):e==="right"?(n=t.right+7,c=t.top+(t.height-h)/2,n+a>d-8&&(n=t.left-a-7)):(n=t.left+(t.width-a)/2,c=t.top-h-7,c<8&&(c=t.bottom+7)),{x:Math.max(8,Math.min(n,d-a-8)),y:Math.max(8,Math.min(c,o-h-8))}}function R1(){R&&clearTimeout(R),R=setTimeout(()=>{Y.value=void 0,R=null},100)}F(()=>{let t=Y.value;if(!t)return;let{opts:a,anchor:h}=t,e=a.placement??"top",p=D("div.s-tt-tip.s-s.neutral.shadow role=tooltip visibility:hidden",a.attrs,()=>{D("mouseenter=",()=>{R&&(clearTimeout(R),R=null)}),D("mouseleave=",R1),v(a.tip)});requestAnimationFrame(()=>{if(!document.body.contains(p))return;let r=B(p),d=h.getBoundingClientRect(),o=new DOMRect(d.x/r,d.y/r,d.width/r,d.height/r),{x:n,y:c}=u0(o,p.offsetWidth,p.offsetHeight,e,r);p.style.left=n+"px",p.style.top=c+"px",p.style.visibility=""})});function y0(t){let a=h=>{R&&(clearTimeout(R),R=null),Y.value={opts:t,anchor:h.currentTarget}};D("mouseenter=",a),D("mouseleave=",R1),D("focusin=",a),D("focusout=",R1),D.clean(()=>{Y.value?.opts===t&&(Y.value=void 0)})}export{C1 as addContextMenu,y0 as addTooltip,U2 as alert,b2 as autocomplete,A2 as box,O as button,V2 as buttonChooser,X as buttonGroup,k2 as checkbox,D2 as closeFloatingMenu,r0 as closeNav,N2 as confirm,M1 as dialog,L2 as form,U1 as getDarkMode,h1 as iconButton,$1 as isDialogOpen,l1 as isFloatingMenuOpen,p0 as main,I2 as menu,F2 as menuButton,W2 as prompt,v1 as revealInStrip,x1 as scrollStrip,v0 as select,m2 as setDarkMode,L1 as showFloatingMenu,K2 as tabs,m0 as textarea,z1 as textline,n1 as toast};
|
|
1
|
+
import q from"aberdeen";var R1=t=>`background: linear-gradient(${t}, color-mix(in oklab, $s-bg, white 9%), color-mix(in oklab, $s-bg, black 9%));`,D1=R1("170deg"),u1=R1("180deg"),m1="staffa:darkMode",Z1=q.proxy({value:s2()});function s2(){try{let t=localStorage.getItem(m1);if(t==="dark")return!0;if(t==="light")return!1}catch{}}function l2(t){Z1.value=t;try{t===void 0?localStorage.removeItem(m1):localStorage.setItem(m1,t?"dark":"light")}catch{}}function B1(t=!1){let a=Z1.value;return a===void 0&&!t?q.darkMode():a}q(()=>{B1()?q.insertGlobalCss({":root, .s-s.neutral":"--s-bg:#0e0f12 --s-text:#e9eaec",".s-s.neutral":"--s-bg:#191b1f --s-text:#e9eaec",".s-s.neutral .s-s.neutral":"--s-bg:#23262b"}):q.insertGlobalCss({":root, .s-s.neutral":"--s-bg:#eef0f3 --s-text:#1d1f24",".s-s.neutral, .s-s.neutral":"--s-bg:#ffffff --s-text:#1d1f24",".s-s.neutral .s-s.neutral":"--s-bg:#f6f7f9"})});q.setSpacingCssVars(1.1);q.insertGlobalCss({"*, *::before, *::after":"box-sizing:border-box",html:"text-size-adjust:100%",body:"m:0 p:$3 line-height:1.5 font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; -webkit-font-smoothing:antialiased background-color:$s-bg text:$s-text",a:"color: $s-link-fg; text-decoration:underline text-underline-offset:2px; transition: color 0.12s, filter 0.12s;","a:hover":"filter: brightness(1.15)","input, button, textarea, select, optgroup":"font:inherit color:inherit","input:where(:not([type=checkbox],[type=radio],[type=range],[type=file],[type=color],[type=image],[type=submit],[type=button],[type=reset],[type=hidden])), textarea, select":"background:$s-bg border: 1px solid $s-faint; r:$s-radius-sm padding: 0.45em 0.65em; max-width:100%","input:where([type=checkbox],[type=radio])":"width:1.15em height:1.15em cursor:pointer","input[type=range]":"appearance:none background:transparent cursor:pointer vertical-align:middle","input[type=range]::-webkit-slider-runnable-track":"height:4px r:99px background:$s-faint","input[type=range]::-moz-range-track":"height:4px r:99px background:$s-faint","input[type=range]::-moz-range-progress":"height:4px r:99px background:$s-accent","input[type=range]::-webkit-slider-thumb":"appearance:none width:16px height:16px margin-top:-6px r:50% background:$s-accent","input[type=range]::-moz-range-thumb":"width:16px height:16px border:0 r:50% background:$s-accent","input[type=file]":"cursor:pointer",progress:"appearance:none border:0 height:6px r:99px background:$s-faint overflow:hidden vertical-align:middle","progress::-webkit-progress-bar":"background:$s-faint r:99px","progress::-webkit-progress-value":"background:$s-accent r:99px","progress::-moz-progress-bar":"background:$s-accent r:99px",meter:"vertical-align:middle",fieldset:"border: 1px solid $s-faint; r:$s-radius-sm padding:$2 min-width:0",legend:"padding: 0 $1; font-weight:600","code, kbd, samp, pre":"font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;",code:"background: color-mix(in oklab, $s-text, $s-bg 86%); padding: 0.12em 0.34em; r:4px font-size:0.9em",pre:"background: color-mix(in oklab, $s-text, $s-bg 92%); p:$3 r: $s-radius; overflow:auto","pre code":"background:transparent p:0","img, svg, video, canvas":"max-width:100% h:auto",hr:"border:0 border-top: 1px solid $s-faint;","::placeholder":"color: $s-muted; opacity:1",":focus-visible":"outline: 2px solid $s-focus; outline-offset:2px",small:"color:$s-muted font-size:0.9em","@media (prefers-reduced-motion: reduce)":{"*, *::before, *::after":"transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; scroll-behavior: auto !important;"},":root":"--s-primary:#00a884 --s-danger:#dc5b41 --s-success:#00a884 --s-warning:#ef6b00 --s-link:#3f8cd8 --s-radius-sm:6px --s-radius:12px --s-radius-lg:18px --s-focus: color-mix(in srgb, $s-primary 38%, transparent); --s-gradient: linear-gradient(135deg, color-mix(in oklab, $s-primary, white 16%), color-mix(in oklab, $s-primary, black 14%));",":root, .s-s.neutral":"--s-accent:$s-primary --s-link-fg:$s-link",".s-s:not(.neutral)":"--s-bg:$s-primary border:0 --s-text:#eee --s-accent:#fff --s-link-fg:#eef --s-muted: color-mix(in srgb, #fff 70%, transparent); --s-faint: color-mix(in srgb, #fff 30%, transparent);",".s-s.danger":"--s-bg:$s-danger",".s-s.success":"--s-bg:$s-success",".s-s.warning":"--s-bg:$s-warning",".s-s.link":"--s-bg:$s-link",".s-s.primary":"--s-bg:$s-primary",":root, .s-s":"--s-muted: color-mix(in oklab, $s-text, $s-bg 42%); --s-faint: color-mix(in oklab, $s-text, $s-bg 80%); color:$s-text accent-color:$s-accent scrollbar-width:thin scrollbar-color: $s-faint transparent;",".s-s, body":D1,".s-s":"r:$s-radius",":where(.s-s.neutral)":"border: 1px solid $s-faint;",".s-s::-webkit-scrollbar, .s-s ::-webkit-scrollbar":"width:10px height:10px",".s-s::-webkit-scrollbar-track, .s-s ::-webkit-scrollbar-track":"background:transparent",".s-s::-webkit-scrollbar-thumb, .s-s ::-webkit-scrollbar-thumb":"background:$s-faint border-radius:99px border: 2px solid transparent; background-clip:padding-box",".s-s.shadow.neutral:not(.s-btn)":"box-shadow: 0 4px 14px rgba(0,0,0,0.13);",".s-s.extra-shadow.neutral:not(.s-btn)":"box-shadow: 0 18px 50px rgba(0,0,0,0.28);",".s-s.shadow:not(.neutral):not(.tonal):not(.outlined)":"box-shadow: 0 4px 14px color-mix(in srgb, $s-bg 30%, transparent);",".s-s.extra-shadow:not(.neutral):not(.tonal):not(.outlined)":"box-shadow: 0 14px 40px color-mix(in srgb, $s-bg 40%, transparent);",".s-s.no-shadow":"box-shadow: none !important;",".s-s:not(.neutral).tonal, .s-s:not(.neutral).outlined":"--s-text:$s-bg --s-accent:$s-bg --s-link-fg:$s-bg --s-faint: color-mix(in srgb, $s-bg 30%, transparent); --s-muted: color-mix(in srgb, $s-bg 70%, transparent);",".s-s:not(.neutral).tonal":"background: color-mix(in srgb, $s-bg 15%, transparent); border: 1px solid $s-faint;",".s-s:not(.neutral).outlined":"background: transparent; border: 1px solid color-mix(in srgb, $s-bg 45%, transparent);",".s-s:not(.neutral) .s-s.tonal, .s-s:not(.neutral) .s-s.outlined":"--s-text:#fff --s-accent:#fff --s-link-fg:#fff "+D1+" border-color: transparent;"});q.insertGlobalCss({".s-preload, .s-preload *, .s-preload *::before, .s-preload *::after":"transition: none !important; animation: none !important;"});if(typeof document<"u"&&typeof requestAnimationFrame=="function"){let t=document.documentElement;t.classList.add("s-preload"),requestAnimationFrame(()=>requestAnimationFrame(()=>t.classList.remove("s-preload")))}q.insertGlobalCss({":disabled, [aria-disabled=true]":"opacity:0.45 filter:saturate(0.6) user-select:none",":disabled, [aria-disabled=true], :disabled *, [aria-disabled=true] *":"pointer-events:none cursor:not-allowed"});var M2="p, ul, ol, dl, blockquote, pre, table, figure, hr, h1, h2, h3, h4, h5, h6";q.insertGlobalCss({[`${M2}`]:{"&":"margin:0","&:not(:first-child)":"margin-top:$3"},"h1, h2, h3, h4, h5, h6":{"&":"line-height:1.15 font-weight:700 text-wrap:balance","&:not(:first-child)":"margin-top:1.4em"},h1:"font-size:2em font-weight:800 letter-spacing:-0.022em",h2:"font-size:1.55em letter-spacing:-0.018em",h3:"font-size:1.3em letter-spacing:-0.011em",h4:"font-size:1.1em",h5:"font-size:0.95em letter-spacing:0.005em",h6:"font-size:0.8em fg:$s-muted text-transform:uppercase letter-spacing:0.07em","ul, ol":{"&":"padding-left:1.5em","> li:not(:first-child), li > &:not(:first-child)":"margin-top:$1"},blockquote:"border-left: 3px solid $s-faint; padding-left: $3; fg: $s-muted",table:"border-collapse:collapse","th, td":"text-align:left padding: $1 $2; border-bottom: 1px solid $s-faint; vertical-align:top",th:"font-weight:600","thead th":"border-bottom: 2px solid $s-faint;",dt:"font-weight:600",dd:"margin-left: 1.5em",figcaption:"fg:$s-muted font-size:0.9em margin-top:$1 text-align:center"});import M from"aberdeen";import F1 from"aberdeen";var r1=640,x2=0;function B(t="s"){return`${t}-${++x2}`}function v(t,...a){t!=null&&(typeof t=="function"?t(...a):F1("rich=",t))}var v2="a[href], button, input, select, textarea, [tabindex]";function j(t,a){let h=p=>p instanceof HTMLElement&&!p.hasAttribute("disabled")&&p.getAttribute("aria-disabled")!=="true"&&p.tabIndex>=0&&p.getClientRects().length>0,e=(a?[...t.querySelectorAll(a)].find(h):void 0)??[...t.querySelectorAll(v2)].find(h);return e?.focus(),e!=null}function F(t){queueMicrotask(()=>F1(t))}import L from"aberdeen";L.insertGlobalCss({".s-field":{"&":"display:flex flex-direction:column gap:$1","> label":"font-weight:600 font-size:0.9em fg:$s-text user-select:none"},".s-req":"fg:$s-danger margin-left:2px",".s-help":"font-size:0.82em fg:$s-muted",".s-error":"font-size:0.82em fg:$s-danger",".s-input":{"&":"w:100% background: color-mix(in oklab, $s-bg, $s-text 4%); color:$s-text border: 1px solid $s-faint; r:$s-radius padding: 0.55em 0.7em; transition: border-color 0.15s, box-shadow 0.15s;","&:hover:not(:disabled)":"border-color: color-mix(in oklab, $s-text, $s-bg 55%);","&:focus-visible":"border-color:$s-accent box-shadow: 0 0 0 3px $s-focus; outline:none","&[aria-invalid=true]":"border-color:$s-danger"}});function I(t,a){let h=t.id??B("field"),e=()=>!!t.error;L("div.s-field",t.attrs,()=>{L(()=>{t.label!=null&&L("label for=",h,()=>{v(t.label),t.required&&L("span.s-req aria-hidden=true #*")})}),a(h,e),L(()=>{t.help!=null&&!t.error&&L("div.s-help",()=>v(t.help))}),L(()=>{t.error&&L("div.s-error role=alert #",t.error)})})}function _(t,a,h,e){L("id=",a),t.name&&L("name=",t.name),L(()=>{t.disabled&&L("disabled=true")}),L(()=>{t.required&&L("aria-required=true")}),L(()=>L("aria-invalid=",h()?"true":"false")),e&&L("bind=",e)}M.insertGlobalCss({".s-ac":{"&":"position:relative","> .s-control":"display:flex flex-wrap:wrap align-items:center gap:$1 background: color-mix(in oklab, $s-bg, $s-text 4%); color:$s-text border: 1px solid $s-faint; r:$s-radius padding: 0.3em 0.4em; cursor:text; transition: border-color 0.15s, box-shadow 0.15s;","> .s-control:hover":"border-color: color-mix(in oklab, $s-text, $s-bg 55%);","> .s-control:focus-within":"border-color:$s-accent box-shadow: 0 0 0 3px $s-focus;","&[aria-invalid=true] > .s-control":"border-color:$s-danger",".s-chip":"display:inline-flex align-items:center gap:$1 font-size:0.85em background: color-mix(in oklab, $s-bg, $s-text 10%); border: 1px solid $s-faint; r:$s-radius padding: 0.1em 0.2em 0.1em 0.5em;",".s-chip > button":"cursor:pointer border:0 background:transparent fg:$s-muted font-size:1.1em line-height:1 padding: 0 0.2em; r:4px",".s-chip > button:hover":"fg:$s-text background:$s-faint",input:"flex:1 min-width:6ch border:0 background:transparent color:inherit outline:none padding:0.25em","> .s-menu":"position:absolute top:100% left:0 right:0 z-index:20 margin-top:4px max-height:15rem overflow-y:auto list-style:none p:$1 margin-bottom:0","> .s-menu li":"margin:0",".s-option":"padding: 0.45em 0.6em; r:6px cursor:pointer transition: background 0.1s;",".s-option[aria-selected=true]":"background: color-mix(in srgb, $s-text 10%, transparent);",".s-add":"fg:$s-accent font-style:italic",".s-empty":"padding: 0.45em 0.6em; fg:$s-muted"}});function m2(t){return typeof t=="string"?{value:t,label:t}:{value:t.value,label:t.label??t.value}}function u2(t){let a=B("ac-menu"),h=M.proxy({query:"",open:!1,active:0}),e=()=>(typeof t.options=="function"?t.options():t.options).map(m2),p=()=>{let n=t.bind?.value;return n==null||n===""?[]:Array.isArray(n)?n:[n]},r=n=>e().find(m=>m.value===n)?.label??n;if(!t.multi){let n=t.bind?M.peek(t.bind,"value"):void 0;typeof n=="string"&&n&&(h.query=M.peek(()=>r(n)))}let d=()=>{let n=new Set(p()),m=e();t.multi&&(m=m.filter(b=>!n.has(b.value)));let g=h.query.trim().toLowerCase();return g&&(m=m.filter(b=>b.label.toLowerCase().includes(g))),m},o=(n,m)=>{if(t.multi){let g=Array.isArray(t.bind?.value)?[...t.bind.value]:[];g.includes(n)||g.push(n),t.bind&&(t.bind.value=g),h.query=""}else t.bind&&(t.bind.value=n),h.query=r(n),h.open=!1;h.active=0,m?.focus()},c=n=>{if(!t.bind)return;let m=t.bind.value??[];t.bind.value=m.filter(g=>g!==n)};I(t,(n,m)=>{M("div.s-ac",t.inputAttrs,()=>{M(()=>M("aria-invalid=",m()?"true":"false"));let g;M("div.s-control",()=>{M("click=",()=>g?.focus()),M(()=>{if(t.multi)for(let b of p())M("span.s-chip",()=>{M("span #",M.peek(()=>r(b))),M("button type=button aria-label=",`Remove ${b}`,()=>{M("#\xD7"),M("click=",l=>{l.stopPropagation(),c(b),g?.focus()})})})}),g=M("input type=text role=combobox autocomplete=off",()=>{M("id=",n,`aria-controls=${a} aria-autocomplete=list`),t.placeholder!=null&&M("placeholder=",t.placeholder),t.disabled&&M("disabled=true"),t.required&&M("aria-required=true"),M("bind=",M.ref(h,"query")),M(()=>M("aria-expanded=",h.open?"true":"false")),M(()=>{let l=d()[h.active];M("aria-activedescendant=",h.open&&l?`${a}-opt-${h.active}`:"")}),M("input=",()=>{h.open=!0,h.active=0}),M("focus=",()=>{h.open=!0}),M("blur=",()=>{setTimeout(()=>u(),150)}),M("keydown=",b=>i(b,g))})}),M(()=>{if(!h.open)return;let b=d(),l=h.query.trim(),f=t.allowCustom!==!1&&l!==""&&!b.some(C=>C.label.toLowerCase()===l.toLowerCase());M("ul.s-menu.s-s.neutral.shadow role=listbox",`id=${a}`,()=>{b.forEach((C,z)=>{M("li.s-option role=option",`id=${a}-opt-${z}`,()=>{M(()=>M("aria-selected=",h.active===z?"true":"false")),M("#",C.label),M("mousedown=",p1=>p1.preventDefault()),M("click=",()=>o(C.value,g)),M("mousemove=",()=>{h.active=z})})}),f&&M("li.s-option.s-add role=option",()=>{M("#",`Add "${l}"`),M("mousedown=",C=>C.preventDefault()),M("click=",()=>o(l,g))}),b.length===0&&!f&&M("li.s-empty #No matches")})}),M(()=>{if(t.name)if(t.multi)for(let b of p())M("input type=hidden",()=>{M("name=",t.name),M("value=",b)});else M("input type=hidden",()=>{M("name=",t.name),M("value=",p()[0]??"")})})})});function i(n,m){let g=d(),b=g.length-1;if(n.key==="ArrowDown")n.preventDefault(),h.open=!0,h.active=Math.min(b,h.active+1);else if(n.key==="ArrowUp")n.preventDefault(),h.active=Math.max(0,h.active-1);else if(n.key==="Enter"){n.preventDefault();let l=g[h.active];l?o(l.value,m):t.allowCustom!==!1&&h.query.trim()?o(h.query.trim(),m):h.open&&(h.open=!1)}else if(n.key==="Escape")h.open&&(n.preventDefault(),h.open=!1,t.multi||(h.query=r(p()[0]??"")));else if(n.key==="Backspace"&&t.multi&&h.query===""){let l=p();l.length&&c(l[l.length-1])}}function u(){h.open=!1,t.multi?h.query="":t.allowCustom!==!1&&h.query.trim()?o(h.query.trim()):h.query=r(p()[0]??"")}}import N from"aberdeen";import y2 from"aberdeen";var Y={size:24,color:"currentColor",strokeWidth:2,cap:"round",join:"round"};function f2(t,a){let h=a.size??Y.size,e=y2('svg.s-icon aria-hidden=true viewBox="0 0 24 24" fill=none',"width=",h,"height=",h,"stroke=",a.color??Y.color,"stroke-width=",a.strokeWidth??Y.strokeWidth,"stroke-linecap=",a.cap??Y.cap,"stroke-linejoin=",a.join??Y.join,a.attrs);e.innerHTML=t}function $(t){return(a={})=>f2(t,a)}var I1=$('<path d="m9 18 6-6-6-6" />');var U1=$('<circle cx="12" cy="12" r="10" />');var N1=$('<path d="M15 3h6v6" /><path d="M10 14 21 3" /><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />');var W1=$('<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" /><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />');var d1=$('<path d="M4 5h16" /><path d="M4 12h16" /><path d="M4 19h16" />');var G1=$('<path d="M12 17v5" /><path d="M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89" /><path d="m2 2 20 20" /><path d="M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11" />'),y1=$('<path d="M12 17v5" /><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z" />');var X1=$('<path d="M22 2 2 22" />');var Q=$('<path d="M18 6 6 18" /><path d="m6 6 12 12" />');import P from"aberdeen";P.insertGlobalCss({".s-btn":{"&":"display:inline-flex align-items:center justify-content:center gap:$2 font-weight:450 line-height:1.1 white-space:nowrap cursor:pointer text-decoration:none padding: $m2 $m3; transition: background 0.15s, border-color 0.15s, color 0.15s, filter 0.15s, box-shadow 0.15s, transform 0.08s;","&:focus-visible":"outline: 3px solid $s-focus; outline-offset: 1px;","&:hover":"filter: brightness(1.06)","&.tonal:hover, &.outlined:hover":"background: color-mix(in srgb, $s-bg 24%, transparent);","&.neutral:hover":"filter:none background: color-mix(in srgb, $s-text 8%, $s-bg);","> svg":"width:1.25em height:1.25em","&:active:not(:disabled)":"transform: translateY(1px)","&.small, .small > &":"padding: $m1 $m2; font-size:0.85em border-radius:$s-radius-sm","&.large, .large > &":"font-size:1.4em border-radius:$s-radius-lg"},".s-icon-btn":{"&":"display:inline-flex align-items:center justify-content:center flex-shrink:0 width:2rem height:2rem p:0 border:0 background:transparent cursor:pointer fg:$s-muted r:$s-radius-sm line-height:1 font-size:1rem text-decoration:none transition: color 0.12s, background 0.12s;","> svg":"width:1.25em height:1.25em","&:hover:not(:disabled):not([aria-disabled=true])":"fg:$s-text background: color-mix(in srgb, $s-text 10%, transparent);","&:focus-visible":"outline: 3px solid $s-focus; outline-offset:1px","&.small, .small > &":"width:1.6rem height:1.6rem font-size:0.8rem","&.large, .large > &":"width:2.4rem height:2.4rem font-size:1.2rem"}});function t1(t){let a=t.href!=null?"a":"button";P(`${a}.s-icon-btn`,t.attrs,()=>{K1(t),P("aria-label=",t.ariaLabel),v(t.icon)})}function K1(t){t.href!=null?(P("role=button"),t.disabled?P("aria-disabled=true"):P("href=",t.href)):(P("type=",t.type??"button"),t.disabled&&P("disabled=true")),t.click&&!t.disabled&&P("click=",t.click)}function O(t={}){let a=typeof t=="string"||typeof t=="function"?{content:t}:t,h=a.href!=null?"a":"button";P(`${h}.s-btn.s-s.shadow`,a.attrs,()=>{K1(a),a.ariaLabel&&P("aria-label=",a.ariaLabel),v(a.icon),v(a.content)})}N.insertGlobalCss({".s-box":{"&":"display:flex flex-direction:column overflow:hidden r: $s-radius-lg; position:relative","&:not(:first-child)":"margin-top: $3","> header":"display:flex align-items:center gap:$2 padding: $2 $3; border:0 border-bottom: 1px solid $s-faint; r:0 font-weight:600","> footer":"display:flex align-items:center justify-content:flex-end gap:$2 padding: $2 $3; border:0 border-top: 1px solid $s-faint; r:0","> div":"p:$3 gap:$3","> header > .s-box-close":"margin-left:auto","> .s-box-close":"position:absolute top:$2 right:$2 z-index:1"}});function g2(t={}){let a=typeof t=="string"||typeof t=="function"?{content:t}:t;N("section.s-box.s-s.neutral.shadow",a.attrs,()=>{N(()=>{a.header!=null?N("header.s-s.neutral",a.headerAttrs,()=>{v(a.header),typeof a.close=="function"&&j1(a.close)}):typeof a.close=="function"&&j1(a.close)}),N("div",a.contentAttrs,()=>{v(a.content)}),N(()=>{a.footer!=null&&N("footer.s-s.neutral",a.footerAttrs,()=>v(a.footer))})})}function j1(t){t1({icon:Q,ariaLabel:"Close",click:t,attrs:".s-box-close"})}import f1 from"aberdeen";import _1 from"aberdeen";_1.insertGlobalCss({".s-bgroup":{"&":"display:inline-flex align-items:stretch","&.s-spaced":"gap:$2 flex-wrap:wrap","&.s-vertical":"flex-direction:column","&.s-attached":"gap:0","&.s-attached:not(.s-vertical) > .s-btn:not(:first-child)":"margin-left:-1px","&.s-attached:not(.s-vertical) > .s-btn:not(:first-child):not(:last-child)":"r:0","&.s-attached:not(.s-vertical) > .s-btn:first-child:not(:last-child)":"border-top-right-radius:0 border-bottom-right-radius:0","&.s-attached:not(.s-vertical) > .s-btn:last-child:not(:first-child)":"border-top-left-radius:0 border-bottom-left-radius:0","&.s-attached.s-vertical > .s-btn:not(:first-child)":"margin-top:-1px","&.s-attached.s-vertical > .s-btn:not(:first-child):not(:last-child)":"r:0","&.s-attached.s-vertical > .s-btn:first-child:not(:last-child)":"border-bottom-left-radius:0 border-bottom-right-radius:0","&.s-attached.s-vertical > .s-btn:last-child:not(:first-child)":"border-top-left-radius:0 border-top-right-radius:0","&.s-attached > .s-btn:hover, &.s-attached > .s-btn:focus-visible":"z-index:1"}});function W(t={}){let h=`.s-${t.layout??"attached"}${t.vertical?".s-vertical":""}`;_1(`div.s-bgroup${h} role=group`,t.attrs,()=>{if(t.buttons)for(let e of t.buttons)O(e);v(t.content)})}function b2(t){f1(()=>{let a=t.bind.value;W({attrs:t.attrs,buttons:Object.entries(t.options).map(([h,e])=>({content:e,ariaLabel:typeof e=="function"?h:void 0,attrs:a===h?".primary":".neutral",click:()=>{t.bind.value=t.allowDeselect&&a===h?void 0:h}}))})}),t.name&&f1(()=>f1("input type=hidden name=",t.name,"value=",t.bind.value??""))}import k from"aberdeen";k.insertGlobalCss({".s-check":{"&":"display:flex flex-direction:column gap:$1","> label":"display:flex align-items:center gap:$2 cursor:pointer user-select:none","> label:has(input:disabled)":"cursor:not-allowed opacity:0.45 filter:saturate(0.6)",input:"cursor:inherit m:0"}});function w2(t={}){let a=t.id??B("check");k("div.s-check",t.attrs,()=>{k("label for=",a,()=>{k("input type=checkbox",t.inputAttrs,()=>{k("id=",a),t.name&&k("name=",t.name),t.checked&&!t.bind&&k("checked=true"),t.change&&k("change=",t.change),k(()=>{t.disabled&&k("disabled=true")}),k(()=>{t.required&&k("aria-required=true")}),t.bind&&k("bind=",t.bind)}),k(()=>{t.label!=null&&v(t.label),t.required&&k("span.s-req aria-hidden=true #*")})}),k(()=>{t.help!=null&&!t.error&&k("div.s-help",()=>v(t.help))}),k(()=>{t.error&&k("div.s-error role=alert #",t.error)})})}import G from"aberdeen";G.insertGlobalCss({".s-form":{"&":"display:flex flex-direction:column gap:$3","&.grid":"display:grid grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap:$3","&.grid > .s-wide, &.grid > footer":"grid-column: 1 / -1;","> footer":"display:flex align-items:center justify-content:flex-end gap:$2 flex-wrap:wrap margin-top:$1"}});function H2(t={}){let a=typeof t=="string"||typeof t=="function"?{content:t}:t;G("form.s-form",a.attrs,()=>{G(()=>{G(".grid=",a.layout==="grid")}),G("submit=",h=>{if(h.preventDefault(),a.submit){let e=new FormData(h.target),p={};for(let r of new Set(e.keys())){let d=e.getAll(r);p[r]=d.length===1?d[0]:d}a.submit(p,h)}}),v(a.content),G(()=>{a.actions&&G("footer",a.actionsAttrs,()=>v(a.actions))})})}import x from"aberdeen";import{current as q1}from"aberdeen/route";import y from"aberdeen";import{matchCurrent as L2,current as c1,go as C2}from"aberdeen/route";import V from"aberdeen";import{grow as A2,shrink as V2}from"aberdeen/transitions";V.insertGlobalCss({".s-toasts":"position:fixed bottom:$3 right:$3 z-index:400 display:flex flex-direction:column gap:$2 pointer-events:none max-width:min(90vw,24rem) w:24rem",".s-toast":{"&":"display:flex align-items:flex-start gap:$2 padding: $3; pointer-events:auto position:relative overflow:hidden",".s-toast-body":"display:flex flex-direction:column gap:$1 flex:1 min-width:0",".s-toast-title":"font-weight:700 line-height:1.3",".s-toast-close":"cursor:pointer border:0 background:transparent fg:$s-muted font-size:1.1em line-height:1 padding: 0 0.15em; r:4px flex-shrink:0 align-self:flex-start",".s-toast-close:hover":"fg:$s-text",".s-toast-close:focus-visible":"outline:none box-shadow: 0 0 0 3px $s-focus; fg:$s-text",".s-toast-progress":"position:absolute bottom:0 left:0 right:0 height:2px background:$s-accent width:100%"}});var k2=0,a1=V.proxy({});F(()=>{V.peek(()=>V.isEmpty(a1))&&V.isEmpty(a1)||V("div.s-toasts",()=>{V.onEach(a1,t=>{let{opts:a,id:h}=t,e=a.type==="danger"||a.type==="warning"?"alert":"status",p=a.type==null||a.type==="neutral"?"neutral":a.type,r=a.duration??6e3,d,o=null,c=()=>{clearTimeout(d),o&&(o.style.transition="none",o.style.width="100%",o.offsetWidth,o.style.transition=`width ${r}ms linear`,o.style.width="0%"),d=setTimeout(()=>g1(h),r)},i=()=>{clearTimeout(d),d=void 0,o&&(o.style.transition="none",o.style.width="100%")};V.clean(()=>clearTimeout(d)),V(`div.s-toast.s-s.${p}.extra-shadow aria-live=polite role=${e}`,"create=",A2,"destroy=",V2,a.attrs,()=>{r>0&&(V("mouseenter=",i),V("mouseleave=",c)),V("div.s-toast-body",()=>{V(()=>{a.title!=null&&V("div.s-toast-title",()=>v(a.title))}),V("div.s-toast-msg",()=>v(a.message))}),V(()=>{a.dismissible!==!1&&V("button.s-toast-close type=button aria-label=Dismiss",()=>{V("#\xD7"),V("click=",()=>g1(h))})}),r>0&&(o=V("div.s-toast-progress"))}),r>0&&requestAnimationFrame(c)})})});function g1(t){delete a1[t]}function o1(t){let a=++k2;return a1[a]={id:a,opts:t},()=>g1(a)}y.insertGlobalCss({".s-menu-list":"position:fixed z-index:350 min-width:10rem display:flex flex-direction:column p:$1 r:$s-radius-lg max-width: calc(100vw - 16px); overflow-y:auto max-height:min(80vh,28rem) transition: opacity 0.15s, transform 0.15s, visibility 0.15s;",".s-menu-list.hidden":"opacity:0 pointer-events:none transform:translateY(-6px) visibility:hidden",".s-menu-item":"display:flex align-items:center gap:$2 w:100% outline:0 scroll-margin:$2 padding: $m2 0; line-height:1.1 r:$s-radius cursor:pointer text-align:left font-weight:450 font-size:0.9em border:0 background:transparent fg:$s-text text-decoration:none transition: color 0.12s, transform 0.12s, text-shadow 0.12s;",".s-menu-item:focus-visible:not([aria-current=page]), .s-menu-item:hover:not([aria-disabled=true]):not([aria-current=page])":"filter:none color: color-mix(in lab, $s-primary 33%, $s-text);",".s-menu-item[aria-current=page]":"color:$s-accent filter:none",".s-menu-list .s-menu-item":"padding-inline:$2",".s-menu-item[aria-disabled=true]":"opacity:0.45 cursor:not-allowed pointer-events:none",".s-menu-icon":"flex-shrink:0",".s-menu-list .s-menu-icon":"display:flex",".s-menu-list .s-menu-icon > svg":"width:1.25em height:1.25em","hr.s-menu-sep":"border:0 height:1px margin: $1 0.6rem; background: linear-gradient(to right, transparent, $s-faint 18%, $s-faint 82%, transparent);",".s-menu-chevron":"margin-left:auto flex-shrink:0 display:flex transition: transform 0.15s ease;",".s-menu-chevron > svg":"width:1em height:1em",".s-menu-details":{"> summary":"list-style:none","> summary::-webkit-details-marker":"display:none","&::details-content":"interpolate-size:allow-keywords block-size:0 overflow-y:clip transition: block-size 0.15s ease, content-visibility 0.15s allow-discrete;","&[open]::details-content":"block-size:auto","&[open] > summary .s-menu-chevron":"transform:rotate(90deg)"},".s-menu-sub":"display:flex flex-direction:column gap:$1 padding-left:$3",".s-menu-inline":"display:flex flex-direction:column gap:$1"});function h1(t,a){y("keydown=",e=>{if(e.key==="Enter"&&e.target.tagName==="A"){queueMicrotask(()=>a?.());return}if(e.key!=="ArrowDown"&&e.key!=="ArrowUp"&&e.key!=="Home"&&e.key!=="End")return;e.preventDefault();let r=[...e.currentTarget.querySelectorAll(".s-menu-item")].filter(i=>i.getAttribute("aria-disabled")!=="true"&&!S2(i));if(!r.length)return;let d=r.indexOf(document.activeElement),o=e.key==="ArrowUp"?-1:1,c=e.key==="Home"?0:e.key==="End"?r.length-1:d<0?o>0?0:r.length-1:(d+o+r.length)%r.length;r[c].focus()});let h=y.derive(()=>b1(t));J1(t,a,h)}function J1(t,a,h){for(let e of t){if(typeof e=="string"||typeof e=="function"){v(e);continue}if("separator"in e){y("hr.s-menu-sep");continue}e.items?$2(e,a,h):z2(e,a)}}function z2(t,a){let h=!1,e=y(t.href?"a.s-menu-item data-panel=open":"button.s-menu-item type=button",t.attrs,()=>{t.href&&(y("href=",t.href),t.target&&y("target=",t.target),y(()=>{let p=!h;h=!0,w1(t)&&(y("aria-current=page"),requestAnimationFrame(()=>e.scrollIntoView({block:"nearest",behavior:p?"instant":"smooth"})))})),t.disabled&&y("aria-disabled=true"),y("click=",p=>{if(t.disabled){p.preventDefault();return}a?.(),t.click?.(p)}),t.icon&&y("span.s-menu-icon",()=>v(t.icon)),v(t.label)})}var Y1=new Map;function Q1(t,a){return Y1.set(t,a),a}function $2(t,a,h){let e=t.href??t2(t.items),p=e!=null?y.derive(()=>H1(t)?Q1(e,!0):h==null||h.value?Q1(e,!1):Y1.get(e)??!1):null;y("details.s-menu-details",()=>{p&&y(()=>{p.value&&y("open=true")}),y("summary.s-menu-item.s-menu-branch",t.attrs,()=>{t.disabled&&y("aria-disabled=true"),y(()=>{w1(t)&&y("aria-current=page")}),y("click=",r=>{if(t.disabled){r.preventDefault();return}e!=null&&(r.preventDefault(),P2(e),C2(e)),t.click?.(r)}),t.icon&&y("span.s-menu-icon",()=>v(t.icon)),v(t.label),y("span.s-menu-chevron aria-hidden=true",()=>I1())}),y("div.s-menu-sub",()=>J1(t.items,a,h))})}function S2(t){for(let a=t.closest("details");a;a=a.parentElement&&a.parentElement.closest("details"))if(!a.open&&t.closest("summary")?.parentElement!==a)return!0;return!1}function b1(t){return t.some(a=>typeof a!="string"&&typeof a!="function"&&!("separator"in a)&&H1(a))}function w1(t){if(t.href!=null&&L2(t.href))return!0;let a=t.match;if(a==null)return!1;let h=c1.path;if(typeof a=="function")return a(h);let e=a.replace(/\/+$/,"")||"/";return h===e||h.startsWith(e==="/"?"/":e+"/")}function H1(t){if(w1(t))return!0;for(let a of t.items??[])if(!(typeof a=="string"||typeof a=="function"||"separator"in a)&&H1(a))return!0;return!1}function t2(t){for(let a of t){if(typeof a=="string"||typeof a=="function"||"separator"in a)continue;let h=a.href??(a.items?t2(a.items):void 0);if(h!=null)return h}}var n1=null;function P2(t){try{n1=new URL(t,location.href).pathname.replace(/\/+$/,"")||"/"}catch{n1=null}}function A1(t){return n1!==t?!1:(n1=null,!0)}var U=y.proxy({opts:null});function Z(){let t=U.opts?.anchor;U.opts=null,t?.focus()}function i1(t){let a=U.opts;return a!=null&&(t==null||a.anchor===t)}function O2(t){i1(t)&&Z()}function q2(t,a){let h=t.offsetWidth,e=t.offsetHeight,p=window.innerWidth,r=window.innerHeight,d=4,o=a.left;o+h>p-8&&(o=Math.max(8,a.right-h));let c=a.bottom+d;c+e>r-8&&a.top-e-d>=8&&(c=a.top-e-d),t.style.left=Math.max(8,o)+"px",t.style.top=Math.max(8,c)+"px"}function E2(t){return[{label:"Open in new tab",icon:N1,click:()=>{window.open(t,"_blank","noopener")}},{label:"Copy link",icon:W1,click:()=>{T2(t)}}]}async function T2(t){let a=new URL(t,location.href).href;try{await navigator.clipboard.writeText(a),o1({message:"Link copied."})}catch{o1({message:"Couldn't copy the link.",type:"danger"})}}F(()=>{let t=U.opts;if(!t)return;let a=y("div.s-menu-list.s-s.neutral.shadow create=hidden destroy=hidden",t.dropdownAttrs,()=>{h1(t.link!=null?[...E2(t.link),{separator:!0},...t.items]:t.items,Z)}),h=r=>{let d=r.target;!a.contains(d)&&(t.closeOnAnchorClick||!t.anchor.contains(d))&&Z()},e=r=>{(r.key==="Escape"||r.key==="Tab")&&(r.preventDefault(),Z())},p=y.peek(c1,"path");y(()=>{c1.path!==p&&!A1(c1.path)&&Z()}),document.addEventListener("click",h,!0),document.addEventListener("keydown",e,!0),y.clean(()=>{document.removeEventListener("click",h,!0),document.removeEventListener("keydown",e,!0)}),requestAnimationFrame(()=>{if(!document.body.contains(a))return;let r=t.at?{left:t.at.x,right:t.at.x,top:t.at.y,bottom:t.at.y}:t.anchor.getBoundingClientRect();q2(a,r),j(a,".s-menu-item[aria-current=page]")})});function D2(t){y("nav.s-menu-inline",t.attrs,()=>h1(t.items,t.onLeafSelect))}function V1(t){return U.opts=t,Z}function k1(t){let a=null;y.clean(()=>{U.opts?.anchor===a&&Z()}),y("contextmenu=",h=>{h.preventDefault(),a=h.currentTarget,V1({...t,anchor:a,at:{x:h.clientX,y:h.clientY},closeOnAnchorClick:!0})})}function R2(t){let a=null;y.clean(()=>{U.opts?.anchor===a&&Z()}),O({icon:d1,...t.button?.content==null?{ariaLabel:"Open menu"}:null,attrs:".neutral",...t.button,click:h=>{if(a=h.currentTarget,U.opts?.anchor===a){Z();return}V1({items:t.items,anchor:a,dropdownAttrs:t.dropdownAttrs})}})}import w from"aberdeen";import X from"aberdeen";function L1(t={}){I(t,(a,h)=>{X("input.s-input",t.inputAttrs,()=>{X("type=",t.type??"text"),t.placeholder!=null&&X("placeholder=",t.placeholder),t.autocomplete!=null&&X("autocomplete=",t.autocomplete),t.value!=null&&!t.bind&&X("value=",t.value),t.input&&X("input=",t.input),t.change&&X("change=",t.change),_(t,a,h,t.bind)})})}w.insertGlobalCss({".s-backdrop":{"&":"position:fixed inset:0 z-index:200 display:block background: rgba(0,0,0,0.55); transition: opacity 0.4s ease-in-out;","&.hidden":"opacity:0 pointer-events:none"},".s-dialog":{"&":"position:fixed z-index:200 top:50% left:50% display:flex flex-direction:column transform:translate(-50%,-50%) min-width:min(20rem,90vw) max-width:min(90vw,44rem) max-height:min(88vh,800px) r: $s-radius-lg; overflow:hidden transition: opacity 0.2s ease-out, transform 0.2s ease-out;","> header":"display:flex align-items:center gap:$2 padding: $2 $3; border:0 border-bottom: 1px solid $s-faint; r:0 font-weight:600 flex-shrink:0","> footer":"display:flex align-items:center justify-content:flex-end gap:$2 padding: $2 $3; border:0 border-top: 1px solid $s-faint; r:0 flex-shrink:0","> div":"p:$3 gap:$3 display:flex flex-direction:column overflow-y:auto flex:1 min-height:0","&.hidden":"opacity:0 pointer-events:none transform: translate(-50%, calc(-50% + 20px)); pointer-events:none"}});var K=w.proxy({}),C1=0,a2=w.derive(()=>{let t=Object.keys(K);if(t.length)return t[t.length-1]});function z1(){return a2.value!=null}F(()=>{w.onEach(K,({resolve:t,opts:a},h)=>{let e=()=>{delete K[h]};w.clean(()=>{a.onClose?.(),t()});let p=w.derive(()=>a2.value!=h);w("div.s-backdrop create=hidden destroy=hidden .hidden=",p,"click=",()=>{a.allowCancel!==!1&&e()});let r=w("div.s-dialog.neutral.s-s.extra-shadow create=hidden destroy=hidden",a.attrs,()=>{w(()=>{a.header!=null&&w("header.s-s.neutral",a.headerAttrs,()=>v(a.header))}),w("div",a.contentAttrs,()=>{v(a.content,e)}),w(()=>{a.footer!=null&&w("footer.s-s.neutral",a.footerAttrs,()=>v(a.footer))})});requestAnimationFrame(()=>{document.body.contains(r)&&j(r)})})});function s1(t){C1||document.addEventListener("keydown",h=>{if(h.key!=="Escape"||h.defaultPrevented)return;let e=w.unproxy(K);for(let p=C1;p>0;p--)if(e[p]){h.preventDefault(),e[p].opts.allowCancel!==!1&&delete K[p];break}});let a=++C1;return t.cancelWithScope!==!1&&w.clean(()=>{delete K[a]}),new Promise(h=>{K[a]={resolve:h,opts:t}})}function Z2(t,a={}){return s1({header:"Alert",allowCancel:!0,content:h=>{w("p",()=>{w("#",t)}),W({layout:"spaced",attrs:"align-self:flex-end",content:()=>{O({content:"OK",click:h})}})},...a})}function B2(t,a={}){return new Promise(h=>{let e=!1;s1({header:"Confirm",allowCancel:!0,content:p=>{w("p",()=>{w("#",t)}),W({layout:"spaced",attrs:"align-self:flex-end",content:()=>{O({content:"Cancel",attrs:".neutral",click:p}),O({content:"OK",click:()=>{e=!0,p()}})}})},...a,onClose:()=>{h(e),a.onClose?.()}})})}function F2(t,a="",h={}){return new Promise(e=>{let p=null;s1({header:"Input",allowCancel:!0,content:r=>{w("p",()=>{w("#",t)});let d=w.proxy({value:a});w("form display:contents",()=>{w("submit=",o=>{o.preventDefault(),p=d.value,r()}),L1({bind:w.ref(d,"value")}),W({layout:"spaced",attrs:"align-self:flex-end",content:()=>{O({content:"Cancel",attrs:".neutral",type:"button",click:r}),O({content:"OK",type:"submit"})}})})},...h,onClose:()=>{e(p),h.onClose?.()}})})}import s,{OPAQUE as e2}from"aberdeen";import*as H from"aberdeen/route";import A from"aberdeen";var I2=$('<path d="m15 18-6-6 6-6"/>'),U2=$('<path d="m9 18 6-6-6-6"/>');A.insertGlobalCss({".s-strip":{"&":"position:relative display:flex min-width:0","> .s-strip-row":"display:flex align-items:center flex:1 min-width:0 overflow-x:auto overflow-y:hidden scrollbar-width:none scroll-behavior:smooth","> .s-strip-row::-webkit-scrollbar":"display:none","> .s-strip-btn":"position:absolute top:0 bottom:0 z-index:1 display:none align-items:center justify-content:center width:2.4em border:0 padding:0 cursor:pointer fg:$s-muted transition: color 0.15s;","> .s-strip-btn:hover":"fg:$s-text","> .s-strip-btn-left":"left:0 justify-content:flex-start background: linear-gradient(to right, $s-bg 45%, transparent)","> .s-strip-btn-right":"right:0 justify-content:flex-end background: linear-gradient(to left, $s-bg 45%, transparent)","&.s-can-left > .s-strip-btn-left, &.s-can-right > .s-strip-btn-right":"display:flex"},".s-tabs":{"&":"display:flex flex-direction:column gap:$3",".s-tabbar":"border-bottom: 1px solid $s-faint;",".s-tablist":"gap:$1 align-items:stretch margin-bottom:-1px",".s-tab":"display:inline-flex align-items:center gap:$2 cursor:pointer background:transparent border:0 color: $s-muted; font-weight:600 padding: 0.6em 0.9em; white-space:nowrap border-bottom: 3px solid transparent; transition: color 0.15s, background 0.15s, border-color 0.15s;",".s-tab:hover:not(:disabled), .s-tab[aria-selected=true]":"color: $s-text;",".s-tab:focus-visible":"outline:none box-shadow: inset 0 0 0 2px $s-focus; r: $s-radius;",".s-tab[aria-selected=true]":"border-image: $s-gradient 1;",".s-tabpanel":"display:block"}});function l1(t){A("div.s-strip",t.attrs,()=>{let a=A("div.s-strip-row",t.stripAttrs,()=>v(t.content));h2(a,-1),h2(a,1),W2(a)})}function M1(t){let a=t.parentElement;if(!a||!t.isConnected)return;let h=parseFloat(getComputedStyle(a).fontSize)*2.6,e=t.getBoundingClientRect(),p=a.getBoundingClientRect(),r=e.left-p.left,d=e.right-p.right;r<h?a.scrollBy({left:r-h,behavior:"smooth"}):d>-h&&a.scrollBy({left:d+h,behavior:"smooth"})}function N2(t){let a=B("tabs"),h=(r,d)=>r.id??String(d),e=t.bind??A.proxy(h(t.tabs[0]??{label:""},0));t.tabs.length>0&&!t.tabs.some((r,d)=>h(r,d)===A.peek(()=>e.value))&&(e.value=h(t.tabs[0],0));let p=(r,d)=>{r.disabled||(e.value=h(r,d))};A("div.s-tabs",t.attrs,()=>{l1({attrs:".s-tabbar",stripAttrs:".s-tablist role=tablist",content:()=>{t.tabs.forEach((r,d)=>{let o=h(r,d),c=A("button.s-tab type=button role=tab",()=>{A("id=",`${a}-tab-${o}`,"aria-controls=",`${a}-panel-${o}`),A(()=>{let i=e.value===o;A("aria-selected=",i?"true":"false"),A("tabindex=",i?"0":"-1"),i&&requestAnimationFrame(()=>M1(c))}),r.disabled&&A("disabled=true"),A("click=",()=>p(r,d)),A("keydown=",i=>G2(i,t.tabs,d,p)),v(r.icon),v(r.label)})})}}),A("div.s-tabpanel role=tabpanel",t.contentAttrs,()=>{A(()=>{let r=e.value,d=t.tabs.findIndex((c,i)=>h(c,i)===r),o=t.tabs[d]??t.tabs[0];o&&(A("id=",`${a}-panel-${h(o,d)}`,"aria-labelledby=",`${a}-tab-${h(o,d)}`),v(o.content))})})})}function h2(t,a){A(`button.s-strip-btn.s-strip-btn-${a<0?"left":"right"} type=button`,()=>{A("tabindex=-1 aria-hidden=true"),A("click=",()=>t.scrollBy({left:a*t.clientWidth*.8,behavior:"smooth"})),(a<0?I2:U2)({size:"1.1em"})})}function W2(t){let a=t.parentElement;if(!a||typeof ResizeObserver>"u")return;let h=()=>{let r=t.scrollWidth-t.clientWidth;a.classList.toggle("s-can-left",t.scrollLeft>1),a.classList.toggle("s-can-right",t.scrollLeft<r-1)};t.addEventListener("scroll",h,{passive:!0});let e=new ResizeObserver(h);e.observe(t);let p=typeof MutationObserver>"u"?void 0:new MutationObserver(r=>{for(let d of r){for(let o of d.addedNodes)o instanceof Element&&e.observe(o);for(let o of d.removedNodes)o instanceof Element&&e.unobserve(o)}h()});p?.observe(t,{childList:!0});for(let r of Array.from(t.children))e.observe(r);h(),A.clean(()=>{t.removeEventListener("scroll",h),e.disconnect(),p?.disconnect()})}function G2(t,a,h,e){let p=h;if(t.key==="ArrowRight"||t.key==="ArrowDown")p=(h+1)%a.length;else if(t.key==="ArrowLeft"||t.key==="ArrowUp")p=(h-1+a.length)%a.length;else if(t.key==="Home")p=0;else if(t.key==="End")p=a.length-1;else return;t.preventDefault();let r=p>=h?1:-1;for(let d=0;d<a.length;d++){let o=a[p];if(o&&!o.disabled){e(o,p),t.currentTarget?.parentElement?.children[p]?.focus();return}p=(p+r+a.length)%a.length}}var P1={integer(t){if(!/^(0|-?[1-9]\d*)$/.test(t))return;let a=Number(t);return Number.isSafeInteger(a)?a:void 0}};function E(t){let a=String(t).replace(/\/+$/,"");return a.startsWith("/")||(a=`/${a}`),a}function e1(t){let a=E(t);return a==="/"?[]:a.slice(1).split("/")}function p2(t){let a=e1(t),h=a.map((e,p)=>{if(!e.startsWith("[")||!e.endsWith("]"))return{kind:"lit",value:e};let r=/^\[\.\.\.([A-Za-z_$][\w$]*)\]$/.exec(e);if(r){if(p!==a.length-1)throw new Error(`Staffa: "${e}" must be the last segment of route "${t}"`);return{kind:"rest",name:r[1]}}let d=/^\[([A-Za-z_$][\w$]*)(?:=([A-Za-z_$][\w$]*))?\]$/.exec(e);if(!d)throw new Error(`Staffa: malformed param "${e}" in route "${t}"`);let[,o,c]=d;if(c&&!(c in P1))throw new Error(`Staffa: unknown matcher "${c}" in route "${t}" (known: ${Object.keys(P1).join(", ")})`);return{kind:"param",name:o,matcher:c}});return{key:t,segs:h}}function X2(t){try{return decodeURIComponent(t)}catch{return t}}function $1(t,a){let h={};for(let e=0;e<t.segs.length;e++){let p=t.segs[e];if(p.kind==="rest")return e>=a.length?null:(h[p.name]=a.slice(e).join("/"),h);if(e>=a.length)return null;let r=a[e];if(p.kind==="lit"){if(r!==p.value)return null}else if(p.matcher){let d=P1[p.matcher](r);if(d===void 0)return null;h[p.name]=d}else h[p.name]=X2(r)}return t.segs.length===a.length?h:null}var o2=250,K2=300,j2=360,O1=540,r2=2;s.insertGlobalCss({":root":`--s-panel-ms:${o2}ms`,".s-panels":"flex:1 min-width:0 min-height:0 position:relative overflow:clip isolation:isolate "+u1,".s-panel":{"&":"position:absolute top:0 bottom:0 left:0 display:flex flex-direction:column "+u1+" visibility:visible transition: left var(--s-panel-ms) ease, transform var(--s-panel-ms) ease-out, opacity var(--s-panel-ms) linear, visibility 0s;","&.s-panel-sep::before":"content:'' position:absolute left:0 top:0.6rem bottom:0.6rem width:1px z-index:1 background: linear-gradient(to bottom, transparent, $s-faint 18%, $s-faint 82%, transparent);","&.s-panel-enter":"opacity:0 transition:none transform: translateX(8cqw);","&.s-panel-closing":"opacity:0 pointer-events:none transform: translateX(8cqw);","&.s-panel-hidden, &.s-panel-parked":"opacity:0 visibility:hidden transition: left var(--s-panel-ms) ease, transform var(--s-panel-ms) ease-out, opacity var(--s-panel-ms) linear, visibility var(--s-panel-ms);","&.s-panel-hidden":"transform: translateX(-8cqw);","&.s-panel-parked":"transform: translateX(8cqw);"},".s-panel > .s-content":"flex:1 min-height:0 overflow-y:auto overflow-x:hidden p:$3",".s-panel-actions":"display:flex align-items:center justify-content:flex-end gap:$1 flex-shrink:0 padding: $3 $3 0;",".s-crumbs > .s-strip-row":"gap:$m1",".s-crumb":{"&":"flex: 1 0 4rem; font-size:0.85em line-height:1.5 fg:$s-muted text-decoration:none white-space:nowrap max-width:max-content overflow:hidden text-overflow:ellipsis transition: color 0.12s;","&.s-crumb-on":"font-weight:600 fg:$s-text","a&:hover":"filter:none color: color-mix(in lab, $s-primary 33%, $s-text);","svg.s-crumb-pin":"vertical-align:-0.12em margin-right:0.3em opacity:0.8 fill:currentColor","svg.s-crumb-unsaved":"vertical-align:0.08em margin-right:0.3em fill:currentColor"},"svg.s-crumb-sep":"flex-shrink:0 opacity:0.4",".s-main.s-shell-snap .s-panel":"transition:none",".s-panel-loading":{"&":"position:absolute inset:0 display:flex align-items:center justify-content:center gap:$1 pointer-events:none",i:"width:0.5rem height:0.5rem r:50% background:$s-muted opacity:0.45 animation: s-panel-pulse 1s ease-in-out infinite;","i:nth-child(2)":"animation-delay:0.15s","i:nth-child(3)":"animation-delay:0.3s"},"@keyframes s-panel-pulse":{"0%, 100%":"opacity:0.25 transform:scale(0.8)","50%":"opacity:0.7 transform:scale(1)"}});var S1=!1,x1=class{[e2]=!0;compiled;ancestors;opts;$state=s.proxy({live:[],focus:0});$open=s.proxy({});nextOrder=0;containerEl;geom;lastGeom;layoutQueued=!1;timers=new Set;intent=null;settling=null;lastSeen=null;queued=null;constructor(a){if(S1)throw new Error("Staffa: only one routed S.main() (one with `routes`) can be active at a time");S1=!0,this.opts=a,this.compiled=Object.entries(a.routes).map(([h,e])=>({...p2(h),draw:e})),this.ancestors=Object.entries(a.ancestors??{}).filter(h=>h[1]!=null).map(([h,e])=>({...p2(h),fn:e})),s(()=>{let h=this.computeTarget(),e={...H.current.search},p=H.current.hash;s.peek(()=>{let r=this.lastSeen;if(r&&r.path!==H.current.path){let d=this.$state.live.find(o=>o.path===r.path);d&&(d.search=r.search,d.hash=r.hash)}this.lastSeen={path:H.current.path,search:e,hash:p},this.propose(h),Array.isArray(H.current.state.panels)||Object.assign(H.current.state,this.stateFor({stack:this.paths(),focus:this.$state.focus}))})}),this.interceptLinks(),this.watchTitle(),this.guardTabClose(),s.clean(()=>{for(let h of this.timers)clearTimeout(h);this.timers.clear(),this.queued?.settle(!1),this.queued=null,S1=!1})}resolve(a){let h=e1(a);for(let e of this.compiled){let p=$1(e,h);if(p)return{draw:e.draw,params:p}}return{draw:this.opts.notFound??J2,params:{}}}matches(a){let h=e1(a);return this.compiled.some(e=>$1(e,h)!=null)}deriveStack(a){let h=E(a),e=this.askAncestors(h),p=e?e.map(E):this.prefixesOf(h),r=[];for(let d of p)d!==h&&!r.includes(d)&&this.matches(d)&&r.push(d);return r.push(h),r}askAncestors(a){let h=e1(a);for(let e of this.ancestors){let p=$1(e,h);if(p)return e.fn(p,a)??void 0}}prefixesOf(a){let h=e1(a),e=[];for(let p=1;p<h.length;p++)e.push("/"+h.slice(0,p).join("/"));return e}pinnedIn(a,h){return a.filter(e=>h.includes(e)?!1:this.$state.live.find(p=>p.path===e)?.$panel.pinned===!0)}unsavedAt(a){return this.$state.live.find(h=>h.path===a)?.$panel.unsaved===!0}targetFor(a,h){let e=Array.isArray(h?.panels)?h.panels.map(String):null;if(e){let p=Array.isArray(h.parked)?h.parked.map(String):[],r=E(a),d=new Set([r]),o=i=>i.map(E).filter(u=>!d.has(u)&&!!d.add(u)),c=o(e);return{stack:[...c,r,...o(p)],focus:c.length}}return s.peek(()=>{let p=this.deriveStack(a).slice(0,-1),r=[...p,...this.pinnedIn(this.paths(),[...p,E(a)]),E(a)];return{stack:r,focus:r.length-1}})}computeTarget(){return this.targetFor(H.current.path,H.current.state)}paths(){return this.$state.live.map(a=>a.path)}propose(a){let h=this.$state.live.filter(e=>!a.stack.includes(e.path)&&e.$panel.unsaved).map(e=>e.path);h.length&&(a={stack:[...a.stack,...h],focus:a.focus}),!(d2(this.paths(),a.stack)&&a.focus===this.$state.focus)&&this.commit(a,H.current.nav)}commit(a,h){this.geom=void 0;let e=H.current.state.pinned,p=new Set(Array.isArray(e)?e.map(String):[]),r=new Map(this.$state.live.map(o=>[o.path,o])),d=[];for(let o of a.stack){let c=r.get(o);if(c){r.delete(o),d.push(c);continue}let i=this.createEntry(o,d.length<=a.focus,p.has(o));h!=="load"&&h!=="back"&&(i.enter=!0),d.push(i),this.$open[o]=i}for(let o of r.values())this.beginClose(o);this.$state.live=d,this.$state.focus=Math.min(a.focus,d.length-1),this.scheduleLayout()}createEntry(a,h,e){let{draw:p,params:r}=this.resolve(a),d={[e2]:!0,order:this.nextOrder++,path:a,draw:p,$ui:s.proxy({holding:!1}),maxWidth:"medium",width:0};return d.$panel=s.proxy({stack:this,params:r,path:a,width:0,visible:h,pinned:e||void 0,close:()=>this.closePath(d.path),open:(o,c)=>this.navigate(o,{from:d.path,how:c})}),d}beginClose(a){a.closing=!0,a.$panel.visible=!1,a.el&&(a.el.style.zIndex=String(r2*this.$state.live.indexOf(a))),delete this.$open[a.path]}playExit(a,h){if(!a.closing){h.remove();return}h.classList.add("s-panel-closing"),h.setAttribute("inert","");let e=()=>{clearTimeout(p),this.timers.delete(p),h.remove()};h.addEventListener("transitionend",r=>{r.target===h&&r.propertyName==="opacity"&&e()});let p=setTimeout(e,o2+80);this.timers.add(p)}intended(){return this.intent??{stack:this.paths(),focus:this.$state.focus}}stateFor(a){return{panels:a.stack.slice(0,a.focus),parked:a.stack.slice(a.focus+1),pinned:this.pinnedPaths()}}pinnedPaths(){return this.$state.live.filter(a=>a.$panel.pinned).map(a=>a.path)}issue(a,h){return this.intent=a,this.settling?(this.queued?.settle(!1),new Promise(e=>{this.queued={run:h,settle:e}})):this.start(h)}start(a){let h=p=>{this.settling=null;let r=this.queued;return this.queued=null,p&&r?this.start(r.run).then(r.settle,()=>r.settle(!1)):(this.intent=null,r?.settle(!1)),p},e=Promise.resolve(a()).then(h,p=>(console.error(p),h(!1)));return this.settling=e,e}focusAt(a){let h=this.intended();if(a<0||a>=h.stack.length||a===h.focus)return Promise.resolve(!1);let e={stack:h.stack,focus:a},p=h.stack[a];return this.issue(e,()=>{let r=this.$state.live.find(d=>d.path===p);return H.go({path:p,search:r?.search,hash:r?.hash,state:this.stateFor(e)})})}back(){return s.peek(()=>{let a=this.intended();return a.focus===a.stack.length-1&&!this.unsavedAt(a.stack[a.focus])?this.closePath(a.stack[a.focus]??""):a.focus===0?Promise.resolve(!1):this.focusAt(a.focus-1)})}closePath(a){return s.peek(()=>{let h=this.intended(),e=h.stack.indexOf(E(a));if(e<0||h.stack.length<2||this.unsavedAt(h.stack[e]))return Promise.resolve(!1);let p=h.stack.filter((i,u)=>u!==e),r=e===h.focus?Math.max(0,e-1):h.focus-(e<h.focus?1:0),d={stack:p,focus:r};if(e===h.focus&&e===h.stack.length-1){let i=this.$state.live.find(m=>m.path===p[r]),u={};i?.search&&(u.search=i.search),i?.hash&&(u.hash=i.hash);let n=p.filter(m=>this.$state.live.find(g=>g.path===m)?.$panel.pinned===!0);return this.issue(d,()=>Promise.resolve(H.back({path:p[r],state:{panels:p.slice(0,r),parked:[]}},u)).then(m=>(m&&(H.current.state.pinned=n),m)))}let o=p[r],c=o!==h.stack[h.focus];return this.issue(d,()=>{let i=c?this.$state.live.find(u=>u.path===o):void 0;return H.go({path:o,search:c?i?.search:{...H.current.search},hash:c?i?.hash:H.current.hash,state:this.stateFor(d)})})})}navigate(a,{from:h,how:e,beneath:p}={}){let r=e??this.opts.linkNavigation,d=r==="open"?null:h??null,o=r==="replace";return s.peek(()=>{let c;try{c=new URL(a,location.href)}catch{return Promise.resolve(!1)}let i=E(c.pathname),u=this.intended(),n=p?-1:u.stack.indexOf(i),m;if(n>=0&&r!=="replace"&&r!=="open"){let f=this.pinnedIn(u.stack.slice(n+1),[]);m={stack:[...u.stack.slice(0,n+1),...f],focus:n}}else{let f=d==null?-1:u.stack.indexOf(d),z=(p?p.map(E):f<0?this.deriveStack(i).slice(0,-1):u.stack.slice(0,o?f:f+1)).filter((T1,n2,i2)=>T1!==i&&i2.indexOf(T1)===n2),p1=[...z,...this.pinnedIn(u.stack,[...z,i,o?d:null])];m={stack:[...p1,i],focus:p1.length}}let g=n>=0?this.$state.live.find(f=>f.path===i):void 0,b=c.search?Object.fromEntries(new URLSearchParams(c.search)):g?.search??{},l=c.hash||g?.hash||"";return m.focus===u.focus&&d2(m.stack,u.stack)&&c.search===location.search&&(c.hash||"")===(location.hash||"")?Promise.resolve(!0):this.issue(m,()=>H.go({path:i,search:b,hash:l,state:this.stateFor(m)}))})}pushPath(a,h){return s.peek(()=>{let e=this.intended();return this.navigate(a,{from:e.stack[e.focus],how:h?"replace":"push"})})}interceptLinks(){H.interceptLinks((a,h)=>{let e=h.getAttribute("data-panel")??void 0,p=h.closest(".s-panel"),r=p?this.$state.live.find(d=>d.el===p):h.closest(".s-panel-origin")?this.$state.live[this.$state.focus]:void 0;return this.navigate(a.href,{from:r?.path,how:e}),!0})}get currentPanel(){return this.$state.live[this.$state.focus]?.$panel}get panels(){return this.$state.live.map(a=>a.$panel)}get currentPanelIndex(){return this.$state.focus}pushPanel(a){return this.pushPath(a,!1)}replacePanel(a){return this.pushPath(a,!0)}openPanelStack(a,h){return this.navigate(a,{how:"open",beneath:h})}closePanel(a){return s.peek(()=>{let h=this.intended();return this.closePath(a??h.stack[h.focus]??"")})}setColumns(a){this.opts.columns!==a&&(this.opts.columns=a,this.scheduleLayout())}setLinkNavigation(a){this.opts.linkNavigation=a}drawCrumbs(){l1({attrs:".s-crumbs role=navigation aria-label=Breadcrumbs",content:()=>{s(()=>{let a=this.panels.map(p=>p.path),h=this.currentPanelIndex,e;for(let p=0;p<a.length;p++){p&&X1({size:"0.85em",attrs:".s-crumb-sep"});let r=this.drawCrumb(a[p],p,p===h);p===h&&(e=r)}requestAnimationFrame(()=>{e&&M1(e)})})}})}drawCrumb(a,h,e){let p=this.$state.live[h];return s(e?"span.s-crumb aria-current=page":"a.s-crumb",()=>{e||s("href=",a),s(()=>{p?.$panel.visible&&s(".s-crumb-on")}),s(()=>{p?.$panel.unsaved&&U1({size:"0.45em",attrs:".s-crumb-unsaved"})}),s(()=>{p?.$panel.pinned&&y1({size:"0.85em",attrs:".s-crumb-pin"})}),s(()=>{s("#",p?.$panel.title??p?.$ui.fallback??(a.split("/").pop()||a))}),k1({link:a,items:[{label:()=>{s(()=>{s("#",p?.$panel.pinned?"Unpin":"Pin")})},icon:()=>{s(()=>{(p?.$panel.pinned?G1:y1)()})},click:()=>{p&&this.togglePin(p)}},{label:"Close",icon:Q,disabled:p?.$panel.unsaved===!0,click:()=>{this.closePath(a)}}]})})}togglePin(a){a.$panel.pinned=!a.$panel.pinned||void 0,H.current.state.pinned=this.pinnedPaths()}watchTitle(){let a=document.title;s(()=>{let h=this.$state.live[this.$state.focus],e=h?.$panel.title??h?.$ui.fallback,p=typeof this.opts.title=="string"?this.opts.title:void 0,r=this.$state.live.some(o=>o.$panel.unsaved),d=e&&p?`${e} \xB7 ${p}`:e||p;d&&(document.title=(r?"\u2022 ":"")+d)}),s.clean(()=>{document.title=a})}guardTabClose(){if(typeof window>"u")return;let a=h=>{let e=this.$state.live.find(p=>p.$panel.unsaved);e&&(h.preventDefault(),h.returnValue=!0,this.flushLayout(),e.$panel.visible||this.focusAt(this.intended().stack.indexOf(e.path)))};s(()=>{this.$state.live.some(h=>h.$panel.unsaved)&&(window.addEventListener("beforeunload",a),s.clean(()=>window.removeEventListener("beforeunload",a)))})}drawColumns(){let a=s("div.s-panels role=main",()=>{this.containerEl=s(),s.onEach(this.$open,h=>this.drawPanel(h),h=>h.order)});if(typeof ResizeObserver<"u"){let h=new ResizeObserver(()=>this.layout());h.observe(a),s.clean(()=>h.disconnect())}s.clean(()=>{this.containerEl===a&&(this.containerEl=void 0)}),this.scheduleLayout()}drawPanel(a){let h;s(()=>{let e=a.$panel.maxWidth;a.maxWidth=e==="small"||e==="large"||e==="none"?e:"medium";let p=this.roomFor(a.maxWidth);p&&(a.width=p,s.peek(a.$panel,"width")!==p&&(a.$panel.width=p),h&&(h.style.width=`${p}px`,this.scheduleLayout()))}),h=s(`section.s-panel${a.width?` w:${a.width}px`:""}`,"destroy=",e=>this.playExit(a,e),()=>{s(()=>this.drawActions(a)),s("div.s-content",()=>{if(a.draw(a.$panel),H.persistScroll(a.path),s.peek(a.$panel,"title")==null){let e=Q2(s());e&&s.peek(a.$ui,"fallback")!==e&&(a.$ui.fallback=e)}}),s(()=>{!a.$panel.loading||a.$ui.holding||s("div.s-panel-loading aria-hidden=true",()=>{s("i"),s("i"),s("i")})})}),a.el=h,a.placed=!1,h.style.transition="none",s.clean(()=>{a.el===h&&(a.el=void 0)}),s(()=>{a.$panel.loading,this.scheduleLayout()}),this.scheduleLayout()}drawActions(a){this.opts.$shell.narrow||a.$panel.actions==null||s("div.s-panel-actions",()=>v(a.$panel.actions))}scheduleLayout(){this.layoutQueued||(this.layoutQueued=!0,requestAnimationFrame(()=>this.flushLayout()))}flushLayout(){this.layoutQueued&&(this.layoutQueued=!1,this.layout())}measure(){let a=this.containerEl,h=a?a.getBoundingClientRect().width:0;if(!h)return;let e=Math.min(h/Math.max(1,Math.floor(h/j2)),O1),p=r=>Math.min(r*e,h);return{area:h,size:{small:e,medium:p(2),large:p(3),none:h}}}geometry(){return this.geom??=this.measure()}roomFor(a){return this.geometry()?.size[a]??0}layout(){let a=this.containerEl,h=a?.closest(".s-main");if(!a||!h)return;let e=this.$state.live,p=e.length;if(!p||e.some(l=>!l.el))return;this.geom=void 0;let r=this.geometry();if(!r)return;let d=this.opts.columns==="single",o=this.lastGeom?.area!==r.area;o&&(this.lastGeom=r,h.classList.add("s-shell-snap"));let c=l=>r.size[l.maxWidth],i=Math.min(this.$state.focus,p-1),u=i,n=c(e[i]);if(!d)for(let l=i-1;l>=0;l--){let f=n+c(e[l]);if(f>r.area)break;n=f,u=l}let m=(r.area-n)/2;for(let l=u;l<=i;l++)e[l].width=c(e[l]);for(let l of e)l.width||(l.width=c(l));let g=[],b=m;for(let l=0;l<p;l++){let f=e[l],C=f.el,z=l>=u&&l<=i;_2(C,z?b:l>i?m+n:m,f.width,r2*l+1),f.$panel.visible!==z&&(f.$panel.visible=z),f.$panel.width!==f.width&&(f.$panel.width=f.width),z&&(b+=f.width),C.classList.toggle("s-panel-sep",z&&l>u),C.classList.toggle("s-panel-hidden",l<u),C.classList.toggle("s-panel-parked",l>i),C.toggleAttribute("inert",!z),!f.placed&&(g.push(f),!f.$panel.loading||f.holdDone?f.$ui.holding=!1:f.$ui.holding||(f.$ui.holding=!0,this.holdEnter(f)),f.enter&&z&&C.classList.add("s-panel-enter"))}(g.length||o)&&a.offsetWidth,o&&h.classList.remove("s-shell-snap");for(let l of g)l.$ui.holding||(l.el.style.transition="",l.el.classList.remove("s-panel-enter"),l.enter=!1,l.placed=!0)}holdEnter(a){let h=setTimeout(()=>{this.timers.delete(h),a.holdDone=!0,a.$ui.holding&&(a.$ui.holding=!1,this.scheduleLayout())},K2);this.timers.add(h)}};function _2(t,a,h,e){t.style.left=`${a}px`,t.style.width=`${h}px`,t.style.zIndex=String(e)}function d2(t,a){return t.length===a.length&&t.every((h,e)=>h===a[e])}function Q2(t){let a=document.createTreeWalker(t,NodeFilter.SHOW_TEXT);for(let h=a.nextNode();h;h=a.nextNode()){let e=h.textContent.trim();if(e)return e.length>48?`${e.slice(0,47).trimEnd()}\u2026`:e}}function J2(t){s("p fg:$s-muted",()=>s("#",`No panel at ${t.path}`))}var Y2=200;x.insertGlobalCss({".s-main":{"&":"display:flex flex-direction:column min-height:100vh max-height:100vh container-type:inline-size","body > &":"margin: calc(-1 * $3)","> header":"border:0 border-bottom: 1px solid $s-faint; r:0 position:sticky top:0 z-index:10","> footer":"border-top: 1px solid $s-faint; fg:$s-muted","> header > .s-bar, > footer > .s-bar":"display:flex align-items:center width:100% margin-inline:auto gap:$3 padding: $2 $3;","> header .s-logo, > header .s-nav-trigger":"display:flex align-items:center flex-shrink:0","> header .s-nav-trigger":"margin-left:-0.375rem","> header .s-logo":"font-size:1.4em background: $s-gradient; -webkit-background-clip:text; background-clip:text; color:transparent;","> header .s-titles":"display:flex flex-direction:column min-width:5rem flex: 0 1 auto;","> header .s-subtitle":"fg:$s-muted font-size:0.85em line-height:1.5 overflow:hidden text-overflow:ellipsis white-space:nowrap","> header .s-title":"font-weight:800 font-size:1.1em line-height:1.2 overflow:hidden text-overflow:ellipsis white-space:nowrap letter-spacing:-0.01em background: $s-gradient; -webkit-background-clip:text; background-clip:text; color:transparent; width:fit-content max-width:100%","> header a.s-logo, > header a.s-title":"text-decoration:none filter:none cursor:pointer","> header .s-menu":"display:flex align-items:center justify-content:flex-end gap:$2 flex: 1 0.1 auto; min-width:0",".s-body":"flex:1 overflow:clip display:flex flex-direction:row min-height:0 justify-content:center position:relative",".s-body-inner":"flex:1 min-width:0 display:flex flex-direction:row min-height:0","&.s-nav-right .s-body-inner":"flex-direction:row-reverse",".s-nav-sep":"width:1px flex-shrink:0 align-self:stretch margin: 0.6rem 0; border:0 background: linear-gradient(to bottom, transparent, $s-faint 18%, $s-faint 82%, transparent);",".s-body main":"flex:1 min-width:0 min-height:0 overflow-x:hidden overflow-y:auto display:flex flex-direction:column transition: transform var(--s-panel-ms) ease;",".s-body main.s-slide-in":"transform: translateX(100%); transition:none",".s-body main > .s-content":"width:100% flex:1 p:$3",".s-body main.s-scroll-y":"margin-right:$3"},".s-nav-panel":{"&":"display:flex flex-direction:column overflow-y:auto flex-shrink:0 width: calc(var(--s-nav-w) - 1px); padding:$3 gap:$1"},".s-nav-page":{"&":"position:absolute inset:0 z-index:5 display:flex flex-direction:column overflow-y:auto overscroll-behavior:contain border:0 r:0 padding:$2 gap:$1 transition: transform var(--s-panel-ms) ease, visibility var(--s-panel-ms);","&.s-nav-page-off":"transform:translateX(-100%) pointer-events:none visibility:hidden",".s-menu-item":"padding: $2 $3; min-height:3rem font-size:1.05em gap:$3"},[`@container (max-width: ${r1}px)`]:{".s-main .s-nav-panel, .s-main .s-nav-sep":"display:none",".s-main > header > .s-bar":"gap:$1 padding: $1 $2;",".s-main .s-body main.s-scroll-y":"margin-right:0"},[`@container (max-width: ${O1}px)`]:{".s-content > .s-box":"margin-inline: calc(-1 * $3); r:0 border-inline:0"}});function t0(t={}){let a=t.nav,h=t.navPosition??"left",e=x.proxy({open:!1}),p=x.proxy({narrow:typeof document<"u"&&document.documentElement.clientWidth<=r1}),r=t.routes;if(r!=null&&t.content!=null)throw new Error("Staffa: S.main() takes either `content` or `routes`, not both");let d=r?new x1({routes:r,notFound:t.notFound,ancestors:t.ancestors,title:t.title,$shell:p}):null;d&&(x(()=>d.setColumns(t.columns)),x(()=>d.setLinkNavigation(t.linkNavigation)));let o=d&&t.home!==null?t.home??"/":null,c=()=>{t.maxWidth!=null&&x("max-width:",t.maxWidth)},i=x("div.s-main",t.attrs,()=>{x(()=>{a==null||!a.items.length?x("--s-nav-w: 0px"):x(`.s-nav-${h}`,`--s-nav-w: ${t.navWidth??Y2}px`)}),x(()=>{(d!=null||t.title!=null||t.subtitle!=null||t.logo!=null||t.menu!=null||a!=null&&a.items.length>0)&&x("header.s-s.neutral",t.topbarAttrs,()=>{x("div.s-bar",()=>{x(c),x(()=>{if(p.narrow&&a!=null&&a.items.length){x("div.s-nav-trigger",()=>r0(a,e));return}t.logo!=null&&x(o!=null?"a.s-logo aria-label=Home":"div.s-logo",()=>{o!=null&&x("href=",o),v(t.logo)})}),x("div.s-titles",()=>{x(()=>{t.title!=null&&x(o!=null?"a.s-title":"div.s-title",()=>{o!=null&&x("href=",o),v(t.title)})}),h0(t,d,a,p)}),x(()=>{let n=p.narrow?d?.currentPanel?.actions:void 0,m=n??t.menu;m!=null&&x(`div.s-menu${n!=null?".s-panel-origin":""}`,()=>v(m))})})})}),x("div.s-body",()=>{x("div.s-body-inner",()=>{x(c),x(()=>{a==null||!a.items.length||(x(`nav.s-nav-panel.s-nav-${h}`,t.navAttrs,()=>{h1(a.items)}),x("div.s-nav-sep aria-hidden=true"))}),c0(t,d)}),x(()=>{a!=null&&a.items.length&&e.open&&d0(a,t.navPageAttrs,e,p)})}),x(()=>{t.footer!=null&&x("footer",()=>{x("div.s-bar",()=>{x(c),v(t.footer)})})})});if(p0(i,p),a!=null||d){let u=n=>{if(n.key!=="Escape"||n.defaultPrevented||z1()||i1())return;let m=i.querySelector(".s-nav-trigger button");if(e.open){n.preventDefault(),e.open=!1,m?.focus();return}if(d&&d.currentPanelIndex>0){n.preventDefault(),d.back();return}let g=i.querySelector(".s-nav-panel");if(g?.offsetParent!=null){let b=g.querySelector("[aria-current=page]")??g.querySelector(".s-menu-item:not([aria-disabled=true])");b&&(n.preventDefault(),b.focus());return}m&&(n.preventDefault(),m.click())};document.addEventListener("keydown",u),x.clean(()=>document.removeEventListener("keydown",u))}return d??void 0}var v1=null;function a0(){v1?.()}function h0(t,a,h,e){x(()=>{if(t.subtitle!=null&&(a==null||e0(a,h,e))){x("div.s-subtitle",()=>v(t.subtitle));return}a?.drawCrumbs()})}function e0(t,a,h){return h.narrow||a==null||t.panels.length>1?!1:b1(a.items)}function p0(t,a){if(typeof ResizeObserver>"u")return;let h=new ResizeObserver(e=>{let p=e[0]?.contentBoxSize?.[0],r=p?p.inlineSize:e[0]?.contentRect.width;r!=null&&(a.narrow=r<=r1)});h.observe(t),x.clean(()=>h.disconnect())}function r0(t,a){t1({icon:t.button?.icon??(()=>x(()=>(a.open?Q:d1)())),ariaLabel:t.button?.ariaLabel??"Open navigation",attrs:t.button?.attrs,click:()=>{a.open=!a.open}})}function d0(t,a,h,e){let p=!1,r=()=>{p=!0,h.open=!1},d=x("nav.s-nav-page.s-s.neutral aria-label=Navigation create=s-nav-page-off destroy=s-nav-page-off",a,()=>h1(t.items,r));v1=r,x.clean(()=>{v1===r&&(v1=null)});let o=x.peek(q1,"path");x(()=>{q1.path!==o&&!A1(q1.path)&&r()});let c=d.closest(".s-main"),i=d.parentElement?.querySelector(":scope > .s-body-inner"),u=i?.querySelector(":scope > main");i?.setAttribute("inert",""),x(()=>{e.narrow||(h.open=!1)}),x.clean(()=>{i?.removeAttribute("inert"),p&&(u&&o0(u),c?.querySelector(".s-nav-trigger button")?.focus())}),requestAnimationFrame(()=>{document.body.contains(d)&&j(d,".s-menu-item[aria-current=page]")})}function o0(t){t.classList.add("s-slide-in"),t.offsetWidth,t.classList.remove("s-slide-in")}function c0(t,a){if(a){a.drawColumns();return}let h=x("main",()=>{x("div.s-content",t.contentAttrs,()=>{v(t.content)})});n0(h)}function n0(t){if(typeof ResizeObserver>"u")return;let a=()=>t.classList.toggle("s-scroll-y",t.offsetWidth>t.clientWidth),h=new ResizeObserver(a);h.observe(t),t.firstElementChild&&h.observe(t.firstElementChild),a(),x.clean(()=>h.disconnect())}import S from"aberdeen";S.insertGlobalCss({".s-select_wrap":{"&":"position:relative display:block",select:"w:100% cursor:pointer padding-right:2.2em; appearance:none","&::after":"content: '\u25BE'; position:absolute right:0.7em top:50%; transform: translateY(-50%); pointer-events:none fg:$s-muted font-size:0.85em"}});function i0(t){I(t,(a,h)=>{S("div.s-select_wrap",()=>{S("select.s-input",t.inputAttrs,()=>{_(t,a,h),S("change=",e=>{t.bind&&(t.bind.value=e.target.value)}),S(()=>{let e=typeof t.options=="function"?t.options():t.options,p=t.bind?.value??"";t.placeholder!=null&&S("option",()=>{S("value= disabled=true hidden=true"),p||S("selected=true"),S("#",t.placeholder)});for(let r of e){let d=typeof r=="string"?{value:r,label:r}:{value:r.value,label:r.label??r.value};S("option",()=>{S("value=",d.value),d.value===p&&S("selected=true"),S("#",d.label)})}})})})})}import T from"aberdeen";T.insertGlobalCss({"textarea.s-input":"resize:vertical min-height:3em line-height:1.45","textarea.s-input.s-autoGrow":"resize:none min-height:2.5em overflow-y:hidden"});function s0(t={}){let a=t.autoGrow!==!1;I(t,(h,e)=>{let p=T("textarea.s-input",t.inputAttrs,()=>{a?(T(".s-autoGrow"),T("input=",r=>{c2(r.currentTarget),t.input&&t.input(r)})):(T("rows=",t.rows??4),T("resize:",t.resize??"vertical"),t.input&&T("input=",t.input)),t.placeholder!=null&&T("placeholder=",t.placeholder),t.value!=null&&!t.bind&&T("value=",t.value),t.change&&T("change=",t.change),_(t,h,e,t.bind)});a&&requestAnimationFrame(()=>c2(p))})}function c2(t){t.style.height="auto",t.style.height=`${t.scrollHeight}px`}import D from"aberdeen";D.insertGlobalCss({".s-tt-tip":{"&":"position:fixed z-index:500 max-width:20rem w:max-content padding: 0.3em 0.65em; font-size:0.85em line-height:1.4 pointer-events:none"}});var J=D.proxy(void 0),R=null;typeof window<"u"&&window.addEventListener("scroll",()=>{J.value=void 0},{capture:!0,passive:!0});function l0(t,a,h,e){let r=window.innerWidth,d=window.innerHeight,o=0,c=0;return e==="bottom"?(o=t.left+(t.width-a)/2,c=t.bottom+7,c+h>d-8&&(c=t.top-h-7)):e==="left"?(o=t.left-a-7,c=t.top+(t.height-h)/2,o<8&&(o=t.right+7)):e==="right"?(o=t.right+7,c=t.top+(t.height-h)/2,o+a>r-8&&(o=t.left-a-7)):(o=t.left+(t.width-a)/2,c=t.top-h-7,c<8&&(c=t.bottom+7)),{x:Math.max(8,Math.min(o,r-a-8)),y:Math.max(8,Math.min(c,d-h-8))}}function E1(){R&&clearTimeout(R),R=setTimeout(()=>{J.value=void 0,R=null},100)}F(()=>{let t=J.value;if(!t)return;let{opts:a,anchor:h}=t,e=a.placement??"top",p=D("div.s-tt-tip.s-s.neutral.shadow role=tooltip visibility:hidden",a.attrs,()=>{D("mouseenter=",()=>{R&&(clearTimeout(R),R=null)}),D("mouseleave=",E1),v(a.tip)});requestAnimationFrame(()=>{if(!document.body.contains(p))return;let r=h.getBoundingClientRect(),{x:d,y:o}=l0(r,p.offsetWidth,p.offsetHeight,e);p.style.left=d+"px",p.style.top=o+"px",p.style.visibility=""})});function M0(t){let a=h=>{R&&(clearTimeout(R),R=null),J.value={opts:t,anchor:h.currentTarget}};D("mouseenter=",a),D("mouseleave=",E1),D("focusin=",a),D("focusout=",E1),D.clean(()=>{J.value?.opts===t&&(J.value=void 0)})}export{k1 as addContextMenu,M0 as addTooltip,Z2 as alert,u2 as autocomplete,g2 as box,O as button,b2 as buttonChooser,W as buttonGroup,w2 as checkbox,O2 as closeFloatingMenu,a0 as closeNav,B2 as confirm,s1 as dialog,H2 as form,B1 as getDarkMode,t1 as iconButton,z1 as isDialogOpen,i1 as isFloatingMenuOpen,t0 as main,D2 as menu,R2 as menuButton,F2 as prompt,M1 as revealInStrip,l1 as scrollStrip,i0 as select,l2 as setDarkMode,V1 as showFloatingMenu,N2 as tabs,s0 as textarea,L1 as textline,o1 as toast};
|
package/package.json
CHANGED
package/src/components/dialog.ts
CHANGED
|
@@ -55,9 +55,7 @@ A.insertGlobalCss({
|
|
|
55
55
|
"position:fixed z-index:200 top:50% left:50% " +
|
|
56
56
|
"display:flex flex-direction:column " +
|
|
57
57
|
"transform:translate(-50%,-50%) " +
|
|
58
|
-
|
|
59
|
-
// zoom (see `watchScale` in main.ts), and these caps mean the window.
|
|
60
|
-
"min-width:20rem max-width:min(calc(90vw/var(--s-zoom,1)),44rem) max-height:min(calc(88vh/var(--s-zoom,1)),800px) " +
|
|
58
|
+
"min-width:min(20rem,90vw) max-width:min(90vw,44rem) max-height:min(88vh,800px) " +
|
|
61
59
|
"r: $s-radius-lg; overflow:hidden " +
|
|
62
60
|
"transition: opacity 0.2s ease-out, transform 0.2s ease-out;",
|
|
63
61
|
"> header":
|
package/src/components/main.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import A from "aberdeen";
|
|
2
2
|
import { current as currentRoute } from "aberdeen/route";
|
|
3
|
-
import { type Slot, type Attributes, drawSlot, focusFirst, NARROW_PX
|
|
3
|
+
import { type Slot, type Attributes, drawSlot, focusFirst, NARROW_PX } from "../core.js";
|
|
4
4
|
import { type MenuOptions, drawMenu, isFloatingMenuOpen, consumeBranchNav, anyCurrent } from "./menu.js";
|
|
5
5
|
// The shell's own chrome glyphs, from the same Lucide set an app draws with —
|
|
6
6
|
// so a nav trigger sits beside app icons as an equal. Named imports, so a
|
|
@@ -280,9 +280,7 @@ const NAV_W = 200;
|
|
|
280
280
|
A.insertGlobalCss({
|
|
281
281
|
".s-main": {
|
|
282
282
|
// container-type so @container queries below can respond to shell width.
|
|
283
|
-
|
|
284
|
-
// zoom (see `watchScale`), and this height means the window.
|
|
285
|
-
"&": "display:flex flex-direction:column min-height:calc(100vh/var(--s-zoom,1)) max-height:calc(100vh/var(--s-zoom,1)) container-type:inline-size",
|
|
283
|
+
"&": "display:flex flex-direction:column min-height:100vh max-height:100vh container-type:inline-size",
|
|
286
284
|
// <body> carries a default $3 padding; when the shell is a direct child of it,
|
|
287
285
|
// cancel that padding with matching negative margins so the chrome still spans
|
|
288
286
|
// edge to edge (and the 100vh sizing stays exact).
|
|
@@ -653,7 +651,6 @@ export function main<R extends RouteTable<R>>(opts: MainOptions<R> = {}): PanelS
|
|
|
653
651
|
}) as HTMLElement;
|
|
654
652
|
|
|
655
653
|
watchNarrow(root, $shell);
|
|
656
|
-
watchScale();
|
|
657
654
|
|
|
658
655
|
// Escape peels back a panel of UI, and finally jumps to the navigation: into
|
|
659
656
|
// the sidebar's current item when the sidebar is showing, or — when it has
|
|
@@ -788,48 +785,6 @@ function taglineFits(ctl: PanelStackController, nav: MenuOptions | undefined, $s
|
|
|
788
785
|
return anyCurrent(nav.items);
|
|
789
786
|
}
|
|
790
787
|
|
|
791
|
-
/** How many mounted shells are watching the window; the listener is one per page. */
|
|
792
|
-
let scaleShells = 0;
|
|
793
|
-
|
|
794
|
-
/** Lay the page out at a virtual {@link MIN_PX} and zoom it down to the window. */
|
|
795
|
-
function applyScale(): void {
|
|
796
|
-
// The real window width: <html> is never zoomed, so this stays unscaled.
|
|
797
|
-
const w = document.documentElement.clientWidth;
|
|
798
|
-
const f = w && w < MIN_PX ? w / MIN_PX : 0;
|
|
799
|
-
document.body.style.zoom = f ? String(f) : "";
|
|
800
|
-
// Published for the vh/vw lengths in the library's CSS, which zoom shrinks
|
|
801
|
-
// and a `/var(--s-zoom,1)` restores to meaning the window.
|
|
802
|
-
if (f) document.body.style.setProperty("--s-zoom", String(f));
|
|
803
|
-
else document.body.style.removeProperty("--s-zoom");
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
/**
|
|
807
|
-
* Below {@link MIN_PX} of window the shell stops squeezing and starts scaling:
|
|
808
|
-
* the page keeps its {@link MIN_PX} layout and CSS `zoom` shrinks it to fit,
|
|
809
|
-
* so a 180px window shows the 360px layout at half size. The zoom goes on
|
|
810
|
-
* `<body>`, so the overlays that portal there — dialogs, menus, toasts,
|
|
811
|
-
* tooltips — scale with the shell. `zoom` rather than `transform:scale`,
|
|
812
|
-
* because zoom keeps layout, container queries and the top layer in one
|
|
813
|
-
* system; what it splits instead is coordinate spaces — window-space rects
|
|
814
|
-
* against element-space lengths — which the few places mixing those bridge
|
|
815
|
-
* with {@link cssZoom}, and vh/vw lengths with `--s-zoom` (see `applyScale`).
|
|
816
|
-
* Browsers that predate `currentCSSZoom` (mid-2024) keep the squeeze.
|
|
817
|
-
*/
|
|
818
|
-
function watchScale(): void {
|
|
819
|
-
if (typeof window === "undefined" || !("currentCSSZoom" in document.documentElement)) return;
|
|
820
|
-
if (++scaleShells === 1) {
|
|
821
|
-
window.addEventListener("resize", applyScale);
|
|
822
|
-
applyScale();
|
|
823
|
-
}
|
|
824
|
-
A.clean(() => {
|
|
825
|
-
if (--scaleShells === 0) {
|
|
826
|
-
window.removeEventListener("resize", applyScale);
|
|
827
|
-
document.body.style.zoom = "";
|
|
828
|
-
document.body.style.removeProperty("--s-zoom");
|
|
829
|
-
}
|
|
830
|
-
});
|
|
831
|
-
}
|
|
832
|
-
|
|
833
788
|
/**
|
|
834
789
|
* Track whether the shell is narrow, for everything that has to agree about it.
|
|
835
790
|
*
|
package/src/components/menu.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import A from "aberdeen";
|
|
2
2
|
import { matchCurrent, current as currentRoute, go } from "aberdeen/route";
|
|
3
|
-
import {
|
|
3
|
+
import { type Slot, type Attributes, drawSlot, mountPortal, focusFirst } from "../core.js";
|
|
4
4
|
import { menu as menuIcon, chevronRight, externalLink as newTabIcon, link as linkIcon } from "../icons.js";
|
|
5
5
|
import { button, type ButtonOptions } from "./button.js";
|
|
6
6
|
import { toast } from "./toast.js";
|
|
@@ -161,7 +161,11 @@ A.insertGlobalCss({
|
|
|
161
161
|
".s-menu-list":
|
|
162
162
|
"position:fixed z-index:350 min-width:10rem display:flex flex-direction:column p:$1 " +
|
|
163
163
|
"r:$s-radius-lg " +
|
|
164
|
-
|
|
164
|
+
// The 16px off max-width is the 8px gap `positionMenu` leaves at either
|
|
165
|
+
// window edge: in a window too narrow for the menu, it narrows rather
|
|
166
|
+
// than hanging off the screen. (A `min-width` from the caller still wins,
|
|
167
|
+
// as CSS says it must — that ask is the app's to keep sensible.)
|
|
168
|
+
"max-width: calc(100vw - 16px); overflow-y:auto max-height:min(80vh,28rem) " +
|
|
165
169
|
"transition: opacity 0.15s, transform 0.15s, visibility 0.15s;",
|
|
166
170
|
".s-menu-list.hidden": "opacity:0 pointer-events:none transform:translateY(-6px) visibility:hidden",
|
|
167
171
|
// One class for both the `<a>` (link) and `<button>` forms — they look
|
|
@@ -538,18 +542,13 @@ export function closeFloatingMenu(anchor?: HTMLElement): void {
|
|
|
538
542
|
}
|
|
539
543
|
|
|
540
544
|
function positionMenu(menuEl: HTMLElement, rect: { left: number; right: number; top: number; bottom: number }): void {
|
|
541
|
-
// The rect arrives in window coordinates (an anchor's rect, or a pointer
|
|
542
|
-
// position); the left/top set below live in the menu's own space. The two
|
|
543
|
-
// differ when the shell has zoomed the page (see `watchScale` in main.ts),
|
|
544
|
-
// so everything is brought into the menu's space first.
|
|
545
|
-
const z = cssZoom(menuEl);
|
|
546
545
|
const mw = menuEl.offsetWidth, mh = menuEl.offsetHeight;
|
|
547
|
-
const vw = window.innerWidth
|
|
546
|
+
const vw = window.innerWidth, vh = window.innerHeight;
|
|
548
547
|
const gap = 4;
|
|
549
|
-
let x = rect.left
|
|
550
|
-
if (x + mw > vw - 8) x = Math.max(8, rect.right
|
|
551
|
-
let y = rect.bottom
|
|
552
|
-
if (y + mh > vh - 8 && rect.top
|
|
548
|
+
let x = rect.left;
|
|
549
|
+
if (x + mw > vw - 8) x = Math.max(8, rect.right - mw);
|
|
550
|
+
let y = rect.bottom + gap;
|
|
551
|
+
if (y + mh > vh - 8 && rect.top - mh - gap >= 8) y = rect.top - mh - gap;
|
|
553
552
|
menuEl.style.left = Math.max(8, x) + "px";
|
|
554
553
|
menuEl.style.top = Math.max(8, y) + "px";
|
|
555
554
|
}
|
package/src/components/panels.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import A, { OPAQUE } from "aberdeen";
|
|
2
2
|
import * as route from "aberdeen/route";
|
|
3
|
-
import { type Slot, drawSlot
|
|
3
|
+
import { type Slot, drawSlot } from "../core.js";
|
|
4
4
|
import {
|
|
5
5
|
circle as dotIcon, pin as pinIcon, pinOff as pinOffIcon,
|
|
6
6
|
slash as sepIcon, x as closeIcon,
|
|
@@ -202,6 +202,10 @@ export interface Panel<P = Record<string, string | number | string[]>> {
|
|
|
202
202
|
* window, never on what else is open, so opening or closing a panel never
|
|
203
203
|
* resizes another — the run of columns just recentres in the area.
|
|
204
204
|
*
|
|
205
|
+
* The ask is a ceiling only; there is no matching floor, since the window can
|
|
206
|
+
* be any width. Aim your layout at 360px — about the narrowest phone still in
|
|
207
|
+
* common use — and let it degrade gracefully below that.
|
|
208
|
+
*
|
|
205
209
|
* Ask only for what your content can actually use: a panel that would cap
|
|
206
210
|
* its own content narrower than its ask is holding room that would have
|
|
207
211
|
* let another column fit beside it.
|
|
@@ -429,13 +433,15 @@ const PAGE_MS = 250;
|
|
|
429
433
|
/** How long a freshly pushed `loading` panel holds its enter animation. */
|
|
430
434
|
const LOADING_HOLD_MS = 300;
|
|
431
435
|
/**
|
|
432
|
-
* The bounds of a column. At least 360px — the phone
|
|
433
|
-
*
|
|
434
|
-
* never reaches (`area / floor(area /
|
|
435
|
-
* lone column of a 540–720px area to it
|
|
436
|
-
* makes an ask's ceiling uniform: never
|
|
436
|
+
* The bounds of a column. At least 360px — about the narrowest phone still in
|
|
437
|
+
* common use, so it is where a panel's layout is aimed. And at most 540: that
|
|
438
|
+
* is the width the multi-column regime never reaches (`area / floor(area /
|
|
439
|
+
* 360)` stays under it), so capping the lone column of a 540–720px area to it
|
|
440
|
+
* too — centred, rather than stretched — makes an ask's ceiling uniform: never
|
|
441
|
+
* wider than its column count × 540. A content area narrower than 360 still
|
|
442
|
+
* gets its single column, just narrower than the minimum.
|
|
437
443
|
*/
|
|
438
|
-
const SMALL_MIN_PX =
|
|
444
|
+
const SMALL_MIN_PX = 360;
|
|
439
445
|
export const SMALL_MAX_PX = 540;
|
|
440
446
|
/**
|
|
441
447
|
* Panels are layered by their depth in the stack, two `z-index` steps per panel:
|
|
@@ -1741,6 +1747,13 @@ export class PanelStackController implements PanelStack {
|
|
|
1741
1747
|
// otherwise. A confirmed leave unloads the document before any of it
|
|
1742
1748
|
// is seen; the history entry the move makes is then where a back
|
|
1743
1749
|
// navigation returns to, which is right: the panel that held the tab.
|
|
1750
|
+
// `visible` is written by the layout pass, which waits for an animation
|
|
1751
|
+
// frame — and the frame owed to the navigation that parked this panel
|
|
1752
|
+
// may not have landed, all the more so in a tab on its way out, which
|
|
1753
|
+
// may never paint again. Settle it first, or a panel parked a moment
|
|
1754
|
+
// ago still reads as on screen and the guard skips the very move it
|
|
1755
|
+
// exists to make.
|
|
1756
|
+
this.flushLayout();
|
|
1744
1757
|
if (!dirty.$panel.visible) void this.focusAt(this.intended().stack.indexOf(dirty.path));
|
|
1745
1758
|
};
|
|
1746
1759
|
// Registered only while a panel actually holds unsaved work: a page with a
|
|
@@ -1884,10 +1897,19 @@ export class PanelStackController implements PanelStack {
|
|
|
1884
1897
|
scheduleLayout(): void {
|
|
1885
1898
|
if (this.layoutQueued) return;
|
|
1886
1899
|
this.layoutQueued = true;
|
|
1887
|
-
requestAnimationFrame(() =>
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1900
|
+
requestAnimationFrame(() => this.flushLayout());
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
/**
|
|
1904
|
+
* Run the pending layout pass now, rather than on the frame it is waiting
|
|
1905
|
+
* for. For the callers that have to *read* what only the pass knows —
|
|
1906
|
+
* `$panel.visible`, `$panel.width` — at a moment when waiting isn't an
|
|
1907
|
+
* option. Does nothing when no pass is owed.
|
|
1908
|
+
*/
|
|
1909
|
+
private flushLayout(): void {
|
|
1910
|
+
if (!this.layoutQueued) return;
|
|
1911
|
+
this.layoutQueued = false;
|
|
1912
|
+
this.layout();
|
|
1891
1913
|
}
|
|
1892
1914
|
|
|
1893
1915
|
/**
|
|
@@ -1915,10 +1937,7 @@ export class PanelStackController implements PanelStack {
|
|
|
1915
1937
|
*/
|
|
1916
1938
|
private measure(): Geometry | undefined {
|
|
1917
1939
|
const el = this.containerEl;
|
|
1918
|
-
|
|
1919
|
-
// back as CSS lengths, which live in the region's own space — different
|
|
1920
|
-
// spaces when the shell has zoomed the page (see `watchScale` in main.ts).
|
|
1921
|
-
const area = el ? el.getBoundingClientRect().width / cssZoom(el) : 0;
|
|
1940
|
+
const area = el ? el.getBoundingClientRect().width : 0;
|
|
1922
1941
|
if (!area) return undefined;
|
|
1923
1942
|
const small = Math.min(area / Math.max(1, Math.floor(area / SMALL_MIN_PX)), SMALL_MAX_PX);
|
|
1924
1943
|
const units = (n: number) => Math.min(n * small, area);
|
package/src/components/tabs.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import A from "aberdeen";
|
|
2
|
-
import {
|
|
2
|
+
import { type Bindable, type Slot, type Attributes, drawSlot, uniqueId } from "../core.js";
|
|
3
3
|
import { mk } from "../icons-helpers.js";
|
|
4
4
|
|
|
5
5
|
/** A single tab definition. */
|
|
@@ -143,11 +143,8 @@ export function revealInStrip(el: HTMLElement): void {
|
|
|
143
143
|
// The overlays are 2.4em wide; clearing a little more than that keeps the
|
|
144
144
|
// revealed item from sitting right against one.
|
|
145
145
|
const pad = parseFloat(getComputedStyle(row).fontSize) * 2.6;
|
|
146
|
-
// The rects are in window coordinates while `scrollBy` counts in the row's
|
|
147
|
-
// own space; their difference scales over by the row's zoom (see `cssZoom`).
|
|
148
|
-
const z = cssZoom(row);
|
|
149
146
|
const box = el.getBoundingClientRect(), strip = row.getBoundingClientRect();
|
|
150
|
-
const left =
|
|
147
|
+
const left = box.left - strip.left, right = box.right - strip.right;
|
|
151
148
|
if (left < pad) row.scrollBy({ left: left - pad, behavior: "smooth" });
|
|
152
149
|
else if (right > -pad) row.scrollBy({ left: right + pad, behavior: "smooth" });
|
|
153
150
|
}
|
package/src/components/toast.ts
CHANGED
|
@@ -32,9 +32,7 @@ A.insertGlobalCss({
|
|
|
32
32
|
".s-toasts":
|
|
33
33
|
"position:fixed bottom:$3 right:$3 z-index:400 " +
|
|
34
34
|
"display:flex flex-direction:column gap:$2 " +
|
|
35
|
-
|
|
36
|
-
// zoom (see `watchScale` in main.ts), and this cap means the window.
|
|
37
|
-
"pointer-events:none max-width:min(calc(90vw/var(--s-zoom,1)),24rem) w:24rem",
|
|
35
|
+
"pointer-events:none max-width:min(90vw,24rem) w:24rem",
|
|
38
36
|
".s-toast": {
|
|
39
37
|
"&":
|
|
40
38
|
"display:flex align-items:flex-start gap:$2 " +
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import A from "aberdeen";
|
|
2
|
-
import {
|
|
2
|
+
import { type Slot, type Attributes, drawSlot, mountPortal } from "../core.js";
|
|
3
3
|
|
|
4
4
|
/** Options for {@link addTooltip}. */
|
|
5
5
|
export interface TooltipOptions {
|
|
@@ -39,12 +39,10 @@ if (typeof window !== "undefined") {
|
|
|
39
39
|
window.addEventListener("scroll", () => { $ttActive.value = undefined; }, { capture: true, passive: true });
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
function computePos(rect: DOMRect, tipW: number, tipH: number, placement: string
|
|
43
|
-
// `rect` is handed over already in the tip's own coordinate space; the
|
|
44
|
-
// window's size has to be brought into it too (see `cssZoom`).
|
|
42
|
+
function computePos(rect: DOMRect, tipW: number, tipH: number, placement: string): { x: number; y: number } {
|
|
45
43
|
const gap = 7;
|
|
46
|
-
const vw = window.innerWidth
|
|
47
|
-
const vh = window.innerHeight
|
|
44
|
+
const vw = window.innerWidth;
|
|
45
|
+
const vh = window.innerHeight;
|
|
48
46
|
let x = 0, y = 0;
|
|
49
47
|
|
|
50
48
|
if (placement === "bottom") {
|
|
@@ -98,12 +96,8 @@ mountPortal(() => {
|
|
|
98
96
|
|
|
99
97
|
requestAnimationFrame(() => {
|
|
100
98
|
if (!document.body.contains(tipEl)) return;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const z = cssZoom(tipEl);
|
|
104
|
-
const r = anchor.getBoundingClientRect();
|
|
105
|
-
const rect = new DOMRect(r.x / z, r.y / z, r.width / z, r.height / z);
|
|
106
|
-
const { x, y } = computePos(rect, tipEl.offsetWidth, tipEl.offsetHeight, placement, z);
|
|
99
|
+
const rect = anchor.getBoundingClientRect();
|
|
100
|
+
const { x, y } = computePos(rect, tipEl.offsetWidth, tipEl.offsetHeight, placement);
|
|
107
101
|
tipEl.style.left = x + "px";
|
|
108
102
|
tipEl.style.top = y + "px";
|
|
109
103
|
tipEl.style.visibility = "";
|
package/src/core.ts
CHANGED
|
@@ -62,25 +62,6 @@ export interface ContentOptions {
|
|
|
62
62
|
*/
|
|
63
63
|
export const NARROW_PX = 640;
|
|
64
64
|
|
|
65
|
-
/**
|
|
66
|
-
* The narrowest layout the library is designed for. A panel must work at this
|
|
67
|
-
* width (panels.ts sizes its columns from it), and a window narrower than this
|
|
68
|
-
* is shown the 360px layout scaled down to fit rather than squeezed further
|
|
69
|
-
* (see `watchScale` in main.ts).
|
|
70
|
-
*/
|
|
71
|
-
export const MIN_PX = 360;
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* `el`'s effective CSS zoom: the factor between its own coordinate space and
|
|
75
|
-
* the window's — 1 wherever `zoom` isn't in play, or in browsers that predate
|
|
76
|
-
* it. A `getBoundingClientRect()` or pointer coordinate is in window space;
|
|
77
|
-
* divide it by this before using it as a length or scroll offset, which live
|
|
78
|
-
* in the element's own space. (`offsetWidth` and friends already do.)
|
|
79
|
-
*/
|
|
80
|
-
export function cssZoom(el: Element): number {
|
|
81
|
-
return (el as { currentCSSZoom?: number }).currentCSSZoom ?? 1;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
65
|
let idCounter = 0;
|
|
85
66
|
/** Generates a process-unique id, used to wire `<label for>` to its control. */
|
|
86
67
|
export function uniqueId(prefix = "s"): string {
|