gridsmith-ui 0.15.0 → 0.16.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/dist/charts.d.ts +20 -1
- package/dist/charts.js +64 -28
- package/dist/charts.js.map +1 -1
- package/dist/chat.js +3 -3
- package/dist/{chunk-ATONRIEB.js → chunk-2U2X6E2X.js} +36 -13
- package/dist/chunk-2U2X6E2X.js.map +1 -0
- package/dist/{chunk-X4CNZFWC.js → chunk-4LDYR7QP.js} +7 -7
- package/dist/chunk-4LDYR7QP.js.map +1 -0
- package/dist/{chunk-VFAKME7Q.js → chunk-5XOJZQIP.js} +106 -29
- package/dist/chunk-5XOJZQIP.js.map +1 -0
- package/dist/{chunk-XCSTU6IJ.js → chunk-PVTGMCVR.js} +3 -3
- package/dist/{chunk-XCSTU6IJ.js.map → chunk-PVTGMCVR.js.map} +1 -1
- package/dist/{chunk-LU3YRNES.js → chunk-XGSQOMEY.js} +4 -4
- package/dist/{chunk-LU3YRNES.js.map → chunk-XGSQOMEY.js.map} +1 -1
- package/dist/{chunk-M3AARGLI.js → chunk-Z63OSN64.js} +9 -8
- package/dist/chunk-Z63OSN64.js.map +1 -0
- package/dist/data-grid.js +1 -1
- package/dist/editor.js +11 -5
- package/dist/editor.js.map +1 -1
- package/dist/{feather-B65FI6CY.js → feather-2JFSFLXN.js} +3 -2
- package/dist/feather-2JFSFLXN.js.map +1 -0
- package/dist/{heroicons-DIR7PXCR.js → heroicons-4AQ4YBVG.js} +3 -2
- package/dist/heroicons-4AQ4YBVG.js.map +1 -0
- package/dist/icons.d.ts +1 -1
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +68 -5
- package/dist/index.js +884 -471
- package/dist/index.js.map +1 -1
- package/dist/kanban.d.ts +11 -1
- package/dist/kanban.js +225 -113
- package/dist/kanban.js.map +1 -1
- package/dist/{lucide-JH2R3TFV.js → lucide-RZC2FEMS.js} +3 -2
- package/dist/lucide-RZC2FEMS.js.map +1 -0
- package/dist/{phosphor-HCVUMVT5.js → phosphor-CEN25FLM.js} +3 -2
- package/dist/phosphor-CEN25FLM.js.map +1 -0
- package/dist/resizable.d.ts +11 -1
- package/dist/resizable.js +79 -21
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +11 -8
- package/dist/{tabler-HHIXSM73.js → tabler-YXXC7Y6B.js} +3 -2
- package/dist/tabler-YXXC7Y6B.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-ATONRIEB.js.map +0 -1
- package/dist/chunk-M3AARGLI.js.map +0 -1
- package/dist/chunk-VFAKME7Q.js.map +0 -1
- package/dist/chunk-X4CNZFWC.js.map +0 -1
- package/dist/feather-B65FI6CY.js.map +0 -1
- package/dist/heroicons-DIR7PXCR.js.map +0 -1
- package/dist/lucide-JH2R3TFV.js.map +0 -1
- package/dist/phosphor-HCVUMVT5.js.map +0 -1
- package/dist/tabler-HHIXSM73.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import { useAppShell, ControlSizeContext, Button,
|
|
2
|
-
export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell } from './chunk-
|
|
3
|
-
import { Skeleton } from './chunk-
|
|
4
|
-
export { Skeleton } from './chunk-
|
|
5
|
-
import { usePopupFocus,
|
|
6
|
-
import { Link } from './chunk-
|
|
7
|
-
export { CodeBlock, Divider, Link } from './chunk-
|
|
8
|
-
import { Badge } from './chunk-
|
|
9
|
-
export { Badge } from './chunk-
|
|
1
|
+
import { useAppShell, ControlSizeContext, Button, useDirtyGuard, OverlayCloseCtx, DiscardConfirm, Spinner, DrawerFooterCtx, useCompact, useElementWidth, Sheet, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, defaultMaxWidth } from './chunk-2U2X6E2X.js';
|
|
2
|
+
export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell, useUnsavedChanges } from './chunk-2U2X6E2X.js';
|
|
3
|
+
import { Skeleton } from './chunk-Z63OSN64.js';
|
|
4
|
+
export { Skeleton } from './chunk-Z63OSN64.js';
|
|
5
|
+
import { FOCUSABLE, usePopupFocus, useOverlayLayer, useFocusTrap, useFocusBeforeOpen, rememberFocus, focusInitial, OVERLAY_CLOSE_ATTR, focusAfterRemoval, rovingTabStop, useGridKeyboard, useNonModalDialog, usePressMarks, useReturnFocus, useCloseOnFocusOut } from './chunk-5XOJZQIP.js';
|
|
6
|
+
import { Link } from './chunk-XGSQOMEY.js';
|
|
7
|
+
export { CodeBlock, Divider, Link } from './chunk-XGSQOMEY.js';
|
|
8
|
+
import { Badge } from './chunk-PVTGMCVR.js';
|
|
9
|
+
export { Badge } from './chunk-PVTGMCVR.js';
|
|
10
10
|
import { inferColumnKinds, CardValue } from './chunk-OENJCGTJ.js';
|
|
11
11
|
import { SplitPaneCtx, useShellPreferences, TableCardCtx, PREFERENCE_HOUSE_DEFAULTS, preferenceActionKey } from './chunk-TKVTZWBN.js';
|
|
12
12
|
export { PreferencesContext, preferenceActionKey, usePreferences } from './chunk-TKVTZWBN.js';
|
|
13
|
-
import { useBreakpoint } from './chunk-CRQ6KCRD.js';
|
|
13
|
+
import { useBreakpoint, readBreakpointPx } from './chunk-CRQ6KCRD.js';
|
|
14
14
|
export { BreakpointWidthProvider, useBreakpoint } from './chunk-CRQ6KCRD.js';
|
|
15
15
|
import { useTextOverflow, Tooltip, usePosition } from './chunk-EMCSARQO.js';
|
|
16
16
|
export { Tooltip, useTextOverflow } from './chunk-EMCSARQO.js';
|
|
17
17
|
import { mergeRefs, Slot } from './chunk-7Q46JXSK.js';
|
|
18
18
|
import { useLatest } from './chunk-WH2FUFAC.js';
|
|
19
|
-
import { Icon } from './chunk-
|
|
20
|
-
import { cn, GLASS_SURFACE, ACTIVE_RING, GLASS_BACKDROP, GLASS_DROPDOWN, ERROR_ACTIVE_RING, ERROR_FOCUS_RING, FOCUS_RING, ERROR_HAS_FOCUS_RING, HAS_FOCUS_RING, ERROR_FOCUS_WITHIN_RING, FOCUS_WITHIN_RING
|
|
21
|
-
import { createContext, forwardRef, useState,
|
|
22
|
-
import { createPortal } from 'react-dom';
|
|
19
|
+
import { Icon } from './chunk-4LDYR7QP.js';
|
|
20
|
+
import { cn, GLASS_SURFACE, ACTIVE_RING, GLASS_BACKDROP, GLASS_DROPDOWN, lockBodyScroll, unlockBodyScroll, GLASS_OVERLAY, ERROR_ACTIVE_RING, ERROR_FOCUS_RING, FOCUS_RING, ERROR_HAS_FOCUS_RING, HAS_FOCUS_RING, ERROR_FOCUS_WITHIN_RING, FOCUS_WITHIN_RING } from './chunk-4KVFH5KC.js';
|
|
21
|
+
import { createContext, forwardRef, useState, useRef, useCallback, useLayoutEffect, useMemo, useContext, useId, memo, useEffect, Children, isValidElement, cloneElement, Fragment as Fragment$1, useSyncExternalStore } from 'react';
|
|
22
|
+
import { createPortal, flushSync } from 'react-dom';
|
|
23
23
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
24
24
|
|
|
25
25
|
function isDivider(entry) {
|
|
@@ -44,10 +44,10 @@ function DropdownMenu({ trigger, items, align = "end", className, container }) {
|
|
|
44
44
|
useEffect(() => {
|
|
45
45
|
if (!open) return;
|
|
46
46
|
const onKeyDown = (e) => {
|
|
47
|
-
if (e.key
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
returnFocus();
|
|
50
|
+
setOpen(false);
|
|
51
51
|
};
|
|
52
52
|
const onClick = (e) => {
|
|
53
53
|
const target = e.target;
|
|
@@ -523,7 +523,7 @@ function Dropdown({
|
|
|
523
523
|
const els = optionButtons();
|
|
524
524
|
const current = els.findIndex((el) => el === document.activeElement);
|
|
525
525
|
if (e.key === "Escape") {
|
|
526
|
-
if (!isTopLayer()) return;
|
|
526
|
+
if (e.defaultPrevented || !isTopLayer()) return;
|
|
527
527
|
e.preventDefault();
|
|
528
528
|
returnFocus();
|
|
529
529
|
setOpen(false);
|
|
@@ -585,14 +585,14 @@ function Dropdown({
|
|
|
585
585
|
};
|
|
586
586
|
const chipsRef = useRef(null);
|
|
587
587
|
const pendingChipFocus = useRef(null);
|
|
588
|
-
const chipCount = selectedValues.length;
|
|
589
588
|
useLayoutEffect(() => {
|
|
590
|
-
const
|
|
591
|
-
if (
|
|
589
|
+
const pending = pendingChipFocus.current;
|
|
590
|
+
if (pending === null) return;
|
|
592
591
|
pendingChipFocus.current = null;
|
|
592
|
+
if (selectedValues.includes(pending.value)) return;
|
|
593
593
|
const chips = Array.from(chipsRef.current?.querySelectorAll("[data-chip-remove]") ?? []);
|
|
594
|
-
focusAfterRemoval(chips, index, triggerRef.current);
|
|
595
|
-
}
|
|
594
|
+
focusAfterRemoval(chips, pending.index, triggerRef.current);
|
|
595
|
+
});
|
|
596
596
|
const displayLabel = multiple ? selectedValues.length > 0 ? `${selectedValues.length} selected` : placeholder : options.find((o) => o.id === selectedValues[0])?.label ?? placeholder;
|
|
597
597
|
const { ref: overflowRef, isTruncated } = useTextOverflow({ lines: 1, content: displayLabel });
|
|
598
598
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn("relative", className), children: [
|
|
@@ -705,7 +705,7 @@ function Dropdown({
|
|
|
705
705
|
{
|
|
706
706
|
"data-chip-remove": "",
|
|
707
707
|
onClick: () => {
|
|
708
|
-
pendingChipFocus.current = i;
|
|
708
|
+
pendingChipFocus.current = { index: i, value: v };
|
|
709
709
|
handleSelect(v);
|
|
710
710
|
},
|
|
711
711
|
className: "hover:text-[var(--ds-text-primary)] cursor-pointer",
|
|
@@ -845,9 +845,14 @@ function Combobox({ value, onChange, options, placeholder = "Search\u2026", disa
|
|
|
845
845
|
} else if (e.key === "Enter" && open && filtered[highlightIdx]) {
|
|
846
846
|
e.preventDefault();
|
|
847
847
|
handleSelect(filtered[highlightIdx].value);
|
|
848
|
-
} else if (e.key === "Tab" && open
|
|
849
|
-
onChange(filtered[highlightIdx].value);
|
|
850
|
-
|
|
848
|
+
} else if (e.key === "Tab" && open) {
|
|
849
|
+
if (moved && filtered[highlightIdx]) onChange(filtered[highlightIdx].value);
|
|
850
|
+
flushSync(() => {
|
|
851
|
+
setOpen(false);
|
|
852
|
+
setQuery("");
|
|
853
|
+
});
|
|
854
|
+
} else if (e.key === "Escape" && open) {
|
|
855
|
+
e.preventDefault();
|
|
851
856
|
setOpen(false);
|
|
852
857
|
setQuery("");
|
|
853
858
|
}
|
|
@@ -1362,8 +1367,9 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1362
1367
|
const raf = requestAnimationFrame(() => focusActiveDay.current());
|
|
1363
1368
|
return () => cancelAnimationFrame(raf);
|
|
1364
1369
|
}, [open, focusActiveDay]);
|
|
1365
|
-
const
|
|
1370
|
+
const choose = (d) => {
|
|
1366
1371
|
returnFocus();
|
|
1372
|
+
onChange(d);
|
|
1367
1373
|
setOpen(false);
|
|
1368
1374
|
};
|
|
1369
1375
|
const dayFirst = useMemo(() => localeDayFirst(), []);
|
|
@@ -1388,10 +1394,10 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1388
1394
|
setOpen(false);
|
|
1389
1395
|
};
|
|
1390
1396
|
const keyHandler = (e) => {
|
|
1391
|
-
if (e.key
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1397
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
1398
|
+
e.preventDefault();
|
|
1399
|
+
returnFocus();
|
|
1400
|
+
setOpen(false);
|
|
1395
1401
|
};
|
|
1396
1402
|
document.addEventListener("mousedown", handler);
|
|
1397
1403
|
document.addEventListener("keydown", keyHandler);
|
|
@@ -1485,8 +1491,7 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1485
1491
|
const selectDay = (day) => {
|
|
1486
1492
|
const d = new Date(year, month, day);
|
|
1487
1493
|
if (isDisabledDay(d)) return;
|
|
1488
|
-
|
|
1489
|
-
closeAndRefocus();
|
|
1494
|
+
choose(d);
|
|
1490
1495
|
};
|
|
1491
1496
|
const rangeA = range?.start ?? null;
|
|
1492
1497
|
const rangeB = range?.end ?? null;
|
|
@@ -1676,8 +1681,7 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1676
1681
|
onClick: () => {
|
|
1677
1682
|
const now = /* @__PURE__ */ new Date();
|
|
1678
1683
|
setViewDate(now);
|
|
1679
|
-
|
|
1680
|
-
closeAndRefocus();
|
|
1684
|
+
choose(now);
|
|
1681
1685
|
},
|
|
1682
1686
|
children: "Today"
|
|
1683
1687
|
}
|
|
@@ -1687,10 +1691,7 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1687
1691
|
{
|
|
1688
1692
|
variant: "ghost",
|
|
1689
1693
|
size: "sm",
|
|
1690
|
-
onClick: () =>
|
|
1691
|
-
onChange(null);
|
|
1692
|
-
closeAndRefocus();
|
|
1693
|
-
},
|
|
1694
|
+
onClick: () => choose(null),
|
|
1694
1695
|
children: "Clear"
|
|
1695
1696
|
}
|
|
1696
1697
|
)
|
|
@@ -1962,6 +1963,10 @@ function DateRangePicker({
|
|
|
1962
1963
|
keyOf: dayKey,
|
|
1963
1964
|
move: (from, e) => moveDay(from, e.key, e.shiftKey, weekStartsOn)
|
|
1964
1965
|
});
|
|
1966
|
+
const pageMonths = (n) => {
|
|
1967
|
+
setViewDate(addMonths(viewDate, n));
|
|
1968
|
+
setFocusDate(addMonthsClamped(focusDate, n));
|
|
1969
|
+
};
|
|
1965
1970
|
const { isTop: isTopLayer, returnFocus } = usePopupFocus(open, { trigger: triggerRef, panel: panelRef, close: () => setOpen(false), tabExits: "edges" });
|
|
1966
1971
|
const focusActiveDay = useLatest(grid.focusActive);
|
|
1967
1972
|
useEffect(() => {
|
|
@@ -1977,10 +1982,10 @@ function DateRangePicker({
|
|
|
1977
1982
|
setOpen(false);
|
|
1978
1983
|
};
|
|
1979
1984
|
const onKey = (e) => {
|
|
1980
|
-
if (e.key
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1985
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
1986
|
+
e.preventDefault();
|
|
1987
|
+
returnFocus();
|
|
1988
|
+
setOpen(false);
|
|
1984
1989
|
};
|
|
1985
1990
|
document.addEventListener("mousedown", onMouse);
|
|
1986
1991
|
document.addEventListener("keydown", onKey);
|
|
@@ -2071,7 +2076,7 @@ function DateRangePicker({
|
|
|
2071
2076
|
}, children: p.label }, p.label)) }),
|
|
2072
2077
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
2073
2078
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between bg-[var(--ds-bg-muted)] rounded-tr-[var(--ds-radius-md)] px-ds-3 py-ds-2", children: [
|
|
2074
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () =>
|
|
2079
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => pageMonths(-1), "aria-label": "Previous month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14, className: "rotate-180" }) }),
|
|
2075
2080
|
/* @__PURE__ */ jsxs("span", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: [
|
|
2076
2081
|
MONTHS2[months[0].getMonth()],
|
|
2077
2082
|
" ",
|
|
@@ -2081,7 +2086,7 @@ function DateRangePicker({
|
|
|
2081
2086
|
" ",
|
|
2082
2087
|
months[1].getFullYear()
|
|
2083
2088
|
] }),
|
|
2084
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () =>
|
|
2089
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => pageMonths(1), "aria-label": "Next month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14 }) })
|
|
2085
2090
|
] }),
|
|
2086
2091
|
/* @__PURE__ */ jsx("div", { ref: gridRef, onKeyDown: grid.onKeyDown, className: "flex gap-ds-4 px-ds-3 py-ds-2", onMouseLeave: () => setHover(null), children: months.map((m) => /* @__PURE__ */ jsxs("div", { role: "grid", "aria-label": `${MONTHS2[m.getMonth()]} ${m.getFullYear()}`, className: "w-[224px] flex flex-col gap-ds-0.5", children: [
|
|
2087
2092
|
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-ds-0.5 mb-ds-0.5", children: dayNames.map((d) => /* @__PURE__ */ jsx("div", { role: "columnheader", className: "text-center text-2xs font-medium text-[var(--ds-text-muted)] py-ds-1", children: d }, d)) }),
|
|
@@ -2135,6 +2140,96 @@ function DateRangePicker({
|
|
|
2135
2140
|
)
|
|
2136
2141
|
] });
|
|
2137
2142
|
}
|
|
2143
|
+
|
|
2144
|
+
// ../../showcase/src/lib/file-accept.ts
|
|
2145
|
+
var MIME_NAMES = {
|
|
2146
|
+
"text/plain": "TXT",
|
|
2147
|
+
"audio/mpeg": "MP3",
|
|
2148
|
+
"video/quicktime": "MOV",
|
|
2149
|
+
"application/msword": "DOC",
|
|
2150
|
+
"application/vnd.ms-excel": "XLS",
|
|
2151
|
+
"application/vnd.ms-powerpoint": "PPT",
|
|
2152
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "DOCX",
|
|
2153
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "XLSX",
|
|
2154
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "PPTX"
|
|
2155
|
+
};
|
|
2156
|
+
var EXT_NAMES = { jpeg: "JPG", tif: "TIFF", htm: "HTML", yml: "YAML" };
|
|
2157
|
+
var FAMILIES = {
|
|
2158
|
+
image: { one: "an image", many: "images" },
|
|
2159
|
+
video: { one: "a video", many: "videos" },
|
|
2160
|
+
audio: { one: "an audio file", many: "audio files" },
|
|
2161
|
+
text: { one: "a text file", many: "text files" }
|
|
2162
|
+
};
|
|
2163
|
+
var READ_AS_WORD = /* @__PURE__ */ new Set(["FLAC", "HEIC", "HEIF", "LOG", "MIDI", "MOV", "RAR", "RAW"]);
|
|
2164
|
+
var extName = (ext) => EXT_NAMES[ext] ?? ext.toUpperCase();
|
|
2165
|
+
function mimeName(mime) {
|
|
2166
|
+
if (MIME_NAMES[mime]) return MIME_NAMES[mime];
|
|
2167
|
+
const subtype = mime.slice(mime.indexOf("/") + 1).replace(/\+.*$/, "").replace(/^(?:x-|vnd\.)/, "");
|
|
2168
|
+
return extName(subtype.slice(subtype.lastIndexOf(".") + 1));
|
|
2169
|
+
}
|
|
2170
|
+
function parseAccept(accept) {
|
|
2171
|
+
return (accept ?? "").split(",").map((t) => t.trim().toLowerCase()).filter(Boolean).map((t) => {
|
|
2172
|
+
if (t === "*" || t === "*/*") return { kind: "any" };
|
|
2173
|
+
if (t.startsWith(".")) return { kind: "format", name: extName(t.slice(1)), suffix: t };
|
|
2174
|
+
if (t.endsWith("/*")) return { kind: "family", family: t.slice(0, -2) };
|
|
2175
|
+
return { kind: "format", name: mimeName(t), mime: t };
|
|
2176
|
+
});
|
|
2177
|
+
}
|
|
2178
|
+
function fileFormat(file) {
|
|
2179
|
+
const dot = file.name.lastIndexOf(".");
|
|
2180
|
+
return dot > 0 ? extName(file.name.slice(dot + 1).toLowerCase()) : null;
|
|
2181
|
+
}
|
|
2182
|
+
function matches(file, tokens) {
|
|
2183
|
+
if (tokens.length === 0 || tokens.some((t) => t.kind === "any")) return true;
|
|
2184
|
+
const name = file.name.toLowerCase();
|
|
2185
|
+
const format = fileFormat(file);
|
|
2186
|
+
const type = file.type.toLowerCase();
|
|
2187
|
+
return tokens.some((t) => {
|
|
2188
|
+
if (t.kind === "family") return type === "" || type.startsWith(`${t.family}/`);
|
|
2189
|
+
if (t.kind !== "format") return false;
|
|
2190
|
+
return t.name === format || t.suffix != null && name.endsWith(t.suffix) || t.mime != null && t.mime === type;
|
|
2191
|
+
});
|
|
2192
|
+
}
|
|
2193
|
+
var joinOr = (items) => items.length < 2 ? items.join("") : `${items.slice(0, -1).join(", ")} or ${items[items.length - 1]}`;
|
|
2194
|
+
var article = (name) => {
|
|
2195
|
+
const asWord = name.replace(/[^A-Z]/g, "").length >= 5 || READ_AS_WORD.has(name);
|
|
2196
|
+
return (asWord ? /^[AEIOU]/ : /^[AEFHILMNORSX]/).test(name) ? "an" : "a";
|
|
2197
|
+
};
|
|
2198
|
+
function typeWords(accept) {
|
|
2199
|
+
const tokens = parseAccept(accept);
|
|
2200
|
+
if (tokens.length === 0 || tokens.some((t) => t.kind === "any" || t.kind === "family" && !FAMILIES[t.family])) return null;
|
|
2201
|
+
const families = [...new Set(tokens.flatMap((t) => t.kind === "family" ? [t.family] : []))].map((f) => FAMILIES[f]);
|
|
2202
|
+
const formats = [...new Set(tokens.flatMap((t) => t.kind === "format" ? [t.name] : []))];
|
|
2203
|
+
const many = `${joinOr([...families.map((f) => f.many), ...formats])}${formats.length ? " files" : ""}`;
|
|
2204
|
+
const one = families.length === 0 ? `${article(formats[0])} ${joinOr(formats)}` : joinOr([...families.map((f) => f.one), ...formats.map((f) => `${article(f)} ${f}`)]);
|
|
2205
|
+
return { one, many };
|
|
2206
|
+
}
|
|
2207
|
+
function sizeWords(bytes) {
|
|
2208
|
+
const units = [["GB", 1024 ** 3], ["MB", 1024 ** 2], ["KB", 1024]];
|
|
2209
|
+
for (const [unit, size] of units) if (bytes >= size) return `${Math.round(bytes / size * 10) / 10} ${unit}`;
|
|
2210
|
+
return `${bytes} bytes`;
|
|
2211
|
+
}
|
|
2212
|
+
var capitalise = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
2213
|
+
function fileConstraints(accept, maxSize, multiple) {
|
|
2214
|
+
const types = typeWords(accept)?.many;
|
|
2215
|
+
const size = maxSize != null ? `up to ${sizeWords(maxSize)}${multiple ? " each" : ""}` : null;
|
|
2216
|
+
const line = [types, size].filter(Boolean).join(" ");
|
|
2217
|
+
return line ? capitalise(line) : null;
|
|
2218
|
+
}
|
|
2219
|
+
function checkFiles(files, { accept, maxSize, multiple }) {
|
|
2220
|
+
if (!multiple && files.length > 1) return { accepted: [], message: "You can only select one file" };
|
|
2221
|
+
const tokens = parseAccept(accept);
|
|
2222
|
+
const types = typeWords(accept);
|
|
2223
|
+
const accepted = [];
|
|
2224
|
+
const reasons = [];
|
|
2225
|
+
for (const file of files) {
|
|
2226
|
+
const subject = multiple ? file.name : "The selected file";
|
|
2227
|
+
if (!matches(file, tokens)) reasons.push(types ? `${subject} must be ${types.one}` : `${subject} is not a file type that can be added here`);
|
|
2228
|
+
else if (maxSize != null && file.size > maxSize) reasons.push(`${subject} must be smaller than ${sizeWords(maxSize)}`);
|
|
2229
|
+
else accepted.push(file);
|
|
2230
|
+
}
|
|
2231
|
+
return { accepted, message: reasons.length ? reasons.join("; ") : null };
|
|
2232
|
+
}
|
|
2138
2233
|
var variantFills = {
|
|
2139
2234
|
default: "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)]",
|
|
2140
2235
|
success: "bg-[var(--ds-status-success)]",
|
|
@@ -2182,6 +2277,66 @@ function Progress({ value, max = 100, variant = "default", size = "md", indeterm
|
|
|
2182
2277
|
] })
|
|
2183
2278
|
] });
|
|
2184
2279
|
}
|
|
2280
|
+
function InlineFieldError({ message, id, className }) {
|
|
2281
|
+
return /* @__PURE__ */ jsxs(
|
|
2282
|
+
"p",
|
|
2283
|
+
{
|
|
2284
|
+
id,
|
|
2285
|
+
role: "alert",
|
|
2286
|
+
className: cn(
|
|
2287
|
+
"flex items-center gap-ds-1.5 text-xs text-[var(--ds-status-error)]",
|
|
2288
|
+
"mt-ds-1.5",
|
|
2289
|
+
className
|
|
2290
|
+
),
|
|
2291
|
+
children: [
|
|
2292
|
+
/* @__PURE__ */ jsx(Icon, { name: "error", size: 14, className: "shrink-0" }),
|
|
2293
|
+
/* @__PURE__ */ jsx("span", { children: message })
|
|
2294
|
+
]
|
|
2295
|
+
}
|
|
2296
|
+
);
|
|
2297
|
+
}
|
|
2298
|
+
var FieldContext = createContext(null);
|
|
2299
|
+
function useField() {
|
|
2300
|
+
return useContext(FieldContext);
|
|
2301
|
+
}
|
|
2302
|
+
function Field({ label, children, hint, error, required, labelAction, id: idProp, className }) {
|
|
2303
|
+
const generated = useId();
|
|
2304
|
+
const id = idProp ?? `field-${generated}`;
|
|
2305
|
+
const hintId = `${id}-hint`;
|
|
2306
|
+
const errorId = `${id}-error`;
|
|
2307
|
+
const hasError = typeof error === "string" && error.length > 0;
|
|
2308
|
+
const describedBy = [hint ? hintId : null, hasError ? errorId : null].filter(Boolean).join(" ") || void 0;
|
|
2309
|
+
const labelId = `${id}-label`;
|
|
2310
|
+
const fieldContext = useMemo(() => ({ controlId: id, labelId, describedBy }), [id, labelId, describedBy]);
|
|
2311
|
+
const controlProps = {
|
|
2312
|
+
id,
|
|
2313
|
+
"aria-describedby": describedBy,
|
|
2314
|
+
...hasError ? { "aria-invalid": true, error: true } : {},
|
|
2315
|
+
...required ? { "aria-required": true, required: true } : {}
|
|
2316
|
+
};
|
|
2317
|
+
let control;
|
|
2318
|
+
if (typeof children === "function") {
|
|
2319
|
+
control = children(controlProps);
|
|
2320
|
+
} else {
|
|
2321
|
+
const child = Children.only(children);
|
|
2322
|
+
if (!isValidElement(child)) throw new Error("Field expects a single form control as its child");
|
|
2323
|
+
const isNative = typeof child.type === "string";
|
|
2324
|
+
const { error: errorFlag, ...ariaOnly } = controlProps;
|
|
2325
|
+
control = cloneElement(child, isNative ? ariaOnly : { ...ariaOnly, ...errorFlag ? { error: true } : {} });
|
|
2326
|
+
}
|
|
2327
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-ds-1.5", className), children: [
|
|
2328
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-ds-2", children: [
|
|
2329
|
+
/* @__PURE__ */ jsxs(Label, { id: labelId, htmlFor: id, children: [
|
|
2330
|
+
label,
|
|
2331
|
+
required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ml-ds-0.5 text-[var(--ds-status-error)]", children: "*" })
|
|
2332
|
+
] }),
|
|
2333
|
+
labelAction
|
|
2334
|
+
] }),
|
|
2335
|
+
/* @__PURE__ */ jsx(FieldContext.Provider, { value: fieldContext, children: control }),
|
|
2336
|
+
hint && /* @__PURE__ */ jsx("p", { id: hintId, className: "text-xs text-[var(--ds-text-muted)]", children: hint }),
|
|
2337
|
+
hasError && /* @__PURE__ */ jsx(InlineFieldError, { id: errorId, message: error, className: "mt-0" })
|
|
2338
|
+
] });
|
|
2339
|
+
}
|
|
2185
2340
|
function TruncFileName({ children, className }) {
|
|
2186
2341
|
const { ref, isTruncated } = useTextOverflow({ lines: 1 });
|
|
2187
2342
|
const el = /* @__PURE__ */ jsx("p", { ref, className: cn("truncate", className), children });
|
|
@@ -2193,37 +2348,57 @@ function formatSize(bytes) {
|
|
|
2193
2348
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
2194
2349
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
2195
2350
|
}
|
|
2196
|
-
function FileUpload({ onFiles, accept, multiple = true, maxSize, className, error = false, label }) {
|
|
2351
|
+
function FileUpload({ onFiles, accept, multiple = true, maxSize, className, error = false, label, id }) {
|
|
2197
2352
|
const [files, setFiles] = useState([]);
|
|
2198
2353
|
const [dragOver, setDragOver] = useState(false);
|
|
2199
|
-
const
|
|
2354
|
+
const [rejected, setRejected] = useState(null);
|
|
2200
2355
|
const inputRef = useRef(null);
|
|
2356
|
+
const nextEntryId = useRef(0);
|
|
2357
|
+
const timers = useRef(/* @__PURE__ */ new Map());
|
|
2358
|
+
useEffect(() => {
|
|
2359
|
+
const running = timers.current;
|
|
2360
|
+
return () => running.forEach(clearInterval);
|
|
2361
|
+
}, []);
|
|
2362
|
+
const field = useField();
|
|
2363
|
+
const ownId = useId();
|
|
2364
|
+
const inputId = id ?? `${ownId}-input`;
|
|
2365
|
+
const constraintsId = `${ownId}-constraints`;
|
|
2366
|
+
const rejectedId = `${ownId}-rejected`;
|
|
2367
|
+
const showLabel = label != null && !field;
|
|
2368
|
+
const constraints = fileConstraints(accept, maxSize, multiple);
|
|
2369
|
+
const invalid = error || rejected != null;
|
|
2370
|
+
const describedBy = [constraints ? constraintsId : null, field?.describedBy, rejected ? rejectedId : null].filter(Boolean).join(" ") || void 0;
|
|
2371
|
+
const stopTimer = (id2) => {
|
|
2372
|
+
clearInterval(timers.current.get(id2));
|
|
2373
|
+
timers.current.delete(id2);
|
|
2374
|
+
};
|
|
2201
2375
|
const addFiles = useCallback(
|
|
2202
2376
|
(fileList) => {
|
|
2203
|
-
const
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2377
|
+
const { accepted, message } = checkFiles(Array.from(fileList), { accept, maxSize, multiple });
|
|
2378
|
+
setRejected(message);
|
|
2379
|
+
if (accepted.length === 0) return;
|
|
2380
|
+
const entries = accepted.map((file) => ({ id: nextEntryId.current++, file, progress: 0, status: "uploading" }));
|
|
2381
|
+
if (!multiple) {
|
|
2382
|
+
timers.current.forEach(clearInterval);
|
|
2383
|
+
timers.current.clear();
|
|
2384
|
+
}
|
|
2385
|
+
setFiles((prev) => multiple ? [...prev, ...entries] : entries);
|
|
2386
|
+
onFiles(accepted);
|
|
2387
|
+
for (const { id: id2 } of entries) {
|
|
2209
2388
|
let progress = 0;
|
|
2210
|
-
const
|
|
2211
|
-
progress
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
clearInterval(
|
|
2215
|
-
|
|
2216
|
-
(prev) => prev.map((f, fi) => fi === prev.length - entries.length + i ? { ...f, progress: 100, status: "complete" } : f)
|
|
2217
|
-
);
|
|
2218
|
-
} else {
|
|
2219
|
-
setFiles(
|
|
2220
|
-
(prev) => prev.map((f, fi) => fi === prev.length - entries.length + i ? { ...f, progress } : f)
|
|
2221
|
-
);
|
|
2389
|
+
const timer = setInterval(() => {
|
|
2390
|
+
progress = Math.min(100, progress + Math.random() * 30 + 10);
|
|
2391
|
+
const done = progress >= 100;
|
|
2392
|
+
if (done) {
|
|
2393
|
+
clearInterval(timer);
|
|
2394
|
+
timers.current.delete(id2);
|
|
2222
2395
|
}
|
|
2396
|
+
setFiles((prev) => prev.map((f) => f.id === id2 ? { ...f, progress, status: done ? "complete" : "uploading" } : f));
|
|
2223
2397
|
}, 300);
|
|
2224
|
-
|
|
2398
|
+
timers.current.set(id2, timer);
|
|
2399
|
+
}
|
|
2225
2400
|
},
|
|
2226
|
-
[maxSize, onFiles]
|
|
2401
|
+
[accept, maxSize, multiple, onFiles]
|
|
2227
2402
|
);
|
|
2228
2403
|
const handleDrop = useCallback(
|
|
2229
2404
|
(e) => {
|
|
@@ -2233,63 +2408,66 @@ function FileUpload({ onFiles, accept, multiple = true, maxSize, className, erro
|
|
|
2233
2408
|
},
|
|
2234
2409
|
[addFiles]
|
|
2235
2410
|
);
|
|
2236
|
-
const removeFile = (
|
|
2237
|
-
|
|
2411
|
+
const removeFile = (id2) => {
|
|
2412
|
+
stopTimer(id2);
|
|
2413
|
+
setFiles((prev) => prev.filter((f) => f.id !== id2));
|
|
2238
2414
|
};
|
|
2239
2415
|
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-ds-3", className), children: [
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
"
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2416
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-ds-1.5", children: [
|
|
2417
|
+
showLabel && /* @__PURE__ */ jsx(Label, { htmlFor: inputId, children: label }),
|
|
2418
|
+
/* @__PURE__ */ jsxs(
|
|
2419
|
+
"div",
|
|
2420
|
+
{
|
|
2421
|
+
onDragOver: (e) => {
|
|
2422
|
+
e.preventDefault();
|
|
2423
|
+
setDragOver(true);
|
|
2424
|
+
},
|
|
2425
|
+
onDragLeave: () => setDragOver(false),
|
|
2426
|
+
onDrop: handleDrop,
|
|
2427
|
+
onClick: () => inputRef.current?.click(),
|
|
2428
|
+
className: cn(
|
|
2429
|
+
"flex flex-col items-center justify-center gap-ds-2 cursor-pointer group",
|
|
2430
|
+
"border-2 border-dashed rounded-[var(--ds-radius-md)]",
|
|
2431
|
+
"transition-colors",
|
|
2432
|
+
// The real file input is visually hidden inside; Tab lands on it and
|
|
2433
|
+
// Enter/Space open the picker natively, so the zone shows its focus.
|
|
2434
|
+
invalid ? ERROR_HAS_FOCUS_RING : HAS_FOCUS_RING,
|
|
2435
|
+
dragOver ? `${ACTIVE_RING} bg-[var(--ds-accent-whisper)]` : invalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-border-default)] hover:border-[var(--ds-accent-primary)] hover:bg-[var(--ds-accent-whisper)]"
|
|
2436
|
+
),
|
|
2437
|
+
style: { padding: "var(--ds-space-8) var(--ds-space-4)" },
|
|
2438
|
+
children: [
|
|
2439
|
+
/* @__PURE__ */ jsx("div", { className: cn(
|
|
2440
|
+
"flex items-center justify-center w-10 h-10 rounded-[var(--ds-radius-full)] transition-colors",
|
|
2441
|
+
"bg-[var(--ds-bg-muted)] group-hover:bg-[var(--ds-accent-subtle)]"
|
|
2442
|
+
), children: /* @__PURE__ */ jsx(Icon, { name: "plus", size: 20, className: "text-[var(--ds-text-muted)] group-hover:text-[var(--ds-accent-primary)] transition-colors" }) }),
|
|
2443
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
2444
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: multiple ? "Drop files here or browse" : "Drop a file here or browse" }),
|
|
2445
|
+
constraints && /* @__PURE__ */ jsx("p", { id: constraintsId, className: "text-xs text-[var(--ds-text-muted)] mt-ds-1", children: constraints })
|
|
2446
|
+
] }),
|
|
2447
|
+
/* @__PURE__ */ jsx(
|
|
2448
|
+
"input",
|
|
2449
|
+
{
|
|
2450
|
+
ref: inputRef,
|
|
2451
|
+
id: inputId,
|
|
2452
|
+
type: "file",
|
|
2453
|
+
accept,
|
|
2454
|
+
multiple,
|
|
2455
|
+
className: "sr-only",
|
|
2456
|
+
"aria-labelledby": field ? field.labelId : void 0,
|
|
2457
|
+
"aria-describedby": describedBy,
|
|
2458
|
+
"aria-invalid": invalid || void 0,
|
|
2459
|
+
onChange: (e) => {
|
|
2460
|
+
if (e.target.files?.length) addFiles(e.target.files);
|
|
2461
|
+
e.target.value = "";
|
|
2462
|
+
}
|
|
2286
2463
|
}
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2464
|
+
)
|
|
2465
|
+
]
|
|
2466
|
+
}
|
|
2467
|
+
),
|
|
2468
|
+
rejected && /* @__PURE__ */ jsx(InlineFieldError, { id: rejectedId, message: rejected, className: "mt-0" })
|
|
2469
|
+
] }),
|
|
2470
|
+
files.length > 0 && /* @__PURE__ */ jsx("ul", { className: "space-y-ds-2", children: files.map((entry) => /* @__PURE__ */ jsxs(
|
|
2293
2471
|
"li",
|
|
2294
2472
|
{
|
|
2295
2473
|
className: cn(
|
|
@@ -2306,10 +2484,10 @@ function FileUpload({ onFiles, accept, multiple = true, maxSize, className, erro
|
|
|
2306
2484
|
entry.status === "uploading" && /* @__PURE__ */ jsx(Progress, { value: entry.progress, size: "sm", className: "mt-ds-1" })
|
|
2307
2485
|
] }),
|
|
2308
2486
|
entry.status === "complete" && /* @__PURE__ */ jsx(Icon, { name: "check", size: 16, className: "text-[var(--ds-status-success)] shrink-0" }),
|
|
2309
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => removeFile(
|
|
2487
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => removeFile(entry.id), "aria-label": "Remove file", children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 14 }) })
|
|
2310
2488
|
]
|
|
2311
2489
|
},
|
|
2312
|
-
|
|
2490
|
+
entry.id
|
|
2313
2491
|
)) })
|
|
2314
2492
|
] });
|
|
2315
2493
|
}
|
|
@@ -2324,9 +2502,17 @@ function SliderRange({
|
|
|
2324
2502
|
className,
|
|
2325
2503
|
ref,
|
|
2326
2504
|
error = false,
|
|
2327
|
-
label
|
|
2505
|
+
label,
|
|
2506
|
+
"aria-label": ariaLabel,
|
|
2507
|
+
"aria-describedby": describedByProp,
|
|
2328
2508
|
trackStyle
|
|
2329
2509
|
}) {
|
|
2510
|
+
const field = useField();
|
|
2511
|
+
const ownId = useId();
|
|
2512
|
+
const showLabel = label != null && !field;
|
|
2513
|
+
const nameId = field ? field.labelId : showLabel ? `${ownId}-label` : void 0;
|
|
2514
|
+
const describedBy = [...new Set([describedByProp, field?.describedBy].join(" ").split(" ").filter(Boolean))].join(" ") || void 0;
|
|
2515
|
+
const thumbName = (part) => nameId ? { "aria-labelledby": part ? `${nameId} ${ownId}-${part}` : nameId } : { "aria-label": ariaLabel ? part ? `${ariaLabel} ${part}` : ariaLabel : void 0 };
|
|
2330
2516
|
const isRange = Array.isArray(value);
|
|
2331
2517
|
const low = isRange ? value[0] : value;
|
|
2332
2518
|
const high = isRange ? value[1] : value;
|
|
@@ -2382,7 +2568,14 @@ function SliderRange({
|
|
|
2382
2568
|
[disabled, min, max, handleChange]
|
|
2383
2569
|
);
|
|
2384
2570
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn("space-y-ds-1", disabled && "opacity-disabled", className), children: [
|
|
2385
|
-
showValue && /* @__PURE__ */
|
|
2571
|
+
(showLabel || showValue) && /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-ds-2", showLabel ? "justify-between" : "justify-end"), children: [
|
|
2572
|
+
showLabel && /* @__PURE__ */ jsx("span", { id: `${ownId}-label`, className: "text-sm font-medium leading-none text-[var(--ds-text-secondary)]", children: label }),
|
|
2573
|
+
showValue && /* @__PURE__ */ jsx("span", { className: "text-xs font-mono tabular-nums text-[var(--ds-text-muted)]", children: isRange ? `${low} \u2013 ${high}` : low })
|
|
2574
|
+
] }),
|
|
2575
|
+
isRange && nameId && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2576
|
+
/* @__PURE__ */ jsx("span", { id: `${ownId}-minimum`, hidden: true, children: "minimum" }),
|
|
2577
|
+
/* @__PURE__ */ jsx("span", { id: `${ownId}-maximum`, hidden: true, children: "maximum" })
|
|
2578
|
+
] }),
|
|
2386
2579
|
/* @__PURE__ */ jsxs(
|
|
2387
2580
|
"div",
|
|
2388
2581
|
{
|
|
@@ -2405,7 +2598,8 @@ function SliderRange({
|
|
|
2405
2598
|
{
|
|
2406
2599
|
role: "slider",
|
|
2407
2600
|
tabIndex: disabled ? -1 : 0,
|
|
2408
|
-
"
|
|
2601
|
+
...thumbName("minimum"),
|
|
2602
|
+
"aria-describedby": describedBy,
|
|
2409
2603
|
"aria-valuemin": min,
|
|
2410
2604
|
"aria-valuemax": high,
|
|
2411
2605
|
"aria-valuenow": low,
|
|
@@ -2429,7 +2623,8 @@ function SliderRange({
|
|
|
2429
2623
|
{
|
|
2430
2624
|
role: "slider",
|
|
2431
2625
|
tabIndex: disabled ? -1 : 0,
|
|
2432
|
-
|
|
2626
|
+
...thumbName(isRange ? "maximum" : void 0),
|
|
2627
|
+
"aria-describedby": describedBy,
|
|
2433
2628
|
"aria-valuemin": isRange ? low : min,
|
|
2434
2629
|
"aria-valuemax": max,
|
|
2435
2630
|
"aria-valuenow": high,
|
|
@@ -2605,10 +2800,10 @@ function TimePicker({
|
|
|
2605
2800
|
setOpen(false);
|
|
2606
2801
|
};
|
|
2607
2802
|
const keyHandler = (e) => {
|
|
2608
|
-
if (e.key
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2803
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
2804
|
+
e.preventDefault();
|
|
2805
|
+
returnFocus();
|
|
2806
|
+
setOpen(false);
|
|
2612
2807
|
};
|
|
2613
2808
|
document.addEventListener("mousedown", handler);
|
|
2614
2809
|
document.addEventListener("keydown", keyHandler);
|
|
@@ -3246,14 +3441,14 @@ function TagInput({
|
|
|
3246
3441
|
);
|
|
3247
3442
|
const containerRef = useRef(null);
|
|
3248
3443
|
const pendingFocus = useRef(null);
|
|
3249
|
-
const tagCount = value.length;
|
|
3250
3444
|
useLayoutEffect(() => {
|
|
3251
|
-
const
|
|
3252
|
-
if (
|
|
3445
|
+
const pending = pendingFocus.current;
|
|
3446
|
+
if (pending === null) return;
|
|
3253
3447
|
pendingFocus.current = null;
|
|
3448
|
+
if (value.includes(pending.tag)) return;
|
|
3254
3449
|
const buttons = Array.from(containerRef.current?.querySelectorAll("[data-tag-remove]") ?? []);
|
|
3255
|
-
focusAfterRemoval(buttons, index, inputRef.current);
|
|
3256
|
-
}
|
|
3450
|
+
focusAfterRemoval(buttons, pending.index, inputRef.current);
|
|
3451
|
+
});
|
|
3257
3452
|
const handleKeyDown = useCallback(
|
|
3258
3453
|
(e) => {
|
|
3259
3454
|
if ((e.key === "Enter" || e.key === ",") && input.trim()) {
|
|
@@ -3308,7 +3503,7 @@ function TagInput({
|
|
|
3308
3503
|
Tag,
|
|
3309
3504
|
{
|
|
3310
3505
|
onRemove: disabled ? void 0 : () => {
|
|
3311
|
-
pendingFocus.current = i;
|
|
3506
|
+
pendingFocus.current = { index: i, tag };
|
|
3312
3507
|
removeTag(tag);
|
|
3313
3508
|
},
|
|
3314
3509
|
disabled,
|
|
@@ -3837,60 +4032,6 @@ function ColorPicker({
|
|
|
3837
4032
|
}
|
|
3838
4033
|
);
|
|
3839
4034
|
}
|
|
3840
|
-
function InlineFieldError({ message, id, className }) {
|
|
3841
|
-
return /* @__PURE__ */ jsxs(
|
|
3842
|
-
"p",
|
|
3843
|
-
{
|
|
3844
|
-
id,
|
|
3845
|
-
role: "alert",
|
|
3846
|
-
className: cn(
|
|
3847
|
-
"flex items-center gap-ds-1.5 text-xs text-[var(--ds-status-error)]",
|
|
3848
|
-
"mt-ds-1.5",
|
|
3849
|
-
className
|
|
3850
|
-
),
|
|
3851
|
-
children: [
|
|
3852
|
-
/* @__PURE__ */ jsx(Icon, { name: "error", size: 14, className: "shrink-0" }),
|
|
3853
|
-
/* @__PURE__ */ jsx("span", { children: message })
|
|
3854
|
-
]
|
|
3855
|
-
}
|
|
3856
|
-
);
|
|
3857
|
-
}
|
|
3858
|
-
function Field({ label, children, hint, error, required, labelAction, id: idProp, className }) {
|
|
3859
|
-
const generated = useId();
|
|
3860
|
-
const id = idProp ?? `field-${generated}`;
|
|
3861
|
-
const hintId = `${id}-hint`;
|
|
3862
|
-
const errorId = `${id}-error`;
|
|
3863
|
-
const hasError = typeof error === "string" && error.length > 0;
|
|
3864
|
-
const describedBy = [hint ? hintId : null, hasError ? errorId : null].filter(Boolean).join(" ") || void 0;
|
|
3865
|
-
const controlProps = {
|
|
3866
|
-
id,
|
|
3867
|
-
"aria-describedby": describedBy,
|
|
3868
|
-
...hasError ? { "aria-invalid": true, error: true } : {},
|
|
3869
|
-
...required ? { "aria-required": true, required: true } : {}
|
|
3870
|
-
};
|
|
3871
|
-
let control;
|
|
3872
|
-
if (typeof children === "function") {
|
|
3873
|
-
control = children(controlProps);
|
|
3874
|
-
} else {
|
|
3875
|
-
const child = Children.only(children);
|
|
3876
|
-
if (!isValidElement(child)) throw new Error("Field expects a single form control as its child");
|
|
3877
|
-
const isNative = typeof child.type === "string";
|
|
3878
|
-
const { error: errorFlag, ...ariaOnly } = controlProps;
|
|
3879
|
-
control = cloneElement(child, isNative ? ariaOnly : { ...ariaOnly, ...errorFlag ? { error: true } : {} });
|
|
3880
|
-
}
|
|
3881
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-ds-1.5", className), children: [
|
|
3882
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-ds-2", children: [
|
|
3883
|
-
/* @__PURE__ */ jsxs(Label, { htmlFor: id, children: [
|
|
3884
|
-
label,
|
|
3885
|
-
required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ml-ds-0.5 text-[var(--ds-status-error)]", children: "*" })
|
|
3886
|
-
] }),
|
|
3887
|
-
labelAction
|
|
3888
|
-
] }),
|
|
3889
|
-
control,
|
|
3890
|
-
hint && /* @__PURE__ */ jsx("p", { id: hintId, className: "text-xs text-[var(--ds-text-muted)]", children: hint }),
|
|
3891
|
-
hasError && /* @__PURE__ */ jsx(InlineFieldError, { id: errorId, message: error, className: "mt-0" })
|
|
3892
|
-
] });
|
|
3893
|
-
}
|
|
3894
4035
|
var variantStyles2 = {
|
|
3895
4036
|
info: "border-[var(--ds-accent-primary)] bg-[var(--ds-accent-subtle)]",
|
|
3896
4037
|
success: "border-[var(--ds-status-success)] bg-[var(--ds-status-success-bg)]",
|
|
@@ -4566,7 +4707,6 @@ function MentionInput({
|
|
|
4566
4707
|
const value = controlledValue ?? internalValue;
|
|
4567
4708
|
const [query, setQuery] = useState("");
|
|
4568
4709
|
const [showPopup, setShowPopup] = useState(false);
|
|
4569
|
-
useOverlayLayer(showPopup);
|
|
4570
4710
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
4571
4711
|
const [triggerStart, setTriggerStart] = useState(-1);
|
|
4572
4712
|
const [popupPos, setPopupPos] = useState({ top: 0, left: 0 });
|
|
@@ -4576,6 +4716,7 @@ function MentionInput({
|
|
|
4576
4716
|
const filtered = suggestions.filter(
|
|
4577
4717
|
(s) => s.label.toLowerCase().includes(query.toLowerCase()) || s.description?.toLowerCase().includes(query.toLowerCase())
|
|
4578
4718
|
);
|
|
4719
|
+
useOverlayLayer(showPopup && filtered.length > 0);
|
|
4579
4720
|
const updateValue = useCallback(
|
|
4580
4721
|
(v) => {
|
|
4581
4722
|
if (controlledValue === void 0) setInternalValue(v);
|
|
@@ -4654,6 +4795,7 @@ function MentionInput({
|
|
|
4654
4795
|
e.preventDefault();
|
|
4655
4796
|
insertMention(filtered[activeIndex]);
|
|
4656
4797
|
} else if (e.key === "Escape") {
|
|
4798
|
+
e.preventDefault();
|
|
4657
4799
|
setShowPopup(false);
|
|
4658
4800
|
}
|
|
4659
4801
|
};
|
|
@@ -4757,6 +4899,8 @@ function MentionInput({
|
|
|
4757
4899
|
] });
|
|
4758
4900
|
}
|
|
4759
4901
|
var CardCtx = createContext(false);
|
|
4902
|
+
var CardActionCtx = createContext(null);
|
|
4903
|
+
var CARD_ACTION_ATTR = "data-card-action";
|
|
4760
4904
|
var CardSurfaceCtx = createContext(false);
|
|
4761
4905
|
var variantStyles3 = {
|
|
4762
4906
|
default: `bg-[var(--ds-bg-surface)] border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] ${GLASS_SURFACE}`,
|
|
@@ -4876,11 +5020,33 @@ var Card = forwardRef(function Card2({
|
|
|
4876
5020
|
const isSelectable = selectable || !!selectType;
|
|
4877
5021
|
const isToggle = selectType === "toggle";
|
|
4878
5022
|
const hasSelectType = !!selectType;
|
|
5023
|
+
const isAction = !isSelectable && variant === "interactive" && !!onClick;
|
|
5024
|
+
const rootRef = useRef(null);
|
|
5025
|
+
const setRoot = useCallback((node) => {
|
|
5026
|
+
rootRef.current = node;
|
|
5027
|
+
if (typeof ref === "function") ref(node);
|
|
5028
|
+
else if (ref) ref.current = node;
|
|
5029
|
+
}, [ref]);
|
|
5030
|
+
const [inner, setInner] = useState({ controls: false, titleId: null });
|
|
5031
|
+
useLayoutEffect(() => {
|
|
5032
|
+
const root = rootRef.current;
|
|
5033
|
+
if (!root || !isAction && !checkable) return;
|
|
5034
|
+
const controls = Array.from(root.querySelectorAll(FOCUSABLE)).some((el) => !el.hasAttribute(CARD_ACTION_ATTR));
|
|
5035
|
+
const titleId = root.querySelector("[data-card-title]")?.id || null;
|
|
5036
|
+
setInner((cur) => cur.controls === controls && cur.titleId === titleId ? cur : { controls, titleId });
|
|
5037
|
+
}, [isAction, checkable, loading, children]);
|
|
5038
|
+
const holdsControls = isAction && inner.controls;
|
|
5039
|
+
const action = useMemo(() => holdsControls ? { activate: () => rootRef.current?.click(), disabled } : null, [holdsControls, disabled]);
|
|
4879
5040
|
const handleClick = isSelectable && !disabled ? (e) => {
|
|
4880
5041
|
onSelectedChange?.(!selected);
|
|
4881
5042
|
onClick?.(e);
|
|
4882
|
-
} : onClick;
|
|
4883
|
-
const
|
|
5043
|
+
} : isAction && disabled ? void 0 : onClick;
|
|
5044
|
+
const handleCardClick = (e) => {
|
|
5045
|
+
if (disabled || !(e.target instanceof Element) || !e.currentTarget.contains(e.target)) return;
|
|
5046
|
+
const control = e.target.closest(FOCUSABLE);
|
|
5047
|
+
if (control && control !== e.currentTarget && e.currentTarget.contains(control)) return;
|
|
5048
|
+
onClick?.(e);
|
|
5049
|
+
};
|
|
4884
5050
|
const handleKeyDown = isSelectable && !disabled ? (e) => {
|
|
4885
5051
|
if (e.key === "Enter" || e.key === " ") {
|
|
4886
5052
|
e.preventDefault();
|
|
@@ -4903,7 +5069,8 @@ var Card = forwardRef(function Card2({
|
|
|
4903
5069
|
e.stopPropagation();
|
|
4904
5070
|
onSelectedChange?.(!selected);
|
|
4905
5071
|
};
|
|
4906
|
-
const
|
|
5072
|
+
const isButton = isSelectable || isAction && !holdsControls;
|
|
5073
|
+
const role = selectType === "radio" ? "radio" : selectType === "checkbox" ? "checkbox" : selectType === "toggle" ? "switch" : isButton ? "button" : void 0;
|
|
4907
5074
|
const ariaAttr = selectType === "radio" || selectType === "checkbox" || selectType === "toggle" ? { "aria-checked": !!selected } : isSelectable ? { "aria-pressed": !!selected } : {};
|
|
4908
5075
|
const showRing = isSelectable && !isToggle && !hasSelectType && selected;
|
|
4909
5076
|
const indicator = selectType === "radio" ? /* @__PURE__ */ jsx(RadioIndicator, { checked: !!selected, disabled }) : selectType === "checkbox" ? /* @__PURE__ */ jsx(CheckboxIndicator, { checked: !!selected, indeterminate, disabled }) : selectType === "toggle" ? /* @__PURE__ */ jsx(ToggleIndicator, { checked: !!selected, disabled }) : null;
|
|
@@ -4911,11 +5078,11 @@ var Card = forwardRef(function Card2({
|
|
|
4911
5078
|
return /* @__PURE__ */ jsxs(
|
|
4912
5079
|
"div",
|
|
4913
5080
|
{
|
|
4914
|
-
ref,
|
|
5081
|
+
ref: setRoot,
|
|
4915
5082
|
"data-card": "",
|
|
4916
5083
|
role,
|
|
4917
|
-
tabIndex: isSelectable ||
|
|
4918
|
-
"aria-disabled":
|
|
5084
|
+
tabIndex: isSelectable || isButton && !disabled ? 0 : void 0,
|
|
5085
|
+
"aria-disabled": isButton && disabled ? true : void 0,
|
|
4919
5086
|
...name && selectType === "radio" ? { "data-radio-group": name } : {},
|
|
4920
5087
|
style: variant === "interactive" ? { ...INTERACTIVE_SCALE_CAP, ...style } : style,
|
|
4921
5088
|
className: cn(
|
|
@@ -4923,15 +5090,15 @@ var Card = forwardRef(function Card2({
|
|
|
4923
5090
|
variantStyles3[variant],
|
|
4924
5091
|
isSelectable && !disabled && "cursor-pointer select-none transition-all duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
|
|
4925
5092
|
isSelectable && !disabled && !selected && "hover:border-[var(--ds-accent-primary)]",
|
|
4926
|
-
|
|
5093
|
+
isButton && "focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
4927
5094
|
(showRing || hasSelectType && selected) && ACTIVE_RING,
|
|
4928
5095
|
hasSelectType && selected && "bg-[var(--ds-accent-subtle)]",
|
|
4929
5096
|
disabled && "opacity-disabled cursor-not-allowed",
|
|
4930
5097
|
className
|
|
4931
5098
|
),
|
|
4932
|
-
onClick: handleClick,
|
|
4933
|
-
onKeyDown: handleKeyDown,
|
|
4934
|
-
onKeyUp: handleKeyUp,
|
|
5099
|
+
onClick: holdsControls ? handleCardClick : handleClick,
|
|
5100
|
+
onKeyDown: holdsControls ? void 0 : handleKeyDown,
|
|
5101
|
+
onKeyUp: holdsControls ? void 0 : handleKeyUp,
|
|
4935
5102
|
...ariaAttr,
|
|
4936
5103
|
...props,
|
|
4937
5104
|
children: [
|
|
@@ -4944,6 +5111,7 @@ var Card = forwardRef(function Card2({
|
|
|
4944
5111
|
onClick: handleCheckableClick,
|
|
4945
5112
|
role: "checkbox",
|
|
4946
5113
|
"aria-checked": !!selected,
|
|
5114
|
+
...inner.titleId ? { "aria-labelledby": inner.titleId } : { "aria-label": "Select" },
|
|
4947
5115
|
tabIndex: 0,
|
|
4948
5116
|
onKeyDown: (e) => {
|
|
4949
5117
|
if (e.key === "Enter" || e.key === " ") {
|
|
@@ -4955,7 +5123,7 @@ var Card = forwardRef(function Card2({
|
|
|
4955
5123
|
children: /* @__PURE__ */ jsx(CheckboxIndicator, { checked: !!selected })
|
|
4956
5124
|
}
|
|
4957
5125
|
),
|
|
4958
|
-
/* @__PURE__ */ jsx(CardSurfaceCtx, { value: true, children: /* @__PURE__ */ jsx(CardCtx, { value: checkable, children: loading ? (
|
|
5126
|
+
/* @__PURE__ */ jsx(CardSurfaceCtx, { value: true, children: /* @__PURE__ */ jsx(CardActionCtx, { value: action, children: /* @__PURE__ */ jsx(CardCtx, { value: checkable, children: loading ? (
|
|
4959
5127
|
// Round 15 (the owner's 52.1): a placeholder stands where the content will stand — inside the card's
|
|
4960
5128
|
// content inset (CardContent's padding), a title-height line then two body lines — never flush against the border.
|
|
4961
5129
|
/* @__PURE__ */ jsx("div", { "data-card-loading": "", "aria-busy": "true", className: cn("pr-ds-5 py-ds-4", checkable ? "pl-ds-10" : "pl-ds-5"), children: /* @__PURE__ */ jsxs("div", { className: "space-y-ds-3", children: [
|
|
@@ -4963,7 +5131,7 @@ var Card = forwardRef(function Card2({
|
|
|
4963
5131
|
/* @__PURE__ */ jsx(Skeleton, { variant: "custom", className: "h-3 w-full" }),
|
|
4964
5132
|
/* @__PURE__ */ jsx(Skeleton, { variant: "custom", className: "h-3 w-2/3" })
|
|
4965
5133
|
] }) })
|
|
4966
|
-
) : children }) })
|
|
5134
|
+
) : children }) }) })
|
|
4967
5135
|
]
|
|
4968
5136
|
}
|
|
4969
5137
|
);
|
|
@@ -4981,6 +5149,7 @@ var CardHeader = forwardRef(function CardHeader2({ className, children, actions,
|
|
|
4981
5149
|
"button",
|
|
4982
5150
|
{
|
|
4983
5151
|
type: "button",
|
|
5152
|
+
"aria-label": "More actions",
|
|
4984
5153
|
className: cn(
|
|
4985
5154
|
"inline-flex items-center justify-center h-8 w-8 rounded-[var(--ds-radius-md)]",
|
|
4986
5155
|
"text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]",
|
|
@@ -5017,20 +5186,42 @@ var cardLineClampClasses = {
|
|
|
5017
5186
|
5: "line-clamp-5",
|
|
5018
5187
|
6: "line-clamp-6"
|
|
5019
5188
|
};
|
|
5020
|
-
var CardTitle = forwardRef(function CardTitle2({ className, children, lines = 2, ...props }, forwardedRef) {
|
|
5189
|
+
var CardTitle = forwardRef(function CardTitle2({ className, children, lines = 2, id, ...props }, forwardedRef) {
|
|
5190
|
+
const action = useContext(CardActionCtx);
|
|
5191
|
+
const generatedId = useId();
|
|
5021
5192
|
const { ref: overflowRef, isTruncated } = useTextOverflow({ lines, disabled: lines === 0 });
|
|
5022
5193
|
const lineClampClass = lines > 0 ? cardLineClampClasses[lines] || `line-clamp-[${lines}]` : "";
|
|
5023
5194
|
const heading = /* @__PURE__ */ jsx(
|
|
5024
5195
|
"h3",
|
|
5025
5196
|
{
|
|
5026
5197
|
ref: (node) => {
|
|
5027
|
-
overflowRef(lines > 0 ? node : null);
|
|
5198
|
+
if (!action) overflowRef(lines > 0 ? node : null);
|
|
5028
5199
|
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
5029
5200
|
else if (forwardedRef) forwardedRef.current = node;
|
|
5030
5201
|
},
|
|
5031
|
-
|
|
5202
|
+
id: id ?? generatedId,
|
|
5203
|
+
"data-card-title": "",
|
|
5204
|
+
className: cn("font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", !action && lines > 0 && lineClampClass, className),
|
|
5032
5205
|
...props,
|
|
5033
|
-
children
|
|
5206
|
+
children: action ? (
|
|
5207
|
+
// The card's action when the card holds controls of its own (Sprint 25.7): a real button, which a click
|
|
5208
|
+
// elsewhere on the card also runs. Its ::after spans the card to draw the card's focus ring, taking no clicks.
|
|
5209
|
+
// The clamp moves inside, since a button lays out its own lines.
|
|
5210
|
+
/* @__PURE__ */ jsx(
|
|
5211
|
+
"button",
|
|
5212
|
+
{
|
|
5213
|
+
type: "button",
|
|
5214
|
+
...{ [CARD_ACTION_ATTR]: "" },
|
|
5215
|
+
disabled: action.disabled,
|
|
5216
|
+
onClick: action.activate,
|
|
5217
|
+
className: cn(
|
|
5218
|
+
"block w-full text-left cursor-pointer [text-overflow:inherit] focus-visible:outline-none disabled:cursor-not-allowed",
|
|
5219
|
+
"after:absolute after:inset-0 after:rounded-[var(--ds-radius-md)] after:pointer-events-none focus-visible:after:shadow-[var(--ds-shadow-focus)]"
|
|
5220
|
+
),
|
|
5221
|
+
children: /* @__PURE__ */ jsx("span", { ref: (node) => overflowRef(lines > 0 ? node : null), className: cn("block [text-overflow:inherit]", lines > 0 && lineClampClass), children })
|
|
5222
|
+
}
|
|
5223
|
+
)
|
|
5224
|
+
) : children
|
|
5034
5225
|
}
|
|
5035
5226
|
);
|
|
5036
5227
|
if (!isTruncated || lines === 0) return heading;
|
|
@@ -6047,10 +6238,10 @@ function OverflowPopover({
|
|
|
6047
6238
|
if (!open) return;
|
|
6048
6239
|
const raf = requestAnimationFrame(() => focusInitial(floatingRef.current));
|
|
6049
6240
|
const onKey = (e) => {
|
|
6050
|
-
if (e.key
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6241
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTop()) return;
|
|
6242
|
+
e.preventDefault();
|
|
6243
|
+
returnFocus();
|
|
6244
|
+
setOpen(false);
|
|
6054
6245
|
};
|
|
6055
6246
|
const onDown = (e) => {
|
|
6056
6247
|
if (!triggerRef.current?.contains(e.target)) setOpen(false);
|
|
@@ -6705,6 +6896,9 @@ function CompactDayCell({
|
|
|
6705
6896
|
const today = isCurrentMonth && isToday(day);
|
|
6706
6897
|
const selected = isCurrentMonth && selectedDate && isSameDay2(day, selectedDate);
|
|
6707
6898
|
const hasEvents = dayEvents.length > 0;
|
|
6899
|
+
const shown = open && hasEvents;
|
|
6900
|
+
const isTop = useOverlayLayer(shown);
|
|
6901
|
+
useCloseOnFocusOut(shown, cellRef, floatingRef, () => setOpen(false), isTop);
|
|
6708
6902
|
const eventColors = dayEvents.slice(0, 3).map((e) => categories[e.category ?? ""]?.color ?? "var(--ds-accent-primary)");
|
|
6709
6903
|
const handleMouseEnter = () => {
|
|
6710
6904
|
if (!hasEvents) return;
|
|
@@ -6723,7 +6917,9 @@ function CompactDayCell({
|
|
|
6723
6917
|
useEffect(() => {
|
|
6724
6918
|
if (!open) return;
|
|
6725
6919
|
const onKey = (e) => {
|
|
6726
|
-
if (e.key
|
|
6920
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTop()) return;
|
|
6921
|
+
e.preventDefault();
|
|
6922
|
+
setOpen(false);
|
|
6727
6923
|
};
|
|
6728
6924
|
const onClick = (e) => {
|
|
6729
6925
|
const t = e.target;
|
|
@@ -6736,7 +6932,7 @@ function CompactDayCell({
|
|
|
6736
6932
|
document.removeEventListener("keydown", onKey);
|
|
6737
6933
|
document.removeEventListener("mousedown", onClick);
|
|
6738
6934
|
};
|
|
6739
|
-
}, [open]);
|
|
6935
|
+
}, [open, isTop]);
|
|
6740
6936
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6741
6937
|
/* @__PURE__ */ jsxs(
|
|
6742
6938
|
"button",
|
|
@@ -6908,10 +7104,10 @@ function MonthDropdown({
|
|
|
6908
7104
|
(panel?.querySelector("[data-current]") ?? panel?.querySelector("button"))?.focus();
|
|
6909
7105
|
});
|
|
6910
7106
|
const onKey = (e) => {
|
|
6911
|
-
if (e.key
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
|
|
7107
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTop()) return;
|
|
7108
|
+
e.preventDefault();
|
|
7109
|
+
returnFocus();
|
|
7110
|
+
setOpen(false);
|
|
6915
7111
|
};
|
|
6916
7112
|
const onClick = (e) => {
|
|
6917
7113
|
const t = e.target;
|
|
@@ -7042,10 +7238,10 @@ function YearDropdown({
|
|
|
7042
7238
|
(panel?.querySelector("[data-current]") ?? panel?.querySelector("button"))?.focus();
|
|
7043
7239
|
});
|
|
7044
7240
|
const onKey = (e) => {
|
|
7045
|
-
if (e.key
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7241
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTop()) return;
|
|
7242
|
+
e.preventDefault();
|
|
7243
|
+
returnFocus();
|
|
7244
|
+
setOpen(false);
|
|
7049
7245
|
};
|
|
7050
7246
|
const onClick = (e) => {
|
|
7051
7247
|
const t = e.target;
|
|
@@ -9877,10 +10073,10 @@ var Breadcrumbs = forwardRef(function Breadcrumbs2({
|
|
|
9877
10073
|
setDropdownOpen(false);
|
|
9878
10074
|
};
|
|
9879
10075
|
const onKeyDown = (e) => {
|
|
9880
|
-
if (e.key
|
|
9881
|
-
|
|
9882
|
-
|
|
9883
|
-
|
|
10076
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTop()) return;
|
|
10077
|
+
e.preventDefault();
|
|
10078
|
+
returnFocus();
|
|
10079
|
+
setDropdownOpen(false);
|
|
9884
10080
|
};
|
|
9885
10081
|
document.addEventListener("mousedown", handler);
|
|
9886
10082
|
document.addEventListener("keydown", onKeyDown);
|
|
@@ -10080,27 +10276,31 @@ function Popover({ open, onOpenChange, trigger, children, side = "bottom", align
|
|
|
10080
10276
|
setTriggerWidth(node?.offsetWidth);
|
|
10081
10277
|
}, []);
|
|
10082
10278
|
const pos = usePosition(triggerRef, floatingRef, open, { side, align, offset: 8, flip: true });
|
|
10083
|
-
const
|
|
10279
|
+
const onOpenChangeRef = useLatest(onOpenChange);
|
|
10280
|
+
const { props: pressMarks, marked } = usePressMarks();
|
|
10281
|
+
const { isTop: isTopLayer, returnFocus } = usePopupFocus(open, { trigger: triggerRef, panel: floatingRef, close: () => onOpenChangeRef.current(false), tabExits: "edges", marked });
|
|
10084
10282
|
useEffect(() => {
|
|
10085
10283
|
if (!open) return;
|
|
10086
10284
|
const onKeyDown = (e) => {
|
|
10087
|
-
if (e.key
|
|
10088
|
-
|
|
10089
|
-
|
|
10090
|
-
|
|
10091
|
-
|
|
10092
|
-
|
|
10285
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
10286
|
+
const active = document.activeElement;
|
|
10287
|
+
if (active && active !== document.body && !triggerRef.current?.contains(active) && !floatingRef.current?.contains(active)) return;
|
|
10288
|
+
e.preventDefault();
|
|
10289
|
+
returnFocus();
|
|
10290
|
+
onOpenChangeRef.current(false);
|
|
10291
|
+
};
|
|
10292
|
+
const onPress = (e) => {
|
|
10093
10293
|
const target = e.target;
|
|
10094
|
-
if (triggerRef.current?.contains(target) || floatingRef.current?.contains(target)) return;
|
|
10095
|
-
|
|
10294
|
+
if (marked(e) || triggerRef.current?.contains(target) || floatingRef.current?.contains(target)) return;
|
|
10295
|
+
onOpenChangeRef.current(false);
|
|
10096
10296
|
};
|
|
10097
10297
|
document.addEventListener("keydown", onKeyDown);
|
|
10098
|
-
document.addEventListener("mousedown",
|
|
10298
|
+
document.addEventListener("mousedown", onPress);
|
|
10099
10299
|
return () => {
|
|
10100
10300
|
document.removeEventListener("keydown", onKeyDown);
|
|
10101
|
-
document.removeEventListener("mousedown",
|
|
10301
|
+
document.removeEventListener("mousedown", onPress);
|
|
10102
10302
|
};
|
|
10103
|
-
}, [open,
|
|
10303
|
+
}, [open, onOpenChangeRef, isTopLayer, returnFocus, marked]);
|
|
10104
10304
|
useEffect(() => {
|
|
10105
10305
|
if (open) focusInitial(floatingRef.current);
|
|
10106
10306
|
}, [open]);
|
|
@@ -10122,6 +10322,7 @@ function Popover({ open, onOpenChange, trigger, children, side = "bottom", align
|
|
|
10122
10322
|
{
|
|
10123
10323
|
ref: floatingRef,
|
|
10124
10324
|
"data-gs": "popover",
|
|
10325
|
+
...pressMarks,
|
|
10125
10326
|
onClick: (e) => e.stopPropagation(),
|
|
10126
10327
|
className: cn(
|
|
10127
10328
|
"fixed z-[var(--ds-z-popover)]",
|
|
@@ -10337,10 +10538,87 @@ function EllipsisJumper({ totalPages, onPageChange }) {
|
|
|
10337
10538
|
}
|
|
10338
10539
|
);
|
|
10339
10540
|
}
|
|
10541
|
+
var HeaderTabRowContext = createContext(null);
|
|
10542
|
+
function useHeaderTabRow() {
|
|
10543
|
+
return useContext(HeaderTabRowContext);
|
|
10544
|
+
}
|
|
10545
|
+
function useNarrowRow(row) {
|
|
10546
|
+
const [narrow, setNarrow] = useState(false);
|
|
10547
|
+
useLayoutEffect(() => {
|
|
10548
|
+
if (!row) return;
|
|
10549
|
+
const limit = readBreakpointPx("sm");
|
|
10550
|
+
const measure = () => setNarrow(row.clientWidth < limit);
|
|
10551
|
+
measure();
|
|
10552
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
10553
|
+
const ro = new ResizeObserver(measure);
|
|
10554
|
+
ro.observe(row);
|
|
10555
|
+
return () => ro.disconnect();
|
|
10556
|
+
}, [row]);
|
|
10557
|
+
return narrow;
|
|
10558
|
+
}
|
|
10340
10559
|
function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal", className }) {
|
|
10341
10560
|
const isHorizontal = orientation === "horizontal";
|
|
10561
|
+
const tabRow = useHeaderTabRow();
|
|
10562
|
+
const narrow = useNarrowRow(tabRow?.row ?? null);
|
|
10563
|
+
const inHeader = isHorizontal && tabRow != null;
|
|
10564
|
+
if (inHeader && narrow) {
|
|
10565
|
+
const current = steps[currentStep];
|
|
10566
|
+
const where = `Step ${Math.min(currentStep + 1, steps.length)} of ${steps.length}`;
|
|
10567
|
+
return /* @__PURE__ */ jsxs("nav", { "data-gs": "stepper", "aria-label": "Progress", className: cn("mx-ds-1", className), children: [
|
|
10568
|
+
/* @__PURE__ */ jsxs("p", { className: cn("mb-ds-2 text-sm font-medium text-[var(--ds-text-secondary)]", tabRow.hasCaption && "sr-only"), children: [
|
|
10569
|
+
where,
|
|
10570
|
+
current ? /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
|
|
10571
|
+
": ",
|
|
10572
|
+
current.label
|
|
10573
|
+
] }) : null
|
|
10574
|
+
] }),
|
|
10575
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "flex gap-ds-1", children: steps.map((step, i) => /* @__PURE__ */ jsx(
|
|
10576
|
+
"div",
|
|
10577
|
+
{
|
|
10578
|
+
className: cn(
|
|
10579
|
+
"h-1.5 flex-1 rounded-[var(--ds-radius-full)] transition-colors",
|
|
10580
|
+
step.status === "error" ? "bg-[var(--ds-status-error)]" : i <= currentStep ? "bg-[var(--ds-accent-primary)]" : "bg-[var(--ds-border-subtle)]"
|
|
10581
|
+
)
|
|
10582
|
+
},
|
|
10583
|
+
i
|
|
10584
|
+
)) })
|
|
10585
|
+
] });
|
|
10586
|
+
}
|
|
10587
|
+
if (inHeader) {
|
|
10588
|
+
return /* @__PURE__ */ jsx("nav", { "data-gs": "stepper", "aria-label": "Progress", className: cn("flex items-start mx-ds-1", className), children: steps.map((step, i) => {
|
|
10589
|
+
const status = step.status ?? (i < currentStep ? "complete" : i === currentStep ? "current" : "upcoming");
|
|
10590
|
+
const isLast = i === steps.length - 1;
|
|
10591
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-start min-w-0", isLast ? "flex-none" : "flex-1"), children: [
|
|
10592
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center w-full", children: [
|
|
10593
|
+
/* @__PURE__ */ jsx(StepCircle, { status, index: i, onClick: onStepChange ? () => onStepChange(i) : void 0, clickable: !!onStepChange }),
|
|
10594
|
+
!isLast && /* @__PURE__ */ jsx(
|
|
10595
|
+
"div",
|
|
10596
|
+
{
|
|
10597
|
+
className: cn(
|
|
10598
|
+
"flex-1 h-0.5 mx-ds-2 transition-colors",
|
|
10599
|
+
i < currentStep ? "bg-[var(--ds-accent-primary)]" : "bg-[var(--ds-border-subtle)]"
|
|
10600
|
+
)
|
|
10601
|
+
}
|
|
10602
|
+
)
|
|
10603
|
+
] }),
|
|
10604
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-ds-2 pr-ds-2", children: [
|
|
10605
|
+
/* @__PURE__ */ jsx(
|
|
10606
|
+
"p",
|
|
10607
|
+
{
|
|
10608
|
+
className: cn(
|
|
10609
|
+
"text-xs font-medium",
|
|
10610
|
+
status === "current" ? "text-[var(--ds-accent-primary)]" : "text-[var(--ds-text-primary)]"
|
|
10611
|
+
),
|
|
10612
|
+
children: step.label
|
|
10613
|
+
}
|
|
10614
|
+
),
|
|
10615
|
+
step.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-[var(--ds-text-muted)] mt-ds-0.5", children: step.description })
|
|
10616
|
+
] })
|
|
10617
|
+
] }, i);
|
|
10618
|
+
}) });
|
|
10619
|
+
}
|
|
10342
10620
|
if (!isHorizontal) {
|
|
10343
|
-
return /* @__PURE__ */ jsx("nav", { "aria-label": "Progress", className: cn("flex flex-col", className), children: steps.map((step, i) => {
|
|
10621
|
+
return /* @__PURE__ */ jsx("nav", { "data-gs": "stepper", "aria-label": "Progress", className: cn("flex flex-col", className), children: steps.map((step, i) => {
|
|
10344
10622
|
const status = step.status ?? (i < currentStep ? "complete" : i === currentStep ? "current" : "upcoming");
|
|
10345
10623
|
const isLast = i === steps.length - 1;
|
|
10346
10624
|
return /* @__PURE__ */ jsxs("div", { className: "flex gap-ds-3", children: [
|
|
@@ -10375,6 +10653,7 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
10375
10653
|
return /* @__PURE__ */ jsx(
|
|
10376
10654
|
"nav",
|
|
10377
10655
|
{
|
|
10656
|
+
"data-gs": "stepper",
|
|
10378
10657
|
"aria-label": "Progress",
|
|
10379
10658
|
className: cn("flex items-start", className),
|
|
10380
10659
|
children: steps.map((step, i) => {
|
|
@@ -10795,6 +11074,7 @@ function computeCompactFlyoutPos(anchorEl, itemsLength) {
|
|
|
10795
11074
|
return { top: Math.max(8, top), left: rect.right - (FLYOUT_BRIDGE_PX - 4) };
|
|
10796
11075
|
}
|
|
10797
11076
|
function CompactFlyout({
|
|
11077
|
+
id,
|
|
10798
11078
|
parentLabel,
|
|
10799
11079
|
items,
|
|
10800
11080
|
anchorEl,
|
|
@@ -10808,22 +11088,23 @@ function CompactFlyout({
|
|
|
10808
11088
|
const pos = useMemo(() => computeCompactFlyoutPos(anchorEl, items.length), [anchorEl, items.length]);
|
|
10809
11089
|
const anchorRef = useRef(anchorEl);
|
|
10810
11090
|
const panelRef = useRef(null);
|
|
11091
|
+
const headingId = useId();
|
|
10811
11092
|
const { isTop: isTopLayer, returnFocus } = usePopupFocus(true, { trigger: anchorRef, panel: panelRef, close: onClose, tabExits: "edges" });
|
|
10812
11093
|
useEffect(() => {
|
|
10813
11094
|
if (!focusIn) return;
|
|
10814
|
-
const raf = requestAnimationFrame(() => panelRef.current?.querySelector(
|
|
11095
|
+
const raf = requestAnimationFrame(() => panelRef.current?.querySelector("a[href]")?.focus());
|
|
10815
11096
|
return () => cancelAnimationFrame(raf);
|
|
10816
11097
|
}, [focusIn]);
|
|
10817
11098
|
useEffect(() => {
|
|
10818
11099
|
function handler(e) {
|
|
10819
|
-
if (!isTopLayer()) return;
|
|
11100
|
+
if (e.defaultPrevented || !isTopLayer()) return;
|
|
10820
11101
|
const inside = !!panelRef.current?.contains(document.activeElement);
|
|
10821
11102
|
if (e.key === "Escape" || e.key === "ArrowLeft" && inside) {
|
|
10822
11103
|
e.preventDefault();
|
|
10823
11104
|
if (inside) returnFocus();
|
|
10824
11105
|
onClose();
|
|
10825
11106
|
} else if (inside && (e.key === "ArrowDown" || e.key === "ArrowUp")) {
|
|
10826
|
-
const links = Array.from(panelRef.current?.querySelectorAll(
|
|
11107
|
+
const links = Array.from(panelRef.current?.querySelectorAll("a[href]") ?? []);
|
|
10827
11108
|
const at = links.indexOf(document.activeElement);
|
|
10828
11109
|
const next = links[(at + (e.key === "ArrowDown" ? 1 : -1) + links.length) % links.length];
|
|
10829
11110
|
if (next) {
|
|
@@ -10846,8 +11127,7 @@ function CompactFlyout({
|
|
|
10846
11127
|
"div",
|
|
10847
11128
|
{
|
|
10848
11129
|
ref: panelRef,
|
|
10849
|
-
|
|
10850
|
-
"aria-label": parentLabel,
|
|
11130
|
+
id,
|
|
10851
11131
|
className: cn(
|
|
10852
11132
|
"min-w-[160px] py-ds-1",
|
|
10853
11133
|
"bg-[var(--ds-sidebar-bg)] rounded-[var(--ds-radius-md)]",
|
|
@@ -10855,12 +11135,11 @@ function CompactFlyout({
|
|
|
10855
11135
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]"
|
|
10856
11136
|
),
|
|
10857
11137
|
children: [
|
|
10858
|
-
/* @__PURE__ */ jsx("p", { className: "px-ds-2 pt-ds-1 pb-ds-1.5 text-2xs font-semibold uppercase tracking-wider text-[var(--ds-sidebar-text-muted)]", children: parentLabel }),
|
|
10859
|
-
/* @__PURE__ */ jsx("
|
|
11138
|
+
/* @__PURE__ */ jsx("p", { id: headingId, className: "px-ds-2 pt-ds-1 pb-ds-1.5 text-2xs font-semibold uppercase tracking-wider text-[var(--ds-sidebar-text-muted)]", children: parentLabel }),
|
|
11139
|
+
/* @__PURE__ */ jsx("ul", { "aria-labelledby": headingId, className: "flex flex-col px-ds-1", style: { gap: "var(--ds-space-0\\.5)" }, children: items.map((child, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
10860
11140
|
"a",
|
|
10861
11141
|
{
|
|
10862
11142
|
href: child.href ?? "#",
|
|
10863
|
-
role: "menuitem",
|
|
10864
11143
|
onClick: (e) => {
|
|
10865
11144
|
e.preventDefault();
|
|
10866
11145
|
onItemClick?.(child, i);
|
|
@@ -10875,9 +11154,8 @@ function CompactFlyout({
|
|
|
10875
11154
|
/* @__PURE__ */ jsx(TruncLabel3, { children: child.label }),
|
|
10876
11155
|
child.badge && /* @__PURE__ */ jsx("span", { className: "shrink-0", children: child.badge })
|
|
10877
11156
|
]
|
|
10878
|
-
}
|
|
10879
|
-
|
|
10880
|
-
)) })
|
|
11157
|
+
}
|
|
11158
|
+
) }, child.label)) })
|
|
10881
11159
|
]
|
|
10882
11160
|
}
|
|
10883
11161
|
)
|
|
@@ -11224,6 +11502,7 @@ function CompactNavItem({
|
|
|
11224
11502
|
onToggleExpand
|
|
11225
11503
|
}) {
|
|
11226
11504
|
const [triggerEl, setTriggerEl] = useState(null);
|
|
11505
|
+
const flyoutId = useId();
|
|
11227
11506
|
const [keyboardOpen, setKeyboardOpen] = useState(false);
|
|
11228
11507
|
if (!isOpen && keyboardOpen) setKeyboardOpen(false);
|
|
11229
11508
|
const handleMouseEnter = useCallback(() => {
|
|
@@ -11255,8 +11534,8 @@ function CompactNavItem({
|
|
|
11255
11534
|
setKeyboardOpen(true);
|
|
11256
11535
|
onOpen(flyoutKey);
|
|
11257
11536
|
} : void 0,
|
|
11258
|
-
"aria-haspopup": !mobile && hasChildren ? "menu" : void 0,
|
|
11259
11537
|
"aria-expanded": hasChildren ? mobile ? expanded : isOpen : void 0,
|
|
11538
|
+
"aria-controls": !mobile && hasChildren && isOpen ? flyoutId : void 0,
|
|
11260
11539
|
className: cn(
|
|
11261
11540
|
"relative flex flex-col items-center justify-center gap-[3px] w-full py-ds-3 px-ds-1 rounded-[var(--ds-radius-md)] transition-colors cursor-pointer",
|
|
11262
11541
|
// Compact tiles have no edge to stroke: they read the fill and text
|
|
@@ -11291,6 +11570,7 @@ function CompactNavItem({
|
|
|
11291
11570
|
!mobile && isOpen && hasChildren && item.children && triggerEl && /* @__PURE__ */ jsx(
|
|
11292
11571
|
CompactFlyout,
|
|
11293
11572
|
{
|
|
11573
|
+
id: flyoutId,
|
|
11294
11574
|
parentLabel: item.label,
|
|
11295
11575
|
items: item.children,
|
|
11296
11576
|
anchorEl: triggerEl,
|
|
@@ -11766,6 +12046,35 @@ function BackButton({ onLight, onClick }) {
|
|
|
11766
12046
|
}
|
|
11767
12047
|
);
|
|
11768
12048
|
}
|
|
12049
|
+
function BackLink({ onClick, onLight }) {
|
|
12050
|
+
return /* @__PURE__ */ jsxs(
|
|
12051
|
+
"button",
|
|
12052
|
+
{
|
|
12053
|
+
type: "button",
|
|
12054
|
+
onClick,
|
|
12055
|
+
className: cn(
|
|
12056
|
+
"inline-flex items-center gap-ds-1 mb-ds-3 text-sm underline underline-offset-4 cursor-pointer",
|
|
12057
|
+
"rounded-[var(--ds-radius-sm)] focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
12058
|
+
onLight ? "text-[var(--ds-text-on-primary)]" : "text-[var(--ds-text-primary)] hover:text-[var(--ds-accent-primary)]"
|
|
12059
|
+
),
|
|
12060
|
+
children: [
|
|
12061
|
+
/* @__PURE__ */ jsx(Icon, { name: "chevron-left", size: 14 }),
|
|
12062
|
+
"Back"
|
|
12063
|
+
]
|
|
12064
|
+
}
|
|
12065
|
+
);
|
|
12066
|
+
}
|
|
12067
|
+
function Caption({ children, onLight, onTint }) {
|
|
12068
|
+
return /* @__PURE__ */ jsx("p", { className: cn(
|
|
12069
|
+
"mb-ds-1 text-sm font-medium",
|
|
12070
|
+
onLight ? "text-[var(--ds-text-on-primary)]/80" : onTint ? "text-[var(--ds-text-muted-on-tint)]" : "text-[var(--ds-text-secondary)]"
|
|
12071
|
+
), children });
|
|
12072
|
+
}
|
|
12073
|
+
function TabRow({ children, hasCaption, className, onBand }) {
|
|
12074
|
+
const [row, setRow] = useState(null);
|
|
12075
|
+
const value = useMemo(() => ({ row, hasCaption }), [row, hasCaption]);
|
|
12076
|
+
return /* @__PURE__ */ jsx("div", { ref: setRow, className: cn(className, onBand && "mx-0 rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-surface)] px-ds-3 py-ds-2"), children: /* @__PURE__ */ jsx(HeaderTabRowContext.Provider, { value, children }) });
|
|
12077
|
+
}
|
|
11769
12078
|
var FLOATING_HEADER = cn(
|
|
11770
12079
|
"rounded-[var(--ds-radius-md)]",
|
|
11771
12080
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
@@ -11783,9 +12092,10 @@ function computeFloatingPadding(navbarFloating, sidebarFloating, overlapActive,
|
|
|
11783
12092
|
var PageHeader = forwardRef(function PageHeader2({
|
|
11784
12093
|
title,
|
|
11785
12094
|
description,
|
|
12095
|
+
caption,
|
|
11786
12096
|
badge,
|
|
11787
12097
|
breadcrumbs,
|
|
11788
|
-
onBack,
|
|
12098
|
+
onBack: onBackProp,
|
|
11789
12099
|
actions,
|
|
11790
12100
|
avatar,
|
|
11791
12101
|
filters,
|
|
@@ -11844,12 +12154,16 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
11844
12154
|
const containedBreadcrumbs = containedBreadcrumbsProp ?? (container?.breadcrumbsInsideHeader && breadcrumbs?.length ? /* @__PURE__ */ jsx(Breadcrumbs, { variant: "contained", itemVariant: r.breadcrumbStyle, bleed: true, contentMaxWidth: gutterWidth, separator: bcSep, items: [...breadcrumbs, { label: title }] }) : void 0);
|
|
11845
12155
|
const noBottomMargin = noBottomMarginProp ?? container?.noBottomMargin;
|
|
11846
12156
|
const overlapActive = container?.overlap ?? false;
|
|
12157
|
+
const focusBack = shell?.focus ? onBackProp : void 0;
|
|
12158
|
+
const onBack = focusBack ? void 0 : onBackProp;
|
|
11847
12159
|
if (behavior === "snapping") {
|
|
11848
12160
|
return /* @__PURE__ */ jsx(
|
|
11849
12161
|
SnappingHeader,
|
|
11850
12162
|
{
|
|
11851
12163
|
title,
|
|
11852
12164
|
description,
|
|
12165
|
+
caption,
|
|
12166
|
+
focusBack,
|
|
11853
12167
|
badge,
|
|
11854
12168
|
breadcrumbs: inlineBreadcrumbs,
|
|
11855
12169
|
onBack,
|
|
@@ -11881,13 +12195,15 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
11881
12195
|
}
|
|
11882
12196
|
let header;
|
|
11883
12197
|
if (variant === "minimal") {
|
|
11884
|
-
header = /* @__PURE__ */ jsx(MinimalHeader, { title, badge, breadcrumbs: inlineBreadcrumbs, actions, breadcrumbPill: bcPill, breadcrumbSeparator: bcSep, as: Heading, className, headerRef: floating ? void 0 : ref, isFloating: floating, contentMaxWidth: gutterWidth });
|
|
12198
|
+
header = /* @__PURE__ */ jsx(MinimalHeader, { title, caption, focusBack, badge, breadcrumbs: inlineBreadcrumbs, actions, tabs, breadcrumbPill: bcPill, breadcrumbSeparator: bcSep, as: Heading, className, headerRef: floating ? void 0 : ref, isFloating: floating, contentMaxWidth: gutterWidth });
|
|
11885
12199
|
} else if (variant === "tabs-integrated") {
|
|
11886
12200
|
header = /* @__PURE__ */ jsx(
|
|
11887
12201
|
TabsIntegratedHeader,
|
|
11888
12202
|
{
|
|
11889
12203
|
title,
|
|
11890
12204
|
description,
|
|
12205
|
+
caption,
|
|
12206
|
+
focusBack,
|
|
11891
12207
|
badge,
|
|
11892
12208
|
breadcrumbs: inlineBreadcrumbs,
|
|
11893
12209
|
onBack,
|
|
@@ -11910,6 +12226,9 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
11910
12226
|
gutter: !insidePaddedColumn,
|
|
11911
12227
|
title,
|
|
11912
12228
|
description,
|
|
12229
|
+
caption,
|
|
12230
|
+
focusBack,
|
|
12231
|
+
tabs,
|
|
11913
12232
|
badge,
|
|
11914
12233
|
breadcrumbs: inlineBreadcrumbs,
|
|
11915
12234
|
onBack,
|
|
@@ -11935,6 +12254,9 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
11935
12254
|
{
|
|
11936
12255
|
title,
|
|
11937
12256
|
description,
|
|
12257
|
+
caption,
|
|
12258
|
+
focusBack,
|
|
12259
|
+
tabs,
|
|
11938
12260
|
badge,
|
|
11939
12261
|
breadcrumbs: inlineBreadcrumbs,
|
|
11940
12262
|
onBack,
|
|
@@ -11975,6 +12297,9 @@ function floatingContentProps(isFloating, contentMaxWidth, extraClassName) {
|
|
|
11975
12297
|
function DefaultHeader({
|
|
11976
12298
|
title,
|
|
11977
12299
|
description,
|
|
12300
|
+
caption,
|
|
12301
|
+
focusBack,
|
|
12302
|
+
tabs,
|
|
11978
12303
|
badge,
|
|
11979
12304
|
breadcrumbs,
|
|
11980
12305
|
onBack,
|
|
@@ -11997,6 +12322,7 @@ function DefaultHeader({
|
|
|
11997
12322
|
return /* @__PURE__ */ jsxs(
|
|
11998
12323
|
"header",
|
|
11999
12324
|
{
|
|
12325
|
+
"data-gs": "page-header",
|
|
12000
12326
|
ref: headerRef,
|
|
12001
12327
|
className: cn(
|
|
12002
12328
|
!hasBanner && (hasBreadcrumbs ? "pt-ds-3 pb-ds-6" : "py-ds-6"),
|
|
@@ -12015,6 +12341,7 @@ function DefaultHeader({
|
|
|
12015
12341
|
children: [
|
|
12016
12342
|
hasBanner && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-[var(--ds-bg-canvas)]/85" }),
|
|
12017
12343
|
/* @__PURE__ */ jsxs("div", { className: inner.className, style: inner.style, children: [
|
|
12344
|
+
focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack }),
|
|
12018
12345
|
hasBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs3, { items: breadcrumbs, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
12019
12346
|
/* @__PURE__ */ jsxs("div", { className: cn(
|
|
12020
12347
|
"flex flex-col @sm:flex-row @sm:items-center justify-between gap-ds-4",
|
|
@@ -12024,6 +12351,7 @@ function DefaultHeader({
|
|
|
12024
12351
|
onBack && /* @__PURE__ */ jsx(BackButton, { onClick: onBack }),
|
|
12025
12352
|
avatar && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: avatar }),
|
|
12026
12353
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
12354
|
+
caption && /* @__PURE__ */ jsx(Caption, { children: caption }),
|
|
12027
12355
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
|
|
12028
12356
|
/* @__PURE__ */ jsx(TruncHeading, { as: Heading, className: "font-[family-name:var(--ds-font-display)] text-3xl font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", children: title }),
|
|
12029
12357
|
badge
|
|
@@ -12033,7 +12361,8 @@ function DefaultHeader({
|
|
|
12033
12361
|
] }),
|
|
12034
12362
|
actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions })
|
|
12035
12363
|
] }),
|
|
12036
|
-
filters && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center flex-wrap gap-ds-3 mt-ds-4", children: filters }) })
|
|
12364
|
+
filters && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center flex-wrap gap-ds-3 mt-ds-4", children: filters }) }),
|
|
12365
|
+
tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-4 -mx-ds-1", children: tabs })
|
|
12037
12366
|
] })
|
|
12038
12367
|
]
|
|
12039
12368
|
}
|
|
@@ -12041,9 +12370,12 @@ function DefaultHeader({
|
|
|
12041
12370
|
}
|
|
12042
12371
|
function MinimalHeader({
|
|
12043
12372
|
title,
|
|
12373
|
+
caption,
|
|
12374
|
+
focusBack,
|
|
12044
12375
|
badge,
|
|
12045
12376
|
breadcrumbs,
|
|
12046
12377
|
actions,
|
|
12378
|
+
tabs,
|
|
12047
12379
|
breadcrumbPill,
|
|
12048
12380
|
breadcrumbSeparator,
|
|
12049
12381
|
as: Heading = "h1",
|
|
@@ -12054,20 +12386,26 @@ function MinimalHeader({
|
|
|
12054
12386
|
}) {
|
|
12055
12387
|
const hasBreadcrumbs = !!(breadcrumbs && breadcrumbs.length > 0);
|
|
12056
12388
|
const inner = floatingContentProps(isFloating, contentMaxWidth);
|
|
12057
|
-
return /* @__PURE__ */ jsx("header", { ref: headerRef, className: cn("py-ds-2", hasBreadcrumbs && "pt-ds-1", isFloating && FLOATING_HEADER, className), children: /* @__PURE__ */ jsxs("div", { className: inner.className, style: inner.style, children: [
|
|
12389
|
+
return /* @__PURE__ */ jsx("header", { "data-gs": "page-header", ref: headerRef, className: cn("py-ds-2", hasBreadcrumbs && "pt-ds-1", tabs && "pb-ds-4", isFloating && FLOATING_HEADER, className), children: /* @__PURE__ */ jsxs("div", { className: inner.className, style: inner.style, children: [
|
|
12390
|
+
focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack }),
|
|
12058
12391
|
hasBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs3, { items: breadcrumbs, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
12392
|
+
caption && /* @__PURE__ */ jsx(Caption, { children: caption }),
|
|
12059
12393
|
/* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between gap-ds-4", hasBreadcrumbs && "mt-ds-0.5"), children: [
|
|
12060
12394
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2 min-w-0", children: [
|
|
12061
12395
|
/* @__PURE__ */ jsx(TruncHeading, { as: Heading, lines: 1, className: "font-[family-name:var(--ds-font-display)] text-xl font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", children: title }),
|
|
12062
12396
|
badge
|
|
12063
12397
|
] }),
|
|
12064
12398
|
actions && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) })
|
|
12065
|
-
] })
|
|
12399
|
+
] }),
|
|
12400
|
+
tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-3 -mx-ds-1", children: tabs })
|
|
12066
12401
|
] }) });
|
|
12067
12402
|
}
|
|
12068
12403
|
function ColourfulHeader({
|
|
12069
12404
|
title,
|
|
12070
12405
|
description,
|
|
12406
|
+
caption,
|
|
12407
|
+
focusBack,
|
|
12408
|
+
tabs,
|
|
12071
12409
|
badge,
|
|
12072
12410
|
breadcrumbs,
|
|
12073
12411
|
onBack,
|
|
@@ -12092,6 +12430,7 @@ function ColourfulHeader({
|
|
|
12092
12430
|
return /* @__PURE__ */ jsxs(
|
|
12093
12431
|
"header",
|
|
12094
12432
|
{
|
|
12433
|
+
"data-gs": "page-header",
|
|
12095
12434
|
ref: headerRef,
|
|
12096
12435
|
className: cn(
|
|
12097
12436
|
"relative overflow-hidden w-full",
|
|
@@ -12135,6 +12474,7 @@ function ColourfulHeader({
|
|
|
12135
12474
|
...overlapActive ? { paddingBottom: `calc(var(--ds-space-6) + var(--ds-overlap, 0px))` } : {}
|
|
12136
12475
|
},
|
|
12137
12476
|
children: [
|
|
12477
|
+
focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack, onLight: isBold }),
|
|
12138
12478
|
hasBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs3, { items: breadcrumbs, onLight: isBold, onTint: !isBold, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
12139
12479
|
/* @__PURE__ */ jsxs("div", { className: cn(
|
|
12140
12480
|
"flex flex-col @sm:flex-row @sm:items-center justify-between gap-ds-4",
|
|
@@ -12144,6 +12484,7 @@ function ColourfulHeader({
|
|
|
12144
12484
|
onBack && /* @__PURE__ */ jsx(BackButton, { onClick: onBack, onLight: isBold }),
|
|
12145
12485
|
avatar && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: avatar }),
|
|
12146
12486
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
12487
|
+
caption && /* @__PURE__ */ jsx(Caption, { onLight: isBold, onTint: !isBold, children: caption }),
|
|
12147
12488
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
|
|
12148
12489
|
/* @__PURE__ */ jsx(TruncHeading, { as: Heading, className: cn(
|
|
12149
12490
|
"font-[family-name:var(--ds-font-display)] text-3xl font-[var(--ds-weight-heading)]",
|
|
@@ -12159,7 +12500,8 @@ function ColourfulHeader({
|
|
|
12159
12500
|
] }),
|
|
12160
12501
|
actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions })
|
|
12161
12502
|
] }),
|
|
12162
|
-
filters && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center flex-wrap gap-ds-3 mt-ds-4", children: filters }) })
|
|
12503
|
+
filters && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center flex-wrap gap-ds-3 mt-ds-4", children: filters }) }),
|
|
12504
|
+
tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-4 -mx-ds-1", onBand: isBold, children: tabs })
|
|
12163
12505
|
]
|
|
12164
12506
|
}
|
|
12165
12507
|
)
|
|
@@ -12170,6 +12512,8 @@ function ColourfulHeader({
|
|
|
12170
12512
|
function SnappingHeader({
|
|
12171
12513
|
title,
|
|
12172
12514
|
description,
|
|
12515
|
+
caption,
|
|
12516
|
+
focusBack,
|
|
12173
12517
|
badge,
|
|
12174
12518
|
breadcrumbs,
|
|
12175
12519
|
onBack,
|
|
@@ -12293,6 +12637,7 @@ function SnappingHeader({
|
|
|
12293
12637
|
const headerEl = /* @__PURE__ */ jsxs(
|
|
12294
12638
|
"header",
|
|
12295
12639
|
{
|
|
12640
|
+
"data-gs": "page-header",
|
|
12296
12641
|
ref: !isFloating ? mergedRef : void 0,
|
|
12297
12642
|
className: cn(
|
|
12298
12643
|
"transition-all duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
|
|
@@ -12329,8 +12674,10 @@ function SnappingHeader({
|
|
|
12329
12674
|
onTint && !backgroundImage && /* @__PURE__ */ jsx(TintWash, {}),
|
|
12330
12675
|
(() => {
|
|
12331
12676
|
const hasBreadcrumbs = !!(breadcrumbs && breadcrumbs.length > 0);
|
|
12332
|
-
const innerContent = isMinimal && !collapsed ? /* @__PURE__ */ jsxs("div", { className: cn("py-ds-2", hasBreadcrumbs && !hideExpandedBreadcrumbs && "pt-ds-1"), children: [
|
|
12677
|
+
const innerContent = isMinimal && !collapsed ? /* @__PURE__ */ jsxs("div", { className: cn("py-ds-2", hasBreadcrumbs && !hideExpandedBreadcrumbs && "pt-ds-1", tabs && "pb-ds-4"), children: [
|
|
12678
|
+
focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack }),
|
|
12333
12679
|
hasBreadcrumbs && !hideExpandedBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs3, { items: breadcrumbs, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
12680
|
+
caption && /* @__PURE__ */ jsx(Caption, { children: caption }),
|
|
12334
12681
|
/* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between gap-ds-4", hasBreadcrumbs && !hideExpandedBreadcrumbs && "mt-ds-0.5"), children: [
|
|
12335
12682
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2 min-w-0", children: [
|
|
12336
12683
|
/* @__PURE__ */ jsx(TruncHeading, { as: Heading, className: "font-[family-name:var(--ds-font-display)] text-xl font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", children: title }),
|
|
@@ -12340,7 +12687,7 @@ function SnappingHeader({
|
|
|
12340
12687
|
] }),
|
|
12341
12688
|
filters && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center flex-wrap gap-ds-3 mt-ds-3", children: filters }) }),
|
|
12342
12689
|
expandedContent && /* @__PURE__ */ jsx("div", { className: "mt-ds-3", children: expandedContent }),
|
|
12343
|
-
tabs && /* @__PURE__ */ jsx(
|
|
12690
|
+
tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-3 -mx-ds-1", children: tabs })
|
|
12344
12691
|
] }) : /* @__PURE__ */ jsxs(
|
|
12345
12692
|
"div",
|
|
12346
12693
|
{
|
|
@@ -12354,6 +12701,7 @@ function SnappingHeader({
|
|
|
12354
12701
|
),
|
|
12355
12702
|
style: !collapsed && isColourful && overlapActive ? { paddingBottom: `calc(var(--ds-space-6) + var(--ds-overlap, 0px))` } : void 0,
|
|
12356
12703
|
children: [
|
|
12704
|
+
!collapsed && focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack, onLight }),
|
|
12357
12705
|
!collapsed && hasBreadcrumbs && !hideExpandedBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs3, { items: breadcrumbs, onLight, onTint, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
12358
12706
|
/* @__PURE__ */ jsxs("div", { className: cn(
|
|
12359
12707
|
"flex justify-between gap-ds-4",
|
|
@@ -12365,6 +12713,7 @@ function SnappingHeader({
|
|
|
12365
12713
|
onBack && !collapsed && /* @__PURE__ */ jsx(BackButton, { onClick: onBack, onLight }),
|
|
12366
12714
|
avatar && !collapsed && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: avatar }),
|
|
12367
12715
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
12716
|
+
!collapsed && caption && /* @__PURE__ */ jsx(Caption, { onLight, onTint, children: caption }),
|
|
12368
12717
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
|
|
12369
12718
|
collapsed && hasBreadcrumbs && (() => {
|
|
12370
12719
|
const lastCrumb = breadcrumbs[breadcrumbs.length - 1];
|
|
@@ -12407,7 +12756,7 @@ function SnappingHeader({
|
|
|
12407
12756
|
] }),
|
|
12408
12757
|
!collapsed && filters && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center flex-wrap gap-ds-3 mt-ds-4", children: filters }) }),
|
|
12409
12758
|
!collapsed && expandedContent && /* @__PURE__ */ jsx("div", { className: "mt-ds-4", children: expandedContent }),
|
|
12410
|
-
!collapsed && tabs && /* @__PURE__ */ jsx(
|
|
12759
|
+
!collapsed && tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-4 -mx-ds-1", onBand: isBoldColourful, children: tabs })
|
|
12411
12760
|
]
|
|
12412
12761
|
}
|
|
12413
12762
|
);
|
|
@@ -12455,6 +12804,8 @@ function SnappingHeader({
|
|
|
12455
12804
|
function TabsIntegratedHeader({
|
|
12456
12805
|
title,
|
|
12457
12806
|
description,
|
|
12807
|
+
caption,
|
|
12808
|
+
focusBack,
|
|
12458
12809
|
badge,
|
|
12459
12810
|
breadcrumbs,
|
|
12460
12811
|
onBack,
|
|
@@ -12471,7 +12822,8 @@ function TabsIntegratedHeader({
|
|
|
12471
12822
|
}) {
|
|
12472
12823
|
const hasBreadcrumbs = !!(breadcrumbs && breadcrumbs.length > 0);
|
|
12473
12824
|
const inner = floatingContentProps(isFloating, contentMaxWidth);
|
|
12474
|
-
return /* @__PURE__ */ jsx("header", { ref: headerRef, className: cn(hasBreadcrumbs ? "pt-ds-3" : "pt-ds-6", "pb-ds-4", isFloating && cn(FLOATING_HEADER, "overflow-hidden"), className), children: /* @__PURE__ */ jsxs("div", { className: inner.className, style: inner.style, children: [
|
|
12825
|
+
return /* @__PURE__ */ jsx("header", { "data-gs": "page-header", ref: headerRef, className: cn(hasBreadcrumbs ? "pt-ds-3" : "pt-ds-6", "pb-ds-4", isFloating && cn(FLOATING_HEADER, "overflow-hidden"), className), children: /* @__PURE__ */ jsxs("div", { className: inner.className, style: inner.style, children: [
|
|
12826
|
+
focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack }),
|
|
12475
12827
|
hasBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs3, { items: breadcrumbs, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
12476
12828
|
/* @__PURE__ */ jsxs("div", { className: cn(
|
|
12477
12829
|
"flex flex-col @sm:flex-row @sm:items-center justify-between gap-ds-4",
|
|
@@ -12481,6 +12833,7 @@ function TabsIntegratedHeader({
|
|
|
12481
12833
|
onBack && /* @__PURE__ */ jsx(BackButton, { onClick: onBack }),
|
|
12482
12834
|
avatar && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: avatar }),
|
|
12483
12835
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
12836
|
+
caption && /* @__PURE__ */ jsx(Caption, { children: caption }),
|
|
12484
12837
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
|
|
12485
12838
|
/* @__PURE__ */ jsx(TruncHeading, { as: Heading, className: "font-[family-name:var(--ds-font-display)] text-3xl font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", children: title }),
|
|
12486
12839
|
badge
|
|
@@ -12490,7 +12843,7 @@ function TabsIntegratedHeader({
|
|
|
12490
12843
|
] }),
|
|
12491
12844
|
actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions })
|
|
12492
12845
|
] }),
|
|
12493
|
-
tabs && /* @__PURE__ */ jsx(
|
|
12846
|
+
tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-4 -mx-ds-1", children: tabs })
|
|
12494
12847
|
] }) });
|
|
12495
12848
|
}
|
|
12496
12849
|
var DEFAULT_BASE = 48;
|
|
@@ -12655,6 +13008,7 @@ function NavMenu({
|
|
|
12655
13008
|
const [open, setOpen] = useState(false);
|
|
12656
13009
|
const triggerRef = useRef(null);
|
|
12657
13010
|
const panelRef = useRef(null);
|
|
13011
|
+
const panelId = useId();
|
|
12658
13012
|
const [pos, setPos] = useState({ top: 0, left: 0, minWidth: 0 });
|
|
12659
13013
|
const close = useCallback(() => setOpen(false), []);
|
|
12660
13014
|
const { isTop: isTopLayer, returnFocus } = usePopupFocus(open, { trigger: triggerRef, panel: panelRef, close, tabExits: "edges" });
|
|
@@ -12680,10 +13034,10 @@ function NavMenu({
|
|
|
12680
13034
|
}
|
|
12681
13035
|
}
|
|
12682
13036
|
function handleKey(e) {
|
|
12683
|
-
if (e.key
|
|
12684
|
-
|
|
12685
|
-
|
|
12686
|
-
|
|
13037
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
13038
|
+
e.preventDefault();
|
|
13039
|
+
returnFocus();
|
|
13040
|
+
close();
|
|
12687
13041
|
}
|
|
12688
13042
|
document.addEventListener("mousedown", handleClick);
|
|
12689
13043
|
document.addEventListener("keydown", handleKey);
|
|
@@ -12725,7 +13079,7 @@ function NavMenu({
|
|
|
12725
13079
|
ref: triggerRef,
|
|
12726
13080
|
onClick: () => setOpen(!open),
|
|
12727
13081
|
"aria-expanded": open,
|
|
12728
|
-
"aria-
|
|
13082
|
+
"aria-controls": open ? panelId : void 0,
|
|
12729
13083
|
className: triggerClasses,
|
|
12730
13084
|
children: [
|
|
12731
13085
|
label,
|
|
@@ -12745,7 +13099,7 @@ function NavMenu({
|
|
|
12745
13099
|
"div",
|
|
12746
13100
|
{
|
|
12747
13101
|
ref: panelRef,
|
|
12748
|
-
|
|
13102
|
+
id: panelId,
|
|
12749
13103
|
"data-gs": "menu",
|
|
12750
13104
|
className: cn(
|
|
12751
13105
|
"fixed z-[var(--ds-z-popover)] py-ds-1.5",
|
|
@@ -12754,7 +13108,7 @@ function NavMenu({
|
|
|
12754
13108
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]"
|
|
12755
13109
|
),
|
|
12756
13110
|
style: { top: pos.top, left: pos.left, minWidth: pos.minWidth },
|
|
12757
|
-
children: items.map((item, i) => {
|
|
13111
|
+
children: /* @__PURE__ */ jsx("ul", { children: items.map((item, i) => {
|
|
12758
13112
|
if (item.children?.length) {
|
|
12759
13113
|
return /* @__PURE__ */ jsx(
|
|
12760
13114
|
NavMenuGroup,
|
|
@@ -12780,7 +13134,7 @@ function NavMenu({
|
|
|
12780
13134
|
},
|
|
12781
13135
|
item.label
|
|
12782
13136
|
);
|
|
12783
|
-
})
|
|
13137
|
+
}) })
|
|
12784
13138
|
}
|
|
12785
13139
|
),
|
|
12786
13140
|
document.body
|
|
@@ -12791,11 +13145,10 @@ function NavMenuItemRow({
|
|
|
12791
13145
|
item,
|
|
12792
13146
|
onClick
|
|
12793
13147
|
}) {
|
|
12794
|
-
return /* @__PURE__ */ jsxs(
|
|
13148
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
12795
13149
|
"a",
|
|
12796
13150
|
{
|
|
12797
13151
|
href: item.href ?? "#",
|
|
12798
|
-
role: "menuitem",
|
|
12799
13152
|
onClick: (e) => {
|
|
12800
13153
|
e.preventDefault();
|
|
12801
13154
|
onClick();
|
|
@@ -12821,14 +13174,15 @@ function NavMenuItemRow({
|
|
|
12821
13174
|
] })
|
|
12822
13175
|
]
|
|
12823
13176
|
}
|
|
12824
|
-
);
|
|
13177
|
+
) });
|
|
12825
13178
|
}
|
|
12826
13179
|
function NavMenuGroup({
|
|
12827
13180
|
group,
|
|
12828
13181
|
isFirst,
|
|
12829
13182
|
onItemClick
|
|
12830
13183
|
}) {
|
|
12831
|
-
|
|
13184
|
+
const headingId = useId();
|
|
13185
|
+
return /* @__PURE__ */ jsxs("li", { children: [
|
|
12832
13186
|
!isFirst && /* @__PURE__ */ jsx(
|
|
12833
13187
|
"div",
|
|
12834
13188
|
{
|
|
@@ -12836,15 +13190,15 @@ function NavMenuGroup({
|
|
|
12836
13190
|
style: { height: "var(--ds-divider-width, 1px)", marginTop: "var(--ds-space-1)", marginBottom: "var(--ds-space-1)" }
|
|
12837
13191
|
}
|
|
12838
13192
|
),
|
|
12839
|
-
/* @__PURE__ */ jsx("p", { className: "px-ds-3 pt-ds-1.5 pb-ds-1 text-2xs font-semibold uppercase tracking-wider text-[var(--ds-text-muted)]", children: group.label }),
|
|
12840
|
-
group.children.map((child) => /* @__PURE__ */ jsx(
|
|
13193
|
+
/* @__PURE__ */ jsx("p", { id: headingId, className: "px-ds-3 pt-ds-1.5 pb-ds-1 text-2xs font-semibold uppercase tracking-wider text-[var(--ds-text-muted)]", children: group.label }),
|
|
13194
|
+
/* @__PURE__ */ jsx("ul", { "aria-labelledby": headingId, children: group.children.map((child) => /* @__PURE__ */ jsx(
|
|
12841
13195
|
NavMenuItemRow,
|
|
12842
13196
|
{
|
|
12843
13197
|
item: child,
|
|
12844
13198
|
onClick: () => onItemClick(child)
|
|
12845
13199
|
},
|
|
12846
13200
|
child.label
|
|
12847
|
-
))
|
|
13201
|
+
)) })
|
|
12848
13202
|
] });
|
|
12849
13203
|
}
|
|
12850
13204
|
function resolveNavItemType(type) {
|
|
@@ -12908,6 +13262,174 @@ function getTypeClasses(type, active) {
|
|
|
12908
13262
|
);
|
|
12909
13263
|
}
|
|
12910
13264
|
}
|
|
13265
|
+
var DEFAULT_BUTTON_ATTR = "data-dialog-default-button";
|
|
13266
|
+
var sizeClasses = {
|
|
13267
|
+
// round 16 (the owner's item 5): the small dialog is 448 px, not 384 — a delete confirmation with a typed field was cramped
|
|
13268
|
+
sm: "max-w-md",
|
|
13269
|
+
md: "max-w-lg",
|
|
13270
|
+
lg: "max-w-2xl",
|
|
13271
|
+
xl: "max-w-4xl",
|
|
13272
|
+
full: "max-w-[calc(100vw-2rem)]"
|
|
13273
|
+
};
|
|
13274
|
+
function Dialog({ open, onClose: onCloseProp, title, description, children, footer, variant = "default", size = "md", alert = false, container, onSubmit, dirty, onDiscard }) {
|
|
13275
|
+
const guard = useDirtyGuard(dirty, onCloseProp, onDiscard);
|
|
13276
|
+
const onClose = guard.requestClose;
|
|
13277
|
+
const titleId = useId();
|
|
13278
|
+
const descriptionId = useId();
|
|
13279
|
+
const isMobile = useBreakpoint("sm");
|
|
13280
|
+
const overlayRef = useRef(null);
|
|
13281
|
+
const dialogRef = useRef(null);
|
|
13282
|
+
const opener = useRef(null);
|
|
13283
|
+
const defaultButtonRef = useRef(null);
|
|
13284
|
+
const onCloseRef = useLatest(onClose);
|
|
13285
|
+
const onSubmitRef = useLatest(onSubmit);
|
|
13286
|
+
const isTopLayer = useOverlayLayer(open);
|
|
13287
|
+
useFocusTrap(dialogRef, open, isTopLayer);
|
|
13288
|
+
const before = useFocusBeforeOpen(open);
|
|
13289
|
+
useEffect(() => {
|
|
13290
|
+
if (!open) return;
|
|
13291
|
+
const active = before.current;
|
|
13292
|
+
opener.current = active instanceof HTMLElement && active !== document.body && active.isConnected ? rememberFocus(active) : null;
|
|
13293
|
+
}, [open, before]);
|
|
13294
|
+
useEffect(() => {
|
|
13295
|
+
if (!open) return;
|
|
13296
|
+
requestAnimationFrame(() => {
|
|
13297
|
+
focusInitial(dialogRef.current, { destructive: variant === "destructive" });
|
|
13298
|
+
});
|
|
13299
|
+
}, [open, variant]);
|
|
13300
|
+
useEffect(() => {
|
|
13301
|
+
if (!open) return;
|
|
13302
|
+
const handler = (e) => {
|
|
13303
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
13304
|
+
e.preventDefault();
|
|
13305
|
+
onCloseRef.current();
|
|
13306
|
+
};
|
|
13307
|
+
document.addEventListener("keydown", handler);
|
|
13308
|
+
return () => {
|
|
13309
|
+
document.removeEventListener("keydown", handler);
|
|
13310
|
+
};
|
|
13311
|
+
}, [open, onCloseRef, isTopLayer]);
|
|
13312
|
+
useEffect(() => {
|
|
13313
|
+
if (!open) return;
|
|
13314
|
+
lockBodyScroll();
|
|
13315
|
+
return () => {
|
|
13316
|
+
unlockBodyScroll();
|
|
13317
|
+
const r = opener.current;
|
|
13318
|
+
opener.current = null;
|
|
13319
|
+
const active = document.activeElement;
|
|
13320
|
+
if (!active || active === document.body || !active.isConnected) r?.restore();
|
|
13321
|
+
};
|
|
13322
|
+
}, [open]);
|
|
13323
|
+
if (!open) return null;
|
|
13324
|
+
return createPortal(
|
|
13325
|
+
/* @__PURE__ */ jsxs(
|
|
13326
|
+
"div",
|
|
13327
|
+
{
|
|
13328
|
+
ref: overlayRef,
|
|
13329
|
+
className: "fixed inset-0 z-[var(--ds-z-modal)] flex items-center justify-center p-ds-4",
|
|
13330
|
+
children: [
|
|
13331
|
+
/* @__PURE__ */ jsx(
|
|
13332
|
+
"div",
|
|
13333
|
+
{
|
|
13334
|
+
className: "fixed inset-0 bg-black/50 [backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))] [-webkit-backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))]",
|
|
13335
|
+
onClick: alert ? void 0 : onClose,
|
|
13336
|
+
"aria-hidden": "true"
|
|
13337
|
+
}
|
|
13338
|
+
),
|
|
13339
|
+
/* @__PURE__ */ jsxs(
|
|
13340
|
+
"form",
|
|
13341
|
+
{
|
|
13342
|
+
onSubmit: (e) => {
|
|
13343
|
+
e.preventDefault();
|
|
13344
|
+
if (variant === "destructive") return;
|
|
13345
|
+
const submitter = e.nativeEvent.submitter;
|
|
13346
|
+
const implicit = !submitter || submitter === defaultButtonRef.current;
|
|
13347
|
+
if (!implicit && submitter.getAttribute("type") !== "submit") return;
|
|
13348
|
+
if (implicit) {
|
|
13349
|
+
const explicit = e.currentTarget.querySelector(`button[type="submit"]:not([${DEFAULT_BUTTON_ATTR}])`);
|
|
13350
|
+
if (explicit?.disabled) return;
|
|
13351
|
+
}
|
|
13352
|
+
onSubmitRef.current?.();
|
|
13353
|
+
},
|
|
13354
|
+
className: "contents",
|
|
13355
|
+
children: [
|
|
13356
|
+
/* @__PURE__ */ jsx(
|
|
13357
|
+
"button",
|
|
13358
|
+
{
|
|
13359
|
+
ref: defaultButtonRef,
|
|
13360
|
+
type: "submit",
|
|
13361
|
+
tabIndex: -1,
|
|
13362
|
+
"aria-hidden": "true",
|
|
13363
|
+
className: "sr-only",
|
|
13364
|
+
...{ [DEFAULT_BUTTON_ATTR]: "" }
|
|
13365
|
+
}
|
|
13366
|
+
),
|
|
13367
|
+
/* @__PURE__ */ jsxs(
|
|
13368
|
+
"div",
|
|
13369
|
+
{
|
|
13370
|
+
ref: dialogRef,
|
|
13371
|
+
role: alert ? "alertdialog" : "dialog",
|
|
13372
|
+
"aria-modal": "true",
|
|
13373
|
+
"data-gs": "dialog",
|
|
13374
|
+
"aria-labelledby": titleId,
|
|
13375
|
+
"aria-describedby": description ? descriptionId : void 0,
|
|
13376
|
+
style: { containerType: "inline-size" },
|
|
13377
|
+
className: cn(
|
|
13378
|
+
"relative z-10 w-full",
|
|
13379
|
+
isMobile ? "max-w-none h-full" : sizeClasses[size],
|
|
13380
|
+
"bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
|
|
13381
|
+
GLASS_OVERLAY,
|
|
13382
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
13383
|
+
isMobile ? "rounded-none" : "rounded-[var(--ds-radius-xl)]",
|
|
13384
|
+
"overflow-hidden",
|
|
13385
|
+
"animate-in fade-in-0 zoom-in-95"
|
|
13386
|
+
),
|
|
13387
|
+
children: [
|
|
13388
|
+
/* @__PURE__ */ jsx(
|
|
13389
|
+
"button",
|
|
13390
|
+
{
|
|
13391
|
+
type: "button",
|
|
13392
|
+
onClick: onClose,
|
|
13393
|
+
...{ [OVERLAY_CLOSE_ATTR]: "" },
|
|
13394
|
+
className: "absolute right-4 top-4 text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
|
|
13395
|
+
"aria-label": "Close",
|
|
13396
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
|
|
13397
|
+
}
|
|
13398
|
+
),
|
|
13399
|
+
/* @__PURE__ */ jsx("div", { className: "p-ds-6", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-ds-3", children: [
|
|
13400
|
+
variant === "destructive" && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center shrink-0 w-10 h-10 rounded-[var(--ds-radius-full)] bg-[var(--ds-status-error-bg)]", children: /* @__PURE__ */ jsx(Icon, { name: "warning", size: 20, className: "text-[var(--ds-status-error)]" }) }),
|
|
13401
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
13402
|
+
/* @__PURE__ */ jsx(
|
|
13403
|
+
"h2",
|
|
13404
|
+
{
|
|
13405
|
+
id: titleId,
|
|
13406
|
+
className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] leading-none tracking-tight",
|
|
13407
|
+
children: title
|
|
13408
|
+
}
|
|
13409
|
+
),
|
|
13410
|
+
description && /* @__PURE__ */ jsx("p", { id: descriptionId, className: "mt-ds-2 text-sm text-[var(--ds-text-muted)]", children: description }),
|
|
13411
|
+
children && /* @__PURE__ */ jsx("div", { className: "mt-ds-4", children: /* @__PURE__ */ jsx(OverlayCloseCtx, { value: onClose, children }) })
|
|
13412
|
+
] })
|
|
13413
|
+
] }) }),
|
|
13414
|
+
/* @__PURE__ */ jsx(DiscardConfirm, { open: guard.confirming, onKeep: guard.keep, onDiscard: guard.discard }),
|
|
13415
|
+
footer && /* @__PURE__ */ jsx("div", { className: cn(
|
|
13416
|
+
"flex justify-end gap-ds-2 p-ds-4",
|
|
13417
|
+
"border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
13418
|
+
"bg-[var(--ds-bg-muted)]",
|
|
13419
|
+
"rounded-b-[var(--ds-radius-xl)]"
|
|
13420
|
+
), children: footer })
|
|
13421
|
+
]
|
|
13422
|
+
}
|
|
13423
|
+
)
|
|
13424
|
+
]
|
|
13425
|
+
}
|
|
13426
|
+
)
|
|
13427
|
+
]
|
|
13428
|
+
}
|
|
13429
|
+
),
|
|
13430
|
+
container ?? document.body
|
|
13431
|
+
);
|
|
13432
|
+
}
|
|
12911
13433
|
function HamburgerButton({ onClick, open, className: cls }) {
|
|
12912
13434
|
return /* @__PURE__ */ jsx(
|
|
12913
13435
|
"button",
|
|
@@ -12963,9 +13485,11 @@ var Navbar = forwardRef(function Navbar2({
|
|
|
12963
13485
|
const [visibleCount, setVisibleCount] = useState(null);
|
|
12964
13486
|
const links = useMemo(() => flattenLinks(navLinks), [navLinks]);
|
|
12965
13487
|
const mobileHidesLinks = !!appShell?.isMobile && (appShell.hasMobileMenu || appShell.hasMobileNav);
|
|
13488
|
+
const focus = appShell?.focus ?? null;
|
|
13489
|
+
const [confirmExit, setConfirmExit] = useState(false);
|
|
12966
13490
|
useEffect(() => {
|
|
12967
13491
|
const header = headerRef.current;
|
|
12968
|
-
if (!header || mobileHidesLinks || links.length === 0 || typeof ResizeObserver === "undefined") return;
|
|
13492
|
+
if (!header || mobileHidesLinks || focus || links.length === 0 || typeof ResizeObserver === "undefined") return;
|
|
12969
13493
|
const measure = () => {
|
|
12970
13494
|
const nav = navRef.current;
|
|
12971
13495
|
if (!nav) return;
|
|
@@ -13002,7 +13526,7 @@ var Navbar = forwardRef(function Navbar2({
|
|
|
13002
13526
|
const ro = new ResizeObserver(measure);
|
|
13003
13527
|
ro.observe(header);
|
|
13004
13528
|
return () => ro.disconnect();
|
|
13005
|
-
}, [mobileHidesLinks, links]);
|
|
13529
|
+
}, [mobileHidesLinks, focus, links]);
|
|
13006
13530
|
const [topInset, setTopInset] = useState(null);
|
|
13007
13531
|
const shellEl = appShell?.container ?? null;
|
|
13008
13532
|
useLayoutEffect(() => {
|
|
@@ -13034,7 +13558,40 @@ var Navbar = forwardRef(function Navbar2({
|
|
|
13034
13558
|
}, [visibleCount, links]);
|
|
13035
13559
|
const showHamburger = appShell?.isMobile && appShell.hasMobileMenu && !(isSmallPhone && appShell.hasMobileNav) || !!onMenuClick;
|
|
13036
13560
|
const handleHamburger = () => onMenuClick ? onMenuClick() : appShell?.setSidebarOpen(!appShell.sidebarOpen);
|
|
13037
|
-
const hideNavLinks = mobileHidesLinks;
|
|
13561
|
+
const hideNavLinks = mobileHidesLinks || !!focus;
|
|
13562
|
+
const shownSearch = focus ? null : search;
|
|
13563
|
+
const requestExit = () => {
|
|
13564
|
+
if (!focus) return;
|
|
13565
|
+
if (focus.kind === "in-app" && appShell?.hasUnsavedChanges) {
|
|
13566
|
+
setConfirmExit(true);
|
|
13567
|
+
return;
|
|
13568
|
+
}
|
|
13569
|
+
focus.onExit?.();
|
|
13570
|
+
};
|
|
13571
|
+
const exitControl = focus ? /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", onClick: requestExit, children: focus.exitLabel ?? (focus.kind === "before-app" ? "Save and log out" : "Exit") }) : null;
|
|
13572
|
+
const shownUserMenu = focus?.kind === "before-app" ? null : userMenu;
|
|
13573
|
+
const asking = confirmExit && focus?.kind === "in-app" && !!appShell?.hasUnsavedChanges;
|
|
13574
|
+
if (confirmExit && !asking) setConfirmExit(false);
|
|
13575
|
+
const exitDialog = focus?.kind === "in-app" ? /* @__PURE__ */ jsx(
|
|
13576
|
+
Dialog,
|
|
13577
|
+
{
|
|
13578
|
+
open: asking,
|
|
13579
|
+
onClose: () => setConfirmExit(false),
|
|
13580
|
+
title: "You have unsaved changes",
|
|
13581
|
+
description: "Exit now and your changes are lost.",
|
|
13582
|
+
variant: "destructive",
|
|
13583
|
+
size: "sm",
|
|
13584
|
+
alert: true,
|
|
13585
|
+
container: shellEl ?? void 0,
|
|
13586
|
+
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
13587
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => setConfirmExit(false), children: "Keep editing" }),
|
|
13588
|
+
/* @__PURE__ */ jsx(Button, { variant: "destructive", onClick: () => {
|
|
13589
|
+
setConfirmExit(false);
|
|
13590
|
+
focus.onExit?.();
|
|
13591
|
+
}, children: "Discard changes" })
|
|
13592
|
+
] })
|
|
13593
|
+
}
|
|
13594
|
+
) : null;
|
|
13038
13595
|
const type = resolveNavItemType(typeProp);
|
|
13039
13596
|
const isMinimal = type === "minimal";
|
|
13040
13597
|
const isFloating = position === "floating";
|
|
@@ -13100,9 +13657,10 @@ var Navbar = forwardRef(function Navbar2({
|
|
|
13100
13657
|
] }),
|
|
13101
13658
|
navLinks && !hideNavLinks ? /* @__PURE__ */ jsx(NavbarTypeContext.Provider, { value: type, children: /* @__PURE__ */ jsx("nav", { ref: navRef, className: "flex items-center gap-ds-2 min-w-0 overflow-x-clip justify-center", "data-navbar-type": type, children: linkRow }) }) : /* @__PURE__ */ jsx("div", { "data-navbar-spacer": "" }),
|
|
13102
13659
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-4 justify-end", children: [
|
|
13103
|
-
|
|
13660
|
+
shownSearch && /* @__PURE__ */ jsx("div", { className: "flex items-center shrink-0", children: shownSearch }),
|
|
13104
13661
|
actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }),
|
|
13105
|
-
|
|
13662
|
+
exitControl && /* @__PURE__ */ jsx("div", { className: "flex items-center shrink-0", children: exitControl }),
|
|
13663
|
+
shownUserMenu && /* @__PURE__ */ jsx("div", { className: cn("flex items-center", resolvedSize === "sm" ? "min-w-0 max-w-[180px]" : "shrink-0"), children: shownUserMenu })
|
|
13106
13664
|
] })
|
|
13107
13665
|
]
|
|
13108
13666
|
}
|
|
@@ -13127,15 +13685,16 @@ var Navbar = forwardRef(function Navbar2({
|
|
|
13127
13685
|
align === "right" && /* @__PURE__ */ jsx("div", { "data-navbar-spacer": "", className: "flex-1" }),
|
|
13128
13686
|
navLinks && !hideNavLinks && /* @__PURE__ */ jsx(NavbarTypeContext.Provider, { value: type, children: /* @__PURE__ */ jsx("nav", { ref: navRef, className: cn("flex items-center gap-ds-2 min-w-0 overflow-x-clip", align === "left" && "flex-1"), "data-navbar-type": type, children: linkRow }) }),
|
|
13129
13687
|
(!navLinks || hideNavLinks) && /* @__PURE__ */ jsx("div", { "data-navbar-spacer": "", className: "flex-1" }),
|
|
13130
|
-
|
|
13688
|
+
shownSearch && /* @__PURE__ */ jsx("div", { className: "flex items-center shrink-0", children: shownSearch }),
|
|
13131
13689
|
actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }),
|
|
13132
|
-
|
|
13690
|
+
exitControl && /* @__PURE__ */ jsx("div", { className: "flex items-center shrink-0", children: exitControl }),
|
|
13691
|
+
shownUserMenu && /* @__PURE__ */ jsx("div", { className: cn("flex items-center", resolvedSize === "sm" ? "min-w-0 max-w-[180px]" : "shrink-0"), children: shownUserMenu })
|
|
13133
13692
|
]
|
|
13134
13693
|
}
|
|
13135
13694
|
);
|
|
13136
13695
|
}
|
|
13137
13696
|
if (isFloating) {
|
|
13138
|
-
return /* @__PURE__ */
|
|
13697
|
+
return /* @__PURE__ */ jsxs(
|
|
13139
13698
|
"div",
|
|
13140
13699
|
{
|
|
13141
13700
|
ref,
|
|
@@ -13145,11 +13704,17 @@ var Navbar = forwardRef(function Navbar2({
|
|
|
13145
13704
|
className
|
|
13146
13705
|
),
|
|
13147
13706
|
style: { padding: "var(--ds-space-3)" },
|
|
13148
|
-
children:
|
|
13707
|
+
children: [
|
|
13708
|
+
headerEl,
|
|
13709
|
+
exitDialog
|
|
13710
|
+
]
|
|
13149
13711
|
}
|
|
13150
13712
|
);
|
|
13151
13713
|
}
|
|
13152
|
-
return
|
|
13714
|
+
return exitDialog ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
13715
|
+
headerEl,
|
|
13716
|
+
exitDialog
|
|
13717
|
+
] }) : headerEl;
|
|
13153
13718
|
});
|
|
13154
13719
|
function MobileHeaderMenu({ items, type = "tint", onItemClick, className }) {
|
|
13155
13720
|
return /* @__PURE__ */ jsx("nav", { className: cn("flex flex-col", className), style: { padding: "var(--ds-space-4)" }, children: /* @__PURE__ */ jsx("div", { className: "flex flex-col", style: { gap: type === "underline" ? 0 : "var(--ds-space-1)" }, children: items.map((item, i) => /* @__PURE__ */ jsx(
|
|
@@ -13241,172 +13806,6 @@ function MobileMenuItem({
|
|
|
13241
13806
|
}
|
|
13242
13807
|
);
|
|
13243
13808
|
}
|
|
13244
|
-
var DEFAULT_BUTTON_ATTR = "data-dialog-default-button";
|
|
13245
|
-
var sizeClasses = {
|
|
13246
|
-
// round 16 (the owner's item 5): the small dialog is 448 px, not 384 — a delete confirmation with a typed field was cramped
|
|
13247
|
-
sm: "max-w-md",
|
|
13248
|
-
md: "max-w-lg",
|
|
13249
|
-
lg: "max-w-2xl",
|
|
13250
|
-
xl: "max-w-4xl",
|
|
13251
|
-
full: "max-w-[calc(100vw-2rem)]"
|
|
13252
|
-
};
|
|
13253
|
-
function Dialog({ open, onClose: onCloseProp, title, description, children, footer, variant = "default", size = "md", alert = false, container, onSubmit, dirty, onDiscard }) {
|
|
13254
|
-
const guard = useDirtyGuard(dirty, onCloseProp, onDiscard);
|
|
13255
|
-
const onClose = guard.requestClose;
|
|
13256
|
-
const titleId = useId();
|
|
13257
|
-
const descriptionId = useId();
|
|
13258
|
-
const isMobile = useBreakpoint("sm");
|
|
13259
|
-
const overlayRef = useRef(null);
|
|
13260
|
-
const dialogRef = useRef(null);
|
|
13261
|
-
const opener = useRef(null);
|
|
13262
|
-
const defaultButtonRef = useRef(null);
|
|
13263
|
-
const onCloseRef = useLatest(onClose);
|
|
13264
|
-
const onSubmitRef = useLatest(onSubmit);
|
|
13265
|
-
const isTopLayer = useOverlayLayer(open);
|
|
13266
|
-
useFocusTrap(dialogRef, open, isTopLayer);
|
|
13267
|
-
const before = useFocusBeforeOpen(open);
|
|
13268
|
-
useEffect(() => {
|
|
13269
|
-
if (!open) return;
|
|
13270
|
-
const active = before.current;
|
|
13271
|
-
opener.current = active instanceof HTMLElement && active !== document.body && active.isConnected ? rememberFocus(active) : null;
|
|
13272
|
-
}, [open, before]);
|
|
13273
|
-
useEffect(() => {
|
|
13274
|
-
if (!open) return;
|
|
13275
|
-
requestAnimationFrame(() => {
|
|
13276
|
-
focusInitial(dialogRef.current, { destructive: variant === "destructive" });
|
|
13277
|
-
});
|
|
13278
|
-
}, [open, variant]);
|
|
13279
|
-
useEffect(() => {
|
|
13280
|
-
if (!open) return;
|
|
13281
|
-
const handler = (e) => {
|
|
13282
|
-
if (e.key === "Escape" && !alert && isTopLayer()) onCloseRef.current();
|
|
13283
|
-
};
|
|
13284
|
-
document.addEventListener("keydown", handler);
|
|
13285
|
-
return () => {
|
|
13286
|
-
document.removeEventListener("keydown", handler);
|
|
13287
|
-
};
|
|
13288
|
-
}, [open, alert, onCloseRef, isTopLayer]);
|
|
13289
|
-
useEffect(() => {
|
|
13290
|
-
if (!open) return;
|
|
13291
|
-
lockBodyScroll();
|
|
13292
|
-
return () => {
|
|
13293
|
-
unlockBodyScroll();
|
|
13294
|
-
const r = opener.current;
|
|
13295
|
-
opener.current = null;
|
|
13296
|
-
const active = document.activeElement;
|
|
13297
|
-
if (!active || active === document.body || !active.isConnected) r?.restore();
|
|
13298
|
-
};
|
|
13299
|
-
}, [open]);
|
|
13300
|
-
if (!open) return null;
|
|
13301
|
-
return createPortal(
|
|
13302
|
-
/* @__PURE__ */ jsxs(
|
|
13303
|
-
"div",
|
|
13304
|
-
{
|
|
13305
|
-
ref: overlayRef,
|
|
13306
|
-
className: "fixed inset-0 z-[var(--ds-z-modal)] flex items-center justify-center p-ds-4",
|
|
13307
|
-
children: [
|
|
13308
|
-
/* @__PURE__ */ jsx(
|
|
13309
|
-
"div",
|
|
13310
|
-
{
|
|
13311
|
-
className: "fixed inset-0 bg-black/50 [backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))] [-webkit-backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))]",
|
|
13312
|
-
onClick: alert ? void 0 : onClose,
|
|
13313
|
-
"aria-hidden": "true"
|
|
13314
|
-
}
|
|
13315
|
-
),
|
|
13316
|
-
/* @__PURE__ */ jsxs(
|
|
13317
|
-
"form",
|
|
13318
|
-
{
|
|
13319
|
-
onSubmit: (e) => {
|
|
13320
|
-
e.preventDefault();
|
|
13321
|
-
if (variant === "destructive") return;
|
|
13322
|
-
const submitter = e.nativeEvent.submitter;
|
|
13323
|
-
const implicit = !submitter || submitter === defaultButtonRef.current;
|
|
13324
|
-
if (!implicit && submitter.getAttribute("type") !== "submit") return;
|
|
13325
|
-
if (implicit) {
|
|
13326
|
-
const explicit = e.currentTarget.querySelector(`button[type="submit"]:not([${DEFAULT_BUTTON_ATTR}])`);
|
|
13327
|
-
if (explicit?.disabled) return;
|
|
13328
|
-
}
|
|
13329
|
-
onSubmitRef.current?.();
|
|
13330
|
-
},
|
|
13331
|
-
className: "contents",
|
|
13332
|
-
children: [
|
|
13333
|
-
/* @__PURE__ */ jsx(
|
|
13334
|
-
"button",
|
|
13335
|
-
{
|
|
13336
|
-
ref: defaultButtonRef,
|
|
13337
|
-
type: "submit",
|
|
13338
|
-
tabIndex: -1,
|
|
13339
|
-
"aria-hidden": "true",
|
|
13340
|
-
className: "sr-only",
|
|
13341
|
-
...{ [DEFAULT_BUTTON_ATTR]: "" }
|
|
13342
|
-
}
|
|
13343
|
-
),
|
|
13344
|
-
/* @__PURE__ */ jsxs(
|
|
13345
|
-
"div",
|
|
13346
|
-
{
|
|
13347
|
-
ref: dialogRef,
|
|
13348
|
-
role: alert ? "alertdialog" : "dialog",
|
|
13349
|
-
"aria-modal": "true",
|
|
13350
|
-
"data-gs": "dialog",
|
|
13351
|
-
"aria-labelledby": titleId,
|
|
13352
|
-
"aria-describedby": description ? descriptionId : void 0,
|
|
13353
|
-
style: { containerType: "inline-size" },
|
|
13354
|
-
className: cn(
|
|
13355
|
-
"relative z-10 w-full",
|
|
13356
|
-
isMobile ? "max-w-none h-full" : sizeClasses[size],
|
|
13357
|
-
"bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
|
|
13358
|
-
GLASS_OVERLAY,
|
|
13359
|
-
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
13360
|
-
isMobile ? "rounded-none" : "rounded-[var(--ds-radius-xl)]",
|
|
13361
|
-
"overflow-hidden",
|
|
13362
|
-
"animate-in fade-in-0 zoom-in-95"
|
|
13363
|
-
),
|
|
13364
|
-
children: [
|
|
13365
|
-
/* @__PURE__ */ jsx(
|
|
13366
|
-
"button",
|
|
13367
|
-
{
|
|
13368
|
-
type: "button",
|
|
13369
|
-
onClick: onClose,
|
|
13370
|
-
...{ [OVERLAY_CLOSE_ATTR]: "" },
|
|
13371
|
-
className: "absolute right-4 top-4 text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
|
|
13372
|
-
"aria-label": "Close",
|
|
13373
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
|
|
13374
|
-
}
|
|
13375
|
-
),
|
|
13376
|
-
/* @__PURE__ */ jsx("div", { className: "p-ds-6", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-ds-3", children: [
|
|
13377
|
-
variant === "destructive" && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center shrink-0 w-10 h-10 rounded-[var(--ds-radius-full)] bg-[var(--ds-status-error-bg)]", children: /* @__PURE__ */ jsx(Icon, { name: "warning", size: 20, className: "text-[var(--ds-status-error)]" }) }),
|
|
13378
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
13379
|
-
/* @__PURE__ */ jsx(
|
|
13380
|
-
"h2",
|
|
13381
|
-
{
|
|
13382
|
-
id: titleId,
|
|
13383
|
-
className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] leading-none tracking-tight",
|
|
13384
|
-
children: title
|
|
13385
|
-
}
|
|
13386
|
-
),
|
|
13387
|
-
description && /* @__PURE__ */ jsx("p", { id: descriptionId, className: "mt-ds-2 text-sm text-[var(--ds-text-muted)]", children: description }),
|
|
13388
|
-
children && /* @__PURE__ */ jsx("div", { className: "mt-ds-4", children: /* @__PURE__ */ jsx(OverlayCloseCtx, { value: onClose, children }) })
|
|
13389
|
-
] })
|
|
13390
|
-
] }) }),
|
|
13391
|
-
/* @__PURE__ */ jsx(DiscardConfirm, { open: guard.confirming, onKeep: guard.keep, onDiscard: guard.discard }),
|
|
13392
|
-
footer && /* @__PURE__ */ jsx("div", { className: cn(
|
|
13393
|
-
"flex justify-end gap-ds-2 p-ds-4",
|
|
13394
|
-
"border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
13395
|
-
"bg-[var(--ds-bg-muted)]",
|
|
13396
|
-
"rounded-b-[var(--ds-radius-xl)]"
|
|
13397
|
-
), children: footer })
|
|
13398
|
-
]
|
|
13399
|
-
}
|
|
13400
|
-
)
|
|
13401
|
-
]
|
|
13402
|
-
}
|
|
13403
|
-
)
|
|
13404
|
-
]
|
|
13405
|
-
}
|
|
13406
|
-
),
|
|
13407
|
-
container ?? document.body
|
|
13408
|
-
);
|
|
13409
|
-
}
|
|
13410
13809
|
function CommandPalette({ open, onOpenChange, commands, placeholder = "Type a command\u2026", loading = false, container }) {
|
|
13411
13810
|
const [query, setQuery] = useState("");
|
|
13412
13811
|
const [selectedIdx, setSelectedIdx] = useState(0);
|
|
@@ -13443,14 +13842,17 @@ function CommandPalette({ open, onOpenChange, commands, placeholder = "Type a co
|
|
|
13443
13842
|
const isTopLayer = useOverlayLayer(open);
|
|
13444
13843
|
useFocusTrap(dialogRef, open, isTopLayer);
|
|
13445
13844
|
const returnFocus = useReturnFocus(open, dialogRef);
|
|
13845
|
+
const onOpenChangeRef = useLatest(onOpenChange);
|
|
13446
13846
|
useEffect(() => {
|
|
13447
13847
|
if (!open) return;
|
|
13448
13848
|
const handler = (e) => {
|
|
13449
|
-
if (e.key
|
|
13849
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
13850
|
+
e.preventDefault();
|
|
13851
|
+
onOpenChangeRef.current(false);
|
|
13450
13852
|
};
|
|
13451
13853
|
document.addEventListener("keydown", handler);
|
|
13452
13854
|
return () => document.removeEventListener("keydown", handler);
|
|
13453
|
-
}, [open,
|
|
13855
|
+
}, [open, onOpenChangeRef, isTopLayer]);
|
|
13454
13856
|
const handleSelect = useCallback(
|
|
13455
13857
|
(cmd) => {
|
|
13456
13858
|
returnFocus();
|
|
@@ -13664,7 +14066,9 @@ function ContextMenu({ items, children, className, ref, container }) {
|
|
|
13664
14066
|
};
|
|
13665
14067
|
const keyHandler = (e) => {
|
|
13666
14068
|
if (e.key === "Escape") {
|
|
13667
|
-
if (isTopLayer())
|
|
14069
|
+
if (e.defaultPrevented || !isTopLayer()) return;
|
|
14070
|
+
e.preventDefault();
|
|
14071
|
+
setOpen(false);
|
|
13668
14072
|
return;
|
|
13669
14073
|
}
|
|
13670
14074
|
const actionable = items.filter((it) => !it.separator && !it.disabled);
|
|
@@ -13801,10 +14205,11 @@ function NotificationCenter({
|
|
|
13801
14205
|
const [internalFilter, setInternalFilter] = useState("all");
|
|
13802
14206
|
const isControlled = controlledOpen !== void 0;
|
|
13803
14207
|
const open = isControlled ? controlledOpen : internalOpen;
|
|
14208
|
+
const onOpenChangeRef = useLatest(onOpenChange);
|
|
13804
14209
|
const setOpen = useCallback((v) => {
|
|
13805
|
-
if (isControlled)
|
|
14210
|
+
if (isControlled) onOpenChangeRef.current?.(v);
|
|
13806
14211
|
else setInternalOpen(v);
|
|
13807
|
-
}, [isControlled,
|
|
14212
|
+
}, [isControlled, onOpenChangeRef]);
|
|
13808
14213
|
const triggerRef = useRef(null);
|
|
13809
14214
|
const panelRef = useRef(null);
|
|
13810
14215
|
const pos = usePosition(triggerRef, panelRef, open, { side: "bottom", align: "end", offset: 8, flip: true });
|
|
@@ -13821,10 +14226,10 @@ function NotificationCenter({
|
|
|
13821
14226
|
useEffect(() => {
|
|
13822
14227
|
if (!open) return;
|
|
13823
14228
|
const onKey = (e) => {
|
|
13824
|
-
if (e.key
|
|
13825
|
-
|
|
13826
|
-
|
|
13827
|
-
|
|
14229
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
14230
|
+
e.preventDefault();
|
|
14231
|
+
returnFocus();
|
|
14232
|
+
setOpen(false);
|
|
13828
14233
|
};
|
|
13829
14234
|
const onClick = (e) => {
|
|
13830
14235
|
const target = e.target;
|
|
@@ -13946,6 +14351,8 @@ function NotificationCenter({
|
|
|
13946
14351
|
ref: triggerRef,
|
|
13947
14352
|
onClick: () => setOpen(!open),
|
|
13948
14353
|
"aria-label": `Notifications${unreadCount ? ` (${unreadCount} unread)` : ""}`,
|
|
14354
|
+
"aria-haspopup": "dialog",
|
|
14355
|
+
"aria-expanded": open,
|
|
13949
14356
|
className: cn(
|
|
13950
14357
|
"relative flex items-center justify-center w-9 h-9",
|
|
13951
14358
|
"rounded-[var(--ds-radius-md)]",
|
|
@@ -13964,6 +14371,8 @@ function NotificationCenter({
|
|
|
13964
14371
|
"div",
|
|
13965
14372
|
{
|
|
13966
14373
|
ref: panelRef,
|
|
14374
|
+
role: "dialog",
|
|
14375
|
+
"aria-label": "Notifications",
|
|
13967
14376
|
className: cn(
|
|
13968
14377
|
"fixed z-[var(--ds-z-popover)] w-[360px] max-h-[480px] flex flex-col",
|
|
13969
14378
|
"bg-[var(--ds-bg-surface-elevated)]",
|
|
@@ -14119,17 +14528,21 @@ function Tour({ steps, open, onClose, onComplete, container }) {
|
|
|
14119
14528
|
const raf = requestAnimationFrame(() => nextRef.current?.focus());
|
|
14120
14529
|
return () => cancelAnimationFrame(raf);
|
|
14121
14530
|
}, [open, current]);
|
|
14531
|
+
const onCloseRef = useLatest(onClose);
|
|
14532
|
+
const handleNextRef = useLatest(handleNext);
|
|
14533
|
+
const handlePrevRef = useLatest(handlePrev);
|
|
14122
14534
|
useEffect(() => {
|
|
14123
14535
|
if (!open) return;
|
|
14124
14536
|
const onKey = (e) => {
|
|
14125
|
-
if (!isTopLayer()) return;
|
|
14126
|
-
|
|
14127
|
-
|
|
14128
|
-
|
|
14537
|
+
if (e.defaultPrevented || !isTopLayer()) return;
|
|
14538
|
+
const act = e.key === "Escape" ? onCloseRef.current : e.key === "ArrowRight" ? handleNextRef.current : e.key === "ArrowLeft" ? handlePrevRef.current : null;
|
|
14539
|
+
if (!act) return;
|
|
14540
|
+
e.preventDefault();
|
|
14541
|
+
act();
|
|
14129
14542
|
};
|
|
14130
14543
|
document.addEventListener("keydown", onKey);
|
|
14131
14544
|
return () => document.removeEventListener("keydown", onKey);
|
|
14132
|
-
}, [open,
|
|
14545
|
+
}, [open, isTopLayer, onCloseRef, handleNextRef, handlePrevRef]);
|
|
14133
14546
|
if (!open || !step) return null;
|
|
14134
14547
|
const padding = 8;
|
|
14135
14548
|
const spotlightRadius = 8;
|
|
@@ -14593,7 +15006,7 @@ function useDestructiveAction(options) {
|
|
|
14593
15006
|
}
|
|
14594
15007
|
setOpen(true);
|
|
14595
15008
|
};
|
|
14596
|
-
const
|
|
15009
|
+
const matches2 = !typedRequired || typed.trim().toLowerCase() === typedText.trim().toLowerCase();
|
|
14597
15010
|
const element = open ? /* @__PURE__ */ jsx(
|
|
14598
15011
|
Dialog,
|
|
14599
15012
|
{
|
|
@@ -14604,7 +15017,7 @@ function useDestructiveAction(options) {
|
|
|
14604
15017
|
variant: "destructive",
|
|
14605
15018
|
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14606
15019
|
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: close, disabled: busy, children: "Cancel" }),
|
|
14607
|
-
/* @__PURE__ */ jsx(Button, { variant: "destructive", onClick: () => void confirm(), disabled: !
|
|
15020
|
+
/* @__PURE__ */ jsx(Button, { variant: "destructive", onClick: () => void confirm(), disabled: !matches2 || busy, loading: busy, children: label })
|
|
14608
15021
|
] }),
|
|
14609
15022
|
children: typedRequired && /* @__PURE__ */ jsx(Field, { label: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14610
15023
|
"Type ",
|