gridsmith-ui 0.17.3 → 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/README.md +19 -13
- 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 +155 -55
- package/dist/index.js +576 -207
- 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 +2 -2
- 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,25 +1,25 @@
|
|
|
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,
|
|
22
|
-
import { createContext, forwardRef, useState, useRef, useCallback, useLayoutEffect, useMemo, useContext, useId, memo, useEffect, useImperativeHandle,
|
|
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
|
+
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';
|
|
25
25
|
|
|
@@ -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
|
] }) });
|
|
@@ -4907,6 +5065,42 @@ function MentionInput({
|
|
|
4907
5065
|
)
|
|
4908
5066
|
] });
|
|
4909
5067
|
}
|
|
5068
|
+
var HEADER_LAYOUT = {
|
|
5069
|
+
row: "flex flex-wrap items-start justify-between gap-ds-4",
|
|
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",
|
|
5073
|
+
actions: "flex items-center gap-ds-2 shrink-0 ml-auto",
|
|
5074
|
+
below: "mt-ds-1.5"
|
|
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
|
+
}
|
|
5100
|
+
function actionsAreBadges(actions) {
|
|
5101
|
+
const items = Children.toArray(actions);
|
|
5102
|
+
return items.length > 0 && items.every((item) => isValidElement(item) && (item.type === Fragment$1 ? actionsAreBadges(item.props.children) : item.type === Badge));
|
|
5103
|
+
}
|
|
4910
5104
|
var CardCtx = createContext(false);
|
|
4911
5105
|
var CardActionCtx = createContext(null);
|
|
4912
5106
|
var CARD_ACTION_ATTR = "data-card-action";
|
|
@@ -5027,7 +5221,6 @@ var Card = forwardRef(function Card2({
|
|
|
5027
5221
|
...props
|
|
5028
5222
|
}, ref) {
|
|
5029
5223
|
const isSelectable = selectable || !!selectType;
|
|
5030
|
-
const isToggle = selectType === "toggle";
|
|
5031
5224
|
const hasSelectType = !!selectType;
|
|
5032
5225
|
const isAction = !isSelectable && variant === "interactive" && !!onClick;
|
|
5033
5226
|
const rootRef = useRef(null);
|
|
@@ -5081,7 +5274,6 @@ var Card = forwardRef(function Card2({
|
|
|
5081
5274
|
const isButton = isSelectable || isAction && !holdsControls;
|
|
5082
5275
|
const role = selectType === "radio" ? "radio" : selectType === "checkbox" ? "checkbox" : selectType === "toggle" ? "switch" : isButton ? "button" : void 0;
|
|
5083
5276
|
const ariaAttr = selectType === "radio" || selectType === "checkbox" || selectType === "toggle" ? { "aria-checked": !!selected } : isSelectable ? { "aria-pressed": !!selected } : {};
|
|
5084
|
-
const showRing = isSelectable && !isToggle && !hasSelectType && selected;
|
|
5085
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;
|
|
5086
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;
|
|
5087
5279
|
return /* @__PURE__ */ jsxs(
|
|
@@ -5100,7 +5292,10 @@ var Card = forwardRef(function Card2({
|
|
|
5100
5292
|
isSelectable && !disabled && "cursor-pointer select-none transition-all duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
|
|
5101
5293
|
isSelectable && !disabled && !selected && "hover:border-[var(--ds-accent-primary)]",
|
|
5102
5294
|
isButton && "focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
|
|
5103
|
-
|
|
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)]",
|
|
5104
5299
|
hasSelectType && selected && "bg-[var(--ds-accent-subtle)]",
|
|
5105
5300
|
disabled && "opacity-disabled cursor-not-allowed",
|
|
5106
5301
|
className
|
|
@@ -5149,7 +5344,7 @@ var CardHeader = forwardRef(function CardHeader2({ className, children, actions,
|
|
|
5149
5344
|
const isCheckable = useContext(CardCtx);
|
|
5150
5345
|
const hasActions = actions || menuItems;
|
|
5151
5346
|
const pl = isCheckable ? "pl-ds-10" : "pl-ds-5";
|
|
5152
|
-
const actionsBlock = hasActions ? /* @__PURE__ */ jsxs("div", { className:
|
|
5347
|
+
const actionsBlock = hasActions ? /* @__PURE__ */ jsxs("div", { className: HEADER_LAYOUT.actions, children: [
|
|
5153
5348
|
actions,
|
|
5154
5349
|
menuItems && /* @__PURE__ */ jsx(
|
|
5155
5350
|
DropdownMenu,
|
|
@@ -5173,9 +5368,23 @@ var CardHeader = forwardRef(function CardHeader2({ className, children, actions,
|
|
|
5173
5368
|
)
|
|
5174
5369
|
] }) : null;
|
|
5175
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);
|
|
5176
5375
|
if (hasActions) {
|
|
5177
|
-
|
|
5178
|
-
|
|
5376
|
+
if (titleLeads) {
|
|
5377
|
+
const below = parts.slice(1);
|
|
5378
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cn(pl, "pr-ds-5 pt-ds-4 last:pb-ds-4", className), ...props, children: [
|
|
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] }),
|
|
5381
|
+
actionsBlock
|
|
5382
|
+
] }),
|
|
5383
|
+
below.length > 0 && /* @__PURE__ */ jsx("div", { className: cn("flex flex-col space-y-ds-1.5 break-words", HEADER_LAYOUT.below), children: below })
|
|
5384
|
+
] });
|
|
5385
|
+
}
|
|
5386
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn(pl, "pr-ds-5 pt-ds-4 last:pb-ds-4", className), ...props, children: /* @__PURE__ */ jsxs("div", { className: HEADER_LAYOUT.row, children: [
|
|
5387
|
+
/* @__PURE__ */ jsxs("div", { className: HEADER_LAYOUT.block, children: [
|
|
5179
5388
|
iconBlock,
|
|
5180
5389
|
children
|
|
5181
5390
|
] }),
|
|
@@ -5210,7 +5419,8 @@ var CardTitle = forwardRef(function CardTitle2({ className, children, lines = 2,
|
|
|
5210
5419
|
},
|
|
5211
5420
|
id: id ?? generatedId,
|
|
5212
5421
|
"data-card-title": "",
|
|
5213
|
-
|
|
5422
|
+
...lines === 1 ? { "data-title-one-line": "" } : {},
|
|
5423
|
+
className: cn(TITLE_TEXT, !action && lines > 0 && lineClampClass, action && lines === 1 && "text-ellipsis", className),
|
|
5214
5424
|
...props,
|
|
5215
5425
|
children: action ? (
|
|
5216
5426
|
// The card's action when the card holds controls of its own (Sprint 25.7): a real button, which a click
|
|
@@ -5378,6 +5588,58 @@ function DataList({ items, columns = 1, className }) {
|
|
|
5378
5588
|
}
|
|
5379
5589
|
);
|
|
5380
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
|
+
}
|
|
5381
5643
|
var sizeStyles3 = {
|
|
5382
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" },
|
|
5383
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" },
|
|
@@ -5507,7 +5769,7 @@ var DescriptionList = forwardRef(function DescriptionList2({
|
|
|
5507
5769
|
]
|
|
5508
5770
|
}
|
|
5509
5771
|
),
|
|
5510
|
-
/* @__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 })
|
|
5511
5773
|
]
|
|
5512
5774
|
},
|
|
5513
5775
|
i
|
|
@@ -5599,6 +5861,69 @@ function Accordion({ items, type = "single", defaultOpen = [], open: controlledO
|
|
|
5599
5861
|
] }, i);
|
|
5600
5862
|
}) });
|
|
5601
5863
|
}
|
|
5864
|
+
var EDGE_FADE = 24;
|
|
5865
|
+
var NONE = { left: false, right: false, vertical: false, gutterRight: 0, gutterBottom: 0 };
|
|
5866
|
+
var same = (a, b) => a.left === b.left && a.right === b.right && a.vertical === b.vertical && a.gutterRight === b.gutterRight && a.gutterBottom === b.gutterBottom;
|
|
5867
|
+
function useScrollEdges(options = {}) {
|
|
5868
|
+
const { enabled = true, fade = EDGE_FADE } = options;
|
|
5869
|
+
const elRef = useRef(null);
|
|
5870
|
+
const observer = useRef(null);
|
|
5871
|
+
const borders = useRef({ x: 0, y: 0 });
|
|
5872
|
+
const [state, setState] = useState(NONE);
|
|
5873
|
+
const measure = useCallback(() => {
|
|
5874
|
+
const el = elRef.current;
|
|
5875
|
+
if (!el) return;
|
|
5876
|
+
const next = {
|
|
5877
|
+
left: el.scrollLeft > 1,
|
|
5878
|
+
right: el.scrollLeft + el.clientWidth < el.scrollWidth - 1,
|
|
5879
|
+
vertical: el.scrollHeight > el.clientHeight + 1,
|
|
5880
|
+
gutterRight: Math.max(0, el.offsetWidth - el.clientWidth - borders.current.x),
|
|
5881
|
+
gutterBottom: Math.max(0, el.offsetHeight - el.clientHeight - borders.current.y)
|
|
5882
|
+
};
|
|
5883
|
+
setState((prev) => same(prev, next) ? prev : next);
|
|
5884
|
+
}, []);
|
|
5885
|
+
const ref = useCallback((el) => {
|
|
5886
|
+
observer.current?.disconnect();
|
|
5887
|
+
observer.current = null;
|
|
5888
|
+
elRef.current = el;
|
|
5889
|
+
if (!el || !enabled) return;
|
|
5890
|
+
const style = getComputedStyle(el);
|
|
5891
|
+
const px = (v) => parseFloat(v) || 0;
|
|
5892
|
+
borders.current = { x: px(style.borderLeftWidth) + px(style.borderRightWidth), y: px(style.borderTopWidth) + px(style.borderBottomWidth) };
|
|
5893
|
+
measure();
|
|
5894
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
5895
|
+
const o = new ResizeObserver(measure);
|
|
5896
|
+
o.observe(el);
|
|
5897
|
+
for (const child of Array.from(el.children)) o.observe(child);
|
|
5898
|
+
observer.current = o;
|
|
5899
|
+
}, [enabled, measure]);
|
|
5900
|
+
const shown = enabled && (state.left || state.right);
|
|
5901
|
+
const { gutterRight: gr, gutterBottom: gb } = state;
|
|
5902
|
+
const fadeLayer = `linear-gradient(to right, ${state.left ? `transparent 0, black ${fade}px` : "black 0"}, ${state.right ? `black calc(100% - ${gr + fade}px), transparent calc(100% - ${gr}px)` : "black 100%"})`;
|
|
5903
|
+
const gutters = [gb > 0 && { size: `100% ${gb}px`, position: "0 100%" }, gr > 0 && { size: `${gr}px 100%`, position: "100% 0" }].filter(Boolean);
|
|
5904
|
+
const mask = shown ? {
|
|
5905
|
+
image: [fadeLayer, ...gutters.map(() => "linear-gradient(black, black)")].join(", "),
|
|
5906
|
+
size: ["100% 100%", ...gutters.map((g) => g.size)].join(", "),
|
|
5907
|
+
position: ["0 0", ...gutters.map((g) => g.position)].join(", ")
|
|
5908
|
+
} : void 0;
|
|
5909
|
+
return {
|
|
5910
|
+
/** The scroller's ref (a callback). */
|
|
5911
|
+
ref,
|
|
5912
|
+
/** The scroller itself, for code that moves it. */
|
|
5913
|
+
elRef,
|
|
5914
|
+
measure,
|
|
5915
|
+
/** Content hides past a side edge: the scroller moves sideways, and its edges fade. */
|
|
5916
|
+
overflowing: shown,
|
|
5917
|
+
/** It scrolls either way, sideways or up and down: a keyboard needs to reach it. */
|
|
5918
|
+
scrollable: enabled && (state.left || state.right || state.vertical),
|
|
5919
|
+
edges: { left: state.left, right: state.right },
|
|
5920
|
+
/** For the scroller: `data-fade` names the faded edges ("left", "right" or "left right"), the style masks them. */
|
|
5921
|
+
fadeProps: {
|
|
5922
|
+
"data-fade": shown ? [state.left && "left", state.right && "right"].filter(Boolean).join(" ") : void 0,
|
|
5923
|
+
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
|
|
5924
|
+
}
|
|
5925
|
+
};
|
|
5926
|
+
}
|
|
5602
5927
|
function TruncCell({ children, lines }) {
|
|
5603
5928
|
const { ref, isTruncated } = useTextOverflow({ lines });
|
|
5604
5929
|
const clampClass = lines === 1 ? "truncate" : `line-clamp-${lines}`;
|
|
@@ -5606,7 +5931,7 @@ function TruncCell({ children, lines }) {
|
|
|
5606
5931
|
if (!isTruncated) return cell;
|
|
5607
5932
|
return /* @__PURE__ */ jsx(Tooltip, { content: children, children: cell });
|
|
5608
5933
|
}
|
|
5609
|
-
var TITLE_CLASSES =
|
|
5934
|
+
var TITLE_CLASSES = TITLE_TEXT;
|
|
5610
5935
|
var FRAME_CLASSES = cn(
|
|
5611
5936
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
|
|
5612
5937
|
"rounded-[var(--ds-radius-md)]",
|
|
@@ -5614,13 +5939,25 @@ var FRAME_CLASSES = cn(
|
|
|
5614
5939
|
"bg-[var(--ds-bg-surface)]"
|
|
5615
5940
|
);
|
|
5616
5941
|
function TableHeading({ title, description, actions, titleId, descriptionId, inset }) {
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5942
|
+
const heading = /* @__PURE__ */ jsx("h3", { id: titleId, className: TITLE_CLASSES, children: title });
|
|
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);
|
|
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;
|
|
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: [
|
|
5949
|
+
/* @__PURE__ */ jsxs("div", { className: HEADER_LAYOUT.block, children: [
|
|
5950
|
+
heading,
|
|
5951
|
+
descriptionText()
|
|
5621
5952
|
] }),
|
|
5622
|
-
|
|
5623
|
-
] })
|
|
5953
|
+
actionsBlock
|
|
5954
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
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 }),
|
|
5957
|
+
actionsBlock
|
|
5958
|
+
] }),
|
|
5959
|
+
descriptionText(HEADER_LAYOUT.below)
|
|
5960
|
+
] }) });
|
|
5624
5961
|
}
|
|
5625
5962
|
function Table({
|
|
5626
5963
|
columns,
|
|
@@ -5645,6 +5982,7 @@ function Table({
|
|
|
5645
5982
|
title,
|
|
5646
5983
|
description,
|
|
5647
5984
|
actions,
|
|
5985
|
+
"aria-label": ariaLabel,
|
|
5648
5986
|
ref
|
|
5649
5987
|
}) {
|
|
5650
5988
|
const headingId = useId();
|
|
@@ -5716,6 +6054,8 @@ function Table({
|
|
|
5716
6054
|
const preferences = useShellPreferences();
|
|
5717
6055
|
const mobileBreakpoint = mobileBreakpointProp ?? preferences.tableToCardsBreakpoint ?? "md";
|
|
5718
6056
|
const isMobile = useBreakpoint(mobileBreakpoint);
|
|
6057
|
+
const { ref: scrollRef, measure: measureScroll, scrollable, fadeProps } = useScrollEdges({ enabled: !isMobile });
|
|
6058
|
+
const [regionFocused, setRegionFocused] = useState(false);
|
|
5719
6059
|
const cardHeading = title ? /* @__PURE__ */ jsx(TableHeading, { title, description, actions, titleId, descriptionId, inset: false }) : null;
|
|
5720
6060
|
const titledCards = (body) => /* @__PURE__ */ jsxs("div", { ref, "data-ds-list": "", "data-gs": "table", className: cn("flex flex-col", className), children: [
|
|
5721
6061
|
cardHeading,
|
|
@@ -5766,7 +6106,7 @@ function Table({
|
|
|
5766
6106
|
}) }) });
|
|
5767
6107
|
return title ? titledCards(cards) : cards;
|
|
5768
6108
|
}
|
|
5769
|
-
const table = /* @__PURE__ */ jsxs("table", { className: "w-full text-sm", ...title ? { "aria-labelledby": titleId, "aria-describedby": description ? descriptionId : void 0 } : {}, children: [
|
|
6109
|
+
const table = /* @__PURE__ */ jsxs("table", { className: "w-full text-sm", ...title ? { "aria-labelledby": titleId, "aria-describedby": description ? descriptionId : void 0 } : ariaLabel ? { "aria-label": ariaLabel } : {}, children: [
|
|
5770
6110
|
/* @__PURE__ */ jsx("thead", { className: cn("bg-[var(--ds-bg-muted)]", stickyHeader && "sticky top-0 z-10"), children: /* @__PURE__ */ jsxs("tr", { className: "border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", children: [
|
|
5771
6111
|
selectable && /* @__PURE__ */ jsx("th", { className: cn("w-10", density === "compact" ? "px-ds-2 py-ds-2" : "px-ds-3 py-ds-3"), children: /* @__PURE__ */ jsx(
|
|
5772
6112
|
Checkbox,
|
|
@@ -5917,26 +6257,37 @@ function Table({
|
|
|
5917
6257
|
] }, i);
|
|
5918
6258
|
}) })
|
|
5919
6259
|
] });
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
6260
|
+
const region = scrollable || regionFocused ? { tabIndex: 0, role: "region", ...title ? { "aria-labelledby": titleId } : { "aria-label": ariaLabel ?? "Table" } } : {};
|
|
6261
|
+
return /* @__PURE__ */ jsxs(
|
|
6262
|
+
"div",
|
|
6263
|
+
{
|
|
6264
|
+
ref,
|
|
6265
|
+
"data-ds-list": "",
|
|
6266
|
+
"data-gs": "table",
|
|
6267
|
+
className: cn("w-full min-w-0 flex flex-col", FRAME_CLASSES, "has-[>[data-table-scroll]:focus-visible]:shadow-[var(--ds-shadow-focus)]", className),
|
|
6268
|
+
children: [
|
|
6269
|
+
title && /* @__PURE__ */ jsx(TableHeading, { title, description, actions, titleId, descriptionId, inset: true }),
|
|
6270
|
+
/* @__PURE__ */ jsx(
|
|
6271
|
+
"div",
|
|
6272
|
+
{
|
|
6273
|
+
ref: scrollRef,
|
|
6274
|
+
"data-table-scroll": "",
|
|
6275
|
+
onScroll: measureScroll,
|
|
6276
|
+
onFocus: (e) => {
|
|
6277
|
+
if (e.target === e.currentTarget) setRegionFocused(true);
|
|
6278
|
+
},
|
|
6279
|
+
onBlur: (e) => {
|
|
6280
|
+
if (e.target === e.currentTarget) setRegionFocused(false);
|
|
6281
|
+
},
|
|
6282
|
+
...fadeProps,
|
|
6283
|
+
...region,
|
|
6284
|
+
className: cn("min-h-0 overflow-x-auto focus-visible:outline-none", title ? "rounded-b-[inherit]" : "rounded-[inherit]"),
|
|
6285
|
+
children: table
|
|
6286
|
+
}
|
|
6287
|
+
)
|
|
6288
|
+
]
|
|
6289
|
+
}
|
|
6290
|
+
);
|
|
5940
6291
|
}
|
|
5941
6292
|
function optionsKeyForFit(options) {
|
|
5942
6293
|
return options.map((o) => `${o.value}:${o.label}`).join("|");
|
|
@@ -5969,9 +6320,12 @@ function SegmentedControl({
|
|
|
5969
6320
|
onHoverChange,
|
|
5970
6321
|
className,
|
|
5971
6322
|
"aria-label": ariaLabel,
|
|
5972
|
-
maxOptions = 6
|
|
6323
|
+
maxOptions = 6,
|
|
6324
|
+
...wiring
|
|
5973
6325
|
}) {
|
|
5974
6326
|
const contextSize = useContext(ControlSizeContext);
|
|
6327
|
+
const control = useFieldControl(wiring);
|
|
6328
|
+
const named = !ariaLabel && control.labelId ? { "aria-labelledby": control.labelId } : {};
|
|
5975
6329
|
const size = sizeProp ?? contextSize ?? "md";
|
|
5976
6330
|
const containerRef = useRef(null);
|
|
5977
6331
|
const [indicator, setIndicator] = useState({ left: 0, width: 0 });
|
|
@@ -6067,6 +6421,7 @@ function SegmentedControl({
|
|
|
6067
6421
|
Dropdown,
|
|
6068
6422
|
{
|
|
6069
6423
|
"aria-label": ariaLabel,
|
|
6424
|
+
...wiring,
|
|
6070
6425
|
size: size === "md" || size === "lg" ? "md" : "sm",
|
|
6071
6426
|
options: options.filter((o) => !o.disabled).map((o) => ({ id: o.value, label: o.label })),
|
|
6072
6427
|
value,
|
|
@@ -6080,7 +6435,12 @@ function SegmentedControl({
|
|
|
6080
6435
|
{
|
|
6081
6436
|
ref: containerRef,
|
|
6082
6437
|
role: "radiogroup",
|
|
6438
|
+
id: control.id,
|
|
6083
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,
|
|
6084
6444
|
onKeyDown: handleKeyDown,
|
|
6085
6445
|
className: cn(
|
|
6086
6446
|
"relative items-center",
|
|
@@ -6090,6 +6450,7 @@ function SegmentedControl({
|
|
|
6090
6450
|
"bg-[var(--ds-bg-muted)]",
|
|
6091
6451
|
"rounded-[var(--ds-radius-lg)]",
|
|
6092
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)]",
|
|
6093
6454
|
className
|
|
6094
6455
|
),
|
|
6095
6456
|
children: [
|
|
@@ -6600,7 +6961,7 @@ function WeekView({
|
|
|
6600
6961
|
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "flex flex-col h-full overflow-hidden", children: [
|
|
6601
6962
|
/* @__PURE__ */ jsxs("div", { className: "flex border-b-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]", children: [
|
|
6602
6963
|
/* @__PURE__ */ jsx("div", { className: "w-14 shrink-0 border-r-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)]" }),
|
|
6603
|
-
/* @__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(
|
|
6604
6965
|
"div",
|
|
6605
6966
|
{
|
|
6606
6967
|
className: "grid",
|
|
@@ -6640,7 +7001,7 @@ function WeekView({
|
|
|
6640
7001
|
] }),
|
|
6641
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: [
|
|
6642
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" }),
|
|
6643
|
-
/* @__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(
|
|
6644
7005
|
"div",
|
|
6645
7006
|
{
|
|
6646
7007
|
className: "grid",
|
|
@@ -6677,7 +7038,7 @@ function WeekView({
|
|
|
6677
7038
|
},
|
|
6678
7039
|
h
|
|
6679
7040
|
)) }),
|
|
6680
|
-
/* @__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(
|
|
6681
7042
|
"div",
|
|
6682
7043
|
{
|
|
6683
7044
|
className: "relative",
|
|
@@ -7690,7 +8051,7 @@ function AvatarGroup({ items, max = 4, size = "sm", ring = "canvas", onOverflowC
|
|
|
7690
8051
|
const shown = items.slice(0, Math.max(0, max));
|
|
7691
8052
|
const hidden = items.slice(shown.length);
|
|
7692
8053
|
const ringClass = cn(
|
|
7693
|
-
"rounded-[var(--ds-radius-full)] ring-2",
|
|
8054
|
+
"relative rounded-[var(--ds-radius-full)] ring-2",
|
|
7694
8055
|
ring === "canvas" ? "ring-[var(--ds-bg-canvas)]" : "ring-[var(--ds-bg-surface)]"
|
|
7695
8056
|
);
|
|
7696
8057
|
const hiddenNames = hidden.map((i) => i.name ?? i.initials).filter(Boolean).join(", ");
|
|
@@ -7990,11 +8351,38 @@ function HorizontalLayout({ items, minItemWidth, className }) {
|
|
|
7990
8351
|
/* @__PURE__ */ jsxs("div", { className: "text-center mt-ds-2 px-ds-3", children: [
|
|
7991
8352
|
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: item.title }),
|
|
7992
8353
|
item.description && /* @__PURE__ */ jsx(ExpandableDescription, { className: "text-center", children: item.description }),
|
|
7993
|
-
|
|
8354
|
+
/* @__PURE__ */ jsx(ItemTime, { item })
|
|
7994
8355
|
] })
|
|
7995
8356
|
] }, i);
|
|
7996
8357
|
}) });
|
|
7997
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
|
+
}
|
|
7998
8386
|
function VerticalLayout({ items, className }) {
|
|
7999
8387
|
return /* @__PURE__ */ jsx("div", { className: cn("relative", className), children: items.map((item, i) => /* @__PURE__ */ jsxs("div", { className: "flex gap-ds-4", children: [
|
|
8000
8388
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
|
|
@@ -8004,7 +8392,7 @@ function VerticalLayout({ items, className }) {
|
|
|
8004
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: [
|
|
8005
8393
|
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: item.title }),
|
|
8006
8394
|
item.description && /* @__PURE__ */ jsx(ExpandableDescription, { children: item.description }),
|
|
8007
|
-
|
|
8395
|
+
/* @__PURE__ */ jsx(ItemTime, { item })
|
|
8008
8396
|
] })
|
|
8009
8397
|
] }, i)) });
|
|
8010
8398
|
}
|
|
@@ -9387,7 +9775,7 @@ var StackedList = forwardRef(function StackedList2({
|
|
|
9387
9775
|
});
|
|
9388
9776
|
var TIME_ZOOMS = ["day", "week", "month", "quarter"];
|
|
9389
9777
|
var DAY_MS = 864e5;
|
|
9390
|
-
var
|
|
9778
|
+
var DATE_ONLY2 = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
9391
9779
|
var utcDay = (y, m, d) => Math.round(Date.UTC(y, m, d) / DAY_MS);
|
|
9392
9780
|
function dayOfDate(d) {
|
|
9393
9781
|
const t = d.getTime();
|
|
@@ -9403,7 +9791,7 @@ function dayOf(value) {
|
|
|
9403
9791
|
if (typeof value === "number") return Number.isFinite(value) ? value : NaN;
|
|
9404
9792
|
if (value instanceof Date) return dayOfDate(value);
|
|
9405
9793
|
if (typeof value !== "string") return NaN;
|
|
9406
|
-
const m =
|
|
9794
|
+
const m = DATE_ONLY2.exec(value.trim());
|
|
9407
9795
|
if (!m) return dayOfDate(new Date(value));
|
|
9408
9796
|
const [y, mo, d] = [Number(m[1]), Number(m[2]) - 1, Number(m[3])];
|
|
9409
9797
|
const day = utcDay(y, mo, d);
|
|
@@ -9416,7 +9804,7 @@ function dateOfDay(day) {
|
|
|
9416
9804
|
return new Date(u.getUTCFullYear(), u.getUTCMonth(), u.getUTCDate(), 0, 0, 0, Math.round((day - whole) * DAY_MS));
|
|
9417
9805
|
}
|
|
9418
9806
|
function isWholeDay(value) {
|
|
9419
|
-
return typeof value === "string" ?
|
|
9807
|
+
return typeof value === "string" ? DATE_ONLY2.test(value.trim()) : Number.isInteger(dayOf(value));
|
|
9420
9808
|
}
|
|
9421
9809
|
function endDayOf(value) {
|
|
9422
9810
|
const day = dayOf(value);
|
|
@@ -11121,40 +11509,22 @@ function trackClasses(orientation) {
|
|
|
11121
11509
|
"border-b-[length:var(--ds-nav-h-track-border)] border-[var(--ds-border-default)]"
|
|
11122
11510
|
);
|
|
11123
11511
|
}
|
|
11124
|
-
var FADE = 24;
|
|
11125
11512
|
function useScrollTrack(activeTab, enabled) {
|
|
11126
|
-
const ref =
|
|
11127
|
-
const [edges, setEdges] = useState({ left: false, right: false });
|
|
11128
|
-
const measure = useCallback(() => {
|
|
11129
|
-
const el = ref.current;
|
|
11130
|
-
if (!el) return;
|
|
11131
|
-
const left = el.scrollLeft > 1;
|
|
11132
|
-
const right = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
|
|
11133
|
-
setEdges((prev) => prev.left === left && prev.right === right ? prev : { left, right });
|
|
11134
|
-
}, []);
|
|
11513
|
+
const { ref, elRef, measure, fadeProps } = useScrollEdges({ enabled });
|
|
11135
11514
|
useLayoutEffect(() => {
|
|
11136
11515
|
if (!enabled) return;
|
|
11137
|
-
|
|
11138
|
-
const el = ref.current;
|
|
11139
|
-
if (!el || typeof ResizeObserver === "undefined") return;
|
|
11140
|
-
const observer = new ResizeObserver(measure);
|
|
11141
|
-
observer.observe(el);
|
|
11142
|
-
return () => observer.disconnect();
|
|
11143
|
-
}, [enabled, measure]);
|
|
11144
|
-
useLayoutEffect(() => {
|
|
11145
|
-
if (!enabled) return;
|
|
11146
|
-
const el = ref.current;
|
|
11516
|
+
const el = elRef.current;
|
|
11147
11517
|
const tab = el?.querySelector('[role="tab"][aria-selected="true"]');
|
|
11148
11518
|
if (!el || !tab) return;
|
|
11149
11519
|
const start = tab.offsetLeft;
|
|
11150
11520
|
const end = start + tab.offsetWidth;
|
|
11151
|
-
if (start < el.scrollLeft +
|
|
11152
|
-
else if (end > el.scrollLeft + el.clientWidth -
|
|
11521
|
+
if (start < el.scrollLeft + EDGE_FADE) el.scrollLeft = Math.max(0, start - EDGE_FADE);
|
|
11522
|
+
else if (end > el.scrollLeft + el.clientWidth - EDGE_FADE) el.scrollLeft = end - el.clientWidth + EDGE_FADE;
|
|
11153
11523
|
measure();
|
|
11154
|
-
}, [activeTab, enabled, measure]);
|
|
11524
|
+
}, [activeTab, enabled, measure, elRef]);
|
|
11155
11525
|
useEffect(() => {
|
|
11156
11526
|
if (!enabled) return;
|
|
11157
|
-
const el =
|
|
11527
|
+
const el = elRef.current;
|
|
11158
11528
|
if (!el) return;
|
|
11159
11529
|
const onWheel = (e) => {
|
|
11160
11530
|
if (el.scrollWidth <= el.clientWidth || Math.abs(e.deltaY) <= Math.abs(e.deltaX)) return;
|
|
@@ -11204,14 +11574,11 @@ function useScrollTrack(activeTab, enabled) {
|
|
|
11204
11574
|
el.removeEventListener("pointercancel", onUp);
|
|
11205
11575
|
el.removeEventListener("click", onClick, true);
|
|
11206
11576
|
};
|
|
11207
|
-
}, [enabled]);
|
|
11208
|
-
const fade = enabled ? [edges.left && "left", edges.right && "right"].filter(Boolean).join(" ") : "";
|
|
11209
|
-
const mask = fade ? `linear-gradient(to right, ${edges.left ? `transparent 0, black ${FADE}px` : "black 0"}, ${edges.right ? `black calc(100% - ${FADE}px), transparent 100%` : "black 100%"})` : void 0;
|
|
11577
|
+
}, [enabled, elRef]);
|
|
11210
11578
|
return {
|
|
11211
11579
|
ref,
|
|
11212
11580
|
onScroll: measure,
|
|
11213
|
-
|
|
11214
|
-
style: mask ? { maskImage: mask, WebkitMaskImage: mask } : void 0
|
|
11581
|
+
...fadeProps
|
|
11215
11582
|
};
|
|
11216
11583
|
}
|
|
11217
11584
|
var SCROLL_TRACK = "overflow-x-auto overflow-y-hidden [scrollbar-width:none] [&::-webkit-scrollbar]:hidden max-w-full";
|
|
@@ -14925,7 +15292,8 @@ function Dialog({ open, onClose: onCloseProp, title, description, children, foot
|
|
|
14925
15292
|
className: cn(
|
|
14926
15293
|
"relative z-10 w-full",
|
|
14927
15294
|
isMobile ? "max-w-none h-full" : sizeClasses[size],
|
|
14928
|
-
|
|
15295
|
+
OVERLAY_SURFACE,
|
|
15296
|
+
"text-[var(--ds-text-primary)]",
|
|
14929
15297
|
GLASS_OVERLAY,
|
|
14930
15298
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
14931
15299
|
isMobile ? "rounded-none" : "rounded-[var(--ds-radius-xl)]",
|
|
@@ -15444,7 +15812,8 @@ function CommandPalette({ open, onOpenChange, commands, placeholder = "Type a co
|
|
|
15444
15812
|
"aria-label": "Command palette",
|
|
15445
15813
|
className: cn(
|
|
15446
15814
|
"relative z-10 w-full max-w-lg",
|
|
15447
|
-
|
|
15815
|
+
OVERLAY_SURFACE,
|
|
15816
|
+
"text-[var(--ds-text-primary)]",
|
|
15448
15817
|
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
15449
15818
|
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
15450
15819
|
"rounded-[var(--ds-radius-xl)] overflow-hidden",
|
|
@@ -16718,6 +17087,6 @@ var TextOverflow = forwardRef(function TextOverflow2({
|
|
|
16718
17087
|
return /* @__PURE__ */ jsx(Tooltip, { content: resolvedTooltipContent, children: content });
|
|
16719
17088
|
});
|
|
16720
17089
|
|
|
16721
|
-
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 };
|
|
16722
17091
|
//# sourceMappingURL=index.js.map
|
|
16723
17092
|
//# sourceMappingURL=index.js.map
|