@tensor_1/react 2.47.0 → 2.49.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 +540 -2
- package/dist/{SchedulingCalendar-B6TakO2h.d.ts → SchedulingCalendar-WWyFL3Eo.d.ts} +51 -2
- package/dist/announce.d.ts +10 -0
- package/dist/announce.js +30 -0
- package/dist/chart-analytic.cjs +33 -25
- package/dist/chart-preset.cjs +23 -15
- package/dist/chart.cjs +23 -15
- package/dist/combobox-model.d.ts +10 -1
- package/dist/combobox-model.js +15 -0
- package/dist/command-palette-model.d.ts +44 -0
- package/dist/command-palette-model.js +36 -0
- package/dist/components/AccountMenu.d.ts +44 -0
- package/dist/components/AccountMenu.js +43 -0
- package/dist/components/AppShell.d.ts +45 -2
- package/dist/components/AppShell.js +116 -5
- package/dist/components/AuditLog.d.ts +128 -0
- package/dist/components/AuditLog.js +196 -0
- package/dist/components/BrandProfiles.js +4 -3
- package/dist/components/Breadcrumbs.d.ts +9 -2
- package/dist/components/Breadcrumbs.js +3 -2
- package/dist/components/Button.d.ts +12 -5
- package/dist/components/Button.js +7 -3
- package/dist/components/Card.d.ts +18 -1
- package/dist/components/Card.js +5 -1
- package/dist/components/ChangeHighlight.d.ts +30 -0
- package/dist/components/ChangeHighlight.js +21 -0
- package/dist/components/ChartCore.js +2 -1
- package/dist/components/Checkbox.d.ts +27 -1
- package/dist/components/Checkbox.js +31 -2
- package/dist/components/Chip.d.ts +7 -3
- package/dist/components/Chip.js +2 -2
- package/dist/components/CodeDisplay.d.ts +65 -0
- package/dist/components/CodeDisplay.js +124 -0
- package/dist/components/Combobox.d.ts +27 -6
- package/dist/components/Combobox.js +195 -58
- package/dist/components/CommandPalette.d.ts +36 -1
- package/dist/components/CommandPalette.js +254 -2
- package/dist/components/ContactCard.d.ts +66 -0
- package/dist/components/ContactCard.js +74 -0
- package/dist/components/Count.d.ts +24 -0
- package/dist/components/Count.js +32 -0
- package/dist/components/DashboardCanvas.js +14 -0
- package/dist/components/DataWorkspace.d.ts +167 -0
- package/dist/components/DataWorkspace.js +380 -0
- package/dist/components/DateFieldParts.d.ts +2 -1
- package/dist/components/DateFieldParts.js +7 -0
- package/dist/components/DatePicker.d.ts +9 -2
- package/dist/components/DatePicker.js +67 -28
- package/dist/components/DateRangePicker.d.ts +12 -2
- package/dist/components/DateRangePicker.js +13 -12
- package/dist/components/DetailPage.d.ts +7 -1
- package/dist/components/DetailPage.js +2 -1
- package/dist/components/Dialogs.d.ts +71 -10
- package/dist/components/Dialogs.js +130 -30
- package/dist/components/DiffViewer.d.ts +23 -3
- package/dist/components/DiffViewer.js +26 -12
- package/dist/components/DiscardPrompt.js +16 -0
- package/dist/components/DisplayPreferences.d.ts +83 -0
- package/dist/components/DisplayPreferences.js +185 -0
- package/dist/components/EditorialHome.d.ts +23 -3
- package/dist/components/EditorialHome.js +16 -11
- package/dist/components/EntityPicker.d.ts +20 -3
- package/dist/components/EntityPicker.js +32 -13
- package/dist/components/FilterEditor.d.ts +18 -4
- package/dist/components/FilterEditor.js +141 -19
- package/dist/components/FocusOnMount.d.ts +282 -0
- package/dist/components/FocusOnMount.js +12 -0
- package/dist/components/InfoTip.js +11 -12
- package/dist/components/InlineEdit.d.ts +87 -20
- package/dist/components/InlineEdit.js +197 -54
- package/dist/components/Input.d.ts +12 -2
- package/dist/components/Input.js +5 -3
- package/dist/components/Kanban.d.ts +14 -3
- package/dist/components/Kanban.js +9 -4
- package/dist/components/Kbd.d.ts +6 -1
- package/dist/components/Kbd.js +6 -6
- package/dist/components/Lightbox.d.ts +41 -5
- package/dist/components/Lightbox.js +95 -9
- package/dist/components/MatchReview.d.ts +40 -1
- package/dist/components/MatchReview.js +130 -4
- package/dist/components/MetricInput.js +3 -2
- package/dist/components/Modal.d.ts +2 -1
- package/dist/components/Modal.js +13 -4
- package/dist/components/MotionList.d.ts +303 -0
- package/dist/components/MotionList.js +175 -0
- package/dist/components/NavFavourites.d.ts +5 -0
- package/dist/components/NavFavourites.js +7 -7
- package/dist/components/OtpInput.d.ts +33 -0
- package/dist/components/OtpInput.js +123 -0
- package/dist/components/PageHeader.d.ts +7 -1
- package/dist/components/PageHeader.js +2 -2
- package/dist/components/Pagination.js +6 -5
- package/dist/components/PasswordInput.d.ts +34 -0
- package/dist/components/PasswordInput.js +101 -0
- package/dist/components/Peek.js +3 -3
- package/dist/components/Popover.js +11 -0
- package/dist/components/PrintLayout.d.ts +63 -0
- package/dist/components/PrintLayout.js +114 -0
- package/dist/components/QrCode.d.ts +47 -0
- package/dist/components/QrCode.js +55 -0
- package/dist/components/QrScanner.d.ts +95 -0
- package/dist/components/QrScanner.js +266 -0
- package/dist/components/RelationshipGraph.d.ts +32 -1
- package/dist/components/RelationshipGraph.js +22 -6
- package/dist/components/RelationshipGraphLayered.d.ts +1 -1
- package/dist/components/RelationshipGraphLayered.js +268 -118
- package/dist/components/RelationshipGraphList.js +33 -6
- package/dist/components/RuleBuilder.js +39 -7
- package/dist/components/SchedulingAgenda.d.ts +3 -1
- package/dist/components/SchedulingCalendar.d.ts +3 -1
- package/dist/components/SchedulingCalendar.js +43 -4
- package/dist/components/SchedulingResourceDay.d.ts +57 -0
- package/dist/components/SchedulingResourceDay.js +287 -0
- package/dist/components/SchedulingTimeGrid.d.ts +3 -1
- package/dist/components/SchedulingTimeline.d.ts +3 -1
- package/dist/components/SearchSuggest.d.ts +23 -3
- package/dist/components/SearchSuggest.js +56 -18
- package/dist/components/Segmented.d.ts +39 -4
- package/dist/components/Segmented.js +39 -5
- package/dist/components/Select.d.ts +3 -2
- package/dist/components/Select.js +7 -1
- package/dist/components/ShortcutHint.d.ts +11 -10
- package/dist/components/ShortcutHint.js +44 -38
- package/dist/components/Sidebar.d.ts +36 -4
- package/dist/components/Sidebar.js +37 -12
- package/dist/components/SortableList.d.ts +45 -0
- package/dist/components/SortableList.js +147 -0
- package/dist/components/Stat.d.ts +28 -3
- package/dist/components/Stat.js +13 -3
- package/dist/components/States.d.ts +33 -1
- package/dist/components/States.js +43 -1
- package/dist/components/StatusPill.d.ts +14 -3
- package/dist/components/StatusPill.js +11 -3
- package/dist/components/Steps.js +2 -1
- package/dist/components/Table.d.ts +9 -2
- package/dist/components/Table.js +4 -2
- package/dist/components/TableControls.js +18 -58
- package/dist/components/TableOverflowProbe.d.ts +12 -0
- package/dist/components/TableOverflowProbe.js +27 -0
- package/dist/components/Tabs.d.ts +2 -1
- package/dist/components/Tabs.js +10 -2
- package/dist/components/TagInput.d.ts +67 -0
- package/dist/components/TagInput.js +342 -0
- package/dist/components/Textarea.d.ts +5 -0
- package/dist/components/Textarea.js +2 -2
- package/dist/components/TimePicker.d.ts +80 -0
- package/dist/components/TimePicker.js +347 -0
- package/dist/components/Toast.d.ts +1 -1
- package/dist/components/Toast.js +109 -4
- package/dist/components/Tooltip.d.ts +8 -4
- package/dist/components/Tooltip.js +86 -28
- package/dist/components/Tree.d.ts +8 -0
- package/dist/components/Tree.js +11 -5
- package/dist/display-preferences-model.d.ts +53 -0
- package/dist/display-preferences-model.js +64 -0
- package/dist/emoji.cjs +143 -49
- package/dist/filter-model.d.ts +59 -3
- package/dist/filter-model.js +67 -2
- package/dist/hooks/useAnchoredPosition.js +14 -2
- package/dist/hooks/useChangeHighlight.d.ts +33 -0
- package/dist/hooks/useChangeHighlight.js +44 -0
- package/dist/hooks/useDeferredReorder.d.ts +32 -0
- package/dist/hooks/useDeferredReorder.js +47 -0
- package/dist/hooks/useDialog.d.ts +5 -0
- package/dist/hooks/useDialog.js +17 -3
- package/dist/hooks/useKeyboardGrab.d.ts +58 -0
- package/dist/hooks/useKeyboardGrab.js +118 -0
- package/dist/hooks/useOptimisticValue.d.ts +51 -0
- package/dist/hooks/useOptimisticValue.js +61 -0
- package/dist/hooks/useReducedMotion.d.ts +4 -1
- package/dist/hooks/useReducedMotion.js +7 -1
- package/dist/hooks/useResolvedFilterLabels.d.ts +15 -0
- package/dist/hooks/useResolvedFilterLabels.js +34 -0
- package/dist/hooks/useSlidingIndicator.d.ts +18 -0
- package/dist/hooks/useSlidingIndicator.js +80 -0
- package/dist/hooks/useVirtualRows.d.ts +21 -2
- package/dist/hooks/useVirtualRows.js +30 -3
- package/dist/icons/Icon.d.ts +1 -1
- package/dist/index.cjs +19687 -13423
- package/dist/index.d.cts +3419 -651
- package/dist/index.d.ts +48 -18
- package/dist/index.js +153 -9
- package/dist/labels-context.d.ts +93 -3
- package/dist/motion.d.ts +11 -0
- package/dist/motion.js +35 -0
- package/dist/overlay-stack.d.ts +6 -0
- package/dist/overlay-stack.js +13 -0
- package/dist/qr-model.d.ts +65 -0
- package/dist/qr-model.js +323 -0
- package/dist/relationship-graph-model.d.ts +92 -3
- package/dist/relationship-graph-model.js +134 -15
- package/dist/reorder.d.ts +30 -0
- package/dist/reorder.js +74 -0
- package/dist/rich-text.cjs +46 -4
- package/dist/scheduling-resource-model.d.ts +76 -0
- package/dist/scheduling-resource-model.js +74 -0
- package/dist/search-suggest-model.js +3 -1
- package/dist/shell-context.d.ts +11 -0
- package/dist/shell-context.js +7 -0
- package/dist/time-field-model.d.ts +46 -0
- package/dist/time-field-model.js +152 -0
- package/dist/toast-store.d.ts +22 -3
- package/dist/toast-store.js +26 -9
- package/package.json +2 -1
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
|
|
4
|
-
import { boundRelationshipGraph, layeredNeighbor, layoutLayeredGraph } from "../relationship-graph-model.js";
|
|
3
|
+
import { useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { boundRelationshipGraph, edgeLabelSize, layeredNeighbor, layoutLayeredGraph, separateEdgeLabels } from "../relationship-graph-model.js";
|
|
5
5
|
import { cx } from "../cx.js";
|
|
6
6
|
import { Maximize2Icon, Minimize2Icon, MinusIcon, PlusIcon, RotateCcwIcon, ScanIcon } from "../icons/components.js";
|
|
7
7
|
import { useKbdPlatform } from "./Kbd.js";
|
|
8
|
+
import { prefersReducedMotion } from "../hooks/useReducedMotion.js";
|
|
8
9
|
import { EquivalentRelationshipList } from "./RelationshipGraphList.js";
|
|
9
10
|
import { Tooltip } from "./Tooltip.js";
|
|
10
11
|
const EMPTY_IDS = /* @__PURE__ */ new Set();
|
|
12
|
+
const useIsomorphicLayoutEffect = typeof document !== "undefined" ? useLayoutEffect : useEffect;
|
|
11
13
|
const MIN_ZOOM = 0.4;
|
|
12
14
|
const MAX_ZOOM = 1.5;
|
|
13
15
|
const READABLE_ZOOM = 0.75;
|
|
14
16
|
const ZOOM_STEP = 1.2;
|
|
15
17
|
const PAN_STEP = 64;
|
|
16
18
|
const FOCUS_MARGIN = 24;
|
|
19
|
+
const DESCRIBED_RELATIONS = 5;
|
|
17
20
|
const HINT_MS = 1600;
|
|
21
|
+
const LABEL_FONT_PX = 12.5;
|
|
22
|
+
const MIN_LABEL_PX = 11;
|
|
23
|
+
const LABEL_CHIP_PAD_X = 6;
|
|
24
|
+
const LABEL_CHIP_PAD_Y = 2;
|
|
18
25
|
const NAV_KEYS = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End"];
|
|
19
26
|
const clampZoom = (zoom) => Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, zoom));
|
|
27
|
+
const footerGutter = (viewport, footer) => footer && footer.parentElement === viewport ? Math.min(footer.offsetHeight, viewport.clientHeight) : 0;
|
|
20
28
|
function initialView(layout, size) {
|
|
21
29
|
if (size.width === 0 || size.height === 0 || layout.width === 0) return { x: 0, y: 0, zoom: 1 };
|
|
22
30
|
const fit = Math.min(size.width / layout.width, size.height / layout.height);
|
|
@@ -60,9 +68,12 @@ function LayeredRelationshipGraph({
|
|
|
60
68
|
focusId,
|
|
61
69
|
onFocusChange,
|
|
62
70
|
controls = "full",
|
|
63
|
-
initialView: initialViewMode = "readable"
|
|
71
|
+
initialView: initialViewMode = "readable",
|
|
72
|
+
revealId,
|
|
73
|
+
markRoot
|
|
64
74
|
}) {
|
|
65
75
|
const hintId = useId();
|
|
76
|
+
const describeId = useId();
|
|
66
77
|
const viewportHintId = useId();
|
|
67
78
|
const compact = controls === "compact";
|
|
68
79
|
const bounded = useMemo(() => boundRelationshipGraph(nodes, edges, maxNodes), [nodes, edges, maxNodes]);
|
|
@@ -85,11 +96,14 @@ function LayeredRelationshipGraph({
|
|
|
85
96
|
const viewportRef = useRef(null);
|
|
86
97
|
const itemRefs = useRef(/* @__PURE__ */ new Map());
|
|
87
98
|
const fullscreenButtonRef = useRef(null);
|
|
99
|
+
const footerRef = useRef(null);
|
|
100
|
+
const edgesRef = useRef(null);
|
|
88
101
|
const [size, setSize] = useState({ width: 0, height: 0 });
|
|
89
102
|
const [view, setView] = useState({ x: 0, y: 0, zoom: 1 });
|
|
90
103
|
const [animate, setAnimate] = useState(false);
|
|
91
104
|
const [localFocus, setLocalFocus] = useState(void 0);
|
|
92
105
|
const [hoverId, setHoverId] = useState(void 0);
|
|
106
|
+
const [focusWithinId, setFocusWithinId] = useState(void 0);
|
|
93
107
|
const [fullscreen, setFullscreen] = useState(false);
|
|
94
108
|
const [wheelHint, setWheelHint] = useState(false);
|
|
95
109
|
const viewRef = useRef(view);
|
|
@@ -116,13 +130,14 @@ function LayeredRelationshipGraph({
|
|
|
116
130
|
useEffect(() => {
|
|
117
131
|
const element = viewportRef.current;
|
|
118
132
|
if (!element) return;
|
|
119
|
-
const measure = () => setSize({ width: element.clientWidth, height: element.clientHeight });
|
|
133
|
+
const measure = () => setSize({ width: element.clientWidth, height: Math.max(0, element.clientHeight - footerGutter(element, footerRef.current)) });
|
|
120
134
|
measure();
|
|
121
135
|
if (typeof ResizeObserver === "undefined") return;
|
|
122
136
|
const observer = new ResizeObserver(measure);
|
|
123
137
|
observer.observe(element);
|
|
138
|
+
if (footerRef.current) observer.observe(footerRef.current);
|
|
124
139
|
return () => observer.disconnect();
|
|
125
|
-
}, []);
|
|
140
|
+
}, [compact]);
|
|
126
141
|
useEffect(() => {
|
|
127
142
|
if (size.width === 0) return;
|
|
128
143
|
const key = `${layout.rootId ?? ""}`;
|
|
@@ -147,7 +162,7 @@ function LayeredRelationshipGraph({
|
|
|
147
162
|
}, [fullscreen]);
|
|
148
163
|
useEffect(() => () => clearTimeout(hintTimer.current), []);
|
|
149
164
|
const moveView = useCallback((next, smooth) => {
|
|
150
|
-
setAnimate(smooth);
|
|
165
|
+
setAnimate(smooth && !prefersReducedMotion());
|
|
151
166
|
setView(next);
|
|
152
167
|
}, []);
|
|
153
168
|
const ensureVisible = useCallback((id, smooth) => {
|
|
@@ -165,8 +180,10 @@ function LayeredRelationshipGraph({
|
|
|
165
180
|
let nextY = y;
|
|
166
181
|
if (left < FOCUS_MARGIN) nextX += FOCUS_MARGIN - left;
|
|
167
182
|
else if (right > width - FOCUS_MARGIN) nextX -= right - (width - FOCUS_MARGIN);
|
|
183
|
+
const footer = footerRef.current;
|
|
184
|
+
const bottomMargin = footer ? Math.max(FOCUS_MARGIN, heightPx - footer.offsetTop + 8) : FOCUS_MARGIN;
|
|
168
185
|
if (top < FOCUS_MARGIN) nextY += FOCUS_MARGIN - top;
|
|
169
|
-
else if (bottom > heightPx -
|
|
186
|
+
else if (bottom > heightPx - bottomMargin) nextY -= bottom - (heightPx - bottomMargin);
|
|
170
187
|
if (nextX !== x || nextY !== y) moveView({ x: nextX, y: nextY, zoom }, smooth);
|
|
171
188
|
}, [moveView]);
|
|
172
189
|
const focusItem = useCallback((id) => {
|
|
@@ -197,6 +214,18 @@ function LayeredRelationshipGraph({
|
|
|
197
214
|
ensureVisible(controlledTarget, true);
|
|
198
215
|
});
|
|
199
216
|
}, [controlledKey, controlledTarget, controlledPresent, ensureVisible]);
|
|
217
|
+
const revealTarget = revealId !== void 0 ? layout.itemOf[revealId] ?? revealId : void 0;
|
|
218
|
+
const revealReady = revealTarget !== void 0 && itemById.has(revealTarget) && size.width > 0;
|
|
219
|
+
const revealedKey = useRef(void 0);
|
|
220
|
+
useEffect(() => {
|
|
221
|
+
if (!revealReady || revealTarget === void 0 || initialisedFor.current === void 0) return;
|
|
222
|
+
if (revealedKey.current === revealTarget) return;
|
|
223
|
+
revealedKey.current = revealTarget;
|
|
224
|
+
requestAnimationFrame(() => ensureVisible(revealTarget, true));
|
|
225
|
+
}, [revealReady, revealTarget, ensureVisible]);
|
|
226
|
+
useEffect(() => {
|
|
227
|
+
if (revealId === void 0) revealedKey.current = void 0;
|
|
228
|
+
}, [revealId]);
|
|
200
229
|
useEffect(() => {
|
|
201
230
|
const element = viewportRef.current;
|
|
202
231
|
if (!element) return;
|
|
@@ -331,18 +360,240 @@ function LayeredRelationshipGraph({
|
|
|
331
360
|
if (nodeAriaLabel) return [nodeAriaLabel(node), item.inCycle ? labels.cycle : void 0, conflict].filter(Boolean).join(", ");
|
|
332
361
|
return [node.label, node.type, node.description, labels.relationships(item.degree), item.inCycle ? labels.cycle : void 0, conflict].filter(Boolean).join(", ");
|
|
333
362
|
};
|
|
363
|
+
const nodeLabelById = useMemo(() => new Map(bounded.nodes.map((node) => [node.id, node.label])), [bounded.nodes]);
|
|
364
|
+
const relationsOf = useMemo(() => {
|
|
365
|
+
const map = /* @__PURE__ */ new Map();
|
|
366
|
+
const add = (id, text) => {
|
|
367
|
+
const list = map.get(id);
|
|
368
|
+
if (list) list.push(text);
|
|
369
|
+
else map.set(id, [text]);
|
|
370
|
+
};
|
|
371
|
+
for (const edge of bounded.edges) {
|
|
372
|
+
if (!nodeLabelById.has(edge.source) || !nodeLabelById.has(edge.target) || edge.source === edge.target) continue;
|
|
373
|
+
const relation = edge.label ?? edge.type ?? labels.relationship;
|
|
374
|
+
const note = edge.description ? ` (${edge.description})` : "";
|
|
375
|
+
add(edge.source, `${labels.relationTo(relation, nodeLabelById.get(edge.target))}${note}`);
|
|
376
|
+
add(edge.target, `${labels.relationFrom(relation, nodeLabelById.get(edge.source))}${note}`);
|
|
377
|
+
}
|
|
378
|
+
const described = /* @__PURE__ */ new Map();
|
|
379
|
+
for (const [id, list] of map) {
|
|
380
|
+
const hidden = list.length - DESCRIBED_RELATIONS;
|
|
381
|
+
described.set(id, hidden > 0 ? `${list.slice(0, DESCRIBED_RELATIONS).join("; ")}; ${labels.moreRelations(hidden, showList)}` : list.join("; "));
|
|
382
|
+
}
|
|
383
|
+
return described;
|
|
384
|
+
}, [bounded.edges, nodeLabelById, labels, showList]);
|
|
385
|
+
const showRoot = markRoot ?? rootId !== void 0;
|
|
334
386
|
const showLabel = (edge) => {
|
|
335
387
|
if (edgeLabels === "never" || edge.label === void 0) return false;
|
|
336
388
|
if (edgeLabels === "always") return true;
|
|
337
|
-
|
|
389
|
+
if (edge.columnLabel) return false;
|
|
390
|
+
return edge.autoLabel || activeIds.has(edge.source) || activeIds.has(edge.target) || focusWithinId === edge.source || focusWithinId === edge.target;
|
|
338
391
|
};
|
|
339
392
|
const viewportStyle = height !== void 0 ? { "--uix-relationship-graph-height": height } : {};
|
|
393
|
+
const zoomStep = Math.min(1, Math.max(0.05, Math.floor(view.zoom * 20) / 20));
|
|
340
394
|
const stageStyle = {
|
|
341
395
|
width: layout.width,
|
|
342
396
|
height: layout.height,
|
|
343
397
|
transform: `translate(${view.x}px, ${view.y}px) scale(${view.zoom})`
|
|
344
398
|
};
|
|
345
399
|
const zoomPercent = Math.round(view.zoom * 100);
|
|
400
|
+
const labelPlacement = useMemo(() => {
|
|
401
|
+
const shown = layout.edges.filter(showLabel);
|
|
402
|
+
const count = /* @__PURE__ */ new Map();
|
|
403
|
+
for (const edge of shown) count.set(edge.label ?? "", (count.get(edge.label ?? "") ?? 0) + 1);
|
|
404
|
+
const scales = /* @__PURE__ */ new Map();
|
|
405
|
+
const boxes = [];
|
|
406
|
+
for (const edge of shown) {
|
|
407
|
+
const lines = edge.kind === "cycle" ? [...edge.labelLines, labels.cycle] : edge.labelLines;
|
|
408
|
+
const size2 = edgeLabelSize(lines);
|
|
409
|
+
const scale = Math.max(1, Math.min(1 / zoomStep, edge.labelRoom / size2.width));
|
|
410
|
+
if (edgeLabels !== "always" && LABEL_FONT_PX * scale * zoomStep < MIN_LABEL_PX - 0.01) continue;
|
|
411
|
+
scales.set(edge.id, scale);
|
|
412
|
+
const priority = (activeIds.has(edge.source) || activeIds.has(edge.target) ? 4 : 0) + (edge.tone || edge.emphasis ? 2 : 0) + (count.get(edge.label ?? "") === 1 ? 1 : 0);
|
|
413
|
+
boxes.push({ id: edge.id, x: edge.labelX, y: edge.labelY, width: size2.width * scale, height: size2.height * scale, priority });
|
|
414
|
+
}
|
|
415
|
+
const placed = separateEdgeLabels(boxes, { maxShift: 48 / zoomStep, obstacles: layout.items });
|
|
416
|
+
return new Map([...placed].map(([id, place]) => [id, { ...place, scale: scales.get(id) ?? 1 }]));
|
|
417
|
+
}, [layout, edgeLabels, activeIds, focusWithinId, labels, zoomStep]);
|
|
418
|
+
const live = useRef({ activate, onItemKeyDown, onFocusChange, toggleCluster, onSelect });
|
|
419
|
+
live.current = { activate, onItemKeyDown, onFocusChange, toggleCluster, onSelect };
|
|
420
|
+
const edgeLayer = useMemo(() => {
|
|
421
|
+
const ordered = layout.edges.map((edge) => ({ edge, active: activeIds.has(edge.source) || activeIds.has(edge.target) || edge.edgeIds.some((id) => highlightedEdgeIds.has(id)) })).sort((a, b) => Number(a.active) - Number(b.active));
|
|
422
|
+
const dimmed = (edge) => dimmedNodeIds.has(edge.source) && dimmedNodeIds.has(edge.target) || void 0;
|
|
423
|
+
return /* @__PURE__ */ jsxs("svg", { ref: edgesRef, className: "uix-relationship-graph__edges", width: layout.width, height: layout.height, "aria-hidden": "true", focusable: "false", children: [
|
|
424
|
+
ordered.map(({ edge, active }) => {
|
|
425
|
+
const angle = edge.arrowAngle * 180 / Math.PI;
|
|
426
|
+
return /* @__PURE__ */ jsxs(
|
|
427
|
+
"g",
|
|
428
|
+
{
|
|
429
|
+
className: "uix-relationship-graph__link",
|
|
430
|
+
"data-edge": edge.id,
|
|
431
|
+
"data-kind": edge.kind,
|
|
432
|
+
"data-bus": edge.bus || void 0,
|
|
433
|
+
"data-active": active || void 0,
|
|
434
|
+
"data-emphasis": edge.emphasis || void 0,
|
|
435
|
+
"data-conflicted": edge.edgeIds.some((id) => conflictedEdgeIds.has(id)) || void 0,
|
|
436
|
+
"data-dimmed": dimmed(edge),
|
|
437
|
+
"data-variant": edge.variant === "dashed" ? "dashed" : void 0,
|
|
438
|
+
"data-tone": edge.tone,
|
|
439
|
+
children: [
|
|
440
|
+
/* @__PURE__ */ jsx("path", { d: edge.path }),
|
|
441
|
+
edge.arrow !== "none" && /* @__PURE__ */ jsx("polygon", { points: arrowPoints, transform: `translate(${edge.arrowX} ${edge.arrowY}) rotate(${angle})` })
|
|
442
|
+
]
|
|
443
|
+
},
|
|
444
|
+
edge.id
|
|
445
|
+
);
|
|
446
|
+
}),
|
|
447
|
+
/* @__PURE__ */ jsx("g", { className: "uix-relationship-graph__edge-labels", children: ordered.map(({ edge, active }) => {
|
|
448
|
+
const placed = labelPlacement.get(edge.id);
|
|
449
|
+
if (!placed || placed.hidden) return null;
|
|
450
|
+
const lines = edge.kind === "cycle" ? [...edge.labelLines, labels.cycle] : edge.labelLines;
|
|
451
|
+
const chip = edgeLabelSize(lines);
|
|
452
|
+
return /* @__PURE__ */ jsxs(
|
|
453
|
+
"g",
|
|
454
|
+
{
|
|
455
|
+
className: "uix-relationship-graph__edge-label",
|
|
456
|
+
"data-edge": edge.id,
|
|
457
|
+
"data-active": active || void 0,
|
|
458
|
+
"data-dimmed": dimmed(edge),
|
|
459
|
+
"data-tone": edge.tone,
|
|
460
|
+
"data-moved": placed.y !== edge.labelY || void 0,
|
|
461
|
+
style: placed.scale !== 1 ? { "--uix-graph-label-scale": placed.scale } : void 0,
|
|
462
|
+
children: [
|
|
463
|
+
/* @__PURE__ */ jsx("rect", { x: placed.x - chip.width / 2, y: placed.y - chip.height / 2, width: chip.width, height: chip.height, rx: 4 }),
|
|
464
|
+
/* @__PURE__ */ jsx("text", { x: placed.x, y: placed.y, textAnchor: "middle", dominantBaseline: "central", children: lines.map((line, index) => /* @__PURE__ */ jsx("tspan", { x: placed.x, dy: index === 0 ? `${-(lines.length - 1) * 0.6}em` : "1.2em", children: line }, index)) })
|
|
465
|
+
]
|
|
466
|
+
},
|
|
467
|
+
edge.id
|
|
468
|
+
);
|
|
469
|
+
}) })
|
|
470
|
+
] });
|
|
471
|
+
}, [layout, activeIds, highlightedEdgeIds, conflictedEdgeIds, dimmedNodeIds, labelPlacement, labels]);
|
|
472
|
+
useIsomorphicLayoutEffect(() => {
|
|
473
|
+
const svg = edgesRef.current;
|
|
474
|
+
if (!svg) return;
|
|
475
|
+
for (const group of Array.from(svg.querySelectorAll(".uix-relationship-graph__edge-label"))) {
|
|
476
|
+
const text = group.querySelector("text");
|
|
477
|
+
const rect = group.querySelector("rect");
|
|
478
|
+
if (!text || !rect || typeof text.getBBox !== "function") continue;
|
|
479
|
+
let box;
|
|
480
|
+
try {
|
|
481
|
+
box = text.getBBox();
|
|
482
|
+
} catch {
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
if (box.width === 0) continue;
|
|
486
|
+
rect.setAttribute("x", String(box.x - LABEL_CHIP_PAD_X));
|
|
487
|
+
rect.setAttribute("y", String(box.y - LABEL_CHIP_PAD_Y));
|
|
488
|
+
rect.setAttribute("width", String(box.width + 2 * LABEL_CHIP_PAD_X));
|
|
489
|
+
rect.setAttribute("height", String(box.height + 2 * LABEL_CHIP_PAD_Y));
|
|
490
|
+
}
|
|
491
|
+
}, [edgeLayer]);
|
|
492
|
+
const itemLayer = useMemo(() => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
493
|
+
layout.columns.map((column) => /* @__PURE__ */ jsxs(
|
|
494
|
+
"div",
|
|
495
|
+
{
|
|
496
|
+
className: "uix-relationship-graph__column",
|
|
497
|
+
"aria-hidden": "true",
|
|
498
|
+
style: { left: column.x, width: layout.nodeWidth + 64 },
|
|
499
|
+
children: [
|
|
500
|
+
labels.column(column.depth, column.count),
|
|
501
|
+
column.edgeLabel !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
502
|
+
" \xB7 ",
|
|
503
|
+
column.edgeLabel
|
|
504
|
+
] })
|
|
505
|
+
]
|
|
506
|
+
},
|
|
507
|
+
column.depth
|
|
508
|
+
)),
|
|
509
|
+
/* @__PURE__ */ 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, itemIndex) => {
|
|
510
|
+
const selected = item.id === selectedItemId;
|
|
511
|
+
const relations = item.node ? relationsOf.get(item.node.id) : void 0;
|
|
512
|
+
const dimmed = item.node ? dimmedNodeIds.has(item.node.id) : item.cluster.members.every((member) => dimmedNodeIds.has(member.id));
|
|
513
|
+
const body = item.cluster ? renderCluster?.(item.cluster) ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
514
|
+
/* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__item-label", children: labels.cluster(item.cluster.members.length, item.cluster.type, item.cluster.edgeLabel) }),
|
|
515
|
+
/* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__item-meta", children: labels.expandCluster })
|
|
516
|
+
] }) : renderNode?.(item.node, { selected, dimmed }) ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
517
|
+
/* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__item-label", children: item.node.label }),
|
|
518
|
+
(item.node.type || item.node.description) && /* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__item-meta", children: [item.node.type, item.node.description].filter(Boolean).join(" \xB7 ") })
|
|
519
|
+
] });
|
|
520
|
+
return /* @__PURE__ */ jsxs(
|
|
521
|
+
"button",
|
|
522
|
+
{
|
|
523
|
+
ref: (element) => {
|
|
524
|
+
if (element) itemRefs.current.set(item.id, element);
|
|
525
|
+
else itemRefs.current.delete(item.id);
|
|
526
|
+
},
|
|
527
|
+
type: "button",
|
|
528
|
+
className: "uix-relationship-graph__item",
|
|
529
|
+
"data-kind": item.kind,
|
|
530
|
+
"data-node-id": item.id,
|
|
531
|
+
"data-selected": selected || void 0,
|
|
532
|
+
"data-dimmed": dimmed || void 0,
|
|
533
|
+
"data-highlighted": item.node && highlightedNodeIds.has(item.node.id) || void 0,
|
|
534
|
+
"data-conflicted": item.node && conflictedNodeIds.has(item.node.id) || void 0,
|
|
535
|
+
"data-root": showRoot && item.id === rootItemId || void 0,
|
|
536
|
+
"data-tone": item.node?.tone,
|
|
537
|
+
"data-flag": item.inCycle || void 0,
|
|
538
|
+
style: { left: item.x, top: item.y, width: item.width, height: item.height },
|
|
539
|
+
tabIndex: item.id === focusedId ? 0 : -1,
|
|
540
|
+
"aria-label": labelFor(item),
|
|
541
|
+
"aria-describedby": relations ? `${describeId}-${itemIndex}` : void 0,
|
|
542
|
+
...item.cluster ? { "aria-expanded": false } : { "aria-pressed": selected },
|
|
543
|
+
onClick: () => live.current.activate(item),
|
|
544
|
+
onKeyDown: (event) => live.current.onItemKeyDown(event, item),
|
|
545
|
+
onFocus: () => {
|
|
546
|
+
setFocusWithinId(item.id);
|
|
547
|
+
if (item.id === focusedId) return;
|
|
548
|
+
setLocalFocus(item.id);
|
|
549
|
+
live.current.onFocusChange?.(item.id);
|
|
550
|
+
},
|
|
551
|
+
onBlur: () => setFocusWithinId((current) => current === item.id ? void 0 : current),
|
|
552
|
+
onPointerEnter: () => setHoverId(item.id),
|
|
553
|
+
onPointerLeave: () => setHoverId((current) => current === item.id ? void 0 : current),
|
|
554
|
+
children: [
|
|
555
|
+
body,
|
|
556
|
+
item.inCycle && /* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__item-flag", "aria-hidden": "true", children: labels.cycle })
|
|
557
|
+
]
|
|
558
|
+
},
|
|
559
|
+
item.id
|
|
560
|
+
);
|
|
561
|
+
}) }),
|
|
562
|
+
/* @__PURE__ */ jsx("div", { hidden: true, children: layout.items.map((item, itemIndex) => {
|
|
563
|
+
const relations = item.node ? relationsOf.get(item.node.id) : void 0;
|
|
564
|
+
return relations ? /* @__PURE__ */ jsx("span", { id: `${describeId}-${itemIndex}`, children: relations }, item.id) : null;
|
|
565
|
+
}) }),
|
|
566
|
+
layout.items.filter((item) => item.expandedGroup).map((item) => {
|
|
567
|
+
const group = item.expandedGroup;
|
|
568
|
+
return /* @__PURE__ */ jsx(
|
|
569
|
+
"button",
|
|
570
|
+
{
|
|
571
|
+
type: "button",
|
|
572
|
+
className: "uix-relationship-graph__collapse",
|
|
573
|
+
"aria-expanded": "true",
|
|
574
|
+
style: { left: item.x, top: item.y - 26, width: item.width },
|
|
575
|
+
onClick: () => live.current.toggleCluster(group.id, group.id),
|
|
576
|
+
children: labels.collapseCluster(group.members.length, group.type)
|
|
577
|
+
},
|
|
578
|
+
`collapse:${group.id}`
|
|
579
|
+
);
|
|
580
|
+
})
|
|
581
|
+
] }), [layout, labels, selectedItemId, focusedId, relationsOf, dimmedNodeIds, highlightedNodeIds, conflictedNodeIds, showRoot, rootItemId, describeId, hintId, bounded, renderNode, renderCluster, nodeAriaLabel]);
|
|
582
|
+
const listLayer = useMemo(() => showList && /* @__PURE__ */ jsx(
|
|
583
|
+
EquivalentRelationshipList,
|
|
584
|
+
{
|
|
585
|
+
nodes: bounded.nodes,
|
|
586
|
+
edges: bounded.edges,
|
|
587
|
+
selectedId,
|
|
588
|
+
labels,
|
|
589
|
+
onSelect: (id) => {
|
|
590
|
+
const node = bounded.nodes.find((candidate) => candidate.id === id);
|
|
591
|
+
if (node) live.current.onSelect?.(node);
|
|
592
|
+
},
|
|
593
|
+
onExpandNeighbors,
|
|
594
|
+
onOpenDetails
|
|
595
|
+
}
|
|
596
|
+
), [showList, bounded, selectedId, labels, onExpandNeighbors, onOpenDetails]);
|
|
346
597
|
const control = (label, icon, onClick, { disabled = false, keys, ref } = {}) => /* @__PURE__ */ jsx(Tooltip, { label, placement: "top", ...keys ? { shortcut: keys } : {}, children: /* @__PURE__ */ jsx("button", { ref, type: "button", className: "uix-relationship-graph__control", "aria-label": label, onClick, disabled, children: icon }) });
|
|
347
598
|
return /* @__PURE__ */ jsxs(
|
|
348
599
|
"section",
|
|
@@ -381,6 +632,7 @@ function LayeredRelationshipGraph({
|
|
|
381
632
|
onPointerMove,
|
|
382
633
|
onPointerUp: onPointerEnd,
|
|
383
634
|
onPointerCancel: onPointerEnd,
|
|
635
|
+
onDragStart: (event) => event.preventDefault(),
|
|
384
636
|
...compact ? {
|
|
385
637
|
tabIndex: 0,
|
|
386
638
|
role: "group",
|
|
@@ -390,103 +642,12 @@ function LayeredRelationshipGraph({
|
|
|
390
642
|
} : {},
|
|
391
643
|
children: [
|
|
392
644
|
/* @__PURE__ */ jsxs("div", { className: "uix-relationship-graph__stage", style: stageStyle, "data-animate": animate || void 0, onTransitionEnd: () => setAnimate(false), children: [
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
const angle = edge.arrowAngle * 180 / Math.PI;
|
|
396
|
-
return /* @__PURE__ */ jsxs(
|
|
397
|
-
"g",
|
|
398
|
-
{
|
|
399
|
-
className: "uix-relationship-graph__link",
|
|
400
|
-
"data-kind": edge.kind,
|
|
401
|
-
"data-active": active || void 0,
|
|
402
|
-
"data-emphasis": edge.emphasis || void 0,
|
|
403
|
-
"data-conflicted": edge.edgeIds.some((id) => conflictedEdgeIds.has(id)) || void 0,
|
|
404
|
-
"data-dimmed": dimmedNodeIds.has(edge.source) && dimmedNodeIds.has(edge.target) || void 0,
|
|
405
|
-
children: [
|
|
406
|
-
/* @__PURE__ */ jsx("path", { d: edge.path }),
|
|
407
|
-
edge.arrow !== "none" && /* @__PURE__ */ jsx("polygon", { points: arrowPoints, transform: `translate(${edge.arrowX} ${edge.arrowY}) rotate(${angle})` }),
|
|
408
|
-
showLabel(edge) && /* @__PURE__ */ 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__ */ jsx("tspan", { x: edge.labelX, dy: index === 0 ? `${-(lines.length - 1) * 0.55}em` : "1.1em", children: line }, index)) })
|
|
409
|
-
]
|
|
410
|
-
},
|
|
411
|
-
edge.id
|
|
412
|
-
);
|
|
413
|
-
}) }),
|
|
414
|
-
layout.columns.map((column) => /* @__PURE__ */ jsx(
|
|
415
|
-
"div",
|
|
416
|
-
{
|
|
417
|
-
className: "uix-relationship-graph__column",
|
|
418
|
-
"aria-hidden": "true",
|
|
419
|
-
style: { left: column.x, width: layout.nodeWidth },
|
|
420
|
-
children: labels.column(column.depth, column.count)
|
|
421
|
-
},
|
|
422
|
-
column.depth
|
|
423
|
-
)),
|
|
424
|
-
/* @__PURE__ */ 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) => {
|
|
425
|
-
const selected = item.id === selectedItemId;
|
|
426
|
-
const dimmed = item.node ? dimmedNodeIds.has(item.node.id) : item.cluster.members.every((member) => dimmedNodeIds.has(member.id));
|
|
427
|
-
const body = item.cluster ? renderCluster?.(item.cluster) ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
428
|
-
/* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__item-label", children: labels.cluster(item.cluster.members.length, item.cluster.type, item.cluster.edgeLabel) }),
|
|
429
|
-
/* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__item-meta", children: labels.expandCluster })
|
|
430
|
-
] }) : renderNode?.(item.node, { selected, dimmed }) ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
431
|
-
/* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__item-label", children: item.node.label }),
|
|
432
|
-
(item.node.type || item.node.description) && /* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__item-meta", children: [item.node.type, item.node.description].filter(Boolean).join(" \xB7 ") })
|
|
433
|
-
] });
|
|
434
|
-
return /* @__PURE__ */ jsxs(
|
|
435
|
-
"button",
|
|
436
|
-
{
|
|
437
|
-
ref: (element) => {
|
|
438
|
-
if (element) itemRefs.current.set(item.id, element);
|
|
439
|
-
else itemRefs.current.delete(item.id);
|
|
440
|
-
},
|
|
441
|
-
type: "button",
|
|
442
|
-
className: "uix-relationship-graph__item",
|
|
443
|
-
"data-kind": item.kind,
|
|
444
|
-
"data-node-id": item.id,
|
|
445
|
-
"data-selected": selected || void 0,
|
|
446
|
-
"data-dimmed": dimmed || void 0,
|
|
447
|
-
"data-highlighted": item.node && highlightedNodeIds.has(item.node.id) || void 0,
|
|
448
|
-
"data-conflicted": item.node && conflictedNodeIds.has(item.node.id) || void 0,
|
|
449
|
-
"data-root": item.id === rootItemId || void 0,
|
|
450
|
-
style: { left: item.x, top: item.y, width: item.width, height: item.height },
|
|
451
|
-
tabIndex: item.id === focusedId ? 0 : -1,
|
|
452
|
-
"aria-label": labelFor(item),
|
|
453
|
-
...item.cluster ? { "aria-expanded": false } : { "aria-pressed": selected },
|
|
454
|
-
onClick: () => activate(item),
|
|
455
|
-
onKeyDown: (event) => onItemKeyDown(event, item),
|
|
456
|
-
onFocus: () => {
|
|
457
|
-
if (item.id === focusedId) return;
|
|
458
|
-
setLocalFocus(item.id);
|
|
459
|
-
onFocusChange?.(item.id);
|
|
460
|
-
},
|
|
461
|
-
onPointerEnter: () => setHoverId(item.id),
|
|
462
|
-
onPointerLeave: () => setHoverId((current) => current === item.id ? void 0 : current),
|
|
463
|
-
children: [
|
|
464
|
-
body,
|
|
465
|
-
item.inCycle && /* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__item-flag", "aria-hidden": "true", children: labels.cycle })
|
|
466
|
-
]
|
|
467
|
-
},
|
|
468
|
-
item.id
|
|
469
|
-
);
|
|
470
|
-
}) }),
|
|
471
|
-
layout.items.filter((item) => item.expandedGroup).map((item) => {
|
|
472
|
-
const group = item.expandedGroup;
|
|
473
|
-
return /* @__PURE__ */ jsx(
|
|
474
|
-
"button",
|
|
475
|
-
{
|
|
476
|
-
type: "button",
|
|
477
|
-
className: "uix-relationship-graph__collapse",
|
|
478
|
-
"aria-expanded": "true",
|
|
479
|
-
style: { left: item.x, top: item.y - 26, width: item.width },
|
|
480
|
-
onClick: () => toggleCluster(group.id, group.id),
|
|
481
|
-
children: labels.collapseCluster(group.members.length, group.type)
|
|
482
|
-
},
|
|
483
|
-
`collapse:${group.id}`
|
|
484
|
-
);
|
|
485
|
-
})
|
|
645
|
+
edgeLayer,
|
|
646
|
+
itemLayer
|
|
486
647
|
] }),
|
|
487
648
|
compact && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
488
649
|
wheelHint && /* @__PURE__ */ jsx("p", { className: "uix-relationship-graph__toast", role: "status", children: labels.navigationHint(modifier) }),
|
|
489
|
-
/* @__PURE__ */ jsxs("div", { className: "uix-relationship-graph__footer", children: [
|
|
650
|
+
/* @__PURE__ */ jsxs("div", { ref: footerRef, className: "uix-relationship-graph__footer", children: [
|
|
490
651
|
/* @__PURE__ */ jsx("p", { className: "uix-relationship-graph__hint", "aria-hidden": "true", children: labels.navigationHint(modifier) }),
|
|
491
652
|
/* @__PURE__ */ jsxs("div", { className: "uix-relationship-graph__controls", role: "group", "aria-label": labels.controls, children: [
|
|
492
653
|
/* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__zoom-level", "aria-live": "polite", children: labels.zoomLevel(zoomPercent) }),
|
|
@@ -508,22 +669,11 @@ function LayeredRelationshipGraph({
|
|
|
508
669
|
]
|
|
509
670
|
}
|
|
510
671
|
),
|
|
511
|
-
legend.length > 0 && /* @__PURE__ */ jsx("ul", { className: "uix-relationship-graph__legend", "aria-label": labels.legend, children: legend.map((entry) => /* @__PURE__ */
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
edges: bounded.edges,
|
|
517
|
-
selectedId,
|
|
518
|
-
labels,
|
|
519
|
-
onSelect: (id) => {
|
|
520
|
-
const node = bounded.nodes.find((candidate) => candidate.id === id);
|
|
521
|
-
if (node) onSelect?.(node);
|
|
522
|
-
},
|
|
523
|
-
onExpandNeighbors,
|
|
524
|
-
onOpenDetails
|
|
525
|
-
}
|
|
526
|
-
)
|
|
672
|
+
legend.length > 0 && /* @__PURE__ */ jsx("ul", { className: "uix-relationship-graph__legend", "aria-label": labels.legend, children: legend.map((entry) => /* @__PURE__ */ jsxs("li", { "data-type": entry.id, "data-tone": entry.tone, "data-shape": entry.shape, "data-variant": entry.variant, children: [
|
|
673
|
+
/* @__PURE__ */ jsx("span", { className: "uix-relationship-graph__legend-mark", "aria-hidden": "true" }),
|
|
674
|
+
entry.label
|
|
675
|
+
] }, entry.id)) }),
|
|
676
|
+
listLayer
|
|
527
677
|
]
|
|
528
678
|
}
|
|
529
679
|
);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useId, useState } from "react";
|
|
2
3
|
import { relationshipNeighbors } from "../relationship-graph-model.js";
|
|
4
|
+
const LISTED_NEIGHBOURS = 8;
|
|
3
5
|
function EquivalentRelationshipList({
|
|
4
6
|
nodes,
|
|
5
7
|
edges,
|
|
@@ -9,16 +11,41 @@ function EquivalentRelationshipList({
|
|
|
9
11
|
onExpandNeighbors,
|
|
10
12
|
onOpenDetails
|
|
11
13
|
}) {
|
|
14
|
+
const id = useId();
|
|
15
|
+
const [open, setOpen] = useState(() => /* @__PURE__ */ new Set());
|
|
12
16
|
const labelById = new Map(nodes.map((node) => [node.id, node.label]));
|
|
13
17
|
return /* @__PURE__ */ jsxs("div", { className: "uix-relationship-graph__list", role: "region", "aria-label": labels.list, children: [
|
|
14
18
|
/* @__PURE__ */ jsx("h3", { children: labels.listHeading }),
|
|
15
|
-
/* @__PURE__ */ jsx("ul", { children: nodes.map((node) => {
|
|
16
|
-
const neighbors = relationshipNeighbors(node.id, edges).map((
|
|
19
|
+
/* @__PURE__ */ jsx("ul", { children: nodes.map((node, index) => {
|
|
20
|
+
const neighbors = relationshipNeighbors(node.id, edges).map((neighbor) => labelById.get(neighbor) ?? neighbor);
|
|
21
|
+
const all = open.has(node.id);
|
|
22
|
+
const shown = all ? neighbors : neighbors.slice(0, LISTED_NEIGHBOURS);
|
|
23
|
+
const headingId = `${id}-${index}`;
|
|
17
24
|
return /* @__PURE__ */ jsxs("li", { "data-selected": selectedId === node.id || void 0, children: [
|
|
18
|
-
/* @__PURE__ */ jsxs("
|
|
19
|
-
/* @__PURE__ */
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
/* @__PURE__ */ jsxs("div", { className: "uix-relationship-graph__list-main", children: [
|
|
26
|
+
/* @__PURE__ */ jsxs("button", { type: "button", onClick: () => onSelect(node.id), "aria-pressed": selectedId === node.id, children: [
|
|
27
|
+
/* @__PURE__ */ jsx("strong", { children: node.label }),
|
|
28
|
+
node.type && /* @__PURE__ */ jsx("span", { children: node.type })
|
|
29
|
+
] }),
|
|
30
|
+
neighbors.length === 0 ? /* @__PURE__ */ jsx("p", { className: "uix-relationship-graph__list-none", children: labels.noConnections }) : /* @__PURE__ */ jsxs("div", { className: "uix-relationship-graph__list-relations", children: [
|
|
31
|
+
/* @__PURE__ */ jsx("span", { id: headingId, children: labels.connectedHeading }),
|
|
32
|
+
/* @__PURE__ */ jsx("ul", { "aria-labelledby": headingId, children: shown.map((name, at) => /* @__PURE__ */ jsx("li", { children: name }, at)) }),
|
|
33
|
+
neighbors.length > LISTED_NEIGHBOURS && /* @__PURE__ */ jsx(
|
|
34
|
+
"button",
|
|
35
|
+
{
|
|
36
|
+
type: "button",
|
|
37
|
+
className: "uix-btn uix-btn--link uix-relationship-graph__list-more",
|
|
38
|
+
"aria-expanded": all,
|
|
39
|
+
onClick: () => setOpen((previous) => {
|
|
40
|
+
const next = new Set(previous);
|
|
41
|
+
if (all) next.delete(node.id);
|
|
42
|
+
else next.add(node.id);
|
|
43
|
+
return next;
|
|
44
|
+
}),
|
|
45
|
+
children: all ? labels.showFewerRelations : labels.showAllRelations(neighbors.length)
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
] })
|
|
22
49
|
] }),
|
|
23
50
|
/* @__PURE__ */ jsxs("span", { className: "uix-relationship-graph__list-actions", children: [
|
|
24
51
|
onExpandNeighbors && /* @__PURE__ */ jsx("button", { type: "button", onClick: () => onExpandNeighbors(node), children: labels.expandNeighbors }),
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from "../rule-builder-model.js";
|
|
14
14
|
import { fillLabel } from "../fill-label.js";
|
|
15
15
|
import { useUixLabels } from "../labels-context.js";
|
|
16
|
+
import { Select } from "./Select.js";
|
|
16
17
|
const DEFAULT_RULE_BUILDER_LABELS = {
|
|
17
18
|
region: "Rule builder",
|
|
18
19
|
summary: "Rule summary",
|
|
@@ -94,10 +95,16 @@ function RuleGroupEditor({ group, depth, root, fields, operators, maxDepth, disa
|
|
|
94
95
|
combinator === "or" ? labels.any : labels.all
|
|
95
96
|
] }) : /* @__PURE__ */ jsxs("label", { children: [
|
|
96
97
|
labels.match,
|
|
97
|
-
/* @__PURE__ */
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
/* @__PURE__ */ jsx(
|
|
99
|
+
Select,
|
|
100
|
+
{
|
|
101
|
+
size: "sm",
|
|
102
|
+
value: group.combinator,
|
|
103
|
+
disabled,
|
|
104
|
+
options: [{ value: "and", label: labels.all }, { value: "or", label: labels.any }],
|
|
105
|
+
onValueChange: (next) => updateNode(group.id, (node) => ({ ...node, combinator: next }))
|
|
106
|
+
}
|
|
107
|
+
)
|
|
101
108
|
] }))
|
|
102
109
|
] }),
|
|
103
110
|
/* @__PURE__ */ jsx("div", { className: "uix-rule-builder__rows", children: group.conditions.map((node, index) => isRuleGroup(node) ? /* @__PURE__ */ jsxs("div", { className: "uix-rule-builder__nested", children: [
|
|
@@ -134,11 +141,27 @@ function ConditionRow({ labels, condition, fields, operators, disabled, onChange
|
|
|
134
141
|
return /* @__PURE__ */ jsxs("div", { className: "uix-rule-builder__condition", children: [
|
|
135
142
|
/* @__PURE__ */ jsxs("label", { children: [
|
|
136
143
|
/* @__PURE__ */ jsx("span", { className: "uix-visually-hidden", children: labels.field }),
|
|
137
|
-
/* @__PURE__ */ jsx(
|
|
144
|
+
/* @__PURE__ */ jsx(
|
|
145
|
+
Select,
|
|
146
|
+
{
|
|
147
|
+
value: condition.field,
|
|
148
|
+
disabled,
|
|
149
|
+
options: fields.map((item) => ({ value: item.id, label: item.label })),
|
|
150
|
+
onValueChange: (next) => setField(next)
|
|
151
|
+
}
|
|
152
|
+
)
|
|
138
153
|
] }),
|
|
139
154
|
/* @__PURE__ */ jsxs("label", { children: [
|
|
140
155
|
/* @__PURE__ */ jsx("span", { className: "uix-visually-hidden", children: labels.operator }),
|
|
141
|
-
/* @__PURE__ */ jsx(
|
|
156
|
+
/* @__PURE__ */ jsx(
|
|
157
|
+
Select,
|
|
158
|
+
{
|
|
159
|
+
value: condition.operator,
|
|
160
|
+
disabled,
|
|
161
|
+
options: availableOperators.map((item) => ({ value: item.id, label: item.label })),
|
|
162
|
+
onValueChange: (next) => onChange({ ...condition, operator: next })
|
|
163
|
+
}
|
|
164
|
+
)
|
|
142
165
|
] }),
|
|
143
166
|
operator?.requiresValue !== false && /* @__PURE__ */ jsx("div", { className: "uix-rule-builder__value", children: field?.renderValueEditor?.({ condition, onChange: (value) => onChange({ ...condition, value }), disabled }) ?? /* @__PURE__ */ 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": fillLabel(labels.valueFor, { field: field?.label ?? labels.itemCondition }) }) }),
|
|
144
167
|
controls
|
|
@@ -243,7 +266,16 @@ function RuleBuilder({
|
|
|
243
266
|
value.then.map((action, index) => {
|
|
244
267
|
const definition = actions.find((item) => item.id === action.type);
|
|
245
268
|
return /* @__PURE__ */ jsxs("div", { className: "uix-rule-builder__action", children: [
|
|
246
|
-
/* @__PURE__ */ jsx(
|
|
269
|
+
/* @__PURE__ */ jsx(
|
|
270
|
+
Select,
|
|
271
|
+
{
|
|
272
|
+
value: action.type,
|
|
273
|
+
disabled,
|
|
274
|
+
"aria-label": labels.actionType,
|
|
275
|
+
options: actions.map((item) => ({ value: item.id, label: item.label })),
|
|
276
|
+
onValueChange: (next) => updateActions(value.then.map((item) => item.id === action.id ? { ...item, type: next } : item))
|
|
277
|
+
}
|
|
278
|
+
),
|
|
247
279
|
definition?.renderParameters?.(action, (parameters) => updateActions(value.then.map((item) => item.id === action.id ? { ...item, parameters } : item)), disabled),
|
|
248
280
|
!disabled && /* @__PURE__ */ jsx(
|
|
249
281
|
RowControls,
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { S as SchedulingAgendaGroup, e as SchedulingCalendarLabels, i as SchedulingDatePart, d as SchedulingCalendarEntry, l as SchedulingMarker, f as SchedulingCalendarOverlay } from '../SchedulingCalendar-
|
|
3
|
+
import { S as SchedulingAgendaGroup, e as SchedulingCalendarLabels, i as SchedulingDatePart, d as SchedulingCalendarEntry, l as SchedulingMarker, f as SchedulingCalendarOverlay } from '../SchedulingCalendar-WWyFL3Eo.js';
|
|
4
4
|
import '../calendar-model.js';
|
|
5
5
|
import '../scheduling-calendar-model.js';
|
|
6
|
+
import './SchedulingResourceDay.js';
|
|
7
|
+
import '../scheduling-resource-model.js';
|
|
6
8
|
|
|
7
9
|
/** The height of one row of the virtualised agenda, in px. The stylesheet uses the same number. */
|
|
8
10
|
declare const AGENDA_VIRTUAL_ROW = 44;
|