@diagrammo/dgmo 0.8.9 → 0.8.10
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/AGENTS.md +3 -0
- package/dist/cli.cjs +191 -191
- package/dist/index.cjs +1318 -724
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +147 -1
- package/dist/index.d.ts +147 -1
- package/dist/index.js +1314 -724
- package/dist/index.js.map +1 -1
- package/docs/language-reference.md +28 -2
- package/gallery/fixtures/sitemap-full.dgmo +1 -0
- package/package.json +1 -1
- package/src/boxes-and-lines/layout.ts +48 -8
- package/src/boxes-and-lines/parser.ts +59 -13
- package/src/boxes-and-lines/renderer.ts +33 -137
- package/src/c4/renderer.ts +25 -138
- package/src/class/renderer.ts +185 -186
- package/src/d3.ts +114 -191
- package/src/er/renderer.ts +52 -245
- package/src/gantt/renderer.ts +140 -182
- package/src/index.ts +21 -1
- package/src/infra/renderer.ts +91 -244
- package/src/kanban/renderer.ts +22 -129
- package/src/org/renderer.ts +103 -170
- package/src/render.ts +39 -9
- package/src/sequence/renderer.ts +31 -151
- package/src/sitemap/layout.ts +180 -38
- package/src/sitemap/parser.ts +64 -23
- package/src/sitemap/renderer.ts +73 -161
- package/src/utils/legend-constants.ts +6 -0
- package/src/utils/legend-d3.ts +400 -0
- package/src/utils/legend-layout.ts +495 -0
- package/src/utils/legend-svg.ts +26 -0
- package/src/utils/legend-types.ts +169 -0
package/dist/index.js
CHANGED
|
@@ -1901,6 +1901,493 @@ var init_legend_constants = __esm({
|
|
|
1901
1901
|
}
|
|
1902
1902
|
});
|
|
1903
1903
|
|
|
1904
|
+
// src/utils/legend-layout.ts
|
|
1905
|
+
function pillWidth(name) {
|
|
1906
|
+
return measureLegendText(name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
1907
|
+
}
|
|
1908
|
+
function entriesWidth(entries) {
|
|
1909
|
+
let w = 0;
|
|
1910
|
+
for (const e of entries) {
|
|
1911
|
+
w += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
1912
|
+
}
|
|
1913
|
+
return w;
|
|
1914
|
+
}
|
|
1915
|
+
function entryWidth(value) {
|
|
1916
|
+
return LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
1917
|
+
}
|
|
1918
|
+
function controlWidth(control) {
|
|
1919
|
+
let w = CONTROL_PILL_PAD;
|
|
1920
|
+
if (control.label) {
|
|
1921
|
+
w += measureLegendText(control.label, CONTROL_FONT_SIZE);
|
|
1922
|
+
if (control.icon) w += CONTROL_ICON_GAP;
|
|
1923
|
+
}
|
|
1924
|
+
if (control.icon) w += 14;
|
|
1925
|
+
if (control.children) {
|
|
1926
|
+
for (const child of control.children) {
|
|
1927
|
+
w += measureLegendText(child.label, CONTROL_FONT_SIZE) + 12;
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
return w;
|
|
1931
|
+
}
|
|
1932
|
+
function capsuleWidth(name, entries, containerWidth, addonWidth = 0) {
|
|
1933
|
+
const pw = pillWidth(name);
|
|
1934
|
+
const maxCapsuleW = containerWidth;
|
|
1935
|
+
const baseW = LEGEND_CAPSULE_PAD * 2 + pw + 4 + addonWidth;
|
|
1936
|
+
const ew = entriesWidth(entries);
|
|
1937
|
+
const singleRowW = baseW + ew;
|
|
1938
|
+
if (singleRowW <= maxCapsuleW) {
|
|
1939
|
+
return {
|
|
1940
|
+
width: singleRowW,
|
|
1941
|
+
entryRows: 1,
|
|
1942
|
+
moreCount: 0,
|
|
1943
|
+
visibleEntries: entries.length
|
|
1944
|
+
};
|
|
1945
|
+
}
|
|
1946
|
+
const rowWidth = maxCapsuleW - LEGEND_CAPSULE_PAD * 2;
|
|
1947
|
+
let row = 1;
|
|
1948
|
+
let rowX = pw + 4;
|
|
1949
|
+
let visible = 0;
|
|
1950
|
+
for (let i = 0; i < entries.length; i++) {
|
|
1951
|
+
const ew2 = entryWidth(entries[i].value);
|
|
1952
|
+
if (rowX + ew2 > rowWidth && rowX > pw + 4) {
|
|
1953
|
+
row++;
|
|
1954
|
+
rowX = 0;
|
|
1955
|
+
if (row > LEGEND_MAX_ENTRY_ROWS) {
|
|
1956
|
+
return {
|
|
1957
|
+
width: maxCapsuleW,
|
|
1958
|
+
entryRows: LEGEND_MAX_ENTRY_ROWS,
|
|
1959
|
+
moreCount: entries.length - visible,
|
|
1960
|
+
visibleEntries: visible
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
rowX += ew2;
|
|
1965
|
+
visible++;
|
|
1966
|
+
}
|
|
1967
|
+
return {
|
|
1968
|
+
width: maxCapsuleW,
|
|
1969
|
+
entryRows: row,
|
|
1970
|
+
moreCount: 0,
|
|
1971
|
+
visibleEntries: entries.length
|
|
1972
|
+
};
|
|
1973
|
+
}
|
|
1974
|
+
function computeLegendLayout(config, state, containerWidth) {
|
|
1975
|
+
const { groups, controls: configControls, mode } = config;
|
|
1976
|
+
const isExport = mode === "inline";
|
|
1977
|
+
const activeGroupName = state.activeGroup?.toLowerCase() ?? null;
|
|
1978
|
+
if (isExport && !activeGroupName) {
|
|
1979
|
+
return {
|
|
1980
|
+
height: 0,
|
|
1981
|
+
width: 0,
|
|
1982
|
+
rows: [],
|
|
1983
|
+
controls: [],
|
|
1984
|
+
pills: [],
|
|
1985
|
+
activeCapsule: void 0
|
|
1986
|
+
};
|
|
1987
|
+
}
|
|
1988
|
+
const visibleGroups = config.showEmptyGroups ? groups : groups.filter((g) => g.entries.length > 0);
|
|
1989
|
+
if (visibleGroups.length === 0 && (!configControls || configControls.length === 0)) {
|
|
1990
|
+
return {
|
|
1991
|
+
height: 0,
|
|
1992
|
+
width: 0,
|
|
1993
|
+
rows: [],
|
|
1994
|
+
controls: [],
|
|
1995
|
+
pills: [],
|
|
1996
|
+
activeCapsule: void 0
|
|
1997
|
+
};
|
|
1998
|
+
}
|
|
1999
|
+
const controlLayouts = [];
|
|
2000
|
+
let totalControlsW = 0;
|
|
2001
|
+
if (configControls && !isExport) {
|
|
2002
|
+
for (const ctrl of configControls) {
|
|
2003
|
+
const w = controlWidth(ctrl);
|
|
2004
|
+
controlLayouts.push({
|
|
2005
|
+
id: ctrl.id,
|
|
2006
|
+
x: 0,
|
|
2007
|
+
// positioned later
|
|
2008
|
+
y: 0,
|
|
2009
|
+
width: w,
|
|
2010
|
+
height: LEGEND_HEIGHT,
|
|
2011
|
+
icon: ctrl.icon,
|
|
2012
|
+
label: ctrl.label,
|
|
2013
|
+
exportBehavior: ctrl.exportBehavior,
|
|
2014
|
+
children: ctrl.children?.map((c) => ({
|
|
2015
|
+
id: c.id,
|
|
2016
|
+
label: c.label,
|
|
2017
|
+
x: 0,
|
|
2018
|
+
y: 0,
|
|
2019
|
+
width: measureLegendText(c.label, CONTROL_FONT_SIZE) + 12,
|
|
2020
|
+
isActive: c.isActive
|
|
2021
|
+
}))
|
|
2022
|
+
});
|
|
2023
|
+
totalControlsW += w + CONTROL_GAP;
|
|
2024
|
+
}
|
|
2025
|
+
if (totalControlsW > 0) totalControlsW -= CONTROL_GAP;
|
|
2026
|
+
} else if (configControls && isExport) {
|
|
2027
|
+
for (const ctrl of configControls) {
|
|
2028
|
+
if (ctrl.exportBehavior === "strip") continue;
|
|
2029
|
+
const w = controlWidth(ctrl);
|
|
2030
|
+
controlLayouts.push({
|
|
2031
|
+
id: ctrl.id,
|
|
2032
|
+
x: 0,
|
|
2033
|
+
y: 0,
|
|
2034
|
+
width: w,
|
|
2035
|
+
height: LEGEND_HEIGHT,
|
|
2036
|
+
icon: ctrl.icon,
|
|
2037
|
+
label: ctrl.label,
|
|
2038
|
+
exportBehavior: ctrl.exportBehavior,
|
|
2039
|
+
children: ctrl.children?.map((c) => ({
|
|
2040
|
+
id: c.id,
|
|
2041
|
+
label: c.label,
|
|
2042
|
+
x: 0,
|
|
2043
|
+
y: 0,
|
|
2044
|
+
width: measureLegendText(c.label, CONTROL_FONT_SIZE) + 12,
|
|
2045
|
+
isActive: c.isActive
|
|
2046
|
+
}))
|
|
2047
|
+
});
|
|
2048
|
+
totalControlsW += w + CONTROL_GAP;
|
|
2049
|
+
}
|
|
2050
|
+
if (totalControlsW > 0) totalControlsW -= CONTROL_GAP;
|
|
2051
|
+
}
|
|
2052
|
+
const controlsSpace = totalControlsW > 0 ? totalControlsW + LEGEND_GROUP_GAP * 2 : 0;
|
|
2053
|
+
const groupAvailW = containerWidth - controlsSpace;
|
|
2054
|
+
const pills = [];
|
|
2055
|
+
let activeCapsule;
|
|
2056
|
+
for (const g of visibleGroups) {
|
|
2057
|
+
const isActive = activeGroupName === g.name.toLowerCase();
|
|
2058
|
+
if (isExport && !isActive) continue;
|
|
2059
|
+
if (isActive) {
|
|
2060
|
+
activeCapsule = buildCapsuleLayout(
|
|
2061
|
+
g,
|
|
2062
|
+
containerWidth,
|
|
2063
|
+
config.capsulePillAddonWidth ?? 0
|
|
2064
|
+
);
|
|
2065
|
+
} else {
|
|
2066
|
+
const pw = pillWidth(g.name);
|
|
2067
|
+
pills.push({
|
|
2068
|
+
groupName: g.name,
|
|
2069
|
+
x: 0,
|
|
2070
|
+
y: 0,
|
|
2071
|
+
width: pw,
|
|
2072
|
+
height: LEGEND_HEIGHT,
|
|
2073
|
+
isActive: false
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
const rows = layoutRows(
|
|
2078
|
+
activeCapsule,
|
|
2079
|
+
pills,
|
|
2080
|
+
controlLayouts,
|
|
2081
|
+
groupAvailW,
|
|
2082
|
+
containerWidth,
|
|
2083
|
+
totalControlsW
|
|
2084
|
+
);
|
|
2085
|
+
const height = rows.length * LEGEND_HEIGHT;
|
|
2086
|
+
const width = containerWidth;
|
|
2087
|
+
return {
|
|
2088
|
+
height,
|
|
2089
|
+
width,
|
|
2090
|
+
rows,
|
|
2091
|
+
activeCapsule,
|
|
2092
|
+
controls: controlLayouts,
|
|
2093
|
+
pills
|
|
2094
|
+
};
|
|
2095
|
+
}
|
|
2096
|
+
function buildCapsuleLayout(group, containerWidth, addonWidth = 0) {
|
|
2097
|
+
const pw = pillWidth(group.name);
|
|
2098
|
+
const info = capsuleWidth(
|
|
2099
|
+
group.name,
|
|
2100
|
+
group.entries,
|
|
2101
|
+
containerWidth,
|
|
2102
|
+
addonWidth
|
|
2103
|
+
);
|
|
2104
|
+
const pill = {
|
|
2105
|
+
groupName: group.name,
|
|
2106
|
+
x: LEGEND_CAPSULE_PAD,
|
|
2107
|
+
y: LEGEND_CAPSULE_PAD,
|
|
2108
|
+
width: pw,
|
|
2109
|
+
height: LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2,
|
|
2110
|
+
isActive: true
|
|
2111
|
+
};
|
|
2112
|
+
const entries = [];
|
|
2113
|
+
let ex = LEGEND_CAPSULE_PAD + pw + 4 + addonWidth;
|
|
2114
|
+
let ey = 0;
|
|
2115
|
+
let rowX = ex;
|
|
2116
|
+
const maxRowW = containerWidth - LEGEND_CAPSULE_PAD * 2;
|
|
2117
|
+
let currentRow = 0;
|
|
2118
|
+
for (let i = 0; i < info.visibleEntries; i++) {
|
|
2119
|
+
const entry = group.entries[i];
|
|
2120
|
+
const ew = entryWidth(entry.value);
|
|
2121
|
+
if (rowX + ew > maxRowW && rowX > ex && i > 0) {
|
|
2122
|
+
currentRow++;
|
|
2123
|
+
rowX = 0;
|
|
2124
|
+
ey = currentRow * LEGEND_HEIGHT;
|
|
2125
|
+
if (currentRow === 0) ex = LEGEND_CAPSULE_PAD + pw + 4;
|
|
2126
|
+
}
|
|
2127
|
+
const dotCx = rowX + LEGEND_DOT_R;
|
|
2128
|
+
const dotCy = ey + LEGEND_HEIGHT / 2;
|
|
2129
|
+
const textX = rowX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
2130
|
+
const textY = ey + LEGEND_HEIGHT / 2;
|
|
2131
|
+
entries.push({
|
|
2132
|
+
value: entry.value,
|
|
2133
|
+
color: entry.color,
|
|
2134
|
+
x: rowX,
|
|
2135
|
+
y: ey,
|
|
2136
|
+
dotCx,
|
|
2137
|
+
dotCy,
|
|
2138
|
+
textX,
|
|
2139
|
+
textY
|
|
2140
|
+
});
|
|
2141
|
+
rowX += ew;
|
|
2142
|
+
}
|
|
2143
|
+
const totalRows = info.entryRows;
|
|
2144
|
+
const capsuleH = totalRows * LEGEND_HEIGHT;
|
|
2145
|
+
return {
|
|
2146
|
+
groupName: group.name,
|
|
2147
|
+
x: 0,
|
|
2148
|
+
y: 0,
|
|
2149
|
+
width: info.width,
|
|
2150
|
+
height: capsuleH,
|
|
2151
|
+
pill,
|
|
2152
|
+
entries,
|
|
2153
|
+
moreCount: info.moreCount > 0 ? info.moreCount : void 0,
|
|
2154
|
+
addonX: addonWidth > 0 ? LEGEND_CAPSULE_PAD + pw + 4 : void 0
|
|
2155
|
+
};
|
|
2156
|
+
}
|
|
2157
|
+
function layoutRows(activeCapsule, pills, controls, groupAvailW, containerWidth, totalControlsW) {
|
|
2158
|
+
const rows = [];
|
|
2159
|
+
const groupItems = [];
|
|
2160
|
+
if (activeCapsule) groupItems.push(activeCapsule);
|
|
2161
|
+
groupItems.push(...pills);
|
|
2162
|
+
let currentRowItems = [];
|
|
2163
|
+
let currentRowW = 0;
|
|
2164
|
+
let rowY = 0;
|
|
2165
|
+
for (const item of groupItems) {
|
|
2166
|
+
const itemW = item.width + LEGEND_GROUP_GAP;
|
|
2167
|
+
if (currentRowW + item.width > groupAvailW && currentRowItems.length > 0) {
|
|
2168
|
+
centerRowItems(currentRowItems, containerWidth, totalControlsW);
|
|
2169
|
+
rows.push({ y: rowY, items: currentRowItems });
|
|
2170
|
+
rowY += LEGEND_HEIGHT;
|
|
2171
|
+
currentRowItems = [];
|
|
2172
|
+
currentRowW = 0;
|
|
2173
|
+
}
|
|
2174
|
+
item.x = currentRowW;
|
|
2175
|
+
item.y = rowY;
|
|
2176
|
+
currentRowItems.push(item);
|
|
2177
|
+
currentRowW += itemW;
|
|
2178
|
+
}
|
|
2179
|
+
if (controls.length > 0) {
|
|
2180
|
+
let cx = containerWidth;
|
|
2181
|
+
for (let i = controls.length - 1; i >= 0; i--) {
|
|
2182
|
+
cx -= controls[i].width;
|
|
2183
|
+
controls[i].x = cx;
|
|
2184
|
+
controls[i].y = 0;
|
|
2185
|
+
cx -= CONTROL_GAP;
|
|
2186
|
+
}
|
|
2187
|
+
if (rows.length > 0) {
|
|
2188
|
+
rows[0].items.push(...controls);
|
|
2189
|
+
} else if (currentRowItems.length > 0) {
|
|
2190
|
+
currentRowItems.push(...controls);
|
|
2191
|
+
} else {
|
|
2192
|
+
currentRowItems.push(...controls);
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
if (currentRowItems.length > 0) {
|
|
2196
|
+
centerRowItems(currentRowItems, containerWidth, totalControlsW);
|
|
2197
|
+
rows.push({ y: rowY, items: currentRowItems });
|
|
2198
|
+
}
|
|
2199
|
+
if (rows.length === 0) {
|
|
2200
|
+
rows.push({ y: 0, items: [] });
|
|
2201
|
+
}
|
|
2202
|
+
return rows;
|
|
2203
|
+
}
|
|
2204
|
+
function centerRowItems(items, containerWidth, totalControlsW) {
|
|
2205
|
+
const groupItems = items.filter((it) => "groupName" in it);
|
|
2206
|
+
if (groupItems.length === 0) return;
|
|
2207
|
+
const totalGroupW = groupItems.reduce((s, it) => s + it.width, 0) + (groupItems.length - 1) * LEGEND_GROUP_GAP;
|
|
2208
|
+
const availW = containerWidth - (totalControlsW > 0 ? totalControlsW + LEGEND_GROUP_GAP * 2 : 0);
|
|
2209
|
+
const offset = Math.max(0, (availW - totalGroupW) / 2);
|
|
2210
|
+
let x = offset;
|
|
2211
|
+
for (const item of groupItems) {
|
|
2212
|
+
item.x = x;
|
|
2213
|
+
x += item.width + LEGEND_GROUP_GAP;
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
function getLegendReservedHeight(config, state, containerWidth) {
|
|
2217
|
+
const layout = computeLegendLayout(config, state, containerWidth);
|
|
2218
|
+
return layout.height;
|
|
2219
|
+
}
|
|
2220
|
+
var LEGEND_MAX_ENTRY_ROWS, CONTROL_PILL_PAD, CONTROL_FONT_SIZE, CONTROL_ICON_GAP, CONTROL_GAP;
|
|
2221
|
+
var init_legend_layout = __esm({
|
|
2222
|
+
"src/utils/legend-layout.ts"() {
|
|
2223
|
+
"use strict";
|
|
2224
|
+
init_legend_constants();
|
|
2225
|
+
LEGEND_MAX_ENTRY_ROWS = 3;
|
|
2226
|
+
CONTROL_PILL_PAD = 16;
|
|
2227
|
+
CONTROL_FONT_SIZE = 11;
|
|
2228
|
+
CONTROL_ICON_GAP = 4;
|
|
2229
|
+
CONTROL_GAP = 8;
|
|
2230
|
+
}
|
|
2231
|
+
});
|
|
2232
|
+
|
|
2233
|
+
// src/utils/legend-d3.ts
|
|
2234
|
+
function renderLegendD3(container, config, state, palette, isDark, callbacks, containerWidth) {
|
|
2235
|
+
const width = containerWidth ?? parseFloat(container.attr("width") || "800");
|
|
2236
|
+
let currentState = { ...state };
|
|
2237
|
+
let currentLayout;
|
|
2238
|
+
const legendG = container.append("g").attr("class", "dgmo-legend");
|
|
2239
|
+
function render2() {
|
|
2240
|
+
currentLayout = computeLegendLayout(config, currentState, width);
|
|
2241
|
+
legendG.selectAll("*").remove();
|
|
2242
|
+
if (currentLayout.height === 0) return;
|
|
2243
|
+
if (currentState.activeGroup) {
|
|
2244
|
+
legendG.attr(
|
|
2245
|
+
"data-legend-active",
|
|
2246
|
+
currentState.activeGroup.toLowerCase()
|
|
2247
|
+
);
|
|
2248
|
+
} else {
|
|
2249
|
+
legendG.attr("data-legend-active", null);
|
|
2250
|
+
}
|
|
2251
|
+
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
2252
|
+
const pillBorder = mix(palette.textMuted, palette.bg, 50);
|
|
2253
|
+
if (currentLayout.activeCapsule) {
|
|
2254
|
+
renderCapsule(
|
|
2255
|
+
legendG,
|
|
2256
|
+
currentLayout.activeCapsule,
|
|
2257
|
+
palette,
|
|
2258
|
+
groupBg,
|
|
2259
|
+
pillBorder,
|
|
2260
|
+
isDark,
|
|
2261
|
+
callbacks
|
|
2262
|
+
);
|
|
2263
|
+
}
|
|
2264
|
+
for (const pill of currentLayout.pills) {
|
|
2265
|
+
renderPill(legendG, pill, palette, groupBg, callbacks);
|
|
2266
|
+
}
|
|
2267
|
+
for (const ctrl of currentLayout.controls) {
|
|
2268
|
+
renderControl(
|
|
2269
|
+
legendG,
|
|
2270
|
+
ctrl,
|
|
2271
|
+
palette,
|
|
2272
|
+
groupBg,
|
|
2273
|
+
pillBorder,
|
|
2274
|
+
isDark,
|
|
2275
|
+
config.controls
|
|
2276
|
+
);
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
render2();
|
|
2280
|
+
return {
|
|
2281
|
+
setState(newState) {
|
|
2282
|
+
currentState = { ...newState };
|
|
2283
|
+
render2();
|
|
2284
|
+
},
|
|
2285
|
+
destroy() {
|
|
2286
|
+
legendG.remove();
|
|
2287
|
+
},
|
|
2288
|
+
getHeight() {
|
|
2289
|
+
return currentLayout?.height ?? 0;
|
|
2290
|
+
},
|
|
2291
|
+
getLayout() {
|
|
2292
|
+
return currentLayout;
|
|
2293
|
+
}
|
|
2294
|
+
};
|
|
2295
|
+
}
|
|
2296
|
+
function renderCapsule(parent, capsule, palette, groupBg, pillBorder, _isDark, callbacks) {
|
|
2297
|
+
const g = parent.append("g").attr("transform", `translate(${capsule.x},${capsule.y})`).attr("data-legend-group", capsule.groupName.toLowerCase()).style("cursor", "pointer");
|
|
2298
|
+
g.append("rect").attr("width", capsule.width).attr("height", capsule.height).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
2299
|
+
const pill = capsule.pill;
|
|
2300
|
+
g.append("rect").attr("x", pill.x).attr("y", pill.y).attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", palette.bg);
|
|
2301
|
+
g.append("rect").attr("x", pill.x).attr("y", pill.y).attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", "none").attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
2302
|
+
g.append("text").attr("x", pill.x + pill.width / 2).attr("y", LEGEND_HEIGHT / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", 500).attr("fill", palette.text).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(capsule.groupName);
|
|
2303
|
+
for (const entry of capsule.entries) {
|
|
2304
|
+
const entryG = g.append("g").attr("data-legend-entry", entry.value.toLowerCase()).attr("data-series-name", entry.value).style("cursor", "pointer");
|
|
2305
|
+
entryG.append("circle").attr("cx", entry.dotCx).attr("cy", entry.dotCy).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
2306
|
+
entryG.append("text").attr("x", entry.textX).attr("y", entry.textY).attr("dominant-baseline", "central").attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).attr("font-family", FONT_FAMILY).text(entry.value);
|
|
2307
|
+
if (callbacks?.onEntryHover) {
|
|
2308
|
+
const groupName = capsule.groupName;
|
|
2309
|
+
const entryValue = entry.value;
|
|
2310
|
+
const onHover = callbacks.onEntryHover;
|
|
2311
|
+
entryG.on("mouseenter", () => onHover(groupName, entryValue)).on("mouseleave", () => onHover(groupName, null));
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
if (capsule.moreCount) {
|
|
2315
|
+
const lastEntry = capsule.entries[capsule.entries.length - 1];
|
|
2316
|
+
const moreX = lastEntry ? lastEntry.textX + measureLegendText(lastEntry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_DOT_GAP * 2 : pill.x + pill.width + 8;
|
|
2317
|
+
const moreY = lastEntry?.textY ?? LEGEND_HEIGHT / 2;
|
|
2318
|
+
g.append("text").attr("x", moreX).attr("y", moreY).attr("dominant-baseline", "central").attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("font-style", "italic").attr("fill", palette.textMuted).attr("font-family", FONT_FAMILY).text(`+${capsule.moreCount} more`);
|
|
2319
|
+
}
|
|
2320
|
+
if (callbacks?.onGroupToggle) {
|
|
2321
|
+
const cb = callbacks.onGroupToggle;
|
|
2322
|
+
const name = capsule.groupName;
|
|
2323
|
+
g.on("click", () => cb(name));
|
|
2324
|
+
}
|
|
2325
|
+
if (callbacks?.onGroupRendered) {
|
|
2326
|
+
callbacks.onGroupRendered(capsule.groupName, g, true);
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
function renderPill(parent, pill, palette, groupBg, callbacks) {
|
|
2330
|
+
const g = parent.append("g").attr("transform", `translate(${pill.x},${pill.y})`).attr("data-legend-group", pill.groupName.toLowerCase()).style("cursor", "pointer");
|
|
2331
|
+
g.append("rect").attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", groupBg);
|
|
2332
|
+
g.append("text").attr("x", pill.width / 2).attr("y", pill.height / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", 500).attr("fill", palette.textMuted).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(pill.groupName);
|
|
2333
|
+
if (callbacks?.onGroupToggle) {
|
|
2334
|
+
const cb = callbacks.onGroupToggle;
|
|
2335
|
+
const name = pill.groupName;
|
|
2336
|
+
g.on("click", () => cb(name));
|
|
2337
|
+
}
|
|
2338
|
+
if (callbacks?.onGroupRendered) {
|
|
2339
|
+
callbacks.onGroupRendered(pill.groupName, g, false);
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
function renderControl(parent, ctrl, palette, _groupBg, pillBorder, _isDark, configControls) {
|
|
2343
|
+
const g = parent.append("g").attr("transform", `translate(${ctrl.x},${ctrl.y})`).attr("data-legend-control", ctrl.id).style("cursor", "pointer");
|
|
2344
|
+
if (ctrl.exportBehavior === "strip") {
|
|
2345
|
+
g.attr("data-export-ignore", "true");
|
|
2346
|
+
}
|
|
2347
|
+
g.append("rect").attr("width", ctrl.width).attr("height", ctrl.height).attr("rx", ctrl.height / 2).attr("fill", "none").attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
2348
|
+
let textX = ctrl.width / 2;
|
|
2349
|
+
if (ctrl.icon && ctrl.label) {
|
|
2350
|
+
const iconG = g.append("g").attr("transform", `translate(8,${(ctrl.height - 14) / 2})`);
|
|
2351
|
+
iconG.html(ctrl.icon);
|
|
2352
|
+
textX = 8 + 14 + LEGEND_ENTRY_DOT_GAP + measureLegendText(ctrl.label, LEGEND_PILL_FONT_SIZE) / 2;
|
|
2353
|
+
}
|
|
2354
|
+
if (ctrl.label) {
|
|
2355
|
+
g.append("text").attr("x", textX).attr("y", ctrl.height / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", 500).attr("fill", palette.textMuted).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(ctrl.label);
|
|
2356
|
+
}
|
|
2357
|
+
if (ctrl.children) {
|
|
2358
|
+
let cx = ctrl.width + 4;
|
|
2359
|
+
for (const child of ctrl.children) {
|
|
2360
|
+
const childG = g.append("g").attr("transform", `translate(${cx},0)`).style("cursor", "pointer");
|
|
2361
|
+
childG.append("rect").attr("width", child.width).attr("height", ctrl.height).attr("rx", ctrl.height / 2).attr(
|
|
2362
|
+
"fill",
|
|
2363
|
+
child.isActive ? palette.primary ?? palette.text : "none"
|
|
2364
|
+
).attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
2365
|
+
childG.append("text").attr("x", child.width / 2).attr("y", ctrl.height / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", child.isActive ? palette.bg : palette.textMuted).attr("font-family", FONT_FAMILY).text(child.label);
|
|
2366
|
+
const configCtrl2 = configControls?.find((c) => c.id === ctrl.id);
|
|
2367
|
+
const configChild = configCtrl2?.children?.find((c) => c.id === child.id);
|
|
2368
|
+
if (configChild?.onClick) {
|
|
2369
|
+
const onClick = configChild.onClick;
|
|
2370
|
+
childG.on("click", () => onClick());
|
|
2371
|
+
}
|
|
2372
|
+
cx += child.width + 4;
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
const configCtrl = configControls?.find((c) => c.id === ctrl.id);
|
|
2376
|
+
if (configCtrl?.onClick) {
|
|
2377
|
+
const onClick = configCtrl.onClick;
|
|
2378
|
+
g.on("click", () => onClick());
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
var init_legend_d3 = __esm({
|
|
2382
|
+
"src/utils/legend-d3.ts"() {
|
|
2383
|
+
"use strict";
|
|
2384
|
+
init_legend_constants();
|
|
2385
|
+
init_legend_layout();
|
|
2386
|
+
init_color_utils();
|
|
2387
|
+
init_fonts();
|
|
2388
|
+
}
|
|
2389
|
+
});
|
|
2390
|
+
|
|
1904
2391
|
// src/utils/title-constants.ts
|
|
1905
2392
|
var TITLE_FONT_SIZE, TITLE_FONT_WEIGHT, TITLE_Y, TITLE_OFFSET;
|
|
1906
2393
|
var init_title_constants = __esm({
|
|
@@ -4830,10 +5317,10 @@ var init_chart = __esm({
|
|
|
4830
5317
|
function esc(s) {
|
|
4831
5318
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
4832
5319
|
}
|
|
4833
|
-
function
|
|
5320
|
+
function pillWidth2(name) {
|
|
4834
5321
|
return measureLegendText(name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
4835
5322
|
}
|
|
4836
|
-
function
|
|
5323
|
+
function entriesWidth2(entries) {
|
|
4837
5324
|
let w = 0;
|
|
4838
5325
|
for (const e of entries) {
|
|
4839
5326
|
w += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
@@ -4841,9 +5328,9 @@ function entriesWidth(entries) {
|
|
|
4841
5328
|
return w;
|
|
4842
5329
|
}
|
|
4843
5330
|
function groupTotalWidth(name, entries, isActive) {
|
|
4844
|
-
const pw =
|
|
5331
|
+
const pw = pillWidth2(name);
|
|
4845
5332
|
if (!isActive) return pw;
|
|
4846
|
-
return LEGEND_CAPSULE_PAD * 2 + pw + 4 +
|
|
5333
|
+
return LEGEND_CAPSULE_PAD * 2 + pw + 4 + entriesWidth2(entries);
|
|
4847
5334
|
}
|
|
4848
5335
|
function renderLegendSvg(groups, options) {
|
|
4849
5336
|
if (groups.length === 0) return { svg: "", height: 0, width: 0 };
|
|
@@ -4851,7 +5338,7 @@ function renderLegendSvg(groups, options) {
|
|
|
4851
5338
|
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
4852
5339
|
const items = groups.filter((g) => g.entries.length > 0).map((g) => {
|
|
4853
5340
|
const isActive = !!activeGroup && g.name.toLowerCase() === activeGroup.toLowerCase();
|
|
4854
|
-
const pw =
|
|
5341
|
+
const pw = pillWidth2(g.name);
|
|
4855
5342
|
const tw = groupTotalWidth(g.name, g.entries, isActive);
|
|
4856
5343
|
return { group: g, isActive, pillWidth: pw, totalWidth: tw };
|
|
4857
5344
|
});
|
|
@@ -4905,6 +5392,19 @@ function renderLegendSvg(groups, options) {
|
|
|
4905
5392
|
const svg = `<g${classAttr}${activeAttr}>${parts.join("")}</g>`;
|
|
4906
5393
|
return { svg, height: LEGEND_HEIGHT, width: totalWidth };
|
|
4907
5394
|
}
|
|
5395
|
+
function renderLegendSvgFromConfig(config, state, palette, containerWidth) {
|
|
5396
|
+
return renderLegendSvg(config.groups, {
|
|
5397
|
+
palette: {
|
|
5398
|
+
bg: palette.bg,
|
|
5399
|
+
surface: palette.surface,
|
|
5400
|
+
text: palette.text,
|
|
5401
|
+
textMuted: palette.textMuted
|
|
5402
|
+
},
|
|
5403
|
+
isDark: palette.isDark,
|
|
5404
|
+
containerWidth,
|
|
5405
|
+
activeGroup: state.activeGroup
|
|
5406
|
+
});
|
|
5407
|
+
}
|
|
4908
5408
|
var init_legend_svg = __esm({
|
|
4909
5409
|
"src/utils/legend-svg.ts"() {
|
|
4910
5410
|
"use strict";
|
|
@@ -8357,7 +8857,12 @@ __export(parser_exports7, {
|
|
|
8357
8857
|
function parseArrowLine(trimmed, palette) {
|
|
8358
8858
|
const bareMatch = trimmed.match(BARE_ARROW_RE);
|
|
8359
8859
|
if (bareMatch) {
|
|
8360
|
-
|
|
8860
|
+
const rawTarget = bareMatch[1].trim();
|
|
8861
|
+
const groupMatch = rawTarget.match(/^\[(.+)\]$/);
|
|
8862
|
+
return {
|
|
8863
|
+
target: groupMatch ? groupMatch[1].trim() : rawTarget,
|
|
8864
|
+
targetIsGroup: !!groupMatch
|
|
8865
|
+
};
|
|
8361
8866
|
}
|
|
8362
8867
|
const arrowMatch = trimmed.match(ARROW_RE);
|
|
8363
8868
|
if (arrowMatch) {
|
|
@@ -8366,8 +8871,14 @@ function parseArrowLine(trimmed, palette) {
|
|
|
8366
8871
|
if (label && !color) {
|
|
8367
8872
|
color = inferArrowColor(label);
|
|
8368
8873
|
}
|
|
8369
|
-
const
|
|
8370
|
-
|
|
8874
|
+
const rawTarget = arrowMatch[3].trim();
|
|
8875
|
+
const groupMatch = rawTarget.match(/^\[(.+)\]$/);
|
|
8876
|
+
return {
|
|
8877
|
+
label,
|
|
8878
|
+
color,
|
|
8879
|
+
target: groupMatch ? groupMatch[1].trim() : rawTarget,
|
|
8880
|
+
targetIsGroup: !!groupMatch
|
|
8881
|
+
};
|
|
8371
8882
|
}
|
|
8372
8883
|
return null;
|
|
8373
8884
|
}
|
|
@@ -8429,6 +8940,7 @@ function parseSitemap(content, palette) {
|
|
|
8429
8940
|
const aliasMap = /* @__PURE__ */ new Map();
|
|
8430
8941
|
const indentStack = [];
|
|
8431
8942
|
const labelToNode = /* @__PURE__ */ new Map();
|
|
8943
|
+
const labelToContainer = /* @__PURE__ */ new Map();
|
|
8432
8944
|
const deferredArrows = [];
|
|
8433
8945
|
for (let i = 0; i < lines.length; i++) {
|
|
8434
8946
|
const line10 = lines[i];
|
|
@@ -8530,6 +9042,7 @@ function parseSitemap(content, palette) {
|
|
|
8530
9042
|
deferredArrows.push({
|
|
8531
9043
|
sourceNode: source,
|
|
8532
9044
|
targetLabel: arrowInfo.target,
|
|
9045
|
+
targetIsGroup: arrowInfo.targetIsGroup,
|
|
8533
9046
|
label: arrowInfo.label,
|
|
8534
9047
|
color: arrowInfo.color,
|
|
8535
9048
|
lineNumber
|
|
@@ -8563,6 +9076,7 @@ function parseSitemap(content, palette) {
|
|
|
8563
9076
|
color
|
|
8564
9077
|
};
|
|
8565
9078
|
attachNode2(node, indent, indentStack, result);
|
|
9079
|
+
labelToContainer.set(label.toLowerCase(), node);
|
|
8566
9080
|
} else if (metadataMatch && indentStack.length > 0) {
|
|
8567
9081
|
const rawKey = metadataMatch[1].trim().toLowerCase();
|
|
8568
9082
|
const key = aliasMap.get(rawKey) ?? rawKey;
|
|
@@ -8603,22 +9117,41 @@ function parseSitemap(content, palette) {
|
|
|
8603
9117
|
}
|
|
8604
9118
|
for (const arrow of deferredArrows) {
|
|
8605
9119
|
const targetKey = arrow.targetLabel.toLowerCase();
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
9120
|
+
if (arrow.targetIsGroup) {
|
|
9121
|
+
const targetContainer = labelToContainer.get(targetKey);
|
|
9122
|
+
if (!targetContainer) {
|
|
9123
|
+
const allLabels = Array.from(labelToContainer.keys());
|
|
9124
|
+
let msg = `Group '[${arrow.targetLabel}]' not found`;
|
|
9125
|
+
const hint = suggest(targetKey, allLabels);
|
|
9126
|
+
if (hint) msg += `. ${hint}`;
|
|
9127
|
+
pushError(arrow.lineNumber, msg);
|
|
9128
|
+
continue;
|
|
9129
|
+
}
|
|
9130
|
+
result.edges.push({
|
|
9131
|
+
sourceId: arrow.sourceNode.id,
|
|
9132
|
+
targetId: targetContainer.id,
|
|
9133
|
+
label: arrow.label,
|
|
9134
|
+
color: arrow.color,
|
|
9135
|
+
lineNumber: arrow.lineNumber
|
|
9136
|
+
});
|
|
9137
|
+
} else {
|
|
9138
|
+
const targetNode = labelToNode.get(targetKey);
|
|
9139
|
+
if (!targetNode) {
|
|
9140
|
+
const allLabels = Array.from(labelToNode.keys());
|
|
9141
|
+
let msg = `Arrow target "${arrow.targetLabel}" not found`;
|
|
9142
|
+
const hint = suggest(targetKey, allLabels);
|
|
9143
|
+
if (hint) msg += `. ${hint}`;
|
|
9144
|
+
pushError(arrow.lineNumber, msg);
|
|
9145
|
+
continue;
|
|
9146
|
+
}
|
|
9147
|
+
result.edges.push({
|
|
9148
|
+
sourceId: arrow.sourceNode.id,
|
|
9149
|
+
targetId: targetNode.id,
|
|
9150
|
+
label: arrow.label,
|
|
9151
|
+
color: arrow.color,
|
|
9152
|
+
lineNumber: arrow.lineNumber
|
|
9153
|
+
});
|
|
8614
9154
|
}
|
|
8615
|
-
result.edges.push({
|
|
8616
|
-
sourceId: arrow.sourceNode.id,
|
|
8617
|
-
targetId: targetNode.id,
|
|
8618
|
-
label: arrow.label,
|
|
8619
|
-
color: arrow.color,
|
|
8620
|
-
lineNumber: arrow.lineNumber
|
|
8621
|
-
});
|
|
8622
9155
|
}
|
|
8623
9156
|
if (result.tagGroups.length > 0) {
|
|
8624
9157
|
const allNodes = [];
|
|
@@ -10332,6 +10865,7 @@ function parseBoxesAndLines(content) {
|
|
|
10332
10865
|
const nodeLabels = /* @__PURE__ */ new Set();
|
|
10333
10866
|
const groupLabels = /* @__PURE__ */ new Set();
|
|
10334
10867
|
let lastNodeLabel = null;
|
|
10868
|
+
let lastSourceIsGroup = false;
|
|
10335
10869
|
const groupStack = [];
|
|
10336
10870
|
let contentStarted = false;
|
|
10337
10871
|
let currentTagGroup = null;
|
|
@@ -10570,6 +11104,8 @@ function parseBoxesAndLines(content) {
|
|
|
10570
11104
|
};
|
|
10571
11105
|
groupLabels.add(label);
|
|
10572
11106
|
groupStack.push({ group, indent, depth: currentDepth });
|
|
11107
|
+
lastNodeLabel = label;
|
|
11108
|
+
lastSourceIsGroup = true;
|
|
10573
11109
|
continue;
|
|
10574
11110
|
}
|
|
10575
11111
|
if (trimmed.includes("->") || trimmed.includes("<->")) {
|
|
@@ -10587,7 +11123,8 @@ function parseBoxesAndLines(content) {
|
|
|
10587
11123
|
);
|
|
10588
11124
|
continue;
|
|
10589
11125
|
}
|
|
10590
|
-
|
|
11126
|
+
const sourcePrefix = lastSourceIsGroup ? `[${lastNodeLabel}]` : lastNodeLabel;
|
|
11127
|
+
edgeText = `${sourcePrefix} ${trimmed}`;
|
|
10591
11128
|
}
|
|
10592
11129
|
const edge = parseEdgeLine(
|
|
10593
11130
|
edgeText,
|
|
@@ -10610,6 +11147,7 @@ function parseBoxesAndLines(content) {
|
|
|
10610
11147
|
continue;
|
|
10611
11148
|
}
|
|
10612
11149
|
lastNodeLabel = node.label;
|
|
11150
|
+
lastSourceIsGroup = false;
|
|
10613
11151
|
const gs = currentGroupState();
|
|
10614
11152
|
const isGroupChild = gs && indent > gs.indent;
|
|
10615
11153
|
if (nodeLabels.has(node.label)) {
|
|
@@ -10637,14 +11175,42 @@ function parseBoxesAndLines(content) {
|
|
|
10637
11175
|
const gs = groupStack.pop();
|
|
10638
11176
|
result.groups.push(gs.group);
|
|
10639
11177
|
}
|
|
11178
|
+
const validEdges = [];
|
|
10640
11179
|
for (const edge of result.edges) {
|
|
10641
|
-
|
|
11180
|
+
let valid = true;
|
|
11181
|
+
if (edge.source.startsWith("__group_")) {
|
|
11182
|
+
const label = edge.source.slice("__group_".length);
|
|
11183
|
+
const found = [...groupLabels].some(
|
|
11184
|
+
(g) => g.toLowerCase() === label.toLowerCase()
|
|
11185
|
+
);
|
|
11186
|
+
if (!found) {
|
|
11187
|
+
result.diagnostics.push(
|
|
11188
|
+
makeDgmoError(edge.lineNumber, `Group '[${label}]' not found`)
|
|
11189
|
+
);
|
|
11190
|
+
valid = false;
|
|
11191
|
+
}
|
|
11192
|
+
} else {
|
|
10642
11193
|
ensureNode(edge.source, edge.lineNumber);
|
|
10643
11194
|
}
|
|
10644
|
-
if (
|
|
11195
|
+
if (edge.target.startsWith("__group_")) {
|
|
11196
|
+
const label = edge.target.slice("__group_".length);
|
|
11197
|
+
const found = [...groupLabels].some(
|
|
11198
|
+
(g) => g.toLowerCase() === label.toLowerCase()
|
|
11199
|
+
);
|
|
11200
|
+
if (!found) {
|
|
11201
|
+
result.diagnostics.push(
|
|
11202
|
+
makeDgmoError(edge.lineNumber, `Group '[${label}]' not found`)
|
|
11203
|
+
);
|
|
11204
|
+
valid = false;
|
|
11205
|
+
}
|
|
11206
|
+
} else {
|
|
10645
11207
|
ensureNode(edge.target, edge.lineNumber);
|
|
10646
11208
|
}
|
|
11209
|
+
if (valid) {
|
|
11210
|
+
validEdges.push(edge);
|
|
11211
|
+
}
|
|
10647
11212
|
}
|
|
11213
|
+
result.edges = validEdges;
|
|
10648
11214
|
if (result.tagGroups.length > 0) {
|
|
10649
11215
|
injectDefaultTagMetadata(result.nodes, result.tagGroups);
|
|
10650
11216
|
validateTagValues(result.nodes, result.tagGroups, pushWarning, suggest);
|
|
@@ -10673,10 +11239,14 @@ function parseNodeLine(trimmed, lineNum, aliasMap, _diagnostics) {
|
|
|
10673
11239
|
description
|
|
10674
11240
|
};
|
|
10675
11241
|
}
|
|
11242
|
+
function resolveEndpoint(name) {
|
|
11243
|
+
const m = name.match(/^\[(.+)\]$/);
|
|
11244
|
+
return m ? groupId2(m[1].trim()) : name;
|
|
11245
|
+
}
|
|
10676
11246
|
function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
10677
11247
|
const biLabeledMatch = trimmed.match(/^(.+?)\s*<-(.+)->\s*(.+)$/);
|
|
10678
11248
|
if (biLabeledMatch) {
|
|
10679
|
-
const source2 = biLabeledMatch[1].trim();
|
|
11249
|
+
const source2 = resolveEndpoint(biLabeledMatch[1].trim());
|
|
10680
11250
|
const label = biLabeledMatch[2].trim();
|
|
10681
11251
|
let rest2 = biLabeledMatch[3].trim();
|
|
10682
11252
|
let metadata2 = {};
|
|
@@ -10697,7 +11267,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10697
11267
|
}
|
|
10698
11268
|
return {
|
|
10699
11269
|
source: source2,
|
|
10700
|
-
target: rest2,
|
|
11270
|
+
target: resolveEndpoint(rest2),
|
|
10701
11271
|
label: label || void 0,
|
|
10702
11272
|
bidirectional: true,
|
|
10703
11273
|
lineNumber: lineNum,
|
|
@@ -10706,7 +11276,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10706
11276
|
}
|
|
10707
11277
|
const biIdx = trimmed.indexOf("<->");
|
|
10708
11278
|
if (biIdx >= 0) {
|
|
10709
|
-
const source2 = trimmed.slice(0, biIdx).trim();
|
|
11279
|
+
const source2 = resolveEndpoint(trimmed.slice(0, biIdx).trim());
|
|
10710
11280
|
let rest2 = trimmed.slice(biIdx + 3).trim();
|
|
10711
11281
|
let metadata2 = {};
|
|
10712
11282
|
const pipeIdx2 = rest2.indexOf("|");
|
|
@@ -10726,7 +11296,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10726
11296
|
}
|
|
10727
11297
|
return {
|
|
10728
11298
|
source: source2,
|
|
10729
|
-
target: rest2,
|
|
11299
|
+
target: resolveEndpoint(rest2),
|
|
10730
11300
|
bidirectional: true,
|
|
10731
11301
|
lineNumber: lineNum,
|
|
10732
11302
|
metadata: metadata2
|
|
@@ -10734,7 +11304,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10734
11304
|
}
|
|
10735
11305
|
const labeledMatch = trimmed.match(/^(.+?)\s+-(.+)->\s*(.+)$/);
|
|
10736
11306
|
if (labeledMatch) {
|
|
10737
|
-
const source2 = labeledMatch[1].trim();
|
|
11307
|
+
const source2 = resolveEndpoint(labeledMatch[1].trim());
|
|
10738
11308
|
const label = labeledMatch[2].trim();
|
|
10739
11309
|
let rest2 = labeledMatch[3].trim();
|
|
10740
11310
|
if (label) {
|
|
@@ -10756,7 +11326,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10756
11326
|
}
|
|
10757
11327
|
return {
|
|
10758
11328
|
source: source2,
|
|
10759
|
-
target: rest2,
|
|
11329
|
+
target: resolveEndpoint(rest2),
|
|
10760
11330
|
label,
|
|
10761
11331
|
bidirectional: false,
|
|
10762
11332
|
lineNumber: lineNum,
|
|
@@ -10766,7 +11336,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10766
11336
|
}
|
|
10767
11337
|
const arrowIdx = trimmed.indexOf("->");
|
|
10768
11338
|
if (arrowIdx < 0) return null;
|
|
10769
|
-
const source = trimmed.slice(0, arrowIdx).trim();
|
|
11339
|
+
const source = resolveEndpoint(trimmed.slice(0, arrowIdx).trim());
|
|
10770
11340
|
let rest = trimmed.slice(arrowIdx + 2).trim();
|
|
10771
11341
|
if (!source || !rest) {
|
|
10772
11342
|
diagnostics.push(
|
|
@@ -10787,7 +11357,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10787
11357
|
}
|
|
10788
11358
|
return {
|
|
10789
11359
|
source,
|
|
10790
|
-
target: rest,
|
|
11360
|
+
target: resolveEndpoint(rest),
|
|
10791
11361
|
bidirectional: false,
|
|
10792
11362
|
lineNumber: lineNum,
|
|
10793
11363
|
metadata
|
|
@@ -11102,14 +11672,14 @@ function computeLegendGroups(tagGroups, showEyeIcons, usedValuesByGroup) {
|
|
|
11102
11672
|
const usedValues = usedValuesByGroup?.get(group.name.toLowerCase());
|
|
11103
11673
|
const visibleEntries = usedValues ? group.entries.filter((e) => usedValues.has(e.value.toLowerCase())) : group.entries;
|
|
11104
11674
|
if (visibleEntries.length === 0) continue;
|
|
11105
|
-
const
|
|
11106
|
-
const minPillWidth =
|
|
11107
|
-
let
|
|
11675
|
+
const pillWidth3 = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD2;
|
|
11676
|
+
const minPillWidth = pillWidth3;
|
|
11677
|
+
let entriesWidth3 = 0;
|
|
11108
11678
|
for (const entry of visibleEntries) {
|
|
11109
|
-
|
|
11679
|
+
entriesWidth3 += LEGEND_DOT_R2 * 2 + LEGEND_ENTRY_DOT_GAP2 + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL2;
|
|
11110
11680
|
}
|
|
11111
11681
|
const eyeSpace = showEyeIcons ? LEGEND_EYE_SIZE2 + LEGEND_EYE_GAP2 : 0;
|
|
11112
|
-
const
|
|
11682
|
+
const capsuleWidth2 = LEGEND_CAPSULE_PAD2 * 2 + pillWidth3 + 4 + eyeSpace + entriesWidth3;
|
|
11113
11683
|
groups.push({
|
|
11114
11684
|
name: group.name,
|
|
11115
11685
|
alias: group.alias,
|
|
@@ -11119,7 +11689,7 @@ function computeLegendGroups(tagGroups, showEyeIcons, usedValuesByGroup) {
|
|
|
11119
11689
|
})),
|
|
11120
11690
|
x: 0,
|
|
11121
11691
|
y: 0,
|
|
11122
|
-
width:
|
|
11692
|
+
width: capsuleWidth2,
|
|
11123
11693
|
height: LEGEND_HEIGHT2,
|
|
11124
11694
|
minifiedWidth: minPillWidth,
|
|
11125
11695
|
minifiedHeight: LEGEND_HEIGHT2
|
|
@@ -12060,66 +12630,77 @@ function renderOrg(container, parsed, layout, palette, isDark, onClickItem, expo
|
|
|
12060
12630
|
}
|
|
12061
12631
|
}
|
|
12062
12632
|
if (fixedLegend || legendOnly || exportDims && hasLegend) {
|
|
12063
|
-
const
|
|
12064
|
-
|
|
12065
|
-
|
|
12066
|
-
|
|
12067
|
-
|
|
12068
|
-
|
|
12069
|
-
|
|
12070
|
-
|
|
12071
|
-
|
|
12072
|
-
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12078
|
-
|
|
12079
|
-
|
|
12080
|
-
|
|
12081
|
-
|
|
12082
|
-
|
|
12633
|
+
const groups = layout.legend.map((g) => ({
|
|
12634
|
+
name: g.name,
|
|
12635
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
12636
|
+
}));
|
|
12637
|
+
const eyeAddonWidth = fixedLegend ? LEGEND_EYE_SIZE + LEGEND_EYE_GAP : 0;
|
|
12638
|
+
const legendParentBase = fixedLegend ? svg.append("g").attr("class", "org-legend-fixed").attr("transform", `translate(0, ${DIAGRAM_PADDING + titleReserve})`) : contentG.append("g");
|
|
12639
|
+
let legendHandle;
|
|
12640
|
+
if (legendOnly) {
|
|
12641
|
+
for (const lg of layout.legend) {
|
|
12642
|
+
const singleConfig = {
|
|
12643
|
+
groups: [
|
|
12644
|
+
{
|
|
12645
|
+
name: lg.name,
|
|
12646
|
+
entries: lg.entries.map((e) => ({
|
|
12647
|
+
value: e.value,
|
|
12648
|
+
color: e.color
|
|
12649
|
+
}))
|
|
12650
|
+
}
|
|
12651
|
+
],
|
|
12652
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
12653
|
+
mode: "fixed"
|
|
12654
|
+
};
|
|
12655
|
+
const singleState = { activeGroup: lg.name };
|
|
12656
|
+
const groupG = legendParentBase.append("g").attr("transform", `translate(${lg.x}, ${lg.y})`);
|
|
12657
|
+
renderLegendD3(
|
|
12658
|
+
groupG,
|
|
12659
|
+
singleConfig,
|
|
12660
|
+
singleState,
|
|
12661
|
+
palette,
|
|
12662
|
+
isDark,
|
|
12663
|
+
void 0,
|
|
12664
|
+
lg.width
|
|
12665
|
+
);
|
|
12666
|
+
groupG.selectAll("[data-legend-group]").classed("org-legend-group", true);
|
|
12667
|
+
}
|
|
12668
|
+
legendHandle = null;
|
|
12669
|
+
} else {
|
|
12670
|
+
const legendConfig = {
|
|
12671
|
+
groups,
|
|
12672
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
12673
|
+
mode: "fixed",
|
|
12674
|
+
capsulePillAddonWidth: eyeAddonWidth
|
|
12675
|
+
};
|
|
12676
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
12677
|
+
legendHandle = renderLegendD3(
|
|
12678
|
+
legendParentBase,
|
|
12679
|
+
legendConfig,
|
|
12680
|
+
legendState,
|
|
12681
|
+
palette,
|
|
12682
|
+
isDark,
|
|
12683
|
+
void 0,
|
|
12684
|
+
fixedLegend ? width : layout.width
|
|
12685
|
+
);
|
|
12686
|
+
legendParentBase.selectAll("[data-legend-group]").classed("org-legend-group", true);
|
|
12083
12687
|
}
|
|
12084
|
-
|
|
12085
|
-
const
|
|
12086
|
-
|
|
12087
|
-
|
|
12088
|
-
|
|
12089
|
-
const gX = fixedPositions?.get(group.name) ?? group.x;
|
|
12090
|
-
const gY = fixedPositions ? 0 : group.y;
|
|
12091
|
-
const gEl = legendParent.append("g").attr("transform", `translate(${gX}, ${gY})`).attr("class", "org-legend-group").attr("data-legend-group", group.name.toLowerCase()).style("cursor", legendOnly ? "default" : "pointer");
|
|
12092
|
-
if (isActive) {
|
|
12093
|
-
gEl.append("rect").attr("width", group.width).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
12094
|
-
}
|
|
12095
|
-
const pillXOff = isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
12096
|
-
const pillYOff = LEGEND_CAPSULE_PAD;
|
|
12097
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
12098
|
-
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", isActive ? palette.bg : groupBg);
|
|
12099
|
-
if (isActive) {
|
|
12100
|
-
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
12101
|
-
}
|
|
12102
|
-
gEl.append("text").attr("x", pillXOff + pillWidth2 / 2).attr("y", LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(pillLabel);
|
|
12103
|
-
if (isActive && fixedLegend) {
|
|
12104
|
-
const groupKey = group.name.toLowerCase();
|
|
12688
|
+
if (fixedLegend && legendHandle) {
|
|
12689
|
+
const computedLayout = legendHandle.getLayout();
|
|
12690
|
+
if (computedLayout.activeCapsule?.addonX != null) {
|
|
12691
|
+
const capsule = computedLayout.activeCapsule;
|
|
12692
|
+
const groupKey = capsule.groupName.toLowerCase();
|
|
12105
12693
|
const isHidden = hiddenAttributes?.has(groupKey) ?? false;
|
|
12106
|
-
const
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
for (const entry of group.entries) {
|
|
12117
|
-
const entryG = gEl.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
12118
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
12119
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
12120
|
-
const entryLabel = entry.value;
|
|
12121
|
-
entryG.append("text").attr("x", textX).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entryLabel);
|
|
12122
|
-
entryX = textX + measureLegendText(entryLabel, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
12694
|
+
const activeGroupEl = legendParentBase.select(
|
|
12695
|
+
`[data-legend-group="${groupKey}"]`
|
|
12696
|
+
);
|
|
12697
|
+
if (!activeGroupEl.empty()) {
|
|
12698
|
+
const eyeX = capsule.addonX;
|
|
12699
|
+
const eyeY = (LEGEND_HEIGHT - LEGEND_EYE_SIZE) / 2;
|
|
12700
|
+
const hitPad = 6;
|
|
12701
|
+
const eyeG = activeGroupEl.append("g").attr("class", "org-legend-eye").attr("data-legend-visibility", groupKey).style("cursor", "pointer").attr("opacity", isHidden ? 0.4 : 0.7);
|
|
12702
|
+
eyeG.append("rect").attr("x", eyeX - hitPad).attr("y", eyeY - hitPad).attr("width", LEGEND_EYE_SIZE + hitPad * 2).attr("height", LEGEND_EYE_SIZE + hitPad * 2).attr("fill", "transparent").attr("pointer-events", "all");
|
|
12703
|
+
eyeG.append("path").attr("d", isHidden ? EYE_CLOSED_PATH : EYE_OPEN_PATH).attr("transform", `translate(${eyeX}, ${eyeY})`).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1.2).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
12123
12704
|
}
|
|
12124
12705
|
}
|
|
12125
12706
|
}
|
|
@@ -12153,6 +12734,7 @@ var init_renderer = __esm({
|
|
|
12153
12734
|
init_parser4();
|
|
12154
12735
|
init_layout();
|
|
12155
12736
|
init_legend_constants();
|
|
12737
|
+
init_legend_d3();
|
|
12156
12738
|
init_title_constants();
|
|
12157
12739
|
DIAGRAM_PADDING = 20;
|
|
12158
12740
|
MAX_SCALE = 3;
|
|
@@ -12182,6 +12764,17 @@ __export(layout_exports2, {
|
|
|
12182
12764
|
layoutSitemap: () => layoutSitemap
|
|
12183
12765
|
});
|
|
12184
12766
|
import dagre from "@dagrejs/dagre";
|
|
12767
|
+
function clipToRectBorder(cx, cy, w, h, tx, ty) {
|
|
12768
|
+
const dx = tx - cx;
|
|
12769
|
+
const dy = ty - cy;
|
|
12770
|
+
if (dx === 0 && dy === 0) return { x: cx, y: cy };
|
|
12771
|
+
const hw = w / 2;
|
|
12772
|
+
const hh = h / 2;
|
|
12773
|
+
const sx = dx !== 0 ? hw / Math.abs(dx) : Infinity;
|
|
12774
|
+
const sy = dy !== 0 ? hh / Math.abs(dy) : Infinity;
|
|
12775
|
+
const s = Math.min(sx, sy);
|
|
12776
|
+
return { x: cx + dx * s, y: cy + dy * s };
|
|
12777
|
+
}
|
|
12185
12778
|
function filterMetadata2(metadata, hiddenAttributes) {
|
|
12186
12779
|
if (!hiddenAttributes || hiddenAttributes.size === 0) return metadata;
|
|
12187
12780
|
const filtered = {};
|
|
@@ -12198,7 +12791,10 @@ function computeCardWidth2(label, meta) {
|
|
|
12198
12791
|
const lineChars = key.length + 2 + value.length;
|
|
12199
12792
|
if (lineChars > maxChars) maxChars = lineChars;
|
|
12200
12793
|
}
|
|
12201
|
-
return Math.max(
|
|
12794
|
+
return Math.max(
|
|
12795
|
+
MIN_CARD_WIDTH2,
|
|
12796
|
+
Math.ceil(maxChars * CHAR_WIDTH2) + CARD_H_PAD2 * 2
|
|
12797
|
+
);
|
|
12202
12798
|
}
|
|
12203
12799
|
function computeCardHeight2(meta) {
|
|
12204
12800
|
const metaCount = Object.keys(meta).length;
|
|
@@ -12207,7 +12803,12 @@ function computeCardHeight2(meta) {
|
|
|
12207
12803
|
}
|
|
12208
12804
|
function resolveNodeColor2(node, tagGroups, activeGroupName) {
|
|
12209
12805
|
if (node.color) return node.color;
|
|
12210
|
-
return resolveTagColor(
|
|
12806
|
+
return resolveTagColor(
|
|
12807
|
+
node.metadata,
|
|
12808
|
+
tagGroups,
|
|
12809
|
+
activeGroupName,
|
|
12810
|
+
node.isContainer
|
|
12811
|
+
);
|
|
12211
12812
|
}
|
|
12212
12813
|
function computeLegendGroups2(tagGroups, usedValuesByGroup) {
|
|
12213
12814
|
const groups = [];
|
|
@@ -12216,21 +12817,21 @@ function computeLegendGroups2(tagGroups, usedValuesByGroup) {
|
|
|
12216
12817
|
const usedValues = usedValuesByGroup?.get(group.name.toLowerCase());
|
|
12217
12818
|
const visibleEntries = usedValues ? group.entries.filter((e) => usedValues.has(e.value.toLowerCase())) : group.entries;
|
|
12218
12819
|
if (visibleEntries.length === 0) continue;
|
|
12219
|
-
const
|
|
12220
|
-
const minPillWidth =
|
|
12221
|
-
let
|
|
12820
|
+
const pillWidth3 = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD3;
|
|
12821
|
+
const minPillWidth = pillWidth3;
|
|
12822
|
+
let entriesWidth3 = 0;
|
|
12222
12823
|
for (const entry of visibleEntries) {
|
|
12223
|
-
|
|
12824
|
+
entriesWidth3 += LEGEND_DOT_R3 * 2 + LEGEND_ENTRY_DOT_GAP3 + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL3;
|
|
12224
12825
|
}
|
|
12225
12826
|
const eyeSpace = LEGEND_EYE_SIZE3 + LEGEND_EYE_GAP3;
|
|
12226
|
-
const
|
|
12827
|
+
const capsuleWidth2 = LEGEND_CAPSULE_PAD3 * 2 + pillWidth3 + 4 + eyeSpace + entriesWidth3;
|
|
12227
12828
|
groups.push({
|
|
12228
12829
|
name: group.name,
|
|
12229
12830
|
alias: group.alias,
|
|
12230
12831
|
entries: visibleEntries.map((e) => ({ value: e.value, color: e.color })),
|
|
12231
12832
|
x: 0,
|
|
12232
12833
|
y: 0,
|
|
12233
|
-
width:
|
|
12834
|
+
width: capsuleWidth2,
|
|
12234
12835
|
height: LEGEND_HEIGHT3,
|
|
12235
12836
|
minifiedWidth: minPillWidth,
|
|
12236
12837
|
minifiedHeight: LEGEND_HEIGHT3
|
|
@@ -12250,10 +12851,20 @@ function flattenNodes(nodes, parentContainerId, parentPageId, hiddenCounts, hidd
|
|
|
12250
12851
|
parentPageId,
|
|
12251
12852
|
meta,
|
|
12252
12853
|
fullMeta: { ...node.metadata },
|
|
12253
|
-
width: Math.max(
|
|
12854
|
+
width: Math.max(
|
|
12855
|
+
MIN_CARD_WIDTH2,
|
|
12856
|
+
node.label.length * CHAR_WIDTH2 + CARD_H_PAD2 * 2
|
|
12857
|
+
),
|
|
12254
12858
|
height: labelHeight + CONTAINER_PAD_BOTTOM2
|
|
12255
12859
|
});
|
|
12256
|
-
flattenNodes(
|
|
12860
|
+
flattenNodes(
|
|
12861
|
+
node.children,
|
|
12862
|
+
node.id,
|
|
12863
|
+
parentPageId,
|
|
12864
|
+
hiddenCounts,
|
|
12865
|
+
hiddenAttributes,
|
|
12866
|
+
result
|
|
12867
|
+
);
|
|
12257
12868
|
} else {
|
|
12258
12869
|
result.push({
|
|
12259
12870
|
sitemapNode: node,
|
|
@@ -12265,14 +12876,28 @@ function flattenNodes(nodes, parentContainerId, parentPageId, hiddenCounts, hidd
|
|
|
12265
12876
|
height: computeCardHeight2(meta)
|
|
12266
12877
|
});
|
|
12267
12878
|
if (node.children.length > 0) {
|
|
12268
|
-
flattenNodes(
|
|
12879
|
+
flattenNodes(
|
|
12880
|
+
node.children,
|
|
12881
|
+
parentContainerId,
|
|
12882
|
+
node.id,
|
|
12883
|
+
hiddenCounts,
|
|
12884
|
+
hiddenAttributes,
|
|
12885
|
+
result
|
|
12886
|
+
);
|
|
12269
12887
|
}
|
|
12270
12888
|
}
|
|
12271
12889
|
}
|
|
12272
12890
|
}
|
|
12273
12891
|
function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, expandAllLegend) {
|
|
12274
12892
|
if (parsed.roots.length === 0) {
|
|
12275
|
-
return {
|
|
12893
|
+
return {
|
|
12894
|
+
nodes: [],
|
|
12895
|
+
edges: [],
|
|
12896
|
+
containers: [],
|
|
12897
|
+
legend: [],
|
|
12898
|
+
width: 0,
|
|
12899
|
+
height: 0
|
|
12900
|
+
};
|
|
12276
12901
|
}
|
|
12277
12902
|
const allNodes = [];
|
|
12278
12903
|
const collect = (node) => {
|
|
@@ -12280,9 +12905,20 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12280
12905
|
for (const child of node.children) collect(child);
|
|
12281
12906
|
};
|
|
12282
12907
|
for (const root of parsed.roots) collect(root);
|
|
12283
|
-
injectDefaultTagMetadata(
|
|
12908
|
+
injectDefaultTagMetadata(
|
|
12909
|
+
allNodes,
|
|
12910
|
+
parsed.tagGroups,
|
|
12911
|
+
(e) => e.isContainer
|
|
12912
|
+
);
|
|
12284
12913
|
const flatNodes = [];
|
|
12285
|
-
flattenNodes(
|
|
12914
|
+
flattenNodes(
|
|
12915
|
+
parsed.roots,
|
|
12916
|
+
null,
|
|
12917
|
+
null,
|
|
12918
|
+
hiddenCounts,
|
|
12919
|
+
hiddenAttributes,
|
|
12920
|
+
flatNodes
|
|
12921
|
+
);
|
|
12286
12922
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
12287
12923
|
for (const flat of flatNodes) {
|
|
12288
12924
|
nodeMap.set(flat.sitemapNode.id, flat);
|
|
@@ -12344,14 +12980,29 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12344
12980
|
g.setParent(flat.sitemapNode.id, flat.parentContainerId);
|
|
12345
12981
|
}
|
|
12346
12982
|
}
|
|
12983
|
+
const expandedContainerIds = /* @__PURE__ */ new Set();
|
|
12984
|
+
for (const cid of containerIds) {
|
|
12985
|
+
if (!collapsedContainerIds.has(cid)) {
|
|
12986
|
+
expandedContainerIds.add(cid);
|
|
12987
|
+
}
|
|
12988
|
+
}
|
|
12989
|
+
const deferredEdgeIndices = [];
|
|
12347
12990
|
for (let i = 0; i < parsed.edges.length; i++) {
|
|
12348
12991
|
const edge = parsed.edges[i];
|
|
12349
|
-
if (g.hasNode(edge.sourceId)
|
|
12350
|
-
|
|
12992
|
+
if (!g.hasNode(edge.sourceId) || !g.hasNode(edge.targetId)) continue;
|
|
12993
|
+
if (expandedContainerIds.has(edge.sourceId) || expandedContainerIds.has(edge.targetId)) {
|
|
12994
|
+
deferredEdgeIndices.push(i);
|
|
12995
|
+
continue;
|
|
12996
|
+
}
|
|
12997
|
+
g.setEdge(
|
|
12998
|
+
edge.sourceId,
|
|
12999
|
+
edge.targetId,
|
|
13000
|
+
{
|
|
12351
13001
|
label: edge.label ?? "",
|
|
12352
13002
|
minlen: 1
|
|
12353
|
-
},
|
|
12354
|
-
|
|
13003
|
+
},
|
|
13004
|
+
`e${i}`
|
|
13005
|
+
);
|
|
12355
13006
|
}
|
|
12356
13007
|
dagre.layout(g);
|
|
12357
13008
|
const layoutNodes = [];
|
|
@@ -12419,19 +13070,52 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12419
13070
|
});
|
|
12420
13071
|
}
|
|
12421
13072
|
}
|
|
13073
|
+
const deferredSet = new Set(deferredEdgeIndices);
|
|
12422
13074
|
const layoutEdges = [];
|
|
12423
13075
|
for (let i = 0; i < parsed.edges.length; i++) {
|
|
12424
13076
|
const edge = parsed.edges[i];
|
|
12425
13077
|
if (!g.hasNode(edge.sourceId) || !g.hasNode(edge.targetId)) continue;
|
|
12426
|
-
|
|
12427
|
-
if (
|
|
13078
|
+
let points;
|
|
13079
|
+
if (deferredSet.has(i)) {
|
|
13080
|
+
const srcNode = g.node(edge.sourceId);
|
|
13081
|
+
const tgtNode = g.node(edge.targetId);
|
|
13082
|
+
if (!srcNode || !tgtNode) continue;
|
|
13083
|
+
const srcPt = clipToRectBorder(
|
|
13084
|
+
srcNode.x,
|
|
13085
|
+
srcNode.y,
|
|
13086
|
+
srcNode.width,
|
|
13087
|
+
srcNode.height,
|
|
13088
|
+
tgtNode.x,
|
|
13089
|
+
tgtNode.y
|
|
13090
|
+
);
|
|
13091
|
+
const tgtPt = clipToRectBorder(
|
|
13092
|
+
tgtNode.x,
|
|
13093
|
+
tgtNode.y,
|
|
13094
|
+
tgtNode.width,
|
|
13095
|
+
tgtNode.height,
|
|
13096
|
+
srcNode.x,
|
|
13097
|
+
srcNode.y
|
|
13098
|
+
);
|
|
13099
|
+
const midX = (srcPt.x + tgtPt.x) / 2;
|
|
13100
|
+
const midY = (srcPt.y + tgtPt.y) / 2;
|
|
13101
|
+
points = [srcPt, { x: midX, y: midY }, tgtPt];
|
|
13102
|
+
} else {
|
|
13103
|
+
const edgeData = g.edge({
|
|
13104
|
+
v: edge.sourceId,
|
|
13105
|
+
w: edge.targetId,
|
|
13106
|
+
name: `e${i}`
|
|
13107
|
+
});
|
|
13108
|
+
if (!edgeData) continue;
|
|
13109
|
+
points = edgeData.points ?? [];
|
|
13110
|
+
}
|
|
12428
13111
|
layoutEdges.push({
|
|
12429
13112
|
sourceId: edge.sourceId,
|
|
12430
13113
|
targetId: edge.targetId,
|
|
12431
|
-
points
|
|
13114
|
+
points,
|
|
12432
13115
|
label: edge.label,
|
|
12433
13116
|
color: edge.color,
|
|
12434
|
-
lineNumber: edge.lineNumber
|
|
13117
|
+
lineNumber: edge.lineNumber,
|
|
13118
|
+
deferred: deferredSet.has(i) || void 0
|
|
12435
13119
|
});
|
|
12436
13120
|
}
|
|
12437
13121
|
{
|
|
@@ -12592,7 +13276,9 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12592
13276
|
usedValuesByGroup.set(key, used);
|
|
12593
13277
|
}
|
|
12594
13278
|
const legendGroups = computeLegendGroups2(parsed.tagGroups, usedValuesByGroup);
|
|
12595
|
-
const visibleGroups = activeTagGroup != null ? legendGroups.filter(
|
|
13279
|
+
const visibleGroups = activeTagGroup != null ? legendGroups.filter(
|
|
13280
|
+
(g2) => g2.name.toLowerCase() === activeTagGroup.toLowerCase()
|
|
13281
|
+
) : legendGroups;
|
|
12596
13282
|
const allExpanded = expandAllLegend && activeTagGroup == null;
|
|
12597
13283
|
const effectiveW = (g2) => activeTagGroup != null || allExpanded ? g2.width : g2.minifiedWidth;
|
|
12598
13284
|
if (visibleGroups.length > 0) {
|
|
@@ -12908,7 +13594,8 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
12908
13594
|
const edgeG = contentG.append("g").attr("class", "sitemap-edge-group").attr("data-line-number", String(edge.lineNumber));
|
|
12909
13595
|
const edgeColor3 = edge.color ?? palette.textMuted;
|
|
12910
13596
|
const markerId = edge.color ? `sm-arrow-${edge.color.replace("#", "")}` : "sm-arrow";
|
|
12911
|
-
const
|
|
13597
|
+
const gen = edge.deferred ? lineGeneratorLinear : lineGenerator;
|
|
13598
|
+
const pathD = gen(edge.points);
|
|
12912
13599
|
if (pathD) {
|
|
12913
13600
|
edgeG.append("path").attr("d", pathD).attr("fill", "none").attr("stroke", edgeColor3).attr("stroke-width", EDGE_STROKE_WIDTH2).attr("marker-end", `url(#${markerId})`).attr("class", "sitemap-edge");
|
|
12914
13601
|
}
|
|
@@ -12999,57 +13686,44 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
12999
13686
|
}
|
|
13000
13687
|
function renderLegend(parent, legendGroups, palette, isDark, activeTagGroup, fixedWidth, hiddenAttributes) {
|
|
13001
13688
|
if (legendGroups.length === 0) return;
|
|
13002
|
-
const
|
|
13003
|
-
|
|
13004
|
-
|
|
13005
|
-
|
|
13006
|
-
|
|
13007
|
-
|
|
13008
|
-
|
|
13009
|
-
|
|
13010
|
-
|
|
13011
|
-
|
|
13012
|
-
|
|
13013
|
-
|
|
13014
|
-
|
|
13015
|
-
|
|
13016
|
-
|
|
13017
|
-
|
|
13018
|
-
|
|
13019
|
-
|
|
13020
|
-
|
|
13021
|
-
|
|
13022
|
-
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
|
|
13026
|
-
|
|
13027
|
-
const
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
legendG.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", pillW).attr("height", pillH).attr("rx", pillH / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
13032
|
-
}
|
|
13033
|
-
legendG.append("text").attr("x", pillXOff + pillW / 2).attr("y", LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(group.name);
|
|
13034
|
-
if (isActive && fixedWidth != null) {
|
|
13035
|
-
const groupKey = group.name.toLowerCase();
|
|
13689
|
+
const groups = legendGroups.map((g) => ({
|
|
13690
|
+
name: g.name,
|
|
13691
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
13692
|
+
}));
|
|
13693
|
+
const isFixedMode = fixedWidth != null;
|
|
13694
|
+
const eyeAddonWidth = isFixedMode ? LEGEND_EYE_SIZE + LEGEND_EYE_GAP : 0;
|
|
13695
|
+
const legendConfig = {
|
|
13696
|
+
groups,
|
|
13697
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
13698
|
+
mode: "fixed",
|
|
13699
|
+
capsulePillAddonWidth: eyeAddonWidth
|
|
13700
|
+
};
|
|
13701
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
13702
|
+
const containerWidth = fixedWidth ?? legendGroups[0]?.x + (legendGroups[0]?.width ?? 200);
|
|
13703
|
+
const legendHandle = renderLegendD3(
|
|
13704
|
+
parent,
|
|
13705
|
+
legendConfig,
|
|
13706
|
+
legendState,
|
|
13707
|
+
palette,
|
|
13708
|
+
isDark,
|
|
13709
|
+
void 0,
|
|
13710
|
+
containerWidth
|
|
13711
|
+
);
|
|
13712
|
+
parent.selectAll("[data-legend-group]").classed("sitemap-legend-group", true);
|
|
13713
|
+
if (isFixedMode) {
|
|
13714
|
+
const computedLayout = legendHandle.getLayout();
|
|
13715
|
+
if (computedLayout.activeCapsule?.addonX != null) {
|
|
13716
|
+
const capsule = computedLayout.activeCapsule;
|
|
13717
|
+
const groupKey = capsule.groupName.toLowerCase();
|
|
13036
13718
|
const isHidden = hiddenAttributes?.has(groupKey) ?? false;
|
|
13037
|
-
const
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
const eyeShift = fixedWidth != null ? LEGEND_EYE_SIZE + LEGEND_EYE_GAP : 0;
|
|
13046
|
-
let entryX = pillXOff + pillW + 4 + eyeShift;
|
|
13047
|
-
for (const entry of group.entries) {
|
|
13048
|
-
const entryG = legendG.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
13049
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
13050
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
13051
|
-
entryG.append("text").attr("x", textX).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
13052
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
13719
|
+
const activeGroupEl = parent.select(`[data-legend-group="${groupKey}"]`);
|
|
13720
|
+
if (!activeGroupEl.empty()) {
|
|
13721
|
+
const eyeX = capsule.addonX;
|
|
13722
|
+
const eyeY = (LEGEND_HEIGHT - LEGEND_EYE_SIZE) / 2;
|
|
13723
|
+
const hitPad = 6;
|
|
13724
|
+
const eyeG = activeGroupEl.append("g").attr("class", "sitemap-legend-eye").attr("data-legend-visibility", groupKey).style("cursor", "pointer").attr("opacity", isHidden ? 0.4 : 0.7);
|
|
13725
|
+
eyeG.append("rect").attr("x", eyeX - hitPad).attr("y", eyeY - hitPad).attr("width", LEGEND_EYE_SIZE + hitPad * 2).attr("height", LEGEND_EYE_SIZE + hitPad * 2).attr("fill", "transparent").attr("pointer-events", "all");
|
|
13726
|
+
eyeG.append("path").attr("d", isHidden ? EYE_CLOSED_PATH : EYE_OPEN_PATH).attr("transform", `translate(${eyeX}, ${eyeY})`).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1.2).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
13053
13727
|
}
|
|
13054
13728
|
}
|
|
13055
13729
|
}
|
|
@@ -13103,13 +13777,14 @@ async function renderSitemapForExport(content, theme, palette) {
|
|
|
13103
13777
|
const brandColor = theme === "transparent" ? "#888" : effectivePalette.textMuted;
|
|
13104
13778
|
return injectBranding2(svgHtml, brandColor);
|
|
13105
13779
|
}
|
|
13106
|
-
var DIAGRAM_PADDING2, MAX_SCALE2, TITLE_HEIGHT2, LABEL_FONT_SIZE2, META_FONT_SIZE2, META_LINE_HEIGHT4, HEADER_HEIGHT4, SEPARATOR_GAP4, EDGE_STROKE_WIDTH2, NODE_STROKE_WIDTH2, CARD_RADIUS2, CONTAINER_RADIUS2, CONTAINER_LABEL_FONT_SIZE2, CONTAINER_META_FONT_SIZE2, CONTAINER_META_LINE_HEIGHT4, CONTAINER_HEADER_HEIGHT2, ARROWHEAD_W, ARROWHEAD_H, EDGE_LABEL_FONT_SIZE, COLLAPSE_BAR_HEIGHT2, LEGEND_FIXED_GAP2, lineGenerator;
|
|
13780
|
+
var DIAGRAM_PADDING2, MAX_SCALE2, TITLE_HEIGHT2, LABEL_FONT_SIZE2, META_FONT_SIZE2, META_LINE_HEIGHT4, HEADER_HEIGHT4, SEPARATOR_GAP4, EDGE_STROKE_WIDTH2, NODE_STROKE_WIDTH2, CARD_RADIUS2, CONTAINER_RADIUS2, CONTAINER_LABEL_FONT_SIZE2, CONTAINER_META_FONT_SIZE2, CONTAINER_META_LINE_HEIGHT4, CONTAINER_HEADER_HEIGHT2, ARROWHEAD_W, ARROWHEAD_H, EDGE_LABEL_FONT_SIZE, COLLAPSE_BAR_HEIGHT2, LEGEND_FIXED_GAP2, lineGenerator, lineGeneratorLinear;
|
|
13107
13781
|
var init_renderer2 = __esm({
|
|
13108
13782
|
"src/sitemap/renderer.ts"() {
|
|
13109
13783
|
"use strict";
|
|
13110
13784
|
init_fonts();
|
|
13111
13785
|
init_color_utils();
|
|
13112
13786
|
init_legend_constants();
|
|
13787
|
+
init_legend_d3();
|
|
13113
13788
|
init_title_constants();
|
|
13114
13789
|
DIAGRAM_PADDING2 = 20;
|
|
13115
13790
|
MAX_SCALE2 = 3;
|
|
@@ -13133,6 +13808,7 @@ var init_renderer2 = __esm({
|
|
|
13133
13808
|
COLLAPSE_BAR_HEIGHT2 = 6;
|
|
13134
13809
|
LEGEND_FIXED_GAP2 = 8;
|
|
13135
13810
|
lineGenerator = d3Shape.line().x((d) => d.x).y((d) => d.y).curve(d3Shape.curveBasis);
|
|
13811
|
+
lineGeneratorLinear = d3Shape.line().x((d) => d.x).y((d) => d.y).curve(d3Shape.curveLinear);
|
|
13136
13812
|
}
|
|
13137
13813
|
});
|
|
13138
13814
|
|
|
@@ -13410,53 +14086,22 @@ function renderKanban(container, parsed, palette, isDark, _onNavigateToLine, exp
|
|
|
13410
14086
|
}
|
|
13411
14087
|
if (parsed.tagGroups.length > 0) {
|
|
13412
14088
|
const legendY = height - LEGEND_HEIGHT;
|
|
13413
|
-
|
|
13414
|
-
|
|
13415
|
-
|
|
13416
|
-
|
|
13417
|
-
|
|
13418
|
-
|
|
13419
|
-
}
|
|
13420
|
-
|
|
13421
|
-
|
|
13422
|
-
|
|
13423
|
-
|
|
13424
|
-
|
|
13425
|
-
|
|
13426
|
-
|
|
13427
|
-
|
|
13428
|
-
|
|
13429
|
-
capsuleContentWidth += LEGEND_DOT_R * 2 + 4 + entry.value.length * LEGEND_ENTRY_FONT_SIZE * 0.6 + 8;
|
|
13430
|
-
}
|
|
13431
|
-
}
|
|
13432
|
-
const capsuleWidth = capsuleContentWidth + capsulePad * 2;
|
|
13433
|
-
if (isActive) {
|
|
13434
|
-
legendContainer.append("rect").attr("x", legendX).attr("y", legendY).attr("width", capsuleWidth).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
13435
|
-
}
|
|
13436
|
-
const pillX = legendX + (isActive ? capsulePad : 0);
|
|
13437
|
-
const pillBg = isActive ? palette.bg : groupBg;
|
|
13438
|
-
legendContainer.append("rect").attr("x", pillX).attr("y", legendY + capsulePad).attr("width", pillWidth2).attr("height", LEGEND_HEIGHT - capsulePad * 2).attr("rx", (LEGEND_HEIGHT - capsulePad * 2) / 2).attr("fill", pillBg).attr("class", "kanban-legend-group").attr("data-legend-group", group.name.toLowerCase());
|
|
13439
|
-
if (isActive) {
|
|
13440
|
-
legendContainer.append("rect").attr("x", pillX).attr("y", legendY + capsulePad).attr("width", pillWidth2).attr("height", LEGEND_HEIGHT - capsulePad * 2).attr("rx", (LEGEND_HEIGHT - capsulePad * 2) / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
13441
|
-
}
|
|
13442
|
-
legendContainer.append("text").attr("x", pillX + pillWidth2 / 2).attr("y", legendY + LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(group.name);
|
|
13443
|
-
if (isActive) {
|
|
13444
|
-
let entryX = pillX + pillWidth2 + 4;
|
|
13445
|
-
for (const entry of group.entries) {
|
|
13446
|
-
const entryG = legendContainer.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
13447
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", legendY + LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
13448
|
-
const entryTextX = entryX + LEGEND_DOT_R * 2 + 4;
|
|
13449
|
-
entryG.append("text").attr("x", entryTextX).attr(
|
|
13450
|
-
"y",
|
|
13451
|
-
legendY + LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1
|
|
13452
|
-
).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
13453
|
-
entryX = entryTextX + entry.value.length * LEGEND_ENTRY_FONT_SIZE * 0.6 + 8;
|
|
13454
|
-
}
|
|
13455
|
-
legendX += capsuleWidth + 12;
|
|
13456
|
-
} else {
|
|
13457
|
-
legendX += pillWidth2 + 12;
|
|
13458
|
-
}
|
|
13459
|
-
}
|
|
14089
|
+
const legendConfig = {
|
|
14090
|
+
groups: parsed.tagGroups,
|
|
14091
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
14092
|
+
mode: exportDims ? "inline" : "fixed"
|
|
14093
|
+
};
|
|
14094
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
14095
|
+
const legendG = svg.append("g").attr("class", "kanban-legend").attr("transform", `translate(${DIAGRAM_PADDING3},${legendY})`);
|
|
14096
|
+
renderLegendD3(
|
|
14097
|
+
legendG,
|
|
14098
|
+
legendConfig,
|
|
14099
|
+
legendState,
|
|
14100
|
+
palette,
|
|
14101
|
+
isDark,
|
|
14102
|
+
void 0,
|
|
14103
|
+
width - DIAGRAM_PADDING3 * 2
|
|
14104
|
+
);
|
|
13460
14105
|
}
|
|
13461
14106
|
const defaultColBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
13462
14107
|
const defaultColHeaderBg = isDark ? mix(palette.surface, palette.bg, 70) : mix(palette.surface, palette.bg, 50);
|
|
@@ -13551,6 +14196,7 @@ var init_renderer3 = __esm({
|
|
|
13551
14196
|
init_parser5();
|
|
13552
14197
|
init_mutations();
|
|
13553
14198
|
init_legend_constants();
|
|
14199
|
+
init_legend_d3();
|
|
13554
14200
|
init_title_constants();
|
|
13555
14201
|
DIAGRAM_PADDING3 = 20;
|
|
13556
14202
|
COLUMN_GAP = 16;
|
|
@@ -13746,14 +14392,9 @@ function collectClassTypes(parsed) {
|
|
|
13746
14392
|
if (c.color) continue;
|
|
13747
14393
|
present.add(c.modifier ?? "class");
|
|
13748
14394
|
}
|
|
13749
|
-
return CLASS_TYPE_ORDER.filter((k) => present.has(k)).map(
|
|
13750
|
-
|
|
13751
|
-
|
|
13752
|
-
let w = 0;
|
|
13753
|
-
for (const e of entries) {
|
|
13754
|
-
w += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.label, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
13755
|
-
}
|
|
13756
|
-
return w;
|
|
14395
|
+
return CLASS_TYPE_ORDER.filter((k) => present.has(k)).map(
|
|
14396
|
+
(k) => CLASS_TYPE_MAP[k]
|
|
14397
|
+
);
|
|
13757
14398
|
}
|
|
13758
14399
|
function classTypeKey(modifier) {
|
|
13759
14400
|
return modifier ?? "class";
|
|
@@ -13822,7 +14463,10 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
|
|
|
13822
14463
|
defs.append("marker").attr("id", "cd-arrow-depend").attr("viewBox", `0 0 ${AW} ${AH}`).attr("refX", AW).attr("refY", AH / 2).attr("markerWidth", AW).attr("markerHeight", AH).attr("orient", "auto").append("polyline").attr("points", `0,0 ${AW},${AH / 2} 0,${AH}`).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1.5);
|
|
13823
14464
|
defs.append("marker").attr("id", "cd-arrow-assoc").attr("viewBox", `0 0 ${AW} ${AH}`).attr("refX", AW).attr("refY", AH / 2).attr("markerWidth", AW).attr("markerHeight", AH).attr("orient", "auto").append("polyline").attr("points", `0,0 ${AW},${AH / 2} 0,${AH}`).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1.5);
|
|
13824
14465
|
if (parsed.title) {
|
|
13825
|
-
const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).style(
|
|
14466
|
+
const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).style(
|
|
14467
|
+
"cursor",
|
|
14468
|
+
onClickItem && parsed.titleLineNumber ? "pointer" : "default"
|
|
14469
|
+
).text(parsed.title);
|
|
13826
14470
|
if (parsed.titleLineNumber) {
|
|
13827
14471
|
titleEl.attr("data-line-number", parsed.titleLineNumber);
|
|
13828
14472
|
if (onClickItem) {
|
|
@@ -13836,32 +14480,33 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
|
|
|
13836
14480
|
}
|
|
13837
14481
|
const isLegendExpanded = legendActive !== false;
|
|
13838
14482
|
if (hasLegend) {
|
|
13839
|
-
const
|
|
13840
|
-
|
|
13841
|
-
|
|
13842
|
-
|
|
13843
|
-
|
|
13844
|
-
|
|
13845
|
-
|
|
13846
|
-
const legendG = svg.append("g").attr("class", "cd-legend").attr("data-legend-group", "type").attr("transform", `translate(${legendX}, ${legendY})`).style("cursor", "pointer");
|
|
13847
|
-
if (isLegendExpanded) {
|
|
13848
|
-
legendG.append("rect").attr("width", totalW).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
13849
|
-
legendG.append("rect").attr("x", LEGEND_CAPSULE_PAD).attr("y", LEGEND_CAPSULE_PAD).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", palette.bg);
|
|
13850
|
-
legendG.append("rect").attr("x", LEGEND_CAPSULE_PAD).attr("y", LEGEND_CAPSULE_PAD).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
13851
|
-
legendG.append("text").attr("x", LEGEND_CAPSULE_PAD + pillWidth2 / 2).attr("y", LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", palette.text).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).text(LEGEND_GROUP_NAME);
|
|
13852
|
-
let entryX = LEGEND_CAPSULE_PAD + pillWidth2 + LEGEND_ENTRY_TRAIL;
|
|
13853
|
-
for (const entry of legendEntries) {
|
|
13854
|
-
const color = palette.colors[entry.colorKey];
|
|
13855
|
-
const typeKey = CLASS_TYPE_ORDER.find((k) => CLASS_TYPE_MAP[k] === entry);
|
|
13856
|
-
const entryG = legendG.append("g").attr("data-legend-entry", typeKey);
|
|
13857
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", color);
|
|
13858
|
-
entryG.append("text").attr("x", entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).attr("font-family", FONT_FAMILY).text(entry.label);
|
|
13859
|
-
entryX += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(entry.label, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
14483
|
+
const legendGroups = [
|
|
14484
|
+
{
|
|
14485
|
+
name: LEGEND_GROUP_NAME,
|
|
14486
|
+
entries: legendEntries.map((entry) => ({
|
|
14487
|
+
value: entry.label,
|
|
14488
|
+
color: palette.colors[entry.colorKey]
|
|
14489
|
+
}))
|
|
13860
14490
|
}
|
|
13861
|
-
|
|
13862
|
-
|
|
13863
|
-
|
|
13864
|
-
|
|
14491
|
+
];
|
|
14492
|
+
const legendConfig = {
|
|
14493
|
+
groups: legendGroups,
|
|
14494
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
14495
|
+
mode: "fixed"
|
|
14496
|
+
};
|
|
14497
|
+
const legendState = {
|
|
14498
|
+
activeGroup: isLegendExpanded ? LEGEND_GROUP_NAME : null
|
|
14499
|
+
};
|
|
14500
|
+
const legendG = svg.append("g").attr("class", "cd-legend").attr("transform", `translate(0,${titleHeight})`);
|
|
14501
|
+
renderLegendD3(
|
|
14502
|
+
legendG,
|
|
14503
|
+
legendConfig,
|
|
14504
|
+
legendState,
|
|
14505
|
+
palette,
|
|
14506
|
+
isDark,
|
|
14507
|
+
void 0,
|
|
14508
|
+
width
|
|
14509
|
+
);
|
|
13865
14510
|
}
|
|
13866
14511
|
const contentG = svg.append("g").attr("transform", `translate(${offsetX}, ${offsetY}) scale(${scale})`);
|
|
13867
14512
|
for (const edge of layout.edges) {
|
|
@@ -13905,7 +14550,13 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
|
|
|
13905
14550
|
const colorOff = !!parsed.options?.["no-auto-color"];
|
|
13906
14551
|
const neutralize = hasLegend && !isLegendExpanded && !node.color;
|
|
13907
14552
|
const effectiveColor = neutralize ? palette.primary : node.color;
|
|
13908
|
-
const fill2 = nodeFill3(
|
|
14553
|
+
const fill2 = nodeFill3(
|
|
14554
|
+
palette,
|
|
14555
|
+
isDark,
|
|
14556
|
+
node.modifier,
|
|
14557
|
+
effectiveColor,
|
|
14558
|
+
colorOff
|
|
14559
|
+
);
|
|
13909
14560
|
const stroke2 = nodeStroke3(palette, node.modifier, effectiveColor, colorOff);
|
|
13910
14561
|
nodeG.append("rect").attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h).attr("rx", 3).attr("ry", 3).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", NODE_STROKE_WIDTH3);
|
|
13911
14562
|
let yPos = -h / 2;
|
|
@@ -13974,15 +14625,10 @@ function renderClassDiagramForExport(content, theme, palette) {
|
|
|
13974
14625
|
const exportWidth = layout.width + DIAGRAM_PADDING4 * 2;
|
|
13975
14626
|
const exportHeight = layout.height + DIAGRAM_PADDING4 * 2 + (parsed.title ? 40 : 0) + legendReserve;
|
|
13976
14627
|
return runInExportContainer(exportWidth, exportHeight, (container) => {
|
|
13977
|
-
renderClassDiagram(
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
palette,
|
|
13982
|
-
isDark,
|
|
13983
|
-
void 0,
|
|
13984
|
-
{ width: exportWidth, height: exportHeight }
|
|
13985
|
-
);
|
|
14628
|
+
renderClassDiagram(container, parsed, layout, palette, isDark, void 0, {
|
|
14629
|
+
width: exportWidth,
|
|
14630
|
+
height: exportHeight
|
|
14631
|
+
});
|
|
13986
14632
|
return extractExportSvg(container, theme);
|
|
13987
14633
|
});
|
|
13988
14634
|
}
|
|
@@ -13993,6 +14639,7 @@ var init_renderer4 = __esm({
|
|
|
13993
14639
|
init_fonts();
|
|
13994
14640
|
init_export_container();
|
|
13995
14641
|
init_legend_constants();
|
|
14642
|
+
init_legend_d3();
|
|
13996
14643
|
init_title_constants();
|
|
13997
14644
|
init_color_utils();
|
|
13998
14645
|
init_parser2();
|
|
@@ -14601,35 +15248,24 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
|
|
|
14601
15248
|
}
|
|
14602
15249
|
}
|
|
14603
15250
|
if (parsed.tagGroups.length > 0) {
|
|
14604
|
-
const LEGEND_PILL_H = LEGEND_HEIGHT - 6;
|
|
14605
|
-
const LEGEND_PILL_RX = Math.floor(LEGEND_PILL_H / 2);
|
|
14606
|
-
const LEGEND_GAP = 8;
|
|
14607
|
-
const legendG = svg.append("g").attr("class", "er-tag-legend");
|
|
14608
|
-
if (activeTagGroup) {
|
|
14609
|
-
legendG.attr("data-legend-active", activeTagGroup.toLowerCase());
|
|
14610
|
-
}
|
|
14611
|
-
let legendX = DIAGRAM_PADDING5;
|
|
14612
15251
|
const legendY = DIAGRAM_PADDING5 + titleHeight;
|
|
14613
|
-
|
|
14614
|
-
|
|
14615
|
-
|
|
14616
|
-
|
|
14617
|
-
|
|
14618
|
-
|
|
14619
|
-
|
|
14620
|
-
|
|
14621
|
-
|
|
14622
|
-
|
|
14623
|
-
|
|
14624
|
-
|
|
14625
|
-
|
|
14626
|
-
|
|
14627
|
-
|
|
14628
|
-
|
|
14629
|
-
|
|
14630
|
-
}
|
|
14631
|
-
legendX += LEGEND_GROUP_GAP;
|
|
14632
|
-
}
|
|
15252
|
+
const legendConfig = {
|
|
15253
|
+
groups: parsed.tagGroups,
|
|
15254
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
15255
|
+
mode: "fixed"
|
|
15256
|
+
};
|
|
15257
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
15258
|
+
const legendG = svg.append("g").attr("class", "er-tag-legend").attr("transform", `translate(0,${legendY})`);
|
|
15259
|
+
renderLegendD3(
|
|
15260
|
+
legendG,
|
|
15261
|
+
legendConfig,
|
|
15262
|
+
legendState,
|
|
15263
|
+
palette,
|
|
15264
|
+
isDark,
|
|
15265
|
+
void 0,
|
|
15266
|
+
viewW
|
|
15267
|
+
);
|
|
15268
|
+
legendG.selectAll("[data-legend-group]").classed("er-legend-group", true);
|
|
14633
15269
|
}
|
|
14634
15270
|
if (semanticRoles) {
|
|
14635
15271
|
const presentRoles = ROLE_ORDER.filter((role) => {
|
|
@@ -14639,55 +15275,35 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
|
|
|
14639
15275
|
return false;
|
|
14640
15276
|
});
|
|
14641
15277
|
if (presentRoles.length > 0) {
|
|
14642
|
-
const measureLabelW = (text, fontSize) => {
|
|
14643
|
-
const dummy = svg.append("text").attr("font-size", fontSize).attr("font-family", FONT_FAMILY).attr("visibility", "hidden").text(text);
|
|
14644
|
-
const measured = dummy.node()?.getComputedTextLength?.() ?? 0;
|
|
14645
|
-
dummy.remove();
|
|
14646
|
-
return measured > 0 ? measured : text.length * fontSize * 0.6;
|
|
14647
|
-
};
|
|
14648
|
-
const labelWidths = /* @__PURE__ */ new Map();
|
|
14649
|
-
for (const role of presentRoles) {
|
|
14650
|
-
labelWidths.set(
|
|
14651
|
-
role,
|
|
14652
|
-
measureLabelW(ROLE_LABELS[role], LEGEND_ENTRY_FONT_SIZE)
|
|
14653
|
-
);
|
|
14654
|
-
}
|
|
14655
|
-
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
14656
|
-
const groupName = "Role";
|
|
14657
|
-
const pillWidth2 = measureLegendText(groupName, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
14658
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
14659
|
-
let totalWidth;
|
|
14660
|
-
let entriesWidth2 = 0;
|
|
14661
|
-
if (semanticActive) {
|
|
14662
|
-
for (const role of presentRoles) {
|
|
14663
|
-
entriesWidth2 += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + labelWidths.get(role) + LEGEND_ENTRY_TRAIL;
|
|
14664
|
-
}
|
|
14665
|
-
totalWidth = LEGEND_CAPSULE_PAD * 2 + pillWidth2 + LEGEND_ENTRY_TRAIL + entriesWidth2;
|
|
14666
|
-
} else {
|
|
14667
|
-
totalWidth = pillWidth2;
|
|
14668
|
-
}
|
|
14669
|
-
const legendX = (viewW - totalWidth) / 2;
|
|
14670
15278
|
const legendY = DIAGRAM_PADDING5 + titleHeight;
|
|
14671
|
-
const
|
|
14672
|
-
|
|
14673
|
-
|
|
14674
|
-
|
|
14675
|
-
|
|
14676
|
-
|
|
14677
|
-
|
|
14678
|
-
for (const role of presentRoles) {
|
|
14679
|
-
const label = ROLE_LABELS[role];
|
|
14680
|
-
const roleColor = palette.colors[ROLE_COLORS[role]];
|
|
14681
|
-
const entryG = semanticLegendG.append("g").attr("data-legend-entry", role);
|
|
14682
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", roleColor);
|
|
14683
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
14684
|
-
entryG.append("text").attr("x", textX).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).attr("font-family", FONT_FAMILY).text(label);
|
|
14685
|
-
entryX = textX + labelWidths.get(role) + LEGEND_ENTRY_TRAIL;
|
|
15279
|
+
const semanticGroups = [
|
|
15280
|
+
{
|
|
15281
|
+
name: "Role",
|
|
15282
|
+
entries: presentRoles.map((role) => ({
|
|
15283
|
+
value: ROLE_LABELS[role],
|
|
15284
|
+
color: palette.colors[ROLE_COLORS[role]]
|
|
15285
|
+
}))
|
|
14686
15286
|
}
|
|
14687
|
-
|
|
14688
|
-
|
|
14689
|
-
|
|
14690
|
-
|
|
15287
|
+
];
|
|
15288
|
+
const legendConfig = {
|
|
15289
|
+
groups: semanticGroups,
|
|
15290
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
15291
|
+
mode: "fixed"
|
|
15292
|
+
};
|
|
15293
|
+
const legendState = {
|
|
15294
|
+
activeGroup: semanticActive ? "Role" : null
|
|
15295
|
+
};
|
|
15296
|
+
const legendG = svg.append("g").attr("class", "er-semantic-legend").attr("transform", `translate(0,${legendY})`);
|
|
15297
|
+
renderLegendD3(
|
|
15298
|
+
legendG,
|
|
15299
|
+
legendConfig,
|
|
15300
|
+
legendState,
|
|
15301
|
+
palette,
|
|
15302
|
+
isDark,
|
|
15303
|
+
void 0,
|
|
15304
|
+
viewW
|
|
15305
|
+
);
|
|
15306
|
+
legendG.selectAll("[data-legend-group]").classed("er-legend-group", true);
|
|
14691
15307
|
}
|
|
14692
15308
|
}
|
|
14693
15309
|
}
|
|
@@ -14730,6 +15346,7 @@ var init_renderer5 = __esm({
|
|
|
14730
15346
|
init_palettes();
|
|
14731
15347
|
init_tag_groups();
|
|
14732
15348
|
init_legend_constants();
|
|
15349
|
+
init_legend_d3();
|
|
14733
15350
|
init_title_constants();
|
|
14734
15351
|
init_parser3();
|
|
14735
15352
|
init_layout4();
|
|
@@ -14754,6 +15371,17 @@ __export(layout_exports5, {
|
|
|
14754
15371
|
layoutBoxesAndLines: () => layoutBoxesAndLines
|
|
14755
15372
|
});
|
|
14756
15373
|
import dagre4 from "@dagrejs/dagre";
|
|
15374
|
+
function clipToRectBorder2(cx, cy, w, h, tx, ty) {
|
|
15375
|
+
const dx = tx - cx;
|
|
15376
|
+
const dy = ty - cy;
|
|
15377
|
+
if (dx === 0 && dy === 0) return { x: cx, y: cy };
|
|
15378
|
+
const hw = w / 2;
|
|
15379
|
+
const hh = h / 2;
|
|
15380
|
+
const sx = dx !== 0 ? hw / Math.abs(dx) : Infinity;
|
|
15381
|
+
const sy = dy !== 0 ? hh / Math.abs(dy) : Infinity;
|
|
15382
|
+
const s = Math.min(sx, sy);
|
|
15383
|
+
return { x: cx + dx * s, y: cy + dy * s };
|
|
15384
|
+
}
|
|
14757
15385
|
function computeNodeSize(_node) {
|
|
14758
15386
|
const PHI = 1.618;
|
|
14759
15387
|
const NODE_HEIGHT = 60;
|
|
@@ -14906,13 +15534,25 @@ function layoutBoxesAndLines(parsed, collapseInfo) {
|
|
|
14906
15534
|
const srcNode = g.node(edge.source);
|
|
14907
15535
|
const tgtNode = g.node(edge.target);
|
|
14908
15536
|
if (!srcNode || !tgtNode) continue;
|
|
14909
|
-
const
|
|
14910
|
-
|
|
14911
|
-
|
|
14912
|
-
|
|
14913
|
-
|
|
14914
|
-
|
|
14915
|
-
|
|
15537
|
+
const srcPt = clipToRectBorder2(
|
|
15538
|
+
srcNode.x,
|
|
15539
|
+
srcNode.y,
|
|
15540
|
+
srcNode.width,
|
|
15541
|
+
srcNode.height,
|
|
15542
|
+
tgtNode.x,
|
|
15543
|
+
tgtNode.y
|
|
15544
|
+
);
|
|
15545
|
+
const tgtPt = clipToRectBorder2(
|
|
15546
|
+
tgtNode.x,
|
|
15547
|
+
tgtNode.y,
|
|
15548
|
+
tgtNode.width,
|
|
15549
|
+
tgtNode.height,
|
|
15550
|
+
srcNode.x,
|
|
15551
|
+
srcNode.y
|
|
15552
|
+
);
|
|
15553
|
+
const midX = (srcPt.x + tgtPt.x) / 2;
|
|
15554
|
+
const midY = (srcPt.y + tgtPt.y) / 2;
|
|
15555
|
+
points = [srcPt, { x: midX, y: midY }, tgtPt];
|
|
14916
15556
|
} else {
|
|
14917
15557
|
const dagreEdge = g.edge(edge.source, edge.target, `e${i}`);
|
|
14918
15558
|
points = dagreEdge?.points ?? [];
|
|
@@ -14935,7 +15575,8 @@ function layoutBoxesAndLines(parsed, collapseInfo) {
|
|
|
14935
15575
|
labelY,
|
|
14936
15576
|
yOffset: edgeYOffsets[i],
|
|
14937
15577
|
parallelCount: edgeParallelCounts[i],
|
|
14938
|
-
metadata: edge.metadata
|
|
15578
|
+
metadata: edge.metadata,
|
|
15579
|
+
deferred: deferredSet.has(i) || void 0
|
|
14939
15580
|
});
|
|
14940
15581
|
}
|
|
14941
15582
|
let maxX = 0;
|
|
@@ -15205,12 +15846,8 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
15205
15846
|
const edgeG = diagramG.append("g").attr("class", "bl-edge-group").attr("data-line-number", String(le.lineNumber));
|
|
15206
15847
|
edgeGroups.set(i, edgeG);
|
|
15207
15848
|
const markerId = `bl-arrow-${color.replace("#", "")}`;
|
|
15208
|
-
const
|
|
15209
|
-
|
|
15210
|
-
(parsed.direction === "TB" ? lineGeneratorTB : lineGeneratorLR)(
|
|
15211
|
-
points
|
|
15212
|
-
) ?? ""
|
|
15213
|
-
).attr("fill", "none").attr("stroke", color).attr("stroke-width", EDGE_STROKE_WIDTH5).attr("marker-end", `url(#${markerId})`);
|
|
15849
|
+
const gen = le.deferred ? lineGeneratorLinear2 : parsed.direction === "TB" ? lineGeneratorTB : lineGeneratorLR;
|
|
15850
|
+
const path = edgeG.append("path").attr("class", "bl-edge").attr("d", gen(points) ?? "").attr("fill", "none").attr("stroke", color).attr("stroke-width", EDGE_STROKE_WIDTH5).attr("marker-end", `url(#${markerId})`);
|
|
15214
15851
|
if (le.bidirectional) {
|
|
15215
15852
|
const revId = `bl-arrow-rev-${color.replace("#", "")}`;
|
|
15216
15853
|
path.attr("marker-start", `url(#${revId})`);
|
|
@@ -15291,50 +15928,23 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
15291
15928
|
}
|
|
15292
15929
|
}
|
|
15293
15930
|
if (parsed.tagGroups.length > 0) {
|
|
15294
|
-
|
|
15295
|
-
|
|
15296
|
-
}
|
|
15297
|
-
|
|
15298
|
-
|
|
15299
|
-
|
|
15300
|
-
|
|
15301
|
-
|
|
15302
|
-
|
|
15303
|
-
|
|
15304
|
-
|
|
15305
|
-
|
|
15306
|
-
|
|
15307
|
-
|
|
15308
|
-
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
}
|
|
15312
|
-
const legendX = Math.max(LEGEND_CAPSULE_PAD, (svgWidth - totalW) / 2);
|
|
15313
|
-
const legendY = titleOffset + 4;
|
|
15314
|
-
const legendG = svg.append("g").attr("transform", `translate(${legendX},${legendY})`);
|
|
15315
|
-
let x = 0;
|
|
15316
|
-
for (const tg of parsed.tagGroups) {
|
|
15317
|
-
const isActiveGroup = activeGroup?.toLowerCase() === tg.name.toLowerCase();
|
|
15318
|
-
const groupG = legendG.append("g").attr("class", "bl-legend-group").attr("data-legend-group", tg.name.toLowerCase()).style("cursor", "pointer");
|
|
15319
|
-
const nameW = measureLegendText(tg.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
15320
|
-
const tagPill = groupG.append("rect").attr("x", x).attr("y", 0).attr("width", nameW).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
15321
|
-
if (isActiveGroup) {
|
|
15322
|
-
tagPill.attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
15323
|
-
}
|
|
15324
|
-
groupG.append("text").attr("x", x + nameW / 2).attr("y", LEGEND_HEIGHT / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", 500).attr("fill", isActiveGroup ? palette.text : palette.textMuted).attr("pointer-events", "none").text(tg.name);
|
|
15325
|
-
x += nameW;
|
|
15326
|
-
if (isActiveGroup) {
|
|
15327
|
-
x += 6;
|
|
15328
|
-
for (const entry of tg.entries) {
|
|
15329
|
-
const entryColor = entry.color || palette.textMuted;
|
|
15330
|
-
const ew = measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE);
|
|
15331
|
-
const entryG = groupG.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
15332
|
-
entryG.append("circle").attr("cx", x + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entryColor);
|
|
15333
|
-
entryG.append("text").attr("x", x + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP).attr("y", LEGEND_HEIGHT / 2).attr("dominant-baseline", "central").attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
15334
|
-
x += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + ew + LEGEND_ENTRY_TRAIL;
|
|
15335
|
-
}
|
|
15336
|
-
}
|
|
15337
|
-
x += LEGEND_GROUP_GAP;
|
|
15931
|
+
const legendConfig = {
|
|
15932
|
+
groups: parsed.tagGroups,
|
|
15933
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
15934
|
+
mode: "fixed"
|
|
15935
|
+
};
|
|
15936
|
+
const legendState = { activeGroup };
|
|
15937
|
+
const legendG = svg.append("g").attr("transform", `translate(0,${titleOffset + 4})`);
|
|
15938
|
+
renderLegendD3(
|
|
15939
|
+
legendG,
|
|
15940
|
+
legendConfig,
|
|
15941
|
+
legendState,
|
|
15942
|
+
palette,
|
|
15943
|
+
isDark,
|
|
15944
|
+
void 0,
|
|
15945
|
+
width
|
|
15946
|
+
);
|
|
15947
|
+
legendG.selectAll("[data-legend-group]").classed("bl-legend-group", true);
|
|
15338
15948
|
}
|
|
15339
15949
|
}
|
|
15340
15950
|
function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark, options) {
|
|
@@ -15342,12 +15952,13 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
|
|
|
15342
15952
|
exportDims: options?.exportDims
|
|
15343
15953
|
});
|
|
15344
15954
|
}
|
|
15345
|
-
var DIAGRAM_PADDING6, NODE_FONT_SIZE, MIN_NODE_FONT_SIZE, META_FONT_SIZE3, EDGE_LABEL_FONT_SIZE4, EDGE_STROKE_WIDTH5, NODE_STROKE_WIDTH5, NODE_RX, COLLAPSE_BAR_HEIGHT3, ARROWHEAD_W2, ARROWHEAD_H2, CHAR_WIDTH_RATIO, NODE_TEXT_PADDING, GROUP_RX, GROUP_LABEL_FONT_SIZE, lineGeneratorLR, lineGeneratorTB;
|
|
15955
|
+
var DIAGRAM_PADDING6, NODE_FONT_SIZE, MIN_NODE_FONT_SIZE, META_FONT_SIZE3, EDGE_LABEL_FONT_SIZE4, EDGE_STROKE_WIDTH5, NODE_STROKE_WIDTH5, NODE_RX, COLLAPSE_BAR_HEIGHT3, ARROWHEAD_W2, ARROWHEAD_H2, CHAR_WIDTH_RATIO, NODE_TEXT_PADDING, GROUP_RX, GROUP_LABEL_FONT_SIZE, lineGeneratorLR, lineGeneratorTB, lineGeneratorLinear2;
|
|
15346
15956
|
var init_renderer6 = __esm({
|
|
15347
15957
|
"src/boxes-and-lines/renderer.ts"() {
|
|
15348
15958
|
"use strict";
|
|
15349
15959
|
init_fonts();
|
|
15350
15960
|
init_legend_constants();
|
|
15961
|
+
init_legend_d3();
|
|
15351
15962
|
init_title_constants();
|
|
15352
15963
|
init_color_utils();
|
|
15353
15964
|
init_tag_groups();
|
|
@@ -15368,6 +15979,7 @@ var init_renderer6 = __esm({
|
|
|
15368
15979
|
GROUP_LABEL_FONT_SIZE = 14;
|
|
15369
15980
|
lineGeneratorLR = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveMonotoneX);
|
|
15370
15981
|
lineGeneratorTB = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveMonotoneY);
|
|
15982
|
+
lineGeneratorLinear2 = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveLinear);
|
|
15371
15983
|
}
|
|
15372
15984
|
});
|
|
15373
15985
|
|
|
@@ -17276,7 +17888,7 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
|
|
|
17276
17888
|
if (activeTagGroup) {
|
|
17277
17889
|
legendParent.attr("data-legend-active", activeTagGroup.toLowerCase());
|
|
17278
17890
|
}
|
|
17279
|
-
|
|
17891
|
+
renderLegend2(
|
|
17280
17892
|
legendParent,
|
|
17281
17893
|
layout,
|
|
17282
17894
|
palette,
|
|
@@ -17637,52 +18249,28 @@ function placeEdgeLabels(labels, edges, obstacleRects) {
|
|
|
17637
18249
|
placedRects.push({ x: lbl.x, y: lbl.y, w: lbl.bgW, h: lbl.bgH });
|
|
17638
18250
|
}
|
|
17639
18251
|
}
|
|
17640
|
-
function
|
|
17641
|
-
const
|
|
17642
|
-
|
|
17643
|
-
|
|
17644
|
-
|
|
17645
|
-
const
|
|
17646
|
-
|
|
17647
|
-
|
|
17648
|
-
|
|
17649
|
-
|
|
17650
|
-
|
|
17651
|
-
|
|
17652
|
-
|
|
17653
|
-
|
|
17654
|
-
|
|
17655
|
-
|
|
17656
|
-
|
|
17657
|
-
|
|
17658
|
-
|
|
17659
|
-
|
|
17660
|
-
|
|
17661
|
-
|
|
17662
|
-
const gY = fixedPositions != null ? 0 : group.y;
|
|
17663
|
-
const gEl = parent.append("g").attr("transform", `translate(${gX}, ${gY})`).attr("class", "c4-legend-group").attr("data-legend-group", group.name.toLowerCase()).style("cursor", "pointer");
|
|
17664
|
-
if (isActive) {
|
|
17665
|
-
gEl.append("rect").attr("width", group.width).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
17666
|
-
}
|
|
17667
|
-
const pillX = isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
17668
|
-
const pillY = LEGEND_CAPSULE_PAD;
|
|
17669
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
17670
|
-
gEl.append("rect").attr("x", pillX).attr("y", pillY).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", isActive ? palette.bg : groupBg);
|
|
17671
|
-
if (isActive) {
|
|
17672
|
-
gEl.append("rect").attr("x", pillX).attr("y", pillY).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
17673
|
-
}
|
|
17674
|
-
gEl.append("text").attr("x", pillX + pillWidth2 / 2).attr("y", LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(pillLabel);
|
|
17675
|
-
if (isActive) {
|
|
17676
|
-
let entryX = pillX + pillWidth2 + 4;
|
|
17677
|
-
for (const entry of group.entries) {
|
|
17678
|
-
const entryG = gEl.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
17679
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
17680
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
17681
|
-
entryG.append("text").attr("x", textX).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
17682
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
17683
|
-
}
|
|
17684
|
-
}
|
|
17685
|
-
}
|
|
18252
|
+
function renderLegend2(parent, layout, palette, isDark, activeTagGroup, fixedWidth) {
|
|
18253
|
+
const groups = layout.legend.map((g) => ({
|
|
18254
|
+
name: g.name,
|
|
18255
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
18256
|
+
}));
|
|
18257
|
+
const legendConfig = {
|
|
18258
|
+
groups,
|
|
18259
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
18260
|
+
mode: "fixed"
|
|
18261
|
+
};
|
|
18262
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
18263
|
+
const containerWidth = fixedWidth ?? layout.width;
|
|
18264
|
+
renderLegendD3(
|
|
18265
|
+
parent,
|
|
18266
|
+
legendConfig,
|
|
18267
|
+
legendState,
|
|
18268
|
+
palette,
|
|
18269
|
+
isDark,
|
|
18270
|
+
void 0,
|
|
18271
|
+
containerWidth
|
|
18272
|
+
);
|
|
18273
|
+
parent.selectAll("[data-legend-group]").classed("c4-legend-group", true);
|
|
17686
18274
|
}
|
|
17687
18275
|
function renderC4Containers(container, parsed, layout, palette, isDark, onClickItem, exportDims, activeTagGroup) {
|
|
17688
18276
|
d3Selection7.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
@@ -17893,7 +18481,7 @@ function renderC4Containers(container, parsed, layout, palette, isDark, onClickI
|
|
|
17893
18481
|
if (activeTagGroup) {
|
|
17894
18482
|
legendParent.attr("data-legend-active", activeTagGroup.toLowerCase());
|
|
17895
18483
|
}
|
|
17896
|
-
|
|
18484
|
+
renderLegend2(
|
|
17897
18485
|
legendParent,
|
|
17898
18486
|
layout,
|
|
17899
18487
|
palette,
|
|
@@ -18021,6 +18609,7 @@ var init_renderer7 = __esm({
|
|
|
18021
18609
|
init_parser6();
|
|
18022
18610
|
init_layout6();
|
|
18023
18611
|
init_legend_constants();
|
|
18612
|
+
init_legend_d3();
|
|
18024
18613
|
init_title_constants();
|
|
18025
18614
|
DIAGRAM_PADDING7 = 20;
|
|
18026
18615
|
MAX_SCALE5 = 3;
|
|
@@ -20910,17 +21499,17 @@ function computeInfraLegendGroups(nodes, tagGroups, palette, edges) {
|
|
|
20910
21499
|
color: r.color,
|
|
20911
21500
|
key: r.name.toLowerCase().replace(/\s+/g, "-")
|
|
20912
21501
|
}));
|
|
20913
|
-
const
|
|
20914
|
-
let
|
|
21502
|
+
const pillWidth3 = measureLegendText("Capabilities", LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21503
|
+
let entriesWidth3 = 0;
|
|
20915
21504
|
for (const e of entries) {
|
|
20916
|
-
|
|
21505
|
+
entriesWidth3 += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
20917
21506
|
}
|
|
20918
21507
|
groups.push({
|
|
20919
21508
|
name: "Capabilities",
|
|
20920
21509
|
type: "role",
|
|
20921
21510
|
entries,
|
|
20922
|
-
width: LEGEND_CAPSULE_PAD * 2 +
|
|
20923
|
-
minifiedWidth:
|
|
21511
|
+
width: LEGEND_CAPSULE_PAD * 2 + pillWidth3 + 4 + entriesWidth3,
|
|
21512
|
+
minifiedWidth: pillWidth3
|
|
20924
21513
|
});
|
|
20925
21514
|
}
|
|
20926
21515
|
for (const tg of tagGroups) {
|
|
@@ -20935,113 +21524,88 @@ function computeInfraLegendGroups(nodes, tagGroups, palette, edges) {
|
|
|
20935
21524
|
}
|
|
20936
21525
|
}
|
|
20937
21526
|
if (entries.length === 0) continue;
|
|
20938
|
-
const
|
|
20939
|
-
let
|
|
21527
|
+
const pillWidth3 = measureLegendText(tg.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21528
|
+
let entriesWidth3 = 0;
|
|
20940
21529
|
for (const e of entries) {
|
|
20941
|
-
|
|
21530
|
+
entriesWidth3 += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
20942
21531
|
}
|
|
20943
21532
|
groups.push({
|
|
20944
21533
|
name: tg.name,
|
|
20945
21534
|
type: "tag",
|
|
20946
21535
|
tagKey: (tg.alias ?? tg.name).toLowerCase(),
|
|
20947
21536
|
entries,
|
|
20948
|
-
width: LEGEND_CAPSULE_PAD * 2 +
|
|
20949
|
-
minifiedWidth:
|
|
21537
|
+
width: LEGEND_CAPSULE_PAD * 2 + pillWidth3 + 4 + entriesWidth3,
|
|
21538
|
+
minifiedWidth: pillWidth3
|
|
20950
21539
|
});
|
|
20951
21540
|
}
|
|
20952
21541
|
return groups;
|
|
20953
21542
|
}
|
|
20954
|
-
function
|
|
20955
|
-
if (!playback) return 0;
|
|
20956
|
-
const pillWidth2 = measureLegendText("Playback", LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
20957
|
-
if (!playback.expanded) return pillWidth2;
|
|
20958
|
-
let entriesW = 8;
|
|
20959
|
-
entriesW += LEGEND_PILL_FONT_SIZE * 0.8 + 6;
|
|
20960
|
-
for (const s of playback.speedOptions) {
|
|
20961
|
-
entriesW += measureLegendText(`${s}x`, LEGEND_ENTRY_FONT_SIZE) + SPEED_BADGE_H_PAD * 2 + SPEED_BADGE_GAP;
|
|
20962
|
-
}
|
|
20963
|
-
return LEGEND_CAPSULE_PAD * 2 + pillWidth2 + entriesW;
|
|
20964
|
-
}
|
|
20965
|
-
function renderLegend4(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback) {
|
|
21543
|
+
function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback) {
|
|
20966
21544
|
if (legendGroups.length === 0 && !playback) return;
|
|
20967
21545
|
const legendG = rootSvg.append("g").attr("transform", `translate(0, ${legendY})`);
|
|
20968
21546
|
if (activeGroup) {
|
|
20969
21547
|
legendG.attr("data-legend-active", activeGroup.toLowerCase());
|
|
20970
21548
|
}
|
|
20971
|
-
const
|
|
20972
|
-
|
|
20973
|
-
|
|
20974
|
-
|
|
20975
|
-
|
|
21549
|
+
const allGroups = legendGroups.map((g) => ({
|
|
21550
|
+
name: g.name,
|
|
21551
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
21552
|
+
}));
|
|
21553
|
+
if (playback) {
|
|
21554
|
+
allGroups.push({ name: "Playback", entries: [] });
|
|
21555
|
+
}
|
|
21556
|
+
const legendConfig = {
|
|
21557
|
+
groups: allGroups,
|
|
21558
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
21559
|
+
mode: "fixed",
|
|
21560
|
+
showEmptyGroups: true
|
|
21561
|
+
};
|
|
21562
|
+
const legendState = { activeGroup };
|
|
21563
|
+
renderLegendD3(
|
|
21564
|
+
legendG,
|
|
21565
|
+
legendConfig,
|
|
21566
|
+
legendState,
|
|
21567
|
+
palette,
|
|
21568
|
+
isDark,
|
|
21569
|
+
void 0,
|
|
21570
|
+
totalWidth
|
|
21571
|
+
);
|
|
21572
|
+
legendG.selectAll("[data-legend-group]").classed("infra-legend-group", true);
|
|
20976
21573
|
for (const group of legendGroups) {
|
|
20977
|
-
const
|
|
20978
|
-
const
|
|
20979
|
-
|
|
20980
|
-
|
|
20981
|
-
|
|
20982
|
-
|
|
20983
|
-
|
|
20984
|
-
}
|
|
20985
|
-
const pillXOff = isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
20986
|
-
const pillYOff = LEGEND_CAPSULE_PAD;
|
|
20987
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
20988
|
-
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", isActive ? palette.bg : groupBg);
|
|
20989
|
-
if (isActive) {
|
|
20990
|
-
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
20991
|
-
}
|
|
20992
|
-
gEl.append("text").attr("x", pillXOff + pillWidth2 / 2).attr("y", LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-family", FONT_FAMILY).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(pillLabel);
|
|
20993
|
-
if (isActive) {
|
|
20994
|
-
let entryX = pillXOff + pillWidth2 + 4;
|
|
20995
|
-
for (const entry of group.entries) {
|
|
20996
|
-
const entryG = gEl.append("g").attr("class", "infra-legend-entry").attr("data-legend-entry", entry.key.toLowerCase()).attr("data-legend-color", entry.color).attr("data-legend-type", group.type).attr(
|
|
21574
|
+
const groupKey = group.name.toLowerCase();
|
|
21575
|
+
for (const entry of group.entries) {
|
|
21576
|
+
const entryEl = legendG.select(
|
|
21577
|
+
`[data-legend-group="${groupKey}"] [data-legend-entry="${entry.value.toLowerCase()}"]`
|
|
21578
|
+
);
|
|
21579
|
+
if (!entryEl.empty()) {
|
|
21580
|
+
entryEl.attr("data-legend-entry", entry.key.toLowerCase()).attr("data-legend-color", entry.color).attr("data-legend-type", group.type).attr(
|
|
20997
21581
|
"data-legend-tag-group",
|
|
20998
21582
|
group.type === "tag" ? group.tagKey ?? "" : null
|
|
20999
|
-
)
|
|
21000
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
21001
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
21002
|
-
entryG.append("text").attr("x", textX).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-family", FONT_FAMILY).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
21003
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
21583
|
+
);
|
|
21004
21584
|
}
|
|
21005
21585
|
}
|
|
21006
|
-
cursorX += effectiveW(group) + LEGEND_GROUP_GAP;
|
|
21007
21586
|
}
|
|
21008
|
-
|
|
21009
|
-
|
|
21010
|
-
|
|
21011
|
-
|
|
21012
|
-
|
|
21013
|
-
const
|
|
21014
|
-
|
|
21015
|
-
|
|
21016
|
-
|
|
21017
|
-
|
|
21018
|
-
|
|
21019
|
-
const
|
|
21020
|
-
|
|
21021
|
-
|
|
21022
|
-
|
|
21023
|
-
|
|
21024
|
-
|
|
21025
|
-
|
|
21026
|
-
|
|
21027
|
-
|
|
21028
|
-
|
|
21029
|
-
|
|
21030
|
-
pbG.append("text").attr("x", entryX).attr("y", entryY).attr("font-family", FONT_FAMILY).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("fill", palette.textMuted).attr("data-playback-action", "toggle-pause").style("cursor", "pointer").text(ppLabel);
|
|
21031
|
-
entryX += LEGEND_PILL_FONT_SIZE * 0.8 + 6;
|
|
21032
|
-
for (const s of playback.speedOptions) {
|
|
21033
|
-
const label = `${s}x`;
|
|
21034
|
-
const isActive = playback.speed === s;
|
|
21035
|
-
const slotW = measureLegendText(label, LEGEND_ENTRY_FONT_SIZE) + SPEED_BADGE_H_PAD * 2;
|
|
21036
|
-
const badgeH = LEGEND_ENTRY_FONT_SIZE + SPEED_BADGE_V_PAD * 2;
|
|
21037
|
-
const badgeY = (LEGEND_HEIGHT - badgeH) / 2;
|
|
21038
|
-
const speedG = pbG.append("g").attr("data-playback-action", "set-speed").attr("data-playback-value", String(s)).style("cursor", "pointer");
|
|
21039
|
-
speedG.append("rect").attr("x", entryX).attr("y", badgeY).attr("width", slotW).attr("height", badgeH).attr("rx", badgeH / 2).attr("fill", isActive ? palette.primary : "transparent");
|
|
21040
|
-
speedG.append("text").attr("x", entryX + slotW / 2).attr("y", entryY).attr("font-family", FONT_FAMILY).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("font-weight", isActive ? "600" : "400").attr("fill", isActive ? palette.bg : palette.textMuted).attr("text-anchor", "middle").text(label);
|
|
21041
|
-
entryX += slotW + SPEED_BADGE_GAP;
|
|
21042
|
-
}
|
|
21043
|
-
}
|
|
21044
|
-
cursorX += fullW + LEGEND_GROUP_GAP;
|
|
21587
|
+
const playbackEl = legendG.select('[data-legend-group="playback"]');
|
|
21588
|
+
if (!playbackEl.empty()) {
|
|
21589
|
+
playbackEl.classed("infra-playback-pill", true);
|
|
21590
|
+
}
|
|
21591
|
+
if (playback && playback.expanded && !playbackEl.empty()) {
|
|
21592
|
+
const pillWidth3 = measureLegendText("Playback", LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21593
|
+
let entryX = pillWidth3 + 8;
|
|
21594
|
+
const entryY = LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1;
|
|
21595
|
+
const ppLabel = playback.paused ? "\u25B6" : "\u23F8";
|
|
21596
|
+
playbackEl.append("text").attr("x", entryX).attr("y", entryY).attr("font-family", FONT_FAMILY).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("fill", palette.textMuted).attr("data-playback-action", "toggle-pause").style("cursor", "pointer").text(ppLabel);
|
|
21597
|
+
entryX += LEGEND_PILL_FONT_SIZE * 0.8 + 6;
|
|
21598
|
+
for (const s of playback.speedOptions) {
|
|
21599
|
+
const label = `${s}x`;
|
|
21600
|
+
const isSpeedActive = playback.speed === s;
|
|
21601
|
+
const slotW = measureLegendText(label, LEGEND_ENTRY_FONT_SIZE) + SPEED_BADGE_H_PAD * 2;
|
|
21602
|
+
const badgeH = LEGEND_ENTRY_FONT_SIZE + SPEED_BADGE_V_PAD * 2;
|
|
21603
|
+
const badgeY = (LEGEND_HEIGHT - badgeH) / 2;
|
|
21604
|
+
const speedG = playbackEl.append("g").attr("data-playback-action", "set-speed").attr("data-playback-value", String(s)).style("cursor", "pointer");
|
|
21605
|
+
speedG.append("rect").attr("x", entryX).attr("y", badgeY).attr("width", slotW).attr("height", badgeH).attr("rx", badgeH / 2).attr("fill", isSpeedActive ? palette.primary : "transparent");
|
|
21606
|
+
speedG.append("text").attr("x", entryX + slotW / 2).attr("y", entryY).attr("font-family", FONT_FAMILY).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("font-weight", isSpeedActive ? "600" : "400").attr("fill", isSpeedActive ? palette.bg : palette.textMuted).attr("text-anchor", "middle").text(label);
|
|
21607
|
+
entryX += slotW + SPEED_BADGE_GAP;
|
|
21608
|
+
}
|
|
21045
21609
|
}
|
|
21046
21610
|
}
|
|
21047
21611
|
function renderInfra(container, layout, palette, isDark, title, titleLineNumber, tagGroups, activeGroup, animate, playback, expandedNodeIds, exportMode, collapsedNodes) {
|
|
@@ -21172,7 +21736,7 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
21172
21736
|
"viewBox",
|
|
21173
21737
|
`0 0 ${containerWidth} ${LEGEND_HEIGHT + LEGEND_FIXED_GAP3}`
|
|
21174
21738
|
).attr("preserveAspectRatio", "xMidYMid meet").style("display", "block").style("pointer-events", "none");
|
|
21175
|
-
|
|
21739
|
+
renderLegend3(
|
|
21176
21740
|
legendSvg,
|
|
21177
21741
|
legendGroups,
|
|
21178
21742
|
containerWidth,
|
|
@@ -21184,7 +21748,7 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
21184
21748
|
);
|
|
21185
21749
|
legendSvg.selectAll(".infra-legend-group").style("pointer-events", "auto");
|
|
21186
21750
|
} else {
|
|
21187
|
-
|
|
21751
|
+
renderLegend3(
|
|
21188
21752
|
rootSvg,
|
|
21189
21753
|
legendGroups,
|
|
21190
21754
|
totalWidth,
|
|
@@ -21216,6 +21780,7 @@ var init_renderer8 = __esm({
|
|
|
21216
21780
|
init_compute();
|
|
21217
21781
|
init_layout8();
|
|
21218
21782
|
init_legend_constants();
|
|
21783
|
+
init_legend_d3();
|
|
21219
21784
|
init_title_constants();
|
|
21220
21785
|
NODE_FONT_SIZE3 = 13;
|
|
21221
21786
|
META_FONT_SIZE5 = 10;
|
|
@@ -22843,7 +23408,7 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
22843
23408
|
const isActive = activeGroupName?.toLowerCase() === group.name.toLowerCase();
|
|
22844
23409
|
const isSwimlane = currentSwimlaneGroup?.toLowerCase() === group.name.toLowerCase();
|
|
22845
23410
|
const showIcon = !legendViewMode && tagGroups.length > 0;
|
|
22846
|
-
const iconReserve = showIcon ? LEGEND_ICON_W : 0;
|
|
23411
|
+
const iconReserve = showIcon && isActive ? LEGEND_ICON_W : 0;
|
|
22847
23412
|
const pillW = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD + iconReserve;
|
|
22848
23413
|
let groupW = pillW;
|
|
22849
23414
|
if (isActive) {
|
|
@@ -22870,83 +23435,110 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
22870
23435
|
const legendX = (containerWidth - totalW) / 2;
|
|
22871
23436
|
const legendRow = svg.append("g").attr("class", "gantt-tag-legend-container").attr("transform", `translate(${legendX}, ${legendY})`);
|
|
22872
23437
|
let cursorX = 0;
|
|
22873
|
-
|
|
22874
|
-
const group = visibleGroups[i];
|
|
22875
|
-
const isActive = activeGroupName?.toLowerCase() === group.name.toLowerCase();
|
|
22876
|
-
const isSwimlane = currentSwimlaneGroup?.toLowerCase() === group.name.toLowerCase();
|
|
23438
|
+
if (visibleGroups.length > 0) {
|
|
22877
23439
|
const showIcon = !legendViewMode && tagGroups.length > 0;
|
|
22878
23440
|
const iconReserve = showIcon ? LEGEND_ICON_W : 0;
|
|
22879
|
-
const
|
|
22880
|
-
|
|
22881
|
-
|
|
22882
|
-
|
|
22883
|
-
|
|
23441
|
+
const legendGroups = visibleGroups.map((g) => {
|
|
23442
|
+
const key = g.name.toLowerCase();
|
|
23443
|
+
const entries = filteredEntries.get(key) ?? g.entries;
|
|
23444
|
+
return {
|
|
23445
|
+
name: g.name,
|
|
23446
|
+
entries: entries.map((e) => ({ value: e.value, color: e.color }))
|
|
23447
|
+
};
|
|
22884
23448
|
});
|
|
22885
|
-
|
|
22886
|
-
|
|
22887
|
-
|
|
22888
|
-
|
|
22889
|
-
|
|
22890
|
-
|
|
22891
|
-
|
|
22892
|
-
|
|
22893
|
-
}
|
|
22894
|
-
const
|
|
22895
|
-
|
|
22896
|
-
|
|
22897
|
-
|
|
22898
|
-
|
|
22899
|
-
|
|
22900
|
-
|
|
22901
|
-
|
|
22902
|
-
|
|
22903
|
-
if (onSwimlaneChange) {
|
|
22904
|
-
onSwimlaneChange(
|
|
22905
|
-
currentSwimlaneGroup?.toLowerCase() === group.name.toLowerCase() ? null : group.name
|
|
22906
|
-
);
|
|
22907
|
-
}
|
|
22908
|
-
});
|
|
22909
|
-
}
|
|
22910
|
-
if (isActive) {
|
|
22911
|
-
const tagKey = group.name.toLowerCase();
|
|
22912
|
-
const entries = filteredEntries.get(tagKey) ?? group.entries;
|
|
22913
|
-
let ex = pillXOff + pillW + LEGEND_CAPSULE_PAD + 4;
|
|
22914
|
-
for (const entry of entries) {
|
|
22915
|
-
const entryValue = entry.value.toLowerCase();
|
|
22916
|
-
const entryG = gEl.append("g").attr("class", "gantt-legend-entry").attr("data-line-number", String(entry.lineNumber)).style("cursor", "pointer");
|
|
22917
|
-
entryG.append("circle").attr("cx", ex + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
22918
|
-
entryG.append("text").attr("x", ex + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 2).attr("text-anchor", "start").attr("font-size", `${LEGEND_ENTRY_FONT_SIZE}px`).attr("fill", palette.textMuted).text(entry.value);
|
|
22919
|
-
entryG.on("mouseenter", () => {
|
|
23449
|
+
const legendConfig = {
|
|
23450
|
+
groups: legendGroups,
|
|
23451
|
+
position: {
|
|
23452
|
+
placement: "top-center",
|
|
23453
|
+
titleRelation: "below-title"
|
|
23454
|
+
},
|
|
23455
|
+
mode: "fixed",
|
|
23456
|
+
capsulePillAddonWidth: iconReserve
|
|
23457
|
+
};
|
|
23458
|
+
const legendState = { activeGroup: activeGroupName };
|
|
23459
|
+
const tagGroupsW = visibleGroups.reduce((s, _, i) => s + groupWidths[i], 0) + Math.max(0, (visibleGroups.length - 1) * LEGEND_GROUP_GAP);
|
|
23460
|
+
const tagGroupG = legendRow.append("g");
|
|
23461
|
+
const legendCallbacks = {
|
|
23462
|
+
onGroupToggle: onToggle,
|
|
23463
|
+
onEntryHover: (groupName, entryValue) => {
|
|
23464
|
+
const tagKey = groupName.toLowerCase();
|
|
23465
|
+
if (entryValue) {
|
|
23466
|
+
const ev = entryValue.toLowerCase();
|
|
22920
23467
|
chartG.selectAll(".gantt-task").each(function() {
|
|
22921
23468
|
const el = d3Selection10.select(this);
|
|
22922
|
-
|
|
22923
|
-
|
|
23469
|
+
el.attr(
|
|
23470
|
+
"opacity",
|
|
23471
|
+
el.attr(`data-tag-${tagKey}`) === ev ? 1 : FADE_OPACITY
|
|
23472
|
+
);
|
|
22924
23473
|
});
|
|
22925
23474
|
chartG.selectAll(".gantt-milestone").attr("opacity", FADE_OPACITY);
|
|
22926
23475
|
chartG.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
22927
23476
|
svg.selectAll(".gantt-task-label").each(function() {
|
|
22928
23477
|
const el = d3Selection10.select(this);
|
|
22929
|
-
|
|
22930
|
-
|
|
23478
|
+
el.attr(
|
|
23479
|
+
"opacity",
|
|
23480
|
+
el.attr(`data-tag-${tagKey}`) === ev ? 1 : FADE_OPACITY
|
|
23481
|
+
);
|
|
22931
23482
|
});
|
|
22932
23483
|
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
22933
23484
|
svg.selectAll(".gantt-lane-header").each(function() {
|
|
22934
23485
|
const el = d3Selection10.select(this);
|
|
22935
|
-
|
|
22936
|
-
|
|
23486
|
+
el.attr(
|
|
23487
|
+
"opacity",
|
|
23488
|
+
el.attr(`data-tag-${tagKey}`) === ev ? 1 : FADE_OPACITY
|
|
23489
|
+
);
|
|
22937
23490
|
});
|
|
22938
23491
|
chartG.selectAll(".gantt-lane-band, .gantt-lane-accent").attr("opacity", FADE_OPACITY);
|
|
22939
|
-
}
|
|
23492
|
+
} else {
|
|
22940
23493
|
if (criticalPathActive) {
|
|
22941
23494
|
applyCriticalPathHighlight(svg, chartG);
|
|
22942
23495
|
} else {
|
|
22943
23496
|
resetHighlightAll(svg, chartG);
|
|
22944
23497
|
}
|
|
22945
|
-
}
|
|
22946
|
-
|
|
23498
|
+
}
|
|
23499
|
+
},
|
|
23500
|
+
onGroupRendered: (groupName, groupEl, _isActive) => {
|
|
23501
|
+
const group = visibleGroups.find((g) => g.name === groupName);
|
|
23502
|
+
if (group) {
|
|
23503
|
+
groupEl.attr("data-tag-group", group.name).attr("data-line-number", String(group.lineNumber));
|
|
23504
|
+
}
|
|
23505
|
+
if (showIcon && _isActive) {
|
|
23506
|
+
const isSwimlane = currentSwimlaneGroup?.toLowerCase() === groupName.toLowerCase();
|
|
23507
|
+
const textW = measureLegendText(groupName, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
23508
|
+
const pillXOff = LEGEND_CAPSULE_PAD;
|
|
23509
|
+
const iconX = pillXOff + textW + 3;
|
|
23510
|
+
const iconY = (LEGEND_HEIGHT - 10) / 2;
|
|
23511
|
+
const iconEl = drawSwimlaneIcon(
|
|
23512
|
+
groupEl,
|
|
23513
|
+
iconX,
|
|
23514
|
+
iconY,
|
|
23515
|
+
isSwimlane,
|
|
23516
|
+
palette
|
|
23517
|
+
);
|
|
23518
|
+
iconEl.append("title").text(`Group by ${groupName}`);
|
|
23519
|
+
iconEl.style("cursor", "pointer").on("click", (event) => {
|
|
23520
|
+
event.stopPropagation();
|
|
23521
|
+
if (onSwimlaneChange) {
|
|
23522
|
+
onSwimlaneChange(
|
|
23523
|
+
currentSwimlaneGroup?.toLowerCase() === groupName.toLowerCase() ? null : groupName
|
|
23524
|
+
);
|
|
23525
|
+
}
|
|
23526
|
+
});
|
|
23527
|
+
}
|
|
22947
23528
|
}
|
|
23529
|
+
};
|
|
23530
|
+
renderLegendD3(
|
|
23531
|
+
tagGroupG,
|
|
23532
|
+
legendConfig,
|
|
23533
|
+
legendState,
|
|
23534
|
+
palette,
|
|
23535
|
+
isDark,
|
|
23536
|
+
legendCallbacks,
|
|
23537
|
+
tagGroupsW
|
|
23538
|
+
);
|
|
23539
|
+
for (let i = 0; i < visibleGroups.length; i++) {
|
|
23540
|
+
cursorX += groupWidths[i] + LEGEND_GROUP_GAP;
|
|
22948
23541
|
}
|
|
22949
|
-
cursorX += groupW + LEGEND_GROUP_GAP;
|
|
22950
23542
|
}
|
|
22951
23543
|
if (hasCriticalPath) {
|
|
22952
23544
|
const cpLineNum = optionLineNumbers["critical-path"];
|
|
@@ -23573,6 +24165,7 @@ var init_renderer9 = __esm({
|
|
|
23573
24165
|
init_tag_groups();
|
|
23574
24166
|
init_d3();
|
|
23575
24167
|
init_legend_constants();
|
|
24168
|
+
init_legend_d3();
|
|
23576
24169
|
init_title_constants();
|
|
23577
24170
|
BAR_H = 22;
|
|
23578
24171
|
ROW_GAP = 6;
|
|
@@ -24743,57 +25336,29 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
24743
25336
|
}
|
|
24744
25337
|
if (parsed.tagGroups.length > 0) {
|
|
24745
25338
|
const legendY = TOP_MARGIN + titleOffset;
|
|
24746
|
-
const
|
|
24747
|
-
|
|
24748
|
-
|
|
24749
|
-
if (tg.entries.length === 0) continue;
|
|
24750
|
-
const isActive = !!activeTagGroup && tg.name.toLowerCase() === activeTagGroup.toLowerCase();
|
|
24751
|
-
const pillWidth2 = measureLegendText(tg.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
24752
|
-
const entries = tg.entries.map((e) => ({
|
|
25339
|
+
const resolvedGroups = parsed.tagGroups.filter((tg) => tg.entries.length > 0).map((tg) => ({
|
|
25340
|
+
name: tg.name,
|
|
25341
|
+
entries: tg.entries.map((e) => ({
|
|
24753
25342
|
value: e.value,
|
|
24754
25343
|
color: resolveColor(e.color) ?? e.color
|
|
24755
|
-
}))
|
|
24756
|
-
|
|
24757
|
-
|
|
24758
|
-
|
|
24759
|
-
|
|
24760
|
-
|
|
24761
|
-
|
|
24762
|
-
|
|
24763
|
-
|
|
24764
|
-
|
|
24765
|
-
|
|
24766
|
-
|
|
24767
|
-
|
|
24768
|
-
|
|
24769
|
-
|
|
24770
|
-
|
|
24771
|
-
|
|
24772
|
-
|
|
24773
|
-
const gEl = legendContainer.append("g").attr("transform", `translate(${legendX}, ${legendY})`).attr("class", "sequence-legend-group").attr("data-legend-group", item.group.name.toLowerCase()).style("cursor", "pointer");
|
|
24774
|
-
if (item.isActive) {
|
|
24775
|
-
gEl.append("rect").attr("width", item.totalWidth).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
24776
|
-
}
|
|
24777
|
-
const pillXOff = item.isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
24778
|
-
const pillYOff = LEGEND_CAPSULE_PAD;
|
|
24779
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
24780
|
-
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", item.pillWidth).attr("height", pillH).attr("rx", pillH / 2).attr("fill", item.isActive ? palette.bg : groupBg);
|
|
24781
|
-
if (item.isActive) {
|
|
24782
|
-
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", item.pillWidth).attr("height", pillH).attr("rx", pillH / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
24783
|
-
}
|
|
24784
|
-
gEl.append("text").attr("x", pillXOff + item.pillWidth / 2).attr("y", LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", item.isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(item.group.name);
|
|
24785
|
-
if (item.isActive) {
|
|
24786
|
-
let entryX = pillXOff + item.pillWidth + 4;
|
|
24787
|
-
for (const entry of item.entries) {
|
|
24788
|
-
const entryG = gEl.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
24789
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
24790
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
24791
|
-
entryG.append("text").attr("x", textX).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
24792
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
24793
|
-
}
|
|
24794
|
-
}
|
|
24795
|
-
legendX += item.totalWidth + LEGEND_GROUP_GAP;
|
|
24796
|
-
}
|
|
25344
|
+
}))
|
|
25345
|
+
}));
|
|
25346
|
+
const legendConfig = {
|
|
25347
|
+
groups: resolvedGroups,
|
|
25348
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
25349
|
+
mode: "fixed"
|
|
25350
|
+
};
|
|
25351
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
25352
|
+
const legendG = svg.append("g").attr("class", "sequence-legend").attr("transform", `translate(0,${legendY})`);
|
|
25353
|
+
renderLegendD3(
|
|
25354
|
+
legendG,
|
|
25355
|
+
legendConfig,
|
|
25356
|
+
legendState,
|
|
25357
|
+
palette,
|
|
25358
|
+
isDark,
|
|
25359
|
+
void 0,
|
|
25360
|
+
svgWidth
|
|
25361
|
+
);
|
|
24797
25362
|
}
|
|
24798
25363
|
for (const group of groups) {
|
|
24799
25364
|
if (group.participantIds.length === 0) continue;
|
|
@@ -25352,6 +25917,7 @@ var init_renderer10 = __esm({
|
|
|
25352
25917
|
init_parser();
|
|
25353
25918
|
init_tag_resolution();
|
|
25354
25919
|
init_legend_constants();
|
|
25920
|
+
init_legend_d3();
|
|
25355
25921
|
init_title_constants();
|
|
25356
25922
|
PARTICIPANT_GAP = 160;
|
|
25357
25923
|
PARTICIPANT_BOX_WIDTH = 120;
|
|
@@ -28012,7 +28578,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28012
28578
|
const LG_ENTRY_FONT_SIZE = LEGEND_ENTRY_FONT_SIZE;
|
|
28013
28579
|
const LG_ENTRY_DOT_GAP = LEGEND_ENTRY_DOT_GAP;
|
|
28014
28580
|
const LG_ENTRY_TRAIL = LEGEND_ENTRY_TRAIL;
|
|
28015
|
-
const LG_GROUP_GAP = LEGEND_GROUP_GAP;
|
|
28016
28581
|
const LG_ICON_W = 20;
|
|
28017
28582
|
const mainSvg = d3Selection13.select(container).select("svg");
|
|
28018
28583
|
const mainG = mainSvg.select("g");
|
|
@@ -28051,11 +28616,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28051
28616
|
(lg) => effectiveColorKey != null && lg.group.name.toLowerCase() === effectiveColorKey
|
|
28052
28617
|
) : legendGroups;
|
|
28053
28618
|
if (visibleGroups.length === 0) return;
|
|
28054
|
-
const totalW = visibleGroups.reduce((s, lg) => {
|
|
28055
|
-
const isActive = viewMode || currentActiveGroup != null && lg.group.name.toLowerCase() === currentActiveGroup.toLowerCase();
|
|
28056
|
-
return s + (isActive ? lg.expandedWidth : lg.minifiedWidth);
|
|
28057
|
-
}, 0) + (visibleGroups.length - 1) * LG_GROUP_GAP;
|
|
28058
|
-
let cx = (width - totalW) / 2;
|
|
28059
28619
|
const legendContainer = mainSvg.append("g").attr("class", "tl-tag-legend-container");
|
|
28060
28620
|
if (currentActiveGroup) {
|
|
28061
28621
|
legendContainer.attr(
|
|
@@ -28063,82 +28623,85 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28063
28623
|
currentActiveGroup.toLowerCase()
|
|
28064
28624
|
);
|
|
28065
28625
|
}
|
|
28066
|
-
|
|
28067
|
-
|
|
28068
|
-
|
|
28069
|
-
|
|
28070
|
-
|
|
28071
|
-
|
|
28072
|
-
|
|
28073
|
-
|
|
28074
|
-
|
|
28075
|
-
|
|
28076
|
-
|
|
28077
|
-
|
|
28078
|
-
|
|
28079
|
-
|
|
28080
|
-
|
|
28081
|
-
|
|
28082
|
-
|
|
28083
|
-
|
|
28084
|
-
|
|
28085
|
-
|
|
28086
|
-
|
|
28087
|
-
|
|
28088
|
-
|
|
28089
|
-
|
|
28090
|
-
|
|
28091
|
-
|
|
28092
|
-
|
|
28093
|
-
|
|
28094
|
-
|
|
28095
|
-
|
|
28626
|
+
const iconAddon = viewMode ? 0 : LG_ICON_W;
|
|
28627
|
+
const centralGroups = visibleGroups.map((lg) => ({
|
|
28628
|
+
name: lg.group.name,
|
|
28629
|
+
entries: lg.group.entries.map((e) => ({
|
|
28630
|
+
value: e.value,
|
|
28631
|
+
color: e.color
|
|
28632
|
+
}))
|
|
28633
|
+
}));
|
|
28634
|
+
const centralActive = viewMode ? effectiveColorKey : currentActiveGroup;
|
|
28635
|
+
const centralConfig = {
|
|
28636
|
+
groups: centralGroups,
|
|
28637
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
28638
|
+
mode: "fixed",
|
|
28639
|
+
capsulePillAddonWidth: iconAddon
|
|
28640
|
+
};
|
|
28641
|
+
const centralState = { activeGroup: centralActive };
|
|
28642
|
+
const centralCallbacks = viewMode ? {} : {
|
|
28643
|
+
onGroupToggle: (groupName) => {
|
|
28644
|
+
currentActiveGroup = currentActiveGroup === groupName.toLowerCase() ? null : groupName.toLowerCase();
|
|
28645
|
+
drawLegend2();
|
|
28646
|
+
recolorEvents2();
|
|
28647
|
+
onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
|
|
28648
|
+
},
|
|
28649
|
+
onEntryHover: (groupName, entryValue) => {
|
|
28650
|
+
const tagKey = groupName.toLowerCase();
|
|
28651
|
+
if (entryValue) {
|
|
28652
|
+
const tagVal = entryValue.toLowerCase();
|
|
28653
|
+
fadeToTagValue(mainG, tagKey, tagVal);
|
|
28654
|
+
mainSvg.selectAll("[data-legend-entry]").each(function() {
|
|
28655
|
+
const el = d3Selection13.select(this);
|
|
28656
|
+
const ev = el.attr("data-legend-entry");
|
|
28657
|
+
const eg = el.attr("data-tag-group") ?? el.node()?.closest?.("[data-tag-group]")?.getAttribute("data-tag-group");
|
|
28658
|
+
el.attr(
|
|
28659
|
+
"opacity",
|
|
28660
|
+
eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY2
|
|
28661
|
+
);
|
|
28662
|
+
});
|
|
28663
|
+
} else {
|
|
28664
|
+
fadeReset(mainG);
|
|
28665
|
+
mainSvg.selectAll("[data-legend-entry]").attr("opacity", 1);
|
|
28666
|
+
}
|
|
28667
|
+
},
|
|
28668
|
+
onGroupRendered: (groupName, groupEl, isActive) => {
|
|
28669
|
+
const groupKey = groupName.toLowerCase();
|
|
28670
|
+
groupEl.attr("data-tag-group", groupKey);
|
|
28671
|
+
if (isActive && !viewMode) {
|
|
28672
|
+
const isSwimActive = currentSwimlaneGroup != null && currentSwimlaneGroup.toLowerCase() === groupKey;
|
|
28673
|
+
const pillWidth3 = measureLegendText(groupName, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
|
|
28674
|
+
const pillXOff = LG_CAPSULE_PAD;
|
|
28675
|
+
const iconX = pillXOff + pillWidth3 + 5;
|
|
28096
28676
|
const iconY = (LG_HEIGHT - 10) / 2;
|
|
28097
|
-
const iconEl = drawSwimlaneIcon3(
|
|
28677
|
+
const iconEl = drawSwimlaneIcon3(
|
|
28678
|
+
groupEl,
|
|
28679
|
+
iconX,
|
|
28680
|
+
iconY,
|
|
28681
|
+
isSwimActive
|
|
28682
|
+
);
|
|
28098
28683
|
iconEl.attr("data-swimlane-toggle", groupKey).on("click", (event) => {
|
|
28099
28684
|
event.stopPropagation();
|
|
28100
28685
|
currentSwimlaneGroup = currentSwimlaneGroup === groupKey ? null : groupKey;
|
|
28101
|
-
onTagStateChange?.(
|
|
28686
|
+
onTagStateChange?.(
|
|
28687
|
+
currentActiveGroup,
|
|
28688
|
+
currentSwimlaneGroup
|
|
28689
|
+
);
|
|
28102
28690
|
relayout2();
|
|
28103
28691
|
});
|
|
28104
|
-
entryX = pillXOff + pillWidth2 + LG_ICON_W + 4;
|
|
28105
|
-
} else {
|
|
28106
|
-
entryX = pillXOff + pillWidth2 + 8;
|
|
28107
|
-
}
|
|
28108
|
-
for (const entry of lg.group.entries) {
|
|
28109
|
-
const tagKey = lg.group.name.toLowerCase();
|
|
28110
|
-
const tagVal = entry.value.toLowerCase();
|
|
28111
|
-
const entryG = gEl.append("g").attr("class", "tl-tag-legend-entry").attr("data-tag-group", tagKey).attr("data-legend-entry", tagVal);
|
|
28112
|
-
if (!viewMode) {
|
|
28113
|
-
entryG.style("cursor", "pointer").on("mouseenter", (event) => {
|
|
28114
|
-
event.stopPropagation();
|
|
28115
|
-
fadeToTagValue(mainG, tagKey, tagVal);
|
|
28116
|
-
mainSvg.selectAll(".tl-tag-legend-entry").each(function() {
|
|
28117
|
-
const el = d3Selection13.select(this);
|
|
28118
|
-
const ev = el.attr("data-legend-entry");
|
|
28119
|
-
if (ev === "__group__") return;
|
|
28120
|
-
const eg = el.attr("data-tag-group");
|
|
28121
|
-
el.attr(
|
|
28122
|
-
"opacity",
|
|
28123
|
-
eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY2
|
|
28124
|
-
);
|
|
28125
|
-
});
|
|
28126
|
-
}).on("mouseleave", (event) => {
|
|
28127
|
-
event.stopPropagation();
|
|
28128
|
-
fadeReset(mainG);
|
|
28129
|
-
mainSvg.selectAll(".tl-tag-legend-entry").attr("opacity", 1);
|
|
28130
|
-
}).on("click", (event) => {
|
|
28131
|
-
event.stopPropagation();
|
|
28132
|
-
});
|
|
28133
|
-
}
|
|
28134
|
-
entryG.append("circle").attr("cx", entryX + LG_DOT_R).attr("cy", LG_HEIGHT / 2).attr("r", LG_DOT_R).attr("fill", entry.color);
|
|
28135
|
-
const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
|
|
28136
|
-
entryG.append("text").attr("x", textX).attr("y", LG_HEIGHT / 2 + LG_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LG_ENTRY_FONT_SIZE).attr("font-family", FONT_FAMILY).attr("fill", palette.textMuted).text(entry.value);
|
|
28137
|
-
entryX = textX + measureLegendText(entry.value, LG_ENTRY_FONT_SIZE) + LG_ENTRY_TRAIL;
|
|
28138
28692
|
}
|
|
28139
28693
|
}
|
|
28140
|
-
|
|
28141
|
-
}
|
|
28694
|
+
};
|
|
28695
|
+
const legendInnerG = legendContainer.append("g").attr("transform", `translate(0, ${legendY})`);
|
|
28696
|
+
renderLegendD3(
|
|
28697
|
+
legendInnerG,
|
|
28698
|
+
centralConfig,
|
|
28699
|
+
centralState,
|
|
28700
|
+
palette,
|
|
28701
|
+
isDark,
|
|
28702
|
+
centralCallbacks,
|
|
28703
|
+
width
|
|
28704
|
+
);
|
|
28142
28705
|
}, recolorEvents2 = function() {
|
|
28143
28706
|
const colorTG = currentActiveGroup ?? swimlaneTagGroup ?? null;
|
|
28144
28707
|
mainG.selectAll(".tl-event").each(function() {
|
|
@@ -28163,7 +28726,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28163
28726
|
};
|
|
28164
28727
|
var drawSwimlaneIcon2 = drawSwimlaneIcon3, relayout = relayout2, drawLegend = drawLegend2, recolorEvents = recolorEvents2;
|
|
28165
28728
|
const legendY = title ? 50 : 10;
|
|
28166
|
-
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
28167
28729
|
const legendGroups = parsed.timelineTagGroups.map((g) => {
|
|
28168
28730
|
const pillW = measureLegendText(g.name, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
|
|
28169
28731
|
const iconSpace = viewMode ? 8 : LG_ICON_W + 4;
|
|
@@ -29405,6 +29967,7 @@ var init_d3 = __esm({
|
|
|
29405
29967
|
init_parsing();
|
|
29406
29968
|
init_tag_groups();
|
|
29407
29969
|
init_legend_constants();
|
|
29970
|
+
init_legend_d3();
|
|
29408
29971
|
init_title_constants();
|
|
29409
29972
|
DEFAULT_CLOUD_OPTIONS = {
|
|
29410
29973
|
rotate: "none",
|
|
@@ -29559,11 +30122,26 @@ async function ensureDom() {
|
|
|
29559
30122
|
const { JSDOM } = await import("jsdom");
|
|
29560
30123
|
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
|
|
29561
30124
|
const win = dom.window;
|
|
29562
|
-
Object.defineProperty(globalThis, "document", {
|
|
29563
|
-
|
|
29564
|
-
|
|
29565
|
-
|
|
29566
|
-
Object.defineProperty(globalThis, "
|
|
30125
|
+
Object.defineProperty(globalThis, "document", {
|
|
30126
|
+
value: win.document,
|
|
30127
|
+
configurable: true
|
|
30128
|
+
});
|
|
30129
|
+
Object.defineProperty(globalThis, "window", {
|
|
30130
|
+
value: win,
|
|
30131
|
+
configurable: true
|
|
30132
|
+
});
|
|
30133
|
+
Object.defineProperty(globalThis, "navigator", {
|
|
30134
|
+
value: win.navigator,
|
|
30135
|
+
configurable: true
|
|
30136
|
+
});
|
|
30137
|
+
Object.defineProperty(globalThis, "HTMLElement", {
|
|
30138
|
+
value: win.HTMLElement,
|
|
30139
|
+
configurable: true
|
|
30140
|
+
});
|
|
30141
|
+
Object.defineProperty(globalThis, "SVGElement", {
|
|
30142
|
+
value: win.SVGElement,
|
|
30143
|
+
configurable: true
|
|
30144
|
+
});
|
|
29567
30145
|
}
|
|
29568
30146
|
async function render(content, options) {
|
|
29569
30147
|
const theme = options?.theme ?? "light";
|
|
@@ -29572,11 +30150,17 @@ async function render(content, options) {
|
|
|
29572
30150
|
const paletteColors = getPalette(paletteName)[theme === "dark" ? "dark" : "light"];
|
|
29573
30151
|
const chartType = parseDgmoChartType(content);
|
|
29574
30152
|
const category = chartType ? getRenderCategory(chartType) : null;
|
|
30153
|
+
const legendExportState = options?.legendState ? {
|
|
30154
|
+
activeTagGroup: options.legendState.activeGroup ?? null,
|
|
30155
|
+
hiddenAttributes: options.legendState.hiddenAttributes ? new Set(options.legendState.hiddenAttributes) : void 0
|
|
30156
|
+
} : void 0;
|
|
29575
30157
|
if (category === "data-chart") {
|
|
29576
|
-
return renderExtendedChartForExport(content, theme, paletteColors, {
|
|
30158
|
+
return renderExtendedChartForExport(content, theme, paletteColors, {
|
|
30159
|
+
branding
|
|
30160
|
+
});
|
|
29577
30161
|
}
|
|
29578
30162
|
await ensureDom();
|
|
29579
|
-
return renderForExport(content, theme, paletteColors,
|
|
30163
|
+
return renderForExport(content, theme, paletteColors, legendExportState, {
|
|
29580
30164
|
branding,
|
|
29581
30165
|
c4Level: options?.c4Level,
|
|
29582
30166
|
c4System: options?.c4System,
|
|
@@ -30299,6 +30883,8 @@ init_flowchart_renderer();
|
|
|
30299
30883
|
init_echarts();
|
|
30300
30884
|
init_legend_svg();
|
|
30301
30885
|
init_legend_constants();
|
|
30886
|
+
init_legend_d3();
|
|
30887
|
+
init_legend_layout();
|
|
30302
30888
|
init_d3();
|
|
30303
30889
|
init_renderer10();
|
|
30304
30890
|
init_colors();
|
|
@@ -31145,6 +31731,7 @@ export {
|
|
|
31145
31731
|
computeCardMove,
|
|
31146
31732
|
computeInfra,
|
|
31147
31733
|
computeInfraLegendGroups,
|
|
31734
|
+
computeLegendLayout,
|
|
31148
31735
|
computeScatterLabelGraphics,
|
|
31149
31736
|
computeTimeTicks,
|
|
31150
31737
|
contrastText,
|
|
@@ -31156,6 +31743,7 @@ export {
|
|
|
31156
31743
|
formatDgmoError,
|
|
31157
31744
|
getAvailablePalettes,
|
|
31158
31745
|
getExtendedChartLegendGroups,
|
|
31746
|
+
getLegendReservedHeight,
|
|
31159
31747
|
getPalette,
|
|
31160
31748
|
getRenderCategory,
|
|
31161
31749
|
getSeriesColors,
|
|
@@ -31244,7 +31832,9 @@ export {
|
|
|
31244
31832
|
renderInfra,
|
|
31245
31833
|
renderKanban,
|
|
31246
31834
|
renderKanbanForExport,
|
|
31835
|
+
renderLegendD3,
|
|
31247
31836
|
renderLegendSvg,
|
|
31837
|
+
renderLegendSvgFromConfig,
|
|
31248
31838
|
renderOrg,
|
|
31249
31839
|
renderOrgForExport,
|
|
31250
31840
|
renderQuadrant,
|