@tensor_1/react 2.16.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.
- package/dist/chart-preset.cjs +15 -3
- package/dist/chart.cjs +15 -3
- package/dist/components/Alert.js +15 -7
- package/dist/components/AppShell.d.ts +3 -1
- package/dist/components/AppShell.js +3 -1
- package/dist/components/Avatar.js +2 -1
- package/dist/components/Button.js +32 -16
- package/dist/components/Card.d.ts +3 -1
- package/dist/components/Card.js +2 -2
- package/dist/components/ChartCore.js +15 -3
- package/dist/components/CommandPalette.d.ts +4 -2
- package/dist/components/CommandPalette.js +66 -13
- package/dist/components/Comments.d.ts +5 -1
- package/dist/components/Comments.js +1 -1
- package/dist/components/Composer.d.ts +8 -1
- package/dist/components/Composer.js +7 -2
- package/dist/components/DetailLayout.js +1 -1
- package/dist/components/Drawer.d.ts +3 -4
- package/dist/components/Drawer.js +6 -4
- package/dist/components/Field.js +6 -3
- package/dist/components/Inbox.d.ts +13 -3
- package/dist/components/Inbox.js +62 -3
- package/dist/components/Input.d.ts +13 -2
- package/dist/components/Input.js +20 -5
- package/dist/components/Kanban.d.ts +15 -3
- package/dist/components/Kanban.js +42 -10
- package/dist/components/Meter.d.ts +3 -1
- package/dist/components/Meter.js +9 -1
- package/dist/components/Modal.d.ts +4 -5
- package/dist/components/Modal.js +4 -4
- package/dist/components/NavFavourites.js +11 -0
- package/dist/components/PageHeader.d.ts +3 -1
- package/dist/components/PageHeader.js +2 -2
- package/dist/components/Peek.d.ts +3 -4
- package/dist/components/Peek.js +9 -6
- package/dist/components/Progress.d.ts +3 -1
- package/dist/components/Progress.js +5 -3
- package/dist/components/Radio.d.ts +3 -1
- package/dist/components/Radio.js +6 -2
- package/dist/components/Spinner.d.ts +3 -1
- package/dist/components/Spinner.js +3 -3
- package/dist/components/Stat.js +5 -1
- package/dist/components/States.d.ts +1 -0
- package/dist/components/States.js +7 -1
- package/dist/components/Table.d.ts +8 -1
- package/dist/components/Table.js +10 -6
- package/dist/components/Tabs.d.ts +13 -1
- package/dist/components/Tabs.js +79 -4
- package/dist/components/Timeline.d.ts +3 -3
- package/dist/components/Timeline.js +3 -3
- package/dist/components/Toast.js +42 -5
- package/dist/components/Tooltip.d.ts +3 -1
- package/dist/components/Tooltip.js +44 -5
- package/dist/components/Tree.d.ts +2 -0
- package/dist/components/Tree.js +26 -4
- package/dist/hooks/useDialog.d.ts +1 -1
- package/dist/hooks/useDialog.js +17 -2
- package/dist/hooks/useTable.d.ts +5 -0
- package/dist/hooks/useTable.js +20 -1
- package/dist/index.cjs +693 -243
- package/dist/index.d.cts +125 -35
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -1
- package/dist/tree-model.d.ts +4 -0
- package/dist/tree-model.js +8 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -134,6 +134,7 @@ __export(src_exports, {
|
|
|
134
134
|
SubNavItem: () => SubNavItem,
|
|
135
135
|
Switch: () => Switch,
|
|
136
136
|
Tab: () => Tab,
|
|
137
|
+
TabPanel: () => TabPanel,
|
|
137
138
|
Table: () => Table,
|
|
138
139
|
TableWrap: () => TableWrap,
|
|
139
140
|
Tabs: () => Tabs,
|
|
@@ -257,8 +258,10 @@ function unlockBodyScroll() {
|
|
|
257
258
|
saved = null;
|
|
258
259
|
}
|
|
259
260
|
}
|
|
260
|
-
function useDialog(open) {
|
|
261
|
+
function useDialog(open, onClose) {
|
|
261
262
|
const ref = (0, import_react.useRef)(null);
|
|
263
|
+
const onCloseRef = (0, import_react.useRef)(onClose);
|
|
264
|
+
onCloseRef.current = onClose;
|
|
262
265
|
(0, import_react.useEffect)(() => {
|
|
263
266
|
const el = ref.current;
|
|
264
267
|
if (!el || !open) {
|
|
@@ -267,8 +270,21 @@ function useDialog(open) {
|
|
|
267
270
|
}
|
|
268
271
|
if (!el.open) el.showModal();
|
|
269
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);
|
|
270
282
|
return () => {
|
|
271
|
-
|
|
283
|
+
el.removeEventListener("close", handleClose);
|
|
284
|
+
if (locked) {
|
|
285
|
+
locked = false;
|
|
286
|
+
unlockBodyScroll();
|
|
287
|
+
}
|
|
272
288
|
if (el.open) el.close();
|
|
273
289
|
};
|
|
274
290
|
}, [open]);
|
|
@@ -541,6 +557,24 @@ function useTable(data, options = {}) {
|
|
|
541
557
|
const toggleAllRows = (0, import_react2.useCallback)(() => setSelected((s) => togglePage(s, pageIds)), [pageIds]);
|
|
542
558
|
const clearSelection = (0, import_react2.useCallback)(() => setSelected(/* @__PURE__ */ new Set()), []);
|
|
543
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
|
+
}, []);
|
|
544
578
|
const view = (0, import_react2.useMemo)(() => ({ sort, filters, q: query }), [sort, filters, query]);
|
|
545
579
|
const viewQueryString = (0, import_react2.useMemo)(() => serializeView(view), [view]);
|
|
546
580
|
const applyView = (0, import_react2.useCallback)((queryString) => {
|
|
@@ -557,6 +591,7 @@ function useTable(data, options = {}) {
|
|
|
557
591
|
selected,
|
|
558
592
|
pinned,
|
|
559
593
|
selectAll,
|
|
594
|
+
announcement,
|
|
560
595
|
toggleSort: doToggleSort,
|
|
561
596
|
setSort,
|
|
562
597
|
setFilters,
|
|
@@ -726,24 +761,40 @@ function useAnchoredPosition(anchor, floatingRef, { open, placement = "bottom-st
|
|
|
726
761
|
// src/components/Button.tsx
|
|
727
762
|
var import_react5 = require("react");
|
|
728
763
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
764
|
+
var warnedIconButton = false;
|
|
729
765
|
var Button = (0, import_react5.forwardRef)(
|
|
730
|
-
({ variant = "secondary", size = "md", icon = false, loading = false, className, children, disabled, ...props }, ref) =>
|
|
731
|
-
"
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
className: cx(
|
|
735
|
-
"uix-btn",
|
|
736
|
-
`uix-btn--${variant}`,
|
|
737
|
-
size !== "md" && `uix-btn--${size}`,
|
|
738
|
-
icon && "uix-btn--icon",
|
|
739
|
-
className
|
|
740
|
-
),
|
|
741
|
-
disabled: disabled || loading,
|
|
742
|
-
"data-loading": loading || void 0,
|
|
743
|
-
...props,
|
|
744
|
-
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.");
|
|
745
770
|
}
|
|
746
|
-
|
|
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
|
+
}
|
|
747
798
|
);
|
|
748
799
|
Button.displayName = "Button";
|
|
749
800
|
function ButtonGroup({ children, className }) {
|
|
@@ -766,7 +817,22 @@ var Input = (0, import_react6.forwardRef)(
|
|
|
766
817
|
)
|
|
767
818
|
);
|
|
768
819
|
Input.displayName = "Input";
|
|
769
|
-
function InputGroup({
|
|
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;
|
|
770
836
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
771
837
|
"div",
|
|
772
838
|
{
|
|
@@ -777,9 +843,9 @@ function InputGroup({ children, leadingIcon, trailingIcon, className }) {
|
|
|
777
843
|
className
|
|
778
844
|
),
|
|
779
845
|
children: [
|
|
780
|
-
leadingIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "uix-input-group__icon", children: leadingIcon }),
|
|
781
|
-
|
|
782
|
-
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 })
|
|
783
849
|
]
|
|
784
850
|
}
|
|
785
851
|
);
|
|
@@ -986,8 +1052,12 @@ var Radio = (0, import_react11.forwardRef)(
|
|
|
986
1052
|
] })
|
|
987
1053
|
);
|
|
988
1054
|
Radio.displayName = "Radio";
|
|
989
|
-
function RadioGroup({ children, className }) {
|
|
990
|
-
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
|
+
] });
|
|
991
1061
|
}
|
|
992
1062
|
|
|
993
1063
|
// src/components/Switch.tsx
|
|
@@ -1009,14 +1079,17 @@ function Field({ label, hint, error, success, required, children, className, htm
|
|
|
1009
1079
|
const uid = (0, import_react13.useId)();
|
|
1010
1080
|
const msgId = `${uid}-msg`;
|
|
1011
1081
|
const describedBy = error || success || hint ? msgId : void 0;
|
|
1082
|
+
const controlId = (0, import_react13.isValidElement)(children) ? children.props.id ?? `${uid}-ctl` : void 0;
|
|
1012
1083
|
const control = (0, import_react13.isValidElement)(children) ? (0, import_react13.cloneElement)(children, {
|
|
1084
|
+
id: controlId,
|
|
1013
1085
|
"aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0,
|
|
1014
|
-
"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)
|
|
1015
1088
|
}) : children;
|
|
1016
1089
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: cx("uix-field", className), children: [
|
|
1017
|
-
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 }),
|
|
1018
1091
|
control,
|
|
1019
|
-
/* @__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 })
|
|
1020
1093
|
] });
|
|
1021
1094
|
}
|
|
1022
1095
|
|
|
@@ -1024,12 +1097,12 @@ function Field({ label, hint, error, success, required, children, className, htm
|
|
|
1024
1097
|
var import_react14 = require("react");
|
|
1025
1098
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1026
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" }) });
|
|
1027
|
-
function Modal({ open, onClose, title, children, footer, className,
|
|
1028
|
-
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);
|
|
1029
1102
|
const titleId = (0, import_react14.useId)();
|
|
1030
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("dialog", { ref, className: cx("uix-dialog", className),
|
|
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: [
|
|
1031
1104
|
(title != null || onClose) && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "uix-dialog__header", children: [
|
|
1032
|
-
title && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("
|
|
1105
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: "uix-dialog__title", id: titleId, children: title }),
|
|
1033
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, {}) })
|
|
1034
1107
|
] }),
|
|
1035
1108
|
children != null && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "uix-dialog__body", children }),
|
|
@@ -1087,13 +1160,15 @@ function PromptDialog({ open, title, description, inputLabel, defaultValue = "",
|
|
|
1087
1160
|
}
|
|
1088
1161
|
|
|
1089
1162
|
// src/components/Drawer.tsx
|
|
1163
|
+
var import_react16 = require("react");
|
|
1090
1164
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1091
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" }) });
|
|
1092
|
-
function Drawer({ open, onClose, title, children, footer, className }) {
|
|
1093
|
-
const ref = useDialog(open);
|
|
1094
|
-
|
|
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: [
|
|
1095
1170
|
(title != null || onClose) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "uix-drawer__header", children: [
|
|
1096
|
-
title && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("
|
|
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 }),
|
|
1097
1172
|
onClose && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1098
1173
|
"button",
|
|
1099
1174
|
{
|
|
@@ -1110,27 +1185,30 @@ function Drawer({ open, onClose, title, children, footer, className }) {
|
|
|
1110
1185
|
}
|
|
1111
1186
|
|
|
1112
1187
|
// src/components/Peek.tsx
|
|
1188
|
+
var import_react17 = require("react");
|
|
1113
1189
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1114
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" }) });
|
|
1115
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" }) });
|
|
1116
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" }) });
|
|
1117
|
-
function Peek({ open, onClose, title, children, footer, onNavPrev, onNavNext, hint, className }) {
|
|
1118
|
-
const ref = useDialog(open);
|
|
1193
|
+
function Peek({ open, onClose, title, children, footer, onNavPrev, onNavNext, hint, className, onClick, ...rest }) {
|
|
1194
|
+
const ref = useDialog(open, onClose);
|
|
1119
1195
|
const hasNav = onNavPrev != null || onNavNext != null;
|
|
1196
|
+
const titleId = (0, import_react17.useId)();
|
|
1120
1197
|
const onBackdropClick = (e) => {
|
|
1198
|
+
onClick?.(e);
|
|
1121
1199
|
if (!onClose || e.target !== e.currentTarget) return;
|
|
1122
1200
|
const r = e.currentTarget.getBoundingClientRect();
|
|
1123
1201
|
if (r.width === 0) return;
|
|
1124
1202
|
const outside = e.clientX < r.left || e.clientX > r.right || e.clientY < r.top || e.clientY > r.bottom;
|
|
1125
1203
|
if (outside) onClose();
|
|
1126
1204
|
};
|
|
1127
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("dialog", { ref, className: cx("uix-peek", className),
|
|
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: [
|
|
1128
1206
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "uix-peek__header", children: [
|
|
1129
1207
|
hasNav && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "uix-peek__nav", children: [
|
|
1130
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { className: "uix-peek__navbtn", onClick: onNavPrev, disabled:
|
|
1131
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { className: "uix-peek__navbtn", onClick: onNavNext, disabled:
|
|
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, {}) })
|
|
1132
1210
|
] }),
|
|
1133
|
-
title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("
|
|
1211
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { className: "uix-peek__title", id: titleId, children: title }),
|
|
1134
1212
|
hint && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "uix-peek__hint", children: hint }),
|
|
1135
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, {}) })
|
|
1136
1214
|
] }),
|
|
@@ -1141,12 +1219,12 @@ function Peek({ open, onClose, title, children, footer, onNavPrev, onNavNext, hi
|
|
|
1141
1219
|
|
|
1142
1220
|
// src/components/Card.tsx
|
|
1143
1221
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1144
|
-
function Card({ title, subtitle, headerAction, footer, children, className, ...props }) {
|
|
1222
|
+
function Card({ title, titleAs: TitleTag = "div", subtitle, headerAction, footer, children, className, ...props }) {
|
|
1145
1223
|
const hasHeader = title != null || subtitle != null || headerAction != null;
|
|
1146
1224
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: cx("uix-card", className), ...props, children: [
|
|
1147
1225
|
hasHeader && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "uix-card__header", children: [
|
|
1148
1226
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { flex: 1 }, children: [
|
|
1149
|
-
title && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1227
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TitleTag, { className: "uix-card__title", children: title }),
|
|
1150
1228
|
subtitle && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "uix-card__subtitle", children: subtitle })
|
|
1151
1229
|
] }),
|
|
1152
1230
|
headerAction
|
|
@@ -1171,12 +1249,12 @@ function CardLink({ title, subtitle, headerAction, footer, children, className,
|
|
|
1171
1249
|
}
|
|
1172
1250
|
|
|
1173
1251
|
// src/components/Breadcrumbs.tsx
|
|
1174
|
-
var
|
|
1252
|
+
var import_react18 = require("react");
|
|
1175
1253
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1176
1254
|
function Breadcrumbs({ items, label, separator = "/", className, ...props }) {
|
|
1177
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) => {
|
|
1178
1256
|
const current = item.current ?? index === items.length - 1;
|
|
1179
|
-
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1257
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_react18.Fragment, { children: [
|
|
1180
1258
|
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("li", { className: "uix-breadcrumbs__sep", "aria-hidden": "true", children: separator }),
|
|
1181
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 }) })
|
|
1182
1260
|
] }, item.id ?? `${item.href ?? "current"}-${index}`);
|
|
@@ -1185,11 +1263,11 @@ function Breadcrumbs({ items, label, separator = "/", className, ...props }) {
|
|
|
1185
1263
|
|
|
1186
1264
|
// src/components/PageHeader.tsx
|
|
1187
1265
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1188
|
-
function PageHeader({ eyebrow, title, subtitle, actions, className, ...props }) {
|
|
1266
|
+
function PageHeader({ eyebrow, title, subtitle, actions, as: TitleTag = "h1", className, ...props }) {
|
|
1189
1267
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("header", { className: cx("uix-page-header", className), ...props, children: [
|
|
1190
1268
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "uix-page-header__titles", children: [
|
|
1191
1269
|
eyebrow != null && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "uix-page-header__eyebrow", children: eyebrow }),
|
|
1192
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1270
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TitleTag, { className: "uix-page-header__title", children: title }),
|
|
1193
1271
|
subtitle != null && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "uix-page-header__subtitle", children: subtitle })
|
|
1194
1272
|
] }),
|
|
1195
1273
|
actions != null && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "uix-page-header__actions", children: actions })
|
|
@@ -1201,7 +1279,7 @@ var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
|
1201
1279
|
function DetailLayout({ side, children, className, ...props }) {
|
|
1202
1280
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: cx("uix-detail", className), ...props, children: [
|
|
1203
1281
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "uix-detail__main", children }),
|
|
1204
|
-
side != null && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("
|
|
1282
|
+
side != null && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("aside", { className: "uix-detail__side", children: side })
|
|
1205
1283
|
] });
|
|
1206
1284
|
}
|
|
1207
1285
|
|
|
@@ -1278,11 +1356,11 @@ function ListItem({ title, meta, trail, leading, children, className, ...props }
|
|
|
1278
1356
|
}
|
|
1279
1357
|
|
|
1280
1358
|
// src/components/DescriptionList.tsx
|
|
1281
|
-
var
|
|
1359
|
+
var import_react19 = require("react");
|
|
1282
1360
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1283
1361
|
function DescriptionList({ items, children, className, ...props }) {
|
|
1284
1362
|
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("dl", { className: cx("uix-dl", className), ...props, children: [
|
|
1285
|
-
items?.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
1363
|
+
items?.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react19.Fragment, { children: [
|
|
1286
1364
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("dt", { children: item.term }),
|
|
1287
1365
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("dd", { children: item.description })
|
|
1288
1366
|
] }, item.id ?? i)),
|
|
@@ -1297,22 +1375,81 @@ function DescriptionItem({ term, children }) {
|
|
|
1297
1375
|
}
|
|
1298
1376
|
|
|
1299
1377
|
// src/components/Tabs.tsx
|
|
1300
|
-
var
|
|
1378
|
+
var import_react20 = require("react");
|
|
1301
1379
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1302
|
-
var TabsCtx = (0,
|
|
1380
|
+
var TabsCtx = (0, import_react20.createContext)({});
|
|
1303
1381
|
function Tabs({ variant = "line", value, onChange, children, className }) {
|
|
1304
|
-
const
|
|
1305
|
-
|
|
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
|
+
] });
|
|
1306
1440
|
}
|
|
1307
1441
|
function Tab({ value, children, disabled, className, onClick, ...props }) {
|
|
1308
|
-
const ctx = (0,
|
|
1442
|
+
const ctx = (0, import_react20.useContext)(TabsCtx);
|
|
1309
1443
|
const selected = ctx.value === value;
|
|
1310
1444
|
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1311
1445
|
"button",
|
|
1312
1446
|
{
|
|
1313
1447
|
role: "tab",
|
|
1448
|
+
id: ctx.baseId ? `${ctx.baseId}-tab-${value}` : void 0,
|
|
1449
|
+
"aria-controls": ctx.baseId ? `${ctx.baseId}-panel-${value}` : void 0,
|
|
1314
1450
|
className: cx("uix-tab", className),
|
|
1315
1451
|
"aria-selected": selected,
|
|
1452
|
+
tabIndex: selected ? 0 : -1,
|
|
1316
1453
|
disabled,
|
|
1317
1454
|
onClick: (e) => {
|
|
1318
1455
|
ctx.onChange?.(value);
|
|
@@ -1323,9 +1460,24 @@ function Tab({ value, children, disabled, className, onClick, ...props }) {
|
|
|
1323
1460
|
}
|
|
1324
1461
|
);
|
|
1325
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
|
+
}
|
|
1326
1478
|
|
|
1327
1479
|
// src/components/AppShell.tsx
|
|
1328
|
-
var
|
|
1480
|
+
var import_react21 = require("react");
|
|
1329
1481
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1330
1482
|
function AppShell({
|
|
1331
1483
|
nav,
|
|
@@ -1333,6 +1485,7 @@ function AppShell({
|
|
|
1333
1485
|
focus,
|
|
1334
1486
|
onExitFocus,
|
|
1335
1487
|
mainBleed,
|
|
1488
|
+
mainId = "uix-main",
|
|
1336
1489
|
sidebar,
|
|
1337
1490
|
topbar,
|
|
1338
1491
|
children,
|
|
@@ -1340,7 +1493,7 @@ function AppShell({
|
|
|
1340
1493
|
...props
|
|
1341
1494
|
}) {
|
|
1342
1495
|
const navState = nav ?? (collapsed ? "rail" : "full");
|
|
1343
|
-
(0,
|
|
1496
|
+
(0, import_react21.useEffect)(() => {
|
|
1344
1497
|
if (!focus || !onExitFocus) return;
|
|
1345
1498
|
const onKey = (e) => {
|
|
1346
1499
|
if (e.key === "Escape") onExitFocus();
|
|
@@ -1357,9 +1510,10 @@ function AppShell({
|
|
|
1357
1510
|
"data-focus": focus || void 0,
|
|
1358
1511
|
...props,
|
|
1359
1512
|
children: [
|
|
1513
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("a", { className: "uix-skiplink", href: `#${mainId}`, children: "Skip to content" }),
|
|
1360
1514
|
sidebar && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "uix-shell__sidebar", children: sidebar }),
|
|
1361
1515
|
topbar && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "uix-shell__topbar", children: topbar }),
|
|
1362
|
-
/* @__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 }),
|
|
1363
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" }) })
|
|
1364
1518
|
]
|
|
1365
1519
|
}
|
|
@@ -1367,7 +1521,7 @@ function AppShell({
|
|
|
1367
1521
|
}
|
|
1368
1522
|
|
|
1369
1523
|
// src/components/Sidebar.tsx
|
|
1370
|
-
var
|
|
1524
|
+
var import_react22 = require("react");
|
|
1371
1525
|
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1372
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" }) });
|
|
1373
1527
|
function Sidebar({ collapsed, nav, onToggle, brand, toggleIcon, children, expandLabel = "Expand sidebar", collapseLabel = "Collapse sidebar", className, ...props }) {
|
|
@@ -1423,12 +1577,12 @@ function NavItem({ icon, badge, active, as: Tag = "a", children, className, ...p
|
|
|
1423
1577
|
);
|
|
1424
1578
|
}
|
|
1425
1579
|
function NavGroup({ icon, label, children, defaultExpanded = true, expanded: controlledExpanded, onExpandedChange }) {
|
|
1426
|
-
const [internalExpanded, setInternalExpanded] = (0,
|
|
1580
|
+
const [internalExpanded, setInternalExpanded] = (0, import_react22.useState)(defaultExpanded);
|
|
1427
1581
|
const expanded = controlledExpanded ?? internalExpanded;
|
|
1428
|
-
const panelId = (0,
|
|
1429
|
-
const triggerRef = (0,
|
|
1430
|
-
const panelRef = (0,
|
|
1431
|
-
(0,
|
|
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)(() => {
|
|
1432
1586
|
panelRef.current?.toggleAttribute("inert", !expanded);
|
|
1433
1587
|
if (!expanded && panelRef.current?.contains(document.activeElement)) triggerRef.current?.focus();
|
|
1434
1588
|
}, [expanded]);
|
|
@@ -1507,7 +1661,7 @@ function StarButton({
|
|
|
1507
1661
|
}
|
|
1508
1662
|
|
|
1509
1663
|
// src/components/NavFavourites.tsx
|
|
1510
|
-
var
|
|
1664
|
+
var import_react23 = require("react");
|
|
1511
1665
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1512
1666
|
var ChevronDownIcon = () => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
1513
1667
|
"svg",
|
|
@@ -1570,13 +1724,14 @@ function NavFavourites({
|
|
|
1570
1724
|
emptyReason,
|
|
1571
1725
|
className
|
|
1572
1726
|
}) {
|
|
1573
|
-
const regionId = (0,
|
|
1574
|
-
const headerRef = (0,
|
|
1575
|
-
const regionRef = (0,
|
|
1576
|
-
const
|
|
1577
|
-
const
|
|
1578
|
-
const
|
|
1579
|
-
(0,
|
|
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)(() => {
|
|
1580
1735
|
const id = focusAfterRef.current;
|
|
1581
1736
|
if (!id) return;
|
|
1582
1737
|
focusAfterRef.current = null;
|
|
@@ -1593,7 +1748,7 @@ function NavFavourites({
|
|
|
1593
1748
|
}
|
|
1594
1749
|
onToggleCollapsed?.();
|
|
1595
1750
|
};
|
|
1596
|
-
const move = (0,
|
|
1751
|
+
const move = (0, import_react23.useCallback)((id, dir) => {
|
|
1597
1752
|
const idx = order.indexOf(id);
|
|
1598
1753
|
const next = idx + dir;
|
|
1599
1754
|
if (idx < 0 || next < 0 || next >= order.length) return;
|
|
@@ -1602,19 +1757,22 @@ function NavFavourites({
|
|
|
1602
1757
|
if (it === void 0) return;
|
|
1603
1758
|
reordered.splice(next, 0, it);
|
|
1604
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}`);
|
|
1605
1762
|
onReorder(reordered);
|
|
1606
1763
|
}, [onReorder, order]);
|
|
1607
|
-
const remove = (0,
|
|
1764
|
+
const remove = (0, import_react23.useCallback)((id) => {
|
|
1608
1765
|
const idx = order.indexOf(id);
|
|
1609
1766
|
const neighbour = order[idx + 1] ?? order[idx - 1] ?? null;
|
|
1610
1767
|
focusAfterRef.current = neighbour;
|
|
1611
1768
|
onRemove(id);
|
|
1612
1769
|
}, [onRemove, order]);
|
|
1613
|
-
const registerTrigger = (0,
|
|
1770
|
+
const registerTrigger = (0, import_react23.useCallback)((id, element) => {
|
|
1614
1771
|
if (element) triggerRefs.current.set(id, element);
|
|
1615
1772
|
else triggerRefs.current.delete(id);
|
|
1616
1773
|
}, []);
|
|
1617
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 }),
|
|
1618
1776
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
1619
1777
|
"button",
|
|
1620
1778
|
{
|
|
@@ -1661,7 +1819,7 @@ function NavFavourites({
|
|
|
1661
1819
|
)
|
|
1662
1820
|
] });
|
|
1663
1821
|
}
|
|
1664
|
-
var FavouriteRow = (0,
|
|
1822
|
+
var FavouriteRow = (0, import_react23.memo)(function FavouriteRow2({
|
|
1665
1823
|
item,
|
|
1666
1824
|
isFirst,
|
|
1667
1825
|
isLast,
|
|
@@ -1670,17 +1828,17 @@ var FavouriteRow = (0, import_react21.memo)(function FavouriteRow2({
|
|
|
1670
1828
|
onRemove,
|
|
1671
1829
|
registerTrigger
|
|
1672
1830
|
}) {
|
|
1673
|
-
const [open, setOpen] = (0,
|
|
1674
|
-
const menuId = (0,
|
|
1675
|
-
const triggerRef = (0,
|
|
1676
|
-
const itemRefs = (0,
|
|
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)([]);
|
|
1677
1835
|
const optionsTemplate = labels.options ?? "{label} favourite options";
|
|
1678
1836
|
const actions = [
|
|
1679
1837
|
...isFirst ? [] : [{ label: labels.moveUp, onSelect: () => onMove(item.id, -1) }],
|
|
1680
1838
|
...isLast ? [] : [{ label: labels.moveDown, onSelect: () => onMove(item.id, 1) }],
|
|
1681
1839
|
{ label: labels.remove.replace("{label}", item.label), onSelect: () => onRemove(item.id) }
|
|
1682
1840
|
];
|
|
1683
|
-
(0,
|
|
1841
|
+
(0, import_react23.useEffect)(() => {
|
|
1684
1842
|
if (open) itemRefs.current[0]?.focus();
|
|
1685
1843
|
}, [open]);
|
|
1686
1844
|
const closeAndReturnFocus = () => {
|
|
@@ -1696,6 +1854,12 @@ var FavouriteRow = (0, import_react21.memo)(function FavouriteRow2({
|
|
|
1696
1854
|
} else if (e.key === "ArrowUp") {
|
|
1697
1855
|
e.preventDefault();
|
|
1698
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();
|
|
1699
1863
|
} else if (e.key === "Escape") {
|
|
1700
1864
|
e.preventDefault();
|
|
1701
1865
|
closeAndReturnFocus();
|
|
@@ -1754,6 +1918,7 @@ var FavouriteRow = (0, import_react21.memo)(function FavouriteRow2({
|
|
|
1754
1918
|
{
|
|
1755
1919
|
id: menuId,
|
|
1756
1920
|
role: "menu",
|
|
1921
|
+
"aria-label": optionsTemplate.replace("{label}", item.label),
|
|
1757
1922
|
onKeyDown: onMenuKeyDown,
|
|
1758
1923
|
className: "uix-favourites__menu",
|
|
1759
1924
|
children: actions.map((action, i) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("li", { role: "presentation", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
@@ -1785,61 +1950,108 @@ var FavouriteRow = (0, import_react21.memo)(function FavouriteRow2({
|
|
|
1785
1950
|
// src/components/Alert.tsx
|
|
1786
1951
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1787
1952
|
function Alert({ tone, title, icon, children, className, ...props }) {
|
|
1788
|
-
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
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
|
+
);
|
|
1795
1968
|
}
|
|
1796
1969
|
|
|
1797
1970
|
// src/components/Spinner.tsx
|
|
1798
1971
|
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1799
|
-
function Spinner({ size = "md", accent, className, ...props }) {
|
|
1972
|
+
function Spinner({ size = "md", accent, label, className, ...props }) {
|
|
1800
1973
|
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1801
1974
|
"span",
|
|
1802
1975
|
{
|
|
1803
1976
|
className: cx("uix-spinner", accent && "uix-spinner--accent", size === "lg" && "uix-spinner--lg", className),
|
|
1804
1977
|
role: "status",
|
|
1805
|
-
|
|
1806
|
-
|
|
1978
|
+
...props,
|
|
1979
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "uix-visually-hidden", children: label ?? "Loading\u2026" })
|
|
1807
1980
|
}
|
|
1808
1981
|
);
|
|
1809
1982
|
}
|
|
1810
1983
|
|
|
1811
1984
|
// src/components/Toast.tsx
|
|
1985
|
+
var import_react24 = require("react");
|
|
1812
1986
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1987
|
+
var ToasterContext = (0, import_react24.createContext)(null);
|
|
1813
1988
|
function Toast({ title, message, tone, icon, onClose, leaving, className, ...props }) {
|
|
1814
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;
|
|
1815
2010
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
1816
2011
|
"div",
|
|
1817
2012
|
{
|
|
1818
2013
|
className: cx("uix-toast", tone && `uix-toast--${tone}`, className),
|
|
1819
2014
|
"data-leaving": leaving || void 0,
|
|
1820
|
-
role: assertive ? "alert" : "status",
|
|
1821
|
-
"aria-live": assertive ? "assertive" : "polite",
|
|
2015
|
+
role: ownLiveRegion ? assertive ? "alert" : "status" : void 0,
|
|
2016
|
+
"aria-live": ownLiveRegion ? assertive ? "assertive" : "polite" : void 0,
|
|
1822
2017
|
...props,
|
|
1823
2018
|
children: [
|
|
1824
2019
|
icon && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "uix-toast__icon", "aria-hidden": "true", children: icon }),
|
|
1825
|
-
/* @__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: [
|
|
1826
2021
|
title && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "uix-toast__title", children: title }),
|
|
1827
2022
|
message && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "uix-toast__msg", children: message })
|
|
1828
2023
|
] }),
|
|
1829
|
-
onClose && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { className: "uix-toast__close", onClick:
|
|
2024
|
+
onClose && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { className: "uix-toast__close", onClick: handleClose, "aria-label": "Dismiss", children: "\xD7" })
|
|
1830
2025
|
]
|
|
1831
2026
|
}
|
|
1832
2027
|
);
|
|
1833
2028
|
}
|
|
1834
2029
|
function Toaster({ children, className, ...props }) {
|
|
1835
|
-
|
|
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
|
+
] }) });
|
|
1836
2045
|
}
|
|
1837
2046
|
|
|
1838
2047
|
// src/components/Table.tsx
|
|
1839
|
-
var
|
|
2048
|
+
var import_react25 = require("react");
|
|
1840
2049
|
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1841
|
-
var TableWrap = (0,
|
|
1842
|
-
return /* @__PURE__ */ (0, import_jsx_runtime32.
|
|
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
|
+
] });
|
|
1843
2055
|
});
|
|
1844
2056
|
function Table({
|
|
1845
2057
|
density = "standard",
|
|
@@ -1878,9 +2090,9 @@ function Th({ sortable, sortDirection, sortOrder, onSort, className, children, o
|
|
|
1878
2090
|
"data-sort": sortable || void 0,
|
|
1879
2091
|
"data-sort-order": sortOrder != null && sortOrder > 0 ? sortOrder : void 0,
|
|
1880
2092
|
"aria-sort": sortDirection && sortDirection !== "none" ? sortDirection : void 0,
|
|
1881
|
-
onClick: sortable
|
|
2093
|
+
onClick: sortable && onSort ? void 0 : onClick,
|
|
1882
2094
|
...props,
|
|
1883
|
-
children
|
|
2095
|
+
children: sortable ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "button", className: "uix-th__sortbtn", onClick: onSort, children }) : children
|
|
1884
2096
|
}
|
|
1885
2097
|
);
|
|
1886
2098
|
}
|
|
@@ -1892,7 +2104,7 @@ function Tr({ selected, pinned, className, children, ...props }) {
|
|
|
1892
2104
|
"tr",
|
|
1893
2105
|
{
|
|
1894
2106
|
className,
|
|
1895
|
-
"
|
|
2107
|
+
"data-selected": selected || void 0,
|
|
1896
2108
|
"data-pinned": pinned || void 0,
|
|
1897
2109
|
...props,
|
|
1898
2110
|
children
|
|
@@ -1915,13 +2127,14 @@ function RowActions({ children, className, ...props }) {
|
|
|
1915
2127
|
function RowAction({ children, className, type = "button", ...props }) {
|
|
1916
2128
|
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type, className: cx("uix-rowact", className), ...props, children });
|
|
1917
2129
|
}
|
|
1918
|
-
function ExpandToggle({ expanded, className, type = "button", ...props }) {
|
|
2130
|
+
function ExpandToggle({ expanded, controls, className, type = "button", ...props }) {
|
|
1919
2131
|
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1920
2132
|
"button",
|
|
1921
2133
|
{
|
|
1922
2134
|
type,
|
|
1923
2135
|
className: cx("uix-table__expand", className),
|
|
1924
2136
|
"aria-expanded": expanded,
|
|
2137
|
+
"aria-controls": controls,
|
|
1925
2138
|
"aria-label": expanded ? "Collapse row" : "Expand row",
|
|
1926
2139
|
...props,
|
|
1927
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" }) })
|
|
@@ -2012,15 +2225,17 @@ function StatusPill({ tone = "neutral", treatment = "filled", dot, children, cla
|
|
|
2012
2225
|
|
|
2013
2226
|
// src/components/Progress.tsx
|
|
2014
2227
|
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
2015
|
-
function Progress({ value = 0, max = 100, indeterminate, className, ...props }) {
|
|
2016
|
-
const
|
|
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;
|
|
2017
2231
|
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
2018
2232
|
"div",
|
|
2019
2233
|
{
|
|
2020
2234
|
role: "progressbar",
|
|
2021
2235
|
"aria-valuemin": 0,
|
|
2022
2236
|
"aria-valuemax": max,
|
|
2023
|
-
"aria-valuenow": indeterminate ? void 0 :
|
|
2237
|
+
"aria-valuenow": indeterminate ? void 0 : clamped,
|
|
2238
|
+
"aria-label": label,
|
|
2024
2239
|
className: cx("uix-progress", indeterminate && "uix-progress--indeterminate", className),
|
|
2025
2240
|
...props,
|
|
2026
2241
|
children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "uix-progress__bar", style: indeterminate ? void 0 : { width: `${pct}%` } })
|
|
@@ -2030,7 +2245,13 @@ function Progress({ value = 0, max = 100, indeterminate, className, ...props })
|
|
|
2030
2245
|
|
|
2031
2246
|
// src/components/Meter.tsx
|
|
2032
2247
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
2033
|
-
|
|
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 }) {
|
|
2034
2255
|
const pct = Math.max(0, Math.min(100, value));
|
|
2035
2256
|
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2036
2257
|
"div",
|
|
@@ -2039,6 +2260,8 @@ function Meter({ value = 0, tone, className, ...props }) {
|
|
|
2039
2260
|
"aria-valuenow": pct,
|
|
2040
2261
|
"aria-valuemin": 0,
|
|
2041
2262
|
"aria-valuemax": 100,
|
|
2263
|
+
"aria-valuetext": tone && tone !== "success" ? `${pct}%, ${toneText[tone]}` : void 0,
|
|
2264
|
+
"aria-label": label,
|
|
2042
2265
|
className: cx("uix-meter", className),
|
|
2043
2266
|
...props,
|
|
2044
2267
|
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
@@ -2063,22 +2286,34 @@ function Stat({ label, value, icon, meta, trend, className, ...props }) {
|
|
|
2063
2286
|
] }),
|
|
2064
2287
|
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "uix-stat__value", children: value }),
|
|
2065
2288
|
(meta != null || trend != null) && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "uix-stat__meta", children: [
|
|
2066
|
-
trend != null && /* @__PURE__ */ (0, import_jsx_runtime37.
|
|
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
|
+
] }),
|
|
2067
2294
|
meta
|
|
2068
2295
|
] })
|
|
2069
2296
|
] });
|
|
2070
2297
|
}
|
|
2071
2298
|
|
|
2072
2299
|
// src/components/Tooltip.tsx
|
|
2073
|
-
var
|
|
2300
|
+
var import_react26 = require("react");
|
|
2074
2301
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2075
2302
|
function Tooltip({ label, placement = "top", className, children, ...props }) {
|
|
2076
|
-
const triggerRef = (0,
|
|
2077
|
-
const bubbleRef = (0,
|
|
2078
|
-
const
|
|
2079
|
-
const
|
|
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)();
|
|
2080
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
|
+
};
|
|
2081
2315
|
const show = () => {
|
|
2316
|
+
cancelClose();
|
|
2082
2317
|
const b = bubbleRef.current;
|
|
2083
2318
|
if (b && !b.matches(":popover-open")) {
|
|
2084
2319
|
try {
|
|
@@ -2089,6 +2324,7 @@ function Tooltip({ label, placement = "top", className, children, ...props }) {
|
|
|
2089
2324
|
setOpen(true);
|
|
2090
2325
|
};
|
|
2091
2326
|
const hide = () => {
|
|
2327
|
+
cancelClose();
|
|
2092
2328
|
const b = bubbleRef.current;
|
|
2093
2329
|
if (b && b.matches(":popover-open")) {
|
|
2094
2330
|
try {
|
|
@@ -2098,7 +2334,20 @@ function Tooltip({ label, placement = "top", className, children, ...props }) {
|
|
|
2098
2334
|
}
|
|
2099
2335
|
setOpen(false);
|
|
2100
2336
|
};
|
|
2101
|
-
|
|
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);
|
|
2102
2351
|
const b = bubbleRef.current;
|
|
2103
2352
|
if (b && b.matches(":popover-open")) {
|
|
2104
2353
|
try {
|
|
@@ -2108,14 +2357,19 @@ function Tooltip({ label, placement = "top", className, children, ...props }) {
|
|
|
2108
2357
|
}
|
|
2109
2358
|
}, []);
|
|
2110
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;
|
|
2111
2364
|
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
2112
2365
|
"span",
|
|
2113
2366
|
{
|
|
2114
2367
|
ref: triggerRef,
|
|
2115
2368
|
className: cx("uix-tooltip", className),
|
|
2116
|
-
"aria-describedby": id,
|
|
2369
|
+
"aria-describedby": single ? void 0 : id,
|
|
2370
|
+
tabIndex: single ? void 0 : 0,
|
|
2117
2371
|
onMouseEnter: show,
|
|
2118
|
-
onMouseLeave:
|
|
2372
|
+
onMouseLeave: scheduleHide,
|
|
2119
2373
|
onFocus: show,
|
|
2120
2374
|
onBlur: hide,
|
|
2121
2375
|
onKeyDown: (e) => {
|
|
@@ -2123,8 +2377,20 @@ function Tooltip({ label, placement = "top", className, children, ...props }) {
|
|
|
2123
2377
|
},
|
|
2124
2378
|
...props,
|
|
2125
2379
|
children: [
|
|
2126
|
-
|
|
2127
|
-
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
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
|
+
)
|
|
2128
2394
|
]
|
|
2129
2395
|
}
|
|
2130
2396
|
);
|
|
@@ -2184,11 +2450,17 @@ function Skeleton({ variant = "block", width, height, className, style, ...props
|
|
|
2184
2450
|
);
|
|
2185
2451
|
}
|
|
2186
2452
|
function LoadingState({ rows = 3, density = "comfortable", label, className, ...props }) {
|
|
2187
|
-
return
|
|
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
|
+
);
|
|
2188
2460
|
}
|
|
2189
2461
|
|
|
2190
2462
|
// src/components/RelativeTime.tsx
|
|
2191
|
-
var
|
|
2463
|
+
var import_react27 = require("react");
|
|
2192
2464
|
|
|
2193
2465
|
// src/relative-time-model.ts
|
|
2194
2466
|
function parseDateValue(value) {
|
|
@@ -2251,12 +2523,12 @@ function RelativeTime({
|
|
|
2251
2523
|
}) {
|
|
2252
2524
|
const interval = refreshInterval === false ? 0 : Math.max(0, refreshInterval);
|
|
2253
2525
|
const fixedNow = now == null ? void 0 : new Date(now).getTime();
|
|
2254
|
-
const subscribe = (0,
|
|
2526
|
+
const subscribe = (0, import_react27.useCallback)((listener) => fixedNow == null ? subscribeRelativeClock(interval, listener) : () => {
|
|
2255
2527
|
}, [fixedNow, interval]);
|
|
2256
|
-
const getSnapshot = (0,
|
|
2257
|
-
const getServerSnapshot = (0,
|
|
2258
|
-
const clock = (0,
|
|
2259
|
-
const date = (0,
|
|
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]);
|
|
2260
2532
|
if (!date) return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("time", { "data-invalid": "true", suppressHydrationWarning: true, ...props, children: invalidLabel });
|
|
2261
2533
|
const current = new Date(clock);
|
|
2262
2534
|
const content = formatter ? formatter({ date, now: current, locale, timeZone }) : (() => {
|
|
@@ -2305,7 +2577,8 @@ var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
|
2305
2577
|
function Avatar({ size = "md", src, alt, children, status, className, ...props }) {
|
|
2306
2578
|
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: cx("uix-avatar", size !== "md" && `uix-avatar--${size}`, className), ...props, children: [
|
|
2307
2579
|
src ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("img", { src, alt: alt ?? "" }) : children,
|
|
2308
|
-
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" })
|
|
2309
2582
|
] });
|
|
2310
2583
|
}
|
|
2311
2584
|
function AvatarGroup({ children, className, ...props }) {
|
|
@@ -2325,7 +2598,7 @@ function UserChip({ avatar, name, sub, className, children, ...props }) {
|
|
|
2325
2598
|
// src/components/Comments.tsx
|
|
2326
2599
|
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2327
2600
|
function Comments({ children, className, ...props }) {
|
|
2328
|
-
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 });
|
|
2329
2602
|
}
|
|
2330
2603
|
function Comment({ avatar, author, meta, children, className, ...props }) {
|
|
2331
2604
|
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: cx("uix-comment", className), ...props, children: [
|
|
@@ -2342,20 +2615,25 @@ function Comment({ avatar, author, meta, children, className, ...props }) {
|
|
|
2342
2615
|
}
|
|
2343
2616
|
|
|
2344
2617
|
// src/components/Composer.tsx
|
|
2618
|
+
var import_react28 = require("react");
|
|
2345
2619
|
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2346
|
-
function Composer({ children, className, ...props }) {
|
|
2347
|
-
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
|
+
}) });
|
|
2348
2626
|
}
|
|
2349
2627
|
function ComposerBar({ children, className, ...props }) {
|
|
2350
2628
|
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: cx("uix-composer__bar", className), ...props, children });
|
|
2351
2629
|
}
|
|
2352
2630
|
|
|
2353
2631
|
// src/components/Segmented.tsx
|
|
2354
|
-
var
|
|
2632
|
+
var import_react29 = require("react");
|
|
2355
2633
|
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2356
|
-
var SegmentedCtx = (0,
|
|
2634
|
+
var SegmentedCtx = (0, import_react29.createContext)({});
|
|
2357
2635
|
function Segmented({ value, onChange, children, className, ...props }) {
|
|
2358
|
-
const contextValue = (0,
|
|
2636
|
+
const contextValue = (0, import_react29.useMemo)(() => ({ value, onChange }), [value, onChange]);
|
|
2359
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 }) });
|
|
2360
2638
|
}
|
|
2361
2639
|
function SegmentedOption({
|
|
@@ -2365,7 +2643,7 @@ function SegmentedOption({
|
|
|
2365
2643
|
onClick,
|
|
2366
2644
|
...props
|
|
2367
2645
|
}) {
|
|
2368
|
-
const ctx = (0,
|
|
2646
|
+
const ctx = (0, import_react29.useContext)(SegmentedCtx);
|
|
2369
2647
|
const selected = ctx.value === value;
|
|
2370
2648
|
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2371
2649
|
"button",
|
|
@@ -2384,12 +2662,12 @@ function SegmentedOption({
|
|
|
2384
2662
|
}
|
|
2385
2663
|
|
|
2386
2664
|
// src/components/TableControls.tsx
|
|
2387
|
-
var
|
|
2665
|
+
var import_react30 = require("react");
|
|
2388
2666
|
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2389
2667
|
function ViewMenu({ density, densityLabel, densityOptions, onDensityChange, zebra, freeze, columns, columnsLabel, onColumnVisibilityChange }) {
|
|
2390
|
-
const densityLabelId = (0,
|
|
2391
|
-
const zebraLabelId = (0,
|
|
2392
|
-
const freezeLabelId = (0,
|
|
2668
|
+
const densityLabelId = (0, import_react30.useId)();
|
|
2669
|
+
const zebraLabelId = (0, import_react30.useId)();
|
|
2670
|
+
const freezeLabelId = (0, import_react30.useId)();
|
|
2393
2671
|
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "uix-view-menu", children: [
|
|
2394
2672
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "uix-view-menu__group", children: [
|
|
2395
2673
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { id: densityLabelId, className: "uix-view-menu__label", children: densityLabel }),
|
|
@@ -2438,11 +2716,11 @@ function SavedViewMenu({ items, onSelect, onPinChange, pinLabel, unpinLabel, emp
|
|
|
2438
2716
|
// src/components/Timeline.tsx
|
|
2439
2717
|
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2440
2718
|
function Timeline({ children, className, ...props }) {
|
|
2441
|
-
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("
|
|
2719
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("ol", { className: cx("uix-timeline", className), ...props, children });
|
|
2442
2720
|
}
|
|
2443
2721
|
function TimelineItem({ node, meta, children, className, ...props }) {
|
|
2444
|
-
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("
|
|
2445
|
-
/* @__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: [
|
|
2446
2724
|
node ?? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "uix-timeline__node" }),
|
|
2447
2725
|
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "uix-timeline__line" })
|
|
2448
2726
|
] }),
|
|
@@ -2454,10 +2732,10 @@ function TimelineItem({ node, meta, children, className, ...props }) {
|
|
|
2454
2732
|
}
|
|
2455
2733
|
|
|
2456
2734
|
// src/components/Pipeline.tsx
|
|
2457
|
-
var
|
|
2735
|
+
var import_react31 = require("react");
|
|
2458
2736
|
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
2459
2737
|
function Pipeline({ detailed = false, children, className, tabIndex, ...props }) {
|
|
2460
|
-
const stages = detailed ?
|
|
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;
|
|
2461
2739
|
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2462
2740
|
"ol",
|
|
2463
2741
|
{
|
|
@@ -2573,7 +2851,7 @@ function Note({ tone, icon, children, className, ...props }) {
|
|
|
2573
2851
|
}
|
|
2574
2852
|
|
|
2575
2853
|
// src/components/Popover.tsx
|
|
2576
|
-
var
|
|
2854
|
+
var import_react32 = require("react");
|
|
2577
2855
|
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
2578
2856
|
function Popover({
|
|
2579
2857
|
popover = "auto",
|
|
@@ -2584,15 +2862,15 @@ function Popover({
|
|
|
2584
2862
|
children,
|
|
2585
2863
|
...props
|
|
2586
2864
|
}) {
|
|
2587
|
-
const ref = (0,
|
|
2588
|
-
const [open, setOpen] = (0,
|
|
2865
|
+
const ref = (0, import_react32.useRef)(null);
|
|
2866
|
+
const [open, setOpen] = (0, import_react32.useState)(false);
|
|
2589
2867
|
const popoverAttr = { popover };
|
|
2590
2868
|
const reposition = useAnchoredPosition(anchor ?? null, ref, {
|
|
2591
2869
|
open: open && !!anchor,
|
|
2592
2870
|
placement,
|
|
2593
2871
|
offset
|
|
2594
2872
|
});
|
|
2595
|
-
(0,
|
|
2873
|
+
(0, import_react32.useEffect)(() => {
|
|
2596
2874
|
const el = ref.current;
|
|
2597
2875
|
if (!el || !anchor) return;
|
|
2598
2876
|
const sync = () => {
|
|
@@ -2607,34 +2885,138 @@ function Popover({
|
|
|
2607
2885
|
}
|
|
2608
2886
|
|
|
2609
2887
|
// src/components/CommandPalette.tsx
|
|
2888
|
+
var import_react33 = require("react");
|
|
2610
2889
|
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
2890
|
+
var CmdkContext = (0, import_react33.createContext)(null);
|
|
2611
2891
|
function CommandPalette({ inputProps, children, className, ...props }) {
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
]
|
|
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
|
+
] }) });
|
|
2616
2925
|
}
|
|
2617
2926
|
function CommandGroup({ label, children }) {
|
|
2618
|
-
|
|
2619
|
-
|
|
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 }),
|
|
2620
2930
|
children
|
|
2621
2931
|
] });
|
|
2622
2932
|
}
|
|
2623
|
-
function CommandItem({ icon, shortcut, active, children, className, ...props }) {
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
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
|
+
);
|
|
2629
2959
|
}
|
|
2630
2960
|
|
|
2631
2961
|
// src/components/Inbox.tsx
|
|
2962
|
+
var import_react34 = require("react");
|
|
2632
2963
|
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
2633
|
-
function Inbox({ children, className, ...props }) {
|
|
2634
|
-
return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: cx("uix-inbox", className), ...props, children });
|
|
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 });
|
|
2635
2966
|
}
|
|
2967
|
+
var InboxListCtx = (0, import_react34.createContext)({});
|
|
2636
2968
|
function InboxList({ children, className, ...props }) {
|
|
2637
|
-
|
|
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
|
+
) });
|
|
2638
3020
|
}
|
|
2639
3021
|
function InboxItem({
|
|
2640
3022
|
subject,
|
|
@@ -2644,13 +3026,19 @@ function InboxItem({
|
|
|
2644
3026
|
selected,
|
|
2645
3027
|
children,
|
|
2646
3028
|
className,
|
|
3029
|
+
id,
|
|
2647
3030
|
...props
|
|
2648
3031
|
}) {
|
|
3032
|
+
const autoId = (0, import_react34.useId)();
|
|
3033
|
+
const itemId = id ?? autoId;
|
|
3034
|
+
const { activeId } = (0, import_react34.useContext)(InboxListCtx);
|
|
2649
3035
|
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
2650
3036
|
"div",
|
|
2651
3037
|
{
|
|
2652
3038
|
role: "option",
|
|
3039
|
+
id: itemId,
|
|
2653
3040
|
"aria-selected": selected ?? false,
|
|
3041
|
+
"data-active": activeId === itemId ? "" : void 0,
|
|
2654
3042
|
className: cx("uix-inbox__item", className),
|
|
2655
3043
|
...unread ? { "data-unread": "" } : {},
|
|
2656
3044
|
...props,
|
|
@@ -2668,29 +3056,60 @@ function InboxDetail({ children, className, ...props }) {
|
|
|
2668
3056
|
}
|
|
2669
3057
|
|
|
2670
3058
|
// src/components/Kanban.tsx
|
|
3059
|
+
var import_react35 = require("react");
|
|
2671
3060
|
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
2672
|
-
function Kanban({ children, className, ...props }) {
|
|
2673
|
-
return /* @__PURE__ */ (0, import_jsx_runtime55.
|
|
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
|
+
] });
|
|
2674
3066
|
}
|
|
2675
3067
|
function KanbanColumn({ title, count, children, className, ...props }) {
|
|
3068
|
+
const headId = (0, import_react35.useId)();
|
|
3069
|
+
const hasHead = title != null || count != null;
|
|
2676
3070
|
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: cx("uix-kanban__col", className), ...props, children: [
|
|
2677
|
-
|
|
3071
|
+
hasHead && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "uix-kanban__head", id: headId, children: [
|
|
2678
3072
|
title,
|
|
2679
3073
|
count != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "uix-kanban__count", children: count })
|
|
2680
3074
|
] }),
|
|
2681
|
-
/* @__PURE__ */ (0, import_jsx_runtime55.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 })
|
|
2682
3076
|
] });
|
|
2683
3077
|
}
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
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
|
+
);
|
|
2690
3109
|
}
|
|
2691
3110
|
|
|
2692
3111
|
// src/components/Tree.tsx
|
|
2693
|
-
var
|
|
3112
|
+
var import_react36 = require("react");
|
|
2694
3113
|
|
|
2695
3114
|
// src/tree-model.ts
|
|
2696
3115
|
function flattenTree(nodes, expanded, level = 1) {
|
|
@@ -2735,6 +3154,14 @@ function treeNav(flat, currentId, key) {
|
|
|
2735
3154
|
case " ":
|
|
2736
3155
|
return cur.hasChildren ? { toggleId: cur.node.id, selectId: cur.node.id } : { selectId: cur.node.id };
|
|
2737
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
|
+
}
|
|
2738
3165
|
return {};
|
|
2739
3166
|
}
|
|
2740
3167
|
}
|
|
@@ -2802,12 +3229,12 @@ function Tree({
|
|
|
2802
3229
|
className,
|
|
2803
3230
|
...props
|
|
2804
3231
|
}) {
|
|
2805
|
-
const [internalExpanded, setInternalExpanded] = (0,
|
|
3232
|
+
const [internalExpanded, setInternalExpanded] = (0, import_react36.useState)(defaultExpanded ?? /* @__PURE__ */ new Set());
|
|
2806
3233
|
const expanded = controlledExpanded ?? internalExpanded;
|
|
2807
|
-
const rootRef = (0,
|
|
2808
|
-
const [focusedId, setFocusedId] = (0,
|
|
3234
|
+
const rootRef = (0, import_react36.useRef)(null);
|
|
3235
|
+
const [focusedId, setFocusedId] = (0, import_react36.useState)(void 0);
|
|
2809
3236
|
const selectable = selected !== void 0 || onSelect != null;
|
|
2810
|
-
const handleToggle = (0,
|
|
3237
|
+
const handleToggle = (0, import_react36.useCallback)((id) => {
|
|
2811
3238
|
if (!controlledExpanded) {
|
|
2812
3239
|
setInternalExpanded((prev) => {
|
|
2813
3240
|
const next = new Set(prev);
|
|
@@ -2818,7 +3245,7 @@ function Tree({
|
|
|
2818
3245
|
}
|
|
2819
3246
|
onToggle?.(id);
|
|
2820
3247
|
}, [controlledExpanded, onToggle]);
|
|
2821
|
-
const flat = (0,
|
|
3248
|
+
const flat = (0, import_react36.useMemo)(() => flattenTree(nodes, expanded), [nodes, expanded]);
|
|
2822
3249
|
const useVirtual = virtualize ?? shouldVirtualize(flat.length);
|
|
2823
3250
|
const tabbableId = focusedId ?? selected ?? nodes[0]?.id;
|
|
2824
3251
|
if (useVirtual) {
|
|
@@ -2889,6 +3316,13 @@ function Tree({
|
|
|
2889
3316
|
setFocusedId(id);
|
|
2890
3317
|
break;
|
|
2891
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
|
+
}
|
|
2892
3326
|
break;
|
|
2893
3327
|
}
|
|
2894
3328
|
};
|
|
@@ -2922,12 +3356,14 @@ function VirtualTreeView({
|
|
|
2922
3356
|
className,
|
|
2923
3357
|
...props
|
|
2924
3358
|
}) {
|
|
2925
|
-
const scrollRef = (0,
|
|
2926
|
-
const [scrollTop, setScrollTop] = (0,
|
|
2927
|
-
const pendingFocus = (0,
|
|
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);
|
|
2928
3363
|
const win = virtualWindow(scrollTop, maxHeight, rowHeight, flat.length);
|
|
2929
3364
|
const rows = flat.slice(win.start, win.end);
|
|
2930
|
-
|
|
3365
|
+
const windowHasTabbable = tabbableId != null && rows.some((f) => f.node.id === tabbableId);
|
|
3366
|
+
(0, import_react36.useEffect)(() => {
|
|
2931
3367
|
if (!pendingFocus.current || focusedId == null) return;
|
|
2932
3368
|
const el = scrollRef.current?.querySelector(`[role="treeitem"][data-id="${CSS.escape(focusedId)}"]`);
|
|
2933
3369
|
if (el) {
|
|
@@ -2935,6 +3371,11 @@ function VirtualTreeView({
|
|
|
2935
3371
|
pendingFocus.current = false;
|
|
2936
3372
|
}
|
|
2937
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
|
+
});
|
|
2938
3379
|
const moveTo = (id) => {
|
|
2939
3380
|
const i = flat.findIndex((f) => f.node.id === id);
|
|
2940
3381
|
if (i < 0) return;
|
|
@@ -2950,6 +3391,7 @@ function VirtualTreeView({
|
|
|
2950
3391
|
setFocusedId(id);
|
|
2951
3392
|
};
|
|
2952
3393
|
const onKeyDown = (e) => {
|
|
3394
|
+
if (e.key.length === 1 && (e.ctrlKey || e.metaKey || e.altKey)) return;
|
|
2953
3395
|
const curId = e.target.closest('[role="treeitem"]')?.dataset.id ?? focusedId;
|
|
2954
3396
|
const act = treeNav(flat, curId, e.key);
|
|
2955
3397
|
if (act.focusId === void 0 && act.toggleId === void 0 && act.selectId === void 0) return;
|
|
@@ -2970,13 +3412,20 @@ function VirtualTreeView({
|
|
|
2970
3412
|
ref: scrollRef,
|
|
2971
3413
|
className: cx("uix-tree", "uix-tree--virtual", className),
|
|
2972
3414
|
role: "tree",
|
|
3415
|
+
tabIndex: -1,
|
|
2973
3416
|
style: { maxHeight, overflow: "auto" },
|
|
2974
3417
|
onScroll: (e) => setScrollTop(e.currentTarget.scrollTop),
|
|
2975
3418
|
onKeyDown,
|
|
3419
|
+
onFocus: () => {
|
|
3420
|
+
hadFocus.current = true;
|
|
3421
|
+
},
|
|
3422
|
+
onBlur: (e) => {
|
|
3423
|
+
if (!e.currentTarget.contains(e.relatedTarget)) hadFocus.current = false;
|
|
3424
|
+
},
|
|
2976
3425
|
...props,
|
|
2977
3426
|
children: [
|
|
2978
|
-
win.padTop > 0 && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("li", { "aria-hidden": "true", style: { height: win.padTop } }),
|
|
2979
|
-
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) => {
|
|
2980
3429
|
const rowStyle = { height: rowHeight, paddingLeft: `calc(${f.level - 1} * var(--uix-space-5))` };
|
|
2981
3430
|
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
2982
3431
|
"li",
|
|
@@ -2988,7 +3437,7 @@ function VirtualTreeView({
|
|
|
2988
3437
|
"aria-expanded": f.hasChildren ? f.isExpanded : void 0,
|
|
2989
3438
|
"aria-selected": selectable ? selected === f.node.id : void 0,
|
|
2990
3439
|
"data-id": f.node.id,
|
|
2991
|
-
tabIndex: tabbableId === f.node.id ? 0 : -1,
|
|
3440
|
+
tabIndex: tabbableId === f.node.id || !windowHasTabbable && i === 0 ? 0 : -1,
|
|
2992
3441
|
className: "uix-tree__item",
|
|
2993
3442
|
onFocus: (e) => {
|
|
2994
3443
|
if (e.target === e.currentTarget) setFocusedId(f.node.id);
|
|
@@ -3008,7 +3457,7 @@ function VirtualTreeView({
|
|
|
3008
3457
|
f.node.id
|
|
3009
3458
|
);
|
|
3010
3459
|
}),
|
|
3011
|
-
win.padBottom > 0 && /* @__PURE__ */ (0, import_jsx_runtime56.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 } })
|
|
3012
3461
|
]
|
|
3013
3462
|
}
|
|
3014
3463
|
);
|
|
@@ -3427,7 +3876,7 @@ function RuleBuilder({
|
|
|
3427
3876
|
}
|
|
3428
3877
|
|
|
3429
3878
|
// src/components/BuilderCanvas.tsx
|
|
3430
|
-
var
|
|
3879
|
+
var import_react37 = require("react");
|
|
3431
3880
|
var import_jsx_runtime59 = require("react/jsx-runtime");
|
|
3432
3881
|
function BuilderCanvas({
|
|
3433
3882
|
items,
|
|
@@ -3443,13 +3892,13 @@ function BuilderCanvas({
|
|
|
3443
3892
|
emptyMessage = "Add an item from the palette to begin.",
|
|
3444
3893
|
className
|
|
3445
3894
|
}) {
|
|
3446
|
-
const [internalSelectedId, setInternalSelectedId] = (0,
|
|
3447
|
-
const [draggedId, setDraggedId] = (0,
|
|
3448
|
-
const propertyHeadingRef = (0,
|
|
3449
|
-
const shouldFocusProperties = (0,
|
|
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);
|
|
3450
3899
|
const selectedId = controlledSelectedId ?? internalSelectedId;
|
|
3451
3900
|
const selected = items.find((item) => item.id === selectedId);
|
|
3452
|
-
(0,
|
|
3901
|
+
(0, import_react37.useEffect)(() => {
|
|
3453
3902
|
if (shouldFocusProperties.current && selected) {
|
|
3454
3903
|
propertyHeadingRef.current?.focus();
|
|
3455
3904
|
shouldFocusProperties.current = false;
|
|
@@ -3540,7 +3989,7 @@ function BuilderCanvas({
|
|
|
3540
3989
|
}
|
|
3541
3990
|
|
|
3542
3991
|
// src/components/SchedulingCalendar.tsx
|
|
3543
|
-
var
|
|
3992
|
+
var import_react38 = require("react");
|
|
3544
3993
|
|
|
3545
3994
|
// src/calendar-model.ts
|
|
3546
3995
|
function fromDateKey(value) {
|
|
@@ -3643,19 +4092,19 @@ function SchedulingCalendar({
|
|
|
3643
4092
|
onRetry,
|
|
3644
4093
|
className
|
|
3645
4094
|
}) {
|
|
3646
|
-
const [internalView, setInternalView] = (0,
|
|
4095
|
+
const [internalView, setInternalView] = (0, import_react38.useState)("month");
|
|
3647
4096
|
const view = controlledView ?? internalView;
|
|
3648
|
-
const [activeDate, setActiveDate] = (0,
|
|
3649
|
-
const gridRef = (0,
|
|
3650
|
-
const visibleEntries = (0,
|
|
3651
|
-
const entrySpans = (0,
|
|
3652
|
-
const overlaySpans = (0,
|
|
3653
|
-
const monthDays = (0,
|
|
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]);
|
|
3654
4103
|
const weekday = ((/* @__PURE__ */ new Date(`${anchorDate}T00:00:00Z`)).getUTCDay() + 6) % 7;
|
|
3655
4104
|
const weekStart = addCalendarDays(anchorDate, -weekday);
|
|
3656
|
-
const weekDays = (0,
|
|
3657
|
-
const days = (0,
|
|
3658
|
-
(0,
|
|
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)(() => {
|
|
3659
4108
|
if (view !== "agenda" && !days.includes(activeDate)) setActiveDate(days[0]);
|
|
3660
4109
|
}, [activeDate, days, view]);
|
|
3661
4110
|
const setView = (next) => {
|
|
@@ -3739,7 +4188,7 @@ function SchedulingCalendar({
|
|
|
3739
4188
|
}
|
|
3740
4189
|
|
|
3741
4190
|
// src/components/DateRangePicker.tsx
|
|
3742
|
-
var
|
|
4191
|
+
var import_react39 = require("react");
|
|
3743
4192
|
var import_jsx_runtime61 = require("react/jsx-runtime");
|
|
3744
4193
|
var monthLabel = (date, locale) => new Intl.DateTimeFormat(locale, { month: "long", year: "numeric", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${date}T00:00:00Z`));
|
|
3745
4194
|
var dateLabel2 = (date, locale) => new Intl.DateTimeFormat(locale, { dateStyle: "full", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${date}T00:00:00Z`));
|
|
@@ -3759,25 +4208,25 @@ function DateRangePicker({
|
|
|
3759
4208
|
disabled,
|
|
3760
4209
|
className
|
|
3761
4210
|
}) {
|
|
3762
|
-
const id = (0,
|
|
3763
|
-
const [internalMonth, setInternalMonth] = (0,
|
|
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)));
|
|
3764
4213
|
const visibleMonth = startOfMonth(controlledMonth ?? internalMonth);
|
|
3765
|
-
const [activeDate, setActiveDate] = (0,
|
|
3766
|
-
const rootRef = (0,
|
|
3767
|
-
const pendingFocus = (0,
|
|
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);
|
|
3768
4217
|
const count = Math.max(1, Math.min(3, months));
|
|
3769
|
-
const calendars = (0,
|
|
4218
|
+
const calendars = (0, import_react39.useMemo)(() => Array.from({ length: count }, (_, index) => {
|
|
3770
4219
|
const month = startOfMonth(addCalendarMonths(visibleMonth, index));
|
|
3771
4220
|
return { month, days: buildMonthGrid(month).filter((day) => day.inMonth) };
|
|
3772
4221
|
}), [visibleMonth, count]);
|
|
3773
4222
|
const rangeInvalid = invalid || !!value.start && !!value.end && value.start > value.end;
|
|
3774
|
-
(0,
|
|
4223
|
+
(0, import_react39.useEffect)(() => {
|
|
3775
4224
|
const first = calendars[0]?.days[0]?.date;
|
|
3776
4225
|
const finalDays = calendars[calendars.length - 1]?.days;
|
|
3777
4226
|
const last = finalDays?.[finalDays.length - 1]?.date;
|
|
3778
4227
|
if (first && last && (activeDate < first || activeDate > last)) setActiveDate(first);
|
|
3779
4228
|
}, [activeDate, calendars]);
|
|
3780
|
-
(0,
|
|
4229
|
+
(0, import_react39.useEffect)(() => {
|
|
3781
4230
|
if (!pendingFocus.current) return;
|
|
3782
4231
|
rootRef.current?.querySelector(`[data-date="${activeDate}"]`)?.focus();
|
|
3783
4232
|
pendingFocus.current = false;
|
|
@@ -3858,7 +4307,7 @@ function DateRangePicker({
|
|
|
3858
4307
|
}
|
|
3859
4308
|
|
|
3860
4309
|
// src/components/RelationshipGraph.tsx
|
|
3861
|
-
var
|
|
4310
|
+
var import_react40 = require("react");
|
|
3862
4311
|
|
|
3863
4312
|
// src/relationship-graph-model.ts
|
|
3864
4313
|
function boundRelationshipGraph(nodes, edges, maxNodes = 40) {
|
|
@@ -3947,13 +4396,13 @@ function RelationshipGraph({
|
|
|
3947
4396
|
onRetry,
|
|
3948
4397
|
className
|
|
3949
4398
|
}) {
|
|
3950
|
-
const bounded = (0,
|
|
3951
|
-
const positioned = (0,
|
|
3952
|
-
const positionedById = (0,
|
|
3953
|
-
const [zoom, setZoom] = (0,
|
|
3954
|
-
const [pan, setPan] = (0,
|
|
3955
|
-
const [focusedId, setFocusedId] = (0,
|
|
3956
|
-
const svgRef = (0,
|
|
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);
|
|
3957
4406
|
const select = (id) => {
|
|
3958
4407
|
const node = bounded.nodes.find((item) => item.id === id);
|
|
3959
4408
|
if (node) onSelect?.(node);
|
|
@@ -4058,7 +4507,7 @@ function RelationshipGraph({
|
|
|
4058
4507
|
}
|
|
4059
4508
|
|
|
4060
4509
|
// src/components/MatchReview.tsx
|
|
4061
|
-
var
|
|
4510
|
+
var import_react41 = require("react");
|
|
4062
4511
|
var import_jsx_runtime63 = require("react/jsx-runtime");
|
|
4063
4512
|
var valueText = (value) => value == null ? "\u2014" : typeof value === "string" ? value : JSON.stringify(value);
|
|
4064
4513
|
function MatchReview({
|
|
@@ -4075,11 +4524,11 @@ function MatchReview({
|
|
|
4075
4524
|
onRetry,
|
|
4076
4525
|
className
|
|
4077
4526
|
}) {
|
|
4078
|
-
const [internalSelection, setInternalSelection] = (0,
|
|
4079
|
-
const [announcement, setAnnouncement] = (0,
|
|
4080
|
-
const [bulkPending, setBulkPending] = (0,
|
|
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);
|
|
4081
4530
|
const selection = selectedIds ?? internalSelection;
|
|
4082
|
-
const pending = (0,
|
|
4531
|
+
const pending = (0, import_react41.useMemo)(() => candidates.filter((candidate) => candidate.status !== "resolved"), [candidates]);
|
|
4083
4532
|
const setSelection = (next) => {
|
|
4084
4533
|
if (selectedIds === void 0) setInternalSelection(next);
|
|
4085
4534
|
onSelectionChange?.(next);
|
|
@@ -4174,7 +4623,7 @@ function MatchReview({
|
|
|
4174
4623
|
}
|
|
4175
4624
|
|
|
4176
4625
|
// src/components/MetricInput.tsx
|
|
4177
|
-
var
|
|
4626
|
+
var import_react42 = require("react");
|
|
4178
4627
|
|
|
4179
4628
|
// src/metric-model.ts
|
|
4180
4629
|
function decimals(value) {
|
|
@@ -4218,11 +4667,11 @@ function MetricInput({
|
|
|
4218
4667
|
className,
|
|
4219
4668
|
id: providedId
|
|
4220
4669
|
}) {
|
|
4221
|
-
const generatedId = (0,
|
|
4670
|
+
const generatedId = (0, import_react42.useId)();
|
|
4222
4671
|
const id = providedId ?? generatedId;
|
|
4223
4672
|
const errorId = `${id}-error`;
|
|
4224
|
-
const [text, setText] = (0,
|
|
4225
|
-
(0,
|
|
4673
|
+
const [text, setText] = (0, import_react42.useState)(() => format(value));
|
|
4674
|
+
(0, import_react42.useEffect)(() => setText(format(value)), [value, format]);
|
|
4226
4675
|
const commit = (input) => {
|
|
4227
4676
|
const parsed = parse(input);
|
|
4228
4677
|
if (input.trim() === "" || parsed !== null) {
|
|
@@ -4331,7 +4780,7 @@ function LicensePositionBar({
|
|
|
4331
4780
|
}
|
|
4332
4781
|
|
|
4333
4782
|
// src/components/BrandProfiles.tsx
|
|
4334
|
-
var
|
|
4783
|
+
var import_react44 = require("react");
|
|
4335
4784
|
|
|
4336
4785
|
// src/color-model.ts
|
|
4337
4786
|
var clamp2 = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
@@ -4400,7 +4849,7 @@ function meetsContrast(background, foreground, minimum = 4.5) {
|
|
|
4400
4849
|
}
|
|
4401
4850
|
|
|
4402
4851
|
// src/components/ColorPicker.tsx
|
|
4403
|
-
var
|
|
4852
|
+
var import_react43 = require("react");
|
|
4404
4853
|
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
4405
4854
|
var EMPTY_COLORS = [];
|
|
4406
4855
|
function ColorPicker({
|
|
@@ -4414,17 +4863,17 @@ function ColorPicker({
|
|
|
4414
4863
|
disabled,
|
|
4415
4864
|
className
|
|
4416
4865
|
}) {
|
|
4417
|
-
const id = (0,
|
|
4418
|
-
const triggerRef = (0,
|
|
4419
|
-
const dialogRef = (0,
|
|
4420
|
-
const [open, setOpen] = (0,
|
|
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);
|
|
4421
4870
|
const normalized = normalizeHex(value) ?? "#000000";
|
|
4422
|
-
const [hexText, setHexText] = (0,
|
|
4423
|
-
const hsv = (0,
|
|
4871
|
+
const [hexText, setHexText] = (0, import_react43.useState)(normalized);
|
|
4872
|
+
const hsv = (0, import_react43.useMemo)(() => rgbToHsv(hexToRgb(normalized)), [normalized]);
|
|
4424
4873
|
const ratio = contrastRatio(normalized, foreground) ?? 0;
|
|
4425
4874
|
const passes = ratio >= minimumContrast;
|
|
4426
|
-
(0,
|
|
4427
|
-
(0,
|
|
4875
|
+
(0, import_react43.useEffect)(() => setHexText(normalized), [normalized]);
|
|
4876
|
+
(0, import_react43.useEffect)(() => {
|
|
4428
4877
|
if (!open) return;
|
|
4429
4878
|
const dialog = dialogRef.current;
|
|
4430
4879
|
dialog?.querySelector("input,button")?.focus();
|
|
@@ -4623,7 +5072,7 @@ function BrandProfileEditor({
|
|
|
4623
5072
|
colorPresets = EMPTY_COLORS2,
|
|
4624
5073
|
className
|
|
4625
5074
|
}) {
|
|
4626
|
-
const [announcement, setAnnouncement] = (0,
|
|
5075
|
+
const [announcement, setAnnouncement] = (0, import_react44.useState)("");
|
|
4627
5076
|
const update = (patch) => onChange({ ...value, ...patch });
|
|
4628
5077
|
const apply = () => {
|
|
4629
5078
|
if (applyTarget !== null) applyBrandProfile(value, applyTarget);
|
|
@@ -4695,7 +5144,7 @@ function BrandProfileEditor({
|
|
|
4695
5144
|
var BrandProfiles = BrandProfileEditor;
|
|
4696
5145
|
|
|
4697
5146
|
// src/components/DiffViewer.tsx
|
|
4698
|
-
var
|
|
5147
|
+
var import_react45 = require("react");
|
|
4699
5148
|
|
|
4700
5149
|
// src/diff-model.ts
|
|
4701
5150
|
function isJsonObject(value) {
|
|
@@ -4765,9 +5214,9 @@ function DiffViewer({
|
|
|
4765
5214
|
labels = DEFAULT_LABELS,
|
|
4766
5215
|
className
|
|
4767
5216
|
}) {
|
|
4768
|
-
const id = (0,
|
|
4769
|
-
const entries = (0,
|
|
4770
|
-
const [internalResolutions, setInternalResolutions] = (0,
|
|
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)({});
|
|
4771
5220
|
const resolutions = controlledResolutions ?? internalResolutions;
|
|
4772
5221
|
const summary = summarizeDiff(entries, resolutions);
|
|
4773
5222
|
const resolve2 = (path, resolution) => {
|
|
@@ -4947,6 +5396,7 @@ function DiffViewer({
|
|
|
4947
5396
|
SubNavItem,
|
|
4948
5397
|
Switch,
|
|
4949
5398
|
Tab,
|
|
5399
|
+
TabPanel,
|
|
4950
5400
|
Table,
|
|
4951
5401
|
TableWrap,
|
|
4952
5402
|
Tabs,
|