@tensor_1/react 2.15.0 → 2.17.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 (82) hide show
  1. package/README.md +5 -0
  2. package/dist/ChartCore-Do6gRBN3.d.cts +44 -0
  3. package/dist/chart-preset.cjs +56 -12
  4. package/dist/chart-preset.d.cts +2 -2
  5. package/dist/chart-preset.d.ts +1 -1
  6. package/dist/chart-preset.js +4 -1
  7. package/dist/chart.cjs +56 -12
  8. package/dist/chart.d.cts +2 -2
  9. package/dist/chart.d.ts +1 -1
  10. package/dist/chart.js +4 -1
  11. package/dist/components/Alert.js +15 -7
  12. package/dist/components/AppShell.d.ts +3 -1
  13. package/dist/components/AppShell.js +3 -1
  14. package/dist/components/Avatar.js +2 -1
  15. package/dist/components/Button.js +32 -16
  16. package/dist/components/Card.d.ts +3 -1
  17. package/dist/components/Card.js +2 -2
  18. package/dist/components/Chart.d.ts +1 -1
  19. package/dist/components/Chart.js +4 -1
  20. package/dist/components/ChartCore.d.ts +24 -3
  21. package/dist/components/ChartCore.js +53 -12
  22. package/dist/components/CommandPalette.d.ts +4 -2
  23. package/dist/components/CommandPalette.js +66 -13
  24. package/dist/components/Comments.d.ts +5 -1
  25. package/dist/components/Comments.js +1 -1
  26. package/dist/components/Composer.d.ts +8 -1
  27. package/dist/components/Composer.js +7 -2
  28. package/dist/components/DetailLayout.js +1 -1
  29. package/dist/components/Drawer.d.ts +3 -4
  30. package/dist/components/Drawer.js +6 -4
  31. package/dist/components/Field.js +6 -3
  32. package/dist/components/Flow.d.ts +26 -0
  33. package/dist/components/Flow.js +48 -0
  34. package/dist/components/Inbox.d.ts +13 -3
  35. package/dist/components/Inbox.js +62 -3
  36. package/dist/components/Input.d.ts +13 -2
  37. package/dist/components/Input.js +20 -5
  38. package/dist/components/Kanban.d.ts +15 -3
  39. package/dist/components/Kanban.js +42 -10
  40. package/dist/components/Meter.d.ts +3 -1
  41. package/dist/components/Meter.js +9 -1
  42. package/dist/components/Modal.d.ts +4 -5
  43. package/dist/components/Modal.js +4 -4
  44. package/dist/components/NavFavourites.js +11 -0
  45. package/dist/components/PageHeader.d.ts +3 -1
  46. package/dist/components/PageHeader.js +2 -2
  47. package/dist/components/Peek.d.ts +3 -4
  48. package/dist/components/Peek.js +9 -6
  49. package/dist/components/Pipeline.d.ts +25 -0
  50. package/dist/components/Pipeline.js +65 -0
  51. package/dist/components/Progress.d.ts +3 -1
  52. package/dist/components/Progress.js +5 -3
  53. package/dist/components/Radio.d.ts +3 -1
  54. package/dist/components/Radio.js +6 -2
  55. package/dist/components/Spinner.d.ts +3 -1
  56. package/dist/components/Spinner.js +3 -3
  57. package/dist/components/Stat.js +5 -1
  58. package/dist/components/States.d.ts +1 -0
  59. package/dist/components/States.js +7 -1
  60. package/dist/components/Table.d.ts +8 -1
  61. package/dist/components/Table.js +10 -6
  62. package/dist/components/Tabs.d.ts +13 -1
  63. package/dist/components/Tabs.js +79 -4
  64. package/dist/components/Timeline.d.ts +3 -3
  65. package/dist/components/Timeline.js +3 -3
  66. package/dist/components/Toast.js +42 -5
  67. package/dist/components/Tooltip.d.ts +3 -1
  68. package/dist/components/Tooltip.js +44 -5
  69. package/dist/components/Tree.d.ts +2 -0
  70. package/dist/components/Tree.js +26 -4
  71. package/dist/hooks/useDialog.d.ts +1 -1
  72. package/dist/hooks/useDialog.js +17 -2
  73. package/dist/hooks/useTable.d.ts +5 -0
  74. package/dist/hooks/useTable.js +20 -1
  75. package/dist/index.cjs +1191 -626
  76. package/dist/index.d.cts +168 -35
  77. package/dist/index.d.ts +4 -2
  78. package/dist/index.js +8 -1
  79. package/dist/tree-model.d.ts +4 -0
  80. package/dist/tree-model.js +8 -0
  81. package/package.json +1 -1
  82. package/dist/ChartCore-Bt1C84ty.d.cts +0 -22
package/dist/index.cjs CHANGED
@@ -67,6 +67,8 @@ __export(src_exports, {
67
67
  Field: () => Field,
68
68
  FilterPopover: () => FilterPopover,
69
69
  FilteredEmptyState: () => FilteredEmptyState,
70
+ Flow: () => Flow,
71
+ FlowNode: () => FlowNode,
70
72
  ForbiddenState: () => ForbiddenState,
71
73
  Highlighted: () => Highlighted,
72
74
  Inbox: () => Inbox,
@@ -99,6 +101,8 @@ __export(src_exports, {
99
101
  PageIntro: () => PageIntro,
100
102
  Pagination: () => Pagination,
101
103
  Peek: () => Peek,
104
+ Pipeline: () => Pipeline,
105
+ PipelineStage: () => PipelineStage,
102
106
  Popover: () => Popover,
103
107
  Progress: () => Progress,
104
108
  PromptDialog: () => PromptDialog,
@@ -130,6 +134,7 @@ __export(src_exports, {
130
134
  SubNavItem: () => SubNavItem,
131
135
  Switch: () => Switch,
132
136
  Tab: () => Tab,
137
+ TabPanel: () => TabPanel,
133
138
  Table: () => Table,
134
139
  TableWrap: () => TableWrap,
135
140
  Tabs: () => Tabs,
@@ -253,8 +258,10 @@ function unlockBodyScroll() {
253
258
  saved = null;
254
259
  }
255
260
  }
256
- function useDialog(open) {
261
+ function useDialog(open, onClose) {
257
262
  const ref = (0, import_react.useRef)(null);
263
+ const onCloseRef = (0, import_react.useRef)(onClose);
264
+ onCloseRef.current = onClose;
258
265
  (0, import_react.useEffect)(() => {
259
266
  const el = ref.current;
260
267
  if (!el || !open) {
@@ -263,8 +270,21 @@ function useDialog(open) {
263
270
  }
264
271
  if (!el.open) el.showModal();
265
272
  lockBodyScroll();
273
+ let locked = true;
274
+ const handleClose = () => {
275
+ if (locked) {
276
+ locked = false;
277
+ unlockBodyScroll();
278
+ }
279
+ onCloseRef.current?.();
280
+ };
281
+ el.addEventListener("close", handleClose);
266
282
  return () => {
267
- unlockBodyScroll();
283
+ el.removeEventListener("close", handleClose);
284
+ if (locked) {
285
+ locked = false;
286
+ unlockBodyScroll();
287
+ }
268
288
  if (el.open) el.close();
269
289
  };
270
290
  }, [open]);
@@ -537,6 +557,24 @@ function useTable(data, options = {}) {
537
557
  const toggleAllRows = (0, import_react2.useCallback)(() => setSelected((s) => togglePage(s, pageIds)), [pageIds]);
538
558
  const clearSelection = (0, import_react2.useCallback)(() => setSelected(/* @__PURE__ */ new Set()), []);
539
559
  const togglePin = (0, import_react2.useCallback)((id) => setPinned((s) => toggleId(s, id)), []);
560
+ const [announcement, setAnnouncement] = (0, import_react2.useState)("");
561
+ const mounted = (0, import_react2.useRef)(false);
562
+ (0, import_react2.useEffect)(() => {
563
+ if (!mounted.current) return;
564
+ const key = sort[0];
565
+ setAnnouncement(key ? `Sorted by ${key.field}, ${key.dir}` : "Sort cleared");
566
+ }, [sort]);
567
+ (0, import_react2.useEffect)(() => {
568
+ if (!mounted.current) return;
569
+ setAnnouncement(`${rows.length} result${rows.length === 1 ? "" : "s"}`);
570
+ }, [filters, query]);
571
+ (0, import_react2.useEffect)(() => {
572
+ if (!mounted.current) return;
573
+ setAnnouncement(`${selected.size} selected`);
574
+ }, [selected]);
575
+ (0, import_react2.useEffect)(() => {
576
+ mounted.current = true;
577
+ }, []);
540
578
  const view = (0, import_react2.useMemo)(() => ({ sort, filters, q: query }), [sort, filters, query]);
541
579
  const viewQueryString = (0, import_react2.useMemo)(() => serializeView(view), [view]);
542
580
  const applyView = (0, import_react2.useCallback)((queryString) => {
@@ -553,6 +591,7 @@ function useTable(data, options = {}) {
553
591
  selected,
554
592
  pinned,
555
593
  selectAll,
594
+ announcement,
556
595
  toggleSort: doToggleSort,
557
596
  setSort,
558
597
  setFilters,
@@ -722,24 +761,40 @@ function useAnchoredPosition(anchor, floatingRef, { open, placement = "bottom-st
722
761
  // src/components/Button.tsx
723
762
  var import_react5 = require("react");
724
763
  var import_jsx_runtime = require("react/jsx-runtime");
764
+ var warnedIconButton = false;
725
765
  var Button = (0, import_react5.forwardRef)(
726
- ({ variant = "secondary", size = "md", icon = false, loading = false, className, children, disabled, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
727
- "button",
728
- {
729
- ref,
730
- className: cx(
731
- "uix-btn",
732
- `uix-btn--${variant}`,
733
- size !== "md" && `uix-btn--${size}`,
734
- icon && "uix-btn--icon",
735
- className
736
- ),
737
- disabled: disabled || loading,
738
- "data-loading": loading || void 0,
739
- ...props,
740
- children
766
+ ({ variant = "secondary", size = "md", icon = false, loading = false, className, children, disabled, onClick, ...props }, ref) => {
767
+ if (!warnedIconButton && icon && children == null && !props["aria-label"] && !props["aria-labelledby"] && typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
768
+ warnedIconButton = true;
769
+ console.warn("uix: icon-only <Button> has no accessible name \u2014 pass aria-label or aria-labelledby.");
741
770
  }
742
- )
771
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
772
+ "button",
773
+ {
774
+ ref,
775
+ className: cx(
776
+ "uix-btn",
777
+ `uix-btn--${variant}`,
778
+ size !== "md" && `uix-btn--${size}`,
779
+ icon && "uix-btn--icon",
780
+ className
781
+ ),
782
+ disabled,
783
+ "aria-disabled": loading || void 0,
784
+ "aria-busy": loading || void 0,
785
+ "data-loading": loading || void 0,
786
+ onClick: loading || onClick ? (e) => {
787
+ if (loading) {
788
+ e.preventDefault();
789
+ return;
790
+ }
791
+ onClick?.(e);
792
+ } : void 0,
793
+ ...props,
794
+ children
795
+ }
796
+ );
797
+ }
743
798
  );
744
799
  Button.displayName = "Button";
745
800
  function ButtonGroup({ children, className }) {
@@ -762,7 +817,22 @@ var Input = (0, import_react6.forwardRef)(
762
817
  )
763
818
  );
764
819
  Input.displayName = "Input";
765
- function InputGroup({ children, leadingIcon, trailingIcon, className }) {
820
+ function InputGroup({
821
+ children,
822
+ leadingIcon,
823
+ trailingIcon,
824
+ className,
825
+ id,
826
+ "aria-describedby": describedBy,
827
+ "aria-invalid": invalid,
828
+ "aria-required": required
829
+ }) {
830
+ const control = (0, import_react6.isValidElement)(children) && (id ?? describedBy ?? invalid ?? required) != null ? (0, import_react6.cloneElement)(children, {
831
+ id: children.props.id ?? id,
832
+ "aria-describedby": children.props["aria-describedby"] ?? describedBy,
833
+ "aria-invalid": children.props["aria-invalid"] ?? invalid,
834
+ "aria-required": children.props["aria-required"] ?? required
835
+ }) : children;
766
836
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
767
837
  "div",
768
838
  {
@@ -773,9 +843,9 @@ function InputGroup({ children, leadingIcon, trailingIcon, className }) {
773
843
  className
774
844
  ),
775
845
  children: [
776
- leadingIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "uix-input-group__icon", children: leadingIcon }),
777
- children,
778
- trailingIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "uix-input-group__icon uix-input-group__icon--trailing", children: trailingIcon })
846
+ leadingIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "uix-input-group__icon", "aria-hidden": "true", children: leadingIcon }),
847
+ control,
848
+ trailingIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "uix-input-group__icon uix-input-group__icon--trailing", "aria-hidden": "true", children: trailingIcon })
779
849
  ]
780
850
  }
781
851
  );
@@ -982,8 +1052,12 @@ var Radio = (0, import_react11.forwardRef)(
982
1052
  ] })
983
1053
  );
984
1054
  Radio.displayName = "Radio";
985
- function RadioGroup({ children, className }) {
986
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cx("uix-radio-group", className), children });
1055
+ function RadioGroup({ children, className, label }) {
1056
+ if (label == null) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cx("uix-radio-group", className), children });
1057
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("fieldset", { className: cx("uix-radio-group", className), children: [
1058
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("legend", { className: "uix-radio-group__legend", children: label }),
1059
+ children
1060
+ ] });
987
1061
  }
988
1062
 
989
1063
  // src/components/Switch.tsx
@@ -1005,14 +1079,17 @@ function Field({ label, hint, error, success, required, children, className, htm
1005
1079
  const uid = (0, import_react13.useId)();
1006
1080
  const msgId = `${uid}-msg`;
1007
1081
  const describedBy = error || success || hint ? msgId : void 0;
1082
+ const controlId = (0, import_react13.isValidElement)(children) ? children.props.id ?? `${uid}-ctl` : void 0;
1008
1083
  const control = (0, import_react13.isValidElement)(children) ? (0, import_react13.cloneElement)(children, {
1084
+ id: controlId,
1009
1085
  "aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0,
1010
- "aria-invalid": error ? true : children.props["aria-invalid"]
1086
+ "aria-invalid": error ? true : children.props["aria-invalid"],
1087
+ "aria-required": children.props["aria-required"] ?? (required || void 0)
1011
1088
  }) : children;
1012
1089
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: cx("uix-field", className), children: [
1013
- label && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: "uix-field__label", htmlFor, "data-required": required || void 0, children: label }),
1090
+ label && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("label", { className: "uix-field__label", htmlFor: htmlFor ?? controlId, "data-required": required || void 0, children: label }),
1014
1091
  control,
1015
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "uix-field__msg", id: msgId, children: error ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "uix-field__error", role: "alert", children: error }) : success ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "uix-field__success", children: success }) : hint ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "uix-field__hint", children: hint }) : null })
1092
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "uix-field__msg", id: msgId, children: error ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "uix-field__error", role: "alert", children: error }) : success ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "uix-field__success", role: "status", children: success }) : hint ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "uix-field__hint", children: hint }) : null })
1016
1093
  ] });
1017
1094
  }
1018
1095
 
@@ -1020,12 +1097,12 @@ function Field({ label, hint, error, success, required, children, className, htm
1020
1097
  var import_react14 = require("react");
1021
1098
  var import_jsx_runtime10 = require("react/jsx-runtime");
1022
1099
  var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M4 4l8 8M12 4l-8 8" }) });
1023
- function Modal({ open, onClose, title, children, footer, className, style, closeLabel = "Close dialog", role = "dialog" }) {
1024
- const ref = useDialog(open);
1100
+ function Modal({ open, onClose, title, children, footer, className, closeLabel = "Close dialog", role = "dialog", ...rest }) {
1101
+ const ref = useDialog(open, onClose);
1025
1102
  const titleId = (0, import_react14.useId)();
1026
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("dialog", { ref, className: cx("uix-dialog", className), style, onClose, role, "aria-labelledby": title != null ? titleId : void 0, children: [
1103
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("dialog", { ref, className: cx("uix-dialog", className), role, "aria-labelledby": title != null ? titleId : void 0, ...rest, children: [
1027
1104
  (title != null || onClose) && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "uix-dialog__header", children: [
1028
- title && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { id: titleId, className: "uix-dialog__title", children: title }),
1105
+ title && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: "uix-dialog__title", id: titleId, children: title }),
1029
1106
  onClose && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: "uix-dialog__close", onClick: onClose, "aria-label": closeLabel, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CloseIcon, {}) })
1030
1107
  ] }),
1031
1108
  children != null && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "uix-dialog__body", children }),
@@ -1083,13 +1160,15 @@ function PromptDialog({ open, title, description, inputLabel, defaultValue = "",
1083
1160
  }
1084
1161
 
1085
1162
  // src/components/Drawer.tsx
1163
+ var import_react16 = require("react");
1086
1164
  var import_jsx_runtime12 = require("react/jsx-runtime");
1087
1165
  var CloseIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M4 4l8 8M12 4l-8 8" }) });
1088
- function Drawer({ open, onClose, title, children, footer, className }) {
1089
- const ref = useDialog(open);
1090
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("dialog", { ref, className: cx("uix-drawer", className), onClose, children: [
1166
+ function Drawer({ open, onClose, title, children, footer, className, ...rest }) {
1167
+ const ref = useDialog(open, onClose);
1168
+ const titleId = (0, import_react16.useId)();
1169
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("dialog", { ref, className: cx("uix-drawer", className), "aria-labelledby": title ? titleId : void 0, ...rest, children: [
1091
1170
  (title != null || onClose) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "uix-drawer__header", children: [
1092
- title && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { fontWeight: 600, fontSize: "var(--uix-text-h3)" }, children: title }),
1171
+ title && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h2", { id: titleId, style: { fontWeight: 600, fontSize: "var(--uix-text-h3)", fontFamily: "inherit", letterSpacing: "inherit", lineHeight: "inherit" }, children: title }),
1093
1172
  onClose && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1094
1173
  "button",
1095
1174
  {
@@ -1106,27 +1185,30 @@ function Drawer({ open, onClose, title, children, footer, className }) {
1106
1185
  }
1107
1186
 
1108
1187
  // src/components/Peek.tsx
1188
+ var import_react17 = require("react");
1109
1189
  var import_jsx_runtime13 = require("react/jsx-runtime");
1110
1190
  var CloseIcon3 = () => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M4 4l8 8M12 4l-8 8" }) });
1111
1191
  var ChevronUp = () => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M2 8l4-4 4 4" }) });
1112
1192
  var ChevronDown = () => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M2 4l4 4 4-4" }) });
1113
- function Peek({ open, onClose, title, children, footer, onNavPrev, onNavNext, hint, className }) {
1114
- const ref = useDialog(open);
1193
+ function Peek({ open, onClose, title, children, footer, onNavPrev, onNavNext, hint, className, onClick, ...rest }) {
1194
+ const ref = useDialog(open, onClose);
1115
1195
  const hasNav = onNavPrev != null || onNavNext != null;
1196
+ const titleId = (0, import_react17.useId)();
1116
1197
  const onBackdropClick = (e) => {
1198
+ onClick?.(e);
1117
1199
  if (!onClose || e.target !== e.currentTarget) return;
1118
1200
  const r = e.currentTarget.getBoundingClientRect();
1119
1201
  if (r.width === 0) return;
1120
1202
  const outside = e.clientX < r.left || e.clientX > r.right || e.clientY < r.top || e.clientY > r.bottom;
1121
1203
  if (outside) onClose();
1122
1204
  };
1123
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("dialog", { ref, className: cx("uix-peek", className), onClose, onClick: onBackdropClick, children: [
1205
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("dialog", { ref, className: cx("uix-peek", className), "aria-labelledby": title ? titleId : void 0, ...rest, onClick: onBackdropClick, children: [
1124
1206
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "uix-peek__header", children: [
1125
1207
  hasNav && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "uix-peek__nav", children: [
1126
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { className: "uix-peek__navbtn", onClick: onNavPrev, disabled: !onNavPrev, "aria-label": "Previous record", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChevronUp, {}) }),
1127
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { className: "uix-peek__navbtn", onClick: onNavNext, disabled: !onNavNext, "aria-label": "Next record", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChevronDown, {}) })
1208
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { className: "uix-peek__navbtn", onClick: () => onNavPrev?.(), "aria-disabled": onNavPrev ? void 0 : true, "aria-label": "Previous record", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChevronUp, {}) }),
1209
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { className: "uix-peek__navbtn", onClick: () => onNavNext?.(), "aria-disabled": onNavNext ? void 0 : true, "aria-label": "Next record", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChevronDown, {}) })
1128
1210
  ] }),
1129
- title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "uix-peek__title", children: title }),
1211
+ title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { className: "uix-peek__title", id: titleId, children: title }),
1130
1212
  hint && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "uix-peek__hint", children: hint }),
1131
1213
  onClose && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { className: "uix-peek__close", onClick: onClose, "aria-label": "Close preview", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CloseIcon3, {}) })
1132
1214
  ] }),
@@ -1137,12 +1219,12 @@ function Peek({ open, onClose, title, children, footer, onNavPrev, onNavNext, hi
1137
1219
 
1138
1220
  // src/components/Card.tsx
1139
1221
  var import_jsx_runtime14 = require("react/jsx-runtime");
1140
- function Card({ title, subtitle, headerAction, footer, children, className, ...props }) {
1222
+ function Card({ title, titleAs: TitleTag = "div", subtitle, headerAction, footer, children, className, ...props }) {
1141
1223
  const hasHeader = title != null || subtitle != null || headerAction != null;
1142
1224
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: cx("uix-card", className), ...props, children: [
1143
1225
  hasHeader && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uix-card__header", children: [
1144
1226
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { flex: 1 }, children: [
1145
- title && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "uix-card__title", children: title }),
1227
+ title && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TitleTag, { className: "uix-card__title", children: title }),
1146
1228
  subtitle && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "uix-card__subtitle", children: subtitle })
1147
1229
  ] }),
1148
1230
  headerAction
