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.
Files changed (37) hide show
  1. package/README.md +19 -13
  2. package/dist/charts.js +3 -3
  3. package/dist/charts.js.map +1 -1
  4. package/dist/chat.js +4 -4
  5. package/dist/{chunk-CIVSNXFG.js → chunk-5PDTHKW3.js} +17 -9
  6. package/dist/chunk-5PDTHKW3.js.map +1 -0
  7. package/dist/{chunk-XGSQOMEY.js → chunk-EQDR57AM.js} +4 -4
  8. package/dist/{chunk-XGSQOMEY.js.map → chunk-EQDR57AM.js.map} +1 -1
  9. package/dist/{chunk-EMCSARQO.js → chunk-ILIODA7W.js} +3 -3
  10. package/dist/{chunk-EMCSARQO.js.map → chunk-ILIODA7W.js.map} +1 -1
  11. package/dist/{chunk-OENJCGTJ.js → chunk-JN37OVTP.js} +4 -4
  12. package/dist/{chunk-OENJCGTJ.js.map → chunk-JN37OVTP.js.map} +1 -1
  13. package/dist/{chunk-4KVFH5KC.js → chunk-M2QRNBDQ.js} +4 -3
  14. package/dist/chunk-M2QRNBDQ.js.map +1 -0
  15. package/dist/{chunk-Z63OSN64.js → chunk-NCIZQYXQ.js} +7 -4
  16. package/dist/chunk-NCIZQYXQ.js.map +1 -0
  17. package/dist/{chunk-PVTGMCVR.js → chunk-XYDIBW3J.js} +4 -4
  18. package/dist/{chunk-PVTGMCVR.js.map → chunk-XYDIBW3J.js.map} +1 -1
  19. package/dist/data-grid.js +3 -3
  20. package/dist/editor.js +3 -3
  21. package/dist/editor.js.map +1 -1
  22. package/dist/index.d.ts +155 -55
  23. package/dist/index.js +576 -207
  24. package/dist/index.js.map +1 -1
  25. package/dist/kanban.js +3 -3
  26. package/dist/resizable.d.ts +8 -1
  27. package/dist/resizable.js +35 -15
  28. package/dist/resizable.js.map +1 -1
  29. package/dist/roots.css +164 -2
  30. package/dist/tailwind.css +14 -0
  31. package/dist/utils.js +1 -1
  32. package/dist/virtualized.js +1 -1
  33. package/dist-static/tailwind.css +14 -0
  34. package/package.json +2 -2
  35. package/dist/chunk-4KVFH5KC.js.map +0 -1
  36. package/dist/chunk-CIVSNXFG.js.map +0 -1
  37. 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-CIVSNXFG.js';
