gridsmith-ui 0.18.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/charts.js +3 -3
- package/dist/charts.js.map +1 -1
- package/dist/chat.js +4 -4
- package/dist/{chunk-CIVSNXFG.js → chunk-5PDTHKW3.js} +17 -9
- package/dist/chunk-5PDTHKW3.js.map +1 -0
- package/dist/{chunk-XGSQOMEY.js → chunk-EQDR57AM.js} +4 -4
- package/dist/{chunk-XGSQOMEY.js.map → chunk-EQDR57AM.js.map} +1 -1
- package/dist/{chunk-EMCSARQO.js → chunk-ILIODA7W.js} +3 -3
- package/dist/{chunk-EMCSARQO.js.map → chunk-ILIODA7W.js.map} +1 -1
- package/dist/{chunk-OENJCGTJ.js → chunk-JN37OVTP.js} +4 -4
- package/dist/{chunk-OENJCGTJ.js.map → chunk-JN37OVTP.js.map} +1 -1
- package/dist/{chunk-4KVFH5KC.js → chunk-M2QRNBDQ.js} +4 -3
- package/dist/chunk-M2QRNBDQ.js.map +1 -0
- package/dist/{chunk-Z63OSN64.js → chunk-NCIZQYXQ.js} +7 -4
- package/dist/chunk-NCIZQYXQ.js.map +1 -0
- package/dist/{chunk-PVTGMCVR.js → chunk-XYDIBW3J.js} +4 -4
- package/dist/{chunk-PVTGMCVR.js.map → chunk-XYDIBW3J.js.map} +1 -1
- package/dist/data-grid.js +3 -3
- package/dist/editor.js +3 -3
- package/dist/editor.js.map +1 -1
- package/dist/index.d.ts +146 -53
- package/dist/index.js +437 -156
- package/dist/index.js.map +1 -1
- package/dist/kanban.js +3 -3
- package/dist/resizable.d.ts +8 -1
- package/dist/resizable.js +35 -15
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +164 -2
- package/dist/tailwind.css +14 -0
- package/dist/utils.js +1 -1
- package/dist/virtualized.js +1 -1
- package/dist-static/tailwind.css +14 -0
- package/package.json +1 -1
- package/dist/chunk-4KVFH5KC.js.map +0 -1
- package/dist/chunk-CIVSNXFG.js.map +0 -1
- package/dist/chunk-Z63OSN64.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { Button, useAppShell, REACT_VERSION_PROBLEM, ControlSizeContext, useDirtyGuard, OverlayCloseCtx, DiscardConfirm, Spinner, DrawerFooterCtx, useCompact, useElementWidth, Sheet, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, defaultMaxWidth } from './chunk-
|
|
2
|
-
export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell, useUnsavedChanges } from './chunk-
|
|
3
|
-
import { Skeleton } from './chunk-
|
|
4
|
-
export { Skeleton } from './chunk-
|
|
1
|
+
import { Button, useAppShell, REACT_VERSION_PROBLEM, ControlSizeContext, useDirtyGuard, OverlayCloseCtx, DiscardConfirm, Spinner, DrawerFooterCtx, useCompact, useElementWidth, Sheet, useCloseSettle, Drawer, useRememberedWidth, pxOf, ResizeEdge, defaultMaxWidth } from './chunk-5PDTHKW3.js';
|
|
2
|
+
export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell, useUnsavedChanges } from './chunk-5PDTHKW3.js';
|
|
3
|
+
import { Skeleton, TITLE_TEXT } from './chunk-NCIZQYXQ.js';
|
|
4
|
+
export { Skeleton } from './chunk-NCIZQYXQ.js';
|
|
5
5
|
import { FOCUSABLE, usePopupFocus, FIELD, ZOOM_KEYS, useOverlayLayer, useFocusTrap, useFocusBeforeOpen, rememberFocus, focusInitial, OVERLAY_CLOSE_ATTR, focusAfterRemoval, rovingTabStop, useGridKeyboard, useNonModalDialog, usePressMarks, useReturnFocus, useCloseOnFocusOut } from './chunk-JXANCXK6.js';
|
|
6
6
|
export { useGridKeyboard } from './chunk-JXANCXK6.js';
|
|
7
|
-
import { Link } from './chunk-
|
|
8
|
-
export { CodeBlock, Divider, Link } from './chunk-
|
|
9
|
-
import { Badge } from './chunk-
|
|
10
|
-
export { Badge } from './chunk-
|
|
11
|
-
import { inferColumnKinds, CardValue } from './chunk-
|
|
7
|
+
import { Link } from './chunk-EQDR57AM.js';
|
|
8
|
+
export { CodeBlock, Divider, Link } from './chunk-EQDR57AM.js';
|
|
9
|
+
import { Badge } from './chunk-XYDIBW3J.js';
|
|
10
|
+
export { Badge } from './chunk-XYDIBW3J.js';
|
|
11
|
+
import { inferColumnKinds, CardValue } from './chunk-JN37OVTP.js';
|
|
12
12
|
import { SplitPaneCtx, useShellPreferences, TableCardCtx, PREFERENCE_HOUSE_DEFAULTS, preferenceActionKey } from './chunk-TKVTZWBN.js';
|
|
13
13
|
export { PreferencesContext, preferenceActionKey, usePreferences } from './chunk-TKVTZWBN.js';
|
|
14
14
|
import { useBreakpoint, readBreakpointPx } from './chunk-CRQ6KCRD.js';
|
|
15
15
|
export { BreakpointWidthProvider, useBreakpoint } from './chunk-CRQ6KCRD.js';
|
|
16
|
-
import { useTextOverflow, Tooltip, usePosition } from './chunk-
|
|
17
|
-
export { Tooltip, useTextOverflow } from './chunk-
|
|
16
|
+
import { useTextOverflow, Tooltip, usePosition } from './chunk-ILIODA7W.js';
|
|
17
|
+
export { Tooltip, useTextOverflow } from './chunk-ILIODA7W.js';
|
|
18
18
|
import { mergeRefs, Slot } from './chunk-7Q46JXSK.js';
|
|
19
19
|
import { useLatest } from './chunk-WH2FUFAC.js';
|
|
20
20
|
import { Icon } from './chunk-4LDYR7QP.js';
|
|
21
|
-
import { cn, GLASS_SURFACE,
|
|
21
|
+
import { cn, GLASS_SURFACE, GLASS_BACKDROP, GLASS_DROPDOWN, lockBodyScroll, unlockBodyScroll, OVERLAY_SURFACE, GLASS_OVERLAY, ERROR_ACTIVE_RING, ACTIVE_RING, ERROR_FOCUS_RING, FOCUS_RING, ERROR_HAS_FOCUS_RING, HAS_FOCUS_RING, ERROR_FOCUS_WITHIN_RING, FOCUS_WITHIN_RING } from './chunk-M2QRNBDQ.js';
|
|
22
22
|
import { createContext, forwardRef, useState, useRef, useCallback, useLayoutEffect, useMemo, useContext, Children, isValidElement, useId, memo, useEffect, useImperativeHandle, Fragment as Fragment$1, cloneElement, useSyncExternalStore } from 'react';
|
|
23
23
|
import { createPortal, flushSync } from 'react-dom';
|
|
24
24
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -184,7 +184,7 @@ function BulkActionBar({ selectedCount, actions, onClearSelection, className })
|
|
|
184
184
|
) : /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2", children: actions.map((action, i) => /* @__PURE__ */ jsx(
|
|
185
185
|
Button,
|
|
186
186
|
{
|
|
187
|
-
variant:
|
|
187
|
+
variant: "secondary",
|
|
188
188
|
size: "sm",
|
|
189
189
|
onClick: action.onClick,
|
|
190
190
|
children: action.label
|
|
@@ -407,6 +407,155 @@ function Toggle({ checked, onChange, label, disabled, error = false, layout = "f
|
|
|
407
407
|
}
|
|
408
408
|
);
|
|
409
409
|
}
|
|
410
|
+
var FormCtx = createContext(null);
|
|
411
|
+
function useFormContext() {
|
|
412
|
+
const ctx = useContext(FormCtx);
|
|
413
|
+
if (!ctx) throw new Error("useFormContext must be used within FormWrapper");
|
|
414
|
+
return ctx;
|
|
415
|
+
}
|
|
416
|
+
function useOptionalFormContext() {
|
|
417
|
+
return useContext(FormCtx);
|
|
418
|
+
}
|
|
419
|
+
function InlineFieldError({ message, id, className }) {
|
|
420
|
+
return /* @__PURE__ */ jsxs(
|
|
421
|
+
"p",
|
|
422
|
+
{
|
|
423
|
+
id,
|
|
424
|
+
role: "alert",
|
|
425
|
+
className: cn(
|
|
426
|
+
"flex items-center gap-ds-1.5 text-xs text-[var(--ds-status-error)]",
|
|
427
|
+
"mt-ds-1.5",
|
|
428
|
+
className
|
|
429
|
+
),
|
|
430
|
+
children: [
|
|
431
|
+
/* @__PURE__ */ jsx(Icon, { name: "error", size: 14, className: "shrink-0" }),
|
|
432
|
+
/* @__PURE__ */ jsx("span", { children: message })
|
|
433
|
+
]
|
|
434
|
+
}
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
var FieldContext = createContext(null);
|
|
438
|
+
function useField() {
|
|
439
|
+
return useContext(FieldContext);
|
|
440
|
+
}
|
|
441
|
+
function useFieldControl(own, options = {}) {
|
|
442
|
+
const field = useField();
|
|
443
|
+
const id = own.id ?? field?.controlId;
|
|
444
|
+
const invalid = !!own.error || own["aria-invalid"] === true || own["aria-invalid"] === "true" || !!field?.invalid;
|
|
445
|
+
const required = !!own.required || own["aria-required"] === true || own["aria-required"] === "true" || !!field?.required;
|
|
446
|
+
const noteId = options.requiredInDescription && required && id ? `${id}-required` : void 0;
|
|
447
|
+
const ids = [own["aria-describedby"], field?.describedBy, noteId].filter(Boolean).join(" ").split(/\s+/).filter(Boolean);
|
|
448
|
+
return {
|
|
449
|
+
id,
|
|
450
|
+
labelId: own["aria-labelledby"] ?? field?.labelId,
|
|
451
|
+
describedBy: [...new Set(ids)].join(" ") || void 0,
|
|
452
|
+
invalid,
|
|
453
|
+
required,
|
|
454
|
+
requiredNote: noteId ? /* @__PURE__ */ jsx("span", { id: noteId, hidden: true, children: "Required" }) : null
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
function Field({ label, children, hint, error, required, labelAction, id: idProp, validate, className }) {
|
|
458
|
+
const generated = useId();
|
|
459
|
+
const id = idProp ?? `field-${generated}`;
|
|
460
|
+
const hintId = `${id}-hint`;
|
|
461
|
+
const errorId = `${id}-error`;
|
|
462
|
+
const form = useOptionalFormContext();
|
|
463
|
+
const mode = form?.validationMode ?? "onBlur";
|
|
464
|
+
const [localError, setLocalError] = useState(void 0);
|
|
465
|
+
const [left, setLeft] = useState(false);
|
|
466
|
+
const checkError = validate ? form ? form.errors[id] : localError : void 0;
|
|
467
|
+
const child = typeof children === "function" ? null : Children.only(children);
|
|
468
|
+
const childProps = child && isValidElement(child) ? child.props : null;
|
|
469
|
+
const latest = useLatest({ validate, childProps, id, mode, left, showing: !!checkError, form });
|
|
470
|
+
const check = useCallback(() => {
|
|
471
|
+
const { validate: fn, childProps: props, id: controlId } = latest.current;
|
|
472
|
+
if (!fn) return void 0;
|
|
473
|
+
const value = props && "value" in props ? props.value : props && "checked" in props ? props.checked : document.getElementById(controlId)?.value;
|
|
474
|
+
const message = fn(value);
|
|
475
|
+
return typeof message === "string" && message.length > 0 ? message : void 0;
|
|
476
|
+
}, [latest]);
|
|
477
|
+
const show = useCallback((message) => {
|
|
478
|
+
const { form: f, id: controlId } = latest.current;
|
|
479
|
+
if (f) f.setError(controlId, message);
|
|
480
|
+
else setLocalError(message);
|
|
481
|
+
}, [latest]);
|
|
482
|
+
const register = form?.register;
|
|
483
|
+
const checks = !!validate;
|
|
484
|
+
useEffect(() => register && checks ? register(id, check) : void 0, [register, checks, id, check]);
|
|
485
|
+
const leaving = useRef(null);
|
|
486
|
+
useEffect(() => () => {
|
|
487
|
+
if (leaving.current) clearTimeout(leaving.current);
|
|
488
|
+
}, []);
|
|
489
|
+
const onFocusCapture = () => {
|
|
490
|
+
if (leaving.current) {
|
|
491
|
+
clearTimeout(leaving.current);
|
|
492
|
+
leaving.current = null;
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
const onBlurCapture = () => {
|
|
496
|
+
if (!validate) return;
|
|
497
|
+
if (leaving.current) clearTimeout(leaving.current);
|
|
498
|
+
leaving.current = setTimeout(() => {
|
|
499
|
+
leaving.current = null;
|
|
500
|
+
setLeft(true);
|
|
501
|
+
if (latest.current.mode !== "onSubmit" || latest.current.showing) show(check());
|
|
502
|
+
}, 0);
|
|
503
|
+
};
|
|
504
|
+
const recheck = () => {
|
|
505
|
+
if (!validate) return;
|
|
506
|
+
setTimeout(() => {
|
|
507
|
+
const { mode: m, left: wasLeft, showing } = latest.current;
|
|
508
|
+
if (m === "onChange" && wasLeft || showing) show(check());
|
|
509
|
+
}, 0);
|
|
510
|
+
};
|
|
511
|
+
const shownError = typeof error === "string" && error.length > 0 ? error : checkError;
|
|
512
|
+
const hasError = typeof shownError === "string" && shownError.length > 0;
|
|
513
|
+
const describedBy = [hint ? hintId : null, hasError ? errorId : null].filter(Boolean).join(" ") || void 0;
|
|
514
|
+
const labelId = `${id}-label`;
|
|
515
|
+
const fieldContext = useMemo(() => ({ controlId: id, labelId, describedBy, invalid: hasError, required: !!required }), [id, labelId, describedBy, hasError, required]);
|
|
516
|
+
const controlProps = {
|
|
517
|
+
id,
|
|
518
|
+
"aria-describedby": describedBy,
|
|
519
|
+
...hasError ? { "aria-invalid": true, error: true } : {},
|
|
520
|
+
...required ? { "aria-required": true, required: true } : {}
|
|
521
|
+
};
|
|
522
|
+
let control;
|
|
523
|
+
if (typeof children === "function") {
|
|
524
|
+
control = children(controlProps);
|
|
525
|
+
} else {
|
|
526
|
+
if (!child || !isValidElement(child)) throw new Error("Field expects a single form control as its child");
|
|
527
|
+
const isNative = typeof child.type === "string";
|
|
528
|
+
const { error: errorFlag, ...ariaOnly } = controlProps;
|
|
529
|
+
const ownOnChange = childProps?.onChange;
|
|
530
|
+
const onChange = validate && !isNative ? { onChange: (...args) => {
|
|
531
|
+
ownOnChange?.(...args);
|
|
532
|
+
recheck();
|
|
533
|
+
} } : {};
|
|
534
|
+
control = cloneElement(child, isNative ? ariaOnly : { ...ariaOnly, ...errorFlag ? { error: true } : {}, ...onChange });
|
|
535
|
+
}
|
|
536
|
+
return (
|
|
537
|
+
// In a settings panel a field keeps the narrow reading width however wide the page is (--ds-form-max, Sprint 25.9 A4)
|
|
538
|
+
/* @__PURE__ */ jsxs(
|
|
539
|
+
"div",
|
|
540
|
+
{
|
|
541
|
+
className: cn("flex flex-col gap-ds-1.5 max-w-[var(--ds-form-max,none)]", className),
|
|
542
|
+
...validate ? { onFocusCapture, onBlurCapture, onInputCapture: recheck } : {},
|
|
543
|
+
children: [
|
|
544
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-ds-2", children: [
|
|
545
|
+
/* @__PURE__ */ jsxs(Label, { id: labelId, htmlFor: id, children: [
|
|
546
|
+
label,
|
|
547
|
+
required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ml-ds-0.5 text-[var(--ds-status-error)]", children: "*" })
|
|
548
|
+
] }),
|
|
549
|
+
labelAction
|
|
550
|
+
] }),
|
|
551
|
+
/* @__PURE__ */ jsx(FieldContext.Provider, { value: fieldContext, children: control }),
|
|
552
|
+
hint && /* @__PURE__ */ jsx("p", { id: hintId, className: "text-xs text-[var(--ds-text-muted)]", children: hint }),
|
|
553
|
+
hasError && /* @__PURE__ */ jsx(InlineFieldError, { id: errorId, message: shownError, className: "mt-0" })
|
|
554
|
+
]
|
|
555
|
+
}
|
|
556
|
+
)
|
|
557
|
+
);
|
|
558
|
+
}
|
|
410
559
|
var DROPDOWN_HEIGHT = {
|
|
411
560
|
sm: "px-ds-2 py-ds-1 text-xs h-[var(--ds-control-height-sm)]",
|
|
412
561
|
md: "px-ds-3 py-ds-2 text-sm h-[var(--ds-control-height-md)]",
|
|
@@ -427,9 +576,16 @@ function Dropdown({
|
|
|
427
576
|
container,
|
|
428
577
|
error = false,
|
|
429
578
|
showChips = true,
|
|
430
|
-
"aria-label": ariaLabel
|
|
579
|
+
"aria-label": ariaLabel,
|
|
580
|
+
...wiring
|
|
431
581
|
}) {
|
|
432
582
|
const contextSize = useContext(ControlSizeContext);
|
|
583
|
+
const generatedId = useId();
|
|
584
|
+
const control = useFieldControl({ ...wiring, error: error || void 0 }, { requiredInDescription: true });
|
|
585
|
+
const triggerId = control.id ?? generatedId;
|
|
586
|
+
const labelSpanId = `${triggerId}-label`;
|
|
587
|
+
const labelledBy = control.labelId ? `${control.labelId} ${triggerId}` : label && !ariaLabel ? `${labelSpanId} ${triggerId}` : void 0;
|
|
588
|
+
const invalid = control.invalid;
|
|
433
589
|
const size = sizeProp ?? contextSize ?? "md";
|
|
434
590
|
const [open, setOpen] = useState(false);
|
|
435
591
|
const [search, setSearch] = useState("");
|
|
@@ -597,11 +753,13 @@ function Dropdown({
|
|
|
597
753
|
const displayLabel = multiple ? selectedValues.length > 0 ? `${selectedValues.length} selected` : placeholder : options.find((o) => o.id === selectedValues[0])?.label ?? placeholder;
|
|
598
754
|
const { ref: overflowRef, isTruncated } = useTextOverflow({ lines: 1, content: displayLabel });
|
|
599
755
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn("relative", className), children: [
|
|
600
|
-
label && /* @__PURE__ */ jsx("span", { className: "block mb-ds-1.5 text-sm font-medium text-[var(--ds-text-secondary)]", children: label }),
|
|
756
|
+
label && /* @__PURE__ */ jsx("span", { id: labelSpanId, className: "block mb-ds-1.5 text-sm font-medium text-[var(--ds-text-secondary)]", children: label }),
|
|
757
|
+
control.requiredNote,
|
|
601
758
|
/* @__PURE__ */ jsxs(
|
|
602
759
|
"button",
|
|
603
760
|
{
|
|
604
761
|
ref: triggerRef,
|
|
762
|
+
id: triggerId,
|
|
605
763
|
type: "button",
|
|
606
764
|
onClick: () => !disabled && setOpen(!open),
|
|
607
765
|
onKeyDown: (e) => {
|
|
@@ -612,22 +770,24 @@ function Dropdown({
|
|
|
612
770
|
}
|
|
613
771
|
},
|
|
614
772
|
disabled,
|
|
615
|
-
"aria-invalid":
|
|
773
|
+
"aria-invalid": invalid || void 0,
|
|
616
774
|
"aria-haspopup": "listbox",
|
|
617
775
|
"aria-expanded": open,
|
|
618
|
-
"aria-label": ariaLabel,
|
|
776
|
+
"aria-label": labelledBy ? void 0 : ariaLabel,
|
|
777
|
+
"aria-labelledby": labelledBy,
|
|
778
|
+
"aria-describedby": control.describedBy,
|
|
619
779
|
className: cn(
|
|
620
780
|
"w-full flex items-center justify-between gap-ds-2",
|
|
621
781
|
DROPDOWN_HEIGHT[size],
|
|
622
782
|
"bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)]",
|
|
623
783
|
"border-[length:var(--ds-border-width)]",
|
|
624
|
-
|
|
784
|
+
invalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
|
|
625
785
|
"rounded-[var(--ds-radius-md)]",
|
|
626
786
|
"shadow-[var(--ds-input-shadow)]",
|
|
627
787
|
"transition-colors",
|
|
628
|
-
!
|
|
629
|
-
open && (
|
|
630
|
-
|
|
788
|
+
!invalid && !disabled && !open && "hover:border-[var(--ds-input-border-hover)]",
|
|
789
|
+
open && (invalid ? ERROR_ACTIVE_RING : ACTIVE_RING),
|
|
790
|
+
invalid ? ERROR_FOCUS_RING : FOCUS_RING,
|
|
631
791
|
"cursor-pointer disabled:cursor-not-allowed disabled:opacity-disabled",
|
|
632
792
|
!selectedValues.length && "text-[var(--ds-text-muted)]"
|
|
633
793
|
),
|
|
@@ -642,9 +802,10 @@ function Dropdown({
|
|
|
642
802
|
"div",
|
|
643
803
|
{
|
|
644
804
|
ref: menuRef,
|
|
805
|
+
tabIndex: -1,
|
|
645
806
|
onClick: (e) => e.stopPropagation(),
|
|
646
807
|
className: cn(
|
|
647
|
-
"fixed z-[var(--ds-z-popover)]",
|
|
808
|
+
"fixed z-[var(--ds-z-popover)] outline-none",
|
|
648
809
|
"bg-[var(--ds-bg-surface-elevated)]",
|
|
649
810
|
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
650
811
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
@@ -771,8 +932,9 @@ var TEXT_SIZE = {
|
|
|
771
932
|
md: "text-sm",
|
|
772
933
|
lg: "text-base"
|
|
773
934
|
};
|
|
774
|
-
function Combobox({ value, onChange, options, placeholder = "Search\u2026", disabled, loading = false, className, ref, container, error = false, size: sizeProp }) {
|
|
935
|
+
function Combobox({ value, onChange, options, placeholder = "Search\u2026", disabled, loading = false, className, ref, container, error = false, size: sizeProp, ...wiring }) {
|
|
775
936
|
const contextSize = useContext(ControlSizeContext);
|
|
937
|
+
const control = useFieldControl({ ...wiring, error: error || void 0 });
|
|
776
938
|
const size = sizeProp ?? contextSize ?? "md";
|
|
777
939
|
const [open, setOpen] = useState(false);
|
|
778
940
|
useOverlayLayer(open);
|
|
@@ -883,12 +1045,12 @@ function Combobox({ value, onChange, options, placeholder = "Search\u2026", disa
|
|
|
883
1045
|
"flex items-center",
|
|
884
1046
|
CONTROL_HEIGHT[size],
|
|
885
1047
|
"border-[length:var(--ds-border-width)]",
|
|
886
|
-
|
|
1048
|
+
control.invalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
|
|
887
1049
|
"bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
|
|
888
1050
|
"shadow-[var(--ds-input-shadow)]",
|
|
889
1051
|
"transition-colors duration-[var(--ds-transition-speed)]",
|
|
890
|
-
!
|
|
891
|
-
|
|
1052
|
+
!control.invalid && !disabled && "hover:border-[var(--ds-input-border-hover)]",
|
|
1053
|
+
control.invalid ? ERROR_HAS_FOCUS_RING : HAS_FOCUS_RING,
|
|
892
1054
|
disabled && "opacity-disabled pointer-events-none"
|
|
893
1055
|
),
|
|
894
1056
|
children: [
|
|
@@ -898,8 +1060,12 @@ function Combobox({ value, onChange, options, placeholder = "Search\u2026", disa
|
|
|
898
1060
|
{
|
|
899
1061
|
ref: mergeInputRefs,
|
|
900
1062
|
type: "text",
|
|
1063
|
+
id: control.id,
|
|
901
1064
|
role: "combobox",
|
|
902
|
-
"aria-
|
|
1065
|
+
"aria-labelledby": wiring["aria-labelledby"],
|
|
1066
|
+
"aria-describedby": control.describedBy,
|
|
1067
|
+
"aria-invalid": control.invalid || void 0,
|
|
1068
|
+
"aria-required": control.required || void 0,
|
|
903
1069
|
"aria-expanded": open,
|
|
904
1070
|
"aria-controls": listboxId,
|
|
905
1071
|
"aria-autocomplete": "list",
|
|
@@ -1312,7 +1478,7 @@ function parseTypedDate(text, dayFirst = localeDayFirst()) {
|
|
|
1312
1478
|
}
|
|
1313
1479
|
return null;
|
|
1314
1480
|
}
|
|
1315
|
-
function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, className, ref, container, error = false, label, id, size: sizeProp, min, max, range: range2 }) {
|
|
1481
|
+
function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, className, ref, container, error = false, label, id, size: sizeProp, min, max, range: range2, ...wiring }) {
|
|
1316
1482
|
const contextSize = useContext(ControlSizeContext);
|
|
1317
1483
|
const size = sizeProp ?? contextSize ?? "md";
|
|
1318
1484
|
const [open, setOpen] = useState(false);
|
|
@@ -1323,7 +1489,8 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1323
1489
|
const panelRef = useRef(null);
|
|
1324
1490
|
const gridRef = useRef(null);
|
|
1325
1491
|
const generatedId = useId();
|
|
1326
|
-
const
|
|
1492
|
+
const control = useFieldControl({ ...wiring, id, error: error || void 0 }, { requiredInDescription: true });
|
|
1493
|
+
const inputId = control.id ?? generatedId;
|
|
1327
1494
|
const pos = usePosition(triggerRef, panelRef, open, { side: "bottom", align: "start", offset: 4, flip: true });
|
|
1328
1495
|
const year = viewDate.getFullYear();
|
|
1329
1496
|
const month = viewDate.getMonth();
|
|
@@ -1508,6 +1675,7 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1508
1675
|
for (let i = 0; i < cells.length; i += 7) weeks.push(cells.slice(i, i + 7));
|
|
1509
1676
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn(className), children: [
|
|
1510
1677
|
label && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "block text-sm font-medium text-[var(--ds-text-primary)] mb-ds-1", children: label }),
|
|
1678
|
+
control.requiredNote,
|
|
1511
1679
|
/* @__PURE__ */ jsxs(
|
|
1512
1680
|
"div",
|
|
1513
1681
|
{
|
|
@@ -1515,9 +1683,11 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1515
1683
|
"data-date-field": "",
|
|
1516
1684
|
role: "group",
|
|
1517
1685
|
id: inputId,
|
|
1518
|
-
"aria-label": label ?? "Date",
|
|
1686
|
+
"aria-label": control.labelId ? void 0 : label ?? "Date",
|
|
1687
|
+
"aria-labelledby": control.labelId,
|
|
1688
|
+
"aria-describedby": control.describedBy,
|
|
1519
1689
|
"aria-description": !value ? placeholder : void 0,
|
|
1520
|
-
"aria-invalid":
|
|
1690
|
+
"aria-invalid": control.invalid || typedInvalid || void 0,
|
|
1521
1691
|
onPaste: (e) => {
|
|
1522
1692
|
const text = e.clipboardData.getData("text");
|
|
1523
1693
|
if (text) {
|
|
@@ -1530,12 +1700,12 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1530
1700
|
CONTROL_HEIGHT2[size],
|
|
1531
1701
|
TEXT_SIZE2[size],
|
|
1532
1702
|
"border-[length:var(--ds-border-width)]",
|
|
1533
|
-
|
|
1703
|
+
control.invalid || typedInvalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
|
|
1534
1704
|
"bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
|
|
1535
1705
|
"shadow-[var(--ds-input-shadow)]",
|
|
1536
1706
|
"transition-colors",
|
|
1537
1707
|
"px-ds-3 py-ds-2",
|
|
1538
|
-
!
|
|
1708
|
+
!control.invalid && !disabled && !open && "hover:border-[var(--ds-input-border-hover)] focus-within:border-[var(--ds-input-border-hover)]",
|
|
1539
1709
|
open && ACTIVE_RING,
|
|
1540
1710
|
disabled && "opacity-disabled cursor-not-allowed",
|
|
1541
1711
|
"text-[var(--ds-text-primary)]"
|
|
@@ -1592,8 +1762,9 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
|
|
|
1592
1762
|
ref: panelRef,
|
|
1593
1763
|
role: "dialog",
|
|
1594
1764
|
"aria-label": "Choose a date",
|
|
1765
|
+
tabIndex: -1,
|
|
1595
1766
|
className: cn(
|
|
1596
|
-
"fixed z-[var(--ds-z-popover)] w-[280px]",
|
|
1767
|
+
"fixed z-[var(--ds-z-popover)] w-[280px] outline-none",
|
|
1597
1768
|
"bg-[var(--ds-bg-surface-elevated)]",
|
|
1598
1769
|
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
1599
1770
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
@@ -1925,7 +2096,8 @@ function DateRangePicker({
|
|
|
1925
2096
|
max,
|
|
1926
2097
|
presets = DEFAULT_DATE_RANGE_PRESETS,
|
|
1927
2098
|
weekStartsOn = 0,
|
|
1928
|
-
size: sizeProp
|
|
2099
|
+
size: sizeProp,
|
|
2100
|
+
...wiring
|
|
1929
2101
|
}) {
|
|
1930
2102
|
const contextSize = useContext(ControlSizeContext);
|
|
1931
2103
|
const size = sizeProp ?? contextSize ?? "md";
|
|
@@ -1935,7 +2107,9 @@ function DateRangePicker({
|
|
|
1935
2107
|
const triggerRef = useRef(null);
|
|
1936
2108
|
const panelRef = useRef(null);
|
|
1937
2109
|
const generatedId = useId();
|
|
1938
|
-
const
|
|
2110
|
+
const control = useFieldControl({ ...wiring, id, error: error || void 0 }, { requiredInDescription: true });
|
|
2111
|
+
const triggerId = control.id ?? generatedId;
|
|
2112
|
+
const labelledBy = control.labelId ? `${control.labelId} ${triggerId}` : void 0;
|
|
1939
2113
|
const pos = usePosition(triggerRef, panelRef, open, { side: "bottom", align: "start", offset: 4, flip: true });
|
|
1940
2114
|
const today = useMemo(() => startOfDay(/* @__PURE__ */ new Date()), []);
|
|
1941
2115
|
const dayNames = getOrderedDayNamesShort(weekStartsOn);
|
|
@@ -2018,6 +2192,7 @@ function DateRangePicker({
|
|
|
2018
2192
|
const summary = value.start && value.end ? `${fmt(value.start)} \u2013 ${fmt(value.end)}` : value.start ? `${fmt(value.start)} \u2013 \u2026` : null;
|
|
2019
2193
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn(className), children: [
|
|
2020
2194
|
label && /* @__PURE__ */ jsx("label", { htmlFor: triggerId, className: "block text-sm font-medium text-[var(--ds-text-primary)] mb-ds-1", children: label }),
|
|
2195
|
+
control.requiredNote,
|
|
2021
2196
|
/* @__PURE__ */ jsxs(
|
|
2022
2197
|
"button",
|
|
2023
2198
|
{
|
|
@@ -2026,7 +2201,9 @@ function DateRangePicker({
|
|
|
2026
2201
|
type: "button",
|
|
2027
2202
|
onClick: () => !disabled && setOpen((o) => !o),
|
|
2028
2203
|
disabled,
|
|
2029
|
-
"aria-
|
|
2204
|
+
"aria-labelledby": labelledBy,
|
|
2205
|
+
"aria-describedby": control.describedBy,
|
|
2206
|
+
"aria-invalid": control.invalid || void 0,
|
|
2030
2207
|
"aria-haspopup": "dialog",
|
|
2031
2208
|
"aria-expanded": open,
|
|
2032
2209
|
className: cn(
|
|
@@ -2034,14 +2211,14 @@ function DateRangePicker({
|
|
|
2034
2211
|
CONTROL_HEIGHT3[size],
|
|
2035
2212
|
TEXT_SIZE3[size],
|
|
2036
2213
|
"border-[length:var(--ds-border-width)]",
|
|
2037
|
-
|
|
2214
|
+
control.invalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
|
|
2038
2215
|
"bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
|
|
2039
2216
|
"shadow-[var(--ds-input-shadow)]",
|
|
2040
2217
|
"transition-colors cursor-pointer",
|
|
2041
2218
|
"px-ds-3 py-ds-2",
|
|
2042
|
-
!
|
|
2043
|
-
open && (
|
|
2044
|
-
|
|
2219
|
+
!control.invalid && !disabled && !open && "hover:border-[var(--ds-input-border-hover)]",
|
|
2220
|
+
open && (control.invalid ? ERROR_ACTIVE_RING : ACTIVE_RING),
|
|
2221
|
+
control.invalid ? ERROR_FOCUS_RING : FOCUS_RING,
|
|
2045
2222
|
disabled && "opacity-disabled cursor-not-allowed",
|
|
2046
2223
|
summary ? "text-[var(--ds-text-primary)]" : "text-[var(--ds-text-muted)]"
|
|
2047
2224
|
),
|
|
@@ -2058,8 +2235,9 @@ function DateRangePicker({
|
|
|
2058
2235
|
ref: panelRef,
|
|
2059
2236
|
role: "dialog",
|
|
2060
2237
|
"aria-label": "Choose a date range",
|
|
2238
|
+
tabIndex: -1,
|
|
2061
2239
|
className: cn(
|
|
2062
|
-
"fixed z-[var(--ds-z-popover)] flex",
|
|
2240
|
+
"fixed z-[var(--ds-z-popover)] flex outline-none",
|
|
2063
2241
|
"bg-[var(--ds-bg-surface-elevated)]",
|
|
2064
2242
|
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
2065
2243
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
@@ -2264,7 +2442,7 @@ function Progress({ value, max = 100, variant = "default", size = "md", indeterm
|
|
|
2264
2442
|
{
|
|
2265
2443
|
className: cn(
|
|
2266
2444
|
"h-full rounded-[var(--ds-radius-full)]",
|
|
2267
|
-
indeterminate ? "animate-[indeterminate_1.5s_ease-in-out_infinite] w-1/3" : "transition-all",
|
|
2445
|
+
indeterminate ? "animate-[gs-indeterminate_1.5s_ease-in-out_infinite] w-1/3" : "transition-all",
|
|
2268
2446
|
variantFills[variant]
|
|
2269
2447
|
),
|
|
2270
2448
|
style: indeterminate ? void 0 : { width: `${pct}%` }
|
|
@@ -2278,69 +2456,6 @@ function Progress({ value, max = 100, variant = "default", size = "md", indeterm
|
|
|
2278
2456
|
] })
|
|
2279
2457
|
] });
|
|
2280
2458
|
}
|
|
2281
|
-
function InlineFieldError({ message, id, className }) {
|
|
2282
|
-
return /* @__PURE__ */ jsxs(
|
|
2283
|
-
"p",
|
|
2284
|
-
{
|
|
2285
|
-
id,
|
|
2286
|
-
role: "alert",
|
|
2287
|
-
className: cn(
|
|
2288
|
-
"flex items-center gap-ds-1.5 text-xs text-[var(--ds-status-error)]",
|
|
2289
|
-
"mt-ds-1.5",
|
|
2290
|
-
className
|
|
2291
|
-
),
|
|
2292
|
-
children: [
|
|
2293
|
-
/* @__PURE__ */ jsx(Icon, { name: "error", size: 14, className: "shrink-0" }),
|
|
2294
|
-
/* @__PURE__ */ jsx("span", { children: message })
|
|
2295
|
-
]
|
|
2296
|
-
}
|
|
2297
|
-
);
|
|
2298
|
-
}
|
|
2299
|
-
var FieldContext = createContext(null);
|
|
2300
|
-
function useField() {
|
|
2301
|
-
return useContext(FieldContext);
|
|
2302
|
-
}
|
|
2303
|
-
function Field({ label, children, hint, error, required, labelAction, id: idProp, className }) {
|
|
2304
|
-
const generated = useId();
|
|
2305
|
-
const id = idProp ?? `field-${generated}`;
|
|
2306
|
-
const hintId = `${id}-hint`;
|
|
2307
|
-
const errorId = `${id}-error`;
|
|
2308
|
-
const hasError = typeof error === "string" && error.length > 0;
|
|
2309
|
-
const describedBy = [hint ? hintId : null, hasError ? errorId : null].filter(Boolean).join(" ") || void 0;
|
|
2310
|
-
const labelId = `${id}-label`;
|
|
2311
|
-
const fieldContext = useMemo(() => ({ controlId: id, labelId, describedBy }), [id, labelId, describedBy]);
|
|
2312
|
-
const controlProps = {
|
|
2313
|
-
id,
|
|
2314
|
-
"aria-describedby": describedBy,
|
|
2315
|
-
...hasError ? { "aria-invalid": true, error: true } : {},
|
|
2316
|
-
...required ? { "aria-required": true, required: true } : {}
|
|
2317
|
-
};
|
|
2318
|
-
let control;
|
|
2319
|
-
if (typeof children === "function") {
|
|
2320
|
-
control = children(controlProps);
|
|
2321
|
-
} else {
|
|
2322
|
-
const child = Children.only(children);
|
|
2323
|
-
if (!isValidElement(child)) throw new Error("Field expects a single form control as its child");
|
|
2324
|
-
const isNative = typeof child.type === "string";
|
|
2325
|
-
const { error: errorFlag, ...ariaOnly } = controlProps;
|
|
2326
|
-
control = cloneElement(child, isNative ? ariaOnly : { ...ariaOnly, ...errorFlag ? { error: true } : {} });
|
|
2327
|
-
}
|
|
2328
|
-
return (
|
|
2329
|
-
// In a settings panel a field keeps the narrow reading width however wide the page is (--ds-form-max, Sprint 25.9 A4)
|
|
2330
|
-
/* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-ds-1.5 max-w-[var(--ds-form-max,none)]", className), children: [
|
|
2331
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-ds-2", children: [
|
|
2332
|
-
/* @__PURE__ */ jsxs(Label, { id: labelId, htmlFor: id, children: [
|
|
2333
|
-
label,
|
|
2334
|
-
required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ml-ds-0.5 text-[var(--ds-status-error)]", children: "*" })
|
|
2335
|
-
] }),
|
|
2336
|
-
labelAction
|
|
2337
|
-
] }),
|
|
2338
|
-
/* @__PURE__ */ jsx(FieldContext.Provider, { value: fieldContext, children: control }),
|
|
2339
|
-
hint && /* @__PURE__ */ jsx("p", { id: hintId, className: "text-xs text-[var(--ds-text-muted)]", children: hint }),
|
|
2340
|
-
hasError && /* @__PURE__ */ jsx(InlineFieldError, { id: errorId, message: error, className: "mt-0" })
|
|
2341
|
-
] })
|
|
2342
|
-
);
|
|
2343
|
-
}
|
|
2344
2459
|
function TruncFileName({ children, className }) {
|
|
2345
2460
|
const { ref, isTruncated } = useTextOverflow({ lines: 1 });
|
|
2346
2461
|
const el = /* @__PURE__ */ jsx("p", { ref, className: cn("truncate", className), children });
|
|
@@ -2726,9 +2841,11 @@ function TimePicker({
|
|
|
2726
2841
|
container,
|
|
2727
2842
|
error = false,
|
|
2728
2843
|
id,
|
|
2729
|
-
size: sizeProp
|
|
2844
|
+
size: sizeProp,
|
|
2845
|
+
...wiring
|
|
2730
2846
|
}) {
|
|
2731
2847
|
const contextSize = useContext(ControlSizeContext);
|
|
2848
|
+
const control = useFieldControl({ ...wiring, id, error: error || void 0 }, { requiredInDescription: true });
|
|
2732
2849
|
const size = sizeProp ?? contextSize ?? "md";
|
|
2733
2850
|
const [open, setOpen] = useState(false);
|
|
2734
2851
|
const triggerRef = useRef(null);
|
|
@@ -2912,15 +3029,18 @@ function TimePicker({
|
|
|
2912
3029
|
return segs[k] === null ? spec.placeholder : pad2(segs[k]);
|
|
2913
3030
|
};
|
|
2914
3031
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn(className), children: [
|
|
3032
|
+
control.requiredNote,
|
|
2915
3033
|
/* @__PURE__ */ jsxs(
|
|
2916
3034
|
"div",
|
|
2917
3035
|
{
|
|
2918
3036
|
ref: triggerRef,
|
|
2919
3037
|
"data-time-field": "",
|
|
2920
3038
|
role: "group",
|
|
2921
|
-
id,
|
|
2922
|
-
"aria-label": "Time",
|
|
2923
|
-
"aria-
|
|
3039
|
+
id: control.id,
|
|
3040
|
+
"aria-label": control.labelId ? void 0 : "Time",
|
|
3041
|
+
"aria-labelledby": control.labelId,
|
|
3042
|
+
"aria-describedby": control.describedBy,
|
|
3043
|
+
"aria-invalid": control.invalid || void 0,
|
|
2924
3044
|
onPaste: (e) => {
|
|
2925
3045
|
const text = e.clipboardData.getData("text");
|
|
2926
3046
|
if (text) {
|
|
@@ -2933,12 +3053,12 @@ function TimePicker({
|
|
|
2933
3053
|
CONTROL_HEIGHT4[size],
|
|
2934
3054
|
TEXT_SIZE4[size],
|
|
2935
3055
|
"border-[length:var(--ds-border-width)]",
|
|
2936
|
-
|
|
3056
|
+
control.invalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
|
|
2937
3057
|
"bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
|
|
2938
3058
|
"shadow-[var(--ds-input-shadow)]",
|
|
2939
3059
|
"transition-colors",
|
|
2940
3060
|
"px-ds-3 py-ds-2",
|
|
2941
|
-
!
|
|
3061
|
+
!control.invalid && !disabled && !open && "hover:border-[var(--ds-input-border-hover)] focus-within:border-[var(--ds-input-border-hover)]",
|
|
2942
3062
|
open && ACTIVE_RING,
|
|
2943
3063
|
disabled && "opacity-disabled cursor-not-allowed",
|
|
2944
3064
|
"text-[var(--ds-text-primary)]"
|
|
@@ -3019,9 +3139,10 @@ function TimePicker({
|
|
|
3019
3139
|
id: listboxId,
|
|
3020
3140
|
role: "dialog",
|
|
3021
3141
|
"aria-label": "Choose a time",
|
|
3142
|
+
tabIndex: -1,
|
|
3022
3143
|
onKeyDown: handlePanelKeyDown,
|
|
3023
3144
|
className: cn(
|
|
3024
|
-
"fixed z-[var(--ds-z-popover)]",
|
|
3145
|
+
"fixed z-[var(--ds-z-popover)] outline-none",
|
|
3025
3146
|
"bg-[var(--ds-bg-surface-elevated)]",
|
|
3026
3147
|
GLASS_DROPDOWN,
|
|
3027
3148
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
@@ -4189,23 +4310,21 @@ function stampFormId(node, formId) {
|
|
|
4189
4310
|
return cloneElement(child, { form: formId });
|
|
4190
4311
|
});
|
|
4191
4312
|
}
|
|
4192
|
-
var FormCtx = createContext(null);
|
|
4193
|
-
function useFormContext() {
|
|
4194
|
-
const ctx = useContext(FormCtx);
|
|
4195
|
-
if (!ctx) throw new Error("useFormContext must be used within FormWrapper");
|
|
4196
|
-
return ctx;
|
|
4197
|
-
}
|
|
4198
4313
|
function collectInvalidFields(form) {
|
|
4199
4314
|
const out = [];
|
|
4200
4315
|
for (const el of Array.from(form.querySelectorAll("[aria-invalid='true']"))) {
|
|
4201
4316
|
const id = el.id || "";
|
|
4202
4317
|
const label = id && form.querySelector(`label[for="${CSS.escape(id)}"]`)?.textContent?.replace(/\*\s*$/, "").trim() || el.getAttribute("aria-label") || el.closest("[data-field]")?.querySelector("label")?.textContent?.trim() || id || "A field";
|
|
4203
|
-
const described = (el.getAttribute("aria-describedby") ?? "").split(/\s+/).filter(Boolean);
|
|
4204
|
-
const message = described.
|
|
4318
|
+
const described = (el.getAttribute("aria-describedby") ?? "").split(/\s+/).filter(Boolean).map((d) => document.getElementById(d)).filter((d) => !!d);
|
|
4319
|
+
const message = described.find((d) => d.getAttribute("role") === "alert")?.textContent?.trim() || described.map((d) => d.textContent?.trim()).find((t) => t && t !== "Required" && /error|invalid|required|must|enter|choose|select|please/i.test(t)) || described.map((d) => d.textContent?.trim()).filter(Boolean).pop() || "Needs attention";
|
|
4205
4320
|
out.push({ id, label, message });
|
|
4206
4321
|
}
|
|
4207
4322
|
return out;
|
|
4208
4323
|
}
|
|
4324
|
+
function focusTarget(el) {
|
|
4325
|
+
if (el.tabIndex >= 0 || /^(?:INPUT|SELECT|TEXTAREA|BUTTON)$/.test(el.tagName)) return el;
|
|
4326
|
+
return el.querySelector("[aria-checked='true'], [aria-selected='true']:not([tabindex='-1'])") ?? el.querySelector("input, select, textarea, button, [tabindex]:not([tabindex='-1'])") ?? el;
|
|
4327
|
+
}
|
|
4209
4328
|
function FormWrapper({ onSubmit, validationMode: validationModeProp, children, actions: actionsProp, actionsAlign: actionsAlignProp, onCancel, cancelLabel = "Cancel", focusFirstError = true, errorSummary = true, className, ref }) {
|
|
4210
4329
|
const preferences = useShellPreferences();
|
|
4211
4330
|
const validationMode = validationModeProp ?? preferences.validationTiming ?? "onSubmit";
|
|
@@ -4246,21 +4365,41 @@ function FormWrapper({ onSubmit, validationMode: validationModeProp, children, a
|
|
|
4246
4365
|
onSubmitRef.current(errorsRef.current);
|
|
4247
4366
|
}
|
|
4248
4367
|
}, [submitted, submitCount, errors, errorsRef, onSubmitRef]);
|
|
4368
|
+
const submittedRef = useLatest(submitted);
|
|
4369
|
+
const errorSummaryRef = useLatest(errorSummary);
|
|
4370
|
+
const summaryRef = useRef(null);
|
|
4371
|
+
const pendingSummaryFocus = useRef(false);
|
|
4372
|
+
const focusSummary = useCallback(() => {
|
|
4373
|
+
const el = summaryRef.current;
|
|
4374
|
+
if (!el) return;
|
|
4375
|
+
if (typeof el.scrollIntoView === "function") el.scrollIntoView({ block: "center", behavior: "smooth" });
|
|
4376
|
+
el.focus({ preventScroll: true });
|
|
4377
|
+
}, []);
|
|
4249
4378
|
const settle = useCallback(() => {
|
|
4250
4379
|
const form = formRef.current;
|
|
4251
4380
|
if (!form) return;
|
|
4252
4381
|
const invalid = collectInvalidFields(form);
|
|
4253
|
-
const next = invalid.length >= 2 ? invalid : [];
|
|
4382
|
+
const next = submittedRef.current && invalid.length >= 2 ? invalid : [];
|
|
4254
4383
|
setSummary((prev) => prev.length === next.length && prev.every((f, i) => f.id === next[i].id && f.message === next[i].message && f.label === next[i].label) ? prev : next);
|
|
4255
4384
|
if (pendingFocus.current && invalid.length > 0) {
|
|
4256
4385
|
pendingFocus.current = false;
|
|
4386
|
+
if (errorSummaryRef.current && next.length >= 2) {
|
|
4387
|
+
if (summaryRef.current) focusSummary();
|
|
4388
|
+
else pendingSummaryFocus.current = true;
|
|
4389
|
+
return;
|
|
4390
|
+
}
|
|
4257
4391
|
const first = form.querySelector("[aria-invalid='true']");
|
|
4258
4392
|
if (first) {
|
|
4259
4393
|
if (typeof first.scrollIntoView === "function") first.scrollIntoView({ block: "center", behavior: "smooth" });
|
|
4260
|
-
first.focus({ preventScroll: true });
|
|
4394
|
+
focusTarget(first).focus({ preventScroll: true });
|
|
4261
4395
|
}
|
|
4262
4396
|
}
|
|
4263
|
-
}, []);
|
|
4397
|
+
}, [submittedRef, errorSummaryRef, focusSummary]);
|
|
4398
|
+
useLayoutEffect(() => {
|
|
4399
|
+
if (!pendingSummaryFocus.current || summary.length < 2) return;
|
|
4400
|
+
pendingSummaryFocus.current = false;
|
|
4401
|
+
focusSummary();
|
|
4402
|
+
}, [summary, focusSummary]);
|
|
4264
4403
|
useLayoutEffect(() => {
|
|
4265
4404
|
if (!submitted) return;
|
|
4266
4405
|
settle();
|
|
@@ -4279,7 +4418,21 @@ function FormWrapper({ onSubmit, validationMode: validationModeProp, children, a
|
|
|
4279
4418
|
pendingFocus.current = false;
|
|
4280
4419
|
}, []);
|
|
4281
4420
|
const setError = useCallback((field, message) => {
|
|
4282
|
-
setErrors((prev) =>
|
|
4421
|
+
setErrors((prev) => prev[field] === message ? prev : { ...prev, [field]: message });
|
|
4422
|
+
}, []);
|
|
4423
|
+
const checks = useRef(/* @__PURE__ */ new Map());
|
|
4424
|
+
const register = useCallback((field, check) => {
|
|
4425
|
+
checks.current.set(field, check);
|
|
4426
|
+
return () => {
|
|
4427
|
+
if (checks.current.get(field) !== check) return;
|
|
4428
|
+
checks.current.delete(field);
|
|
4429
|
+
setErrors((prev) => {
|
|
4430
|
+
if (!(field in prev)) return prev;
|
|
4431
|
+
const next = { ...prev };
|
|
4432
|
+
delete next[field];
|
|
4433
|
+
return next;
|
|
4434
|
+
});
|
|
4435
|
+
};
|
|
4283
4436
|
}, []);
|
|
4284
4437
|
const clearErrors = useCallback(() => {
|
|
4285
4438
|
setErrors({});
|
|
@@ -4289,6 +4442,11 @@ function FormWrapper({ onSubmit, validationMode: validationModeProp, children, a
|
|
|
4289
4442
|
const handleSubmit = useCallback(
|
|
4290
4443
|
(e) => {
|
|
4291
4444
|
e.preventDefault();
|
|
4445
|
+
if (checks.current.size > 0) {
|
|
4446
|
+
const found = {};
|
|
4447
|
+
for (const [field, check] of checks.current) found[field] = check();
|
|
4448
|
+
setErrors((prev) => ({ ...prev, ...found }));
|
|
4449
|
+
}
|
|
4292
4450
|
pendingSubmit.current = true;
|
|
4293
4451
|
pendingFocus.current = focusFirstError;
|
|
4294
4452
|
setSubmitted(true);
|
|
@@ -4301,7 +4459,7 @@ function FormWrapper({ onSubmit, validationMode: validationModeProp, children, a
|
|
|
4301
4459
|
const el = id ? document.getElementById(id) : null;
|
|
4302
4460
|
if (el) {
|
|
4303
4461
|
el.scrollIntoView?.({ block: "center" });
|
|
4304
|
-
el.focus();
|
|
4462
|
+
focusTarget(el).focus();
|
|
4305
4463
|
}
|
|
4306
4464
|
};
|
|
4307
4465
|
const summaryNode = errorSummary && summary.length >= 2 ? typeof errorSummary === "function" ? errorSummary(summary) : /* @__PURE__ */ jsx(Alert, { variant: "error", title: `${summary.length} fields need attention`, className: "mb-ds-4", children: /* @__PURE__ */ jsx("ul", { className: "list-disc pl-ds-5 flex flex-col gap-ds-1", children: summary.map((f) => /* @__PURE__ */ jsxs("li", { children: [
|
|
@@ -4310,8 +4468,8 @@ function FormWrapper({ onSubmit, validationMode: validationModeProp, children, a
|
|
|
4310
4468
|
f.message
|
|
4311
4469
|
] }, f.id || f.label)) }) }) : null;
|
|
4312
4470
|
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;
|
|
4313
|
-
return /* @__PURE__ */ jsx(FormCtx.Provider, { value: { errors, setError, clearErrors, validationMode, submitted }, 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,none)]", className), noValidate: true, children: [
|
|
4314
|
-
summaryNode && /* @__PURE__ */ jsx("div", { "data-form-error-summary": "", children: summaryNode }),
|
|
4471
|
+
return /* @__PURE__ */ jsx(FormCtx.Provider, { value: { errors, setError, clearErrors, validationMode, submitted, register }, 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,none)]", className), noValidate: true, children: [
|
|
4472
|
+
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 }),
|
|
4315
4473
|
children,
|
|
4316
4474
|
actionsNode
|
|
4317
4475
|
] }) });
|
|
@@ -4909,11 +5067,36 @@ function MentionInput({
|
|
|
4909
5067
|
}
|
|
4910
5068
|
var HEADER_LAYOUT = {
|
|
4911
5069
|
row: "flex flex-wrap items-start justify-between gap-ds-4",
|
|
4912
|
-
block: "flex flex-col space-y-ds-1.5 grow basis-1/2 [
|
|
4913
|
-
titleLeads: "grow basis-1/2 max-w-max [
|
|
5070
|
+
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",
|
|
5071
|
+
titleLeads: "grow basis-1/2 max-w-max break-words has-[[data-title-one-line]]:min-w-0",
|
|
5072
|
+
floorOff: "min-w-0",
|
|
4914
5073
|
actions: "flex items-center gap-ds-2 shrink-0 ml-auto",
|
|
4915
5074
|
below: "mt-ds-1.5"
|
|
4916
5075
|
};
|
|
5076
|
+
function useTitleFloorFits(rowRef, active) {
|
|
5077
|
+
const [fits, setFits] = useState(true);
|
|
5078
|
+
useLayoutEffect(() => {
|
|
5079
|
+
const row = rowRef.current;
|
|
5080
|
+
if (!active || !row) return;
|
|
5081
|
+
const measure = () => {
|
|
5082
|
+
const title = row.querySelector("h1, h2, h3, h4, h5, h6");
|
|
5083
|
+
if (!title) return;
|
|
5084
|
+
const width = title.style.width;
|
|
5085
|
+
title.style.width = "min-content";
|
|
5086
|
+
const longest = title.getBoundingClientRect().width;
|
|
5087
|
+
title.style.width = width;
|
|
5088
|
+
if (longest === 0) return;
|
|
5089
|
+
const next = longest <= row.clientWidth + 0.5;
|
|
5090
|
+
setFits((was) => was === next ? was : next);
|
|
5091
|
+
};
|
|
5092
|
+
measure();
|
|
5093
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
5094
|
+
const observer = new ResizeObserver(measure);
|
|
5095
|
+
observer.observe(row);
|
|
5096
|
+
return () => observer.disconnect();
|
|
5097
|
+
}, [rowRef, active]);
|
|
5098
|
+
return fits;
|
|
5099
|
+
}
|
|
4917
5100
|
function actionsAreBadges(actions) {
|
|
4918
5101
|
const items = Children.toArray(actions);
|
|
4919
5102
|
return items.length > 0 && items.every((item) => isValidElement(item) && (item.type === Fragment$1 ? actionsAreBadges(item.props.children) : item.type === Badge));
|
|
@@ -5038,7 +5221,6 @@ var Card = forwardRef(function Card2({
|
|
|
5038
5221
|
...props
|
|
5039
5222
|
}, ref) {
|
|
5040
5223
|
const isSelectable = selectable || !!selectType;
|
|
5041
|
-
const isToggle = selectType === "toggle";
|
|
5042
5224
|
const hasSelectType = !!selectType;
|
|
5043
5225
|
const isAction = !isSelectable && variant === "interactive" && !!onClick;
|
|
5044
5226
|
const rootRef = useRef(null);
|
|
@@ -5092,7 +5274,6 @@ var Card = forwardRef(function Card2({
|
|
|
5092
5274
|
const isButton = isSelectable || isAction && !holdsControls;
|
|
5093
5275
|
const role = selectType === "radio" ? "radio" : selectType === "checkbox" ? "checkbox" : selectType === "toggle" ? "switch" : isButton ? "button" : void 0;
|
|
5094
5276
|
const ariaAttr = selectType === "radio" || selectType === "checkbox" || selectType === "toggle" ? { "aria-checked": !!selected } : isSelectable ? { "aria-pressed": !!selected } : {};
|
|
5095
|
-
const showRing = isSelectable && !isToggle && !hasSelectType && selected;
|
|
5096
5277
|
const indicator = selectType === "radio" ? /* @__PURE__ */ jsx(RadioIndicator, { checked: !!selected, disabled }) : selectType === "checkbox" ? /* @__PURE__ */ jsx(CheckboxIndicator, { checked: !!selected, indeterminate, disabled }) : selectType === "toggle" ? /* @__PURE__ */ jsx(ToggleIndicator, { checked: !!selected, disabled }) : null;
|
|
5097
5278
|
const defaultCheckBadge = !hasSelectType && !checkable && selected && !loading ? /* @__PURE__ */ jsx("div", { className: "absolute top-ds-3 right-ds-3 w-5 h-5 rounded-[var(--ds-radius-full)] bg-[var(--ds-accent-primary)] flex items-center justify-center", children: /* @__PURE__ */ jsx(Icon, { name: "check", size: 12, className: "text-[var(--ds-text-on-primary)]" }) }) : null;
|
|
5098
5279
|
return /* @__PURE__ */ jsxs(
|
|
@@ -5111,7 +5292,10 @@ var Card = forwardRef(function Card2({
|
|
|
5111
5292
|
isSelectable && !disabled && "cursor-pointer select-none transition-all duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
|
|
5112
5293
|
isSelectable && !disabled && !selected && "hover:border-[var(--ds-accent-primary)]",
|
|
5113
5294
|
isButton && "focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
5114
|
-
|
|
5295
|
+
// Selected is the accent border, with the accent-subtle fill on a card with a selectType. No ring: a ring round the
|
|
5296
|
+
// whole card is the focus state (focus-visible:shadow-[var(--ds-shadow-focus)] above), and the active halo other
|
|
5297
|
+
// controls take (ACTIVE_RING, since Sprint 20.6) made a selected card look focused (the owner, 27 September 2026).
|
|
5298
|
+
isSelectable && selected && "border-[var(--ds-border-focus)]",
|
|
5115
5299
|
hasSelectType && selected && "bg-[var(--ds-accent-subtle)]",
|
|
5116
5300
|
disabled && "opacity-disabled cursor-not-allowed",
|
|
5117
5301
|
className
|
|
@@ -5184,14 +5368,16 @@ var CardHeader = forwardRef(function CardHeader2({ className, children, actions,
|
|
|
5184
5368
|
)
|
|
5185
5369
|
] }) : null;
|
|
5186
5370
|
const iconBlock = icon ? /* @__PURE__ */ jsx("span", { className: "shrink-0 h-10 w-10 rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-muted)] flex items-center justify-center mb-ds-1", children: /* @__PURE__ */ jsx(Icon, { name: icon, size: 20, className: "text-[var(--ds-text-secondary)]" }) }) : null;
|
|
5371
|
+
const parts = Children.toArray(children);
|
|
5372
|
+
const titleLeads = !!hasActions && !iconBlock && !menuItems && actionsAreBadges(actions) && parts.length > 0 && isValidElement(parts[0]) && parts[0].type === CardTitle;
|
|
5373
|
+
const leadRowRef = useRef(null);
|
|
5374
|
+
const leadFloorFits = useTitleFloorFits(leadRowRef, titleLeads);
|
|
5187
5375
|
if (hasActions) {
|
|
5188
|
-
const parts = Children.toArray(children);
|
|
5189
|
-
const titleLeads = !iconBlock && !menuItems && actionsAreBadges(actions) && parts.length > 0 && isValidElement(parts[0]) && parts[0].type === CardTitle;
|
|
5190
5376
|
if (titleLeads) {
|
|
5191
5377
|
const below = parts.slice(1);
|
|
5192
5378
|
return /* @__PURE__ */ jsxs("div", { ref, className: cn(pl, "pr-ds-5 pt-ds-4 last:pb-ds-4", className), ...props, children: [
|
|
5193
|
-
/* @__PURE__ */ jsxs("div", { className: HEADER_LAYOUT.row, children: [
|
|
5194
|
-
/* @__PURE__ */ jsx("div", { "data-card-title-row": "", className: HEADER_LAYOUT.titleLeads, children: parts[0] }),
|
|
5379
|
+
/* @__PURE__ */ jsxs("div", { ref: leadRowRef, className: HEADER_LAYOUT.row, children: [
|
|
5380
|
+
/* @__PURE__ */ jsx("div", { "data-card-title-row": "", className: cn(HEADER_LAYOUT.titleLeads, !leadFloorFits && HEADER_LAYOUT.floorOff), children: parts[0] }),
|
|
5195
5381
|
actionsBlock
|
|
5196
5382
|
] }),
|
|
5197
5383
|
below.length > 0 && /* @__PURE__ */ jsx("div", { className: cn("flex flex-col space-y-ds-1.5 break-words", HEADER_LAYOUT.below), children: below })
|
|
@@ -5233,7 +5419,8 @@ var CardTitle = forwardRef(function CardTitle2({ className, children, lines = 2,
|
|
|
5233
5419
|
},
|
|
5234
5420
|
id: id ?? generatedId,
|
|
5235
5421
|
"data-card-title": "",
|
|
5236
|
-
|
|
5422
|
+
...lines === 1 ? { "data-title-one-line": "" } : {},
|
|
5423
|
+
className: cn(TITLE_TEXT, !action && lines > 0 && lineClampClass, action && lines === 1 && "text-ellipsis", className),
|
|
5237
5424
|
...props,
|
|
5238
5425
|
children: action ? (
|
|
5239
5426
|
// The card's action when the card holds controls of its own (Sprint 25.7): a real button, which a click
|
|
@@ -5401,6 +5588,58 @@ function DataList({ items, columns = 1, className }) {
|
|
|
5401
5588
|
}
|
|
5402
5589
|
);
|
|
5403
5590
|
}
|
|
5591
|
+
var COUNT_FROM_PAGE = [
|
|
5592
|
+
"[&:has(>:nth-child(2):last-child)]:[--gs-cards:2]",
|
|
5593
|
+
"[&:has(>:nth-child(3):last-child)]:[--gs-cards:3]",
|
|
5594
|
+
"[&:has(>:nth-child(4):last-child)]:[--gs-cards:4]",
|
|
5595
|
+
"[&:has(>:nth-child(5):last-child)]:[--gs-cards:5]",
|
|
5596
|
+
"[&:has(>:nth-child(6):last-child)]:[--gs-cards:6]",
|
|
5597
|
+
"[&:has(>:nth-child(7):last-child)]:[--gs-cards:7]",
|
|
5598
|
+
"[&:has(>:nth-child(8):last-child)]:[--gs-cards:8]",
|
|
5599
|
+
"[&:has(>:nth-child(9):last-child)]:[--gs-cards:9]",
|
|
5600
|
+
"[&:has(>:nth-child(10):last-child)]:[--gs-cards:10]",
|
|
5601
|
+
"[&:has(>:nth-child(11):last-child)]:[--gs-cards:11]",
|
|
5602
|
+
"[&:has(>:nth-child(12))]:[--gs-cards:12]"
|
|
5603
|
+
].join(" ");
|
|
5604
|
+
function countCards(children) {
|
|
5605
|
+
let n = 0;
|
|
5606
|
+
Children.forEach(children, (child) => {
|
|
5607
|
+
if (isValidElement(child) && child.type === Fragment$1) n += countCards(child.props.children);
|
|
5608
|
+
else if (child !== null && child !== void 0 && typeof child !== "boolean" && child !== "") n += 1;
|
|
5609
|
+
});
|
|
5610
|
+
return n;
|
|
5611
|
+
}
|
|
5612
|
+
function CardGrid({ minWidth = "14rem", maxColumns = 4, compare = false, gap = "var(--ds-space-4)", className, style, children, ref, ...props }) {
|
|
5613
|
+
const most = Math.max(1, Math.floor(maxColumns));
|
|
5614
|
+
const n = compare ? "var(--gs-cards, var(--gs-cards-counted))" : String(most);
|
|
5615
|
+
const share = `calc((100% - (${n} - 1) * var(--gs-card-gap)) / ${n})`;
|
|
5616
|
+
const column = compare ? `max(${share}, min(100%, calc((${n} * ${minWidth} + (${n} - 1) * var(--gs-card-gap) - 100%) * 999)))` : `max(min(${minWidth}, 100%), ${share})`;
|
|
5617
|
+
const template = {
|
|
5618
|
+
"--gs-card-gap": gap,
|
|
5619
|
+
...compare ? { "--gs-cards-counted": Math.max(1, countCards(children)) } : {},
|
|
5620
|
+
gap: "var(--gs-card-gap)",
|
|
5621
|
+
gridTemplateColumns: `repeat(auto-fill, minmax(${column}, 1fr))`,
|
|
5622
|
+
// a comparison's cards share their rows: the headers, the contents and the footers line up across the row
|
|
5623
|
+
...compare ? { gridAutoRows: "auto 1fr auto" } : {}
|
|
5624
|
+
};
|
|
5625
|
+
return /* @__PURE__ */ jsx(
|
|
5626
|
+
"div",
|
|
5627
|
+
{
|
|
5628
|
+
ref,
|
|
5629
|
+
"data-card-grid": compare ? "compare" : "",
|
|
5630
|
+
className: cn(
|
|
5631
|
+
"grid",
|
|
5632
|
+
compare && COUNT_FROM_PAGE,
|
|
5633
|
+
// each card spans its three rows and lays its parts in them; anything else just fills them
|
|
5634
|
+
compare && "[&>*]:row-span-3 [&>[data-card]]:grid [&>[data-card]]:grid-rows-subgrid [&>[data-card]]:gap-y-0",
|
|
5635
|
+
className
|
|
5636
|
+
),
|
|
5637
|
+
style: { ...template, ...style },
|
|
5638
|
+
...props,
|
|
5639
|
+
children
|
|
5640
|
+
}
|
|
5641
|
+
);
|
|
5642
|
+
}
|
|
5404
5643
|
var sizeStyles3 = {
|
|
5405
5644
|
sm: { gap: "gap-ds-0.5", label: "text-[length:var(--ds-font-size-xs)]", value: "text-[length:var(--ds-font-size-xs)]", iconSize: 12, py: "py-ds-1.5" },
|
|
5406
5645
|
md: { gap: "gap-ds-1", label: "text-[length:var(--ds-font-size-sm)]", value: "text-[length:var(--ds-font-size-sm)]", iconSize: 14, py: "py-ds-2.5" },
|
|
@@ -5530,7 +5769,7 @@ var DescriptionList = forwardRef(function DescriptionList2({
|
|
|
5530
5769
|
]
|
|
5531
5770
|
}
|
|
5532
5771
|
),
|
|
5533
|
-
/* @__PURE__ */ jsx("dd", { className: cn("font-normal text-[var(--ds-text-primary)] text-right flex-1 min-w-0", s.value), children: item.value })
|
|
5772
|
+
/* @__PURE__ */ jsx("dd", { className: cn("font-normal text-[var(--ds-text-primary)] text-right flex-1 min-w-0 [overflow-wrap:anywhere] [:where(&)>*]:[justify-content:safe_flex-end] [:where(&)>*]:flex-wrap", s.value), children: item.value })
|
|
5534
5773
|
]
|
|
5535
5774
|
},
|
|
5536
5775
|
i
|
|
@@ -5692,7 +5931,7 @@ function TruncCell({ children, lines }) {
|
|
|
5692
5931
|
if (!isTruncated) return cell;
|
|
5693
5932
|
return /* @__PURE__ */ jsx(Tooltip, { content: children, children: cell });
|
|
5694
5933
|
}
|
|
5695
|
-
var TITLE_CLASSES =
|
|
5934
|
+
var TITLE_CLASSES = TITLE_TEXT;
|
|
5696
5935
|
var FRAME_CLASSES = cn(
|
|
5697
5936
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
5698
5937
|
"rounded-[var(--ds-radius-md)]",
|
|
@@ -5702,16 +5941,19 @@ var FRAME_CLASSES = cn(
|
|
|
5702
5941
|
function TableHeading({ title, description, actions, titleId, descriptionId, inset }) {
|
|
5703
5942
|
const heading = /* @__PURE__ */ jsx("h3", { id: titleId, className: TITLE_CLASSES, children: title });
|
|
5704
5943
|
const actionsBlock = actions ? /* @__PURE__ */ jsx("div", { className: HEADER_LAYOUT.actions, children: actions }) : null;
|
|
5944
|
+
const titleLeads = !actions || actionsAreBadges(actions);
|
|
5945
|
+
const leadRowRef = useRef(null);
|
|
5946
|
+
const leadFloorFits = useTitleFloorFits(leadRowRef, titleLeads);
|
|
5705
5947
|
const descriptionText = (className) => description ? /* @__PURE__ */ jsx("p", { id: descriptionId, className: cn(className, "text-sm text-[var(--ds-text-muted)] break-words"), children: description }) : null;
|
|
5706
|
-
return /* @__PURE__ */ jsx("div", { "data-table-heading": "", className: cn(inset ? "px-ds-5 py-ds-4" : "pb-ds-4"), children:
|
|
5948
|
+
return /* @__PURE__ */ jsx("div", { "data-table-heading": "", className: cn(inset ? "px-ds-5 py-ds-4" : "pb-ds-4"), children: !titleLeads ? /* @__PURE__ */ jsxs("div", { className: HEADER_LAYOUT.row, children: [
|
|
5707
5949
|
/* @__PURE__ */ jsxs("div", { className: HEADER_LAYOUT.block, children: [
|
|
5708
5950
|
heading,
|
|
5709
5951
|
descriptionText()
|
|
5710
5952
|
] }),
|
|
5711
5953
|
actionsBlock
|
|
5712
5954
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5713
|
-
/* @__PURE__ */ jsxs("div", { className: HEADER_LAYOUT.row, children: [
|
|
5714
|
-
/* @__PURE__ */ jsx("div", { className: HEADER_LAYOUT.titleLeads, children: heading }),
|
|
5955
|
+
/* @__PURE__ */ jsxs("div", { ref: leadRowRef, className: HEADER_LAYOUT.row, children: [
|
|
5956
|
+
/* @__PURE__ */ jsx("div", { className: cn(HEADER_LAYOUT.titleLeads, !leadFloorFits && HEADER_LAYOUT.floorOff), children: heading }),
|
|
5715
5957
|
actionsBlock
|
|
5716
5958
|
] }),
|
|
5717
5959
|
descriptionText(HEADER_LAYOUT.below)
|
|
@@ -6078,9 +6320,12 @@ function SegmentedControl({
|
|
|
6078
6320
|
onHoverChange,
|
|
6079
6321
|
className,
|
|
6080
6322
|
"aria-label": ariaLabel,
|
|
6081
|
-
maxOptions = 6
|
|
6323
|
+
maxOptions = 6,
|
|
6324
|
+
...wiring
|
|
6082
6325
|
}) {
|
|
6083
6326
|
const contextSize = useContext(ControlSizeContext);
|
|
6327
|
+
const control = useFieldControl(wiring);
|
|
6328
|
+
const named = !ariaLabel && control.labelId ? { "aria-labelledby": control.labelId } : {};
|
|
6084
6329
|
const size = sizeProp ?? contextSize ?? "md";
|
|
6085
6330
|
const containerRef = useRef(null);
|
|
6086
6331
|
const [indicator, setIndicator] = useState({ left: 0, width: 0 });
|
|
@@ -6176,6 +6421,7 @@ function SegmentedControl({
|
|
|
6176
6421
|
Dropdown,
|
|
6177
6422
|
{
|
|
6178
6423
|
"aria-label": ariaLabel,
|
|
6424
|
+
...wiring,
|
|
6179
6425
|
size: size === "md" || size === "lg" ? "md" : "sm",
|
|
6180
6426
|
options: options.filter((o) => !o.disabled).map((o) => ({ id: o.value, label: o.label })),
|
|
6181
6427
|
value,
|
|
@@ -6189,7 +6435,12 @@ function SegmentedControl({
|
|
|
6189
6435
|
{
|
|
6190
6436
|
ref: containerRef,
|
|
6191
6437
|
role: "radiogroup",
|
|
6438
|
+
id: control.id,
|
|
6192
6439
|
"aria-label": ariaLabel,
|
|
6440
|
+
...named,
|
|
6441
|
+
"aria-describedby": control.describedBy,
|
|
6442
|
+
"aria-invalid": control.invalid || void 0,
|
|
6443
|
+
"aria-required": control.required || void 0,
|
|
6193
6444
|
onKeyDown: handleKeyDown,
|
|
6194
6445
|
className: cn(
|
|
6195
6446
|
"relative items-center",
|
|
@@ -6199,6 +6450,7 @@ function SegmentedControl({
|
|
|
6199
6450
|
"bg-[var(--ds-bg-muted)]",
|
|
6200
6451
|
"rounded-[var(--ds-radius-lg)]",
|
|
6201
6452
|
variant === "default" && "border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
6453
|
+
control.invalid && "border-[length:var(--ds-border-width)] border-[var(--ds-status-error)]",
|
|
6202
6454
|
className
|
|
6203
6455
|
),
|
|
6204
6456
|
children: [
|
|
@@ -6709,7 +6961,7 @@ function WeekView({
|
|
|
6709
6961
|
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "flex flex-col h-full overflow-hidden", children: [
|
|
6710
6962
|
/* @__PURE__ */ jsxs("div", { className: "flex border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", children: [
|
|
6711
6963
|
/* @__PURE__ */ jsx("div", { className: "w-14 shrink-0 border-r-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]" }),
|
|
6712
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-x-auto scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6964
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6713
6965
|
"div",
|
|
6714
6966
|
{
|
|
6715
6967
|
className: "grid",
|
|
@@ -6749,7 +7001,7 @@ function WeekView({
|
|
|
6749
7001
|
] }),
|
|
6750
7002
|
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: [
|
|
6751
7003
|
/* @__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" }),
|
|
6752
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-x-auto scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
7004
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6753
7005
|
"div",
|
|
6754
7006
|
{
|
|
6755
7007
|
className: "grid",
|
|
@@ -6786,7 +7038,7 @@ function WeekView({
|
|
|
6786
7038
|
},
|
|
6787
7039
|
h
|
|
6788
7040
|
)) }),
|
|
6789
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-x-auto scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
7041
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-x-auto gs-scrollbar-none", "data-week-scroll": true, children: /* @__PURE__ */ jsx(
|
|
6790
7042
|
"div",
|
|
6791
7043
|
{
|
|
6792
7044
|
className: "relative",
|
|
@@ -7799,7 +8051,7 @@ function AvatarGroup({ items, max = 4, size = "sm", ring = "canvas", onOverflowC
|
|
|
7799
8051
|
const shown = items.slice(0, Math.max(0, max));
|
|
7800
8052
|
const hidden = items.slice(shown.length);
|
|
7801
8053
|
const ringClass = cn(
|
|
7802
|
-
"rounded-[var(--ds-radius-full)] ring-2",
|
|
8054
|
+
"relative rounded-[var(--ds-radius-full)] ring-2",
|
|
7803
8055
|
ring === "canvas" ? "ring-[var(--ds-bg-canvas)]" : "ring-[var(--ds-bg-surface)]"
|
|
7804
8056
|
);
|
|
7805
8057
|
const hiddenNames = hidden.map((i) => i.name ?? i.initials).filter(Boolean).join(", ");
|
|
@@ -8099,11 +8351,38 @@ function HorizontalLayout({ items, minItemWidth, className }) {
|
|
|
8099
8351
|
/* @__PURE__ */ jsxs("div", { className: "text-center mt-ds-2 px-ds-3", children: [
|
|
8100
8352
|
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: item.title }),
|
|
8101
8353
|
item.description && /* @__PURE__ */ jsx(ExpandableDescription, { className: "text-center", children: item.description }),
|
|
8102
|
-
|
|
8354
|
+
/* @__PURE__ */ jsx(ItemTime, { item })
|
|
8103
8355
|
] })
|
|
8104
8356
|
] }, i);
|
|
8105
8357
|
}) });
|
|
8106
8358
|
}
|
|
8359
|
+
var EXACT = new Intl.DateTimeFormat(void 0, { dateStyle: "medium", timeStyle: "short" });
|
|
8360
|
+
var EXACT_DAY = new Intl.DateTimeFormat(void 0, { dateStyle: "medium" });
|
|
8361
|
+
var DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
8362
|
+
function exactTime(value) {
|
|
8363
|
+
if (typeof value === "string") {
|
|
8364
|
+
const day = DATE_ONLY.exec(value.trim());
|
|
8365
|
+
if (day) {
|
|
8366
|
+
const [y, m, d] = [Number(day[1]), Number(day[2]) - 1, Number(day[3])];
|
|
8367
|
+
const date2 = new Date(y, m, d);
|
|
8368
|
+
return date2.getFullYear() === y && date2.getMonth() === m && date2.getDate() === d ? { iso: value.trim(), text: EXACT_DAY.format(date2) } : null;
|
|
8369
|
+
}
|
|
8370
|
+
}
|
|
8371
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
8372
|
+
return Number.isNaN(date.getTime()) ? null : { iso: date.toISOString(), text: EXACT.format(date) };
|
|
8373
|
+
}
|
|
8374
|
+
function ItemTime({ item }) {
|
|
8375
|
+
const exact = item.dateTime ? exactTime(item.dateTime) : null;
|
|
8376
|
+
if (!item.timestamp && !exact) return null;
|
|
8377
|
+
return /* @__PURE__ */ jsx("p", { className: "text-2xs text-[var(--ds-text-muted)] mt-ds-0.5 tabular-nums", children: exact ? /* @__PURE__ */ jsxs("time", { dateTime: exact.iso, title: exact.text, children: [
|
|
8378
|
+
item.timestamp ?? exact.text,
|
|
8379
|
+
item.timestamp && /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
|
|
8380
|
+
" (",
|
|
8381
|
+
exact.text,
|
|
8382
|
+
")"
|
|
8383
|
+
] })
|
|
8384
|
+
] }) : item.timestamp });
|
|
8385
|
+
}
|
|
8107
8386
|
function VerticalLayout({ items, className }) {
|
|
8108
8387
|
return /* @__PURE__ */ jsx("div", { className: cn("relative", className), children: items.map((item, i) => /* @__PURE__ */ jsxs("div", { className: "flex gap-ds-4", children: [
|
|
8109
8388
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
|
|
@@ -8113,7 +8392,7 @@ function VerticalLayout({ items, className }) {
|
|
|
8113
8392
|
/* @__PURE__ */ jsxs("div", { className: cn("pb-ds-6 min-w-0", i === items.length - 1 && "pb-0"), style: item.icon ? { paddingTop: ICON_TEXT_OFFSET } : void 0, children: [
|
|
8114
8393
|
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: item.title }),
|
|
8115
8394
|
item.description && /* @__PURE__ */ jsx(ExpandableDescription, { children: item.description }),
|
|
8116
|
-
|
|
8395
|
+
/* @__PURE__ */ jsx(ItemTime, { item })
|
|
8117
8396
|
] })
|
|
8118
8397
|
] }, i)) });
|
|
8119
8398
|
}
|
|
@@ -9496,7 +9775,7 @@ var StackedList = forwardRef(function StackedList2({
|
|
|
9496
9775
|
});
|
|
9497
9776
|
var TIME_ZOOMS = ["day", "week", "month", "quarter"];
|
|
9498
9777
|
var DAY_MS = 864e5;
|
|
9499
|
-
var
|
|
9778
|
+
var DATE_ONLY2 = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
9500
9779
|
var utcDay = (y, m, d) => Math.round(Date.UTC(y, m, d) / DAY_MS);
|
|
9501
9780
|
function dayOfDate(d) {
|
|
9502
9781
|
const t = d.getTime();
|
|
@@ -9512,7 +9791,7 @@ function dayOf(value) {
|
|
|
9512
9791
|
if (typeof value === "number") return Number.isFinite(value) ? value : NaN;
|
|
9513
9792
|
if (value instanceof Date) return dayOfDate(value);
|
|
9514
9793
|
if (typeof value !== "string") return NaN;
|
|
9515
|
-
const m =
|
|
9794
|
+
const m = DATE_ONLY2.exec(value.trim());
|
|
9516
9795
|
if (!m) return dayOfDate(new Date(value));
|
|
9517
9796
|
const [y, mo, d] = [Number(m[1]), Number(m[2]) - 1, Number(m[3])];
|
|
9518
9797
|
const day = utcDay(y, mo, d);
|
|
@@ -9525,7 +9804,7 @@ function dateOfDay(day) {
|
|
|
9525
9804
|
return new Date(u.getUTCFullYear(), u.getUTCMonth(), u.getUTCDate(), 0, 0, 0, Math.round((day - whole) * DAY_MS));
|
|
9526
9805
|
}
|
|
9527
9806
|
function isWholeDay(value) {
|
|
9528
|
-
return typeof value === "string" ?
|
|
9807
|
+
return typeof value === "string" ? DATE_ONLY2.test(value.trim()) : Number.isInteger(dayOf(value));
|
|
9529
9808
|
}
|
|
9530
9809
|
function endDayOf(value) {
|
|
9531
9810
|
const day = dayOf(value);
|
|
@@ -15013,7 +15292,8 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
15013
15292
|
className: cn(
|
|
15014
15293
|
"relative z-10 w-full",
|
|
15015
15294
|
isMobile ? "max-w-none h-full" : sizeClasses[size],
|
|
15016
|
-
|
|
15295
|
+
OVERLAY_SURFACE,
|
|
15296
|
+
"text-[var(--ds-text-primary)]",
|
|
15017
15297
|
GLASS_OVERLAY,
|
|
15018
15298
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
15019
15299
|
isMobile ? "rounded-none" : "rounded-[var(--ds-radius-xl)]",
|
|
@@ -15532,7 +15812,8 @@ function CommandPalette({ open, onOpenChange, commands, placeholder = "Type a co
|
|
|
15532
15812
|
"aria-label": "Command palette",
|
|
15533
15813
|
className: cn(
|
|
15534
15814
|
"relative z-10 w-full max-w-lg",
|
|
15535
|
-
|
|
15815
|
+
OVERLAY_SURFACE,
|
|
15816
|
+
"text-[var(--ds-text-primary)]",
|
|
15536
15817
|
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
15537
15818
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
15538
15819
|
"rounded-[var(--ds-radius-xl)] overflow-hidden",
|
|
@@ -16806,6 +17087,6 @@ var TextOverflow = forwardRef(function TextOverflow2({
|
|
|
16806
17087
|
return /* @__PURE__ */ jsx(Tooltip, { content: resolvedTooltipContent, children: content });
|
|
16807
17088
|
});
|
|
16808
17089
|
|
|
16809
|
-
export { Accordion, ActionPanel, ActionPanelGroup, Alert, AsidePanel, Avatar, AvatarGroup, BottomNav, Breadcrumbs, BulkActionBar, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, ChatMessageList, ChatPanel, Checkbox, CheckboxGroup, CheckboxGroupItem, Collapsible, ColorPicker, Combobox, CommandPalette, ContextMenu, CornerPanel, DEFAULT_DATE_RANGE_PRESETS, DataList, DatePicker, DateRangePicker, DescriptionList, Dialog, Dock, Dropdown, DropdownMenu, EmptyState, EntityCell, Field, FileUpload, FormWrapper, Gantt, HoverCard, InlineFieldError, Input, Kbd, Label, Launcher, MentionInput, MobileHeaderMenu, NavItem, NavMenu, Navbar, NotificationCenter, NumberInput, PageContainer, PageHeader, Pagination, PinInput, Popover, Progress, RadioGroup, Rating, ScrollArea, SectionHeading, SegmentedControl, SettingsLayout, Sidebar, SidebarNav, SliderRange, StackedList, StatsCard, StatusDot, Stepper, TIME_ZOOMS, Table, TableToolbar, Tabs, Tag, TagInput, TextOverflow, Textarea, TimeBar, TimePicker, TimeRow, TimeScaleHeader, TimeViewport, Timeline, Toast, ToastProvider, Toggle, Tour, TransferList, TreeView, dateOfDay, dayOf, endDayOf, fitLabel, fitLabels, formatDateRange, timeExtent, useContentWidth, useDestructiveAction, useFittedLabels, useFormContext, usePagination, useSidebar, useTextMeasure, useTimeScale, useTimeViewport, useTimeViewportLayout, useToast, useToastOptional };
|
|
17090
|
+
export { Accordion, ActionPanel, ActionPanelGroup, Alert, AsidePanel, Avatar, AvatarGroup, BottomNav, Breadcrumbs, 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, Dropdown, DropdownMenu, EmptyState, EntityCell, Field, FileUpload, FormWrapper, Gantt, HoverCard, InlineFieldError, Input, Kbd, Label, Launcher, MentionInput, MobileHeaderMenu, NavItem, NavMenu, Navbar, NotificationCenter, NumberInput, PageContainer, PageHeader, Pagination, PinInput, Popover, Progress, RadioGroup, Rating, ScrollArea, SectionHeading, SegmentedControl, SettingsLayout, Sidebar, SidebarNav, SliderRange, StackedList, StatsCard, StatusDot, Stepper, TIME_ZOOMS, Table, TableToolbar, Tabs, Tag, TagInput, TextOverflow, Textarea, TimeBar, TimePicker, TimeRow, TimeScaleHeader, TimeViewport, Timeline, Toast, ToastProvider, Toggle, Tour, TransferList, TreeView, dateOfDay, dayOf, endDayOf, fitLabel, fitLabels, formatDateRange, timeExtent, useContentWidth, useDestructiveAction, useFittedLabels, useFormContext, usePagination, useSidebar, useTextMeasure, useTimeScale, useTimeViewport, useTimeViewportLayout, useToast, useToastOptional };
|
|
16810
17091
|
//# sourceMappingURL=index.js.map
|
|
16811
17092
|
//# sourceMappingURL=index.js.map
|