@@ -1167,12 +1249,12 @@ function CardLink({ title, subtitle, headerAction, footer, children, className,
1167
1249
  }
1168
1250
 
1169
1251
  // src/components/Breadcrumbs.tsx
1170
- var import_react16 = require("react");
1252
+ var import_react18 = require("react");
1171
1253
  var import_jsx_runtime15 = require("react/jsx-runtime");
1172
1254
  function Breadcrumbs({ items, label, separator = "/", className, ...props }) {
1173
1255
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("nav", { "aria-label": label, className, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("ol", { className: "uix-breadcrumbs", children: items.map((item, index) => {
1174
1256
  const current = item.current ?? index === items.length - 1;
1175
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react16.Fragment, { children: [
1257
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react18.Fragment, { children: [
1176
1258
  index > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("li", { className: "uix-breadcrumbs__sep", "aria-hidden": "true", children: separator }),
1177
1259
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("li", { children: item.href && !current ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("a", { href: item.href, children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { "aria-current": current ? "page" : void 0, children: item.label }) })
1178
1260
  ] }, item.id ?? `${item.href ?? "current"}-${index}`);
@@ -1181,11 +1263,11 @@ function Breadcrumbs({ items, label, separator = "/", className, ...props }) {
1181
1263
 
1182
1264
  // src/components/PageHeader.tsx
1183
1265
  var import_jsx_runtime16 = require("react/jsx-runtime");
1184
- function PageHeader({ eyebrow, title, subtitle, actions, className, ...props }) {
1266
+ function PageHeader({ eyebrow, title, subtitle, actions, as: TitleTag = "h1", className, ...props }) {
1185
1267
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("header", { className: cx("uix-page-header", className), ...props, children: [
1186
1268
  /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "uix-page-header__titles", children: [
1187
1269
  eyebrow != null && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "uix-page-header__eyebrow", children: eyebrow }),
1188
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h1", { className: "uix-page-header__title", children: title }),
1270
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TitleTag, { className: "uix-page-header__title", children: title }),
1189
1271
  subtitle != null && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "uix-page-header__subtitle", children: subtitle })
1190
1272
  ] }),
1191
1273
  actions != null && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "uix-page-header__actions", children: actions })
@@ -1197,7 +1279,7 @@ var import_jsx_runtime17 = require("react/jsx-runtime");
1197
1279
  function DetailLayout({ side, children, className, ...props }) {
1198
1280
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: cx("uix-detail", className), ...props, children: [
1199
1281
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "uix-detail__main", children }),
1200
- side != null && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "uix-detail__side", children: side })
1282
+ side != null && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("aside", { className: "uix-detail__side", children: side })
1201
1283
  ] });
1202
1284
  }
1203
1285
 
@@ -1274,11 +1356,11 @@ function ListItem({ title, meta, trail, leading, children, className, ...props }
1274
1356
  }
1275
1357
 
1276
1358
  // src/components/DescriptionList.tsx
1277
- var import_react17 = require("react");
1359
+ var import_react19 = require("react");
1278
1360
  var import_jsx_runtime23 = require("react/jsx-runtime");
1279
1361
  function DescriptionList({ items, children, className, ...props }) {
1280
1362
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("dl", { className: cx("uix-dl", className), ...props, children: [
1281
- items?.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react17.Fragment, { children: [
1363
+ items?.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react19.Fragment, { children: [
1282
1364
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("dt", { children: item.term }),
1283
1365
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("dd", { children: item.description })
1284
1366
  ] }, item.id ?? i)),
@@ -1293,22 +1375,81 @@ function DescriptionItem({ term, children }) {
1293
1375
  }
1294
1376
 
1295
1377
  // src/components/Tabs.tsx
1296
- var import_react18 = require("react");
1378
+ var import_react20 = require("react");
1297
1379
  var import_jsx_runtime24 = require("react/jsx-runtime");
1298
- var TabsCtx = (0, import_react18.createContext)({});
1380
+ var TabsCtx = (0, import_react20.createContext)({});
1299
1381
  function Tabs({ variant = "line", value, onChange, children, className }) {
1300
- const contextValue = (0, import_react18.useMemo)(() => ({ value, onChange }), [value, onChange]);
1301
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TabsCtx.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { role: "tablist", className: cx("uix-tabs", `uix-tabs--${variant}`, className), children }) });
1382
+ const baseId = (0, import_react20.useId)();
1383
+ const listRef = (0, import_react20.useRef)(null);
1384
+ const contextValue = (0, import_react20.useMemo)(() => ({ value, onChange, baseId }), [value, onChange, baseId]);
1385
+ const kids = import_react20.Children.toArray(children);
1386
+ const panels = kids.filter((k) => (0, import_react20.isValidElement)(k) && k.type === TabPanel);
1387
+ const tabs = kids.filter((k) => !((0, import_react20.isValidElement)(k) && k.type === TabPanel));
1388
+ (0, import_react20.useEffect)(() => {
1389
+ const list = listRef.current;
1390
+ if (!list) return;
1391
+ const all = Array.from(list.querySelectorAll('[role="tab"]'));
1392
+ const enabled = all.filter((t) => !t.matches(":disabled"));
1393
+ const active = enabled.find((t) => t.getAttribute("aria-selected") === "true") ?? enabled[0];
1394
+ for (const t of all) t.tabIndex = t === active ? 0 : -1;
1395
+ });
1396
+ const onKeyDown = (e) => {
1397
+ const items = Array.from(
1398
+ listRef.current?.querySelectorAll('[role="tab"]:not(:disabled)') ?? []
1399
+ );
1400
+ const cur = e.target.closest('[role="tab"]');
1401
+ const idx = cur ? items.indexOf(cur) : -1;
1402
+ if (idx < 0 || items.length === 0) return;
1403
+ let next;
1404
+ switch (e.key) {
1405
+ case "ArrowRight":
1406
+ next = (idx + 1) % items.length;
1407
+ break;
1408
+ case "ArrowLeft":
1409
+ next = (idx - 1 + items.length) % items.length;
1410
+ break;
1411
+ case "Home":
1412
+ next = 0;
1413
+ break;
1414
+ case "End":
1415
+ next = items.length - 1;
1416
+ break;
1417
+ default:
1418
+ return;
1419
+ }
1420
+ e.preventDefault();
1421
+ const target = items[next];
1422
+ if (target) {
1423
+ target.focus();
1424
+ target.click();
1425
+ }
1426
+ };
1427
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(TabsCtx.Provider, { value: contextValue, children: [
1428
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1429
+ "div",
1430
+ {
1431
+ ref: listRef,
1432
+ role: "tablist",
1433
+ className: cx("uix-tabs", `uix-tabs--${variant}`, className),
1434
+ onKeyDown,
1435
+ children: tabs
1436
+ }
1437
+ ),
1438
+ panels
1439
+ ] });
1302
1440
  }
1303
1441
  function Tab({ value, children, disabled, className, onClick, ...props }) {
1304
- const ctx = (0, import_react18.useContext)(TabsCtx);
1442
+ const ctx = (0, import_react20.useContext)(TabsCtx);
1305
1443
  const selected = ctx.value === value;
1306
1444
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1307
1445
  "button",
1308
1446
  {
1309
1447
  role: "tab",
1448
+ id: ctx.baseId ? `${ctx.baseId}-tab-${value}` : void 0,
1449
+ "aria-controls": ctx.baseId ? `${ctx.baseId}-panel-${value}` : void 0,
1310
1450
  className: cx("uix-tab", className),
1311
1451
  "aria-selected": selected,
1452
+ tabIndex: selected ? 0 : -1,
1312
1453
  disabled,
1313
1454
  onClick: (e) => {
1314
1455
  ctx.onChange?.(value);
@@ -1319,9 +1460,24 @@ function Tab({ value, children, disabled, className, onClick, ...props }) {
1319
1460
  }
1320
1461
  );
1321
1462
  }
1463
+ function TabPanel({ value, children, ...props }) {
1464
+ const ctx = (0, import_react20.useContext)(TabsCtx);
1465
+ if (ctx.value !== value) return null;
1466
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1467
+ "div",
1468
+ {
1469
+ role: "tabpanel",
1470
+ id: ctx.baseId ? `${ctx.baseId}-panel-${value}` : void 0,
1471
+ "aria-labelledby": ctx.baseId ? `${ctx.baseId}-tab-${value}` : void 0,
1472
+ tabIndex: 0,
1473
+ ...props,
1474
+ children
1475
+ }
1476
+ );
1477
+ }
1322
1478
 
1323
1479
  // src/components/AppShell.tsx
1324
- var import_react19 = require("react");
1480
+ var import_react21 = require("react");
1325
1481
  var import_jsx_runtime25 = require("react/jsx-runtime");
1326
1482
  function AppShell({
1327
1483
  nav,
@@ -1329,6 +1485,7 @@ function AppShell({
1329
1485
  focus,
1330
1486
  onExitFocus,
1331
1487
  mainBleed,
1488
+ mainId = "uix-main",
1332
1489
  sidebar,
1333
1490
  topbar,
1334
1491
  children,
@@ -1336,7 +1493,7 @@ function AppShell({
1336
1493
  ...props
1337
1494
  }) {
1338
1495
  const navState = nav ?? (collapsed ? "rail" : "full");
1339
- (0, import_react19.useEffect)(() => {
1496
+ (0, import_react21.useEffect)(() => {
1340
1497
  if (!focus || !onExitFocus) return;
1341
1498
  const onKey = (e) => {
1342
1499
  if (e.key === "Escape") onExitFocus();
@@ -1353,9 +1510,10 @@ function AppShell({
1353
1510
  "data-focus": focus || void 0,
1354
1511
  ...props,
1355
1512
  children: [
1513
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("a", { className: "uix-skiplink", href: `#${mainId}`, children: "Skip to content" }),
1356
1514
  sidebar && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "uix-shell__sidebar", children: sidebar }),
1357
1515
  topbar && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "uix-shell__topbar", children: topbar }),
1358
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("main", { className: cx("uix-shell__main", mainBleed && "uix-shell__main--bleed"), children }),
1516
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("main", { id: mainId, tabIndex: -1, className: cx("uix-shell__main", mainBleed && "uix-shell__main--bleed"), children }),
1359
1517
  focus && onExitFocus && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "uix-shell__focus-exit", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", onClick: onExitFocus, children: "Esc \xB7 Exit focus" }) })
1360
1518
  ]
1361
1519
  }
@@ -1363,7 +1521,7 @@ function AppShell({
1363
1521
  }
1364
1522
 
1365
1523
  // src/components/Sidebar.tsx
1366
- var import_react20 = require("react");
1524
+ var import_react22 = require("react");
1367
1525
  var import_jsx_runtime26 = require("react/jsx-runtime");
1368
1526
  var ChevronIcon = () => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("svg", { className: "uix-navgroup__chevron", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("path", { d: "M2 4l4 4 4-4" }) });
1369
1527
  function Sidebar({ collapsed, nav, onToggle, brand, toggleIcon, children, expandLabel = "Expand sidebar", collapseLabel = "Collapse sidebar", className, ...props }) {
@@ -1419,12 +1577,12 @@ function NavItem({ icon, badge, active, as: Tag = "a", children, className, ...p
1419
1577
  );
1420
1578
  }
1421
1579
  function NavGroup({ icon, label, children, defaultExpanded = true, expanded: controlledExpanded, onExpandedChange }) {
1422
- const [internalExpanded, setInternalExpanded] = (0, import_react20.useState)(defaultExpanded);
1580
+ const [internalExpanded, setInternalExpanded] = (0, import_react22.useState)(defaultExpanded);
1423
1581
  const expanded = controlledExpanded ?? internalExpanded;
1424
- const panelId = (0, import_react20.useId)();
1425
- const triggerRef = (0, import_react20.useRef)(null);
1426
- const panelRef = (0, import_react20.useRef)(null);
1427
- (0, import_react20.useEffect)(() => {
1582
+ const panelId = (0, import_react22.useId)();
1583
+ const triggerRef = (0, import_react22.useRef)(null);
1584
+ const panelRef = (0, import_react22.useRef)(null);
1585
+ (0, import_react22.useEffect)(() => {
1428
1586
  panelRef.current?.toggleAttribute("inert", !expanded);
1429
1587
  if (!expanded && panelRef.current?.contains(document.activeElement)) triggerRef.current?.focus();
1430
1588
  }, [expanded]);
@@ -1503,7 +1661,7 @@ function StarButton({
1503
1661
  }
1504
1662
 
1505
1663
  // src/components/NavFavourites.tsx
1506
- var import_react21 = require("react");
1664
+ var import_react23 = require("react");
1507
1665
  var import_jsx_runtime28 = require("react/jsx-runtime");
1508
1666
  var ChevronDownIcon = () => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
1509
1667
  "svg",
@@ -1566,13 +1724,14 @@ function NavFavourites({
1566
1724
  emptyReason,
1567
1725
  className
1568
1726
  }) {
1569
- const regionId = (0, import_react21.useId)();
1570
- const headerRef = (0, import_react21.useRef)(null);
1571
- const regionRef = (0, import_react21.useRef)(null);
1572
- const focusAfterRef = (0, import_react21.useRef)(null);
1573
- const triggerRefs = (0, import_react21.useRef)(/* @__PURE__ */ new Map());
1574
- const order = (0, import_react21.useMemo)(() => items.map((item) => item.id), [items]);
1575
- (0, import_react21.useEffect)(() => {
1727
+ const regionId = (0, import_react23.useId)();
1728
+ const headerRef = (0, import_react23.useRef)(null);
1729
+ const regionRef = (0, import_react23.useRef)(null);
1730
+ const [announcement, setAnnouncement] = (0, import_react23.useState)("");
1731
+ const focusAfterRef = (0, import_react23.useRef)(null);
1732
+ const triggerRefs = (0, import_react23.useRef)(/* @__PURE__ */ new Map());
1733
+ const order = (0, import_react23.useMemo)(() => items.map((item) => item.id), [items]);
1734
+ (0, import_react23.useEffect)(() => {
1576
1735
  const id = focusAfterRef.current;
1577
1736
  if (!id) return;
1578
1737
  focusAfterRef.current = null;
@@ -1589,7 +1748,7 @@ function NavFavourites({
1589
1748
  }
1590
1749
  onToggleCollapsed?.();
1591
1750
  };
1592
- const move = (0, import_react21.useCallback)((id, dir) => {
1751
+ const move = (0, import_react23.useCallback)((id, dir) => {
1593
1752
  const idx = order.indexOf(id);
1594
1753
  const next = idx + dir;
1595
1754
  if (idx < 0 || next < 0 || next >= order.length) return;
@@ -1598,19 +1757,22 @@ function NavFavourites({
1598
1757
  if (it === void 0) return;
1599
1758
  reordered.splice(next, 0, it);
1600
1759
  focusAfterRef.current = id;
1760
+ const moved = items.find((i) => i.id === id);
1761
+ if (moved) setAnnouncement(`${moved.label} moved to position ${next + 1} of ${order.length}`);
1601
1762
  onReorder(reordered);
1602
1763
  }, [onReorder, order]);
1603
- const remove = (0, import_react21.useCallback)((id) => {
1764
+ const remove = (0, import_react23.useCallback)((id) => {
1604
1765
  const idx = order.indexOf(id);
1605
1766
  const neighbour = order[idx + 1] ?? order[idx - 1] ?? null;
1606
1767
  focusAfterRef.current = neighbour;
1607
1768
  onRemove(id);
1608
1769
  }, [onRemove, order]);
1609
- const registerTrigger = (0, import_react21.useCallback)((id, element) => {
1770
+ const registerTrigger = (0, import_react23.useCallback)((id, element) => {
1610
1771
  if (element) triggerRefs.current.set(id, element);
1611
1772
  else triggerRefs.current.delete(id);
1612
1773
  }, []);
1613
1774
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: cx("uix-favourites", className), children: [
1775
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { role: "status", className: "uix-visually-hidden", children: announcement }),
1614
1776
  /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
1615
1777
  "button",
1616
1778
  {
@@ -1657,7 +1819,7 @@ function NavFavourites({
1657
1819
  )
1658
1820
  ] });
1659
1821
  }
1660
- var FavouriteRow = (0, import_react21.memo)(function FavouriteRow2({
1822
+ var FavouriteRow = (0, import_react23.memo)(function FavouriteRow2({
1661
1823
  item,
1662
1824
  isFirst,
1663
1825
  isLast,
@@ -1666,17 +1828,17 @@ var FavouriteRow = (0, import_react21.memo)(function FavouriteRow2({
1666
1828
  onRemove,
1667
1829
  registerTrigger
1668
1830
  }) {
1669
- const [open, setOpen] = (0, import_react21.useState)(false);
1670
- const menuId = (0, import_react21.useId)();
1671
- const triggerRef = (0, import_react21.useRef)(null);
1672
- const itemRefs = (0, import_react21.useRef)([]);
1831
+ const [open, setOpen] = (0, import_react23.useState)(false);
1832
+ const menuId = (0, import_react23.useId)();
1833
+ const triggerRef = (0, import_react23.useRef)(null);
1834
+ const itemRefs = (0, import_react23.useRef)([]);
1673
1835
  const optionsTemplate = labels.options ?? "{label} favourite options";
1674
1836
  const actions = [
1675
1837
  ...isFirst ? [] : [{ label: labels.moveUp, onSelect: () => onMove(item.id, -1) }],
1676
1838
  ...isLast ? [] : [{ label: labels.moveDown, onSelect: () => onMove(item.id, 1) }],
1677
1839
  { label: labels.remove.replace("{label}", item.label), onSelect: () => onRemove(item.id) }
1678
1840
  ];
1679
- (0, import_react21.useEffect)(() => {
1841
+ (0, import_react23.useEffect)(() => {
1680
1842
  if (open) itemRefs.current[0]?.focus();
1681
1843
  }, [open]);
1682
1844
  const closeAndReturnFocus = () => {
@@ -1692,6 +1854,12 @@ var FavouriteRow = (0, import_react21.memo)(function FavouriteRow2({
1692
1854
  } else if (e.key === "ArrowUp") {
1693
1855
  e.preventDefault();
1694
1856
  menuItems[(currentIdx - 1 + menuItems.length) % menuItems.length]?.focus();
1857
+ } else if (e.key === "Home") {
1858
+ e.preventDefault();
1859
+ menuItems[0]?.focus();
1860
+ } else if (e.key === "End") {
1861
+ e.preventDefault();
1862
+ menuItems[menuItems.length - 1]?.focus();
1695
1863
  } else if (e.key === "Escape") {
1696
1864
  e.preventDefault();
1697
1865
  closeAndReturnFocus();
@@ -1750,6 +1918,7 @@ var FavouriteRow = (0, import_react21.memo)(function FavouriteRow2({
1750
1918
  {
1751
1919
  id: menuId,
1752
1920
  role: "menu",
1921
+ "aria-label": optionsTemplate.replace("{label}", item.label),
1753
1922
  onKeyDown: onMenuKeyDown,
1754
1923
  className: "uix-favourites__menu",
1755
1924
  children: actions.map((action, i) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("li", { role: "presentation", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
@@ -1781,61 +1950,108 @@ var FavouriteRow = (0, import_react21.memo)(function FavouriteRow2({
1781
1950
  // src/components/Alert.tsx
1782
1951
  var import_jsx_runtime29 = require("react/jsx-runtime");
1783
1952
  function Alert({ tone, title, icon, children, className, ...props }) {
1784
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: cx("uix-alert", tone && tone !== "neutral" && `uix-alert--${tone}`, className), ...props, children: [
1785
- icon && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "uix-alert__icon", children: icon }),
1786
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { children: [
1787
- title && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "uix-alert__title", children: title }),
1788
- children && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "uix-alert__body", children })
1789
- ] })
1790
- ] });
1953
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
1954
+ "div",
1955
+ {
1956
+ className: cx("uix-alert", tone && tone !== "neutral" && `uix-alert--${tone}`, className),
1957
+ role: tone === "danger" || tone === "warning" ? "alert" : "status",
1958
+ ...props,
1959
+ children: [
1960
+ icon && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "uix-alert__icon", children: icon }),
1961
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { children: [
1962
+ title && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "uix-alert__title", children: title }),
1963
+ children && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "uix-alert__body", children })
1964
+ ] })
1965
+ ]
1966
+ }
1967
+ );
1791
1968
  }
1792
1969
 
1793
1970
  // src/components/Spinner.tsx
1794
1971
  var import_jsx_runtime30 = require("react/jsx-runtime");
1795
- function Spinner({ size = "md", accent, className, ...props }) {
1972
+ function Spinner({ size = "md", accent, label, className, ...props }) {
1796
1973
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
1797
1974
  "span",
1798
1975
  {
1799
1976
  className: cx("uix-spinner", accent && "uix-spinner--accent", size === "lg" && "uix-spinner--lg", className),
1800
1977
  role: "status",
1801
- "aria-label": "Loading",
1802
- ...props
1978
+ ...props,
1979
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "uix-visually-hidden", children: label ?? "Loading\u2026" })
1803
1980
  }
1804
1981
  );
1805
1982
  }
1806
1983
 
1807
1984
  // src/components/Toast.tsx
1985
+ var import_react24 = require("react");
1808
1986
  var import_jsx_runtime31 = require("react/jsx-runtime");
1987
+ var ToasterContext = (0, import_react24.createContext)(null);
1809
1988
  function Toast({ title, message, tone, icon, onClose, leaving, className, ...props }) {
1810
1989
  const assertive = tone === "danger";
1990
+ const toaster = (0, import_react24.useContext)(ToasterContext);
1991
+ const bodyRef = (0, import_react24.useRef)(null);
1992
+ (0, import_react24.useEffect)(() => {
1993
+ if (assertive || !toaster) return;
1994
+ const text = bodyRef.current?.textContent?.trim();
1995
+ if (text) toaster.announce(text);
1996
+ }, []);
1997
+ const handleClose = (e) => {
1998
+ const btn = e.currentTarget;
1999
+ if (document.activeElement === btn) {
2000
+ const toasterEl = btn.closest(".uix-toaster");
2001
+ if (toasterEl) {
2002
+ const closes = Array.from(toasterEl.querySelectorAll(".uix-toast__close"));
2003
+ const i = closes.indexOf(btn);
2004
+ (closes[i + 1] ?? closes[i - 1])?.focus();
2005
+ }
2006
+ }
2007
+ onClose?.();
2008
+ };
2009
+ const ownLiveRegion = assertive || !toaster;
1811
2010
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
1812
2011
  "div",
1813
2012
  {
1814
2013
  className: cx("uix-toast", tone && `uix-toast--${tone}`, className),
1815
2014
  "data-leaving": leaving || void 0,
1816
- role: assertive ? "alert" : "status",
1817
- "aria-live": assertive ? "assertive" : "polite",
2015
+ role: ownLiveRegion ? assertive ? "alert" : "status" : void 0,
2016
+ "aria-live": ownLiveRegion ? assertive ? "assertive" : "polite" : void 0,
1818
2017
  ...props,
1819
2018
  children: [
1820
2019
  icon && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "uix-toast__icon", "aria-hidden": "true", children: icon }),
1821
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "uix-toast__body", children: [
2020
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "uix-toast__body", ref: bodyRef, children: [
1822
2021
  title && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "uix-toast__title", children: title }),
1823
2022
  message && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "uix-toast__msg", children: message })
1824
2023
  ] }),
1825
- onClose && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { className: "uix-toast__close", onClick: onClose, "aria-label": "Dismiss", children: "\xD7" })
2024
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { className: "uix-toast__close", onClick: handleClose, "aria-label": "Dismiss", children: "\xD7" })
1826
2025
  ]
1827
2026
  }
1828
2027
  );
1829
2028
  }
1830
2029
  function Toaster({ children, className, ...props }) {
1831
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cx("uix-toaster", className), ...props, children });
2030
+ const [announced, setAnnounced] = (0, import_react24.useState)("");
2031
+ const clearTimer = (0, import_react24.useRef)(null);
2032
+ const announce = (0, import_react24.useCallback)((text) => {
2033
+ setAnnounced((cur) => cur ? `${cur} ${text}` : text);
2034
+ if (clearTimer.current != null) clearTimeout(clearTimer.current);
2035
+ clearTimer.current = window.setTimeout(() => setAnnounced(""), 3e3);
2036
+ }, []);
2037
+ (0, import_react24.useEffect)(() => () => {
2038
+ if (clearTimer.current != null) clearTimeout(clearTimer.current);
2039
+ }, []);
2040
+ const ctx = (0, import_react24.useMemo)(() => ({ announce }), [announce]);
2041
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ToasterContext.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: cx("uix-toaster", className), role: "region", "aria-label": "Notifications", ...props, children: [
2042
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "uix-visually-hidden", role: "status", "aria-live": "polite", children: announced }),
2043
+ children
2044
+ ] }) });
1832
2045
  }
1833
2046
 
1834
2047
  // src/components/Table.tsx
1835
- var import_react22 = require("react");
2048
+ var import_react25 = require("react");
1836
2049
  var import_jsx_runtime32 = require("react/jsx-runtime");
1837
- var TableWrap = (0, import_react22.forwardRef)(function TableWrap2({ children, className, ...props }, ref) {
1838
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { ref, className: cx("uix-table-wrap", className), ...props, children });
2050
+ var TableWrap = (0, import_react25.forwardRef)(function TableWrap2({ announcement, children, className, ...props }, ref) {
2051
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { ref, className: cx("uix-table-wrap", className), ...props, children: [
2052
+ announcement != null && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { role: "status", className: "uix-visually-hidden", children: announcement }),
2053
+ children
2054
+ ] });
1839
2055
  });
1840
2056
  function Table({
1841
2057
  density = "standard",
@@ -1874,9 +2090,9 @@ function Th({ sortable, sortDirection, sortOrder, onSort, className, children, o
1874
2090
  "data-sort": sortable || void 0,
1875
2091
  "data-sort-order": sortOrder != null && sortOrder > 0 ? sortOrder : void 0,
1876
2092
  "aria-sort": sortDirection && sortDirection !== "none" ? sortDirection : void 0,
1877
- onClick: sortable ? onSort ?? onClick : onClick,
2093
+ onClick: sortable && onSort ? void 0 : onClick,
1878
2094
  ...props,
1879
- children
2095
+ children: sortable ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "button", className: "uix-th__sortbtn", onClick: onSort, children }) : children
1880
2096
  }
1881
2097
  );
1882
2098
  }
@@ -1888,7 +2104,7 @@ function Tr({ selected, pinned, className, children, ...props }) {
1888
2104
  "tr",
1889
2105
  {
1890
2106
  className,
1891
- "aria-selected": selected || void 0,
2107
+ "data-selected": selected || void 0,
1892
2108
  "data-pinned": pinned || void 0,
1893
2109
  ...props,
1894
2110
  children
@@ -1911,13 +2127,14 @@ function RowActions({ children, className, ...props }) {
1911
2127
  function RowAction({ children, className, type = "button", ...props }) {
1912
2128
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type, className: cx("uix-rowact", className), ...props, children });
1913
2129
  }
1914
- function ExpandToggle({ expanded, className, type = "button", ...props }) {
2130
+ function ExpandToggle({ expanded, controls, className, type = "button", ...props }) {
1915
2131
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
1916
2132
  "button",
1917
2133
  {
1918
2134
  type,
1919
2135
  className: cx("uix-table__expand", className),
1920
2136
  "aria-expanded": expanded,
2137
+ "aria-controls": controls,
1921
2138
  "aria-label": expanded ? "Collapse row" : "Expand row",
1922
2139
  ...props,
1923
2140
  children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { d: "M6 4l4 4-4 4" }) })
@@ -2008,15 +2225,17 @@ function StatusPill({ tone = "neutral", treatment = "filled", dot, children, cla
2008
2225
 
2009
2226
  // src/components/Progress.tsx
2010
2227
  var import_jsx_runtime35 = require("react/jsx-runtime");
2011
- function Progress({ value = 0, max = 100, indeterminate, className, ...props }) {
2012
- const pct = Math.max(0, Math.min(100, value / (max || 100) * 100));
2228
+ function Progress({ value = 0, max = 100, indeterminate, label, className, ...props }) {
2229
+ const clamped = Math.max(0, Math.min(max || 100, value));
2230
+ const pct = clamped / (max || 100) * 100;
2013
2231
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
2014
2232
  "div",
2015
2233
  {
2016
2234
  role: "progressbar",
2017
2235
  "aria-valuemin": 0,
2018
2236
  "aria-valuemax": max,
2019
- "aria-valuenow": indeterminate ? void 0 : value,
2237
+ "aria-valuenow": indeterminate ? void 0 : clamped,
2238
+ "aria-label": label,
2020
2239
  className: cx("uix-progress", indeterminate && "uix-progress--indeterminate", className),
2021
2240
  ...props,
2022
2241
  children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "uix-progress__bar", style: indeterminate ? void 0 : { width: `${pct}%` } })
@@ -2026,7 +2245,13 @@ function Progress({ value = 0, max = 100, indeterminate, className, ...props })
2026
2245
 
2027
2246
  // src/components/Meter.tsx
2028
2247
  var import_jsx_runtime36 = require("react/jsx-runtime");
2029
- function Meter({ value = 0, tone, className, ...props }) {
2248
+ var toneText = {
2249
+ warning: "warning",
2250
+ danger: "critical",
2251
+ attention: "needs attention",
2252
+ overdue: "overdue"
2253
+ };
2254
+ function Meter({ value = 0, tone, label, className, ...props }) {
2030
2255
  const pct = Math.max(0, Math.min(100, value));
2031
2256
  return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
2032
2257
  "div",
@@ -2035,6 +2260,8 @@ function Meter({ value = 0, tone, className, ...props }) {
2035
2260
  "aria-valuenow": pct,
2036
2261
  "aria-valuemin": 0,
2037
2262
  "aria-valuemax": 100,
2263
+ "aria-valuetext": tone && tone !== "success" ? `${pct}%, ${toneText[tone]}` : void 0,
2264
+ "aria-label": label,
2038
2265
  className: cx("uix-meter", className),
2039
2266
  ...props,
2040
2267
  children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
@@ -2059,22 +2286,34 @@ function Stat({ label, value, icon, meta, trend, className, ...props }) {
2059
2286
  ] }),
2060
2287
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "uix-stat__value", children: value }),
2061
2288
  (meta != null || trend != null) && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "uix-stat__meta", children: [
2062
- trend != null && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: cx("uix-stat__trend", `uix-stat__trend--${trend.direction}`), children: trend.label }),
2289
+ trend != null && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: cx("uix-stat__trend", `uix-stat__trend--${trend.direction}`), children: [
2290
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: trend.direction === "up" ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("path", { d: "M12 19V5m-6 6 6-6 6 6" }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("path", { d: "M12 5v14m6-6-6 6-6-6" }) }),
2291
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "uix-visually-hidden", children: trend.direction === "up" ? "up" : "down" }),
2292
+ trend.label
2293
+ ] }),
2063
2294
  meta
2064
2295
  ] })
2065
2296
  ] });
2066
2297
  }
