@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.cjs
CHANGED
|
@@ -1923,6 +1923,493 @@ var init_legend_constants = __esm({
|
|
|
1923
1923
|
}
|
|
1924
1924
|
});
|
|
1925
1925
|
|
|
1926
|
+
// src/utils/legend-layout.ts
|
|
1927
|
+
function pillWidth(name) {
|
|
1928
|
+
return measureLegendText(name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
1929
|
+
}
|
|
1930
|
+
function entriesWidth(entries) {
|
|
1931
|
+
let w = 0;
|
|
1932
|
+
for (const e of entries) {
|
|
1933
|
+
w += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
1934
|
+
}
|
|
1935
|
+
return w;
|
|
1936
|
+
}
|
|
1937
|
+
function entryWidth(value) {
|
|
1938
|
+
return LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
1939
|
+
}
|
|
1940
|
+
function controlWidth(control) {
|
|
1941
|
+
let w = CONTROL_PILL_PAD;
|
|
1942
|
+
if (control.label) {
|
|
1943
|
+
w += measureLegendText(control.label, CONTROL_FONT_SIZE);
|
|
1944
|
+
if (control.icon) w += CONTROL_ICON_GAP;
|
|
1945
|
+
}
|
|
1946
|
+
if (control.icon) w += 14;
|
|
1947
|
+
if (control.children) {
|
|
1948
|
+
for (const child of control.children) {
|
|
1949
|
+
w += measureLegendText(child.label, CONTROL_FONT_SIZE) + 12;
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
return w;
|
|
1953
|
+
}
|
|
1954
|
+
function capsuleWidth(name, entries, containerWidth, addonWidth = 0) {
|
|
1955
|
+
const pw = pillWidth(name);
|
|
1956
|
+
const maxCapsuleW = containerWidth;
|
|
1957
|
+
const baseW = LEGEND_CAPSULE_PAD * 2 + pw + 4 + addonWidth;
|
|
1958
|
+
const ew = entriesWidth(entries);
|
|
1959
|
+
const singleRowW = baseW + ew;
|
|
1960
|
+
if (singleRowW <= maxCapsuleW) {
|
|
1961
|
+
return {
|
|
1962
|
+
width: singleRowW,
|
|
1963
|
+
entryRows: 1,
|
|
1964
|
+
moreCount: 0,
|
|
1965
|
+
visibleEntries: entries.length
|
|
1966
|
+
};
|
|
1967
|
+
}
|
|
1968
|
+
const rowWidth = maxCapsuleW - LEGEND_CAPSULE_PAD * 2;
|
|
1969
|
+
let row = 1;
|
|
1970
|
+
let rowX = pw + 4;
|
|
1971
|
+
let visible = 0;
|
|
1972
|
+
for (let i = 0; i < entries.length; i++) {
|
|
1973
|
+
const ew2 = entryWidth(entries[i].value);
|
|
1974
|
+
if (rowX + ew2 > rowWidth && rowX > pw + 4) {
|
|
1975
|
+
row++;
|
|
1976
|
+
rowX = 0;
|
|
1977
|
+
if (row > LEGEND_MAX_ENTRY_ROWS) {
|
|
1978
|
+
return {
|
|
1979
|
+
width: maxCapsuleW,
|
|
1980
|
+
entryRows: LEGEND_MAX_ENTRY_ROWS,
|
|
1981
|
+
moreCount: entries.length - visible,
|
|
1982
|
+
visibleEntries: visible
|
|
1983
|
+
};
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
rowX += ew2;
|
|
1987
|
+
visible++;
|
|
1988
|
+
}
|
|
1989
|
+
return {
|
|
1990
|
+
width: maxCapsuleW,
|
|
1991
|
+
entryRows: row,
|
|
1992
|
+
moreCount: 0,
|
|
1993
|
+
visibleEntries: entries.length
|
|
1994
|
+
};
|
|
1995
|
+
}
|
|
1996
|
+
function computeLegendLayout(config, state, containerWidth) {
|
|
1997
|
+
const { groups, controls: configControls, mode } = config;
|
|
1998
|
+
const isExport = mode === "inline";
|
|
1999
|
+
const activeGroupName = state.activeGroup?.toLowerCase() ?? null;
|
|
2000
|
+
if (isExport && !activeGroupName) {
|
|
2001
|
+
return {
|
|
2002
|
+
height: 0,
|
|
2003
|
+
width: 0,
|
|
2004
|
+
rows: [],
|
|
2005
|
+
controls: [],
|
|
2006
|
+
pills: [],
|
|
2007
|
+
activeCapsule: void 0
|
|
2008
|
+
};
|
|
2009
|
+
}
|
|
2010
|
+
const visibleGroups = config.showEmptyGroups ? groups : groups.filter((g) => g.entries.length > 0);
|
|
2011
|
+
if (visibleGroups.length === 0 && (!configControls || configControls.length === 0)) {
|
|
2012
|
+
return {
|
|
2013
|
+
height: 0,
|
|
2014
|
+
width: 0,
|
|
2015
|
+
rows: [],
|
|
2016
|
+
controls: [],
|
|
2017
|
+
pills: [],
|
|
2018
|
+
activeCapsule: void 0
|
|
2019
|
+
};
|
|
2020
|
+
}
|
|
2021
|
+
const controlLayouts = [];
|
|
2022
|
+
let totalControlsW = 0;
|
|
2023
|
+
if (configControls && !isExport) {
|
|
2024
|
+
for (const ctrl of configControls) {
|
|
2025
|
+
const w = controlWidth(ctrl);
|
|
2026
|
+
controlLayouts.push({
|
|
2027
|
+
id: ctrl.id,
|
|
2028
|
+
x: 0,
|
|
2029
|
+
// positioned later
|
|
2030
|
+
y: 0,
|
|
2031
|
+
width: w,
|
|
2032
|
+
height: LEGEND_HEIGHT,
|
|
2033
|
+
icon: ctrl.icon,
|
|
2034
|
+
label: ctrl.label,
|
|
2035
|
+
exportBehavior: ctrl.exportBehavior,
|
|
2036
|
+
children: ctrl.children?.map((c) => ({
|
|
2037
|
+
id: c.id,
|
|
2038
|
+
label: c.label,
|
|
2039
|
+
x: 0,
|
|
2040
|
+
y: 0,
|
|
2041
|
+
width: measureLegendText(c.label, CONTROL_FONT_SIZE) + 12,
|
|
2042
|
+
isActive: c.isActive
|
|
2043
|
+
}))
|
|
2044
|
+
});
|
|
2045
|
+
totalControlsW += w + CONTROL_GAP;
|
|
2046
|
+
}
|
|
2047
|
+
if (totalControlsW > 0) totalControlsW -= CONTROL_GAP;
|
|
2048
|
+
} else if (configControls && isExport) {
|
|
2049
|
+
for (const ctrl of configControls) {
|
|
2050
|
+
if (ctrl.exportBehavior === "strip") continue;
|
|
2051
|
+
const w = controlWidth(ctrl);
|
|
2052
|
+
controlLayouts.push({
|
|
2053
|
+
id: ctrl.id,
|
|
2054
|
+
x: 0,
|
|
2055
|
+
y: 0,
|
|
2056
|
+
width: w,
|
|
2057
|
+
height: LEGEND_HEIGHT,
|
|
2058
|
+
icon: ctrl.icon,
|
|
2059
|
+
label: ctrl.label,
|
|
2060
|
+
exportBehavior: ctrl.exportBehavior,
|
|
2061
|
+
children: ctrl.children?.map((c) => ({
|
|
2062
|
+
id: c.id,
|
|
2063
|
+
label: c.label,
|
|
2064
|
+
x: 0,
|
|
2065
|
+
y: 0,
|
|
2066
|
+
width: measureLegendText(c.label, CONTROL_FONT_SIZE) + 12,
|
|
2067
|
+
isActive: c.isActive
|
|
2068
|
+
}))
|
|
2069
|
+
});
|
|
2070
|
+
totalControlsW += w + CONTROL_GAP;
|
|
2071
|
+
}
|
|
2072
|
+
if (totalControlsW > 0) totalControlsW -= CONTROL_GAP;
|
|
2073
|
+
}
|
|
2074
|
+
const controlsSpace = totalControlsW > 0 ? totalControlsW + LEGEND_GROUP_GAP * 2 : 0;
|
|
2075
|
+
const groupAvailW = containerWidth - controlsSpace;
|
|
2076
|
+
const pills = [];
|
|
2077
|
+
let activeCapsule;
|
|
2078
|
+
for (const g of visibleGroups) {
|
|
2079
|
+
const isActive = activeGroupName === g.name.toLowerCase();
|
|
2080
|
+
if (isExport && !isActive) continue;
|
|
2081
|
+
if (isActive) {
|
|
2082
|
+
activeCapsule = buildCapsuleLayout(
|
|
2083
|
+
g,
|
|
2084
|
+
containerWidth,
|
|
2085
|
+
config.capsulePillAddonWidth ?? 0
|
|
2086
|
+
);
|
|
2087
|
+
} else {
|
|
2088
|
+
const pw = pillWidth(g.name);
|
|
2089
|
+
pills.push({
|
|
2090
|
+
groupName: g.name,
|
|
2091
|
+
x: 0,
|
|
2092
|
+
y: 0,
|
|
2093
|
+
width: pw,
|
|
2094
|
+
height: LEGEND_HEIGHT,
|
|
2095
|
+
isActive: false
|
|
2096
|
+
});
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
const rows = layoutRows(
|
|
2100
|
+
activeCapsule,
|
|
2101
|
+
pills,
|
|
2102
|
+
controlLayouts,
|
|
2103
|
+
groupAvailW,
|
|
2104
|
+
containerWidth,
|
|
2105
|
+
totalControlsW
|
|
2106
|
+
);
|
|
2107
|
+
const height = rows.length * LEGEND_HEIGHT;
|
|
2108
|
+
const width = containerWidth;
|
|
2109
|
+
return {
|
|
2110
|
+
height,
|
|
2111
|
+
width,
|
|
2112
|
+
rows,
|
|
2113
|
+
activeCapsule,
|
|
2114
|
+
controls: controlLayouts,
|
|
2115
|
+
pills
|
|
2116
|
+
};
|
|
2117
|
+
}
|
|
2118
|
+
function buildCapsuleLayout(group, containerWidth, addonWidth = 0) {
|
|
2119
|
+
const pw = pillWidth(group.name);
|
|
2120
|
+
const info = capsuleWidth(
|
|
2121
|
+
group.name,
|
|
2122
|
+
group.entries,
|
|
2123
|
+
containerWidth,
|
|
2124
|
+
addonWidth
|
|
2125
|
+
);
|
|
2126
|
+
const pill = {
|
|
2127
|
+
groupName: group.name,
|
|
2128
|
+
x: LEGEND_CAPSULE_PAD,
|
|
2129
|
+
y: LEGEND_CAPSULE_PAD,
|
|
2130
|
+
width: pw,
|
|
2131
|
+
height: LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2,
|
|
2132
|
+
isActive: true
|
|
2133
|
+
};
|
|
2134
|
+
const entries = [];
|
|
2135
|
+
let ex = LEGEND_CAPSULE_PAD + pw + 4 + addonWidth;
|
|
2136
|
+
let ey = 0;
|
|
2137
|
+
let rowX = ex;
|
|
2138
|
+
const maxRowW = containerWidth - LEGEND_CAPSULE_PAD * 2;
|
|
2139
|
+
let currentRow = 0;
|
|
2140
|
+
for (let i = 0; i < info.visibleEntries; i++) {
|
|
2141
|
+
const entry = group.entries[i];
|
|
2142
|
+
const ew = entryWidth(entry.value);
|
|
2143
|
+
if (rowX + ew > maxRowW && rowX > ex && i > 0) {
|
|
2144
|
+
currentRow++;
|
|
2145
|
+
rowX = 0;
|
|
2146
|
+
ey = currentRow * LEGEND_HEIGHT;
|
|
2147
|
+
if (currentRow === 0) ex = LEGEND_CAPSULE_PAD + pw + 4;
|
|
2148
|
+
}
|
|
2149
|
+
const dotCx = rowX + LEGEND_DOT_R;
|
|
2150
|
+
const dotCy = ey + LEGEND_HEIGHT / 2;
|
|
2151
|
+
const textX = rowX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
2152
|
+
const textY = ey + LEGEND_HEIGHT / 2;
|
|
2153
|
+
entries.push({
|
|
2154
|
+
value: entry.value,
|
|
2155
|
+
color: entry.color,
|
|
2156
|
+
x: rowX,
|
|
2157
|
+
y: ey,
|
|
2158
|
+
dotCx,
|
|
2159
|
+
dotCy,
|
|
2160
|
+
textX,
|
|
2161
|
+
textY
|
|
2162
|
+
});
|
|
2163
|
+
rowX += ew;
|
|
2164
|
+
}
|
|
2165
|
+
const totalRows = info.entryRows;
|
|
2166
|
+
const capsuleH = totalRows * LEGEND_HEIGHT;
|
|
2167
|
+
return {
|
|
2168
|
+
groupName: group.name,
|
|
2169
|
+
x: 0,
|
|
2170
|
+
y: 0,
|
|
2171
|
+
width: info.width,
|
|
2172
|
+
height: capsuleH,
|
|
2173
|
+
pill,
|
|
2174
|
+
entries,
|
|
2175
|
+
moreCount: info.moreCount > 0 ? info.moreCount : void 0,
|
|
2176
|
+
addonX: addonWidth > 0 ? LEGEND_CAPSULE_PAD + pw + 4 : void 0
|
|
2177
|
+
};
|
|
2178
|
+
}
|
|
2179
|
+
function layoutRows(activeCapsule, pills, controls, groupAvailW, containerWidth, totalControlsW) {
|
|
2180
|
+
const rows = [];
|
|
2181
|
+
const groupItems = [];
|
|
2182
|
+
if (activeCapsule) groupItems.push(activeCapsule);
|
|
2183
|
+
groupItems.push(...pills);
|
|
2184
|
+
let currentRowItems = [];
|
|
2185
|
+
let currentRowW = 0;
|
|
2186
|
+
let rowY = 0;
|
|
2187
|
+
for (const item of groupItems) {
|
|
2188
|
+
const itemW = item.width + LEGEND_GROUP_GAP;
|
|
2189
|
+
if (currentRowW + item.width > groupAvailW && currentRowItems.length > 0) {
|
|
2190
|
+
centerRowItems(currentRowItems, containerWidth, totalControlsW);
|
|
2191
|
+
rows.push({ y: rowY, items: currentRowItems });
|
|
2192
|
+
rowY += LEGEND_HEIGHT;
|
|
2193
|
+
currentRowItems = [];
|
|
2194
|
+
currentRowW = 0;
|
|
2195
|
+
}
|
|
2196
|
+
item.x = currentRowW;
|
|
2197
|
+
item.y = rowY;
|
|
2198
|
+
currentRowItems.push(item);
|
|
2199
|
+
currentRowW += itemW;
|
|
2200
|
+
}
|
|
2201
|
+
if (controls.length > 0) {
|
|
2202
|
+
let cx = containerWidth;
|
|
2203
|
+
for (let i = controls.length - 1; i >= 0; i--) {
|
|
2204
|
+
cx -= controls[i].width;
|
|
2205
|
+
controls[i].x = cx;
|
|
2206
|
+
controls[i].y = 0;
|
|
2207
|
+
cx -= CONTROL_GAP;
|
|
2208
|
+
}
|
|
2209
|
+
if (rows.length > 0) {
|
|
2210
|
+
rows[0].items.push(...controls);
|
|
2211
|
+
} else if (currentRowItems.length > 0) {
|
|
2212
|
+
currentRowItems.push(...controls);
|
|
2213
|
+
} else {
|
|
2214
|
+
currentRowItems.push(...controls);
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
if (currentRowItems.length > 0) {
|
|
2218
|
+
centerRowItems(currentRowItems, containerWidth, totalControlsW);
|
|
2219
|
+
rows.push({ y: rowY, items: currentRowItems });
|
|
2220
|
+
}
|
|
2221
|
+
if (rows.length === 0) {
|
|
2222
|
+
rows.push({ y: 0, items: [] });
|
|
2223
|
+
}
|
|
2224
|
+
return rows;
|
|
2225
|
+
}
|
|
2226
|
+
function centerRowItems(items, containerWidth, totalControlsW) {
|
|
2227
|
+
const groupItems = items.filter((it) => "groupName" in it);
|
|
2228
|
+
if (groupItems.length === 0) return;
|
|
2229
|
+
const totalGroupW = groupItems.reduce((s, it) => s + it.width, 0) + (groupItems.length - 1) * LEGEND_GROUP_GAP;
|
|
2230
|
+
const availW = containerWidth - (totalControlsW > 0 ? totalControlsW + LEGEND_GROUP_GAP * 2 : 0);
|
|
2231
|
+
const offset = Math.max(0, (availW - totalGroupW) / 2);
|
|
2232
|
+
let x = offset;
|
|
2233
|
+
for (const item of groupItems) {
|
|
2234
|
+
item.x = x;
|
|
2235
|
+
x += item.width + LEGEND_GROUP_GAP;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
function getLegendReservedHeight(config, state, containerWidth) {
|
|
2239
|
+
const layout = computeLegendLayout(config, state, containerWidth);
|
|
2240
|
+
return layout.height;
|
|
2241
|
+
}
|
|
2242
|
+
var LEGEND_MAX_ENTRY_ROWS, CONTROL_PILL_PAD, CONTROL_FONT_SIZE, CONTROL_ICON_GAP, CONTROL_GAP;
|
|
2243
|
+
var init_legend_layout = __esm({
|
|
2244
|
+
"src/utils/legend-layout.ts"() {
|
|
2245
|
+
"use strict";
|
|
2246
|
+
init_legend_constants();
|
|
2247
|
+
LEGEND_MAX_ENTRY_ROWS = 3;
|
|
2248
|
+
CONTROL_PILL_PAD = 16;
|
|
2249
|
+
CONTROL_FONT_SIZE = 11;
|
|
2250
|
+
CONTROL_ICON_GAP = 4;
|
|
2251
|
+
CONTROL_GAP = 8;
|
|
2252
|
+
}
|
|
2253
|
+
});
|
|
2254
|
+
|
|
2255
|
+
// src/utils/legend-d3.ts
|
|
2256
|
+
function renderLegendD3(container, config, state, palette, isDark, callbacks, containerWidth) {
|
|
2257
|
+
const width = containerWidth ?? parseFloat(container.attr("width") || "800");
|
|
2258
|
+
let currentState = { ...state };
|
|
2259
|
+
let currentLayout;
|
|
2260
|
+
const legendG = container.append("g").attr("class", "dgmo-legend");
|
|
2261
|
+
function render2() {
|
|
2262
|
+
currentLayout = computeLegendLayout(config, currentState, width);
|
|
2263
|
+
legendG.selectAll("*").remove();
|
|
2264
|
+
if (currentLayout.height === 0) return;
|
|
2265
|
+
if (currentState.activeGroup) {
|
|
2266
|
+
legendG.attr(
|
|
2267
|
+
"data-legend-active",
|
|
2268
|
+
currentState.activeGroup.toLowerCase()
|
|
2269
|
+
);
|
|
2270
|
+
} else {
|
|
2271
|
+
legendG.attr("data-legend-active", null);
|
|
2272
|
+
}
|
|
2273
|
+
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
2274
|
+
const pillBorder = mix(palette.textMuted, palette.bg, 50);
|
|
2275
|
+
if (currentLayout.activeCapsule) {
|
|
2276
|
+
renderCapsule(
|
|
2277
|
+
legendG,
|
|
2278
|
+
currentLayout.activeCapsule,
|
|
2279
|
+
palette,
|
|
2280
|
+
groupBg,
|
|
2281
|
+
pillBorder,
|
|
2282
|
+
isDark,
|
|
2283
|
+
callbacks
|
|
2284
|
+
);
|
|
2285
|
+
}
|
|
2286
|
+
for (const pill of currentLayout.pills) {
|
|
2287
|
+
renderPill(legendG, pill, palette, groupBg, callbacks);
|
|
2288
|
+
}
|
|
2289
|
+
for (const ctrl of currentLayout.controls) {
|
|
2290
|
+
renderControl(
|
|
2291
|
+
legendG,
|
|
2292
|
+
ctrl,
|
|
2293
|
+
palette,
|
|
2294
|
+
groupBg,
|
|
2295
|
+
pillBorder,
|
|
2296
|
+
isDark,
|
|
2297
|
+
config.controls
|
|
2298
|
+
);
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
render2();
|
|
2302
|
+
return {
|
|
2303
|
+
setState(newState) {
|
|
2304
|
+
currentState = { ...newState };
|
|
2305
|
+
render2();
|
|
2306
|
+
},
|
|
2307
|
+
destroy() {
|
|
2308
|
+
legendG.remove();
|
|
2309
|
+
},
|
|
2310
|
+
getHeight() {
|
|
2311
|
+
return currentLayout?.height ?? 0;
|
|
2312
|
+
},
|
|
2313
|
+
getLayout() {
|
|
2314
|
+
return currentLayout;
|
|
2315
|
+
}
|
|
2316
|
+
};
|
|
2317
|
+
}
|
|
2318
|
+
function renderCapsule(parent, capsule, palette, groupBg, pillBorder, _isDark, callbacks) {
|
|
2319
|
+
const g = parent.append("g").attr("transform", `translate(${capsule.x},${capsule.y})`).attr("data-legend-group", capsule.groupName.toLowerCase()).style("cursor", "pointer");
|
|
2320
|
+
g.append("rect").attr("width", capsule.width).attr("height", capsule.height).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
2321
|
+
const pill = capsule.pill;
|
|
2322
|
+
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);
|
|
2323
|
+
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);
|
|
2324
|
+
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);
|
|
2325
|
+
for (const entry of capsule.entries) {
|
|
2326
|
+
const entryG = g.append("g").attr("data-legend-entry", entry.value.toLowerCase()).attr("data-series-name", entry.value).style("cursor", "pointer");
|
|
2327
|
+
entryG.append("circle").attr("cx", entry.dotCx).attr("cy", entry.dotCy).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
2328
|
+
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);
|
|
2329
|
+
if (callbacks?.onEntryHover) {
|
|
2330
|
+
const groupName = capsule.groupName;
|
|
2331
|
+
const entryValue = entry.value;
|
|
2332
|
+
const onHover = callbacks.onEntryHover;
|
|
2333
|
+
entryG.on("mouseenter", () => onHover(groupName, entryValue)).on("mouseleave", () => onHover(groupName, null));
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
if (capsule.moreCount) {
|
|
2337
|
+
const lastEntry = capsule.entries[capsule.entries.length - 1];
|
|
2338
|
+
const moreX = lastEntry ? lastEntry.textX + measureLegendText(lastEntry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_DOT_GAP * 2 : pill.x + pill.width + 8;
|
|
2339
|
+
const moreY = lastEntry?.textY ?? LEGEND_HEIGHT / 2;
|
|
2340
|
+
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`);
|
|
2341
|
+
}
|
|
2342
|
+
if (callbacks?.onGroupToggle) {
|
|
2343
|
+
const cb = callbacks.onGroupToggle;
|
|
2344
|
+
const name = capsule.groupName;
|
|
2345
|
+
g.on("click", () => cb(name));
|
|
2346
|
+
}
|
|
2347
|
+
if (callbacks?.onGroupRendered) {
|
|
2348
|
+
callbacks.onGroupRendered(capsule.groupName, g, true);
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
function renderPill(parent, pill, palette, groupBg, callbacks) {
|
|
2352
|
+
const g = parent.append("g").attr("transform", `translate(${pill.x},${pill.y})`).attr("data-legend-group", pill.groupName.toLowerCase()).style("cursor", "pointer");
|
|
2353
|
+
g.append("rect").attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", groupBg);
|
|
2354
|
+
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);
|
|
2355
|
+
if (callbacks?.onGroupToggle) {
|
|
2356
|
+
const cb = callbacks.onGroupToggle;
|
|
2357
|
+
const name = pill.groupName;
|
|
2358
|
+
g.on("click", () => cb(name));
|
|
2359
|
+
}
|
|
2360
|
+
if (callbacks?.onGroupRendered) {
|
|
2361
|
+
callbacks.onGroupRendered(pill.groupName, g, false);
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
function renderControl(parent, ctrl, palette, _groupBg, pillBorder, _isDark, configControls) {
|
|
2365
|
+
const g = parent.append("g").attr("transform", `translate(${ctrl.x},${ctrl.y})`).attr("data-legend-control", ctrl.id).style("cursor", "pointer");
|
|
2366
|
+
if (ctrl.exportBehavior === "strip") {
|
|
2367
|
+
g.attr("data-export-ignore", "true");
|
|
2368
|
+
}
|
|
2369
|
+
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);
|
|
2370
|
+
let textX = ctrl.width / 2;
|
|
2371
|
+
if (ctrl.icon && ctrl.label) {
|
|
2372
|
+
const iconG = g.append("g").attr("transform", `translate(8,${(ctrl.height - 14) / 2})`);
|
|
2373
|
+
iconG.html(ctrl.icon);
|
|
2374
|
+
textX = 8 + 14 + LEGEND_ENTRY_DOT_GAP + measureLegendText(ctrl.label, LEGEND_PILL_FONT_SIZE) / 2;
|
|
2375
|
+
}
|
|
2376
|
+
if (ctrl.label) {
|
|
2377
|
+
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);
|
|
2378
|
+
}
|
|
2379
|
+
if (ctrl.children) {
|
|
2380
|
+
let cx = ctrl.width + 4;
|
|
2381
|
+
for (const child of ctrl.children) {
|
|
2382
|
+
const childG = g.append("g").attr("transform", `translate(${cx},0)`).style("cursor", "pointer");
|
|
2383
|
+
childG.append("rect").attr("width", child.width).attr("height", ctrl.height).attr("rx", ctrl.height / 2).attr(
|
|
2384
|
+
"fill",
|
|
2385
|
+
child.isActive ? palette.primary ?? palette.text : "none"
|
|
2386
|
+
).attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
2387
|
+
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);
|
|
2388
|
+
const configCtrl2 = configControls?.find((c) => c.id === ctrl.id);
|
|
2389
|
+
const configChild = configCtrl2?.children?.find((c) => c.id === child.id);
|
|
2390
|
+
if (configChild?.onClick) {
|
|
2391
|
+
const onClick = configChild.onClick;
|
|
2392
|
+
childG.on("click", () => onClick());
|
|
2393
|
+
}
|
|
2394
|
+
cx += child.width + 4;
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
const configCtrl = configControls?.find((c) => c.id === ctrl.id);
|
|
2398
|
+
if (configCtrl?.onClick) {
|
|
2399
|
+
const onClick = configCtrl.onClick;
|
|
2400
|
+
g.on("click", () => onClick());
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
var init_legend_d3 = __esm({
|
|
2404
|
+
"src/utils/legend-d3.ts"() {
|
|
2405
|
+
"use strict";
|
|
2406
|
+
init_legend_constants();
|
|
2407
|
+
init_legend_layout();
|
|
2408
|
+
init_color_utils();
|
|
2409
|
+
init_fonts();
|
|
2410
|
+
}
|
|
2411
|
+
});
|
|
2412
|
+
|
|
1926
2413
|
// src/utils/title-constants.ts
|
|
1927
2414
|
var TITLE_FONT_SIZE, TITLE_FONT_WEIGHT, TITLE_Y, TITLE_OFFSET;
|
|
1928
2415
|
var init_title_constants = __esm({
|
|
@@ -4852,10 +5339,10 @@ var init_chart = __esm({
|
|
|
4852
5339
|
function esc(s) {
|
|
4853
5340
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
4854
5341
|
}
|
|
4855
|
-
function
|
|
5342
|
+
function pillWidth2(name) {
|
|
4856
5343
|
return measureLegendText(name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
4857
5344
|
}
|
|
4858
|
-
function
|
|
5345
|
+
function entriesWidth2(entries) {
|
|
4859
5346
|
let w = 0;
|
|
4860
5347
|
for (const e of entries) {
|
|
4861
5348
|
w += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
@@ -4863,9 +5350,9 @@ function entriesWidth(entries) {
|
|
|
4863
5350
|
return w;
|
|
4864
5351
|
}
|
|
4865
5352
|
function groupTotalWidth(name, entries, isActive) {
|
|
4866
|
-
const pw =
|
|
5353
|
+
const pw = pillWidth2(name);
|
|
4867
5354
|
if (!isActive) return pw;
|
|
4868
|
-
return LEGEND_CAPSULE_PAD * 2 + pw + 4 +
|
|
5355
|
+
return LEGEND_CAPSULE_PAD * 2 + pw + 4 + entriesWidth2(entries);
|
|
4869
5356
|
}
|
|
4870
5357
|
function renderLegendSvg(groups, options) {
|
|
4871
5358
|
if (groups.length === 0) return { svg: "", height: 0, width: 0 };
|
|
@@ -4873,7 +5360,7 @@ function renderLegendSvg(groups, options) {
|
|
|
4873
5360
|
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
4874
5361
|
const items = groups.filter((g) => g.entries.length > 0).map((g) => {
|
|
4875
5362
|
const isActive = !!activeGroup && g.name.toLowerCase() === activeGroup.toLowerCase();
|
|
4876
|
-
const pw =
|
|
5363
|
+
const pw = pillWidth2(g.name);
|
|
4877
5364
|
const tw = groupTotalWidth(g.name, g.entries, isActive);
|
|
4878
5365
|
return { group: g, isActive, pillWidth: pw, totalWidth: tw };
|
|
4879
5366
|
});
|
|
@@ -4927,6 +5414,19 @@ function renderLegendSvg(groups, options) {
|
|
|
4927
5414
|
const svg = `<g${classAttr}${activeAttr}>${parts.join("")}</g>`;
|
|
4928
5415
|
return { svg, height: LEGEND_HEIGHT, width: totalWidth };
|
|
4929
5416
|
}
|
|
5417
|
+
function renderLegendSvgFromConfig(config, state, palette, containerWidth) {
|
|
5418
|
+
return renderLegendSvg(config.groups, {
|
|
5419
|
+
palette: {
|
|
5420
|
+
bg: palette.bg,
|
|
5421
|
+
surface: palette.surface,
|
|
5422
|
+
text: palette.text,
|
|
5423
|
+
textMuted: palette.textMuted
|
|
5424
|
+
},
|
|
5425
|
+
isDark: palette.isDark,
|
|
5426
|
+
containerWidth,
|
|
5427
|
+
activeGroup: state.activeGroup
|
|
5428
|
+
});
|
|
5429
|
+
}
|
|
4930
5430
|
var init_legend_svg = __esm({
|
|
4931
5431
|
"src/utils/legend-svg.ts"() {
|
|
4932
5432
|
"use strict";
|
|
@@ -8379,7 +8879,12 @@ __export(parser_exports7, {
|
|
|
8379
8879
|
function parseArrowLine(trimmed, palette) {
|
|
8380
8880
|
const bareMatch = trimmed.match(BARE_ARROW_RE);
|
|
8381
8881
|
if (bareMatch) {
|
|
8382
|
-
|
|
8882
|
+
const rawTarget = bareMatch[1].trim();
|
|
8883
|
+
const groupMatch = rawTarget.match(/^\[(.+)\]$/);
|
|
8884
|
+
return {
|
|
8885
|
+
target: groupMatch ? groupMatch[1].trim() : rawTarget,
|
|
8886
|
+
targetIsGroup: !!groupMatch
|
|
8887
|
+
};
|
|
8383
8888
|
}
|
|
8384
8889
|
const arrowMatch = trimmed.match(ARROW_RE);
|
|
8385
8890
|
if (arrowMatch) {
|
|
@@ -8388,8 +8893,14 @@ function parseArrowLine(trimmed, palette) {
|
|
|
8388
8893
|
if (label && !color) {
|
|
8389
8894
|
color = inferArrowColor(label);
|
|
8390
8895
|
}
|
|
8391
|
-
const
|
|
8392
|
-
|
|
8896
|
+
const rawTarget = arrowMatch[3].trim();
|
|
8897
|
+
const groupMatch = rawTarget.match(/^\[(.+)\]$/);
|
|
8898
|
+
return {
|
|
8899
|
+
label,
|
|
8900
|
+
color,
|
|
8901
|
+
target: groupMatch ? groupMatch[1].trim() : rawTarget,
|
|
8902
|
+
targetIsGroup: !!groupMatch
|
|
8903
|
+
};
|
|
8393
8904
|
}
|
|
8394
8905
|
return null;
|
|
8395
8906
|
}
|
|
@@ -8451,6 +8962,7 @@ function parseSitemap(content, palette) {
|
|
|
8451
8962
|
const aliasMap = /* @__PURE__ */ new Map();
|
|
8452
8963
|
const indentStack = [];
|
|
8453
8964
|
const labelToNode = /* @__PURE__ */ new Map();
|
|
8965
|
+
const labelToContainer = /* @__PURE__ */ new Map();
|
|
8454
8966
|
const deferredArrows = [];
|
|
8455
8967
|
for (let i = 0; i < lines.length; i++) {
|
|
8456
8968
|
const line10 = lines[i];
|
|
@@ -8552,6 +9064,7 @@ function parseSitemap(content, palette) {
|
|
|
8552
9064
|
deferredArrows.push({
|
|
8553
9065
|
sourceNode: source,
|
|
8554
9066
|
targetLabel: arrowInfo.target,
|
|
9067
|
+
targetIsGroup: arrowInfo.targetIsGroup,
|
|
8555
9068
|
label: arrowInfo.label,
|
|
8556
9069
|
color: arrowInfo.color,
|
|
8557
9070
|
lineNumber
|
|
@@ -8585,6 +9098,7 @@ function parseSitemap(content, palette) {
|
|
|
8585
9098
|
color
|
|
8586
9099
|
};
|
|
8587
9100
|
attachNode2(node, indent, indentStack, result);
|
|
9101
|
+
labelToContainer.set(label.toLowerCase(), node);
|
|
8588
9102
|
} else if (metadataMatch && indentStack.length > 0) {
|
|
8589
9103
|
const rawKey = metadataMatch[1].trim().toLowerCase();
|
|
8590
9104
|
const key = aliasMap.get(rawKey) ?? rawKey;
|
|
@@ -8625,22 +9139,41 @@ function parseSitemap(content, palette) {
|
|
|
8625
9139
|
}
|
|
8626
9140
|
for (const arrow of deferredArrows) {
|
|
8627
9141
|
const targetKey = arrow.targetLabel.toLowerCase();
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
9142
|
+
if (arrow.targetIsGroup) {
|
|
9143
|
+
const targetContainer = labelToContainer.get(targetKey);
|
|
9144
|
+
if (!targetContainer) {
|
|
9145
|
+
const allLabels = Array.from(labelToContainer.keys());
|
|
9146
|
+
let msg = `Group '[${arrow.targetLabel}]' not found`;
|
|
9147
|
+
const hint = suggest(targetKey, allLabels);
|
|
9148
|
+
if (hint) msg += `. ${hint}`;
|
|
9149
|
+
pushError(arrow.lineNumber, msg);
|
|
9150
|
+
continue;
|
|
9151
|
+
}
|
|
9152
|
+
result.edges.push({
|
|
9153
|
+
sourceId: arrow.sourceNode.id,
|
|
9154
|
+
targetId: targetContainer.id,
|
|
9155
|
+
label: arrow.label,
|
|
9156
|
+
color: arrow.color,
|
|
9157
|
+
lineNumber: arrow.lineNumber
|
|
9158
|
+
});
|
|
9159
|
+
} else {
|
|
9160
|
+
const targetNode = labelToNode.get(targetKey);
|
|
9161
|
+
if (!targetNode) {
|
|
9162
|
+
const allLabels = Array.from(labelToNode.keys());
|
|
9163
|
+
let msg = `Arrow target "${arrow.targetLabel}" not found`;
|
|
9164
|
+
const hint = suggest(targetKey, allLabels);
|
|
9165
|
+
if (hint) msg += `. ${hint}`;
|
|
9166
|
+
pushError(arrow.lineNumber, msg);
|
|
9167
|
+
continue;
|
|
9168
|
+
}
|
|
9169
|
+
result.edges.push({
|
|
9170
|
+
sourceId: arrow.sourceNode.id,
|
|
9171
|
+
targetId: targetNode.id,
|
|
9172
|
+
label: arrow.label,
|
|
9173
|
+
color: arrow.color,
|
|
9174
|
+
lineNumber: arrow.lineNumber
|
|
9175
|
+
});
|
|
8636
9176
|
}
|
|
8637
|
-
result.edges.push({
|
|
8638
|
-
sourceId: arrow.sourceNode.id,
|
|
8639
|
-
targetId: targetNode.id,
|
|
8640
|
-
label: arrow.label,
|
|
8641
|
-
color: arrow.color,
|
|
8642
|
-
lineNumber: arrow.lineNumber
|
|
8643
|
-
});
|
|
8644
9177
|
}
|
|
8645
9178
|
if (result.tagGroups.length > 0) {
|
|
8646
9179
|
const allNodes = [];
|
|
@@ -10354,6 +10887,7 @@ function parseBoxesAndLines(content) {
|
|
|
10354
10887
|
const nodeLabels = /* @__PURE__ */ new Set();
|
|
10355
10888
|
const groupLabels = /* @__PURE__ */ new Set();
|
|
10356
10889
|
let lastNodeLabel = null;
|
|
10890
|
+
let lastSourceIsGroup = false;
|
|
10357
10891
|
const groupStack = [];
|
|
10358
10892
|
let contentStarted = false;
|
|
10359
10893
|
let currentTagGroup = null;
|
|
@@ -10592,6 +11126,8 @@ function parseBoxesAndLines(content) {
|
|
|
10592
11126
|
};
|
|
10593
11127
|
groupLabels.add(label);
|
|
10594
11128
|
groupStack.push({ group, indent, depth: currentDepth });
|
|
11129
|
+
lastNodeLabel = label;
|
|
11130
|
+
lastSourceIsGroup = true;
|
|
10595
11131
|
continue;
|
|
10596
11132
|
}
|
|
10597
11133
|
if (trimmed.includes("->") || trimmed.includes("<->")) {
|
|
@@ -10609,7 +11145,8 @@ function parseBoxesAndLines(content) {
|
|
|
10609
11145
|
);
|
|
10610
11146
|
continue;
|
|
10611
11147
|
}
|
|
10612
|
-
|
|
11148
|
+
const sourcePrefix = lastSourceIsGroup ? `[${lastNodeLabel}]` : lastNodeLabel;
|
|
11149
|
+
edgeText = `${sourcePrefix} ${trimmed}`;
|
|
10613
11150
|
}
|
|
10614
11151
|
const edge = parseEdgeLine(
|
|
10615
11152
|
edgeText,
|
|
@@ -10632,6 +11169,7 @@ function parseBoxesAndLines(content) {
|
|
|
10632
11169
|
continue;
|
|
10633
11170
|
}
|
|
10634
11171
|
lastNodeLabel = node.label;
|
|
11172
|
+
lastSourceIsGroup = false;
|
|
10635
11173
|
const gs = currentGroupState();
|
|
10636
11174
|
const isGroupChild = gs && indent > gs.indent;
|
|
10637
11175
|
if (nodeLabels.has(node.label)) {
|
|
@@ -10659,14 +11197,42 @@ function parseBoxesAndLines(content) {
|
|
|
10659
11197
|
const gs = groupStack.pop();
|
|
10660
11198
|
result.groups.push(gs.group);
|
|
10661
11199
|
}
|
|
11200
|
+
const validEdges = [];
|
|
10662
11201
|
for (const edge of result.edges) {
|
|
10663
|
-
|
|
11202
|
+
let valid = true;
|
|
11203
|
+
if (edge.source.startsWith("__group_")) {
|
|
11204
|
+
const label = edge.source.slice("__group_".length);
|
|
11205
|
+
const found = [...groupLabels].some(
|
|
11206
|
+
(g) => g.toLowerCase() === label.toLowerCase()
|
|
11207
|
+
);
|
|
11208
|
+
if (!found) {
|
|
11209
|
+
result.diagnostics.push(
|
|
11210
|
+
makeDgmoError(edge.lineNumber, `Group '[${label}]' not found`)
|
|
11211
|
+
);
|
|
11212
|
+
valid = false;
|
|
11213
|
+
}
|
|
11214
|
+
} else {
|
|
10664
11215
|
ensureNode(edge.source, edge.lineNumber);
|
|
10665
11216
|
}
|
|
10666
|
-
if (
|
|
11217
|
+
if (edge.target.startsWith("__group_")) {
|
|
11218
|
+
const label = edge.target.slice("__group_".length);
|
|
11219
|
+
const found = [...groupLabels].some(
|
|
11220
|
+
(g) => g.toLowerCase() === label.toLowerCase()
|
|
11221
|
+
);
|
|
11222
|
+
if (!found) {
|
|
11223
|
+
result.diagnostics.push(
|
|
11224
|
+
makeDgmoError(edge.lineNumber, `Group '[${label}]' not found`)
|
|
11225
|
+
);
|
|
11226
|
+
valid = false;
|
|
11227
|
+
}
|
|
11228
|
+
} else {
|
|
10667
11229
|
ensureNode(edge.target, edge.lineNumber);
|
|
10668
11230
|
}
|
|
11231
|
+
if (valid) {
|
|
11232
|
+
validEdges.push(edge);
|
|
11233
|
+
}
|
|
10669
11234
|
}
|
|
11235
|
+
result.edges = validEdges;
|
|
10670
11236
|
if (result.tagGroups.length > 0) {
|
|
10671
11237
|
injectDefaultTagMetadata(result.nodes, result.tagGroups);
|
|
10672
11238
|
validateTagValues(result.nodes, result.tagGroups, pushWarning, suggest);
|
|
@@ -10695,10 +11261,14 @@ function parseNodeLine(trimmed, lineNum, aliasMap, _diagnostics) {
|
|
|
10695
11261
|
description
|
|
10696
11262
|
};
|
|
10697
11263
|
}
|
|
11264
|
+
function resolveEndpoint(name) {
|
|
11265
|
+
const m = name.match(/^\[(.+)\]$/);
|
|
11266
|
+
return m ? groupId2(m[1].trim()) : name;
|
|
11267
|
+
}
|
|
10698
11268
|
function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
10699
11269
|
const biLabeledMatch = trimmed.match(/^(.+?)\s*<-(.+)->\s*(.+)$/);
|
|
10700
11270
|
if (biLabeledMatch) {
|
|
10701
|
-
const source2 = biLabeledMatch[1].trim();
|
|
11271
|
+
const source2 = resolveEndpoint(biLabeledMatch[1].trim());
|
|
10702
11272
|
const label = biLabeledMatch[2].trim();
|
|
10703
11273
|
let rest2 = biLabeledMatch[3].trim();
|
|
10704
11274
|
let metadata2 = {};
|
|
@@ -10719,7 +11289,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10719
11289
|
}
|
|
10720
11290
|
return {
|
|
10721
11291
|
source: source2,
|
|
10722
|
-
target: rest2,
|
|
11292
|
+
target: resolveEndpoint(rest2),
|
|
10723
11293
|
label: label || void 0,
|
|
10724
11294
|
bidirectional: true,
|
|
10725
11295
|
lineNumber: lineNum,
|
|
@@ -10728,7 +11298,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10728
11298
|
}
|
|
10729
11299
|
const biIdx = trimmed.indexOf("<->");
|
|
10730
11300
|
if (biIdx >= 0) {
|
|
10731
|
-
const source2 = trimmed.slice(0, biIdx).trim();
|
|
11301
|
+
const source2 = resolveEndpoint(trimmed.slice(0, biIdx).trim());
|
|
10732
11302
|
let rest2 = trimmed.slice(biIdx + 3).trim();
|
|
10733
11303
|
let metadata2 = {};
|
|
10734
11304
|
const pipeIdx2 = rest2.indexOf("|");
|
|
@@ -10748,7 +11318,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10748
11318
|
}
|
|
10749
11319
|
return {
|
|
10750
11320
|
source: source2,
|
|
10751
|
-
target: rest2,
|
|
11321
|
+
target: resolveEndpoint(rest2),
|
|
10752
11322
|
bidirectional: true,
|
|
10753
11323
|
lineNumber: lineNum,
|
|
10754
11324
|
metadata: metadata2
|
|
@@ -10756,7 +11326,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10756
11326
|
}
|
|
10757
11327
|
const labeledMatch = trimmed.match(/^(.+?)\s+-(.+)->\s*(.+)$/);
|
|
10758
11328
|
if (labeledMatch) {
|
|
10759
|
-
const source2 = labeledMatch[1].trim();
|
|
11329
|
+
const source2 = resolveEndpoint(labeledMatch[1].trim());
|
|
10760
11330
|
const label = labeledMatch[2].trim();
|
|
10761
11331
|
let rest2 = labeledMatch[3].trim();
|
|
10762
11332
|
if (label) {
|
|
@@ -10778,7 +11348,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10778
11348
|
}
|
|
10779
11349
|
return {
|
|
10780
11350
|
source: source2,
|
|
10781
|
-
target: rest2,
|
|
11351
|
+
target: resolveEndpoint(rest2),
|
|
10782
11352
|
label,
|
|
10783
11353
|
bidirectional: false,
|
|
10784
11354
|
lineNumber: lineNum,
|
|
@@ -10788,7 +11358,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10788
11358
|
}
|
|
10789
11359
|
const arrowIdx = trimmed.indexOf("->");
|
|
10790
11360
|
if (arrowIdx < 0) return null;
|
|
10791
|
-
const source = trimmed.slice(0, arrowIdx).trim();
|
|
11361
|
+
const source = resolveEndpoint(trimmed.slice(0, arrowIdx).trim());
|
|
10792
11362
|
let rest = trimmed.slice(arrowIdx + 2).trim();
|
|
10793
11363
|
if (!source || !rest) {
|
|
10794
11364
|
diagnostics.push(
|
|
@@ -10809,7 +11379,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10809
11379
|
}
|
|
10810
11380
|
return {
|
|
10811
11381
|
source,
|
|
10812
|
-
target: rest,
|
|
11382
|
+
target: resolveEndpoint(rest),
|
|
10813
11383
|
bidirectional: false,
|
|
10814
11384
|
lineNumber: lineNum,
|
|
10815
11385
|
metadata
|
|
@@ -11123,14 +11693,14 @@ function computeLegendGroups(tagGroups, showEyeIcons, usedValuesByGroup) {
|
|
|
11123
11693
|
const usedValues = usedValuesByGroup?.get(group.name.toLowerCase());
|
|
11124
11694
|
const visibleEntries = usedValues ? group.entries.filter((e) => usedValues.has(e.value.toLowerCase())) : group.entries;
|
|
11125
11695
|
if (visibleEntries.length === 0) continue;
|
|
11126
|
-
const
|
|
11127
|
-
const minPillWidth =
|
|
11128
|
-
let
|
|
11696
|
+
const pillWidth3 = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD2;
|
|
11697
|
+
const minPillWidth = pillWidth3;
|
|
11698
|
+
let entriesWidth3 = 0;
|
|
11129
11699
|
for (const entry of visibleEntries) {
|
|
11130
|
-
|
|
11700
|
+
entriesWidth3 += LEGEND_DOT_R2 * 2 + LEGEND_ENTRY_DOT_GAP2 + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL2;
|
|
11131
11701
|
}
|
|
11132
11702
|
const eyeSpace = showEyeIcons ? LEGEND_EYE_SIZE2 + LEGEND_EYE_GAP2 : 0;
|
|
11133
|
-
const
|
|
11703
|
+
const capsuleWidth2 = LEGEND_CAPSULE_PAD2 * 2 + pillWidth3 + 4 + eyeSpace + entriesWidth3;
|
|
11134
11704
|
groups.push({
|
|
11135
11705
|
name: group.name,
|
|
11136
11706
|
alias: group.alias,
|
|
@@ -11140,7 +11710,7 @@ function computeLegendGroups(tagGroups, showEyeIcons, usedValuesByGroup) {
|
|
|
11140
11710
|
})),
|
|
11141
11711
|
x: 0,
|
|
11142
11712
|
y: 0,
|
|
11143
|
-
width:
|
|
11713
|
+
width: capsuleWidth2,
|
|
11144
11714
|
height: LEGEND_HEIGHT2,
|
|
11145
11715
|
minifiedWidth: minPillWidth,
|
|
11146
11716
|
minifiedHeight: LEGEND_HEIGHT2
|
|
@@ -12081,66 +12651,77 @@ function renderOrg(container, parsed, layout, palette, isDark, onClickItem, expo
|
|
|
12081
12651
|
}
|
|
12082
12652
|
}
|
|
12083
12653
|
if (fixedLegend || legendOnly || exportDims && hasLegend) {
|
|
12084
|
-
const
|
|
12085
|
-
|
|
12086
|
-
|
|
12087
|
-
|
|
12088
|
-
|
|
12089
|
-
|
|
12090
|
-
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
|
|
12094
|
-
|
|
12095
|
-
|
|
12096
|
-
|
|
12097
|
-
|
|
12098
|
-
|
|
12099
|
-
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
|
|
12103
|
-
|
|
12654
|
+
const groups = layout.legend.map((g) => ({
|
|
12655
|
+
name: g.name,
|
|
12656
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
12657
|
+
}));
|
|
12658
|
+
const eyeAddonWidth = fixedLegend ? LEGEND_EYE_SIZE + LEGEND_EYE_GAP : 0;
|
|
12659
|
+
const legendParentBase = fixedLegend ? svg.append("g").attr("class", "org-legend-fixed").attr("transform", `translate(0, ${DIAGRAM_PADDING + titleReserve})`) : contentG.append("g");
|
|
12660
|
+
let legendHandle;
|
|
12661
|
+
if (legendOnly) {
|
|
12662
|
+
for (const lg of layout.legend) {
|
|
12663
|
+
const singleConfig = {
|
|
12664
|
+
groups: [
|
|
12665
|
+
{
|
|
12666
|
+
name: lg.name,
|
|
12667
|
+
entries: lg.entries.map((e) => ({
|
|
12668
|
+
value: e.value,
|
|
12669
|
+
color: e.color
|
|
12670
|
+
}))
|
|
12671
|
+
}
|
|
12672
|
+
],
|
|
12673
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
12674
|
+
mode: "fixed"
|
|
12675
|
+
};
|
|
12676
|
+
const singleState = { activeGroup: lg.name };
|
|
12677
|
+
const groupG = legendParentBase.append("g").attr("transform", `translate(${lg.x}, ${lg.y})`);
|
|
12678
|
+
renderLegendD3(
|
|
12679
|
+
groupG,
|
|
12680
|
+
singleConfig,
|
|
12681
|
+
singleState,
|
|
12682
|
+
palette,
|
|
12683
|
+
isDark,
|
|
12684
|
+
void 0,
|
|
12685
|
+
lg.width
|
|
12686
|
+
);
|
|
12687
|
+
groupG.selectAll("[data-legend-group]").classed("org-legend-group", true);
|
|
12688
|
+
}
|
|
12689
|
+
legendHandle = null;
|
|
12690
|
+
} else {
|
|
12691
|
+
const legendConfig = {
|
|
12692
|
+
groups,
|
|
12693
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
12694
|
+
mode: "fixed",
|
|
12695
|
+
capsulePillAddonWidth: eyeAddonWidth
|
|
12696
|
+
};
|
|
12697
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
12698
|
+
legendHandle = renderLegendD3(
|
|
12699
|
+
legendParentBase,
|
|
12700
|
+
legendConfig,
|
|
12701
|
+
legendState,
|
|
12702
|
+
palette,
|
|
12703
|
+
isDark,
|
|
12704
|
+
void 0,
|
|
12705
|
+
fixedLegend ? width : layout.width
|
|
12706
|
+
);
|
|
12707
|
+
legendParentBase.selectAll("[data-legend-group]").classed("org-legend-group", true);
|
|
12104
12708
|
}
|
|
12105
|
-
|
|
12106
|
-
const
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
const gX = fixedPositions?.get(group.name) ?? group.x;
|
|
12111
|
-
const gY = fixedPositions ? 0 : group.y;
|
|
12112
|
-
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");
|
|
12113
|
-
if (isActive) {
|
|
12114
|
-
gEl.append("rect").attr("width", group.width).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
12115
|
-
}
|
|
12116
|
-
const pillXOff = isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
12117
|
-
const pillYOff = LEGEND_CAPSULE_PAD;
|
|
12118
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
12119
|
-
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);
|
|
12120
|
-
if (isActive) {
|
|
12121
|
-
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);
|
|
12122
|
-
}
|
|
12123
|
-
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);
|
|
12124
|
-
if (isActive && fixedLegend) {
|
|
12125
|
-
const groupKey = group.name.toLowerCase();
|
|
12709
|
+
if (fixedLegend && legendHandle) {
|
|
12710
|
+
const computedLayout = legendHandle.getLayout();
|
|
12711
|
+
if (computedLayout.activeCapsule?.addonX != null) {
|
|
12712
|
+
const capsule = computedLayout.activeCapsule;
|
|
12713
|
+
const groupKey = capsule.groupName.toLowerCase();
|
|
12126
12714
|
const isHidden = hiddenAttributes?.has(groupKey) ?? false;
|
|
12127
|
-
const
|
|
12128
|
-
|
|
12129
|
-
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
|
|
12137
|
-
for (const entry of group.entries) {
|
|
12138
|
-
const entryG = gEl.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
12139
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
12140
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
12141
|
-
const entryLabel = entry.value;
|
|
12142
|
-
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);
|
|
12143
|
-
entryX = textX + measureLegendText(entryLabel, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
12715
|
+
const activeGroupEl = legendParentBase.select(
|
|
12716
|
+
`[data-legend-group="${groupKey}"]`
|
|
12717
|
+
);
|
|
12718
|
+
if (!activeGroupEl.empty()) {
|
|
12719
|
+
const eyeX = capsule.addonX;
|
|
12720
|
+
const eyeY = (LEGEND_HEIGHT - LEGEND_EYE_SIZE) / 2;
|
|
12721
|
+
const hitPad = 6;
|
|
12722
|
+
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);
|
|
12723
|
+
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");
|
|
12724
|
+
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");
|
|
12144
12725
|
}
|
|
12145
12726
|
}
|
|
12146
12727
|
}
|
|
@@ -12175,6 +12756,7 @@ var init_renderer = __esm({
|
|
|
12175
12756
|
init_parser4();
|
|
12176
12757
|
init_layout();
|
|
12177
12758
|
init_legend_constants();
|
|
12759
|
+
init_legend_d3();
|
|
12178
12760
|
init_title_constants();
|
|
12179
12761
|
DIAGRAM_PADDING = 20;
|
|
12180
12762
|
MAX_SCALE = 3;
|
|
@@ -12203,6 +12785,17 @@ var layout_exports2 = {};
|
|
|
12203
12785
|
__export(layout_exports2, {
|
|
12204
12786
|
layoutSitemap: () => layoutSitemap
|
|
12205
12787
|
});
|
|
12788
|
+
function clipToRectBorder(cx, cy, w, h, tx, ty) {
|
|
12789
|
+
const dx = tx - cx;
|
|
12790
|
+
const dy = ty - cy;
|
|
12791
|
+
if (dx === 0 && dy === 0) return { x: cx, y: cy };
|
|
12792
|
+
const hw = w / 2;
|
|
12793
|
+
const hh = h / 2;
|
|
12794
|
+
const sx = dx !== 0 ? hw / Math.abs(dx) : Infinity;
|
|
12795
|
+
const sy = dy !== 0 ? hh / Math.abs(dy) : Infinity;
|
|
12796
|
+
const s = Math.min(sx, sy);
|
|
12797
|
+
return { x: cx + dx * s, y: cy + dy * s };
|
|
12798
|
+
}
|
|
12206
12799
|
function filterMetadata2(metadata, hiddenAttributes) {
|
|
12207
12800
|
if (!hiddenAttributes || hiddenAttributes.size === 0) return metadata;
|
|
12208
12801
|
const filtered = {};
|
|
@@ -12219,7 +12812,10 @@ function computeCardWidth2(label, meta) {
|
|
|
12219
12812
|
const lineChars = key.length + 2 + value.length;
|
|
12220
12813
|
if (lineChars > maxChars) maxChars = lineChars;
|
|
12221
12814
|
}
|
|
12222
|
-
return Math.max(
|
|
12815
|
+
return Math.max(
|
|
12816
|
+
MIN_CARD_WIDTH2,
|
|
12817
|
+
Math.ceil(maxChars * CHAR_WIDTH2) + CARD_H_PAD2 * 2
|
|
12818
|
+
);
|
|
12223
12819
|
}
|
|
12224
12820
|
function computeCardHeight2(meta) {
|
|
12225
12821
|
const metaCount = Object.keys(meta).length;
|
|
@@ -12228,7 +12824,12 @@ function computeCardHeight2(meta) {
|
|
|
12228
12824
|
}
|
|
12229
12825
|
function resolveNodeColor2(node, tagGroups, activeGroupName) {
|
|
12230
12826
|
if (node.color) return node.color;
|
|
12231
|
-
return resolveTagColor(
|
|
12827
|
+
return resolveTagColor(
|
|
12828
|
+
node.metadata,
|
|
12829
|
+
tagGroups,
|
|
12830
|
+
activeGroupName,
|
|
12831
|
+
node.isContainer
|
|
12832
|
+
);
|
|
12232
12833
|
}
|
|
12233
12834
|
function computeLegendGroups2(tagGroups, usedValuesByGroup) {
|
|
12234
12835
|
const groups = [];
|
|
@@ -12237,21 +12838,21 @@ function computeLegendGroups2(tagGroups, usedValuesByGroup) {
|
|
|
12237
12838
|
const usedValues = usedValuesByGroup?.get(group.name.toLowerCase());
|
|
12238
12839
|
const visibleEntries = usedValues ? group.entries.filter((e) => usedValues.has(e.value.toLowerCase())) : group.entries;
|
|
12239
12840
|
if (visibleEntries.length === 0) continue;
|
|
12240
|
-
const
|
|
12241
|
-
const minPillWidth =
|
|
12242
|
-
let
|
|
12841
|
+
const pillWidth3 = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD3;
|
|
12842
|
+
const minPillWidth = pillWidth3;
|
|
12843
|
+
let entriesWidth3 = 0;
|
|
12243
12844
|
for (const entry of visibleEntries) {
|
|
12244
|
-
|
|
12845
|
+
entriesWidth3 += LEGEND_DOT_R3 * 2 + LEGEND_ENTRY_DOT_GAP3 + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL3;
|
|
12245
12846
|
}
|
|
12246
12847
|
const eyeSpace = LEGEND_EYE_SIZE3 + LEGEND_EYE_GAP3;
|
|
12247
|
-
const
|
|
12848
|
+
const capsuleWidth2 = LEGEND_CAPSULE_PAD3 * 2 + pillWidth3 + 4 + eyeSpace + entriesWidth3;
|
|
12248
12849
|
groups.push({
|
|
12249
12850
|
name: group.name,
|
|
12250
12851
|
alias: group.alias,
|
|
12251
12852
|
entries: visibleEntries.map((e) => ({ value: e.value, color: e.color })),
|
|
12252
12853
|
x: 0,
|
|
12253
12854
|
y: 0,
|
|
12254
|
-
width:
|
|
12855
|
+
width: capsuleWidth2,
|
|
12255
12856
|
height: LEGEND_HEIGHT3,
|
|
12256
12857
|
minifiedWidth: minPillWidth,
|
|
12257
12858
|
minifiedHeight: LEGEND_HEIGHT3
|
|
@@ -12271,10 +12872,20 @@ function flattenNodes(nodes, parentContainerId, parentPageId, hiddenCounts, hidd
|
|
|
12271
12872
|
parentPageId,
|
|
12272
12873
|
meta,
|
|
12273
12874
|
fullMeta: { ...node.metadata },
|
|
12274
|
-
width: Math.max(
|
|
12875
|
+
width: Math.max(
|
|
12876
|
+
MIN_CARD_WIDTH2,
|
|
12877
|
+
node.label.length * CHAR_WIDTH2 + CARD_H_PAD2 * 2
|
|
12878
|
+
),
|
|
12275
12879
|
height: labelHeight + CONTAINER_PAD_BOTTOM2
|
|
12276
12880
|
});
|
|
12277
|
-
flattenNodes(
|
|
12881
|
+
flattenNodes(
|
|
12882
|
+
node.children,
|
|
12883
|
+
node.id,
|
|
12884
|
+
parentPageId,
|
|
12885
|
+
hiddenCounts,
|
|
12886
|
+
hiddenAttributes,
|
|
12887
|
+
result
|
|
12888
|
+
);
|
|
12278
12889
|
} else {
|
|
12279
12890
|
result.push({
|
|
12280
12891
|
sitemapNode: node,
|
|
@@ -12286,14 +12897,28 @@ function flattenNodes(nodes, parentContainerId, parentPageId, hiddenCounts, hidd
|
|
|
12286
12897
|
height: computeCardHeight2(meta)
|
|
12287
12898
|
});
|
|
12288
12899
|
if (node.children.length > 0) {
|
|
12289
|
-
flattenNodes(
|
|
12900
|
+
flattenNodes(
|
|
12901
|
+
node.children,
|
|
12902
|
+
parentContainerId,
|
|
12903
|
+
node.id,
|
|
12904
|
+
hiddenCounts,
|
|
12905
|
+
hiddenAttributes,
|
|
12906
|
+
result
|
|
12907
|
+
);
|
|
12290
12908
|
}
|
|
12291
12909
|
}
|
|
12292
12910
|
}
|
|
12293
12911
|
}
|
|
12294
12912
|
function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, expandAllLegend) {
|
|
12295
12913
|
if (parsed.roots.length === 0) {
|
|
12296
|
-
return {
|
|
12914
|
+
return {
|
|
12915
|
+
nodes: [],
|
|
12916
|
+
edges: [],
|
|
12917
|
+
containers: [],
|
|
12918
|
+
legend: [],
|
|
12919
|
+
width: 0,
|
|
12920
|
+
height: 0
|
|
12921
|
+
};
|
|
12297
12922
|
}
|
|
12298
12923
|
const allNodes = [];
|
|
12299
12924
|
const collect = (node) => {
|
|
@@ -12301,9 +12926,20 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12301
12926
|
for (const child of node.children) collect(child);
|
|
12302
12927
|
};
|
|
12303
12928
|
for (const root of parsed.roots) collect(root);
|
|
12304
|
-
injectDefaultTagMetadata(
|
|
12929
|
+
injectDefaultTagMetadata(
|
|
12930
|
+
allNodes,
|
|
12931
|
+
parsed.tagGroups,
|
|
12932
|
+
(e) => e.isContainer
|
|
12933
|
+
);
|
|
12305
12934
|
const flatNodes = [];
|
|
12306
|
-
flattenNodes(
|
|
12935
|
+
flattenNodes(
|
|
12936
|
+
parsed.roots,
|
|
12937
|
+
null,
|
|
12938
|
+
null,
|
|
12939
|
+
hiddenCounts,
|
|
12940
|
+
hiddenAttributes,
|
|
12941
|
+
flatNodes
|
|
12942
|
+
);
|
|
12307
12943
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
12308
12944
|
for (const flat of flatNodes) {
|
|
12309
12945
|
nodeMap.set(flat.sitemapNode.id, flat);
|
|
@@ -12365,14 +13001,29 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12365
13001
|
g.setParent(flat.sitemapNode.id, flat.parentContainerId);
|
|
12366
13002
|
}
|
|
12367
13003
|
}
|
|
13004
|
+
const expandedContainerIds = /* @__PURE__ */ new Set();
|
|
13005
|
+
for (const cid of containerIds) {
|
|
13006
|
+
if (!collapsedContainerIds.has(cid)) {
|
|
13007
|
+
expandedContainerIds.add(cid);
|
|
13008
|
+
}
|
|
13009
|
+
}
|
|
13010
|
+
const deferredEdgeIndices = [];
|
|
12368
13011
|
for (let i = 0; i < parsed.edges.length; i++) {
|
|
12369
13012
|
const edge = parsed.edges[i];
|
|
12370
|
-
if (g.hasNode(edge.sourceId)
|
|
12371
|
-
|
|
13013
|
+
if (!g.hasNode(edge.sourceId) || !g.hasNode(edge.targetId)) continue;
|
|
13014
|
+
if (expandedContainerIds.has(edge.sourceId) || expandedContainerIds.has(edge.targetId)) {
|
|
13015
|
+
deferredEdgeIndices.push(i);
|
|
13016
|
+
continue;
|
|
13017
|
+
}
|
|
13018
|
+
g.setEdge(
|
|
13019
|
+
edge.sourceId,
|
|
13020
|
+
edge.targetId,
|
|
13021
|
+
{
|
|
12372
13022
|
label: edge.label ?? "",
|
|
12373
13023
|
minlen: 1
|
|
12374
|
-
},
|
|
12375
|
-
|
|
13024
|
+
},
|
|
13025
|
+
`e${i}`
|
|
13026
|
+
);
|
|
12376
13027
|
}
|
|
12377
13028
|
import_dagre.default.layout(g);
|
|
12378
13029
|
const layoutNodes = [];
|
|
@@ -12440,19 +13091,52 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12440
13091
|
});
|
|
12441
13092
|
}
|
|
12442
13093
|
}
|
|
13094
|
+
const deferredSet = new Set(deferredEdgeIndices);
|
|
12443
13095
|
const layoutEdges = [];
|
|
12444
13096
|
for (let i = 0; i < parsed.edges.length; i++) {
|
|
12445
13097
|
const edge = parsed.edges[i];
|
|
12446
13098
|
if (!g.hasNode(edge.sourceId) || !g.hasNode(edge.targetId)) continue;
|
|
12447
|
-
|
|
12448
|
-
if (
|
|
13099
|
+
let points;
|
|
13100
|
+
if (deferredSet.has(i)) {
|
|
13101
|
+
const srcNode = g.node(edge.sourceId);
|
|
13102
|
+
const tgtNode = g.node(edge.targetId);
|
|
13103
|
+
if (!srcNode || !tgtNode) continue;
|
|
13104
|
+
const srcPt = clipToRectBorder(
|
|
13105
|
+
srcNode.x,
|
|
13106
|
+
srcNode.y,
|
|
13107
|
+
srcNode.width,
|
|
13108
|
+
srcNode.height,
|
|
13109
|
+
tgtNode.x,
|
|
13110
|
+
tgtNode.y
|
|
13111
|
+
);
|
|
13112
|
+
const tgtPt = clipToRectBorder(
|
|
13113
|
+
tgtNode.x,
|
|
13114
|
+
tgtNode.y,
|
|
13115
|
+
tgtNode.width,
|
|
13116
|
+
tgtNode.height,
|
|
13117
|
+
srcNode.x,
|
|
13118
|
+
srcNode.y
|
|
13119
|
+
);
|
|
13120
|
+
const midX = (srcPt.x + tgtPt.x) / 2;
|
|
13121
|
+
const midY = (srcPt.y + tgtPt.y) / 2;
|
|
13122
|
+
points = [srcPt, { x: midX, y: midY }, tgtPt];
|
|
13123
|
+
} else {
|
|
13124
|
+
const edgeData = g.edge({
|
|
13125
|
+
v: edge.sourceId,
|
|
13126
|
+
w: edge.targetId,
|
|
13127
|
+
name: `e${i}`
|
|
13128
|
+
});
|
|
13129
|
+
if (!edgeData) continue;
|
|
13130
|
+
points = edgeData.points ?? [];
|
|
13131
|
+
}
|
|
12449
13132
|
layoutEdges.push({
|
|
12450
13133
|
sourceId: edge.sourceId,
|
|
12451
13134
|
targetId: edge.targetId,
|
|
12452
|
-
points
|
|
13135
|
+
points,
|
|
12453
13136
|
label: edge.label,
|
|
12454
13137
|
color: edge.color,
|
|
12455
|
-
lineNumber: edge.lineNumber
|
|
13138
|
+
lineNumber: edge.lineNumber,
|
|
13139
|
+
deferred: deferredSet.has(i) || void 0
|
|
12456
13140
|
});
|
|
12457
13141
|
}
|
|
12458
13142
|
{
|
|
@@ -12613,7 +13297,9 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12613
13297
|
usedValuesByGroup.set(key, used);
|
|
12614
13298
|
}
|
|
12615
13299
|
const legendGroups = computeLegendGroups2(parsed.tagGroups, usedValuesByGroup);
|
|
12616
|
-
const visibleGroups = activeTagGroup != null ? legendGroups.filter(
|
|
13300
|
+
const visibleGroups = activeTagGroup != null ? legendGroups.filter(
|
|
13301
|
+
(g2) => g2.name.toLowerCase() === activeTagGroup.toLowerCase()
|
|
13302
|
+
) : legendGroups;
|
|
12617
13303
|
const allExpanded = expandAllLegend && activeTagGroup == null;
|
|
12618
13304
|
const effectiveW = (g2) => activeTagGroup != null || allExpanded ? g2.width : g2.minifiedWidth;
|
|
12619
13305
|
if (visibleGroups.length > 0) {
|
|
@@ -12928,7 +13614,8 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
12928
13614
|
const edgeG = contentG.append("g").attr("class", "sitemap-edge-group").attr("data-line-number", String(edge.lineNumber));
|
|
12929
13615
|
const edgeColor3 = edge.color ?? palette.textMuted;
|
|
12930
13616
|
const markerId = edge.color ? `sm-arrow-${edge.color.replace("#", "")}` : "sm-arrow";
|
|
12931
|
-
const
|
|
13617
|
+
const gen = edge.deferred ? lineGeneratorLinear : lineGenerator;
|
|
13618
|
+
const pathD = gen(edge.points);
|
|
12932
13619
|
if (pathD) {
|
|
12933
13620
|
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");
|
|
12934
13621
|
}
|
|
@@ -13019,57 +13706,44 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
13019
13706
|
}
|
|
13020
13707
|
function renderLegend(parent, legendGroups, palette, isDark, activeTagGroup, fixedWidth, hiddenAttributes) {
|
|
13021
13708
|
if (legendGroups.length === 0) return;
|
|
13022
|
-
const
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
|
|
13026
|
-
|
|
13027
|
-
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
|
|
13046
|
-
|
|
13047
|
-
const
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13051
|
-
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);
|
|
13052
|
-
}
|
|
13053
|
-
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);
|
|
13054
|
-
if (isActive && fixedWidth != null) {
|
|
13055
|
-
const groupKey = group.name.toLowerCase();
|
|
13709
|
+
const groups = legendGroups.map((g) => ({
|
|
13710
|
+
name: g.name,
|
|
13711
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
13712
|
+
}));
|
|
13713
|
+
const isFixedMode = fixedWidth != null;
|
|
13714
|
+
const eyeAddonWidth = isFixedMode ? LEGEND_EYE_SIZE + LEGEND_EYE_GAP : 0;
|
|
13715
|
+
const legendConfig = {
|
|
13716
|
+
groups,
|
|
13717
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
13718
|
+
mode: "fixed",
|
|
13719
|
+
capsulePillAddonWidth: eyeAddonWidth
|
|
13720
|
+
};
|
|
13721
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
13722
|
+
const containerWidth = fixedWidth ?? legendGroups[0]?.x + (legendGroups[0]?.width ?? 200);
|
|
13723
|
+
const legendHandle = renderLegendD3(
|
|
13724
|
+
parent,
|
|
13725
|
+
legendConfig,
|
|
13726
|
+
legendState,
|
|
13727
|
+
palette,
|
|
13728
|
+
isDark,
|
|
13729
|
+
void 0,
|
|
13730
|
+
containerWidth
|
|
13731
|
+
);
|
|
13732
|
+
parent.selectAll("[data-legend-group]").classed("sitemap-legend-group", true);
|
|
13733
|
+
if (isFixedMode) {
|
|
13734
|
+
const computedLayout = legendHandle.getLayout();
|
|
13735
|
+
if (computedLayout.activeCapsule?.addonX != null) {
|
|
13736
|
+
const capsule = computedLayout.activeCapsule;
|
|
13737
|
+
const groupKey = capsule.groupName.toLowerCase();
|
|
13056
13738
|
const isHidden = hiddenAttributes?.has(groupKey) ?? false;
|
|
13057
|
-
const
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
|
|
13061
|
-
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
const eyeShift = fixedWidth != null ? LEGEND_EYE_SIZE + LEGEND_EYE_GAP : 0;
|
|
13066
|
-
let entryX = pillXOff + pillW + 4 + eyeShift;
|
|
13067
|
-
for (const entry of group.entries) {
|
|
13068
|
-
const entryG = legendG.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
13069
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
13070
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
13071
|
-
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);
|
|
13072
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
13739
|
+
const activeGroupEl = parent.select(`[data-legend-group="${groupKey}"]`);
|
|
13740
|
+
if (!activeGroupEl.empty()) {
|
|
13741
|
+
const eyeX = capsule.addonX;
|
|
13742
|
+
const eyeY = (LEGEND_HEIGHT - LEGEND_EYE_SIZE) / 2;
|
|
13743
|
+
const hitPad = 6;
|
|
13744
|
+
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);
|
|
13745
|
+
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");
|
|
13746
|
+
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");
|
|
13073
13747
|
}
|
|
13074
13748
|
}
|
|
13075
13749
|
}
|
|
@@ -13123,7 +13797,7 @@ async function renderSitemapForExport(content, theme, palette) {
|
|
|
13123
13797
|
const brandColor = theme === "transparent" ? "#888" : effectivePalette.textMuted;
|
|
13124
13798
|
return injectBranding2(svgHtml, brandColor);
|
|
13125
13799
|
}
|
|
13126
|
-
var d3Selection2, d3Shape, 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;
|
|
13800
|
+
var d3Selection2, d3Shape, 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;
|
|
13127
13801
|
var init_renderer2 = __esm({
|
|
13128
13802
|
"src/sitemap/renderer.ts"() {
|
|
13129
13803
|
"use strict";
|
|
@@ -13132,6 +13806,7 @@ var init_renderer2 = __esm({
|
|
|
13132
13806
|
init_fonts();
|
|
13133
13807
|
init_color_utils();
|
|
13134
13808
|
init_legend_constants();
|
|
13809
|
+
init_legend_d3();
|
|
13135
13810
|
init_title_constants();
|
|
13136
13811
|
DIAGRAM_PADDING2 = 20;
|
|
13137
13812
|
MAX_SCALE2 = 3;
|
|
@@ -13155,6 +13830,7 @@ var init_renderer2 = __esm({
|
|
|
13155
13830
|
COLLAPSE_BAR_HEIGHT2 = 6;
|
|
13156
13831
|
LEGEND_FIXED_GAP2 = 8;
|
|
13157
13832
|
lineGenerator = d3Shape.line().x((d) => d.x).y((d) => d.y).curve(d3Shape.curveBasis);
|
|
13833
|
+
lineGeneratorLinear = d3Shape.line().x((d) => d.x).y((d) => d.y).curve(d3Shape.curveLinear);
|
|
13158
13834
|
}
|
|
13159
13835
|
});
|
|
13160
13836
|
|
|
@@ -13431,53 +14107,22 @@ function renderKanban(container, parsed, palette, isDark, _onNavigateToLine, exp
|
|
|
13431
14107
|
}
|
|
13432
14108
|
if (parsed.tagGroups.length > 0) {
|
|
13433
14109
|
const legendY = height - LEGEND_HEIGHT;
|
|
13434
|
-
|
|
13435
|
-
|
|
13436
|
-
|
|
13437
|
-
|
|
13438
|
-
|
|
13439
|
-
|
|
13440
|
-
}
|
|
13441
|
-
|
|
13442
|
-
|
|
13443
|
-
|
|
13444
|
-
|
|
13445
|
-
|
|
13446
|
-
|
|
13447
|
-
|
|
13448
|
-
|
|
13449
|
-
|
|
13450
|
-
capsuleContentWidth += LEGEND_DOT_R * 2 + 4 + entry.value.length * LEGEND_ENTRY_FONT_SIZE * 0.6 + 8;
|
|
13451
|
-
}
|
|
13452
|
-
}
|
|
13453
|
-
const capsuleWidth = capsuleContentWidth + capsulePad * 2;
|
|
13454
|
-
if (isActive) {
|
|
13455
|
-
legendContainer.append("rect").attr("x", legendX).attr("y", legendY).attr("width", capsuleWidth).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
13456
|
-
}
|
|
13457
|
-
const pillX = legendX + (isActive ? capsulePad : 0);
|
|
13458
|
-
const pillBg = isActive ? palette.bg : groupBg;
|
|
13459
|
-
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());
|
|
13460
|
-
if (isActive) {
|
|
13461
|
-
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);
|
|
13462
|
-
}
|
|
13463
|
-
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);
|
|
13464
|
-
if (isActive) {
|
|
13465
|
-
let entryX = pillX + pillWidth2 + 4;
|
|
13466
|
-
for (const entry of group.entries) {
|
|
13467
|
-
const entryG = legendContainer.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
13468
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", legendY + LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
13469
|
-
const entryTextX = entryX + LEGEND_DOT_R * 2 + 4;
|
|
13470
|
-
entryG.append("text").attr("x", entryTextX).attr(
|
|
13471
|
-
"y",
|
|
13472
|
-
legendY + LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1
|
|
13473
|
-
).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
13474
|
-
entryX = entryTextX + entry.value.length * LEGEND_ENTRY_FONT_SIZE * 0.6 + 8;
|
|
13475
|
-
}
|
|
13476
|
-
legendX += capsuleWidth + 12;
|
|
13477
|
-
} else {
|
|
13478
|
-
legendX += pillWidth2 + 12;
|
|
13479
|
-
}
|
|
13480
|
-
}
|
|
14110
|
+
const legendConfig = {
|
|
14111
|
+
groups: parsed.tagGroups,
|
|
14112
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
14113
|
+
mode: exportDims ? "inline" : "fixed"
|
|
14114
|
+
};
|
|
14115
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
14116
|
+
const legendG = svg.append("g").attr("class", "kanban-legend").attr("transform", `translate(${DIAGRAM_PADDING3},${legendY})`);
|
|
14117
|
+
renderLegendD3(
|
|
14118
|
+
legendG,
|
|
14119
|
+
legendConfig,
|
|
14120
|
+
legendState,
|
|
14121
|
+
palette,
|
|
14122
|
+
isDark,
|
|
14123
|
+
void 0,
|
|
14124
|
+
width - DIAGRAM_PADDING3 * 2
|
|
14125
|
+
);
|
|
13481
14126
|
}
|
|
13482
14127
|
const defaultColBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
13483
14128
|
const defaultColHeaderBg = isDark ? mix(palette.surface, palette.bg, 70) : mix(palette.surface, palette.bg, 50);
|
|
@@ -13573,6 +14218,7 @@ var init_renderer3 = __esm({
|
|
|
13573
14218
|
init_parser5();
|
|
13574
14219
|
init_mutations();
|
|
13575
14220
|
init_legend_constants();
|
|
14221
|
+
init_legend_d3();
|
|
13576
14222
|
init_title_constants();
|
|
13577
14223
|
DIAGRAM_PADDING3 = 20;
|
|
13578
14224
|
COLUMN_GAP = 16;
|
|
@@ -13766,14 +14412,9 @@ function collectClassTypes(parsed) {
|
|
|
13766
14412
|
if (c.color) continue;
|
|
13767
14413
|
present.add(c.modifier ?? "class");
|
|
13768
14414
|
}
|
|
13769
|
-
return CLASS_TYPE_ORDER.filter((k) => present.has(k)).map(
|
|
13770
|
-
|
|
13771
|
-
|
|
13772
|
-
let w = 0;
|
|
13773
|
-
for (const e of entries) {
|
|
13774
|
-
w += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.label, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
13775
|
-
}
|
|
13776
|
-
return w;
|
|
14415
|
+
return CLASS_TYPE_ORDER.filter((k) => present.has(k)).map(
|
|
14416
|
+
(k) => CLASS_TYPE_MAP[k]
|
|
14417
|
+
);
|
|
13777
14418
|
}
|
|
13778
14419
|
function classTypeKey(modifier) {
|
|
13779
14420
|
return modifier ?? "class";
|
|
@@ -13842,7 +14483,10 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
|
|
|
13842
14483
|
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);
|
|
13843
14484
|
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);
|
|
13844
14485
|
if (parsed.title) {
|
|
13845
|
-
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(
|
|
14486
|
+
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(
|
|
14487
|
+
"cursor",
|
|
14488
|
+
onClickItem && parsed.titleLineNumber ? "pointer" : "default"
|
|
14489
|
+
).text(parsed.title);
|
|
13846
14490
|
if (parsed.titleLineNumber) {
|
|
13847
14491
|
titleEl.attr("data-line-number", parsed.titleLineNumber);
|
|
13848
14492
|
if (onClickItem) {
|
|
@@ -13856,32 +14500,33 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
|
|
|
13856
14500
|
}
|
|
13857
14501
|
const isLegendExpanded = legendActive !== false;
|
|
13858
14502
|
if (hasLegend) {
|
|
13859
|
-
const
|
|
13860
|
-
|
|
13861
|
-
|
|
13862
|
-
|
|
13863
|
-
|
|
13864
|
-
|
|
13865
|
-
|
|
13866
|
-
const legendG = svg.append("g").attr("class", "cd-legend").attr("data-legend-group", "type").attr("transform", `translate(${legendX}, ${legendY})`).style("cursor", "pointer");
|
|
13867
|
-
if (isLegendExpanded) {
|
|
13868
|
-
legendG.append("rect").attr("width", totalW).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
13869
|
-
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);
|
|
13870
|
-
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);
|
|
13871
|
-
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);
|
|
13872
|
-
let entryX = LEGEND_CAPSULE_PAD + pillWidth2 + LEGEND_ENTRY_TRAIL;
|
|
13873
|
-
for (const entry of legendEntries) {
|
|
13874
|
-
const color = palette.colors[entry.colorKey];
|
|
13875
|
-
const typeKey = CLASS_TYPE_ORDER.find((k) => CLASS_TYPE_MAP[k] === entry);
|
|
13876
|
-
const entryG = legendG.append("g").attr("data-legend-entry", typeKey);
|
|
13877
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", color);
|
|
13878
|
-
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);
|
|
13879
|
-
entryX += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(entry.label, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
14503
|
+
const legendGroups = [
|
|
14504
|
+
{
|
|
14505
|
+
name: LEGEND_GROUP_NAME,
|
|
14506
|
+
entries: legendEntries.map((entry) => ({
|
|
14507
|
+
value: entry.label,
|
|
14508
|
+
color: palette.colors[entry.colorKey]
|
|
14509
|
+
}))
|
|
13880
14510
|
}
|
|
13881
|
-
|
|
13882
|
-
|
|
13883
|
-
|
|
13884
|
-
|
|
14511
|
+
];
|
|
14512
|
+
const legendConfig = {
|
|
14513
|
+
groups: legendGroups,
|
|
14514
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
14515
|
+
mode: "fixed"
|
|
14516
|
+
};
|
|
14517
|
+
const legendState = {
|
|
14518
|
+
activeGroup: isLegendExpanded ? LEGEND_GROUP_NAME : null
|
|
14519
|
+
};
|
|
14520
|
+
const legendG = svg.append("g").attr("class", "cd-legend").attr("transform", `translate(0,${titleHeight})`);
|
|
14521
|
+
renderLegendD3(
|
|
14522
|
+
legendG,
|
|
14523
|
+
legendConfig,
|
|
14524
|
+
legendState,
|
|
14525
|
+
palette,
|
|
14526
|
+
isDark,
|
|
14527
|
+
void 0,
|
|
14528
|
+
width
|
|
14529
|
+
);
|
|
13885
14530
|
}
|
|
13886
14531
|
const contentG = svg.append("g").attr("transform", `translate(${offsetX}, ${offsetY}) scale(${scale})`);
|
|
13887
14532
|
for (const edge of layout.edges) {
|
|
@@ -13925,7 +14570,13 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
|
|
|
13925
14570
|
const colorOff = !!parsed.options?.["no-auto-color"];
|
|
13926
14571
|
const neutralize = hasLegend && !isLegendExpanded && !node.color;
|
|
13927
14572
|
const effectiveColor = neutralize ? palette.primary : node.color;
|
|
13928
|
-
const fill2 = nodeFill3(
|
|
14573
|
+
const fill2 = nodeFill3(
|
|
14574
|
+
palette,
|
|
14575
|
+
isDark,
|
|
14576
|
+
node.modifier,
|
|
14577
|
+
effectiveColor,
|
|
14578
|
+
colorOff
|
|
14579
|
+
);
|
|
13929
14580
|
const stroke2 = nodeStroke3(palette, node.modifier, effectiveColor, colorOff);
|
|
13930
14581
|
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);
|
|
13931
14582
|
let yPos = -h / 2;
|
|
@@ -13994,15 +14645,10 @@ function renderClassDiagramForExport(content, theme, palette) {
|
|
|
13994
14645
|
const exportWidth = layout.width + DIAGRAM_PADDING4 * 2;
|
|
13995
14646
|
const exportHeight = layout.height + DIAGRAM_PADDING4 * 2 + (parsed.title ? 40 : 0) + legendReserve;
|
|
13996
14647
|
return runInExportContainer(exportWidth, exportHeight, (container) => {
|
|
13997
|
-
renderClassDiagram(
|
|
13998
|
-
|
|
13999
|
-
|
|
14000
|
-
|
|
14001
|
-
palette,
|
|
14002
|
-
isDark,
|
|
14003
|
-
void 0,
|
|
14004
|
-
{ width: exportWidth, height: exportHeight }
|
|
14005
|
-
);
|
|
14648
|
+
renderClassDiagram(container, parsed, layout, palette, isDark, void 0, {
|
|
14649
|
+
width: exportWidth,
|
|
14650
|
+
height: exportHeight
|
|
14651
|
+
});
|
|
14006
14652
|
return extractExportSvg(container, theme);
|
|
14007
14653
|
});
|
|
14008
14654
|
}
|
|
@@ -14015,6 +14661,7 @@ var init_renderer4 = __esm({
|
|
|
14015
14661
|
init_fonts();
|
|
14016
14662
|
init_export_container();
|
|
14017
14663
|
init_legend_constants();
|
|
14664
|
+
init_legend_d3();
|
|
14018
14665
|
init_title_constants();
|
|
14019
14666
|
init_color_utils();
|
|
14020
14667
|
init_parser2();
|
|
@@ -14621,35 +15268,24 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
|
|
|
14621
15268
|
}
|
|
14622
15269
|
}
|
|
14623
15270
|
if (parsed.tagGroups.length > 0) {
|
|
14624
|
-
const LEGEND_PILL_H = LEGEND_HEIGHT - 6;
|
|
14625
|
-
const LEGEND_PILL_RX = Math.floor(LEGEND_PILL_H / 2);
|
|
14626
|
-
const LEGEND_GAP = 8;
|
|
14627
|
-
const legendG = svg.append("g").attr("class", "er-tag-legend");
|
|
14628
|
-
if (activeTagGroup) {
|
|
14629
|
-
legendG.attr("data-legend-active", activeTagGroup.toLowerCase());
|
|
14630
|
-
}
|
|
14631
|
-
let legendX = DIAGRAM_PADDING5;
|
|
14632
15271
|
const legendY = DIAGRAM_PADDING5 + titleHeight;
|
|
14633
|
-
|
|
14634
|
-
|
|
14635
|
-
|
|
14636
|
-
|
|
14637
|
-
|
|
14638
|
-
|
|
14639
|
-
|
|
14640
|
-
|
|
14641
|
-
|
|
14642
|
-
|
|
14643
|
-
|
|
14644
|
-
|
|
14645
|
-
|
|
14646
|
-
|
|
14647
|
-
|
|
14648
|
-
|
|
14649
|
-
|
|
14650
|
-
}
|
|
14651
|
-
legendX += LEGEND_GROUP_GAP;
|
|
14652
|
-
}
|
|
15272
|
+
const legendConfig = {
|
|
15273
|
+
groups: parsed.tagGroups,
|
|
15274
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
15275
|
+
mode: "fixed"
|
|
15276
|
+
};
|
|
15277
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
15278
|
+
const legendG = svg.append("g").attr("class", "er-tag-legend").attr("transform", `translate(0,${legendY})`);
|
|
15279
|
+
renderLegendD3(
|
|
15280
|
+
legendG,
|
|
15281
|
+
legendConfig,
|
|
15282
|
+
legendState,
|
|
15283
|
+
palette,
|
|
15284
|
+
isDark,
|
|
15285
|
+
void 0,
|
|
15286
|
+
viewW
|
|
15287
|
+
);
|
|
15288
|
+
legendG.selectAll("[data-legend-group]").classed("er-legend-group", true);
|
|
14653
15289
|
}
|
|
14654
15290
|
if (semanticRoles) {
|
|
14655
15291
|
const presentRoles = ROLE_ORDER.filter((role) => {
|
|
@@ -14659,55 +15295,35 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
|
|
|
14659
15295
|
return false;
|
|
14660
15296
|
});
|
|
14661
15297
|
if (presentRoles.length > 0) {
|
|
14662
|
-
const measureLabelW = (text, fontSize) => {
|
|
14663
|
-
const dummy = svg.append("text").attr("font-size", fontSize).attr("font-family", FONT_FAMILY).attr("visibility", "hidden").text(text);
|
|
14664
|
-
const measured = dummy.node()?.getComputedTextLength?.() ?? 0;
|
|
14665
|
-
dummy.remove();
|
|
14666
|
-
return measured > 0 ? measured : text.length * fontSize * 0.6;
|
|
14667
|
-
};
|
|
14668
|
-
const labelWidths = /* @__PURE__ */ new Map();
|
|
14669
|
-
for (const role of presentRoles) {
|
|
14670
|
-
labelWidths.set(
|
|
14671
|
-
role,
|
|
14672
|
-
measureLabelW(ROLE_LABELS[role], LEGEND_ENTRY_FONT_SIZE)
|
|
14673
|
-
);
|
|
14674
|
-
}
|
|
14675
|
-
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
14676
|
-
const groupName = "Role";
|
|
14677
|
-
const pillWidth2 = measureLegendText(groupName, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
14678
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
14679
|
-
let totalWidth;
|
|
14680
|
-
let entriesWidth2 = 0;
|
|
14681
|
-
if (semanticActive) {
|
|
14682
|
-
for (const role of presentRoles) {
|
|
14683
|
-
entriesWidth2 += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + labelWidths.get(role) + LEGEND_ENTRY_TRAIL;
|
|
14684
|
-
}
|
|
14685
|
-
totalWidth = LEGEND_CAPSULE_PAD * 2 + pillWidth2 + LEGEND_ENTRY_TRAIL + entriesWidth2;
|
|
14686
|
-
} else {
|
|
14687
|
-
totalWidth = pillWidth2;
|
|
14688
|
-
}
|
|
14689
|
-
const legendX = (viewW - totalWidth) / 2;
|
|
14690
15298
|
const legendY = DIAGRAM_PADDING5 + titleHeight;
|
|
14691
|
-
const
|
|
14692
|
-
|
|
14693
|
-
|
|
14694
|
-
|
|
14695
|
-
|
|
14696
|
-
|
|
14697
|
-
|
|
14698
|
-
for (const role of presentRoles) {
|
|
14699
|
-
const label = ROLE_LABELS[role];
|
|
14700
|
-
const roleColor = palette.colors[ROLE_COLORS[role]];
|
|
14701
|
-
const entryG = semanticLegendG.append("g").attr("data-legend-entry", role);
|
|
14702
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", roleColor);
|
|
14703
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
14704
|
-
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);
|
|
14705
|
-
entryX = textX + labelWidths.get(role) + LEGEND_ENTRY_TRAIL;
|
|
15299
|
+
const semanticGroups = [
|
|
15300
|
+
{
|
|
15301
|
+
name: "Role",
|
|
15302
|
+
entries: presentRoles.map((role) => ({
|
|
15303
|
+
value: ROLE_LABELS[role],
|
|
15304
|
+
color: palette.colors[ROLE_COLORS[role]]
|
|
15305
|
+
}))
|
|
14706
15306
|
}
|
|
14707
|
-
|
|
14708
|
-
|
|
14709
|
-
|
|
14710
|
-
|
|
15307
|
+
];
|
|
15308
|
+
const legendConfig = {
|
|
15309
|
+
groups: semanticGroups,
|
|
15310
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
15311
|
+
mode: "fixed"
|
|
15312
|
+
};
|
|
15313
|
+
const legendState = {
|
|
15314
|
+
activeGroup: semanticActive ? "Role" : null
|
|
15315
|
+
};
|
|
15316
|
+
const legendG = svg.append("g").attr("class", "er-semantic-legend").attr("transform", `translate(0,${legendY})`);
|
|
15317
|
+
renderLegendD3(
|
|
15318
|
+
legendG,
|
|
15319
|
+
legendConfig,
|
|
15320
|
+
legendState,
|
|
15321
|
+
palette,
|
|
15322
|
+
isDark,
|
|
15323
|
+
void 0,
|
|
15324
|
+
viewW
|
|
15325
|
+
);
|
|
15326
|
+
legendG.selectAll("[data-legend-group]").classed("er-legend-group", true);
|
|
14711
15327
|
}
|
|
14712
15328
|
}
|
|
14713
15329
|
}
|
|
@@ -14752,6 +15368,7 @@ var init_renderer5 = __esm({
|
|
|
14752
15368
|
init_palettes();
|
|
14753
15369
|
init_tag_groups();
|
|
14754
15370
|
init_legend_constants();
|
|
15371
|
+
init_legend_d3();
|
|
14755
15372
|
init_title_constants();
|
|
14756
15373
|
init_parser3();
|
|
14757
15374
|
init_layout4();
|
|
@@ -14775,6 +15392,17 @@ var layout_exports5 = {};
|
|
|
14775
15392
|
__export(layout_exports5, {
|
|
14776
15393
|
layoutBoxesAndLines: () => layoutBoxesAndLines
|
|
14777
15394
|
});
|
|
15395
|
+
function clipToRectBorder2(cx, cy, w, h, tx, ty) {
|
|
15396
|
+
const dx = tx - cx;
|
|
15397
|
+
const dy = ty - cy;
|
|
15398
|
+
if (dx === 0 && dy === 0) return { x: cx, y: cy };
|
|
15399
|
+
const hw = w / 2;
|
|
15400
|
+
const hh = h / 2;
|
|
15401
|
+
const sx = dx !== 0 ? hw / Math.abs(dx) : Infinity;
|
|
15402
|
+
const sy = dy !== 0 ? hh / Math.abs(dy) : Infinity;
|
|
15403
|
+
const s = Math.min(sx, sy);
|
|
15404
|
+
return { x: cx + dx * s, y: cy + dy * s };
|
|
15405
|
+
}
|
|
14778
15406
|
function computeNodeSize(_node) {
|
|
14779
15407
|
const PHI = 1.618;
|
|
14780
15408
|
const NODE_HEIGHT = 60;
|
|
@@ -14927,13 +15555,25 @@ function layoutBoxesAndLines(parsed, collapseInfo) {
|
|
|
14927
15555
|
const srcNode = g.node(edge.source);
|
|
14928
15556
|
const tgtNode = g.node(edge.target);
|
|
14929
15557
|
if (!srcNode || !tgtNode) continue;
|
|
14930
|
-
const
|
|
14931
|
-
|
|
14932
|
-
|
|
14933
|
-
|
|
14934
|
-
|
|
14935
|
-
|
|
14936
|
-
|
|
15558
|
+
const srcPt = clipToRectBorder2(
|
|
15559
|
+
srcNode.x,
|
|
15560
|
+
srcNode.y,
|
|
15561
|
+
srcNode.width,
|
|
15562
|
+
srcNode.height,
|
|
15563
|
+
tgtNode.x,
|
|
15564
|
+
tgtNode.y
|
|
15565
|
+
);
|
|
15566
|
+
const tgtPt = clipToRectBorder2(
|
|
15567
|
+
tgtNode.x,
|
|
15568
|
+
tgtNode.y,
|
|
15569
|
+
tgtNode.width,
|
|
15570
|
+
tgtNode.height,
|
|
15571
|
+
srcNode.x,
|
|
15572
|
+
srcNode.y
|
|
15573
|
+
);
|
|
15574
|
+
const midX = (srcPt.x + tgtPt.x) / 2;
|
|
15575
|
+
const midY = (srcPt.y + tgtPt.y) / 2;
|
|
15576
|
+
points = [srcPt, { x: midX, y: midY }, tgtPt];
|
|
14937
15577
|
} else {
|
|
14938
15578
|
const dagreEdge = g.edge(edge.source, edge.target, `e${i}`);
|
|
14939
15579
|
points = dagreEdge?.points ?? [];
|
|
@@ -14956,7 +15596,8 @@ function layoutBoxesAndLines(parsed, collapseInfo) {
|
|
|
14956
15596
|
labelY,
|
|
14957
15597
|
yOffset: edgeYOffsets[i],
|
|
14958
15598
|
parallelCount: edgeParallelCounts[i],
|
|
14959
|
-
metadata: edge.metadata
|
|
15599
|
+
metadata: edge.metadata,
|
|
15600
|
+
deferred: deferredSet.has(i) || void 0
|
|
14960
15601
|
});
|
|
14961
15602
|
}
|
|
14962
15603
|
let maxX = 0;
|
|
@@ -15225,12 +15866,8 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
15225
15866
|
const edgeG = diagramG.append("g").attr("class", "bl-edge-group").attr("data-line-number", String(le.lineNumber));
|
|
15226
15867
|
edgeGroups.set(i, edgeG);
|
|
15227
15868
|
const markerId = `bl-arrow-${color.replace("#", "")}`;
|
|
15228
|
-
const
|
|
15229
|
-
|
|
15230
|
-
(parsed.direction === "TB" ? lineGeneratorTB : lineGeneratorLR)(
|
|
15231
|
-
points
|
|
15232
|
-
) ?? ""
|
|
15233
|
-
).attr("fill", "none").attr("stroke", color).attr("stroke-width", EDGE_STROKE_WIDTH5).attr("marker-end", `url(#${markerId})`);
|
|
15869
|
+
const gen = le.deferred ? lineGeneratorLinear2 : parsed.direction === "TB" ? lineGeneratorTB : lineGeneratorLR;
|
|
15870
|
+
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})`);
|
|
15234
15871
|
if (le.bidirectional) {
|
|
15235
15872
|
const revId = `bl-arrow-rev-${color.replace("#", "")}`;
|
|
15236
15873
|
path.attr("marker-start", `url(#${revId})`);
|
|
@@ -15311,50 +15948,23 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
15311
15948
|
}
|
|
15312
15949
|
}
|
|
15313
15950
|
if (parsed.tagGroups.length > 0) {
|
|
15314
|
-
|
|
15315
|
-
|
|
15316
|
-
}
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15321
|
-
|
|
15322
|
-
|
|
15323
|
-
|
|
15324
|
-
|
|
15325
|
-
|
|
15326
|
-
|
|
15327
|
-
|
|
15328
|
-
|
|
15329
|
-
|
|
15330
|
-
|
|
15331
|
-
}
|
|
15332
|
-
const legendX = Math.max(LEGEND_CAPSULE_PAD, (svgWidth - totalW) / 2);
|
|
15333
|
-
const legendY = titleOffset + 4;
|
|
15334
|
-
const legendG = svg.append("g").attr("transform", `translate(${legendX},${legendY})`);
|
|
15335
|
-
let x = 0;
|
|
15336
|
-
for (const tg of parsed.tagGroups) {
|
|
15337
|
-
const isActiveGroup = activeGroup?.toLowerCase() === tg.name.toLowerCase();
|
|
15338
|
-
const groupG = legendG.append("g").attr("class", "bl-legend-group").attr("data-legend-group", tg.name.toLowerCase()).style("cursor", "pointer");
|
|
15339
|
-
const nameW = measureLegendText(tg.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
15340
|
-
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);
|
|
15341
|
-
if (isActiveGroup) {
|
|
15342
|
-
tagPill.attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
15343
|
-
}
|
|
15344
|
-
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);
|
|
15345
|
-
x += nameW;
|
|
15346
|
-
if (isActiveGroup) {
|
|
15347
|
-
x += 6;
|
|
15348
|
-
for (const entry of tg.entries) {
|
|
15349
|
-
const entryColor = entry.color || palette.textMuted;
|
|
15350
|
-
const ew = measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE);
|
|
15351
|
-
const entryG = groupG.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
15352
|
-
entryG.append("circle").attr("cx", x + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entryColor);
|
|
15353
|
-
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);
|
|
15354
|
-
x += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + ew + LEGEND_ENTRY_TRAIL;
|
|
15355
|
-
}
|
|
15356
|
-
}
|
|
15357
|
-
x += LEGEND_GROUP_GAP;
|
|
15951
|
+
const legendConfig = {
|
|
15952
|
+
groups: parsed.tagGroups,
|
|
15953
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
15954
|
+
mode: "fixed"
|
|
15955
|
+
};
|
|
15956
|
+
const legendState = { activeGroup };
|
|
15957
|
+
const legendG = svg.append("g").attr("transform", `translate(0,${titleOffset + 4})`);
|
|
15958
|
+
renderLegendD3(
|
|
15959
|
+
legendG,
|
|
15960
|
+
legendConfig,
|
|
15961
|
+
legendState,
|
|
15962
|
+
palette,
|
|
15963
|
+
isDark,
|
|
15964
|
+
void 0,
|
|
15965
|
+
width
|
|
15966
|
+
);
|
|
15967
|
+
legendG.selectAll("[data-legend-group]").classed("bl-legend-group", true);
|
|
15358
15968
|
}
|
|
15359
15969
|
}
|
|
15360
15970
|
function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark, options) {
|
|
@@ -15362,7 +15972,7 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
|
|
|
15362
15972
|
exportDims: options?.exportDims
|
|
15363
15973
|
});
|
|
15364
15974
|
}
|
|
15365
|
-
var d3Selection6, d3Shape4, 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;
|
|
15975
|
+
var d3Selection6, d3Shape4, 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;
|
|
15366
15976
|
var init_renderer6 = __esm({
|
|
15367
15977
|
"src/boxes-and-lines/renderer.ts"() {
|
|
15368
15978
|
"use strict";
|
|
@@ -15370,6 +15980,7 @@ var init_renderer6 = __esm({
|
|
|
15370
15980
|
d3Shape4 = __toESM(require("d3-shape"), 1);
|
|
15371
15981
|
init_fonts();
|
|
15372
15982
|
init_legend_constants();
|
|
15983
|
+
init_legend_d3();
|
|
15373
15984
|
init_title_constants();
|
|
15374
15985
|
init_color_utils();
|
|
15375
15986
|
init_tag_groups();
|
|
@@ -15390,6 +16001,7 @@ var init_renderer6 = __esm({
|
|
|
15390
16001
|
GROUP_LABEL_FONT_SIZE = 14;
|
|
15391
16002
|
lineGeneratorLR = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveMonotoneX);
|
|
15392
16003
|
lineGeneratorTB = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveMonotoneY);
|
|
16004
|
+
lineGeneratorLinear2 = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveLinear);
|
|
15393
16005
|
}
|
|
15394
16006
|
});
|
|
15395
16007
|
|
|
@@ -17296,7 +17908,7 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
|
|
|
17296
17908
|
if (activeTagGroup) {
|
|
17297
17909
|
legendParent.attr("data-legend-active", activeTagGroup.toLowerCase());
|
|
17298
17910
|
}
|
|
17299
|
-
|
|
17911
|
+
renderLegend2(
|
|
17300
17912
|
legendParent,
|
|
17301
17913
|
layout,
|
|
17302
17914
|
palette,
|
|
@@ -17657,52 +18269,28 @@ function placeEdgeLabels(labels, edges, obstacleRects) {
|
|
|
17657
18269
|
placedRects.push({ x: lbl.x, y: lbl.y, w: lbl.bgW, h: lbl.bgH });
|
|
17658
18270
|
}
|
|
17659
18271
|
}
|
|
17660
|
-
function
|
|
17661
|
-
const
|
|
17662
|
-
|
|
17663
|
-
|
|
17664
|
-
|
|
17665
|
-
const
|
|
17666
|
-
|
|
17667
|
-
|
|
17668
|
-
|
|
17669
|
-
|
|
17670
|
-
|
|
17671
|
-
|
|
17672
|
-
|
|
17673
|
-
|
|
17674
|
-
|
|
17675
|
-
|
|
17676
|
-
|
|
17677
|
-
|
|
17678
|
-
|
|
17679
|
-
|
|
17680
|
-
|
|
17681
|
-
|
|
17682
|
-
const gY = fixedPositions != null ? 0 : group.y;
|
|
17683
|
-
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");
|
|
17684
|
-
if (isActive) {
|
|
17685
|
-
gEl.append("rect").attr("width", group.width).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
17686
|
-
}
|
|
17687
|
-
const pillX = isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
17688
|
-
const pillY = LEGEND_CAPSULE_PAD;
|
|
17689
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
17690
|
-
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);
|
|
17691
|
-
if (isActive) {
|
|
17692
|
-
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);
|
|
17693
|
-
}
|
|
17694
|
-
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);
|
|
17695
|
-
if (isActive) {
|
|
17696
|
-
let entryX = pillX + pillWidth2 + 4;
|
|
17697
|
-
for (const entry of group.entries) {
|
|
17698
|
-
const entryG = gEl.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
17699
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
17700
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
17701
|
-
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);
|
|
17702
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
17703
|
-
}
|
|
17704
|
-
}
|
|
17705
|
-
}
|
|
18272
|
+
function renderLegend2(parent, layout, palette, isDark, activeTagGroup, fixedWidth) {
|
|
18273
|
+
const groups = layout.legend.map((g) => ({
|
|
18274
|
+
name: g.name,
|
|
18275
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
18276
|
+
}));
|
|
18277
|
+
const legendConfig = {
|
|
18278
|
+
groups,
|
|
18279
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
18280
|
+
mode: "fixed"
|
|
18281
|
+
};
|
|
18282
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
18283
|
+
const containerWidth = fixedWidth ?? layout.width;
|
|
18284
|
+
renderLegendD3(
|
|
18285
|
+
parent,
|
|
18286
|
+
legendConfig,
|
|
18287
|
+
legendState,
|
|
18288
|
+
palette,
|
|
18289
|
+
isDark,
|
|
18290
|
+
void 0,
|
|
18291
|
+
containerWidth
|
|
18292
|
+
);
|
|
18293
|
+
parent.selectAll("[data-legend-group]").classed("c4-legend-group", true);
|
|
17706
18294
|
}
|
|
17707
18295
|
function renderC4Containers(container, parsed, layout, palette, isDark, onClickItem, exportDims, activeTagGroup) {
|
|
17708
18296
|
d3Selection7.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
@@ -17913,7 +18501,7 @@ function renderC4Containers(container, parsed, layout, palette, isDark, onClickI
|
|
|
17913
18501
|
if (activeTagGroup) {
|
|
17914
18502
|
legendParent.attr("data-legend-active", activeTagGroup.toLowerCase());
|
|
17915
18503
|
}
|
|
17916
|
-
|
|
18504
|
+
renderLegend2(
|
|
17917
18505
|
legendParent,
|
|
17918
18506
|
layout,
|
|
17919
18507
|
palette,
|
|
@@ -18043,6 +18631,7 @@ var init_renderer7 = __esm({
|
|
|
18043
18631
|
init_parser6();
|
|
18044
18632
|
init_layout6();
|
|
18045
18633
|
init_legend_constants();
|
|
18634
|
+
init_legend_d3();
|
|
18046
18635
|
init_title_constants();
|
|
18047
18636
|
DIAGRAM_PADDING7 = 20;
|
|
18048
18637
|
MAX_SCALE5 = 3;
|
|
@@ -20930,17 +21519,17 @@ function computeInfraLegendGroups(nodes, tagGroups, palette, edges) {
|
|
|
20930
21519
|
color: r.color,
|
|
20931
21520
|
key: r.name.toLowerCase().replace(/\s+/g, "-")
|
|
20932
21521
|
}));
|
|
20933
|
-
const
|
|
20934
|
-
let
|
|
21522
|
+
const pillWidth3 = measureLegendText("Capabilities", LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21523
|
+
let entriesWidth3 = 0;
|
|
20935
21524
|
for (const e of entries) {
|
|
20936
|
-
|
|
21525
|
+
entriesWidth3 += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
20937
21526
|
}
|
|
20938
21527
|
groups.push({
|
|
20939
21528
|
name: "Capabilities",
|
|
20940
21529
|
type: "role",
|
|
20941
21530
|
entries,
|
|
20942
|
-
width: LEGEND_CAPSULE_PAD * 2 +
|
|
20943
|
-
minifiedWidth:
|
|
21531
|
+
width: LEGEND_CAPSULE_PAD * 2 + pillWidth3 + 4 + entriesWidth3,
|
|
21532
|
+
minifiedWidth: pillWidth3
|
|
20944
21533
|
});
|
|
20945
21534
|
}
|
|
20946
21535
|
for (const tg of tagGroups) {
|
|
@@ -20955,113 +21544,88 @@ function computeInfraLegendGroups(nodes, tagGroups, palette, edges) {
|
|
|
20955
21544
|
}
|
|
20956
21545
|
}
|
|
20957
21546
|
if (entries.length === 0) continue;
|
|
20958
|
-
const
|
|
20959
|
-
let
|
|
21547
|
+
const pillWidth3 = measureLegendText(tg.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21548
|
+
let entriesWidth3 = 0;
|
|
20960
21549
|
for (const e of entries) {
|
|
20961
|
-
|
|
21550
|
+
entriesWidth3 += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
20962
21551
|
}
|
|
20963
21552
|
groups.push({
|
|
20964
21553
|
name: tg.name,
|
|
20965
21554
|
type: "tag",
|
|
20966
21555
|
tagKey: (tg.alias ?? tg.name).toLowerCase(),
|
|
20967
21556
|
entries,
|
|
20968
|
-
width: LEGEND_CAPSULE_PAD * 2 +
|
|
20969
|
-
minifiedWidth:
|
|
21557
|
+
width: LEGEND_CAPSULE_PAD * 2 + pillWidth3 + 4 + entriesWidth3,
|
|
21558
|
+
minifiedWidth: pillWidth3
|
|
20970
21559
|
});
|
|
20971
21560
|
}
|
|
20972
21561
|
return groups;
|
|
20973
21562
|
}
|
|
20974
|
-
function
|
|
20975
|
-
if (!playback) return 0;
|
|
20976
|
-
const pillWidth2 = measureLegendText("Playback", LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
20977
|
-
if (!playback.expanded) return pillWidth2;
|
|
20978
|
-
let entriesW = 8;
|
|
20979
|
-
entriesW += LEGEND_PILL_FONT_SIZE * 0.8 + 6;
|
|
20980
|
-
for (const s of playback.speedOptions) {
|
|
20981
|
-
entriesW += measureLegendText(`${s}x`, LEGEND_ENTRY_FONT_SIZE) + SPEED_BADGE_H_PAD * 2 + SPEED_BADGE_GAP;
|
|
20982
|
-
}
|
|
20983
|
-
return LEGEND_CAPSULE_PAD * 2 + pillWidth2 + entriesW;
|
|
20984
|
-
}
|
|
20985
|
-
function renderLegend4(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback) {
|
|
21563
|
+
function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback) {
|
|
20986
21564
|
if (legendGroups.length === 0 && !playback) return;
|
|
20987
21565
|
const legendG = rootSvg.append("g").attr("transform", `translate(0, ${legendY})`);
|
|
20988
21566
|
if (activeGroup) {
|
|
20989
21567
|
legendG.attr("data-legend-active", activeGroup.toLowerCase());
|
|
20990
21568
|
}
|
|
20991
|
-
const
|
|
20992
|
-
|
|
20993
|
-
|
|
20994
|
-
|
|
20995
|
-
|
|
21569
|
+
const allGroups = legendGroups.map((g) => ({
|
|
21570
|
+
name: g.name,
|
|
21571
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
21572
|
+
}));
|
|
21573
|
+
if (playback) {
|
|
21574
|
+
allGroups.push({ name: "Playback", entries: [] });
|
|
21575
|
+
}
|
|
21576
|
+
const legendConfig = {
|
|
21577
|
+
groups: allGroups,
|
|
21578
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
21579
|
+
mode: "fixed",
|
|
21580
|
+
showEmptyGroups: true
|
|
21581
|
+
};
|
|
21582
|
+
const legendState = { activeGroup };
|
|
21583
|
+
renderLegendD3(
|
|
21584
|
+
legendG,
|
|
21585
|
+
legendConfig,
|
|
21586
|
+
legendState,
|
|
21587
|
+
palette,
|
|
21588
|
+
isDark,
|
|
21589
|
+
void 0,
|
|
21590
|
+
totalWidth
|
|
21591
|
+
);
|
|
21592
|
+
legendG.selectAll("[data-legend-group]").classed("infra-legend-group", true);
|
|
20996
21593
|
for (const group of legendGroups) {
|
|
20997
|
-
const
|
|
20998
|
-
const
|
|
20999
|
-
|
|
21000
|
-
|
|
21001
|
-
|
|
21002
|
-
|
|
21003
|
-
|
|
21004
|
-
}
|
|
21005
|
-
const pillXOff = isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
21006
|
-
const pillYOff = LEGEND_CAPSULE_PAD;
|
|
21007
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
21008
|
-
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);
|
|
21009
|
-
if (isActive) {
|
|
21010
|
-
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);
|
|
21011
|
-
}
|
|
21012
|
-
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);
|
|
21013
|
-
if (isActive) {
|
|
21014
|
-
let entryX = pillXOff + pillWidth2 + 4;
|
|
21015
|
-
for (const entry of group.entries) {
|
|
21016
|
-
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(
|
|
21594
|
+
const groupKey = group.name.toLowerCase();
|
|
21595
|
+
for (const entry of group.entries) {
|
|
21596
|
+
const entryEl = legendG.select(
|
|
21597
|
+
`[data-legend-group="${groupKey}"] [data-legend-entry="${entry.value.toLowerCase()}"]`
|
|
21598
|
+
);
|
|
21599
|
+
if (!entryEl.empty()) {
|
|
21600
|
+
entryEl.attr("data-legend-entry", entry.key.toLowerCase()).attr("data-legend-color", entry.color).attr("data-legend-type", group.type).attr(
|
|
21017
21601
|
"data-legend-tag-group",
|
|
21018
21602
|
group.type === "tag" ? group.tagKey ?? "" : null
|
|
21019
|
-
)
|
|
21020
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
21021
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
21022
|
-
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);
|
|
21023
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
21603
|
+
);
|
|
21024
21604
|
}
|
|
21025
21605
|
}
|
|
21026
|
-
cursorX += effectiveW(group) + LEGEND_GROUP_GAP;
|
|
21027
21606
|
}
|
|
21028
|
-
|
|
21029
|
-
|
|
21030
|
-
|
|
21031
|
-
|
|
21032
|
-
|
|
21033
|
-
const
|
|
21034
|
-
|
|
21035
|
-
|
|
21036
|
-
|
|
21037
|
-
|
|
21038
|
-
|
|
21039
|
-
const
|
|
21040
|
-
|
|
21041
|
-
|
|
21042
|
-
|
|
21043
|
-
|
|
21044
|
-
|
|
21045
|
-
|
|
21046
|
-
|
|
21047
|
-
|
|
21048
|
-
|
|
21049
|
-
|
|
21050
|
-
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);
|
|
21051
|
-
entryX += LEGEND_PILL_FONT_SIZE * 0.8 + 6;
|
|
21052
|
-
for (const s of playback.speedOptions) {
|
|
21053
|
-
const label = `${s}x`;
|
|
21054
|
-
const isActive = playback.speed === s;
|
|
21055
|
-
const slotW = measureLegendText(label, LEGEND_ENTRY_FONT_SIZE) + SPEED_BADGE_H_PAD * 2;
|
|
21056
|
-
const badgeH = LEGEND_ENTRY_FONT_SIZE + SPEED_BADGE_V_PAD * 2;
|
|
21057
|
-
const badgeY = (LEGEND_HEIGHT - badgeH) / 2;
|
|
21058
|
-
const speedG = pbG.append("g").attr("data-playback-action", "set-speed").attr("data-playback-value", String(s)).style("cursor", "pointer");
|
|
21059
|
-
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");
|
|
21060
|
-
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);
|
|
21061
|
-
entryX += slotW + SPEED_BADGE_GAP;
|
|
21062
|
-
}
|
|
21063
|
-
}
|
|
21064
|
-
cursorX += fullW + LEGEND_GROUP_GAP;
|
|
21607
|
+
const playbackEl = legendG.select('[data-legend-group="playback"]');
|
|
21608
|
+
if (!playbackEl.empty()) {
|
|
21609
|
+
playbackEl.classed("infra-playback-pill", true);
|
|
21610
|
+
}
|
|
21611
|
+
if (playback && playback.expanded && !playbackEl.empty()) {
|
|
21612
|
+
const pillWidth3 = measureLegendText("Playback", LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21613
|
+
let entryX = pillWidth3 + 8;
|
|
21614
|
+
const entryY = LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1;
|
|
21615
|
+
const ppLabel = playback.paused ? "\u25B6" : "\u23F8";
|
|
21616
|
+
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);
|
|
21617
|
+
entryX += LEGEND_PILL_FONT_SIZE * 0.8 + 6;
|
|
21618
|
+
for (const s of playback.speedOptions) {
|
|
21619
|
+
const label = `${s}x`;
|
|
21620
|
+
const isSpeedActive = playback.speed === s;
|
|
21621
|
+
const slotW = measureLegendText(label, LEGEND_ENTRY_FONT_SIZE) + SPEED_BADGE_H_PAD * 2;
|
|
21622
|
+
const badgeH = LEGEND_ENTRY_FONT_SIZE + SPEED_BADGE_V_PAD * 2;
|
|
21623
|
+
const badgeY = (LEGEND_HEIGHT - badgeH) / 2;
|
|
21624
|
+
const speedG = playbackEl.append("g").attr("data-playback-action", "set-speed").attr("data-playback-value", String(s)).style("cursor", "pointer");
|
|
21625
|
+
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");
|
|
21626
|
+
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);
|
|
21627
|
+
entryX += slotW + SPEED_BADGE_GAP;
|
|
21628
|
+
}
|
|
21065
21629
|
}
|
|
21066
21630
|
}
|
|
21067
21631
|
function renderInfra(container, layout, palette, isDark, title, titleLineNumber, tagGroups, activeGroup, animate, playback, expandedNodeIds, exportMode, collapsedNodes) {
|
|
@@ -21192,7 +21756,7 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
21192
21756
|
"viewBox",
|
|
21193
21757
|
`0 0 ${containerWidth} ${LEGEND_HEIGHT + LEGEND_FIXED_GAP3}`
|
|
21194
21758
|
).attr("preserveAspectRatio", "xMidYMid meet").style("display", "block").style("pointer-events", "none");
|
|
21195
|
-
|
|
21759
|
+
renderLegend3(
|
|
21196
21760
|
legendSvg,
|
|
21197
21761
|
legendGroups,
|
|
21198
21762
|
containerWidth,
|
|
@@ -21204,7 +21768,7 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
21204
21768
|
);
|
|
21205
21769
|
legendSvg.selectAll(".infra-legend-group").style("pointer-events", "auto");
|
|
21206
21770
|
} else {
|
|
21207
|
-
|
|
21771
|
+
renderLegend3(
|
|
21208
21772
|
rootSvg,
|
|
21209
21773
|
legendGroups,
|
|
21210
21774
|
totalWidth,
|
|
@@ -21238,6 +21802,7 @@ var init_renderer8 = __esm({
|
|
|
21238
21802
|
init_compute();
|
|
21239
21803
|
init_layout8();
|
|
21240
21804
|
init_legend_constants();
|
|
21805
|
+
init_legend_d3();
|
|
21241
21806
|
init_title_constants();
|
|
21242
21807
|
NODE_FONT_SIZE3 = 13;
|
|
21243
21808
|
META_FONT_SIZE5 = 10;
|
|
@@ -22863,7 +23428,7 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
22863
23428
|
const isActive = activeGroupName?.toLowerCase() === group.name.toLowerCase();
|
|
22864
23429
|
const isSwimlane = currentSwimlaneGroup?.toLowerCase() === group.name.toLowerCase();
|
|
22865
23430
|
const showIcon = !legendViewMode && tagGroups.length > 0;
|
|
22866
|
-
const iconReserve = showIcon ? LEGEND_ICON_W : 0;
|
|
23431
|
+
const iconReserve = showIcon && isActive ? LEGEND_ICON_W : 0;
|
|
22867
23432
|
const pillW = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD + iconReserve;
|
|
22868
23433
|
let groupW = pillW;
|
|
22869
23434
|
if (isActive) {
|
|
@@ -22890,83 +23455,110 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
22890
23455
|
const legendX = (containerWidth - totalW) / 2;
|
|
22891
23456
|
const legendRow = svg.append("g").attr("class", "gantt-tag-legend-container").attr("transform", `translate(${legendX}, ${legendY})`);
|
|
22892
23457
|
let cursorX = 0;
|
|
22893
|
-
|
|
22894
|
-
const group = visibleGroups[i];
|
|
22895
|
-
const isActive = activeGroupName?.toLowerCase() === group.name.toLowerCase();
|
|
22896
|
-
const isSwimlane = currentSwimlaneGroup?.toLowerCase() === group.name.toLowerCase();
|
|
23458
|
+
if (visibleGroups.length > 0) {
|
|
22897
23459
|
const showIcon = !legendViewMode && tagGroups.length > 0;
|
|
22898
23460
|
const iconReserve = showIcon ? LEGEND_ICON_W : 0;
|
|
22899
|
-
const
|
|
22900
|
-
|
|
22901
|
-
|
|
22902
|
-
|
|
22903
|
-
|
|
23461
|
+
const legendGroups = visibleGroups.map((g) => {
|
|
23462
|
+
const key = g.name.toLowerCase();
|
|
23463
|
+
const entries = filteredEntries.get(key) ?? g.entries;
|
|
23464
|
+
return {
|
|
23465
|
+
name: g.name,
|
|
23466
|
+
entries: entries.map((e) => ({ value: e.value, color: e.color }))
|
|
23467
|
+
};
|
|
22904
23468
|
});
|
|
22905
|
-
|
|
22906
|
-
|
|
22907
|
-
|
|
22908
|
-
|
|
22909
|
-
|
|
22910
|
-
|
|
22911
|
-
|
|
22912
|
-
|
|
22913
|
-
}
|
|
22914
|
-
const
|
|
22915
|
-
|
|
22916
|
-
|
|
22917
|
-
|
|
22918
|
-
|
|
22919
|
-
|
|
22920
|
-
|
|
22921
|
-
|
|
22922
|
-
|
|
22923
|
-
if (onSwimlaneChange) {
|
|
22924
|
-
onSwimlaneChange(
|
|
22925
|
-
currentSwimlaneGroup?.toLowerCase() === group.name.toLowerCase() ? null : group.name
|
|
22926
|
-
);
|
|
22927
|
-
}
|
|
22928
|
-
});
|
|
22929
|
-
}
|
|
22930
|
-
if (isActive) {
|
|
22931
|
-
const tagKey = group.name.toLowerCase();
|
|
22932
|
-
const entries = filteredEntries.get(tagKey) ?? group.entries;
|
|
22933
|
-
let ex = pillXOff + pillW + LEGEND_CAPSULE_PAD + 4;
|
|
22934
|
-
for (const entry of entries) {
|
|
22935
|
-
const entryValue = entry.value.toLowerCase();
|
|
22936
|
-
const entryG = gEl.append("g").attr("class", "gantt-legend-entry").attr("data-line-number", String(entry.lineNumber)).style("cursor", "pointer");
|
|
22937
|
-
entryG.append("circle").attr("cx", ex + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
22938
|
-
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);
|
|
22939
|
-
entryG.on("mouseenter", () => {
|
|
23469
|
+
const legendConfig = {
|
|
23470
|
+
groups: legendGroups,
|
|
23471
|
+
position: {
|
|
23472
|
+
placement: "top-center",
|
|
23473
|
+
titleRelation: "below-title"
|
|
23474
|
+
},
|
|
23475
|
+
mode: "fixed",
|
|
23476
|
+
capsulePillAddonWidth: iconReserve
|
|
23477
|
+
};
|
|
23478
|
+
const legendState = { activeGroup: activeGroupName };
|
|
23479
|
+
const tagGroupsW = visibleGroups.reduce((s, _, i) => s + groupWidths[i], 0) + Math.max(0, (visibleGroups.length - 1) * LEGEND_GROUP_GAP);
|
|
23480
|
+
const tagGroupG = legendRow.append("g");
|
|
23481
|
+
const legendCallbacks = {
|
|
23482
|
+
onGroupToggle: onToggle,
|
|
23483
|
+
onEntryHover: (groupName, entryValue) => {
|
|
23484
|
+
const tagKey = groupName.toLowerCase();
|
|
23485
|
+
if (entryValue) {
|
|
23486
|
+
const ev = entryValue.toLowerCase();
|
|
22940
23487
|
chartG.selectAll(".gantt-task").each(function() {
|
|
22941
23488
|
const el = d3Selection10.select(this);
|
|
22942
|
-
|
|
22943
|
-
|
|
23489
|
+
el.attr(
|
|
23490
|
+
"opacity",
|
|
23491
|
+
el.attr(`data-tag-${tagKey}`) === ev ? 1 : FADE_OPACITY
|
|
23492
|
+
);
|
|
22944
23493
|
});
|
|
22945
23494
|
chartG.selectAll(".gantt-milestone").attr("opacity", FADE_OPACITY);
|
|
22946
23495
|
chartG.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
22947
23496
|
svg.selectAll(".gantt-task-label").each(function() {
|
|
22948
23497
|
const el = d3Selection10.select(this);
|
|
22949
|
-
|
|
22950
|
-
|
|
23498
|
+
el.attr(
|
|
23499
|
+
"opacity",
|
|
23500
|
+
el.attr(`data-tag-${tagKey}`) === ev ? 1 : FADE_OPACITY
|
|
23501
|
+
);
|
|
22951
23502
|
});
|
|
22952
23503
|
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
22953
23504
|
svg.selectAll(".gantt-lane-header").each(function() {
|
|
22954
23505
|
const el = d3Selection10.select(this);
|
|
22955
|
-
|
|
22956
|
-
|
|
23506
|
+
el.attr(
|
|
23507
|
+
"opacity",
|
|
23508
|
+
el.attr(`data-tag-${tagKey}`) === ev ? 1 : FADE_OPACITY
|
|
23509
|
+
);
|
|
22957
23510
|
});
|
|
22958
23511
|
chartG.selectAll(".gantt-lane-band, .gantt-lane-accent").attr("opacity", FADE_OPACITY);
|
|
22959
|
-
}
|
|
23512
|
+
} else {
|
|
22960
23513
|
if (criticalPathActive) {
|
|
22961
23514
|
applyCriticalPathHighlight(svg, chartG);
|
|
22962
23515
|
} else {
|
|
22963
23516
|
resetHighlightAll(svg, chartG);
|
|
22964
23517
|
}
|
|
22965
|
-
}
|
|
22966
|
-
|
|
23518
|
+
}
|
|
23519
|
+
},
|
|
23520
|
+
onGroupRendered: (groupName, groupEl, _isActive) => {
|
|
23521
|
+
const group = visibleGroups.find((g) => g.name === groupName);
|
|
23522
|
+
if (group) {
|
|
23523
|
+
groupEl.attr("data-tag-group", group.name).attr("data-line-number", String(group.lineNumber));
|
|
23524
|
+
}
|
|
23525
|
+
if (showIcon && _isActive) {
|
|
23526
|
+
const isSwimlane = currentSwimlaneGroup?.toLowerCase() === groupName.toLowerCase();
|
|
23527
|
+
const textW = measureLegendText(groupName, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
23528
|
+
const pillXOff = LEGEND_CAPSULE_PAD;
|
|
23529
|
+
const iconX = pillXOff + textW + 3;
|
|
23530
|
+
const iconY = (LEGEND_HEIGHT - 10) / 2;
|
|
23531
|
+
const iconEl = drawSwimlaneIcon(
|
|
23532
|
+
groupEl,
|
|
23533
|
+
iconX,
|
|
23534
|
+
iconY,
|
|
23535
|
+
isSwimlane,
|
|
23536
|
+
palette
|
|
23537
|
+
);
|
|
23538
|
+
iconEl.append("title").text(`Group by ${groupName}`);
|
|
23539
|
+
iconEl.style("cursor", "pointer").on("click", (event) => {
|
|
23540
|
+
event.stopPropagation();
|
|
23541
|
+
if (onSwimlaneChange) {
|
|
23542
|
+
onSwimlaneChange(
|
|
23543
|
+
currentSwimlaneGroup?.toLowerCase() === groupName.toLowerCase() ? null : groupName
|
|
23544
|
+
);
|
|
23545
|
+
}
|
|
23546
|
+
});
|
|
23547
|
+
}
|
|
22967
23548
|
}
|
|
23549
|
+
};
|
|
23550
|
+
renderLegendD3(
|
|
23551
|
+
tagGroupG,
|
|
23552
|
+
legendConfig,
|
|
23553
|
+
legendState,
|
|
23554
|
+
palette,
|
|
23555
|
+
isDark,
|
|
23556
|
+
legendCallbacks,
|
|
23557
|
+
tagGroupsW
|
|
23558
|
+
);
|
|
23559
|
+
for (let i = 0; i < visibleGroups.length; i++) {
|
|
23560
|
+
cursorX += groupWidths[i] + LEGEND_GROUP_GAP;
|
|
22968
23561
|
}
|
|
22969
|
-
cursorX += groupW + LEGEND_GROUP_GAP;
|
|
22970
23562
|
}
|
|
22971
23563
|
if (hasCriticalPath) {
|
|
22972
23564
|
const cpLineNum = optionLineNumbers["critical-path"];
|
|
@@ -23595,6 +24187,7 @@ var init_renderer9 = __esm({
|
|
|
23595
24187
|
init_tag_groups();
|
|
23596
24188
|
init_d3();
|
|
23597
24189
|
init_legend_constants();
|
|
24190
|
+
init_legend_d3();
|
|
23598
24191
|
init_title_constants();
|
|
23599
24192
|
BAR_H = 22;
|
|
23600
24193
|
ROW_GAP = 6;
|
|
@@ -24764,57 +25357,29 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
24764
25357
|
}
|
|
24765
25358
|
if (parsed.tagGroups.length > 0) {
|
|
24766
25359
|
const legendY = TOP_MARGIN + titleOffset;
|
|
24767
|
-
const
|
|
24768
|
-
|
|
24769
|
-
|
|
24770
|
-
if (tg.entries.length === 0) continue;
|
|
24771
|
-
const isActive = !!activeTagGroup && tg.name.toLowerCase() === activeTagGroup.toLowerCase();
|
|
24772
|
-
const pillWidth2 = measureLegendText(tg.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
24773
|
-
const entries = tg.entries.map((e) => ({
|
|
25360
|
+
const resolvedGroups = parsed.tagGroups.filter((tg) => tg.entries.length > 0).map((tg) => ({
|
|
25361
|
+
name: tg.name,
|
|
25362
|
+
entries: tg.entries.map((e) => ({
|
|
24774
25363
|
value: e.value,
|
|
24775
25364
|
color: resolveColor(e.color) ?? e.color
|
|
24776
|
-
}))
|
|
24777
|
-
|
|
24778
|
-
|
|
24779
|
-
|
|
24780
|
-
|
|
24781
|
-
|
|
24782
|
-
|
|
24783
|
-
|
|
24784
|
-
|
|
24785
|
-
|
|
24786
|
-
|
|
24787
|
-
|
|
24788
|
-
|
|
24789
|
-
|
|
24790
|
-
|
|
24791
|
-
|
|
24792
|
-
|
|
24793
|
-
|
|
24794
|
-
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");
|
|
24795
|
-
if (item.isActive) {
|
|
24796
|
-
gEl.append("rect").attr("width", item.totalWidth).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
24797
|
-
}
|
|
24798
|
-
const pillXOff = item.isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
24799
|
-
const pillYOff = LEGEND_CAPSULE_PAD;
|
|
24800
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
24801
|
-
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);
|
|
24802
|
-
if (item.isActive) {
|
|
24803
|
-
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);
|
|
24804
|
-
}
|
|
24805
|
-
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);
|
|
24806
|
-
if (item.isActive) {
|
|
24807
|
-
let entryX = pillXOff + item.pillWidth + 4;
|
|
24808
|
-
for (const entry of item.entries) {
|
|
24809
|
-
const entryG = gEl.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
24810
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
24811
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
24812
|
-
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);
|
|
24813
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
24814
|
-
}
|
|
24815
|
-
}
|
|
24816
|
-
legendX += item.totalWidth + LEGEND_GROUP_GAP;
|
|
24817
|
-
}
|
|
25365
|
+
}))
|
|
25366
|
+
}));
|
|
25367
|
+
const legendConfig = {
|
|
25368
|
+
groups: resolvedGroups,
|
|
25369
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
25370
|
+
mode: "fixed"
|
|
25371
|
+
};
|
|
25372
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
25373
|
+
const legendG = svg.append("g").attr("class", "sequence-legend").attr("transform", `translate(0,${legendY})`);
|
|
25374
|
+
renderLegendD3(
|
|
25375
|
+
legendG,
|
|
25376
|
+
legendConfig,
|
|
25377
|
+
legendState,
|
|
25378
|
+
palette,
|
|
25379
|
+
isDark,
|
|
25380
|
+
void 0,
|
|
25381
|
+
svgWidth
|
|
25382
|
+
);
|
|
24818
25383
|
}
|
|
24819
25384
|
for (const group of groups) {
|
|
24820
25385
|
if (group.participantIds.length === 0) continue;
|
|
@@ -25374,6 +25939,7 @@ var init_renderer10 = __esm({
|
|
|
25374
25939
|
init_parser();
|
|
25375
25940
|
init_tag_resolution();
|
|
25376
25941
|
init_legend_constants();
|
|
25942
|
+
init_legend_d3();
|
|
25377
25943
|
init_title_constants();
|
|
25378
25944
|
PARTICIPANT_GAP = 160;
|
|
25379
25945
|
PARTICIPANT_BOX_WIDTH = 120;
|
|
@@ -28029,7 +28595,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28029
28595
|
const LG_ENTRY_FONT_SIZE = LEGEND_ENTRY_FONT_SIZE;
|
|
28030
28596
|
const LG_ENTRY_DOT_GAP = LEGEND_ENTRY_DOT_GAP;
|
|
28031
28597
|
const LG_ENTRY_TRAIL = LEGEND_ENTRY_TRAIL;
|
|
28032
|
-
const LG_GROUP_GAP = LEGEND_GROUP_GAP;
|
|
28033
28598
|
const LG_ICON_W = 20;
|
|
28034
28599
|
const mainSvg = d3Selection13.select(container).select("svg");
|
|
28035
28600
|
const mainG = mainSvg.select("g");
|
|
@@ -28068,11 +28633,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28068
28633
|
(lg) => effectiveColorKey != null && lg.group.name.toLowerCase() === effectiveColorKey
|
|
28069
28634
|
) : legendGroups;
|
|
28070
28635
|
if (visibleGroups.length === 0) return;
|
|
28071
|
-
const totalW = visibleGroups.reduce((s, lg) => {
|
|
28072
|
-
const isActive = viewMode || currentActiveGroup != null && lg.group.name.toLowerCase() === currentActiveGroup.toLowerCase();
|
|
28073
|
-
return s + (isActive ? lg.expandedWidth : lg.minifiedWidth);
|
|
28074
|
-
}, 0) + (visibleGroups.length - 1) * LG_GROUP_GAP;
|
|
28075
|
-
let cx = (width - totalW) / 2;
|
|
28076
28636
|
const legendContainer = mainSvg.append("g").attr("class", "tl-tag-legend-container");
|
|
28077
28637
|
if (currentActiveGroup) {
|
|
28078
28638
|
legendContainer.attr(
|
|
@@ -28080,82 +28640,85 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28080
28640
|
currentActiveGroup.toLowerCase()
|
|
28081
28641
|
);
|
|
28082
28642
|
}
|
|
28083
|
-
|
|
28084
|
-
|
|
28085
|
-
|
|
28086
|
-
|
|
28087
|
-
|
|
28088
|
-
|
|
28089
|
-
|
|
28090
|
-
|
|
28091
|
-
|
|
28092
|
-
|
|
28093
|
-
|
|
28094
|
-
|
|
28095
|
-
|
|
28096
|
-
|
|
28097
|
-
|
|
28098
|
-
|
|
28099
|
-
|
|
28100
|
-
|
|
28101
|
-
|
|
28102
|
-
|
|
28103
|
-
|
|
28104
|
-
|
|
28105
|
-
|
|
28106
|
-
|
|
28107
|
-
|
|
28108
|
-
|
|
28109
|
-
|
|
28110
|
-
|
|
28111
|
-
|
|
28112
|
-
|
|
28643
|
+
const iconAddon = viewMode ? 0 : LG_ICON_W;
|
|
28644
|
+
const centralGroups = visibleGroups.map((lg) => ({
|
|
28645
|
+
name: lg.group.name,
|
|
28646
|
+
entries: lg.group.entries.map((e) => ({
|
|
28647
|
+
value: e.value,
|
|
28648
|
+
color: e.color
|
|
28649
|
+
}))
|
|
28650
|
+
}));
|
|
28651
|
+
const centralActive = viewMode ? effectiveColorKey : currentActiveGroup;
|
|
28652
|
+
const centralConfig = {
|
|
28653
|
+
groups: centralGroups,
|
|
28654
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
28655
|
+
mode: "fixed",
|
|
28656
|
+
capsulePillAddonWidth: iconAddon
|
|
28657
|
+
};
|
|
28658
|
+
const centralState = { activeGroup: centralActive };
|
|
28659
|
+
const centralCallbacks = viewMode ? {} : {
|
|
28660
|
+
onGroupToggle: (groupName) => {
|
|
28661
|
+
currentActiveGroup = currentActiveGroup === groupName.toLowerCase() ? null : groupName.toLowerCase();
|
|
28662
|
+
drawLegend2();
|
|
28663
|
+
recolorEvents2();
|
|
28664
|
+
onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
|
|
28665
|
+
},
|
|
28666
|
+
onEntryHover: (groupName, entryValue) => {
|
|
28667
|
+
const tagKey = groupName.toLowerCase();
|
|
28668
|
+
if (entryValue) {
|
|
28669
|
+
const tagVal = entryValue.toLowerCase();
|
|
28670
|
+
fadeToTagValue(mainG, tagKey, tagVal);
|
|
28671
|
+
mainSvg.selectAll("[data-legend-entry]").each(function() {
|
|
28672
|
+
const el = d3Selection13.select(this);
|
|
28673
|
+
const ev = el.attr("data-legend-entry");
|
|
28674
|
+
const eg = el.attr("data-tag-group") ?? el.node()?.closest?.("[data-tag-group]")?.getAttribute("data-tag-group");
|
|
28675
|
+
el.attr(
|
|
28676
|
+
"opacity",
|
|
28677
|
+
eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY2
|
|
28678
|
+
);
|
|
28679
|
+
});
|
|
28680
|
+
} else {
|
|
28681
|
+
fadeReset(mainG);
|
|
28682
|
+
mainSvg.selectAll("[data-legend-entry]").attr("opacity", 1);
|
|
28683
|
+
}
|
|
28684
|
+
},
|
|
28685
|
+
onGroupRendered: (groupName, groupEl, isActive) => {
|
|
28686
|
+
const groupKey = groupName.toLowerCase();
|
|
28687
|
+
groupEl.attr("data-tag-group", groupKey);
|
|
28688
|
+
if (isActive && !viewMode) {
|
|
28689
|
+
const isSwimActive = currentSwimlaneGroup != null && currentSwimlaneGroup.toLowerCase() === groupKey;
|
|
28690
|
+
const pillWidth3 = measureLegendText(groupName, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
|
|
28691
|
+
const pillXOff = LG_CAPSULE_PAD;
|
|
28692
|
+
const iconX = pillXOff + pillWidth3 + 5;
|
|
28113
28693
|
const iconY = (LG_HEIGHT - 10) / 2;
|
|
28114
|
-
const iconEl = drawSwimlaneIcon3(
|
|
28694
|
+
const iconEl = drawSwimlaneIcon3(
|
|
28695
|
+
groupEl,
|
|
28696
|
+
iconX,
|
|
28697
|
+
iconY,
|
|
28698
|
+
isSwimActive
|
|
28699
|
+
);
|
|
28115
28700
|
iconEl.attr("data-swimlane-toggle", groupKey).on("click", (event) => {
|
|
28116
28701
|
event.stopPropagation();
|
|
28117
28702
|
currentSwimlaneGroup = currentSwimlaneGroup === groupKey ? null : groupKey;
|
|
28118
|
-
onTagStateChange?.(
|
|
28703
|
+
onTagStateChange?.(
|
|
28704
|
+
currentActiveGroup,
|
|
28705
|
+
currentSwimlaneGroup
|
|
28706
|
+
);
|
|
28119
28707
|
relayout2();
|
|
28120
28708
|
});
|
|
28121
|
-
entryX = pillXOff + pillWidth2 + LG_ICON_W + 4;
|
|
28122
|
-
} else {
|
|
28123
|
-
entryX = pillXOff + pillWidth2 + 8;
|
|
28124
|
-
}
|
|
28125
|
-
for (const entry of lg.group.entries) {
|
|
28126
|
-
const tagKey = lg.group.name.toLowerCase();
|
|
28127
|
-
const tagVal = entry.value.toLowerCase();
|
|
28128
|
-
const entryG = gEl.append("g").attr("class", "tl-tag-legend-entry").attr("data-tag-group", tagKey).attr("data-legend-entry", tagVal);
|
|
28129
|
-
if (!viewMode) {
|
|
28130
|
-
entryG.style("cursor", "pointer").on("mouseenter", (event) => {
|
|
28131
|
-
event.stopPropagation();
|
|
28132
|
-
fadeToTagValue(mainG, tagKey, tagVal);
|
|
28133
|
-
mainSvg.selectAll(".tl-tag-legend-entry").each(function() {
|
|
28134
|
-
const el = d3Selection13.select(this);
|
|
28135
|
-
const ev = el.attr("data-legend-entry");
|
|
28136
|
-
if (ev === "__group__") return;
|
|
28137
|
-
const eg = el.attr("data-tag-group");
|
|
28138
|
-
el.attr(
|
|
28139
|
-
"opacity",
|
|
28140
|
-
eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY2
|
|
28141
|
-
);
|
|
28142
|
-
});
|
|
28143
|
-
}).on("mouseleave", (event) => {
|
|
28144
|
-
event.stopPropagation();
|
|
28145
|
-
fadeReset(mainG);
|
|
28146
|
-
mainSvg.selectAll(".tl-tag-legend-entry").attr("opacity", 1);
|
|
28147
|
-
}).on("click", (event) => {
|
|
28148
|
-
event.stopPropagation();
|
|
28149
|
-
});
|
|
28150
|
-
}
|
|
28151
|
-
entryG.append("circle").attr("cx", entryX + LG_DOT_R).attr("cy", LG_HEIGHT / 2).attr("r", LG_DOT_R).attr("fill", entry.color);
|
|
28152
|
-
const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
|
|
28153
|
-
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);
|
|
28154
|
-
entryX = textX + measureLegendText(entry.value, LG_ENTRY_FONT_SIZE) + LG_ENTRY_TRAIL;
|
|
28155
28709
|
}
|
|
28156
28710
|
}
|
|
28157
|
-
|
|
28158
|
-
}
|
|
28711
|
+
};
|
|
28712
|
+
const legendInnerG = legendContainer.append("g").attr("transform", `translate(0, ${legendY})`);
|
|
28713
|
+
renderLegendD3(
|
|
28714
|
+
legendInnerG,
|
|
28715
|
+
centralConfig,
|
|
28716
|
+
centralState,
|
|
28717
|
+
palette,
|
|
28718
|
+
isDark,
|
|
28719
|
+
centralCallbacks,
|
|
28720
|
+
width
|
|
28721
|
+
);
|
|
28159
28722
|
}, recolorEvents2 = function() {
|
|
28160
28723
|
const colorTG = currentActiveGroup ?? swimlaneTagGroup ?? null;
|
|
28161
28724
|
mainG.selectAll(".tl-event").each(function() {
|
|
@@ -28180,7 +28743,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28180
28743
|
};
|
|
28181
28744
|
var drawSwimlaneIcon2 = drawSwimlaneIcon3, relayout = relayout2, drawLegend = drawLegend2, recolorEvents = recolorEvents2;
|
|
28182
28745
|
const legendY = title ? 50 : 10;
|
|
28183
|
-
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
28184
28746
|
const legendGroups = parsed.timelineTagGroups.map((g) => {
|
|
28185
28747
|
const pillW = measureLegendText(g.name, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
|
|
28186
28748
|
const iconSpace = viewMode ? 8 : LG_ICON_W + 4;
|
|
@@ -29427,6 +29989,7 @@ var init_d3 = __esm({
|
|
|
29427
29989
|
init_parsing();
|
|
29428
29990
|
init_tag_groups();
|
|
29429
29991
|
init_legend_constants();
|
|
29992
|
+
init_legend_d3();
|
|
29430
29993
|
init_title_constants();
|
|
29431
29994
|
DEFAULT_CLOUD_OPTIONS = {
|
|
29432
29995
|
rotate: "none",
|
|
@@ -29605,6 +30168,7 @@ __export(index_exports, {
|
|
|
29605
30168
|
computeCardMove: () => computeCardMove,
|
|
29606
30169
|
computeInfra: () => computeInfra,
|
|
29607
30170
|
computeInfraLegendGroups: () => computeInfraLegendGroups,
|
|
30171
|
+
computeLegendLayout: () => computeLegendLayout,
|
|
29608
30172
|
computeScatterLabelGraphics: () => computeScatterLabelGraphics,
|
|
29609
30173
|
computeTimeTicks: () => computeTimeTicks,
|
|
29610
30174
|
contrastText: () => contrastText,
|
|
@@ -29616,6 +30180,7 @@ __export(index_exports, {
|
|
|
29616
30180
|
formatDgmoError: () => formatDgmoError,
|
|
29617
30181
|
getAvailablePalettes: () => getAvailablePalettes,
|
|
29618
30182
|
getExtendedChartLegendGroups: () => getExtendedChartLegendGroups,
|
|
30183
|
+
getLegendReservedHeight: () => getLegendReservedHeight,
|
|
29619
30184
|
getPalette: () => getPalette,
|
|
29620
30185
|
getRenderCategory: () => getRenderCategory,
|
|
29621
30186
|
getSeriesColors: () => getSeriesColors,
|
|
@@ -29704,7 +30269,9 @@ __export(index_exports, {
|
|
|
29704
30269
|
renderInfra: () => renderInfra,
|
|
29705
30270
|
renderKanban: () => renderKanban,
|
|
29706
30271
|
renderKanbanForExport: () => renderKanbanForExport,
|
|
30272
|
+
renderLegendD3: () => renderLegendD3,
|
|
29707
30273
|
renderLegendSvg: () => renderLegendSvg,
|
|
30274
|
+
renderLegendSvgFromConfig: () => renderLegendSvgFromConfig,
|
|
29708
30275
|
renderOrg: () => renderOrg,
|
|
29709
30276
|
renderOrgForExport: () => renderOrgForExport,
|
|
29710
30277
|
renderQuadrant: () => renderQuadrant,
|
|
@@ -29744,11 +30311,26 @@ async function ensureDom() {
|
|
|
29744
30311
|
const { JSDOM } = await import("jsdom");
|
|
29745
30312
|
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
|
|
29746
30313
|
const win = dom.window;
|
|
29747
|
-
Object.defineProperty(globalThis, "document", {
|
|
29748
|
-
|
|
29749
|
-
|
|
29750
|
-
|
|
29751
|
-
Object.defineProperty(globalThis, "
|
|
30314
|
+
Object.defineProperty(globalThis, "document", {
|
|
30315
|
+
value: win.document,
|
|
30316
|
+
configurable: true
|
|
30317
|
+
});
|
|
30318
|
+
Object.defineProperty(globalThis, "window", {
|
|
30319
|
+
value: win,
|
|
30320
|
+
configurable: true
|
|
30321
|
+
});
|
|
30322
|
+
Object.defineProperty(globalThis, "navigator", {
|
|
30323
|
+
value: win.navigator,
|
|
30324
|
+
configurable: true
|
|
30325
|
+
});
|
|
30326
|
+
Object.defineProperty(globalThis, "HTMLElement", {
|
|
30327
|
+
value: win.HTMLElement,
|
|
30328
|
+
configurable: true
|
|
30329
|
+
});
|
|
30330
|
+
Object.defineProperty(globalThis, "SVGElement", {
|
|
30331
|
+
value: win.SVGElement,
|
|
30332
|
+
configurable: true
|
|
30333
|
+
});
|
|
29752
30334
|
}
|
|
29753
30335
|
async function render(content, options) {
|
|
29754
30336
|
const theme = options?.theme ?? "light";
|
|
@@ -29757,11 +30339,17 @@ async function render(content, options) {
|
|
|
29757
30339
|
const paletteColors = getPalette(paletteName)[theme === "dark" ? "dark" : "light"];
|
|
29758
30340
|
const chartType = parseDgmoChartType(content);
|
|
29759
30341
|
const category = chartType ? getRenderCategory(chartType) : null;
|
|
30342
|
+
const legendExportState = options?.legendState ? {
|
|
30343
|
+
activeTagGroup: options.legendState.activeGroup ?? null,
|
|
30344
|
+
hiddenAttributes: options.legendState.hiddenAttributes ? new Set(options.legendState.hiddenAttributes) : void 0
|
|
30345
|
+
} : void 0;
|
|
29760
30346
|
if (category === "data-chart") {
|
|
29761
|
-
return renderExtendedChartForExport(content, theme, paletteColors, {
|
|
30347
|
+
return renderExtendedChartForExport(content, theme, paletteColors, {
|
|
30348
|
+
branding
|
|
30349
|
+
});
|
|
29762
30350
|
}
|
|
29763
30351
|
await ensureDom();
|
|
29764
|
-
return renderForExport(content, theme, paletteColors,
|
|
30352
|
+
return renderForExport(content, theme, paletteColors, legendExportState, {
|
|
29765
30353
|
branding,
|
|
29766
30354
|
c4Level: options?.c4Level,
|
|
29767
30355
|
c4System: options?.c4System,
|
|
@@ -30484,6 +31072,8 @@ init_flowchart_renderer();
|
|
|
30484
31072
|
init_echarts();
|
|
30485
31073
|
init_legend_svg();
|
|
30486
31074
|
init_legend_constants();
|
|
31075
|
+
init_legend_d3();
|
|
31076
|
+
init_legend_layout();
|
|
30487
31077
|
init_d3();
|
|
30488
31078
|
init_renderer10();
|
|
30489
31079
|
init_colors();
|
|
@@ -31328,6 +31918,7 @@ init_branding();
|
|
|
31328
31918
|
computeCardMove,
|
|
31329
31919
|
computeInfra,
|
|
31330
31920
|
computeInfraLegendGroups,
|
|
31921
|
+
computeLegendLayout,
|
|
31331
31922
|
computeScatterLabelGraphics,
|
|
31332
31923
|
computeTimeTicks,
|
|
31333
31924
|
contrastText,
|
|
@@ -31339,6 +31930,7 @@ init_branding();
|
|
|
31339
31930
|
formatDgmoError,
|
|
31340
31931
|
getAvailablePalettes,
|
|
31341
31932
|
getExtendedChartLegendGroups,
|
|
31933
|
+
getLegendReservedHeight,
|
|
31342
31934
|
getPalette,
|
|
31343
31935
|
getRenderCategory,
|
|
31344
31936
|
getSeriesColors,
|
|
@@ -31427,7 +32019,9 @@ init_branding();
|
|
|
31427
32019
|
renderInfra,
|
|
31428
32020
|
renderKanban,
|
|
31429
32021
|
renderKanbanForExport,
|
|
32022
|
+
renderLegendD3,
|
|
31430
32023
|
renderLegendSvg,
|
|
32024
|
+
renderLegendSvgFromConfig,
|
|
31431
32025
|
renderOrg,
|
|
31432
32026
|
renderOrgForExport,
|
|
31433
32027
|
renderQuadrant,
|