gridsmith-ui 0.22.0 → 0.24.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/Breadcrumbs-CGS8GKl-.d.ts +33 -0
- package/dist/chat.js +1 -1
- package/dist/chunk-2PWGJ4PK.js +45 -0
- package/dist/chunk-2PWGJ4PK.js.map +1 -0
- package/dist/chunk-2YSEME33.js +118 -0
- package/dist/chunk-2YSEME33.js.map +1 -0
- package/dist/chunk-3BRQRKDO.js +72 -0
- package/dist/chunk-3BRQRKDO.js.map +1 -0
- package/dist/{chunk-2RV23OBK.js → chunk-6XAU44U4.js} +25 -10
- package/dist/chunk-6XAU44U4.js.map +1 -0
- package/dist/{chunk-RT7RYGC3.js → chunk-JXANCXK6.js} +4 -39
- package/dist/chunk-JXANCXK6.js.map +1 -0
- package/dist/{chunk-AAYCQXZQ.js → chunk-MV7JXWXK.js} +630 -411
- package/dist/chunk-MV7JXWXK.js.map +1 -0
- package/dist/{chunk-EYMGLK4M.js → chunk-SVP2IG4S.js} +2 -2
- package/dist/{chunk-EYMGLK4M.js.map → chunk-SVP2IG4S.js.map} +1 -1
- package/dist/chunk-WOVYHFUD.js +50 -0
- package/dist/chunk-WOVYHFUD.js.map +1 -0
- package/dist/chunk-XVB55M3N.js +42 -0
- package/dist/chunk-XVB55M3N.js.map +1 -0
- package/dist/data-grid.js +5 -3
- package/dist/data-grid.js.map +1 -1
- package/dist/editor.js +11 -3
- package/dist/editor.js.map +1 -1
- package/dist/index.d.ts +227 -45
- package/dist/index.js +843 -586
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +23 -4
- package/dist/kanban.js.map +1 -1
- package/dist/resizable.d.ts +17 -2
- package/dist/resizable.js +102 -24
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +19 -4
- package/dist/tokens.css +20 -3
- package/dist/virtualized.js +5 -2
- package/dist/virtualized.js.map +1 -1
- package/dist-static/tokens.css +20 -3
- package/package.json +1 -1
- package/dist/chunk-2RV23OBK.js.map +0 -1
- package/dist/chunk-AAYCQXZQ.js.map +0 -1
- package/dist/chunk-RG4KUCRS.js +0 -9
- package/dist/chunk-RG4KUCRS.js.map +0 -1
- package/dist/chunk-RT7RYGC3.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
import { useAppShell, REACT_VERSION_PROBLEM, useOverlayMark, useDirtyGuard, OverlayMarkScope, OverlayCloseCtx, DiscardConfirm, OVERLAY_ROOT_ATTR, OverlayMarkCtx,
|
|
2
|
-
export { AppShell,
|
|
1
|
+
import { useAppShell, REACT_VERSION_PROBLEM, Breadcrumbs, useCrumbFollow, crumbGoes, useOverlayMark, useDirtyGuard, useScrollbarInset, DrawerFooterCtx, OverlayMarkScope, OverlayCloseCtx, insetLessScrollbar, DiscardConfirm, OVERLAY_ROOT_ATTR, OverlayMarkCtx, useCompact, useElementWidth, DrawerPanel, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, defaultMaxWidth } from './chunk-MV7JXWXK.js';
|
|
2
|
+
export { AppShell, Breadcrumbs, Drawer, SkipLink, useAppShell, useUnsavedChanges } from './chunk-MV7JXWXK.js';
|
|
3
3
|
import { Skeleton, TITLE_TEXT } from './chunk-NCIZQYXQ.js';
|
|
4
4
|
export { Skeleton } from './chunk-NCIZQYXQ.js';
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import { useScrollEdges, EDGE_FADE } from './chunk-3BRQRKDO.js';
|
|
6
|
+
import { Link } from './chunk-SVP2IG4S.js';
|
|
7
|
+
export { CodeBlock, Divider, Link } from './chunk-SVP2IG4S.js';
|
|
8
|
+
import { useFillHeight, FillContext } from './chunk-2YSEME33.js';
|
|
7
9
|
import { Badge } from './chunk-SBTBMAIU.js';
|
|
8
10
|
export { Badge } from './chunk-SBTBMAIU.js';
|
|
9
11
|
import { inferColumnKinds, useCardsSwitch, CARDS_BELOW, kindOfRenderedText, CardValue } from './chunk-IVCVNAXG.js';
|
|
10
|
-
import { useWholeListCheck, pagerPart, Pagination, Dropdown, useFieldControl, useField, warnOnce, Label, InlineFieldError, AddAnotherRowCtx,
|
|
11
|
-
export { Dropdown, Field, InlineFieldError, Input, Label, NumberInput, Pagination, Popover, Textarea, Toggle, usePagination } from './chunk-
|
|
12
|
-
import { SplitPaneCtx, TableCardCtx } from './chunk-RG4KUCRS.js';
|
|
12
|
+
import { useWholeListCheck, pagerPart, Pagination, Input, CHECK_FILL, Dropdown, FilterRowContext, SWITCH_KNOB_ON, SWITCH_KNOB_OFF, SWITCH_KNOB_MOTION, SWITCH_TRACK_ON, SWITCH_TRACK_OFF, useFieldControl, useField, warnOnce, Label, InlineFieldError, AddAnotherRowCtx, Field } from './chunk-6XAU44U4.js';
|
|
13
|
+
export { Dropdown, Field, InlineFieldError, Input, Label, NumberInput, Pagination, Popover, Textarea, Toggle, usePagination } from './chunk-6XAU44U4.js';
|
|
13
14
|
import { Button, ControlSizeContext, triggerType, Spinner, useShellPreferences, preferenceActionKey } from './chunk-7TOJ4G7S.js';
|
|
14
15
|
export { Button, ButtonSizeContext, ControlSizeContext, PreferencesContext, Spinner, preferenceActionKey, usePreferences } from './chunk-7TOJ4G7S.js';
|
|
15
16
|
import { useBreakpoint, readBreakpointPx } from './chunk-CRQ6KCRD.js';
|
|
16
17
|
export { BreakpointWidthProvider, useBreakpoint } from './chunk-CRQ6KCRD.js';
|
|
17
|
-
import {
|
|
18
|
-
export { useFormContext
|
|
18
|
+
import { FormChangeCtx, useReportedChange, useOptionalFormContext, FormCtx } from './chunk-XVB55M3N.js';
|
|
19
|
+
export { useFormContext } from './chunk-XVB55M3N.js';
|
|
20
|
+
import { CardSurfaceCtx, useScrollsInside, SplitPaneCtx, PageActionsCtx, SurfaceBoundary, useFramesItself, TableCardCtx } from './chunk-2PWGJ4PK.js';
|
|
21
|
+
import { FOCUSABLE, usePopupFocus, FIELD, ZOOM_KEYS, useOverlayLayer, useFocusTrap, useFocusBeforeOpen, rememberFocus, focusInitial, OVERLAY_CLOSE_ATTR, rovingTabStop, useGridKeyboard, focusAfterRemoval, useNonModalDialog, useReturnFocus, useCloseOnFocusOut } from './chunk-JXANCXK6.js';
|
|
22
|
+
export { useGridKeyboard } from './chunk-JXANCXK6.js';
|
|
19
23
|
import { useTextOverflow, Tooltip, usePosition } from './chunk-CXMV7SXJ.js';
|
|
20
24
|
export { Tooltip, useTextOverflow } from './chunk-CXMV7SXJ.js';
|
|
21
25
|
import { mergeRefs, Slot } from './chunk-7Q46JXSK.js';
|
|
@@ -508,7 +512,7 @@ function Checkbox({ checked, onChange: onChangeProp, label, size = "md", disable
|
|
|
508
512
|
"border-[2px]",
|
|
509
513
|
"transition-all",
|
|
510
514
|
"peer-focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
511
|
-
filled ?
|
|
515
|
+
filled ? cn(CHECK_FILL, "border-[var(--ds-check-border)]") : "bg-[var(--ds-input-bg)] border-[var(--ds-input-border)]",
|
|
512
516
|
disabled && "pointer-events-none"
|
|
513
517
|
),
|
|
514
518
|
children: /* @__PURE__ */ jsx(
|
|
@@ -629,7 +633,8 @@ function RadioGroup({ value, onChange: onChangeProp, options, orientation = "ver
|
|
|
629
633
|
selected && "border-[var(--ds-check-border)]",
|
|
630
634
|
"group-focus-visible:shadow-[var(--ds-shadow-focus)]"
|
|
631
635
|
),
|
|
632
|
-
children: selected &&
|
|
636
|
+
children: selected && // Sprint 25.14 A20: the checked colour, as a checkbox's fill (a preset whose accent falls short of 3:1 sets it)
|
|
637
|
+
/* @__PURE__ */ jsx("span", { className: cn("h-2.5 w-2.5 rounded-[var(--ds-radius-full)]", CHECK_FILL) })
|
|
633
638
|
}
|
|
634
639
|
),
|
|
635
640
|
/* @__PURE__ */ jsx("span", { className: "text-sm text-[var(--ds-text-primary)]", children: option.label })
|
|
@@ -1880,9 +1885,9 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
1880
1885
|
useEffect(() => {
|
|
1881
1886
|
const owner = inputRef.current?.form;
|
|
1882
1887
|
if (!owner) return;
|
|
1883
|
-
const
|
|
1884
|
-
owner.addEventListener("submit",
|
|
1885
|
-
return () => owner.removeEventListener("submit",
|
|
1888
|
+
const clear2 = () => setRejected(null);
|
|
1889
|
+
owner.addEventListener("submit", clear2);
|
|
1890
|
+
return () => owner.removeEventListener("submit", clear2);
|
|
1886
1891
|
}, []);
|
|
1887
1892
|
const invalid = error || rejected != null || !!waiting;
|
|
1888
1893
|
const describedBy = [constraints ? constraintsId : null, field?.describedBy, rejected ? rejectedId : null, waiting ? waitingId : null].filter(Boolean).join(" ") || void 0;
|
|
@@ -1991,7 +1996,7 @@ function FileUpload({ onFiles, files, upload, onCancel, onRetry, onRemove, accep
|
|
|
1991
1996
|
// The real file input is visually hidden inside; Tab lands on it and
|
|
1992
1997
|
// Enter/Space open the picker natively, so the zone shows its focus.
|
|
1993
1998
|
invalid ? ERROR_HAS_FOCUS_RING : HAS_FOCUS_RING,
|
|
1994
|
-
dragOver ? `${ACTIVE_RING} bg-[var(--ds-accent-whisper)]` : invalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-border
|
|
1999
|
+
dragOver ? `${ACTIVE_RING} bg-[var(--ds-accent-whisper)]` : invalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)] hover:border-[var(--ds-accent-primary)] hover:bg-[var(--ds-accent-whisper)]"
|
|
1995
2000
|
),
|
|
1996
2001
|
style: { padding: "var(--ds-space-8) var(--ds-space-4)" },
|
|
1997
2002
|
children: [
|
|
@@ -2165,7 +2170,7 @@ function SliderRange({
|
|
|
2165
2170
|
!trackStyle && /* @__PURE__ */ jsx(
|
|
2166
2171
|
"div",
|
|
2167
2172
|
{
|
|
2168
|
-
className: "absolute h-1.5 rounded-[var(--ds-radius-full)]
|
|
2173
|
+
className: cn("absolute h-1.5 rounded-[var(--ds-radius-full)]", CHECK_FILL),
|
|
2169
2174
|
style: {
|
|
2170
2175
|
left: `${isRange ? pct(low) : 0}%`,
|
|
2171
2176
|
width: `${isRange ? pct(high) - pct(low) : pct(low)}%`
|
|
@@ -2189,7 +2194,7 @@ function SliderRange({
|
|
|
2189
2194
|
className: cn(
|
|
2190
2195
|
"absolute w-ds-4 h-ds-4 -translate-x-1/2 rounded-[var(--ds-radius-full)]",
|
|
2191
2196
|
"bg-[var(--ds-bg-surface)] border-2",
|
|
2192
|
-
error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-
|
|
2197
|
+
error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-check-border)]",
|
|
2193
2198
|
"shadow-[var(--ds-shadow-sm)]",
|
|
2194
2199
|
"transition-[shadow,transform] duration-200 ease-out",
|
|
2195
2200
|
"focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
@@ -2215,7 +2220,7 @@ function SliderRange({
|
|
|
2215
2220
|
className: cn(
|
|
2216
2221
|
"absolute w-ds-4 h-ds-4 -translate-x-1/2 rounded-[var(--ds-radius-full)]",
|
|
2217
2222
|
"bg-[var(--ds-bg-surface)] border-2",
|
|
2218
|
-
error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-
|
|
2223
|
+
error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-check-border)]",
|
|
2219
2224
|
"shadow-[var(--ds-shadow-sm)]",
|
|
2220
2225
|
"transition-[shadow,transform] duration-200 ease-out",
|
|
2221
2226
|
"focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
@@ -2988,7 +2993,7 @@ function PinInput({
|
|
|
2988
2993
|
role: "group",
|
|
2989
2994
|
"aria-label": "PIN input",
|
|
2990
2995
|
"aria-invalid": error || void 0,
|
|
2991
|
-
className: cn("inline-flex items-center gap-ds-2", className),
|
|
2996
|
+
className: cn("inline-flex w-fit items-center gap-ds-2", className),
|
|
2992
2997
|
children: digits.map((digit, i) => /* @__PURE__ */ jsx(
|
|
2993
2998
|
"input",
|
|
2994
2999
|
{
|
|
@@ -3153,7 +3158,9 @@ function Rating({
|
|
|
3153
3158
|
"aria-required": readOnly ? void 0 : control.required || void 0,
|
|
3154
3159
|
onKeyDown: readOnly ? void 0 : handleKeyDown,
|
|
3155
3160
|
className: cn(
|
|
3156
|
-
|
|
3161
|
+
// Sprint 25.14 A21: its own width in a Field's column, not the field's; w-fit, not self-start, so a row or a
|
|
3162
|
+
// centred column still aligns it (the review of 30 September)
|
|
3163
|
+
"inline-flex w-fit items-center gap-ds-0.5",
|
|
3157
3164
|
error && "border-[length:var(--ds-border-width)] border-[var(--ds-status-error)] rounded-[var(--ds-radius-sm)] p-ds-0.5",
|
|
3158
3165
|
className
|
|
3159
3166
|
),
|
|
@@ -3583,7 +3590,7 @@ function focusTarget(el) {
|
|
|
3583
3590
|
if (el.tabIndex >= 0 || /^(?:INPUT|SELECT|TEXTAREA|BUTTON)$/.test(el.tagName)) return el;
|
|
3584
3591
|
return el.querySelector("[aria-checked='true'], [aria-selected='true']:not([tabindex='-1'])") ?? el.querySelector("input, select, textarea, button, [tabindex]:not([tabindex='-1'])") ?? el;
|
|
3585
3592
|
}
|
|
3586
|
-
function FormWrapper({ onSubmit, validationMode: validationModeProp, children, actions: actionsProp, actionsAlign: actionsAlignProp, onCancel, cancelLabel = "Cancel", focusFirstError = true, errorSummary = true, className, ref }) {
|
|
3593
|
+
function FormWrapper({ onSubmit, validationMode: validationModeProp, children, actions: actionsProp, actionsAlign: actionsAlignProp, onCancel, cancelLabel = "Cancel", focusFirstError = true, errorSummary = true, fullWidth = false, className, ref }) {
|
|
3587
3594
|
const preferences = useShellPreferences();
|
|
3588
3595
|
const validationMode = validationModeProp ?? preferences.validationTiming ?? "onSubmit";
|
|
3589
3596
|
const actionsAlign = actionsAlignProp ?? preferences.formActions?.align ?? "end";
|
|
@@ -3750,7 +3757,7 @@ function FormWrapper({ onSubmit, validationMode: validationModeProp, children, a
|
|
|
3750
3757
|
f.message
|
|
3751
3758
|
] }, f.id || f.label)) }) }) : null;
|
|
3752
3759
|
const actionsNode = actions && !drawerFooter ? /* @__PURE__ */ jsx("div", { "data-form-actions": "", className: cn("flex flex-wrap items-center gap-ds-2 pt-ds-2", actionsAlign === "end" ? "justify-end" : "justify-start"), children: actions }) : null;
|
|
3753
|
-
return /* @__PURE__ */ jsx(FormCtx.Provider, { value: { errors, setError, clearErrors, validationMode, submitted, register }, children: /* @__PURE__ */ jsx(FormChangeCtx.Provider, { value: reportChange, children: /* @__PURE__ */ jsxs("form", { ref: setRefs, id: drawerFooter ? formId : void 0, onSubmit: handleSubmit, onFocusCapture: userActed, onInputCapture: userActed, className: cn("flex flex-col gap-ds-5 max-w-[var(--ds-form-max,
|
|
3760
|
+
return /* @__PURE__ */ jsx(FormCtx.Provider, { value: { errors, setError, clearErrors, validationMode, submitted, register }, children: /* @__PURE__ */ jsx(FormChangeCtx.Provider, { value: reportChange, children: /* @__PURE__ */ jsxs("form", { ref: setRefs, id: drawerFooter ? formId : void 0, onSubmit: handleSubmit, onFocusCapture: userActed, onInputCapture: userActed, className: cn("flex flex-col gap-ds-5 max-w-[var(--ds-form-max,calc(var(--ds-bp-md)_-_2*var(--ds-space-6)))]", className), style: fullWidth ? { "--ds-form-max": "none" } : void 0, noValidate: true, children: [
|
|
3754
3761
|
summaryNode && /* @__PURE__ */ jsx("div", { ref: summaryRef, "data-form-error-summary": "", tabIndex: -1, className: "rounded-[var(--ds-radius-md)] outline-none focus-visible:shadow-[var(--ds-shadow-focus)]", children: summaryNode }),
|
|
3755
3762
|
children,
|
|
3756
3763
|
actionsNode
|
|
@@ -4373,7 +4380,6 @@ function holdsHeader(children) {
|
|
|
4373
4380
|
}
|
|
4374
4381
|
var CardActionCtx = createContext(null);
|
|
4375
4382
|
var CARD_ACTION_ATTR = "data-card-action";
|
|
4376
|
-
var CardSurfaceCtx = createContext(false);
|
|
4377
4383
|
var variantStyles3 = {
|
|
4378
4384
|
default: `bg-[var(--ds-bg-surface)] border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] ${GLASS_SURFACE}`,
|
|
4379
4385
|
featured: [
|
|
@@ -4409,7 +4415,8 @@ function RadioIndicator({ checked, disabled }) {
|
|
|
4409
4415
|
{
|
|
4410
4416
|
className: cn(
|
|
4411
4417
|
"h-2.5 w-2.5 rounded-[var(--ds-radius-full)] transition-transform duration-[var(--ds-transition-speed)]",
|
|
4412
|
-
|
|
4418
|
+
// Sprint 25.14 A20: the radio's selected dot (lib/control-looks.ts)
|
|
4419
|
+
checked ? cn(CHECK_FILL, "scale-100") : "scale-0"
|
|
4413
4420
|
)
|
|
4414
4421
|
}
|
|
4415
4422
|
)
|
|
@@ -4427,7 +4434,8 @@ function CheckboxIndicator({ checked, indeterminate, disabled }) {
|
|
|
4427
4434
|
"rounded-[calc(var(--ds-radius-sm)*0.6)]",
|
|
4428
4435
|
"border-[2px] transition-all duration-[var(--ds-transition-speed)]",
|
|
4429
4436
|
disabled && "opacity-disabled",
|
|
4430
|
-
|
|
4437
|
+
// Sprint 25.14 A20: the checkbox's checked fill (lib/control-looks.ts)
|
|
4438
|
+
filled ? cn(CHECK_FILL, "border-[var(--ds-check-border)]") : "bg-[var(--ds-input-bg)] border-[var(--ds-input-border)]"
|
|
4431
4439
|
),
|
|
4432
4440
|
children: /* @__PURE__ */ jsx(
|
|
4433
4441
|
"svg",
|
|
@@ -4455,13 +4463,14 @@ function ToggleIndicator({ checked, disabled }) {
|
|
|
4455
4463
|
"border-[length:var(--ds-border-width)] rounded-[var(--ds-radius-full)]",
|
|
4456
4464
|
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
4457
4465
|
disabled && "opacity-disabled",
|
|
4458
|
-
|
|
4466
|
+
// Sprint 25.14 A20: the Toggle's track and knob, on and off (lib/control-looks.ts)
|
|
4467
|
+
checked ? SWITCH_TRACK_ON : SWITCH_TRACK_OFF
|
|
4459
4468
|
),
|
|
4460
4469
|
style: { width: 44, height: 24 },
|
|
4461
4470
|
children: /* @__PURE__ */ jsx(
|
|
4462
4471
|
"span",
|
|
4463
4472
|
{
|
|
4464
|
-
className: "pointer-events-none inline-block shrink-0
|
|
4473
|
+
className: cn("pointer-events-none inline-block shrink-0 rounded-[var(--ds-radius-full)]", checked ? SWITCH_KNOB_ON : SWITCH_KNOB_OFF, SWITCH_KNOB_MOTION),
|
|
4465
4474
|
style: {
|
|
4466
4475
|
width: 16,
|
|
4467
4476
|
height: 16,
|
|
@@ -4647,9 +4656,9 @@ var Card = forwardRef(function Card2({
|
|
|
4647
4656
|
...props,
|
|
4648
4657
|
children: [
|
|
4649
4658
|
!loading && !hasHeader && checkbox && /* @__PURE__ */ jsxs("div", { "data-card-header-row": "", className: "flex items-center gap-ds-2 px-ds-5 pt-ds-4", children: [
|
|
4650
|
-
checkbox,
|
|
4651
4659
|
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "grow" }),
|
|
4652
|
-
check && /* @__PURE__ */ jsx("span", { "data-card-selection": "", className: "shrink-0 flex", children: check })
|
|
4660
|
+
check && /* @__PURE__ */ jsx("span", { "data-card-selection": "", className: "shrink-0 flex", children: check }),
|
|
4661
|
+
checkbox
|
|
4653
4662
|
] }),
|
|
4654
4663
|
!loading && !hasHeader && !checkbox && check && /* @__PURE__ */ jsx("div", { "data-card-selection": "", className: "absolute top-ds-3 right-ds-3 z-[1] flex", children: check }),
|
|
4655
4664
|
/* @__PURE__ */ jsx(CardSurfaceCtx, { value: true, children: /* @__PURE__ */ jsx(CardActionCtx, { value: action, children: /* @__PURE__ */ jsx(CardRowCtx, { value: rowParts, children: loading ? (
|
|
@@ -4724,7 +4733,7 @@ var CardHeader = forwardRef(function CardHeader2(allProps, ref) {
|
|
|
4724
4733
|
}
|
|
4725
4734
|
) : null;
|
|
4726
4735
|
const band = (order) => cn("shrink-0 self-start flex items-center", TITLE_LINE, order);
|
|
4727
|
-
const checkbox = owns && row.checkbox ? /* @__PURE__ */ jsx("span", { className: band("order-
|
|
4736
|
+
const checkbox = owns && row.checkbox ? /* @__PURE__ */ jsx("span", { className: band("order-5"), children: row.checkbox }) : null;
|
|
4728
4737
|
const check = owns && row.check ? /* @__PURE__ */ jsx("span", { "data-card-selection": "", className: band("order-4"), children: row.check }) : null;
|
|
4729
4738
|
const menuPart = menu ? /* @__PURE__ */ jsx("span", { className: band("order-6"), children: menu }) : null;
|
|
4730
4739
|
const { lead, title, rest } = splitTitle(children);
|
|
@@ -4734,15 +4743,14 @@ var CardHeader = forwardRef(function CardHeader2(allProps, ref) {
|
|
|
4734
4743
|
const actionsSlot = "actions" in allProps ? /* @__PURE__ */ jsx("div", { "data-header-actions": "", className: "contents", children: partsOf(actions).map((item, i) => /* @__PURE__ */ jsx("span", { className: cn("flex items-center shrink-0", TITLE_LINE), children: item }, isValidElement(item) && item.key !== null ? item.key : i)) }) : null;
|
|
4735
4744
|
return /* @__PURE__ */ jsxs("div", { ref, "data-card-header": "", className: cn("flex flex-col px-ds-5 pt-ds-4 last:pb-ds-4 min-w-0", className), ...props, children: [
|
|
4736
4745
|
topLine && /* @__PURE__ */ jsxs("div", { "data-card-icon-row": iconBlock ? "" : void 0, "data-card-lead-row": iconBlock ? void 0 : "", className: cn("flex items-start gap-ds-2", iconBlock ? "mb-ds-2.5" : "mb-ds-1.5"), children: [
|
|
4737
|
-
checkbox,
|
|
4738
4746
|
topLine,
|
|
4739
4747
|
iconBlock && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "grow -ml-ds-2" }),
|
|
4740
4748
|
check,
|
|
4749
|
+
checkbox,
|
|
4741
4750
|
menuPart
|
|
4742
4751
|
] }),
|
|
4743
4752
|
iconBlock && leadBlock && /* @__PURE__ */ jsx("div", { className: "flex mb-ds-1.5", children: leadBlock }),
|
|
4744
4753
|
/* @__PURE__ */ jsxs("div", { "data-card-header-row": "", className: "flex items-start gap-ds-2 min-w-0", children: [
|
|
4745
|
-
!topLine && checkbox,
|
|
4746
4754
|
/* @__PURE__ */ jsxs("div", { "data-card-title-line": "", className: TITLE_ROW, children: [
|
|
4747
4755
|
title && /* @__PURE__ */ jsx(
|
|
4748
4756
|
"div",
|
|
@@ -4756,6 +4764,7 @@ var CardHeader = forwardRef(function CardHeader2(allProps, ref) {
|
|
|
4756
4764
|
!ownBlock && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "order-3 grow basis-0 -ml-ds-2" })
|
|
4757
4765
|
] }),
|
|
4758
4766
|
!topLine && check,
|
|
4767
|
+
!topLine && checkbox,
|
|
4759
4768
|
!topLine && menuPart
|
|
4760
4769
|
] }),
|
|
4761
4770
|
rest.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-col space-y-ds-1.5 break-words mt-ds-1.5 min-w-0", children: rest })
|
|
@@ -4842,7 +4851,7 @@ var CardFooter = forwardRef(function CardFooter2({ className, children, ...props
|
|
|
4842
4851
|
});
|
|
4843
4852
|
function TruncLabel({ children }) {
|
|
4844
4853
|
const { ref, isTruncated } = useTextOverflow({ lines: 1 });
|
|
4845
|
-
const el = /* @__PURE__ */ jsx("span", { ref, className: "text-xs font-medium text-[var(--ds-text-muted)] uppercase tracking-wider truncate min-w-0", children });
|
|
4854
|
+
const el = /* @__PURE__ */ jsx("span", { ref, className: "block text-xs font-medium text-[var(--ds-text-muted)] uppercase tracking-wider truncate min-w-0", children });
|
|
4846
4855
|
if (!isTruncated) return el;
|
|
4847
4856
|
return /* @__PURE__ */ jsx(Tooltip, { content: children, children: el });
|
|
4848
4857
|
}
|
|
@@ -4887,13 +4896,15 @@ function StatsCard({ value, label, trend, icon, layout = "card", interactive, on
|
|
|
4887
4896
|
} : void 0,
|
|
4888
4897
|
children: [
|
|
4889
4898
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-ds-2 min-w-0", children: [
|
|
4890
|
-
/* @__PURE__ */
|
|
4899
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
4900
|
+
/* @__PURE__ */ jsx(TruncLabel, { children: label }),
|
|
4901
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-ds-2 mt-ds-2 flex-wrap", children: [
|
|
4902
|
+
/* @__PURE__ */ jsx("span", { className: "font-[family-name:var(--ds-font-display)] text-2xl font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] leading-none tabular-nums", children: value }),
|
|
4903
|
+
trend && /* @__PURE__ */ jsx(TrendBadge, { trend })
|
|
4904
|
+
] })
|
|
4905
|
+
] }),
|
|
4891
4906
|
icon && /* @__PURE__ */ jsx("div", { className: "shrink-0 flex items-center justify-center w-8 h-8 rounded-[var(--ds-radius-sm)] bg-[var(--ds-bg-muted)]", children: /* @__PURE__ */ jsx(Icon, { name: icon, size: 16, className: "text-[var(--ds-text-muted)]" }) })
|
|
4892
4907
|
] }),
|
|
4893
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-ds-2 mt-ds-2 flex-wrap", children: [
|
|
4894
|
-
/* @__PURE__ */ jsx("span", { className: "font-[family-name:var(--ds-font-display)] text-2xl font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] leading-none tabular-nums", children: value }),
|
|
4895
|
-
trend && /* @__PURE__ */ jsx(TrendBadge, { trend })
|
|
4896
|
-
] }),
|
|
4897
4908
|
children && /* @__PURE__ */ jsx("div", { className: "mt-ds-3 text-xs text-[var(--ds-text-muted)]", children })
|
|
4898
4909
|
]
|
|
4899
4910
|
}
|
|
@@ -4978,6 +4989,7 @@ function countCards(children) {
|
|
|
4978
4989
|
return n;
|
|
4979
4990
|
}
|
|
4980
4991
|
function CardGrid({ minWidth, maxColumns = 4, compare = false, gap = "var(--ds-space-4)", fill: fill2 = true, className, style, children, ref, ...props }) {
|
|
4992
|
+
useFramesItself();
|
|
4981
4993
|
const most = Math.max(1, Math.floor(maxColumns));
|
|
4982
4994
|
const drawn = "var(--gs-cards, var(--gs-cards-counted))";
|
|
4983
4995
|
const min = "var(--gs-card-min)";
|
|
@@ -5286,71 +5298,6 @@ function Accordion({ items, type = "single", defaultOpen = [], open: controlledO
|
|
|
5286
5298
|
] }, i);
|
|
5287
5299
|
}) });
|
|
5288
5300
|
}
|
|
5289
|
-
var EDGE_FADE = 24;
|
|
5290
|
-
var NONE = { left: false, right: false, vertical: false, gutterRight: 0, gutterBottom: 0 };
|
|
5291
|
-
var same = (a, b) => a.left === b.left && a.right === b.right && a.vertical === b.vertical && a.gutterRight === b.gutterRight && a.gutterBottom === b.gutterBottom;
|
|
5292
|
-
function useScrollEdges(options = {}) {
|
|
5293
|
-
const { enabled = true, fade = EDGE_FADE, noFade } = options;
|
|
5294
|
-
const elRef = useRef(null);
|
|
5295
|
-
const observer = useRef(null);
|
|
5296
|
-
const borders = useRef({ x: 0, y: 0 });
|
|
5297
|
-
const [state, setState] = useState(NONE);
|
|
5298
|
-
const measure = useCallback(() => {
|
|
5299
|
-
const el = elRef.current;
|
|
5300
|
-
if (!el) return;
|
|
5301
|
-
const next = {
|
|
5302
|
-
left: el.scrollLeft > 1,
|
|
5303
|
-
right: el.scrollLeft + el.clientWidth < el.scrollWidth - 1,
|
|
5304
|
-
vertical: el.scrollHeight > el.clientHeight + 1,
|
|
5305
|
-
gutterRight: Math.max(0, el.offsetWidth - el.clientWidth - borders.current.x),
|
|
5306
|
-
gutterBottom: Math.max(0, el.offsetHeight - el.clientHeight - borders.current.y)
|
|
5307
|
-
};
|
|
5308
|
-
setState((prev) => same(prev, next) ? prev : next);
|
|
5309
|
-
}, []);
|
|
5310
|
-
const ref = useCallback((el) => {
|
|
5311
|
-
observer.current?.disconnect();
|
|
5312
|
-
observer.current = null;
|
|
5313
|
-
elRef.current = el;
|
|
5314
|
-
if (!el || !enabled) return;
|
|
5315
|
-
const style = getComputedStyle(el);
|
|
5316
|
-
const px = (v) => parseFloat(v) || 0;
|
|
5317
|
-
borders.current = { x: px(style.borderLeftWidth) + px(style.borderRightWidth), y: px(style.borderTopWidth) + px(style.borderBottomWidth) };
|
|
5318
|
-
measure();
|
|
5319
|
-
if (typeof ResizeObserver === "undefined") return;
|
|
5320
|
-
const o = new ResizeObserver(measure);
|
|
5321
|
-
o.observe(el);
|
|
5322
|
-
for (const child of Array.from(el.children)) o.observe(child);
|
|
5323
|
-
observer.current = o;
|
|
5324
|
-
}, [enabled, measure]);
|
|
5325
|
-
const fadeLeft = state.left && !noFade?.left;
|
|
5326
|
-
const fadeRight = state.right && !noFade?.right;
|
|
5327
|
-
const shown = enabled && (fadeLeft || fadeRight);
|
|
5328
|
-
const { gutterRight: gr, gutterBottom: gb } = state;
|
|
5329
|
-
const fadeLayer = `linear-gradient(to right, ${fadeLeft ? `transparent 0, black ${fade}px` : "black 0"}, ${fadeRight ? `black calc(100% - ${gr + fade}px), transparent calc(100% - ${gr}px)` : "black 100%"})`;
|
|
5330
|
-
const gutters = [gb > 0 && { size: `100% ${gb}px`, position: "0 100%" }, gr > 0 && { size: `${gr}px 100%`, position: "100% 0" }].filter(Boolean);
|
|
5331
|
-
const mask = shown ? {
|
|
5332
|
-
image: [fadeLayer, ...gutters.map(() => "linear-gradient(black, black)")].join(", "),
|
|
5333
|
-
size: ["100% 100%", ...gutters.map((g) => g.size)].join(", "),
|
|
5334
|
-
position: ["0 0", ...gutters.map((g) => g.position)].join(", ")
|
|
5335
|
-
} : void 0;
|
|
5336
|
-
return {
|
|
5337
|
-
/** The scroller's ref (a callback). */
|
|
5338
|
-
ref,
|
|
5339
|
-
/** The scroller itself, for code that moves it. */
|
|
5340
|
-
elRef,
|
|
5341
|
-
measure,
|
|
5342
|
-
/** Content hides past a side edge: the scroller moves sideways, and its edges fade (but those in `noFade`). */
|
|
5343
|
-
overflowing: enabled && (state.left || state.right),
|
|
5344
|
-
/** It scrolls either way, sideways or up and down: a keyboard needs to reach it. */
|
|
5345
|
-
scrollable: enabled && (state.left || state.right || state.vertical),
|
|
5346
|
-
edges: { left: state.left, right: state.right },
|
|
5347
|
-
/** For the scroller: `data-fade` names the faded edges ("left", "right" or "left right"), the style masks them. */
|
|
5348
|
-
fadeProps: {
|
|
5349
|
-
"data-fade": shown ? [fadeLeft && "left", fadeRight && "right"].filter(Boolean).join(" ") : void 0,
|
|
5350
|
-
style: mask ? { maskImage: mask.image, WebkitMaskImage: mask.image, maskSize: mask.size, WebkitMaskSize: mask.size, maskPosition: mask.position, WebkitMaskPosition: mask.position, maskRepeat: "no-repeat", WebkitMaskRepeat: "no-repeat" } : void 0
|
|
5351
|
-
}
|
|
5352
|
-
};
|
|
5353
|
-
}
|
|
5354
5301
|
var HEADER_LAYOUT = {
|
|
5355
5302
|
row: "flex flex-wrap items-start justify-between gap-ds-4",
|
|
5356
5303
|
block: "flex flex-col space-y-ds-1.5 grow basis-1/2 break-words max-w-full has-[[data-title-one-line]]:min-w-0",
|
|
@@ -5409,6 +5356,9 @@ var PINNED_LAYERS = cn(
|
|
|
5409
5356
|
);
|
|
5410
5357
|
var PIN_SHADOW = "oklch(0 0 0 / 0.18)";
|
|
5411
5358
|
var ROW_CONTROL = `${FOCUSABLE}, label, [role="button"], [role="checkbox"], [role="switch"], [role="menuitem"], [role="link"]`;
|
|
5359
|
+
function clickIsCard(e) {
|
|
5360
|
+
return clickIsRows(e) && !(e.target instanceof Element && e.target.closest("[data-card-detail]"));
|
|
5361
|
+
}
|
|
5412
5362
|
function clickIsRows(e) {
|
|
5413
5363
|
const target = e.target;
|
|
5414
5364
|
if (!(target instanceof Element) || !e.currentTarget.contains(target)) return false;
|
|
@@ -5511,8 +5461,11 @@ function TableHeading({ title, description, actions, titleId, descriptionId, ins
|
|
|
5511
5461
|
descriptionText(HEADER_LAYOUT.below)
|
|
5512
5462
|
] }) });
|
|
5513
5463
|
}
|
|
5514
|
-
var NO_PINS = { start: [], end: [], nameFits: false, frame: 0 };
|
|
5515
|
-
var samePins = (a, b) => a.nameFits === b.nameFits && a.frame === b.frame && a.start.join() === b.start.join() && a.end.join() === b.end.join();
|
|
5464
|
+
var NO_PINS = { start: [], end: [], nameFits: false, frame: 0, panel: null };
|
|
5465
|
+
var samePins = (a, b) => a.nameFits === b.nameFits && a.frame === b.frame && a.start.join() === b.start.join() && a.end.join() === b.end.join() && a.panel?.join() === b.panel?.join();
|
|
5466
|
+
function PanelContent({ children }) {
|
|
5467
|
+
return /* @__PURE__ */ jsx(SurfaceBoundary, { children });
|
|
5468
|
+
}
|
|
5516
5469
|
function Table({
|
|
5517
5470
|
columns: columnsProp,
|
|
5518
5471
|
data,
|
|
@@ -5545,6 +5498,7 @@ function Table({
|
|
|
5545
5498
|
"aria-label": ariaLabel,
|
|
5546
5499
|
ref
|
|
5547
5500
|
}) {
|
|
5501
|
+
useFramesItself();
|
|
5548
5502
|
const headingId = useId();
|
|
5549
5503
|
const titleId = `${headingId}-title`;
|
|
5550
5504
|
const descriptionId = `${headingId}-description`;
|
|
@@ -5686,6 +5640,7 @@ function Table({
|
|
|
5686
5640
|
const cells = Array.from(table2.querySelectorAll(":scope > thead > tr > th"));
|
|
5687
5641
|
if (!cells.length) return;
|
|
5688
5642
|
const widths = cells.map((c) => c.getBoundingClientRect().width);
|
|
5643
|
+
if (!widths.some((w) => w > 0)) return;
|
|
5689
5644
|
const start = [];
|
|
5690
5645
|
let at = 0;
|
|
5691
5646
|
for (let i = 0; i < lead; i++) {
|
|
@@ -5702,7 +5657,9 @@ function Table({
|
|
|
5702
5657
|
const frame = scroller.clientWidth;
|
|
5703
5658
|
const nameFits = nameIndex >= 0 && frame > 0 && at + nameWidth + fromRight <= frame / 2;
|
|
5704
5659
|
if (nameFits) start.push(at);
|
|
5705
|
-
const
|
|
5660
|
+
const pad3 = (cell, side) => cell ? parseFloat(getComputedStyle(cell)[side]) || 0 : 0;
|
|
5661
|
+
const panel = cells.length > lead ? [at + pad3(cells[lead], "paddingLeft"), pad3(cells[cells.length - 1], "paddingRight")] : null;
|
|
5662
|
+
const next = { start, end, nameFits, frame, panel };
|
|
5706
5663
|
setPins((prev) => samePins(prev, next) ? prev : next);
|
|
5707
5664
|
};
|
|
5708
5665
|
measure();
|
|
@@ -5742,9 +5699,16 @@ function Table({
|
|
|
5742
5699
|
const expandedKey = expanded.map(String).join("");
|
|
5743
5700
|
const shownBefore = useRef(/* @__PURE__ */ new Set());
|
|
5744
5701
|
const pendingScroll = useRef(null);
|
|
5702
|
+
const scrollFrame = useRef(0);
|
|
5745
5703
|
const scrollToRow = useCallback((key) => {
|
|
5746
|
-
|
|
5747
|
-
|
|
5704
|
+
cancelAnimationFrame(scrollFrame.current);
|
|
5705
|
+
scrollFrame.current = requestAnimationFrame(() => {
|
|
5706
|
+
const row = rootRef.current?.querySelector(`[data-row-key="${CSS.escape(key)}"], [data-row-index="${CSS.escape(key)}"]`);
|
|
5707
|
+
if (!row || typeof row.scrollIntoView !== "function") return;
|
|
5708
|
+
const panel = row.nextElementSibling?.querySelector("[data-row-panel]") ? row.nextElementSibling : null;
|
|
5709
|
+
panel?.scrollIntoView({ block: "nearest" });
|
|
5710
|
+
row.scrollIntoView({ block: "nearest" });
|
|
5711
|
+
});
|
|
5748
5712
|
}, [rootRef]);
|
|
5749
5713
|
useEffect(() => {
|
|
5750
5714
|
const now = new Set(expanded.map(String));
|
|
@@ -5806,8 +5770,8 @@ function Table({
|
|
|
5806
5770
|
const row = rootRef.current?.querySelector(was.row);
|
|
5807
5771
|
if (!row) return;
|
|
5808
5772
|
const controls = Array.from(row.querySelectorAll(FOCUSABLE));
|
|
5809
|
-
const
|
|
5810
|
-
(
|
|
5773
|
+
const same = was.control === null ? null : controls.find((el) => (el.getAttribute("aria-labelledby") ?? el.getAttribute("aria-label") ?? el.textContent) === was.control);
|
|
5774
|
+
(same ?? (row.tabIndex >= 0 ? row : controls[0]))?.focus({ preventScroll: true });
|
|
5811
5775
|
}, [isMobile, rootRef]);
|
|
5812
5776
|
if (isMobile) {
|
|
5813
5777
|
if (loading) {
|
|
@@ -5823,6 +5787,14 @@ function Table({
|
|
|
5823
5787
|
drawn.map(({ row, originalIdx }) => {
|
|
5824
5788
|
const isSelected = selectedSet.has(originalIdx);
|
|
5825
5789
|
const id = idOf(row, originalIdx);
|
|
5790
|
+
const opens = !!expandable && !!renderExpanded;
|
|
5791
|
+
const isExpanded = opens && expandedSet.has(String(id));
|
|
5792
|
+
const toggleCard = (card) => {
|
|
5793
|
+
const closing = isExpanded;
|
|
5794
|
+
const inDetail = closing && card.querySelector("[data-card-detail]")?.contains(document.activeElement);
|
|
5795
|
+
toggleExpand(id);
|
|
5796
|
+
if (inDetail) card.querySelector("[data-card-toggle]")?.focus();
|
|
5797
|
+
};
|
|
5826
5798
|
return /* @__PURE__ */ jsxs(
|
|
5827
5799
|
"div",
|
|
5828
5800
|
{
|
|
@@ -5833,10 +5805,15 @@ function Table({
|
|
|
5833
5805
|
"rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-surface)]",
|
|
5834
5806
|
"p-ds-4 space-y-ds-3",
|
|
5835
5807
|
isSelected && ACTIVE_RING,
|
|
5836
|
-
onRowClick && "cursor-pointer hover:bg-[var(--ds-bg-muted)] focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]"
|
|
5808
|
+
onRowClick && "cursor-pointer hover:bg-[var(--ds-bg-muted)] focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
5809
|
+
// with no onRowClick a tap on the card opens and closes it, as a click on the row does; the toggle is the
|
|
5810
|
+
// keyboard's way
|
|
5811
|
+
!onRowClick && canOpenByClick && "cursor-pointer"
|
|
5837
5812
|
),
|
|
5838
5813
|
onClick: onRowClick ? (e) => {
|
|
5839
|
-
if (
|
|
5814
|
+
if (clickIsCard(e)) onRowClick(row, originalIdx);
|
|
5815
|
+
} : canOpenByClick ? (e) => {
|
|
5816
|
+
if (clickIsCard(e)) toggleCard(e.currentTarget);
|
|
5840
5817
|
} : void 0,
|
|
5841
5818
|
tabIndex: onRowClick ? 0 : void 0,
|
|
5842
5819
|
onKeyDown: onRowClick ? (e) => {
|
|
@@ -5853,7 +5830,36 @@ function Table({
|
|
|
5853
5830
|
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-[var(--ds-text-secondary)] font-medium text-xs uppercase tracking-wider", children: col.header }),
|
|
5854
5831
|
/* @__PURE__ */ jsx(CardValue, { value: row[col.key], id: lead + c === nameIndex ? `${headingId}-card-name-${idPart(id)}` : void 0 })
|
|
5855
5832
|
] }, col.key)),
|
|
5856
|
-
|
|
5833
|
+
opens && // Alert's disclosure: a button that says whether it is open, at the card's foot, the detail below it, so
|
|
5834
|
+
// the control the user pressed stays where it was. Its name carries the row's (T15).
|
|
5835
|
+
/* @__PURE__ */ jsxs("div", { className: "pt-ds-1", children: [
|
|
5836
|
+
/* @__PURE__ */ jsxs(
|
|
5837
|
+
"button",
|
|
5838
|
+
{
|
|
5839
|
+
type: "button",
|
|
5840
|
+
"data-card-toggle": "",
|
|
5841
|
+
"aria-expanded": isExpanded,
|
|
5842
|
+
...nameIndex >= 0 ? { "aria-labelledby": `${headingId}-card-toggle-${idPart(id)} ${headingId}-card-name-${idPart(id)}` } : {},
|
|
5843
|
+
onClick: (e) => {
|
|
5844
|
+
e.stopPropagation();
|
|
5845
|
+
toggleCard(e.currentTarget.closest("[data-row]"));
|
|
5846
|
+
},
|
|
5847
|
+
className: cn(
|
|
5848
|
+
// at least 24 px tall: the card around it is a target too, so its own box must meet the size (WCAG 2.5.8)
|
|
5849
|
+
"inline-flex min-h-[24px] items-center gap-ds-1 text-xs font-medium cursor-pointer",
|
|
5850
|
+
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
5851
|
+
"text-[var(--ds-accent-primary)] hover:bg-[var(--ds-accent-muted)]",
|
|
5852
|
+
"rounded-[var(--ds-radius-sm)] px-ds-1.5 py-ds-0.5 -mx-ds-1.5",
|
|
5853
|
+
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]"
|
|
5854
|
+
),
|
|
5855
|
+
children: [
|
|
5856
|
+
/* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 12, className: cn("transition-transform duration-[var(--ds-transition-speed)]", isExpanded && "rotate-90") }),
|
|
5857
|
+
/* @__PURE__ */ jsx("span", { id: `${headingId}-card-toggle-${idPart(id)}`, children: isExpanded ? "Hide details" : "Show details" })
|
|
5858
|
+
]
|
|
5859
|
+
}
|
|
5860
|
+
),
|
|
5861
|
+
isExpanded && /* @__PURE__ */ jsx("div", { "data-card-detail": "", className: "mt-ds-3 pt-ds-3 border-t-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] text-sm text-[var(--ds-text-secondary)]", children: /* @__PURE__ */ jsx(PanelContent, { children: renderExpanded(row, originalIdx) }) })
|
|
5862
|
+
] })
|
|
5857
5863
|
]
|
|
5858
5864
|
},
|
|
5859
5865
|
String(id)
|
|
@@ -5953,7 +5959,8 @@ function Table({
|
|
|
5953
5959
|
{
|
|
5954
5960
|
...marksOf(row, originalIdx),
|
|
5955
5961
|
className: cn(
|
|
5956
|
-
|
|
5962
|
+
// an opened row's divider is under its panel (A6)
|
|
5963
|
+
!(expandable && isExpanded && renderExpanded) && "border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0",
|
|
5957
5964
|
// the row's background and its tint change together, so its pinned cells and the rest fade as one
|
|
5958
5965
|
// (roots.css registers --gs-row-tint as a colour so it can)
|
|
5959
5966
|
"transition-[background-color,--gs-row-tint]",
|
|
@@ -6038,12 +6045,21 @@ function Table({
|
|
|
6038
6045
|
]
|
|
6039
6046
|
}
|
|
6040
6047
|
),
|
|
6041
|
-
expandable && isExpanded && renderExpanded && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
|
|
6048
|
+
expandable && isExpanded && renderExpanded && /* @__PURE__ */ jsx("tr", { className: "border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] last:border-b-0", children: /* @__PURE__ */ jsx(
|
|
6042
6049
|
"td",
|
|
6043
6050
|
{
|
|
6044
6051
|
colSpan: cellCount,
|
|
6045
|
-
className: "
|
|
6046
|
-
|
|
6052
|
+
className: cn("py-ds-4 text-sm text-[var(--ds-text-primary)]", !pins.panel && (density === "compact" ? "px-ds-3" : "px-ds-4")),
|
|
6053
|
+
style: pins.panel ? { paddingLeft: pins.panel[0], paddingRight: pins.panel[1] } : void 0,
|
|
6054
|
+
children: /* @__PURE__ */ jsx(
|
|
6055
|
+
"div",
|
|
6056
|
+
{
|
|
6057
|
+
"data-row-panel": "",
|
|
6058
|
+
className: "sticky",
|
|
6059
|
+
style: pins.panel ? { left: pins.panel[0], maxWidth: pins.frame ? pins.frame - pins.panel[0] - pins.panel[1] : void 0 } : { left: 0 },
|
|
6060
|
+
children: /* @__PURE__ */ jsx(PanelContent, { children: renderExpanded(row, originalIdx) })
|
|
6061
|
+
}
|
|
6062
|
+
)
|
|
6047
6063
|
}
|
|
6048
6064
|
) })
|
|
6049
6065
|
] }, String(id));
|
|
@@ -6109,6 +6125,9 @@ var indicatorInset = {
|
|
|
6109
6125
|
md: "4px",
|
|
6110
6126
|
lg: "4px"
|
|
6111
6127
|
};
|
|
6128
|
+
function segmentRadius(inset, bordered) {
|
|
6129
|
+
return `max(var(--ds-radius-sm), calc(var(--ds-radius-md) - ${inset}${bordered ? " - var(--ds-border-width)" : ""}))`;
|
|
6130
|
+
}
|
|
6112
6131
|
function SegmentedControl({
|
|
6113
6132
|
value,
|
|
6114
6133
|
onChange: onChangeProp,
|
|
@@ -6244,22 +6263,32 @@ function SegmentedControl({
|
|
|
6244
6263
|
onKeyDown: handleKeyDown,
|
|
6245
6264
|
className: cn(
|
|
6246
6265
|
"relative items-center",
|
|
6247
|
-
|
|
6266
|
+
// Sprint 25.14 A21: in a Field's column a track that isn't full width keeps its own width; w-fit, not self-start,
|
|
6267
|
+
// so a row or a centred column still aligns it (the review of 30 September)
|
|
6268
|
+
fullWidth ? "flex w-full" : "inline-flex w-fit",
|
|
6248
6269
|
containerPadding[size],
|
|
6249
6270
|
containerHeight[size],
|
|
6250
6271
|
"bg-[var(--ds-bg-muted)]",
|
|
6251
|
-
|
|
6272
|
+
// The owner's review of 1 October 2026: the frame's corner is a field's, so the two change together with the
|
|
6273
|
+
// theme's radius; the segments inside sit concentric with it (SEGMENT_RADIUS)
|
|
6274
|
+
"rounded-[var(--ds-radius-md)]",
|
|
6275
|
+
// The frame's edge is a button's: each segment is a labelled button, so the frame isn't what identifies the
|
|
6276
|
+
// control, and WCAG 1.4.11 asks no 3:1 of it. The selected segment carries the 3:1 edge instead (below)
|
|
6252
6277
|
variant === "default" && "border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
6253
6278
|
control.invalid && "border-[length:var(--ds-border-width)] border-[var(--ds-status-error)]",
|
|
6254
6279
|
className
|
|
6255
6280
|
),
|
|
6281
|
+
style: { "--ds-segment-radius": segmentRadius(indicatorInset[size], variant === "default" || !!control.invalid) },
|
|
6256
6282
|
children: [
|
|
6257
6283
|
/* @__PURE__ */ jsx(
|
|
6258
6284
|
"div",
|
|
6259
6285
|
{
|
|
6260
6286
|
className: cn(
|
|
6261
|
-
"absolute rounded-[var(--ds-radius
|
|
6287
|
+
"absolute rounded-[var(--ds-segment-radius)]",
|
|
6262
6288
|
"bg-[var(--ds-bg-surface)]",
|
|
6289
|
+
// The selected state is what the control shows, so its edge is the one at 3:1 (WCAG 1.4.11), against the
|
|
6290
|
+
// frame's fill and its own: the surface on the muted fill alone measures 1.05–1.46:1 across the presets
|
|
6291
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-input-border)]",
|
|
6263
6292
|
variant === "default" && "shadow-[var(--ds-shadow-sm)]",
|
|
6264
6293
|
"transition-all motion-reduce:transition-none"
|
|
6265
6294
|
),
|
|
@@ -6290,7 +6319,7 @@ function SegmentedControl({
|
|
|
6290
6319
|
className: cn(
|
|
6291
6320
|
"relative z-10 inline-flex items-center justify-center self-stretch font-medium whitespace-nowrap",
|
|
6292
6321
|
fullWidth && "flex-1",
|
|
6293
|
-
"rounded-[var(--ds-radius
|
|
6322
|
+
"rounded-[var(--ds-segment-radius)]",
|
|
6294
6323
|
"transition-colors cursor-pointer",
|
|
6295
6324
|
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
6296
6325
|
sizes2[size],
|
|
@@ -6736,6 +6765,7 @@ function WeekView({
|
|
|
6736
6765
|
const hasAllDay = allDayEvents.some((d) => d.length > 0);
|
|
6737
6766
|
const containerRef = useRef(null);
|
|
6738
6767
|
const syncingScroll = useRef(false);
|
|
6768
|
+
const { ref: edgesRef, measure: measureEdges, fadeProps: edgeFade } = useScrollEdges();
|
|
6739
6769
|
const handleScroll = useCallback((e) => {
|
|
6740
6770
|
if (syncingScroll.current) return;
|
|
6741
6771
|
syncingScroll.current = true;
|
|
@@ -6761,7 +6791,7 @@ function WeekView({
|
|
|
6761
6791
|
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "flex flex-col h-full overflow-hidden", children: [
|
|
6762
6792
|
/* @__PURE__ */ jsxs("div", { className: "flex border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", children: [
|
|
6763
6793
|
/* @__PURE__ */ jsx("div", { className: "w-14 shrink-0 border-r-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]" }),
|
|
6764
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6794
|
+
/* @__PURE__ */ jsx("div", { ref: edgesRef, onScroll: measureEdges, ...edgeFade, className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6765
6795
|
"div",
|
|
6766
6796
|
{
|
|
6767
6797
|
className: "grid",
|
|
@@ -6801,7 +6831,7 @@ function WeekView({
|
|
|
6801
6831
|
] }),
|
|
6802
6832
|
hasAllDay && /* @__PURE__ */ jsxs("div", { className: "flex border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] bg-[var(--ds-bg-muted)]/30", children: [
|
|
6803
6833
|
/* @__PURE__ */ jsx("div", { className: "w-14 shrink-0 border-r-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] text-2xs text-[var(--ds-text-muted)] px-ds-1 py-ds-1 text-right", children: "all-day" }),
|
|
6804
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6834
|
+
/* @__PURE__ */ jsx("div", { ...edgeFade, className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6805
6835
|
"div",
|
|
6806
6836
|
{
|
|
6807
6837
|
className: "grid",
|
|
@@ -6838,7 +6868,7 @@ function WeekView({
|
|
|
6838
6868
|
},
|
|
6839
6869
|
h
|
|
6840
6870
|
)) }),
|
|
6841
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6871
|
+
/* @__PURE__ */ jsx("div", { ...edgeFade, className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6842
6872
|
"div",
|
|
6843
6873
|
{
|
|
6844
6874
|
className: "relative",
|
|
@@ -7404,16 +7434,16 @@ function MonthDropdown({
|
|
|
7404
7434
|
)
|
|
7405
7435
|
] }),
|
|
7406
7436
|
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-ds-1", children: MONTH_NAMES_SHORT.map((name, i) => {
|
|
7407
|
-
const
|
|
7437
|
+
const isActive2 = i === currentMonth && browseYear === currentYear;
|
|
7408
7438
|
return /* @__PURE__ */ jsx(
|
|
7409
7439
|
"button",
|
|
7410
7440
|
{
|
|
7411
7441
|
className: cn(
|
|
7412
7442
|
"px-ds-2 py-ds-1.5 text-xs font-medium rounded-[var(--ds-radius-sm)] cursor-pointer transition-colors",
|
|
7413
7443
|
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
7414
|
-
|
|
7444
|
+
isActive2 ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-emphasis)] hover:text-[var(--ds-text-primary)]"
|
|
7415
7445
|
),
|
|
7416
|
-
"data-current":
|
|
7446
|
+
"data-current": isActive2 || void 0,
|
|
7417
7447
|
onClick: () => {
|
|
7418
7448
|
returnFocus();
|
|
7419
7449
|
onSelect(new Date(browseYear, i, 1));
|
|
@@ -7882,7 +7912,6 @@ function AvatarGroup({ items, max = 4, size = "sm", ring = "canvas", onOverflowC
|
|
|
7882
7912
|
alt: item.alt ?? item.name ?? initials,
|
|
7883
7913
|
initials,
|
|
7884
7914
|
size,
|
|
7885
|
-
status: item.status,
|
|
7886
7915
|
color: item.color,
|
|
7887
7916
|
className: ringClass
|
|
7888
7917
|
},
|
|
@@ -8002,7 +8031,7 @@ function TableToolbar({
|
|
|
8002
8031
|
const iconSize = size === "sm" ? 14 : 16;
|
|
8003
8032
|
const count = activeFilterCount ?? activeFilters?.length ?? 0;
|
|
8004
8033
|
const hasChips = !!activeFilters?.length;
|
|
8005
|
-
const inPane = useContext(SplitPaneCtx);
|
|
8034
|
+
const inPane = !!useContext(SplitPaneCtx);
|
|
8006
8035
|
const searchFills = inPane || !primaryFilter && !filters && !actions;
|
|
8007
8036
|
const hasControls = !!(search || primaryFilter || filters || actions);
|
|
8008
8037
|
const noun = (n) => n === 1 ? resultNoun[0] : resultNoun[1];
|
|
@@ -8201,6 +8230,7 @@ function VerticalLayout({ items, className }) {
|
|
|
8201
8230
|
] }, i)) });
|
|
8202
8231
|
}
|
|
8203
8232
|
function Timeline({ items: allItems, orientation = "vertical", minItemWidth = 200, className, ref, pager }) {
|
|
8233
|
+
useScrollsInside();
|
|
8204
8234
|
useWholeListCheck("Timeline", allItems.length, pager);
|
|
8205
8235
|
const items = pagerPart(allItems, pager);
|
|
8206
8236
|
const measureRef = useRef(null);
|
|
@@ -8287,12 +8317,27 @@ var Collapsible = Object.assign(CollapsibleRoot, {
|
|
|
8287
8317
|
Trigger: CollapsibleTrigger,
|
|
8288
8318
|
Content: CollapsibleContent
|
|
8289
8319
|
});
|
|
8320
|
+
var SYMBOL = /[⌘⇧⌥⌃⎋⏎↵⌫⌦⇥↑↓←→]/u;
|
|
8321
|
+
function keyParts(text) {
|
|
8322
|
+
const parts = [];
|
|
8323
|
+
let run = "";
|
|
8324
|
+
for (const ch of Array.from(text)) {
|
|
8325
|
+
if (SYMBOL.test(ch)) {
|
|
8326
|
+
if (run.trim()) parts.push(run.trim());
|
|
8327
|
+
run = "";
|
|
8328
|
+
parts.push(ch);
|
|
8329
|
+
} else run += ch;
|
|
8330
|
+
}
|
|
8331
|
+
if (run.trim()) parts.push(run.trim());
|
|
8332
|
+
return parts;
|
|
8333
|
+
}
|
|
8290
8334
|
function Kbd({ children, className }) {
|
|
8335
|
+
const parts = typeof children === "string" ? keyParts(children) : null;
|
|
8291
8336
|
return /* @__PURE__ */ jsx(
|
|
8292
8337
|
"kbd",
|
|
8293
8338
|
{
|
|
8294
8339
|
className: cn(
|
|
8295
|
-
"inline-flex items-center justify-center min-w-[2.5em] px-ds-1.5 py-ds-0.5",
|
|
8340
|
+
"inline-flex items-center justify-center gap-[0.25em] min-w-[2.5em] px-ds-1.5 py-ds-0.5",
|
|
8296
8341
|
"text-xs leading-none font-[family-name:var(--ds-font-mono)]",
|
|
8297
8342
|
"text-[var(--ds-text-secondary)]",
|
|
8298
8343
|
"bg-[var(--ds-bg-surface)]",
|
|
@@ -8301,16 +8346,30 @@ function Kbd({ children, className }) {
|
|
|
8301
8346
|
"rounded-[var(--ds-radius-sm)]",
|
|
8302
8347
|
className
|
|
8303
8348
|
),
|
|
8304
|
-
children
|
|
8349
|
+
children: parts && parts.length > 1 ? parts.map((p, i) => /* @__PURE__ */ jsx("span", { children: p }, i)) : children
|
|
8305
8350
|
}
|
|
8306
8351
|
);
|
|
8307
8352
|
}
|
|
8353
|
+
|
|
8354
|
+
// ../../showcase/src/lib/nested-items.ts
|
|
8355
|
+
function holdsCurrent(items, isCurrent) {
|
|
8356
|
+
return !!items?.some((item) => isCurrent(item) || holdsCurrent(item.children, isCurrent));
|
|
8357
|
+
}
|
|
8308
8358
|
function TruncLabel2({ children }) {
|
|
8309
8359
|
const { ref, isTruncated } = useTextOverflow({ lines: 1 });
|
|
8310
8360
|
const label = /* @__PURE__ */ jsx("span", { ref, className: "truncate", children });
|
|
8311
8361
|
if (!isTruncated) return label;
|
|
8312
8362
|
return /* @__PURE__ */ jsx(Tooltip, { content: children, children: label });
|
|
8313
8363
|
}
|
|
8364
|
+
function foldersHolding(nodes, selected) {
|
|
8365
|
+
const ids = [];
|
|
8366
|
+
for (const node of nodes) {
|
|
8367
|
+
if (!holdsCurrent(node.children, (n) => selected.has(n.id))) continue;
|
|
8368
|
+
ids.push(node.id, ...foldersHolding(node.children, selected));
|
|
8369
|
+
}
|
|
8370
|
+
return ids;
|
|
8371
|
+
}
|
|
8372
|
+
var inTree = (nodes, id) => holdsCurrent(nodes, (n) => n.id === id);
|
|
8314
8373
|
function allDescendantIds(node) {
|
|
8315
8374
|
const ids = [node.id];
|
|
8316
8375
|
if (node.children) {
|
|
@@ -8325,13 +8384,26 @@ function TreeView({
|
|
|
8325
8384
|
checkable,
|
|
8326
8385
|
defaultExpanded = [],
|
|
8327
8386
|
defaultSelected = [],
|
|
8387
|
+
selected: selectedProp,
|
|
8328
8388
|
defaultChecked = [],
|
|
8329
8389
|
onSelect,
|
|
8330
8390
|
onCheck,
|
|
8331
8391
|
className
|
|
8332
8392
|
}) {
|
|
8333
|
-
const [
|
|
8334
|
-
const
|
|
8393
|
+
const [ownSelected, setOwnSelected] = useState(() => new Set(defaultSelected));
|
|
8394
|
+
const selected = useMemo(() => selectedProp ? new Set(selectedProp) : ownSelected, [selectedProp, ownSelected]);
|
|
8395
|
+
const [expanded, setExpanded] = useState(() => /* @__PURE__ */ new Set([...defaultExpanded, ...foldersHolding(nodes, selected)]));
|
|
8396
|
+
const revealed = useRef(null);
|
|
8397
|
+
if (revealed.current === null) revealed.current = new Set([...selected].filter((id) => inTree(nodes, id)));
|
|
8398
|
+
useEffect(() => {
|
|
8399
|
+
const seen = revealed.current;
|
|
8400
|
+
const fresh = [...selected].filter((id) => !seen.has(id) && inTree(nodes, id));
|
|
8401
|
+
if (!fresh.length) return;
|
|
8402
|
+
for (const id of fresh) seen.add(id);
|
|
8403
|
+
const folders = foldersHolding(nodes, new Set(fresh));
|
|
8404
|
+
if (folders.length) setExpanded((prev) => folders.every((id) => prev.has(id)) ? prev : /* @__PURE__ */ new Set([...prev, ...folders]));
|
|
8405
|
+
}, [nodes, selected]);
|
|
8406
|
+
const holding = useMemo(() => new Set(foldersHolding(nodes, selected)), [nodes, selected]);
|
|
8335
8407
|
const [checked, setChecked] = useState(new Set(defaultChecked));
|
|
8336
8408
|
const baseId = useId();
|
|
8337
8409
|
const toggleExpand = useCallback((id) => {
|
|
@@ -8345,20 +8417,18 @@ function TreeView({
|
|
|
8345
8417
|
const handleSelect = useCallback(
|
|
8346
8418
|
(id) => {
|
|
8347
8419
|
if (!selectable) return;
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
|
|
8358
|
-
return next;
|
|
8359
|
-
});
|
|
8420
|
+
let next;
|
|
8421
|
+
if (multiSelect) {
|
|
8422
|
+
next = new Set(selected);
|
|
8423
|
+
if (next.has(id)) next.delete(id);
|
|
8424
|
+
else next.add(id);
|
|
8425
|
+
} else {
|
|
8426
|
+
next = selected.has(id) ? /* @__PURE__ */ new Set() : /* @__PURE__ */ new Set([id]);
|
|
8427
|
+
}
|
|
8428
|
+
if (!selectedProp) setOwnSelected(next);
|
|
8429
|
+
onSelect?.(Array.from(next));
|
|
8360
8430
|
},
|
|
8361
|
-
[selectable, multiSelect, onSelect]
|
|
8431
|
+
[selectable, multiSelect, selected, selectedProp, onSelect]
|
|
8362
8432
|
);
|
|
8363
8433
|
const handleCheck = useCallback(
|
|
8364
8434
|
(node) => {
|
|
@@ -8443,6 +8513,7 @@ function TreeView({
|
|
|
8443
8513
|
baseId,
|
|
8444
8514
|
expanded,
|
|
8445
8515
|
selected,
|
|
8516
|
+
holding,
|
|
8446
8517
|
checked,
|
|
8447
8518
|
checkable,
|
|
8448
8519
|
selectable,
|
|
@@ -8461,6 +8532,7 @@ function TreeNodeRow({
|
|
|
8461
8532
|
baseId,
|
|
8462
8533
|
expanded,
|
|
8463
8534
|
selected,
|
|
8535
|
+
holding,
|
|
8464
8536
|
checkable,
|
|
8465
8537
|
selectable,
|
|
8466
8538
|
toggleExpand,
|
|
@@ -8472,6 +8544,7 @@ function TreeNodeRow({
|
|
|
8472
8544
|
const hasChildren = !!node.children?.length;
|
|
8473
8545
|
const isExpanded = expanded.has(node.id);
|
|
8474
8546
|
const isSelected = selected.has(node.id);
|
|
8547
|
+
const holdsSelection = !isSelected && holding.has(node.id);
|
|
8475
8548
|
const checkState = checkable ? getCheckState(node) : "unchecked";
|
|
8476
8549
|
return /* @__PURE__ */ jsxs("div", { role: "treeitem", "aria-expanded": hasChildren ? isExpanded : void 0, "aria-selected": selectable ? isSelected : void 0, children: [
|
|
8477
8550
|
/* @__PURE__ */ jsxs(
|
|
@@ -8487,6 +8560,9 @@ function TreeNodeRow({
|
|
|
8487
8560
|
// transparent placeholder so content never shifts on selection.
|
|
8488
8561
|
"border-l-[length:var(--ds-tree-active-rail)]",
|
|
8489
8562
|
isSelected ? "bg-[var(--ds-tree-active-bg)] text-[var(--ds-tree-active-text)] font-medium border-[var(--ds-accent-primary)]" : "border-transparent text-[var(--ds-text-primary)] hover:bg-[var(--ds-tab-hover-bg)] hover:text-[var(--ds-text-primary)]",
|
|
8563
|
+
// A folder holding the selection, as SidebarNav draws a parent of the current page (Sprint 25.16 A18): no
|
|
8564
|
+
// fill, so it reads the plain tokens, never the active set (pill's on-primary text would vanish here).
|
|
8565
|
+
holdsSelection && "font-medium",
|
|
8490
8566
|
node.disabled && "opacity-disabled pointer-events-none"
|
|
8491
8567
|
),
|
|
8492
8568
|
style: { paddingLeft: `calc(var(--ds-space-3) * ${depth} + var(--ds-space-2))` },
|
|
@@ -8513,7 +8589,7 @@ function TreeNodeRow({
|
|
|
8513
8589
|
{
|
|
8514
8590
|
name: "chevron-right",
|
|
8515
8591
|
size: 14,
|
|
8516
|
-
className: cn(isSelected ? "text-[var(--ds-tree-active-muted)]" : "text-[var(--ds-text-muted)]", "transition-transform", isExpanded && "rotate-90")
|
|
8592
|
+
className: cn(isSelected ? "text-[var(--ds-tree-active-muted)]" : holdsSelection ? "text-[var(--ds-accent-primary)]" : "text-[var(--ds-text-muted)]", "transition-transform", isExpanded && "rotate-90")
|
|
8517
8593
|
}
|
|
8518
8594
|
)
|
|
8519
8595
|
}
|
|
@@ -8528,7 +8604,7 @@ function TreeNodeRow({
|
|
|
8528
8604
|
}
|
|
8529
8605
|
}
|
|
8530
8606
|
),
|
|
8531
|
-
node.icon && /* @__PURE__ */ jsx(Icon, { name: node.icon, size: 16, className: cn("shrink-0", isSelected ? "text-[var(--ds-tree-active-text)]" : "text-[var(--ds-text-muted)]") }),
|
|
8607
|
+
node.icon && /* @__PURE__ */ jsx(Icon, { name: node.icon, size: 16, className: cn("shrink-0", isSelected ? "text-[var(--ds-tree-active-text)]" : holdsSelection ? "text-[var(--ds-accent-primary)]" : "text-[var(--ds-text-muted)]") }),
|
|
8532
8608
|
/* @__PURE__ */ jsx(TruncLabel2, { children: node.label })
|
|
8533
8609
|
]
|
|
8534
8610
|
}
|
|
@@ -8541,6 +8617,7 @@ function TreeNodeRow({
|
|
|
8541
8617
|
baseId,
|
|
8542
8618
|
expanded,
|
|
8543
8619
|
selected,
|
|
8620
|
+
holding,
|
|
8544
8621
|
checked: /* @__PURE__ */ new Set(),
|
|
8545
8622
|
checkable,
|
|
8546
8623
|
selectable,
|
|
@@ -8898,7 +8975,8 @@ function ChatInputBar({ onSend, busy, onStop, onAttach, onVoice, placeholder })
|
|
|
8898
8975
|
className: cn(
|
|
8899
8976
|
"flex flex-col",
|
|
8900
8977
|
"rounded-[var(--ds-radius-lg)]",
|
|
8901
|
-
|
|
8978
|
+
// Sprint 25.14 A20: the composer is a field, its edge at 3:1 like every other control's
|
|
8979
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-input-border)]",
|
|
8902
8980
|
"bg-[var(--ds-input-bg)]",
|
|
8903
8981
|
"shadow-[var(--ds-input-shadow)]",
|
|
8904
8982
|
FOCUS_WITHIN_RING,
|
|
@@ -9191,6 +9269,28 @@ function useCornerInset(corner, inset, priority, target) {
|
|
|
9191
9269
|
return claimCornerInset(corner, inset, priority, el);
|
|
9192
9270
|
}, [corner, inset, priority, target]);
|
|
9193
9271
|
}
|
|
9272
|
+
function Sheet({ open, onClose: onCloseProp, title, children, footer, dirty, onDiscard, snapPoints = [0.5, 0.92], container, flush, keepMounted = false, id, labelledBy }) {
|
|
9273
|
+
const { marked, mark } = useOverlayMark(open);
|
|
9274
|
+
const guard = useDirtyGuard(dirty ?? marked, onCloseProp, onDiscard);
|
|
9275
|
+
return /* @__PURE__ */ jsx(
|
|
9276
|
+
DrawerPanel,
|
|
9277
|
+
{
|
|
9278
|
+
form: "sheet",
|
|
9279
|
+
open,
|
|
9280
|
+
onClose: guard.requestClose,
|
|
9281
|
+
title,
|
|
9282
|
+
footer,
|
|
9283
|
+
container,
|
|
9284
|
+
flush,
|
|
9285
|
+
snapPoints,
|
|
9286
|
+
keepMounted,
|
|
9287
|
+
id,
|
|
9288
|
+
labelledBy,
|
|
9289
|
+
confirm: /* @__PURE__ */ jsx(DiscardConfirm, { open: guard.confirming, onKeep: guard.keep, onDiscard: guard.discard }),
|
|
9290
|
+
children: /* @__PURE__ */ jsx(DrawerFooterCtx, { value: null, children: /* @__PURE__ */ jsx(OverlayCloseCtx, { value: guard.requestClose, children: /* @__PURE__ */ jsx(OverlayMarkScope, { mark, children }) }) })
|
|
9291
|
+
}
|
|
9292
|
+
);
|
|
9293
|
+
}
|
|
9194
9294
|
var DEFAULT_OFFSET = "var(--ds-space-4)";
|
|
9195
9295
|
var CORNER_PANEL_ANCHOR_INSET = "calc(var(--ds-space-12) + var(--ds-space-3))";
|
|
9196
9296
|
function CornerPanel({
|
|
@@ -9475,9 +9575,10 @@ var StackedList = forwardRef(function StackedList2({
|
|
|
9475
9575
|
hover,
|
|
9476
9576
|
pager
|
|
9477
9577
|
}, ref) {
|
|
9578
|
+
useScrollsInside();
|
|
9478
9579
|
const isPhone = useBreakpoint("sm");
|
|
9479
9580
|
const inCard = useContext(CardSurfaceCtx);
|
|
9480
|
-
const inPane = useContext(SplitPaneCtx);
|
|
9581
|
+
const inPane = !!useContext(SplitPaneCtx);
|
|
9481
9582
|
const variant = variantProp ?? (flush || hover === "title" ? "articles" : "list");
|
|
9482
9583
|
const legacy = flush !== void 0 || hover !== void 0;
|
|
9483
9584
|
useEffect(() => {
|
|
@@ -10144,6 +10245,8 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
10144
10245
|
className
|
|
10145
10246
|
}, ref) {
|
|
10146
10247
|
const scrollerRef = useRef(null);
|
|
10248
|
+
const rootRef = useRef(null);
|
|
10249
|
+
const fill2 = useFillHeight(rootRef);
|
|
10147
10250
|
const headerRef = useRef(null);
|
|
10148
10251
|
const rowsRef = useRef(null);
|
|
10149
10252
|
const [frame, setFrame] = useState({ width: 0, header: 0 });
|
|
@@ -10366,23 +10469,26 @@ var TimeViewport = forwardRef(function TimeViewport2({
|
|
|
10366
10469
|
};
|
|
10367
10470
|
const headerNode = header === void 0 ? /* @__PURE__ */ jsx(TimeScaleHeader, {}) : header;
|
|
10368
10471
|
const hasHeader = headerNode != null || labelHeader != null;
|
|
10369
|
-
const bar = toolbar === false ? null :
|
|
10370
|
-
|
|
10371
|
-
|
|
10372
|
-
/* @__PURE__ */
|
|
10373
|
-
|
|
10374
|
-
|
|
10375
|
-
|
|
10376
|
-
|
|
10377
|
-
|
|
10378
|
-
|
|
10379
|
-
|
|
10380
|
-
|
|
10381
|
-
|
|
10472
|
+
const bar = toolbar === false ? null : (
|
|
10473
|
+
// a wrapped line (a chart's key, or controls on a phone) stands a row gap apart (Sprint 25.16 A43)
|
|
10474
|
+
/* @__PURE__ */ jsxs("div", { className: cn("flex shrink-0 flex-wrap items-center gap-x-ds-1 gap-y-ds-2 px-ds-2 py-ds-1.5 border-b-[length:var(--ds-border-width)]", border), children: [
|
|
10475
|
+
onZoomChange && levels.length > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10476
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Zoom out", "aria-disabled": !canZoomOut || void 0, className: "aria-disabled:opacity-disabled aria-disabled:cursor-not-allowed", onClick: () => zoom(1), children: /* @__PURE__ */ jsx(Icon, { name: "minus", size: 14 }) }),
|
|
10477
|
+
/* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "min-w-[4.5rem] text-center text-xs text-[var(--ds-text-secondary)]", children: ZOOM_NAMES[scale.zoom] }),
|
|
10478
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Zoom in", "aria-disabled": !canZoomIn || void 0, className: "aria-disabled:opacity-disabled aria-disabled:cursor-not-allowed", onClick: () => zoom(-1), children: /* @__PURE__ */ jsx(Icon, { name: "plus", size: 14 }) })
|
|
10479
|
+
] }),
|
|
10480
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Previous period", onClick: () => api.page(-1), children: /* @__PURE__ */ jsx(Icon, { name: "chevron-left", size: 14 }) }),
|
|
10481
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", disabled: todayAtX === null, onClick: () => {
|
|
10482
|
+
if (todayAtX !== null) setLeft(todayAtX - visibleWidth / 2);
|
|
10483
|
+
}, children: "Today" }),
|
|
10484
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Next period", onClick: () => api.page(1), children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14 }) }),
|
|
10485
|
+
toolbar
|
|
10486
|
+
] })
|
|
10487
|
+
);
|
|
10382
10488
|
return (
|
|
10383
10489
|
// Inline-size containment: the rows' width never widens the frame (in a grid or flex parent it would, and the
|
|
10384
10490
|
// wider frame would extend the scale again). The viewport takes the width it is given and scrolls inside it.
|
|
10385
|
-
/* @__PURE__ */ jsx("div", { "data-time-viewport": "", "data-compact": phone || void 0, className: cn("flex h-full min-h-0 w-full min-w-0 flex-col [contain:inline-size] bg-[var(--ds-bg-surface)]", className), onKeyDown, children: /* @__PURE__ */ jsx(TimeViewportCtx, { value: layout, children: /* @__PURE__ */ jsxs(TimeViewportScrollCtx, { value: store, children: [
|
|
10491
|
+
/* @__PURE__ */ jsx("div", { ref: rootRef, "data-time-viewport": "", "data-compact": phone || void 0, "data-fill": fill2 != null ? "" : void 0, className: cn("flex h-full min-h-0 w-full min-w-0 flex-col [contain:inline-size] bg-[var(--ds-bg-surface)]", className), style: fill2 != null ? { height: fill2 } : void 0, onKeyDown, children: /* @__PURE__ */ jsx(TimeViewportCtx, { value: layout, children: /* @__PURE__ */ jsxs(TimeViewportScrollCtx, { value: store, children: [
|
|
10386
10492
|
bar,
|
|
10387
10493
|
/* @__PURE__ */ jsxs("div", { className: "relative min-h-0 flex-1", children: [
|
|
10388
10494
|
/* @__PURE__ */ jsx(
|
|
@@ -10658,7 +10764,7 @@ function Cue({ name, size }) {
|
|
|
10658
10764
|
function Legend({ statuses }) {
|
|
10659
10765
|
const entries = Object.entries(statuses);
|
|
10660
10766
|
if (!entries.length) return null;
|
|
10661
|
-
return /* @__PURE__ */ jsx("ul", { "aria-label": "Status key", className: "
|
|
10767
|
+
return /* @__PURE__ */ jsx("ul", { "aria-label": "Status key", className: "flex flex-wrap items-center gap-x-ds-3 gap-y-ds-1 text-xs text-[var(--ds-text-secondary)]", children: entries.map(([key, s]) => {
|
|
10662
10768
|
const tone = TONES[s.tone] ?? TONES.neutral;
|
|
10663
10769
|
return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-ds-1.5", children: [
|
|
10664
10770
|
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn("grid size-4 shrink-0 place-items-center rounded-[var(--ds-radius-sm)]", EDGE, tone.fill, tone.on), children: /* @__PURE__ */ jsx(Cue, { name: s.icon ?? tone.icon, size: 10 }) }),
|
|
@@ -10706,6 +10812,7 @@ function Gantt({
|
|
|
10706
10812
|
"aria-label": ariaLabel,
|
|
10707
10813
|
className
|
|
10708
10814
|
}) {
|
|
10815
|
+
useScrollsInside();
|
|
10709
10816
|
const [zoomState, setZoomState] = useState(defaultZoom);
|
|
10710
10817
|
const zoom = zoomProp ?? zoomState;
|
|
10711
10818
|
const changeZoom = (next) => {
|
|
@@ -10999,6 +11106,8 @@ function Gantt({
|
|
|
10999
11106
|
};
|
|
11000
11107
|
const legend = /* @__PURE__ */ jsx(Legend, { statuses });
|
|
11001
11108
|
const legendApart = toolbar === false && hasStatuses;
|
|
11109
|
+
const apartRef = useRef(null);
|
|
11110
|
+
const apartFill = useFillHeight(apartRef, legendApart);
|
|
11002
11111
|
const chart = /* @__PURE__ */ jsx(
|
|
11003
11112
|
TimeViewport,
|
|
11004
11113
|
{
|
|
@@ -11008,6 +11117,7 @@ function Gantt({
|
|
|
11008
11117
|
labelHeader,
|
|
11009
11118
|
toolbar: toolbar === false ? false : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11010
11119
|
toolbar,
|
|
11120
|
+
hasStatuses && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "min-w-0 flex-1" }),
|
|
11011
11121
|
legend
|
|
11012
11122
|
] }),
|
|
11013
11123
|
tabStop: false,
|
|
@@ -11036,9 +11146,9 @@ function Gantt({
|
|
|
11036
11146
|
}
|
|
11037
11147
|
);
|
|
11038
11148
|
if (!legendApart) return chart;
|
|
11039
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full min-h-0 w-full min-w-0 flex-col", className), children: [
|
|
11040
|
-
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 px-ds-2 py-ds-1.5", children: legend }),
|
|
11041
|
-
chart
|
|
11149
|
+
return /* @__PURE__ */ jsxs("div", { ref: apartRef, "data-fill": apartFill != null ? "" : void 0, className: cn("flex h-full min-h-0 w-full min-w-0 flex-col", className), style: apartFill != null ? { height: apartFill } : void 0, children: [
|
|
11150
|
+
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 justify-end px-ds-2 py-ds-1.5", children: legend }),
|
|
11151
|
+
/* @__PURE__ */ jsx(FillContext, { value: true, children: chart })
|
|
11042
11152
|
] });
|
|
11043
11153
|
}
|
|
11044
11154
|
var DEFAULT_OFFSET2 = "var(--ds-space-4)";
|
|
@@ -11464,14 +11574,14 @@ function TabButton({
|
|
|
11464
11574
|
hasPanel
|
|
11465
11575
|
}) {
|
|
11466
11576
|
const { ref: truncRef, isTruncated } = useTextOverflow({ lines: 1, disabled: !truncate && orientation !== "horizontal" });
|
|
11467
|
-
const
|
|
11577
|
+
const isActive2 = activeTab === id;
|
|
11468
11578
|
const tabId = `ds-tab-${id}`;
|
|
11469
11579
|
const panelId = hasPanel === false ? void 0 : `ds-tabpanel-${id}`;
|
|
11470
11580
|
const badgeBg = orientation === "vertical" ? "bg-[var(--ds-nav-v-badge-bg)]" : "bg-[var(--ds-nav-h-badge-bg)]";
|
|
11471
11581
|
const countBadge = count !== void 0 ? /* @__PURE__ */ jsx("span", { className: cn(
|
|
11472
11582
|
orientation === "vertical" ? "ml-ds-2" : "",
|
|
11473
11583
|
"px-ds-1.5 py-ds-0.5 text-xs rounded-[var(--ds-radius-sm)]",
|
|
11474
|
-
|
|
11584
|
+
isActive2 ? cn(badgeBg, "text-[var(--ds-text-on-primary)]") : "bg-[var(--ds-bg-emphasis)] text-[var(--ds-text-muted)]"
|
|
11475
11585
|
), children: count }) : null;
|
|
11476
11586
|
if (orientation === "vertical") {
|
|
11477
11587
|
const btn2 = /* @__PURE__ */ jsxs(
|
|
@@ -11480,10 +11590,10 @@ function TabButton({
|
|
|
11480
11590
|
type: "button",
|
|
11481
11591
|
id: tabId,
|
|
11482
11592
|
role: "tab",
|
|
11483
|
-
"aria-selected":
|
|
11593
|
+
"aria-selected": isActive2,
|
|
11484
11594
|
"aria-controls": panelId,
|
|
11485
11595
|
"aria-disabled": disabled || void 0,
|
|
11486
|
-
tabIndex:
|
|
11596
|
+
tabIndex: isActive2 ? 0 : -1,
|
|
11487
11597
|
onClick: disabled ? void 0 : () => onTabChange(id),
|
|
11488
11598
|
onKeyDown,
|
|
11489
11599
|
className: cn(
|
|
@@ -11495,7 +11605,7 @@ function TabButton({
|
|
|
11495
11605
|
// Every item carries the rail width as a transparent placeholder so the
|
|
11496
11606
|
// label does not shift when the rail appears on the active item.
|
|
11497
11607
|
"border-l-[length:var(--ds-nav-v-active-rail)]",
|
|
11498
|
-
|
|
11608
|
+
isActive2 ? "bg-[var(--ds-nav-v-active-bg)] text-[var(--ds-nav-v-active-text)] border-[var(--ds-accent-primary)]" : "border-transparent text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-tab-hover-bg)]",
|
|
11499
11609
|
className
|
|
11500
11610
|
),
|
|
11501
11611
|
children: [
|
|
@@ -11516,26 +11626,29 @@ function TabButton({
|
|
|
11516
11626
|
type: "button",
|
|
11517
11627
|
id: tabId,
|
|
11518
11628
|
role: "tab",
|
|
11519
|
-
"aria-selected":
|
|
11629
|
+
"aria-selected": isActive2,
|
|
11520
11630
|
"aria-controls": panelId,
|
|
11521
11631
|
"aria-disabled": disabled || void 0,
|
|
11522
|
-
tabIndex:
|
|
11632
|
+
tabIndex: isActive2 ? 0 : -1,
|
|
11523
11633
|
onClick: disabled ? void 0 : () => onTabChange(id),
|
|
11524
11634
|
onKeyDown,
|
|
11525
11635
|
className: cn(
|
|
11526
|
-
|
|
11636
|
+
// Sprint 25.14 A38: a flex box, so the label sits in the middle of the tab. On a text line an icon's baseline
|
|
11637
|
+
// pushed the line 3 px taller and the label to its top (R28-72); a tab with an icon is now as tall as one
|
|
11638
|
+
// without, as a truncating tab (flex already) always was.
|
|
11639
|
+
"flex items-center justify-center px-ds-4 py-ds-2.5 text-sm font-medium",
|
|
11527
11640
|
// never wrap: the strip scrolls when the tabs do not fit (round 17, 54.4)
|
|
11528
11641
|
!fullWidth && !truncate && "shrink-0 whitespace-nowrap",
|
|
11529
11642
|
disabled ? "cursor-not-allowed opacity-disabled" : "cursor-pointer",
|
|
11530
11643
|
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
11531
11644
|
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
11532
11645
|
fullWidth && "flex-1",
|
|
11533
|
-
truncate && "flex-1 min-w-0
|
|
11646
|
+
truncate && "flex-1 min-w-0 justify-start",
|
|
11534
11647
|
"rounded-[var(--ds-nav-h-item-radius)]",
|
|
11535
|
-
|
|
11648
|
+
isActive2 ? "bg-[var(--ds-nav-h-active-bg)] text-[var(--ds-nav-h-active-text)] border-[var(--ds-accent-primary)]" : "text-[var(--ds-nav-h-inactive-text)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-nav-h-hover-bg)]",
|
|
11536
11649
|
className
|
|
11537
11650
|
),
|
|
11538
|
-
style:
|
|
11651
|
+
style: isActive2 ? { borderBottomWidth: "var(--ds-nav-h-indicator)", marginBottom: "calc(var(--ds-nav-h-track-border) * -1)" } : void 0,
|
|
11539
11652
|
children: truncate ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11540
11653
|
icon && /* @__PURE__ */ jsx(Icon, { name: icon, size: 16, className: "shrink-0" }),
|
|
11541
11654
|
/* @__PURE__ */ jsx("span", { ref: truncRef, className: "truncate min-w-0 flex-1", children: label }),
|
|
@@ -11764,241 +11877,6 @@ function SettingsLayout({
|
|
|
11764
11877
|
/* @__PURE__ */ jsx("div", { "data-settings-panel": "", className: cn("flex-1", PANEL_CLASSES), style: PANEL_STYLE, children })
|
|
11765
11878
|
] });
|
|
11766
11879
|
}
|
|
11767
|
-
function SeparatorIcon({ type, size }) {
|
|
11768
|
-
const iconSize = size === "sm" ? 10 : 12;
|
|
11769
|
-
if (type === "chevron") return /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: iconSize });
|
|
11770
|
-
if (type === "arrow") return /* @__PURE__ */ jsx(Icon, { name: "arrow-right", size: iconSize });
|
|
11771
|
-
if (type === "dot") return /* @__PURE__ */ jsx("span", { children: "\xB7" });
|
|
11772
|
-
return /* @__PURE__ */ jsx("span", { children: "/" });
|
|
11773
|
-
}
|
|
11774
|
-
var Breadcrumbs = forwardRef(function Breadcrumbs2({
|
|
11775
|
-
items,
|
|
11776
|
-
separator = "chevron",
|
|
11777
|
-
variant = "inline",
|
|
11778
|
-
itemVariant,
|
|
11779
|
-
size = "md",
|
|
11780
|
-
showIcons = false,
|
|
11781
|
-
maxItems,
|
|
11782
|
-
bleed = false,
|
|
11783
|
-
contentMaxWidth,
|
|
11784
|
-
className,
|
|
11785
|
-
container
|
|
11786
|
-
}, ref) {
|
|
11787
|
-
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
11788
|
-
const [activeIdx, setActiveIdx] = useState(0);
|
|
11789
|
-
const ellipsisBtnRef = useRef(null);
|
|
11790
|
-
const dropdownRef = useRef(null);
|
|
11791
|
-
const closeDropdown = useCallback(() => setDropdownOpen(false), []);
|
|
11792
|
-
const { isTop, returnFocus } = usePopupFocus(dropdownOpen, { trigger: ellipsisBtnRef, panel: dropdownRef, close: closeDropdown, tabExits: "any" });
|
|
11793
|
-
const pos = usePosition(ellipsisBtnRef, dropdownRef, dropdownOpen, { side: "bottom", align: "start", offset: 4, flip: true });
|
|
11794
|
-
const effectiveMaxItems = maxItems ? Math.max(maxItems, 2) : void 0;
|
|
11795
|
-
const shouldCollapse = effectiveMaxItems && items.length > effectiveMaxItems;
|
|
11796
|
-
const collapsedItems = shouldCollapse ? items.slice(1, -(effectiveMaxItems - 1)) : [];
|
|
11797
|
-
const visibleItems = shouldCollapse ? [...items.slice(0, 1), null, ...items.slice(-(effectiveMaxItems - 1))] : items;
|
|
11798
|
-
useEffect(() => {
|
|
11799
|
-
if (!dropdownOpen) return;
|
|
11800
|
-
const handler = (e) => {
|
|
11801
|
-
const target = e.target;
|
|
11802
|
-
if (ellipsisBtnRef.current?.contains(target) || dropdownRef.current?.contains(target)) return;
|
|
11803
|
-
setDropdownOpen(false);
|
|
11804
|
-
};
|
|
11805
|
-
const onKeyDown = (e) => {
|
|
11806
|
-
if (e.key !== "Escape" || e.defaultPrevented || !isTop()) return;
|
|
11807
|
-
e.preventDefault();
|
|
11808
|
-
returnFocus();
|
|
11809
|
-
setDropdownOpen(false);
|
|
11810
|
-
};
|
|
11811
|
-
document.addEventListener("mousedown", handler);
|
|
11812
|
-
document.addEventListener("keydown", onKeyDown);
|
|
11813
|
-
return () => {
|
|
11814
|
-
document.removeEventListener("mousedown", handler);
|
|
11815
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
11816
|
-
};
|
|
11817
|
-
}, [dropdownOpen, isTop, returnFocus]);
|
|
11818
|
-
useEffect(() => {
|
|
11819
|
-
if (!dropdownOpen) return;
|
|
11820
|
-
const id = requestAnimationFrame(() => dropdownRef.current?.querySelector(`[data-index="${activeIdx}"]`)?.focus());
|
|
11821
|
-
return () => cancelAnimationFrame(id);
|
|
11822
|
-
}, [dropdownOpen, activeIdx]);
|
|
11823
|
-
function onMenuKeyDown(e) {
|
|
11824
|
-
const last = collapsedItems.length - 1;
|
|
11825
|
-
const next = e.key === "ArrowDown" ? activeIdx >= last ? 0 : activeIdx + 1 : e.key === "ArrowUp" ? activeIdx <= 0 ? last : activeIdx - 1 : e.key === "Home" ? 0 : e.key === "End" ? last : null;
|
|
11826
|
-
if (next === null) return;
|
|
11827
|
-
e.preventDefault();
|
|
11828
|
-
setActiveIdx(next);
|
|
11829
|
-
}
|
|
11830
|
-
const textClass = size === "sm" ? "text-xs" : "text-sm";
|
|
11831
|
-
const gapClass = size === "sm" ? "gap-ds-1" : "gap-ds-1.5";
|
|
11832
|
-
const iconSize = size === "sm" ? 12 : 14;
|
|
11833
|
-
const isContainedBleed = variant === "contained" && bleed;
|
|
11834
|
-
const wrapperClasses = cn(
|
|
11835
|
-
variant === "contained" && !bleed && cn(
|
|
11836
|
-
"bg-[var(--ds-bg-muted)] rounded-[var(--ds-radius-md)]",
|
|
11837
|
-
size === "sm" ? "py-ds-1 px-ds-2" : "py-ds-1.5 px-ds-3"
|
|
11838
|
-
),
|
|
11839
|
-
!isContainedBleed && className
|
|
11840
|
-
);
|
|
11841
|
-
function renderItem(item, _index, isLast) {
|
|
11842
|
-
const isPill = itemVariant === "pill" || variant === "pill" && !itemVariant;
|
|
11843
|
-
const insideContained = variant === "contained";
|
|
11844
|
-
const pillClasses = isPill ? cn(
|
|
11845
|
-
"rounded-[var(--ds-radius-full)]",
|
|
11846
|
-
insideContained ? "bg-[var(--ds-bg-surface)]" : "bg-[var(--ds-bg-muted)]",
|
|
11847
|
-
size === "sm" ? "px-ds-2 py-[2px]" : "px-ds-2.5 py-ds-0.5"
|
|
11848
|
-
) : "";
|
|
11849
|
-
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11850
|
-
showIcons && item.icon && /* @__PURE__ */ jsx(Icon, { name: item.icon, size: iconSize, className: "shrink-0" }),
|
|
11851
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: item.label })
|
|
11852
|
-
] });
|
|
11853
|
-
if (isLast) {
|
|
11854
|
-
return /* @__PURE__ */ jsx(
|
|
11855
|
-
"span",
|
|
11856
|
-
{
|
|
11857
|
-
"aria-current": "page",
|
|
11858
|
-
className: cn(
|
|
11859
|
-
"font-medium text-[var(--ds-text-primary)] flex items-center",
|
|
11860
|
-
gapClass,
|
|
11861
|
-
pillClasses
|
|
11862
|
-
),
|
|
11863
|
-
children: content
|
|
11864
|
-
}
|
|
11865
|
-
);
|
|
11866
|
-
}
|
|
11867
|
-
return /* @__PURE__ */ jsx(
|
|
11868
|
-
"a",
|
|
11869
|
-
{
|
|
11870
|
-
href: item.href ?? "#",
|
|
11871
|
-
onClick: (e) => {
|
|
11872
|
-
e.preventDefault();
|
|
11873
|
-
item.onClick?.();
|
|
11874
|
-
},
|
|
11875
|
-
className: cn(
|
|
11876
|
-
"text-[var(--ds-text-secondary)] flex items-center",
|
|
11877
|
-
"hover:text-[var(--ds-text-primary)]",
|
|
11878
|
-
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
11879
|
-
gapClass,
|
|
11880
|
-
pillClasses
|
|
11881
|
-
),
|
|
11882
|
-
children: content
|
|
11883
|
-
}
|
|
11884
|
-
);
|
|
11885
|
-
}
|
|
11886
|
-
const listContent = /* @__PURE__ */ jsx("ol", { className: cn("flex items-center flex-wrap", gapClass, textClass), children: visibleItems.map((item, i) => {
|
|
11887
|
-
if (item === null) {
|
|
11888
|
-
return /* @__PURE__ */ jsxs("li", { className: cn("flex items-center", gapClass), children: [
|
|
11889
|
-
i > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-[var(--ds-text-secondary)] select-none flex items-center", children: /* @__PURE__ */ jsx(SeparatorIcon, { type: separator, size }) }),
|
|
11890
|
-
/* @__PURE__ */ jsx(
|
|
11891
|
-
"button",
|
|
11892
|
-
{
|
|
11893
|
-
type: "button",
|
|
11894
|
-
ref: ellipsisBtnRef,
|
|
11895
|
-
onClick: () => {
|
|
11896
|
-
if (!dropdownOpen) setActiveIdx(0);
|
|
11897
|
-
setDropdownOpen(!dropdownOpen);
|
|
11898
|
-
},
|
|
11899
|
-
"aria-label": "Show hidden breadcrumbs",
|
|
11900
|
-
"aria-expanded": dropdownOpen,
|
|
11901
|
-
"aria-haspopup": "menu",
|
|
11902
|
-
className: cn(
|
|
11903
|
-
"text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)]",
|
|
11904
|
-
"transition-colors duration-[var(--ds-transition-speed)] cursor-pointer",
|
|
11905
|
-
"flex items-center",
|
|
11906
|
-
(itemVariant === "pill" || variant === "pill" && !itemVariant) && cn(
|
|
11907
|
-
"rounded-[var(--ds-radius-full)]",
|
|
11908
|
-
variant === "contained" ? "bg-[var(--ds-bg-surface)]" : "bg-[var(--ds-bg-muted)]",
|
|
11909
|
-
size === "sm" ? "px-ds-2 py-[2px]" : "px-ds-2.5 py-ds-0.5"
|
|
11910
|
-
)
|
|
11911
|
-
),
|
|
11912
|
-
children: "\xB7\xB7\xB7"
|
|
11913
|
-
}
|
|
11914
|
-
)
|
|
11915
|
-
] }, "__ellipsis");
|
|
11916
|
-
}
|
|
11917
|
-
const isLast = i === visibleItems.length - 1;
|
|
11918
|
-
return /* @__PURE__ */ jsxs("li", { className: cn("flex items-center", gapClass), children: [
|
|
11919
|
-
i > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "text-[var(--ds-text-secondary)] select-none flex items-center", children: /* @__PURE__ */ jsx(SeparatorIcon, { type: separator, size }) }),
|
|
11920
|
-
renderItem(item, i, isLast)
|
|
11921
|
-
] }, i);
|
|
11922
|
-
}) });
|
|
11923
|
-
const dropdown = dropdownOpen && collapsedItems.length > 0 && createPortal(
|
|
11924
|
-
/* @__PURE__ */ jsx(
|
|
11925
|
-
"div",
|
|
11926
|
-
{
|
|
11927
|
-
ref: dropdownRef,
|
|
11928
|
-
role: "menu",
|
|
11929
|
-
"aria-label": "Hidden breadcrumbs",
|
|
11930
|
-
onKeyDown: onMenuKeyDown,
|
|
11931
|
-
className: cn(
|
|
11932
|
-
"fixed z-[var(--ds-z-popover)] min-w-[160px] max-h-60 overflow-auto",
|
|
11933
|
-
"bg-[var(--ds-bg-surface-elevated)]",
|
|
11934
|
-
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
11935
|
-
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
11936
|
-
"rounded-[var(--ds-radius-md)]",
|
|
11937
|
-
"shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]",
|
|
11938
|
-
"py-ds-1"
|
|
11939
|
-
),
|
|
11940
|
-
style: { top: pos.top, left: pos.left },
|
|
11941
|
-
children: collapsedItems.map((ci, idx) => /* @__PURE__ */ jsxs(
|
|
11942
|
-
"button",
|
|
11943
|
-
{
|
|
11944
|
-
type: "button",
|
|
11945
|
-
"data-index": idx,
|
|
11946
|
-
role: "menuitem",
|
|
11947
|
-
tabIndex: idx === activeIdx ? 0 : -1,
|
|
11948
|
-
className: cn(
|
|
11949
|
-
"flex items-center w-full text-left text-sm cursor-pointer",
|
|
11950
|
-
"px-ds-3 py-ds-1.5 transition-colors",
|
|
11951
|
-
"text-[var(--ds-text-secondary)]",
|
|
11952
|
-
"hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]",
|
|
11953
|
-
"focus-visible:outline-none focus-visible:bg-[var(--ds-bg-muted)] focus-visible:text-[var(--ds-text-primary)] focus-visible:shadow-[inset_var(--ds-shadow-focus)]",
|
|
11954
|
-
gapClass
|
|
11955
|
-
),
|
|
11956
|
-
onClick: () => {
|
|
11957
|
-
setDropdownOpen(false);
|
|
11958
|
-
ci.onClick?.();
|
|
11959
|
-
},
|
|
11960
|
-
children: [
|
|
11961
|
-
showIcons && ci.icon && /* @__PURE__ */ jsx(Icon, { name: ci.icon, size: iconSize, className: "shrink-0" }),
|
|
11962
|
-
ci.label
|
|
11963
|
-
]
|
|
11964
|
-
},
|
|
11965
|
-
idx
|
|
11966
|
-
))
|
|
11967
|
-
}
|
|
11968
|
-
),
|
|
11969
|
-
container ?? document.body
|
|
11970
|
-
);
|
|
11971
|
-
if (isContainedBleed) {
|
|
11972
|
-
return /* @__PURE__ */ jsxs(
|
|
11973
|
-
"nav",
|
|
11974
|
-
{
|
|
11975
|
-
ref,
|
|
11976
|
-
"aria-label": "Breadcrumb",
|
|
11977
|
-
className: cn(
|
|
11978
|
-
"w-full bg-[var(--ds-bg-muted)]",
|
|
11979
|
-
// Hairline under the band: it sits within ~1.2:1 of both canvas and a tinted header, so the edge needs a line.
|
|
11980
|
-
"border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
11981
|
-
className
|
|
11982
|
-
),
|
|
11983
|
-
children: [
|
|
11984
|
-
/* @__PURE__ */ jsx(
|
|
11985
|
-
"div",
|
|
11986
|
-
{
|
|
11987
|
-
className: cn("w-full mx-auto px-ds-6", size === "sm" ? "py-ds-1" : "py-ds-1.5"),
|
|
11988
|
-
style: { maxWidth: contentMaxWidth ?? "var(--ds-bp-xl)" },
|
|
11989
|
-
children: listContent
|
|
11990
|
-
}
|
|
11991
|
-
),
|
|
11992
|
-
dropdown
|
|
11993
|
-
]
|
|
11994
|
-
}
|
|
11995
|
-
);
|
|
11996
|
-
}
|
|
11997
|
-
return /* @__PURE__ */ jsxs("nav", { ref, "aria-label": "Breadcrumb", className: wrapperClasses, children: [
|
|
11998
|
-
listContent,
|
|
11999
|
-
dropdown
|
|
12000
|
-
] });
|
|
12001
|
-
});
|
|
12002
11880
|
var HeaderTabRowContext = createContext(null);
|
|
12003
11881
|
function useHeaderTabRow() {
|
|
12004
11882
|
return useContext(HeaderTabRowContext);
|
|
@@ -12051,13 +11929,13 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12051
11929
|
const isLast = i === steps.length - 1;
|
|
12052
11930
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col items-start min-w-0", isLast ? "flex-none" : "flex-1"), children: [
|
|
12053
11931
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center w-full", children: [
|
|
12054
|
-
/* @__PURE__ */ jsx(StepCircle, { status, index: i, onClick: onStepChange ? () => onStepChange(i) : void 0, clickable: !!onStepChange }),
|
|
11932
|
+
/* @__PURE__ */ jsx(StepCircle, { status, index: i, label: step.label, onClick: onStepChange && !step.disabled ? () => onStepChange(i) : void 0, clickable: !!onStepChange && !step.disabled }),
|
|
12055
11933
|
!isLast && /* @__PURE__ */ jsx(
|
|
12056
11934
|
"div",
|
|
12057
11935
|
{
|
|
12058
11936
|
className: cn(
|
|
12059
11937
|
"flex-1 h-0.5 mx-ds-2 transition-colors",
|
|
12060
|
-
i < currentStep ? "bg-[var(--ds-accent-primary)]" : "bg-[var(--ds-border-subtle)]"
|
|
11938
|
+
i < currentStep || steps[i + 1]?.status === "complete" ? "bg-[var(--ds-accent-primary)]" : "bg-[var(--ds-border-subtle)]"
|
|
12061
11939
|
)
|
|
12062
11940
|
}
|
|
12063
11941
|
)
|
|
@@ -12084,13 +11962,13 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12084
11962
|
const isLast = i === steps.length - 1;
|
|
12085
11963
|
return /* @__PURE__ */ jsxs("div", { className: "flex gap-ds-3", children: [
|
|
12086
11964
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
|
|
12087
|
-
/* @__PURE__ */ jsx(StepCircle, { status, index: i, onClick: onStepChange ? () => onStepChange(i) : void 0, clickable: !!onStepChange }),
|
|
11965
|
+
/* @__PURE__ */ jsx(StepCircle, { status, index: i, label: step.label, onClick: onStepChange && !step.disabled ? () => onStepChange(i) : void 0, clickable: !!onStepChange && !step.disabled }),
|
|
12088
11966
|
!isLast && /* @__PURE__ */ jsx(
|
|
12089
11967
|
"div",
|
|
12090
11968
|
{
|
|
12091
11969
|
className: cn(
|
|
12092
11970
|
"w-0.5 flex-1 min-h-6 transition-colors",
|
|
12093
|
-
i < currentStep ? "bg-[var(--ds-accent-primary)]" : "bg-[var(--ds-border-subtle)]"
|
|
11971
|
+
i < currentStep || steps[i + 1]?.status === "complete" ? "bg-[var(--ds-accent-primary)]" : "bg-[var(--ds-border-subtle)]"
|
|
12094
11972
|
)
|
|
12095
11973
|
}
|
|
12096
11974
|
)
|
|
@@ -12131,13 +12009,13 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12131
12009
|
)
|
|
12132
12010
|
}
|
|
12133
12011
|
),
|
|
12134
|
-
/* @__PURE__ */ jsx(StepCircle, { status, index: i, onClick: onStepChange ? () => onStepChange(i) : void 0, clickable: !!onStepChange }),
|
|
12012
|
+
/* @__PURE__ */ jsx(StepCircle, { status, index: i, label: step.label, onClick: onStepChange && !step.disabled ? () => onStepChange(i) : void 0, clickable: !!onStepChange && !step.disabled }),
|
|
12135
12013
|
/* @__PURE__ */ jsx(
|
|
12136
12014
|
"div",
|
|
12137
12015
|
{
|
|
12138
12016
|
className: cn(
|
|
12139
12017
|
"flex-1 h-0.5 transition-colors",
|
|
12140
|
-
isLast ? "bg-transparent" : i < currentStep ? "bg-[var(--ds-accent-primary)]" : "bg-[var(--ds-border-subtle)]"
|
|
12018
|
+
isLast ? "bg-transparent" : i < currentStep || steps[i + 1]?.status === "complete" ? "bg-[var(--ds-accent-primary)]" : "bg-[var(--ds-border-subtle)]"
|
|
12141
12019
|
)
|
|
12142
12020
|
}
|
|
12143
12021
|
)
|
|
@@ -12160,13 +12038,14 @@ function Stepper({ steps, currentStep, onStepChange, orientation = "horizontal",
|
|
|
12160
12038
|
}
|
|
12161
12039
|
);
|
|
12162
12040
|
}
|
|
12163
|
-
function StepCircle({ status, index, onClick, clickable }) {
|
|
12041
|
+
function StepCircle({ status, index, label, onClick, clickable }) {
|
|
12164
12042
|
return /* @__PURE__ */ jsx(
|
|
12165
12043
|
"button",
|
|
12166
12044
|
{
|
|
12167
12045
|
type: "button",
|
|
12168
12046
|
onClick,
|
|
12169
12047
|
disabled: !clickable,
|
|
12048
|
+
"aria-label": `Step ${index + 1}: ${label}${status === "complete" ? ", completed" : ""}`,
|
|
12170
12049
|
"aria-current": status === "current" ? "step" : void 0,
|
|
12171
12050
|
className: cn(
|
|
12172
12051
|
"flex items-center justify-center shrink-0 w-8 h-8 rounded-[var(--ds-radius-full)] text-xs font-bold transition-colors",
|
|
@@ -12177,7 +12056,9 @@ function StepCircle({ status, index, onClick, clickable }) {
|
|
|
12177
12056
|
status === "current" && `border-2 ${ACTIVE_RING} text-[var(--ds-accent-primary)] bg-[var(--ds-bg-surface)]`,
|
|
12178
12057
|
status === "error" && "bg-[var(--ds-status-error)] text-[var(--ds-text-on-error)]",
|
|
12179
12058
|
status === "loading" && `border-2 ${ACTIVE_RING} text-[var(--ds-accent-primary)] bg-[var(--ds-bg-surface)] animate-pulse`,
|
|
12180
|
-
status === "upcoming" && "border-[length:var(--ds-border-width)] border-[var(--ds-border-default)] text-[var(--ds-text-muted)] bg-[var(--ds-bg-surface)]"
|
|
12059
|
+
status === "upcoming" && "border-[length:var(--ds-border-width)] border-[var(--ds-border-default)] text-[var(--ds-text-muted)] bg-[var(--ds-bg-surface)]",
|
|
12060
|
+
// a step reached but not done (the user went back) can be gone to: it answers the pointer as the done ones do
|
|
12061
|
+
status === "upcoming" && clickable && "hover:border-[var(--ds-accent-primary)] hover:text-[var(--ds-accent-primary)]"
|
|
12181
12062
|
),
|
|
12182
12063
|
children: status === "complete" ? /* @__PURE__ */ jsx(Icon, { name: "check", size: 14 }) : status === "error" ? /* @__PURE__ */ jsx(Icon, { name: "warning", size: 14 }) : index + 1
|
|
12183
12064
|
}
|
|
@@ -12509,17 +12390,13 @@ function TruncLabel3({ children, className, side = "right", container, lines = 1
|
|
|
12509
12390
|
if (!isTruncated) return label;
|
|
12510
12391
|
return /* @__PURE__ */ jsx(Tooltip, { content: children, side, delay: 200, container, children: label });
|
|
12511
12392
|
}
|
|
12512
|
-
|
|
12513
|
-
return items.some(
|
|
12514
|
-
(it) => it.active || it.children && hasActiveDescendant(it.children)
|
|
12515
|
-
);
|
|
12516
|
-
}
|
|
12393
|
+
var isActive = (item) => !!item.active;
|
|
12517
12394
|
function collectInitialExpanded(items, prefix = "") {
|
|
12518
12395
|
const keys = [];
|
|
12519
12396
|
for (const item of items) {
|
|
12520
12397
|
if (!item.children?.length) continue;
|
|
12521
12398
|
const key = prefix ? `${prefix}/${item.label}` : item.label;
|
|
12522
|
-
if (item.defaultExpanded ||
|
|
12399
|
+
if (item.defaultExpanded || holdsCurrent(item.children, isActive)) {
|
|
12523
12400
|
keys.push(key);
|
|
12524
12401
|
}
|
|
12525
12402
|
keys.push(...collectInitialExpanded(item.children, key));
|
|
@@ -12741,7 +12618,7 @@ function SidebarNav({
|
|
|
12741
12618
|
function renderCompactItem(item, index, parentKey) {
|
|
12742
12619
|
const hasChildren = !!item.children?.length;
|
|
12743
12620
|
const key = makeKey(item.label, parentKey);
|
|
12744
|
-
const childActive = hasChildren &&
|
|
12621
|
+
const childActive = hasChildren && holdsCurrent(item.children, isActive);
|
|
12745
12622
|
const isOpen = openFlyout === key;
|
|
12746
12623
|
return /* @__PURE__ */ jsx(
|
|
12747
12624
|
CompactNavItem,
|
|
@@ -12775,7 +12652,7 @@ function SidebarNav({
|
|
|
12775
12652
|
return renderLeaf(item, depth, index);
|
|
12776
12653
|
}
|
|
12777
12654
|
const isExpanded = expandedItems.has(key);
|
|
12778
|
-
const childActive =
|
|
12655
|
+
const childActive = holdsCurrent(item.children, isActive);
|
|
12779
12656
|
const isRoot = depth === 0;
|
|
12780
12657
|
const rootPy = isSm ? "py-ds-1.5" : "py-ds-2";
|
|
12781
12658
|
const childPy = isSm ? "py-ds-1" : "py-ds-1.5";
|
|
@@ -13345,7 +13222,7 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
13345
13222
|
const noteShown = useCallback((id, variant, action, fresh) => {
|
|
13346
13223
|
if (runs.current.size) shownDuringRuns.current.push({ seq: ++showSeq.current, at: Date.now(), id, variant, action, fresh });
|
|
13347
13224
|
}, []);
|
|
13348
|
-
const
|
|
13225
|
+
const update2 = useCallback((id, message, options = {}) => {
|
|
13349
13226
|
const list2 = entries.current;
|
|
13350
13227
|
const at = list2.findIndex((t2) => t2.id === id);
|
|
13351
13228
|
if (at === -1) return;
|
|
@@ -13395,21 +13272,21 @@ function ToastProvider({ children, maxVisible = 3, position = "bottom-right", du
|
|
|
13395
13272
|
success: (m, o) => toast(m, { ...o, variant: "success" }),
|
|
13396
13273
|
warning: (m, o) => toast(m, { ...o, variant: "warning" }),
|
|
13397
13274
|
error: (m, o) => toast(m, { ...o, variant: "error" }),
|
|
13398
|
-
update,
|
|
13275
|
+
update: update2,
|
|
13399
13276
|
dismiss: remove,
|
|
13400
13277
|
dismissAll,
|
|
13401
13278
|
promise: async (promise, messages, options = {}) => {
|
|
13402
13279
|
const id = toast(messages.loading, { ...options, variant: "default", duration: Infinity });
|
|
13403
13280
|
try {
|
|
13404
13281
|
const value = await promise;
|
|
13405
|
-
|
|
13282
|
+
update2(id, typeof messages.success === "function" ? messages.success(value) : messages.success, { variant: "success", duration });
|
|
13406
13283
|
return value;
|
|
13407
13284
|
} catch (err) {
|
|
13408
|
-
|
|
13285
|
+
update2(id, typeof messages.error === "function" ? messages.error(err) : messages.error, { variant: "error", duration });
|
|
13409
13286
|
throw err;
|
|
13410
13287
|
}
|
|
13411
13288
|
}
|
|
13412
|
-
}), [toast,
|
|
13289
|
+
}), [toast, update2, remove, dismissAll, duration]);
|
|
13413
13290
|
const ledger = useMemo(() => ({
|
|
13414
13291
|
begin: () => {
|
|
13415
13292
|
const run = ++runSeq.current;
|
|
@@ -13737,18 +13614,20 @@ function pageMaxWidth(resolved) {
|
|
|
13737
13614
|
}
|
|
13738
13615
|
var paddingClasses = {
|
|
13739
13616
|
none: "",
|
|
13740
|
-
|
|
13617
|
+
// the page's gutter, which an overlay's header, body and footer share (Sprint 25.14 A36)
|
|
13618
|
+
default: "px-[var(--ds-page-gutter)]",
|
|
13741
13619
|
wide: "px-ds-10"
|
|
13742
13620
|
};
|
|
13621
|
+
var FILLED_BOTTOM = "has-[[data-fill]]:pb-[var(--ds-page-gutter)]";
|
|
13743
13622
|
var verticalPaddingClasses = {
|
|
13744
13623
|
none: "",
|
|
13745
|
-
default:
|
|
13746
|
-
spacious:
|
|
13624
|
+
default: `pt-ds-8 pb-ds-12 ${FILLED_BOTTOM}`,
|
|
13625
|
+
spacious: `pt-ds-8 pb-ds-16 ${FILLED_BOTTOM}`
|
|
13747
13626
|
};
|
|
13748
13627
|
var bottomPaddingClasses = {
|
|
13749
13628
|
none: "",
|
|
13750
|
-
default:
|
|
13751
|
-
spacious:
|
|
13629
|
+
default: `pb-ds-12 ${FILLED_BOTTOM}`,
|
|
13630
|
+
spacious: `pb-ds-16 ${FILLED_BOTTOM}`
|
|
13752
13631
|
};
|
|
13753
13632
|
var bottomPaddingValues = {
|
|
13754
13633
|
none: "0px",
|
|
@@ -13771,6 +13650,38 @@ function useContentWidth(width) {
|
|
|
13771
13650
|
return () => request(null);
|
|
13772
13651
|
}, [request, width]);
|
|
13773
13652
|
}
|
|
13653
|
+
function PageActions({ children }) {
|
|
13654
|
+
const slot = useContext(PageActionsCtx);
|
|
13655
|
+
const add = slot?.add;
|
|
13656
|
+
useEffect(() => add?.(), [add]);
|
|
13657
|
+
const target = slot?.target;
|
|
13658
|
+
return target ? createPortal(/* @__PURE__ */ jsx(ControlSizeContext, { value: target.size, children }), target.el) : null;
|
|
13659
|
+
}
|
|
13660
|
+
var pageOrder = (a, b) => a.el.compareDocumentPosition(b.el) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
|
|
13661
|
+
function usePageActionsSlot() {
|
|
13662
|
+
const outer = useContext(PageActionsCtx);
|
|
13663
|
+
const [asking, setAsking] = useState(0);
|
|
13664
|
+
const [slots, setSlots] = useState([]);
|
|
13665
|
+
const register = useCallback((el, size) => {
|
|
13666
|
+
setSlots((list) => [...list.filter((s) => s.el !== el), { el, size }]);
|
|
13667
|
+
return () => setSlots((list) => list.filter((s) => s.el !== el));
|
|
13668
|
+
}, []);
|
|
13669
|
+
const outerAdd = outer?.add;
|
|
13670
|
+
const add = useCallback(() => {
|
|
13671
|
+
setAsking((n) => n + 1);
|
|
13672
|
+
const releaseOuter = outerAdd?.();
|
|
13673
|
+
let released = false;
|
|
13674
|
+
return () => {
|
|
13675
|
+
if (released) return;
|
|
13676
|
+
released = true;
|
|
13677
|
+
setAsking((n) => n - 1);
|
|
13678
|
+
releaseOuter?.();
|
|
13679
|
+
};
|
|
13680
|
+
}, [outerAdd]);
|
|
13681
|
+
const own = useMemo(() => [...slots].sort(pageOrder)[0] ?? null, [slots]);
|
|
13682
|
+
const target = own ?? outer?.target ?? null;
|
|
13683
|
+
return useMemo(() => ({ wanted: asking > 0, target, register, add }), [asking, target, register, add]);
|
|
13684
|
+
}
|
|
13774
13685
|
function usePageContainer() {
|
|
13775
13686
|
return useContext(PageContainerContext);
|
|
13776
13687
|
}
|
|
@@ -13847,6 +13758,7 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
13847
13758
|
headerCount.current = Math.max(0, headerCount.current + (present ? 1 : -1));
|
|
13848
13759
|
setWrappedHeader(headerCount.current > 0);
|
|
13849
13760
|
}, []);
|
|
13761
|
+
const pageActions = usePageActionsSlot();
|
|
13850
13762
|
const launcherCorner = shell?.launcherCorner ?? null;
|
|
13851
13763
|
const vPad = verticalPadding ?? "default";
|
|
13852
13764
|
const launcherPadding = launcherCorner ? { paddingBottom: `max(${bottomPaddingValues[vPad]}, var(--ds-toast-inset-${launcherCorner}, 0px))` } : {};
|
|
@@ -13892,7 +13804,7 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
13892
13804
|
observedRef.current = null;
|
|
13893
13805
|
}, []);
|
|
13894
13806
|
if (headerIdx === -1 || !headerEl || !r) {
|
|
13895
|
-
return /* @__PURE__ */ jsx(PageContainerContext, { value: { contentMaxWidth: maxWidthValue, placement: "inside", containedBreadcrumbs: false, breadcrumbsInsideHeader: false, noBottomMargin: false, overlap: false, setPinnedHeight, reportHeader, requestContentWidth, insidePaddedColumn: true }, children: /* @__PURE__ */ jsx(
|
|
13807
|
+
return /* @__PURE__ */ jsx(PageActionsCtx, { value: pageActions, children: /* @__PURE__ */ jsx(PageContainerContext, { value: { contentMaxWidth: maxWidthValue, placement: "inside", containedBreadcrumbs: false, breadcrumbsInsideHeader: false, noBottomMargin: false, overlap: false, setPinnedHeight, reportHeader, requestContentWidth, insidePaddedColumn: true }, children: /* @__PURE__ */ jsx(
|
|
13896
13808
|
"div",
|
|
13897
13809
|
{
|
|
13898
13810
|
ref: setRoot,
|
|
@@ -13908,7 +13820,7 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
13908
13820
|
style: { maxWidth: maxWidthValue, containerType: "inline-size", ...launcherPadding },
|
|
13909
13821
|
children: capped(children)
|
|
13910
13822
|
}
|
|
13911
|
-
) });
|
|
13823
|
+
) }) });
|
|
13912
13824
|
}
|
|
13913
13825
|
const rest = kids.filter((_, i) => i !== headerIdx);
|
|
13914
13826
|
const snapping = r.behavior === "snapping";
|
|
@@ -13929,7 +13841,7 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
13929
13841
|
...overlapActive ? { marginTop: "calc(-1 * var(--ds-overlap, 0px))", position: "relative", zIndex: 1 } : {}
|
|
13930
13842
|
} : void 0;
|
|
13931
13843
|
const column = /* @__PURE__ */ jsx(PageContainerContext, { value: { contentMaxWidth: maxWidthValue, placement: "inside", containedBreadcrumbs: false, breadcrumbsInsideHeader: false, noBottomMargin: false, overlap: false, setPinnedHeight, reportHeader, requestContentWidth, insidePaddedColumn: true }, children: /* @__PURE__ */ jsx("div", { ref: columnRef, className: cn(columnClass(contentPadding), bottomPaddingClasses[vPad], className), style: { ...columnStyle, ...launcherPadding }, children: capped(rest) }) });
|
|
13932
|
-
return /* @__PURE__ */ jsxs("div", { ref: setRoot, "data-page-container": "", "data-width": dataWidth, className: "w-full", children: [
|
|
13844
|
+
return /* @__PURE__ */ jsx(PageActionsCtx, { value: pageActions, children: /* @__PURE__ */ jsxs("div", { ref: setRoot, "data-page-container": "", "data-width": dataWidth, className: "w-full", children: [
|
|
13933
13845
|
placement === "block" ? /* @__PURE__ */ jsx("div", { style: floatingBlockPadding(r.navbarFloating, r.sidebarFloating, overlapActive), children: /* @__PURE__ */ jsxs("div", { className: FLOATING_BLOCK, children: [
|
|
13934
13846
|
strip,
|
|
13935
13847
|
colourful ? header : /* @__PURE__ */ jsx("div", { className: columnClass(padding), style: columnStyle, children: header })
|
|
@@ -13941,7 +13853,7 @@ var PageContainer = forwardRef(function PageContainer2({
|
|
|
13941
13853
|
/* @__PURE__ */ jsx("div", { className: columnClass(padding), style: columnStyle, children: header })
|
|
13942
13854
|
] }),
|
|
13943
13855
|
wrapperStyle ? /* @__PURE__ */ jsx("div", { style: wrapperStyle, children: column }) : column
|
|
13944
|
-
] });
|
|
13856
|
+
] }) });
|
|
13945
13857
|
});
|
|
13946
13858
|
function TruncHeading({ as: Tag3 = "h1", className, children, lines: linesProp }) {
|
|
13947
13859
|
const lines = linesProp ?? (Tag3 === "h1" ? 2 : 1);
|
|
@@ -13969,7 +13881,8 @@ function outerHeight(el) {
|
|
|
13969
13881
|
const s = getComputedStyle(el);
|
|
13970
13882
|
return el.getBoundingClientRect().height + (parseFloat(s.marginTop) || 0) + (parseFloat(s.marginBottom) || 0);
|
|
13971
13883
|
}
|
|
13972
|
-
function
|
|
13884
|
+
function Breadcrumbs2({ items, onLight, onTint, pill, separator = "chevron" }) {
|
|
13885
|
+
const follow = useCrumbFollow();
|
|
13973
13886
|
if (!items.length) return null;
|
|
13974
13887
|
const mutedCls = onLight ? "text-[var(--ds-text-on-primary)]/40" : onTint ? "text-[var(--ds-text-muted-on-tint)]" : "text-[var(--ds-text-secondary)]";
|
|
13975
13888
|
const sepEl = (key) => {
|
|
@@ -13984,17 +13897,15 @@ function Breadcrumbs3({ items, onLight, onTint, pill, separator = "chevron" }) {
|
|
|
13984
13897
|
onLight ? "bg-[var(--ds-text-on-primary)]/10" : onTint ? "bg-[var(--ds-bg-surface)]/70" : "bg-[var(--ds-bg-muted)]"
|
|
13985
13898
|
) : "";
|
|
13986
13899
|
return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsx("ol", { className: "flex items-center gap-ds-1.5 text-sm", children: items.map((item, i) => {
|
|
13987
|
-
const isNavigable =
|
|
13900
|
+
const isNavigable = crumbGoes(item);
|
|
13901
|
+
const isCurrent = !isNavigable && i === items.length - 1;
|
|
13988
13902
|
return /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-ds-1.5", children: [
|
|
13989
13903
|
i > 0 && sepEl(i),
|
|
13990
13904
|
isNavigable ? /* @__PURE__ */ jsx(
|
|
13991
13905
|
"a",
|
|
13992
13906
|
{
|
|
13993
13907
|
href: item.href ?? "#",
|
|
13994
|
-
onClick: (e) =>
|
|
13995
|
-
e.preventDefault();
|
|
13996
|
-
item.onClick?.();
|
|
13997
|
-
},
|
|
13908
|
+
onClick: (e) => follow(e, item),
|
|
13998
13909
|
className: cn(
|
|
13999
13910
|
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
14000
13911
|
onLight ? "text-[var(--ds-text-on-primary)]/60 hover:text-[var(--ds-text-on-primary)]/90" : cn(mutedCls, "hover:text-[var(--ds-text-primary)]"),
|
|
@@ -14002,9 +13913,8 @@ function Breadcrumbs3({ items, onLight, onTint, pill, separator = "chevron" }) {
|
|
|
14002
13913
|
),
|
|
14003
13914
|
children: item.label
|
|
14004
13915
|
}
|
|
14005
|
-
) : /* @__PURE__ */ jsx("span", { className: cn(
|
|
14006
|
-
"font-medium",
|
|
14007
|
-
onLight ? "text-[var(--ds-text-on-primary)]/80" : "text-[var(--ds-text-primary)]",
|
|
13916
|
+
) : /* @__PURE__ */ jsx("span", { "aria-current": isCurrent ? "page" : void 0, className: cn(
|
|
13917
|
+
isCurrent ? cn("font-medium", onLight ? "text-[var(--ds-text-on-primary)]/80" : "text-[var(--ds-text-primary)]") : onLight ? "text-[var(--ds-text-on-primary)]/60" : mutedCls,
|
|
14008
13918
|
pillCls
|
|
14009
13919
|
), children: item.label })
|
|
14010
13920
|
] }, i);
|
|
@@ -14019,6 +13929,11 @@ function TintWash() {
|
|
|
14019
13929
|
}
|
|
14020
13930
|
);
|
|
14021
13931
|
}
|
|
13932
|
+
function PageActionsSlotMark({ register }) {
|
|
13933
|
+
const size = useContext(ControlSizeContext);
|
|
13934
|
+
const ref = useCallback((el) => el ? register(el, size) : void 0, [register, size]);
|
|
13935
|
+
return /* @__PURE__ */ jsx("span", { ref, "data-page-actions": "", className: "contents" });
|
|
13936
|
+
}
|
|
14022
13937
|
function BackButton({ onLight, onClick }) {
|
|
14023
13938
|
return /* @__PURE__ */ jsx(
|
|
14024
13939
|
"button",
|
|
@@ -14065,10 +13980,18 @@ function Caption({ children, onLight, onTint }) {
|
|
|
14065
13980
|
onLight ? "text-[var(--ds-text-on-primary)]/80" : onTint ? "text-[var(--ds-text-muted-on-tint)]" : "text-[var(--ds-text-secondary)]"
|
|
14066
13981
|
), children });
|
|
14067
13982
|
}
|
|
13983
|
+
var ON_BAND_STRIP = cn(
|
|
13984
|
+
"rounded-[var(--ds-radius-md)] px-ds-3 py-ds-2 border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
13985
|
+
"bg-[var(--ds-bg-surface)] supports-[color:oklch(from_red_l_c_h)]:bg-[oklch(from_var(--ds-bg-surface)_l_c_h_/_max(alpha,min(1,alpha*1000)*0.6))]",
|
|
13986
|
+
GLASS_SURFACE
|
|
13987
|
+
);
|
|
14068
13988
|
function TabRow({ children, hasCaption, className, onBand }) {
|
|
14069
13989
|
const [row, setRow] = useState(null);
|
|
14070
13990
|
const value = useMemo(() => ({ row, hasCaption }), [row, hasCaption]);
|
|
14071
|
-
return /* @__PURE__ */ jsx("div", { ref: setRow, className: cn(className, onBand && "mx-0
|
|
13991
|
+
return /* @__PURE__ */ jsx("div", { ref: setRow, className: cn(className, onBand && cn("mx-0", ON_BAND_STRIP)), children: /* @__PURE__ */ jsx(HeaderTabRowContext.Provider, { value, children }) });
|
|
13992
|
+
}
|
|
13993
|
+
function FilterRow({ children, className, onBand }) {
|
|
13994
|
+
return /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx(FilterRowContext.Provider, { value: true, children: /* @__PURE__ */ jsx("div", { "data-gs": "filter-row", className: cn("flex items-center flex-wrap gap-ds-3", className, onBand && cn("w-fit max-w-full", ON_BAND_STRIP)), children }) }) });
|
|
14072
13995
|
}
|
|
14073
13996
|
var FLOATING_HEADER = cn(
|
|
14074
13997
|
"rounded-[var(--ds-radius-md)]",
|
|
@@ -14117,6 +14040,11 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
14117
14040
|
}, ref) {
|
|
14118
14041
|
const shell = useAppShell();
|
|
14119
14042
|
const container = usePageContainer();
|
|
14043
|
+
const pageActions = useContext(PageActionsCtx);
|
|
14044
|
+
const shownActions = pageActions?.wanted ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14045
|
+
actions,
|
|
14046
|
+
/* @__PURE__ */ jsx(PageActionsSlotMark, { register: pageActions.register })
|
|
14047
|
+
] }) : actions;
|
|
14120
14048
|
const reportHeader = container?.reportHeader;
|
|
14121
14049
|
useLayoutEffect(() => {
|
|
14122
14050
|
if (!reportHeader) return;
|
|
@@ -14162,7 +14090,7 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
14162
14090
|
badge,
|
|
14163
14091
|
breadcrumbs: inlineBreadcrumbs,
|
|
14164
14092
|
onBack,
|
|
14165
|
-
actions,
|
|
14093
|
+
actions: shownActions,
|
|
14166
14094
|
avatar,
|
|
14167
14095
|
filters,
|
|
14168
14096
|
expandedContent,
|
|
@@ -14190,7 +14118,7 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
14190
14118
|
}
|
|
14191
14119
|
let header;
|
|
14192
14120
|
if (variant === "minimal") {
|
|
14193
|
-
header = /* @__PURE__ */ jsx(MinimalHeader, { title, description, caption, focusBack, badge, breadcrumbs: inlineBreadcrumbs, actions, tabs, breadcrumbPill: bcPill, breadcrumbSeparator: bcSep, as: Heading, className, headerRef: floating ? void 0 : ref, isFloating: floating, contentMaxWidth: gutterWidth });
|
|
14121
|
+
header = /* @__PURE__ */ jsx(MinimalHeader, { title, description, caption, focusBack, badge, breadcrumbs: inlineBreadcrumbs, actions: shownActions, tabs, breadcrumbPill: bcPill, breadcrumbSeparator: bcSep, as: Heading, className, headerRef: floating ? void 0 : ref, isFloating: floating, contentMaxWidth: gutterWidth });
|
|
14194
14122
|
} else if (variant === "tabs-integrated") {
|
|
14195
14123
|
header = /* @__PURE__ */ jsx(
|
|
14196
14124
|
TabsIntegratedHeader,
|
|
@@ -14202,7 +14130,7 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
14202
14130
|
badge,
|
|
14203
14131
|
breadcrumbs: inlineBreadcrumbs,
|
|
14204
14132
|
onBack,
|
|
14205
|
-
actions,
|
|
14133
|
+
actions: shownActions,
|
|
14206
14134
|
avatar,
|
|
14207
14135
|
tabs,
|
|
14208
14136
|
breadcrumbPill: bcPill,
|
|
@@ -14227,7 +14155,7 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
14227
14155
|
badge,
|
|
14228
14156
|
breadcrumbs: inlineBreadcrumbs,
|
|
14229
14157
|
onBack,
|
|
14230
|
-
actions,
|
|
14158
|
+
actions: shownActions,
|
|
14231
14159
|
avatar,
|
|
14232
14160
|
filters,
|
|
14233
14161
|
intensity,
|
|
@@ -14255,7 +14183,7 @@ var PageHeader = forwardRef(function PageHeader2({
|
|
|
14255
14183
|
badge,
|
|
14256
14184
|
breadcrumbs: inlineBreadcrumbs,
|
|
14257
14185
|
onBack,
|
|
14258
|
-
actions,
|
|
14186
|
+
actions: shownActions,
|
|
14259
14187
|
avatar,
|
|
14260
14188
|
filters,
|
|
14261
14189
|
bannerImage,
|
|
@@ -14337,7 +14265,7 @@ function DefaultHeader({
|
|
|
14337
14265
|
hasBanner && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-[var(--ds-bg-canvas)]/85" }),
|
|
14338
14266
|
/* @__PURE__ */ jsxs("div", { className: inner.className, style: inner.style, children: [
|
|
14339
14267
|
focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack }),
|
|
14340
|
-
hasBreadcrumbs && /* @__PURE__ */ jsx(
|
|
14268
|
+
hasBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs2, { items: breadcrumbs, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
14341
14269
|
/* @__PURE__ */ jsxs("div", { className: cn(
|
|
14342
14270
|
"flex flex-col @sm:flex-row @sm:items-center justify-between gap-ds-4",
|
|
14343
14271
|
hasBreadcrumbs && "mt-ds-1"
|
|
@@ -14356,7 +14284,7 @@ function DefaultHeader({
|
|
|
14356
14284
|
] }),
|
|
14357
14285
|
actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions })
|
|
14358
14286
|
] }),
|
|
14359
|
-
filters && /* @__PURE__ */ jsx(
|
|
14287
|
+
filters && /* @__PURE__ */ jsx(FilterRow, { className: "mt-ds-4", children: filters }),
|
|
14360
14288
|
tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-4 -mx-ds-1", children: tabs })
|
|
14361
14289
|
] })
|
|
14362
14290
|
]
|
|
@@ -14384,7 +14312,7 @@ function MinimalHeader({
|
|
|
14384
14312
|
const inner = floatingContentProps(isFloating, contentMaxWidth);
|
|
14385
14313
|
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: [
|
|
14386
14314
|
focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack }),
|
|
14387
|
-
hasBreadcrumbs && /* @__PURE__ */ jsx(
|
|
14315
|
+
hasBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs2, { items: breadcrumbs, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
14388
14316
|
caption && /* @__PURE__ */ jsx(Caption, { children: caption }),
|
|
14389
14317
|
/* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between gap-ds-4", hasBreadcrumbs && "mt-ds-0.5"), children: [
|
|
14390
14318
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2 min-w-0", children: [
|
|
@@ -14468,11 +14396,13 @@ function ColourfulHeader({
|
|
|
14468
14396
|
style: {
|
|
14469
14397
|
maxWidth: gutter ? contentMaxWidth ?? "var(--ds-bp-xl)" : void 0,
|
|
14470
14398
|
containerType: "inline-size",
|
|
14471
|
-
|
|
14399
|
+
// under the overlap, the gap from the header's last row to the cards is the page's own (space-6): the band's
|
|
14400
|
+
// bottom edge counts in it (the owner, 30 September: 26 px above the cards, 24 below)
|
|
14401
|
+
...overlapActive ? { paddingBottom: `calc(var(--ds-space-6) + var(--ds-overlap, 0px) - ${isBold && !isFloating ? "2px" : "var(--ds-border-width)"})` } : {}
|
|
14472
14402
|
},
|
|
14473
14403
|
children: [
|
|
14474
14404
|
focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack, onLight: isBold }),
|
|
14475
|
-
hasBreadcrumbs && /* @__PURE__ */ jsx(
|
|
14405
|
+
hasBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs2, { items: breadcrumbs, onLight: isBold, onTint: !isBold, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
14476
14406
|
/* @__PURE__ */ jsxs("div", { className: cn(
|
|
14477
14407
|
"flex flex-col @sm:flex-row @sm:items-center justify-between gap-ds-4",
|
|
14478
14408
|
hasBreadcrumbs && "mt-ds-1"
|
|
@@ -14497,7 +14427,7 @@ function ColourfulHeader({
|
|
|
14497
14427
|
] }),
|
|
14498
14428
|
actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions })
|
|
14499
14429
|
] }),
|
|
14500
|
-
filters && /* @__PURE__ */ jsx(
|
|
14430
|
+
filters && /* @__PURE__ */ jsx(FilterRow, { className: "mt-ds-4", onBand: isBold, children: filters }),
|
|
14501
14431
|
tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-4 -mx-ds-1", onBand: isBold, children: tabs })
|
|
14502
14432
|
]
|
|
14503
14433
|
}
|
|
@@ -14539,6 +14469,7 @@ function SnappingHeader({
|
|
|
14539
14469
|
stickyTop = "top-[var(--ds-navbar-height)]"
|
|
14540
14470
|
}) {
|
|
14541
14471
|
const [collapsed, setCollapsed] = useState(false);
|
|
14472
|
+
const followCrumb = useCrumbFollow();
|
|
14542
14473
|
const container = usePageContainer();
|
|
14543
14474
|
const stickyRef = useRef(null);
|
|
14544
14475
|
const setStickyRef = useCallback((node) => {
|
|
@@ -14673,7 +14604,7 @@ function SnappingHeader({
|
|
|
14673
14604
|
const hasBreadcrumbs = !!(breadcrumbs && breadcrumbs.length > 0);
|
|
14674
14605
|
const innerContent = isMinimal && !collapsed ? /* @__PURE__ */ jsxs("div", { className: cn("py-ds-2", hasBreadcrumbs && !hideExpandedBreadcrumbs && "pt-ds-1", tabs && "pb-ds-4"), children: [
|
|
14675
14606
|
focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack }),
|
|
14676
|
-
hasBreadcrumbs && !hideExpandedBreadcrumbs && /* @__PURE__ */ jsx(
|
|
14607
|
+
hasBreadcrumbs && !hideExpandedBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs2, { items: breadcrumbs, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
14677
14608
|
caption && /* @__PURE__ */ jsx(Caption, { children: caption }),
|
|
14678
14609
|
/* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between gap-ds-4", hasBreadcrumbs && !hideExpandedBreadcrumbs && "mt-ds-0.5"), children: [
|
|
14679
14610
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2 min-w-0", children: [
|
|
@@ -14683,7 +14614,7 @@ function SnappingHeader({
|
|
|
14683
14614
|
actions && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) })
|
|
14684
14615
|
] }),
|
|
14685
14616
|
description && /* @__PURE__ */ jsx(ClampedText, { className: "mt-ds-1 text-sm text-[var(--ds-text-secondary)]", children: description }),
|
|
14686
|
-
filters && /* @__PURE__ */ jsx(
|
|
14617
|
+
filters && /* @__PURE__ */ jsx(FilterRow, { className: "mt-ds-3", children: filters }),
|
|
14687
14618
|
expandedContent && /* @__PURE__ */ jsx("div", { className: "mt-ds-3", children: expandedContent }),
|
|
14688
14619
|
tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-3 -mx-ds-1", children: tabs })
|
|
14689
14620
|
] }) : /* @__PURE__ */ jsxs(
|
|
@@ -14697,10 +14628,10 @@ function SnappingHeader({
|
|
|
14697
14628
|
hasBreadcrumbs && !hideExpandedBreadcrumbs ? "pt-ds-3" : "pt-ds-6"
|
|
14698
14629
|
]
|
|
14699
14630
|
),
|
|
14700
|
-
style: !collapsed && isColourful && overlapActive ? { paddingBottom: `calc(var(--ds-space-6) + var(--ds-overlap, 0px))` } : void 0,
|
|
14631
|
+
style: !collapsed && isColourful && overlapActive ? { paddingBottom: `calc(var(--ds-space-6) + var(--ds-overlap, 0px) - ${isBoldColourful && !(isFloating && !wrapperHasCard) ? "2px" : "var(--ds-border-width)"})` } : void 0,
|
|
14701
14632
|
children: [
|
|
14702
14633
|
!collapsed && focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack, onLight }),
|
|
14703
|
-
!collapsed && hasBreadcrumbs && !hideExpandedBreadcrumbs && /* @__PURE__ */ jsx(
|
|
14634
|
+
!collapsed && hasBreadcrumbs && !hideExpandedBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs2, { items: breadcrumbs, onLight, onTint, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
14704
14635
|
/* @__PURE__ */ jsxs("div", { className: cn(
|
|
14705
14636
|
"flex justify-between gap-ds-4",
|
|
14706
14637
|
collapsed ? "items-center" : "flex-col @sm:flex-row @sm:items-center",
|
|
@@ -14715,17 +14646,14 @@ function SnappingHeader({
|
|
|
14715
14646
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
|
|
14716
14647
|
collapsed && hasBreadcrumbs && (() => {
|
|
14717
14648
|
const lastCrumb = breadcrumbs[breadcrumbs.length - 1];
|
|
14718
|
-
const isClickable = !!
|
|
14649
|
+
const isClickable = !!lastCrumb && crumbGoes(lastCrumb);
|
|
14719
14650
|
const Tag3 = isClickable ? "a" : "span";
|
|
14720
14651
|
return /* @__PURE__ */ jsxs(
|
|
14721
14652
|
Tag3,
|
|
14722
14653
|
{
|
|
14723
14654
|
...isClickable ? {
|
|
14724
14655
|
href: lastCrumb.href ?? "#",
|
|
14725
|
-
onClick: (e) =>
|
|
14726
|
-
e.preventDefault();
|
|
14727
|
-
lastCrumb.onClick?.();
|
|
14728
|
-
}
|
|
14656
|
+
onClick: (e) => followCrumb(e, lastCrumb)
|
|
14729
14657
|
} : {},
|
|
14730
14658
|
className: cn(
|
|
14731
14659
|
"text-sm hidden @sm:inline-flex items-center gap-ds-1",
|
|
@@ -14752,7 +14680,7 @@ function SnappingHeader({
|
|
|
14752
14680
|
] }),
|
|
14753
14681
|
actions && (collapsed ? /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) }) : /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }))
|
|
14754
14682
|
] }),
|
|
14755
|
-
!collapsed && filters && /* @__PURE__ */ jsx(
|
|
14683
|
+
!collapsed && filters && /* @__PURE__ */ jsx(FilterRow, { className: "mt-ds-4", onBand: isBoldColourful, children: filters }),
|
|
14756
14684
|
!collapsed && expandedContent && /* @__PURE__ */ jsx("div", { className: "mt-ds-4", children: expandedContent }),
|
|
14757
14685
|
!collapsed && tabs && /* @__PURE__ */ jsx(TabRow, { hasCaption: !!caption, className: "mt-ds-4 -mx-ds-1", onBand: isBoldColourful, children: tabs })
|
|
14758
14686
|
]
|
|
@@ -14822,7 +14750,7 @@ function TabsIntegratedHeader({
|
|
|
14822
14750
|
const inner = floatingContentProps(isFloating, contentMaxWidth);
|
|
14823
14751
|
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: [
|
|
14824
14752
|
focusBack && /* @__PURE__ */ jsx(BackLink, { onClick: focusBack }),
|
|
14825
|
-
hasBreadcrumbs && /* @__PURE__ */ jsx(
|
|
14753
|
+
hasBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs2, { items: breadcrumbs, pill: breadcrumbPill, separator: breadcrumbSeparator }),
|
|
14826
14754
|
/* @__PURE__ */ jsxs("div", { className: cn(
|
|
14827
14755
|
"flex flex-col @sm:flex-row @sm:items-center justify-between gap-ds-4",
|
|
14828
14756
|
hasBreadcrumbs && "mt-ds-1"
|
|
@@ -14989,6 +14917,73 @@ function Dock({
|
|
|
14989
14917
|
}
|
|
14990
14918
|
);
|
|
14991
14919
|
}
|
|
14920
|
+
function resolveNavItemType(type) {
|
|
14921
|
+
return type === "default" ? "tint" : type;
|
|
14922
|
+
}
|
|
14923
|
+
var NavbarTypeContext = createContext("tint");
|
|
14924
|
+
var NavItem = forwardRef(function NavItem2({ label, icon, active = false, href, onClick, type: typeProp, className, children }, ref) {
|
|
14925
|
+
const contextType = useContext(NavbarTypeContext);
|
|
14926
|
+
const type = resolveNavItemType(typeProp ?? contextType);
|
|
14927
|
+
const baseClasses = cn(
|
|
14928
|
+
"inline-flex items-center gap-ds-2 cursor-pointer select-none whitespace-nowrap",
|
|
14929
|
+
// one line: the navbar measures each link (round 12)
|
|
14930
|
+
"transition-colors duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
|
|
14931
|
+
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
14932
|
+
"text-[length:var(--ds-font-size-sm)]"
|
|
14933
|
+
);
|
|
14934
|
+
const typeClasses = getTypeClasses(type, active);
|
|
14935
|
+
return /* @__PURE__ */ jsxs(
|
|
14936
|
+
"a",
|
|
14937
|
+
{
|
|
14938
|
+
ref,
|
|
14939
|
+
href: href ?? "#",
|
|
14940
|
+
onClick,
|
|
14941
|
+
"aria-current": active ? "page" : void 0,
|
|
14942
|
+
className: cn(baseClasses, typeClasses, className),
|
|
14943
|
+
children: [
|
|
14944
|
+
icon && /* @__PURE__ */ jsx(Icon, { name: icon, size: 16 }),
|
|
14945
|
+
children ?? label,
|
|
14946
|
+
type === "underline" && active && /* @__PURE__ */ jsx(NavUnderline, {})
|
|
14947
|
+
]
|
|
14948
|
+
}
|
|
14949
|
+
);
|
|
14950
|
+
});
|
|
14951
|
+
function getTypeClasses(type, active) {
|
|
14952
|
+
switch (type) {
|
|
14953
|
+
case "pill":
|
|
14954
|
+
return cn(
|
|
14955
|
+
"px-ds-2 py-ds-1 rounded-[var(--ds-radius-sm)]",
|
|
14956
|
+
active ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)] font-[var(--ds-weight-heading)]" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]"
|
|
14957
|
+
);
|
|
14958
|
+
case "underline":
|
|
14959
|
+
return cn(
|
|
14960
|
+
"px-ds-2 py-ds-2 relative",
|
|
14961
|
+
active ? "text-[var(--ds-text-primary)] font-[var(--ds-weight-heading)]" : "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)]"
|
|
14962
|
+
);
|
|
14963
|
+
case "minimal":
|
|
14964
|
+
return cn(
|
|
14965
|
+
"px-ds-2 py-ds-1",
|
|
14966
|
+
active ? "text-[var(--ds-accent-primary)] font-medium" : "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-secondary)]"
|
|
14967
|
+
);
|
|
14968
|
+
case "tint":
|
|
14969
|
+
return cn(
|
|
14970
|
+
"px-ds-2 py-ds-1 rounded-[var(--ds-radius-sm)]",
|
|
14971
|
+
active ? "bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-primary)] font-[var(--ds-weight-heading)]" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]"
|
|
14972
|
+
);
|
|
14973
|
+
}
|
|
14974
|
+
}
|
|
14975
|
+
function NavUnderline() {
|
|
14976
|
+
return /* @__PURE__ */ jsx(
|
|
14977
|
+
"span",
|
|
14978
|
+
{
|
|
14979
|
+
className: "absolute bottom-0 left-ds-1 right-ds-1 rounded-t-full bg-[var(--ds-accent-primary)]",
|
|
14980
|
+
style: { height: "2px" }
|
|
14981
|
+
}
|
|
14982
|
+
);
|
|
14983
|
+
}
|
|
14984
|
+
function navItemClasses(type, active) {
|
|
14985
|
+
return cn("text-[length:var(--ds-font-size-sm)]", getTypeClasses(type, active));
|
|
14986
|
+
}
|
|
14992
14987
|
function TruncSpan({ children, className }) {
|
|
14993
14988
|
const { ref, isTruncated } = useTextOverflow({ lines: 1 });
|
|
14994
14989
|
const el = /* @__PURE__ */ jsx("span", { ref, className: cn("truncate", className), children });
|
|
@@ -14999,7 +14994,7 @@ function NavMenu({
|
|
|
14999
14994
|
label,
|
|
15000
14995
|
items,
|
|
15001
14996
|
active = false,
|
|
15002
|
-
type
|
|
14997
|
+
type: typeProp,
|
|
15003
14998
|
onItemClick,
|
|
15004
14999
|
className
|
|
15005
15000
|
}) {
|
|
@@ -15047,27 +15042,14 @@ function NavMenu({
|
|
|
15047
15042
|
const hasActiveChild = active || items.some(
|
|
15048
15043
|
(it) => it.active || it.children?.some((c) => c.active)
|
|
15049
15044
|
);
|
|
15045
|
+
const contextType = useContext(NavbarTypeContext);
|
|
15046
|
+
const type = resolveNavItemType(typeProp ?? contextType);
|
|
15050
15047
|
const isUnderline = type === "underline";
|
|
15051
|
-
const isMinimal = type === "minimal";
|
|
15052
|
-
const isPill = type === "pill";
|
|
15053
15048
|
const triggerClasses = cn(
|
|
15054
|
-
"inline-flex items-center gap-ds-1 cursor-pointer
|
|
15049
|
+
"inline-flex items-center gap-ds-1 cursor-pointer select-none whitespace-nowrap",
|
|
15050
|
+
"transition-colors duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
|
|
15055
15051
|
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
15056
|
-
|
|
15057
|
-
"px-ds-3 py-ds-2 text-sm border-b-2 -mb-[2px]",
|
|
15058
|
-
hasActiveChild ? "border-[var(--ds-accent-primary)] text-[var(--ds-text-primary)] font-medium" : "border-transparent text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:border-[var(--ds-border-default)]"
|
|
15059
|
-
) : isMinimal ? cn(
|
|
15060
|
-
"px-ds-2 py-ds-1 text-sm",
|
|
15061
|
-
hasActiveChild ? "text-[var(--ds-text-primary)] font-medium" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)]"
|
|
15062
|
-
) : isPill ? cn(
|
|
15063
|
-
"px-ds-3 py-ds-1.5 text-sm rounded-[var(--ds-radius-md)]",
|
|
15064
|
-
hasActiveChild ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)] font-medium" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]"
|
|
15065
|
-
) : cn(
|
|
15066
|
-
// tint (and the deprecated `default` alias) — the same soft accent fill
|
|
15067
|
-
// NavItem uses, so a menu trigger and a link read as one row (decision 30).
|
|
15068
|
-
"px-ds-3 py-ds-1.5 text-sm rounded-[var(--ds-radius-md)]",
|
|
15069
|
-
hasActiveChild ? "bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-primary)] font-medium" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-muted)] hover:text-[var(--ds-text-primary)]"
|
|
15070
|
-
),
|
|
15052
|
+
navItemClasses(type, hasActiveChild),
|
|
15071
15053
|
className
|
|
15072
15054
|
);
|
|
15073
15055
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -15089,7 +15071,8 @@ function NavMenu({
|
|
|
15089
15071
|
size: 12,
|
|
15090
15072
|
className: cn("transition-transform", open && "rotate-180")
|
|
15091
15073
|
}
|
|
15092
|
-
)
|
|
15074
|
+
),
|
|
15075
|
+
isUnderline && hasActiveChild && /* @__PURE__ */ jsx(NavUnderline, {})
|
|
15093
15076
|
]
|
|
15094
15077
|
}
|
|
15095
15078
|
),
|
|
@@ -15200,67 +15183,6 @@ function NavMenuGroup({
|
|
|
15200
15183
|
)) })
|
|
15201
15184
|
] });
|
|
15202
15185
|
}
|
|
15203
|
-
function resolveNavItemType(type) {
|
|
15204
|
-
return type === "default" ? "tint" : type;
|
|
15205
|
-
}
|
|
15206
|
-
var NavbarTypeContext = createContext("tint");
|
|
15207
|
-
var NavItem = forwardRef(function NavItem2({ label, icon, active = false, href, onClick, type: typeProp, className, children }, ref) {
|
|
15208
|
-
const contextType = useContext(NavbarTypeContext);
|
|
15209
|
-
const type = resolveNavItemType(typeProp ?? contextType);
|
|
15210
|
-
const baseClasses = cn(
|
|
15211
|
-
"inline-flex items-center gap-ds-2 cursor-pointer select-none whitespace-nowrap",
|
|
15212
|
-
// one line: the navbar measures each link (round 12)
|
|
15213
|
-
"transition-colors duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
|
|
15214
|
-
"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
15215
|
-
"text-[length:var(--ds-font-size-sm)]"
|
|
15216
|
-
);
|
|
15217
|
-
const typeClasses = getTypeClasses(type, active);
|
|
15218
|
-
return /* @__PURE__ */ jsxs(
|
|
15219
|
-
"a",
|
|
15220
|
-
{
|
|
15221
|
-
ref,
|
|
15222
|
-
href: href ?? "#",
|
|
15223
|
-
onClick,
|
|
15224
|
-
"aria-current": active ? "page" : void 0,
|
|
15225
|
-
className: cn(baseClasses, typeClasses, className),
|
|
15226
|
-
children: [
|
|
15227
|
-
icon && /* @__PURE__ */ jsx(Icon, { name: icon, size: 16 }),
|
|
15228
|
-
children ?? label,
|
|
15229
|
-
type === "underline" && active && /* @__PURE__ */ jsx(
|
|
15230
|
-
"span",
|
|
15231
|
-
{
|
|
15232
|
-
className: "absolute bottom-0 left-ds-1 right-ds-1 rounded-t-full bg-[var(--ds-accent-primary)]",
|
|
15233
|
-
style: { height: "2px" }
|
|
15234
|
-
}
|
|
15235
|
-
)
|
|
15236
|
-
]
|
|
15237
|
-
}
|
|
15238
|
-
);
|
|
15239
|
-
});
|
|
15240
|
-
function getTypeClasses(type, active) {
|
|
15241
|
-
switch (type) {
|
|
15242
|
-
case "pill":
|
|
15243
|
-
return cn(
|
|
15244
|
-
"px-ds-2 py-ds-1 rounded-[var(--ds-radius-sm)]",
|
|
15245
|
-
active ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)] font-[var(--ds-weight-heading)]" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]"
|
|
15246
|
-
);
|
|
15247
|
-
case "underline":
|
|
15248
|
-
return cn(
|
|
15249
|
-
"px-ds-2 py-ds-2 relative",
|
|
15250
|
-
active ? "text-[var(--ds-text-primary)] font-[var(--ds-weight-heading)]" : "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)]"
|
|
15251
|
-
);
|
|
15252
|
-
case "minimal":
|
|
15253
|
-
return cn(
|
|
15254
|
-
"px-ds-2 py-ds-1",
|
|
15255
|
-
active ? "text-[var(--ds-accent-primary)] font-medium" : "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-secondary)]"
|
|
15256
|
-
);
|
|
15257
|
-
case "tint":
|
|
15258
|
-
return cn(
|
|
15259
|
-
"px-ds-2 py-ds-1 rounded-[var(--ds-radius-sm)]",
|
|
15260
|
-
active ? "bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-primary)] font-[var(--ds-weight-heading)]" : "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]"
|
|
15261
|
-
);
|
|
15262
|
-
}
|
|
15263
|
-
}
|
|
15264
15186
|
var DEFAULT_BUTTON_ATTR = "data-dialog-default-button";
|
|
15265
15187
|
var sizeClasses = {
|
|
15266
15188
|
// round 16 (the owner's item 5): the small dialog is 448 px, not 384 — a delete confirmation with a typed field was cramped
|
|
@@ -15281,6 +15203,7 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
15281
15203
|
const dialogRef = useRef(null);
|
|
15282
15204
|
const opener = useRef(null);
|
|
15283
15205
|
const defaultButtonRef = useRef(null);
|
|
15206
|
+
const bodyRef = useScrollbarInset();
|
|
15284
15207
|
const onCloseRef = useLatest(onClose);
|
|
15285
15208
|
const onSubmitRef = useLatest(onSubmit);
|
|
15286
15209
|
const isTopLayer = useOverlayLayer(open);
|
|
@@ -15326,7 +15249,7 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
15326
15249
|
"div",
|
|
15327
15250
|
{
|
|
15328
15251
|
ref: overlayRef,
|
|
15329
|
-
className: "fixed inset-0 z-[var(--ds-z-modal)] flex items-center justify-center p-ds-4",
|
|
15252
|
+
className: cn("fixed inset-0 z-[var(--ds-z-modal)] flex items-center justify-center", !isMobile && "p-ds-4"),
|
|
15330
15253
|
children: [
|
|
15331
15254
|
/* @__PURE__ */ jsx(
|
|
15332
15255
|
"div",
|
|
@@ -15376,31 +15299,22 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
15376
15299
|
"data-gs": "dialog",
|
|
15377
15300
|
"aria-labelledby": titleId,
|
|
15378
15301
|
"aria-describedby": description ? descriptionId : void 0,
|
|
15379
|
-
style: { containerType: "inline-size" },
|
|
15302
|
+
style: { containerType: "inline-size", "--ds-form-max": "none" },
|
|
15380
15303
|
className: cn(
|
|
15381
|
-
|
|
15304
|
+
// a column: the title row, a body that scrolls when it is taller than the room, and the footer (Sprint 25.14,
|
|
15305
|
+
// with A36's full-screen phone dialog: its content ran past the screen with the footer cut off)
|
|
15306
|
+
"relative z-10 w-full flex flex-col max-h-full",
|
|
15382
15307
|
isMobile ? "max-w-none h-full" : sizeClasses[size],
|
|
15383
15308
|
OVERLAY_SURFACE,
|
|
15384
15309
|
"text-[var(--ds-text-primary)]",
|
|
15385
15310
|
GLASS_OVERLAY,
|
|
15386
|
-
|
|
15387
|
-
isMobile ? "rounded-none" : "rounded-[var(--ds-radius-xl)]",
|
|
15311
|
+
// full screen on a phone: no edge to draw, so the content sits at the gutter from the screen's edge
|
|
15312
|
+
isMobile ? "rounded-none" : "rounded-[var(--ds-radius-xl)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
15388
15313
|
"overflow-hidden",
|
|
15389
15314
|
"animate-in fade-in-0 zoom-in-95"
|
|
15390
15315
|
),
|
|
15391
15316
|
children: [
|
|
15392
|
-
/* @__PURE__ */
|
|
15393
|
-
"button",
|
|
15394
|
-
{
|
|
15395
|
-
type: "button",
|
|
15396
|
-
onClick: onClose,
|
|
15397
|
-
...{ [OVERLAY_CLOSE_ATTR]: "" },
|
|
15398
|
-
className: "absolute right-4 top-4 text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
|
|
15399
|
-
"aria-label": "Close",
|
|
15400
|
-
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
|
|
15401
|
-
}
|
|
15402
|
-
),
|
|
15403
|
-
/* @__PURE__ */ jsx("div", { className: "p-ds-6", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-ds-3", children: [
|
|
15317
|
+
/* @__PURE__ */ jsxs("div", { className: cn("shrink-0 flex items-start gap-ds-3 pt-ds-6 px-[var(--ds-page-gutter)]", children ? "pb-ds-4" : "pb-ds-6"), children: [
|
|
15404
15318
|
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)]" }) }),
|
|
15405
15319
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
15406
15320
|
/* @__PURE__ */ jsx(
|
|
@@ -15411,16 +15325,39 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
15411
15325
|
children: title
|
|
15412
15326
|
}
|
|
15413
15327
|
),
|
|
15414
|
-
description && /* @__PURE__ */ jsx("p", { id: descriptionId, className: "mt-ds-2 text-sm text-[var(--ds-text-muted)]", children: description })
|
|
15415
|
-
|
|
15416
|
-
|
|
15417
|
-
|
|
15328
|
+
description && /* @__PURE__ */ jsx("p", { id: descriptionId, className: "mt-ds-2 text-sm text-[var(--ds-text-muted)]", children: description })
|
|
15329
|
+
] }),
|
|
15330
|
+
/* @__PURE__ */ jsx(
|
|
15331
|
+
"button",
|
|
15332
|
+
{
|
|
15333
|
+
type: "button",
|
|
15334
|
+
onClick: onClose,
|
|
15335
|
+
...{ [OVERLAY_CLOSE_ATTR]: "" },
|
|
15336
|
+
className: "shrink-0 text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
|
|
15337
|
+
"aria-label": "Close",
|
|
15338
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
|
|
15339
|
+
}
|
|
15340
|
+
)
|
|
15341
|
+
] }),
|
|
15342
|
+
children && /* @__PURE__ */ jsx(
|
|
15343
|
+
"div",
|
|
15344
|
+
{
|
|
15345
|
+
ref: bodyRef,
|
|
15346
|
+
className: "min-h-0 flex-[0_1_auto] overflow-y-auto pb-ds-6",
|
|
15347
|
+
style: {
|
|
15348
|
+
paddingLeft: variant === "destructive" ? "calc(var(--ds-page-gutter) + 2.5rem + var(--ds-space-3))" : "var(--ds-page-gutter)",
|
|
15349
|
+
paddingRight: insetLessScrollbar("var(--ds-page-gutter)")
|
|
15350
|
+
},
|
|
15351
|
+
children: /* @__PURE__ */ jsx(SurfaceBoundary, { children: /* @__PURE__ */ jsx(DrawerFooterCtx, { value: null, children: /* @__PURE__ */ jsx(OverlayMarkScope, { mark, children: /* @__PURE__ */ jsx(OverlayCloseCtx, { value: onClose, children }) }) }) })
|
|
15352
|
+
}
|
|
15353
|
+
),
|
|
15354
|
+
isMobile && /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "flex-1 min-h-0" }),
|
|
15418
15355
|
/* @__PURE__ */ jsx(DiscardConfirm, { open: guard.confirming, onKeep: guard.keep, onDiscard: guard.discard }),
|
|
15419
15356
|
footer && /* @__PURE__ */ jsx("div", { className: cn(
|
|
15420
|
-
"flex justify-end gap-ds-2
|
|
15357
|
+
"shrink-0 flex justify-end gap-ds-2 py-ds-4 px-[var(--ds-page-gutter)]",
|
|
15421
15358
|
"border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
15422
15359
|
"bg-[var(--ds-bg-muted)]",
|
|
15423
|
-
"rounded-b-[var(--ds-radius-xl)]"
|
|
15360
|
+
!isMobile && "rounded-b-[var(--ds-radius-xl)]"
|
|
15424
15361
|
), children: footer })
|
|
15425
15362
|
]
|
|
15426
15363
|
}
|
|
@@ -15573,7 +15510,7 @@ var Navbar = forwardRef(function Navbar2({
|
|
|
15573
15510
|
}
|
|
15574
15511
|
focus.onExit?.();
|
|
15575
15512
|
};
|
|
15576
|
-
const exitControl = focus ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: requestExit, children: focus.exitLabel ?? (focus.kind === "before-app" ? "Save and log out" : "Exit") }) : null;
|
|
15513
|
+
const exitControl = focus && !appShell?.flowLeft ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: requestExit, children: focus.exitLabel ?? (focus.kind === "before-app" ? "Save and log out" : "Exit") }) : null;
|
|
15577
15514
|
const shownUserMenu = focus?.kind === "before-app" ? null : userMenu;
|
|
15578
15515
|
const asking = confirmExit && focus?.kind === "in-app" && !!appShell?.hasUnsavedChanges;
|
|
15579
15516
|
if (confirmExit && !asking) setConfirmExit(false);
|
|
@@ -16707,6 +16644,310 @@ function getPopoverPosition(rect, placement, padding) {
|
|
|
16707
16644
|
top = Math.max(8, Math.min(top, window.innerHeight - popH - 8));
|
|
16708
16645
|
return { top, left };
|
|
16709
16646
|
}
|
|
16647
|
+
var FLOW_STORAGE_PREFIX = "gridsmith-flow:";
|
|
16648
|
+
var stores = /* @__PURE__ */ new Map();
|
|
16649
|
+
var storeFor = (key) => {
|
|
16650
|
+
let store = stores.get(key);
|
|
16651
|
+
if (!store) {
|
|
16652
|
+
store = { value: null, raw: void 0, stale: false, listeners: /* @__PURE__ */ new Set(), finished: false, focusStep: null, left: null };
|
|
16653
|
+
stores.set(key, store);
|
|
16654
|
+
}
|
|
16655
|
+
return store;
|
|
16656
|
+
};
|
|
16657
|
+
var notify = (store) => store.listeners.forEach((listener) => listener());
|
|
16658
|
+
function subscribeTo(key, listener) {
|
|
16659
|
+
const store = storeFor(key);
|
|
16660
|
+
store.listeners.add(listener);
|
|
16661
|
+
if (!store.onStorage && typeof window !== "undefined") {
|
|
16662
|
+
store.onStorage = (e) => {
|
|
16663
|
+
if (e.key !== null && e.key !== FLOW_STORAGE_PREFIX + key) return;
|
|
16664
|
+
store.stale = true;
|
|
16665
|
+
notify(store);
|
|
16666
|
+
};
|
|
16667
|
+
window.addEventListener("storage", store.onStorage);
|
|
16668
|
+
}
|
|
16669
|
+
return () => {
|
|
16670
|
+
store.listeners.delete(listener);
|
|
16671
|
+
if (store.listeners.size > 0) return;
|
|
16672
|
+
if (store.onStorage) window.removeEventListener("storage", store.onStorage);
|
|
16673
|
+
store.onStorage = void 0;
|
|
16674
|
+
store.finished = false;
|
|
16675
|
+
};
|
|
16676
|
+
}
|
|
16677
|
+
var readRaw = (key) => {
|
|
16678
|
+
try {
|
|
16679
|
+
return window.localStorage.getItem(FLOW_STORAGE_PREFIX + key);
|
|
16680
|
+
} catch {
|
|
16681
|
+
return null;
|
|
16682
|
+
}
|
|
16683
|
+
};
|
|
16684
|
+
function readRecord(key) {
|
|
16685
|
+
return parseRecord(readRaw(key));
|
|
16686
|
+
}
|
|
16687
|
+
function parseRecord(raw) {
|
|
16688
|
+
try {
|
|
16689
|
+
if (!raw) return null;
|
|
16690
|
+
const stored = JSON.parse(raw);
|
|
16691
|
+
const furthest = Math.max(1, Math.floor(Number(stored.furthest)) || 1);
|
|
16692
|
+
const current = Math.floor(Number(stored.current)) || void 0;
|
|
16693
|
+
return { furthest, current, answers: stored.answers ?? {} };
|
|
16694
|
+
} catch {
|
|
16695
|
+
return null;
|
|
16696
|
+
}
|
|
16697
|
+
}
|
|
16698
|
+
function writeRecord(key, value) {
|
|
16699
|
+
for (const text of [() => JSON.stringify(value), () => JSON.stringify({ furthest: value.furthest, current: value.current })]) {
|
|
16700
|
+
try {
|
|
16701
|
+
const raw = text();
|
|
16702
|
+
window.localStorage.setItem(FLOW_STORAGE_PREFIX + key, raw);
|
|
16703
|
+
return raw;
|
|
16704
|
+
} catch {
|
|
16705
|
+
}
|
|
16706
|
+
}
|
|
16707
|
+
return null;
|
|
16708
|
+
}
|
|
16709
|
+
function snapshot(key) {
|
|
16710
|
+
const store = storeFor(key);
|
|
16711
|
+
if (store.raw === void 0 || store.stale || store.listeners.size === 0) {
|
|
16712
|
+
store.stale = false;
|
|
16713
|
+
const raw = readRaw(key);
|
|
16714
|
+
if (raw !== store.raw || store.value === null) {
|
|
16715
|
+
store.raw = raw;
|
|
16716
|
+
store.value = parseRecord(raw) ?? { furthest: 1, answers: {} };
|
|
16717
|
+
}
|
|
16718
|
+
}
|
|
16719
|
+
return store.value;
|
|
16720
|
+
}
|
|
16721
|
+
function update(key, change) {
|
|
16722
|
+
const store = storeFor(key);
|
|
16723
|
+
const raw = readRaw(key);
|
|
16724
|
+
if (raw !== null && raw !== store.raw) {
|
|
16725
|
+
store.raw = raw;
|
|
16726
|
+
store.value = parseRecord(raw) ?? store.value;
|
|
16727
|
+
}
|
|
16728
|
+
store.value = change(store.value ?? { furthest: 1, answers: {} });
|
|
16729
|
+
store.raw = writeRecord(key, store.value) ?? store.raw;
|
|
16730
|
+
store.stale = false;
|
|
16731
|
+
notify(store);
|
|
16732
|
+
}
|
|
16733
|
+
function clear(key) {
|
|
16734
|
+
const store = storeFor(key);
|
|
16735
|
+
try {
|
|
16736
|
+
window.localStorage.removeItem(FLOW_STORAGE_PREFIX + key);
|
|
16737
|
+
} catch {
|
|
16738
|
+
}
|
|
16739
|
+
store.value = null;
|
|
16740
|
+
store.raw = void 0;
|
|
16741
|
+
notify(store);
|
|
16742
|
+
}
|
|
16743
|
+
function markFlowMove(storageKey, step) {
|
|
16744
|
+
storeFor(storageKey).focusStep = step;
|
|
16745
|
+
}
|
|
16746
|
+
function stepJustLeft(storageKey) {
|
|
16747
|
+
const left = storeFor(storageKey).left;
|
|
16748
|
+
return left && Date.now() - left.time < 3e3 ? left.step : null;
|
|
16749
|
+
}
|
|
16750
|
+
function readFlowProgress(storageKey, initialAnswers) {
|
|
16751
|
+
const record = typeof window === "undefined" ? null : readRecord(storageKey);
|
|
16752
|
+
return record ? { ...record, answers: { ...initialAnswers, ...record.answers } } : null;
|
|
16753
|
+
}
|
|
16754
|
+
function useFlowNavigate(navigate) {
|
|
16755
|
+
const shellNavigate = useAppShell()?.navigate;
|
|
16756
|
+
return useCallback((href, options) => {
|
|
16757
|
+
const go = navigate ?? shellNavigate;
|
|
16758
|
+
if (go) go(href, options);
|
|
16759
|
+
else if (options?.replace) window.location.replace(href);
|
|
16760
|
+
else window.location.assign(href);
|
|
16761
|
+
}, [navigate, shellNavigate]);
|
|
16762
|
+
}
|
|
16763
|
+
function focusHeading() {
|
|
16764
|
+
const heading = document.querySelector("main h1") ?? document.querySelector("main");
|
|
16765
|
+
if (!heading) return;
|
|
16766
|
+
if (!heading.hasAttribute("tabindex")) heading.setAttribute("tabindex", "-1");
|
|
16767
|
+
heading.focus({ preventScroll: false });
|
|
16768
|
+
}
|
|
16769
|
+
function focusAfterLeaving() {
|
|
16770
|
+
if (typeof window === "undefined" || typeof requestAnimationFrame === "undefined") return () => {
|
|
16771
|
+
};
|
|
16772
|
+
const from = window.location.href;
|
|
16773
|
+
const old = document.querySelector("main h1");
|
|
16774
|
+
const oldText = old?.textContent ?? null;
|
|
16775
|
+
return () => {
|
|
16776
|
+
let frames = 0;
|
|
16777
|
+
const tick = () => {
|
|
16778
|
+
const heading = document.querySelector("main h1");
|
|
16779
|
+
const drawn = window.location.href !== from && !!heading && (heading !== old || heading.textContent !== oldText);
|
|
16780
|
+
if (!drawn) {
|
|
16781
|
+
if (++frames < 60) requestAnimationFrame(tick);
|
|
16782
|
+
return;
|
|
16783
|
+
}
|
|
16784
|
+
const active = document.activeElement;
|
|
16785
|
+
if (!active || active === document.body || !active.isConnected) focusHeading();
|
|
16786
|
+
};
|
|
16787
|
+
requestAnimationFrame(tick);
|
|
16788
|
+
};
|
|
16789
|
+
}
|
|
16790
|
+
var titleBase = null;
|
|
16791
|
+
var titleUsers = 0;
|
|
16792
|
+
function usePageTitle(title) {
|
|
16793
|
+
useEffect(() => {
|
|
16794
|
+
if (!title || typeof document === "undefined") return;
|
|
16795
|
+
if (titleUsers++ === 0) titleBase = document.title;
|
|
16796
|
+
document.title = titleBase ? `${title} \u2013 ${titleBase}` : title;
|
|
16797
|
+
return () => {
|
|
16798
|
+
if (--titleUsers > 0) return;
|
|
16799
|
+
if (titleBase !== null) document.title = titleBase;
|
|
16800
|
+
titleBase = null;
|
|
16801
|
+
};
|
|
16802
|
+
}, [title]);
|
|
16803
|
+
}
|
|
16804
|
+
var shownSteps = (steps, answers) => steps.filter((s) => !s.when || s.when(answers));
|
|
16805
|
+
var STEP = /^[1-9]\d*$/;
|
|
16806
|
+
function useFlowSteps(options) {
|
|
16807
|
+
const { steps, at, href, initialAnswers, exitTo, finishTo } = options;
|
|
16808
|
+
const key = options.storageKey || null;
|
|
16809
|
+
const go = useFlowNavigate(options.navigate);
|
|
16810
|
+
const subscribe = useCallback((listener) => key ? subscribeTo(key, listener) : () => {
|
|
16811
|
+
}, [key]);
|
|
16812
|
+
const stored = useSyncExternalStore(subscribe, () => key ? snapshot(key) : null, () => null);
|
|
16813
|
+
const answers = useMemo(() => ({ ...initialAnswers, ...stored?.answers ?? {} }), [initialAnswers, stored]);
|
|
16814
|
+
const shown = useMemo(() => shownSteps(steps, answers), [steps, answers]);
|
|
16815
|
+
const total = Math.max(shown.length, 1);
|
|
16816
|
+
const furthest = Math.min(stored?.furthest ?? 1, total);
|
|
16817
|
+
const asked = at !== void 0 && STEP.test(at) ? Number(at) : NaN;
|
|
16818
|
+
const valid = asked >= 1 && asked <= furthest;
|
|
16819
|
+
const step = valid ? asked : furthest;
|
|
16820
|
+
const finished = !!key && storeFor(key).finished;
|
|
16821
|
+
const ready = !!key && stored != null && valid && !finished;
|
|
16822
|
+
const redirected = useRef(null);
|
|
16823
|
+
useEffect(() => {
|
|
16824
|
+
if (!key || storeFor(key).finished) return;
|
|
16825
|
+
if (!stored || valid) {
|
|
16826
|
+
redirected.current = null;
|
|
16827
|
+
return;
|
|
16828
|
+
}
|
|
16829
|
+
const target = href(furthest);
|
|
16830
|
+
if (redirected.current === `${at} ${target}`) return;
|
|
16831
|
+
redirected.current = `${at} ${target}`;
|
|
16832
|
+
go(target, { replace: true });
|
|
16833
|
+
}, [key, stored, valid, furthest, href, go, at]);
|
|
16834
|
+
useEffect(() => {
|
|
16835
|
+
if (key && ready && stored?.current !== step) update(key, (v) => ({ ...v, current: step }));
|
|
16836
|
+
}, [key, ready, stored?.current, step]);
|
|
16837
|
+
useEffect(() => {
|
|
16838
|
+
if (!key || !ready) return;
|
|
16839
|
+
const store = storeFor(key);
|
|
16840
|
+
if (store.focusStep !== step) return;
|
|
16841
|
+
store.focusStep = null;
|
|
16842
|
+
focusHeading();
|
|
16843
|
+
}, [key, ready, step]);
|
|
16844
|
+
useLayoutEffect(() => {
|
|
16845
|
+
if (!key || !ready) return;
|
|
16846
|
+
const store = storeFor(key);
|
|
16847
|
+
return () => {
|
|
16848
|
+
store.left = { step, time: Date.now() };
|
|
16849
|
+
};
|
|
16850
|
+
}, [key, ready, step]);
|
|
16851
|
+
const current = shown[step - 1] ?? steps[0];
|
|
16852
|
+
usePageTitle(ready ? current.title : null);
|
|
16853
|
+
const setAnswers = useCallback((patch) => {
|
|
16854
|
+
if (!key) return;
|
|
16855
|
+
update(key, (before) => {
|
|
16856
|
+
const prev = { ...initialAnswers, ...before.answers };
|
|
16857
|
+
const next2 = { ...prev, ...patch };
|
|
16858
|
+
const here = Math.max(step, before.current ?? step);
|
|
16859
|
+
const ahead = (list) => list.slice(here).map((s) => s.label).join("\0");
|
|
16860
|
+
const changes = ahead(shownSteps(steps, prev)) !== ahead(shownSteps(steps, next2));
|
|
16861
|
+
return { ...before, furthest: changes ? Math.min(before.furthest, here) : before.furthest, answers: next2 };
|
|
16862
|
+
});
|
|
16863
|
+
}, [key, initialAnswers, step, steps]);
|
|
16864
|
+
const moveTo = useCallback((target) => {
|
|
16865
|
+
if (key) storeFor(key).focusStep = target;
|
|
16866
|
+
go(href(target));
|
|
16867
|
+
}, [key, go, href]);
|
|
16868
|
+
const goTo = useCallback((target) => {
|
|
16869
|
+
if (!Number.isInteger(target) || target < 1 || target > furthest || target === step) return;
|
|
16870
|
+
moveTo(target);
|
|
16871
|
+
}, [furthest, step, moveTo]);
|
|
16872
|
+
const next = useCallback((patch) => {
|
|
16873
|
+
if (!key) return;
|
|
16874
|
+
if (patch) setAnswers(patch);
|
|
16875
|
+
const shownNow = patch ? shownSteps(steps, { ...answers, ...patch }) : shown;
|
|
16876
|
+
if (step >= shownNow.length) return;
|
|
16877
|
+
update(key, (v) => ({ ...v, furthest: Math.max(v.furthest, step + 1), current: step + 1 }));
|
|
16878
|
+
moveTo(step + 1);
|
|
16879
|
+
}, [key, setAnswers, steps, answers, shown, step, moveTo]);
|
|
16880
|
+
const back = step > 1 ? () => moveTo(step - 1) : void 0;
|
|
16881
|
+
const saveAndExit = useCallback(() => {
|
|
16882
|
+
if (key && stored) update(key, (v) => ({ ...v, current: step }));
|
|
16883
|
+
const left = focusAfterLeaving();
|
|
16884
|
+
go(exitTo);
|
|
16885
|
+
left();
|
|
16886
|
+
}, [key, stored, step, go, exitTo]);
|
|
16887
|
+
const finish = useCallback(() => {
|
|
16888
|
+
if (key) storeFor(key).finished = true;
|
|
16889
|
+
const left = focusAfterLeaving();
|
|
16890
|
+
go(finishTo);
|
|
16891
|
+
if (key) clear(key);
|
|
16892
|
+
left();
|
|
16893
|
+
}, [key, go, finishTo]);
|
|
16894
|
+
return {
|
|
16895
|
+
ready,
|
|
16896
|
+
step,
|
|
16897
|
+
total,
|
|
16898
|
+
current,
|
|
16899
|
+
caption: `Step ${step} of ${total}`,
|
|
16900
|
+
title: current.title,
|
|
16901
|
+
answers,
|
|
16902
|
+
setAnswers,
|
|
16903
|
+
furthest,
|
|
16904
|
+
isFirst: step === 1,
|
|
16905
|
+
isLast: step === total,
|
|
16906
|
+
next,
|
|
16907
|
+
back,
|
|
16908
|
+
goTo,
|
|
16909
|
+
stepper: {
|
|
16910
|
+
steps: shown.map((s, i) => ({
|
|
16911
|
+
label: s.label,
|
|
16912
|
+
status: i + 1 < furthest && i + 1 !== step ? "complete" : void 0,
|
|
16913
|
+
disabled: i + 1 > furthest || void 0
|
|
16914
|
+
})),
|
|
16915
|
+
currentStep: step - 1,
|
|
16916
|
+
onStepChange: (index) => goTo(index + 1)
|
|
16917
|
+
},
|
|
16918
|
+
saveAndExit,
|
|
16919
|
+
finish
|
|
16920
|
+
};
|
|
16921
|
+
}
|
|
16922
|
+
function FlowSaved({ storageKey, href, title = "Your progress has been saved", children, navigate }) {
|
|
16923
|
+
const go = useFlowNavigate(navigate);
|
|
16924
|
+
const titleId = useId();
|
|
16925
|
+
const markFlowLeft = useAppShell()?.markFlowLeft;
|
|
16926
|
+
useLayoutEffect(() => markFlowLeft?.(), [markFlowLeft]);
|
|
16927
|
+
const [saved, setSaved] = useState(void 0);
|
|
16928
|
+
useLayoutEffect(() => {
|
|
16929
|
+
const progress = readFlowProgress(storageKey, {});
|
|
16930
|
+
const step = progress ? progress.current ?? progress.furthest : null;
|
|
16931
|
+
setSaved(step === null ? null : { step, behind: stepJustLeft(storageKey) === step });
|
|
16932
|
+
}, [storageKey]);
|
|
16933
|
+
const resume = () => {
|
|
16934
|
+
const step = saved?.step ?? 1;
|
|
16935
|
+
markFlowMove(storageKey, step);
|
|
16936
|
+
if (saved?.behind) window.history.back();
|
|
16937
|
+
else go(href(step), { replace: true });
|
|
16938
|
+
};
|
|
16939
|
+
useLayoutEffect(() => {
|
|
16940
|
+
if (saved !== void 0) focusHeading();
|
|
16941
|
+
}, [saved]);
|
|
16942
|
+
const heading = saved === null ? "There's no saved progress" : title;
|
|
16943
|
+
usePageTitle(saved === void 0 ? null : heading);
|
|
16944
|
+
return /* @__PURE__ */ jsx(PageContainer, { width: "narrow", children: /* @__PURE__ */ jsxs("section", { "aria-labelledby": titleId, className: "flex min-h-[60vh] flex-col items-center justify-center py-ds-12 text-center", children: [
|
|
16945
|
+
saved !== null && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "grid size-14 place-items-center rounded-[var(--ds-radius-full)] bg-[var(--ds-status-success-bg)] text-[var(--ds-status-success)]", children: /* @__PURE__ */ jsx(Icon, { name: "check", size: 28 }) }),
|
|
16946
|
+
/* @__PURE__ */ jsx("h1", { id: titleId, className: "mt-ds-6 font-[family-name:var(--ds-font-display)] text-3xl font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", children: heading }),
|
|
16947
|
+
/* @__PURE__ */ jsx("div", { className: "mt-ds-3 max-w-md text-[var(--ds-text-secondary)]", children: saved === null ? /* @__PURE__ */ jsx("p", { children: "Nothing has been saved in this browser yet." }) : children ?? /* @__PURE__ */ jsx("p", { children: "Your answers are kept in this browser. Come back to it to carry on where you left off." }) }),
|
|
16948
|
+
/* @__PURE__ */ jsx("div", { className: "mt-ds-8 flex flex-wrap justify-center gap-ds-3", children: /* @__PURE__ */ jsx(Button, { type: "button", onClick: resume, children: saved === null ? "Start" : "Continue" }) })
|
|
16949
|
+
] }) });
|
|
16950
|
+
}
|
|
16710
16951
|
function useDestructiveAction(options) {
|
|
16711
16952
|
const { action, title, description, confirmLabel, typeToConfirm, onConfirm, onUndo, doneMessage, undoMessage, restoredMessage, severity } = options;
|
|
16712
16953
|
const preferences = useShellPreferences();
|
|
@@ -16872,6 +17113,8 @@ function pastTenseOf(label) {
|
|
|
16872
17113
|
}
|
|
16873
17114
|
var SectionHeading = forwardRef(function SectionHeading2({
|
|
16874
17115
|
title,
|
|
17116
|
+
onTitleChange,
|
|
17117
|
+
titleLabel = "Title",
|
|
16875
17118
|
description,
|
|
16876
17119
|
actions,
|
|
16877
17120
|
badge,
|
|
@@ -16883,6 +17126,8 @@ var SectionHeading = forwardRef(function SectionHeading2({
|
|
|
16883
17126
|
}, ref) {
|
|
16884
17127
|
const isPhone = useBreakpoint("sm");
|
|
16885
17128
|
const pane = variant === "pane";
|
|
17129
|
+
const inDetail = useContext(SplitPaneCtx) === "detail";
|
|
17130
|
+
const editable = !!onTitleChange;
|
|
16886
17131
|
return /* @__PURE__ */ jsxs(
|
|
16887
17132
|
"div",
|
|
16888
17133
|
{
|
|
@@ -16890,7 +17135,7 @@ var SectionHeading = forwardRef(function SectionHeading2({
|
|
|
16890
17135
|
"data-gs": "section-heading",
|
|
16891
17136
|
"data-variant": variant,
|
|
16892
17137
|
className: cn(
|
|
16893
|
-
pane ? "shrink-0
|
|
17138
|
+
pane ? cn("shrink-0 pt-ds-4 pb-ds-3 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]", inDetail ? "px-[var(--ds-page-gutter)]" : "px-ds-4") : "mb-[var(--ds-heading-gap)]",
|
|
16894
17139
|
!pane && bordered && "border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] pb-ds-4",
|
|
16895
17140
|
className
|
|
16896
17141
|
),
|
|
@@ -16899,11 +17144,23 @@ var SectionHeading = forwardRef(function SectionHeading2({
|
|
|
16899
17144
|
"flex gap-ds-4",
|
|
16900
17145
|
// the actions wrap under the title when the two do not fit on one line (round 11: a search Input in a 284 px
|
|
16901
17146
|
// pane's actions slot squeezed "Inbox" to "I."); below sm they always stack
|
|
16902
|
-
isPhone && actions ? "flex-col" : "flex-wrap items-
|
|
17147
|
+
isPhone && actions ? "flex-col" : cn("flex-wrap justify-between", editable && !description ? "items-center" : "items-start")
|
|
16903
17148
|
), children: [
|
|
16904
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
17149
|
+
/* @__PURE__ */ jsxs("div", { className: cn("min-w-0", editable && !(isPhone && actions) && "flex-[1_1_20ch] text-lg"), children: [
|
|
16905
17150
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
|
|
16906
|
-
|
|
17151
|
+
editable ? (
|
|
17152
|
+
// the field is the title: the heading holds it, so the page's headings still name the view by its title
|
|
17153
|
+
/* @__PURE__ */ jsx("h2", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx(
|
|
17154
|
+
Input,
|
|
17155
|
+
{
|
|
17156
|
+
size: "md",
|
|
17157
|
+
"aria-label": titleLabel,
|
|
17158
|
+
value: title,
|
|
17159
|
+
onChange: (e) => onTitleChange(e.target.value),
|
|
17160
|
+
className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]"
|
|
17161
|
+
}
|
|
17162
|
+
) })
|
|
17163
|
+
) : /* @__PURE__ */ jsx("h2", { className: cn("font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", pane ? "truncate" : "min-w-0 break-words"), children: title }),
|
|
16907
17164
|
badge,
|
|
16908
17165
|
count !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "neutral", size: "sm", children: count })
|
|
16909
17166
|
] }),
|
|
@@ -17010,6 +17267,6 @@ var TextOverflow = forwardRef(function TextOverflow2({
|
|
|
17010
17267
|
return /* @__PURE__ */ jsx(Tooltip, { content: resolvedTooltipContent, children: content });
|
|
17011
17268
|
});
|
|
17012
17269
|
|
|
17013
|
-
export { Accordion, ActionPanel, ActionPanelGroup, AddAnother, Alert, AsidePanel, Avatar, AvatarGroup, BottomNav,
|
|
17270
|
+
export { Accordion, ActionPanel, ActionPanelGroup, AddAnother, Alert, AsidePanel, Avatar, AvatarGroup, BottomNav, BulkActionBar, Calendar, Card, CardContent, CardDescription, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, ChatMessageList, ChatPanel, Checkbox, CheckboxGroup, CheckboxGroupItem, Collapsible, ColorPicker, Combobox, CommandPalette, ContextMenu, CornerPanel, DEFAULT_DATE_RANGE_PRESETS, DataList, DatePicker, DateRangePicker, DescriptionList, Dialog, Dock, DropdownMenu, EmptyState, EntityCell, FileUpload, FlowSaved, FormWrapper, Gantt, HoverCard, Kbd, Launcher, MentionInput, MobileHeaderMenu, NavItem, NavMenu, Navbar, NotificationCenter, PageActions, PageContainer, PageHeader, PinInput, Progress, RadioGroup, Rating, ScrollArea, SectionHeading, SegmentedControl, SettingsLayout, Sheet, Sidebar, SidebarNav, SliderRange, StackedList, StatsCard, StatusDot, Stepper, TIME_ZOOMS, Table, TableToolbar, Tabs, Tag, TagInput, TextOverflow, TimeBar, TimePicker, TimeRow, TimeScaleHeader, TimeViewport, Timeline, Toast, ToastProvider, Tour, TransferList, TreeView, dateOfDay, dayOf, endDayOf, fitLabel, fitLabels, formatDateRange, readFlowProgress, timeExtent, useContentWidth, useDestructiveAction, useFittedLabels, useFlowSteps, useSidebar, useTextMeasure, useTimeScale, useTimeViewport, useTimeViewportLayout, useToast, useToastOptional };
|
|
17014
17271
|
//# sourceMappingURL=index.js.map
|
|
17015
17272
|
//# sourceMappingURL=index.js.map
|