2067
2298
 
2068
2299
  // src/components/Tooltip.tsx
2069
- var import_react23 = require("react");
2300
+ var import_react26 = require("react");
2070
2301
  var import_jsx_runtime38 = require("react/jsx-runtime");
2071
2302
  function Tooltip({ label, placement = "top", className, children, ...props }) {
2072
- const triggerRef = (0, import_react23.useRef)(null);
2073
- const bubbleRef = (0, import_react23.useRef)(null);
2074
- const [open, setOpen] = (0, import_react23.useState)(false);
2075
- const id = (0, import_react23.useId)();
2303
+ const triggerRef = (0, import_react26.useRef)(null);
2304
+ const bubbleRef = (0, import_react26.useRef)(null);
2305
+ const closeTimer = (0, import_react26.useRef)(null);
2306
+ const [open, setOpen] = (0, import_react26.useState)(false);
2307
+ const id = (0, import_react26.useId)();
2076
2308
  useAnchoredPosition(triggerRef, bubbleRef, { open, placement, offset: 6 });
2309
+ const cancelClose = () => {
2310
+ if (closeTimer.current != null) {
2311
+ clearTimeout(closeTimer.current);
2312
+ closeTimer.current = null;
2313
+ }
2314
+ };
2077
2315
  const show = () => {
2316
+ cancelClose();
2078
2317
  const b = bubbleRef.current;
2079
2318
  if (b && !b.matches(":popover-open")) {
2080
2319
  try {
@@ -2085,6 +2324,7 @@ function Tooltip({ label, placement = "top", className, children, ...props }) {
2085
2324
  setOpen(true);
2086
2325
  };
2087
2326
  const hide = () => {
2327
+ cancelClose();
2088
2328
  const b = bubbleRef.current;
2089
2329
  if (b && b.matches(":popover-open")) {
2090
2330
  try {
@@ -2094,7 +2334,20 @@ function Tooltip({ label, placement = "top", className, children, ...props }) {
2094
2334
  }
2095
2335
  setOpen(false);
2096
2336
  };
2097
- (0, import_react23.useEffect)(() => () => {
2337
+ const scheduleHide = () => {
2338
+ cancelClose();
2339
+ closeTimer.current = window.setTimeout(hide, 100);
2340
+ };
2341
+ (0, import_react26.useEffect)(() => {
2342
+ if (!open) return;
2343
+ const onKey = (e) => {
2344
+ if (e.key === "Escape") hide();
2345
+ };
2346
+ document.addEventListener("keydown", onKey);
2347
+ return () => document.removeEventListener("keydown", onKey);
2348
+ }, [open]);
2349
+ (0, import_react26.useEffect)(() => () => {
2350
+ if (closeTimer.current != null) clearTimeout(closeTimer.current);
2098
2351
  const b = bubbleRef.current;
2099
2352
  if (b && b.matches(":popover-open")) {
2100
2353
  try {
@@ -2104,14 +2357,19 @@ function Tooltip({ label, placement = "top", className, children, ...props }) {
2104
2357
  }
2105
2358
  }, []);
2106
2359
  const bubbleAttr = { popover: "manual" };
2360
+ const single = (0, import_react26.isValidElement)(children);
2361
+ const child = single ? (0, import_react26.cloneElement)(children, {
2362
+ "aria-describedby": [children.props["aria-describedby"], id].filter(Boolean).join(" ")
2363
+ }) : children;
2107
2364
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
2108
2365
  "span",
2109
2366
  {
2110
2367
  ref: triggerRef,
2111
2368
  className: cx("uix-tooltip", className),
2112
- "aria-describedby": id,
2369
+ "aria-describedby": single ? void 0 : id,
2370
+ tabIndex: single ? void 0 : 0,
2113
2371
  onMouseEnter: show,
2114
- onMouseLeave: hide,
2372
+ onMouseLeave: scheduleHide,
2115
2373
  onFocus: show,
2116
2374
  onBlur: hide,
2117
2375
  onKeyDown: (e) => {
@@ -2119,8 +2377,20 @@ function Tooltip({ label, placement = "top", className, children, ...props }) {
2119
2377
  },
2120
2378
  ...props,
2121
2379
  children: [
2122
- children,
2123
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { ref: bubbleRef, id, role: "tooltip", className: "uix-tooltip__bubble", ...bubbleAttr, children: label })
2380
+ child,
2381
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
2382
+ "span",
2383
+ {
2384
+ ref: bubbleRef,
2385
+ id,
2386
+ role: "tooltip",
2387
+ className: "uix-tooltip__bubble",
2388
+ onMouseEnter: cancelClose,
2389
+ onMouseLeave: scheduleHide,
2390
+ ...bubbleAttr,
2391
+ children: label
2392
+ }
2393
+ )
2124
2394
  ]
2125
2395
  }
2126
2396
  );
@@ -2180,11 +2450,17 @@ function Skeleton({ variant = "block", width, height, className, style, ...props
2180
2450
  );
2181
2451
  }
2182
2452
  function LoadingState({ rows = 3, density = "comfortable", label, className, ...props }) {
2183
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: cx("uix-stack", density === "compact" && "uix-stack--compact", className), role: "status", "aria-busy": "true", "aria-label": label, ...props, children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Skeleton, { variant: "text", width: `${92 - i % 3 * 14}%` }, i)) });
2453
+ return (
2454
+ // no aria-busy: busy=true tells AT the region isn't ready and suppresses the announcement (UIX-A11Y-4)
2455
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: cx("uix-stack", density === "compact" && "uix-stack--compact", className), role: "status", ...props, children: [
2456
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "uix-visually-hidden", children: label ?? "Loading" }),
2457
+ Array.from({ length: rows }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Skeleton, { variant: "text", width: `${92 - i % 3 * 14}%` }, i))
2458
+ ] })
2459
+ );
2184
2460
  }
2185
2461
 
2186
2462
  // src/components/RelativeTime.tsx
2187
- var import_react24 = require("react");
2463
+ var import_react27 = require("react");
2188
2464
 
2189
2465
  // src/relative-time-model.ts
2190
2466
  function parseDateValue(value) {
@@ -2247,12 +2523,12 @@ function RelativeTime({
2247
2523
  }) {
2248
2524
  const interval = refreshInterval === false ? 0 : Math.max(0, refreshInterval);
2249
2525
  const fixedNow = now == null ? void 0 : new Date(now).getTime();
2250
- const subscribe = (0, import_react24.useCallback)((listener) => fixedNow == null ? subscribeRelativeClock(interval, listener) : () => {
2526
+ const subscribe = (0, import_react27.useCallback)((listener) => fixedNow == null ? subscribeRelativeClock(interval, listener) : () => {
2251
2527
  }, [fixedNow, interval]);
2252
- const getSnapshot = (0, import_react24.useCallback)(() => fixedNow ?? readRelativeClock(interval), [fixedNow, interval]);
2253
- const getServerSnapshot = (0, import_react24.useCallback)(() => fixedNow ?? Date.now(), [fixedNow]);
2254
- const clock = (0, import_react24.useSyncExternalStore)(subscribe, getSnapshot, getServerSnapshot);
2255
- const date = (0, import_react24.useMemo)(() => parseDateValue(value), [value]);
2528
+ const getSnapshot = (0, import_react27.useCallback)(() => fixedNow ?? readRelativeClock(interval), [fixedNow, interval]);
2529
+ const getServerSnapshot = (0, import_react27.useCallback)(() => fixedNow ?? Date.now(), [fixedNow]);
2530
+ const clock = (0, import_react27.useSyncExternalStore)(subscribe, getSnapshot, getServerSnapshot);
2531
+ const date = (0, import_react27.useMemo)(() => parseDateValue(value), [value]);
2256
2532
  if (!date) return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("time", { "data-invalid": "true", suppressHydrationWarning: true, ...props, children: invalidLabel });
2257
2533
  const current = new Date(clock);
2258
2534
  const content = formatter ? formatter({ date, now: current, locale, timeZone }) : (() => {
@@ -2301,7 +2577,8 @@ var import_jsx_runtime43 = require("react/jsx-runtime");
2301
2577
  function Avatar({ size = "md", src, alt, children, status, className, ...props }) {
2302
2578
  return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: cx("uix-avatar", size !== "md" && `uix-avatar--${size}`, className), ...props, children: [
2303
2579
  src ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("img", { src, alt: alt ?? "" }) : children,
2304
- status && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "uix-avatar__status" })
2580
+ status && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "uix-avatar__status", "aria-hidden": "true" }),
2581
+ status && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "uix-visually-hidden", children: "online" })
2305
2582
  ] });
2306
2583
  }
2307
2584
  function AvatarGroup({ children, className, ...props }) {
@@ -2321,7 +2598,7 @@ function UserChip({ avatar, name, sub, className, children, ...props }) {
2321
2598
  // src/components/Comments.tsx
2322
2599
  var import_jsx_runtime44 = require("react/jsx-runtime");
2323
2600
  function Comments({ children, className, ...props }) {
2324
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: cx("uix-comments", className), ...props, children });
2601
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { role: "log", className: cx("uix-comments", className), ...props, children });
2325
2602
  }
2326
2603
  function Comment({ avatar, author, meta, children, className, ...props }) {
2327
2604
  return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: cx("uix-comment", className), ...props, children: [
@@ -2338,20 +2615,25 @@ function Comment({ avatar, author, meta, children, className, ...props }) {
2338
2615
  }
2339
2616
 
2340
2617
  // src/components/Composer.tsx
2618
+ var import_react28 = require("react");
2341
2619
  var import_jsx_runtime45 = require("react/jsx-runtime");
2342
- function Composer({ children, className, ...props }) {
2343
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: cx("uix-composer", className), ...props, children });
2620
+ function Composer({ children, className, label = "Add a comment", ...props }) {
2621
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: cx("uix-composer", className), ...props, children: import_react28.Children.map(children, (child) => {
2622
+ if (!(0, import_react28.isValidElement)(child) || child.type !== "textarea") return child;
2623
+ const p = child.props;
2624
+ return p["aria-label"] || p["aria-labelledby"] || p.id ? child : (0, import_react28.cloneElement)(child, { "aria-label": label });
2625
+ }) });
2344
2626
  }
2345
2627
  function ComposerBar({ children, className, ...props }) {
2346
2628
  return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: cx("uix-composer__bar", className), ...props, children });
2347
2629
  }
2348
2630
 
2349
2631
  // src/components/Segmented.tsx
2350
- var import_react25 = require("react");
2632
+ var import_react29 = require("react");
2351
2633
  var import_jsx_runtime46 = require("react/jsx-runtime");
2352
- var SegmentedCtx = (0, import_react25.createContext)({});
2634
+ var SegmentedCtx = (0, import_react29.createContext)({});
2353
2635
  function Segmented({ value, onChange, children, className, ...props }) {
2354
- const contextValue = (0, import_react25.useMemo)(() => ({ value, onChange }), [value, onChange]);
2636
+ const contextValue = (0, import_react29.useMemo)(() => ({ value, onChange }), [value, onChange]);
2355
2637
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(SegmentedCtx.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { role: "group", className: cx("uix-segmented", className), ...props, children }) });
2356
2638
  }
2357
2639
  function SegmentedOption({
@@ -2361,7 +2643,7 @@ function SegmentedOption({
2361
2643
  onClick,
2362
2644
  ...props
2363
2645
  }) {
2364
- const ctx = (0, import_react25.useContext)(SegmentedCtx);
2646
+ const ctx = (0, import_react29.useContext)(SegmentedCtx);
2365
2647
  const selected = ctx.value === value;
2366
2648
  return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
2367
2649
  "button",
@@ -2380,12 +2662,12 @@ function SegmentedOption({
2380
2662
  }
2381
2663
 
2382
2664
  // src/components/TableControls.tsx
2383
- var import_react26 = require("react");
2665
+ var import_react30 = require("react");
2384
2666
  var import_jsx_runtime47 = require("react/jsx-runtime");
2385
2667
  function ViewMenu({ density, densityLabel, densityOptions, onDensityChange, zebra, freeze, columns, columnsLabel, onColumnVisibilityChange }) {
2386
- const densityLabelId = (0, import_react26.useId)();
2387
- const zebraLabelId = (0, import_react26.useId)();
2388
- const freezeLabelId = (0, import_react26.useId)();
2668
+ const densityLabelId = (0, import_react30.useId)();
2669
+ const zebraLabelId = (0, import_react30.useId)();
2670
+ const freezeLabelId = (0, import_react30.useId)();
2389
2671
  return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "uix-view-menu", children: [
2390
2672
  /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "uix-view-menu__group", children: [
2391
2673
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { id: densityLabelId, className: "uix-view-menu__label", children: densityLabel }),
@@ -2434,11 +2716,11 @@ function SavedViewMenu({ items, onSelect, onPinChange, pinLabel, unpinLabel, emp
2434
2716
  // src/components/Timeline.tsx
2435
2717
  var import_jsx_runtime48 = require("react/jsx-runtime");
2436
2718
  function Timeline({ children, className, ...props }) {
2437
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: cx("uix-timeline", className), ...props, children });
2719
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("ol", { className: cx("uix-timeline", className), ...props, children });
2438
2720
  }
2439
2721
  function TimelineItem({ node, meta, children, className, ...props }) {
2440
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: cx("uix-timeline__item", className), ...props, children: [
2441
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "uix-timeline__rail", children: [
2722
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("li", { className: cx("uix-timeline__item", className), ...props, children: [
2723
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "uix-timeline__rail", "aria-hidden": "true", children: [
2442
2724
  node ?? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "uix-timeline__node" }),
2443
2725
  /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "uix-timeline__line" })
2444
2726
  ] }),
@@ -2449,21 +2731,128 @@ function TimelineItem({ node, meta, children, className, ...props }) {
2449
2731
  ] });
2450
2732
  }
2451
2733
 
2452
- // src/components/Prose.tsx
2734
+ // src/components/Pipeline.tsx
2735
+ var import_react31 = require("react");
2453
2736
  var import_jsx_runtime49 = require("react/jsx-runtime");
2737
+ function Pipeline({ detailed = false, children, className, tabIndex, ...props }) {
2738
+ const stages = detailed ? import_react31.Children.map(children, (child) => (0, import_react31.isValidElement)(child) && child.type === PipelineStage ? (0, import_react31.cloneElement)(child, { detailed: child.props.detailed ?? true }) : child) : children;
2739
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
2740
+ "ol",
2741
+ {
2742
+ className: cx("uix-pipeline", detailed && "uix-pipeline--detailed", className),
2743
+ tabIndex: tabIndex ?? (detailed ? 0 : void 0),
2744
+ ...props,
2745
+ children: stages
2746
+ }
2747
+ );
2748
+ }
2749
+ var DEFAULT_STATE_LABELS = {
2750
+ pending: "Pending",
2751
+ waiting: "Waiting",
2752
+ active: "Active",
2753
+ current: "Current",
2754
+ running: "Running",
2755
+ done: "Done",
2756
+ complete: "Complete",
2757
+ blocked: "Blocked",
2758
+ failed: "Failed",
2759
+ error: "Error"
2760
+ };
2761
+ function PipelineStage({
2762
+ label,
2763
+ state = "pending",
2764
+ stateLabel: stateLabel2,
2765
+ description,
2766
+ meta,
2767
+ marker,
2768
+ detailed = false,
2769
+ current: currentProp,
2770
+ className,
2771
+ ...props
2772
+ }) {
2773
+ const current = currentProp ?? (state === "active" || state === "current" || state === "running");
2774
+ const resolvedStateLabel = stateLabel2 ?? DEFAULT_STATE_LABELS[state];
2775
+ const showDetails = detailed || description != null || meta != null || marker != null;
2776
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
2777
+ "li",
2778
+ {
2779
+ className: cx("uix-pipeline__stage", className),
2780
+ "data-state": state,
2781
+ "aria-current": current ? "step" : void 0,
2782
+ ...props,
2783
+ children: showDetails ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
2784
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "uix-pipeline__marker", "aria-hidden": "true", children: marker }),
2785
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "uix-pipeline__content", children: [
2786
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "uix-pipeline__eyebrow", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "uix-pipeline__state", children: resolvedStateLabel }) }),
2787
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "uix-pipeline__title", children: label }),
2788
+ description != null && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "uix-pipeline__description", children: description }),
2789
+ meta != null && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "uix-pipeline__meta", children: meta })
2790
+ ] })
2791
+ ] }) : label
2792
+ }
2793
+ );
2794
+ }
2795
+
2796
+ // src/components/Flow.tsx
2797
+ var import_jsx_runtime50 = require("react/jsx-runtime");
2798
+ function Flow({ variant = "linear", panel = false, children, className, role = "group", ...props }) {
2799
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
2800
+ "div",
2801
+ {
2802
+ className: cx("uix-flow", `uix-flow--${variant}`, panel && "uix-flow--panel", className),
2803
+ role,
2804
+ ...props,
2805
+ children
2806
+ }
2807
+ );
2808
+ }
2809
+ var FLOW_STATE_LABELS = {
2810
+ pending: "Pending",
2811
+ active: "Active",
2812
+ running: "Running",
2813
+ done: "Done",
2814
+ error: "Error"
2815
+ };
2816
+ function FlowNode({
2817
+ title,
2818
+ state = "pending",
2819
+ stateLabel: stateLabel2,
2820
+ eyebrow,
2821
+ meta,
2822
+ icon,
2823
+ footer,
2824
+ wide = false,
2825
+ className,
2826
+ ...props
2827
+ }) {
2828
+ const resolvedStateLabel = stateLabel2 ?? FLOW_STATE_LABELS[state];
2829
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: cx("uix-node", `uix-node--${state}`, icon == null && "uix-node--no-icon", wide && "uix-node--wide", className), ...props, children: [
2830
+ icon != null && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "uix-node__icon", "aria-hidden": "true", children: icon }),
2831
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "uix-node__body", children: [
2832
+ eyebrow != null && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uix-node__eyebrow", children: eyebrow }),
2833
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uix-node__title", children: title }),
2834
+ meta != null && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uix-node__meta", children: meta }),
2835
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uix-node__status", children: resolvedStateLabel })
2836
+ ] }),
2837
+ footer != null && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uix-node__footer", children: footer })
2838
+ ] });
2839
+ }
2840
+
2841
+ // src/components/Prose.tsx
2842
+ var import_jsx_runtime51 = require("react/jsx-runtime");
2454
2843
  function Prose({ children, className, ...props }) {
2455
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: cx("uix-prose", className), ...props, children });
2844
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: cx("uix-prose", className), ...props, children });
2456
2845
  }
2457
2846
  function Note({ tone, icon, children, className, ...props }) {
2458
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: cx("uix-note", tone && `uix-note--${tone}`, className), ...props, children: [
2459
- icon != null && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "uix-note__icon", children: icon }),
2460
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "uix-note__body", children })
2847
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: cx("uix-note", tone && `uix-note--${tone}`, className), ...props, children: [
2848
+ icon != null && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "uix-note__icon", children: icon }),
2849
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "uix-note__body", children })
2461
2850
  ] });
2462
2851
  }
2463
2852
 
2464
2853
  // src/components/Popover.tsx
2465
- var import_react27 = require("react");
2466
- var import_jsx_runtime50 = require("react/jsx-runtime");
2854
+ var import_react32 = require("react");
2855
+ var import_jsx_runtime52 = require("react/jsx-runtime");
2467
2856
  function Popover({
2468
2857
  popover = "auto",
2469
2858
  anchor,
@@ -2473,15 +2862,15 @@ function Popover({
2473
2862
  children,
2474
2863
  ...props
2475
2864
  }) {
2476
- const ref = (0, import_react27.useRef)(null);
2477
- const [open, setOpen] = (0, import_react27.useState)(false);
2865
+ const ref = (0, import_react32.useRef)(null);
2866
+ const [open, setOpen] = (0, import_react32.useState)(false);
2478
2867
  const popoverAttr = { popover };
2479
2868
  const reposition = useAnchoredPosition(anchor ?? null, ref, {
2480
2869
  open: open && !!anchor,
2481
2870
  placement,
2482
2871
  offset
2483
2872
  });
2484
- (0, import_react27.useEffect)(() => {
2873
+ (0, import_react32.useEffect)(() => {
2485
2874
  const el = ref.current;
2486
2875
  if (!el || !anchor) return;
2487
2876
  const sync = () => {
@@ -2492,38 +2881,142 @@ function Popover({
2492
2881
  el.addEventListener("toggle", sync);
2493
2882
  return () => el.removeEventListener("toggle", sync);
2494
2883
  }, [anchor, reposition]);
2495
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { ref, className: cx("uix-popover", className), ...popoverAttr, ...props, children });
2884
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { ref, className: cx("uix-popover", className), ...popoverAttr, ...props, children });
2496
2885
  }
2497
2886
 
2498
2887
  // src/components/CommandPalette.tsx
2499
- var import_jsx_runtime51 = require("react/jsx-runtime");
2888
+ var import_react33 = require("react");
2889
+ var import_jsx_runtime53 = require("react/jsx-runtime");
2890
+ var CmdkContext = (0, import_react33.createContext)(null);
2500
2891
  function CommandPalette({ inputProps, children, className, ...props }) {
2501
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: cx("uix-cmdk", className), ...props, children: [
2502
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("input", { className: "uix-cmdk__input", ...inputProps }),
2503
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "uix-cmdk__list", children })
2504
- ] });
2892
+ const listId = (0, import_react33.useId)();
2893
+ const [activeId, setActiveId] = (0, import_react33.useState)(null);
2894
+ const [count, setCount] = (0, import_react33.useState)(0);
2895
+ const [announced, setAnnounced] = (0, import_react33.useState)("");
2896
+ const setActive = (0, import_react33.useCallback)((id, active) => {
2897
+ setActiveId((cur) => active ? id : cur === id ? null : cur);
2898
+ }, []);
2899
+ const registerItem = (0, import_react33.useCallback)(() => {
2900
+ setCount((c) => c + 1);
2901
+ return () => setCount((c) => c - 1);
2902
+ }, []);
2903
+ (0, import_react33.useEffect)(() => {
2904
+ const t = window.setTimeout(() => setAnnounced(`${count} result${count === 1 ? "" : "s"}`), 150);
2905
+ return () => clearTimeout(t);
2906
+ }, [count]);
2907
+ const ctx = (0, import_react33.useMemo)(() => ({ listId, setActive, registerItem }), [listId, setActive, registerItem]);
2908
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(CmdkContext.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: cx("uix-cmdk", className), ...props, children: [
2909
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
2910
+ "input",
2911
+ {
2912
+ className: "uix-cmdk__input",
2913
+ role: "combobox",
2914
+ "aria-expanded": "true",
2915
+ "aria-autocomplete": "list",
2916
+ "aria-controls": listId,
2917
+ "aria-activedescendant": activeId ?? void 0,
2918
+ "aria-label": "Command palette",
2919
+ ...inputProps
2920
+ }
2921
+ ),
2922
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "uix-cmdk__list", role: "listbox", id: listId, children }),
2923
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "uix-visually-hidden", role: "status", children: announced })
2924
+ ] }) });
2505
2925
  }
