@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.cjs
CHANGED
|
@@ -75,7 +75,7 @@ function Callout({ data }) {
|
|
|
75
75
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "note", "aria-label": CALLOUT_LABELS[type], style: containerStyle11, children: [
|
|
76
76
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: iconStyle, "aria-hidden": "true", children: CALLOUT_ICONS[type] }),
|
|
77
77
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: bodyStyle3, children: [
|
|
78
|
-
title && /* @__PURE__ */ jsxRuntime.jsx("div", { style: titleStyle2, children: title }),
|
|
78
|
+
title && /* @__PURE__ */ jsxRuntime.jsx("div", { style: titleStyle2, children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: title }) }),
|
|
79
79
|
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content }) })
|
|
80
80
|
] })
|
|
81
81
|
] });
|
|
@@ -87,6 +87,34 @@ var calloutDefinition = {
|
|
|
87
87
|
schema: schemas.calloutSchema,
|
|
88
88
|
render: Callout
|
|
89
89
|
};
|
|
90
|
+
|
|
91
|
+
// src/utils/inlineToText.ts
|
|
92
|
+
function inlineToText(content) {
|
|
93
|
+
if (typeof content === "string") {
|
|
94
|
+
return content;
|
|
95
|
+
}
|
|
96
|
+
return content.map((node) => {
|
|
97
|
+
switch (node.type) {
|
|
98
|
+
case "text":
|
|
99
|
+
return node.value;
|
|
100
|
+
case "strong":
|
|
101
|
+
case "emphasis":
|
|
102
|
+
case "delete":
|
|
103
|
+
case "link":
|
|
104
|
+
return inlineToText(node.children);
|
|
105
|
+
case "inlineCode":
|
|
106
|
+
return node.value;
|
|
107
|
+
case "image":
|
|
108
|
+
return node.alt ?? "";
|
|
109
|
+
case "break":
|
|
110
|
+
return "\n";
|
|
111
|
+
default:
|
|
112
|
+
return "";
|
|
113
|
+
}
|
|
114
|
+
}).join("");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/chart/render.ts
|
|
90
118
|
var DEFAULT_WIDTH = 600;
|
|
91
119
|
var DEFAULT_HEIGHT = 400;
|
|
92
120
|
var MARGIN = { top: 20, right: 30, bottom: 50, left: 60 };
|
|
@@ -134,7 +162,7 @@ function renderAxes(g, xScale, yScale, xAxisConfig, yAxisConfig, innerWidth, inn
|
|
|
134
162
|
}
|
|
135
163
|
xAxisG.selectAll("text, line, path").attr("fill", "var(--glyph-text, #1a2035)").attr("stroke", "var(--glyph-grid, #1a2035)");
|
|
136
164
|
if (xAxisConfig?.label) {
|
|
137
|
-
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);
|
|
165
|
+
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));
|
|
138
166
|
}
|
|
139
167
|
const yAxisG = g.append("g").attr("class", "y-axis");
|
|
140
168
|
yAxisG.call(
|
|
@@ -142,7 +170,7 @@ function renderAxes(g, xScale, yScale, xAxisConfig, yAxisConfig, innerWidth, inn
|
|
|
142
170
|
);
|
|
143
171
|
yAxisG.selectAll("text, line, path").attr("fill", "var(--glyph-text, #1a2035)").attr("stroke", "var(--glyph-grid, #1a2035)");
|
|
144
172
|
if (yAxisConfig?.label) {
|
|
145
|
-
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);
|
|
173
|
+
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));
|
|
146
174
|
}
|
|
147
175
|
}
|
|
148
176
|
function renderGridLines(g, yScale, innerWidth) {
|
|
@@ -198,7 +226,7 @@ function renderLegend(sel, series, marginLeft, marginTop, fontSize = "12px") {
|
|
|
198
226
|
const color3 = COLOR_SCHEME[i % COLOR_SCHEME.length] ?? "var(--glyph-text, #1a2035)";
|
|
199
227
|
const row = legendG.append("g").attr("transform", `translate(0,${String(i * 20)})`);
|
|
200
228
|
row.append("rect").attr("width", 14).attr("height", 14).attr("fill", color3).attr("rx", 2);
|
|
201
|
-
row.append("text").attr("x", 20).attr("y", 11).attr("fill", "var(--glyph-text, #1a2035)").attr("font-size", fontSize).text(s.name);
|
|
229
|
+
row.append("text").attr("x", 20).attr("y", 11).attr("fill", "var(--glyph-text, #1a2035)").attr("font-size", fontSize).text(inlineToText(s.name));
|
|
202
230
|
});
|
|
203
231
|
}
|
|
204
232
|
function ChartAccessibleTable({
|
|
@@ -229,10 +257,10 @@ function ChartAccessibleTable({
|
|
|
229
257
|
" chart data"
|
|
230
258
|
] }),
|
|
231
259
|
series.map((s, si) => /* @__PURE__ */ jsxRuntime.jsxs("tbody", { children: [
|
|
232
|
-
/* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("th", { colSpan: 2, children: s.name }) }),
|
|
260
|
+
/* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("th", { colSpan: 2, children: inlineToText(s.name) }) }),
|
|
233
261
|
/* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
234
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { children: xLabel
|
|
235
|
-
/* @__PURE__ */ jsxRuntime.jsx("th", { children: yLabel
|
|
262
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { children: xLabel ? inlineToText(xLabel) : xKey }),
|
|
263
|
+
/* @__PURE__ */ jsxRuntime.jsx("th", { children: yLabel ? inlineToText(yLabel) : yKey })
|
|
236
264
|
] }),
|
|
237
265
|
s.data.map((d, di) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
238
266
|
/* @__PURE__ */ jsxRuntime.jsx("td", { children: String(d[xKey] ?? "") }),
|
|
@@ -283,6 +311,7 @@ function renderAllSeries(g, type, series, scales, xKey, yKey, showTooltip, hideT
|
|
|
283
311
|
const { xScale, xScalePoint, yScale, innerHeight } = scales;
|
|
284
312
|
series.forEach((s, i) => {
|
|
285
313
|
const color3 = COLOR_SCHEME[i % COLOR_SCHEME.length] ?? "#333";
|
|
314
|
+
const seriesName = inlineToText(s.name);
|
|
286
315
|
switch (type) {
|
|
287
316
|
case "line":
|
|
288
317
|
renderLineSeries(
|
|
@@ -294,7 +323,7 @@ function renderAllSeries(g, type, series, scales, xKey, yKey, showTooltip, hideT
|
|
|
294
323
|
xKey,
|
|
295
324
|
color3,
|
|
296
325
|
i,
|
|
297
|
-
|
|
326
|
+
seriesName,
|
|
298
327
|
showTooltip,
|
|
299
328
|
hideTooltip
|
|
300
329
|
);
|
|
@@ -310,7 +339,7 @@ function renderAllSeries(g, type, series, scales, xKey, yKey, showTooltip, hideT
|
|
|
310
339
|
innerHeight,
|
|
311
340
|
color3,
|
|
312
341
|
i,
|
|
313
|
-
|
|
342
|
+
seriesName,
|
|
314
343
|
showTooltip,
|
|
315
344
|
hideTooltip
|
|
316
345
|
);
|
|
@@ -327,7 +356,7 @@ function renderAllSeries(g, type, series, scales, xKey, yKey, showTooltip, hideT
|
|
|
327
356
|
i,
|
|
328
357
|
series.length,
|
|
329
358
|
innerHeight,
|
|
330
|
-
|
|
359
|
+
seriesName,
|
|
331
360
|
showTooltip,
|
|
332
361
|
hideTooltip
|
|
333
362
|
);
|
|
@@ -340,7 +369,7 @@ function renderAllSeries(g, type, series, scales, xKey, yKey, showTooltip, hideT
|
|
|
340
369
|
xScalePoint,
|
|
341
370
|
yScale,
|
|
342
371
|
scales.innerWidth,
|
|
343
|
-
|
|
372
|
+
seriesName,
|
|
344
373
|
showTooltip,
|
|
345
374
|
hideTooltip
|
|
346
375
|
);
|
|
@@ -720,7 +749,7 @@ function TableHead({
|
|
|
720
749
|
whiteSpace: "nowrap"
|
|
721
750
|
},
|
|
722
751
|
children: [
|
|
723
|
-
col.label,
|
|
752
|
+
/* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: col.label }),
|
|
724
753
|
col.sortable ? sortIndicator(direction) : ""
|
|
725
754
|
]
|
|
726
755
|
},
|
|
@@ -1046,7 +1075,7 @@ function Tabs({ data, block, onInteraction }) {
|
|
|
1046
1075
|
outline: "revert",
|
|
1047
1076
|
outlineOffset: "2px"
|
|
1048
1077
|
},
|
|
1049
|
-
children: tab.label
|
|
1078
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: tab.label })
|
|
1050
1079
|
},
|
|
1051
1080
|
tabId
|
|
1052
1081
|
);
|
|
@@ -1072,7 +1101,7 @@ function Tabs({ data, block, onInteraction }) {
|
|
|
1072
1101
|
color: "var(--glyph-heading, #0a0e1a)",
|
|
1073
1102
|
lineHeight: 1.6
|
|
1074
1103
|
},
|
|
1075
|
-
children: tab.content
|
|
1104
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: tab.content })
|
|
1076
1105
|
},
|
|
1077
1106
|
panelId
|
|
1078
1107
|
);
|
|
@@ -1323,6 +1352,92 @@ var timelineDefinition = {
|
|
|
1323
1352
|
schema: schemas.timelineSchema,
|
|
1324
1353
|
render: Timeline
|
|
1325
1354
|
};
|
|
1355
|
+
|
|
1356
|
+
// src/utils/measureText.ts
|
|
1357
|
+
var measurementCache = /* @__PURE__ */ new WeakMap();
|
|
1358
|
+
function measurePlainText(text, style) {
|
|
1359
|
+
const canvas = document.createElement("canvas");
|
|
1360
|
+
const ctx = canvas.getContext("2d");
|
|
1361
|
+
if (!ctx) {
|
|
1362
|
+
const avgCharWidth = parseInt(style.fontSize) * 0.6;
|
|
1363
|
+
return {
|
|
1364
|
+
width: text.length * avgCharWidth,
|
|
1365
|
+
height: parseInt(style.fontSize) * 1.2
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
const fontWeight = style.fontWeight ?? "normal";
|
|
1369
|
+
ctx.font = `${fontWeight} ${style.fontSize} ${style.fontFamily}`;
|
|
1370
|
+
const metrics = ctx.measureText(text);
|
|
1371
|
+
const width = metrics.width;
|
|
1372
|
+
const height = parseInt(style.fontSize) * 1.2;
|
|
1373
|
+
return { width, height };
|
|
1374
|
+
}
|
|
1375
|
+
function measureHtmlText(content, style) {
|
|
1376
|
+
const cached = measurementCache.get(content);
|
|
1377
|
+
if (cached) {
|
|
1378
|
+
return cached;
|
|
1379
|
+
}
|
|
1380
|
+
const container = document.createElement("div");
|
|
1381
|
+
container.style.position = "absolute";
|
|
1382
|
+
container.style.visibility = "hidden";
|
|
1383
|
+
container.style.left = "-9999px";
|
|
1384
|
+
container.style.top = "-9999px";
|
|
1385
|
+
container.style.fontSize = style.fontSize;
|
|
1386
|
+
container.style.fontFamily = style.fontFamily;
|
|
1387
|
+
container.style.fontWeight = style.fontWeight ?? "normal";
|
|
1388
|
+
container.style.whiteSpace = "pre-wrap";
|
|
1389
|
+
container.style.wordBreak = "break-word";
|
|
1390
|
+
if (style.maxWidth) {
|
|
1391
|
+
container.style.maxWidth = `${style.maxWidth}px`;
|
|
1392
|
+
}
|
|
1393
|
+
container.innerHTML = inlineNodesToHtml(content);
|
|
1394
|
+
document.body.appendChild(container);
|
|
1395
|
+
const rect = container.getBoundingClientRect();
|
|
1396
|
+
const dimensions = {
|
|
1397
|
+
width: Math.ceil(rect.width),
|
|
1398
|
+
height: Math.ceil(rect.height)
|
|
1399
|
+
};
|
|
1400
|
+
document.body.removeChild(container);
|
|
1401
|
+
measurementCache.set(content, dimensions);
|
|
1402
|
+
return dimensions;
|
|
1403
|
+
}
|
|
1404
|
+
function inlineNodesToHtml(nodes) {
|
|
1405
|
+
return nodes.map((node) => {
|
|
1406
|
+
switch (node.type) {
|
|
1407
|
+
case "text":
|
|
1408
|
+
return escapeHtml(node.value);
|
|
1409
|
+
case "strong":
|
|
1410
|
+
return `<strong>${inlineNodesToHtml(node.children)}</strong>`;
|
|
1411
|
+
case "emphasis":
|
|
1412
|
+
return `<em>${inlineNodesToHtml(node.children)}</em>`;
|
|
1413
|
+
case "delete":
|
|
1414
|
+
return `<del>${inlineNodesToHtml(node.children)}</del>`;
|
|
1415
|
+
case "inlineCode":
|
|
1416
|
+
return `<code>${escapeHtml(node.value)}</code>`;
|
|
1417
|
+
case "link":
|
|
1418
|
+
return `<a href="${escapeHtml(node.url)}">${inlineNodesToHtml(node.children)}</a>`;
|
|
1419
|
+
case "image":
|
|
1420
|
+
return `<img src="${escapeHtml(node.src)}" alt="${escapeHtml(node.alt ?? "")}" />`;
|
|
1421
|
+
case "break":
|
|
1422
|
+
return "<br />";
|
|
1423
|
+
default:
|
|
1424
|
+
return "";
|
|
1425
|
+
}
|
|
1426
|
+
}).join("");
|
|
1427
|
+
}
|
|
1428
|
+
function escapeHtml(str) {
|
|
1429
|
+
const div = document.createElement("div");
|
|
1430
|
+
div.textContent = str;
|
|
1431
|
+
return div.innerHTML;
|
|
1432
|
+
}
|
|
1433
|
+
function measureText(content, style) {
|
|
1434
|
+
if (typeof content === "string") {
|
|
1435
|
+
return measurePlainText(content, style);
|
|
1436
|
+
}
|
|
1437
|
+
return measureHtmlText(content, style);
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
// src/graph/layout.ts
|
|
1326
1441
|
var RANKDIR_MAP = {
|
|
1327
1442
|
"top-down": "TB",
|
|
1328
1443
|
"left-right": "LR",
|
|
@@ -1345,10 +1460,17 @@ function computeDagreLayout(nodes, edges, direction = "top-down") {
|
|
|
1345
1460
|
});
|
|
1346
1461
|
g.setDefaultEdgeLabel(() => ({}));
|
|
1347
1462
|
for (const node of nodes) {
|
|
1463
|
+
const labelDimensions = measureText(node.label, {
|
|
1464
|
+
fontSize: "13px",
|
|
1465
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
1466
|
+
maxWidth: 200
|
|
1467
|
+
});
|
|
1468
|
+
const nodeWidth = Math.max(120, Math.min(250, labelDimensions.width + 40));
|
|
1469
|
+
const nodeHeight = Math.max(40, labelDimensions.height + 20);
|
|
1348
1470
|
g.setNode(node.id, {
|
|
1349
1471
|
label: node.label,
|
|
1350
|
-
width:
|
|
1351
|
-
height:
|
|
1472
|
+
width: nodeWidth,
|
|
1473
|
+
height: nodeHeight
|
|
1352
1474
|
});
|
|
1353
1475
|
}
|
|
1354
1476
|
for (const edge of edges) {
|
|
@@ -1455,6 +1577,326 @@ function computeForceLayout(nodes, edges) {
|
|
|
1455
1577
|
height: maxY + LAYOUT_PADDING
|
|
1456
1578
|
};
|
|
1457
1579
|
}
|
|
1580
|
+
function useZoomInteraction({
|
|
1581
|
+
svgRef,
|
|
1582
|
+
rootRef,
|
|
1583
|
+
interactionMode
|
|
1584
|
+
}) {
|
|
1585
|
+
const [isActive, setIsActive] = react.useState(interactionMode === "always");
|
|
1586
|
+
const [hasAttemptedScroll, setHasAttemptedScroll] = react.useState(false);
|
|
1587
|
+
const containerRef = react.useRef(null);
|
|
1588
|
+
react.useEffect(() => {
|
|
1589
|
+
setIsActive(interactionMode === "always");
|
|
1590
|
+
setHasAttemptedScroll(false);
|
|
1591
|
+
}, [interactionMode]);
|
|
1592
|
+
const filterFunction = react.useCallback(
|
|
1593
|
+
(event) => {
|
|
1594
|
+
if (interactionMode === "always") {
|
|
1595
|
+
return true;
|
|
1596
|
+
}
|
|
1597
|
+
if (interactionMode === "modifier-key") {
|
|
1598
|
+
if (event.type === "mousedown") return true;
|
|
1599
|
+
if (event.type === "wheel") {
|
|
1600
|
+
const wheelEvent = event;
|
|
1601
|
+
const hasModifier = wheelEvent.altKey;
|
|
1602
|
+
if (!hasModifier && !hasAttemptedScroll) {
|
|
1603
|
+
setHasAttemptedScroll(true);
|
|
1604
|
+
setTimeout(() => setHasAttemptedScroll(false), 3e3);
|
|
1605
|
+
}
|
|
1606
|
+
return hasModifier;
|
|
1607
|
+
}
|
|
1608
|
+
return true;
|
|
1609
|
+
}
|
|
1610
|
+
if (interactionMode === "click-to-activate") {
|
|
1611
|
+
return isActive;
|
|
1612
|
+
}
|
|
1613
|
+
return true;
|
|
1614
|
+
},
|
|
1615
|
+
[interactionMode, isActive, hasAttemptedScroll]
|
|
1616
|
+
);
|
|
1617
|
+
react.useEffect(() => {
|
|
1618
|
+
if (interactionMode !== "modifier-key" || !svgRef.current) return;
|
|
1619
|
+
const svg = svgRef.current;
|
|
1620
|
+
const container = svg.parentElement;
|
|
1621
|
+
if (!container) return;
|
|
1622
|
+
const handleWheel = (event) => {
|
|
1623
|
+
const target = event.target;
|
|
1624
|
+
if (event.altKey && svg.contains(target)) {
|
|
1625
|
+
event.preventDefault();
|
|
1626
|
+
event.stopPropagation();
|
|
1627
|
+
}
|
|
1628
|
+
};
|
|
1629
|
+
container.addEventListener("wheel", handleWheel, { passive: false, capture: true });
|
|
1630
|
+
return () => {
|
|
1631
|
+
container.removeEventListener("wheel", handleWheel, { capture: true });
|
|
1632
|
+
};
|
|
1633
|
+
}, [interactionMode, svgRef]);
|
|
1634
|
+
const zoomBehavior = react.useMemo(() => {
|
|
1635
|
+
const zoom3 = d32__namespace.zoom().scaleExtent([0.1, 4]);
|
|
1636
|
+
if (typeof zoom3.filter === "function") {
|
|
1637
|
+
zoom3.filter(filterFunction);
|
|
1638
|
+
}
|
|
1639
|
+
zoom3.on("zoom", (event) => {
|
|
1640
|
+
if (rootRef.current) {
|
|
1641
|
+
d32__namespace.select(rootRef.current).attr("transform", event.transform.toString());
|
|
1642
|
+
}
|
|
1643
|
+
});
|
|
1644
|
+
return zoom3;
|
|
1645
|
+
}, [filterFunction, rootRef]);
|
|
1646
|
+
const handleActivate = react.useCallback(() => {
|
|
1647
|
+
if (interactionMode === "click-to-activate") {
|
|
1648
|
+
setIsActive(true);
|
|
1649
|
+
}
|
|
1650
|
+
}, [interactionMode]);
|
|
1651
|
+
react.useEffect(() => {
|
|
1652
|
+
if (interactionMode !== "click-to-activate" || !isActive) return;
|
|
1653
|
+
const handleKeyDown = (e) => {
|
|
1654
|
+
if (e.key === "Escape") {
|
|
1655
|
+
setIsActive(false);
|
|
1656
|
+
}
|
|
1657
|
+
};
|
|
1658
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
1659
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1660
|
+
}, [interactionMode, isActive]);
|
|
1661
|
+
react.useEffect(() => {
|
|
1662
|
+
if (interactionMode !== "click-to-activate" || !isActive) return;
|
|
1663
|
+
const handleClickOutside = (e) => {
|
|
1664
|
+
const container = svgRef.current?.parentElement;
|
|
1665
|
+
if (container && !container.contains(e.target)) {
|
|
1666
|
+
setIsActive(false);
|
|
1667
|
+
}
|
|
1668
|
+
};
|
|
1669
|
+
document.addEventListener("click", handleClickOutside, true);
|
|
1670
|
+
return () => document.removeEventListener("click", handleClickOutside, true);
|
|
1671
|
+
}, [interactionMode, isActive, svgRef]);
|
|
1672
|
+
react.useEffect(() => {
|
|
1673
|
+
if (svgRef.current) {
|
|
1674
|
+
containerRef.current = svgRef.current.parentElement;
|
|
1675
|
+
}
|
|
1676
|
+
}, [svgRef]);
|
|
1677
|
+
const overlayProps = react.useMemo(() => {
|
|
1678
|
+
if (interactionMode === "always") return null;
|
|
1679
|
+
if (interactionMode === "modifier-key" && !hasAttemptedScroll) return null;
|
|
1680
|
+
if (interactionMode === "click-to-activate" && isActive) return null;
|
|
1681
|
+
return {
|
|
1682
|
+
mode: interactionMode,
|
|
1683
|
+
isActive,
|
|
1684
|
+
onActivate: handleActivate,
|
|
1685
|
+
width: "100%",
|
|
1686
|
+
height: "100%"
|
|
1687
|
+
};
|
|
1688
|
+
}, [interactionMode, isActive, hasAttemptedScroll, handleActivate]);
|
|
1689
|
+
const zoomIn = react.useCallback(() => {
|
|
1690
|
+
if (!svgRef.current) return;
|
|
1691
|
+
d32__namespace.select(svgRef.current).transition().duration(300).call(zoomBehavior.scaleBy, 1.3);
|
|
1692
|
+
}, [svgRef, zoomBehavior]);
|
|
1693
|
+
const zoomOut = react.useCallback(() => {
|
|
1694
|
+
if (!svgRef.current) return;
|
|
1695
|
+
d32__namespace.select(svgRef.current).transition().duration(300).call(zoomBehavior.scaleBy, 1 / 1.3);
|
|
1696
|
+
}, [svgRef, zoomBehavior]);
|
|
1697
|
+
const resetZoom = react.useCallback(() => {
|
|
1698
|
+
if (!svgRef.current) return;
|
|
1699
|
+
d32__namespace.select(svgRef.current).transition().duration(300).call(zoomBehavior.transform, d32__namespace.zoomIdentity);
|
|
1700
|
+
}, [svgRef, zoomBehavior]);
|
|
1701
|
+
return {
|
|
1702
|
+
isActive,
|
|
1703
|
+
overlayProps,
|
|
1704
|
+
zoomBehavior,
|
|
1705
|
+
zoomIn,
|
|
1706
|
+
zoomOut,
|
|
1707
|
+
resetZoom
|
|
1708
|
+
};
|
|
1709
|
+
}
|
|
1710
|
+
function InteractionOverlay({
|
|
1711
|
+
mode,
|
|
1712
|
+
isActive,
|
|
1713
|
+
onActivate,
|
|
1714
|
+
width,
|
|
1715
|
+
height
|
|
1716
|
+
}) {
|
|
1717
|
+
if (mode === "modifier-key") {
|
|
1718
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1719
|
+
"div",
|
|
1720
|
+
{
|
|
1721
|
+
className: "glyph-interaction-overlay",
|
|
1722
|
+
style: {
|
|
1723
|
+
...OVERLAY_BASE_STYLE,
|
|
1724
|
+
width,
|
|
1725
|
+
height,
|
|
1726
|
+
pointerEvents: "none"
|
|
1727
|
+
},
|
|
1728
|
+
"aria-hidden": "true",
|
|
1729
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: TOOLTIP_STYLE, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: TOOLTIP_TEXT_STYLE, children: "Alt + scroll to zoom" }) })
|
|
1730
|
+
}
|
|
1731
|
+
);
|
|
1732
|
+
}
|
|
1733
|
+
if (mode === "click-to-activate" && !isActive) {
|
|
1734
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1735
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1736
|
+
"div",
|
|
1737
|
+
{
|
|
1738
|
+
className: "glyph-interaction-overlay",
|
|
1739
|
+
style: {
|
|
1740
|
+
...OVERLAY_BASE_STYLE,
|
|
1741
|
+
...ACTIVATION_OVERLAY_STYLE,
|
|
1742
|
+
width,
|
|
1743
|
+
height
|
|
1744
|
+
},
|
|
1745
|
+
onClick: onActivate,
|
|
1746
|
+
role: "button",
|
|
1747
|
+
tabIndex: 0,
|
|
1748
|
+
"aria-label": "Click to activate graph interaction",
|
|
1749
|
+
onKeyDown: (e) => {
|
|
1750
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1751
|
+
e.preventDefault();
|
|
1752
|
+
onActivate();
|
|
1753
|
+
}
|
|
1754
|
+
},
|
|
1755
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: ACTIVATION_TEXT_STYLE, children: "Click to interact" })
|
|
1756
|
+
}
|
|
1757
|
+
),
|
|
1758
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: SR_ONLY_STYLE, role: "status", "aria-live": "polite", "aria-atomic": "true", children: "Graph interaction inactive. Click to activate." })
|
|
1759
|
+
] });
|
|
1760
|
+
}
|
|
1761
|
+
if (mode === "click-to-activate" && isActive) {
|
|
1762
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1763
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1764
|
+
"div",
|
|
1765
|
+
{
|
|
1766
|
+
style: {
|
|
1767
|
+
...OVERLAY_BASE_STYLE,
|
|
1768
|
+
width,
|
|
1769
|
+
height,
|
|
1770
|
+
pointerEvents: "none",
|
|
1771
|
+
border: "2px solid var(--glyph-interaction-active-border, #0a9d7c)",
|
|
1772
|
+
borderRadius: "4px"
|
|
1773
|
+
},
|
|
1774
|
+
"aria-hidden": "true"
|
|
1775
|
+
}
|
|
1776
|
+
),
|
|
1777
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: SR_ONLY_STYLE, role: "status", "aria-live": "polite", "aria-atomic": "true", children: "Graph interaction active. Press Escape to deactivate." })
|
|
1778
|
+
] });
|
|
1779
|
+
}
|
|
1780
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {});
|
|
1781
|
+
}
|
|
1782
|
+
var OVERLAY_BASE_STYLE = {
|
|
1783
|
+
position: "absolute",
|
|
1784
|
+
top: 0,
|
|
1785
|
+
left: 0,
|
|
1786
|
+
display: "flex",
|
|
1787
|
+
alignItems: "center",
|
|
1788
|
+
justifyContent: "center",
|
|
1789
|
+
zIndex: 10
|
|
1790
|
+
};
|
|
1791
|
+
var TOOLTIP_STYLE = {
|
|
1792
|
+
position: "absolute",
|
|
1793
|
+
bottom: "12px",
|
|
1794
|
+
right: "12px",
|
|
1795
|
+
padding: "6px 10px",
|
|
1796
|
+
backgroundColor: "var(--glyph-interaction-tooltip-bg, rgba(26, 32, 53, 0.9))",
|
|
1797
|
+
color: "var(--glyph-interaction-tooltip-text, #f4f6fa)",
|
|
1798
|
+
borderRadius: "4px",
|
|
1799
|
+
fontSize: "12px",
|
|
1800
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
1801
|
+
fontWeight: 500,
|
|
1802
|
+
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
|
|
1803
|
+
pointerEvents: "none"
|
|
1804
|
+
};
|
|
1805
|
+
var TOOLTIP_TEXT_STYLE = {
|
|
1806
|
+
display: "flex",
|
|
1807
|
+
alignItems: "center",
|
|
1808
|
+
gap: "4px"
|
|
1809
|
+
};
|
|
1810
|
+
var ACTIVATION_OVERLAY_STYLE = {
|
|
1811
|
+
backgroundColor: "var(--glyph-interaction-overlay-bg, rgba(244, 246, 250, 0.8))",
|
|
1812
|
+
cursor: "pointer",
|
|
1813
|
+
transition: "background-color 0.2s ease"
|
|
1814
|
+
};
|
|
1815
|
+
var ACTIVATION_TEXT_STYLE = {
|
|
1816
|
+
padding: "12px 20px",
|
|
1817
|
+
backgroundColor: "var(--glyph-interaction-tooltip-bg, rgba(26, 32, 53, 0.9))",
|
|
1818
|
+
color: "var(--glyph-interaction-tooltip-text, #f4f6fa)",
|
|
1819
|
+
borderRadius: "6px",
|
|
1820
|
+
fontSize: "14px",
|
|
1821
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
1822
|
+
fontWeight: 500,
|
|
1823
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.2)"
|
|
1824
|
+
};
|
|
1825
|
+
var SR_ONLY_STYLE = {
|
|
1826
|
+
position: "absolute",
|
|
1827
|
+
width: "1px",
|
|
1828
|
+
height: "1px",
|
|
1829
|
+
padding: 0,
|
|
1830
|
+
margin: "-1px",
|
|
1831
|
+
overflow: "hidden",
|
|
1832
|
+
clip: "rect(0, 0, 0, 0)",
|
|
1833
|
+
whiteSpace: "nowrap",
|
|
1834
|
+
border: 0
|
|
1835
|
+
};
|
|
1836
|
+
function ZoomControls({ onZoomIn, onZoomOut, onReset }) {
|
|
1837
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: CONTROLS_CONTAINER_STYLE, children: [
|
|
1838
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1839
|
+
"button",
|
|
1840
|
+
{
|
|
1841
|
+
onClick: onZoomIn,
|
|
1842
|
+
style: BUTTON_STYLE,
|
|
1843
|
+
"aria-label": "Zoom in",
|
|
1844
|
+
title: "Zoom in",
|
|
1845
|
+
type: "button",
|
|
1846
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", children: [
|
|
1847
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "4", x2: "8", y2: "12", strokeWidth: "2" }),
|
|
1848
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "4", y1: "8", x2: "12", y2: "8", strokeWidth: "2" })
|
|
1849
|
+
] })
|
|
1850
|
+
}
|
|
1851
|
+
),
|
|
1852
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1853
|
+
"button",
|
|
1854
|
+
{
|
|
1855
|
+
onClick: onZoomOut,
|
|
1856
|
+
style: BUTTON_STYLE,
|
|
1857
|
+
"aria-label": "Zoom out",
|
|
1858
|
+
title: "Zoom out",
|
|
1859
|
+
type: "button",
|
|
1860
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "4", y1: "8", x2: "12", y2: "8", strokeWidth: "2" }) })
|
|
1861
|
+
}
|
|
1862
|
+
),
|
|
1863
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1864
|
+
"button",
|
|
1865
|
+
{
|
|
1866
|
+
onClick: onReset,
|
|
1867
|
+
style: BUTTON_STYLE,
|
|
1868
|
+
"aria-label": "Reset zoom",
|
|
1869
|
+
title: "Reset zoom",
|
|
1870
|
+
type: "button",
|
|
1871
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "3", width: "10", height: "10", strokeWidth: "2", rx: "1" }) })
|
|
1872
|
+
}
|
|
1873
|
+
)
|
|
1874
|
+
] });
|
|
1875
|
+
}
|
|
1876
|
+
var CONTROLS_CONTAINER_STYLE = {
|
|
1877
|
+
position: "absolute",
|
|
1878
|
+
top: "12px",
|
|
1879
|
+
right: "12px",
|
|
1880
|
+
display: "flex",
|
|
1881
|
+
flexDirection: "column",
|
|
1882
|
+
gap: "4px",
|
|
1883
|
+
zIndex: 10
|
|
1884
|
+
};
|
|
1885
|
+
var BUTTON_STYLE = {
|
|
1886
|
+
width: "32px",
|
|
1887
|
+
height: "32px",
|
|
1888
|
+
padding: "0",
|
|
1889
|
+
display: "flex",
|
|
1890
|
+
alignItems: "center",
|
|
1891
|
+
justifyContent: "center",
|
|
1892
|
+
backgroundColor: "var(--glyph-surface-raised, #f4f6fa)",
|
|
1893
|
+
border: "1px solid var(--glyph-border, #d0d8e4)",
|
|
1894
|
+
borderRadius: "4px",
|
|
1895
|
+
color: "var(--glyph-text, #1a2035)",
|
|
1896
|
+
cursor: "pointer",
|
|
1897
|
+
transition: "all 0.2s ease",
|
|
1898
|
+
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)"
|
|
1899
|
+
};
|
|
1458
1900
|
var GROUP_PALETTE = [
|
|
1459
1901
|
"#00d4aa",
|
|
1460
1902
|
// cyan-green
|
|
@@ -1501,7 +1943,7 @@ function getThemeVar(container, varName, fallback) {
|
|
|
1501
1943
|
return getComputedStyle(container).getPropertyValue(varName).trim() || fallback;
|
|
1502
1944
|
}
|
|
1503
1945
|
var ARROW_MARKER_ID = "glyph-graph-arrowhead";
|
|
1504
|
-
function renderGraph(svgElement, layout, groupIndex, outgoingRefs, onNavigate, onNodeClick) {
|
|
1946
|
+
function renderGraph(svgElement, layout, groupIndex, outgoingRefs, onNavigate, zoomBehavior, onNodeClick) {
|
|
1505
1947
|
const svg = d32__namespace.select(svgElement);
|
|
1506
1948
|
svg.selectAll("*").remove();
|
|
1507
1949
|
const width = Math.max(layout.width, 200);
|
|
@@ -1514,9 +1956,6 @@ function renderGraph(svgElement, layout, groupIndex, outgoingRefs, onNavigate, o
|
|
|
1514
1956
|
const nodeStrokeWidth = getThemeVar(container, "--glyph-node-stroke-width", "1.5");
|
|
1515
1957
|
const nodeFillOpacity = getThemeVar(container, "--glyph-node-fill-opacity", "0.85");
|
|
1516
1958
|
const root = svg.append("g").attr("class", "glyph-graph-root");
|
|
1517
|
-
const zoomBehavior = d32__namespace.zoom().scaleExtent([0.1, 4]).on("zoom", (event) => {
|
|
1518
|
-
root.attr("transform", event.transform.toString());
|
|
1519
|
-
});
|
|
1520
1959
|
svg.call(zoomBehavior);
|
|
1521
1960
|
const navigableNodes = /* @__PURE__ */ new Set();
|
|
1522
1961
|
const refByAnchor = /* @__PURE__ */ new Map();
|
|
@@ -1534,7 +1973,7 @@ function renderGraph(svgElement, layout, groupIndex, outgoingRefs, onNavigate, o
|
|
|
1534
1973
|
if (edge.label) {
|
|
1535
1974
|
const mid = edge.points[Math.floor(edge.points.length / 2)];
|
|
1536
1975
|
if (mid) {
|
|
1537
|
-
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);
|
|
1976
|
+
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));
|
|
1538
1977
|
}
|
|
1539
1978
|
}
|
|
1540
1979
|
}
|
|
@@ -1551,7 +1990,7 @@ function renderGraph(svgElement, layout, groupIndex, outgoingRefs, onNavigate, o
|
|
|
1551
1990
|
} else {
|
|
1552
1991
|
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);
|
|
1553
1992
|
}
|
|
1554
|
-
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);
|
|
1993
|
+
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));
|
|
1555
1994
|
if (isNavigable || onNodeClick) {
|
|
1556
1995
|
nodeG.attr("cursor", "pointer");
|
|
1557
1996
|
nodeG.on("click", () => {
|
|
@@ -1559,7 +1998,7 @@ function renderGraph(svgElement, layout, groupIndex, outgoingRefs, onNavigate, o
|
|
|
1559
1998
|
const ref = refByAnchor.get(node.id);
|
|
1560
1999
|
if (ref) onNavigate(ref);
|
|
1561
2000
|
}
|
|
1562
|
-
onNodeClick?.(node.id, node.label);
|
|
2001
|
+
onNodeClick?.(node.id, inlineToText(node.label));
|
|
1563
2002
|
});
|
|
1564
2003
|
}
|
|
1565
2004
|
}
|
|
@@ -1573,6 +2012,7 @@ function Graph({
|
|
|
1573
2012
|
container
|
|
1574
2013
|
}) {
|
|
1575
2014
|
const svgRef = react.useRef(null);
|
|
2015
|
+
const rootRef = react.useRef(null);
|
|
1576
2016
|
const groupIndex = react.useRef(/* @__PURE__ */ new Map());
|
|
1577
2017
|
const layoutResult = react.useMemo(() => {
|
|
1578
2018
|
const direction = resolveLayout(data);
|
|
@@ -1581,6 +2021,12 @@ function Graph({
|
|
|
1581
2021
|
}
|
|
1582
2022
|
return computeDagreLayout(data.nodes, data.edges, direction);
|
|
1583
2023
|
}, [data]);
|
|
2024
|
+
const { overlayProps, zoomBehavior, zoomIn, zoomOut, resetZoom } = useZoomInteraction({
|
|
2025
|
+
svgRef,
|
|
2026
|
+
rootRef,
|
|
2027
|
+
interactionMode: data.interactionMode ?? "modifier-key",
|
|
2028
|
+
blockId: block.id
|
|
2029
|
+
});
|
|
1584
2030
|
const handleNodeClick = react.useMemo(() => {
|
|
1585
2031
|
if (!onInteraction) return void 0;
|
|
1586
2032
|
return (nodeId, nodeLabel) => {
|
|
@@ -1601,27 +2047,36 @@ function Graph({
|
|
|
1601
2047
|
groupIndex.current,
|
|
1602
2048
|
outgoingRefs,
|
|
1603
2049
|
onNavigate,
|
|
2050
|
+
zoomBehavior,
|
|
1604
2051
|
handleNodeClick
|
|
1605
2052
|
);
|
|
1606
|
-
|
|
2053
|
+
const rootElement = svgRef.current.querySelector(".glyph-graph-root");
|
|
2054
|
+
if (rootElement) {
|
|
2055
|
+
rootRef.current = rootElement;
|
|
2056
|
+
}
|
|
2057
|
+
}, [layoutResult, outgoingRefs, onNavigate, zoomBehavior, handleNodeClick]);
|
|
1607
2058
|
const ariaLabel = `${data.type} graph with ${data.nodes.length} nodes and ${data.edges.length} edges`;
|
|
1608
2059
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "glyph-graph-container", children: [
|
|
1609
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
2060
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
|
|
2061
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2062
|
+
"svg",
|
|
2063
|
+
{
|
|
2064
|
+
ref: svgRef,
|
|
2065
|
+
role: "img",
|
|
2066
|
+
"aria-label": ariaLabel,
|
|
2067
|
+
width: "100%",
|
|
2068
|
+
height: "100%",
|
|
2069
|
+
style: {
|
|
2070
|
+
minHeight: container.tier === "compact" ? 200 : 300,
|
|
2071
|
+
maxHeight: container.tier === "compact" ? 500 : 700,
|
|
2072
|
+
display: "block"
|
|
2073
|
+
}
|
|
1621
2074
|
}
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
2075
|
+
),
|
|
2076
|
+
overlayProps && /* @__PURE__ */ jsxRuntime.jsx(InteractionOverlay, { ...overlayProps }),
|
|
2077
|
+
/* @__PURE__ */ jsxRuntime.jsx(ZoomControls, { onZoomIn: zoomIn, onZoomOut: zoomOut, onReset: resetZoom })
|
|
2078
|
+
] }),
|
|
2079
|
+
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "sr-only", "aria-label": "Graph data", style: SR_ONLY_STYLE2, children: [
|
|
1625
2080
|
/* @__PURE__ */ jsxRuntime.jsx("caption", { children: "Graph nodes and connections" }),
|
|
1626
2081
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1627
2082
|
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: "Node" }),
|
|
@@ -1635,7 +2090,7 @@ function Graph({
|
|
|
1635
2090
|
return `${dir} ${target}${e.label ? ` (${e.label})` : ""}`;
|
|
1636
2091
|
}).join(", ");
|
|
1637
2092
|
return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1638
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { children: node.label }),
|
|
2093
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { children: inlineToText(node.label) }),
|
|
1639
2094
|
/* @__PURE__ */ jsxRuntime.jsx("td", { children: node.group ?? "" }),
|
|
1640
2095
|
/* @__PURE__ */ jsxRuntime.jsx("td", { children: connections })
|
|
1641
2096
|
] }, node.id);
|
|
@@ -1643,7 +2098,7 @@ function Graph({
|
|
|
1643
2098
|
] })
|
|
1644
2099
|
] });
|
|
1645
2100
|
}
|
|
1646
|
-
var
|
|
2101
|
+
var SR_ONLY_STYLE2 = {
|
|
1647
2102
|
position: "absolute",
|
|
1648
2103
|
width: "1px",
|
|
1649
2104
|
height: "1px",
|
|
@@ -1669,14 +2124,20 @@ var NODE_SEP2 = 60;
|
|
|
1669
2124
|
var RANK_SEP2 = 80;
|
|
1670
2125
|
var EDGE_SEP2 = 10;
|
|
1671
2126
|
var LAYOUT_PADDING2 = 40;
|
|
1672
|
-
var CHAR_WIDTH = 7.5;
|
|
1673
2127
|
function computeEntitySize(entity) {
|
|
1674
2128
|
const attrs = entity.attributes ?? [];
|
|
1675
2129
|
const height = ENTITY_HEADER_HEIGHT + attrs.length * ENTITY_ATTR_HEIGHT + ENTITY_PADDING;
|
|
1676
|
-
|
|
2130
|
+
const labelDimensions = measureText(entity.label, {
|
|
2131
|
+
fontSize: "14px",
|
|
2132
|
+
fontFamily: "Inter, system-ui, sans-serif"
|
|
2133
|
+
});
|
|
2134
|
+
let maxTextWidth = labelDimensions.width;
|
|
1677
2135
|
for (const attr of attrs) {
|
|
1678
|
-
const
|
|
1679
|
-
|
|
2136
|
+
const attrNameDimensions = measureText(attr.name, {
|
|
2137
|
+
fontSize: "12px",
|
|
2138
|
+
fontFamily: "ui-monospace, monospace"
|
|
2139
|
+
});
|
|
2140
|
+
maxTextWidth = Math.max(maxTextWidth, attrNameDimensions.width + 100);
|
|
1680
2141
|
}
|
|
1681
2142
|
const width = Math.max(ENTITY_MIN_WIDTH, maxTextWidth + ENTITY_PADDING * 2 + 16);
|
|
1682
2143
|
return { width, height };
|
|
@@ -1767,16 +2228,13 @@ function drawCrowsFoot(g, x, y, angle, symbol) {
|
|
|
1767
2228
|
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)");
|
|
1768
2229
|
}
|
|
1769
2230
|
}
|
|
1770
|
-
function renderRelation(svgElement, layout) {
|
|
2231
|
+
function renderRelation(svgElement, layout, zoomBehavior) {
|
|
1771
2232
|
const svg = d32__namespace.select(svgElement);
|
|
1772
2233
|
svg.selectAll("*").remove();
|
|
1773
2234
|
const width = Math.max(layout.width, 200);
|
|
1774
2235
|
const height = Math.max(layout.height, 200);
|
|
1775
2236
|
svg.attr("viewBox", `0 0 ${width} ${height}`);
|
|
1776
2237
|
const root = svg.append("g").attr("class", "glyph-relation-root");
|
|
1777
|
-
const zoomBehavior = d32__namespace.zoom().scaleExtent([0.1, 4]).on("zoom", (event) => {
|
|
1778
|
-
root.attr("transform", event.transform.toString());
|
|
1779
|
-
});
|
|
1780
2238
|
svg.call(zoomBehavior);
|
|
1781
2239
|
const entityMap = /* @__PURE__ */ new Map();
|
|
1782
2240
|
for (const entity of layout.entities) {
|
|
@@ -1803,7 +2261,7 @@ function renderRelation(svgElement, layout) {
|
|
|
1803
2261
|
if (rel.label) {
|
|
1804
2262
|
const mid = rel.points[Math.floor(rel.points.length / 2)];
|
|
1805
2263
|
if (mid) {
|
|
1806
|
-
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);
|
|
2264
|
+
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));
|
|
1807
2265
|
}
|
|
1808
2266
|
}
|
|
1809
2267
|
const pFirst = rel.points[0];
|
|
@@ -1831,7 +2289,7 @@ function renderRelation(svgElement, layout) {
|
|
|
1831
2289
|
const headerHeight = ENTITY_HEADER_HEIGHT;
|
|
1832
2290
|
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)");
|
|
1833
2291
|
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)");
|
|
1834
|
-
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);
|
|
2292
|
+
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));
|
|
1835
2293
|
if (attrs.length > 0) {
|
|
1836
2294
|
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);
|
|
1837
2295
|
}
|
|
@@ -1840,7 +2298,7 @@ function renderRelation(svgElement, layout) {
|
|
|
1840
2298
|
if (!attr) continue;
|
|
1841
2299
|
const attrY = y + headerHeight + i * ENTITY_ATTR_HEIGHT + ENTITY_ATTR_HEIGHT / 2 + 4;
|
|
1842
2300
|
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)");
|
|
1843
|
-
const nameSpan = textEl.append("tspan").text(attr.name);
|
|
2301
|
+
const nameSpan = textEl.append("tspan").text(inlineToText(attr.name));
|
|
1844
2302
|
if (attr.primaryKey) {
|
|
1845
2303
|
nameSpan.attr("font-weight", "bold").attr("text-decoration", "underline");
|
|
1846
2304
|
}
|
|
@@ -1848,29 +2306,44 @@ function renderRelation(svgElement, layout) {
|
|
|
1848
2306
|
}
|
|
1849
2307
|
}
|
|
1850
2308
|
}
|
|
1851
|
-
function Relation({ data }) {
|
|
2309
|
+
function Relation({ data, block }) {
|
|
1852
2310
|
const svgRef = react.useRef(null);
|
|
2311
|
+
const rootRef = react.useRef(null);
|
|
1853
2312
|
const layoutResult = react.useMemo(() => {
|
|
1854
2313
|
return computeRelationLayout(data);
|
|
1855
2314
|
}, [data]);
|
|
2315
|
+
const { overlayProps, zoomBehavior, zoomIn, zoomOut, resetZoom } = useZoomInteraction({
|
|
2316
|
+
svgRef,
|
|
2317
|
+
rootRef,
|
|
2318
|
+
interactionMode: data.interactionMode ?? "modifier-key",
|
|
2319
|
+
blockId: block.id
|
|
2320
|
+
});
|
|
1856
2321
|
react.useEffect(() => {
|
|
1857
2322
|
if (!svgRef.current) return;
|
|
1858
|
-
renderRelation(svgRef.current, layoutResult);
|
|
1859
|
-
|
|
2323
|
+
renderRelation(svgRef.current, layoutResult, zoomBehavior);
|
|
2324
|
+
const rootElement = svgRef.current.querySelector(".glyph-relation-root");
|
|
2325
|
+
if (rootElement) {
|
|
2326
|
+
rootRef.current = rootElement;
|
|
2327
|
+
}
|
|
2328
|
+
}, [layoutResult, zoomBehavior]);
|
|
1860
2329
|
const ariaLabel = `Entity-relationship diagram with ${data.entities.length} entities and ${data.relationships.length} relationships`;
|
|
1861
2330
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "glyph-relation-container", children: [
|
|
1862
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
2331
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
|
|
2332
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2333
|
+
"svg",
|
|
2334
|
+
{
|
|
2335
|
+
ref: svgRef,
|
|
2336
|
+
role: "img",
|
|
2337
|
+
"aria-label": ariaLabel,
|
|
2338
|
+
width: "100%",
|
|
2339
|
+
height: "100%",
|
|
2340
|
+
style: { minHeight: 300, maxHeight: 700, display: "block" }
|
|
2341
|
+
}
|
|
2342
|
+
),
|
|
2343
|
+
overlayProps && /* @__PURE__ */ jsxRuntime.jsx(InteractionOverlay, { ...overlayProps }),
|
|
2344
|
+
/* @__PURE__ */ jsxRuntime.jsx(ZoomControls, { onZoomIn: zoomIn, onZoomOut: zoomOut, onReset: resetZoom })
|
|
2345
|
+
] }),
|
|
2346
|
+
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "sr-only", "aria-label": "Entity-relationship data", style: SR_ONLY_STYLE3, children: [
|
|
1874
2347
|
/* @__PURE__ */ jsxRuntime.jsx("caption", { children: "Entities and relationships" }),
|
|
1875
2348
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1876
2349
|
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: "Entity" }),
|
|
@@ -1885,7 +2358,7 @@ function Relation({ data }) {
|
|
|
1885
2358
|
return `${dir} ${target} [${r.cardinality}]${r.label ? ` (${r.label})` : ""}`;
|
|
1886
2359
|
}).join(", ");
|
|
1887
2360
|
return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
1888
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { children: entity.label }),
|
|
2361
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { children: inlineToText(entity.label) }),
|
|
1889
2362
|
/* @__PURE__ */ jsxRuntime.jsx("td", { children: attrs }),
|
|
1890
2363
|
/* @__PURE__ */ jsxRuntime.jsx("td", { children: rels })
|
|
1891
2364
|
] }, entity.id);
|
|
@@ -1893,7 +2366,7 @@ function Relation({ data }) {
|
|
|
1893
2366
|
] })
|
|
1894
2367
|
] });
|
|
1895
2368
|
}
|
|
1896
|
-
var
|
|
2369
|
+
var SR_ONLY_STYLE3 = {
|
|
1897
2370
|
position: "absolute",
|
|
1898
2371
|
width: "1px",
|
|
1899
2372
|
height: "1px",
|
|
@@ -2423,9 +2896,9 @@ function CodeDiff({ data, block }) {
|
|
|
2423
2896
|
}
|
|
2424
2897
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { id: baseId, role: "region", "aria-label": summary, style: containerStyle11, children: [
|
|
2425
2898
|
(beforeLabel || afterLabel) && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: labelBarStyle, children: [
|
|
2426
|
-
beforeLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { children: beforeLabel }),
|
|
2899
|
+
beforeLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: beforeLabel }) }),
|
|
2427
2900
|
beforeLabel && afterLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u2192" }),
|
|
2428
|
-
afterLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { children: afterLabel })
|
|
2901
|
+
afterLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: afterLabel }) })
|
|
2429
2902
|
] }),
|
|
2430
2903
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsx("table", { role: "grid", style: tableStyle2, children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: diffLines.map((line6, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2431
2904
|
"tr",
|
|
@@ -2529,7 +3002,7 @@ function renderNodeShape(nodeG, node, fillOpacity, strokeWidth) {
|
|
|
2529
3002
|
}
|
|
2530
3003
|
}
|
|
2531
3004
|
}
|
|
2532
|
-
function renderFlowchart(svgElement, layout) {
|
|
3005
|
+
function renderFlowchart(svgElement, layout, zoomBehavior) {
|
|
2533
3006
|
const svg = d32__namespace.select(svgElement);
|
|
2534
3007
|
svg.selectAll("*").remove();
|
|
2535
3008
|
const width = Math.max(layout.width, 200);
|
|
@@ -2541,9 +3014,6 @@ function renderFlowchart(svgElement, layout) {
|
|
|
2541
3014
|
const nodeStrokeWidth = getThemeVar2(container, "--glyph-node-stroke-width", "1.5");
|
|
2542
3015
|
const nodeFillOpacity = getThemeVar2(container, "--glyph-node-fill-opacity", "0.85");
|
|
2543
3016
|
const root = svg.append("g").attr("class", "glyph-flowchart-root");
|
|
2544
|
-
const zoomBehavior = d32__namespace.zoom().scaleExtent([0.1, 4]).on("zoom", (event) => {
|
|
2545
|
-
root.attr("transform", event.transform.toString());
|
|
2546
|
-
});
|
|
2547
3017
|
svg.call(zoomBehavior);
|
|
2548
3018
|
const lineGen = d32__namespace.line().x((d) => d.x).y((d) => d.y).curve(d32__namespace.curveBasis);
|
|
2549
3019
|
const edgeGroup = root.append("g").attr("class", "glyph-flowchart-edges");
|
|
@@ -2553,7 +3023,7 @@ function renderFlowchart(svgElement, layout) {
|
|
|
2553
3023
|
if (edge.label) {
|
|
2554
3024
|
const mid = edge.points[Math.floor(edge.points.length / 2)];
|
|
2555
3025
|
if (mid) {
|
|
2556
|
-
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);
|
|
3026
|
+
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));
|
|
2557
3027
|
}
|
|
2558
3028
|
}
|
|
2559
3029
|
}
|
|
@@ -2561,19 +3031,34 @@ function renderFlowchart(svgElement, layout) {
|
|
|
2561
3031
|
for (const node of layout.nodes) {
|
|
2562
3032
|
const nodeG = nodeGroup.append("g").attr("class", "glyph-flowchart-node");
|
|
2563
3033
|
renderNodeShape(nodeG, node, nodeFillOpacity, nodeStrokeWidth);
|
|
2564
|
-
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);
|
|
3034
|
+
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));
|
|
2565
3035
|
}
|
|
2566
3036
|
}
|
|
2567
|
-
function Flowchart({
|
|
3037
|
+
function Flowchart({
|
|
3038
|
+
data,
|
|
3039
|
+
block,
|
|
3040
|
+
container
|
|
3041
|
+
}) {
|
|
2568
3042
|
const svgRef = react.useRef(null);
|
|
3043
|
+
const rootRef = react.useRef(null);
|
|
2569
3044
|
const layoutResult = react.useMemo(() => computeLayout(data.nodes, data.edges, data.direction), [data]);
|
|
3045
|
+
const { overlayProps, zoomBehavior, zoomIn, zoomOut, resetZoom } = useZoomInteraction({
|
|
3046
|
+
svgRef,
|
|
3047
|
+
rootRef,
|
|
3048
|
+
interactionMode: data.interactionMode ?? "modifier-key",
|
|
3049
|
+
blockId: block.id
|
|
3050
|
+
});
|
|
2570
3051
|
react.useEffect(() => {
|
|
2571
3052
|
if (!svgRef.current) return;
|
|
2572
|
-
renderFlowchart(svgRef.current, layoutResult);
|
|
2573
|
-
|
|
3053
|
+
renderFlowchart(svgRef.current, layoutResult, zoomBehavior);
|
|
3054
|
+
const rootElement = svgRef.current.querySelector(".glyph-flowchart-root");
|
|
3055
|
+
if (rootElement) {
|
|
3056
|
+
rootRef.current = rootElement;
|
|
3057
|
+
}
|
|
3058
|
+
}, [layoutResult, zoomBehavior]);
|
|
2574
3059
|
const nodeCount = data.nodes.length;
|
|
2575
3060
|
const edgeCount = data.edges.length;
|
|
2576
|
-
const ariaLabel = data.title ? `${data.title}: flowchart with ${nodeCount} nodes and ${edgeCount} edges` : `Flowchart with ${nodeCount} nodes and ${edgeCount} edges`;
|
|
3061
|
+
const ariaLabel = data.title ? `${inlineToText(data.title)}: flowchart with ${nodeCount} nodes and ${edgeCount} edges` : `Flowchart with ${nodeCount} nodes and ${edgeCount} edges`;
|
|
2577
3062
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "glyph-flowchart-container", children: [
|
|
2578
3063
|
data.title && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2579
3064
|
"div",
|
|
@@ -2585,25 +3070,29 @@ function Flowchart({ data, container }) {
|
|
|
2585
3070
|
color: "var(--glyph-heading, #edf0f5)",
|
|
2586
3071
|
marginBottom: "0.5rem"
|
|
2587
3072
|
},
|
|
2588
|
-
children: data.title
|
|
3073
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: data.title })
|
|
2589
3074
|
}
|
|
2590
3075
|
),
|
|
2591
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
3076
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
|
|
3077
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3078
|
+
"svg",
|
|
3079
|
+
{
|
|
3080
|
+
ref: svgRef,
|
|
3081
|
+
role: "img",
|
|
3082
|
+
"aria-label": ariaLabel,
|
|
3083
|
+
width: "100%",
|
|
3084
|
+
height: "100%",
|
|
3085
|
+
style: {
|
|
3086
|
+
minHeight: container.tier === "compact" ? 200 : 300,
|
|
3087
|
+
maxHeight: container.tier === "compact" ? 500 : 700,
|
|
3088
|
+
display: "block"
|
|
3089
|
+
}
|
|
2603
3090
|
}
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
3091
|
+
),
|
|
3092
|
+
overlayProps && /* @__PURE__ */ jsxRuntime.jsx(InteractionOverlay, { ...overlayProps }),
|
|
3093
|
+
/* @__PURE__ */ jsxRuntime.jsx(ZoomControls, { onZoomIn: zoomIn, onZoomOut: zoomOut, onReset: resetZoom })
|
|
3094
|
+
] }),
|
|
3095
|
+
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "sr-only", "aria-label": "Flowchart data", style: SR_ONLY_STYLE4, children: [
|
|
2607
3096
|
/* @__PURE__ */ jsxRuntime.jsx("caption", { children: "Flowchart nodes and connections" }),
|
|
2608
3097
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2609
3098
|
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: "Node" }),
|
|
@@ -2614,10 +3103,10 @@ function Flowchart({ data, container }) {
|
|
|
2614
3103
|
const connections = data.edges.filter((e) => e.from === node.id || e.to === node.id).map((e) => {
|
|
2615
3104
|
const target = e.from === node.id ? e.to : e.from;
|
|
2616
3105
|
const dir = e.from === node.id ? "->" : "<-";
|
|
2617
|
-
return `${dir} ${target}${e.label ? ` (${e.label})` : ""}`;
|
|
3106
|
+
return `${dir} ${target}${e.label ? ` (${inlineToText(e.label)})` : ""}`;
|
|
2618
3107
|
}).join(", ");
|
|
2619
3108
|
return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
2620
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { children: node.label }),
|
|
3109
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { children: inlineToText(node.label) }),
|
|
2621
3110
|
/* @__PURE__ */ jsxRuntime.jsx("td", { children: node.type }),
|
|
2622
3111
|
/* @__PURE__ */ jsxRuntime.jsx("td", { children: connections })
|
|
2623
3112
|
] }, node.id);
|
|
@@ -2625,7 +3114,7 @@ function Flowchart({ data, container }) {
|
|
|
2625
3114
|
] })
|
|
2626
3115
|
] });
|
|
2627
3116
|
}
|
|
2628
|
-
var
|
|
3117
|
+
var SR_ONLY_STYLE4 = {
|
|
2629
3118
|
position: "absolute",
|
|
2630
3119
|
width: "1px",
|
|
2631
3120
|
height: "1px",
|
|
@@ -3039,20 +3528,24 @@ function renderActorBox(actor, cx, y, keyPrefix, width = ACTOR_WIDTH, height = A
|
|
|
3039
3528
|
strokeWidth: 1.5
|
|
3040
3529
|
}
|
|
3041
3530
|
),
|
|
3042
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3043
|
-
"
|
|
3531
|
+
/* @__PURE__ */ jsxRuntime.jsx("foreignObject", { x: cx - width / 2, y, width, height, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3532
|
+
"div",
|
|
3044
3533
|
{
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3534
|
+
style: {
|
|
3535
|
+
display: "flex",
|
|
3536
|
+
alignItems: "center",
|
|
3537
|
+
justifyContent: "center",
|
|
3538
|
+
width: "100%",
|
|
3539
|
+
height: "100%",
|
|
3540
|
+
fontSize,
|
|
3541
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
3542
|
+
fontWeight: 600,
|
|
3543
|
+
color: "var(--glyph-text, #d4dae3)",
|
|
3544
|
+
textAlign: "center"
|
|
3545
|
+
},
|
|
3546
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: actor.label })
|
|
3054
3547
|
}
|
|
3055
|
-
)
|
|
3548
|
+
) })
|
|
3056
3549
|
] }, `${keyPrefix}-${actor.id}`);
|
|
3057
3550
|
}
|
|
3058
3551
|
function renderSelfMessage(x, y, label, idx, fontSize = "12px") {
|
|
@@ -3067,18 +3560,19 @@ function renderSelfMessage(x, y, label, idx, fontSize = "12px") {
|
|
|
3067
3560
|
markerEnd: "url(#seq-arrow-solid)"
|
|
3068
3561
|
}
|
|
3069
3562
|
),
|
|
3070
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3071
|
-
"
|
|
3563
|
+
/* @__PURE__ */ jsxRuntime.jsx("foreignObject", { x: x + SELF_ARC_WIDTH + 6, y, width: 150, height: SELF_ARC_HEIGHT, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3564
|
+
"div",
|
|
3072
3565
|
{
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3566
|
+
style: {
|
|
3567
|
+
display: "flex",
|
|
3568
|
+
alignItems: "center",
|
|
3569
|
+
fontSize,
|
|
3570
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
3571
|
+
color: "var(--glyph-text, #d4dae3)"
|
|
3572
|
+
},
|
|
3573
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: label })
|
|
3080
3574
|
}
|
|
3081
|
-
)
|
|
3575
|
+
) })
|
|
3082
3576
|
] }, `msg-${idx}`);
|
|
3083
3577
|
}
|
|
3084
3578
|
function renderStandardMessage(fromX, toX, y, label, isDashed, idx, fontSize = "12px") {
|
|
@@ -3098,18 +3592,20 @@ function renderStandardMessage(fromX, toX, y, label, isDashed, idx, fontSize = "
|
|
|
3098
3592
|
markerEnd: `url(#${markerId})`
|
|
3099
3593
|
}
|
|
3100
3594
|
),
|
|
3101
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3102
|
-
"
|
|
3595
|
+
/* @__PURE__ */ jsxRuntime.jsx("foreignObject", { x: midX - 75, y: y - 22, width: 150, height: 20, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3596
|
+
"div",
|
|
3103
3597
|
{
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3598
|
+
style: {
|
|
3599
|
+
display: "flex",
|
|
3600
|
+
justifyContent: "center",
|
|
3601
|
+
fontSize,
|
|
3602
|
+
fontFamily: "Inter, system-ui, sans-serif",
|
|
3603
|
+
color: "var(--glyph-text, #d4dae3)",
|
|
3604
|
+
textAlign: "center"
|
|
3605
|
+
},
|
|
3606
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: label })
|
|
3111
3607
|
}
|
|
3112
|
-
)
|
|
3608
|
+
) })
|
|
3113
3609
|
] }, `msg-${idx}`);
|
|
3114
3610
|
}
|
|
3115
3611
|
function Sequence({ data, container }) {
|
|
@@ -3134,7 +3630,7 @@ function Sequence({ data, container }) {
|
|
|
3134
3630
|
const firstMsgY = lifelineStartY + MSG_SPACING;
|
|
3135
3631
|
const lastMsgY = firstMsgY + (messageCount - 1) * MSG_SPACING;
|
|
3136
3632
|
const svgHeight = lastMsgY + BOTTOM_PADDING + effectiveActorHeight;
|
|
3137
|
-
const ariaLabel = data.title ? `${data.title}: sequence diagram with ${actorCount} actors and ${messageCount} messages` : `Sequence diagram with ${actorCount} actors and ${messageCount} messages`;
|
|
3633
|
+
const ariaLabel = data.title ? `${inlineToText(data.title)}: sequence diagram with ${actorCount} actors and ${messageCount} messages` : `Sequence diagram with ${actorCount} actors and ${messageCount} messages`;
|
|
3138
3634
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "glyph-sequence-container", children: [
|
|
3139
3635
|
data.title && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3140
3636
|
"div",
|
|
@@ -3146,7 +3642,7 @@ function Sequence({ data, container }) {
|
|
|
3146
3642
|
color: "var(--glyph-heading, #edf0f5)",
|
|
3147
3643
|
marginBottom: "0.5rem"
|
|
3148
3644
|
},
|
|
3149
|
-
children: data.title
|
|
3645
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: data.title })
|
|
3150
3646
|
}
|
|
3151
3647
|
),
|
|
3152
3648
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -3247,7 +3743,7 @@ function Sequence({ data, container }) {
|
|
|
3247
3743
|
]
|
|
3248
3744
|
}
|
|
3249
3745
|
),
|
|
3250
|
-
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "sr-only", "aria-label": "Sequence data", style:
|
|
3746
|
+
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "sr-only", "aria-label": "Sequence data", style: SR_ONLY_STYLE5, children: [
|
|
3251
3747
|
/* @__PURE__ */ jsxRuntime.jsx("caption", { children: "Sequence messages in order" }),
|
|
3252
3748
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3253
3749
|
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: "#" }),
|
|
@@ -3261,16 +3757,16 @@ function Sequence({ data, container }) {
|
|
|
3261
3757
|
const toActor = data.actors.find((a) => a.id === msg.to);
|
|
3262
3758
|
return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3263
3759
|
/* @__PURE__ */ jsxRuntime.jsx("td", { children: idx + 1 }),
|
|
3264
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { children: fromActor
|
|
3265
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { children: toActor
|
|
3266
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { children: msg.label }),
|
|
3760
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { children: fromActor ? inlineToText(fromActor.label) : msg.from }),
|
|
3761
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { children: toActor ? inlineToText(toActor.label) : msg.to }),
|
|
3762
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { children: inlineToText(msg.label) }),
|
|
3267
3763
|
/* @__PURE__ */ jsxRuntime.jsx("td", { children: msg.type })
|
|
3268
3764
|
] }, idx);
|
|
3269
3765
|
}) })
|
|
3270
3766
|
] })
|
|
3271
3767
|
] });
|
|
3272
3768
|
}
|
|
3273
|
-
var
|
|
3769
|
+
var SR_ONLY_STYLE5 = {
|
|
3274
3770
|
position: "absolute",
|
|
3275
3771
|
width: "1px",
|
|
3276
3772
|
height: "1px",
|
|
@@ -3676,7 +4172,7 @@ function Architecture({
|
|
|
3676
4172
|
}
|
|
3677
4173
|
}
|
|
3678
4174
|
),
|
|
3679
|
-
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "sr-only", "aria-label": "Architecture data", style:
|
|
4175
|
+
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "sr-only", "aria-label": "Architecture data", style: SR_ONLY_STYLE6, children: [
|
|
3680
4176
|
/* @__PURE__ */ jsxRuntime.jsx("caption", { children: "Architecture nodes and connections" }),
|
|
3681
4177
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
3682
4178
|
/* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: "Node" }),
|
|
@@ -3720,7 +4216,7 @@ function countLeafNodes(children) {
|
|
|
3720
4216
|
}
|
|
3721
4217
|
return count;
|
|
3722
4218
|
}
|
|
3723
|
-
var
|
|
4219
|
+
var SR_ONLY_STYLE6 = {
|
|
3724
4220
|
position: "absolute",
|
|
3725
4221
|
width: "1px",
|
|
3726
4222
|
height: "1px",
|
|
@@ -3908,7 +4404,7 @@ function layoutTree(data) {
|
|
|
3908
4404
|
};
|
|
3909
4405
|
}
|
|
3910
4406
|
function renderAccessibleList(root, children) {
|
|
3911
|
-
return /* @__PURE__ */ jsxRuntime.jsx("ul", { style:
|
|
4407
|
+
return /* @__PURE__ */ jsxRuntime.jsx("ul", { style: SR_ONLY_STYLE7, role: "list", "aria-label": "Mind map structure", children: /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
3912
4408
|
root,
|
|
3913
4409
|
children.length > 0 && renderAccessibleChildren(children)
|
|
3914
4410
|
] }) });
|
|
@@ -4035,7 +4531,7 @@ function MindMap({ data, container }) {
|
|
|
4035
4531
|
renderAccessibleList(data.root, data.children)
|
|
4036
4532
|
] });
|
|
4037
4533
|
}
|
|
4038
|
-
var
|
|
4534
|
+
var SR_ONLY_STYLE7 = {
|
|
4039
4535
|
position: "absolute",
|
|
4040
4536
|
width: "1px",
|
|
4041
4537
|
height: "1px",
|
|
@@ -4110,7 +4606,7 @@ function Equation({ data }) {
|
|
|
4110
4606
|
const ariaLabel = `Equation: ${data.expression}`;
|
|
4111
4607
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle, role: "math", "aria-label": ariaLabel, children: [
|
|
4112
4608
|
error || html === "" ? /* @__PURE__ */ jsxRuntime.jsx("code", { style: fallbackStyle, children: data.expression }) : /* @__PURE__ */ jsxRuntime.jsx("span", { dangerouslySetInnerHTML: { __html: html } }),
|
|
4113
|
-
data.label !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: labelStyle2, children: data.label })
|
|
4609
|
+
data.label !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: labelStyle2, children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: data.label }) })
|
|
4114
4610
|
] });
|
|
4115
4611
|
}
|
|
4116
4612
|
if (data.steps !== void 0 && data.steps.length > 0) {
|
|
@@ -4121,10 +4617,10 @@ function Equation({ data }) {
|
|
|
4121
4617
|
const { html, error } = renderLatex(step.expression);
|
|
4122
4618
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: stepRowStyle, children: [
|
|
4123
4619
|
error || html === "" ? /* @__PURE__ */ jsxRuntime.jsx("code", { style: fallbackStyle, children: step.expression }) : /* @__PURE__ */ jsxRuntime.jsx("span", { dangerouslySetInnerHTML: { __html: html } }),
|
|
4124
|
-
step.annotation !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: annotationStyle, children: step.annotation })
|
|
4620
|
+
step.annotation !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: annotationStyle, children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: step.annotation }) })
|
|
4125
4621
|
] }, idx);
|
|
4126
4622
|
}) }),
|
|
4127
|
-
data.label !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: labelStyle2, children: data.label })
|
|
4623
|
+
data.label !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: labelStyle2, children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: data.label }) })
|
|
4128
4624
|
] });
|
|
4129
4625
|
}
|
|
4130
4626
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: containerStyle, role: "math", "aria-label": "Empty equation", children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--glyph-text-muted, #6b7a94)" }, children: "No equation provided" }) });
|
|
@@ -6550,8 +7046,8 @@ function Kanban({
|
|
|
6550
7046
|
style: cardStyle(isGrabbed, card.priority),
|
|
6551
7047
|
onKeyDown: (e) => handleCardKeyDown(e, card.id, col.id, cardIndex),
|
|
6552
7048
|
children: [
|
|
6553
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: cardTitleStyle, children: card.title }),
|
|
6554
|
-
card.description && /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardDescStyle, children: card.description }),
|
|
7049
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: cardTitleStyle, children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: card.title }) }),
|
|
7050
|
+
card.description && /* @__PURE__ */ jsxRuntime.jsx("div", { style: cardDescStyle, children: /* @__PURE__ */ jsxRuntime.jsx(runtime.RichText, { content: card.description }) }),
|
|
6555
7051
|
card.tags && card.tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: tagContainerStyle, children: card.tags.map((tag) => /* @__PURE__ */ jsxRuntime.jsx("span", { style: tagStyle, children: tag }, tag)) })
|
|
6556
7052
|
]
|
|
6557
7053
|
},
|