2
- export { AppShell, Button, ButtonSizeContext, ControlSizeContext, Drawer, Sheet, SkipLink, Spinner, useAppShell, useUnsavedChanges } from './chunk-CIVSNXFG.js';
3
- import { Skeleton } from './chunk-Z63OSN64.js';
4
- export { Skeleton } from './chunk-Z63OSN64.js';
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-XGSQOMEY.js';
8
- export { CodeBlock, Divider, Link } from './chunk-XGSQOMEY.js';
9
- import { Badge } from './chunk-PVTGMCVR.js';
10
- export { Badge } from './chunk-PVTGMCVR.js';
11
- import { inferColumnKinds, CardValue } from './chunk-OENJCGTJ.js';
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-EMCSARQO.js';
17
- export { Tooltip, useTextOverflow } from './chunk-EMCSARQO.js';
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, ACTIVE_RING, GLASS_BACKDROP, GLASS_DROPDOWN, lockBodyScroll, unlockBodyScroll, GLASS_OVERLAY, ERROR_ACTIVE_RING, ERROR_FOCUS_RING, FOCUS_RING, ERROR_HAS_FOCUS_RING, HAS_FOCUS_RING, ERROR_FOCUS_WITHIN_RING, FOCUS_WITHIN_RING } from './chunk-4KVFH5KC.js';
22
- import { createContext, forwardRef, useState, useRef, useCallback, useLayoutEffect, useMemo, useContext, useId, memo, useEffect, useImperativeHandle, Children, isValidElement, cloneElement, Fragment as Fragment$1, useSyncExternalStore } from 'react';
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: action.variant === "destructive" ? "destructive" : "secondary",
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": error || void 0,
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
- error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
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
- !error && !disabled && !open && "hover:border-[var(--ds-input-border-hover)]",
629
- open && (error ? ERROR_ACTIVE_RING : ACTIVE_RING),
630
- error ? ERROR_FOCUS_RING : FOCUS_RING,
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
- error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
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
- !error && !disabled && "hover:border-[var(--ds-input-border-hover)]",
891
- error ? ERROR_HAS_FOCUS_RING : HAS_FOCUS_RING,
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-invalid": error || void 0,
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 inputId = id ?? generatedId;
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": error || typedInvalid || void 0,
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
- error || typedInvalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
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
- !error && !disabled && !open && "hover:border-[var(--ds-input-border-hover)] focus-within:border-[var(--ds-input-border-hover)]",
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 triggerId = id ?? generatedId;
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-invalid": error || void 0,
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
- error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
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
- !error && !disabled && !open && "hover:border-[var(--ds-input-border-hover)]",
2043
- open && (error ? ERROR_ACTIVE_RING : ACTIVE_RING),
2044
- error ? ERROR_FOCUS_RING : FOCUS_RING,
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-invalid": error || void 0,
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
- error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
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
- !error && !disabled && !open && "hover:border-[var(--ds-input-border-hover)] focus-within:border-[var(--ds-input-border-hover)]",
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.map((d) => document.getElementById(d)?.textContent?.trim()).find((t) => t && /error|invalid|required|must|enter|choose|select|please/i.test(t)) ?? described.map((d) => document.getElementById(d)?.textContent?.trim()).filter(Boolean).pop() ?? "Needs attention";
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) => ({ ...prev, [field]: message }));
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
- (showRing || hasSelectType && selected) && ACTIVE_RING,
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: "flex items-center gap-ds-2 shrink-0 ml-auto", children: [
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
- 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: "flex flex-wrap items-start justify-between gap-ds-4", children: [
5178
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-ds-1.5 grow basis-1/2 [min-width:min-content] break-words", children: [
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
- className: cn("font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", !action && lines > 0 && lineClampClass, className),
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 = "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] break-words";
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
- return /* @__PURE__ */ jsxs("div", { "data-table-heading": "", className: cn("flex flex-wrap items-start justify-between gap-ds-4", inset ? "px-ds-5 py-ds-4" : "pb-ds-4"), children: [
5618
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-ds-1.5 grow basis-1/2 [min-width:min-content] break-words", children: [
5619
- /* @__PURE__ */ jsx("h3", { id: titleId, className: TITLE_CLASSES, children: title }),
5620
- description && /* @__PURE__ */ jsx("p", { id: descriptionId, className: "text-sm text-[var(--ds-text-muted)]", children: description })
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
- actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0 ml-auto", children: actions })
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
- if (!title) {
5921
- return /* @__PURE__ */ jsx(
5922
- "div",
5923
- {
5924
- ref,
5925
- "data-ds-list": "",
5926
- "data-gs": "table",
5927
- className: cn(
5928
- "w-full overflow-x-auto",
5929
- FRAME_CLASSES,
5930
- className
5931
- ),
5932
- children: table
5933
- }
5934
- );
5935
- }
5936
- return /* @__PURE__ */ jsxs("div", { ref, "data-ds-list": "", "data-gs": "table", className: cn("w-full flex flex-col", FRAME_CLASSES, className), children: [
5937
- /* @__PURE__ */ jsx(TableHeading, { title, description, actions, titleId, descriptionId, inset: true }),
5938
- /* @__PURE__ */ jsx("div", { "data-table-scroll": "", className: "min-h-0 overflow-x-auto rounded-b-[inherit]", children: table })
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
- item.timestamp && /* @__PURE__ */ jsx("p", { className: "text-2xs text-[var(--ds-text-muted)] mt-ds-0.5 tabular-nums", children: item.timestamp })
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
- item.timestamp && /* @__PURE__ */ jsx("p", { className: "text-2xs text-[var(--ds-text-muted)] mt-ds-0.5 tabular-nums", children: item.timestamp })
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 DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
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 = DATE_ONLY.exec(value.trim());
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" ? DATE_ONLY.test(value.trim()) : Number.isInteger(dayOf(value));
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 = useRef(null);
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
- measure();
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 + FADE) el.scrollLeft = Math.max(0, start - FADE);
11152
- else if (end > el.scrollLeft + el.clientWidth - FADE) el.scrollLeft = end - el.clientWidth + FADE;
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 = ref.current;
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
- "data-fade": fade || void 0,
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
- "bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
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
- "bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
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