2506
2926
  function CommandGroup({ label, children }) {
2507
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
2508
- label != null && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "uix-cmdk__group", children: label }),
2927
+ const labelId = (0, import_react33.useId)();
2928
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { role: "group", "aria-labelledby": label != null ? labelId : void 0, children: [
2929
+ label != null && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "uix-cmdk__group", id: labelId, children: label }),
2509
2930
  children
2510
2931
  ] });
2511
2932
  }
2512
- function CommandItem({ icon, shortcut, active, children, className, ...props }) {
2513
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: cx("uix-cmdk__item", className), "data-active": active || void 0, ...props, children: [
2514
- icon,
2515
- /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { children }),
2516
- shortcut
2517
- ] });
2933
+ function CommandItem({ icon, shortcut, active, children, className, id, ...props }) {
2934
+ const ctx = (0, import_react33.useContext)(CmdkContext);
2935
+ const autoId = (0, import_react33.useId)();
2936
+ const itemId = id ?? autoId;
2937
+ (0, import_react33.useEffect)(() => ctx?.registerItem(), [ctx]);
2938
+ (0, import_react33.useEffect)(() => {
2939
+ if (!ctx || !active) return;
2940
+ ctx.setActive(itemId, true);
2941
+ return () => ctx.setActive(itemId, false);
2942
+ }, [ctx, itemId, active]);
2943
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
2944
+ "div",
2945
+ {
2946
+ className: cx("uix-cmdk__item", className),
2947
+ "data-active": active || void 0,
2948
+ id: itemId,
2949
+ role: "option",
2950
+ "aria-selected": !!active,
2951
+ ...props,
2952
+ children: [
2953
+ icon,
2954
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { children }),
2955
+ shortcut
2956
+ ]
2957
+ }
2958
+ );
2518
2959
  }
2519
2960
 
2520
2961
  // src/components/Inbox.tsx
2521
- var import_jsx_runtime52 = require("react/jsx-runtime");
2522
- function Inbox({ children, className, ...props }) {
2523
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: cx("uix-inbox", className), ...props, children });
2962
+ var import_react34 = require("react");
2963
+ var import_jsx_runtime54 = require("react/jsx-runtime");
2964
+ function Inbox({ view, children, className, ...props }) {
2965
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: cx("uix-inbox", className), "data-view": view, ...props, children });
2524
2966
  }
2967
+ var InboxListCtx = (0, import_react34.createContext)({});
2525
2968
  function InboxList({ children, className, ...props }) {
2526
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: cx("uix-inbox__list", className), role: "listbox", ...props, children });
2969
+ const listRef = (0, import_react34.useRef)(null);
2970
+ const [activeId, setActiveId] = (0, import_react34.useState)(void 0);
2971
+ const ctx = (0, import_react34.useMemo)(() => ({ activeId }), [activeId]);
2972
+ const onKeyDown = (e) => {
2973
+ const opts = Array.from(listRef.current?.querySelectorAll('[role="option"]') ?? []);
2974
+ if (opts.length === 0) return;
2975
+ const idx = opts.findIndex((el2) => el2.id === activeId);
2976
+ let next;
2977
+ switch (e.key) {
2978
+ case "ArrowDown":
2979
+ next = Math.min(idx + 1, opts.length - 1);
2980
+ break;
2981
+ case "ArrowUp":
2982
+ next = idx < 0 ? 0 : Math.max(idx - 1, 0);
2983
+ break;
2984
+ case "Home":
2985
+ next = 0;
2986
+ break;
2987
+ case "End":
2988
+ next = opts.length - 1;
2989
+ break;
2990
+ case "Enter":
2991
+ case " ":
2992
+ if (idx >= 0) {
2993
+ e.preventDefault();
2994
+ opts[idx]?.click();
2995
+ }
2996
+ return;
2997
+ default:
2998
+ return;
2999
+ }
3000
+ e.preventDefault();
3001
+ const el = opts[next];
3002
+ if (!el || !el.id) return;
3003
+ setActiveId(el.id);
3004
+ el.scrollIntoView({ block: "nearest" });
3005
+ };
3006
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(InboxListCtx.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
3007
+ "div",
3008
+ {
3009
+ ref: listRef,
3010
+ className: cx("uix-inbox__list", className),
3011
+ role: "listbox",
3012
+ tabIndex: 0,
3013
+ "aria-label": "Inbox",
3014
+ "aria-activedescendant": activeId,
3015
+ onKeyDown,
3016
+ ...props,
3017
+ children
3018
+ }
3019
+ ) });
2527
3020
  }
2528
3021
  function InboxItem({
2529
3022
  subject,
@@ -2533,53 +3026,90 @@ function InboxItem({
2533
3026
  selected,
2534
3027
  children,
2535
3028
  className,
3029
+ id,
2536
3030
  ...props
2537
3031
  }) {
2538
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
3032
+ const autoId = (0, import_react34.useId)();
3033
+ const itemId = id ?? autoId;
3034
+ const { activeId } = (0, import_react34.useContext)(InboxListCtx);
3035
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
2539
3036
  "div",
2540
3037
  {
2541
3038
  role: "option",
3039
+ id: itemId,
2542
3040
  "aria-selected": selected ?? false,
3041
+ "data-active": activeId === itemId ? "" : void 0,
2543
3042
  className: cx("uix-inbox__item", className),
2544
3043
  ...unread ? { "data-unread": "" } : {},
2545
3044
  ...props,
2546
3045
  children: [
2547
3046
  leading,
2548
- subject != null && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "uix-inbox__subject", children: subject }),
2549
- preview != null && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "uix-inbox__preview", children: preview }),
3047
+ subject != null && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "uix-inbox__subject", children: subject }),
3048
+ preview != null && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "uix-inbox__preview", children: preview }),
2550
3049
  children
2551
3050
  ]
2552
3051
  }
2553
3052
  );
2554
3053
  }
2555
3054
  function InboxDetail({ children, className, ...props }) {
2556
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: cx("uix-inbox__detail", className), ...props, children });
3055
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: cx("uix-inbox__detail", className), ...props, children });
2557
3056
  }
2558
3057
 
2559
3058
  // src/components/Kanban.tsx
2560
- var import_jsx_runtime53 = require("react/jsx-runtime");
2561
- function Kanban({ children, className, ...props }) {
2562
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: cx("uix-kanban", className), ...props, children });
3059
+ var import_react35 = require("react");
3060
+ var import_jsx_runtime55 = require("react/jsx-runtime");
3061
+ function Kanban({ announcement, children, className, ...props }) {
3062
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: cx("uix-kanban", className), ...props, children: [
3063
+ announcement != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { role: "status", className: "uix-visually-hidden", children: announcement }),
3064
+ children
3065
+ ] });
2563
3066
  }
2564
3067
  function KanbanColumn({ title, count, children, className, ...props }) {
2565
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: cx("uix-kanban__col", className), ...props, children: [
2566
- (title != null || count != null) && /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "uix-kanban__head", children: [
3068
+ const headId = (0, import_react35.useId)();
3069
+ const hasHead = title != null || count != null;
3070
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: cx("uix-kanban__col", className), ...props, children: [
3071
+ hasHead && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "uix-kanban__head", id: headId, children: [
2567
3072
  title,
2568
- count != null && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "uix-kanban__count", children: count })
3073
+ count != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-kanban__count", children: count })
2569
3074
  ] }),
2570
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "uix-kanban__body", children })
3075
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "uix-kanban__body", role: "list", "aria-labelledby": hasHead ? headId : void 0, children })
2571
3076
  ] });
2572
3077
  }
2573
- function KanbanCard({ title, meta, children, className, ...props }) {
2574
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: cx("uix-kanban__card", className), ...props, children: [
2575
- title && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "uix-kanban__card-title", children: title }),
2576
- meta && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "uix-kanban__card-meta", children: meta }),
2577
- children
2578
- ] });
3078
+ var MOVE_KEYS = {
3079
+ ArrowUp: "up",
3080
+ ArrowDown: "down",
3081
+ ArrowLeft: "left",
3082
+ ArrowRight: "right"
3083
+ };
3084
+ function KanbanCard({ title, meta, children, className, onMove, onKeyDown, ...props }) {
3085
+ const handleKeyDown = (e) => {
3086
+ onKeyDown?.(e);
3087
+ if (!onMove || !e.altKey || e.defaultPrevented) return;
3088
+ const dir = MOVE_KEYS[e.key];
3089
+ if (dir) {
3090
+ e.preventDefault();
3091
+ onMove(dir);
3092
+ }
3093
+ };
3094
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
3095
+ "div",
3096
+ {
3097
+ role: "listitem",
3098
+ tabIndex: 0,
3099
+ className: cx("uix-kanban__card", className),
3100
+ onKeyDown: handleKeyDown,
3101
+ ...props,
3102
+ children: [
3103
+ title && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "uix-kanban__card-title", children: title }),
3104
+ meta && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "uix-kanban__card-meta", children: meta }),
3105
+ children
3106
+ ]
3107
+ }
3108
+ );
2579
3109
  }
2580
3110
 
2581
3111
  // src/components/Tree.tsx
2582
- var import_react28 = require("react");
3112
+ var import_react36 = require("react");
2583
3113
 
2584
3114
  // src/tree-model.ts
2585
3115
  function flattenTree(nodes, expanded, level = 1) {
@@ -2624,17 +3154,25 @@ function treeNav(flat, currentId, key) {
2624
3154
  case " ":
2625
3155
  return cur.hasChildren ? { toggleId: cur.node.id, selectId: cur.node.id } : { selectId: cur.node.id };
2626
3156
  default:
3157
+ if (key.length === 1) {
3158
+ const q = key.toLowerCase();
3159
+ for (let step = 1; step <= flat.length; step++) {
3160
+ const f = flat[(idx + step) % flat.length];
3161
+ const label = f.node.typeaheadLabel ?? (typeof f.node.label === "string" ? f.node.label : void 0);
3162
+ if (label != null && label.toLowerCase().startsWith(q)) return { focusId: f.node.id };
3163
+ }
3164
+ }
2627
3165
  return {};
2628
3166
  }
2629
3167
  }
2630
3168
 
2631
3169
  // src/components/Tree.tsx
2632
- var import_jsx_runtime54 = require("react/jsx-runtime");
2633
- var ChevronIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("svg", { viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("path", { d: "M2 4l4 4 4-4" }) });
3170
+ var import_jsx_runtime56 = require("react/jsx-runtime");
3171
+ var ChevronIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("svg", { viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("path", { d: "M2 4l4 4 4-4" }) });
2634
3172
  function TreeNode({ node, expanded, selected, selectable, tabbableId, onToggle, onSelect, onFocusNode, level = 1 }) {
2635
3173
  const hasChildren = Array.isArray(node.children) && node.children.length > 0;
2636
3174
  const isExpanded = expanded.has(node.id);
2637
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
3175
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
2638
3176
  "li",
2639
3177
  {
2640
3178
  role: "treeitem",
@@ -2654,12 +3192,12 @@ function TreeNode({ node, expanded, selected, selectable, tabbableId, onToggle,
2654
3192
  onFocusNode(node.id);
2655
3193
  },
2656
3194
  children: [
2657
- /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "uix-tree__row", children: [
2658
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "uix-tree__toggle", children: hasChildren && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(ChevronIcon2, {}) }),
2659
- node.icon && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { "aria-hidden": "true", children: node.icon }),
2660
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "uix-tree__label", children: node.label })
3195
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "uix-tree__row", children: [
3196
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "uix-tree__toggle", children: hasChildren && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(ChevronIcon2, {}) }),
3197
+ node.icon && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { "aria-hidden": "true", children: node.icon }),
3198
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "uix-tree__label", children: node.label })
2661
3199
  ] }),
