@glyphjs/components 0.3.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +644 -148
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -26
- package/dist/index.d.ts +39 -26
- package/dist/index.js +645 -149
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { accordionSchema, annotateSchema, architectureSchema, calloutSchema, cardSchema, chartSchema, codediffSchema, comparisonSchema, equationSchema, filetreeSchema, flowchartSchema, formSchema, graphSchema, infographicSchema, kanbanSchema, kpiSchema, matrixSchema, mindmapSchema, pollSchema, quizSchema, rankerSchema, ratingSchema, relationSchema, sequenceSchema, sliderSchema, stepsSchema, tableSchema, tabsSchema, timelineSchema } from '@glyphjs/schemas';
|
|
2
2
|
import { RichText } from '@glyphjs/runtime';
|
|
3
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import { useRef, useState, useEffect, useCallback, useMemo } from 'react';
|
|
5
5
|
import * as d32 from 'd3';
|
|
6
6
|
import { scaleTime, scaleOrdinal } from 'd3';
|
|
@@ -50,7 +50,7 @@ function Callout({ data }) {
|
|
|
50
50
|
return /* @__PURE__ */ jsxs("div", { role: "note", "aria-label": CALLOUT_LABELS[type], style: containerStyle11, children: [
|
|
51
51
|
/* @__PURE__ */ jsx("span", { style: iconStyle, "aria-hidden": "true", children: CALLOUT_ICONS[type] }),
|
|
52
52
|
/* @__PURE__ */ jsxs("div", { style: bodyStyle3, children: [
|
|
53
|
-
title && /* @__PURE__ */ jsx("div", { style: titleStyle2, children: title }),
|
|
53
|
+
title && /* @__PURE__ */ jsx("div", { style: titleStyle2, children: /* @__PURE__ */ jsx(RichText, { content: title }) }),
|
|
54
54
|
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(RichText, { content }) })
|
|
55
55
|
] })
|
|
56
56
|
] });
|
|
@@ -62,6 +62,34 @@ var calloutDefinition = {
|
|
|
62
62
|
schema: calloutSchema,
|
|
63
63
|
render: Callout
|
|
64
64
|
};
|
|
65
|
+
|
|
66
|
+
// src/utils/inlineToText.ts
|
|
67
|
+
function inlineToText(content) {
|
|
68
|
+
if (typeof content === "string") {
|
|
69
|
+
return content;
|
|
70
|
+
}
|
|
71
|
+
return content.map((node) => {
|
|
72
|
+
switch (node.type) {
|
|
73
|
+
case "text":
|
|
74
|
+
return node.value;
|
|
75
|
+
case "strong":
|
|
76
|
+
case "emphasis":
|
|
77
|
+
case "delete":
|
|
78
|
+
case "link":
|
|
79
|
+
return inlineToText(node.children);
|
|
80
|
+
case "inlineCode":
|
|
81
|
+
return node.value;
|
|
82
|
+
case "image":
|
|
83
|
+
return node.alt ?? "";
|
|
84
|
+
case "break":
|
|
85
|
+
return "\n";
|
|
86
|
+
default:
|
|
87
|
+
return "";
|
|
88
|
+
}
|
|
89
|
+
}).join("");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// src/chart/render.ts
|
|
65
93
|
var DEFAULT_WIDTH = 600;
|
|
66
94
|
var DEFAULT_HEIGHT = 400;
|
|
67
95
|
var MARGIN = { top: 20, right: 30, bottom: 50, left: 60 };
|
|
@@ -109,7 +137,7 @@ function renderAxes(g, xScale, yScale, xAxisConfig, yAxisConfig, innerWidth, inn
|
|
|
109
137
|
}
|
|
110
138
|
xAxisG.selectAll("text, line, path").attr("fill", "var(--glyph-text, #1a2035)").attr("stroke", "var(--glyph-grid, #1a2035)");
|
|
111
139
|
if (xAxisConfig?.label) {
|
|
112
|
-
g.append("text").attr("class", "x-label").attr("x", innerWidth / 2).attr("y", innerHeight + MARGIN.bottom - 6).attr("text-anchor", "middle").attr("fill", "var(--glyph-text, #1a2035)").attr("font-size", "12px").text(xAxisConfig.label);
|
|
140
|
+
g.append("text").attr("class", "x-label").attr("x", innerWidth / 2).attr("y", innerHeight + MARGIN.bottom - 6).attr("text-anchor", "middle").attr("fill", "var(--glyph-text, #1a2035)").attr("font-size", "12px").text(inlineToText(xAxisConfig.label));
|
|
113
141
|
}
|
|
114
142
|
const yAxisG = g.append("g").attr("class", "y-axis");
|
|
115
143
|
yAxisG.call(
|
|
@@ -117,7 +145,7 @@ function renderAxes(g, xScale, yScale, xAxisConfig, yAxisConfig, innerWidth, inn
|
|
|
117
145
|
);
|
|
118
146
|
yAxisG.selectAll("text, line, path").attr("fill", "var(--glyph-text, #1a2035)").attr("stroke", "var(--glyph-grid, #1a2035)");
|
|
119
147
|
if (yAxisConfig?.label) {
|
|
120
|
-
g.append("text").attr("class", "y-label").attr("transform", "rotate(-90)").attr("x", -innerHeight / 2).attr("y", -MARGIN.left + 14).attr("text-anchor", "middle").attr("fill", "var(--glyph-text, #1a2035)").attr("font-size", "12px").text(yAxisConfig.label);
|
|
148
|
+
g.append("text").attr("class", "y-label").attr("transform", "rotate(-90)").attr("x", -innerHeight / 2).attr("y", -MARGIN.left + 14).attr("text-anchor", "middle").attr("fill", "var(--glyph-text, #1a2035)").attr("font-size", "12px").text(inlineToText(yAxisConfig.label));
|
|
121
149
|
}
|
|
122
150
|
}
|
|
123
151
|
function renderGridLines(g, yScale, innerWidth) {
|
|
@@ -173,7 +201,7 @@ function renderLegend(sel, series, marginLeft, marginTop, fontSize = "12px") {
|
|
|
173
201
|
const color3 = COLOR_SCHEME[i % COLOR_SCHEME.length] ?? "var(--glyph-text, #1a2035)";
|
|
174
202
|
const row = legendG.append("g").attr("transform", `translate(0,${String(i * 20)})`);
|
|
175
203
|
row.append("rect").attr("width", 14).attr("height", 14).attr("fill", color3).attr("rx", 2);
|
|
176
|
-
row.append("text").attr("x", 20).attr("y", 11).attr("fill", "var(--glyph-text, #1a2035)").attr("font-size", fontSize).text(s.name);
|
|
204
|
+
row.append("text").attr("x", 20).attr("y", 11).attr("fill", "var(--glyph-text, #1a2035)").attr("font-size", fontSize).text(inlineToText(s.name));
|
|
177
205
|
});
|
|
178
206
|
}
|
|
179
207
|
function ChartAccessibleTable({
|
|
@@ -204,10 +232,10 @@ function ChartAccessibleTable({
|
|
|
204
232
|
" chart data"
|
|
205
233
|
] }),
|
|
206
234
|
series.map((s, si) => /* @__PURE__ */ jsxs("tbody", { children: [
|
|
207
|
-
/* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("th", { colSpan: 2, children: s.name }) }),
|
|
235
|
+
/* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("th", { colSpan: 2, children: inlineToText(s.name) }) }),
|
|
208
236
|
/* @__PURE__ */ jsxs("tr", { children: [
|
|
209
|
-
/* @__PURE__ */ jsx("th", { children: xLabel
|
|
210
|
-
/* @__PURE__ */ jsx("th", { children: yLabel
|
|
237
|
+
/* @__PURE__ */ jsx("th", { children: xLabel ? inlineToText(xLabel) : xKey }),
|
|
238
|
+
/* @__PURE__ */ jsx("th", { children: yLabel ? inlineToText(yLabel) : yKey })
|
|
211
239
|
] }),
|
|
212
240
|
s.data.map((d, di) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
213
241
|
/* @__PURE__ */ jsx("td", { children: String(d[xKey] ?? "") }),
|
|
@@ -258,6 +286,7 @@ function renderAllSeries(g, type, series, scales, xKey, yKey, showTooltip, hideT
|
|
|
258
286
|
const { xScale, xScalePoint, yScale, innerHeight } = scales;
|
|
259
287
|
series.forEach((s, i) => {
|
|
260
288
|
const color3 = COLOR_SCHEME[i % COLOR_SCHEME.length] ?? "#333";
|
|
289
|
+
const seriesName = inlineToText(s.name);
|
|
261
290
|
switch (type) {
|
|
262
291
|
case "line":
|
|
263
292
|
renderLineSeries(
|
|
@@ -269,7 +298,7 @@ function renderAllSeries(g, type, series, scales, xKey, yKey, showTooltip, hideT
|
|
|
269
298
|
xKey,
|
|
270
299
|
color3,
|
|
271
300
|
i,
|
|
272
|
-
|
|
301
|
+
seriesName,
|
|
273
302
|
showTooltip,
|
|
274
303
|
hideTooltip
|
|
275
304
|
);
|
|
@@ -285,7 +314,7 @@ function renderAllSeries(g, type, series, scales, xKey, yKey, showTooltip, hideT
|
|
|
285
314
|
innerHeight,
|
|
286
315
|
color3,
|
|
287
316
|
i,
|
|
288
|
-
|
|
317
|
+
seriesName,
|
|
289
318
|
showTooltip,
|
|
290
319
|
hideTooltip
|
|
291
320
|
);
|
|
@@ -302,7 +331,7 @@ function renderAllSeries(g, type, series, scales, xKey, yKey, showTooltip, hideT
|
|
|
302
331
|
i,
|
|
303
332
|
series.length,
|
|
304
333
|
innerHeight,
|
|
305
|
-
|
|
334
|
+
seriesName,
|
|
306
335
|
showTooltip,
|
|
307
336
|
hideTooltip
|
|
308
337
|
);
|
|
@@ -315,7 +344,7 @@ function renderAllSeries(g, type, series, scales, xKey, yKey, showTooltip, hideT
|
|
|
315
344
|
xScalePoint,
|
|
316
345
|
yScale,
|
|
317
346
|
scales.innerWidth,
|
|
318
|
-
|
|
347
|
+
seriesName,
|
|
319
348
|
showTooltip,
|
|
320
349
|
hideTooltip
|
|
321
350
|
);
|
|
@@ -695,7 +724,7 @@ function TableHead({
|
|
|
695
724
|
whiteSpace: "nowrap"
|
|
696
725
|
},
|
|
697
726
|
children: [
|
|
698
|
-
col.label,
|
|
727
|
+
/* @__PURE__ */ jsx(RichText, { content: col.label }),
|
|
699
728
|
col.sortable ? sortIndicator(direction) : ""
|
|
700
729
|
]
|
|
701
730
|
},
|
|
@@ -1021,7 +1050,7 @@ function Tabs({ data, block, onInteraction }) {
|
|
|
1021
1050
|
outline: "revert",
|
|
1022
1051
|
outlineOffset: "2px"
|
|
1023
1052
|
},
|
|
1024
|
-
children: tab.label
|
|
1053
|
+
children: /* @__PURE__ */ jsx(RichText, { content: tab.label })
|
|
1025
1054
|
},
|
|
1026
1055
|
tabId
|
|
1027
1056
|
);
|
|
@@ -1047,7 +1076,7 @@ function Tabs({ data, block, onInteraction }) {
|
|
|
1047
1076
|
color: "var(--glyph-heading, #0a0e1a)",
|
|
1048
1077
|
lineHeight: 1.6
|
|
1049
1078
|
},
|
|
1050
|
-
children: tab.content
|
|
1079
|
+
children: /* @__PURE__ */ jsx(RichText, { content: tab.content })
|
|
1051
1080
|
},
|
|
1052
1081
|
panelId
|
|
1053
1082
|
);
|
|
@@ -1298,6 +1327,92 @@ var timelineDefinition = {
|
|
|
1298
1327
|
schema: timelineSchema,
|
|
1299
1328
|
render: Timeline
|
|
1300
1329
|
};
|
|
1330
|
+
|
|
1331
|
+
// src/utils/measureText.ts
|
|
1332
|
+
var measurementCache = /* @__PURE__ */ new WeakMap();
|
|
1333
|
+
function measurePlainText(text, style) {
|
|
1334
|
+
const canvas = document.createElement("canvas");
|
|
1335
|
+
const ctx = canvas.getContext("2d");
|
|
1336
|
+
if (!ctx) {
|
|
1337
|
+
const avgCharWidth = parseInt(style.fontSize) * 0.6;
|
|
1338
|
+
return {
|
|
1339
|
+
width: text.length * avgCharWidth,
|
|
1340
|
+
height: parseInt(style.fontSize) * 1.2
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
const fontWeight = style.fontWeight ?? "normal";
|
|
1344
|
+
ctx.font = `${fontWeight} ${style.fontSize} ${style.fontFamily}`;
|
|
1345
|
+
const metrics = ctx.measureText(text);
|
|
1346
|
+
const width = metrics.width;
|
|
1347
|
+
const height = parseInt(style.fontSize) * 1.2;
|
|
1348
|
+
return { width, height };
|
|
1349
|
+
}
|
|
1350
|
+
function measureHtmlText(content, style) {
|
|
1351
|
+
const cached = measurementCache.get(content);
|
|
1352
|
+
if (cached) {
|
|
1353
|
+
return cached;
|
|
1354
|
+
}
|
|
1355
|
+
const container = document.createElement("div");
|
|
1356
|
+
container.style.position = "absolute";
|
|
1357
|
+
container.style.visibility = "hidden";
|
|
1358
|
+
container.style.left = "-9999px";
|
|
1359
|
+
container.style.top = "-9999px";
|
|
1360
|
+
container.style.fontSize = style.fontSize;
|
|
1361
|
+
container.style.fontFamily = style.fontFamily;
|
|
1362
|
+
container.style.fontWeight = style.fontWeight ?? "normal";
|
|
1363
|
+
container.style.whiteSpace = "pre-wrap";
|
|
1364
|
+
container.style.wordBreak = "break-word";
|
|
1365
|
+
if (style.maxWidth) {
|
|
1366
|
+
container.style.maxWidth = `${style.maxWidth}px`;
|
|
1367
|
+
}
|
|
1368
|
+
container.innerHTML = inlineNodesToHtml(content);
|
|
1369
|
+
document.body.appendChild(container);
|
|
1370
|
+
const rect = container.getBoundingClientRect();
|
|
1371
|
+
const dimensions = {
|
|
1372
|
+
width: Math.ceil(rect.width),
|
|
1373
|
+
height: Math.ceil(rect.height)
|
|
1374
|
+
};
|
|
1375
|
+
document.body.removeChild(container);
|
|
1376
|
+
measurementCache.set(content, dimensions);
|
|
1377
|
+
return dimensions;
|
|
1378
|
+
}
|
|
1379
|
+
function inlineNodesToHtml(nodes) {
|
|
1380
|
+
return nodes.map((node) => {
|
|
1381
|
+
switch (node.type) {
|
|
1382
|
+
case "text":
|
|
1383
|
+
return escapeHtml(node.value);
|
|
1384
|
+
case "strong":
|
|
1385
|
+
return `<strong>${inlineNodesToHtml(node.children)}</strong>`;
|
|
1386
|
+
case "emphasis":
|
|
1387
|
+
return `<em>${inlineNodesToHtml(node.children)}</em>`;
|
|
1388
|
+
case "delete":
|
|
1389
|
+
return `<del>${inlineNodesToHtml(node.children)}</del>`;
|
|
1390
|
+
case "inlineCode":
|
|
1391
|
+
return `<code>${escapeHtml(node.value)}</code>`;
|
|
1392
|
+
case "link":
|
|
1393
|
+
return `<a href="${escapeHtml(node.url)}">${inlineNodesToHtml(node.children)}</a>`;
|
|
1394
|
+
case "image":
|
|
1395
|
+
return `<img src="${escapeHtml(node.src)}" alt="${escapeHtml(node.alt ?? "")}" />`;
|
|
1396
|
+
case "break":
|
|
1397
|
+
return "<br />";
|
|
1398
|
+
default:
|
|
1399
|
+
return "";
|
|
1400
|
+
}
|
|
1401
|
+
}).join("");
|
|
1402
|
+
}
|
|
1403
|
+
function escapeHtml(str) {
|
|
1404
|
+
const div = document.createElement("div");
|
|
1405
|
+
div.textContent = str;
|
|
1406
|
+
return div.innerHTML;
|
|
1407
|
+
}
|
|
1408
|
+
function measureText(content, style) {
|
|
1409
|
+
if (typeof content === "string") {
|
|
1410
|
+
return measurePlainText(content, style);
|
|
1411
|
+
}
|
|
1412
|
+
return measureHtmlText(content, style);
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
// src/graph/layout.ts
|
|
1301
1416
|
var RANKDIR_MAP = {
|
|
1302
1417
|
"top-down": "TB",
|
|
1303
1418
|
"left-right": "LR",
|
|
@@ -1320,10 +1435,17 @@ function computeDagreLayout(nodes, edges, direction = "top-down") {
|
|
|
1320
1435
|
});
|
|
1321
1436
|
g.setDefaultEdgeLabel(() => ({}));
|
|
1322
1437
|
for (const node of nodes) {
|
|
1438
|
+
const labelDimensions = measureText(node.label, {
|
|
1439
|
+
fontSize: "13px",
|
|
1440
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
1441
|
+
maxWidth: 200
|
|
1442
|
+
});
|
|
1443
|
+
const nodeWidth = Math.max(120, Math.min(250, labelDimensions.width + 40));
|
|
1444
|
+
const nodeHeight = Math.max(40, labelDimensions.height + 20);
|
|
1323
1445
|
g.setNode(node.id, {
|
|
1324
1446
|
label: node.label,
|
|
1325
|
-
width:
|
|
1326
|
-
height:
|
|
1447
|
+
width: nodeWidth,
|
|
1448
|
+
height: nodeHeight
|
|
1327
1449
|
});
|
|
1328
1450
|
}
|
|
1329
1451
|
for (const edge of edges) {
|
|
@@ -1430,6 +1552,326 @@ function computeForceLayout(nodes, edges) {
|
|
|
1430
1552
|
height: maxY + LAYOUT_PADDING
|
|
1431
1553
|
};
|
|
1432
1554
|
}
|
|
1555
|
+
function useZoomInteraction({
|
|
1556
|
+
svgRef,
|
|
1557
|
+
rootRef,
|
|
1558
|
+
interactionMode
|
|
1559
|
+
}) {
|
|
1560
|
+
const [isActive, setIsActive] = useState(interactionMode === "always");
|
|
1561
|
+
const [hasAttemptedScroll, setHasAttemptedScroll] = useState(false);
|
|
1562
|
+
const containerRef = useRef(null);
|
|
1563
|
+
useEffect(() => {
|
|
1564
|
+
setIsActive(interactionMode === "always");
|
|
1565
|
+
setHasAttemptedScroll(false);
|
|
1566
|
+
}, [interactionMode]);
|
|
1567
|
+
const filterFunction = useCallback(
|
|
1568
|
+
(event) => {
|
|
1569
|
+
if (interactionMode === "always") {
|
|
1570
|
+
return true;
|
|
1571
|
+
}
|
|
1572
|
+
if (interactionMode === "modifier-key") {
|
|
1573
|
+
if (event.type === "mousedown") return true;
|
|
1574
|
+
if (event.type === "wheel") {
|
|
1575
|
+
const wheelEvent = event;
|
|
1576
|
+
const hasModifier = wheelEvent.altKey;
|
|
1577
|
+
if (!hasModifier && !hasAttemptedScroll) {
|
|
1578
|
+
setHasAttemptedScroll(true);
|
|
1579
|
+
setTimeout(() => setHasAttemptedScroll(false), 3e3);
|
|
1580
|
+
}
|
|
1581
|
+
return hasModifier;
|
|
1582
|
+
}
|
|
1583
|
+
return true;
|
|
1584
|
+
}
|
|
1585
|
+
if (interactionMode === "click-to-activate") {
|
|
1586
|
+
return isActive;
|
|
1587
|
+
}
|
|
1588
|
+
return true;
|
|
1589
|
+
},
|
|
1590
|
+
[interactionMode, isActive, hasAttemptedScroll]
|
|
1591
|
+
);
|
|
1592
|
+
useEffect(() => {
|
|
1593
|
+
if (interactionMode !== "modifier-key" || !svgRef.current) return;
|
|
1594
|
+
const svg = svgRef.current;
|
|
1595
|
+
const container = svg.parentElement;
|
|
1596
|
+
if (!container) return;
|
|
1597
|
+
const handleWheel = (event) => {
|
|
1598
|
+
const target = event.target;
|
|
1599
|
+
if (event.altKey && svg.contains(target)) {
|
|
1600
|
+
event.preventDefault();
|
|
1601
|
+
event.stopPropagation();
|
|
1602
|
+
}
|
|
1603
|
+
};
|
|
1604
|
+
container.addEventListener("wheel", handleWheel, { passive: false, capture: true });
|
|
1605
|
+
return () => {
|
|
1606
|
+
container.removeEventListener("wheel", handleWheel, { capture: true });
|
|
1607
|
+
};
|
|
1608
|
+
}, [interactionMode, svgRef]);
|
|
1609
|
+
const zoomBehavior = useMemo(() => {
|
|
1610
|
+
const zoom3 = d32.zoom().scaleExtent([0.1, 4]);
|
|
1611
|
+
if (typeof zoom3.filter === "function") {
|
|
1612
|
+
zoom3.filter(filterFunction);
|
|
1613
|
+
}
|
|
1614
|
+
zoom3.on("zoom", (event) => {
|
|
1615
|
+
if (rootRef.current) {
|
|
1616
|
+
d32.select(rootRef.current).attr("transform", event.transform.toString());
|
|
1617
|
+
}
|
|
1618
|
+
});
|
|
1619
|
+
return zoom3;
|
|
1620
|
+
}, [filterFunction, rootRef]);
|
|
1621
|
+
const handleActivate = useCallback(() => {
|
|
1622
|
+
if (interactionMode === "click-to-activate") {
|
|
1623
|
+
setIsActive(true);
|
|
1624
|
+
}
|
|
1625
|
+
}, [interactionMode]);
|
|
1626
|
+
useEffect(() => {
|
|
1627
|
+
if (interactionMode !== "click-to-activate" || !isActive) return;
|
|
1628
|
+
const handleKeyDown = (e) => {
|
|
1629
|
+
if (e.key === "Escape") {
|
|
1630
|
+
setIsActive(false);
|
|
1631
|
+
}
|
|
1632
|
+
};
|
|
1633
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
1634
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1635
|
+
}, [interactionMode, isActive]);
|
|
1636
|
+
useEffect(() => {
|
|
1637
|
+
if (interactionMode !== "click-to-activate" || !isActive) return;
|
|
1638
|
+
const handleClickOutside = (e) => {
|
|
1639
|
+
const container = svgRef.current?.parentElement;
|
|
1640
|
+
if (container && !container.contains(e.target)) {
|
|
1641
|
+
setIsActive(false);
|
|
1642
|
+
}
|
|
1643
|
+
};
|
|
1644
|
+
document.addEventListener("click", handleClickOutside, true);
|
|
1645
|
+
return () => document.removeEventListener("click", handleClickOutside, true);
|
|
1646
|
+
}, [interactionMode, isActive, svgRef]);
|
|
1647
|
+
useEffect(() => {
|
|
1648
|
+
if (svgRef.current) {
|
|
1649
|
+
containerRef.current = svgRef.current.parentElement;
|
|
1650
|
+
}
|
|
1651
|
+
}, [svgRef]);
|
|
1652
|
+
const overlayProps = useMemo(() => {
|
|
1653
|
+
if (interactionMode === "always") return null;
|
|
1654
|
+
if (interactionMode === "modifier-key" && !hasAttemptedScroll) return null;
|
|
1655
|
+
if (interactionMode === "click-to-activate" && isActive) return null;
|
|
1656
|
+
return {
|
|
1657
|
+
mode: interactionMode,
|
|
1658
|
+
isActive,
|
|
1659
|
+
onActivate: handleActivate,
|
|
1660
|
+
width: "100%",
|
|
1661
|
+
height: "100%"
|
|
1662
|
+
};
|
|
1663
|
+
}, [interactionMode, isActive, hasAttemptedScroll, handleActivate]);
|
|
1664
|
+
const zoomIn = useCallback(() => {
|
|
1665
|
+
if (!svgRef.current) return;
|
|
1666
|
+
d32.select(svgRef.current).transition().duration(300).call(zoomBehavior.scaleBy, 1.3);
|
|
1667
|
+
}, [svgRef, zoomBehavior]);
|
|
1668
|
+
const zoomOut = useCallback(() => {
|
|
1669
|
+
if (!svgRef.current) return;
|
|
1670
|
+
d32.select(svgRef.current).transition().duration(300).call(zoomBehavior.scaleBy, 1 / 1.3);
|
|
1671
|
+
}, [svgRef, zoomBehavior]);
|
|
1672
|
+
const resetZoom = useCallback(() => {
|
|
1673
|
+
if (!svgRef.current) return;
|
|
1674
|
+
d32.select(svgRef.current).transition().duration(300).call(zoomBehavior.transform, d32.zoomIdentity);
|
|
1675
|
+
}, [svgRef, zoomBehavior]);
|
|
1676
|
+
return {
|
|
1677
|
+
isActive,
|
|
1678
|
+
overlayProps,
|
|
1679
|
+
zoomBehavior,
|
|
1680
|
+
zoomIn,
|
|
1681
|
+
zoomOut,
|
|
1682
|
+
resetZoom
|
|
1683
|
+
};
|
|
1684
|
+
}
|
|
1685
|
+
function InteractionOverlay({
|
|
1686
|
+
mode,
|
|
1687
|
+
isActive,
|
|
1688
|
+
onActivate,
|
|
1689
|
+
width,
|
|
1690
|
+
height
|
|
1691
|
+
}) {
|
|
1692
|
+
if (mode === "modifier-key") {
|
|
1693
|
+
return /* @__PURE__ */ jsx(
|
|
1694
|
+
"div",
|
|
1695
|
+
{
|
|
1696
|
+
className: "glyph-interaction-overlay",
|
|
1697
|
+
style: {
|
|
1698
|
+
...OVERLAY_BASE_STYLE,
|
|
1699
|
+
width,
|
|
1700
|
+
height,
|
|
1701
|
+
pointerEvents: "none"
|
|
1702
|
+
},
|
|
1703
|
+
"aria-hidden": "true",
|
|
1704
|
+
children: /* @__PURE__ */ jsx("div", { style: TOOLTIP_STYLE, children: /* @__PURE__ */ jsx("span", { style: TOOLTIP_TEXT_STYLE, children: "Alt + scroll to zoom" }) })
|
|
1705
|
+
}
|
|
1706
|
+
);
|
|
1707
|
+
}
|
|
1708
|
+
if (mode === "click-to-activate" && !isActive) {
|
|
1709
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1710
|
+
/* @__PURE__ */ jsx(
|
|
1711
|
+
"div",
|
|
1712
|
+
{
|
|
1713
|
+
className: "glyph-interaction-overlay",
|
|
1714
|
+
style: {
|
|
1715
|
+
...OVERLAY_BASE_STYLE,
|
|
1716
|
+
...ACTIVATION_OVERLAY_STYLE,
|
|
1717
|
+
width,
|
|
1718
|
+
height
|
|
1719
|
+
},
|
|
1720
|
+
onClick: onActivate,
|
|
1721
|
+
role: "button",
|
|
1722
|
+
tabIndex: 0,
|
|
1723
|
+
"aria-label": "Click to activate graph interaction",
|
|
1724
|
+
onKeyDown: (e) => {
|
|
1725
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1726
|
+
e.preventDefault();
|
|
1727
|
+
onActivate();
|
|
1728
|
+
}
|
|
1729
|
+
},
|
|
1730
|
+
children: /* @__PURE__ */ jsx("div", { style: ACTIVATION_TEXT_STYLE, children: "Click to interact" })
|
|
1731
|
+
}
|
|
1732
|
+
),
|
|
1733
|
+
/* @__PURE__ */ jsx("div", { style: SR_ONLY_STYLE, role: "status", "aria-live": "polite", "aria-atomic": "true", children: "Graph interaction inactive. Click to activate." })
|
|
1734
|
+
] });
|
|
1735
|
+
}
|
|
1736
|
+
if (mode === "click-to-activate" && isActive) {
|
|
1737
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1738
|
+
/* @__PURE__ */ jsx(
|
|
1739
|
+
"div",
|
|
1740
|
+
{
|
|
1741
|
+
style: {
|
|
1742
|
+
...OVERLAY_BASE_STYLE,
|
|
1743
|
+
width,
|
|
1744
|
+
height,
|
|
1745
|
+
pointerEvents: "none",
|
|
1746
|
+
border: "2px solid var(--glyph-interaction-active-border, #0a9d7c)",
|
|
1747
|
+
borderRadius: "4px"
|
|
1748
|
+
},
|
|
1749
|
+
"aria-hidden": "true"
|
|
1750
|
+
}
|
|
1751
|
+
),
|
|
1752
|
+
/* @__PURE__ */ jsx("div", { style: SR_ONLY_STYLE, role: "status", "aria-live": "polite", "aria-atomic": "true", children: "Graph interaction active. Press Escape to deactivate." })
|
|
1753
|
+
] });
|
|
1754
|
+
}
|
|
1755
|
+
return /* @__PURE__ */ jsx(Fragment, {});
|
|
1756
|
+
}
|
|
1757
|
+
var OVERLAY_BASE_STYLE = {
|
|
1758
|
+
position: "absolute",
|
|
1759
|
+
top: 0,
|
|
1760
|
+
left: 0,
|
|
1761
|
+
display: "flex",
|
|
1762
|
+
alignItems: "center",
|
|
1763
|
+
justifyContent: "center",
|
|
1764
|
+
zIndex: 10
|
|
1765
|
+
};
|
|
1766
|
+
var TOOLTIP_STYLE = {
|
|
1767
|
+
position: "absolute",
|
|
1768
|
+
bottom: "12px",
|
|
1769
|
+
right: "12px",
|
|
1770
|
+
padding: "6px 10px",
|
|
1771
|
+
backgroundColor: "var(--glyph-interaction-tooltip-bg, rgba(26, 32, 53, 0.9))",
|
|
1772
|
+
color: "var(--glyph-interaction-tooltip-text, #f4f6fa)",
|
|
1773
|
+
borderRadius: "4px",
|
|
1774
|
+
fontSize: "12px",
|
|
1775
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
1776
|
+
fontWeight: 500,
|
|
1777
|
+
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
|
|
1778
|
+
pointerEvents: "none"
|
|
1779
|
+
};
|
|
1780
|
+
var TOOLTIP_TEXT_STYLE = {
|
|
1781
|
+
display: "flex",
|
|
1782
|
+
alignItems: "center",
|
|
1783
|
+
gap: "4px"
|
|
1784
|
+
};
|
|
1785
|
+
var ACTIVATION_OVERLAY_STYLE = {
|
|
1786
|
+
backgroundColor: "var(--glyph-interaction-overlay-bg, rgba(244, 246, 250, 0.8))",
|
|
1787
|
+
cursor: "pointer",
|
|
1788
|
+
transition: "background-color 0.2s ease"
|
|
1789
|
+
};
|
|
1790
|
+
var ACTIVATION_TEXT_STYLE = {
|
|
1791
|
+
padding: "12px 20px",
|
|
1792
|
+
backgroundColor: "var(--glyph-interaction-tooltip-bg, rgba(26, 32, 53, 0.9))",
|
|
1793
|
+
color: "var(--glyph-interaction-tooltip-text, #f4f6fa)",
|
|
1794
|
+
borderRadius: "6px",
|
|
1795
|
+
fontSize: "14px",
|
|
1796
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
1797
|
+
fontWeight: 500,
|
|
1798
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.2)"
|
|
1799
|
+
};
|
|
1800
|
+
var SR_ONLY_STYLE = {
|
|
1801
|
+
position: "absolute",
|
|
1802
|
+
width: "1px",
|
|
1803
|
+
height: "1px",
|
|
1804
|
+
padding: 0,
|
|
1805
|
+
margin: "-1px",
|
|
1806
|
+
overflow: "hidden",
|
|
1807
|
+
clip: "rect(0, 0, 0, 0)",
|
|
1808
|
+
whiteSpace: "nowrap",
|
|
1809
|
+
border: 0
|
|
1810
|
+
};
|
|
1811
|
+
function ZoomControls({ onZoomIn, onZoomOut, onReset }) {
|
|
1812
|
+
return /* @__PURE__ */ jsxs("div", { style: CONTROLS_CONTAINER_STYLE, children: [
|
|
1813
|
+
/* @__PURE__ */ jsx(
|
|
1814
|
+
"button",
|
|
1815
|
+
{
|
|
1816
|
+
onClick: onZoomIn,
|
|
1817
|
+
style: BUTTON_STYLE,
|
|
1818
|
+
"aria-label": "Zoom in",
|
|
1819
|
+
title: "Zoom in",
|
|
1820
|
+
type: "button",
|
|
1821
|
+
children: /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", children: [
|
|
1822
|
+
/* @__PURE__ */ jsx("line", { x1: "8", y1: "4", x2: "8", y2: "12", strokeWidth: "2" }),
|
|
1823
|
+
/* @__PURE__ */ jsx("line", { x1: "4", y1: "8", x2: "12", y2: "8", strokeWidth: "2" })
|
|
1824
|
+
] })
|
|
1825
|
+
}
|
|
1826
|
+
),
|
|
1827
|
+
/* @__PURE__ */ jsx(
|
|
1828
|
+
"button",
|
|
1829
|
+
{
|
|
1830
|
+
onClick: onZoomOut,
|
|
1831
|
+
style: BUTTON_STYLE,
|
|
1832
|
+
"aria-label": "Zoom out",
|
|
1833
|
+
title: "Zoom out",
|
|
1834
|
+
type: "button",
|
|
1835
|
+
children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", children: /* @__PURE__ */ jsx("line", { x1: "4", y1: "8", x2: "12", y2: "8", strokeWidth: "2" }) })
|
|
1836
|
+
}
|
|
1837
|
+
),
|
|
1838
|
+
/* @__PURE__ */ jsx(
|
|
1839
|
+
"button",
|
|
1840
|
+
{
|
|
1841
|
+
onClick: onReset,
|
|
1842
|
+
style: BUTTON_STYLE,
|
|
1843
|
+
"aria-label": "Reset zoom",
|
|
1844
|
+
title: "Reset zoom",
|
|
1845
|
+
type: "button",
|
|
1846
|
+
children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", children: /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "10", height: "10", strokeWidth: "2", rx: "1" }) })
|
|
1847
|
+
}
|
|
1848
|
+
)
|
|
1849
|
+
] });
|
|
1850
|
+
}
|
|
1851
|
+
var CONTROLS_CONTAINER_STYLE = {
|
|
1852
|
+
position: "absolute",
|
|
1853
|
+
top: "12px",
|
|
1854
|
+
right: "12px",
|
|
1855
|
+
display: "flex",
|
|
1856
|
+
flexDirection: "column",
|
|
1857
|
+
gap: "4px",
|
|
1858
|
+
zIndex: 10
|
|
1859
|
+
};
|
|
1860
|
+
var BUTTON_STYLE = {
|
|
1861
|
+
width: "32px",
|
|
1862
|
+
height: "32px",
|
|
1863
|
+
padding: "0",
|
|
1864
|
+
display: "flex",
|
|
1865
|
+
alignItems: "center",
|
|
1866
|
+
justifyContent: "center",
|
|
1867
|
+
backgroundColor: "var(--glyph-surface-raised, #f4f6fa)",
|
|
1868
|
+
border: "1px solid var(--glyph-border, #d0d8e4)",
|
|
1869
|
+
borderRadius: "4px",
|
|
1870
|
+
color: "var(--glyph-text, #1a2035)",
|
|
1871
|
+
cursor: "pointer",
|
|
1872
|
+
transition: "all 0.2s ease",
|
|
1873
|
+
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)"
|
|
1874
|
+
};
|
|
1433
1875
|
var GROUP_PALETTE = [
|
|
1434
1876
|
"#00d4aa",
|
|
1435
1877
|
// cyan-green
|
|
@@ -1476,7 +1918,7 @@ function getThemeVar(container, varName, fallback) {
|
|
|
1476
1918
|
return getComputedStyle(container).getPropertyValue(varName).trim() || fallback;
|
|
1477
1919
|
}
|
|
1478
1920
|
var ARROW_MARKER_ID = "glyph-graph-arrowhead";
|
|
1479
|
-
function renderGraph(svgElement, layout, groupIndex, outgoingRefs, onNavigate, onNodeClick) {
|
|
1921
|
+
function renderGraph(svgElement, layout, groupIndex, outgoingRefs, onNavigate, zoomBehavior, onNodeClick) {
|
|
1480
1922
|
const svg = d32.select(svgElement);
|
|
1481
1923
|
svg.selectAll("*").remove();
|
|
1482
1924
|
const width = Math.max(layout.width, 200);
|
|
@@ -1489,9 +1931,6 @@ function renderGraph(svgElement, layout, groupIndex, outgoingRefs, onNavigate, o
|
|
|
1489
1931
|
const nodeStrokeWidth = getThemeVar(container, "--glyph-node-stroke-width", "1.5");
|
|
1490
1932
|
const nodeFillOpacity = getThemeVar(container, "--glyph-node-fill-opacity", "0.85");
|
|
1491
1933
|
const root = svg.append("g").attr("class", "glyph-graph-root");
|
|
1492
|
-
const zoomBehavior = d32.zoom().scaleExtent([0.1, 4]).on("zoom", (event) => {
|
|
1493
|
-
root.attr("transform", event.transform.toString());
|
|
1494
|
-
});
|
|
1495
1934
|
svg.call(zoomBehavior);
|
|
1496
1935
|
const navigableNodes = /* @__PURE__ */ new Set();
|
|
1497
1936
|
const refByAnchor = /* @__PURE__ */ new Map();
|
|
@@ -1509,7 +1948,7 @@ function renderGraph(svgElement, layout, groupIndex, outgoingRefs, onNavigate, o
|
|
|
1509
1948
|
if (edge.label) {
|
|
1510
1949
|
const mid = edge.points[Math.floor(edge.points.length / 2)];
|
|
1511
1950
|
if (mid) {
|
|
1512
|
-
edgeG.append("text").attr("x", mid.x).attr("y", mid.y - 8).attr("text-anchor", "middle").attr("font-size", "11px").attr("fill", "var(--glyph-edge-color, #6b7a94)").text(edge.label);
|
|
1951
|
+
edgeG.append("text").attr("x", mid.x).attr("y", mid.y - 8).attr("text-anchor", "middle").attr("font-size", "11px").attr("fill", "var(--glyph-edge-color, #6b7a94)").text(inlineToText(edge.label));
|
|
1513
1952
|
}
|
|
1514
1953
|
}
|
|
1515
1954
|
}
|
|
@@ -1526,7 +1965,7 @@ function renderGraph(svgElement, layout, groupIndex, outgoingRefs, onNavigate, o
|
|
|
1526
1965
|
} else {
|
|
1527
1966
|
nodeG.append("rect").attr("x", nodeX).attr("y", nodeY).attr("width", node.width).attr("height", node.height).attr("rx", nodeRadius).attr("ry", nodeRadius).attr("fill", node.style?.["fill"] ?? color3).attr("stroke", node.style?.["stroke"] ?? defaultStroke).attr("stroke-width", node.style?.["stroke-width"] ?? nodeStrokeWidth).attr("opacity", nodeFillOpacity);
|
|
1528
1967
|
}
|
|
1529
|
-
nodeG.append("text").attr("x", node.x).attr("y", node.y).attr("dy", "0.35em").attr("text-anchor", "middle").attr("font-size", "13px").attr("font-family", "Inter, system-ui, sans-serif").attr("fill", "var(--glyph-node-label-color, #fff)").attr("pointer-events", "none").text(node.label);
|
|
1968
|
+
nodeG.append("text").attr("x", node.x).attr("y", node.y).attr("dy", "0.35em").attr("text-anchor", "middle").attr("font-size", "13px").attr("font-family", "Inter, system-ui, sans-serif").attr("fill", "var(--glyph-node-label-color, #fff)").attr("pointer-events", "none").text(inlineToText(node.label));
|
|
1530
1969
|
if (isNavigable || onNodeClick) {
|
|
1531
1970
|
nodeG.attr("cursor", "pointer");
|
|
1532
1971
|
nodeG.on("click", () => {
|
|
@@ -1534,7 +1973,7 @@ function renderGraph(svgElement, layout, groupIndex, outgoingRefs, onNavigate, o
|
|
|
1534
1973
|
const ref = refByAnchor.get(node.id);
|
|
1535
1974
|
if (ref) onNavigate(ref);
|
|
1536
1975
|
}
|
|
1537
|
-
onNodeClick?.(node.id, node.label);
|
|
1976
|
+
onNodeClick?.(node.id, inlineToText(node.label));
|
|
1538
1977
|
});
|
|
1539
1978
|
}
|
|
1540
1979
|
}
|
|
@@ -1548,6 +1987,7 @@ function Graph({
|
|
|
1548
1987
|
container
|
|
1549
1988
|
}) {
|
|
1550
1989
|
const svgRef = useRef(null);
|
|
1990
|
+
const rootRef = useRef(null);
|
|
1551
1991
|
const groupIndex = useRef(/* @__PURE__ */ new Map());
|
|
1552
1992
|
const layoutResult = useMemo(() => {
|
|
1553
1993
|
const direction = resolveLayout(data);
|
|
@@ -1556,6 +1996,12 @@ function Graph({
|
|
|
1556
1996
|
}
|
|
1557
1997
|
return computeDagreLayout(data.nodes, data.edges, direction);
|
|
1558
1998
|
}, [data]);
|
|
1999
|
+
const { overlayProps, zoomBehavior, zoomIn, zoomOut, resetZoom } = useZoomInteraction({
|
|
2000
|
+
svgRef,
|
|
2001
|
+
rootRef,
|
|
2002
|
+
interactionMode: data.interactionMode ?? "modifier-key",
|
|
2003
|
+
blockId: block.id
|
|
2004
|
+
});
|
|
1559
2005
|
const handleNodeClick = useMemo(() => {
|
|
1560
2006
|
if (!onInteraction) return void 0;
|
|
1561
2007
|
return (nodeId, nodeLabel) => {
|
|
@@ -1576,27 +2022,36 @@ function Graph({
|
|
|
1576
2022
|
groupIndex.current,
|
|
1577
2023
|
outgoingRefs,
|
|
1578
2024
|
onNavigate,
|
|
2025
|
+
zoomBehavior,
|
|
1579
2026
|
handleNodeClick
|
|
1580
2027
|
);
|
|
1581
|
-
|
|
2028
|
+
const rootElement = svgRef.current.querySelector(".glyph-graph-root");
|
|
2029
|
+
if (rootElement) {
|
|
2030
|
+
rootRef.current = rootElement;
|
|
2031
|
+
}
|
|
2032
|
+
}, [layoutResult, outgoingRefs, onNavigate, zoomBehavior, handleNodeClick]);
|
|
1582
2033
|
const ariaLabel = `${data.type} graph with ${data.nodes.length} nodes and ${data.edges.length} edges`;
|
|
1583
2034
|
return /* @__PURE__ */ jsxs("div", { className: "glyph-graph-container", children: [
|
|
1584
|
-
/* @__PURE__ */
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
2035
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
2036
|
+
/* @__PURE__ */ jsx(
|
|
2037
|
+
"svg",
|
|
2038
|
+
{
|
|
2039
|
+
ref: svgRef,
|
|
2040
|
+
role: "img",
|
|
2041
|
+
"aria-label": ariaLabel,
|
|
2042
|
+
width: "100%",
|
|
2043
|
+
height: "100%",
|
|
2044
|
+
style: {
|
|
2045
|
+
minHeight: container.tier === "compact" ? 200 : 300,
|
|
2046
|
+
maxHeight: container.tier === "compact" ? 500 : 700,
|
|
2047
|
+
display: "block"
|
|
2048
|
+
}
|
|
1596
2049
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
2050
|
+
),
|
|
2051
|
+
overlayProps && /* @__PURE__ */ jsx(InteractionOverlay, { ...overlayProps }),
|
|
2052
|
+
/* @__PURE__ */ jsx(ZoomControls, { onZoomIn: zoomIn, onZoomOut: zoomOut, onReset: resetZoom })
|
|
2053
|
+
] }),
|
|
2054
|
+
/* @__PURE__ */ jsxs("table", { className: "sr-only", "aria-label": "Graph data", style: SR_ONLY_STYLE2, children: [
|
|
1600
2055
|
/* @__PURE__ */ jsx("caption", { children: "Graph nodes and connections" }),
|
|
1601
2056
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1602
2057
|
/* @__PURE__ */ jsx("th", { scope: "col", children: "Node" }),
|
|
@@ -1610,7 +2065,7 @@ function Graph({
|
|
|
1610
2065
|
return `${dir} ${target}${e.label ? ` (${e.label})` : ""}`;
|
|
1611
2066
|
}).join(", ");
|
|
1612
2067
|
return /* @__PURE__ */ jsxs("tr", { children: [
|
|
1613
|
-
/* @__PURE__ */ jsx("td", { children: node.label }),
|
|
2068
|
+
/* @__PURE__ */ jsx("td", { children: inlineToText(node.label) }),
|
|
1614
2069
|
/* @__PURE__ */ jsx("td", { children: node.group ?? "" }),
|
|
1615
2070
|
/* @__PURE__ */ jsx("td", { children: connections })
|
|
1616
2071
|
] }, node.id);
|
|
@@ -1618,7 +2073,7 @@ function Graph({
|
|
|
1618
2073
|
] })
|
|
1619
2074
|
] });
|
|
1620
2075
|
}
|
|
1621
|
-
var
|
|
2076
|
+
var SR_ONLY_STYLE2 = {
|
|
1622
2077
|
position: "absolute",
|
|
1623
2078
|
width: "1px",
|
|
1624
2079
|
height: "1px",
|
|
@@ -1644,14 +2099,20 @@ var NODE_SEP2 = 60;
|
|
|
1644
2099
|
var RANK_SEP2 = 80;
|
|
1645
2100
|
var EDGE_SEP2 = 10;
|
|
1646
2101
|
var LAYOUT_PADDING2 = 40;
|
|
1647
|
-
var CHAR_WIDTH = 7.5;
|
|
1648
2102
|
function computeEntitySize(entity) {
|
|
1649
2103
|
const attrs = entity.attributes ?? [];
|
|
1650
2104
|
const height = ENTITY_HEADER_HEIGHT + attrs.length * ENTITY_ATTR_HEIGHT + ENTITY_PADDING;
|
|
1651
|
-
|
|
2105
|
+
const labelDimensions = measureText(entity.label, {
|
|
2106
|
+
fontSize: "14px",
|
|
2107
|
+
fontFamily: "Inter, system-ui, sans-serif"
|
|
2108
|
+
});
|
|
2109
|
+
let maxTextWidth = labelDimensions.width;
|
|
1652
2110
|
for (const attr of attrs) {
|
|
1653
|
-
const
|
|
1654
|
-
|
|
2111
|
+
const attrNameDimensions = measureText(attr.name, {
|
|
2112
|
+
fontSize: "12px",
|
|
2113
|
+
fontFamily: "ui-monospace, monospace"
|
|
2114
|
+
});
|
|
2115
|
+
maxTextWidth = Math.max(maxTextWidth, attrNameDimensions.width + 100);
|
|
1655
2116
|
}
|
|
1656
2117
|
const width = Math.max(ENTITY_MIN_WIDTH, maxTextWidth + ENTITY_PADDING * 2 + 16);
|
|
1657
2118
|
return { width, height };
|
|
@@ -1742,16 +2203,13 @@ function drawCrowsFoot(g, x, y, angle, symbol) {
|
|
|
1742
2203
|
g.append("line").attr("x1", tx - Math.cos(perpAngle) * halfLen).attr("y1", ty - Math.sin(perpAngle) * halfLen).attr("x2", tx + Math.cos(perpAngle) * halfLen).attr("y2", ty + Math.sin(perpAngle) * halfLen).attr("stroke", "var(--glyph-relation-line, #6b7a94)").attr("stroke-width", "var(--glyph-node-stroke-width, 1.5)");
|
|
1743
2204
|
}
|
|
1744
2205
|
}
|
|
1745
|
-
function renderRelation(svgElement, layout) {
|
|
2206
|
+
function renderRelation(svgElement, layout, zoomBehavior) {
|
|
1746
2207
|
const svg = d32.select(svgElement);
|
|
1747
2208
|
svg.selectAll("*").remove();
|
|
1748
2209
|
const width = Math.max(layout.width, 200);
|
|
1749
2210
|
const height = Math.max(layout.height, 200);
|
|
1750
2211
|
svg.attr("viewBox", `0 0 ${width} ${height}`);
|
|
1751
2212
|
const root = svg.append("g").attr("class", "glyph-relation-root");
|
|
1752
|
-
const zoomBehavior = d32.zoom().scaleExtent([0.1, 4]).on("zoom", (event) => {
|
|
1753
|
-
root.attr("transform", event.transform.toString());
|
|
1754
|
-
});
|
|
1755
2213
|
svg.call(zoomBehavior);
|
|
1756
2214
|
const entityMap = /* @__PURE__ */ new Map();
|
|
1757
2215
|
for (const entity of layout.entities) {
|
|
@@ -1778,7 +2236,7 @@ function renderRelation(svgElement, layout) {
|
|
|
1778
2236
|
if (rel.label) {
|
|
1779
2237
|
const mid = rel.points[Math.floor(rel.points.length / 2)];
|
|
1780
2238
|
if (mid) {
|
|
1781
|
-
edgeG.append("text").attr("x", mid.x).attr("y", mid.y - 10).attr("text-anchor", "middle").attr("font-size", "11px").attr("font-family", "Inter, system-ui, sans-serif").attr("fill", "var(--glyph-relation-label, #6b7a94)").text(rel.label);
|
|
2239
|
+
edgeG.append("text").attr("x", mid.x).attr("y", mid.y - 10).attr("text-anchor", "middle").attr("font-size", "11px").attr("font-family", "Inter, system-ui, sans-serif").attr("fill", "var(--glyph-relation-label, #6b7a94)").text(inlineToText(rel.label));
|
|
1782
2240
|
}
|
|
1783
2241
|
}
|
|
1784
2242
|
const pFirst = rel.points[0];
|
|
@@ -1806,7 +2264,7 @@ function renderRelation(svgElement, layout) {
|
|
|
1806
2264
|
const headerHeight = ENTITY_HEADER_HEIGHT;
|
|
1807
2265
|
entityG.append("rect").attr("x", x).attr("y", y).attr("width", entity.width).attr("height", headerHeight).attr("rx", 4).attr("ry", 4).attr("fill", "var(--glyph-relation-header-bg, #00d4aa)");
|
|
1808
2266
|
entityG.append("rect").attr("x", x).attr("y", y + headerHeight - 4).attr("width", entity.width).attr("height", 4).attr("fill", "var(--glyph-relation-header-bg, #00d4aa)");
|
|
1809
|
-
entityG.append("text").attr("x", entity.x).attr("y", y + headerHeight / 2).attr("dy", "0.35em").attr("text-anchor", "middle").attr("font-size", "13px").attr("font-weight", "bold").attr("font-family", "Inter, system-ui, sans-serif").attr("fill", "var(--glyph-relation-header-text, #fff)").text(entity.label);
|
|
2267
|
+
entityG.append("text").attr("x", entity.x).attr("y", y + headerHeight / 2).attr("dy", "0.35em").attr("text-anchor", "middle").attr("font-size", "13px").attr("font-weight", "bold").attr("font-family", "Inter, system-ui, sans-serif").attr("fill", "var(--glyph-relation-header-text, #fff)").text(inlineToText(entity.label));
|
|
1810
2268
|
if (attrs.length > 0) {
|
|
1811
2269
|
entityG.append("line").attr("x1", x).attr("y1", y + headerHeight).attr("x2", x + entity.width).attr("y2", y + headerHeight).attr("stroke", "var(--glyph-relation-entity-border, #a8b5c8)").attr("stroke-width", 1);
|
|
1812
2270
|
}
|
|
@@ -1815,7 +2273,7 @@ function renderRelation(svgElement, layout) {
|
|
|
1815
2273
|
if (!attr) continue;
|
|
1816
2274
|
const attrY = y + headerHeight + i * ENTITY_ATTR_HEIGHT + ENTITY_ATTR_HEIGHT / 2 + 4;
|
|
1817
2275
|
const textEl = entityG.append("text").attr("x", x + ENTITY_PADDING).attr("y", attrY).attr("dy", "0.35em").attr("font-size", "12px").attr("font-family", "system-ui, -apple-system, monospace").attr("fill", "var(--glyph-relation-attr-text, #1a2035)");
|
|
1818
|
-
const nameSpan = textEl.append("tspan").text(attr.name);
|
|
2276
|
+
const nameSpan = textEl.append("tspan").text(inlineToText(attr.name));
|
|
1819
2277
|
if (attr.primaryKey) {
|
|
1820
2278
|
nameSpan.attr("font-weight", "bold").attr("text-decoration", "underline");
|
|
1821
2279
|
}
|
|
@@ -1823,29 +2281,44 @@ function renderRelation(svgElement, layout) {
|
|
|
1823
2281
|
}
|
|
1824
2282
|
}
|
|
1825
2283
|
}
|
|
1826
|
-
function Relation({ data }) {
|
|
2284
|
+
function Relation({ data, block }) {
|
|
1827
2285
|
const svgRef = useRef(null);
|
|
2286
|
+
const rootRef = useRef(null);
|
|
1828
2287
|
const layoutResult = useMemo(() => {
|
|
1829
2288
|
return computeRelationLayout(data);
|
|
1830
2289
|
}, [data]);
|
|
2290
|
+
const { overlayProps, zoomBehavior, zoomIn, zoomOut, resetZoom } = useZoomInteraction({
|
|
2291
|
+
svgRef,
|
|
2292
|
+
rootRef,
|
|
2293
|
+
interactionMode: data.interactionMode ?? "modifier-key",
|
|
2294
|
+
blockId: block.id
|
|
2295
|
+
});
|
|
1831
2296
|
useEffect(() => {
|
|
1832
2297
|
if (!svgRef.current) return;
|
|
1833
|
-
renderRelation(svgRef.current, layoutResult);
|
|
1834
|
-
|
|
2298
|
+
renderRelation(svgRef.current, layoutResult, zoomBehavior);
|
|
2299
|
+
const rootElement = svgRef.current.querySelector(".glyph-relation-root");
|
|
2300
|
+
if (rootElement) {
|
|
2301
|
+
rootRef.current = rootElement;
|
|
2302
|
+
}
|
|
2303
|
+
}, [layoutResult, zoomBehavior]);
|
|
1835
2304
|
const ariaLabel = `Entity-relationship diagram with ${data.entities.length} entities and ${data.relationships.length} relationships`;
|
|
1836
2305
|
return /* @__PURE__ */ jsxs("div", { className: "glyph-relation-container", children: [
|
|
1837
|
-
/* @__PURE__ */
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
2306
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
2307
|
+
/* @__PURE__ */ jsx(
|
|
2308
|
+
"svg",
|
|
2309
|
+
{
|
|
2310
|
+
ref: svgRef,
|
|
2311
|
+
role: "img",
|
|
2312
|
+
"aria-label": ariaLabel,
|
|
2313
|
+
width: "100%",
|
|
2314
|
+
height: "100%",
|
|
2315
|
+
style: { minHeight: 300, maxHeight: 700, display: "block" }
|
|
2316
|
+
}
|
|
2317
|
+
),
|
|
2318
|
+
overlayProps && /* @__PURE__ */ jsx(InteractionOverlay, { ...overlayProps }),
|
|
2319
|
+
/* @__PURE__ */ jsx(ZoomControls, { onZoomIn: zoomIn, onZoomOut: zoomOut, onReset: resetZoom })
|
|
2320
|
+
] }),
|
|
2321
|
+
/* @__PURE__ */ jsxs("table", { className: "sr-only", "aria-label": "Entity-relationship data", style: SR_ONLY_STYLE3, children: [
|
|
1849
2322
|
/* @__PURE__ */ jsx("caption", { children: "Entities and relationships" }),
|
|
1850
2323
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1851
2324
|
/* @__PURE__ */ jsx("th", { scope: "col", children: "Entity" }),
|
|
@@ -1860,7 +2333,7 @@ function Relation({ data }) {
|
|
|
1860
2333
|
return `${dir} ${target} [${r.cardinality}]${r.label ? ` (${r.label})` : ""}`;
|
|
1861
2334
|
}).join(", ");
|
|
1862
2335
|
return /* @__PURE__ */ jsxs("tr", { children: [
|
|
1863
|
-
/* @__PURE__ */ jsx("td", { children: entity.label }),
|
|
2336
|
+
/* @__PURE__ */ jsx("td", { children: inlineToText(entity.label) }),
|
|
1864
2337
|
/* @__PURE__ */ jsx("td", { children: attrs }),
|
|
1865
2338
|
/* @__PURE__ */ jsx("td", { children: rels })
|
|
1866
2339
|
] }, entity.id);
|
|
@@ -1868,7 +2341,7 @@ function Relation({ data }) {
|
|
|
1868
2341
|
] })
|
|
1869
2342
|
] });
|
|
1870
2343
|
}
|
|
1871
|
-
var
|
|
2344
|
+
var SR_ONLY_STYLE3 = {
|
|
1872
2345
|
position: "absolute",
|
|
1873
2346
|
width: "1px",
|
|
1874
2347
|
height: "1px",
|
|
@@ -2398,9 +2871,9 @@ function CodeDiff({ data, block }) {
|
|
|
2398
2871
|
}
|
|
2399
2872
|
return /* @__PURE__ */ jsxs("div", { id: baseId, role: "region", "aria-label": summary, style: containerStyle11, children: [
|
|
2400
2873
|
(beforeLabel || afterLabel) && /* @__PURE__ */ jsxs("div", { style: labelBarStyle, children: [
|
|
2401
|
-
beforeLabel && /* @__PURE__ */ jsx("span", { children: beforeLabel }),
|
|
2874
|
+
beforeLabel && /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(RichText, { content: beforeLabel }) }),
|
|
2402
2875
|
beforeLabel && afterLabel && /* @__PURE__ */ jsx("span", { children: "\u2192" }),
|
|
2403
|
-
afterLabel && /* @__PURE__ */ jsx("span", { children: afterLabel })
|
|
2876
|
+
afterLabel && /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(RichText, { content: afterLabel }) })
|
|
2404
2877
|
] }),
|
|
2405
2878
|
/* @__PURE__ */ jsx("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsx("table", { role: "grid", style: tableStyle2, children: /* @__PURE__ */ jsx("tbody", { children: diffLines.map((line6, i) => /* @__PURE__ */ jsxs(
|
|
2406
2879
|
"tr",
|
|
@@ -2504,7 +2977,7 @@ function renderNodeShape(nodeG, node, fillOpacity, strokeWidth) {
|
|
|
2504
2977
|
}
|
|
2505
2978
|
}
|
|
2506
2979
|
}
|
|
2507
|
-
function renderFlowchart(svgElement, layout) {
|
|
2980
|
+
function renderFlowchart(svgElement, layout, zoomBehavior) {
|
|
2508
2981
|
const svg = d32.select(svgElement);
|
|
2509
2982
|
svg.selectAll("*").remove();
|
|
2510
2983
|
const width = Math.max(layout.width, 200);
|
|
@@ -2516,9 +2989,6 @@ function renderFlowchart(svgElement, layout) {
|
|
|
2516
2989
|
const nodeStrokeWidth = getThemeVar2(container, "--glyph-node-stroke-width", "1.5");
|
|
2517
2990
|
const nodeFillOpacity = getThemeVar2(container, "--glyph-node-fill-opacity", "0.85");
|
|
2518
2991
|
const root = svg.append("g").attr("class", "glyph-flowchart-root");
|
|
2519
|
-
const zoomBehavior = d32.zoom().scaleExtent([0.1, 4]).on("zoom", (event) => {
|
|
2520
|
-
root.attr("transform", event.transform.toString());
|
|
2521
|
-
});
|
|
2522
2992
|
svg.call(zoomBehavior);
|
|
2523
2993
|
const lineGen = d32.line().x((d) => d.x).y((d) => d.y).curve(d32.curveBasis);
|
|
2524
2994
|
const edgeGroup = root.append("g").attr("class", "glyph-flowchart-edges");
|
|
@@ -2528,7 +2998,7 @@ function renderFlowchart(svgElement, layout) {
|
|
|
2528
2998
|
if (edge.label) {
|
|
2529
2999
|
const mid = edge.points[Math.floor(edge.points.length / 2)];
|
|
2530
3000
|
if (mid) {
|
|
2531
|
-
edgeG.append("text").attr("x", mid.x).attr("y", mid.y - 8).attr("text-anchor", "middle").attr("font-size", "11px").attr("fill", "var(--glyph-text-muted, #6b7a94)").text(edge.label);
|
|
3001
|
+
edgeG.append("text").attr("x", mid.x).attr("y", mid.y - 8).attr("text-anchor", "middle").attr("font-size", "11px").attr("fill", "var(--glyph-text-muted, #6b7a94)").text(inlineToText(edge.label));
|
|
2532
3002
|
}
|
|
2533
3003
|
}
|
|
2534
3004
|
}
|
|
@@ -2536,19 +3006,34 @@ function renderFlowchart(svgElement, layout) {
|
|
|
2536
3006
|
for (const node of layout.nodes) {
|
|
2537
3007
|
const nodeG = nodeGroup.append("g").attr("class", "glyph-flowchart-node");
|
|
2538
3008
|
renderNodeShape(nodeG, node, nodeFillOpacity, nodeStrokeWidth);
|
|
2539
|
-
nodeG.append("text").attr("x", node.x).attr("y", node.y).attr("dy", "0.35em").attr("text-anchor", "middle").attr("font-size", "13px").attr("font-family", "Inter, system-ui, sans-serif").attr("fill", "var(--glyph-node-label-color, #fff)").attr("pointer-events", "none").text(node.label);
|
|
3009
|
+
nodeG.append("text").attr("x", node.x).attr("y", node.y).attr("dy", "0.35em").attr("text-anchor", "middle").attr("font-size", "13px").attr("font-family", "Inter, system-ui, sans-serif").attr("fill", "var(--glyph-node-label-color, #fff)").attr("pointer-events", "none").text(inlineToText(node.label));
|
|
2540
3010
|
}
|
|
2541
3011
|
}
|
|
2542
|
-
function Flowchart({
|
|
3012
|
+
function Flowchart({
|
|
3013
|
+
data,
|
|
3014
|
+
block,
|
|
3015
|
+
container
|
|
3016
|
+
}) {
|
|
2543
3017
|
const svgRef = useRef(null);
|
|
3018
|
+
const rootRef = useRef(null);
|
|
2544
3019
|
const layoutResult = useMemo(() => computeLayout(data.nodes, data.edges, data.direction), [data]);
|
|
3020
|
+
const { overlayProps, zoomBehavior, zoomIn, zoomOut, resetZoom } = useZoomInteraction({
|
|
3021
|
+
svgRef,
|
|
3022
|
+
rootRef,
|
|
3023
|
+
interactionMode: data.interactionMode ?? "modifier-key",
|
|
3024
|
+
blockId: block.id
|
|
3025
|
+
});
|
|
2545
3026
|
useEffect(() => {
|
|
2546
3027
|
if (!svgRef.current) return;
|
|
2547
|
-
renderFlowchart(svgRef.current, layoutResult);
|
|
2548
|
-
|
|
3028
|
+
renderFlowchart(svgRef.current, layoutResult, zoomBehavior);
|
|
3029
|
+
const rootElement = svgRef.current.querySelector(".glyph-flowchart-root");
|
|
3030
|
+
if (rootElement) {
|
|
3031
|
+
rootRef.current = rootElement;
|
|
3032
|
+
}
|
|
3033
|
+
}, [layoutResult, zoomBehavior]);
|
|
2549
3034
|
const nodeCount = data.nodes.length;
|
|
2550
3035
|
const edgeCount = data.edges.length;
|
|
2551
|
-
const ariaLabel = data.title ? `${data.title}: flowchart with ${nodeCount} nodes and ${edgeCount} edges` : `Flowchart with ${nodeCount} nodes and ${edgeCount} edges`;
|
|
3036
|
+
const ariaLabel = data.title ? `${inlineToText(data.title)}: flowchart with ${nodeCount} nodes and ${edgeCount} edges` : `Flowchart with ${nodeCount} nodes and ${edgeCount} edges`;
|
|
2552
3037
|
return /* @__PURE__ */ jsxs("div", { className: "glyph-flowchart-container", children: [
|
|
2553
3038
|
data.title && /* @__PURE__ */ jsx(
|
|
2554
3039
|
"div",
|
|
@@ -2560,25 +3045,29 @@ function Flowchart({ data, container }) {
|
|
|
2560
3045
|
color: "var(--glyph-heading, #edf0f5)",
|
|
2561
3046
|
marginBottom: "0.5rem"
|
|
2562
3047
|
},
|
|
2563
|
-
children: data.title
|
|
3048
|
+
children: /* @__PURE__ */ jsx(RichText, { content: data.title })
|
|
2564
3049
|
}
|
|
2565
3050
|
),
|
|
2566
|
-
/* @__PURE__ */
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
3051
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
3052
|
+
/* @__PURE__ */ jsx(
|
|
3053
|
+
"svg",
|
|
3054
|
+
{
|
|
3055
|
+
ref: svgRef,
|
|
3056
|
+
role: "img",
|
|
3057
|
+
"aria-label": ariaLabel,
|
|
3058
|
+
width: "100%",
|
|
3059
|
+
height: "100%",
|
|
3060
|
+
style: {
|
|
3061
|
+
minHeight: container.tier === "compact" ? 200 : 300,
|
|
3062
|
+
maxHeight: container.tier === "compact" ? 500 : 700,
|
|
3063
|
+
display: "block"
|
|
3064
|
+
}
|
|
2578
3065
|
}
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
3066
|
+
),
|
|
3067
|
+
overlayProps && /* @__PURE__ */ jsx(InteractionOverlay, { ...overlayProps }),
|
|
3068
|
+
/* @__PURE__ */ jsx(ZoomControls, { onZoomIn: zoomIn, onZoomOut: zoomOut, onReset: resetZoom })
|
|
3069
|
+
] }),
|
|
3070
|
+
/* @__PURE__ */ jsxs("table", { className: "sr-only", "aria-label": "Flowchart data", style: SR_ONLY_STYLE4, children: [
|
|
2582
3071
|
/* @__PURE__ */ jsx("caption", { children: "Flowchart nodes and connections" }),
|
|
2583
3072
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
2584
3073
|
/* @__PURE__ */ jsx("th", { scope: "col", children: "Node" }),
|
|
@@ -2589,10 +3078,10 @@ function Flowchart({ data, container }) {
|
|
|
2589
3078
|
const connections = data.edges.filter((e) => e.from === node.id || e.to === node.id).map((e) => {
|
|
2590
3079
|
const target = e.from === node.id ? e.to : e.from;
|
|
2591
3080
|
const dir = e.from === node.id ? "->" : "<-";
|
|
2592
|
-
return `${dir} ${target}${e.label ? ` (${e.label})` : ""}`;
|
|
3081
|
+
return `${dir} ${target}${e.label ? ` (${inlineToText(e.label)})` : ""}`;
|
|
2593
3082
|
}).join(", ");
|
|
2594
3083
|
return /* @__PURE__ */ jsxs("tr", { children: [
|
|
2595
|
-
/* @__PURE__ */ jsx("td", { children: node.label }),
|
|
3084
|
+
/* @__PURE__ */ jsx("td", { children: inlineToText(node.label) }),
|
|
2596
3085
|
/* @__PURE__ */ jsx("td", { children: node.type }),
|
|
2597
3086
|
/* @__PURE__ */ jsx("td", { children: connections })
|
|
2598
3087
|
] }, node.id);
|
|
@@ -2600,7 +3089,7 @@ function Flowchart({ data, container }) {
|
|
|
2600
3089
|
] })
|
|
2601
3090
|
] });
|
|
2602
3091
|
}
|
|
2603
|
-
var
|
|
3092
|
+
var SR_ONLY_STYLE4 = {
|
|
2604
3093
|
position: "absolute",
|
|
2605
3094
|
width: "1px",
|
|
2606
3095
|
height: "1px",
|
|
@@ -3014,20 +3503,24 @@ function renderActorBox(actor, cx, y, keyPrefix, width = ACTOR_WIDTH, height = A
|
|
|
3014
3503
|
strokeWidth: 1.5
|
|
3015
3504
|
}
|
|
3016
3505
|
),
|
|
3017
|
-
/* @__PURE__ */ jsx(
|
|
3018
|
-
"
|
|
3506
|
+
/* @__PURE__ */ jsx("foreignObject", { x: cx - width / 2, y, width, height, children: /* @__PURE__ */ jsx(
|
|
3507
|
+
"div",
|
|
3019
3508
|
{
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3509
|
+
style: {
|
|
3510
|
+
display: "flex",
|
|
3511
|
+
alignItems: "center",
|
|
3512
|
+
justifyContent: "center",
|
|
3513
|
+
width: "100%",
|
|
3514
|
+
height: "100%",
|
|
3515
|
+
fontSize,
|
|
3516
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
3517
|
+
fontWeight: 600,
|
|
3518
|
+
color: "var(--glyph-text, #d4dae3)",
|
|
3519
|
+
textAlign: "center"
|
|
3520
|
+
},
|
|
3521
|
+
children: /* @__PURE__ */ jsx(RichText, { content: actor.label })
|
|
3029
3522
|
}
|
|
3030
|
-
)
|
|
3523
|
+
) })
|
|
3031
3524
|
] }, `${keyPrefix}-${actor.id}`);
|
|
3032
3525
|
}
|
|
3033
3526
|
function renderSelfMessage(x, y, label, idx, fontSize = "12px") {
|
|
@@ -3042,18 +3535,19 @@ function renderSelfMessage(x, y, label, idx, fontSize = "12px") {
|
|
|
3042
3535
|
markerEnd: "url(#seq-arrow-solid)"
|
|
3043
3536
|
}
|
|
3044
3537
|
),
|
|
3045
|
-
/* @__PURE__ */ jsx(
|
|
3046
|
-
"
|
|
3538
|
+
/* @__PURE__ */ jsx("foreignObject", { x: x + SELF_ARC_WIDTH + 6, y, width: 150, height: SELF_ARC_HEIGHT, children: /* @__PURE__ */ jsx(
|
|
3539
|
+
"div",
|
|
3047
3540
|
{
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3541
|
+
style: {
|
|
3542
|
+
display: "flex",
|
|
3543
|
+
alignItems: "center",
|
|
3544
|
+
fontSize,
|
|
3545
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
3546
|
+
color: "var(--glyph-text, #d4dae3)"
|
|
3547
|
+
},
|
|
3548
|
+
children: /* @__PURE__ */ jsx(RichText, { content: label })
|
|
3055
3549
|
}
|
|
3056
|
-
)
|
|
3550
|
+
) })
|
|
3057
3551
|
] }, `msg-${idx}`);
|
|
3058
3552
|
}
|
|
3059
3553
|
function renderStandardMessage(fromX, toX, y, label, isDashed, idx, fontSize = "12px") {
|
|
@@ -3073,18 +3567,20 @@ function renderStandardMessage(fromX, toX, y, label, isDashed, idx, fontSize = "
|
|
|
3073
3567
|
markerEnd: `url(#${markerId})`
|
|
3074
3568
|
}
|
|
3075
3569
|
),
|
|
3076
|
-
/* @__PURE__ */ jsx(
|
|
3077
|
-
"
|
|
3570
|
+
/* @__PURE__ */ jsx("foreignObject", { x: midX - 75, y: y - 22, width: 150, height: 20, children: /* @__PURE__ */ jsx(
|
|
3571
|
+
"div",
|
|
3078
3572
|
{
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3573
|
+
style: {
|
|
3574
|
+
display: "flex",
|
|
3575
|
+
justifyContent: "center",
|
|
3576
|
+
fontSize,
|
|
3577
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
3578
|
+
color: "var(--glyph-text, #d4dae3)",
|
|
3579
|
+
textAlign: "center"
|
|
3580
|
+
},
|
|
3581
|
+
children: /* @__PURE__ */ jsx(RichText, { content: label })
|
|
3086
3582
|
}
|
|
3087
|
-
)
|
|
3583
|
+
) })
|
|
3088
3584
|
] }, `msg-${idx}`);
|
|
3089
3585
|
}
|
|
3090
3586
|
function Sequence({ data, container }) {
|
|
@@ -3109,7 +3605,7 @@ function Sequence({ data, container }) {
|
|
|
3109
3605
|
const firstMsgY = lifelineStartY + MSG_SPACING;
|
|
3110
3606
|
const lastMsgY = firstMsgY + (messageCount - 1) * MSG_SPACING;
|
|
3111
3607
|
const svgHeight = lastMsgY + BOTTOM_PADDING + effectiveActorHeight;
|
|
3112
|
-
const ariaLabel = data.title ? `${data.title}: sequence diagram with ${actorCount} actors and ${messageCount} messages` : `Sequence diagram with ${actorCount} actors and ${messageCount} messages`;
|
|
3608
|
+
const ariaLabel = data.title ? `${inlineToText(data.title)}: sequence diagram with ${actorCount} actors and ${messageCount} messages` : `Sequence diagram with ${actorCount} actors and ${messageCount} messages`;
|
|
3113
3609
|
return /* @__PURE__ */ jsxs("div", { className: "glyph-sequence-container", children: [
|
|
3114
3610
|
data.title && /* @__PURE__ */ jsx(
|
|
3115
3611
|
"div",
|
|
@@ -3121,7 +3617,7 @@ function Sequence({ data, container }) {
|
|
|
3121
3617
|
color: "var(--glyph-heading, #edf0f5)",
|
|
3122
3618
|
marginBottom: "0.5rem"
|
|
3123
3619
|
},
|
|
3124
|
-
children: data.title
|
|
3620
|
+
children: /* @__PURE__ */ jsx(RichText, { content: data.title })
|
|
3125
3621
|
}
|
|
3126
3622
|
),
|
|
3127
3623
|
/* @__PURE__ */ jsxs(
|
|
@@ -3222,7 +3718,7 @@ function Sequence({ data, container }) {
|
|
|
3222
3718
|
]
|
|
3223
3719
|
}
|
|
3224
3720
|
),
|
|
3225
|
-
/* @__PURE__ */ jsxs("table", { className: "sr-only", "aria-label": "Sequence data", style:
|
|
3721
|
+
/* @__PURE__ */ jsxs("table", { className: "sr-only", "aria-label": "Sequence data", style: SR_ONLY_STYLE5, children: [
|
|
3226
3722
|
/* @__PURE__ */ jsx("caption", { children: "Sequence messages in order" }),
|
|
3227
3723
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
3228
3724
|
/* @__PURE__ */ jsx("th", { scope: "col", children: "#" }),
|
|
@@ -3236,16 +3732,16 @@ function Sequence({ data, container }) {
|
|
|
3236
3732
|
const toActor = data.actors.find((a) => a.id === msg.to);
|
|
3237
3733
|
return /* @__PURE__ */ jsxs("tr", { children: [
|
|
3238
3734
|
/* @__PURE__ */ jsx("td", { children: idx + 1 }),
|
|
3239
|
-
/* @__PURE__ */ jsx("td", { children: fromActor
|
|
3240
|
-
/* @__PURE__ */ jsx("td", { children: toActor
|
|
3241
|
-
/* @__PURE__ */ jsx("td", { children: msg.label }),
|
|
3735
|
+
/* @__PURE__ */ jsx("td", { children: fromActor ? inlineToText(fromActor.label) : msg.from }),
|
|
3736
|
+
/* @__PURE__ */ jsx("td", { children: toActor ? inlineToText(toActor.label) : msg.to }),
|
|
3737
|
+
/* @__PURE__ */ jsx("td", { children: inlineToText(msg.label) }),
|
|
3242
3738
|
/* @__PURE__ */ jsx("td", { children: msg.type })
|
|
3243
3739
|
] }, idx);
|
|
3244
3740
|
}) })
|
|
3245
3741
|
] })
|
|
3246
3742
|
] });
|
|
3247
3743
|
}
|
|
3248
|
-
var
|
|
3744
|
+
var SR_ONLY_STYLE5 = {
|
|
3249
3745
|
position: "absolute",
|
|
3250
3746
|
width: "1px",
|
|
3251
3747
|
height: "1px",
|
|
@@ -3651,7 +4147,7 @@ function Architecture({
|
|
|
3651
4147
|
}
|
|
3652
4148
|
}
|
|
3653
4149
|
),
|
|
3654
|
-
/* @__PURE__ */ jsxs("table", { className: "sr-only", "aria-label": "Architecture data", style:
|
|
4150
|
+
/* @__PURE__ */ jsxs("table", { className: "sr-only", "aria-label": "Architecture data", style: SR_ONLY_STYLE6, children: [
|
|
3655
4151
|
/* @__PURE__ */ jsx("caption", { children: "Architecture nodes and connections" }),
|
|
3656
4152
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
3657
4153
|
/* @__PURE__ */ jsx("th", { scope: "col", children: "Node" }),
|
|
@@ -3695,7 +4191,7 @@ function countLeafNodes(children) {
|
|
|
3695
4191
|
}
|
|
3696
4192
|
return count;
|
|
3697
4193
|
}
|
|
3698
|
-
var
|
|
4194
|
+
var SR_ONLY_STYLE6 = {
|
|
3699
4195
|
position: "absolute",
|
|
3700
4196
|
width: "1px",
|
|
3701
4197
|
height: "1px",
|
|
@@ -3883,7 +4379,7 @@ function layoutTree(data) {
|
|
|
3883
4379
|
};
|
|
3884
4380
|
}
|
|
3885
4381
|
function renderAccessibleList(root, children) {
|
|
3886
|
-
return /* @__PURE__ */ jsx("ul", { style:
|
|
4382
|
+
return /* @__PURE__ */ jsx("ul", { style: SR_ONLY_STYLE7, role: "list", "aria-label": "Mind map structure", children: /* @__PURE__ */ jsxs("li", { children: [
|
|
3887
4383
|
root,
|
|
3888
4384
|
children.length > 0 && renderAccessibleChildren(children)
|
|
3889
4385
|
] }) });
|
|
@@ -4010,7 +4506,7 @@ function MindMap({ data, container }) {
|
|
|
4010
4506
|
renderAccessibleList(data.root, data.children)
|
|
4011
4507
|
] });
|
|
4012
4508
|
}
|
|
4013
|
-
var
|
|
4509
|
+
var SR_ONLY_STYLE7 = {
|
|
4014
4510
|
position: "absolute",
|
|
4015
4511
|
width: "1px",
|
|
4016
4512
|
height: "1px",
|
|
@@ -4085,7 +4581,7 @@ function Equation({ data }) {
|
|
|
4085
4581
|
const ariaLabel = `Equation: ${data.expression}`;
|
|
4086
4582
|
return /* @__PURE__ */ jsxs("div", { style: containerStyle, role: "math", "aria-label": ariaLabel, children: [
|
|
4087
4583
|
error || html === "" ? /* @__PURE__ */ jsx("code", { style: fallbackStyle, children: data.expression }) : /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: html } }),
|
|
4088
|
-
data.label !== void 0 && /* @__PURE__ */ jsx("div", { style: labelStyle2, children: data.label })
|
|
4584
|
+
data.label !== void 0 && /* @__PURE__ */ jsx("div", { style: labelStyle2, children: /* @__PURE__ */ jsx(RichText, { content: data.label }) })
|
|
4089
4585
|
] });
|
|
4090
4586
|
}
|
|
4091
4587
|
if (data.steps !== void 0 && data.steps.length > 0) {
|
|
@@ -4096,10 +4592,10 @@ function Equation({ data }) {
|
|
|
4096
4592
|
const { html, error } = renderLatex(step.expression);
|
|
4097
4593
|
return /* @__PURE__ */ jsxs("div", { style: stepRowStyle, children: [
|
|
4098
4594
|
error || html === "" ? /* @__PURE__ */ jsx("code", { style: fallbackStyle, children: step.expression }) : /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: html } }),
|
|
4099
|
-
step.annotation !== void 0 && /* @__PURE__ */ jsx("span", { style: annotationStyle, children: step.annotation })
|
|
4595
|
+
step.annotation !== void 0 && /* @__PURE__ */ jsx("span", { style: annotationStyle, children: /* @__PURE__ */ jsx(RichText, { content: step.annotation }) })
|
|
4100
4596
|
] }, idx);
|
|
4101
4597
|
}) }),
|
|
4102
|
-
data.label !== void 0 && /* @__PURE__ */ jsx("div", { style: labelStyle2, children: data.label })
|
|
4598
|
+
data.label !== void 0 && /* @__PURE__ */ jsx("div", { style: labelStyle2, children: /* @__PURE__ */ jsx(RichText, { content: data.label }) })
|
|
4103
4599
|
] });
|
|
4104
4600
|
}
|
|
4105
4601
|
return /* @__PURE__ */ jsx("div", { style: containerStyle, role: "math", "aria-label": "Empty equation", children: /* @__PURE__ */ jsx("span", { style: { color: "var(--glyph-text-muted, #6b7a94)" }, children: "No equation provided" }) });
|
|
@@ -6525,8 +7021,8 @@ function Kanban({
|
|
|
6525
7021
|
style: cardStyle(isGrabbed, card.priority),
|
|
6526
7022
|
onKeyDown: (e) => handleCardKeyDown(e, card.id, col.id, cardIndex),
|
|
6527
7023
|
children: [
|
|
6528
|
-
/* @__PURE__ */ jsx("div", { style: cardTitleStyle, children: card.title }),
|
|
6529
|
-
card.description && /* @__PURE__ */ jsx("div", { style: cardDescStyle, children: card.description }),
|
|
7024
|
+
/* @__PURE__ */ jsx("div", { style: cardTitleStyle, children: /* @__PURE__ */ jsx(RichText, { content: card.title }) }),
|
|
7025
|
+
card.description && /* @__PURE__ */ jsx("div", { style: cardDescStyle, children: /* @__PURE__ */ jsx(RichText, { content: card.description }) }),
|
|
6530
7026
|
card.tags && card.tags.length > 0 && /* @__PURE__ */ jsx("div", { style: tagContainerStyle, children: card.tags.map((tag) => /* @__PURE__ */ jsx("span", { style: tagStyle, children: tag }, tag)) })
|
|
6531
7027
|
]
|
|
6532
7028
|
},
|