@tensor_1/react 2.17.0 → 2.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -1
- package/dist/components/Comments.d.ts +18 -2
- package/dist/components/Comments.js +37 -12
- package/dist/components/EditorIcons.d.ts +39 -0
- package/dist/components/EditorIcons.js +51 -0
- package/dist/components/EmojiGlyph.d.ts +10 -0
- package/dist/components/EmojiGlyph.js +18 -0
- package/dist/components/EmojiPicker.d.ts +60 -0
- package/dist/components/EmojiPicker.js +277 -0
- package/dist/components/Markdown.d.ts +36 -0
- package/dist/components/Markdown.js +104 -0
- package/dist/components/ReactionBar.d.ts +57 -0
- package/dist/components/ReactionBar.js +81 -0
- package/dist/components/RelationshipGraph.d.ts +81 -3
- package/dist/components/RelationshipGraph.js +102 -59
- package/dist/components/RelationshipGraphLayered.d.ts +8 -0
- package/dist/components/RelationshipGraphLayered.js +420 -0
- package/dist/components/RelationshipGraphList.d.ts +16 -0
- package/dist/components/RelationshipGraphList.js +33 -0
- package/dist/components/RichTextEditor.d.ts +128 -0
- package/dist/components/RichTextEditor.js +954 -0
- package/dist/components/SaveStatus.d.ts +32 -0
- package/dist/components/SaveStatus.js +21 -0
- package/dist/components/Tabs.d.ts +10 -3
- package/dist/components/Tabs.js +5 -3
- package/dist/emoji-image-WQLh8ZQP.d.cts +128 -0
- package/dist/emoji-image.d.ts +25 -0
- package/dist/emoji-image.js +80 -0
- package/dist/emoji-model.d.ts +66 -0
- package/dist/emoji-model.js +108 -0
- package/dist/emoji.cjs +871 -0
- package/dist/emoji.d.cts +57 -0
- package/dist/emoji.d.ts +6 -0
- package/dist/emoji.js +18 -0
- package/dist/index.cjs +1503 -540
- package/dist/index.d.cts +245 -65
- package/dist/index.d.ts +3 -2
- package/dist/index.js +11 -2
- package/dist/markdown-model.d.ts +75 -0
- package/dist/markdown-model.js +438 -0
- package/dist/markdown.cjs +585 -0
- package/dist/markdown.d.cts +115 -0
- package/dist/markdown.d.ts +4 -0
- package/dist/markdown.js +9 -0
- package/dist/overlay-position-CEGSz6Z2.d.cts +59 -0
- package/dist/relationship-graph-model.d.ts +112 -1
- package/dist/relationship-graph-model.js +420 -1
- package/dist/rich-text/emoji-items.d.ts +14 -0
- package/dist/rich-text/emoji-items.js +7 -0
- package/dist/rich-text/pipeline.d.ts +91 -0
- package/dist/rich-text/pipeline.js +379 -0
- package/dist/rich-text/round-trip.d.ts +24 -0
- package/dist/rich-text/round-trip.js +11 -0
- package/dist/rich-text.cjs +2578 -0
- package/dist/rich-text.d.cts +148 -0
- package/dist/rich-text.d.ts +8 -0
- package/dist/rich-text.js +10 -0
- package/dist/url-policy.d.ts +9 -0
- package/dist/url-policy.js +11 -0
- package/package.json +82 -1
package/dist/index.cjs
CHANGED
|
@@ -50,6 +50,8 @@ __export(src_exports, {
|
|
|
50
50
|
ConfirmDialog: () => ConfirmDialog,
|
|
51
51
|
ContentList: () => ContentList,
|
|
52
52
|
ContentListItem: () => ContentListItem,
|
|
53
|
+
DEFAULT_RELATIONSHIP_GRAPH_LABELS: () => DEFAULT_RELATIONSHIP_GRAPH_LABELS,
|
|
54
|
+
DEFAULT_SAVE_STATUS_LABELS: () => DEFAULT_SAVE_STATUS_LABELS,
|
|
53
55
|
DateRangePicker: () => DateRangePicker,
|
|
54
56
|
DescriptionItem: () => DescriptionItem,
|
|
55
57
|
DescriptionList: () => DescriptionList,
|
|
@@ -116,6 +118,7 @@ __export(src_exports, {
|
|
|
116
118
|
RowAction: () => RowAction,
|
|
117
119
|
RowActions: () => RowActions,
|
|
118
120
|
RuleBuilder: () => RuleBuilder,
|
|
121
|
+
SaveStatus: () => SaveStatus,
|
|
119
122
|
SavedViewMenu: () => SavedViewMenu,
|
|
120
123
|
SchedulingCalendar: () => SchedulingCalendar,
|
|
121
124
|
SectionHead: () => SectionHead,
|
|
@@ -161,6 +164,8 @@ __export(src_exports, {
|
|
|
161
164
|
buildThreeWayDiff: () => buildThreeWayDiff,
|
|
162
165
|
clampMetricValue: () => clampMetricValue,
|
|
163
166
|
clampWidth: () => clampWidth,
|
|
167
|
+
classifyLayeredEdges: () => classifyLayeredEdges,
|
|
168
|
+
clusterIdFor: () => clusterIdFor,
|
|
164
169
|
computePosition: () => computePosition,
|
|
165
170
|
contrastRatio: () => contrastRatio,
|
|
166
171
|
cx: () => cx,
|
|
@@ -175,6 +180,8 @@ __export(src_exports, {
|
|
|
175
180
|
isDateInRange: () => isDateInRange,
|
|
176
181
|
isDateUnavailable: () => isDateUnavailable,
|
|
177
182
|
isRuleGroup: () => isRuleGroup,
|
|
183
|
+
layeredNeighbor: () => layeredNeighbor,
|
|
184
|
+
layoutLayeredGraph: () => layoutLayeredGraph,
|
|
178
185
|
layoutRelationshipGraph: () => layoutRelationshipGraph,
|
|
179
186
|
mapRuleGroup: () => mapRuleGroup,
|
|
180
187
|
matchFilter: () => matchFilter,
|
|
@@ -216,6 +223,7 @@ __export(src_exports, {
|
|
|
216
223
|
useVirtualRows: () => useVirtualRows,
|
|
217
224
|
validateRuleDefinition: () => validateRuleDefinition,
|
|
218
225
|
virtualWindow: () => virtualWindow,
|
|
226
|
+
wrapEdgeLabel: () => wrapEdgeLabel,
|
|
219
227
|
zonedDateKey: () => zonedDateKey,
|
|
220
228
|
zonedDateSpan: () => zonedDateSpan
|
|
221
229
|
});
|
|
@@ -1460,16 +1468,18 @@ function Tab({ value, children, disabled, className, onClick, ...props }) {
|
|
|
1460
1468
|
}
|
|
1461
1469
|
);
|
|
1462
1470
|
}
|
|
1463
|
-
function TabPanel({ value, children, ...props }) {
|
|
1471
|
+
function TabPanel({ value, children, keepMounted, ...props }) {
|
|
1464
1472
|
const ctx = (0, import_react20.useContext)(TabsCtx);
|
|
1465
|
-
|
|
1473
|
+
const selected = ctx.value === value;
|
|
1474
|
+
if (!selected && !keepMounted) return null;
|
|
1466
1475
|
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1467
1476
|
"div",
|
|
1468
1477
|
{
|
|
1469
1478
|
role: "tabpanel",
|
|
1470
1479
|
id: ctx.baseId ? `${ctx.baseId}-panel-${value}` : void 0,
|
|
1471
1480
|
"aria-labelledby": ctx.baseId ? `${ctx.baseId}-tab-${value}` : void 0,
|
|
1472
|
-
|
|
1481
|
+
hidden: !selected || void 0,
|
|
1482
|
+
tabIndex: selected ? 0 : -1,
|
|
1473
1483
|
...props,
|
|
1474
1484
|
children
|
|
1475
1485
|
}
|
|
@@ -2600,41 +2610,84 @@ var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
|
2600
2610
|
function Comments({ children, className, ...props }) {
|
|
2601
2611
|
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { role: "log", className: cx("uix-comments", className), ...props, children });
|
|
2602
2612
|
}
|
|
2603
|
-
function Comment({
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2613
|
+
function Comment({
|
|
2614
|
+
avatar,
|
|
2615
|
+
author,
|
|
2616
|
+
meta,
|
|
2617
|
+
children,
|
|
2618
|
+
className,
|
|
2619
|
+
variant = "person",
|
|
2620
|
+
systemLabel = "System",
|
|
2621
|
+
replyTo,
|
|
2622
|
+
replyToLabel = "In reply to",
|
|
2623
|
+
...props
|
|
2624
|
+
}) {
|
|
2625
|
+
const system = variant === "system";
|
|
2626
|
+
const byline = author ?? (system ? systemLabel : void 0);
|
|
2627
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
2628
|
+
"div",
|
|
2629
|
+
{
|
|
2630
|
+
className: cx("uix-comment", system && "uix-comment--system", className),
|
|
2631
|
+
"data-variant": system ? "system" : void 0,
|
|
2632
|
+
...props,
|
|
2633
|
+
children: [
|
|
2634
|
+
avatar ?? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { "aria-hidden": "true" }),
|
|
2635
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "uix-comment__body", children: [
|
|
2636
|
+
(byline != null || meta != null) && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "uix-comment__meta", children: [
|
|
2637
|
+
byline != null && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "uix-comment__author", children: byline }),
|
|
2638
|
+
byline != null && meta != null ? " \xB7 " : null,
|
|
2639
|
+
meta
|
|
2640
|
+
] }),
|
|
2641
|
+
replyTo != null && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("blockquote", { className: "uix-comment__reply", children: [
|
|
2642
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "uix-comment__reply-label", children: replyToLabel }),
|
|
2643
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "uix-comment__reply-body", children: replyTo })
|
|
2644
|
+
] }),
|
|
2645
|
+
children
|
|
2646
|
+
] })
|
|
2647
|
+
]
|
|
2648
|
+
}
|
|
2649
|
+
);
|
|
2650
|
+
}
|
|
2651
|
+
|
|
2652
|
+
// src/components/SaveStatus.tsx
|
|
2653
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2654
|
+
var DEFAULT_SAVE_STATUS_LABELS = {
|
|
2655
|
+
saving: "Saving\u2026",
|
|
2656
|
+
saved: "Saved",
|
|
2657
|
+
failed: "Could not save",
|
|
2658
|
+
retry: "Try again"
|
|
2659
|
+
};
|
|
2660
|
+
function SaveStatus({ state, labels, onRetry, className, ...props }) {
|
|
2661
|
+
const text = { ...DEFAULT_SAVE_STATUS_LABELS, ...labels };
|
|
2662
|
+
const message = state === "idle" ? "" : text[state];
|
|
2663
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: cx("uix-save-status", className), "data-state": state, ...props, children: [
|
|
2664
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "uix-save-status__icon", "aria-hidden": "true" }),
|
|
2665
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "uix-save-status__text", role: "status", "aria-live": "polite", children: message }),
|
|
2666
|
+
state === "failed" && onRetry && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("button", { type: "button", className: "uix-btn uix-btn--link uix-btn--sm uix-save-status__retry", onClick: onRetry, children: text.retry })
|
|
2614
2667
|
] });
|
|
2615
2668
|
}
|
|
2616
2669
|
|
|
2617
2670
|
// src/components/Composer.tsx
|
|
2618
2671
|
var import_react28 = require("react");
|
|
2619
|
-
var
|
|
2672
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2620
2673
|
function Composer({ children, className, label = "Add a comment", ...props }) {
|
|
2621
|
-
return /* @__PURE__ */ (0,
|
|
2674
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: cx("uix-composer", className), ...props, children: import_react28.Children.map(children, (child) => {
|
|
2622
2675
|
if (!(0, import_react28.isValidElement)(child) || child.type !== "textarea") return child;
|
|
2623
2676
|
const p = child.props;
|
|
2624
2677
|
return p["aria-label"] || p["aria-labelledby"] || p.id ? child : (0, import_react28.cloneElement)(child, { "aria-label": label });
|
|
2625
2678
|
}) });
|
|
2626
2679
|
}
|
|
2627
2680
|
function ComposerBar({ children, className, ...props }) {
|
|
2628
|
-
return /* @__PURE__ */ (0,
|
|
2681
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: cx("uix-composer__bar", className), ...props, children });
|
|
2629
2682
|
}
|
|
2630
2683
|
|
|
2631
2684
|
// src/components/Segmented.tsx
|
|
2632
2685
|
var import_react29 = require("react");
|
|
2633
|
-
var
|
|
2686
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2634
2687
|
var SegmentedCtx = (0, import_react29.createContext)({});
|
|
2635
2688
|
function Segmented({ value, onChange, children, className, ...props }) {
|
|
2636
2689
|
const contextValue = (0, import_react29.useMemo)(() => ({ value, onChange }), [value, onChange]);
|
|
2637
|
-
return /* @__PURE__ */ (0,
|
|
2690
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(SegmentedCtx.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { role: "group", className: cx("uix-segmented", className), ...props, children }) });
|
|
2638
2691
|
}
|
|
2639
2692
|
function SegmentedOption({
|
|
2640
2693
|
value,
|
|
@@ -2645,7 +2698,7 @@ function SegmentedOption({
|
|
|
2645
2698
|
}) {
|
|
2646
2699
|
const ctx = (0, import_react29.useContext)(SegmentedCtx);
|
|
2647
2700
|
const selected = ctx.value === value;
|
|
2648
|
-
return /* @__PURE__ */ (0,
|
|
2701
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2649
2702
|
"button",
|
|
2650
2703
|
{
|
|
2651
2704
|
type: "button",
|
|
@@ -2663,69 +2716,69 @@ function SegmentedOption({
|
|
|
2663
2716
|
|
|
2664
2717
|
// src/components/TableControls.tsx
|
|
2665
2718
|
var import_react30 = require("react");
|
|
2666
|
-
var
|
|
2719
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2667
2720
|
function ViewMenu({ density, densityLabel, densityOptions, onDensityChange, zebra, freeze, columns, columnsLabel, onColumnVisibilityChange }) {
|
|
2668
2721
|
const densityLabelId = (0, import_react30.useId)();
|
|
2669
2722
|
const zebraLabelId = (0, import_react30.useId)();
|
|
2670
2723
|
const freezeLabelId = (0, import_react30.useId)();
|
|
2671
|
-
return /* @__PURE__ */ (0,
|
|
2672
|
-
/* @__PURE__ */ (0,
|
|
2673
|
-
/* @__PURE__ */ (0,
|
|
2674
|
-
/* @__PURE__ */ (0,
|
|
2724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "uix-view-menu", children: [
|
|
2725
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "uix-view-menu__group", children: [
|
|
2726
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { id: densityLabelId, className: "uix-view-menu__label", children: densityLabel }),
|
|
2727
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Segmented, { value: density, onChange: onDensityChange, "aria-labelledby": densityLabelId, children: densityOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(SegmentedOption, { value: option.value, children: option.label }, option.value)) })
|
|
2675
2728
|
] }),
|
|
2676
|
-
(zebra || freeze) && /* @__PURE__ */ (0,
|
|
2677
|
-
zebra && /* @__PURE__ */ (0,
|
|
2678
|
-
/* @__PURE__ */ (0,
|
|
2679
|
-
/* @__PURE__ */ (0,
|
|
2729
|
+
(zebra || freeze) && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "uix-view-menu__group", children: [
|
|
2730
|
+
zebra && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "uix-view-menu__row", children: [
|
|
2731
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { id: zebraLabelId, children: zebra.label }),
|
|
2732
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Switch, { checked: zebra.checked, "aria-labelledby": zebraLabelId, onChange: (event) => zebra.onChange(event.currentTarget.checked) })
|
|
2680
2733
|
] }),
|
|
2681
|
-
freeze && /* @__PURE__ */ (0,
|
|
2682
|
-
/* @__PURE__ */ (0,
|
|
2683
|
-
/* @__PURE__ */ (0,
|
|
2734
|
+
freeze && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "uix-view-menu__row", children: [
|
|
2735
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { id: freezeLabelId, children: freeze.label }),
|
|
2736
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Switch, { checked: freeze.checked, "aria-labelledby": freezeLabelId, onChange: (event) => freeze.onChange(event.currentTarget.checked) })
|
|
2684
2737
|
] })
|
|
2685
2738
|
] }),
|
|
2686
|
-
columns && columns.length > 0 && /* @__PURE__ */ (0,
|
|
2687
|
-
columnsLabel != null && /* @__PURE__ */ (0,
|
|
2688
|
-
/* @__PURE__ */ (0,
|
|
2739
|
+
columns && columns.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "uix-view-menu__group", children: [
|
|
2740
|
+
columnsLabel != null && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "uix-view-menu__label", children: columnsLabel }),
|
|
2741
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "uix-view-menu__cols", children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Checkbox, { label: column.label, checked: column.visible, disabled: column.disabled, onChange: (event) => onColumnVisibilityChange?.(column.id, event.currentTarget.checked) }, column.id)) })
|
|
2689
2742
|
] })
|
|
2690
2743
|
] });
|
|
2691
2744
|
}
|
|
2692
2745
|
function FilterPopover({ label, type = "text", value, onValueChange, options, applyLabel, clearLabel, onApply, onClear, placeholder }) {
|
|
2693
|
-
return /* @__PURE__ */ (0,
|
|
2694
|
-
/* @__PURE__ */ (0,
|
|
2695
|
-
/* @__PURE__ */ (0,
|
|
2696
|
-
type === "select" || type === "enum" || type === "boolean" ? /* @__PURE__ */ (0,
|
|
2746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "uix-filter-popover", children: [
|
|
2747
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("label", { className: "uix-label", children: [
|
|
2748
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { children: label }),
|
|
2749
|
+
type === "select" || type === "enum" || type === "boolean" ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("select", { className: "uix-select", value, onChange: (event) => onValueChange(event.currentTarget.value), children: options?.map((option) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("option", { value: option.value, children: option.label }, option.value)) }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Input, { type, value, placeholder, onChange: (event) => onValueChange(event.currentTarget.value) })
|
|
2697
2750
|
] }),
|
|
2698
|
-
/* @__PURE__ */ (0,
|
|
2699
|
-
/* @__PURE__ */ (0,
|
|
2700
|
-
/* @__PURE__ */ (0,
|
|
2751
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "uix-filter-popover__actions", children: [
|
|
2752
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Button, { type: "button", onClick: onClear, children: clearLabel }),
|
|
2753
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Button, { type: "button", variant: "primary", onClick: onApply, children: applyLabel })
|
|
2701
2754
|
] })
|
|
2702
2755
|
] });
|
|
2703
2756
|
}
|
|
2704
2757
|
function SavedViewMenu({ items, onSelect, onPinChange, pinLabel, unpinLabel, emptyLabel, actions, footer }) {
|
|
2705
|
-
return /* @__PURE__ */ (0,
|
|
2706
|
-
items.length === 0 && emptyLabel != null && /* @__PURE__ */ (0,
|
|
2707
|
-
items.map((item) => /* @__PURE__ */ (0,
|
|
2708
|
-
/* @__PURE__ */ (0,
|
|
2709
|
-
onPinChange && /* @__PURE__ */ (0,
|
|
2758
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("ul", { className: "uix-menu uix-saved-views", children: [
|
|
2759
|
+
items.length === 0 && emptyLabel != null && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("li", { className: "uix-menu__label", children: emptyLabel }),
|
|
2760
|
+
items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("li", { className: "uix-saved-views__row", children: [
|
|
2761
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", className: "uix-menu__item", "data-active": item.active || void 0, onClick: () => onSelect(item.id), children: item.label }),
|
|
2762
|
+
onPinChange && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", className: "uix-saved-views__pin", "aria-label": item.pinned ? unpinLabel : pinLabel, "data-on": item.pinned || void 0, onClick: () => onPinChange(item.id, !item.pinned), children: "\u2605" }),
|
|
2710
2763
|
actions?.(item)
|
|
2711
2764
|
] }, item.id)),
|
|
2712
|
-
footer != null && /* @__PURE__ */ (0,
|
|
2765
|
+
footer != null && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("li", { className: "uix-saved-views__footer", children: footer })
|
|
2713
2766
|
] });
|
|
2714
2767
|
}
|
|
2715
2768
|
|
|
2716
2769
|
// src/components/Timeline.tsx
|
|
2717
|
-
var
|
|
2770
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
2718
2771
|
function Timeline({ children, className, ...props }) {
|
|
2719
|
-
return /* @__PURE__ */ (0,
|
|
2772
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("ol", { className: cx("uix-timeline", className), ...props, children });
|
|
2720
2773
|
}
|
|
2721
2774
|
function TimelineItem({ node, meta, children, className, ...props }) {
|
|
2722
|
-
return /* @__PURE__ */ (0,
|
|
2723
|
-
/* @__PURE__ */ (0,
|
|
2724
|
-
node ?? /* @__PURE__ */ (0,
|
|
2725
|
-
/* @__PURE__ */ (0,
|
|
2775
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("li", { className: cx("uix-timeline__item", className), ...props, children: [
|
|
2776
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "uix-timeline__rail", "aria-hidden": "true", children: [
|
|
2777
|
+
node ?? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "uix-timeline__node" }),
|
|
2778
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "uix-timeline__line" })
|
|
2726
2779
|
] }),
|
|
2727
|
-
/* @__PURE__ */ (0,
|
|
2728
|
-
meta != null && /* @__PURE__ */ (0,
|
|
2780
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "uix-timeline__body", children: [
|
|
2781
|
+
meta != null && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "uix-timeline__meta", children: meta }),
|
|
2729
2782
|
children
|
|
2730
2783
|
] })
|
|
2731
2784
|
] });
|
|
@@ -2733,10 +2786,10 @@ function TimelineItem({ node, meta, children, className, ...props }) {
|
|
|
2733
2786
|
|
|
2734
2787
|
// src/components/Pipeline.tsx
|
|
2735
2788
|
var import_react31 = require("react");
|
|
2736
|
-
var
|
|
2789
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
2737
2790
|
function Pipeline({ detailed = false, children, className, tabIndex, ...props }) {
|
|
2738
2791
|
const stages = detailed ? import_react31.Children.map(children, (child) => (0, import_react31.isValidElement)(child) && child.type === PipelineStage ? (0, import_react31.cloneElement)(child, { detailed: child.props.detailed ?? true }) : child) : children;
|
|
2739
|
-
return /* @__PURE__ */ (0,
|
|
2792
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
2740
2793
|
"ol",
|
|
2741
2794
|
{
|
|
2742
2795
|
className: cx("uix-pipeline", detailed && "uix-pipeline--detailed", className),
|
|
@@ -2773,20 +2826,20 @@ function PipelineStage({
|
|
|
2773
2826
|
const current = currentProp ?? (state === "active" || state === "current" || state === "running");
|
|
2774
2827
|
const resolvedStateLabel = stateLabel2 ?? DEFAULT_STATE_LABELS[state];
|
|
2775
2828
|
const showDetails = detailed || description != null || meta != null || marker != null;
|
|
2776
|
-
return /* @__PURE__ */ (0,
|
|
2829
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
2777
2830
|
"li",
|
|
2778
2831
|
{
|
|
2779
2832
|
className: cx("uix-pipeline__stage", className),
|
|
2780
2833
|
"data-state": state,
|
|
2781
2834
|
"aria-current": current ? "step" : void 0,
|
|
2782
2835
|
...props,
|
|
2783
|
-
children: showDetails ? /* @__PURE__ */ (0,
|
|
2784
|
-
/* @__PURE__ */ (0,
|
|
2785
|
-
/* @__PURE__ */ (0,
|
|
2786
|
-
/* @__PURE__ */ (0,
|
|
2787
|
-
/* @__PURE__ */ (0,
|
|
2788
|
-
description != null && /* @__PURE__ */ (0,
|
|
2789
|
-
meta != null && /* @__PURE__ */ (0,
|
|
2836
|
+
children: showDetails ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, { children: [
|
|
2837
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "uix-pipeline__marker", "aria-hidden": "true", children: marker }),
|
|
2838
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "uix-pipeline__content", children: [
|
|
2839
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uix-pipeline__eyebrow", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "uix-pipeline__state", children: resolvedStateLabel }) }),
|
|
2840
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uix-pipeline__title", children: label }),
|
|
2841
|
+
description != null && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uix-pipeline__description", children: description }),
|
|
2842
|
+
meta != null && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "uix-pipeline__meta", children: meta })
|
|
2790
2843
|
] })
|
|
2791
2844
|
] }) : label
|
|
2792
2845
|
}
|
|
@@ -2794,9 +2847,9 @@ function PipelineStage({
|
|
|
2794
2847
|
}
|
|
2795
2848
|
|
|
2796
2849
|
// src/components/Flow.tsx
|
|
2797
|
-
var
|
|
2850
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
2798
2851
|
function Flow({ variant = "linear", panel = false, children, className, role = "group", ...props }) {
|
|
2799
|
-
return /* @__PURE__ */ (0,
|
|
2852
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
2800
2853
|
"div",
|
|
2801
2854
|
{
|
|
2802
2855
|
className: cx("uix-flow", `uix-flow--${variant}`, panel && "uix-flow--panel", className),
|
|
@@ -2826,33 +2879,33 @@ function FlowNode({
|
|
|
2826
2879
|
...props
|
|
2827
2880
|
}) {
|
|
2828
2881
|
const resolvedStateLabel = stateLabel2 ?? FLOW_STATE_LABELS[state];
|
|
2829
|
-
return /* @__PURE__ */ (0,
|
|
2830
|
-
icon != null && /* @__PURE__ */ (0,
|
|
2831
|
-
/* @__PURE__ */ (0,
|
|
2832
|
-
eyebrow != null && /* @__PURE__ */ (0,
|
|
2833
|
-
/* @__PURE__ */ (0,
|
|
2834
|
-
meta != null && /* @__PURE__ */ (0,
|
|
2835
|
-
/* @__PURE__ */ (0,
|
|
2882
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: cx("uix-node", `uix-node--${state}`, icon == null && "uix-node--no-icon", wide && "uix-node--wide", className), ...props, children: [
|
|
2883
|
+
icon != null && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("span", { className: "uix-node__icon", "aria-hidden": "true", children: icon }),
|
|
2884
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "uix-node__body", children: [
|
|
2885
|
+
eyebrow != null && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "uix-node__eyebrow", children: eyebrow }),
|
|
2886
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "uix-node__title", children: title }),
|
|
2887
|
+
meta != null && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "uix-node__meta", children: meta }),
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "uix-node__status", children: resolvedStateLabel })
|
|
2836
2889
|
] }),
|
|
2837
|
-
footer != null && /* @__PURE__ */ (0,
|
|
2890
|
+
footer != null && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "uix-node__footer", children: footer })
|
|
2838
2891
|
] });
|
|
2839
2892
|
}
|
|
2840
2893
|
|
|
2841
2894
|
// src/components/Prose.tsx
|
|
2842
|
-
var
|
|
2895
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
2843
2896
|
function Prose({ children, className, ...props }) {
|
|
2844
|
-
return /* @__PURE__ */ (0,
|
|
2897
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: cx("uix-prose", className), ...props, children });
|
|
2845
2898
|
}
|
|
2846
2899
|
function Note({ tone, icon, children, className, ...props }) {
|
|
2847
|
-
return /* @__PURE__ */ (0,
|
|
2848
|
-
icon != null && /* @__PURE__ */ (0,
|
|
2849
|
-
/* @__PURE__ */ (0,
|
|
2900
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: cx("uix-note", tone && `uix-note--${tone}`, className), ...props, children: [
|
|
2901
|
+
icon != null && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "uix-note__icon", children: icon }),
|
|
2902
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "uix-note__body", children })
|
|
2850
2903
|
] });
|
|
2851
2904
|
}
|
|
2852
2905
|
|
|
2853
2906
|
// src/components/Popover.tsx
|
|
2854
2907
|
var import_react32 = require("react");
|
|
2855
|
-
var
|
|
2908
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
2856
2909
|
function Popover({
|
|
2857
2910
|
popover = "auto",
|
|
2858
2911
|
anchor,
|
|
@@ -2881,12 +2934,12 @@ function Popover({
|
|
|
2881
2934
|
el.addEventListener("toggle", sync);
|
|
2882
2935
|
return () => el.removeEventListener("toggle", sync);
|
|
2883
2936
|
}, [anchor, reposition]);
|
|
2884
|
-
return /* @__PURE__ */ (0,
|
|
2937
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { ref, className: cx("uix-popover", className), ...popoverAttr, ...props, children });
|
|
2885
2938
|
}
|
|
2886
2939
|
|
|
2887
2940
|
// src/components/CommandPalette.tsx
|
|
2888
2941
|
var import_react33 = require("react");
|
|
2889
|
-
var
|
|
2942
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
2890
2943
|
var CmdkContext = (0, import_react33.createContext)(null);
|
|
2891
2944
|
function CommandPalette({ inputProps, children, className, ...props }) {
|
|
2892
2945
|
const listId = (0, import_react33.useId)();
|
|
@@ -2905,8 +2958,8 @@ function CommandPalette({ inputProps, children, className, ...props }) {
|
|
|
2905
2958
|
return () => clearTimeout(t);
|
|
2906
2959
|
}, [count]);
|
|
2907
2960
|
const ctx = (0, import_react33.useMemo)(() => ({ listId, setActive, registerItem }), [listId, setActive, registerItem]);
|
|
2908
|
-
return /* @__PURE__ */ (0,
|
|
2909
|
-
/* @__PURE__ */ (0,
|
|
2961
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(CmdkContext.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: cx("uix-cmdk", className), ...props, children: [
|
|
2962
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
2910
2963
|
"input",
|
|
2911
2964
|
{
|
|
2912
2965
|
className: "uix-cmdk__input",
|
|
@@ -2919,14 +2972,14 @@ function CommandPalette({ inputProps, children, className, ...props }) {
|
|
|
2919
2972
|
...inputProps
|
|
2920
2973
|
}
|
|
2921
2974
|
),
|
|
2922
|
-
/* @__PURE__ */ (0,
|
|
2923
|
-
/* @__PURE__ */ (0,
|
|
2975
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "uix-cmdk__list", role: "listbox", id: listId, children }),
|
|
2976
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "uix-visually-hidden", role: "status", children: announced })
|
|
2924
2977
|
] }) });
|
|
2925
2978
|
}
|
|
2926
2979
|
function CommandGroup({ label, children }) {
|
|
2927
2980
|
const labelId = (0, import_react33.useId)();
|
|
2928
|
-
return /* @__PURE__ */ (0,
|
|
2929
|
-
label != null && /* @__PURE__ */ (0,
|
|
2981
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { role: "group", "aria-labelledby": label != null ? labelId : void 0, children: [
|
|
2982
|
+
label != null && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "uix-cmdk__group", id: labelId, children: label }),
|
|
2930
2983
|
children
|
|
2931
2984
|
] });
|
|
2932
2985
|
}
|
|
@@ -2940,7 +2993,7 @@ function CommandItem({ icon, shortcut, active, children, className, id, ...props
|
|
|
2940
2993
|
ctx.setActive(itemId, true);
|
|
2941
2994
|
return () => ctx.setActive(itemId, false);
|
|
2942
2995
|
}, [ctx, itemId, active]);
|
|
2943
|
-
return /* @__PURE__ */ (0,
|
|
2996
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
2944
2997
|
"div",
|
|
2945
2998
|
{
|
|
2946
2999
|
className: cx("uix-cmdk__item", className),
|
|
@@ -2951,7 +3004,7 @@ function CommandItem({ icon, shortcut, active, children, className, id, ...props
|
|
|
2951
3004
|
...props,
|
|
2952
3005
|
children: [
|
|
2953
3006
|
icon,
|
|
2954
|
-
/* @__PURE__ */ (0,
|
|
3007
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { children }),
|
|
2955
3008
|
shortcut
|
|
2956
3009
|
]
|
|
2957
3010
|
}
|
|
@@ -2960,9 +3013,9 @@ function CommandItem({ icon, shortcut, active, children, className, id, ...props
|
|
|
2960
3013
|
|
|
2961
3014
|
// src/components/Inbox.tsx
|
|
2962
3015
|
var import_react34 = require("react");
|
|
2963
|
-
var
|
|
3016
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
2964
3017
|
function Inbox({ view, children, className, ...props }) {
|
|
2965
|
-
return /* @__PURE__ */ (0,
|
|
3018
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: cx("uix-inbox", className), "data-view": view, ...props, children });
|
|
2966
3019
|
}
|
|
2967
3020
|
var InboxListCtx = (0, import_react34.createContext)({});
|
|
2968
3021
|
function InboxList({ children, className, ...props }) {
|
|
@@ -3003,7 +3056,7 @@ function InboxList({ children, className, ...props }) {
|
|
|
3003
3056
|
setActiveId(el.id);
|
|
3004
3057
|
el.scrollIntoView({ block: "nearest" });
|
|
3005
3058
|
};
|
|
3006
|
-
return /* @__PURE__ */ (0,
|
|
3059
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(InboxListCtx.Provider, { value: ctx, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
3007
3060
|
"div",
|
|
3008
3061
|
{
|
|
3009
3062
|
ref: listRef,
|
|
@@ -3032,7 +3085,7 @@ function InboxItem({
|
|
|
3032
3085
|
const autoId = (0, import_react34.useId)();
|
|
3033
3086
|
const itemId = id ?? autoId;
|
|
3034
3087
|
const { activeId } = (0, import_react34.useContext)(InboxListCtx);
|
|
3035
|
-
return /* @__PURE__ */ (0,
|
|
3088
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
|
|
3036
3089
|
"div",
|
|
3037
3090
|
{
|
|
3038
3091
|
role: "option",
|
|
@@ -3044,35 +3097,35 @@ function InboxItem({
|
|
|
3044
3097
|
...props,
|
|
3045
3098
|
children: [
|
|
3046
3099
|
leading,
|
|
3047
|
-
subject != null && /* @__PURE__ */ (0,
|
|
3048
|
-
preview != null && /* @__PURE__ */ (0,
|
|
3100
|
+
subject != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "uix-inbox__subject", children: subject }),
|
|
3101
|
+
preview != null && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "uix-inbox__preview", children: preview }),
|
|
3049
3102
|
children
|
|
3050
3103
|
]
|
|
3051
3104
|
}
|
|
3052
3105
|
);
|
|
3053
3106
|
}
|
|
3054
3107
|
function InboxDetail({ children, className, ...props }) {
|
|
3055
|
-
return /* @__PURE__ */ (0,
|
|
3108
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: cx("uix-inbox__detail", className), ...props, children });
|
|
3056
3109
|
}
|
|
3057
3110
|
|
|
3058
3111
|
// src/components/Kanban.tsx
|
|
3059
3112
|
var import_react35 = require("react");
|
|
3060
|
-
var
|
|
3113
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
3061
3114
|
function Kanban({ announcement, children, className, ...props }) {
|
|
3062
|
-
return /* @__PURE__ */ (0,
|
|
3063
|
-
announcement != null && /* @__PURE__ */ (0,
|
|
3115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: cx("uix-kanban", className), ...props, children: [
|
|
3116
|
+
announcement != null && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { role: "status", className: "uix-visually-hidden", children: announcement }),
|
|
3064
3117
|
children
|
|
3065
3118
|
] });
|
|
3066
3119
|
}
|
|
3067
3120
|
function KanbanColumn({ title, count, children, className, ...props }) {
|
|
3068
3121
|
const headId = (0, import_react35.useId)();
|
|
3069
3122
|
const hasHead = title != null || count != null;
|
|
3070
|
-
return /* @__PURE__ */ (0,
|
|
3071
|
-
hasHead && /* @__PURE__ */ (0,
|
|
3123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: cx("uix-kanban__col", className), ...props, children: [
|
|
3124
|
+
hasHead && /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "uix-kanban__head", id: headId, children: [
|
|
3072
3125
|
title,
|
|
3073
|
-
count != null && /* @__PURE__ */ (0,
|
|
3126
|
+
count != null && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "uix-kanban__count", children: count })
|
|
3074
3127
|
] }),
|
|
3075
|
-
/* @__PURE__ */ (0,
|
|
3128
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "uix-kanban__body", role: "list", "aria-labelledby": hasHead ? headId : void 0, children })
|
|
3076
3129
|
] });
|
|
3077
3130
|
}
|
|
3078
3131
|
var MOVE_KEYS = {
|
|
@@ -3091,7 +3144,7 @@ function KanbanCard({ title, meta, children, className, onMove, onKeyDown, ...pr
|
|
|
3091
3144
|
onMove(dir);
|
|
3092
3145
|
}
|
|
3093
3146
|
};
|
|
3094
|
-
return /* @__PURE__ */ (0,
|
|
3147
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
3095
3148
|
"div",
|
|
3096
3149
|
{
|
|
3097
3150
|
role: "listitem",
|
|
@@ -3100,8 +3153,8 @@ function KanbanCard({ title, meta, children, className, onMove, onKeyDown, ...pr
|
|
|
3100
3153
|
onKeyDown: handleKeyDown,
|
|
3101
3154
|
...props,
|
|
3102
3155
|
children: [
|
|
3103
|
-
title && /* @__PURE__ */ (0,
|
|
3104
|
-
meta && /* @__PURE__ */ (0,
|
|
3156
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "uix-kanban__card-title", children: title }),
|
|
3157
|
+
meta && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "uix-kanban__card-meta", children: meta }),
|
|
3105
3158
|
children
|
|
3106
3159
|
]
|
|
3107
3160
|
}
|
|
@@ -3167,12 +3220,12 @@ function treeNav(flat, currentId, key) {
|
|
|
3167
3220
|
}
|
|
3168
3221
|
|
|
3169
3222
|
// src/components/Tree.tsx
|
|
3170
|
-
var
|
|
3171
|
-
var ChevronIcon2 = () => /* @__PURE__ */ (0,
|
|
3223
|
+
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
3224
|
+
var ChevronIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("svg", { viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("path", { d: "M2 4l4 4 4-4" }) });
|
|
3172
3225
|
function TreeNode({ node, expanded, selected, selectable, tabbableId, onToggle, onSelect, onFocusNode, level = 1 }) {
|
|
3173
3226
|
const hasChildren = Array.isArray(node.children) && node.children.length > 0;
|
|
3174
3227
|
const isExpanded = expanded.has(node.id);
|
|
3175
|
-
return /* @__PURE__ */ (0,
|
|
3228
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
|
|
3176
3229
|
"li",
|
|
3177
3230
|
{
|
|
3178
3231
|
role: "treeitem",
|
|
@@ -3192,12 +3245,12 @@ function TreeNode({ node, expanded, selected, selectable, tabbableId, onToggle,
|
|
|
3192
3245
|
onFocusNode(node.id);
|
|
3193
3246
|
},
|
|
3194
3247
|
children: [
|
|
3195
|
-
/* @__PURE__ */ (0,
|
|
3196
|
-
/* @__PURE__ */ (0,
|
|
3197
|
-
node.icon && /* @__PURE__ */ (0,
|
|
3198
|
-
/* @__PURE__ */ (0,
|
|
3248
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "uix-tree__row", children: [
|
|
3249
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-tree__toggle", children: hasChildren && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ChevronIcon2, {}) }),
|
|
3250
|
+
node.icon && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { "aria-hidden": "true", children: node.icon }),
|
|
3251
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-tree__label", children: node.label })
|
|
3199
3252
|
] }),
|
|
3200
|
-
hasChildren && isExpanded && /* @__PURE__ */ (0,
|
|
3253
|
+
hasChildren && isExpanded && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("ul", { role: "group", className: "uix-tree__group", children: node.children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
3201
3254
|
TreeNode,
|
|
3202
3255
|
{
|
|
3203
3256
|
node: child,
|
|
@@ -3249,7 +3302,7 @@ function Tree({
|
|
|
3249
3302
|
const useVirtual = virtualize ?? shouldVirtualize(flat.length);
|
|
3250
3303
|
const tabbableId = focusedId ?? selected ?? nodes[0]?.id;
|
|
3251
3304
|
if (useVirtual) {
|
|
3252
|
-
return /* @__PURE__ */ (0,
|
|
3305
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
3253
3306
|
VirtualTreeView,
|
|
3254
3307
|
{
|
|
3255
3308
|
flat,
|
|
@@ -3326,7 +3379,7 @@ function Tree({
|
|
|
3326
3379
|
break;
|
|
3327
3380
|
}
|
|
3328
3381
|
};
|
|
3329
|
-
return /* @__PURE__ */ (0,
|
|
3382
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("ul", { ref: rootRef, className: cx("uix-tree", className), role: "tree", onKeyDown, ...props, children: nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
3330
3383
|
TreeNode,
|
|
3331
3384
|
{
|
|
3332
3385
|
node,
|
|
@@ -3406,7 +3459,7 @@ function VirtualTreeView({
|
|
|
3406
3459
|
}
|
|
3407
3460
|
if (act.focusId !== void 0) moveTo(act.focusId);
|
|
3408
3461
|
};
|
|
3409
|
-
return /* @__PURE__ */ (0,
|
|
3462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
|
|
3410
3463
|
"ul",
|
|
3411
3464
|
{
|
|
3412
3465
|
ref: scrollRef,
|
|
@@ -3424,10 +3477,10 @@ function VirtualTreeView({
|
|
|
3424
3477
|
},
|
|
3425
3478
|
...props,
|
|
3426
3479
|
children: [
|
|
3427
|
-
win.padTop > 0 && /* @__PURE__ */ (0,
|
|
3480
|
+
win.padTop > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("li", { role: "presentation", "aria-hidden": "true", style: { height: win.padTop } }),
|
|
3428
3481
|
rows.map((f, i) => {
|
|
3429
3482
|
const rowStyle = { height: rowHeight, paddingLeft: `calc(${f.level - 1} * var(--uix-space-5))` };
|
|
3430
|
-
return /* @__PURE__ */ (0,
|
|
3483
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
3431
3484
|
"li",
|
|
3432
3485
|
{
|
|
3433
3486
|
role: "treeitem",
|
|
@@ -3448,23 +3501,23 @@ function VirtualTreeView({
|
|
|
3448
3501
|
onSelect?.(f.node.id);
|
|
3449
3502
|
setFocusedId(f.node.id);
|
|
3450
3503
|
},
|
|
3451
|
-
children: /* @__PURE__ */ (0,
|
|
3452
|
-
/* @__PURE__ */ (0,
|
|
3453
|
-
f.node.icon && /* @__PURE__ */ (0,
|
|
3454
|
-
/* @__PURE__ */ (0,
|
|
3504
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "uix-tree__row", style: rowStyle, children: [
|
|
3505
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-tree__toggle", children: f.hasChildren && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ChevronIcon2, {}) }),
|
|
3506
|
+
f.node.icon && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { "aria-hidden": "true", children: f.node.icon }),
|
|
3507
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "uix-tree__label", children: f.node.label })
|
|
3455
3508
|
] })
|
|
3456
3509
|
},
|
|
3457
3510
|
f.node.id
|
|
3458
3511
|
);
|
|
3459
3512
|
}),
|
|
3460
|
-
win.padBottom > 0 && /* @__PURE__ */ (0,
|
|
3513
|
+
win.padBottom > 0 && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("li", { role: "presentation", "aria-hidden": "true", style: { height: win.padBottom } })
|
|
3461
3514
|
]
|
|
3462
3515
|
}
|
|
3463
3516
|
);
|
|
3464
3517
|
}
|
|
3465
3518
|
|
|
3466
3519
|
// src/components/EditorialHome.tsx
|
|
3467
|
-
var
|
|
3520
|
+
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
3468
3521
|
function PageIntro({
|
|
3469
3522
|
kicker,
|
|
3470
3523
|
title,
|
|
@@ -3477,39 +3530,39 @@ function PageIntro({
|
|
|
3477
3530
|
children,
|
|
3478
3531
|
...props
|
|
3479
3532
|
}) {
|
|
3480
|
-
return /* @__PURE__ */ (0,
|
|
3481
|
-
/* @__PURE__ */ (0,
|
|
3482
|
-
kicker != null && /* @__PURE__ */ (0,
|
|
3483
|
-
/* @__PURE__ */ (0,
|
|
3484
|
-
lede != null && /* @__PURE__ */ (0,
|
|
3533
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("section", { className: cx("uix-page-intro", className), ...props, children: [
|
|
3534
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { children: [
|
|
3535
|
+
kicker != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-page-kicker", children: kicker }),
|
|
3536
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("h1", { className: "uix-page-title", children: title }),
|
|
3537
|
+
lede != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-page-lede", children: lede })
|
|
3485
3538
|
] }),
|
|
3486
|
-
search != null && /* @__PURE__ */ (0,
|
|
3487
|
-
searchLabel != null && /* @__PURE__ */ (0,
|
|
3539
|
+
search != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { children: [
|
|
3540
|
+
searchLabel != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-intro-search__label", children: searchLabel }),
|
|
3488
3541
|
search
|
|
3489
3542
|
] }),
|
|
3490
|
-
shortcuts != null && /* @__PURE__ */ (0,
|
|
3543
|
+
shortcuts != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uix-shortcut-grid", "aria-label": shortcutsLabel, children: shortcuts }),
|
|
3491
3544
|
children
|
|
3492
3545
|
] });
|
|
3493
3546
|
}
|
|
3494
3547
|
function SectionHead({ title, titleId, action, className, ...props }) {
|
|
3495
|
-
return /* @__PURE__ */ (0,
|
|
3496
|
-
/* @__PURE__ */ (0,
|
|
3548
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: cx("uix-section-head", className), ...props, children: [
|
|
3549
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("h2", { className: "uix-section-title", id: titleId, children: title }),
|
|
3497
3550
|
action
|
|
3498
3551
|
] });
|
|
3499
3552
|
}
|
|
3500
3553
|
function NoticeQueue({ icon, title, summary, meta, position, actions, className, ...props }) {
|
|
3501
|
-
return /* @__PURE__ */ (0,
|
|
3554
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("section", { className: cx("uix-notice", className), ...props, children: [
|
|
3502
3555
|
icon,
|
|
3503
|
-
/* @__PURE__ */ (0,
|
|
3504
|
-
/* @__PURE__ */ (0,
|
|
3505
|
-
title != null && /* @__PURE__ */ (0,
|
|
3556
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-notice__content", "aria-live": "polite", children: [
|
|
3557
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("p", { className: "uix-notice__copy", children: [
|
|
3558
|
+
title != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("strong", { children: title }),
|
|
3506
3559
|
title != null && summary != null && " ",
|
|
3507
3560
|
summary
|
|
3508
3561
|
] }),
|
|
3509
|
-
meta != null && /* @__PURE__ */ (0,
|
|
3562
|
+
meta != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-notice__meta", children: meta })
|
|
3510
3563
|
] }),
|
|
3511
|
-
(position != null || actions != null) && /* @__PURE__ */ (0,
|
|
3512
|
-
position != null && /* @__PURE__ */ (0,
|
|
3564
|
+
(position != null || actions != null) && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-notice__actions", children: [
|
|
3565
|
+
position != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-notice__position", children: position }),
|
|
3513
3566
|
actions
|
|
3514
3567
|
] })
|
|
3515
3568
|
] });
|
|
@@ -3527,8 +3580,8 @@ function FeaturedStage({
|
|
|
3527
3580
|
className,
|
|
3528
3581
|
...props
|
|
3529
3582
|
}) {
|
|
3530
|
-
return /* @__PURE__ */ (0,
|
|
3531
|
-
/* @__PURE__ */ (0,
|
|
3583
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("article", { className: cx("uix-featured__stage", className), ...props, children: [
|
|
3584
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
3532
3585
|
"div",
|
|
3533
3586
|
{
|
|
3534
3587
|
className: "uix-featured__visual",
|
|
@@ -3538,32 +3591,32 @@ function FeaturedStage({
|
|
|
3538
3591
|
children: visual
|
|
3539
3592
|
}
|
|
3540
3593
|
),
|
|
3541
|
-
/* @__PURE__ */ (0,
|
|
3542
|
-
(eyebrow != null || ordinal != null) && /* @__PURE__ */ (0,
|
|
3543
|
-
ordinal != null && /* @__PURE__ */ (0,
|
|
3594
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-featured__content", "aria-live": "polite", children: [
|
|
3595
|
+
(eyebrow != null || ordinal != null) && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("p", { className: "uix-featured__eyebrow", children: [
|
|
3596
|
+
ordinal != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-featured__now", children: ordinal }),
|
|
3544
3597
|
eyebrow
|
|
3545
3598
|
] }),
|
|
3546
|
-
/* @__PURE__ */ (0,
|
|
3547
|
-
description != null && /* @__PURE__ */ (0,
|
|
3548
|
-
meta != null && /* @__PURE__ */ (0,
|
|
3599
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("h2", { className: "uix-featured__title", id: titleId, children: title }),
|
|
3600
|
+
description != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-featured__description", children: description }),
|
|
3601
|
+
meta != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-featured__meta", children: meta }),
|
|
3549
3602
|
action
|
|
3550
3603
|
] })
|
|
3551
3604
|
] });
|
|
3552
3605
|
}
|
|
3553
3606
|
function FeaturedRundown({ eyebrow, title, titleId, meta, children, className, ...props }) {
|
|
3554
|
-
return /* @__PURE__ */ (0,
|
|
3555
|
-
/* @__PURE__ */ (0,
|
|
3556
|
-
/* @__PURE__ */ (0,
|
|
3557
|
-
eyebrow != null && /* @__PURE__ */ (0,
|
|
3558
|
-
/* @__PURE__ */ (0,
|
|
3607
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("aside", { className: cx("uix-rundown", className), ...props, children: [
|
|
3608
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-rundown__head", children: [
|
|
3609
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { children: [
|
|
3610
|
+
eyebrow != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-rundown__eyebrow", children: eyebrow }),
|
|
3611
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("h2", { className: "uix-rundown__title", id: titleId, children: title })
|
|
3559
3612
|
] }),
|
|
3560
3613
|
meta
|
|
3561
3614
|
] }),
|
|
3562
|
-
/* @__PURE__ */ (0,
|
|
3615
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: "uix-rundown__items", children })
|
|
3563
3616
|
] });
|
|
3564
3617
|
}
|
|
3565
3618
|
function FeaturedRundownItem({ number, topic, title, selected = false, className, ...props }) {
|
|
3566
|
-
return /* @__PURE__ */ (0,
|
|
3619
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
3567
3620
|
"button",
|
|
3568
3621
|
{
|
|
3569
3622
|
type: "button",
|
|
@@ -3572,63 +3625,63 @@ function FeaturedRundownItem({ number, topic, title, selected = false, className
|
|
|
3572
3625
|
"data-selected": selected ? "true" : "false",
|
|
3573
3626
|
...props,
|
|
3574
3627
|
children: [
|
|
3575
|
-
number != null && /* @__PURE__ */ (0,
|
|
3576
|
-
/* @__PURE__ */ (0,
|
|
3577
|
-
topic != null && /* @__PURE__ */ (0,
|
|
3578
|
-
/* @__PURE__ */ (0,
|
|
3628
|
+
number != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-rundown__number", children: number }),
|
|
3629
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("span", { children: [
|
|
3630
|
+
topic != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-rundown__topic", children: topic }),
|
|
3631
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-rundown__item-title", children: title })
|
|
3579
3632
|
] })
|
|
3580
3633
|
]
|
|
3581
3634
|
}
|
|
3582
3635
|
);
|
|
3583
3636
|
}
|
|
3584
3637
|
function NewsLead({ meta, title, summary, className, ...props }) {
|
|
3585
|
-
return /* @__PURE__ */ (0,
|
|
3586
|
-
meta != null && /* @__PURE__ */ (0,
|
|
3587
|
-
/* @__PURE__ */ (0,
|
|
3588
|
-
summary != null && /* @__PURE__ */ (0,
|
|
3638
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("article", { className: cx("uix-news-lead", className), ...props, children: [
|
|
3639
|
+
meta != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-news-lead__meta", children: meta }),
|
|
3640
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("h3", { className: "uix-news-lead__title", children: title }),
|
|
3641
|
+
summary != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-news-lead__summary", children: summary })
|
|
3589
3642
|
] });
|
|
3590
3643
|
}
|
|
3591
3644
|
function ContentList({ children, className, ...props }) {
|
|
3592
|
-
return /* @__PURE__ */ (0,
|
|
3645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("ul", { className: cx("uix-content-list", className), ...props, children });
|
|
3593
3646
|
}
|
|
3594
3647
|
function ContentListItem({ title, meta, trailing, className, ...props }) {
|
|
3595
|
-
return /* @__PURE__ */ (0,
|
|
3596
|
-
/* @__PURE__ */ (0,
|
|
3597
|
-
/* @__PURE__ */ (0,
|
|
3598
|
-
meta != null && /* @__PURE__ */ (0,
|
|
3648
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("li", { className: cx("uix-content-list__item", className), ...props, children: [
|
|
3649
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { children: [
|
|
3650
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-content-list__title", children: title }),
|
|
3651
|
+
meta != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-content-list__meta", children: meta })
|
|
3599
3652
|
] }),
|
|
3600
3653
|
trailing
|
|
3601
3654
|
] });
|
|
3602
3655
|
}
|
|
3603
3656
|
function ResourceGrid({ children, className, ...props }) {
|
|
3604
|
-
return /* @__PURE__ */ (0,
|
|
3657
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("div", { className: cx("uix-resource-grid", className), ...props, children });
|
|
3605
3658
|
}
|
|
3606
3659
|
function StatLine({ items, children, className, ...props }) {
|
|
3607
|
-
return /* @__PURE__ */ (0,
|
|
3608
|
-
items?.map((item, i) => /* @__PURE__ */ (0,
|
|
3609
|
-
/* @__PURE__ */ (0,
|
|
3610
|
-
/* @__PURE__ */ (0,
|
|
3660
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: cx("uix-stat-line", className), ...props, children: [
|
|
3661
|
+
items?.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-stat-line__item", children: [
|
|
3662
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-stat-line__value", children: item.value }),
|
|
3663
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-stat-line__label", children: item.label })
|
|
3611
3664
|
] }, item.id ?? i)),
|
|
3612
3665
|
children
|
|
3613
3666
|
] });
|
|
3614
3667
|
}
|
|
3615
3668
|
function EventRow({ month, day, title, meta, className, ...props }) {
|
|
3616
|
-
return /* @__PURE__ */ (0,
|
|
3617
|
-
/* @__PURE__ */ (0,
|
|
3618
|
-
/* @__PURE__ */ (0,
|
|
3619
|
-
/* @__PURE__ */ (0,
|
|
3669
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: cx("uix-event-row", className), ...props, children: [
|
|
3670
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "uix-event-date", children: [
|
|
3671
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-event-date__month", children: month }),
|
|
3672
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-event-date__day", children: day })
|
|
3620
3673
|
] }),
|
|
3621
|
-
/* @__PURE__ */ (0,
|
|
3622
|
-
/* @__PURE__ */ (0,
|
|
3623
|
-
meta != null && /* @__PURE__ */ (0,
|
|
3674
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { children: [
|
|
3675
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-event-row__title", children: title }),
|
|
3676
|
+
meta != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("p", { className: "uix-event-row__meta", children: meta })
|
|
3624
3677
|
] })
|
|
3625
3678
|
] });
|
|
3626
3679
|
}
|
|
3627
3680
|
function StatusRow({ indicator, name, meta, className, ...props }) {
|
|
3628
|
-
return /* @__PURE__ */ (0,
|
|
3681
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: cx("uix-status-row", className), ...props, children: [
|
|
3629
3682
|
indicator,
|
|
3630
|
-
/* @__PURE__ */ (0,
|
|
3631
|
-
meta != null && /* @__PURE__ */ (0,
|
|
3683
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-status-row__name", children: name }),
|
|
3684
|
+
meta != null && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "uix-list-meta", children: meta })
|
|
3632
3685
|
] });
|
|
3633
3686
|
}
|
|
3634
3687
|
|
|
@@ -3725,7 +3778,7 @@ function summarizeRule(value, labels = {}) {
|
|
|
3725
3778
|
}
|
|
3726
3779
|
|
|
3727
3780
|
// src/components/RuleBuilder.tsx
|
|
3728
|
-
var
|
|
3781
|
+
var import_jsx_runtime59 = require("react/jsx-runtime");
|
|
3729
3782
|
var ruleId = 0;
|
|
3730
3783
|
var nextId = (prefix) => `${prefix}-${Date.now().toString(36)}-${(++ruleId).toString(36)}`;
|
|
3731
3784
|
function defaultCondition(fields, operators) {
|
|
@@ -3741,21 +3794,21 @@ function RuleGroupEditor({ group, depth, root, fields, operators, maxDepth, disa
|
|
|
3741
3794
|
combinator: "and",
|
|
3742
3795
|
conditions: [defaultCondition(fields, operators)]
|
|
3743
3796
|
}, maxDepth));
|
|
3744
|
-
return /* @__PURE__ */ (0,
|
|
3745
|
-
/* @__PURE__ */ (0,
|
|
3746
|
-
/* @__PURE__ */ (0,
|
|
3747
|
-
/* @__PURE__ */ (0,
|
|
3797
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("fieldset", { className: "uix-rule-builder__group", "data-depth": depth, children: [
|
|
3798
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("legend", { className: "uix-rule-builder__group-heading", children: [
|
|
3799
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { children: depth === 1 ? "When" : "Group" }),
|
|
3800
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("label", { children: [
|
|
3748
3801
|
"Match",
|
|
3749
|
-
/* @__PURE__ */ (0,
|
|
3750
|
-
/* @__PURE__ */ (0,
|
|
3751
|
-
/* @__PURE__ */ (0,
|
|
3802
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("select", { className: "uix-select uix-select--sm", value: group.combinator, disabled, onChange: (event) => updateNode(group.id, (node) => ({ ...node, combinator: event.currentTarget.value })), children: [
|
|
3803
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("option", { value: "and", children: "all (AND)" }),
|
|
3804
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("option", { value: "or", children: "any (OR)" })
|
|
3752
3805
|
] })
|
|
3753
3806
|
] })
|
|
3754
3807
|
] }),
|
|
3755
|
-
/* @__PURE__ */ (0,
|
|
3756
|
-
/* @__PURE__ */ (0,
|
|
3757
|
-
/* @__PURE__ */ (0,
|
|
3758
|
-
] }, node.id) : /* @__PURE__ */ (0,
|
|
3808
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "uix-rule-builder__rows", children: group.conditions.map((node, index) => isRuleGroup(node) ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "uix-rule-builder__nested", children: [
|
|
3809
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RuleGroupEditor, { ...{ group: node, depth: depth + 1, root, fields, operators, maxDepth, disabled, onRootChange, labels } }),
|
|
3810
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RowControls, { label: "group", first: index === 0, last: index === group.conditions.length - 1, disabled, onUp: () => onRootChange(moveRuleNode(root, node.id, -1)), onDown: () => onRootChange(moveRuleNode(root, node.id, 1)), onRemove: () => onRootChange(removeRuleNode(root, node.id)) })
|
|
3811
|
+
] }, node.id) : /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
3759
3812
|
ConditionRow,
|
|
3760
3813
|
{
|
|
3761
3814
|
condition: node,
|
|
@@ -3763,13 +3816,13 @@ function RuleGroupEditor({ group, depth, root, fields, operators, maxDepth, disa
|
|
|
3763
3816
|
operators,
|
|
3764
3817
|
disabled,
|
|
3765
3818
|
onChange: (condition) => updateNode(node.id, () => condition),
|
|
3766
|
-
controls: /* @__PURE__ */ (0,
|
|
3819
|
+
controls: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RowControls, { label: "condition", first: index === 0, last: index === group.conditions.length - 1, disabled, onUp: () => onRootChange(moveRuleNode(root, node.id, -1)), onDown: () => onRootChange(moveRuleNode(root, node.id, 1)), onRemove: () => onRootChange(removeRuleNode(root, node.id)) })
|
|
3767
3820
|
},
|
|
3768
3821
|
node.id
|
|
3769
3822
|
)) }),
|
|
3770
|
-
/* @__PURE__ */ (0,
|
|
3771
|
-
/* @__PURE__ */ (0,
|
|
3772
|
-
/* @__PURE__ */ (0,
|
|
3823
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "uix-rule-builder__add", children: [
|
|
3824
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", onClick: addCondition, disabled: disabled || fields.length === 0 || operators.length === 0, children: labels.addCondition }),
|
|
3825
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: addGroup, disabled: disabled || depth >= maxDepth, children: labels.addGroup })
|
|
3773
3826
|
] })
|
|
3774
3827
|
] });
|
|
3775
3828
|
}
|
|
@@ -3782,24 +3835,24 @@ function ConditionRow({ condition, fields, operators, disabled, onChange, contro
|
|
|
3782
3835
|
const nextOperator = operators.find((item) => nextField?.operators?.includes(item.id)) ?? availableOperators[0] ?? operators[0];
|
|
3783
3836
|
onChange({ ...condition, field: id, operator: nextOperator?.id ?? "" });
|
|
3784
3837
|
};
|
|
3785
|
-
return /* @__PURE__ */ (0,
|
|
3786
|
-
/* @__PURE__ */ (0,
|
|
3787
|
-
/* @__PURE__ */ (0,
|
|
3788
|
-
/* @__PURE__ */ (0,
|
|
3838
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "uix-rule-builder__condition", children: [
|
|
3839
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("label", { children: [
|
|
3840
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "uix-visually-hidden", children: "Field" }),
|
|
3841
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("select", { className: "uix-select", value: condition.field, onChange: (event) => setField(event.currentTarget.value), disabled, children: fields.map((item) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("option", { value: item.id, children: item.label }, item.id)) })
|
|
3789
3842
|
] }),
|
|
3790
|
-
/* @__PURE__ */ (0,
|
|
3791
|
-
/* @__PURE__ */ (0,
|
|
3792
|
-
/* @__PURE__ */ (0,
|
|
3843
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("label", { children: [
|
|
3844
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "uix-visually-hidden", children: "Operator" }),
|
|
3845
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("select", { className: "uix-select", value: condition.operator, onChange: (event) => onChange({ ...condition, operator: event.currentTarget.value }), disabled, children: availableOperators.map((item) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("option", { value: item.id, children: item.label }, item.id)) })
|
|
3793
3846
|
] }),
|
|
3794
|
-
operator?.requiresValue !== false && /* @__PURE__ */ (0,
|
|
3847
|
+
operator?.requiresValue !== false && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "uix-rule-builder__value", children: field?.renderValueEditor?.({ condition, onChange: (value) => onChange({ ...condition, value }), disabled }) ?? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("input", { className: "uix-input", value: typeof condition.value === "string" || typeof condition.value === "number" ? condition.value : condition.value == null ? "" : JSON.stringify(condition.value), onChange: (event) => onChange({ ...condition, value: event.currentTarget.value }), disabled, "aria-label": `Value for ${field?.label ?? "condition"}` }) }),
|
|
3795
3848
|
controls
|
|
3796
3849
|
] });
|
|
3797
3850
|
}
|
|
3798
3851
|
function RowControls({ label, first, last, disabled, onUp, onDown, onRemove }) {
|
|
3799
|
-
return /* @__PURE__ */ (0,
|
|
3800
|
-
/* @__PURE__ */ (0,
|
|
3801
|
-
/* @__PURE__ */ (0,
|
|
3802
|
-
/* @__PURE__ */ (0,
|
|
3852
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("span", { className: "uix-rule-builder__row-actions", children: [
|
|
3853
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: onUp, disabled: disabled || first, "aria-label": `Move ${label} up`, children: "Up" }),
|
|
3854
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: onDown, disabled: disabled || last, "aria-label": `Move ${label} down`, children: "Down" }),
|
|
3855
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: onRemove, disabled, "aria-label": `Remove ${label}`, children: "Remove" })
|
|
3803
3856
|
] });
|
|
3804
3857
|
}
|
|
3805
3858
|
function RuleBuilder({
|
|
@@ -3820,9 +3873,9 @@ function RuleBuilder({
|
|
|
3820
3873
|
const fieldLabels = Object.fromEntries(fields.map((field) => [field.id, field.label]));
|
|
3821
3874
|
const operatorLabels = Object.fromEntries(operators.map((operator) => [operator.id, operator.label]));
|
|
3822
3875
|
const actionLabels = Object.fromEntries(actions.map((action) => [action.id, action.label]));
|
|
3823
|
-
if (readOnly) return /* @__PURE__ */ (0,
|
|
3824
|
-
/* @__PURE__ */ (0,
|
|
3825
|
-
issues.length > 0 && /* @__PURE__ */ (0,
|
|
3876
|
+
if (readOnly) return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("section", { className: cx("uix-rule-builder uix-rule-builder--summary", className), "aria-label": "Rule summary", children: [
|
|
3877
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("p", { children: summarizeRule(value, { fields: fieldLabels, operators: operatorLabels, actions: actionLabels }) }),
|
|
3878
|
+
issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("p", { className: "uix-rule-builder__invalid", children: [
|
|
3826
3879
|
"Rule has ",
|
|
3827
3880
|
issues.length,
|
|
3828
3881
|
" validation issue",
|
|
@@ -3831,16 +3884,16 @@ function RuleBuilder({
|
|
|
3831
3884
|
] })
|
|
3832
3885
|
] });
|
|
3833
3886
|
const updateActions = (next) => onChange({ ...value, then: next });
|
|
3834
|
-
return /* @__PURE__ */ (0,
|
|
3835
|
-
/* @__PURE__ */ (0,
|
|
3836
|
-
/* @__PURE__ */ (0,
|
|
3837
|
-
/* @__PURE__ */ (0,
|
|
3887
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("section", { className: cx("uix-rule-builder", className), "aria-label": "Rule builder", children: [
|
|
3888
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(RuleGroupEditor, { group: value.when, depth: 1, root: value.when, fields, operators, maxDepth, disabled: readOnly, onRootChange: (when) => onChange({ ...value, when }), labels: { addCondition: addConditionLabel, addGroup: addGroupLabel } }),
|
|
3889
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("fieldset", { className: "uix-rule-builder__actions", children: [
|
|
3890
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("legend", { children: "Then" }),
|
|
3838
3891
|
value.then.map((action, index) => {
|
|
3839
3892
|
const definition = actions.find((item) => item.id === action.type);
|
|
3840
|
-
return /* @__PURE__ */ (0,
|
|
3841
|
-
/* @__PURE__ */ (0,
|
|
3893
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "uix-rule-builder__action", children: [
|
|
3894
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("select", { className: "uix-select", value: action.type, onChange: (event) => updateActions(value.then.map((item) => item.id === action.id ? { ...item, type: event.currentTarget.value } : item)), "aria-label": "Action type", children: actions.map((item) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("option", { value: item.id, children: item.label }, item.id)) }),
|
|
3842
3895
|
definition?.renderParameters?.(action, (parameters) => updateActions(value.then.map((item) => item.id === action.id ? { ...item, parameters } : item)), false),
|
|
3843
|
-
/* @__PURE__ */ (0,
|
|
3896
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
3844
3897
|
RowControls,
|
|
3845
3898
|
{
|
|
3846
3899
|
label: "action",
|
|
@@ -3862,22 +3915,22 @@ function RuleBuilder({
|
|
|
3862
3915
|
)
|
|
3863
3916
|
] }, action.id);
|
|
3864
3917
|
}),
|
|
3865
|
-
/* @__PURE__ */ (0,
|
|
3918
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", disabled: actions.length === 0, onClick: () => updateActions([...value.then, { id: nextId("action"), type: actions[0]?.id ?? "", parameters: {} }]), children: addActionLabel })
|
|
3866
3919
|
] }),
|
|
3867
|
-
/* @__PURE__ */ (0,
|
|
3868
|
-
/* @__PURE__ */ (0,
|
|
3920
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "uix-rule-builder__validation", "aria-live": "polite", children: issues.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { children: "Rule is valid." }) : /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
|
|
3921
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("strong", { children: [
|
|
3869
3922
|
issues.length,
|
|
3870
3923
|
" validation issue",
|
|
3871
3924
|
issues.length === 1 ? "" : "s"
|
|
3872
3925
|
] }),
|
|
3873
|
-
/* @__PURE__ */ (0,
|
|
3926
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("ul", { children: issues.map((issue, index) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("li", { children: issue.message }, `${issue.path}-${index}`)) })
|
|
3874
3927
|
] }) })
|
|
3875
3928
|
] });
|
|
3876
3929
|
}
|
|
3877
3930
|
|
|
3878
3931
|
// src/components/BuilderCanvas.tsx
|
|
3879
3932
|
var import_react37 = require("react");
|
|
3880
|
-
var
|
|
3933
|
+
var import_jsx_runtime60 = require("react/jsx-runtime");
|
|
3881
3934
|
function BuilderCanvas({
|
|
3882
3935
|
items,
|
|
3883
3936
|
onItemsChange,
|
|
@@ -3932,27 +3985,27 @@ function BuilderCanvas({
|
|
|
3932
3985
|
if (from >= 0 && to >= 0) onItemsChange(reorder(items, from, to));
|
|
3933
3986
|
setDraggedId(void 0);
|
|
3934
3987
|
};
|
|
3935
|
-
return /* @__PURE__ */ (0,
|
|
3936
|
-
/* @__PURE__ */ (0,
|
|
3937
|
-
/* @__PURE__ */ (0,
|
|
3938
|
-
palette.length === 0 ? /* @__PURE__ */ (0,
|
|
3939
|
-
/* @__PURE__ */ (0,
|
|
3940
|
-
item.description && /* @__PURE__ */ (0,
|
|
3941
|
-
/* @__PURE__ */ (0,
|
|
3988
|
+
return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("section", { className: cx("uix-builder-canvas", className), "aria-label": "Builder canvas", children: [
|
|
3989
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("aside", { className: "uix-builder-canvas__palette", "aria-label": "Item palette", children: [
|
|
3990
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("h3", { children: "Palette" }),
|
|
3991
|
+
palette.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { children: "No item types available." }) : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("ul", { children: palette.map((item) => /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", onClick: () => add(item), children: [
|
|
3992
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("strong", { children: item.label }),
|
|
3993
|
+
item.description && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { children: item.description }),
|
|
3994
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { "aria-hidden": "true", children: "Add" })
|
|
3942
3995
|
] }) }, item.id)) })
|
|
3943
3996
|
] }),
|
|
3944
|
-
/* @__PURE__ */ (0,
|
|
3945
|
-
/* @__PURE__ */ (0,
|
|
3946
|
-
loading ? /* @__PURE__ */ (0,
|
|
3947
|
-
/* @__PURE__ */ (0,
|
|
3948
|
-
onRetry && /* @__PURE__ */ (0,
|
|
3949
|
-
] }) : items.length === 0 ? /* @__PURE__ */ (0,
|
|
3950
|
-
/* @__PURE__ */ (0,
|
|
3951
|
-
palette[0] && /* @__PURE__ */ (0,
|
|
3997
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "uix-builder-canvas__workspace", children: [
|
|
3998
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("h3", { children: "Canvas" }),
|
|
3999
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("div", { className: "uix-builder-canvas__state", role: "status", children: "Loading canvas\u2026" }) : error ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "uix-builder-canvas__state", role: "alert", children: [
|
|
4000
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { children: error }),
|
|
4001
|
+
onRetry && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: "Try again" })
|
|
4002
|
+
] }) : items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: "uix-builder-canvas__state", children: [
|
|
4003
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { children: emptyMessage }),
|
|
4004
|
+
palette[0] && /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("button", { type: "button", className: "uix-btn uix-btn--primary", onClick: () => add(palette[0]), children: [
|
|
3952
4005
|
"Add ",
|
|
3953
4006
|
palette[0].label
|
|
3954
4007
|
] })
|
|
3955
|
-
] }) : /* @__PURE__ */ (0,
|
|
4008
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("ol", { className: "uix-builder-canvas__items", children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(
|
|
3956
4009
|
"li",
|
|
3957
4010
|
{
|
|
3958
4011
|
draggable: true,
|
|
@@ -3962,27 +4015,27 @@ function BuilderCanvas({
|
|
|
3962
4015
|
onDrop: (event) => drop(event, item.id),
|
|
3963
4016
|
className: cx("uix-builder-canvas__item", selectedId === item.id && "uix-builder-canvas__item--selected"),
|
|
3964
4017
|
children: [
|
|
3965
|
-
/* @__PURE__ */ (0,
|
|
3966
|
-
/* @__PURE__ */ (0,
|
|
3967
|
-
item.description && /* @__PURE__ */ (0,
|
|
4018
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", className: "uix-builder-canvas__item-main", "aria-pressed": selectedId === item.id, onClick: () => select(item.id), children: renderItem?.(item, selectedId === item.id) ?? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)(import_jsx_runtime60.Fragment, { children: [
|
|
4019
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("strong", { children: item.label }),
|
|
4020
|
+
item.description && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("span", { children: item.description })
|
|
3968
4021
|
] }) }),
|
|
3969
|
-
/* @__PURE__ */ (0,
|
|
3970
|
-
/* @__PURE__ */ (0,
|
|
3971
|
-
/* @__PURE__ */ (0,
|
|
3972
|
-
/* @__PURE__ */ (0,
|
|
4022
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("span", { className: "uix-builder-canvas__item-actions", children: [
|
|
4023
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", onClick: () => move(item.id, -1), disabled: index === 0, "aria-label": `Move ${item.label} up`, children: "Up" }),
|
|
4024
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", onClick: () => move(item.id, 1), disabled: index === items.length - 1, "aria-label": `Move ${item.label} down`, children: "Down" }),
|
|
4025
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("button", { type: "button", onClick: () => remove(item.id), "aria-label": `Remove ${item.label}`, children: "Remove" })
|
|
3973
4026
|
] })
|
|
3974
4027
|
]
|
|
3975
4028
|
},
|
|
3976
4029
|
item.id
|
|
3977
4030
|
)) })
|
|
3978
4031
|
] }),
|
|
3979
|
-
/* @__PURE__ */ (0,
|
|
3980
|
-
/* @__PURE__ */ (0,
|
|
3981
|
-
!selected ? /* @__PURE__ */ (0,
|
|
3982
|
-
/* @__PURE__ */ (0,
|
|
3983
|
-
/* @__PURE__ */ (0,
|
|
3984
|
-
/* @__PURE__ */ (0,
|
|
3985
|
-
/* @__PURE__ */ (0,
|
|
4032
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("aside", { className: "uix-builder-canvas__properties", "aria-label": "Item properties", children: [
|
|
4033
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("h3", { ref: propertyHeadingRef, tabIndex: -1, children: "Properties" }),
|
|
4034
|
+
!selected ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { children: "Select a canvas item to edit its properties." }) : renderProperties?.(selected, (updated) => onItemsChange(items.map((item) => item.id === updated.id ? updated : item))) ?? /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("dl", { children: [
|
|
4035
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("dt", { children: "Type" }),
|
|
4036
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("dd", { children: selected.type }),
|
|
4037
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("dt", { children: "Label" }),
|
|
4038
|
+
/* @__PURE__ */ (0, import_jsx_runtime60.jsx)("dd", { children: selected.label })
|
|
3986
4039
|
] })
|
|
3987
4040
|
] })
|
|
3988
4041
|
] });
|
|
@@ -4070,7 +4123,7 @@ function isDateUnavailable(date, options) {
|
|
|
4070
4123
|
}
|
|
4071
4124
|
|
|
4072
4125
|
// src/components/SchedulingCalendar.tsx
|
|
4073
|
-
var
|
|
4126
|
+
var import_jsx_runtime61 = require("react/jsx-runtime");
|
|
4074
4127
|
var stateLabel = { scheduled: "Scheduled", conflicted: "Conflicted", "in-progress": "In progress", "blackout-violation": "Blackout violation" };
|
|
4075
4128
|
var stateTone = (state) => state === "scheduled" ? "info" : state === "in-progress" ? "success" : "danger";
|
|
4076
4129
|
var dateLabel = (date, locale) => new Intl.DateTimeFormat(locale, { dateStyle: "full", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${date}T00:00:00Z`));
|
|
@@ -4138,58 +4191,58 @@ function SchedulingCalendar({
|
|
|
4138
4191
|
return date >= span.start && date <= span.end;
|
|
4139
4192
|
});
|
|
4140
4193
|
const formatInstant = (instant) => new Intl.DateTimeFormat(locale, { timeZone, dateStyle: "medium", timeStyle: "short" }).format(new Date(instant));
|
|
4141
|
-
return /* @__PURE__ */ (0,
|
|
4142
|
-
/* @__PURE__ */ (0,
|
|
4143
|
-
/* @__PURE__ */ (0,
|
|
4144
|
-
/* @__PURE__ */ (0,
|
|
4145
|
-
/* @__PURE__ */ (0,
|
|
4194
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("section", { className: cx("uix-scheduling-calendar", className), "aria-label": `Scheduling calendar in ${timeZone}`, children: [
|
|
4195
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "uix-scheduling-calendar__header", children: [
|
|
4196
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { children: [
|
|
4197
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => movePeriod(-1), disabled: !onAnchorDateChange, children: "Previous" }),
|
|
4198
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => movePeriod(1), disabled: !onAnchorDateChange, children: "Next" })
|
|
4146
4199
|
] }),
|
|
4147
|
-
/* @__PURE__ */ (0,
|
|
4148
|
-
/* @__PURE__ */ (0,
|
|
4200
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("strong", { children: view === "month" ? new Intl.DateTimeFormat(locale, { month: "long", year: "numeric", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${anchorDate}T00:00:00Z`)) : `${dateLabel(weekStart, locale)} \u2013 ${dateLabel(weekDays[weekDays.length - 1], locale)}` }),
|
|
4201
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "uix-segmented", role: "group", "aria-label": "Calendar view", children: ["month", "week", "agenda"].map((option) => /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("button", { type: "button", className: "uix-segmented__option", "aria-pressed": view === option, "data-selected": view === option || void 0, onClick: () => setView(option), children: [
|
|
4149
4202
|
option[0].toUpperCase(),
|
|
4150
4203
|
option.slice(1)
|
|
4151
4204
|
] }, option)) })
|
|
4152
4205
|
] }),
|
|
4153
|
-
loading ? /* @__PURE__ */ (0,
|
|
4154
|
-
/* @__PURE__ */ (0,
|
|
4155
|
-
onRetry && /* @__PURE__ */ (0,
|
|
4156
|
-
] }) : view === "agenda" ? /* @__PURE__ */ (0,
|
|
4206
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "uix-scheduling-calendar__state", role: "status", children: "Loading schedule\u2026" }) : error ? /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "uix-scheduling-calendar__state", role: "alert", children: [
|
|
4207
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { children: error }),
|
|
4208
|
+
onRetry && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: "Try again" })
|
|
4209
|
+
] }) : view === "agenda" ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "uix-scheduling-calendar__agenda", role: "region", "aria-label": "Schedule agenda", children: visibleEntries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("p", { children: "No scheduled entries match the current filters." }) : /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("ol", { children: [...visibleEntries].sort((a, b) => a.start.localeCompare(b.start)).map((entry) => {
|
|
4157
4210
|
const state = entry.state ?? "scheduled";
|
|
4158
|
-
return /* @__PURE__ */ (0,
|
|
4159
|
-
/* @__PURE__ */ (0,
|
|
4160
|
-
/* @__PURE__ */ (0,
|
|
4161
|
-
/* @__PURE__ */ (0,
|
|
4211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("button", { type: "button", onClick: () => onSelectEntry?.(entry), children: [
|
|
4212
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { children: [
|
|
4213
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("strong", { children: renderEntry?.(entry) ?? entry.title }),
|
|
4214
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("span", { children: [
|
|
4162
4215
|
formatInstant(entry.start),
|
|
4163
4216
|
" \u2013 ",
|
|
4164
4217
|
formatInstant(entry.end)
|
|
4165
4218
|
] }),
|
|
4166
|
-
entry.meta && /* @__PURE__ */ (0,
|
|
4219
|
+
entry.meta && /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { children: entry.meta })
|
|
4167
4220
|
] }),
|
|
4168
|
-
/* @__PURE__ */ (0,
|
|
4221
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)(StatusPill, { tone: stateTone(state), children: stateLabel[state] })
|
|
4169
4222
|
] }) }, entry.id);
|
|
4170
|
-
}) }) }) : /* @__PURE__ */ (0,
|
|
4223
|
+
}) }) }) : /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { ref: gridRef, className: cx("uix-scheduling-calendar__grid", view === "week" && "uix-scheduling-calendar__grid--week"), role: "group", "aria-label": `${view} schedule`, children: days.map((date, index) => {
|
|
4171
4224
|
const dayEntries = entriesFor(date);
|
|
4172
4225
|
const dayOverlays = overlaysFor(date);
|
|
4173
|
-
return /* @__PURE__ */ (0,
|
|
4174
|
-
/* @__PURE__ */ (0,
|
|
4175
|
-
dayOverlays.map((overlay) => /* @__PURE__ */ (0,
|
|
4176
|
-
/* @__PURE__ */ (0,
|
|
4226
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("div", { className: "uix-scheduling-calendar__day", "data-outside": view === "month" && !monthDays[index].inMonth || void 0, children: [
|
|
4227
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("button", { type: "button", className: "uix-scheduling-calendar__date", "data-calendar-date": date, tabIndex: activeDate === date ? 0 : -1, onFocus: () => setActiveDate(date), onKeyDown: (event) => onDayKeyDown(event, date), "aria-label": dateLabel(date, locale), children: Number(date.slice(-2)) }),
|
|
4228
|
+
dayOverlays.map((overlay) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "uix-scheduling-calendar__overlay", "data-kind": overlay.kind, children: overlay.label }, overlay.id)),
|
|
4229
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "uix-scheduling-calendar__entries", children: dayEntries.map((entry) => {
|
|
4177
4230
|
const span = entrySpans.get(entry.id);
|
|
4178
4231
|
const state = entry.state ?? "scheduled";
|
|
4179
|
-
return /* @__PURE__ */ (0,
|
|
4180
|
-
/* @__PURE__ */ (0,
|
|
4181
|
-
/* @__PURE__ */ (0,
|
|
4232
|
+
return /* @__PURE__ */ (0, import_jsx_runtime61.jsxs)("button", { type: "button", className: "uix-scheduling-calendar__entry", "data-state": state, "data-range-start": date === span.start || void 0, "data-range-end": date === span.end || void 0, onClick: () => onSelectEntry?.(entry), "aria-label": `${entry.title}, ${stateLabel[state]}, ${formatInstant(entry.start)} to ${formatInstant(entry.end)}`, children: [
|
|
4233
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { children: renderEntry?.(entry) ?? entry.title }),
|
|
4234
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { className: "uix-visually-hidden", children: stateLabel[state] })
|
|
4182
4235
|
] }, entry.id);
|
|
4183
4236
|
}) })
|
|
4184
4237
|
] }, date);
|
|
4185
4238
|
}) }),
|
|
4186
|
-
/* @__PURE__ */ (0,
|
|
4239
|
+
/* @__PURE__ */ (0, import_jsx_runtime61.jsx)("div", { className: "uix-scheduling-calendar__legend", "aria-label": "Schedule state legend", children: ["scheduled", "conflicted", "in-progress", "blackout-violation"].map((state) => /* @__PURE__ */ (0, import_jsx_runtime61.jsx)("span", { "data-state": state, children: stateLabel[state] }, state)) })
|
|
4187
4240
|
] });
|
|
4188
4241
|
}
|
|
4189
4242
|
|
|
4190
4243
|
// src/components/DateRangePicker.tsx
|
|
4191
4244
|
var import_react39 = require("react");
|
|
4192
|
-
var
|
|
4245
|
+
var import_jsx_runtime62 = require("react/jsx-runtime");
|
|
4193
4246
|
var monthLabel = (date, locale) => new Intl.DateTimeFormat(locale, { month: "long", year: "numeric", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${date}T00:00:00Z`));
|
|
4194
4247
|
var dateLabel2 = (date, locale) => new Intl.DateTimeFormat(locale, { dateStyle: "full", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${date}T00:00:00Z`));
|
|
4195
4248
|
function DateRangePicker({
|
|
@@ -4264,23 +4317,23 @@ function DateRangePicker({
|
|
|
4264
4317
|
}
|
|
4265
4318
|
};
|
|
4266
4319
|
const announcement = !value.start ? "No date range selected." : !value.end ? `Start date ${dateLabel2(value.start, locale)} selected. Choose an end date.` : `${dateLabel2(value.start, locale)} to ${dateLabel2(value.end, locale)} selected.`;
|
|
4267
|
-
return /* @__PURE__ */ (0,
|
|
4268
|
-
/* @__PURE__ */ (0,
|
|
4269
|
-
/* @__PURE__ */ (0,
|
|
4270
|
-
/* @__PURE__ */ (0,
|
|
4271
|
-
/* @__PURE__ */ (0,
|
|
4272
|
-
/* @__PURE__ */ (0,
|
|
4320
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("section", { className: cx("uix-date-range-picker", rangeInvalid && "uix-date-range-picker--invalid", className), "aria-labelledby": `${id}-label`, children: [
|
|
4321
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "uix-date-range-picker__header", children: [
|
|
4322
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("h3", { id: `${id}-label`, children: label }),
|
|
4323
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { children: [
|
|
4324
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => setMonth(addCalendarMonths(visibleMonth, -1)), "aria-label": "Show previous month", children: "Previous" }),
|
|
4325
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => setMonth(addCalendarMonths(visibleMonth, 1)), "aria-label": "Show next month", children: "Next" })
|
|
4273
4326
|
] })
|
|
4274
4327
|
] }),
|
|
4275
|
-
/* @__PURE__ */ (0,
|
|
4276
|
-
/* @__PURE__ */ (0,
|
|
4277
|
-
/* @__PURE__ */ (0,
|
|
4278
|
-
/* @__PURE__ */ (0,
|
|
4279
|
-
Array.from({ length: ((/* @__PURE__ */ new Date(`${month}T00:00:00Z`)).getUTCDay() + 6) % 7 }, (_, index) => /* @__PURE__ */ (0,
|
|
4328
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { ref: rootRef, className: "uix-date-range-picker__months", children: calendars.map(({ month, days }) => /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "uix-date-range-picker__month", children: [
|
|
4329
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("h4", { children: monthLabel(month, locale) }),
|
|
4330
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "uix-date-range-picker__weekdays", "aria-hidden": "true", children: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"].map((day) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { children: day }, day)) }),
|
|
4331
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "uix-date-range-picker__grid", role: "group", "aria-label": monthLabel(month, locale), children: [
|
|
4332
|
+
Array.from({ length: ((/* @__PURE__ */ new Date(`${month}T00:00:00Z`)).getUTCDay() + 6) % 7 }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { "aria-hidden": "true" }, `blank-${index}`)),
|
|
4280
4333
|
days.map((day) => {
|
|
4281
4334
|
const unavailable = disabled || isDateUnavailable(day.date, { min, max, isDisabled: isDateDisabled });
|
|
4282
4335
|
const edge = day.date === value.start ? "start" : day.date === value.end ? "end" : void 0;
|
|
4283
|
-
return /* @__PURE__ */ (0,
|
|
4336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
|
|
4284
4337
|
"button",
|
|
4285
4338
|
{
|
|
4286
4339
|
type: "button",
|
|
@@ -4301,13 +4354,13 @@ function DateRangePicker({
|
|
|
4301
4354
|
})
|
|
4302
4355
|
] })
|
|
4303
4356
|
] }, month)) }),
|
|
4304
|
-
/* @__PURE__ */ (0,
|
|
4305
|
-
rangeInvalid && /* @__PURE__ */ (0,
|
|
4357
|
+
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: "uix-date-range-picker__selection", "aria-live": "polite", children: announcement }),
|
|
4358
|
+
rangeInvalid && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("p", { className: "uix-field__error", role: "alert", children: invalidMessage })
|
|
4306
4359
|
] });
|
|
4307
4360
|
}
|
|
4308
4361
|
|
|
4309
4362
|
// src/components/RelationshipGraph.tsx
|
|
4310
|
-
var
|
|
4363
|
+
var import_react41 = require("react");
|
|
4311
4364
|
|
|
4312
4365
|
// src/relationship-graph-model.ts
|
|
4313
4366
|
function boundRelationshipGraph(nodes, edges, maxNodes = 40) {
|
|
@@ -4372,37 +4425,973 @@ function traverseRelationshipNode(nodes, currentId, direction) {
|
|
|
4372
4425
|
const current = Math.max(0, nodes.findIndex((node) => node.id === currentId));
|
|
4373
4426
|
return nodes[(current + direction + nodes.length) % nodes.length]?.id;
|
|
4374
4427
|
}
|
|
4428
|
+
var LAYERED_GEOMETRY = {
|
|
4429
|
+
standard: { nodeWidth: 176, nodeHeight: 76, columnGap: 96, rowGap: 12 },
|
|
4430
|
+
compact: { nodeWidth: 160, nodeHeight: 60, columnGap: 80, rowGap: 8 }
|
|
4431
|
+
};
|
|
4432
|
+
var LAYERED_PADDING = 16;
|
|
4433
|
+
var LAYERED_HEADER = 28;
|
|
4434
|
+
var GROUP_HEADER = 28;
|
|
4435
|
+
var AUTO_LABEL_MAX_FANOUT = 4;
|
|
4436
|
+
var LABEL_CHAR_WIDTH = 5.6;
|
|
4437
|
+
var LABEL_MAX_LINES = 2;
|
|
4438
|
+
function wrapEdgeLabel(label, width) {
|
|
4439
|
+
const max = Math.max(4, Math.floor(width / LABEL_CHAR_WIDTH));
|
|
4440
|
+
const clip = (word) => word.length > max ? `${word.slice(0, max - 1)}\u2026` : word;
|
|
4441
|
+
const lines = [];
|
|
4442
|
+
let current = "";
|
|
4443
|
+
for (const word of label.split(/\s+/).filter(Boolean)) {
|
|
4444
|
+
const next = current ? `${current} ${word}` : word;
|
|
4445
|
+
if (next.length <= max) {
|
|
4446
|
+
current = next;
|
|
4447
|
+
continue;
|
|
4448
|
+
}
|
|
4449
|
+
if (current) lines.push(current);
|
|
4450
|
+
current = clip(word);
|
|
4451
|
+
if (lines.length === LABEL_MAX_LINES) break;
|
|
4452
|
+
}
|
|
4453
|
+
if (current && lines.length < LABEL_MAX_LINES) lines.push(current);
|
|
4454
|
+
if (lines.length === LABEL_MAX_LINES) {
|
|
4455
|
+
const consumed = lines.join(" ").replace(/…$/, "").length;
|
|
4456
|
+
if (consumed < label.replace(/\s+/g, " ").trim().length) {
|
|
4457
|
+
const last = lines[LABEL_MAX_LINES - 1];
|
|
4458
|
+
lines[LABEL_MAX_LINES - 1] = last.endsWith("\u2026") ? last : `${last.slice(0, Math.max(1, max - 1))}\u2026`;
|
|
4459
|
+
}
|
|
4460
|
+
}
|
|
4461
|
+
return lines;
|
|
4462
|
+
}
|
|
4463
|
+
var drawableEdge = (edge, ids) => ids.has(edge.source) && ids.has(edge.target) && edge.source !== edge.target;
|
|
4464
|
+
function classifyLayeredEdges(nodes, edges, rootId = nodes[0]?.id) {
|
|
4465
|
+
const ids = new Set(nodes.map((node) => node.id));
|
|
4466
|
+
const root = rootId !== void 0 && ids.has(rootId) ? rootId : nodes[0]?.id;
|
|
4467
|
+
const outgoing = /* @__PURE__ */ new Map();
|
|
4468
|
+
for (const edge of edges) {
|
|
4469
|
+
if (!drawableEdge(edge, ids)) continue;
|
|
4470
|
+
const list = outgoing.get(edge.source);
|
|
4471
|
+
if (list) list.push(edge.target);
|
|
4472
|
+
else outgoing.set(edge.source, [edge.target]);
|
|
4473
|
+
}
|
|
4474
|
+
const bfs = /* @__PURE__ */ new Map();
|
|
4475
|
+
if (root !== void 0) {
|
|
4476
|
+
bfs.set(root, 0);
|
|
4477
|
+
const queue = [root];
|
|
4478
|
+
for (let head = 0; head < queue.length; head += 1) {
|
|
4479
|
+
const current = queue[head];
|
|
4480
|
+
for (const next of outgoing.get(current) ?? []) {
|
|
4481
|
+
if (!bfs.has(next)) {
|
|
4482
|
+
bfs.set(next, bfs.get(current) + 1);
|
|
4483
|
+
queue.push(next);
|
|
4484
|
+
}
|
|
4485
|
+
}
|
|
4486
|
+
}
|
|
4487
|
+
}
|
|
4488
|
+
const depthById = /* @__PURE__ */ new Map();
|
|
4489
|
+
let deepest = 0;
|
|
4490
|
+
for (const node of nodes) {
|
|
4491
|
+
const supplied = node.depth !== void 0 && Number.isFinite(node.depth) ? Math.max(0, Math.floor(node.depth)) : void 0;
|
|
4492
|
+
const depth = supplied ?? bfs.get(node.id);
|
|
4493
|
+
if (depth === void 0) continue;
|
|
4494
|
+
depthById.set(node.id, depth);
|
|
4495
|
+
deepest = Math.max(deepest, depth);
|
|
4496
|
+
}
|
|
4497
|
+
for (const node of nodes) if (!depthById.has(node.id)) depthById.set(node.id, deepest + 1);
|
|
4498
|
+
const forwardOut = /* @__PURE__ */ new Map();
|
|
4499
|
+
const kindById = /* @__PURE__ */ new Map();
|
|
4500
|
+
const backEdges = [];
|
|
4501
|
+
for (const edge of edges) {
|
|
4502
|
+
if (!drawableEdge(edge, ids)) continue;
|
|
4503
|
+
const from = depthById.get(edge.source);
|
|
4504
|
+
const to = depthById.get(edge.target);
|
|
4505
|
+
if (to === from + 1) {
|
|
4506
|
+
kindById.set(edge.id, "forward");
|
|
4507
|
+
const list = forwardOut.get(edge.source);
|
|
4508
|
+
if (list) list.push(edge.target);
|
|
4509
|
+
else forwardOut.set(edge.source, [edge.target]);
|
|
4510
|
+
} else if (to < from) {
|
|
4511
|
+
backEdges.push(edge);
|
|
4512
|
+
} else {
|
|
4513
|
+
kindById.set(edge.id, "lateral");
|
|
4514
|
+
}
|
|
4515
|
+
}
|
|
4516
|
+
for (const edge of backEdges) {
|
|
4517
|
+
const limit = depthById.get(edge.source);
|
|
4518
|
+
const seen = /* @__PURE__ */ new Set([edge.target]);
|
|
4519
|
+
const stack = [edge.target];
|
|
4520
|
+
let closes = false;
|
|
4521
|
+
while (stack.length > 0 && !closes) {
|
|
4522
|
+
const current = stack.pop();
|
|
4523
|
+
for (const next of forwardOut.get(current) ?? []) {
|
|
4524
|
+
if (next === edge.source) {
|
|
4525
|
+
closes = true;
|
|
4526
|
+
break;
|
|
4527
|
+
}
|
|
4528
|
+
if (!seen.has(next) && depthById.get(next) < limit) {
|
|
4529
|
+
seen.add(next);
|
|
4530
|
+
stack.push(next);
|
|
4531
|
+
}
|
|
4532
|
+
}
|
|
4533
|
+
}
|
|
4534
|
+
kindById.set(edge.id, closes ? "cycle" : "lateral");
|
|
4535
|
+
}
|
|
4536
|
+
return { depthById, kindById };
|
|
4537
|
+
}
|
|
4538
|
+
function clusterIdFor(parentId, type, edgeType) {
|
|
4539
|
+
return `cluster:${parentId}:${type ?? ""}:${edgeType ?? ""}`;
|
|
4540
|
+
}
|
|
4541
|
+
var mean = (values) => values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
4542
|
+
var round1 = (value) => Math.round(value * 10) / 10;
|
|
4543
|
+
function layoutLayeredGraph(nodes, edges, options = {}) {
|
|
4544
|
+
const { nodeWidth, nodeHeight, columnGap, rowGap } = LAYERED_GEOMETRY[options.density ?? "standard"];
|
|
4545
|
+
const threshold = options.clusterThreshold ?? 6;
|
|
4546
|
+
const expanded = options.expandedClusterIds ?? /* @__PURE__ */ new Set();
|
|
4547
|
+
const rootId = options.rootId !== void 0 && nodes.some((node) => node.id === options.rootId) ? options.rootId : nodes[0]?.id;
|
|
4548
|
+
if (nodes.length === 0) {
|
|
4549
|
+
return {
|
|
4550
|
+
rootId,
|
|
4551
|
+
items: [],
|
|
4552
|
+
edges: [],
|
|
4553
|
+
clusters: [],
|
|
4554
|
+
columns: [],
|
|
4555
|
+
itemOf: {},
|
|
4556
|
+
width: 0,
|
|
4557
|
+
height: 0,
|
|
4558
|
+
nodeWidth,
|
|
4559
|
+
nodeHeight,
|
|
4560
|
+
headerHeight: LAYERED_HEADER
|
|
4561
|
+
};
|
|
4562
|
+
}
|
|
4563
|
+
const { depthById, kindById } = classifyLayeredEdges(nodes, edges, rootId);
|
|
4564
|
+
const drawable = edges.filter((edge) => kindById.has(edge.id));
|
|
4565
|
+
const forwardParents = /* @__PURE__ */ new Map();
|
|
4566
|
+
const forwardChildCount = /* @__PURE__ */ new Map();
|
|
4567
|
+
const inCycle = /* @__PURE__ */ new Set();
|
|
4568
|
+
const nodeDegree = /* @__PURE__ */ new Map();
|
|
4569
|
+
for (const edge of drawable) {
|
|
4570
|
+
nodeDegree.set(edge.source, (nodeDegree.get(edge.source) ?? 0) + 1);
|
|
4571
|
+
nodeDegree.set(edge.target, (nodeDegree.get(edge.target) ?? 0) + 1);
|
|
4572
|
+
if (kindById.get(edge.id) === "forward") {
|
|
4573
|
+
const list = forwardParents.get(edge.target);
|
|
4574
|
+
if (list) list.push(edge);
|
|
4575
|
+
else forwardParents.set(edge.target, [edge]);
|
|
4576
|
+
forwardChildCount.set(edge.source, (forwardChildCount.get(edge.source) ?? 0) + 1);
|
|
4577
|
+
} else {
|
|
4578
|
+
inCycle.add(edge.source);
|
|
4579
|
+
inCycle.add(edge.target);
|
|
4580
|
+
}
|
|
4581
|
+
}
|
|
4582
|
+
const groups = /* @__PURE__ */ new Map();
|
|
4583
|
+
if (threshold > 0) {
|
|
4584
|
+
for (const node of nodes) {
|
|
4585
|
+
if (node.id === rootId || inCycle.has(node.id) || (forwardChildCount.get(node.id) ?? 0) > 0) continue;
|
|
4586
|
+
const parents = forwardParents.get(node.id) ?? [];
|
|
4587
|
+
if (parents.length !== 1) continue;
|
|
4588
|
+
const via = parents[0];
|
|
4589
|
+
const id = clusterIdFor(via.source, node.type, via.type);
|
|
4590
|
+
const group = groups.get(id);
|
|
4591
|
+
if (group) {
|
|
4592
|
+
group.members.push(node);
|
|
4593
|
+
continue;
|
|
4594
|
+
}
|
|
4595
|
+
const created = { id, parentId: via.source, depth: depthById.get(node.id), members: [node] };
|
|
4596
|
+
if (node.type !== void 0) created.type = node.type;
|
|
4597
|
+
if (via.type !== void 0) created.edgeType = via.type;
|
|
4598
|
+
const edgeLabel = via.label ?? via.type;
|
|
4599
|
+
if (edgeLabel !== void 0) created.edgeLabel = edgeLabel;
|
|
4600
|
+
groups.set(id, created);
|
|
4601
|
+
}
|
|
4602
|
+
}
|
|
4603
|
+
const clusterById = /* @__PURE__ */ new Map();
|
|
4604
|
+
const itemOf = {};
|
|
4605
|
+
const expandedGroupOf = /* @__PURE__ */ new Map();
|
|
4606
|
+
for (const group of groups.values()) {
|
|
4607
|
+
if (group.members.length < threshold) continue;
|
|
4608
|
+
if (expanded.has(group.id)) {
|
|
4609
|
+
for (const member of group.members) expandedGroupOf.set(member.id, group);
|
|
4610
|
+
continue;
|
|
4611
|
+
}
|
|
4612
|
+
clusterById.set(group.id, group);
|
|
4613
|
+
for (const member of group.members) itemOf[member.id] = group.id;
|
|
4614
|
+
}
|
|
4615
|
+
for (const node of nodes) if (itemOf[node.id] === void 0) itemOf[node.id] = node.id;
|
|
4616
|
+
const columnsByDepth = /* @__PURE__ */ new Map();
|
|
4617
|
+
const itemById = /* @__PURE__ */ new Map();
|
|
4618
|
+
for (const node of nodes) {
|
|
4619
|
+
const id = itemOf[node.id];
|
|
4620
|
+
if (itemById.has(id)) continue;
|
|
4621
|
+
const cluster = clusterById.get(id);
|
|
4622
|
+
const depth = depthById.get(node.id);
|
|
4623
|
+
const item = {
|
|
4624
|
+
id,
|
|
4625
|
+
kind: cluster ? "cluster" : "node",
|
|
4626
|
+
depth,
|
|
4627
|
+
index: 0,
|
|
4628
|
+
x: 0,
|
|
4629
|
+
y: 0,
|
|
4630
|
+
width: nodeWidth,
|
|
4631
|
+
height: nodeHeight,
|
|
4632
|
+
parents: [],
|
|
4633
|
+
children: [],
|
|
4634
|
+
inCycle: cluster ? false : inCycle.has(node.id),
|
|
4635
|
+
degree: cluster ? cluster.members.length : nodeDegree.get(node.id) ?? 0
|
|
4636
|
+
};
|
|
4637
|
+
if (cluster) item.cluster = cluster;
|
|
4638
|
+
else item.node = node;
|
|
4639
|
+
itemById.set(id, item);
|
|
4640
|
+
const column = columnsByDepth.get(depth);
|
|
4641
|
+
if (column) column.push(item);
|
|
4642
|
+
else columnsByDepth.set(depth, [item]);
|
|
4643
|
+
}
|
|
4644
|
+
for (const edge of drawable) {
|
|
4645
|
+
if (kindById.get(edge.id) !== "forward") continue;
|
|
4646
|
+
const from = itemById.get(itemOf[edge.source]);
|
|
4647
|
+
const to = itemById.get(itemOf[edge.target]);
|
|
4648
|
+
if (!from.children.includes(to.id)) from.children.push(to.id);
|
|
4649
|
+
if (!to.parents.includes(from.id)) to.parents.push(from.id);
|
|
4650
|
+
}
|
|
4651
|
+
const depths = [...columnsByDepth.keys()].sort((a, b) => a - b);
|
|
4652
|
+
const position = /* @__PURE__ */ new Map();
|
|
4653
|
+
const reindex = (column) => {
|
|
4654
|
+
column.forEach((item, index) => {
|
|
4655
|
+
item.index = index;
|
|
4656
|
+
position.set(item.id, index);
|
|
4657
|
+
});
|
|
4658
|
+
};
|
|
4659
|
+
for (const depth of depths) reindex(columnsByDepth.get(depth));
|
|
4660
|
+
const groupOfItem = (item) => item.node ? expandedGroupOf.get(item.node.id) : void 0;
|
|
4661
|
+
const sweep = (depth, neighbours) => {
|
|
4662
|
+
const keyed = columnsByDepth.get(depth).map((item) => {
|
|
4663
|
+
const around = neighbours(item).map((id) => position.get(id)).filter((value) => value !== void 0);
|
|
4664
|
+
return { item, key: around.length > 0 ? mean(around) : item.index, tie: item.index };
|
|
4665
|
+
});
|
|
4666
|
+
keyed.sort((a, b) => a.key - b.key || a.tie - b.tie);
|
|
4667
|
+
const ordered = [];
|
|
4668
|
+
const placed = /* @__PURE__ */ new Set();
|
|
4669
|
+
for (const { item } of keyed) {
|
|
4670
|
+
if (placed.has(item.id)) continue;
|
|
4671
|
+
const group = groupOfItem(item);
|
|
4672
|
+
for (const candidate of group ? keyed.map((entry) => entry.item).filter((other) => groupOfItem(other) === group) : [item]) {
|
|
4673
|
+
if (placed.has(candidate.id)) continue;
|
|
4674
|
+
ordered.push(candidate);
|
|
4675
|
+
placed.add(candidate.id);
|
|
4676
|
+
}
|
|
4677
|
+
}
|
|
4678
|
+
columnsByDepth.set(depth, ordered);
|
|
4679
|
+
reindex(ordered);
|
|
4680
|
+
};
|
|
4681
|
+
const inner = depths.slice(1);
|
|
4682
|
+
for (const depth of inner) sweep(depth, (item) => item.parents);
|
|
4683
|
+
for (const depth of [...inner].reverse()) sweep(depth, (item) => item.children);
|
|
4684
|
+
for (const depth of inner) sweep(depth, (item) => item.parents);
|
|
4685
|
+
const top = LAYERED_PADDING + LAYERED_HEADER;
|
|
4686
|
+
const columns = [];
|
|
4687
|
+
let width = 0;
|
|
4688
|
+
let height = 0;
|
|
4689
|
+
for (const depth of depths) {
|
|
4690
|
+
const column = columnsByDepth.get(depth);
|
|
4691
|
+
const x = LAYERED_PADDING + depth * (nodeWidth + columnGap);
|
|
4692
|
+
let cursor = top;
|
|
4693
|
+
let count = 0;
|
|
4694
|
+
const ledGroups = /* @__PURE__ */ new Set();
|
|
4695
|
+
for (const item of column) {
|
|
4696
|
+
const parentCentres = item.parents.map((id) => itemById.get(id)).filter((parent) => parent.depth < depth).map((parent) => parent.y + parent.height / 2);
|
|
4697
|
+
const group = groupOfItem(item);
|
|
4698
|
+
const leadsGroup = group !== void 0 && !ledGroups.has(group);
|
|
4699
|
+
if (group) ledGroups.add(group);
|
|
4700
|
+
const floor = cursor + (leadsGroup ? GROUP_HEADER : 0);
|
|
4701
|
+
const target = parentCentres.length > 0 ? mean(parentCentres) - item.height / 2 : floor;
|
|
4702
|
+
item.x = x;
|
|
4703
|
+
item.y = round1(Math.max(target, floor));
|
|
4704
|
+
if (leadsGroup) item.expandedGroup = group;
|
|
4705
|
+
cursor = item.y + item.height + rowGap;
|
|
4706
|
+
count += item.cluster ? item.cluster.members.length : 1;
|
|
4707
|
+
width = Math.max(width, x + item.width);
|
|
4708
|
+
height = Math.max(height, item.y + item.height);
|
|
4709
|
+
}
|
|
4710
|
+
columns.push({ depth, x, count });
|
|
4711
|
+
}
|
|
4712
|
+
const byPosition = (a, b) => (position.get(a) ?? 0) - (position.get(b) ?? 0);
|
|
4713
|
+
for (const item of itemById.values()) {
|
|
4714
|
+
item.children.sort(byPosition);
|
|
4715
|
+
item.parents.sort(byPosition);
|
|
4716
|
+
}
|
|
4717
|
+
const routed = /* @__PURE__ */ new Map();
|
|
4718
|
+
for (const edge of drawable) {
|
|
4719
|
+
const kind = kindById.get(edge.id);
|
|
4720
|
+
const from = itemById.get(itemOf[edge.source]);
|
|
4721
|
+
const to = itemById.get(itemOf[edge.target]);
|
|
4722
|
+
const key = from.kind === "cluster" || to.kind === "cluster" ? `${from.id}->${to.id}` : edge.id;
|
|
4723
|
+
const existing = routed.get(key);
|
|
4724
|
+
if (existing) {
|
|
4725
|
+
existing.edgeIds.push(edge.id);
|
|
4726
|
+
continue;
|
|
4727
|
+
}
|
|
4728
|
+
let startX;
|
|
4729
|
+
let startY;
|
|
4730
|
+
let endX;
|
|
4731
|
+
let endY;
|
|
4732
|
+
let path;
|
|
4733
|
+
let labelX;
|
|
4734
|
+
let labelY;
|
|
4735
|
+
let startAngle;
|
|
4736
|
+
let endAngle;
|
|
4737
|
+
if (kind === "forward") {
|
|
4738
|
+
startX = from.x + from.width;
|
|
4739
|
+
startY = from.y + from.height / 2;
|
|
4740
|
+
endX = to.x;
|
|
4741
|
+
endY = to.y + to.height / 2;
|
|
4742
|
+
const bend = Math.max(columnGap / 2, 24);
|
|
4743
|
+
path = `M${round1(startX)} ${round1(startY)} C${round1(startX + bend)} ${round1(startY)} ${round1(endX - bend)} ${round1(endY)} ${round1(endX)} ${round1(endY)}`;
|
|
4744
|
+
labelX = (startX + endX) / 2;
|
|
4745
|
+
labelY = (startY + endY) / 2;
|
|
4746
|
+
startAngle = Math.PI;
|
|
4747
|
+
endAngle = 0;
|
|
4748
|
+
} else if (from.depth === to.depth) {
|
|
4749
|
+
startX = from.x + from.width;
|
|
4750
|
+
startY = from.y + from.height / 2;
|
|
4751
|
+
endX = to.x + to.width;
|
|
4752
|
+
endY = to.y + to.height / 2;
|
|
4753
|
+
const bulge = Math.min(columnGap - 8, 20 + Math.abs(endY - startY) * 0.1);
|
|
4754
|
+
path = `M${round1(startX)} ${round1(startY)} C${round1(startX + bulge)} ${round1(startY)} ${round1(endX + bulge)} ${round1(endY)} ${round1(endX)} ${round1(endY)}`;
|
|
4755
|
+
labelX = startX + bulge * 0.75;
|
|
4756
|
+
labelY = (startY + endY) / 2;
|
|
4757
|
+
startAngle = Math.PI;
|
|
4758
|
+
endAngle = Math.PI;
|
|
4759
|
+
} else {
|
|
4760
|
+
startX = from.x + from.width / 2;
|
|
4761
|
+
startY = from.y + from.height;
|
|
4762
|
+
endX = to.x + to.width / 2;
|
|
4763
|
+
endY = to.y + to.height;
|
|
4764
|
+
const dip = 28 + Math.abs(endX - startX) * 0.12;
|
|
4765
|
+
const low = Math.max(startY, endY) + dip;
|
|
4766
|
+
path = `M${round1(startX)} ${round1(startY)} C${round1(startX)} ${round1(low)} ${round1(endX)} ${round1(low)} ${round1(endX)} ${round1(endY)}`;
|
|
4767
|
+
labelX = (startX + endX) / 2;
|
|
4768
|
+
labelY = low - dip * 0.25;
|
|
4769
|
+
startAngle = -Math.PI / 2;
|
|
4770
|
+
endAngle = -Math.PI / 2;
|
|
4771
|
+
height = Math.max(height, low);
|
|
4772
|
+
}
|
|
4773
|
+
const arrow = edge.arrow ?? "forward";
|
|
4774
|
+
const atStart = arrow === "backward";
|
|
4775
|
+
const entry = {
|
|
4776
|
+
id: key,
|
|
4777
|
+
source: from.id,
|
|
4778
|
+
target: to.id,
|
|
4779
|
+
kind,
|
|
4780
|
+
edgeIds: [edge.id],
|
|
4781
|
+
arrow,
|
|
4782
|
+
emphasis: edge.emphasis === true,
|
|
4783
|
+
path,
|
|
4784
|
+
labelX: round1(labelX),
|
|
4785
|
+
labelY: round1(labelY),
|
|
4786
|
+
arrowX: round1(atStart ? startX : endX),
|
|
4787
|
+
arrowY: round1(atStart ? startY : endY),
|
|
4788
|
+
arrowAngle: atStart ? startAngle : endAngle,
|
|
4789
|
+
labelLines: [],
|
|
4790
|
+
autoLabel: to.kind !== "cluster" && (edge.emphasis === true || kind === "forward" && from.children.length <= AUTO_LABEL_MAX_FANOUT)
|
|
4791
|
+
};
|
|
4792
|
+
if (edge.type !== void 0) entry.type = edge.type;
|
|
4793
|
+
const label = edge.label ?? edge.type;
|
|
4794
|
+
if (label !== void 0) entry.label = label;
|
|
4795
|
+
routed.set(key, entry);
|
|
4796
|
+
}
|
|
4797
|
+
const seenLabels = /* @__PURE__ */ new Set();
|
|
4798
|
+
for (const entry of routed.values()) {
|
|
4799
|
+
if (entry.label === void 0) continue;
|
|
4800
|
+
entry.labelLines = wrapEdgeLabel(entry.label, columnGap - 8);
|
|
4801
|
+
if (!entry.autoLabel || entry.emphasis || entry.kind !== "forward") continue;
|
|
4802
|
+
const key = `${entry.source}|${entry.label}`;
|
|
4803
|
+
if (seenLabels.has(key)) entry.autoLabel = false;
|
|
4804
|
+
else seenLabels.add(key);
|
|
4805
|
+
}
|
|
4806
|
+
return {
|
|
4807
|
+
rootId,
|
|
4808
|
+
items: depths.flatMap((depth) => columnsByDepth.get(depth)),
|
|
4809
|
+
edges: [...routed.values()],
|
|
4810
|
+
clusters: [...clusterById.values()],
|
|
4811
|
+
columns,
|
|
4812
|
+
itemOf,
|
|
4813
|
+
width: round1(width + LAYERED_PADDING),
|
|
4814
|
+
height: round1(height + LAYERED_PADDING + 8),
|
|
4815
|
+
nodeWidth,
|
|
4816
|
+
nodeHeight,
|
|
4817
|
+
headerHeight: LAYERED_HEADER
|
|
4818
|
+
};
|
|
4819
|
+
}
|
|
4820
|
+
function layeredNeighbor(layout, currentId, key) {
|
|
4821
|
+
const root = layout.rootId !== void 0 ? layout.itemOf[layout.rootId] : layout.items[0]?.id;
|
|
4822
|
+
const current = layout.items.find((item) => item.id === currentId);
|
|
4823
|
+
if (!current) return root ?? layout.items[0]?.id;
|
|
4824
|
+
const column = layout.items.filter((item) => item.depth === current.depth);
|
|
4825
|
+
switch (key) {
|
|
4826
|
+
case "ArrowUp":
|
|
4827
|
+
return column[current.index - 1]?.id;
|
|
4828
|
+
case "ArrowDown":
|
|
4829
|
+
return column[current.index + 1]?.id;
|
|
4830
|
+
case "ArrowRight":
|
|
4831
|
+
return current.children[0];
|
|
4832
|
+
case "ArrowLeft":
|
|
4833
|
+
return current.parents[0];
|
|
4834
|
+
case "Home":
|
|
4835
|
+
return root;
|
|
4836
|
+
case "End":
|
|
4837
|
+
return column[column.length - 1]?.id;
|
|
4838
|
+
default:
|
|
4839
|
+
return void 0;
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4375
4842
|
|
|
4376
|
-
// src/components/
|
|
4377
|
-
var
|
|
4843
|
+
// src/components/RelationshipGraphLayered.tsx
|
|
4844
|
+
var import_react40 = require("react");
|
|
4845
|
+
|
|
4846
|
+
// src/components/RelationshipGraphList.tsx
|
|
4847
|
+
var import_jsx_runtime63 = require("react/jsx-runtime");
|
|
4848
|
+
function EquivalentRelationshipList({
|
|
4849
|
+
nodes,
|
|
4850
|
+
edges,
|
|
4851
|
+
selectedId,
|
|
4852
|
+
labels,
|
|
4853
|
+
onSelect,
|
|
4854
|
+
onExpandNeighbors,
|
|
4855
|
+
onOpenDetails
|
|
4856
|
+
}) {
|
|
4857
|
+
const labelById = new Map(nodes.map((node) => [node.id, node.label]));
|
|
4858
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "uix-relationship-graph__list", role: "region", "aria-label": labels.list, children: [
|
|
4859
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("h3", { children: labels.listHeading }),
|
|
4860
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("ul", { children: nodes.map((node) => {
|
|
4861
|
+
const neighbors = relationshipNeighbors(node.id, edges).map((id) => labelById.get(id) ?? id);
|
|
4862
|
+
return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("li", { "data-selected": selectedId === node.id || void 0, children: [
|
|
4863
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("button", { type: "button", onClick: () => onSelect(node.id), "aria-pressed": selectedId === node.id, children: [
|
|
4864
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("strong", { children: node.label }),
|
|
4865
|
+
node.type && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { children: node.type }),
|
|
4866
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { children: neighbors.length ? labels.connectedTo(neighbors.join(", ")) : labels.noConnections })
|
|
4867
|
+
] }),
|
|
4868
|
+
/* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "uix-relationship-graph__list-actions", children: [
|
|
4869
|
+
onExpandNeighbors && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("button", { type: "button", onClick: () => onExpandNeighbors(node), children: labels.expandNeighbors }),
|
|
4870
|
+
onOpenDetails && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("button", { type: "button", onClick: () => onOpenDetails(node), children: labels.openDetails })
|
|
4871
|
+
] })
|
|
4872
|
+
] }, node.id);
|
|
4873
|
+
}) })
|
|
4874
|
+
] });
|
|
4875
|
+
}
|
|
4876
|
+
|
|
4877
|
+
// src/components/RelationshipGraphLayered.tsx
|
|
4878
|
+
var import_jsx_runtime64 = require("react/jsx-runtime");
|
|
4378
4879
|
var EMPTY_IDS = /* @__PURE__ */ new Set();
|
|
4379
|
-
var
|
|
4380
|
-
|
|
4880
|
+
var MIN_ZOOM = 0.4;
|
|
4881
|
+
var MAX_ZOOM = 1.5;
|
|
4882
|
+
var READABLE_ZOOM = 0.75;
|
|
4883
|
+
var ZOOM_STEP = 1.2;
|
|
4884
|
+
var PAN_STEP = 64;
|
|
4885
|
+
var FOCUS_MARGIN = 24;
|
|
4886
|
+
var NAV_KEYS = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End"];
|
|
4887
|
+
var clampZoom = (zoom) => Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, zoom));
|
|
4888
|
+
function initialView(layout, size) {
|
|
4889
|
+
if (size.width === 0 || size.height === 0 || layout.width === 0) return { x: 0, y: 0, zoom: 1 };
|
|
4890
|
+
const fit = Math.min(size.width / layout.width, size.height / layout.height);
|
|
4891
|
+
if (fit < READABLE_ZOOM) return { x: 0, y: 0, zoom: READABLE_ZOOM };
|
|
4892
|
+
const zoom = Math.min(fit, 1);
|
|
4893
|
+
return { x: (size.width - layout.width * zoom) / 2, y: Math.max(0, (size.height - layout.height * zoom) / 2), zoom };
|
|
4894
|
+
}
|
|
4895
|
+
function fitView(layout, size) {
|
|
4896
|
+
if (size.width === 0 || layout.width === 0) return { x: 0, y: 0, zoom: 1 };
|
|
4897
|
+
const zoom = clampZoom(Math.min(size.width / layout.width, size.height / layout.height, 1));
|
|
4898
|
+
return { x: (size.width - layout.width * zoom) / 2, y: Math.max(0, (size.height - layout.height * zoom) / 2), zoom };
|
|
4899
|
+
}
|
|
4900
|
+
var arrowPoints = "0,0 -8,-4.5 -8,4.5";
|
|
4901
|
+
function LayeredRelationshipGraph({
|
|
4381
4902
|
nodes,
|
|
4382
4903
|
edges,
|
|
4383
4904
|
selectedId,
|
|
4384
4905
|
onSelect,
|
|
4385
4906
|
onExpandNeighbors,
|
|
4386
4907
|
onOpenDetails,
|
|
4387
|
-
maxNodes =
|
|
4908
|
+
maxNodes = 400,
|
|
4388
4909
|
density = "standard",
|
|
4389
4910
|
highlightedNodeIds = EMPTY_IDS,
|
|
4390
4911
|
conflictedNodeIds = EMPTY_IDS,
|
|
4391
4912
|
highlightedEdgeIds = EMPTY_IDS,
|
|
4392
4913
|
conflictedEdgeIds = EMPTY_IDS,
|
|
4393
|
-
legend =
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4914
|
+
legend = [],
|
|
4915
|
+
className,
|
|
4916
|
+
labels,
|
|
4917
|
+
rootId,
|
|
4918
|
+
renderNode,
|
|
4919
|
+
nodeAriaLabel,
|
|
4920
|
+
renderCluster,
|
|
4921
|
+
clusterThreshold,
|
|
4922
|
+
expandedClusterIds,
|
|
4923
|
+
onToggleCluster,
|
|
4924
|
+
dimmedNodeIds = EMPTY_IDS,
|
|
4925
|
+
edgeLabels = "auto",
|
|
4926
|
+
showList = true,
|
|
4927
|
+
height,
|
|
4928
|
+
focusId,
|
|
4929
|
+
onFocusChange
|
|
4398
4930
|
}) {
|
|
4931
|
+
const hintId = (0, import_react40.useId)();
|
|
4399
4932
|
const bounded = (0, import_react40.useMemo)(() => boundRelationshipGraph(nodes, edges, maxNodes), [nodes, edges, maxNodes]);
|
|
4400
|
-
const
|
|
4401
|
-
const
|
|
4402
|
-
const
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4933
|
+
const [localExpanded, setLocalExpanded] = (0, import_react40.useState)(EMPTY_IDS);
|
|
4934
|
+
const expanded = expandedClusterIds ?? localExpanded;
|
|
4935
|
+
const layout = (0, import_react40.useMemo)(
|
|
4936
|
+
() => layoutLayeredGraph(bounded.nodes, bounded.edges, {
|
|
4937
|
+
...rootId !== void 0 ? { rootId } : {},
|
|
4938
|
+
...clusterThreshold !== void 0 ? { clusterThreshold } : {},
|
|
4939
|
+
expandedClusterIds: expanded,
|
|
4940
|
+
density
|
|
4941
|
+
}),
|
|
4942
|
+
[bounded, rootId, clusterThreshold, expanded, density]
|
|
4943
|
+
);
|
|
4944
|
+
const itemById = (0, import_react40.useMemo)(() => new Map(layout.items.map((item) => [item.id, item])), [layout]);
|
|
4945
|
+
const viewportRef = (0, import_react40.useRef)(null);
|
|
4946
|
+
const itemRefs = (0, import_react40.useRef)(/* @__PURE__ */ new Map());
|
|
4947
|
+
const [size, setSize] = (0, import_react40.useState)({ width: 0, height: 0 });
|
|
4948
|
+
const [view, setView] = (0, import_react40.useState)({ x: 0, y: 0, zoom: 1 });
|
|
4949
|
+
const [animate, setAnimate] = (0, import_react40.useState)(false);
|
|
4950
|
+
const [localFocus, setLocalFocus] = (0, import_react40.useState)(void 0);
|
|
4951
|
+
const [hoverId, setHoverId] = (0, import_react40.useState)(void 0);
|
|
4952
|
+
const viewRef = (0, import_react40.useRef)(view);
|
|
4953
|
+
viewRef.current = view;
|
|
4954
|
+
const layoutRef = (0, import_react40.useRef)(layout);
|
|
4955
|
+
layoutRef.current = layout;
|
|
4956
|
+
const pendingFocus = (0, import_react40.useRef)(void 0);
|
|
4957
|
+
const initialisedFor = (0, import_react40.useRef)(void 0);
|
|
4958
|
+
const rootItemId = layout.rootId !== void 0 ? layout.itemOf[layout.rootId] : layout.items[0]?.id;
|
|
4959
|
+
const requestedFocus = focusId !== void 0 ? layout.itemOf[focusId] ?? focusId : localFocus;
|
|
4960
|
+
const focusedId = requestedFocus !== void 0 && itemById.has(requestedFocus) ? requestedFocus : rootItemId;
|
|
4961
|
+
const selectedItemId = selectedId !== void 0 ? layout.itemOf[selectedId] : void 0;
|
|
4962
|
+
const activeIds = (0, import_react40.useMemo)(
|
|
4963
|
+
() => new Set([hoverId, selectedItemId].filter((id) => id !== void 0)),
|
|
4964
|
+
[hoverId, selectedItemId]
|
|
4965
|
+
);
|
|
4966
|
+
(0, import_react40.useEffect)(() => {
|
|
4967
|
+
const element = viewportRef.current;
|
|
4968
|
+
if (!element) return;
|
|
4969
|
+
const measure = () => setSize({ width: element.clientWidth, height: element.clientHeight });
|
|
4970
|
+
measure();
|
|
4971
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
4972
|
+
const observer = new ResizeObserver(measure);
|
|
4973
|
+
observer.observe(element);
|
|
4974
|
+
return () => observer.disconnect();
|
|
4975
|
+
}, []);
|
|
4976
|
+
(0, import_react40.useEffect)(() => {
|
|
4977
|
+
if (size.width === 0) return;
|
|
4978
|
+
const key = `${layout.rootId ?? ""}`;
|
|
4979
|
+
if (initialisedFor.current === key) return;
|
|
4980
|
+
initialisedFor.current = key;
|
|
4981
|
+
setView(initialView(layout, size));
|
|
4982
|
+
}, [layout, size]);
|
|
4983
|
+
const moveView = (0, import_react40.useCallback)((next, smooth) => {
|
|
4984
|
+
setAnimate(smooth);
|
|
4985
|
+
setView(next);
|
|
4986
|
+
}, []);
|
|
4987
|
+
const ensureVisible = (0, import_react40.useCallback)((id, smooth) => {
|
|
4988
|
+
const element = viewportRef.current;
|
|
4989
|
+
const item = layoutRef.current.items.find((candidate) => candidate.id === id);
|
|
4990
|
+
if (!element || !item) return;
|
|
4991
|
+
const { x, y, zoom } = viewRef.current;
|
|
4992
|
+
const width = element.clientWidth;
|
|
4993
|
+
const heightPx = element.clientHeight;
|
|
4994
|
+
const left = item.x * zoom + x;
|
|
4995
|
+
const top = item.y * zoom + y;
|
|
4996
|
+
const right = left + item.width * zoom;
|
|
4997
|
+
const bottom = top + item.height * zoom;
|
|
4998
|
+
let nextX = x;
|
|
4999
|
+
let nextY = y;
|
|
5000
|
+
if (left < FOCUS_MARGIN) nextX += FOCUS_MARGIN - left;
|
|
5001
|
+
else if (right > width - FOCUS_MARGIN) nextX -= right - (width - FOCUS_MARGIN);
|
|
5002
|
+
if (top < FOCUS_MARGIN) nextY += FOCUS_MARGIN - top;
|
|
5003
|
+
else if (bottom > heightPx - FOCUS_MARGIN) nextY -= bottom - (heightPx - FOCUS_MARGIN);
|
|
5004
|
+
if (nextX !== x || nextY !== y) moveView({ x: nextX, y: nextY, zoom }, smooth);
|
|
5005
|
+
}, [moveView]);
|
|
5006
|
+
const focusItem = (0, import_react40.useCallback)((id) => {
|
|
5007
|
+
setLocalFocus(id);
|
|
5008
|
+
onFocusChange?.(id);
|
|
5009
|
+
requestAnimationFrame(() => {
|
|
5010
|
+
itemRefs.current.get(id)?.focus({ preventScroll: true });
|
|
5011
|
+
ensureVisible(id, true);
|
|
5012
|
+
});
|
|
5013
|
+
}, [ensureVisible, onFocusChange]);
|
|
5014
|
+
(0, import_react40.useEffect)(() => {
|
|
5015
|
+
const wanted = pendingFocus.current;
|
|
5016
|
+
if (wanted !== void 0 && itemById.has(wanted)) {
|
|
5017
|
+
pendingFocus.current = void 0;
|
|
5018
|
+
focusItem(wanted);
|
|
5019
|
+
}
|
|
5020
|
+
}, [itemById, focusItem]);
|
|
5021
|
+
const controlledTarget = focusId !== void 0 ? layout.itemOf[focusId] ?? focusId : void 0;
|
|
5022
|
+
const controlledPresent = controlledTarget !== void 0 && itemById.has(controlledTarget);
|
|
5023
|
+
const controlledKey = `${controlledTarget ?? ""}|${controlledPresent}`;
|
|
5024
|
+
const lastControlledKey = (0, import_react40.useRef)(controlledKey);
|
|
5025
|
+
(0, import_react40.useEffect)(() => {
|
|
5026
|
+
if (lastControlledKey.current === controlledKey) return;
|
|
5027
|
+
lastControlledKey.current = controlledKey;
|
|
5028
|
+
if (!controlledPresent || controlledTarget === void 0) return;
|
|
5029
|
+
requestAnimationFrame(() => {
|
|
5030
|
+
itemRefs.current.get(controlledTarget)?.focus({ preventScroll: true });
|
|
5031
|
+
ensureVisible(controlledTarget, true);
|
|
5032
|
+
});
|
|
5033
|
+
}, [controlledKey, controlledTarget, controlledPresent, ensureVisible]);
|
|
5034
|
+
(0, import_react40.useEffect)(() => {
|
|
5035
|
+
const element = viewportRef.current;
|
|
5036
|
+
if (!element) return;
|
|
5037
|
+
const onWheel = (event) => {
|
|
5038
|
+
if (!event.ctrlKey && !event.metaKey) return;
|
|
5039
|
+
event.preventDefault();
|
|
5040
|
+
const rect = element.getBoundingClientRect();
|
|
5041
|
+
const px = event.clientX - rect.left;
|
|
5042
|
+
const py = event.clientY - rect.top;
|
|
5043
|
+
const current = viewRef.current;
|
|
5044
|
+
const zoom = clampZoom(current.zoom * Math.exp(-event.deltaY * 2e-3));
|
|
5045
|
+
const ratio = zoom / current.zoom;
|
|
5046
|
+
setAnimate(false);
|
|
5047
|
+
setView({ zoom, x: px - (px - current.x) * ratio, y: py - (py - current.y) * ratio });
|
|
5048
|
+
};
|
|
5049
|
+
element.addEventListener("wheel", onWheel, { passive: false });
|
|
5050
|
+
return () => element.removeEventListener("wheel", onWheel);
|
|
5051
|
+
}, []);
|
|
5052
|
+
const pointers = (0, import_react40.useRef)(/* @__PURE__ */ new Map());
|
|
5053
|
+
const pinchDistance = (0, import_react40.useRef)(void 0);
|
|
5054
|
+
const onPointerDown = (event) => {
|
|
5055
|
+
if (event.target.closest("button")) return;
|
|
5056
|
+
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
5057
|
+
pointers.current.set(event.pointerId, { x: event.clientX, y: event.clientY });
|
|
5058
|
+
pinchDistance.current = void 0;
|
|
5059
|
+
setAnimate(false);
|
|
5060
|
+
};
|
|
5061
|
+
const onPointerMove = (event) => {
|
|
5062
|
+
const previous = pointers.current.get(event.pointerId);
|
|
5063
|
+
if (!previous) return;
|
|
5064
|
+
const current = { x: event.clientX, y: event.clientY };
|
|
5065
|
+
pointers.current.set(event.pointerId, current);
|
|
5066
|
+
const all = [...pointers.current.values()];
|
|
5067
|
+
if (all.length >= 2) {
|
|
5068
|
+
const [a, b] = all;
|
|
5069
|
+
const distance = Math.hypot(a.x - b.x, a.y - b.y);
|
|
5070
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
5071
|
+
const mx = (a.x + b.x) / 2 - rect.left;
|
|
5072
|
+
const my = (a.y + b.y) / 2 - rect.top;
|
|
5073
|
+
if (pinchDistance.current !== void 0 && pinchDistance.current > 0) {
|
|
5074
|
+
const base = viewRef.current;
|
|
5075
|
+
const zoom = clampZoom(base.zoom * (distance / pinchDistance.current));
|
|
5076
|
+
const ratio = zoom / base.zoom;
|
|
5077
|
+
setView({ zoom, x: mx - (mx - base.x) * ratio, y: my - (my - base.y) * ratio });
|
|
5078
|
+
}
|
|
5079
|
+
pinchDistance.current = distance;
|
|
5080
|
+
return;
|
|
5081
|
+
}
|
|
5082
|
+
const dx = current.x - previous.x;
|
|
5083
|
+
const dy = current.y - previous.y;
|
|
5084
|
+
setView((value) => ({ ...value, x: value.x + dx, y: value.y + dy }));
|
|
5085
|
+
};
|
|
5086
|
+
const onPointerEnd = (event) => {
|
|
5087
|
+
pointers.current.delete(event.pointerId);
|
|
5088
|
+
pinchDistance.current = void 0;
|
|
5089
|
+
};
|
|
5090
|
+
const zoomBy = (factor) => {
|
|
5091
|
+
const current = viewRef.current;
|
|
5092
|
+
const zoom = clampZoom(current.zoom * factor);
|
|
5093
|
+
const ratio = zoom / current.zoom;
|
|
5094
|
+
const cx0 = size.width / 2;
|
|
5095
|
+
const cy0 = size.height / 2;
|
|
5096
|
+
moveView({ zoom, x: cx0 - (cx0 - current.x) * ratio, y: cy0 - (cy0 - current.y) * ratio }, true);
|
|
5097
|
+
};
|
|
5098
|
+
const panBy = (dx, dy) => moveView({ ...viewRef.current, x: viewRef.current.x + dx, y: viewRef.current.y + dy }, true);
|
|
5099
|
+
const toggleCluster = (clusterId, focusAfter) => {
|
|
5100
|
+
const isExpanded = expanded.has(clusterId);
|
|
5101
|
+
pendingFocus.current = focusAfter;
|
|
5102
|
+
if (expandedClusterIds === void 0) {
|
|
5103
|
+
setLocalExpanded((previous) => {
|
|
5104
|
+
const next = new Set(previous);
|
|
5105
|
+
if (isExpanded) next.delete(clusterId);
|
|
5106
|
+
else next.add(clusterId);
|
|
5107
|
+
return next;
|
|
5108
|
+
});
|
|
5109
|
+
}
|
|
5110
|
+
onToggleCluster?.(clusterId, !isExpanded);
|
|
5111
|
+
};
|
|
5112
|
+
const activate = (item) => {
|
|
5113
|
+
if (item.cluster) {
|
|
5114
|
+
toggleCluster(item.cluster.id, item.cluster.members[0]?.id ?? item.id);
|
|
5115
|
+
return;
|
|
5116
|
+
}
|
|
5117
|
+
if (item.node) {
|
|
5118
|
+
setLocalFocus(item.id);
|
|
5119
|
+
onFocusChange?.(item.id);
|
|
5120
|
+
onSelect?.(item.node);
|
|
5121
|
+
}
|
|
5122
|
+
};
|
|
5123
|
+
const onItemKeyDown = (event, item) => {
|
|
5124
|
+
if (NAV_KEYS.includes(event.key)) {
|
|
5125
|
+
event.preventDefault();
|
|
5126
|
+
const next = layeredNeighbor(layout, item.id, event.key);
|
|
5127
|
+
if (next !== void 0) focusItem(next);
|
|
5128
|
+
}
|
|
5129
|
+
};
|
|
5130
|
+
const labelFor = (item) => {
|
|
5131
|
+
if (item.cluster) {
|
|
5132
|
+
const cluster = item.cluster;
|
|
5133
|
+
return `${labels.cluster(cluster.members.length, cluster.type, cluster.edgeLabel)}, ${labels.expandCluster}`;
|
|
5134
|
+
}
|
|
5135
|
+
const node = item.node;
|
|
5136
|
+
const conflict = conflictedNodeIds.has(node.id) ? labels.conflict : void 0;
|
|
5137
|
+
if (nodeAriaLabel) return [nodeAriaLabel(node), item.inCycle ? labels.cycle : void 0, conflict].filter(Boolean).join(", ");
|
|
5138
|
+
return [node.label, node.type, node.description, labels.relationships(item.degree), item.inCycle ? labels.cycle : void 0, conflict].filter(Boolean).join(", ");
|
|
5139
|
+
};
|
|
5140
|
+
const showLabel = (edge) => {
|
|
5141
|
+
if (edgeLabels === "never" || edge.label === void 0) return false;
|
|
5142
|
+
if (edgeLabels === "always") return true;
|
|
5143
|
+
return edge.autoLabel || activeIds.has(edge.source) || activeIds.has(edge.target) || focusedId === edge.source || focusedId === edge.target;
|
|
5144
|
+
};
|
|
5145
|
+
const viewportStyle = height !== void 0 ? { "--uix-relationship-graph-height": height } : {};
|
|
5146
|
+
const stageStyle = {
|
|
5147
|
+
width: layout.width,
|
|
5148
|
+
height: layout.height,
|
|
5149
|
+
transform: `translate(${view.x}px, ${view.y}px) scale(${view.zoom})`
|
|
5150
|
+
};
|
|
5151
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("section", { className: cx("uix-relationship-graph", "uix-relationship-graph--layered", density === "compact" && "uix-relationship-graph--compact", className), "aria-label": labels.graph, children: [
|
|
5152
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "uix-relationship-graph__toolbar", role: "group", "aria-label": labels.controls, children: [
|
|
5153
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", onClick: () => zoomBy(ZOOM_STEP), disabled: view.zoom >= MAX_ZOOM, children: labels.zoomIn }),
|
|
5154
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", onClick: () => zoomBy(1 / ZOOM_STEP), disabled: view.zoom <= MIN_ZOOM, children: labels.zoomOut }),
|
|
5155
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", onClick: () => moveView(fitView(layout, size), true), children: labels.fit }),
|
|
5156
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", onClick: () => moveView(initialView(layout, size), true), children: labels.reset }),
|
|
5157
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", onClick: () => panBy(PAN_STEP, 0), "aria-label": labels.panLeft, children: labels.left }),
|
|
5158
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", onClick: () => panBy(0, PAN_STEP), "aria-label": labels.panUp, children: labels.up }),
|
|
5159
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", onClick: () => panBy(0, -PAN_STEP), "aria-label": labels.panDown, children: labels.down }),
|
|
5160
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("button", { type: "button", onClick: () => panBy(-PAN_STEP, 0), "aria-label": labels.panRight, children: labels.right }),
|
|
5161
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { "aria-live": "polite", children: labels.zoomLevel(Math.round(view.zoom * 100)) })
|
|
5162
|
+
] }),
|
|
5163
|
+
bounded.omittedNodeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("p", { className: "uix-relationship-graph__bounded", role: "status", children: labels.bounded(bounded.nodes.length, bounded.omittedNodeCount) }),
|
|
5164
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("p", { id: hintId, className: "uix-visually-hidden", children: labels.keyboardHint }),
|
|
5165
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
5166
|
+
"div",
|
|
5167
|
+
{
|
|
5168
|
+
ref: viewportRef,
|
|
5169
|
+
className: "uix-relationship-graph__viewport",
|
|
5170
|
+
style: viewportStyle,
|
|
5171
|
+
onPointerDown,
|
|
5172
|
+
onPointerMove,
|
|
5173
|
+
onPointerUp: onPointerEnd,
|
|
5174
|
+
onPointerCancel: onPointerEnd,
|
|
5175
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)("div", { className: "uix-relationship-graph__stage", style: stageStyle, "data-animate": animate || void 0, onTransitionEnd: () => setAnimate(false), children: [
|
|
5176
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("svg", { className: "uix-relationship-graph__edges", width: layout.width, height: layout.height, "aria-hidden": "true", focusable: "false", children: layout.edges.map((edge) => {
|
|
5177
|
+
const active = activeIds.has(edge.source) || activeIds.has(edge.target) || edge.edgeIds.some((id) => highlightedEdgeIds.has(id));
|
|
5178
|
+
const angle = edge.arrowAngle * 180 / Math.PI;
|
|
5179
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
|
|
5180
|
+
"g",
|
|
5181
|
+
{
|
|
5182
|
+
className: "uix-relationship-graph__link",
|
|
5183
|
+
"data-kind": edge.kind,
|
|
5184
|
+
"data-active": active || void 0,
|
|
5185
|
+
"data-emphasis": edge.emphasis || void 0,
|
|
5186
|
+
"data-conflicted": edge.edgeIds.some((id) => conflictedEdgeIds.has(id)) || void 0,
|
|
5187
|
+
"data-dimmed": dimmedNodeIds.has(edge.source) && dimmedNodeIds.has(edge.target) || void 0,
|
|
5188
|
+
children: [
|
|
5189
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("path", { d: edge.path }),
|
|
5190
|
+
edge.arrow !== "none" && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("polygon", { points: arrowPoints, transform: `translate(${edge.arrowX} ${edge.arrowY}) rotate(${angle})` }),
|
|
5191
|
+
showLabel(edge) && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("text", { x: edge.labelX, y: edge.labelY, textAnchor: "middle", dominantBaseline: "middle", children: (edge.kind === "cycle" ? [...edge.labelLines, labels.cycle] : edge.labelLines).map((line, index, lines) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("tspan", { x: edge.labelX, dy: index === 0 ? `${-(lines.length - 1) * 0.55}em` : "1.1em", children: line }, index)) })
|
|
5192
|
+
]
|
|
5193
|
+
},
|
|
5194
|
+
edge.id
|
|
5195
|
+
);
|
|
5196
|
+
}) }),
|
|
5197
|
+
layout.columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
5198
|
+
"div",
|
|
5199
|
+
{
|
|
5200
|
+
className: "uix-relationship-graph__column",
|
|
5201
|
+
"aria-hidden": "true",
|
|
5202
|
+
style: { left: column.x, width: layout.nodeWidth },
|
|
5203
|
+
children: labels.column(column.depth, column.count)
|
|
5204
|
+
},
|
|
5205
|
+
column.depth
|
|
5206
|
+
)),
|
|
5207
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("div", { role: "group", "aria-roledescription": labels.roleDescription, "aria-label": labels.graphSummary(bounded.nodes.length, bounded.edges.length), "aria-describedby": hintId, children: layout.items.map((item) => {
|
|
5208
|
+
const selected = item.id === selectedItemId;
|
|
5209
|
+
const dimmed = item.node ? dimmedNodeIds.has(item.node.id) : item.cluster.members.every((member) => dimmedNodeIds.has(member.id));
|
|
5210
|
+
const body = item.cluster ? renderCluster?.(item.cluster) ?? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(import_jsx_runtime64.Fragment, { children: [
|
|
5211
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "uix-relationship-graph__item-label", children: labels.cluster(item.cluster.members.length, item.cluster.type, item.cluster.edgeLabel) }),
|
|
5212
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "uix-relationship-graph__item-meta", children: labels.expandCluster })
|
|
5213
|
+
] }) : renderNode?.(item.node, { selected, dimmed }) ?? /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(import_jsx_runtime64.Fragment, { children: [
|
|
5214
|
+
/* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "uix-relationship-graph__item-label", children: item.node.label }),
|
|
5215
|
+
(item.node.type || item.node.description) && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "uix-relationship-graph__item-meta", children: [item.node.type, item.node.description].filter(Boolean).join(" \xB7 ") })
|
|
5216
|
+
] });
|
|
5217
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
|
|
5218
|
+
"button",
|
|
5219
|
+
{
|
|
5220
|
+
ref: (element) => {
|
|
5221
|
+
if (element) itemRefs.current.set(item.id, element);
|
|
5222
|
+
else itemRefs.current.delete(item.id);
|
|
5223
|
+
},
|
|
5224
|
+
type: "button",
|
|
5225
|
+
className: "uix-relationship-graph__item",
|
|
5226
|
+
"data-kind": item.kind,
|
|
5227
|
+
"data-node-id": item.id,
|
|
5228
|
+
"data-selected": selected || void 0,
|
|
5229
|
+
"data-dimmed": dimmed || void 0,
|
|
5230
|
+
"data-highlighted": item.node && highlightedNodeIds.has(item.node.id) || void 0,
|
|
5231
|
+
"data-conflicted": item.node && conflictedNodeIds.has(item.node.id) || void 0,
|
|
5232
|
+
"data-root": item.id === rootItemId || void 0,
|
|
5233
|
+
style: { left: item.x, top: item.y, width: item.width, height: item.height },
|
|
5234
|
+
tabIndex: item.id === focusedId ? 0 : -1,
|
|
5235
|
+
"aria-label": labelFor(item),
|
|
5236
|
+
...item.cluster ? { "aria-expanded": false } : { "aria-pressed": selected },
|
|
5237
|
+
onClick: () => activate(item),
|
|
5238
|
+
onKeyDown: (event) => onItemKeyDown(event, item),
|
|
5239
|
+
onFocus: () => {
|
|
5240
|
+
if (item.id === focusedId) return;
|
|
5241
|
+
setLocalFocus(item.id);
|
|
5242
|
+
onFocusChange?.(item.id);
|
|
5243
|
+
},
|
|
5244
|
+
onPointerEnter: () => setHoverId(item.id),
|
|
5245
|
+
onPointerLeave: () => setHoverId((current) => current === item.id ? void 0 : current),
|
|
5246
|
+
children: [
|
|
5247
|
+
body,
|
|
5248
|
+
item.inCycle && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("span", { className: "uix-relationship-graph__item-flag", "aria-hidden": "true", children: labels.cycle })
|
|
5249
|
+
]
|
|
5250
|
+
},
|
|
5251
|
+
item.id
|
|
5252
|
+
);
|
|
5253
|
+
}) }),
|
|
5254
|
+
layout.items.filter((item) => item.expandedGroup).map((item) => {
|
|
5255
|
+
const group = item.expandedGroup;
|
|
5256
|
+
return /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
5257
|
+
"button",
|
|
5258
|
+
{
|
|
5259
|
+
type: "button",
|
|
5260
|
+
className: "uix-relationship-graph__collapse",
|
|
5261
|
+
"aria-expanded": "true",
|
|
5262
|
+
style: { left: item.x, top: item.y - 26, width: item.width },
|
|
5263
|
+
onClick: () => toggleCluster(group.id, group.id),
|
|
5264
|
+
children: labels.collapseCluster(group.members.length, group.type)
|
|
5265
|
+
},
|
|
5266
|
+
`collapse:${group.id}`
|
|
5267
|
+
);
|
|
5268
|
+
})
|
|
5269
|
+
] })
|
|
5270
|
+
}
|
|
5271
|
+
),
|
|
5272
|
+
legend.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("ul", { className: "uix-relationship-graph__legend", "aria-label": labels.legend, children: legend.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime64.jsx)("li", { "data-type": entry.id, children: entry.label }, entry.id)) }),
|
|
5273
|
+
showList && /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
|
|
5274
|
+
EquivalentRelationshipList,
|
|
5275
|
+
{
|
|
5276
|
+
nodes: bounded.nodes,
|
|
5277
|
+
edges: bounded.edges,
|
|
5278
|
+
selectedId,
|
|
5279
|
+
labels,
|
|
5280
|
+
onSelect: (id) => {
|
|
5281
|
+
const node = bounded.nodes.find((candidate) => candidate.id === id);
|
|
5282
|
+
if (node) onSelect?.(node);
|
|
5283
|
+
},
|
|
5284
|
+
onExpandNeighbors,
|
|
5285
|
+
onOpenDetails
|
|
5286
|
+
}
|
|
5287
|
+
)
|
|
5288
|
+
] });
|
|
5289
|
+
}
|
|
5290
|
+
|
|
5291
|
+
// src/components/RelationshipGraph.tsx
|
|
5292
|
+
var import_jsx_runtime65 = require("react/jsx-runtime");
|
|
5293
|
+
var DEFAULT_RELATIONSHIP_GRAPH_LABELS = {
|
|
5294
|
+
graph: "Relationship graph",
|
|
5295
|
+
controls: "Graph view controls",
|
|
5296
|
+
list: "Accessible relationship list",
|
|
5297
|
+
listHeading: "Relationship list",
|
|
5298
|
+
legend: "Relationship types",
|
|
5299
|
+
panLeft: "Pan left",
|
|
5300
|
+
panRight: "Pan right",
|
|
5301
|
+
panUp: "Pan up",
|
|
5302
|
+
panDown: "Pan down",
|
|
5303
|
+
left: "Left",
|
|
5304
|
+
right: "Right",
|
|
5305
|
+
up: "Up",
|
|
5306
|
+
down: "Down",
|
|
5307
|
+
zoomIn: "Zoom in",
|
|
5308
|
+
zoomOut: "Zoom out",
|
|
5309
|
+
fit: "Fit",
|
|
5310
|
+
reset: "Reset view",
|
|
5311
|
+
zoomLevel: (percent) => `Zoom ${percent}%`,
|
|
5312
|
+
bounded: (shown, omitted) => `Showing ${shown} nodes; ${omitted} outside this bounded neighborhood.`,
|
|
5313
|
+
graphSummary: (nodes, edges) => `Graph with ${nodes} nodes and ${edges} relationships`,
|
|
5314
|
+
relationship: "Relationship",
|
|
5315
|
+
conflict: "conflict",
|
|
5316
|
+
connectedTo: (names) => `Connected to ${names}`,
|
|
5317
|
+
noConnections: "No visible connections",
|
|
5318
|
+
expandNeighbors: "Expand neighbors",
|
|
5319
|
+
openDetails: "Open details",
|
|
5320
|
+
column: (depth, count) => `${depth === 0 ? "Start" : `${depth} ${depth === 1 ? "hop" : "hops"}`} \xB7 ${count}`,
|
|
5321
|
+
cluster: (count, type, edgeLabel) => `${count} \xD7 ${type ?? "items"}${edgeLabel ? ` \xB7 ${edgeLabel}` : ""}`,
|
|
5322
|
+
expandCluster: "Show all",
|
|
5323
|
+
collapseCluster: (count, type) => `Collapse ${count} ${type ?? "items"}`,
|
|
5324
|
+
cycle: "cycle",
|
|
5325
|
+
relationships: (count) => `${count} ${count === 1 ? "relationship" : "relationships"}`,
|
|
5326
|
+
roleDescription: "relationship map",
|
|
5327
|
+
keyboardHint: "Arrow keys move between connected items, Enter selects, Home returns to the start.",
|
|
5328
|
+
loading: "Loading relationships\u2026",
|
|
5329
|
+
retry: "Try again",
|
|
5330
|
+
emptyTitle: "No relationships to display.",
|
|
5331
|
+
emptyHint: "Adjust the neighborhood or filters to include a node."
|
|
5332
|
+
};
|
|
5333
|
+
var EMPTY_IDS2 = /* @__PURE__ */ new Set();
|
|
5334
|
+
var EMPTY_LEGEND = [];
|
|
5335
|
+
var RADIAL_SCALE_X = 6;
|
|
5336
|
+
var RADIAL_SCALE_Y = 4;
|
|
5337
|
+
var RADIAL_NODE_HALF_W = 55;
|
|
5338
|
+
var RADIAL_NODE_HALF_H = 18;
|
|
5339
|
+
var RADIAL_MARGIN = 12;
|
|
5340
|
+
function radialViewBox(nodes) {
|
|
5341
|
+
if (nodes.length === 0) return "0 0 600 400";
|
|
5342
|
+
const xs = nodes.map((node) => node.x * RADIAL_SCALE_X);
|
|
5343
|
+
const ys = nodes.map((node) => node.y * RADIAL_SCALE_Y);
|
|
5344
|
+
const minX = Math.min(...xs) - RADIAL_NODE_HALF_W - RADIAL_MARGIN;
|
|
5345
|
+
const maxX = Math.max(...xs) + RADIAL_NODE_HALF_W + RADIAL_MARGIN;
|
|
5346
|
+
const minY = Math.min(...ys) - RADIAL_NODE_HALF_H - RADIAL_MARGIN;
|
|
5347
|
+
const maxY = Math.max(...ys) + RADIAL_NODE_HALF_H + RADIAL_MARGIN;
|
|
5348
|
+
const round = (value) => Number(value.toFixed(2));
|
|
5349
|
+
const width = Math.max(round(maxX - minX), 600);
|
|
5350
|
+
const height = Math.max(round(maxY - minY), 400);
|
|
5351
|
+
return `${round(minX)} ${round(minY)} ${width} ${height}`;
|
|
5352
|
+
}
|
|
5353
|
+
function RelationshipGraph(props) {
|
|
5354
|
+
const labels = (0, import_react41.useMemo)(() => ({ ...DEFAULT_RELATIONSHIP_GRAPH_LABELS, ...props.labels }), [props.labels]);
|
|
5355
|
+
const stateClass = cx("uix-relationship-graph uix-relationship-graph--state", props.className);
|
|
5356
|
+
if (props.loading) return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: stateClass, role: "status", children: labels.loading });
|
|
5357
|
+
if (props.error) {
|
|
5358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: stateClass, role: "alert", children: [
|
|
5359
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("p", { children: props.error }),
|
|
5360
|
+
props.onRetry && /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: props.onRetry, children: labels.retry })
|
|
5361
|
+
] });
|
|
5362
|
+
}
|
|
5363
|
+
if (props.nodes.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: stateClass, children: [
|
|
5364
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("p", { children: labels.emptyTitle }),
|
|
5365
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("p", { children: labels.emptyHint })
|
|
5366
|
+
] });
|
|
5367
|
+
if (props.layout === "layered") return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(LayeredRelationshipGraph, { ...props, labels });
|
|
5368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(RadialRelationshipGraph, { ...props, labels });
|
|
5369
|
+
}
|
|
5370
|
+
function RadialRelationshipGraph({
|
|
5371
|
+
nodes,
|
|
5372
|
+
edges,
|
|
5373
|
+
selectedId,
|
|
5374
|
+
onSelect,
|
|
5375
|
+
onExpandNeighbors,
|
|
5376
|
+
onOpenDetails,
|
|
5377
|
+
maxNodes = 40,
|
|
5378
|
+
density = "standard",
|
|
5379
|
+
highlightedNodeIds = EMPTY_IDS2,
|
|
5380
|
+
conflictedNodeIds = EMPTY_IDS2,
|
|
5381
|
+
highlightedEdgeIds = EMPTY_IDS2,
|
|
5382
|
+
conflictedEdgeIds = EMPTY_IDS2,
|
|
5383
|
+
legend = EMPTY_LEGEND,
|
|
5384
|
+
className,
|
|
5385
|
+
labels,
|
|
5386
|
+
showList = true
|
|
5387
|
+
}) {
|
|
5388
|
+
const bounded = (0, import_react41.useMemo)(() => boundRelationshipGraph(nodes, edges, maxNodes), [nodes, edges, maxNodes]);
|
|
5389
|
+
const positioned = (0, import_react41.useMemo)(() => layoutRelationshipGraph(bounded.nodes, bounded.edges, selectedId), [bounded, selectedId]);
|
|
5390
|
+
const positionedById = (0, import_react41.useMemo)(() => new Map(positioned.map((node) => [node.id, node])), [positioned]);
|
|
5391
|
+
const [zoom, setZoom] = (0, import_react41.useState)(1);
|
|
5392
|
+
const [pan, setPan] = (0, import_react41.useState)({ x: 0, y: 0 });
|
|
5393
|
+
const [focusedId, setFocusedId] = (0, import_react41.useState)(selectedId ?? positioned[0]?.id);
|
|
5394
|
+
const svgRef = (0, import_react41.useRef)(null);
|
|
4406
5395
|
const select = (id) => {
|
|
4407
5396
|
const node = bounded.nodes.find((item) => item.id === id);
|
|
4408
5397
|
if (node) onSelect?.(node);
|
|
@@ -4425,49 +5414,30 @@ function RelationshipGraph({
|
|
|
4425
5414
|
setZoom(1);
|
|
4426
5415
|
setPan({ x: 0, y: 0 });
|
|
4427
5416
|
};
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: "uix-relationship-graph__toolbar", "aria-label": "Graph view controls", children: [
|
|
4439
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, x: value.x - 24 })), "aria-label": "Pan left", children: "Left" }),
|
|
4440
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, y: value.y - 24 })), "aria-label": "Pan up", children: "Up" }),
|
|
4441
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, y: value.y + 24 })), "aria-label": "Pan down", children: "Down" }),
|
|
4442
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, x: value.x + 24 })), "aria-label": "Pan right", children: "Right" }),
|
|
4443
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => setZoom((value) => Math.min(2, Number((value + 0.2).toFixed(1)))), "aria-label": "Zoom in", children: "Zoom in" }),
|
|
4444
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => setZoom((value) => Math.max(0.5, Number((value - 0.2).toFixed(1)))), "aria-label": "Zoom out", children: "Zoom out" }),
|
|
4445
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: reset, children: "Reset view" }),
|
|
4446
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { "aria-live": "polite", children: [
|
|
4447
|
-
"Zoom ",
|
|
4448
|
-
Math.round(zoom * 100),
|
|
4449
|
-
"%"
|
|
4450
|
-
] })
|
|
5417
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("section", { className: cx("uix-relationship-graph", `uix-relationship-graph--${density}`, className), "aria-label": labels.graph, children: [
|
|
5418
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("div", { className: "uix-relationship-graph__toolbar", "aria-label": labels.controls, children: [
|
|
5419
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, x: value.x - 24 })), "aria-label": labels.panLeft, children: labels.left }),
|
|
5420
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, y: value.y - 24 })), "aria-label": labels.panUp, children: labels.up }),
|
|
5421
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, y: value.y + 24 })), "aria-label": labels.panDown, children: labels.down }),
|
|
5422
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, x: value.x + 24 })), "aria-label": labels.panRight, children: labels.right }),
|
|
5423
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("button", { type: "button", onClick: () => setZoom((value) => Math.min(2, Number((value + 0.2).toFixed(1)))), "aria-label": labels.zoomIn, children: labels.zoomIn }),
|
|
5424
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("button", { type: "button", onClick: () => setZoom((value) => Math.max(0.5, Number((value - 0.2).toFixed(1)))), "aria-label": labels.zoomOut, children: labels.zoomOut }),
|
|
5425
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("button", { type: "button", onClick: reset, children: labels.reset }),
|
|
5426
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("span", { "aria-live": "polite", children: labels.zoomLevel(Math.round(zoom * 100)) })
|
|
4451
5427
|
] }),
|
|
4452
|
-
bounded.omittedNodeCount > 0 && /* @__PURE__ */ (0,
|
|
4453
|
-
|
|
4454
|
-
bounded.nodes.length,
|
|
4455
|
-
" nodes; ",
|
|
4456
|
-
bounded.omittedNodeCount,
|
|
4457
|
-
" outside this bounded neighborhood."
|
|
4458
|
-
] }),
|
|
4459
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("div", { className: "uix-relationship-graph__visual", children: /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("svg", { ref: svgRef, viewBox: "0 0 600 400", role: "group", "aria-label": `Graph with ${bounded.nodes.length} nodes and ${bounded.edges.length} relationships`, children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("g", { transform: `translate(${pan.x} ${pan.y}) scale(${zoom})`, children: [
|
|
5428
|
+
bounded.omittedNodeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("p", { className: "uix-relationship-graph__bounded", role: "status", children: labels.bounded(bounded.nodes.length, bounded.omittedNodeCount) }),
|
|
5429
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "uix-relationship-graph__visual", children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("svg", { ref: svgRef, viewBox: radialViewBox(positioned), role: "group", "aria-label": labels.graphSummary(bounded.nodes.length, bounded.edges.length), children: /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("g", { transform: `translate(${pan.x} ${pan.y}) scale(${zoom})`, children: [
|
|
4460
5430
|
bounded.edges.map((edge) => {
|
|
4461
5431
|
const source = positionedById.get(edge.source);
|
|
4462
5432
|
const target = positionedById.get(edge.target);
|
|
4463
|
-
return /* @__PURE__ */ (0,
|
|
5433
|
+
return /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("line", { x1: source.x * RADIAL_SCALE_X, y1: source.y * RADIAL_SCALE_Y, x2: target.x * RADIAL_SCALE_X, y2: target.y * RADIAL_SCALE_Y, className: "uix-relationship-graph__edge", "data-highlighted": highlightedEdgeIds.has(edge.id) || void 0, "data-conflicted": conflictedEdgeIds.has(edge.id) || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("title", { children: edge.label ?? edge.type ?? labels.relationship }) }, edge.id);
|
|
4464
5434
|
}),
|
|
4465
|
-
positioned.map((node) => /* @__PURE__ */ (0,
|
|
5435
|
+
positioned.map((node) => /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)(
|
|
4466
5436
|
"g",
|
|
4467
5437
|
{
|
|
4468
|
-
transform: `translate(${node.x *
|
|
5438
|
+
transform: `translate(${node.x * RADIAL_SCALE_X} ${node.y * RADIAL_SCALE_Y})`,
|
|
4469
5439
|
role: "button",
|
|
4470
|
-
"aria-label": `${node.label}${node.type ? `, ${node.type}` : ""}${conflictedNodeIds.has(node.id) ?
|
|
5440
|
+
"aria-label": `${node.label}${node.type ? `, ${node.type}` : ""}${conflictedNodeIds.has(node.id) ? `, ${labels.conflict}` : ""}`,
|
|
4471
5441
|
tabIndex: focusedId === node.id ? 0 : -1,
|
|
4472
5442
|
"data-node-id": node.id,
|
|
4473
5443
|
className: "uix-relationship-graph__node",
|
|
@@ -4478,37 +5448,22 @@ function RelationshipGraph({
|
|
|
4478
5448
|
onKeyDown: (event) => onNodeKeyDown(event, node.id),
|
|
4479
5449
|
onClick: () => select(node.id),
|
|
4480
5450
|
children: [
|
|
4481
|
-
/* @__PURE__ */ (0,
|
|
4482
|
-
/* @__PURE__ */ (0,
|
|
5451
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("title", { children: node.label }),
|
|
5452
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("rect", { x: -RADIAL_NODE_HALF_W, y: -RADIAL_NODE_HALF_H, width: RADIAL_NODE_HALF_W * 2, height: RADIAL_NODE_HALF_H * 2, rx: "8" }),
|
|
5453
|
+
/* @__PURE__ */ (0, import_jsx_runtime65.jsx)("text", { textAnchor: "middle", dominantBaseline: "middle", children: node.label.length > 16 ? `${node.label.slice(0, 15)}\u2026` : node.label })
|
|
4483
5454
|
]
|
|
4484
5455
|
},
|
|
4485
5456
|
node.id
|
|
4486
5457
|
))
|
|
4487
5458
|
] }) }) }),
|
|
4488
|
-
legend.length > 0 && /* @__PURE__ */ (0,
|
|
4489
|
-
/* @__PURE__ */ (0,
|
|
4490
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("h3", { children: "Relationship list" }),
|
|
4491
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("ul", { children: bounded.nodes.map((node) => {
|
|
4492
|
-
const neighbors = relationshipNeighbors(node.id, bounded.edges).map((id) => bounded.nodes.find((item) => item.id === id)?.label ?? id);
|
|
4493
|
-
return /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("li", { "data-selected": selectedId === node.id || void 0, children: [
|
|
4494
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("button", { type: "button", onClick: () => select(node.id), "aria-pressed": selectedId === node.id, children: [
|
|
4495
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("strong", { children: node.label }),
|
|
4496
|
-
node.type && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { children: node.type }),
|
|
4497
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsx)("span", { children: neighbors.length ? `Connected to ${neighbors.join(", ")}` : "No visible connections" })
|
|
4498
|
-
] }),
|
|
4499
|
-
/* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("span", { className: "uix-relationship-graph__list-actions", children: [
|
|
4500
|
-
onExpandNeighbors && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => onExpandNeighbors(node), children: "Expand neighbors" }),
|
|
4501
|
-
onOpenDetails && /* @__PURE__ */ (0, import_jsx_runtime62.jsx)("button", { type: "button", onClick: () => onOpenDetails(node), children: "Open details" })
|
|
4502
|
-
] })
|
|
4503
|
-
] }, node.id);
|
|
4504
|
-
}) })
|
|
4505
|
-
] })
|
|
5459
|
+
legend.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("ul", { className: "uix-relationship-graph__legend", "aria-label": labels.legend, children: legend.map((item) => /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("li", { "data-type": item.id, children: item.label }, item.id)) }),
|
|
5460
|
+
showList && /* @__PURE__ */ (0, import_jsx_runtime65.jsx)(EquivalentRelationshipList, { nodes: bounded.nodes, edges: bounded.edges, selectedId, labels, onSelect: select, onExpandNeighbors, onOpenDetails })
|
|
4506
5461
|
] });
|
|
4507
5462
|
}
|
|
4508
5463
|
|
|
4509
5464
|
// src/components/MatchReview.tsx
|
|
4510
|
-
var
|
|
4511
|
-
var
|
|
5465
|
+
var import_react42 = require("react");
|
|
5466
|
+
var import_jsx_runtime66 = require("react/jsx-runtime");
|
|
4512
5467
|
var valueText = (value) => value == null ? "\u2014" : typeof value === "string" ? value : JSON.stringify(value);
|
|
4513
5468
|
function MatchReview({
|
|
4514
5469
|
incoming,
|
|
@@ -4524,11 +5479,11 @@ function MatchReview({
|
|
|
4524
5479
|
onRetry,
|
|
4525
5480
|
className
|
|
4526
5481
|
}) {
|
|
4527
|
-
const [internalSelection, setInternalSelection] = (0,
|
|
4528
|
-
const [announcement, setAnnouncement] = (0,
|
|
4529
|
-
const [bulkPending, setBulkPending] = (0,
|
|
5482
|
+
const [internalSelection, setInternalSelection] = (0, import_react42.useState)(/* @__PURE__ */ new Set());
|
|
5483
|
+
const [announcement, setAnnouncement] = (0, import_react42.useState)("");
|
|
5484
|
+
const [bulkPending, setBulkPending] = (0, import_react42.useState)(false);
|
|
4530
5485
|
const selection = selectedIds ?? internalSelection;
|
|
4531
|
-
const pending = (0,
|
|
5486
|
+
const pending = (0, import_react42.useMemo)(() => candidates.filter((candidate) => candidate.status !== "resolved"), [candidates]);
|
|
4532
5487
|
const setSelection = (next) => {
|
|
4533
5488
|
if (selectedIds === void 0) setInternalSelection(next);
|
|
4534
5489
|
onSelectionChange?.(next);
|
|
@@ -4556,55 +5511,55 @@ function MatchReview({
|
|
|
4556
5511
|
setBulkPending(false);
|
|
4557
5512
|
}
|
|
4558
5513
|
};
|
|
4559
|
-
if (loading) return /* @__PURE__ */ (0,
|
|
4560
|
-
if (error) return /* @__PURE__ */ (0,
|
|
4561
|
-
/* @__PURE__ */ (0,
|
|
4562
|
-
onRetry && /* @__PURE__ */ (0,
|
|
5514
|
+
if (loading) return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: cx("uix-match-review uix-match-review--state", className), role: "status", children: "Loading match candidates\u2026" });
|
|
5515
|
+
if (error) return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: cx("uix-match-review uix-match-review--state", className), role: "alert", children: [
|
|
5516
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("p", { children: error }),
|
|
5517
|
+
onRetry && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: "Try again" })
|
|
4563
5518
|
] });
|
|
4564
|
-
if (candidates.length === 0) return /* @__PURE__ */ (0,
|
|
4565
|
-
/* @__PURE__ */ (0,
|
|
4566
|
-
/* @__PURE__ */ (0,
|
|
5519
|
+
if (candidates.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: cx("uix-match-review uix-match-review--state", className), children: [
|
|
5520
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("p", { children: "No candidate matches found." }),
|
|
5521
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("p", { children: "Choose another record source or continue without a match." })
|
|
4567
5522
|
] });
|
|
4568
|
-
return /* @__PURE__ */ (0,
|
|
4569
|
-
/* @__PURE__ */ (0,
|
|
4570
|
-
/* @__PURE__ */ (0,
|
|
4571
|
-
/* @__PURE__ */ (0,
|
|
4572
|
-
/* @__PURE__ */ (0,
|
|
5523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("section", { className: cx("uix-match-review", className), "aria-label": "Match review", children: [
|
|
5524
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "uix-match-review__summary", children: [
|
|
5525
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { children: [
|
|
5526
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("strong", { children: incomingLabel }),
|
|
5527
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { children: [
|
|
4573
5528
|
pending.length,
|
|
4574
5529
|
" pending of ",
|
|
4575
5530
|
candidates.length
|
|
4576
5531
|
] })
|
|
4577
5532
|
] }),
|
|
4578
|
-
/* @__PURE__ */ (0,
|
|
4579
|
-
/* @__PURE__ */ (0,
|
|
5533
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "uix-match-review__incoming", children: fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { children: [
|
|
5534
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("b", { children: field.label }),
|
|
4580
5535
|
field.render?.(incoming[field.id], incoming) ?? valueText(incoming[field.id])
|
|
4581
5536
|
] }, field.id)) })
|
|
4582
5537
|
] }),
|
|
4583
|
-
onBulkDecision && /* @__PURE__ */ (0,
|
|
4584
|
-
/* @__PURE__ */ (0,
|
|
5538
|
+
onBulkDecision && /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("div", { className: "uix-match-review__bulk", "aria-label": "Bulk candidate actions", children: [
|
|
5539
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("span", { children: [
|
|
4585
5540
|
selection.size,
|
|
4586
5541
|
" selected"
|
|
4587
5542
|
] }),
|
|
4588
|
-
/* @__PURE__ */ (0,
|
|
4589
|
-
/* @__PURE__ */ (0,
|
|
5543
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", disabled: selection.size === 0 || bulkPending, onClick: () => void runBulk("accept"), children: bulkPending ? "Applying\u2026" : "Accept selected" }),
|
|
5544
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", disabled: selection.size === 0 || bulkPending, onClick: () => void runBulk("dismiss"), children: bulkPending ? "Applying\u2026" : "Dismiss selected" })
|
|
4590
5545
|
] }),
|
|
4591
|
-
/* @__PURE__ */ (0,
|
|
4592
|
-
/* @__PURE__ */ (0,
|
|
4593
|
-
/* @__PURE__ */ (0,
|
|
4594
|
-
/* @__PURE__ */ (0,
|
|
4595
|
-
/* @__PURE__ */ (0,
|
|
4596
|
-
fields.map((field) => /* @__PURE__ */ (0,
|
|
4597
|
-
/* @__PURE__ */ (0,
|
|
4598
|
-
/* @__PURE__ */ (0,
|
|
5546
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "uix-match-review__table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("table", { className: "uix-table uix-match-review__table", children: [
|
|
5547
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("caption", { className: "uix-visually-hidden", children: "Candidate matches and available decisions" }),
|
|
5548
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { children: [
|
|
5549
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { scope: "col", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "uix-visually-hidden", children: "Select" }) }),
|
|
5550
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { scope: "col", children: "Confidence" }),
|
|
5551
|
+
fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { scope: "col", children: field.label }, field.id)),
|
|
5552
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { scope: "col", children: "Status" }),
|
|
5553
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("th", { scope: "col", children: "Actions" })
|
|
4599
5554
|
] }) }),
|
|
4600
|
-
/* @__PURE__ */ (0,
|
|
5555
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("tbody", { children: candidates.map((candidate) => {
|
|
4601
5556
|
const resolved = candidate.status === "resolved";
|
|
4602
|
-
return /* @__PURE__ */ (0,
|
|
4603
|
-
/* @__PURE__ */ (0,
|
|
4604
|
-
/* @__PURE__ */ (0,
|
|
4605
|
-
fields.map((field) => /* @__PURE__ */ (0,
|
|
4606
|
-
/* @__PURE__ */ (0,
|
|
4607
|
-
/* @__PURE__ */ (0,
|
|
5557
|
+
return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)("tr", { "data-status": candidate.status ?? "pending", children: [
|
|
5558
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("input", { type: "checkbox", checked: selection.has(candidate.id), onChange: () => toggle(candidate.id), "aria-label": `Select candidate ${candidate.id}` }) }),
|
|
5559
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "uix-match-review__confidence", children: candidate.confidence == null ? "Not scored" : `${Math.round(candidate.confidence * 100)}%` }) }),
|
|
5560
|
+
fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: field.render?.(candidate.record[field.id], candidate.record) ?? valueText(candidate.record[field.id]) }, field.id)),
|
|
5561
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(StatusPill, { tone: resolved ? "success" : "warning", children: resolved ? candidate.decision ?? "Resolved" : "Pending" }) }),
|
|
5562
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("div", { className: "uix-match-review__actions", children: ["accept", "dismiss", "split", "pick-other"].map((action) => /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
|
|
4608
5563
|
"button",
|
|
4609
5564
|
{
|
|
4610
5565
|
type: "button",
|
|
@@ -4618,12 +5573,12 @@ function MatchReview({
|
|
|
4618
5573
|
] }, candidate.id);
|
|
4619
5574
|
}) })
|
|
4620
5575
|
] }) }),
|
|
4621
|
-
/* @__PURE__ */ (0,
|
|
5576
|
+
/* @__PURE__ */ (0, import_jsx_runtime66.jsx)("p", { className: "uix-visually-hidden", "aria-live": "polite", children: announcement })
|
|
4622
5577
|
] });
|
|
4623
5578
|
}
|
|
4624
5579
|
|
|
4625
5580
|
// src/components/MetricInput.tsx
|
|
4626
|
-
var
|
|
5581
|
+
var import_react43 = require("react");
|
|
4627
5582
|
|
|
4628
5583
|
// src/metric-model.ts
|
|
4629
5584
|
function decimals(value) {
|
|
@@ -4648,7 +5603,7 @@ function parseMetricValue(value) {
|
|
|
4648
5603
|
}
|
|
4649
5604
|
|
|
4650
5605
|
// src/components/MetricInput.tsx
|
|
4651
|
-
var
|
|
5606
|
+
var import_jsx_runtime67 = require("react/jsx-runtime");
|
|
4652
5607
|
var defaultMetricFormat = (input) => input == null ? "" : String(input);
|
|
4653
5608
|
function MetricInput({
|
|
4654
5609
|
value,
|
|
@@ -4667,11 +5622,11 @@ function MetricInput({
|
|
|
4667
5622
|
className,
|
|
4668
5623
|
id: providedId
|
|
4669
5624
|
}) {
|
|
4670
|
-
const generatedId = (0,
|
|
5625
|
+
const generatedId = (0, import_react43.useId)();
|
|
4671
5626
|
const id = providedId ?? generatedId;
|
|
4672
5627
|
const errorId = `${id}-error`;
|
|
4673
|
-
const [text, setText] = (0,
|
|
4674
|
-
(0,
|
|
5628
|
+
const [text, setText] = (0, import_react43.useState)(() => format(value));
|
|
5629
|
+
(0, import_react43.useEffect)(() => setText(format(value)), [value, format]);
|
|
4675
5630
|
const commit = (input) => {
|
|
4676
5631
|
const parsed = parse(input);
|
|
4677
5632
|
if (input.trim() === "" || parsed !== null) {
|
|
@@ -4697,10 +5652,10 @@ function MetricInput({
|
|
|
4697
5652
|
const parsed = parse(event.currentTarget.value);
|
|
4698
5653
|
setText(parsed === null && event.currentTarget.value.trim() !== "" ? format(value) : format(parsed));
|
|
4699
5654
|
};
|
|
4700
|
-
return /* @__PURE__ */ (0,
|
|
4701
|
-
/* @__PURE__ */ (0,
|
|
4702
|
-
/* @__PURE__ */ (0,
|
|
4703
|
-
/* @__PURE__ */ (0,
|
|
5655
|
+
return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: cx("uix-metric-input", invalid && "uix-metric-input--invalid", className), children: [
|
|
5656
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("label", { className: "uix-field__label", htmlFor: id, children: label }),
|
|
5657
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "uix-metric-input__control", children: [
|
|
5658
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
|
|
4704
5659
|
Input,
|
|
4705
5660
|
{
|
|
4706
5661
|
id,
|
|
@@ -4719,22 +5674,22 @@ function MetricInput({
|
|
|
4719
5674
|
readOnly
|
|
4720
5675
|
}
|
|
4721
5676
|
),
|
|
4722
|
-
unit && /* @__PURE__ */ (0,
|
|
4723
|
-
/* @__PURE__ */ (0,
|
|
4724
|
-
/* @__PURE__ */ (0,
|
|
4725
|
-
/* @__PURE__ */ (0,
|
|
5677
|
+
unit && /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "uix-metric-input__unit", "aria-hidden": "true", children: unit }),
|
|
5678
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "uix-metric-input__steps", children: [
|
|
5679
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("button", { type: "button", className: "uix-metric-input__step", onClick: () => stepBy(1), disabled: disabled || readOnly, "aria-label": `Increase ${label}`, children: "+" }),
|
|
5680
|
+
/* @__PURE__ */ (0, import_jsx_runtime67.jsx)("button", { type: "button", className: "uix-metric-input__step", onClick: () => stepBy(-1), disabled: disabled || readOnly, "aria-label": `Decrease ${label}`, children: "\u2212" })
|
|
4726
5681
|
] })
|
|
4727
5682
|
] }),
|
|
4728
|
-
unit && /* @__PURE__ */ (0,
|
|
5683
|
+
unit && /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("span", { className: "uix-visually-hidden", children: [
|
|
4729
5684
|
"Unit: ",
|
|
4730
5685
|
unit
|
|
4731
5686
|
] }),
|
|
4732
|
-
invalid && errorMessage && /* @__PURE__ */ (0,
|
|
5687
|
+
invalid && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { id: errorId, className: "uix-field__error", children: errorMessage })
|
|
4733
5688
|
] });
|
|
4734
5689
|
}
|
|
4735
5690
|
|
|
4736
5691
|
// src/components/LicensePositionBar.tsx
|
|
4737
|
-
var
|
|
5692
|
+
var import_jsx_runtime68 = require("react/jsx-runtime");
|
|
4738
5693
|
var defaultCapacityFormat = (value) => new Intl.NumberFormat().format(value);
|
|
4739
5694
|
function LicensePositionBar({
|
|
4740
5695
|
consumed,
|
|
@@ -4755,18 +5710,18 @@ function LicensePositionBar({
|
|
|
4755
5710
|
const percent = safeEntitled === 0 ? safeConsumed > 0 ? 100 : 0 : safeConsumed / safeEntitled * 100;
|
|
4756
5711
|
const format = (value) => `${formatValue(value)}${unit ? ` ${unit}` : ""}`;
|
|
4757
5712
|
const summary = `${consumedLabel}: ${format(safeConsumed)}. ${entitledLabel}: ${format(safeEntitled)}. ${over > 0 ? `${format(over)} ${overLabel}` : `${format(available)} ${availableLabel}`}.`;
|
|
4758
|
-
return /* @__PURE__ */ (0,
|
|
4759
|
-
/* @__PURE__ */ (0,
|
|
4760
|
-
/* @__PURE__ */ (0,
|
|
5713
|
+
return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: cx("uix-license-position", over > 0 && "uix-license-position--over", className), ...props, children: [
|
|
5714
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "uix-license-position__header", children: [
|
|
5715
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("span", { className: "uix-license-position__value", children: [
|
|
4761
5716
|
format(safeConsumed),
|
|
4762
5717
|
" / ",
|
|
4763
5718
|
format(safeEntitled)
|
|
4764
5719
|
] }),
|
|
4765
|
-
/* @__PURE__ */ (0,
|
|
5720
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)(StatusPill, { tone: over > 0 ? "danger" : percent >= 80 ? "warning" : "success", children: over > 0 ? `${format(over)} ${overLabel}` : `${format(available)} ${availableLabel}` })
|
|
4766
5721
|
] }),
|
|
4767
|
-
/* @__PURE__ */ (0,
|
|
4768
|
-
/* @__PURE__ */ (0,
|
|
4769
|
-
over > 0 && /* @__PURE__ */ (0,
|
|
5722
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "uix-license-position__track", children: [
|
|
5723
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)(Meter, { value: Math.min(100, percent), tone: over > 0 ? "danger" : percent >= 80 ? "warning" : "success", "aria-label": summary, "aria-valuetext": summary }),
|
|
5724
|
+
over > 0 && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
|
|
4770
5725
|
"span",
|
|
4771
5726
|
{
|
|
4772
5727
|
className: "uix-license-position__overflow",
|
|
@@ -4775,12 +5730,12 @@ function LicensePositionBar({
|
|
|
4775
5730
|
}
|
|
4776
5731
|
)
|
|
4777
5732
|
] }),
|
|
4778
|
-
/* @__PURE__ */ (0,
|
|
5733
|
+
/* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "uix-visually-hidden", children: summary })
|
|
4779
5734
|
] });
|
|
4780
5735
|
}
|
|
4781
5736
|
|
|
4782
5737
|
// src/components/BrandProfiles.tsx
|
|
4783
|
-
var
|
|
5738
|
+
var import_react45 = require("react");
|
|
4784
5739
|
|
|
4785
5740
|
// src/color-model.ts
|
|
4786
5741
|
var clamp2 = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
@@ -4849,8 +5804,8 @@ function meetsContrast(background, foreground, minimum = 4.5) {
|
|
|
4849
5804
|
}
|
|
4850
5805
|
|
|
4851
5806
|
// src/components/ColorPicker.tsx
|
|
4852
|
-
var
|
|
4853
|
-
var
|
|
5807
|
+
var import_react44 = require("react");
|
|
5808
|
+
var import_jsx_runtime69 = require("react/jsx-runtime");
|
|
4854
5809
|
var EMPTY_COLORS = [];
|
|
4855
5810
|
function ColorPicker({
|
|
4856
5811
|
value,
|
|
@@ -4863,17 +5818,17 @@ function ColorPicker({
|
|
|
4863
5818
|
disabled,
|
|
4864
5819
|
className
|
|
4865
5820
|
}) {
|
|
4866
|
-
const id = (0,
|
|
4867
|
-
const triggerRef = (0,
|
|
4868
|
-
const dialogRef = (0,
|
|
4869
|
-
const [open, setOpen] = (0,
|
|
5821
|
+
const id = (0, import_react44.useId)();
|
|
5822
|
+
const triggerRef = (0, import_react44.useRef)(null);
|
|
5823
|
+
const dialogRef = (0, import_react44.useRef)(null);
|
|
5824
|
+
const [open, setOpen] = (0, import_react44.useState)(false);
|
|
4870
5825
|
const normalized = normalizeHex(value) ?? "#000000";
|
|
4871
|
-
const [hexText, setHexText] = (0,
|
|
4872
|
-
const hsv = (0,
|
|
5826
|
+
const [hexText, setHexText] = (0, import_react44.useState)(normalized);
|
|
5827
|
+
const hsv = (0, import_react44.useMemo)(() => rgbToHsv(hexToRgb(normalized)), [normalized]);
|
|
4873
5828
|
const ratio = contrastRatio(normalized, foreground) ?? 0;
|
|
4874
5829
|
const passes = ratio >= minimumContrast;
|
|
4875
|
-
(0,
|
|
4876
|
-
(0,
|
|
5830
|
+
(0, import_react44.useEffect)(() => setHexText(normalized), [normalized]);
|
|
5831
|
+
(0, import_react44.useEffect)(() => {
|
|
4877
5832
|
if (!open) return;
|
|
4878
5833
|
const dialog = dialogRef.current;
|
|
4879
5834
|
dialog?.querySelector("input,button")?.focus();
|
|
@@ -4916,8 +5871,8 @@ function ColorPicker({
|
|
|
4916
5871
|
if (next) onChange(next);
|
|
4917
5872
|
};
|
|
4918
5873
|
const sampleStyle = { backgroundColor: normalized };
|
|
4919
|
-
return /* @__PURE__ */ (0,
|
|
4920
|
-
/* @__PURE__ */ (0,
|
|
5874
|
+
return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: cx("uix-color-picker", className), children: [
|
|
5875
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
|
|
4921
5876
|
"button",
|
|
4922
5877
|
{
|
|
4923
5878
|
ref: triggerRef,
|
|
@@ -4929,12 +5884,12 @@ function ColorPicker({
|
|
|
4929
5884
|
onClick: () => setOpen((current) => !current),
|
|
4930
5885
|
disabled,
|
|
4931
5886
|
children: [
|
|
4932
|
-
/* @__PURE__ */ (0,
|
|
4933
|
-
/* @__PURE__ */ (0,
|
|
5887
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "uix-color-picker__swatch", style: sampleStyle, "aria-hidden": "true" }),
|
|
5888
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: normalized })
|
|
4934
5889
|
]
|
|
4935
5890
|
}
|
|
4936
5891
|
),
|
|
4937
|
-
open && /* @__PURE__ */ (0,
|
|
5892
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
|
|
4938
5893
|
"div",
|
|
4939
5894
|
{
|
|
4940
5895
|
ref: dialogRef,
|
|
@@ -4945,57 +5900,57 @@ function ColorPicker({
|
|
|
4945
5900
|
className: "uix-color-picker__popover",
|
|
4946
5901
|
onKeyDown: onDialogKeyDown,
|
|
4947
5902
|
children: [
|
|
4948
|
-
/* @__PURE__ */ (0,
|
|
4949
|
-
/* @__PURE__ */ (0,
|
|
5903
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "uix-color-picker__preview", style: sampleStyle, children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { style: { color: foreground }, children: "Aa" }) }),
|
|
5904
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("label", { className: "uix-color-picker__range", children: [
|
|
4950
5905
|
"Hue ",
|
|
4951
|
-
/* @__PURE__ */ (0,
|
|
5906
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { children: [
|
|
4952
5907
|
Math.round(hsv.h),
|
|
4953
5908
|
"\xB0"
|
|
4954
5909
|
] }),
|
|
4955
|
-
/* @__PURE__ */ (0,
|
|
5910
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("input", { type: "range", min: "0", max: "359", value: Math.round(hsv.h), onChange: (event) => updateHsv({ h: Number(event.currentTarget.value) }) })
|
|
4956
5911
|
] }),
|
|
4957
|
-
/* @__PURE__ */ (0,
|
|
5912
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("label", { className: "uix-color-picker__range", children: [
|
|
4958
5913
|
"Saturation ",
|
|
4959
|
-
/* @__PURE__ */ (0,
|
|
5914
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { children: [
|
|
4960
5915
|
Math.round(hsv.s * 100),
|
|
4961
5916
|
"%"
|
|
4962
5917
|
] }),
|
|
4963
|
-
/* @__PURE__ */ (0,
|
|
5918
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("input", { type: "range", min: "0", max: "100", value: Math.round(hsv.s * 100), onChange: (event) => updateHsv({ s: Number(event.currentTarget.value) / 100 }) })
|
|
4964
5919
|
] }),
|
|
4965
|
-
/* @__PURE__ */ (0,
|
|
5920
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("label", { className: "uix-color-picker__range", children: [
|
|
4966
5921
|
"Brightness ",
|
|
4967
|
-
/* @__PURE__ */ (0,
|
|
5922
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { children: [
|
|
4968
5923
|
Math.round(hsv.v * 100),
|
|
4969
5924
|
"%"
|
|
4970
5925
|
] }),
|
|
4971
|
-
/* @__PURE__ */ (0,
|
|
5926
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("input", { type: "range", min: "0", max: "100", value: Math.round(hsv.v * 100), onChange: (event) => updateHsv({ v: Number(event.currentTarget.value) / 100 }) })
|
|
4972
5927
|
] }),
|
|
4973
|
-
/* @__PURE__ */ (0,
|
|
5928
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("label", { className: "uix-color-picker__hex", children: [
|
|
4974
5929
|
"Hex",
|
|
4975
|
-
/* @__PURE__ */ (0,
|
|
4976
|
-
/* @__PURE__ */ (0,
|
|
5930
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { className: "uix-color-picker__hex-row", children: [
|
|
5931
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("input", { className: "uix-input", value: hexText, onChange: (event) => setHexText(event.currentTarget.value), onBlur: commitHex, onKeyDown: (event) => {
|
|
4977
5932
|
if (event.key === "Enter") commitHex();
|
|
4978
5933
|
}, "aria-invalid": !normalizeHex(hexText) }),
|
|
4979
|
-
/* @__PURE__ */ (0,
|
|
5934
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", onClick: commitHex, disabled: !normalizeHex(hexText), children: "Set" })
|
|
4980
5935
|
] })
|
|
4981
5936
|
] }),
|
|
4982
|
-
(presets.length > 0 || recent.length > 0) && /* @__PURE__ */ (0,
|
|
4983
|
-
presets.length > 0 && /* @__PURE__ */ (0,
|
|
4984
|
-
/* @__PURE__ */ (0,
|
|
4985
|
-
/* @__PURE__ */ (0,
|
|
5937
|
+
(presets.length > 0 || recent.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "uix-color-picker__palettes", children: [
|
|
5938
|
+
presets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("fieldset", { children: [
|
|
5939
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("legend", { children: "Presets" }),
|
|
5940
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { children: presets.map((color) => /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("button", { type: "button", className: "uix-color-picker__preset", style: { backgroundColor: normalizeHex(color) ?? color }, onClick: () => choose(color), "aria-label": `Use preset ${color}` }, color)) })
|
|
4986
5941
|
] }),
|
|
4987
|
-
recent.length > 0 && /* @__PURE__ */ (0,
|
|
4988
|
-
/* @__PURE__ */ (0,
|
|
4989
|
-
/* @__PURE__ */ (0,
|
|
5942
|
+
recent.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("fieldset", { children: [
|
|
5943
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("legend", { children: "Recent" }),
|
|
5944
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { children: recent.map((color) => /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("button", { type: "button", className: "uix-color-picker__preset", style: { backgroundColor: normalizeHex(color) ?? color }, onClick: () => choose(color), "aria-label": `Use recent color ${color}` }, color)) })
|
|
4990
5945
|
] })
|
|
4991
5946
|
] }),
|
|
4992
|
-
/* @__PURE__ */ (0,
|
|
5947
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("p", { className: cx("uix-color-picker__contrast", passes ? "uix-color-picker__contrast--pass" : "uix-color-picker__contrast--fail"), role: "status", "aria-live": "polite", children: [
|
|
4993
5948
|
"Contrast ",
|
|
4994
5949
|
ratio.toFixed(2),
|
|
4995
5950
|
":1 \u2014 ",
|
|
4996
5951
|
passes ? `passes WCAG AA (${minimumContrast}:1)` : `does not meet WCAG AA (${minimumContrast}:1)`
|
|
4997
5952
|
] }),
|
|
4998
|
-
/* @__PURE__ */ (0,
|
|
5953
|
+
/* @__PURE__ */ (0, import_jsx_runtime69.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary uix-btn--sm", onClick: close, children: "Done" })
|
|
4999
5954
|
]
|
|
5000
5955
|
}
|
|
5001
5956
|
)
|
|
@@ -5003,7 +5958,7 @@ function ColorPicker({
|
|
|
5003
5958
|
}
|
|
5004
5959
|
|
|
5005
5960
|
// src/components/BrandProfiles.tsx
|
|
5006
|
-
var
|
|
5961
|
+
var import_jsx_runtime70 = require("react/jsx-runtime");
|
|
5007
5962
|
var PROFILE_PROPERTIES = {
|
|
5008
5963
|
brand: "--uix-brand",
|
|
5009
5964
|
brandForeground: "--uix-brand-fg",
|
|
@@ -5072,7 +6027,7 @@ function BrandProfileEditor({
|
|
|
5072
6027
|
colorPresets = EMPTY_COLORS2,
|
|
5073
6028
|
className
|
|
5074
6029
|
}) {
|
|
5075
|
-
const [announcement, setAnnouncement] = (0,
|
|
6030
|
+
const [announcement, setAnnouncement] = (0, import_react45.useState)("");
|
|
5076
6031
|
const update = (patch) => onChange({ ...value, ...patch });
|
|
5077
6032
|
const apply = () => {
|
|
5078
6033
|
if (applyTarget !== null) applyBrandProfile(value, applyTarget);
|
|
@@ -5089,54 +6044,54 @@ function BrandProfileEditor({
|
|
|
5089
6044
|
...value.typography?.sans ? { "--uix-font-sans": value.typography.sans } : {},
|
|
5090
6045
|
...value.typography?.heading ? { "--uix-font-heading": value.typography.heading } : {}
|
|
5091
6046
|
};
|
|
5092
|
-
return /* @__PURE__ */ (0,
|
|
5093
|
-
/* @__PURE__ */ (0,
|
|
5094
|
-
profiles.length > 0 && /* @__PURE__ */ (0,
|
|
6047
|
+
return /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("section", { className: cx("uix-brand-profiles", className), "aria-label": "Brand profile editor", children: [
|
|
6048
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "uix-brand-profiles__form", children: [
|
|
6049
|
+
profiles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("label", { className: "uix-field__label", children: [
|
|
5095
6050
|
"Profile",
|
|
5096
|
-
/* @__PURE__ */ (0,
|
|
6051
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("select", { className: "uix-select", value: value.id, onChange: (event) => {
|
|
5097
6052
|
const selected = profiles.find((profile) => profile.id === event.currentTarget.value);
|
|
5098
6053
|
if (selected) onSelectProfile?.(selected);
|
|
5099
|
-
}, children: profiles.map((profile) => /* @__PURE__ */ (0,
|
|
6054
|
+
}, children: profiles.map((profile) => /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("option", { value: profile.id, children: profile.name }, profile.id)) })
|
|
5100
6055
|
] }),
|
|
5101
|
-
/* @__PURE__ */ (0,
|
|
6056
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("label", { className: "uix-field__label", children: [
|
|
5102
6057
|
"Name",
|
|
5103
|
-
/* @__PURE__ */ (0,
|
|
6058
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("input", { className: "uix-input", value: value.name, onChange: (event) => update({ name: event.currentTarget.value }) })
|
|
5104
6059
|
] }),
|
|
5105
|
-
/* @__PURE__ */ (0,
|
|
5106
|
-
/* @__PURE__ */ (0,
|
|
6060
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "uix-brand-profiles__colors", children: [
|
|
6061
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("label", { children: [
|
|
5107
6062
|
"Brand",
|
|
5108
|
-
/* @__PURE__ */ (0,
|
|
6063
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)(ColorPicker, { label: "Brand color", value: value.brand, foreground: value.brandForeground, presets: colorPresets, onChange: (brand) => update({ brand }) })
|
|
5109
6064
|
] }),
|
|
5110
|
-
/* @__PURE__ */ (0,
|
|
6065
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("label", { children: [
|
|
5111
6066
|
"On brand",
|
|
5112
|
-
/* @__PURE__ */ (0,
|
|
6067
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)(ColorPicker, { label: "Brand foreground color", value: value.brandForeground, foreground: value.brand, presets: colorPresets, onChange: (brandForeground) => update({ brandForeground }) })
|
|
5113
6068
|
] })
|
|
5114
6069
|
] }),
|
|
5115
|
-
/* @__PURE__ */ (0,
|
|
6070
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("label", { className: "uix-field__label", children: [
|
|
5116
6071
|
"Body font",
|
|
5117
|
-
/* @__PURE__ */ (0,
|
|
6072
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("input", { className: "uix-input", value: value.typography?.sans ?? "", onChange: (event) => update({ typography: { ...value.typography, sans: event.currentTarget.value || void 0 } }) })
|
|
5118
6073
|
] }),
|
|
5119
|
-
/* @__PURE__ */ (0,
|
|
6074
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("label", { className: "uix-field__label", children: [
|
|
5120
6075
|
"Heading font",
|
|
5121
|
-
/* @__PURE__ */ (0,
|
|
6076
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("input", { className: "uix-input", value: value.typography?.heading ?? "", onChange: (event) => update({ typography: { ...value.typography, heading: event.currentTarget.value || void 0 } }) })
|
|
5122
6077
|
] }),
|
|
5123
|
-
/* @__PURE__ */ (0,
|
|
6078
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("label", { className: "uix-file-upload uix-brand-profiles__upload", children: [
|
|
5124
6079
|
"Logo file",
|
|
5125
|
-
/* @__PURE__ */ (0,
|
|
6080
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("input", { type: "file", accept: "image/*", onChange: onFile })
|
|
5126
6081
|
] }),
|
|
5127
|
-
/* @__PURE__ */ (0,
|
|
5128
|
-
/* @__PURE__ */ (0,
|
|
6082
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary", onClick: apply, children: "Apply profile" }),
|
|
6083
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "uix-visually-hidden", "aria-live": "polite", children: announcement })
|
|
5129
6084
|
] }),
|
|
5130
|
-
/* @__PURE__ */ (0,
|
|
5131
|
-
/* @__PURE__ */ (0,
|
|
5132
|
-
value.logo ? /* @__PURE__ */ (0,
|
|
5133
|
-
/* @__PURE__ */ (0,
|
|
6085
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "uix-brand-profiles__preview", style: previewStyle, "aria-label": `Live preview of ${value.name}`, children: [
|
|
6086
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "uix-brand-profiles__preview-header", children: [
|
|
6087
|
+
value.logo ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("img", { src: value.logo.src, alt: value.logo.alt }) : /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "uix-brand-profiles__logo-placeholder", children: "Logo" }),
|
|
6088
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("strong", { children: value.name || "Brand preview" })
|
|
5134
6089
|
] }),
|
|
5135
|
-
/* @__PURE__ */ (0,
|
|
5136
|
-
/* @__PURE__ */ (0,
|
|
5137
|
-
/* @__PURE__ */ (0,
|
|
5138
|
-
/* @__PURE__ */ (0,
|
|
5139
|
-
/* @__PURE__ */ (0,
|
|
6090
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("div", { className: "uix-brand-profiles__preview-body", children: [
|
|
6091
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("h3", { children: "Readable, serializable branding" }),
|
|
6092
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("p", { children: "Accent, links, rings, and muted states continue through the existing UIx token chain." }),
|
|
6093
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary", children: "Primary action" }),
|
|
6094
|
+
/* @__PURE__ */ (0, import_jsx_runtime70.jsx)("a", { href: "#brand-profile-preview", children: "Preview link" })
|
|
5140
6095
|
] })
|
|
5141
6096
|
] })
|
|
5142
6097
|
] });
|
|
@@ -5144,7 +6099,7 @@ function BrandProfileEditor({
|
|
|
5144
6099
|
var BrandProfiles = BrandProfileEditor;
|
|
5145
6100
|
|
|
5146
6101
|
// src/components/DiffViewer.tsx
|
|
5147
|
-
var
|
|
6102
|
+
var import_react46 = require("react");
|
|
5148
6103
|
|
|
5149
6104
|
// src/diff-model.ts
|
|
5150
6105
|
function isJsonObject(value) {
|
|
@@ -5195,7 +6150,7 @@ function summarizeDiff(entries, resolutions = {}) {
|
|
|
5195
6150
|
}
|
|
5196
6151
|
|
|
5197
6152
|
// src/components/DiffViewer.tsx
|
|
5198
|
-
var
|
|
6153
|
+
var import_jsx_runtime71 = require("react/jsx-runtime");
|
|
5199
6154
|
var GROUPS = [
|
|
5200
6155
|
{ kind: "conflicted", label: "Conflicted" },
|
|
5201
6156
|
{ kind: "changed", label: "Changed" },
|
|
@@ -5214,65 +6169,65 @@ function DiffViewer({
|
|
|
5214
6169
|
labels = DEFAULT_LABELS,
|
|
5215
6170
|
className
|
|
5216
6171
|
}) {
|
|
5217
|
-
const id = (0,
|
|
5218
|
-
const entries = (0,
|
|
5219
|
-
const [internalResolutions, setInternalResolutions] = (0,
|
|
6172
|
+
const id = (0, import_react46.useId)();
|
|
6173
|
+
const entries = (0, import_react46.useMemo)(() => providedEntries ?? buildThreeWayDiff(base, current, incoming), [providedEntries, base, current, incoming]);
|
|
6174
|
+
const [internalResolutions, setInternalResolutions] = (0, import_react46.useState)({});
|
|
5220
6175
|
const resolutions = controlledResolutions ?? internalResolutions;
|
|
5221
6176
|
const summary = summarizeDiff(entries, resolutions);
|
|
5222
6177
|
const resolve2 = (path, resolution) => {
|
|
5223
6178
|
if (controlledResolutions === void 0) setInternalResolutions((currentState) => ({ ...currentState, [path]: resolution }));
|
|
5224
6179
|
onResolutionChange?.(path, resolution);
|
|
5225
6180
|
};
|
|
5226
|
-
if (entries.length === 0) return /* @__PURE__ */ (0,
|
|
5227
|
-
/* @__PURE__ */ (0,
|
|
5228
|
-
/* @__PURE__ */ (0,
|
|
6181
|
+
if (entries.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("section", { className: cx("uix-diff-viewer uix-diff-viewer--empty", className), "aria-label": "Configuration differences", children: [
|
|
6182
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("h3", { children: "No differences" }),
|
|
6183
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("p", { children: "Base, current, and incoming values are aligned." })
|
|
5229
6184
|
] });
|
|
5230
|
-
return /* @__PURE__ */ (0,
|
|
5231
|
-
/* @__PURE__ */ (0,
|
|
5232
|
-
GROUPS.map((group) => /* @__PURE__ */ (0,
|
|
5233
|
-
/* @__PURE__ */ (0,
|
|
6185
|
+
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("section", { className: cx("uix-diff-viewer", className), "aria-label": "Configuration differences", children: [
|
|
6186
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "uix-diff-viewer__summary", "aria-label": "Difference summary", children: [
|
|
6187
|
+
GROUPS.map((group) => /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("span", { children: [
|
|
6188
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("b", { children: summary[group.kind] }),
|
|
5234
6189
|
" ",
|
|
5235
6190
|
group.label.toLowerCase()
|
|
5236
6191
|
] }, group.kind)),
|
|
5237
|
-
/* @__PURE__ */ (0,
|
|
5238
|
-
/* @__PURE__ */ (0,
|
|
6192
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("span", { children: [
|
|
6193
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("b", { children: summary.resolved }),
|
|
5239
6194
|
" resolved"
|
|
5240
6195
|
] }),
|
|
5241
|
-
/* @__PURE__ */ (0,
|
|
5242
|
-
/* @__PURE__ */ (0,
|
|
6196
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("span", { children: [
|
|
6197
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("b", { children: summary.pending }),
|
|
5243
6198
|
" pending"
|
|
5244
6199
|
] })
|
|
5245
6200
|
] }),
|
|
5246
6201
|
GROUPS.map((group) => {
|
|
5247
6202
|
const grouped = entries.filter((entry) => entry.kind === group.kind);
|
|
5248
6203
|
if (!grouped.length) return null;
|
|
5249
|
-
return /* @__PURE__ */ (0,
|
|
5250
|
-
/* @__PURE__ */ (0,
|
|
6204
|
+
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("section", { className: "uix-diff-viewer__group", "aria-labelledby": `${id}-${group.kind}`, children: [
|
|
6205
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("h3", { id: `${id}-${group.kind}`, children: [
|
|
5251
6206
|
group.label,
|
|
5252
6207
|
" ",
|
|
5253
|
-
/* @__PURE__ */ (0,
|
|
6208
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("span", { children: grouped.length })
|
|
5254
6209
|
] }),
|
|
5255
6210
|
grouped.map((entry) => {
|
|
5256
6211
|
const resolution = resolutions[entry.path] ?? "pending";
|
|
5257
|
-
return /* @__PURE__ */ (0,
|
|
5258
|
-
/* @__PURE__ */ (0,
|
|
5259
|
-
/* @__PURE__ */ (0,
|
|
5260
|
-
/* @__PURE__ */ (0,
|
|
6212
|
+
return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("details", { className: "uix-diff-viewer__entry", "data-kind": entry.kind, open: entry.kind === "conflicted", children: [
|
|
6213
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("summary", { children: [
|
|
6214
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("code", { children: entry.path }),
|
|
6215
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)(StatusPill, { tone: resolution === "pending" ? "warning" : "success", children: resolution })
|
|
5261
6216
|
] }),
|
|
5262
|
-
/* @__PURE__ */ (0,
|
|
5263
|
-
/* @__PURE__ */ (0,
|
|
5264
|
-
/* @__PURE__ */ (0,
|
|
6217
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("div", { className: "uix-diff-viewer__versions", children: ["base", "current", "incoming"].map((version) => /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { role: "region", "aria-label": `${labels[version] ?? `${version[0].toUpperCase()}${version.slice(1)}`} value for ${entry.path}`, children: [
|
|
6218
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("strong", { children: labels[version] ?? `${version[0].toUpperCase()}${version.slice(1)}` }),
|
|
6219
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("pre", { children: renderValue(entry[version]) })
|
|
5265
6220
|
] }, version)) }),
|
|
5266
|
-
/* @__PURE__ */ (0,
|
|
5267
|
-
/* @__PURE__ */ (0,
|
|
5268
|
-
/* @__PURE__ */ (0,
|
|
5269
|
-
/* @__PURE__ */ (0,
|
|
6221
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("div", { className: "uix-diff-viewer__actions", "aria-label": `Resolve ${entry.path}`, children: [
|
|
6222
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary uix-btn--sm", "aria-pressed": resolution === "accept", onClick: () => resolve2(entry.path, "accept"), children: "Accept incoming" }),
|
|
6223
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", "aria-pressed": resolution === "skip", onClick: () => resolve2(entry.path, "skip"), children: "Keep current" }),
|
|
6224
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", "aria-pressed": resolution === "pending", onClick: () => resolve2(entry.path, "pending"), children: "Mark pending" })
|
|
5270
6225
|
] })
|
|
5271
6226
|
] }, entry.path);
|
|
5272
6227
|
})
|
|
5273
6228
|
] }, group.kind);
|
|
5274
6229
|
}),
|
|
5275
|
-
/* @__PURE__ */ (0,
|
|
6230
|
+
/* @__PURE__ */ (0, import_jsx_runtime71.jsxs)("p", { className: "uix-visually-hidden", "aria-live": "polite", children: [
|
|
5276
6231
|
summary.resolved,
|
|
5277
6232
|
" of ",
|
|
5278
6233
|
entries.length,
|
|
@@ -5312,6 +6267,8 @@ function DiffViewer({
|
|
|
5312
6267
|
ConfirmDialog,
|
|
5313
6268
|
ContentList,
|
|
5314
6269
|
ContentListItem,
|
|
6270
|
+
DEFAULT_RELATIONSHIP_GRAPH_LABELS,
|
|
6271
|
+
DEFAULT_SAVE_STATUS_LABELS,
|
|
5315
6272
|
DateRangePicker,
|
|
5316
6273
|
DescriptionItem,
|
|
5317
6274
|
DescriptionList,
|
|
@@ -5378,6 +6335,7 @@ function DiffViewer({
|
|
|
5378
6335
|
RowAction,
|
|
5379
6336
|
RowActions,
|
|
5380
6337
|
RuleBuilder,
|
|
6338
|
+
SaveStatus,
|
|
5381
6339
|
SavedViewMenu,
|
|
5382
6340
|
SchedulingCalendar,
|
|
5383
6341
|
SectionHead,
|
|
@@ -5423,6 +6381,8 @@ function DiffViewer({
|
|
|
5423
6381
|
buildThreeWayDiff,
|
|
5424
6382
|
clampMetricValue,
|
|
5425
6383
|
clampWidth,
|
|
6384
|
+
classifyLayeredEdges,
|
|
6385
|
+
clusterIdFor,
|
|
5426
6386
|
computePosition,
|
|
5427
6387
|
contrastRatio,
|
|
5428
6388
|
cx,
|
|
@@ -5437,6 +6397,8 @@ function DiffViewer({
|
|
|
5437
6397
|
isDateInRange,
|
|
5438
6398
|
isDateUnavailable,
|
|
5439
6399
|
isRuleGroup,
|
|
6400
|
+
layeredNeighbor,
|
|
6401
|
+
layoutLayeredGraph,
|
|
5440
6402
|
layoutRelationshipGraph,
|
|
5441
6403
|
mapRuleGroup,
|
|
5442
6404
|
matchFilter,
|
|
@@ -5478,6 +6440,7 @@ function DiffViewer({
|
|
|
5478
6440
|
useVirtualRows,
|
|
5479
6441
|
validateRuleDefinition,
|
|
5480
6442
|
virtualWindow,
|
|
6443
|
+
wrapEdgeLabel,
|
|
5481
6444
|
zonedDateKey,
|
|
5482
6445
|
zonedDateSpan
|
|
5483
6446
|
});
|