2662
- hasChildren && isExpanded && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("ul", { role: "group", className: "uix-tree__group", children: node.children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
3200
+ hasChildren && isExpanded && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("ul", { role: "group", className: "uix-tree__group", children: node.children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
2663
3201
  TreeNode,
2664
3202
  {
2665
3203
  node: child,
@@ -2691,12 +3229,12 @@ function Tree({
2691
3229
  className,
2692
3230
  ...props
2693
3231
  }) {
2694
- const [internalExpanded, setInternalExpanded] = (0, import_react28.useState)(defaultExpanded ?? /* @__PURE__ */ new Set());
3232
+ const [internalExpanded, setInternalExpanded] = (0, import_react36.useState)(defaultExpanded ?? /* @__PURE__ */ new Set());
2695
3233
  const expanded = controlledExpanded ?? internalExpanded;
2696
- const rootRef = (0, import_react28.useRef)(null);
2697
- const [focusedId, setFocusedId] = (0, import_react28.useState)(void 0);
3234
+ const rootRef = (0, import_react36.useRef)(null);
3235
+ const [focusedId, setFocusedId] = (0, import_react36.useState)(void 0);
2698
3236
  const selectable = selected !== void 0 || onSelect != null;
2699
- const handleToggle = (0, import_react28.useCallback)((id) => {
3237
+ const handleToggle = (0, import_react36.useCallback)((id) => {
2700
3238
  if (!controlledExpanded) {
2701
3239
  setInternalExpanded((prev) => {
2702
3240
  const next = new Set(prev);
@@ -2707,11 +3245,11 @@ function Tree({
2707
3245
  }
2708
3246
  onToggle?.(id);
2709
3247
  }, [controlledExpanded, onToggle]);
2710
- const flat = (0, import_react28.useMemo)(() => flattenTree(nodes, expanded), [nodes, expanded]);
3248
+ const flat = (0, import_react36.useMemo)(() => flattenTree(nodes, expanded), [nodes, expanded]);
2711
3249
  const useVirtual = virtualize ?? shouldVirtualize(flat.length);
2712
3250
  const tabbableId = focusedId ?? selected ?? nodes[0]?.id;
2713
3251
  if (useVirtual) {
2714
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
3252
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
2715
3253
  VirtualTreeView,
2716
3254
  {
2717
3255
  flat,
@@ -2778,10 +3316,17 @@ function Tree({
2778
3316
  setFocusedId(id);
2779
3317
  break;
2780
3318
  default:
3319
+ if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
3320
+ const act = treeNav(flat, id, e.key);
3321
+ if (act.focusId !== void 0) {
3322
+ e.preventDefault();
3323
+ focusItem(rootRef.current?.querySelector(`[role="treeitem"][data-id="${CSS.escape(act.focusId)}"]`));
3324
+ }
3325
+ }
2781
3326
  break;
2782
3327
  }
2783
3328
  };
2784
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("ul", { ref: rootRef, className: cx("uix-tree", className), role: "tree", onKeyDown, ...props, children: nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
3329
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("ul", { ref: rootRef, className: cx("uix-tree", className), role: "tree", onKeyDown, ...props, children: nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
2785
3330
  TreeNode,
2786
3331
  {
2787
3332
  node,
@@ -2811,12 +3356,14 @@ function VirtualTreeView({
2811
3356
  className,
2812
3357
  ...props
2813
3358
  }) {
2814
- const scrollRef = (0, import_react28.useRef)(null);
2815
- const [scrollTop, setScrollTop] = (0, import_react28.useState)(0);
2816
- const pendingFocus = (0, import_react28.useRef)(false);
3359
+ const scrollRef = (0, import_react36.useRef)(null);
3360
+ const [scrollTop, setScrollTop] = (0, import_react36.useState)(0);
3361
+ const pendingFocus = (0, import_react36.useRef)(false);
3362
+ const hadFocus = (0, import_react36.useRef)(false);
2817
3363
  const win = virtualWindow(scrollTop, maxHeight, rowHeight, flat.length);
2818
3364
  const rows = flat.slice(win.start, win.end);
2819
- (0, import_react28.useEffect)(() => {
3365
+ const windowHasTabbable = tabbableId != null && rows.some((f) => f.node.id === tabbableId);
3366
+ (0, import_react36.useEffect)(() => {
2820
3367
  if (!pendingFocus.current || focusedId == null) return;
2821
3368
  const el = scrollRef.current?.querySelector(`[role="treeitem"][data-id="${CSS.escape(focusedId)}"]`);
2822
3369
  if (el) {
@@ -2824,6 +3371,11 @@ function VirtualTreeView({
2824
3371
  pendingFocus.current = false;
2825
3372
  }
2826
3373
  }, [focusedId, win.start, win.end]);
3374
+ (0, import_react36.useEffect)(() => {
3375
+ if (!hadFocus.current || pendingFocus.current) return;
3376
+ const active = document.activeElement;
3377
+ if (active === document.body || active == null) scrollRef.current?.focus({ preventScroll: true });
3378
+ });
2827
3379
  const moveTo = (id) => {
2828
3380
  const i = flat.findIndex((f) => f.node.id === id);
2829
3381
  if (i < 0) return;
@@ -2839,6 +3391,7 @@ function VirtualTreeView({
2839
3391
  setFocusedId(id);
2840
3392
  };
2841
3393
  const onKeyDown = (e) => {
3394
+ if (e.key.length === 1 && (e.ctrlKey || e.metaKey || e.altKey)) return;
2842
3395
  const curId = e.target.closest('[role="treeitem"]')?.dataset.id ?? focusedId;
2843
3396
  const act = treeNav(flat, curId, e.key);
2844
3397
  if (act.focusId === void 0 && act.toggleId === void 0 && act.selectId === void 0) return;
@@ -2853,21 +3406,28 @@ function VirtualTreeView({
2853
3406
  }
2854
3407
  if (act.focusId !== void 0) moveTo(act.focusId);
2855
3408
  };
2856
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
3409
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
2857
3410
  "ul",
2858
3411
  {
2859
3412
  ref: scrollRef,
2860
3413
  className: cx("uix-tree", "uix-tree--virtual", className),
2861
3414
  role: "tree",
3415
+ tabIndex: -1,
2862
3416
  style: { maxHeight, overflow: "auto" },
2863
3417
  onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
2864
3418
  onKeyDown,
3419
+ onFocus: () => {
3420
+ hadFocus.current = true;
3421
+ },
3422
+ onBlur: (e) => {
3423
+ if (!e.currentTarget.contains(e.relatedTarget)) hadFocus.current = false;
3424
+ },
2865
3425
  ...props,
2866
3426
  children: [
2867
- win.padTop > 0 && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("li", { "aria-hidden": "true", style: { height: win.padTop } }),
2868
- rows.map((f) => {
3427
+ win.padTop > 0 && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("li", { role: "presentation", "aria-hidden": "true", style: { height: win.padTop } }),
3428
+ rows.map((f, i) => {
2869
3429
  const rowStyle = { height: rowHeight, paddingLeft: `calc(${f.level - 1} * var(--uix-space-5))` };
2870
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
3430
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
2871
3431
  "li",
2872
3432
  {
2873
3433
  role: "treeitem",
@@ -2877,7 +3437,7 @@ function VirtualTreeView({
2877
3437
  "aria-expanded": f.hasChildren ? f.isExpanded : void 0,
2878
3438
  "aria-selected": selectable ? selected === f.node.id : void 0,
2879
3439
  "data-id": f.node.id,
2880
- tabIndex: tabbableId === f.node.id ? 0 : -1,
3440
+ tabIndex: tabbableId === f.node.id || !windowHasTabbable && i === 0 ? 0 : -1,
2881
3441
  className: "uix-tree__item",
2882
3442
  onFocus: (e) => {
2883
3443
  if (e.target === e.currentTarget) setFocusedId(f.node.id);
@@ -2888,23 +3448,23 @@ function VirtualTreeView({
2888
3448
  onSelect?.(f.node.id);
2889
3449
  setFocusedId(f.node.id);
2890
3450
  },
2891
- children: /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "uix-tree__row", style: rowStyle, children: [
2892
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "uix-tree__toggle", children: f.hasChildren && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(ChevronIcon2, {}) }),
2893
- f.node.icon && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { "aria-hidden": "true", children: f.node.icon }),
2894
- /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "uix-tree__label", children: f.node.label })
3451
+ children: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "uix-tree__row", style: rowStyle, children: [
3452
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "uix-tree__toggle", children: f.hasChildren && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(ChevronIcon2, {}) }),
3453
+ f.node.icon && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { "aria-hidden": "true", children: f.node.icon }),
3454
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "uix-tree__label", children: f.node.label })
2895
3455
  ] })
2896
3456
  },
2897
3457
  f.node.id
2898
3458
  );
2899
3459
  }),
2900
- win.padBottom > 0 && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("li", { "aria-hidden": "true", style: { height: win.padBottom } })
3460
+ win.padBottom > 0 && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("li", { role: "presentation", "aria-hidden": "true", style: { height: win.padBottom } })
2901
3461
  ]
2902
3462
  }
2903
3463
  );
2904
3464
  }
2905
3465
 
2906
3466
  // src/components/EditorialHome.tsx
2907
- var import_jsx_runtime55 = require("react/jsx-runtime");
3467
+ var import_jsx_runtime57 = require("react/jsx-runtime");
2908
3468
  function PageIntro({
2909
3469
  kicker,
2910
3470
  title,
@@ -2917,39 +3477,39 @@ function PageIntro({
2917
3477
  children,
2918
3478
  ...props
2919
3479
  }) {
2920
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("section", { className: cx("uix-page-intro", className), ...props, children: [
2921
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { children: [
2922
- kicker != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-page-kicker", children: kicker }),
2923
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("h1", { className: "uix-page-title", children: title }),
2924
- lede != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-page-lede", children: lede })
3480
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("section", { className: cx("uix-page-intro", className), ...props, children: [
3481
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { children: [
3482
+ kicker != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-page-kicker", children: kicker }),
3483
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h1", { className: "uix-page-title", children: title }),
3484
+ lede != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-page-lede", children: lede })
2925
3485
  ] }),
2926
- search != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { children: [
2927
- searchLabel != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-intro-search__label", children: searchLabel }),
3486
+ search != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { children: [
3487
+ searchLabel != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-intro-search__label", children: searchLabel }),
2928
3488
  search
2929
3489
  ] }),
2930
- shortcuts != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "uix-shortcut-grid", "aria-label": shortcutsLabel, children: shortcuts }),
3490
+ shortcuts != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uix-shortcut-grid", "aria-label": shortcutsLabel, children: shortcuts }),
2931
3491
  children
2932
3492
  ] });
2933
3493
  }
2934
3494
  function SectionHead({ title, titleId, action, className, ...props }) {
2935
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: cx("uix-section-head", className), ...props, children: [
2936
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("h2", { className: "uix-section-title", id: titleId, children: title }),
3495
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: cx("uix-section-head", className), ...props, children: [
3496
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h2", { className: "uix-section-title", id: titleId, children: title }),
2937
3497
  action
2938
3498
  ] });
2939
3499
  }
2940
3500
  function NoticeQueue({ icon, title, summary, meta, position, actions, className, ...props }) {
2941
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("section", { className: cx("uix-notice", className), ...props, children: [
3501
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("section", { className: cx("uix-notice", className), ...props, children: [
2942
3502
  icon,
2943
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "uix-notice__content", "aria-live": "polite", children: [
2944
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("p", { className: "uix-notice__copy", children: [
2945
- title != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("strong", { children: title }),
3503
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uix-notice__content", "aria-live": "polite", children: [
3504
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("p", { className: "uix-notice__copy", children: [
3505
+ title != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("strong", { children: title }),
2946
3506
  title != null && summary != null && " ",
2947
3507
  summary
2948
3508
  ] }),
2949
- meta != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-notice__meta", children: meta })
3509
+ meta != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-notice__meta", children: meta })
2950
3510
  ] }),
2951
- (position != null || actions != null) && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "uix-notice__actions", children: [
2952
- position != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-notice__position", children: position }),
3511
+ (position != null || actions != null) && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uix-notice__actions", children: [
3512
+ position != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-notice__position", children: position }),
2953
3513
  actions
2954
3514
  ] })
2955
3515
  ] });
@@ -2967,8 +3527,8 @@ function FeaturedStage({
2967
3527
  className,
2968
3528
  ...props
2969
3529
  }) {
2970
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("article", { className: cx("uix-featured__stage", className), ...props, children: [
2971
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
3530
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("article", { className: cx("uix-featured__stage", className), ...props, children: [
3531
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
2972
3532
  "div",
2973
3533
  {
2974
3534
  className: "uix-featured__visual",
@@ -2978,32 +3538,32 @@ function FeaturedStage({
2978
3538
  children: visual
2979
3539
  }
2980
3540
  ),
2981
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "uix-featured__content", "aria-live": "polite", children: [
2982
- (eyebrow != null || ordinal != null) && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("p", { className: "uix-featured__eyebrow", children: [
2983
- ordinal != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-featured__now", children: ordinal }),
3541
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uix-featured__content", "aria-live": "polite", children: [
3542
+ (eyebrow != null || ordinal != null) && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("p", { className: "uix-featured__eyebrow", children: [
3543
+ ordinal != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-featured__now", children: ordinal }),
2984
3544
  eyebrow
2985
3545
  ] }),
2986
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("h2", { className: "uix-featured__title", id: titleId, children: title }),
2987
- description != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-featured__description", children: description }),
2988
- meta != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-featured__meta", children: meta }),
3546
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h2", { className: "uix-featured__title", id: titleId, children: title }),
3547
+ description != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-featured__description", children: description }),
3548
+ meta != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-featured__meta", children: meta }),
2989
3549
  action
2990
3550
  ] })
2991
3551
  ] });
2992
3552
  }
2993
3553
  function FeaturedRundown({ eyebrow, title, titleId, meta, children, className, ...props }) {
2994
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("aside", { className: cx("uix-rundown", className), ...props, children: [
2995
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "uix-rundown__head", children: [
2996
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { children: [
2997
- eyebrow != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-rundown__eyebrow", children: eyebrow }),
2998
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("h2", { className: "uix-rundown__title", id: titleId, children: title })
3554
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("aside", { className: cx("uix-rundown", className), ...props, children: [
3555
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uix-rundown__head", children: [
3556
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { children: [
3557
+ eyebrow != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-rundown__eyebrow", children: eyebrow }),
3558
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h2", { className: "uix-rundown__title", id: titleId, children: title })
2999
3559
  ] }),
3000
3560
  meta
3001
3561
  ] }),
3002
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "uix-rundown__items", children })
3562
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uix-rundown__items", children })
3003
3563
  ] });
3004
3564
  }
3005
3565
  function FeaturedRundownItem({ number, topic, title, selected = false, className, ...props }) {
3006
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
3566
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
3007
3567
  "button",
3008
3568
  {
3009
3569
  type: "button",
@@ -3012,63 +3572,63 @@ function FeaturedRundownItem({ number, topic, title, selected = false, className
3012
3572
  "data-selected": selected ? "true" : "false",
3013
3573
  ...props,
3014
3574
  children: [
3015
- number != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-rundown__number", children: number }),
3016
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { children: [
3017
- topic != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-rundown__topic", children: topic }),
3018
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-rundown__item-title", children: title })
3575
+ number != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-rundown__number", children: number }),
3576
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { children: [
3577
+ topic != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-rundown__topic", children: topic }),
3578
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-rundown__item-title", children: title })
3019
3579
  ] })
3020
3580
  ]
3021
3581
  }
3022
3582
  );
3023
3583
  }
3024
3584
  function NewsLead({ meta, title, summary, className, ...props }) {
3025
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("article", { className: cx("uix-news-lead", className), ...props, children: [
3026
- meta != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-news-lead__meta", children: meta }),
3027
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("h3", { className: "uix-news-lead__title", children: title }),
3028
- summary != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-news-lead__summary", children: summary })
3585
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("article", { className: cx("uix-news-lead", className), ...props, children: [
3586
+ meta != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-news-lead__meta", children: meta }),
3587
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h3", { className: "uix-news-lead__title", children: title }),
3588
+ summary != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-news-lead__summary", children: summary })
3029
3589
  ] });
3030
3590
  }
3031
3591
  function ContentList({ children, className, ...props }) {
3032
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("ul", { className: cx("uix-content-list", className), ...props, children });
3592
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("ul", { className: cx("uix-content-list", className), ...props, children });
3033
3593
  }
3034
3594
  function ContentListItem({ title, meta, trailing, className, ...props }) {
3035
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("li", { className: cx("uix-content-list__item", className), ...props, children: [
3036
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { children: [
3037
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-content-list__title", children: title }),
3038
- meta != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-content-list__meta", children: meta })
3595
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("li", { className: cx("uix-content-list__item", className), ...props, children: [
3596
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { children: [
3597
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-content-list__title", children: title }),
3598
+ meta != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-content-list__meta", children: meta })
3039
3599
  ] }),
3040
3600
  trailing
3041
3601
  ] });
3042
3602
  }
3043
3603
  function ResourceGrid({ children, className, ...props }) {
3044
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: cx("uix-resource-grid", className), ...props, children });
3604
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: cx("uix-resource-grid", className), ...props, children });
3045
3605
  }
3046
3606
  function StatLine({ items, children, className, ...props }) {
3047
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: cx("uix-stat-line", className), ...props, children: [
3048
- items?.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "uix-stat-line__item", children: [
3049
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-stat-line__value", children: item.value }),
3050
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-stat-line__label", children: item.label })
3607
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: cx("uix-stat-line", className), ...props, children: [
3608
+ items?.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uix-stat-line__item", children: [
3609
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-stat-line__value", children: item.value }),
3610
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-stat-line__label", children: item.label })
3051
3611
  ] }, item.id ?? i)),
3052
3612
  children
3053
3613
  ] });
3054
3614
  }
3055
3615
  function EventRow({ month, day, title, meta, className, ...props }) {
3056
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: cx("uix-event-row", className), ...props, children: [
3057
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "uix-event-date", children: [
3058
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-event-date__month", children: month }),
3059
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-event-date__day", children: day })
3616
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: cx("uix-event-row", className), ...props, children: [
3617
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uix-event-date", children: [
3618
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-event-date__month", children: month }),
3619
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-event-date__day", children: day })
3060
3620
  ] }),
3061
- /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { children: [
3062
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-event-row__title", children: title }),
3063
- meta != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "uix-event-row__meta", children: meta })
3621
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { children: [
3622
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-event-row__title", children: title }),
3623
+ meta != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { className: "uix-event-row__meta", children: meta })
3064
3624
  ] })
3065
3625
  ] });
3066
3626
  }
3067
3627
  function StatusRow({ indicator, name, meta, className, ...props }) {
3068
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: cx("uix-status-row", className), ...props, children: [
3628
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: cx("uix-status-row", className), ...props, children: [
3069
3629
  indicator,
3070
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-status-row__name", children: name }),
3071
- meta != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-list-meta", children: meta })
3630
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-status-row__name", children: name }),
3631
+ meta != null && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-list-meta", children: meta })
3072
3632
  ] });
3073
3633
  }
3074
3634
 
@@ -3165,7 +3725,7 @@ function summarizeRule(value, labels = {}) {
3165
3725
  }
3166
3726
 
3167
3727
  // src/components/RuleBuilder.tsx
3168
- var import_jsx_runtime56 = require("react/jsx-runtime");
3728
+ var import_jsx_runtime58 = require("react/jsx-runtime");
3169
3729
  var ruleId = 0;
3170
3730
  var nextId = (prefix) => `${prefix}-${Date.now().toString(36)}-${(++ruleId).toString(36)}`;
3171
3731
  function defaultCondition(fields, operators) {
@@ -3181,21 +3741,21 @@ function RuleGroupEditor({ group, depth, root, fields, operators, maxDepth, disa
3181
3741
  combinator: "and",
3182
3742
  conditions: [defaultCondition(fields, operators)]
3183
3743
  }, maxDepth));
3184
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("fieldset", { className: "uix-rule-builder__group", "data-depth": depth, children: [
3185
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("legend", { className: "uix-rule-builder__group-heading", children: [
3186
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { children: depth === 1 ? "When" : "Group" }),
3187
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("label", { children: [
3744
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("fieldset", { className: "uix-rule-builder__group", "data-depth": depth, children: [
3745
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("legend", { className: "uix-rule-builder__group-heading", children: [
3746
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: depth === 1 ? "When" : "Group" }),
3747
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("label", { children: [
3188
3748
  "Match",
3189
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("select", { className: "uix-select uix-select--sm", value: group.combinator, disabled, onChange: (event) => updateNode(group.id, (node) => ({ ...node, combinator: event.currentTarget.value })), children: [
3190
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("option", { value: "and", children: "all (AND)" }),
3191
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("option", { value: "or", children: "any (OR)" })
3749
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("select", { className: "uix-select uix-select--sm", value: group.combinator, disabled, onChange: (event) => updateNode(group.id, (node) => ({ ...node, combinator: event.currentTarget.value })), children: [
3750
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("option", { value: "and", children: "all (AND)" }),
3751
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("option", { value: "or", children: "any (OR)" })
3192
3752
  ] })
3193
3753
  ] })
3194
3754
  ] }),
3195
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "uix-rule-builder__rows", children: group.conditions.map((node, index) => isRuleGroup(node) ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "uix-rule-builder__nested", children: [
3196
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RuleGroupEditor, { ...{ group: node, depth: depth + 1, root, fields, operators, maxDepth, disabled, onRootChange, labels } }),
3197
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RowControls, { label: "group", first: index === 0, last: index === group.conditions.length - 1, disabled, onUp: () => onRootChange(moveRuleNode(root, node.id, -1)), onDown: () => onRootChange(moveRuleNode(root, node.id, 1)), onRemove: () => onRootChange(removeRuleNode(root, node.id)) })
3198
- ] }, node.id) : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
3755
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uix-rule-builder__rows", children: group.conditions.map((node, index) => isRuleGroup(node) ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-rule-builder__nested", children: [
3756
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(RuleGroupEditor, { ...{ group: node, depth: depth + 1, root, fields, operators, maxDepth, disabled, onRootChange, labels } }),
3757
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(RowControls, { label: "group", first: index === 0, last: index === group.conditions.length - 1, disabled, onUp: () => onRootChange(moveRuleNode(root, node.id, -1)), onDown: () => onRootChange(moveRuleNode(root, node.id, 1)), onRemove: () => onRootChange(removeRuleNode(root, node.id)) })
3758
+ ] }, node.id) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
3199
3759
  ConditionRow,
3200
3760
  {
3201
3761
  condition: node,
@@ -3203,13 +3763,13 @@ function RuleGroupEditor({ group, depth, root, fields, operators, maxDepth, disa
3203
3763
  operators,
3204
3764
  disabled,
3205
3765
  onChange: (condition) => updateNode(node.id, () => condition),
3206
- controls: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RowControls, { label: "condition", first: index === 0, last: index === group.conditions.length - 1, disabled, onUp: () => onRootChange(moveRuleNode(root, node.id, -1)), onDown: () => onRootChange(moveRuleNode(root, node.id, 1)), onRemove: () => onRootChange(removeRuleNode(root, node.id)) })
3766
+ controls: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(RowControls, { label: "condition", first: index === 0, last: index === group.conditions.length - 1, disabled, onUp: () => onRootChange(moveRuleNode(root, node.id, -1)), onDown: () => onRootChange(moveRuleNode(root, node.id, 1)), onRemove: () => onRootChange(removeRuleNode(root, node.id)) })
3207
3767
  },
3208
3768
  node.id
3209
3769
  )) }),
3210
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "uix-rule-builder__add", children: [
3211
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", onClick: addCondition, disabled: disabled || fields.length === 0 || operators.length === 0, children: labels.addCondition }),
3212
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: addGroup, disabled: disabled || depth >= maxDepth, children: labels.addGroup })
3770
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-rule-builder__add", children: [
3771
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", onClick: addCondition, disabled: disabled || fields.length === 0 || operators.length === 0, children: labels.addCondition }),
3772
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: addGroup, disabled: disabled || depth >= maxDepth, children: labels.addGroup })
3213
3773
  ] })
3214
3774
  ] });
3215
3775
  }
@@ -3222,24 +3782,24 @@ function ConditionRow({ condition, fields, operators, disabled, onChange, contro
3222
3782
  const nextOperator = operators.find((item) => nextField?.operators?.includes(item.id)) ?? availableOperators[0] ?? operators[0];
3223
3783
  onChange({ ...condition, field: id, operator: nextOperator?.id ?? "" });
3224
3784
  };
3225
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "uix-rule-builder__condition", children: [
3226
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("label", { children: [
3227
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "uix-visually-hidden", children: "Field" }),
3228
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("select", { className: "uix-select", value: condition.field, onChange: (event) => setField(event.currentTarget.value), disabled, children: fields.map((item) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("option", { value: item.id, children: item.label }, item.id)) })
3785
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-rule-builder__condition", children: [
3786
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("label", { children: [
3787
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-visually-hidden", children: "Field" }),
3788
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("select", { className: "uix-select", value: condition.field, onChange: (event) => setField(event.currentTarget.value), disabled, children: fields.map((item) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("option", { value: item.id, children: item.label }, item.id)) })
3229
3789
  ] }),
3230
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("label", { children: [
3231
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "uix-visually-hidden", children: "Operator" }),
3232
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("select", { className: "uix-select", value: condition.operator, onChange: (event) => onChange({ ...condition, operator: event.currentTarget.value }), disabled, children: availableOperators.map((item) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("option", { value: item.id, children: item.label }, item.id)) })
3790
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("label", { children: [
3791
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-visually-hidden", children: "Operator" }),
3792
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("select", { className: "uix-select", value: condition.operator, onChange: (event) => onChange({ ...condition, operator: event.currentTarget.value }), disabled, children: availableOperators.map((item) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("option", { value: item.id, children: item.label }, item.id)) })
3233
3793
  ] }),
3234
- operator?.requiresValue !== false && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "uix-rule-builder__value", children: field?.renderValueEditor?.({ condition, onChange: (value) => onChange({ ...condition, value }), disabled }) ?? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("input", { className: "uix-input", value: typeof condition.value === "string" || typeof condition.value === "number" ? condition.value : condition.value == null ? "" : JSON.stringify(condition.value), onChange: (event) => onChange({ ...condition, value: event.currentTarget.value }), disabled, "aria-label": `Value for ${field?.label ?? "condition"}` }) }),
3794
+ operator?.requiresValue !== false && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uix-rule-builder__value", children: field?.renderValueEditor?.({ condition, onChange: (value) => onChange({ ...condition, value }), disabled }) ?? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("input", { className: "uix-input", value: typeof condition.value === "string" || typeof condition.value === "number" ? condition.value : condition.value == null ? "" : JSON.stringify(condition.value), onChange: (event) => onChange({ ...condition, value: event.currentTarget.value }), disabled, "aria-label": `Value for ${field?.label ?? "condition"}` }) }),
3235
3795
  controls
3236
3796
  ] });
3237
3797
  }
3238
3798
  function RowControls({ label, first, last, disabled, onUp, onDown, onRemove }) {
3239
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("span", { className: "uix-rule-builder__row-actions", children: [
3240
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: onUp, disabled: disabled || first, "aria-label": `Move ${label} up`, children: "Up" }),
3241
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: onDown, disabled: disabled || last, "aria-label": `Move ${label} down`, children: "Down" }),
3242
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: onRemove, disabled, "aria-label": `Remove ${label}`, children: "Remove" })
3799
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { className: "uix-rule-builder__row-actions", children: [
3800
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: onUp, disabled: disabled || first, "aria-label": `Move ${label} up`, children: "Up" }),
3801
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: onDown, disabled: disabled || last, "aria-label": `Move ${label} down`, children: "Down" }),
3802
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: onRemove, disabled, "aria-label": `Remove ${label}`, children: "Remove" })
3243
3803
  ] });
3244
3804
  }
3245
3805
  function RuleBuilder({
@@ -3260,9 +3820,9 @@ function RuleBuilder({
3260
3820
  const fieldLabels = Object.fromEntries(fields.map((field) => [field.id, field.label]));
3261
3821
  const operatorLabels = Object.fromEntries(operators.map((operator) => [operator.id, operator.label]));
3262
3822
  const actionLabels = Object.fromEntries(actions.map((action) => [action.id, action.label]));
3263
- if (readOnly) return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("section", { className: cx("uix-rule-builder uix-rule-builder--summary", className), "aria-label": "Rule summary", children: [
3264
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { children: summarizeRule(value, { fields: fieldLabels, operators: operatorLabels, actions: actionLabels }) }),
3265
- issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("p", { className: "uix-rule-builder__invalid", children: [
3823
+ if (readOnly) return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("section", { className: cx("uix-rule-builder uix-rule-builder--summary", className), "aria-label": "Rule summary", children: [
3824
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { children: summarizeRule(value, { fields: fieldLabels, operators: operatorLabels, actions: actionLabels }) }),
3825
+ issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("p", { className: "uix-rule-builder__invalid", children: [
3266
3826
  "Rule has ",
3267
3827
  issues.length,
3268
3828
  " validation issue",
@@ -3271,16 +3831,16 @@ function RuleBuilder({
3271
3831
  ] })
3272
3832
  ] });
3273
3833
  const updateActions = (next) => onChange({ ...value, then: next });
3274
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("section", { className: cx("uix-rule-builder", className), "aria-label": "Rule builder", children: [
3275
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(RuleGroupEditor, { group: value.when, depth: 1, root: value.when, fields, operators, maxDepth, disabled: readOnly, onRootChange: (when) => onChange({ ...value, when }), labels: { addCondition: addConditionLabel, addGroup: addGroupLabel } }),
3276
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("fieldset", { className: "uix-rule-builder__actions", children: [
3277
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("legend", { children: "Then" }),
3834
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("section", { className: cx("uix-rule-builder", className), "aria-label": "Rule builder", children: [
3835
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(RuleGroupEditor, { group: value.when, depth: 1, root: value.when, fields, operators, maxDepth, disabled: readOnly, onRootChange: (when) => onChange({ ...value, when }), labels: { addCondition: addConditionLabel, addGroup: addGroupLabel } }),
3836
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("fieldset", { className: "uix-rule-builder__actions", children: [
3837
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("legend", { children: "Then" }),
3278
3838
  value.then.map((action, index) => {
3279
3839
  const definition = actions.find((item) => item.id === action.type);
3280
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "uix-rule-builder__action", children: [
3281
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("select", { className: "uix-select", value: action.type, onChange: (event) => updateActions(value.then.map((item) => item.id === action.id ? { ...item, type: event.currentTarget.value } : item)), "aria-label": "Action type", children: actions.map((item) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("option", { value: item.id, children: item.label }, item.id)) }),
3840
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-rule-builder__action", children: [
3841
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("select", { className: "uix-select", value: action.type, onChange: (event) => updateActions(value.then.map((item) => item.id === action.id ? { ...item, type: event.currentTarget.value } : item)), "aria-label": "Action type", children: actions.map((item) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("option", { value: item.id, children: item.label }, item.id)) }),
3282
3842
  definition?.renderParameters?.(action, (parameters) => updateActions(value.then.map((item) => item.id === action.id ? { ...item, parameters } : item)), false),
3283
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
3843
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
3284
3844
  RowControls,
3285
3845
  {
3286
3846
  label: "action",
@@ -3302,22 +3862,22 @@ function RuleBuilder({
3302
3862
  )
3303
3863
  ] }, action.id);
3304
3864
  }),
3305
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", disabled: actions.length === 0, onClick: () => updateActions([...value.then, { id: nextId("action"), type: actions[0]?.id ?? "", parameters: {} }]), children: addActionLabel })
3865
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", disabled: actions.length === 0, onClick: () => updateActions([...value.then, { id: nextId("action"), type: actions[0]?.id ?? "", parameters: {} }]), children: addActionLabel })
3306
3866
  ] }),
3307
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "uix-rule-builder__validation", "aria-live": "polite", children: issues.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { children: "Rule is valid." }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
3308
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("strong", { children: [
3867
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uix-rule-builder__validation", "aria-live": "polite", children: issues.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: "Rule is valid." }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(import_jsx_runtime58.Fragment, { children: [
3868
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("strong", { children: [
3309
3869
  issues.length,
3310
3870
  " validation issue",
3311
3871
  issues.length === 1 ? "" : "s"
3312
3872
  ] }),
3313
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("ul", { children: issues.map((issue, index) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("li", { children: issue.message }, `${issue.path}-${index}`)) })
3873
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("ul", { children: issues.map((issue, index) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("li", { children: issue.message }, `${issue.path}-${index}`)) })
3314
3874
  ] }) })
3315
3875
  ] });
3316
3876
  }
3317
3877
 
3318
3878
  // src/components/BuilderCanvas.tsx
3319
- var import_react29 = require("react");
3320
- var import_jsx_runtime57 = require("react/jsx-runtime");
3879
+ var import_react37 = require("react");
3880
+ var import_jsx_runtime59 = require("react/jsx-runtime");
3321
3881
  function BuilderCanvas({
3322
3882
  items,
3323
3883
  onItemsChange,
@@ -3332,13 +3892,13 @@ function BuilderCanvas({
3332
3892
  emptyMessage = "Add an item from the palette to begin.",
3333
3893
  className
3334
3894
  }) {
3335
- const [internalSelectedId, setInternalSelectedId] = (0, import_react29.useState)();
3336
- const [draggedId, setDraggedId] = (0, import_react29.useState)();
3337
- const propertyHeadingRef = (0, import_react29.useRef)(null);
3338
- const shouldFocusProperties = (0, import_react29.useRef)(false);
3895
+ const [internalSelectedId, setInternalSelectedId] = (0, import_react37.useState)();
3896
+ const [draggedId, setDraggedId] = (0, import_react37.useState)();
3897
+ const propertyHeadingRef = (0, import_react37.useRef)(null);
3898
+ const shouldFocusProperties = (0, import_react37.useRef)(false);
3339
3899
  const selectedId = controlledSelectedId ?? internalSelectedId;
3340
3900
  const selected = items.find((item) => item.id === selectedId);
3341
- (0, import_react29.useEffect)(() => {
3901
+ (0, import_react37.useEffect)(() => {
3342
3902
  if (shouldFocusProperties.current && selected) {
3343
3903
  propertyHeadingRef.current?.focus();
3344
3904
  shouldFocusProperties.current = false;
@@ -3372,27 +3932,27 @@ function BuilderCanvas({
3372
3932
  if (from >= 0 && to >= 0) onItemsChange(reorder(items, from, to));
3373
3933
  setDraggedId(void 0);
3374
3934
  };
3375
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("section", { className: cx("uix-builder-canvas", className), "aria-label": "Builder canvas", children: [
3376
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("aside", { className: "uix-builder-canvas__palette", "aria-label": "Item palette", children: [
3377
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h3", { children: "Palette" }),
3378
- palette.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { children: "No item types available." }) : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("ul", { children: palette.map((item) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("button", { type: "button", onClick: () => add(item), children: [
3379
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("strong", { children: item.label }),
3380
- item.description && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { children: item.description }),
3381
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { "aria-hidden": "true", children: "Add" })
3935
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("section", { className: cx("uix-builder-canvas", className), "aria-label": "Builder canvas", children: [
3936
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("aside", { className: "uix-builder-canvas__palette", "aria-label": "Item palette", children: [
3937
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("h3", { children: "Palette" }),
3938
+ palette.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { children: "No item types available." }) : /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("ul", { children: palette.map((item) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("button", { type: "button", onClick: () => add(item), children: [
3939
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("strong", { children: item.label }),
3940
+ item.description && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { children: item.description }),
3941
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { "aria-hidden": "true", children: "Add" })
3382
3942
  ] }) }, item.id)) })
3383
3943
  ] }),
3384
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uix-builder-canvas__workspace", children: [
3385
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h3", { children: "Canvas" }),
3386
- loading ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uix-builder-canvas__state", role: "status", children: "Loading canvas\u2026" }) : error ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uix-builder-canvas__state", role: "alert", children: [
3387
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { children: error }),
3388
- onRetry && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: "Try again" })
3389
- ] }) : items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uix-builder-canvas__state", children: [
3390
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { children: emptyMessage }),
3391
- palette[0] && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("button", { type: "button", className: "uix-btn uix-btn--primary", onClick: () => add(palette[0]), children: [
3944
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "uix-builder-canvas__workspace", children: [
3945
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("h3", { children: "Canvas" }),
3946
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "uix-builder-canvas__state", role: "status", children: "Loading canvas\u2026" }) : error ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "uix-builder-canvas__state", role: "alert", children: [
3947
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { children: error }),
3948
+ onRetry && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: "Try again" })
3949
+ ] }) : items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "uix-builder-canvas__state", children: [
3950
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { children: emptyMessage }),
3951
+ palette[0] && /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("button", { type: "button", className: "uix-btn uix-btn--primary", onClick: () => add(palette[0]), children: [
3392
3952
  "Add ",
3393
3953
  palette[0].label
3394
3954
  ] })
3395
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("ol", { className: "uix-builder-canvas__items", children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
3955
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("ol", { className: "uix-builder-canvas__items", children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(
3396
3956
  "li",
3397
3957
  {
3398
3958
  draggable: true,
@@ -3402,34 +3962,34 @@ function BuilderCanvas({
3402
3962
  onDrop: (event) => drop(event, item.id),
3403
3963
  className: cx("uix-builder-canvas__item", selectedId === item.id && "uix-builder-canvas__item--selected"),
3404
3964
  children: [
3405
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("button", { type: "button", className: "uix-builder-canvas__item-main", "aria-pressed": selectedId === item.id, onClick: () => select(item.id), children: renderItem?.(item, selectedId === item.id) ?? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
3406
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("strong", { children: item.label }),
3407
- item.description && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { children: item.description })
3965
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", className: "uix-builder-canvas__item-main", "aria-pressed": selectedId === item.id, onClick: () => select(item.id), children: renderItem?.(item, selectedId === item.id) ?? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
3966
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("strong", { children: item.label }),
3967
+ item.description && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { children: item.description })
3408
3968
  ] }) }),
3409
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "uix-builder-canvas__item-actions", children: [
3410
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("button", { type: "button", onClick: () => move(item.id, -1), disabled: index === 0, "aria-label": `Move ${item.label} up`, children: "Up" }),
3411
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("button", { type: "button", onClick: () => move(item.id, 1), disabled: index === items.length - 1, "aria-label": `Move ${item.label} down`, children: "Down" }),
3412
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("button", { type: "button", onClick: () => remove(item.id), "aria-label": `Remove ${item.label}`, children: "Remove" })
3969
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "uix-builder-canvas__item-actions", children: [
3970
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", onClick: () => move(item.id, -1), disabled: index === 0, "aria-label": `Move ${item.label} up`, children: "Up" }),
3971
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", onClick: () => move(item.id, 1), disabled: index === items.length - 1, "aria-label": `Move ${item.label} down`, children: "Down" }),
3972
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", onClick: () => remove(item.id), "aria-label": `Remove ${item.label}`, children: "Remove" })
3413
3973
  ] })
3414
3974
  ]
3415
3975
  },
3416
3976
  item.id
3417
3977
  )) })
3418
3978
  ] }),
3419
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("aside", { className: "uix-builder-canvas__properties", "aria-label": "Item properties", children: [
3420
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("h3", { ref: propertyHeadingRef, tabIndex: -1, children: "Properties" }),
3421
- !selected ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("p", { children: "Select a canvas item to edit its properties." }) : renderProperties?.(selected, (updated) => onItemsChange(items.map((item) => item.id === updated.id ? updated : item))) ?? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("dl", { children: [
3422
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("dt", { children: "Type" }),
3423
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("dd", { children: selected.type }),
3424
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("dt", { children: "Label" }),
3425
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("dd", { children: selected.label })
3979
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("aside", { className: "uix-builder-canvas__properties", "aria-label": "Item properties", children: [
3980
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("h3", { ref: propertyHeadingRef, tabIndex: -1, children: "Properties" }),
3981
+ !selected ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { children: "Select a canvas item to edit its properties." }) : renderProperties?.(selected, (updated) => onItemsChange(items.map((item) => item.id === updated.id ? updated : item))) ?? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("dl", { children: [
3982
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("dt", { children: "Type" }),
3983
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("dd", { children: selected.type }),
3984
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("dt", { children: "Label" }),
3985
+ /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("dd", { children: selected.label })
3426
3986
  ] })
3427
3987
  ] })
3428
3988
  ] });
3429
3989
  }
3430
3990
 
3431
3991
  // src/components/SchedulingCalendar.tsx
3432
- var import_react30 = require("react");
3992
+ var import_react38 = require("react");
3433
3993
 
3434
3994
  // src/calendar-model.ts
3435
3995
  function fromDateKey(value) {
@@ -3510,7 +4070,7 @@ function isDateUnavailable(date, options) {
3510
4070
  }
3511
4071
 
3512
4072
  // src/components/SchedulingCalendar.tsx
3513
- var import_jsx_runtime58 = require("react/jsx-runtime");
4073
+ var import_jsx_runtime60 = require("react/jsx-runtime");
3514
4074
  var stateLabel = { scheduled: "Scheduled", conflicted: "Conflicted", "in-progress": "In progress", "blackout-violation": "Blackout violation" };
3515
4075
  var stateTone = (state) => state === "scheduled" ? "info" : state === "in-progress" ? "success" : "danger";
3516
4076
  var dateLabel = (date, locale) => new Intl.DateTimeFormat(locale, { dateStyle: "full", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${date}T00:00:00Z`));
@@ -3532,19 +4092,19 @@ function SchedulingCalendar({
3532
4092
  onRetry,
3533
4093
  className
3534
4094
  }) {
3535
- const [internalView, setInternalView] = (0, import_react30.useState)("month");
4095
+ const [internalView, setInternalView] = (0, import_react38.useState)("month");
3536
4096
  const view = controlledView ?? internalView;
3537
- const [activeDate, setActiveDate] = (0, import_react30.useState)(anchorDate);
3538
- const gridRef = (0, import_react30.useRef)(null);
3539
- const visibleEntries = (0, import_react30.useMemo)(() => entries.filter((entry) => filter?.(entry) ?? true), [entries, filter]);
3540
- const entrySpans = (0, import_react30.useMemo)(() => new Map(visibleEntries.map((entry) => [entry.id, zonedDateSpan(entry.start, entry.end, timeZone)])), [visibleEntries, timeZone]);
3541
- const overlaySpans = (0, import_react30.useMemo)(() => new Map(overlays.map((overlay) => [overlay.id, { start: overlay.start.slice(0, 10), end: overlay.end.slice(0, 10) }])), [overlays]);
3542
- const monthDays = (0, import_react30.useMemo)(() => buildMonthGrid(startOfMonth(anchorDate)), [anchorDate]);
4097
+ const [activeDate, setActiveDate] = (0, import_react38.useState)(anchorDate);
4098
+ const gridRef = (0, import_react38.useRef)(null);
4099
+ const visibleEntries = (0, import_react38.useMemo)(() => entries.filter((entry) => filter?.(entry) ?? true), [entries, filter]);
4100
+ const entrySpans = (0, import_react38.useMemo)(() => new Map(visibleEntries.map((entry) => [entry.id, zonedDateSpan(entry.start, entry.end, timeZone)])), [visibleEntries, timeZone]);
4101
+ const overlaySpans = (0, import_react38.useMemo)(() => new Map(overlays.map((overlay) => [overlay.id, { start: overlay.start.slice(0, 10), end: overlay.end.slice(0, 10) }])), [overlays]);
4102
+ const monthDays = (0, import_react38.useMemo)(() => buildMonthGrid(startOfMonth(anchorDate)), [anchorDate]);
3543
4103
  const weekday = ((/* @__PURE__ */ new Date(`${anchorDate}T00:00:00Z`)).getUTCDay() + 6) % 7;
3544
4104
  const weekStart = addCalendarDays(anchorDate, -weekday);
3545
- const weekDays = (0, import_react30.useMemo)(() => Array.from({ length: 7 }, (_, index) => addCalendarDays(weekStart, index)), [weekStart]);
3546
- const days = (0, import_react30.useMemo)(() => view === "month" ? monthDays.map((day) => day.date) : weekDays, [view, monthDays, weekDays]);
3547
- (0, import_react30.useEffect)(() => {
4105
+ const weekDays = (0, import_react38.useMemo)(() => Array.from({ length: 7 }, (_, index) => addCalendarDays(weekStart, index)), [weekStart]);
4106
+ const days = (0, import_react38.useMemo)(() => view === "month" ? monthDays.map((day) => day.date) : weekDays, [view, monthDays, weekDays]);
4107
+ (0, import_react38.useEffect)(() => {
3548
4108
  if (view !== "agenda" && !days.includes(activeDate)) setActiveDate(days[0]);
3549
4109
  }, [activeDate, days, view]);
3550
4110
  const setView = (next) => {
@@ -3578,58 +4138,58 @@ function SchedulingCalendar({
3578
4138
  return date >= span.start && date <= span.end;
3579
4139
  });
3580
4140
  const formatInstant = (instant) => new Intl.DateTimeFormat(locale, { timeZone, dateStyle: "medium", timeStyle: "short" }).format(new Date(instant));
3581
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("section", { className: cx("uix-scheduling-calendar", className), "aria-label": `Scheduling calendar in ${timeZone}`, children: [
3582
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-scheduling-calendar__header", children: [
3583
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { children: [
3584
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => movePeriod(-1), disabled: !onAnchorDateChange, children: "Previous" }),
3585
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => movePeriod(1), disabled: !onAnchorDateChange, children: "Next" })
4141
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("section", { className: cx("uix-scheduling-calendar", className), "aria-label": `Scheduling calendar in ${timeZone}`, children: [
4142
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "uix-scheduling-calendar__header", children: [
4143
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { children: [
4144
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => movePeriod(-1), disabled: !onAnchorDateChange, children: "Previous" }),
4145
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => movePeriod(1), disabled: !onAnchorDateChange, children: "Next" })
3586
4146
  ] }),
3587
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("strong", { children: view === "month" ? new Intl.DateTimeFormat(locale, { month: "long", year: "numeric", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${anchorDate}T00:00:00Z`)) : `${dateLabel(weekStart, locale)} \u2013 ${dateLabel(weekDays[weekDays.length - 1], locale)}` }),
3588
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uix-segmented", role: "group", "aria-label": "Calendar view", children: ["month", "week", "agenda"].map((option) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("button", { type: "button", className: "uix-segmented__option", "aria-pressed": view === option, "data-selected": view === option || void 0, onClick: () => setView(option), children: [
4147
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("strong", { children: view === "month" ? new Intl.DateTimeFormat(locale, { month: "long", year: "numeric", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${anchorDate}T00:00:00Z`)) : `${dateLabel(weekStart, locale)} \u2013 ${dateLabel(weekDays[weekDays.length - 1], locale)}` }),
4148
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "uix-segmented", role: "group", "aria-label": "Calendar view", children: ["month", "week", "agenda"].map((option) => /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "uix-segmented__option", "aria-pressed": view === option, "data-selected": view === option || void 0, onClick: () => setView(option), children: [
3589
4149
  option[0].toUpperCase(),
3590
4150
  option.slice(1)
3591
4151
  ] }, option)) })
3592
4152
  ] }),
3593
- loading ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uix-scheduling-calendar__state", role: "status", children: "Loading schedule\u2026" }) : error ? /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-scheduling-calendar__state", role: "alert", children: [
3594
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { children: error }),
3595
- onRetry && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: "Try again" })
3596
- ] }) : view === "agenda" ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uix-scheduling-calendar__agenda", role: "region", "aria-label": "Schedule agenda", children: visibleEntries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { children: "No scheduled entries match the current filters." }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("ol", { children: [...visibleEntries].sort((a, b) => a.start.localeCompare(b.start)).map((entry) => {
4153
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "uix-scheduling-calendar__state", role: "status", children: "Loading schedule\u2026" }) : error ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "uix-scheduling-calendar__state", role: "alert", children: [
4154
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { children: error }),
4155
+ onRetry && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: "Try again" })
4156
+ ] }) : view === "agenda" ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "uix-scheduling-calendar__agenda", role: "region", "aria-label": "Schedule agenda", children: visibleEntries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { children: "No scheduled entries match the current filters." }) : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("ol", { children: [...visibleEntries].sort((a, b) => a.start.localeCompare(b.start)).map((entry) => {
3597
4157
  const state = entry.state ?? "scheduled";
3598
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("button", { type: "button", onClick: () => onSelectEntry?.(entry), children: [
3599
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { children: [
3600
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("strong", { children: renderEntry?.(entry) ?? entry.title }),
3601
- /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { children: [
4158
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", onClick: () => onSelectEntry?.(entry), children: [
4159
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { children: [
4160
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("strong", { children: renderEntry?.(entry) ?? entry.title }),
4161
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { children: [
3602
4162
  formatInstant(entry.start),
3603
4163
  " \u2013 ",
3604
4164
  formatInstant(entry.end)
3605
4165
  ] }),
3606
- entry.meta && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: entry.meta })
4166
+ entry.meta && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { children: entry.meta })
3607
4167
  ] }),
3608
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(StatusPill, { tone: stateTone(state), children: stateLabel[state] })
4168
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(StatusPill, { tone: stateTone(state), children: stateLabel[state] })
3609
4169
  ] }) }, entry.id);
3610
- }) }) }) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { ref: gridRef, className: cx("uix-scheduling-calendar__grid", view === "week" && "uix-scheduling-calendar__grid--week"), role: "group", "aria-label": `${view} schedule`, children: days.map((date, index) => {
4170
+ }) }) }) : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { ref: gridRef, className: cx("uix-scheduling-calendar__grid", view === "week" && "uix-scheduling-calendar__grid--week"), role: "group", "aria-label": `${view} schedule`, children: days.map((date, index) => {
3611
4171
  const dayEntries = entriesFor(date);
3612
4172
  const dayOverlays = overlaysFor(date);
3613
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-scheduling-calendar__day", "data-outside": view === "month" && !monthDays[index].inMonth || void 0, children: [
3614
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("button", { type: "button", className: "uix-scheduling-calendar__date", "data-calendar-date": date, tabIndex: activeDate === date ? 0 : -1, onFocus: () => setActiveDate(date), onKeyDown: (event) => onDayKeyDown(event, date), "aria-label": dateLabel(date, locale), children: Number(date.slice(-2)) }),
3615
- dayOverlays.map((overlay) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-scheduling-calendar__overlay", "data-kind": overlay.kind, children: overlay.label }, overlay.id)),
3616
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uix-scheduling-calendar__entries", children: dayEntries.map((entry) => {
4173
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "uix-scheduling-calendar__day", "data-outside": view === "month" && !monthDays[index].inMonth || void 0, children: [
4174
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", className: "uix-scheduling-calendar__date", "data-calendar-date": date, tabIndex: activeDate === date ? 0 : -1, onFocus: () => setActiveDate(date), onKeyDown: (event) => onDayKeyDown(event, date), "aria-label": dateLabel(date, locale), children: Number(date.slice(-2)) }),
4175
+ dayOverlays.map((overlay) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "uix-scheduling-calendar__overlay", "data-kind": overlay.kind, children: overlay.label }, overlay.id)),
4176
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "uix-scheduling-calendar__entries", children: dayEntries.map((entry) => {
3617
4177
  const span = entrySpans.get(entry.id);
3618
4178
  const state = entry.state ?? "scheduled";
3619
- return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("button", { type: "button", className: "uix-scheduling-calendar__entry", "data-state": state, "data-range-start": date === span.start || void 0, "data-range-end": date === span.end || void 0, onClick: () => onSelectEntry?.(entry), "aria-label": `${entry.title}, ${stateLabel[state]}, ${formatInstant(entry.start)} to ${formatInstant(entry.end)}`, children: [
3620
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { children: renderEntry?.(entry) ?? entry.title }),
3621
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-visually-hidden", children: stateLabel[state] })
4179
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "uix-scheduling-calendar__entry", "data-state": state, "data-range-start": date === span.start || void 0, "data-range-end": date === span.end || void 0, onClick: () => onSelectEntry?.(entry), "aria-label": `${entry.title}, ${stateLabel[state]}, ${formatInstant(entry.start)} to ${formatInstant(entry.end)}`, children: [
4180
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { children: renderEntry?.(entry) ?? entry.title }),
4181
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { className: "uix-visually-hidden", children: stateLabel[state] })
3622
4182
  ] }, entry.id);
3623
4183
  }) })
3624
4184
  ] }, date);
3625
4185
  }) }),
3626
- /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uix-scheduling-calendar__legend", "aria-label": "Schedule state legend", children: ["scheduled", "conflicted", "in-progress", "blackout-violation"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { "data-state": state, children: stateLabel[state] }, state)) })
4186
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "uix-scheduling-calendar__legend", "aria-label": "Schedule state legend", children: ["scheduled", "conflicted", "in-progress", "blackout-violation"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { "data-state": state, children: stateLabel[state] }, state)) })
3627
4187
  ] });
3628
4188
  }
3629
4189
 
3630
4190
  // src/components/DateRangePicker.tsx
3631
- var import_react31 = require("react");
3632
- var import_jsx_runtime59 = require("react/jsx-runtime");
4191
+ var import_react39 = require("react");
4192
+ var import_jsx_runtime61 = require("react/jsx-runtime");
3633
4193
  var monthLabel = (date, locale) => new Intl.DateTimeFormat(locale, { month: "long", year: "numeric", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${date}T00:00:00Z`));
3634
4194
  var dateLabel2 = (date, locale) => new Intl.DateTimeFormat(locale, { dateStyle: "full", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${date}T00:00:00Z`));
3635
4195
  function DateRangePicker({
@@ -3648,25 +4208,25 @@ function DateRangePicker({
3648
4208
  disabled,
3649
4209
  className
3650
4210
  }) {
3651
- const id = (0, import_react31.useId)();
3652
- const [internalMonth, setInternalMonth] = (0, import_react31.useState)(() => startOfMonth(controlledMonth ?? value.start ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)));
4211
+ const id = (0, import_react39.useId)();
4212
+ const [internalMonth, setInternalMonth] = (0, import_react39.useState)(() => startOfMonth(controlledMonth ?? value.start ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)));
3653
4213
  const visibleMonth = startOfMonth(controlledMonth ?? internalMonth);
3654
- const [activeDate, setActiveDate] = (0, import_react31.useState)(value.end ?? value.start ?? visibleMonth);
3655
- const rootRef = (0, import_react31.useRef)(null);
3656
- const pendingFocus = (0, import_react31.useRef)(false);
4214
+ const [activeDate, setActiveDate] = (0, import_react39.useState)(value.end ?? value.start ?? visibleMonth);
4215
+ const rootRef = (0, import_react39.useRef)(null);
4216
+ const pendingFocus = (0, import_react39.useRef)(false);
3657
4217
  const count = Math.max(1, Math.min(3, months));
3658
- const calendars = (0, import_react31.useMemo)(() => Array.from({ length: count }, (_, index) => {
4218
+ const calendars = (0, import_react39.useMemo)(() => Array.from({ length: count }, (_, index) => {
3659
4219
  const month = startOfMonth(addCalendarMonths(visibleMonth, index));
3660
4220
  return { month, days: buildMonthGrid(month).filter((day) => day.inMonth) };
3661
4221
  }), [visibleMonth, count]);
3662
4222
  const rangeInvalid = invalid || !!value.start && !!value.end && value.start > value.end;
3663
- (0, import_react31.useEffect)(() => {
4223
+ (0, import_react39.useEffect)(() => {
3664
4224
  const first = calendars[0]?.days[0]?.date;
3665
4225
  const finalDays = calendars[calendars.length - 1]?.days;
3666
4226
  const last = finalDays?.[finalDays.length - 1]?.date;
3667
4227
  if (first && last && (activeDate < first || activeDate > last)) setActiveDate(first);
3668
4228
  }, [activeDate, calendars]);
3669
- (0, import_react31.useEffect)(() => {
4229
+ (0, import_react39.useEffect)(() => {
3670
4230
  if (!pendingFocus.current) return;
3671
4231
  rootRef.current?.querySelector(`[data-date="${activeDate}"]`)?.focus();
3672
4232
  pendingFocus.current = false;
@@ -3704,23 +4264,23 @@ function DateRangePicker({
3704
4264
  }
3705
4265
  };
3706
4266
  const announcement = !value.start ? "No date range selected." : !value.end ? `Start date ${dateLabel2(value.start, locale)} selected. Choose an end date.` : `${dateLabel2(value.start, locale)} to ${dateLabel2(value.end, locale)} selected.`;
3707
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("section", { className: cx("uix-date-range-picker", rangeInvalid && "uix-date-range-picker--invalid", className), "aria-labelledby": `${id}-label`, children: [
3708
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "uix-date-range-picker__header", children: [
3709
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("h3", { id: `${id}-label`, children: label }),
3710
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { children: [
3711
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => setMonth(addCalendarMonths(visibleMonth, -1)), "aria-label": "Show previous month", children: "Previous" }),
3712
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => setMonth(addCalendarMonths(visibleMonth, 1)), "aria-label": "Show next month", children: "Next" })
4267
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("section", { className: cx("uix-date-range-picker", rangeInvalid && "uix-date-range-picker--invalid", className), "aria-labelledby": `${id}-label`, children: [
4268
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "uix-date-range-picker__header", children: [
4269
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("h3", { id: `${id}-label`, children: label }),
4270
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { children: [
4271
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => setMonth(addCalendarMonths(visibleMonth, -1)), "aria-label": "Show previous month", children: "Previous" }),
4272
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => setMonth(addCalendarMonths(visibleMonth, 1)), "aria-label": "Show next month", children: "Next" })
3713
4273
  ] })
3714
4274
  ] }),
3715
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { ref: rootRef, className: "uix-date-range-picker__months", children: calendars.map(({ month, days }) => /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "uix-date-range-picker__month", children: [
3716
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("h4", { children: monthLabel(month, locale) }),
3717
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "uix-date-range-picker__weekdays", "aria-hidden": "true", children: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"].map((day) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { children: day }, day)) }),
3718
- /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "uix-date-range-picker__grid", role: "group", "aria-label": monthLabel(month, locale), children: [
3719
- Array.from({ length: ((/* @__PURE__ */ new Date(`${month}T00:00:00Z`)).getUTCDay() + 6) % 7 }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { "aria-hidden": "true" }, `blank-${index}`)),
4275
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { ref: rootRef, className: "uix-date-range-picker__months", children: calendars.map(({ month, days }) => /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "uix-date-range-picker__month", children: [
4276
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("h4", { children: monthLabel(month, locale) }),
4277
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "uix-date-range-picker__weekdays", "aria-hidden": "true", children: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"].map((day) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { children: day }, day)) }),
4278
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "uix-date-range-picker__grid", role: "group", "aria-label": monthLabel(month, locale), children: [
4279
+ Array.from({ length: ((/* @__PURE__ */ new Date(`${month}T00:00:00Z`)).getUTCDay() + 6) % 7 }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { "aria-hidden": "true" }, `blank-${index}`)),
3720
4280
  days.map((day) => {
3721
4281
  const unavailable = disabled || isDateUnavailable(day.date, { min, max, isDisabled: isDateDisabled });
3722
4282
  const edge = day.date === value.start ? "start" : day.date === value.end ? "end" : void 0;
3723
- return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
4283
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
3724
4284
  "button",
3725
4285
  {
3726
4286
  type: "button",
@@ -3741,13 +4301,13 @@ function DateRangePicker({
3741
4301
  })
3742
4302
  ] })
3743
4303
  ] }, month)) }),
3744
- /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "uix-date-range-picker__selection", "aria-live": "polite", children: announcement }),
3745
- rangeInvalid && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { className: "uix-field__error", role: "alert", children: invalidMessage })
4304
+ /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "uix-date-range-picker__selection", "aria-live": "polite", children: announcement }),
4305
+ rangeInvalid && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "uix-field__error", role: "alert", children: invalidMessage })
3746
4306
  ] });
3747
4307
  }
3748
4308
 
3749
4309
  // src/components/RelationshipGraph.tsx
3750
- var import_react32 = require("react");
4310
+ var import_react40 = require("react");
3751
4311
 
3752
4312
  // src/relationship-graph-model.ts
3753
4313
  function boundRelationshipGraph(nodes, edges, maxNodes = 40) {
@@ -3814,7 +4374,7 @@ function traverseRelationshipNode(nodes, currentId, direction) {
3814
4374
  }
3815
4375
 
3816
4376
  // src/components/RelationshipGraph.tsx
3817
- var import_jsx_runtime60 = require("react/jsx-runtime");
4377
+ var import_jsx_runtime62 = require("react/jsx-runtime");
3818
4378
  var EMPTY_IDS = /* @__PURE__ */ new Set();
3819
4379
  var EMPTY_LEGEND = [];
3820
4380
  function RelationshipGraph({
@@ -3836,13 +4396,13 @@ function RelationshipGraph({
3836
4396
  onRetry,
3837
4397
  className
3838
4398
  }) {
3839
- const bounded = (0, import_react32.useMemo)(() => boundRelationshipGraph(nodes, edges, maxNodes), [nodes, edges, maxNodes]);
3840
- const positioned = (0, import_react32.useMemo)(() => layoutRelationshipGraph(bounded.nodes, bounded.edges, selectedId), [bounded, selectedId]);
3841
- const positionedById = (0, import_react32.useMemo)(() => new Map(positioned.map((node) => [node.id, node])), [positioned]);
3842
- const [zoom, setZoom] = (0, import_react32.useState)(1);
3843
- const [pan, setPan] = (0, import_react32.useState)({ x: 0, y: 0 });
3844
- const [focusedId, setFocusedId] = (0, import_react32.useState)(selectedId ?? positioned[0]?.id);
3845
- const svgRef = (0, import_react32.useRef)(null);
4399
+ const bounded = (0, import_react40.useMemo)(() => boundRelationshipGraph(nodes, edges, maxNodes), [nodes, edges, maxNodes]);
4400
+ const positioned = (0, import_react40.useMemo)(() => layoutRelationshipGraph(bounded.nodes, bounded.edges, selectedId), [bounded, selectedId]);
4401
+ const positionedById = (0, import_react40.useMemo)(() => new Map(positioned.map((node) => [node.id, node])), [positioned]);
4402
+ const [zoom, setZoom] = (0, import_react40.useState)(1);
4403
+ const [pan, setPan] = (0, import_react40.useState)({ x: 0, y: 0 });
4404
+ const [focusedId, setFocusedId] = (0, import_react40.useState)(selectedId ?? positioned[0]?.id);
4405
+ const svgRef = (0, import_react40.useRef)(null);
3846
4406
  const select = (id) => {
3847
4407
  const node = bounded.nodes.find((item) => item.id === id);
3848
4408
  if (node) onSelect?.(node);
@@ -3865,44 +4425,44 @@ function RelationshipGraph({
3865
4425
  setZoom(1);
3866
4426
  setPan({ x: 0, y: 0 });
3867
4427
  };
3868
- if (loading) return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: cx("uix-relationship-graph uix-relationship-graph--state", className), role: "status", children: "Loading relationships\u2026" });
3869
- if (error) return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: cx("uix-relationship-graph uix-relationship-graph--state", className), role: "alert", children: [
3870
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { children: error }),
3871
- onRetry && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: "Try again" })
4428
+ if (loading) return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: cx("uix-relationship-graph uix-relationship-graph--state", className), role: "status", children: "Loading relationships\u2026" });
4429
+ if (error) return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: cx("uix-relationship-graph uix-relationship-graph--state", className), role: "alert", children: [
4430
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { children: error }),
4431
+ onRetry && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: "Try again" })
3872
4432
  ] });
3873
- if (bounded.nodes.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: cx("uix-relationship-graph uix-relationship-graph--state", className), children: [
3874
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { children: "No relationships to display." }),
3875
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { children: "Adjust the neighborhood or filters to include a node." })
4433
+ if (bounded.nodes.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: cx("uix-relationship-graph uix-relationship-graph--state", className), children: [
4434
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { children: "No relationships to display." }),
4435
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { children: "Adjust the neighborhood or filters to include a node." })
3876
4436
  ] });
3877
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("section", { className: cx("uix-relationship-graph", `uix-relationship-graph--${density}`, className), "aria-label": "Relationship graph", children: [
3878
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "uix-relationship-graph__toolbar", "aria-label": "Graph view controls", children: [
3879
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, x: value.x - 24 })), "aria-label": "Pan left", children: "Left" }),
3880
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, y: value.y - 24 })), "aria-label": "Pan up", children: "Up" }),
3881
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, y: value.y + 24 })), "aria-label": "Pan down", children: "Down" }),
3882
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, x: value.x + 24 })), "aria-label": "Pan right", children: "Right" }),
3883
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", onClick: () => setZoom((value) => Math.min(2, Number((value + 0.2).toFixed(1)))), "aria-label": "Zoom in", children: "Zoom in" }),
3884
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", onClick: () => setZoom((value) => Math.max(0.5, Number((value - 0.2).toFixed(1)))), "aria-label": "Zoom out", children: "Zoom out" }),
3885
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", onClick: reset, children: "Reset view" }),
3886
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { "aria-live": "polite", children: [
4437
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("section", { className: cx("uix-relationship-graph", `uix-relationship-graph--${density}`, className), "aria-label": "Relationship graph", children: [
4438
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "uix-relationship-graph__toolbar", "aria-label": "Graph view controls", children: [
4439
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, x: value.x - 24 })), "aria-label": "Pan left", children: "Left" }),
4440
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, y: value.y - 24 })), "aria-label": "Pan up", children: "Up" }),
4441
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, y: value.y + 24 })), "aria-label": "Pan down", children: "Down" }),
4442
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, x: value.x + 24 })), "aria-label": "Pan right", children: "Right" }),
4443
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => setZoom((value) => Math.min(2, Number((value + 0.2).toFixed(1)))), "aria-label": "Zoom in", children: "Zoom in" }),
4444
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => setZoom((value) => Math.max(0.5, Number((value - 0.2).toFixed(1)))), "aria-label": "Zoom out", children: "Zoom out" }),
4445
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: reset, children: "Reset view" }),
4446
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { "aria-live": "polite", children: [
3887
4447
  "Zoom ",
3888
4448
  Math.round(zoom * 100),
3889
4449
  "%"
3890
4450
  ] })
3891
4451
  ] }),
3892
- bounded.omittedNodeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("p", { className: "uix-relationship-graph__bounded", role: "status", children: [
4452
+ bounded.omittedNodeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("p", { className: "uix-relationship-graph__bounded", role: "status", children: [
3893
4453
  "Showing ",
3894
4454
  bounded.nodes.length,
3895
4455
  " nodes; ",
3896
4456
  bounded.omittedNodeCount,
3897
4457
  " outside this bounded neighborhood."
3898
4458
  ] }),
3899
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "uix-relationship-graph__visual", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("svg", { ref: svgRef, viewBox: "0 0 600 400", role: "group", "aria-label": `Graph with ${bounded.nodes.length} nodes and ${bounded.edges.length} relationships`, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("g", { transform: `translate(${pan.x} ${pan.y}) scale(${zoom})`, children: [
4459
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "uix-relationship-graph__visual", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("svg", { ref: svgRef, viewBox: "0 0 600 400", role: "group", "aria-label": `Graph with ${bounded.nodes.length} nodes and ${bounded.edges.length} relationships`, children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("g", { transform: `translate(${pan.x} ${pan.y}) scale(${zoom})`, children: [
3900
4460
  bounded.edges.map((edge) => {
3901
4461
  const source = positionedById.get(edge.source);
3902
4462
  const target = positionedById.get(edge.target);
3903
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("line", { x1: source.x * 6, y1: source.y * 4, x2: target.x * 6, y2: target.y * 4, className: "uix-relationship-graph__edge", "data-highlighted": highlightedEdgeIds.has(edge.id) || void 0, "data-conflicted": conflictedEdgeIds.has(edge.id) || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("title", { children: edge.label ?? edge.type ?? "Relationship" }) }, edge.id);
4463
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("line", { x1: source.x * 6, y1: source.y * 4, x2: target.x * 6, y2: target.y * 4, className: "uix-relationship-graph__edge", "data-highlighted": highlightedEdgeIds.has(edge.id) || void 0, "data-conflicted": conflictedEdgeIds.has(edge.id) || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("title", { children: edge.label ?? edge.type ?? "Relationship" }) }, edge.id);
3904
4464
  }),
3905
- positioned.map((node) => /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
4465
+ positioned.map((node) => /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)(
3906
4466
  "g",
3907
4467
  {
3908
4468
  transform: `translate(${node.x * 6} ${node.y * 4})`,
@@ -3918,27 +4478,27 @@ function RelationshipGraph({
3918
4478
  onKeyDown: (event) => onNodeKeyDown(event, node.id),
3919
4479
  onClick: () => select(node.id),
3920
4480
  children: [
3921
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("rect", { x: "-55", y: "-18", width: "110", height: "36", rx: "8" }),
3922
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("text", { textAnchor: "middle", dominantBaseline: "middle", children: node.label.length > 16 ? `${node.label.slice(0, 15)}\u2026` : node.label })
4481
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("rect", { x: "-55", y: "-18", width: "110", height: "36", rx: "8" }),
4482
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("text", { textAnchor: "middle", dominantBaseline: "middle", children: node.label.length > 16 ? `${node.label.slice(0, 15)}\u2026` : node.label })
3923
4483
  ]
3924
4484
  },
3925
4485
  node.id
3926
4486
  ))
3927
4487
  ] }) }) }),
3928
- legend.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("ul", { className: "uix-relationship-graph__legend", "aria-label": "Relationship types", children: legend.map((item) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("li", { "data-type": item.id, children: item.label }, item.id)) }),
3929
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "uix-relationship-graph__list", role: "region", "aria-label": "Accessible relationship list", children: [
3930
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("h3", { children: "Relationship list" }),
3931
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("ul", { children: bounded.nodes.map((node) => {
4488
+ legend.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("ul", { className: "uix-relationship-graph__legend", "aria-label": "Relationship types", children: legend.map((item) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("li", { "data-type": item.id, children: item.label }, item.id)) }),
4489
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "uix-relationship-graph__list", role: "region", "aria-label": "Accessible relationship list", children: [
4490
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("h3", { children: "Relationship list" }),
4491
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("ul", { children: bounded.nodes.map((node) => {
3932
4492
  const neighbors = relationshipNeighbors(node.id, bounded.edges).map((id) => bounded.nodes.find((item) => item.id === id)?.label ?? id);
3933
- return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("li", { "data-selected": selectedId === node.id || void 0, children: [
3934
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", onClick: () => select(node.id), "aria-pressed": selectedId === node.id, children: [
3935
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("strong", { children: node.label }),
3936
- node.type && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { children: node.type }),
3937
- /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { children: neighbors.length ? `Connected to ${neighbors.join(", ")}` : "No visible connections" })
4493
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("li", { "data-selected": selectedId === node.id || void 0, children: [
4494
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", onClick: () => select(node.id), "aria-pressed": selectedId === node.id, children: [
4495
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("strong", { children: node.label }),
4496
+ node.type && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { children: node.type }),
4497
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { children: neighbors.length ? `Connected to ${neighbors.join(", ")}` : "No visible connections" })
3938
4498
  ] }),
3939
- /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "uix-relationship-graph__list-actions", children: [
3940
- onExpandNeighbors && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", onClick: () => onExpandNeighbors(node), children: "Expand neighbors" }),
3941
- onOpenDetails && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", onClick: () => onOpenDetails(node), children: "Open details" })
4499
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "uix-relationship-graph__list-actions", children: [
4500
+ onExpandNeighbors && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => onExpandNeighbors(node), children: "Expand neighbors" }),
4501
+ onOpenDetails && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => onOpenDetails(node), children: "Open details" })
3942
4502
  ] })
3943
4503
  ] }, node.id);
3944
4504
  }) })
@@ -3947,8 +4507,8 @@ function RelationshipGraph({
3947
4507
  }
3948
4508
 
3949
4509
  // src/components/MatchReview.tsx
3950
- var import_react33 = require("react");
3951
- var import_jsx_runtime61 = require("react/jsx-runtime");
4510
+ var import_react41 = require("react");
4511
+ var import_jsx_runtime63 = require("react/jsx-runtime");
3952
4512
  var valueText = (value) => value == null ? "\u2014" : typeof value === "string" ? value : JSON.stringify(value);
3953
4513
  function MatchReview({
3954
4514
  incoming,
@@ -3964,11 +4524,11 @@ function MatchReview({
3964
4524
  onRetry,
3965
4525
  className
3966
4526
  }) {
3967
- const [internalSelection, setInternalSelection] = (0, import_react33.useState)(/* @__PURE__ */ new Set());
3968
- const [announcement, setAnnouncement] = (0, import_react33.useState)("");
3969
- const [bulkPending, setBulkPending] = (0, import_react33.useState)(false);
4527
+ const [internalSelection, setInternalSelection] = (0, import_react41.useState)(/* @__PURE__ */ new Set());
4528
+ const [announcement, setAnnouncement] = (0, import_react41.useState)("");
4529
+ const [bulkPending, setBulkPending] = (0, import_react41.useState)(false);
3970
4530
  const selection = selectedIds ?? internalSelection;
3971
- const pending = (0, import_react33.useMemo)(() => candidates.filter((candidate) => candidate.status !== "resolved"), [candidates]);
4531
+ const pending = (0, import_react41.useMemo)(() => candidates.filter((candidate) => candidate.status !== "resolved"), [candidates]);
3972
4532
  const setSelection = (next) => {
3973
4533
  if (selectedIds === void 0) setInternalSelection(next);
3974
4534
  onSelectionChange?.(next);
@@ -3996,55 +4556,55 @@ function MatchReview({
3996
4556
  setBulkPending(false);
3997
4557
  }
3998
4558
  };
3999
- if (loading) return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: cx("uix-match-review uix-match-review--state", className), role: "status", children: "Loading match candidates\u2026" });
4000
- if (error) return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: cx("uix-match-review uix-match-review--state", className), role: "alert", children: [
4001
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { children: error }),
4002
- onRetry && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: "Try again" })
4559
+ if (loading) return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: cx("uix-match-review uix-match-review--state", className), role: "status", children: "Loading match candidates\u2026" });
4560
+ if (error) return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: cx("uix-match-review uix-match-review--state", className), role: "alert", children: [
4561
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { children: error }),
4562
+ onRetry && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: "Try again" })
4003
4563
  ] });
4004
- if (candidates.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: cx("uix-match-review uix-match-review--state", className), children: [
4005
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { children: "No candidate matches found." }),
4006
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { children: "Choose another record source or continue without a match." })
4564
+ if (candidates.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: cx("uix-match-review uix-match-review--state", className), children: [
4565
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { children: "No candidate matches found." }),
4566
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { children: "Choose another record source or continue without a match." })
4007
4567
  ] });
4008
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("section", { className: cx("uix-match-review", className), "aria-label": "Match review", children: [
4009
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "uix-match-review__summary", children: [
4010
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { children: [
4011
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("strong", { children: incomingLabel }),
4012
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { children: [
4568
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("section", { className: cx("uix-match-review", className), "aria-label": "Match review", children: [
4569
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uix-match-review__summary", children: [
4570
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { children: [
4571
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("strong", { children: incomingLabel }),
4572
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { children: [
4013
4573
  pending.length,
4014
4574
  " pending of ",
4015
4575
  candidates.length
4016
4576
  ] })
4017
4577
  ] }),
4018
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "uix-match-review__incoming", children: fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { children: [
4019
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("b", { children: field.label }),
4578
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "uix-match-review__incoming", children: fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { children: [
4579
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("b", { children: field.label }),
4020
4580
  field.render?.(incoming[field.id], incoming) ?? valueText(incoming[field.id])
4021
4581
  ] }, field.id)) })
4022
4582
  ] }),
4023
- onBulkDecision && /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "uix-match-review__bulk", "aria-label": "Bulk candidate actions", children: [
4024
- /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { children: [
4583
+ onBulkDecision && /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uix-match-review__bulk", "aria-label": "Bulk candidate actions", children: [
4584
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { children: [
4025
4585
  selection.size,
4026
4586
  " selected"
4027
4587
  ] }),
4028
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", disabled: selection.size === 0 || bulkPending, onClick: () => void runBulk("accept"), children: bulkPending ? "Applying\u2026" : "Accept selected" }),
4029
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", disabled: selection.size === 0 || bulkPending, onClick: () => void runBulk("dismiss"), children: bulkPending ? "Applying\u2026" : "Dismiss selected" })
4588
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", disabled: selection.size === 0 || bulkPending, onClick: () => void runBulk("accept"), children: bulkPending ? "Applying\u2026" : "Accept selected" }),
4589
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", disabled: selection.size === 0 || bulkPending, onClick: () => void runBulk("dismiss"), children: bulkPending ? "Applying\u2026" : "Dismiss selected" })
4030
4590
  ] }),
4031
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "uix-match-review__table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("table", { className: "uix-table uix-match-review__table", children: [
4032
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("caption", { className: "uix-visually-hidden", children: "Candidate matches and available decisions" }),
4033
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("tr", { children: [
4034
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("th", { scope: "col", children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "uix-visually-hidden", children: "Select" }) }),
4035
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("th", { scope: "col", children: "Confidence" }),
4036
- fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("th", { scope: "col", children: field.label }, field.id)),
4037
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("th", { scope: "col", children: "Status" }),
4038
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("th", { scope: "col", children: "Actions" })
4591
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "uix-match-review__table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("table", { className: "uix-table uix-match-review__table", children: [
4592
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("caption", { className: "uix-visually-hidden", children: "Candidate matches and available decisions" }),
4593
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("tr", { children: [
4594
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { scope: "col", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "uix-visually-hidden", children: "Select" }) }),
4595
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { scope: "col", children: "Confidence" }),
4596
+ fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { scope: "col", children: field.label }, field.id)),
4597
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { scope: "col", children: "Status" }),
4598
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("th", { scope: "col", children: "Actions" })
4039
4599
  ] }) }),
4040
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("tbody", { children: candidates.map((candidate) => {
4600
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("tbody", { children: candidates.map((candidate) => {
4041
4601
  const resolved = candidate.status === "resolved";
4042
- return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("tr", { "data-status": candidate.status ?? "pending", children: [
4043
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("input", { type: "checkbox", checked: selection.has(candidate.id), onChange: () => toggle(candidate.id), "aria-label": `Select candidate ${candidate.id}` }) }),
4044
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "uix-match-review__confidence", children: candidate.confidence == null ? "Not scored" : `${Math.round(candidate.confidence * 100)}%` }) }),
4045
- fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("td", { children: field.render?.(candidate.record[field.id], candidate.record) ?? valueText(candidate.record[field.id]) }, field.id)),
4046
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(StatusPill, { tone: resolved ? "success" : "warning", children: resolved ? candidate.decision ?? "Resolved" : "Pending" }) }),
4047
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "uix-match-review__actions", children: ["accept", "dismiss", "split", "pick-other"].map((action) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
4602
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("tr", { "data-status": candidate.status ?? "pending", children: [
4603
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("input", { type: "checkbox", checked: selection.has(candidate.id), onChange: () => toggle(candidate.id), "aria-label": `Select candidate ${candidate.id}` }) }),
4604
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "uix-match-review__confidence", children: candidate.confidence == null ? "Not scored" : `${Math.round(candidate.confidence * 100)}%` }) }),
4605
+ fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { children: field.render?.(candidate.record[field.id], candidate.record) ?? valueText(candidate.record[field.id]) }, field.id)),
4606
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(StatusPill, { tone: resolved ? "success" : "warning", children: resolved ? candidate.decision ?? "Resolved" : "Pending" }) }),
4607
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("div", { className: "uix-match-review__actions", children: ["accept", "dismiss", "split", "pick-other"].map((action) => /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4048
4608
  "button",
4049
4609
  {
4050
4610
  type: "button",
@@ -4058,12 +4618,12 @@ function MatchReview({
4058
4618
  ] }, candidate.id);
4059
4619
  }) })
4060
4620
  ] }) }),
4061
- /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { className: "uix-visually-hidden", "aria-live": "polite", children: announcement })
4621
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("p", { className: "uix-visually-hidden", "aria-live": "polite", children: announcement })
4062
4622
  ] });
4063
4623
  }
4064
4624
 
4065
4625
  // src/components/MetricInput.tsx
4066
- var import_react34 = require("react");
4626
+ var import_react42 = require("react");
4067
4627
 
4068
4628
  // src/metric-model.ts
4069
4629
  function decimals(value) {
@@ -4088,7 +4648,7 @@ function parseMetricValue(value) {
4088
4648
  }
4089
4649
 
4090
4650
  // src/components/MetricInput.tsx
4091
- var import_jsx_runtime62 = require("react/jsx-runtime");
4651
+ var import_jsx_runtime64 = require("react/jsx-runtime");
4092
4652
  var defaultMetricFormat = (input) => input == null ? "" : String(input);
4093
4653
  function MetricInput({
4094
4654
  value,
@@ -4107,11 +4667,11 @@ function MetricInput({
4107
4667
  className,
4108
4668
  id: providedId
4109
4669
  }) {
4110
- const generatedId = (0, import_react34.useId)();
4670
+ const generatedId = (0, import_react42.useId)();
4111
4671
  const id = providedId ?? generatedId;
4112
4672
  const errorId = `${id}-error`;
4113
- const [text, setText] = (0, import_react34.useState)(() => format(value));
4114
- (0, import_react34.useEffect)(() => setText(format(value)), [value, format]);
4673
+ const [text, setText] = (0, import_react42.useState)(() => format(value));
4674
+ (0, import_react42.useEffect)(() => setText(format(value)), [value, format]);
4115
4675
  const commit = (input) => {
4116
4676
  const parsed = parse(input);
4117
4677
  if (input.trim() === "" || parsed !== null) {
@@ -4137,10 +4697,10 @@ function MetricInput({
4137
4697
  const parsed = parse(event.currentTarget.value);
4138
4698
  setText(parsed === null && event.currentTarget.value.trim() !== "" ? format(value) : format(parsed));
4139
4699
  };
4140
- return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: cx("uix-metric-input", invalid && "uix-metric-input--invalid", className), children: [
4141
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("label", { className: "uix-field__label", htmlFor: id, children: label }),
4142
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "uix-metric-input__control", children: [
4143
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
4700
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: cx("uix-metric-input", invalid && "uix-metric-input--invalid", className), children: [
4701
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("label", { className: "uix-field__label", htmlFor: id, children: label }),
4702
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "uix-metric-input__control", children: [
4703
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
4144
4704
  Input,
4145
4705
  {
4146
4706
  id,
@@ -4159,22 +4719,22 @@ function MetricInput({
4159
4719
  readOnly
4160
4720
  }
4161
4721
  ),
4162
- unit && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { className: "uix-metric-input__unit", "aria-hidden": "true", children: unit }),
4163
- /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "uix-metric-input__steps", children: [
4164
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", className: "uix-metric-input__step", onClick: () => stepBy(1), disabled: disabled || readOnly, "aria-label": `Increase ${label}`, children: "+" }),
4165
- /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", className: "uix-metric-input__step", onClick: () => stepBy(-1), disabled: disabled || readOnly, "aria-label": `Decrease ${label}`, children: "\u2212" })
4722
+ unit && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "uix-metric-input__unit", "aria-hidden": "true", children: unit }),
4723
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "uix-metric-input__steps", children: [
4724
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", className: "uix-metric-input__step", onClick: () => stepBy(1), disabled: disabled || readOnly, "aria-label": `Increase ${label}`, children: "+" }),
4725
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", className: "uix-metric-input__step", onClick: () => stepBy(-1), disabled: disabled || readOnly, "aria-label": `Decrease ${label}`, children: "\u2212" })
4166
4726
  ] })
4167
4727
  ] }),
4168
- unit && /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "uix-visually-hidden", children: [
4728
+ unit && /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "uix-visually-hidden", children: [
4169
4729
  "Unit: ",
4170
4730
  unit
4171
4731
  ] }),
4172
- invalid && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { id: errorId, className: "uix-field__error", children: errorMessage })
4732
+ invalid && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { id: errorId, className: "uix-field__error", children: errorMessage })
4173
4733
  ] });
4174
4734
  }
4175
4735
 
4176
4736
  // src/components/LicensePositionBar.tsx
4177
- var import_jsx_runtime63 = require("react/jsx-runtime");
4737
+ var import_jsx_runtime65 = require("react/jsx-runtime");
4178
4738
  var defaultCapacityFormat = (value) => new Intl.NumberFormat().format(value);
4179
4739
  function LicensePositionBar({
4180
4740
  consumed,
@@ -4195,18 +4755,18 @@ function LicensePositionBar({
4195
4755
  const percent = safeEntitled === 0 ? safeConsumed > 0 ? 100 : 0 : safeConsumed / safeEntitled * 100;
4196
4756
  const format = (value) => `${formatValue(value)}${unit ? ` ${unit}` : ""}`;
4197
4757
  const summary = `${consumedLabel}: ${format(safeConsumed)}. ${entitledLabel}: ${format(safeEntitled)}. ${over > 0 ? `${format(over)} ${overLabel}` : `${format(available)} ${availableLabel}`}.`;
4198
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: cx("uix-license-position", over > 0 && "uix-license-position--over", className), ...props, children: [
4199
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uix-license-position__header", children: [
4200
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "uix-license-position__value", children: [
4758
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: cx("uix-license-position", over > 0 && "uix-license-position--over", className), ...props, children: [
4759
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "uix-license-position__header", children: [
4760
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("span", { className: "uix-license-position__value", children: [
4201
4761
  format(safeConsumed),
4202
4762
  " / ",
4203
4763
  format(safeEntitled)
4204
4764
  ] }),
4205
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(StatusPill, { tone: over > 0 ? "danger" : percent >= 80 ? "warning" : "success", children: over > 0 ? `${format(over)} ${overLabel}` : `${format(available)} ${availableLabel}` })
4765
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(StatusPill, { tone: over > 0 ? "danger" : percent >= 80 ? "warning" : "success", children: over > 0 ? `${format(over)} ${overLabel}` : `${format(available)} ${availableLabel}` })
4206
4766
  ] }),
4207
- /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uix-license-position__track", children: [
4208
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(Meter, { value: Math.min(100, percent), tone: over > 0 ? "danger" : percent >= 80 ? "warning" : "success", "aria-label": summary, "aria-valuetext": summary }),
4209
- over > 0 && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4767
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "uix-license-position__track", children: [
4768
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(Meter, { value: Math.min(100, percent), tone: over > 0 ? "danger" : percent >= 80 ? "warning" : "success", "aria-label": summary, "aria-valuetext": summary }),
4769
+ over > 0 && /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(
4210
4770
  "span",
4211
4771
  {
4212
4772
  className: "uix-license-position__overflow",
@@ -4215,12 +4775,12 @@ function LicensePositionBar({
4215
4775
  }
4216
4776
  )
4217
4777
  ] }),
4218
- /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "uix-visually-hidden", children: summary })
4778
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "uix-visually-hidden", children: summary })
4219
4779
  ] });
4220
4780
  }
4221
4781
 
4222
4782
  // src/components/BrandProfiles.tsx
4223
- var import_react36 = require("react");
4783
+ var import_react44 = require("react");
4224
4784
 
4225
4785
  // src/color-model.ts
4226
4786
  var clamp2 = (value, min, max) => Math.min(max, Math.max(min, value));
@@ -4289,8 +4849,8 @@ function meetsContrast(background, foreground, minimum = 4.5) {
4289
4849
  }
4290
4850
 
4291
4851
  // src/components/ColorPicker.tsx
4292
- var import_react35 = require("react");
4293
- var import_jsx_runtime64 = require("react/jsx-runtime");
4852
+ var import_react43 = require("react");
4853
+ var import_jsx_runtime66 = require("react/jsx-runtime");
4294
4854
  var EMPTY_COLORS = [];
4295
4855
  function ColorPicker({
4296
4856
  value,
@@ -4303,17 +4863,17 @@ function ColorPicker({
4303
4863
  disabled,
4304
4864
  className
4305
4865
  }) {
4306
- const id = (0, import_react35.useId)();
4307
- const triggerRef = (0, import_react35.useRef)(null);
4308
- const dialogRef = (0, import_react35.useRef)(null);
4309
- const [open, setOpen] = (0, import_react35.useState)(false);
4866
+ const id = (0, import_react43.useId)();
4867
+ const triggerRef = (0, import_react43.useRef)(null);
4868
+ const dialogRef = (0, import_react43.useRef)(null);
4869
+ const [open, setOpen] = (0, import_react43.useState)(false);
4310
4870
  const normalized = normalizeHex(value) ?? "#000000";
4311
- const [hexText, setHexText] = (0, import_react35.useState)(normalized);
4312
- const hsv = (0, import_react35.useMemo)(() => rgbToHsv(hexToRgb(normalized)), [normalized]);
4871
+ const [hexText, setHexText] = (0, import_react43.useState)(normalized);
4872
+ const hsv = (0, import_react43.useMemo)(() => rgbToHsv(hexToRgb(normalized)), [normalized]);
4313
4873
  const ratio = contrastRatio(normalized, foreground) ?? 0;
4314
4874
  const passes = ratio >= minimumContrast;
4315
- (0, import_react35.useEffect)(() => setHexText(normalized), [normalized]);
4316
- (0, import_react35.useEffect)(() => {
4875
+ (0, import_react43.useEffect)(() => setHexText(normalized), [normalized]);
4876
+ (0, import_react43.useEffect)(() => {
4317
4877
  if (!open) return;
4318
4878
  const dialog = dialogRef.current;
4319
4879
  dialog?.querySelector("input,button")?.focus();
@@ -4356,8 +4916,8 @@ function ColorPicker({
4356
4916
  if (next) onChange(next);
4357
4917
  };
4358
4918
  const sampleStyle = { backgroundColor: normalized };
4359
- return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: cx("uix-color-picker", className), children: [
4360
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
4919
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: cx("uix-color-picker", className), children: [
4920
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
4361
4921
  "button",
4362
4922
  {
4363
4923
  ref: triggerRef,
@@ -4369,12 +4929,12 @@ function ColorPicker({
4369
4929
  onClick: () => setOpen((current) => !current),
4370
4930
  disabled,
4371
4931
  children: [
4372
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "uix-color-picker__swatch", style: sampleStyle, "aria-hidden": "true" }),
4373
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { children: normalized })
4932
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "uix-color-picker__swatch", style: sampleStyle, "aria-hidden": "true" }),
4933
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children: normalized })
4374
4934
  ]
4375
4935
  }
4376
4936
  ),
4377
- open && /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
4937
+ open && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
4378
4938
  "div",
4379
4939
  {
4380
4940
  ref: dialogRef,
@@ -4385,57 +4945,57 @@ function ColorPicker({
4385
4945
  className: "uix-color-picker__popover",
4386
4946
  onKeyDown: onDialogKeyDown,
4387
4947
  children: [
4388
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { className: "uix-color-picker__preview", style: sampleStyle, children: /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { style: { color: foreground }, children: "Aa" }) }),
4389
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("label", { className: "uix-color-picker__range", children: [
4948
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "uix-color-picker__preview", style: sampleStyle, children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { style: { color: foreground }, children: "Aa" }) }),
4949
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("label", { className: "uix-color-picker__range", children: [
4390
4950
  "Hue ",
4391
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { children: [
4951
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { children: [
4392
4952
  Math.round(hsv.h),
4393
4953
  "\xB0"
4394
4954
  ] }),
4395
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("input", { type: "range", min: "0", max: "359", value: Math.round(hsv.h), onChange: (event) => updateHsv({ h: Number(event.currentTarget.value) }) })
4955
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("input", { type: "range", min: "0", max: "359", value: Math.round(hsv.h), onChange: (event) => updateHsv({ h: Number(event.currentTarget.value) }) })
4396
4956
  ] }),
4397
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("label", { className: "uix-color-picker__range", children: [
4957
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("label", { className: "uix-color-picker__range", children: [
4398
4958
  "Saturation ",
4399
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { children: [
4959
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { children: [
4400
4960
  Math.round(hsv.s * 100),
4401
4961
  "%"
4402
4962
  ] }),
4403
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("input", { type: "range", min: "0", max: "100", value: Math.round(hsv.s * 100), onChange: (event) => updateHsv({ s: Number(event.currentTarget.value) / 100 }) })
4963
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("input", { type: "range", min: "0", max: "100", value: Math.round(hsv.s * 100), onChange: (event) => updateHsv({ s: Number(event.currentTarget.value) / 100 }) })
4404
4964
  ] }),
4405
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("label", { className: "uix-color-picker__range", children: [
4965
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("label", { className: "uix-color-picker__range", children: [
4406
4966
  "Brightness ",
4407
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { children: [
4967
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { children: [
4408
4968
  Math.round(hsv.v * 100),
4409
4969
  "%"
4410
4970
  ] }),
4411
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("input", { type: "range", min: "0", max: "100", value: Math.round(hsv.v * 100), onChange: (event) => updateHsv({ v: Number(event.currentTarget.value) / 100 }) })
4971
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("input", { type: "range", min: "0", max: "100", value: Math.round(hsv.v * 100), onChange: (event) => updateHsv({ v: Number(event.currentTarget.value) / 100 }) })
4412
4972
  ] }),
4413
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("label", { className: "uix-color-picker__hex", children: [
4973
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("label", { className: "uix-color-picker__hex", children: [
4414
4974
  "Hex",
4415
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("span", { className: "uix-color-picker__hex-row", children: [
4416
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("input", { className: "uix-input", value: hexText, onChange: (event) => setHexText(event.currentTarget.value), onBlur: commitHex, onKeyDown: (event) => {
4975
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { className: "uix-color-picker__hex-row", children: [
4976
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("input", { className: "uix-input", value: hexText, onChange: (event) => setHexText(event.currentTarget.value), onBlur: commitHex, onKeyDown: (event) => {
4417
4977
  if (event.key === "Enter") commitHex();
4418
4978
  }, "aria-invalid": !normalizeHex(hexText) }),
4419
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", onClick: commitHex, disabled: !normalizeHex(hexText), children: "Set" })
4979
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", onClick: commitHex, disabled: !normalizeHex(hexText), children: "Set" })
4420
4980
  ] })
4421
4981
  ] }),
4422
- (presets.length > 0 || recent.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "uix-color-picker__palettes", children: [
4423
- presets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("fieldset", { children: [
4424
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("legend", { children: "Presets" }),
4425
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { children: presets.map((color) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", className: "uix-color-picker__preset", style: { backgroundColor: normalizeHex(color) ?? color }, onClick: () => choose(color), "aria-label": `Use preset ${color}` }, color)) })
4982
+ (presets.length > 0 || recent.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "uix-color-picker__palettes", children: [
4983
+ presets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("fieldset", { children: [
4984
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("legend", { children: "Presets" }),
4985
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { children: presets.map((color) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "uix-color-picker__preset", style: { backgroundColor: normalizeHex(color) ?? color }, onClick: () => choose(color), "aria-label": `Use preset ${color}` }, color)) })
4426
4986
  ] }),
4427
- recent.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("fieldset", { children: [
4428
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("legend", { children: "Recent" }),
4429
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { children: recent.map((color) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", className: "uix-color-picker__preset", style: { backgroundColor: normalizeHex(color) ?? color }, onClick: () => choose(color), "aria-label": `Use recent color ${color}` }, color)) })
4987
+ recent.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("fieldset", { children: [
4988
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("legend", { children: "Recent" }),
4989
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { children: recent.map((color) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "uix-color-picker__preset", style: { backgroundColor: normalizeHex(color) ?? color }, onClick: () => choose(color), "aria-label": `Use recent color ${color}` }, color)) })
4430
4990
  ] })
4431
4991
  ] }),
4432
- /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("p", { className: cx("uix-color-picker__contrast", passes ? "uix-color-picker__contrast--pass" : "uix-color-picker__contrast--fail"), role: "status", "aria-live": "polite", children: [
4992
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("p", { className: cx("uix-color-picker__contrast", passes ? "uix-color-picker__contrast--pass" : "uix-color-picker__contrast--fail"), role: "status", "aria-live": "polite", children: [
4433
4993
  "Contrast ",
4434
4994
  ratio.toFixed(2),
4435
4995
  ":1 \u2014 ",
4436
4996
  passes ? `passes WCAG AA (${minimumContrast}:1)` : `does not meet WCAG AA (${minimumContrast}:1)`
4437
4997
  ] }),
4438
- /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary uix-btn--sm", onClick: close, children: "Done" })
4998
+ /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary uix-btn--sm", onClick: close, children: "Done" })
4439
4999
  ]
4440
5000
  }
4441
5001
  )
@@ -4443,7 +5003,7 @@ function ColorPicker({
4443
5003
  }
4444
5004
 
4445
5005
  // src/components/BrandProfiles.tsx
4446
- var import_jsx_runtime65 = require("react/jsx-runtime");
5006
+ var import_jsx_runtime67 = require("react/jsx-runtime");
4447
5007
  var PROFILE_PROPERTIES = {
4448
5008
  brand: "--uix-brand",
4449
5009
  brandForeground: "--uix-brand-fg",
@@ -4512,7 +5072,7 @@ function BrandProfileEditor({
4512
5072
  colorPresets = EMPTY_COLORS2,
4513
5073
  className
4514
5074
  }) {
4515
- const [announcement, setAnnouncement] = (0, import_react36.useState)("");
5075
+ const [announcement, setAnnouncement] = (0, import_react44.useState)("");
4516
5076
  const update = (patch) => onChange({ ...value, ...patch });
4517
5077
  const apply = () => {
4518
5078
  if (applyTarget !== null) applyBrandProfile(value, applyTarget);
@@ -4529,54 +5089,54 @@ function BrandProfileEditor({
4529
5089
  ...value.typography?.sans ? { "--uix-font-sans": value.typography.sans } : {},
4530
5090
  ...value.typography?.heading ? { "--uix-font-heading": value.typography.heading } : {}
4531
5091
  };
4532
- return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("section", { className: cx("uix-brand-profiles", className), "aria-label": "Brand profile editor", children: [
4533
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "uix-brand-profiles__form", children: [
4534
- profiles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("label", { className: "uix-field__label", children: [
5092
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("section", { className: cx("uix-brand-profiles", className), "aria-label": "Brand profile editor", children: [
5093
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "uix-brand-profiles__form", children: [
5094
+ profiles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("label", { className: "uix-field__label", children: [
4535
5095
  "Profile",
4536
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("select", { className: "uix-select", value: value.id, onChange: (event) => {
5096
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("select", { className: "uix-select", value: value.id, onChange: (event) => {
4537
5097
  const selected = profiles.find((profile) => profile.id === event.currentTarget.value);
4538
5098
  if (selected) onSelectProfile?.(selected);
4539
- }, children: profiles.map((profile) => /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("option", { value: profile.id, children: profile.name }, profile.id)) })
5099
+ }, children: profiles.map((profile) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("option", { value: profile.id, children: profile.name }, profile.id)) })
4540
5100
  ] }),
4541
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("label", { className: "uix-field__label", children: [
5101
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("label", { className: "uix-field__label", children: [
4542
5102
  "Name",
4543
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("input", { className: "uix-input", value: value.name, onChange: (event) => update({ name: event.currentTarget.value }) })
5103
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("input", { className: "uix-input", value: value.name, onChange: (event) => update({ name: event.currentTarget.value }) })
4544
5104
  ] }),
4545
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "uix-brand-profiles__colors", children: [
4546
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("label", { children: [
5105
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "uix-brand-profiles__colors", children: [
5106
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("label", { children: [
4547
5107
  "Brand",
4548
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(ColorPicker, { label: "Brand color", value: value.brand, foreground: value.brandForeground, presets: colorPresets, onChange: (brand) => update({ brand }) })
5108
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(ColorPicker, { label: "Brand color", value: value.brand, foreground: value.brandForeground, presets: colorPresets, onChange: (brand) => update({ brand }) })
4549
5109
  ] }),
4550
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("label", { children: [
5110
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("label", { children: [
4551
5111
  "On brand",
4552
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(ColorPicker, { label: "Brand foreground color", value: value.brandForeground, foreground: value.brand, presets: colorPresets, onChange: (brandForeground) => update({ brandForeground }) })
5112
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(ColorPicker, { label: "Brand foreground color", value: value.brandForeground, foreground: value.brand, presets: colorPresets, onChange: (brandForeground) => update({ brandForeground }) })
4553
5113
  ] })
4554
5114
  ] }),
4555
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("label", { className: "uix-field__label", children: [
5115
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("label", { className: "uix-field__label", children: [
4556
5116
  "Body font",
4557
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("input", { className: "uix-input", value: value.typography?.sans ?? "", onChange: (event) => update({ typography: { ...value.typography, sans: event.currentTarget.value || void 0 } }) })
5117
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("input", { className: "uix-input", value: value.typography?.sans ?? "", onChange: (event) => update({ typography: { ...value.typography, sans: event.currentTarget.value || void 0 } }) })
4558
5118
  ] }),
4559
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("label", { className: "uix-field__label", children: [
5119
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("label", { className: "uix-field__label", children: [
4560
5120
  "Heading font",
4561
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("input", { className: "uix-input", value: value.typography?.heading ?? "", onChange: (event) => update({ typography: { ...value.typography, heading: event.currentTarget.value || void 0 } }) })
5121
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("input", { className: "uix-input", value: value.typography?.heading ?? "", onChange: (event) => update({ typography: { ...value.typography, heading: event.currentTarget.value || void 0 } }) })
4562
5122
  ] }),
4563
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("label", { className: "uix-file-upload uix-brand-profiles__upload", children: [
5123
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("label", { className: "uix-file-upload uix-brand-profiles__upload", children: [
4564
5124
  "Logo file",
4565
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("input", { type: "file", accept: "image/*", onChange: onFile })
5125
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("input", { type: "file", accept: "image/*", onChange: onFile })
4566
5126
  ] }),
4567
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary", onClick: apply, children: "Apply profile" }),
4568
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "uix-visually-hidden", "aria-live": "polite", children: announcement })
5127
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary", onClick: apply, children: "Apply profile" }),
5128
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "uix-visually-hidden", "aria-live": "polite", children: announcement })
4569
5129
  ] }),
4570
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "uix-brand-profiles__preview", style: previewStyle, "aria-label": `Live preview of ${value.name}`, children: [
4571
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "uix-brand-profiles__preview-header", children: [
4572
- value.logo ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("img", { src: value.logo.src, alt: value.logo.alt }) : /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { className: "uix-brand-profiles__logo-placeholder", children: "Logo" }),
4573
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("strong", { children: value.name || "Brand preview" })
5130
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "uix-brand-profiles__preview", style: previewStyle, "aria-label": `Live preview of ${value.name}`, children: [
5131
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "uix-brand-profiles__preview-header", children: [
5132
+ value.logo ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("img", { src: value.logo.src, alt: value.logo.alt }) : /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "uix-brand-profiles__logo-placeholder", children: "Logo" }),
5133
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("strong", { children: value.name || "Brand preview" })
4574
5134
  ] }),
4575
- /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "uix-brand-profiles__preview-body", children: [
4576
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("h3", { children: "Readable, serializable branding" }),
4577
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("p", { children: "Accent, links, rings, and muted states continue through the existing UIx token chain." }),
4578
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary", children: "Primary action" }),
4579
- /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("a", { href: "#brand-profile-preview", children: "Preview link" })
5135
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "uix-brand-profiles__preview-body", children: [
5136
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("h3", { children: "Readable, serializable branding" }),
5137
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("p", { children: "Accent, links, rings, and muted states continue through the existing UIx token chain." }),
5138
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary", children: "Primary action" }),
5139
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("a", { href: "#brand-profile-preview", children: "Preview link" })
4580
5140
  ] })
4581
5141
  ] })
4582
5142
  ] });
@@ -4584,7 +5144,7 @@ function BrandProfileEditor({
4584
5144
  var BrandProfiles = BrandProfileEditor;
4585
5145
 
4586
5146
  // src/components/DiffViewer.tsx
4587
- var import_react37 = require("react");
5147
+ var import_react45 = require("react");
4588
5148
 
4589
5149
  // src/diff-model.ts
4590
5150
  function isJsonObject(value) {
@@ -4635,7 +5195,7 @@ function summarizeDiff(entries, resolutions = {}) {
4635
5195
  }
4636
5196
 
4637
5197
  // src/components/DiffViewer.tsx
4638
- var import_jsx_runtime66 = require("react/jsx-runtime");
5198
+ var import_jsx_runtime68 = require("react/jsx-runtime");
4639
5199
  var GROUPS = [
4640
5200
  { kind: "conflicted", label: "Conflicted" },
4641
5201
  { kind: "changed", label: "Changed" },
@@ -4654,65 +5214,65 @@ function DiffViewer({
4654
5214
  labels = DEFAULT_LABELS,
4655
5215
  className
4656
5216
  }) {
4657
- const id = (0, import_react37.useId)();
4658
- const entries = (0, import_react37.useMemo)(() => providedEntries ?? buildThreeWayDiff(base, current, incoming), [providedEntries, base, current, incoming]);
4659
- const [internalResolutions, setInternalResolutions] = (0, import_react37.useState)({});
5217
+ const id = (0, import_react45.useId)();
5218
+ const entries = (0, import_react45.useMemo)(() => providedEntries ?? buildThreeWayDiff(base, current, incoming), [providedEntries, base, current, incoming]);
5219
+ const [internalResolutions, setInternalResolutions] = (0, import_react45.useState)({});
4660
5220
  const resolutions = controlledResolutions ?? internalResolutions;
4661
5221
  const summary = summarizeDiff(entries, resolutions);
4662
5222
  const resolve2 = (path, resolution) => {
4663
5223
  if (controlledResolutions === void 0) setInternalResolutions((currentState) => ({ ...currentState, [path]: resolution }));
4664
5224
  onResolutionChange?.(path, resolution);
4665
5225
  };
4666
- if (entries.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("section", { className: cx("uix-diff-viewer uix-diff-viewer--empty", className), "aria-label": "Configuration differences", children: [
4667
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("h3", { children: "No differences" }),
4668
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("p", { children: "Base, current, and incoming values are aligned." })
5226
+ if (entries.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("section", { className: cx("uix-diff-viewer uix-diff-viewer--empty", className), "aria-label": "Configuration differences", children: [
5227
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("h3", { children: "No differences" }),
5228
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("p", { children: "Base, current, and incoming values are aligned." })
4669
5229
  ] });
4670
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("section", { className: cx("uix-diff-viewer", className), "aria-label": "Configuration differences", children: [
4671
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "uix-diff-viewer__summary", "aria-label": "Difference summary", children: [
4672
- GROUPS.map((group) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { children: [
4673
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("b", { children: summary[group.kind] }),
5230
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("section", { className: cx("uix-diff-viewer", className), "aria-label": "Configuration differences", children: [
5231
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "uix-diff-viewer__summary", "aria-label": "Difference summary", children: [
5232
+ GROUPS.map((group) => /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { children: [
5233
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("b", { children: summary[group.kind] }),
4674
5234
  " ",
4675
5235
  group.label.toLowerCase()
4676
5236
  ] }, group.kind)),
4677
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { children: [
4678
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("b", { children: summary.resolved }),
5237
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { children: [
5238
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("b", { children: summary.resolved }),
4679
5239
  " resolved"
4680
5240
  ] }),
4681
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { children: [
4682
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("b", { children: summary.pending }),
5241
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { children: [
5242
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("b", { children: summary.pending }),
4683
5243
  " pending"
4684
5244
  ] })
4685
5245
  ] }),
4686
5246
  GROUPS.map((group) => {
4687
5247
  const grouped = entries.filter((entry) => entry.kind === group.kind);
4688
5248
  if (!grouped.length) return null;
4689
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("section", { className: "uix-diff-viewer__group", "aria-labelledby": `${id}-${group.kind}`, children: [
4690
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("h3", { id: `${id}-${group.kind}`, children: [
5249
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("section", { className: "uix-diff-viewer__group", "aria-labelledby": `${id}-${group.kind}`, children: [
5250
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("h3", { id: `${id}-${group.kind}`, children: [
4691
5251
  group.label,
4692
5252
  " ",
4693
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { children: grouped.length })
5253
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: grouped.length })
4694
5254
  ] }),
4695
5255
  grouped.map((entry) => {
4696
5256
  const resolution = resolutions[entry.path] ?? "pending";
4697
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("details", { className: "uix-diff-viewer__entry", "data-kind": entry.kind, open: entry.kind === "conflicted", children: [
4698
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("summary", { children: [
4699
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("code", { children: entry.path }),
4700
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(StatusPill, { tone: resolution === "pending" ? "warning" : "success", children: resolution })
5257
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("details", { className: "uix-diff-viewer__entry", "data-kind": entry.kind, open: entry.kind === "conflicted", children: [
5258
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("summary", { children: [
5259
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("code", { children: entry.path }),
5260
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(StatusPill, { tone: resolution === "pending" ? "warning" : "success", children: resolution })
4701
5261
  ] }),
4702
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "uix-diff-viewer__versions", children: ["base", "current", "incoming"].map((version) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { role: "region", "aria-label": `${labels[version] ?? `${version[0].toUpperCase()}${version.slice(1)}`} value for ${entry.path}`, children: [
4703
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("strong", { children: labels[version] ?? `${version[0].toUpperCase()}${version.slice(1)}` }),
4704
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("pre", { children: renderValue(entry[version]) })
5262
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "uix-diff-viewer__versions", children: ["base", "current", "incoming"].map((version) => /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { role: "region", "aria-label": `${labels[version] ?? `${version[0].toUpperCase()}${version.slice(1)}`} value for ${entry.path}`, children: [
5263
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("strong", { children: labels[version] ?? `${version[0].toUpperCase()}${version.slice(1)}` }),
5264
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("pre", { children: renderValue(entry[version]) })
4705
5265
  ] }, version)) }),
4706
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "uix-diff-viewer__actions", "aria-label": `Resolve ${entry.path}`, children: [
4707
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary uix-btn--sm", "aria-pressed": resolution === "accept", onClick: () => resolve2(entry.path, "accept"), children: "Accept incoming" }),
4708
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", "aria-pressed": resolution === "skip", onClick: () => resolve2(entry.path, "skip"), children: "Keep current" }),
4709
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", "aria-pressed": resolution === "pending", onClick: () => resolve2(entry.path, "pending"), children: "Mark pending" })
5266
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "uix-diff-viewer__actions", "aria-label": `Resolve ${entry.path}`, children: [
5267
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary uix-btn--sm", "aria-pressed": resolution === "accept", onClick: () => resolve2(entry.path, "accept"), children: "Accept incoming" }),
5268
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", "aria-pressed": resolution === "skip", onClick: () => resolve2(entry.path, "skip"), children: "Keep current" }),
5269
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", "aria-pressed": resolution === "pending", onClick: () => resolve2(entry.path, "pending"), children: "Mark pending" })
4710
5270
  ] })
4711
5271
  ] }, entry.path);
4712
5272
  })
4713
5273
  ] }, group.kind);
4714
5274
  }),
4715
- /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("p", { className: "uix-visually-hidden", "aria-live": "polite", children: [
5275
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("p", { className: "uix-visually-hidden", "aria-live": "polite", children: [
4716
5276
  summary.resolved,
4717
5277
  " of ",
4718
5278
  entries.length,
@@ -4769,6 +5329,8 @@ function DiffViewer({
4769
5329
  Field,
4770
5330
  FilterPopover,
4771
5331
  FilteredEmptyState,
5332
+ Flow,
5333
+ FlowNode,
4772
5334
  ForbiddenState,
4773
5335
  Highlighted,
4774
5336
  Inbox,
@@ -4801,6 +5363,8 @@ function DiffViewer({
4801
5363
  PageIntro,
4802
5364
  Pagination,
4803
5365
  Peek,
5366
+ Pipeline,
5367
+ PipelineStage,
4804
5368
  Popover,
4805
5369
  Progress,
4806
5370
  PromptDialog,
@@ -4832,6 +5396,7 @@ function DiffViewer({
4832
5396
  SubNavItem,
4833
5397
  Switch,
4834
5398
  Tab,
5399
+ TabPanel,
4835
5400
  Table,
4836
5401
  TableWrap,
4837
5402
  Tabs,