@diagrammo/dgmo 0.8.8 → 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 +181 -179
- package/dist/index.cjs +1425 -933
- 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 +1421 -933
- 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/echarts.ts +99 -214
- package/src/er/renderer.ts +52 -245
- package/src/gantt/renderer.ts +140 -182
- package/src/index.ts +21 -1
- package/src/infra/renderer.ts +91 -244
- package/src/kanban/renderer.ts +22 -129
- package/src/org/renderer.ts +103 -170
- package/src/render.ts +39 -9
- package/src/sequence/renderer.ts +31 -151
- package/src/sitemap/layout.ts +180 -38
- package/src/sitemap/parser.ts +64 -23
- package/src/sitemap/renderer.ts +73 -161
- package/src/utils/legend-constants.ts +6 -0
- package/src/utils/legend-d3.ts +400 -0
- package/src/utils/legend-layout.ts +495 -0
- package/src/utils/legend-svg.ts +26 -0
- package/src/utils/legend-types.ts +169 -0
package/dist/index.js
CHANGED
|
@@ -1901,6 +1901,493 @@ var init_legend_constants = __esm({
|
|
|
1901
1901
|
}
|
|
1902
1902
|
});
|
|
1903
1903
|
|
|
1904
|
+
// src/utils/legend-layout.ts
|
|
1905
|
+
function pillWidth(name) {
|
|
1906
|
+
return measureLegendText(name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
1907
|
+
}
|
|
1908
|
+
function entriesWidth(entries) {
|
|
1909
|
+
let w = 0;
|
|
1910
|
+
for (const e of entries) {
|
|
1911
|
+
w += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
1912
|
+
}
|
|
1913
|
+
return w;
|
|
1914
|
+
}
|
|
1915
|
+
function entryWidth(value) {
|
|
1916
|
+
return LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
1917
|
+
}
|
|
1918
|
+
function controlWidth(control) {
|
|
1919
|
+
let w = CONTROL_PILL_PAD;
|
|
1920
|
+
if (control.label) {
|
|
1921
|
+
w += measureLegendText(control.label, CONTROL_FONT_SIZE);
|
|
1922
|
+
if (control.icon) w += CONTROL_ICON_GAP;
|
|
1923
|
+
}
|
|
1924
|
+
if (control.icon) w += 14;
|
|
1925
|
+
if (control.children) {
|
|
1926
|
+
for (const child of control.children) {
|
|
1927
|
+
w += measureLegendText(child.label, CONTROL_FONT_SIZE) + 12;
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
return w;
|
|
1931
|
+
}
|
|
1932
|
+
function capsuleWidth(name, entries, containerWidth, addonWidth = 0) {
|
|
1933
|
+
const pw = pillWidth(name);
|
|
1934
|
+
const maxCapsuleW = containerWidth;
|
|
1935
|
+
const baseW = LEGEND_CAPSULE_PAD * 2 + pw + 4 + addonWidth;
|
|
1936
|
+
const ew = entriesWidth(entries);
|
|
1937
|
+
const singleRowW = baseW + ew;
|
|
1938
|
+
if (singleRowW <= maxCapsuleW) {
|
|
1939
|
+
return {
|
|
1940
|
+
width: singleRowW,
|
|
1941
|
+
entryRows: 1,
|
|
1942
|
+
moreCount: 0,
|
|
1943
|
+
visibleEntries: entries.length
|
|
1944
|
+
};
|
|
1945
|
+
}
|
|
1946
|
+
const rowWidth = maxCapsuleW - LEGEND_CAPSULE_PAD * 2;
|
|
1947
|
+
let row = 1;
|
|
1948
|
+
let rowX = pw + 4;
|
|
1949
|
+
let visible = 0;
|
|
1950
|
+
for (let i = 0; i < entries.length; i++) {
|
|
1951
|
+
const ew2 = entryWidth(entries[i].value);
|
|
1952
|
+
if (rowX + ew2 > rowWidth && rowX > pw + 4) {
|
|
1953
|
+
row++;
|
|
1954
|
+
rowX = 0;
|
|
1955
|
+
if (row > LEGEND_MAX_ENTRY_ROWS) {
|
|
1956
|
+
return {
|
|
1957
|
+
width: maxCapsuleW,
|
|
1958
|
+
entryRows: LEGEND_MAX_ENTRY_ROWS,
|
|
1959
|
+
moreCount: entries.length - visible,
|
|
1960
|
+
visibleEntries: visible
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
rowX += ew2;
|
|
1965
|
+
visible++;
|
|
1966
|
+
}
|
|
1967
|
+
return {
|
|
1968
|
+
width: maxCapsuleW,
|
|
1969
|
+
entryRows: row,
|
|
1970
|
+
moreCount: 0,
|
|
1971
|
+
visibleEntries: entries.length
|
|
1972
|
+
};
|
|
1973
|
+
}
|
|
1974
|
+
function computeLegendLayout(config, state, containerWidth) {
|
|
1975
|
+
const { groups, controls: configControls, mode } = config;
|
|
1976
|
+
const isExport = mode === "inline";
|
|
1977
|
+
const activeGroupName = state.activeGroup?.toLowerCase() ?? null;
|
|
1978
|
+
if (isExport && !activeGroupName) {
|
|
1979
|
+
return {
|
|
1980
|
+
height: 0,
|
|
1981
|
+
width: 0,
|
|
1982
|
+
rows: [],
|
|
1983
|
+
controls: [],
|
|
1984
|
+
pills: [],
|
|
1985
|
+
activeCapsule: void 0
|
|
1986
|
+
};
|
|
1987
|
+
}
|
|
1988
|
+
const visibleGroups = config.showEmptyGroups ? groups : groups.filter((g) => g.entries.length > 0);
|
|
1989
|
+
if (visibleGroups.length === 0 && (!configControls || configControls.length === 0)) {
|
|
1990
|
+
return {
|
|
1991
|
+
height: 0,
|
|
1992
|
+
width: 0,
|
|
1993
|
+
rows: [],
|
|
1994
|
+
controls: [],
|
|
1995
|
+
pills: [],
|
|
1996
|
+
activeCapsule: void 0
|
|
1997
|
+
};
|
|
1998
|
+
}
|
|
1999
|
+
const controlLayouts = [];
|
|
2000
|
+
let totalControlsW = 0;
|
|
2001
|
+
if (configControls && !isExport) {
|
|
2002
|
+
for (const ctrl of configControls) {
|
|
2003
|
+
const w = controlWidth(ctrl);
|
|
2004
|
+
controlLayouts.push({
|
|
2005
|
+
id: ctrl.id,
|
|
2006
|
+
x: 0,
|
|
2007
|
+
// positioned later
|
|
2008
|
+
y: 0,
|
|
2009
|
+
width: w,
|
|
2010
|
+
height: LEGEND_HEIGHT,
|
|
2011
|
+
icon: ctrl.icon,
|
|
2012
|
+
label: ctrl.label,
|
|
2013
|
+
exportBehavior: ctrl.exportBehavior,
|
|
2014
|
+
children: ctrl.children?.map((c) => ({
|
|
2015
|
+
id: c.id,
|
|
2016
|
+
label: c.label,
|
|
2017
|
+
x: 0,
|
|
2018
|
+
y: 0,
|
|
2019
|
+
width: measureLegendText(c.label, CONTROL_FONT_SIZE) + 12,
|
|
2020
|
+
isActive: c.isActive
|
|
2021
|
+
}))
|
|
2022
|
+
});
|
|
2023
|
+
totalControlsW += w + CONTROL_GAP;
|
|
2024
|
+
}
|
|
2025
|
+
if (totalControlsW > 0) totalControlsW -= CONTROL_GAP;
|
|
2026
|
+
} else if (configControls && isExport) {
|
|
2027
|
+
for (const ctrl of configControls) {
|
|
2028
|
+
if (ctrl.exportBehavior === "strip") continue;
|
|
2029
|
+
const w = controlWidth(ctrl);
|
|
2030
|
+
controlLayouts.push({
|
|
2031
|
+
id: ctrl.id,
|
|
2032
|
+
x: 0,
|
|
2033
|
+
y: 0,
|
|
2034
|
+
width: w,
|
|
2035
|
+
height: LEGEND_HEIGHT,
|
|
2036
|
+
icon: ctrl.icon,
|
|
2037
|
+
label: ctrl.label,
|
|
2038
|
+
exportBehavior: ctrl.exportBehavior,
|
|
2039
|
+
children: ctrl.children?.map((c) => ({
|
|
2040
|
+
id: c.id,
|
|
2041
|
+
label: c.label,
|
|
2042
|
+
x: 0,
|
|
2043
|
+
y: 0,
|
|
2044
|
+
width: measureLegendText(c.label, CONTROL_FONT_SIZE) + 12,
|
|
2045
|
+
isActive: c.isActive
|
|
2046
|
+
}))
|
|
2047
|
+
});
|
|
2048
|
+
totalControlsW += w + CONTROL_GAP;
|
|
2049
|
+
}
|
|
2050
|
+
if (totalControlsW > 0) totalControlsW -= CONTROL_GAP;
|
|
2051
|
+
}
|
|
2052
|
+
const controlsSpace = totalControlsW > 0 ? totalControlsW + LEGEND_GROUP_GAP * 2 : 0;
|
|
2053
|
+
const groupAvailW = containerWidth - controlsSpace;
|
|
2054
|
+
const pills = [];
|
|
2055
|
+
let activeCapsule;
|
|
2056
|
+
for (const g of visibleGroups) {
|
|
2057
|
+
const isActive = activeGroupName === g.name.toLowerCase();
|
|
2058
|
+
if (isExport && !isActive) continue;
|
|
2059
|
+
if (isActive) {
|
|
2060
|
+
activeCapsule = buildCapsuleLayout(
|
|
2061
|
+
g,
|
|
2062
|
+
containerWidth,
|
|
2063
|
+
config.capsulePillAddonWidth ?? 0
|
|
2064
|
+
);
|
|
2065
|
+
} else {
|
|
2066
|
+
const pw = pillWidth(g.name);
|
|
2067
|
+
pills.push({
|
|
2068
|
+
groupName: g.name,
|
|
2069
|
+
x: 0,
|
|
2070
|
+
y: 0,
|
|
2071
|
+
width: pw,
|
|
2072
|
+
height: LEGEND_HEIGHT,
|
|
2073
|
+
isActive: false
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
const rows = layoutRows(
|
|
2078
|
+
activeCapsule,
|
|
2079
|
+
pills,
|
|
2080
|
+
controlLayouts,
|
|
2081
|
+
groupAvailW,
|
|
2082
|
+
containerWidth,
|
|
2083
|
+
totalControlsW
|
|
2084
|
+
);
|
|
2085
|
+
const height = rows.length * LEGEND_HEIGHT;
|
|
2086
|
+
const width = containerWidth;
|
|
2087
|
+
return {
|
|
2088
|
+
height,
|
|
2089
|
+
width,
|
|
2090
|
+
rows,
|
|
2091
|
+
activeCapsule,
|
|
2092
|
+
controls: controlLayouts,
|
|
2093
|
+
pills
|
|
2094
|
+
};
|
|
2095
|
+
}
|
|
2096
|
+
function buildCapsuleLayout(group, containerWidth, addonWidth = 0) {
|
|
2097
|
+
const pw = pillWidth(group.name);
|
|
2098
|
+
const info = capsuleWidth(
|
|
2099
|
+
group.name,
|
|
2100
|
+
group.entries,
|
|
2101
|
+
containerWidth,
|
|
2102
|
+
addonWidth
|
|
2103
|
+
);
|
|
2104
|
+
const pill = {
|
|
2105
|
+
groupName: group.name,
|
|
2106
|
+
x: LEGEND_CAPSULE_PAD,
|
|
2107
|
+
y: LEGEND_CAPSULE_PAD,
|
|
2108
|
+
width: pw,
|
|
2109
|
+
height: LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2,
|
|
2110
|
+
isActive: true
|
|
2111
|
+
};
|
|
2112
|
+
const entries = [];
|
|
2113
|
+
let ex = LEGEND_CAPSULE_PAD + pw + 4 + addonWidth;
|
|
2114
|
+
let ey = 0;
|
|
2115
|
+
let rowX = ex;
|
|
2116
|
+
const maxRowW = containerWidth - LEGEND_CAPSULE_PAD * 2;
|
|
2117
|
+
let currentRow = 0;
|
|
2118
|
+
for (let i = 0; i < info.visibleEntries; i++) {
|
|
2119
|
+
const entry = group.entries[i];
|
|
2120
|
+
const ew = entryWidth(entry.value);
|
|
2121
|
+
if (rowX + ew > maxRowW && rowX > ex && i > 0) {
|
|
2122
|
+
currentRow++;
|
|
2123
|
+
rowX = 0;
|
|
2124
|
+
ey = currentRow * LEGEND_HEIGHT;
|
|
2125
|
+
if (currentRow === 0) ex = LEGEND_CAPSULE_PAD + pw + 4;
|
|
2126
|
+
}
|
|
2127
|
+
const dotCx = rowX + LEGEND_DOT_R;
|
|
2128
|
+
const dotCy = ey + LEGEND_HEIGHT / 2;
|
|
2129
|
+
const textX = rowX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
2130
|
+
const textY = ey + LEGEND_HEIGHT / 2;
|
|
2131
|
+
entries.push({
|
|
2132
|
+
value: entry.value,
|
|
2133
|
+
color: entry.color,
|
|
2134
|
+
x: rowX,
|
|
2135
|
+
y: ey,
|
|
2136
|
+
dotCx,
|
|
2137
|
+
dotCy,
|
|
2138
|
+
textX,
|
|
2139
|
+
textY
|
|
2140
|
+
});
|
|
2141
|
+
rowX += ew;
|
|
2142
|
+
}
|
|
2143
|
+
const totalRows = info.entryRows;
|
|
2144
|
+
const capsuleH = totalRows * LEGEND_HEIGHT;
|
|
2145
|
+
return {
|
|
2146
|
+
groupName: group.name,
|
|
2147
|
+
x: 0,
|
|
2148
|
+
y: 0,
|
|
2149
|
+
width: info.width,
|
|
2150
|
+
height: capsuleH,
|
|
2151
|
+
pill,
|
|
2152
|
+
entries,
|
|
2153
|
+
moreCount: info.moreCount > 0 ? info.moreCount : void 0,
|
|
2154
|
+
addonX: addonWidth > 0 ? LEGEND_CAPSULE_PAD + pw + 4 : void 0
|
|
2155
|
+
};
|
|
2156
|
+
}
|
|
2157
|
+
function layoutRows(activeCapsule, pills, controls, groupAvailW, containerWidth, totalControlsW) {
|
|
2158
|
+
const rows = [];
|
|
2159
|
+
const groupItems = [];
|
|
2160
|
+
if (activeCapsule) groupItems.push(activeCapsule);
|
|
2161
|
+
groupItems.push(...pills);
|
|
2162
|
+
let currentRowItems = [];
|
|
2163
|
+
let currentRowW = 0;
|
|
2164
|
+
let rowY = 0;
|
|
2165
|
+
for (const item of groupItems) {
|
|
2166
|
+
const itemW = item.width + LEGEND_GROUP_GAP;
|
|
2167
|
+
if (currentRowW + item.width > groupAvailW && currentRowItems.length > 0) {
|
|
2168
|
+
centerRowItems(currentRowItems, containerWidth, totalControlsW);
|
|
2169
|
+
rows.push({ y: rowY, items: currentRowItems });
|
|
2170
|
+
rowY += LEGEND_HEIGHT;
|
|
2171
|
+
currentRowItems = [];
|
|
2172
|
+
currentRowW = 0;
|
|
2173
|
+
}
|
|
2174
|
+
item.x = currentRowW;
|
|
2175
|
+
item.y = rowY;
|
|
2176
|
+
currentRowItems.push(item);
|
|
2177
|
+
currentRowW += itemW;
|
|
2178
|
+
}
|
|
2179
|
+
if (controls.length > 0) {
|
|
2180
|
+
let cx = containerWidth;
|
|
2181
|
+
for (let i = controls.length - 1; i >= 0; i--) {
|
|
2182
|
+
cx -= controls[i].width;
|
|
2183
|
+
controls[i].x = cx;
|
|
2184
|
+
controls[i].y = 0;
|
|
2185
|
+
cx -= CONTROL_GAP;
|
|
2186
|
+
}
|
|
2187
|
+
if (rows.length > 0) {
|
|
2188
|
+
rows[0].items.push(...controls);
|
|
2189
|
+
} else if (currentRowItems.length > 0) {
|
|
2190
|
+
currentRowItems.push(...controls);
|
|
2191
|
+
} else {
|
|
2192
|
+
currentRowItems.push(...controls);
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
if (currentRowItems.length > 0) {
|
|
2196
|
+
centerRowItems(currentRowItems, containerWidth, totalControlsW);
|
|
2197
|
+
rows.push({ y: rowY, items: currentRowItems });
|
|
2198
|
+
}
|
|
2199
|
+
if (rows.length === 0) {
|
|
2200
|
+
rows.push({ y: 0, items: [] });
|
|
2201
|
+
}
|
|
2202
|
+
return rows;
|
|
2203
|
+
}
|
|
2204
|
+
function centerRowItems(items, containerWidth, totalControlsW) {
|
|
2205
|
+
const groupItems = items.filter((it) => "groupName" in it);
|
|
2206
|
+
if (groupItems.length === 0) return;
|
|
2207
|
+
const totalGroupW = groupItems.reduce((s, it) => s + it.width, 0) + (groupItems.length - 1) * LEGEND_GROUP_GAP;
|
|
2208
|
+
const availW = containerWidth - (totalControlsW > 0 ? totalControlsW + LEGEND_GROUP_GAP * 2 : 0);
|
|
2209
|
+
const offset = Math.max(0, (availW - totalGroupW) / 2);
|
|
2210
|
+
let x = offset;
|
|
2211
|
+
for (const item of groupItems) {
|
|
2212
|
+
item.x = x;
|
|
2213
|
+
x += item.width + LEGEND_GROUP_GAP;
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
function getLegendReservedHeight(config, state, containerWidth) {
|
|
2217
|
+
const layout = computeLegendLayout(config, state, containerWidth);
|
|
2218
|
+
return layout.height;
|
|
2219
|
+
}
|
|
2220
|
+
var LEGEND_MAX_ENTRY_ROWS, CONTROL_PILL_PAD, CONTROL_FONT_SIZE, CONTROL_ICON_GAP, CONTROL_GAP;
|
|
2221
|
+
var init_legend_layout = __esm({
|
|
2222
|
+
"src/utils/legend-layout.ts"() {
|
|
2223
|
+
"use strict";
|
|
2224
|
+
init_legend_constants();
|
|
2225
|
+
LEGEND_MAX_ENTRY_ROWS = 3;
|
|
2226
|
+
CONTROL_PILL_PAD = 16;
|
|
2227
|
+
CONTROL_FONT_SIZE = 11;
|
|
2228
|
+
CONTROL_ICON_GAP = 4;
|
|
2229
|
+
CONTROL_GAP = 8;
|
|
2230
|
+
}
|
|
2231
|
+
});
|
|
2232
|
+
|
|
2233
|
+
// src/utils/legend-d3.ts
|
|
2234
|
+
function renderLegendD3(container, config, state, palette, isDark, callbacks, containerWidth) {
|
|
2235
|
+
const width = containerWidth ?? parseFloat(container.attr("width") || "800");
|
|
2236
|
+
let currentState = { ...state };
|
|
2237
|
+
let currentLayout;
|
|
2238
|
+
const legendG = container.append("g").attr("class", "dgmo-legend");
|
|
2239
|
+
function render2() {
|
|
2240
|
+
currentLayout = computeLegendLayout(config, currentState, width);
|
|
2241
|
+
legendG.selectAll("*").remove();
|
|
2242
|
+
if (currentLayout.height === 0) return;
|
|
2243
|
+
if (currentState.activeGroup) {
|
|
2244
|
+
legendG.attr(
|
|
2245
|
+
"data-legend-active",
|
|
2246
|
+
currentState.activeGroup.toLowerCase()
|
|
2247
|
+
);
|
|
2248
|
+
} else {
|
|
2249
|
+
legendG.attr("data-legend-active", null);
|
|
2250
|
+
}
|
|
2251
|
+
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
2252
|
+
const pillBorder = mix(palette.textMuted, palette.bg, 50);
|
|
2253
|
+
if (currentLayout.activeCapsule) {
|
|
2254
|
+
renderCapsule(
|
|
2255
|
+
legendG,
|
|
2256
|
+
currentLayout.activeCapsule,
|
|
2257
|
+
palette,
|
|
2258
|
+
groupBg,
|
|
2259
|
+
pillBorder,
|
|
2260
|
+
isDark,
|
|
2261
|
+
callbacks
|
|
2262
|
+
);
|
|
2263
|
+
}
|
|
2264
|
+
for (const pill of currentLayout.pills) {
|
|
2265
|
+
renderPill(legendG, pill, palette, groupBg, callbacks);
|
|
2266
|
+
}
|
|
2267
|
+
for (const ctrl of currentLayout.controls) {
|
|
2268
|
+
renderControl(
|
|
2269
|
+
legendG,
|
|
2270
|
+
ctrl,
|
|
2271
|
+
palette,
|
|
2272
|
+
groupBg,
|
|
2273
|
+
pillBorder,
|
|
2274
|
+
isDark,
|
|
2275
|
+
config.controls
|
|
2276
|
+
);
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
render2();
|
|
2280
|
+
return {
|
|
2281
|
+
setState(newState) {
|
|
2282
|
+
currentState = { ...newState };
|
|
2283
|
+
render2();
|
|
2284
|
+
},
|
|
2285
|
+
destroy() {
|
|
2286
|
+
legendG.remove();
|
|
2287
|
+
},
|
|
2288
|
+
getHeight() {
|
|
2289
|
+
return currentLayout?.height ?? 0;
|
|
2290
|
+
},
|
|
2291
|
+
getLayout() {
|
|
2292
|
+
return currentLayout;
|
|
2293
|
+
}
|
|
2294
|
+
};
|
|
2295
|
+
}
|
|
2296
|
+
function renderCapsule(parent, capsule, palette, groupBg, pillBorder, _isDark, callbacks) {
|
|
2297
|
+
const g = parent.append("g").attr("transform", `translate(${capsule.x},${capsule.y})`).attr("data-legend-group", capsule.groupName.toLowerCase()).style("cursor", "pointer");
|
|
2298
|
+
g.append("rect").attr("width", capsule.width).attr("height", capsule.height).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
2299
|
+
const pill = capsule.pill;
|
|
2300
|
+
g.append("rect").attr("x", pill.x).attr("y", pill.y).attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", palette.bg);
|
|
2301
|
+
g.append("rect").attr("x", pill.x).attr("y", pill.y).attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", "none").attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
2302
|
+
g.append("text").attr("x", pill.x + pill.width / 2).attr("y", LEGEND_HEIGHT / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", 500).attr("fill", palette.text).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(capsule.groupName);
|
|
2303
|
+
for (const entry of capsule.entries) {
|
|
2304
|
+
const entryG = g.append("g").attr("data-legend-entry", entry.value.toLowerCase()).attr("data-series-name", entry.value).style("cursor", "pointer");
|
|
2305
|
+
entryG.append("circle").attr("cx", entry.dotCx).attr("cy", entry.dotCy).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
2306
|
+
entryG.append("text").attr("x", entry.textX).attr("y", entry.textY).attr("dominant-baseline", "central").attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).attr("font-family", FONT_FAMILY).text(entry.value);
|
|
2307
|
+
if (callbacks?.onEntryHover) {
|
|
2308
|
+
const groupName = capsule.groupName;
|
|
2309
|
+
const entryValue = entry.value;
|
|
2310
|
+
const onHover = callbacks.onEntryHover;
|
|
2311
|
+
entryG.on("mouseenter", () => onHover(groupName, entryValue)).on("mouseleave", () => onHover(groupName, null));
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
if (capsule.moreCount) {
|
|
2315
|
+
const lastEntry = capsule.entries[capsule.entries.length - 1];
|
|
2316
|
+
const moreX = lastEntry ? lastEntry.textX + measureLegendText(lastEntry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_DOT_GAP * 2 : pill.x + pill.width + 8;
|
|
2317
|
+
const moreY = lastEntry?.textY ?? LEGEND_HEIGHT / 2;
|
|
2318
|
+
g.append("text").attr("x", moreX).attr("y", moreY).attr("dominant-baseline", "central").attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("font-style", "italic").attr("fill", palette.textMuted).attr("font-family", FONT_FAMILY).text(`+${capsule.moreCount} more`);
|
|
2319
|
+
}
|
|
2320
|
+
if (callbacks?.onGroupToggle) {
|
|
2321
|
+
const cb = callbacks.onGroupToggle;
|
|
2322
|
+
const name = capsule.groupName;
|
|
2323
|
+
g.on("click", () => cb(name));
|
|
2324
|
+
}
|
|
2325
|
+
if (callbacks?.onGroupRendered) {
|
|
2326
|
+
callbacks.onGroupRendered(capsule.groupName, g, true);
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
function renderPill(parent, pill, palette, groupBg, callbacks) {
|
|
2330
|
+
const g = parent.append("g").attr("transform", `translate(${pill.x},${pill.y})`).attr("data-legend-group", pill.groupName.toLowerCase()).style("cursor", "pointer");
|
|
2331
|
+
g.append("rect").attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", groupBg);
|
|
2332
|
+
g.append("text").attr("x", pill.width / 2).attr("y", pill.height / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", 500).attr("fill", palette.textMuted).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(pill.groupName);
|
|
2333
|
+
if (callbacks?.onGroupToggle) {
|
|
2334
|
+
const cb = callbacks.onGroupToggle;
|
|
2335
|
+
const name = pill.groupName;
|
|
2336
|
+
g.on("click", () => cb(name));
|
|
2337
|
+
}
|
|
2338
|
+
if (callbacks?.onGroupRendered) {
|
|
2339
|
+
callbacks.onGroupRendered(pill.groupName, g, false);
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
function renderControl(parent, ctrl, palette, _groupBg, pillBorder, _isDark, configControls) {
|
|
2343
|
+
const g = parent.append("g").attr("transform", `translate(${ctrl.x},${ctrl.y})`).attr("data-legend-control", ctrl.id).style("cursor", "pointer");
|
|
2344
|
+
if (ctrl.exportBehavior === "strip") {
|
|
2345
|
+
g.attr("data-export-ignore", "true");
|
|
2346
|
+
}
|
|
2347
|
+
g.append("rect").attr("width", ctrl.width).attr("height", ctrl.height).attr("rx", ctrl.height / 2).attr("fill", "none").attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
2348
|
+
let textX = ctrl.width / 2;
|
|
2349
|
+
if (ctrl.icon && ctrl.label) {
|
|
2350
|
+
const iconG = g.append("g").attr("transform", `translate(8,${(ctrl.height - 14) / 2})`);
|
|
2351
|
+
iconG.html(ctrl.icon);
|
|
2352
|
+
textX = 8 + 14 + LEGEND_ENTRY_DOT_GAP + measureLegendText(ctrl.label, LEGEND_PILL_FONT_SIZE) / 2;
|
|
2353
|
+
}
|
|
2354
|
+
if (ctrl.label) {
|
|
2355
|
+
g.append("text").attr("x", textX).attr("y", ctrl.height / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", 500).attr("fill", palette.textMuted).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(ctrl.label);
|
|
2356
|
+
}
|
|
2357
|
+
if (ctrl.children) {
|
|
2358
|
+
let cx = ctrl.width + 4;
|
|
2359
|
+
for (const child of ctrl.children) {
|
|
2360
|
+
const childG = g.append("g").attr("transform", `translate(${cx},0)`).style("cursor", "pointer");
|
|
2361
|
+
childG.append("rect").attr("width", child.width).attr("height", ctrl.height).attr("rx", ctrl.height / 2).attr(
|
|
2362
|
+
"fill",
|
|
2363
|
+
child.isActive ? palette.primary ?? palette.text : "none"
|
|
2364
|
+
).attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
2365
|
+
childG.append("text").attr("x", child.width / 2).attr("y", ctrl.height / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", child.isActive ? palette.bg : palette.textMuted).attr("font-family", FONT_FAMILY).text(child.label);
|
|
2366
|
+
const configCtrl2 = configControls?.find((c) => c.id === ctrl.id);
|
|
2367
|
+
const configChild = configCtrl2?.children?.find((c) => c.id === child.id);
|
|
2368
|
+
if (configChild?.onClick) {
|
|
2369
|
+
const onClick = configChild.onClick;
|
|
2370
|
+
childG.on("click", () => onClick());
|
|
2371
|
+
}
|
|
2372
|
+
cx += child.width + 4;
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
const configCtrl = configControls?.find((c) => c.id === ctrl.id);
|
|
2376
|
+
if (configCtrl?.onClick) {
|
|
2377
|
+
const onClick = configCtrl.onClick;
|
|
2378
|
+
g.on("click", () => onClick());
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
var init_legend_d3 = __esm({
|
|
2382
|
+
"src/utils/legend-d3.ts"() {
|
|
2383
|
+
"use strict";
|
|
2384
|
+
init_legend_constants();
|
|
2385
|
+
init_legend_layout();
|
|
2386
|
+
init_color_utils();
|
|
2387
|
+
init_fonts();
|
|
2388
|
+
}
|
|
2389
|
+
});
|
|
2390
|
+
|
|
1904
2391
|
// src/utils/title-constants.ts
|
|
1905
2392
|
var TITLE_FONT_SIZE, TITLE_FONT_WEIGHT, TITLE_Y, TITLE_OFFSET;
|
|
1906
2393
|
var init_title_constants = __esm({
|
|
@@ -4830,10 +5317,10 @@ var init_chart = __esm({
|
|
|
4830
5317
|
function esc(s) {
|
|
4831
5318
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
4832
5319
|
}
|
|
4833
|
-
function
|
|
5320
|
+
function pillWidth2(name) {
|
|
4834
5321
|
return measureLegendText(name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
4835
5322
|
}
|
|
4836
|
-
function
|
|
5323
|
+
function entriesWidth2(entries) {
|
|
4837
5324
|
let w = 0;
|
|
4838
5325
|
for (const e of entries) {
|
|
4839
5326
|
w += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
@@ -4841,9 +5328,9 @@ function entriesWidth(entries) {
|
|
|
4841
5328
|
return w;
|
|
4842
5329
|
}
|
|
4843
5330
|
function groupTotalWidth(name, entries, isActive) {
|
|
4844
|
-
const pw =
|
|
5331
|
+
const pw = pillWidth2(name);
|
|
4845
5332
|
if (!isActive) return pw;
|
|
4846
|
-
return LEGEND_CAPSULE_PAD * 2 + pw + 4 +
|
|
5333
|
+
return LEGEND_CAPSULE_PAD * 2 + pw + 4 + entriesWidth2(entries);
|
|
4847
5334
|
}
|
|
4848
5335
|
function renderLegendSvg(groups, options) {
|
|
4849
5336
|
if (groups.length === 0) return { svg: "", height: 0, width: 0 };
|
|
@@ -4851,7 +5338,7 @@ function renderLegendSvg(groups, options) {
|
|
|
4851
5338
|
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
4852
5339
|
const items = groups.filter((g) => g.entries.length > 0).map((g) => {
|
|
4853
5340
|
const isActive = !!activeGroup && g.name.toLowerCase() === activeGroup.toLowerCase();
|
|
4854
|
-
const pw =
|
|
5341
|
+
const pw = pillWidth2(g.name);
|
|
4855
5342
|
const tw = groupTotalWidth(g.name, g.entries, isActive);
|
|
4856
5343
|
return { group: g, isActive, pillWidth: pw, totalWidth: tw };
|
|
4857
5344
|
});
|
|
@@ -4905,6 +5392,19 @@ function renderLegendSvg(groups, options) {
|
|
|
4905
5392
|
const svg = `<g${classAttr}${activeAttr}>${parts.join("")}</g>`;
|
|
4906
5393
|
return { svg, height: LEGEND_HEIGHT, width: totalWidth };
|
|
4907
5394
|
}
|
|
5395
|
+
function renderLegendSvgFromConfig(config, state, palette, containerWidth) {
|
|
5396
|
+
return renderLegendSvg(config.groups, {
|
|
5397
|
+
palette: {
|
|
5398
|
+
bg: palette.bg,
|
|
5399
|
+
surface: palette.surface,
|
|
5400
|
+
text: palette.text,
|
|
5401
|
+
textMuted: palette.textMuted
|
|
5402
|
+
},
|
|
5403
|
+
isDark: palette.isDark,
|
|
5404
|
+
containerWidth,
|
|
5405
|
+
activeGroup: state.activeGroup
|
|
5406
|
+
});
|
|
5407
|
+
}
|
|
4908
5408
|
var init_legend_svg = __esm({
|
|
4909
5409
|
"src/utils/legend-svg.ts"() {
|
|
4910
5410
|
"use strict";
|
|
@@ -5334,52 +5834,26 @@ function buildChartCommons(parsed, palette, isDark) {
|
|
|
5334
5834
|
fontFamily: FONT_FAMILY
|
|
5335
5835
|
}
|
|
5336
5836
|
} : void 0;
|
|
5337
|
-
const tooltipTheme = {
|
|
5338
|
-
backgroundColor: palette.surface,
|
|
5339
|
-
borderColor: palette.border,
|
|
5340
|
-
textStyle: { color: palette.text }
|
|
5341
|
-
};
|
|
5342
5837
|
return {
|
|
5343
5838
|
textColor,
|
|
5344
5839
|
axisLineColor,
|
|
5345
5840
|
splitLineColor,
|
|
5346
5841
|
gridOpacity,
|
|
5347
5842
|
colors,
|
|
5348
|
-
titleConfig
|
|
5349
|
-
tooltipTheme
|
|
5843
|
+
titleConfig
|
|
5350
5844
|
};
|
|
5351
5845
|
}
|
|
5352
5846
|
function buildExtendedChartOption(parsed, palette, isDark) {
|
|
5353
5847
|
if (parsed.error) {
|
|
5354
5848
|
return {};
|
|
5355
5849
|
}
|
|
5356
|
-
const {
|
|
5357
|
-
textColor,
|
|
5358
|
-
axisLineColor,
|
|
5359
|
-
gridOpacity,
|
|
5360
|
-
colors,
|
|
5361
|
-
titleConfig,
|
|
5362
|
-
tooltipTheme
|
|
5363
|
-
} = buildChartCommons(parsed, palette, isDark);
|
|
5850
|
+
const { textColor, axisLineColor, gridOpacity, colors, titleConfig } = buildChartCommons(parsed, palette, isDark);
|
|
5364
5851
|
if (parsed.type === "sankey") {
|
|
5365
|
-
return buildSankeyOption(
|
|
5366
|
-
parsed,
|
|
5367
|
-
textColor,
|
|
5368
|
-
colors,
|
|
5369
|
-
titleConfig,
|
|
5370
|
-
tooltipTheme
|
|
5371
|
-
);
|
|
5852
|
+
return buildSankeyOption(parsed, textColor, colors, titleConfig);
|
|
5372
5853
|
}
|
|
5373
5854
|
if (parsed.type === "chord") {
|
|
5374
5855
|
const bg = isDark ? palette.surface : palette.bg;
|
|
5375
|
-
return buildChordOption(
|
|
5376
|
-
parsed,
|
|
5377
|
-
textColor,
|
|
5378
|
-
colors,
|
|
5379
|
-
bg,
|
|
5380
|
-
titleConfig,
|
|
5381
|
-
tooltipTheme
|
|
5382
|
-
);
|
|
5856
|
+
return buildChordOption(parsed, textColor, colors, bg, titleConfig);
|
|
5383
5857
|
}
|
|
5384
5858
|
if (parsed.type === "function") {
|
|
5385
5859
|
return buildFunctionOption(
|
|
@@ -5389,8 +5863,7 @@ function buildExtendedChartOption(parsed, palette, isDark) {
|
|
|
5389
5863
|
axisLineColor,
|
|
5390
5864
|
gridOpacity,
|
|
5391
5865
|
colors,
|
|
5392
|
-
titleConfig
|
|
5393
|
-
tooltipTheme
|
|
5866
|
+
titleConfig
|
|
5394
5867
|
);
|
|
5395
5868
|
}
|
|
5396
5869
|
if (parsed.type === "scatter") {
|
|
@@ -5403,20 +5876,12 @@ function buildExtendedChartOption(parsed, palette, isDark) {
|
|
|
5403
5876
|
gridOpacity,
|
|
5404
5877
|
colors,
|
|
5405
5878
|
bg,
|
|
5406
|
-
titleConfig
|
|
5407
|
-
tooltipTheme
|
|
5879
|
+
titleConfig
|
|
5408
5880
|
);
|
|
5409
5881
|
}
|
|
5410
5882
|
if (parsed.type === "funnel") {
|
|
5411
5883
|
const bg = isDark ? palette.surface : palette.bg;
|
|
5412
|
-
return buildFunnelOption(
|
|
5413
|
-
parsed,
|
|
5414
|
-
textColor,
|
|
5415
|
-
colors,
|
|
5416
|
-
bg,
|
|
5417
|
-
titleConfig,
|
|
5418
|
-
tooltipTheme
|
|
5419
|
-
);
|
|
5884
|
+
return buildFunnelOption(parsed, textColor, colors, bg, titleConfig);
|
|
5420
5885
|
}
|
|
5421
5886
|
return buildHeatmapOption(
|
|
5422
5887
|
parsed,
|
|
@@ -5424,11 +5889,10 @@ function buildExtendedChartOption(parsed, palette, isDark) {
|
|
|
5424
5889
|
isDark,
|
|
5425
5890
|
textColor,
|
|
5426
5891
|
axisLineColor,
|
|
5427
|
-
titleConfig
|
|
5428
|
-
tooltipTheme
|
|
5892
|
+
titleConfig
|
|
5429
5893
|
);
|
|
5430
5894
|
}
|
|
5431
|
-
function buildSankeyOption(parsed, textColor, colors, titleConfig
|
|
5895
|
+
function buildSankeyOption(parsed, textColor, colors, titleConfig) {
|
|
5432
5896
|
const nodeSet = /* @__PURE__ */ new Set();
|
|
5433
5897
|
if (parsed.links) {
|
|
5434
5898
|
for (const link of parsed.links) {
|
|
@@ -5447,17 +5911,15 @@ function buildSankeyOption(parsed, textColor, colors, titleConfig, tooltipTheme)
|
|
|
5447
5911
|
title: titleConfig,
|
|
5448
5912
|
xAxis: { show: false },
|
|
5449
5913
|
yAxis: { show: false },
|
|
5450
|
-
tooltip: {
|
|
5451
|
-
show: false,
|
|
5452
|
-
...tooltipTheme
|
|
5453
|
-
},
|
|
5454
5914
|
series: [
|
|
5455
5915
|
{
|
|
5456
5916
|
type: "sankey",
|
|
5457
5917
|
emphasis: {
|
|
5458
5918
|
focus: "adjacency",
|
|
5459
|
-
blurScope: "global"
|
|
5919
|
+
blurScope: "global",
|
|
5920
|
+
itemStyle: { opacity: 1 }
|
|
5460
5921
|
},
|
|
5922
|
+
blur: BLUR_DIM,
|
|
5461
5923
|
nodeAlign: "left",
|
|
5462
5924
|
nodeGap: 12,
|
|
5463
5925
|
nodeWidth: 20,
|
|
@@ -5480,7 +5942,7 @@ function buildSankeyOption(parsed, textColor, colors, titleConfig, tooltipTheme)
|
|
|
5480
5942
|
]
|
|
5481
5943
|
};
|
|
5482
5944
|
}
|
|
5483
|
-
function buildChordOption(parsed, textColor, colors, bg, titleConfig
|
|
5945
|
+
function buildChordOption(parsed, textColor, colors, bg, titleConfig) {
|
|
5484
5946
|
const nodeSet = /* @__PURE__ */ new Set();
|
|
5485
5947
|
if (parsed.links) {
|
|
5486
5948
|
for (const link of parsed.links) {
|
|
@@ -5514,17 +5976,6 @@ function buildChordOption(parsed, textColor, colors, bg, titleConfig, tooltipThe
|
|
|
5514
5976
|
return {
|
|
5515
5977
|
...CHART_BASE,
|
|
5516
5978
|
title: titleConfig,
|
|
5517
|
-
tooltip: {
|
|
5518
|
-
trigger: "item",
|
|
5519
|
-
...tooltipTheme,
|
|
5520
|
-
formatter: (params) => {
|
|
5521
|
-
const p = params;
|
|
5522
|
-
if (p.data && p.data.source && p.data.target) {
|
|
5523
|
-
return `${p.data.source} \u2192 ${p.data.target}: ${p.data.value}`;
|
|
5524
|
-
}
|
|
5525
|
-
return "";
|
|
5526
|
-
}
|
|
5527
|
-
},
|
|
5528
5979
|
xAxis: { show: false },
|
|
5529
5980
|
yAxis: { show: false },
|
|
5530
5981
|
series: [
|
|
@@ -5583,11 +6034,13 @@ function buildChordOption(parsed, textColor, colors, bg, titleConfig, tooltipThe
|
|
|
5583
6034
|
},
|
|
5584
6035
|
emphasis: {
|
|
5585
6036
|
focus: "adjacency",
|
|
6037
|
+
itemStyle: { opacity: 1 },
|
|
5586
6038
|
lineStyle: {
|
|
5587
6039
|
width: 5,
|
|
5588
6040
|
opacity: 1
|
|
5589
6041
|
}
|
|
5590
|
-
}
|
|
6042
|
+
},
|
|
6043
|
+
blur: BLUR_DIM
|
|
5591
6044
|
}
|
|
5592
6045
|
]
|
|
5593
6046
|
};
|
|
@@ -5601,7 +6054,7 @@ function evaluateExpression(expr, x) {
|
|
|
5601
6054
|
return NaN;
|
|
5602
6055
|
}
|
|
5603
6056
|
}
|
|
5604
|
-
function buildFunctionOption(parsed, palette, textColor, axisLineColor, gridOpacity, colors, titleConfig
|
|
6057
|
+
function buildFunctionOption(parsed, palette, textColor, axisLineColor, gridOpacity, colors, titleConfig) {
|
|
5605
6058
|
const xRange = parsed.xRange ?? { min: -10, max: 10 };
|
|
5606
6059
|
const samples = 200;
|
|
5607
6060
|
const step = (xRange.max - xRange.min) / samples;
|
|
@@ -5634,19 +6087,13 @@ function buildFunctionOption(parsed, palette, textColor, axisLineColor, gridOpac
|
|
|
5634
6087
|
opacity: 0.15
|
|
5635
6088
|
}
|
|
5636
6089
|
},
|
|
5637
|
-
emphasis: EMPHASIS_SELF
|
|
6090
|
+
emphasis: EMPHASIS_SELF,
|
|
6091
|
+
blur: BLUR_DIM
|
|
5638
6092
|
};
|
|
5639
6093
|
});
|
|
5640
6094
|
return {
|
|
5641
6095
|
...CHART_BASE,
|
|
5642
6096
|
title: titleConfig,
|
|
5643
|
-
tooltip: {
|
|
5644
|
-
trigger: "axis",
|
|
5645
|
-
...tooltipTheme,
|
|
5646
|
-
axisPointer: {
|
|
5647
|
-
type: "cross"
|
|
5648
|
-
}
|
|
5649
|
-
},
|
|
5650
6097
|
legend: {
|
|
5651
6098
|
data: (parsed.functions ?? []).map((fn) => fn.name),
|
|
5652
6099
|
bottom: 10,
|
|
@@ -5895,7 +6342,7 @@ function dataToPixel(dataX, dataY, xMin, xMax, yMin, yMax, gridLeftPct, gridRigh
|
|
|
5895
6342
|
const py = gridTopPx + (yMax - dataY) / (yMax - yMin) * plotHeight;
|
|
5896
6343
|
return { px, py };
|
|
5897
6344
|
}
|
|
5898
|
-
function buildScatterOption(parsed, palette, textColor, axisLineColor, gridOpacity, colors, bg, titleConfig
|
|
6345
|
+
function buildScatterOption(parsed, palette, textColor, axisLineColor, gridOpacity, colors, bg, titleConfig) {
|
|
5899
6346
|
const points = parsed.scatterPoints ?? [];
|
|
5900
6347
|
const defaultSize = 15;
|
|
5901
6348
|
const hasCategories = points.some((p) => p.category !== void 0);
|
|
@@ -5911,11 +6358,9 @@ function buildScatterOption(parsed, palette, textColor, axisLineColor, gridOpaci
|
|
|
5911
6358
|
};
|
|
5912
6359
|
const emphasisConfig = {
|
|
5913
6360
|
focus: "self",
|
|
5914
|
-
itemStyle: {
|
|
5915
|
-
shadowBlur: 10,
|
|
5916
|
-
shadowColor: "rgba(0, 0, 0, 0.3)"
|
|
5917
|
-
}
|
|
6361
|
+
itemStyle: { opacity: 1 }
|
|
5918
6362
|
};
|
|
6363
|
+
const blurConfig = BLUR_DIM;
|
|
5919
6364
|
let series;
|
|
5920
6365
|
if (hasCategories) {
|
|
5921
6366
|
const categories2 = [
|
|
@@ -5946,7 +6391,8 @@ function buildScatterOption(parsed, palette, textColor, axisLineColor, gridOpaci
|
|
|
5946
6391
|
borderWidth: CHART_BORDER_WIDTH
|
|
5947
6392
|
},
|
|
5948
6393
|
label: labelConfig,
|
|
5949
|
-
emphasis: emphasisConfig
|
|
6394
|
+
emphasis: emphasisConfig,
|
|
6395
|
+
blur: blurConfig
|
|
5950
6396
|
};
|
|
5951
6397
|
});
|
|
5952
6398
|
} else {
|
|
@@ -5968,24 +6414,11 @@ function buildScatterOption(parsed, palette, textColor, axisLineColor, gridOpaci
|
|
|
5968
6414
|
type: "scatter",
|
|
5969
6415
|
data,
|
|
5970
6416
|
label: labelConfig,
|
|
5971
|
-
emphasis: emphasisConfig
|
|
6417
|
+
emphasis: emphasisConfig,
|
|
6418
|
+
blur: blurConfig
|
|
5972
6419
|
}
|
|
5973
6420
|
];
|
|
5974
6421
|
}
|
|
5975
|
-
const tooltip = {
|
|
5976
|
-
trigger: "item",
|
|
5977
|
-
...tooltipTheme,
|
|
5978
|
-
formatter: (params) => {
|
|
5979
|
-
const p = params;
|
|
5980
|
-
const xLabel = parsed.xlabel || "x";
|
|
5981
|
-
const yLabel = parsed.ylabel || "y";
|
|
5982
|
-
let html = `<strong>${p.name}</strong>`;
|
|
5983
|
-
if (hasCategories) html += `<br/>${p.seriesName}`;
|
|
5984
|
-
html += `<br/>${xLabel}: ${p.value[0]}<br/>${yLabel}: ${p.value[1]}`;
|
|
5985
|
-
if (hasSize) html += `<br/>${parsed.sizelabel || "size"}: ${p.value[2]}`;
|
|
5986
|
-
return html;
|
|
5987
|
-
}
|
|
5988
|
-
};
|
|
5989
6422
|
const xValues = points.map((p) => p.x);
|
|
5990
6423
|
const yValues = points.map((p) => p.y);
|
|
5991
6424
|
const xMin = Math.min(...xValues);
|
|
@@ -6066,7 +6499,6 @@ function buildScatterOption(parsed, palette, textColor, axisLineColor, gridOpaci
|
|
|
6066
6499
|
...CHART_BASE,
|
|
6067
6500
|
title: titleConfig,
|
|
6068
6501
|
...legendConfig && { legend: legendConfig },
|
|
6069
|
-
tooltip,
|
|
6070
6502
|
grid: {
|
|
6071
6503
|
left: `${gridLeft}%`,
|
|
6072
6504
|
right: `${gridRight}%`,
|
|
@@ -6128,7 +6560,7 @@ function buildScatterOption(parsed, palette, textColor, axisLineColor, gridOpaci
|
|
|
6128
6560
|
...graphic && { graphic }
|
|
6129
6561
|
};
|
|
6130
6562
|
}
|
|
6131
|
-
function buildHeatmapOption(parsed, palette, isDark, textColor, axisLineColor, titleConfig
|
|
6563
|
+
function buildHeatmapOption(parsed, palette, isDark, textColor, axisLineColor, titleConfig) {
|
|
6132
6564
|
const bg = isDark ? palette.surface : palette.bg;
|
|
6133
6565
|
const heatmapRows = parsed.heatmapRows ?? [];
|
|
6134
6566
|
const columns = parsed.columns ?? [];
|
|
@@ -6146,16 +6578,6 @@ function buildHeatmapOption(parsed, palette, isDark, textColor, axisLineColor, t
|
|
|
6146
6578
|
return {
|
|
6147
6579
|
...CHART_BASE,
|
|
6148
6580
|
title: titleConfig,
|
|
6149
|
-
tooltip: {
|
|
6150
|
-
trigger: "item",
|
|
6151
|
-
...tooltipTheme,
|
|
6152
|
-
formatter: (params) => {
|
|
6153
|
-
const p = params;
|
|
6154
|
-
const colName = columns[p.data[0]] ?? p.data[0];
|
|
6155
|
-
const rowName = rowLabels[p.data[1]] ?? p.data[1];
|
|
6156
|
-
return `${rowName} / ${colName}: <strong>${p.data[2]}</strong>`;
|
|
6157
|
-
}
|
|
6158
|
-
},
|
|
6159
6581
|
grid: {
|
|
6160
6582
|
left: "3%",
|
|
6161
6583
|
right: "10%",
|
|
@@ -6225,19 +6647,15 @@ function buildHeatmapOption(parsed, palette, isDark, textColor, axisLineColor, t
|
|
|
6225
6647
|
fontWeight: "bold"
|
|
6226
6648
|
},
|
|
6227
6649
|
emphasis: {
|
|
6228
|
-
...EMPHASIS_SELF
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
shadowColor: "rgba(0, 0, 0, 0.5)"
|
|
6232
|
-
}
|
|
6233
|
-
}
|
|
6650
|
+
...EMPHASIS_SELF
|
|
6651
|
+
},
|
|
6652
|
+
blur: BLUR_DIM
|
|
6234
6653
|
}
|
|
6235
6654
|
]
|
|
6236
6655
|
};
|
|
6237
6656
|
}
|
|
6238
|
-
function buildFunnelOption(parsed, textColor, colors, bg, titleConfig
|
|
6657
|
+
function buildFunnelOption(parsed, textColor, colors, bg, titleConfig) {
|
|
6239
6658
|
const sorted = [...parsed.data].sort((a, b) => b.value - a.value);
|
|
6240
|
-
const topValue = sorted.length > 0 ? sorted[0].value : 1;
|
|
6241
6659
|
const data = sorted.map((d) => {
|
|
6242
6660
|
const stroke2 = d.color ?? colors[parsed.data.indexOf(d) % colors.length];
|
|
6243
6661
|
return {
|
|
@@ -6272,25 +6690,6 @@ function buildFunnelOption(parsed, textColor, colors, bg, titleConfig, tooltipTh
|
|
|
6272
6690
|
title: titleConfig,
|
|
6273
6691
|
xAxis: { show: false },
|
|
6274
6692
|
yAxis: { show: false },
|
|
6275
|
-
tooltip: {
|
|
6276
|
-
trigger: "item",
|
|
6277
|
-
...tooltipTheme,
|
|
6278
|
-
formatter: (params) => {
|
|
6279
|
-
const p = params;
|
|
6280
|
-
const val = p.value;
|
|
6281
|
-
const prev = prevValueMap.get(p.name) ?? val;
|
|
6282
|
-
const isFirst = p.dataIndex === 0;
|
|
6283
|
-
if (isFirst) return "";
|
|
6284
|
-
const parts = [];
|
|
6285
|
-
const stepDrop = ((1 - val / prev) * 100).toFixed(1);
|
|
6286
|
-
parts.push(`Step drop-off: ${stepDrop}%`);
|
|
6287
|
-
if (topValue > 0) {
|
|
6288
|
-
const totalDrop = ((1 - val / topValue) * 100).toFixed(1);
|
|
6289
|
-
parts.push(`Overall drop-off: ${totalDrop}%`);
|
|
6290
|
-
}
|
|
6291
|
-
return parts.join("<br/>");
|
|
6292
|
-
}
|
|
6293
|
-
},
|
|
6294
6693
|
series: [
|
|
6295
6694
|
{
|
|
6296
6695
|
type: "funnel",
|
|
@@ -6308,11 +6707,9 @@ function buildFunnelOption(parsed, textColor, colors, bg, titleConfig, tooltipTh
|
|
|
6308
6707
|
lineStyle: { color: textColor, opacity: 0.3 }
|
|
6309
6708
|
},
|
|
6310
6709
|
emphasis: {
|
|
6311
|
-
...EMPHASIS_SELF
|
|
6312
|
-
label: {
|
|
6313
|
-
fontSize: 15
|
|
6314
|
-
}
|
|
6710
|
+
...EMPHASIS_SELF
|
|
6315
6711
|
},
|
|
6712
|
+
blur: BLUR_DIM,
|
|
6316
6713
|
data
|
|
6317
6714
|
},
|
|
6318
6715
|
{
|
|
@@ -6406,8 +6803,7 @@ function buildSimpleChartOption(parsed, palette, isDark, chartWidth) {
|
|
|
6406
6803
|
splitLineColor,
|
|
6407
6804
|
gridOpacity,
|
|
6408
6805
|
colors,
|
|
6409
|
-
titleConfig
|
|
6410
|
-
tooltipTheme
|
|
6806
|
+
titleConfig
|
|
6411
6807
|
} = buildChartCommons(parsed, palette, isDark);
|
|
6412
6808
|
const bg = isDark ? palette.surface : palette.bg;
|
|
6413
6809
|
switch (parsed.type) {
|
|
@@ -6421,7 +6817,6 @@ function buildSimpleChartOption(parsed, palette, isDark, chartWidth) {
|
|
|
6421
6817
|
colors,
|
|
6422
6818
|
bg,
|
|
6423
6819
|
titleConfig,
|
|
6424
|
-
tooltipTheme,
|
|
6425
6820
|
chartWidth
|
|
6426
6821
|
);
|
|
6427
6822
|
case "bar-stacked":
|
|
@@ -6434,7 +6829,6 @@ function buildSimpleChartOption(parsed, palette, isDark, chartWidth) {
|
|
|
6434
6829
|
colors,
|
|
6435
6830
|
bg,
|
|
6436
6831
|
titleConfig,
|
|
6437
|
-
tooltipTheme,
|
|
6438
6832
|
chartWidth
|
|
6439
6833
|
);
|
|
6440
6834
|
case "line":
|
|
@@ -6447,7 +6841,6 @@ function buildSimpleChartOption(parsed, palette, isDark, chartWidth) {
|
|
|
6447
6841
|
gridOpacity,
|
|
6448
6842
|
colors,
|
|
6449
6843
|
titleConfig,
|
|
6450
|
-
tooltipTheme,
|
|
6451
6844
|
chartWidth
|
|
6452
6845
|
) : buildLineOption(
|
|
6453
6846
|
parsed,
|
|
@@ -6457,7 +6850,6 @@ function buildSimpleChartOption(parsed, palette, isDark, chartWidth) {
|
|
|
6457
6850
|
splitLineColor,
|
|
6458
6851
|
gridOpacity,
|
|
6459
6852
|
titleConfig,
|
|
6460
|
-
tooltipTheme,
|
|
6461
6853
|
chartWidth
|
|
6462
6854
|
);
|
|
6463
6855
|
case "area":
|
|
@@ -6469,7 +6861,6 @@ function buildSimpleChartOption(parsed, palette, isDark, chartWidth) {
|
|
|
6469
6861
|
splitLineColor,
|
|
6470
6862
|
gridOpacity,
|
|
6471
6863
|
titleConfig,
|
|
6472
|
-
tooltipTheme,
|
|
6473
6864
|
chartWidth
|
|
6474
6865
|
);
|
|
6475
6866
|
case "pie":
|
|
@@ -6479,7 +6870,6 @@ function buildSimpleChartOption(parsed, palette, isDark, chartWidth) {
|
|
|
6479
6870
|
getSegmentColors(palette, parsed.data.length),
|
|
6480
6871
|
bg,
|
|
6481
6872
|
titleConfig,
|
|
6482
|
-
tooltipTheme,
|
|
6483
6873
|
false
|
|
6484
6874
|
);
|
|
6485
6875
|
case "doughnut":
|
|
@@ -6489,7 +6879,6 @@ function buildSimpleChartOption(parsed, palette, isDark, chartWidth) {
|
|
|
6489
6879
|
getSegmentColors(palette, parsed.data.length),
|
|
6490
6880
|
bg,
|
|
6491
6881
|
titleConfig,
|
|
6492
|
-
tooltipTheme,
|
|
6493
6882
|
true
|
|
6494
6883
|
);
|
|
6495
6884
|
case "radar":
|
|
@@ -6499,8 +6888,7 @@ function buildSimpleChartOption(parsed, palette, isDark, chartWidth) {
|
|
|
6499
6888
|
isDark,
|
|
6500
6889
|
textColor,
|
|
6501
6890
|
gridOpacity,
|
|
6502
|
-
titleConfig
|
|
6503
|
-
tooltipTheme
|
|
6891
|
+
titleConfig
|
|
6504
6892
|
);
|
|
6505
6893
|
case "polar-area":
|
|
6506
6894
|
return buildPolarAreaOption(
|
|
@@ -6508,21 +6896,36 @@ function buildSimpleChartOption(parsed, palette, isDark, chartWidth) {
|
|
|
6508
6896
|
textColor,
|
|
6509
6897
|
getSegmentColors(palette, parsed.data.length),
|
|
6510
6898
|
bg,
|
|
6511
|
-
titleConfig
|
|
6512
|
-
tooltipTheme
|
|
6899
|
+
titleConfig
|
|
6513
6900
|
);
|
|
6514
6901
|
}
|
|
6515
6902
|
}
|
|
6516
6903
|
function makeChartGrid(options) {
|
|
6904
|
+
const left = options.yLabel ? "12%" : "3%";
|
|
6517
6905
|
return {
|
|
6518
|
-
left
|
|
6906
|
+
left,
|
|
6519
6907
|
right: "4%",
|
|
6520
6908
|
bottom: options.hasLegend ? "15%" : options.xLabel ? "10%" : "3%",
|
|
6521
6909
|
top: options.hasTitle ? "15%" : "5%",
|
|
6522
6910
|
containLabel: true
|
|
6523
6911
|
};
|
|
6524
6912
|
}
|
|
6525
|
-
function
|
|
6913
|
+
function wrapLabel(text, maxChars) {
|
|
6914
|
+
const words = text.split(" ");
|
|
6915
|
+
const lines = [];
|
|
6916
|
+
let current = "";
|
|
6917
|
+
for (const word of words) {
|
|
6918
|
+
if (current && current.length + 1 + word.length > maxChars) {
|
|
6919
|
+
lines.push(current);
|
|
6920
|
+
current = word;
|
|
6921
|
+
} else {
|
|
6922
|
+
current = current ? current + " " + word : word;
|
|
6923
|
+
}
|
|
6924
|
+
}
|
|
6925
|
+
if (current) lines.push(current);
|
|
6926
|
+
return lines.join("\n");
|
|
6927
|
+
}
|
|
6928
|
+
function buildBarOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, bg, titleConfig, chartWidth) {
|
|
6526
6929
|
const { xLabel, yLabel } = resolveAxisLabels(parsed);
|
|
6527
6930
|
const isHorizontal = parsed.orientation === "horizontal";
|
|
6528
6931
|
const labels = parsed.data.map((d) => d.label);
|
|
@@ -6537,7 +6940,11 @@ function buildBarOption(parsed, textColor, axisLineColor, splitLineColor, gridOp
|
|
|
6537
6940
|
}
|
|
6538
6941
|
};
|
|
6539
6942
|
});
|
|
6540
|
-
const
|
|
6943
|
+
const catLabels = isHorizontal ? labels.map((l) => wrapLabel(l, 12)) : labels;
|
|
6944
|
+
const maxVisibleLen = Math.max(
|
|
6945
|
+
...catLabels.map((l) => Math.max(...l.split("\n").map((seg) => seg.length)))
|
|
6946
|
+
);
|
|
6947
|
+
const hCatGap = isHorizontal && yLabel ? Math.max(40, maxVisibleLen * 8 + 16) : void 0;
|
|
6541
6948
|
const categoryAxis = makeGridAxis(
|
|
6542
6949
|
"category",
|
|
6543
6950
|
textColor,
|
|
@@ -6545,29 +6952,38 @@ function buildBarOption(parsed, textColor, axisLineColor, splitLineColor, gridOp
|
|
|
6545
6952
|
splitLineColor,
|
|
6546
6953
|
gridOpacity,
|
|
6547
6954
|
isHorizontal ? yLabel : xLabel,
|
|
6548
|
-
|
|
6955
|
+
catLabels,
|
|
6549
6956
|
hCatGap,
|
|
6550
6957
|
!isHorizontal ? chartWidth : void 0
|
|
6551
6958
|
);
|
|
6959
|
+
const hValueGap = isHorizontal && xLabel ? 40 : void 0;
|
|
6552
6960
|
const valueAxis = makeGridAxis(
|
|
6553
6961
|
"value",
|
|
6554
6962
|
textColor,
|
|
6555
6963
|
axisLineColor,
|
|
6556
6964
|
splitLineColor,
|
|
6557
6965
|
gridOpacity,
|
|
6558
|
-
isHorizontal ? xLabel : yLabel
|
|
6966
|
+
isHorizontal ? xLabel : yLabel,
|
|
6967
|
+
void 0,
|
|
6968
|
+
hValueGap
|
|
6559
6969
|
);
|
|
6560
6970
|
return {
|
|
6561
6971
|
...CHART_BASE,
|
|
6562
6972
|
title: titleConfig,
|
|
6563
|
-
grid: makeChartGrid({
|
|
6973
|
+
grid: makeChartGrid({
|
|
6974
|
+
xLabel,
|
|
6975
|
+
yLabel,
|
|
6976
|
+
hasTitle: !!parsed.title,
|
|
6977
|
+
isHorizontal
|
|
6978
|
+
}),
|
|
6564
6979
|
xAxis: isHorizontal ? valueAxis : categoryAxis,
|
|
6565
|
-
yAxis: isHorizontal ? categoryAxis : valueAxis,
|
|
6980
|
+
yAxis: isHorizontal ? { ...categoryAxis, inverse: true } : valueAxis,
|
|
6566
6981
|
series: [
|
|
6567
6982
|
{
|
|
6568
6983
|
type: "bar",
|
|
6569
6984
|
data,
|
|
6570
|
-
emphasis: EMPHASIS_SELF
|
|
6985
|
+
emphasis: EMPHASIS_SELF,
|
|
6986
|
+
blur: BLUR_DIM
|
|
6571
6987
|
}
|
|
6572
6988
|
]
|
|
6573
6989
|
};
|
|
@@ -6584,7 +7000,7 @@ function buildMarkArea(eras, labels, textColor, defaultColor) {
|
|
|
6584
7000
|
if (eras.length === 0) return void 0;
|
|
6585
7001
|
return {
|
|
6586
7002
|
silent: false,
|
|
6587
|
-
tooltip: { show:
|
|
7003
|
+
tooltip: { show: false },
|
|
6588
7004
|
data: eras.map((era) => {
|
|
6589
7005
|
const startIdx = labels.indexOf(era.start);
|
|
6590
7006
|
const endIdx = labels.indexOf(era.end);
|
|
@@ -6607,7 +7023,7 @@ function buildMarkArea(eras, labels, textColor, defaultColor) {
|
|
|
6607
7023
|
})
|
|
6608
7024
|
};
|
|
6609
7025
|
}
|
|
6610
|
-
function buildLineOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, titleConfig,
|
|
7026
|
+
function buildLineOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, titleConfig, chartWidth) {
|
|
6611
7027
|
const { xLabel, yLabel } = resolveAxisLabels(parsed);
|
|
6612
7028
|
const lineColor = parsed.color ?? parsed.seriesNameColors?.[0] ?? palette.primary;
|
|
6613
7029
|
const labels = parsed.data.map((d) => d.label);
|
|
@@ -6618,11 +7034,6 @@ function buildLineOption(parsed, palette, textColor, axisLineColor, splitLineCol
|
|
|
6618
7034
|
return {
|
|
6619
7035
|
...CHART_BASE,
|
|
6620
7036
|
title: titleConfig,
|
|
6621
|
-
tooltip: {
|
|
6622
|
-
trigger: "axis",
|
|
6623
|
-
...tooltipTheme,
|
|
6624
|
-
axisPointer: { type: "line" }
|
|
6625
|
-
},
|
|
6626
7037
|
grid: makeChartGrid({ xLabel, yLabel, hasTitle: !!parsed.title }),
|
|
6627
7038
|
xAxis: makeGridAxis(
|
|
6628
7039
|
"category",
|
|
@@ -6653,12 +7064,13 @@ function buildLineOption(parsed, palette, textColor, axisLineColor, splitLineCol
|
|
|
6653
7064
|
lineStyle: { color: lineColor, width: 3 },
|
|
6654
7065
|
itemStyle: { color: lineColor },
|
|
6655
7066
|
emphasis: EMPHASIS_LINE,
|
|
7067
|
+
blur: BLUR_DIM,
|
|
6656
7068
|
...markArea && { markArea }
|
|
6657
7069
|
}
|
|
6658
7070
|
]
|
|
6659
7071
|
};
|
|
6660
7072
|
}
|
|
6661
|
-
function buildMultiLineOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig,
|
|
7073
|
+
function buildMultiLineOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, chartWidth) {
|
|
6662
7074
|
const { xLabel, yLabel } = resolveAxisLabels(parsed);
|
|
6663
7075
|
const seriesNames = parsed.seriesNames ?? [];
|
|
6664
7076
|
const labels = parsed.data.map((d) => d.label);
|
|
@@ -6679,17 +7091,13 @@ function buildMultiLineOption(parsed, palette, textColor, axisLineColor, splitLi
|
|
|
6679
7091
|
lineStyle: { color, width: 3 },
|
|
6680
7092
|
itemStyle: { color },
|
|
6681
7093
|
emphasis: EMPHASIS_LINE,
|
|
7094
|
+
blur: BLUR_DIM,
|
|
6682
7095
|
...idx === 0 && markArea && { markArea }
|
|
6683
7096
|
};
|
|
6684
7097
|
});
|
|
6685
7098
|
return {
|
|
6686
7099
|
...CHART_BASE,
|
|
6687
7100
|
title: titleConfig,
|
|
6688
|
-
tooltip: {
|
|
6689
|
-
trigger: "axis",
|
|
6690
|
-
...tooltipTheme,
|
|
6691
|
-
axisPointer: { type: "line" }
|
|
6692
|
-
},
|
|
6693
7101
|
legend: {
|
|
6694
7102
|
data: seriesNames,
|
|
6695
7103
|
bottom: 10,
|
|
@@ -6724,7 +7132,7 @@ function buildMultiLineOption(parsed, palette, textColor, axisLineColor, splitLi
|
|
|
6724
7132
|
series
|
|
6725
7133
|
};
|
|
6726
7134
|
}
|
|
6727
|
-
function buildAreaOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, titleConfig,
|
|
7135
|
+
function buildAreaOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, titleConfig, chartWidth) {
|
|
6728
7136
|
const { xLabel, yLabel } = resolveAxisLabels(parsed);
|
|
6729
7137
|
const lineColor = parsed.color ?? parsed.seriesNameColors?.[0] ?? palette.primary;
|
|
6730
7138
|
const labels = parsed.data.map((d) => d.label);
|
|
@@ -6735,11 +7143,6 @@ function buildAreaOption(parsed, palette, textColor, axisLineColor, splitLineCol
|
|
|
6735
7143
|
return {
|
|
6736
7144
|
...CHART_BASE,
|
|
6737
7145
|
title: titleConfig,
|
|
6738
|
-
tooltip: {
|
|
6739
|
-
trigger: "axis",
|
|
6740
|
-
...tooltipTheme,
|
|
6741
|
-
axisPointer: { type: "line" }
|
|
6742
|
-
},
|
|
6743
7146
|
grid: makeChartGrid({ xLabel, yLabel, hasTitle: !!parsed.title }),
|
|
6744
7147
|
xAxis: makeGridAxis(
|
|
6745
7148
|
"category",
|
|
@@ -6771,6 +7174,7 @@ function buildAreaOption(parsed, palette, textColor, axisLineColor, splitLineCol
|
|
|
6771
7174
|
itemStyle: { color: lineColor },
|
|
6772
7175
|
areaStyle: { opacity: 0.25 },
|
|
6773
7176
|
emphasis: EMPHASIS_LINE,
|
|
7177
|
+
blur: BLUR_DIM,
|
|
6774
7178
|
...markArea && { markArea }
|
|
6775
7179
|
}
|
|
6776
7180
|
]
|
|
@@ -6802,7 +7206,7 @@ function pieLabelLayout(parsed) {
|
|
|
6802
7206
|
if (maxLen > 18) return { outerRadius: 55, fontSize: 13 };
|
|
6803
7207
|
return { outerRadius: 70, fontSize: 14 };
|
|
6804
7208
|
}
|
|
6805
|
-
function buildPieOption(parsed, textColor, colors, bg, titleConfig,
|
|
7209
|
+
function buildPieOption(parsed, textColor, colors, bg, titleConfig, isDoughnut) {
|
|
6806
7210
|
const HIDE_AXES = { xAxis: { show: false }, yAxis: { show: false } };
|
|
6807
7211
|
const data = parsed.data.map((d, i) => {
|
|
6808
7212
|
const stroke2 = d.color ?? colors[i % colors.length];
|
|
@@ -6821,10 +7225,6 @@ function buildPieOption(parsed, textColor, colors, bg, titleConfig, tooltipTheme
|
|
|
6821
7225
|
...CHART_BASE,
|
|
6822
7226
|
...HIDE_AXES,
|
|
6823
7227
|
title: titleConfig,
|
|
6824
|
-
tooltip: {
|
|
6825
|
-
trigger: "item",
|
|
6826
|
-
...tooltipTheme
|
|
6827
|
-
},
|
|
6828
7228
|
series: [
|
|
6829
7229
|
{
|
|
6830
7230
|
type: "pie",
|
|
@@ -6838,12 +7238,13 @@ function buildPieOption(parsed, textColor, colors, bg, titleConfig, tooltipTheme
|
|
|
6838
7238
|
fontSize
|
|
6839
7239
|
},
|
|
6840
7240
|
labelLine: { show: true },
|
|
6841
|
-
emphasis: EMPHASIS_SELF
|
|
7241
|
+
emphasis: EMPHASIS_SELF,
|
|
7242
|
+
blur: BLUR_DIM
|
|
6842
7243
|
}
|
|
6843
7244
|
]
|
|
6844
7245
|
};
|
|
6845
7246
|
}
|
|
6846
|
-
function buildRadarOption(parsed, palette, isDark, textColor, gridOpacity, titleConfig
|
|
7247
|
+
function buildRadarOption(parsed, palette, isDark, textColor, gridOpacity, titleConfig) {
|
|
6847
7248
|
const bg = isDark ? palette.surface : palette.bg;
|
|
6848
7249
|
const radarColor = parsed.color ?? parsed.seriesNameColors?.[0] ?? palette.primary;
|
|
6849
7250
|
const values = parsed.data.map((d) => d.value);
|
|
@@ -6857,10 +7258,6 @@ function buildRadarOption(parsed, palette, isDark, textColor, gridOpacity, title
|
|
|
6857
7258
|
title: titleConfig,
|
|
6858
7259
|
xAxis: { show: false },
|
|
6859
7260
|
yAxis: { show: false },
|
|
6860
|
-
tooltip: {
|
|
6861
|
-
trigger: "item",
|
|
6862
|
-
...tooltipTheme
|
|
6863
|
-
},
|
|
6864
7261
|
radar: {
|
|
6865
7262
|
indicator,
|
|
6866
7263
|
axisName: {
|
|
@@ -6897,12 +7294,13 @@ function buildRadarOption(parsed, palette, isDark, textColor, gridOpacity, title
|
|
|
6897
7294
|
}
|
|
6898
7295
|
}
|
|
6899
7296
|
],
|
|
6900
|
-
emphasis: EMPHASIS_SELF
|
|
7297
|
+
emphasis: EMPHASIS_SELF,
|
|
7298
|
+
blur: BLUR_DIM
|
|
6901
7299
|
}
|
|
6902
7300
|
]
|
|
6903
7301
|
};
|
|
6904
7302
|
}
|
|
6905
|
-
function buildPolarAreaOption(parsed, textColor, colors, bg, titleConfig
|
|
7303
|
+
function buildPolarAreaOption(parsed, textColor, colors, bg, titleConfig) {
|
|
6906
7304
|
const data = parsed.data.map((d, i) => {
|
|
6907
7305
|
const stroke2 = d.color ?? colors[i % colors.length];
|
|
6908
7306
|
return {
|
|
@@ -6920,10 +7318,6 @@ function buildPolarAreaOption(parsed, textColor, colors, bg, titleConfig, toolti
|
|
|
6920
7318
|
title: titleConfig,
|
|
6921
7319
|
xAxis: { show: false },
|
|
6922
7320
|
yAxis: { show: false },
|
|
6923
|
-
tooltip: {
|
|
6924
|
-
trigger: "item",
|
|
6925
|
-
...tooltipTheme
|
|
6926
|
-
},
|
|
6927
7321
|
series: [
|
|
6928
7322
|
{
|
|
6929
7323
|
type: "pie",
|
|
@@ -6941,12 +7335,13 @@ function buildPolarAreaOption(parsed, textColor, colors, bg, titleConfig, toolti
|
|
|
6941
7335
|
fontSize: pieLabelLayout(parsed).fontSize
|
|
6942
7336
|
},
|
|
6943
7337
|
labelLine: { show: true },
|
|
6944
|
-
emphasis: EMPHASIS_SELF
|
|
7338
|
+
emphasis: EMPHASIS_SELF,
|
|
7339
|
+
blur: BLUR_DIM
|
|
6945
7340
|
}
|
|
6946
7341
|
]
|
|
6947
7342
|
};
|
|
6948
7343
|
}
|
|
6949
|
-
function buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, bg, titleConfig,
|
|
7344
|
+
function buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, bg, titleConfig, chartWidth) {
|
|
6950
7345
|
const { xLabel, yLabel } = resolveAxisLabels(parsed);
|
|
6951
7346
|
const isHorizontal = parsed.orientation === "horizontal";
|
|
6952
7347
|
const seriesNames = parsed.seriesNames ?? [];
|
|
@@ -6975,7 +7370,8 @@ function buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor,
|
|
|
6975
7370
|
fontWeight: "bold",
|
|
6976
7371
|
fontFamily: FONT_FAMILY
|
|
6977
7372
|
},
|
|
6978
|
-
emphasis:
|
|
7373
|
+
emphasis: EMPHASIS_SERIES,
|
|
7374
|
+
blur: BLUR_DIM
|
|
6979
7375
|
};
|
|
6980
7376
|
});
|
|
6981
7377
|
const hCatGap = isHorizontal && yLabel ? Math.max(40, Math.max(...labels.map((l) => l.length)) * 8 + 16) : void 0;
|
|
@@ -7016,7 +7412,7 @@ function buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor,
|
|
|
7016
7412
|
hasLegend: true
|
|
7017
7413
|
}),
|
|
7018
7414
|
xAxis: isHorizontal ? valueAxis : categoryAxis,
|
|
7019
|
-
yAxis: isHorizontal ? categoryAxis : valueAxis,
|
|
7415
|
+
yAxis: isHorizontal ? { ...categoryAxis, inverse: true } : valueAxis,
|
|
7020
7416
|
series
|
|
7021
7417
|
};
|
|
7022
7418
|
}
|
|
@@ -7100,7 +7496,7 @@ async function renderExtendedChartForExport(content, theme, palette, options) {
|
|
|
7100
7496
|
chart.dispose();
|
|
7101
7497
|
}
|
|
7102
7498
|
}
|
|
7103
|
-
var EMPHASIS_SELF, EMPHASIS_LINE, CHART_BASE, CHART_BORDER_WIDTH, VALID_EXTENDED_TYPES, KNOWN_EXTENDED_OPTIONS, ECHART_EXPORT_WIDTH, ECHART_EXPORT_HEIGHT, STANDARD_CHART_TYPES;
|
|
7499
|
+
var EMPHASIS_SELF, EMPHASIS_SERIES, BLUR_DIM, EMPHASIS_LINE, CHART_BASE, CHART_BORDER_WIDTH, VALID_EXTENDED_TYPES, KNOWN_EXTENDED_OPTIONS, ECHART_EXPORT_WIDTH, ECHART_EXPORT_HEIGHT, STANDARD_CHART_TYPES;
|
|
7104
7500
|
var init_echarts = __esm({
|
|
7105
7501
|
"src/echarts.ts"() {
|
|
7106
7502
|
"use strict";
|
|
@@ -7114,20 +7510,22 @@ var init_echarts = __esm({
|
|
|
7114
7510
|
init_colors();
|
|
7115
7511
|
init_parsing();
|
|
7116
7512
|
init_chart();
|
|
7117
|
-
EMPHASIS_SELF = {
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
}
|
|
7513
|
+
EMPHASIS_SELF = {
|
|
7514
|
+
focus: "self",
|
|
7515
|
+
blurScope: "global",
|
|
7516
|
+
itemStyle: { opacity: 1 }
|
|
7517
|
+
};
|
|
7518
|
+
EMPHASIS_SERIES = {
|
|
7519
|
+
focus: "series",
|
|
7520
|
+
blurScope: "global",
|
|
7521
|
+
itemStyle: { opacity: 1 }
|
|
7127
7522
|
};
|
|
7523
|
+
BLUR_DIM = { itemStyle: { opacity: 0.15 }, lineStyle: { opacity: 0.15 } };
|
|
7524
|
+
EMPHASIS_LINE = { ...EMPHASIS_SELF };
|
|
7128
7525
|
CHART_BASE = {
|
|
7129
7526
|
backgroundColor: "transparent",
|
|
7130
|
-
animation: false
|
|
7527
|
+
animation: false,
|
|
7528
|
+
tooltip: { show: false }
|
|
7131
7529
|
};
|
|
7132
7530
|
CHART_BORDER_WIDTH = 2;
|
|
7133
7531
|
VALID_EXTENDED_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -8459,7 +8857,12 @@ __export(parser_exports7, {
|
|
|
8459
8857
|
function parseArrowLine(trimmed, palette) {
|
|
8460
8858
|
const bareMatch = trimmed.match(BARE_ARROW_RE);
|
|
8461
8859
|
if (bareMatch) {
|
|
8462
|
-
|
|
8860
|
+
const rawTarget = bareMatch[1].trim();
|
|
8861
|
+
const groupMatch = rawTarget.match(/^\[(.+)\]$/);
|
|
8862
|
+
return {
|
|
8863
|
+
target: groupMatch ? groupMatch[1].trim() : rawTarget,
|
|
8864
|
+
targetIsGroup: !!groupMatch
|
|
8865
|
+
};
|
|
8463
8866
|
}
|
|
8464
8867
|
const arrowMatch = trimmed.match(ARROW_RE);
|
|
8465
8868
|
if (arrowMatch) {
|
|
@@ -8468,8 +8871,14 @@ function parseArrowLine(trimmed, palette) {
|
|
|
8468
8871
|
if (label && !color) {
|
|
8469
8872
|
color = inferArrowColor(label);
|
|
8470
8873
|
}
|
|
8471
|
-
const
|
|
8472
|
-
|
|
8874
|
+
const rawTarget = arrowMatch[3].trim();
|
|
8875
|
+
const groupMatch = rawTarget.match(/^\[(.+)\]$/);
|
|
8876
|
+
return {
|
|
8877
|
+
label,
|
|
8878
|
+
color,
|
|
8879
|
+
target: groupMatch ? groupMatch[1].trim() : rawTarget,
|
|
8880
|
+
targetIsGroup: !!groupMatch
|
|
8881
|
+
};
|
|
8473
8882
|
}
|
|
8474
8883
|
return null;
|
|
8475
8884
|
}
|
|
@@ -8531,6 +8940,7 @@ function parseSitemap(content, palette) {
|
|
|
8531
8940
|
const aliasMap = /* @__PURE__ */ new Map();
|
|
8532
8941
|
const indentStack = [];
|
|
8533
8942
|
const labelToNode = /* @__PURE__ */ new Map();
|
|
8943
|
+
const labelToContainer = /* @__PURE__ */ new Map();
|
|
8534
8944
|
const deferredArrows = [];
|
|
8535
8945
|
for (let i = 0; i < lines.length; i++) {
|
|
8536
8946
|
const line10 = lines[i];
|
|
@@ -8632,6 +9042,7 @@ function parseSitemap(content, palette) {
|
|
|
8632
9042
|
deferredArrows.push({
|
|
8633
9043
|
sourceNode: source,
|
|
8634
9044
|
targetLabel: arrowInfo.target,
|
|
9045
|
+
targetIsGroup: arrowInfo.targetIsGroup,
|
|
8635
9046
|
label: arrowInfo.label,
|
|
8636
9047
|
color: arrowInfo.color,
|
|
8637
9048
|
lineNumber
|
|
@@ -8665,6 +9076,7 @@ function parseSitemap(content, palette) {
|
|
|
8665
9076
|
color
|
|
8666
9077
|
};
|
|
8667
9078
|
attachNode2(node, indent, indentStack, result);
|
|
9079
|
+
labelToContainer.set(label.toLowerCase(), node);
|
|
8668
9080
|
} else if (metadataMatch && indentStack.length > 0) {
|
|
8669
9081
|
const rawKey = metadataMatch[1].trim().toLowerCase();
|
|
8670
9082
|
const key = aliasMap.get(rawKey) ?? rawKey;
|
|
@@ -8705,22 +9117,41 @@ function parseSitemap(content, palette) {
|
|
|
8705
9117
|
}
|
|
8706
9118
|
for (const arrow of deferredArrows) {
|
|
8707
9119
|
const targetKey = arrow.targetLabel.toLowerCase();
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
9120
|
+
if (arrow.targetIsGroup) {
|
|
9121
|
+
const targetContainer = labelToContainer.get(targetKey);
|
|
9122
|
+
if (!targetContainer) {
|
|
9123
|
+
const allLabels = Array.from(labelToContainer.keys());
|
|
9124
|
+
let msg = `Group '[${arrow.targetLabel}]' not found`;
|
|
9125
|
+
const hint = suggest(targetKey, allLabels);
|
|
9126
|
+
if (hint) msg += `. ${hint}`;
|
|
9127
|
+
pushError(arrow.lineNumber, msg);
|
|
9128
|
+
continue;
|
|
9129
|
+
}
|
|
9130
|
+
result.edges.push({
|
|
9131
|
+
sourceId: arrow.sourceNode.id,
|
|
9132
|
+
targetId: targetContainer.id,
|
|
9133
|
+
label: arrow.label,
|
|
9134
|
+
color: arrow.color,
|
|
9135
|
+
lineNumber: arrow.lineNumber
|
|
9136
|
+
});
|
|
9137
|
+
} else {
|
|
9138
|
+
const targetNode = labelToNode.get(targetKey);
|
|
9139
|
+
if (!targetNode) {
|
|
9140
|
+
const allLabels = Array.from(labelToNode.keys());
|
|
9141
|
+
let msg = `Arrow target "${arrow.targetLabel}" not found`;
|
|
9142
|
+
const hint = suggest(targetKey, allLabels);
|
|
9143
|
+
if (hint) msg += `. ${hint}`;
|
|
9144
|
+
pushError(arrow.lineNumber, msg);
|
|
9145
|
+
continue;
|
|
9146
|
+
}
|
|
9147
|
+
result.edges.push({
|
|
9148
|
+
sourceId: arrow.sourceNode.id,
|
|
9149
|
+
targetId: targetNode.id,
|
|
9150
|
+
label: arrow.label,
|
|
9151
|
+
color: arrow.color,
|
|
9152
|
+
lineNumber: arrow.lineNumber
|
|
9153
|
+
});
|
|
8716
9154
|
}
|
|
8717
|
-
result.edges.push({
|
|
8718
|
-
sourceId: arrow.sourceNode.id,
|
|
8719
|
-
targetId: targetNode.id,
|
|
8720
|
-
label: arrow.label,
|
|
8721
|
-
color: arrow.color,
|
|
8722
|
-
lineNumber: arrow.lineNumber
|
|
8723
|
-
});
|
|
8724
9155
|
}
|
|
8725
9156
|
if (result.tagGroups.length > 0) {
|
|
8726
9157
|
const allNodes = [];
|
|
@@ -10434,6 +10865,7 @@ function parseBoxesAndLines(content) {
|
|
|
10434
10865
|
const nodeLabels = /* @__PURE__ */ new Set();
|
|
10435
10866
|
const groupLabels = /* @__PURE__ */ new Set();
|
|
10436
10867
|
let lastNodeLabel = null;
|
|
10868
|
+
let lastSourceIsGroup = false;
|
|
10437
10869
|
const groupStack = [];
|
|
10438
10870
|
let contentStarted = false;
|
|
10439
10871
|
let currentTagGroup = null;
|
|
@@ -10672,6 +11104,8 @@ function parseBoxesAndLines(content) {
|
|
|
10672
11104
|
};
|
|
10673
11105
|
groupLabels.add(label);
|
|
10674
11106
|
groupStack.push({ group, indent, depth: currentDepth });
|
|
11107
|
+
lastNodeLabel = label;
|
|
11108
|
+
lastSourceIsGroup = true;
|
|
10675
11109
|
continue;
|
|
10676
11110
|
}
|
|
10677
11111
|
if (trimmed.includes("->") || trimmed.includes("<->")) {
|
|
@@ -10689,7 +11123,8 @@ function parseBoxesAndLines(content) {
|
|
|
10689
11123
|
);
|
|
10690
11124
|
continue;
|
|
10691
11125
|
}
|
|
10692
|
-
|
|
11126
|
+
const sourcePrefix = lastSourceIsGroup ? `[${lastNodeLabel}]` : lastNodeLabel;
|
|
11127
|
+
edgeText = `${sourcePrefix} ${trimmed}`;
|
|
10693
11128
|
}
|
|
10694
11129
|
const edge = parseEdgeLine(
|
|
10695
11130
|
edgeText,
|
|
@@ -10712,6 +11147,7 @@ function parseBoxesAndLines(content) {
|
|
|
10712
11147
|
continue;
|
|
10713
11148
|
}
|
|
10714
11149
|
lastNodeLabel = node.label;
|
|
11150
|
+
lastSourceIsGroup = false;
|
|
10715
11151
|
const gs = currentGroupState();
|
|
10716
11152
|
const isGroupChild = gs && indent > gs.indent;
|
|
10717
11153
|
if (nodeLabels.has(node.label)) {
|
|
@@ -10739,14 +11175,42 @@ function parseBoxesAndLines(content) {
|
|
|
10739
11175
|
const gs = groupStack.pop();
|
|
10740
11176
|
result.groups.push(gs.group);
|
|
10741
11177
|
}
|
|
11178
|
+
const validEdges = [];
|
|
10742
11179
|
for (const edge of result.edges) {
|
|
10743
|
-
|
|
11180
|
+
let valid = true;
|
|
11181
|
+
if (edge.source.startsWith("__group_")) {
|
|
11182
|
+
const label = edge.source.slice("__group_".length);
|
|
11183
|
+
const found = [...groupLabels].some(
|
|
11184
|
+
(g) => g.toLowerCase() === label.toLowerCase()
|
|
11185
|
+
);
|
|
11186
|
+
if (!found) {
|
|
11187
|
+
result.diagnostics.push(
|
|
11188
|
+
makeDgmoError(edge.lineNumber, `Group '[${label}]' not found`)
|
|
11189
|
+
);
|
|
11190
|
+
valid = false;
|
|
11191
|
+
}
|
|
11192
|
+
} else {
|
|
10744
11193
|
ensureNode(edge.source, edge.lineNumber);
|
|
10745
11194
|
}
|
|
10746
|
-
if (
|
|
11195
|
+
if (edge.target.startsWith("__group_")) {
|
|
11196
|
+
const label = edge.target.slice("__group_".length);
|
|
11197
|
+
const found = [...groupLabels].some(
|
|
11198
|
+
(g) => g.toLowerCase() === label.toLowerCase()
|
|
11199
|
+
);
|
|
11200
|
+
if (!found) {
|
|
11201
|
+
result.diagnostics.push(
|
|
11202
|
+
makeDgmoError(edge.lineNumber, `Group '[${label}]' not found`)
|
|
11203
|
+
);
|
|
11204
|
+
valid = false;
|
|
11205
|
+
}
|
|
11206
|
+
} else {
|
|
10747
11207
|
ensureNode(edge.target, edge.lineNumber);
|
|
10748
11208
|
}
|
|
11209
|
+
if (valid) {
|
|
11210
|
+
validEdges.push(edge);
|
|
11211
|
+
}
|
|
10749
11212
|
}
|
|
11213
|
+
result.edges = validEdges;
|
|
10750
11214
|
if (result.tagGroups.length > 0) {
|
|
10751
11215
|
injectDefaultTagMetadata(result.nodes, result.tagGroups);
|
|
10752
11216
|
validateTagValues(result.nodes, result.tagGroups, pushWarning, suggest);
|
|
@@ -10775,10 +11239,14 @@ function parseNodeLine(trimmed, lineNum, aliasMap, _diagnostics) {
|
|
|
10775
11239
|
description
|
|
10776
11240
|
};
|
|
10777
11241
|
}
|
|
11242
|
+
function resolveEndpoint(name) {
|
|
11243
|
+
const m = name.match(/^\[(.+)\]$/);
|
|
11244
|
+
return m ? groupId2(m[1].trim()) : name;
|
|
11245
|
+
}
|
|
10778
11246
|
function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
10779
11247
|
const biLabeledMatch = trimmed.match(/^(.+?)\s*<-(.+)->\s*(.+)$/);
|
|
10780
11248
|
if (biLabeledMatch) {
|
|
10781
|
-
const source2 = biLabeledMatch[1].trim();
|
|
11249
|
+
const source2 = resolveEndpoint(biLabeledMatch[1].trim());
|
|
10782
11250
|
const label = biLabeledMatch[2].trim();
|
|
10783
11251
|
let rest2 = biLabeledMatch[3].trim();
|
|
10784
11252
|
let metadata2 = {};
|
|
@@ -10799,7 +11267,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10799
11267
|
}
|
|
10800
11268
|
return {
|
|
10801
11269
|
source: source2,
|
|
10802
|
-
target: rest2,
|
|
11270
|
+
target: resolveEndpoint(rest2),
|
|
10803
11271
|
label: label || void 0,
|
|
10804
11272
|
bidirectional: true,
|
|
10805
11273
|
lineNumber: lineNum,
|
|
@@ -10808,7 +11276,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10808
11276
|
}
|
|
10809
11277
|
const biIdx = trimmed.indexOf("<->");
|
|
10810
11278
|
if (biIdx >= 0) {
|
|
10811
|
-
const source2 = trimmed.slice(0, biIdx).trim();
|
|
11279
|
+
const source2 = resolveEndpoint(trimmed.slice(0, biIdx).trim());
|
|
10812
11280
|
let rest2 = trimmed.slice(biIdx + 3).trim();
|
|
10813
11281
|
let metadata2 = {};
|
|
10814
11282
|
const pipeIdx2 = rest2.indexOf("|");
|
|
@@ -10828,7 +11296,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10828
11296
|
}
|
|
10829
11297
|
return {
|
|
10830
11298
|
source: source2,
|
|
10831
|
-
target: rest2,
|
|
11299
|
+
target: resolveEndpoint(rest2),
|
|
10832
11300
|
bidirectional: true,
|
|
10833
11301
|
lineNumber: lineNum,
|
|
10834
11302
|
metadata: metadata2
|
|
@@ -10836,7 +11304,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10836
11304
|
}
|
|
10837
11305
|
const labeledMatch = trimmed.match(/^(.+?)\s+-(.+)->\s*(.+)$/);
|
|
10838
11306
|
if (labeledMatch) {
|
|
10839
|
-
const source2 = labeledMatch[1].trim();
|
|
11307
|
+
const source2 = resolveEndpoint(labeledMatch[1].trim());
|
|
10840
11308
|
const label = labeledMatch[2].trim();
|
|
10841
11309
|
let rest2 = labeledMatch[3].trim();
|
|
10842
11310
|
if (label) {
|
|
@@ -10858,7 +11326,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10858
11326
|
}
|
|
10859
11327
|
return {
|
|
10860
11328
|
source: source2,
|
|
10861
|
-
target: rest2,
|
|
11329
|
+
target: resolveEndpoint(rest2),
|
|
10862
11330
|
label,
|
|
10863
11331
|
bidirectional: false,
|
|
10864
11332
|
lineNumber: lineNum,
|
|
@@ -10868,7 +11336,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10868
11336
|
}
|
|
10869
11337
|
const arrowIdx = trimmed.indexOf("->");
|
|
10870
11338
|
if (arrowIdx < 0) return null;
|
|
10871
|
-
const source = trimmed.slice(0, arrowIdx).trim();
|
|
11339
|
+
const source = resolveEndpoint(trimmed.slice(0, arrowIdx).trim());
|
|
10872
11340
|
let rest = trimmed.slice(arrowIdx + 2).trim();
|
|
10873
11341
|
if (!source || !rest) {
|
|
10874
11342
|
diagnostics.push(
|
|
@@ -10889,7 +11357,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10889
11357
|
}
|
|
10890
11358
|
return {
|
|
10891
11359
|
source,
|
|
10892
|
-
target: rest,
|
|
11360
|
+
target: resolveEndpoint(rest),
|
|
10893
11361
|
bidirectional: false,
|
|
10894
11362
|
lineNumber: lineNum,
|
|
10895
11363
|
metadata
|
|
@@ -11204,14 +11672,14 @@ function computeLegendGroups(tagGroups, showEyeIcons, usedValuesByGroup) {
|
|
|
11204
11672
|
const usedValues = usedValuesByGroup?.get(group.name.toLowerCase());
|
|
11205
11673
|
const visibleEntries = usedValues ? group.entries.filter((e) => usedValues.has(e.value.toLowerCase())) : group.entries;
|
|
11206
11674
|
if (visibleEntries.length === 0) continue;
|
|
11207
|
-
const
|
|
11208
|
-
const minPillWidth =
|
|
11209
|
-
let
|
|
11675
|
+
const pillWidth3 = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD2;
|
|
11676
|
+
const minPillWidth = pillWidth3;
|
|
11677
|
+
let entriesWidth3 = 0;
|
|
11210
11678
|
for (const entry of visibleEntries) {
|
|
11211
|
-
|
|
11679
|
+
entriesWidth3 += LEGEND_DOT_R2 * 2 + LEGEND_ENTRY_DOT_GAP2 + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL2;
|
|
11212
11680
|
}
|
|
11213
11681
|
const eyeSpace = showEyeIcons ? LEGEND_EYE_SIZE2 + LEGEND_EYE_GAP2 : 0;
|
|
11214
|
-
const
|
|
11682
|
+
const capsuleWidth2 = LEGEND_CAPSULE_PAD2 * 2 + pillWidth3 + 4 + eyeSpace + entriesWidth3;
|
|
11215
11683
|
groups.push({
|
|
11216
11684
|
name: group.name,
|
|
11217
11685
|
alias: group.alias,
|
|
@@ -11221,7 +11689,7 @@ function computeLegendGroups(tagGroups, showEyeIcons, usedValuesByGroup) {
|
|
|
11221
11689
|
})),
|
|
11222
11690
|
x: 0,
|
|
11223
11691
|
y: 0,
|
|
11224
|
-
width:
|
|
11692
|
+
width: capsuleWidth2,
|
|
11225
11693
|
height: LEGEND_HEIGHT2,
|
|
11226
11694
|
minifiedWidth: minPillWidth,
|
|
11227
11695
|
minifiedHeight: LEGEND_HEIGHT2
|
|
@@ -12162,66 +12630,77 @@ function renderOrg(container, parsed, layout, palette, isDark, onClickItem, expo
|
|
|
12162
12630
|
}
|
|
12163
12631
|
}
|
|
12164
12632
|
if (fixedLegend || legendOnly || exportDims && hasLegend) {
|
|
12165
|
-
const
|
|
12166
|
-
|
|
12167
|
-
|
|
12168
|
-
|
|
12169
|
-
|
|
12170
|
-
|
|
12171
|
-
|
|
12172
|
-
|
|
12173
|
-
|
|
12174
|
-
|
|
12175
|
-
|
|
12176
|
-
|
|
12177
|
-
|
|
12178
|
-
|
|
12179
|
-
|
|
12180
|
-
|
|
12181
|
-
|
|
12182
|
-
|
|
12183
|
-
|
|
12184
|
-
|
|
12633
|
+
const groups = layout.legend.map((g) => ({
|
|
12634
|
+
name: g.name,
|
|
12635
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
12636
|
+
}));
|
|
12637
|
+
const eyeAddonWidth = fixedLegend ? LEGEND_EYE_SIZE + LEGEND_EYE_GAP : 0;
|
|
12638
|
+
const legendParentBase = fixedLegend ? svg.append("g").attr("class", "org-legend-fixed").attr("transform", `translate(0, ${DIAGRAM_PADDING + titleReserve})`) : contentG.append("g");
|
|
12639
|
+
let legendHandle;
|
|
12640
|
+
if (legendOnly) {
|
|
12641
|
+
for (const lg of layout.legend) {
|
|
12642
|
+
const singleConfig = {
|
|
12643
|
+
groups: [
|
|
12644
|
+
{
|
|
12645
|
+
name: lg.name,
|
|
12646
|
+
entries: lg.entries.map((e) => ({
|
|
12647
|
+
value: e.value,
|
|
12648
|
+
color: e.color
|
|
12649
|
+
}))
|
|
12650
|
+
}
|
|
12651
|
+
],
|
|
12652
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
12653
|
+
mode: "fixed"
|
|
12654
|
+
};
|
|
12655
|
+
const singleState = { activeGroup: lg.name };
|
|
12656
|
+
const groupG = legendParentBase.append("g").attr("transform", `translate(${lg.x}, ${lg.y})`);
|
|
12657
|
+
renderLegendD3(
|
|
12658
|
+
groupG,
|
|
12659
|
+
singleConfig,
|
|
12660
|
+
singleState,
|
|
12661
|
+
palette,
|
|
12662
|
+
isDark,
|
|
12663
|
+
void 0,
|
|
12664
|
+
lg.width
|
|
12665
|
+
);
|
|
12666
|
+
groupG.selectAll("[data-legend-group]").classed("org-legend-group", true);
|
|
12667
|
+
}
|
|
12668
|
+
legendHandle = null;
|
|
12669
|
+
} else {
|
|
12670
|
+
const legendConfig = {
|
|
12671
|
+
groups,
|
|
12672
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
12673
|
+
mode: "fixed",
|
|
12674
|
+
capsulePillAddonWidth: eyeAddonWidth
|
|
12675
|
+
};
|
|
12676
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
12677
|
+
legendHandle = renderLegendD3(
|
|
12678
|
+
legendParentBase,
|
|
12679
|
+
legendConfig,
|
|
12680
|
+
legendState,
|
|
12681
|
+
palette,
|
|
12682
|
+
isDark,
|
|
12683
|
+
void 0,
|
|
12684
|
+
fixedLegend ? width : layout.width
|
|
12685
|
+
);
|
|
12686
|
+
legendParentBase.selectAll("[data-legend-group]").classed("org-legend-group", true);
|
|
12185
12687
|
}
|
|
12186
|
-
|
|
12187
|
-
const
|
|
12188
|
-
|
|
12189
|
-
|
|
12190
|
-
|
|
12191
|
-
const gX = fixedPositions?.get(group.name) ?? group.x;
|
|
12192
|
-
const gY = fixedPositions ? 0 : group.y;
|
|
12193
|
-
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");
|
|
12194
|
-
if (isActive) {
|
|
12195
|
-
gEl.append("rect").attr("width", group.width).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
12196
|
-
}
|
|
12197
|
-
const pillXOff = isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
12198
|
-
const pillYOff = LEGEND_CAPSULE_PAD;
|
|
12199
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
12200
|
-
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);
|
|
12201
|
-
if (isActive) {
|
|
12202
|
-
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);
|
|
12203
|
-
}
|
|
12204
|
-
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);
|
|
12205
|
-
if (isActive && fixedLegend) {
|
|
12206
|
-
const groupKey = group.name.toLowerCase();
|
|
12688
|
+
if (fixedLegend && legendHandle) {
|
|
12689
|
+
const computedLayout = legendHandle.getLayout();
|
|
12690
|
+
if (computedLayout.activeCapsule?.addonX != null) {
|
|
12691
|
+
const capsule = computedLayout.activeCapsule;
|
|
12692
|
+
const groupKey = capsule.groupName.toLowerCase();
|
|
12207
12693
|
const isHidden = hiddenAttributes?.has(groupKey) ?? false;
|
|
12208
|
-
const
|
|
12209
|
-
|
|
12210
|
-
|
|
12211
|
-
|
|
12212
|
-
|
|
12213
|
-
|
|
12214
|
-
|
|
12215
|
-
|
|
12216
|
-
|
|
12217
|
-
|
|
12218
|
-
for (const entry of group.entries) {
|
|
12219
|
-
const entryG = gEl.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
12220
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
12221
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
12222
|
-
const entryLabel = entry.value;
|
|
12223
|
-
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);
|
|
12224
|
-
entryX = textX + measureLegendText(entryLabel, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
12694
|
+
const activeGroupEl = legendParentBase.select(
|
|
12695
|
+
`[data-legend-group="${groupKey}"]`
|
|
12696
|
+
);
|
|
12697
|
+
if (!activeGroupEl.empty()) {
|
|
12698
|
+
const eyeX = capsule.addonX;
|
|
12699
|
+
const eyeY = (LEGEND_HEIGHT - LEGEND_EYE_SIZE) / 2;
|
|
12700
|
+
const hitPad = 6;
|
|
12701
|
+
const eyeG = activeGroupEl.append("g").attr("class", "org-legend-eye").attr("data-legend-visibility", groupKey).style("cursor", "pointer").attr("opacity", isHidden ? 0.4 : 0.7);
|
|
12702
|
+
eyeG.append("rect").attr("x", eyeX - hitPad).attr("y", eyeY - hitPad).attr("width", LEGEND_EYE_SIZE + hitPad * 2).attr("height", LEGEND_EYE_SIZE + hitPad * 2).attr("fill", "transparent").attr("pointer-events", "all");
|
|
12703
|
+
eyeG.append("path").attr("d", isHidden ? EYE_CLOSED_PATH : EYE_OPEN_PATH).attr("transform", `translate(${eyeX}, ${eyeY})`).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1.2).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
12225
12704
|
}
|
|
12226
12705
|
}
|
|
12227
12706
|
}
|
|
@@ -12255,6 +12734,7 @@ var init_renderer = __esm({
|
|
|
12255
12734
|
init_parser4();
|
|
12256
12735
|
init_layout();
|
|
12257
12736
|
init_legend_constants();
|
|
12737
|
+
init_legend_d3();
|
|
12258
12738
|
init_title_constants();
|
|
12259
12739
|
DIAGRAM_PADDING = 20;
|
|
12260
12740
|
MAX_SCALE = 3;
|
|
@@ -12284,6 +12764,17 @@ __export(layout_exports2, {
|
|
|
12284
12764
|
layoutSitemap: () => layoutSitemap
|
|
12285
12765
|
});
|
|
12286
12766
|
import dagre from "@dagrejs/dagre";
|
|
12767
|
+
function clipToRectBorder(cx, cy, w, h, tx, ty) {
|
|
12768
|
+
const dx = tx - cx;
|
|
12769
|
+
const dy = ty - cy;
|
|
12770
|
+
if (dx === 0 && dy === 0) return { x: cx, y: cy };
|
|
12771
|
+
const hw = w / 2;
|
|
12772
|
+
const hh = h / 2;
|
|
12773
|
+
const sx = dx !== 0 ? hw / Math.abs(dx) : Infinity;
|
|
12774
|
+
const sy = dy !== 0 ? hh / Math.abs(dy) : Infinity;
|
|
12775
|
+
const s = Math.min(sx, sy);
|
|
12776
|
+
return { x: cx + dx * s, y: cy + dy * s };
|
|
12777
|
+
}
|
|
12287
12778
|
function filterMetadata2(metadata, hiddenAttributes) {
|
|
12288
12779
|
if (!hiddenAttributes || hiddenAttributes.size === 0) return metadata;
|
|
12289
12780
|
const filtered = {};
|
|
@@ -12300,7 +12791,10 @@ function computeCardWidth2(label, meta) {
|
|
|
12300
12791
|
const lineChars = key.length + 2 + value.length;
|
|
12301
12792
|
if (lineChars > maxChars) maxChars = lineChars;
|
|
12302
12793
|
}
|
|
12303
|
-
return Math.max(
|
|
12794
|
+
return Math.max(
|
|
12795
|
+
MIN_CARD_WIDTH2,
|
|
12796
|
+
Math.ceil(maxChars * CHAR_WIDTH2) + CARD_H_PAD2 * 2
|
|
12797
|
+
);
|
|
12304
12798
|
}
|
|
12305
12799
|
function computeCardHeight2(meta) {
|
|
12306
12800
|
const metaCount = Object.keys(meta).length;
|
|
@@ -12309,7 +12803,12 @@ function computeCardHeight2(meta) {
|
|
|
12309
12803
|
}
|
|
12310
12804
|
function resolveNodeColor2(node, tagGroups, activeGroupName) {
|
|
12311
12805
|
if (node.color) return node.color;
|
|
12312
|
-
return resolveTagColor(
|
|
12806
|
+
return resolveTagColor(
|
|
12807
|
+
node.metadata,
|
|
12808
|
+
tagGroups,
|
|
12809
|
+
activeGroupName,
|
|
12810
|
+
node.isContainer
|
|
12811
|
+
);
|
|
12313
12812
|
}
|
|
12314
12813
|
function computeLegendGroups2(tagGroups, usedValuesByGroup) {
|
|
12315
12814
|
const groups = [];
|
|
@@ -12318,21 +12817,21 @@ function computeLegendGroups2(tagGroups, usedValuesByGroup) {
|
|
|
12318
12817
|
const usedValues = usedValuesByGroup?.get(group.name.toLowerCase());
|
|
12319
12818
|
const visibleEntries = usedValues ? group.entries.filter((e) => usedValues.has(e.value.toLowerCase())) : group.entries;
|
|
12320
12819
|
if (visibleEntries.length === 0) continue;
|
|
12321
|
-
const
|
|
12322
|
-
const minPillWidth =
|
|
12323
|
-
let
|
|
12820
|
+
const pillWidth3 = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD3;
|
|
12821
|
+
const minPillWidth = pillWidth3;
|
|
12822
|
+
let entriesWidth3 = 0;
|
|
12324
12823
|
for (const entry of visibleEntries) {
|
|
12325
|
-
|
|
12824
|
+
entriesWidth3 += LEGEND_DOT_R3 * 2 + LEGEND_ENTRY_DOT_GAP3 + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL3;
|
|
12326
12825
|
}
|
|
12327
12826
|
const eyeSpace = LEGEND_EYE_SIZE3 + LEGEND_EYE_GAP3;
|
|
12328
|
-
const
|
|
12827
|
+
const capsuleWidth2 = LEGEND_CAPSULE_PAD3 * 2 + pillWidth3 + 4 + eyeSpace + entriesWidth3;
|
|
12329
12828
|
groups.push({
|
|
12330
12829
|
name: group.name,
|
|
12331
12830
|
alias: group.alias,
|
|
12332
12831
|
entries: visibleEntries.map((e) => ({ value: e.value, color: e.color })),
|
|
12333
12832
|
x: 0,
|
|
12334
12833
|
y: 0,
|
|
12335
|
-
width:
|
|
12834
|
+
width: capsuleWidth2,
|
|
12336
12835
|
height: LEGEND_HEIGHT3,
|
|
12337
12836
|
minifiedWidth: minPillWidth,
|
|
12338
12837
|
minifiedHeight: LEGEND_HEIGHT3
|
|
@@ -12352,10 +12851,20 @@ function flattenNodes(nodes, parentContainerId, parentPageId, hiddenCounts, hidd
|
|
|
12352
12851
|
parentPageId,
|
|
12353
12852
|
meta,
|
|
12354
12853
|
fullMeta: { ...node.metadata },
|
|
12355
|
-
width: Math.max(
|
|
12854
|
+
width: Math.max(
|
|
12855
|
+
MIN_CARD_WIDTH2,
|
|
12856
|
+
node.label.length * CHAR_WIDTH2 + CARD_H_PAD2 * 2
|
|
12857
|
+
),
|
|
12356
12858
|
height: labelHeight + CONTAINER_PAD_BOTTOM2
|
|
12357
12859
|
});
|
|
12358
|
-
flattenNodes(
|
|
12860
|
+
flattenNodes(
|
|
12861
|
+
node.children,
|
|
12862
|
+
node.id,
|
|
12863
|
+
parentPageId,
|
|
12864
|
+
hiddenCounts,
|
|
12865
|
+
hiddenAttributes,
|
|
12866
|
+
result
|
|
12867
|
+
);
|
|
12359
12868
|
} else {
|
|
12360
12869
|
result.push({
|
|
12361
12870
|
sitemapNode: node,
|
|
@@ -12367,14 +12876,28 @@ function flattenNodes(nodes, parentContainerId, parentPageId, hiddenCounts, hidd
|
|
|
12367
12876
|
height: computeCardHeight2(meta)
|
|
12368
12877
|
});
|
|
12369
12878
|
if (node.children.length > 0) {
|
|
12370
|
-
flattenNodes(
|
|
12879
|
+
flattenNodes(
|
|
12880
|
+
node.children,
|
|
12881
|
+
parentContainerId,
|
|
12882
|
+
node.id,
|
|
12883
|
+
hiddenCounts,
|
|
12884
|
+
hiddenAttributes,
|
|
12885
|
+
result
|
|
12886
|
+
);
|
|
12371
12887
|
}
|
|
12372
12888
|
}
|
|
12373
12889
|
}
|
|
12374
12890
|
}
|
|
12375
12891
|
function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, expandAllLegend) {
|
|
12376
12892
|
if (parsed.roots.length === 0) {
|
|
12377
|
-
return {
|
|
12893
|
+
return {
|
|
12894
|
+
nodes: [],
|
|
12895
|
+
edges: [],
|
|
12896
|
+
containers: [],
|
|
12897
|
+
legend: [],
|
|
12898
|
+
width: 0,
|
|
12899
|
+
height: 0
|
|
12900
|
+
};
|
|
12378
12901
|
}
|
|
12379
12902
|
const allNodes = [];
|
|
12380
12903
|
const collect = (node) => {
|
|
@@ -12382,9 +12905,20 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12382
12905
|
for (const child of node.children) collect(child);
|
|
12383
12906
|
};
|
|
12384
12907
|
for (const root of parsed.roots) collect(root);
|
|
12385
|
-
injectDefaultTagMetadata(
|
|
12908
|
+
injectDefaultTagMetadata(
|
|
12909
|
+
allNodes,
|
|
12910
|
+
parsed.tagGroups,
|
|
12911
|
+
(e) => e.isContainer
|
|
12912
|
+
);
|
|
12386
12913
|
const flatNodes = [];
|
|
12387
|
-
flattenNodes(
|
|
12914
|
+
flattenNodes(
|
|
12915
|
+
parsed.roots,
|
|
12916
|
+
null,
|
|
12917
|
+
null,
|
|
12918
|
+
hiddenCounts,
|
|
12919
|
+
hiddenAttributes,
|
|
12920
|
+
flatNodes
|
|
12921
|
+
);
|
|
12388
12922
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
12389
12923
|
for (const flat of flatNodes) {
|
|
12390
12924
|
nodeMap.set(flat.sitemapNode.id, flat);
|
|
@@ -12446,14 +12980,29 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12446
12980
|
g.setParent(flat.sitemapNode.id, flat.parentContainerId);
|
|
12447
12981
|
}
|
|
12448
12982
|
}
|
|
12983
|
+
const expandedContainerIds = /* @__PURE__ */ new Set();
|
|
12984
|
+
for (const cid of containerIds) {
|
|
12985
|
+
if (!collapsedContainerIds.has(cid)) {
|
|
12986
|
+
expandedContainerIds.add(cid);
|
|
12987
|
+
}
|
|
12988
|
+
}
|
|
12989
|
+
const deferredEdgeIndices = [];
|
|
12449
12990
|
for (let i = 0; i < parsed.edges.length; i++) {
|
|
12450
12991
|
const edge = parsed.edges[i];
|
|
12451
|
-
if (g.hasNode(edge.sourceId)
|
|
12452
|
-
|
|
12992
|
+
if (!g.hasNode(edge.sourceId) || !g.hasNode(edge.targetId)) continue;
|
|
12993
|
+
if (expandedContainerIds.has(edge.sourceId) || expandedContainerIds.has(edge.targetId)) {
|
|
12994
|
+
deferredEdgeIndices.push(i);
|
|
12995
|
+
continue;
|
|
12996
|
+
}
|
|
12997
|
+
g.setEdge(
|
|
12998
|
+
edge.sourceId,
|
|
12999
|
+
edge.targetId,
|
|
13000
|
+
{
|
|
12453
13001
|
label: edge.label ?? "",
|
|
12454
13002
|
minlen: 1
|
|
12455
|
-
},
|
|
12456
|
-
|
|
13003
|
+
},
|
|
13004
|
+
`e${i}`
|
|
13005
|
+
);
|
|
12457
13006
|
}
|
|
12458
13007
|
dagre.layout(g);
|
|
12459
13008
|
const layoutNodes = [];
|
|
@@ -12521,19 +13070,52 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12521
13070
|
});
|
|
12522
13071
|
}
|
|
12523
13072
|
}
|
|
13073
|
+
const deferredSet = new Set(deferredEdgeIndices);
|
|
12524
13074
|
const layoutEdges = [];
|
|
12525
13075
|
for (let i = 0; i < parsed.edges.length; i++) {
|
|
12526
13076
|
const edge = parsed.edges[i];
|
|
12527
13077
|
if (!g.hasNode(edge.sourceId) || !g.hasNode(edge.targetId)) continue;
|
|
12528
|
-
|
|
12529
|
-
if (
|
|
13078
|
+
let points;
|
|
13079
|
+
if (deferredSet.has(i)) {
|
|
13080
|
+
const srcNode = g.node(edge.sourceId);
|
|
13081
|
+
const tgtNode = g.node(edge.targetId);
|
|
13082
|
+
if (!srcNode || !tgtNode) continue;
|
|
13083
|
+
const srcPt = clipToRectBorder(
|
|
13084
|
+
srcNode.x,
|
|
13085
|
+
srcNode.y,
|
|
13086
|
+
srcNode.width,
|
|
13087
|
+
srcNode.height,
|
|
13088
|
+
tgtNode.x,
|
|
13089
|
+
tgtNode.y
|
|
13090
|
+
);
|
|
13091
|
+
const tgtPt = clipToRectBorder(
|
|
13092
|
+
tgtNode.x,
|
|
13093
|
+
tgtNode.y,
|
|
13094
|
+
tgtNode.width,
|
|
13095
|
+
tgtNode.height,
|
|
13096
|
+
srcNode.x,
|
|
13097
|
+
srcNode.y
|
|
13098
|
+
);
|
|
13099
|
+
const midX = (srcPt.x + tgtPt.x) / 2;
|
|
13100
|
+
const midY = (srcPt.y + tgtPt.y) / 2;
|
|
13101
|
+
points = [srcPt, { x: midX, y: midY }, tgtPt];
|
|
13102
|
+
} else {
|
|
13103
|
+
const edgeData = g.edge({
|
|
13104
|
+
v: edge.sourceId,
|
|
13105
|
+
w: edge.targetId,
|
|
13106
|
+
name: `e${i}`
|
|
13107
|
+
});
|
|
13108
|
+
if (!edgeData) continue;
|
|
13109
|
+
points = edgeData.points ?? [];
|
|
13110
|
+
}
|
|
12530
13111
|
layoutEdges.push({
|
|
12531
13112
|
sourceId: edge.sourceId,
|
|
12532
13113
|
targetId: edge.targetId,
|
|
12533
|
-
points
|
|
13114
|
+
points,
|
|
12534
13115
|
label: edge.label,
|
|
12535
13116
|
color: edge.color,
|
|
12536
|
-
lineNumber: edge.lineNumber
|
|
13117
|
+
lineNumber: edge.lineNumber,
|
|
13118
|
+
deferred: deferredSet.has(i) || void 0
|
|
12537
13119
|
});
|
|
12538
13120
|
}
|
|
12539
13121
|
{
|
|
@@ -12694,7 +13276,9 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12694
13276
|
usedValuesByGroup.set(key, used);
|
|
12695
13277
|
}
|
|
12696
13278
|
const legendGroups = computeLegendGroups2(parsed.tagGroups, usedValuesByGroup);
|
|
12697
|
-
const visibleGroups = activeTagGroup != null ? legendGroups.filter(
|
|
13279
|
+
const visibleGroups = activeTagGroup != null ? legendGroups.filter(
|
|
13280
|
+
(g2) => g2.name.toLowerCase() === activeTagGroup.toLowerCase()
|
|
13281
|
+
) : legendGroups;
|
|
12698
13282
|
const allExpanded = expandAllLegend && activeTagGroup == null;
|
|
12699
13283
|
const effectiveW = (g2) => activeTagGroup != null || allExpanded ? g2.width : g2.minifiedWidth;
|
|
12700
13284
|
if (visibleGroups.length > 0) {
|
|
@@ -13010,7 +13594,8 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
13010
13594
|
const edgeG = contentG.append("g").attr("class", "sitemap-edge-group").attr("data-line-number", String(edge.lineNumber));
|
|
13011
13595
|
const edgeColor3 = edge.color ?? palette.textMuted;
|
|
13012
13596
|
const markerId = edge.color ? `sm-arrow-${edge.color.replace("#", "")}` : "sm-arrow";
|
|
13013
|
-
const
|
|
13597
|
+
const gen = edge.deferred ? lineGeneratorLinear : lineGenerator;
|
|
13598
|
+
const pathD = gen(edge.points);
|
|
13014
13599
|
if (pathD) {
|
|
13015
13600
|
edgeG.append("path").attr("d", pathD).attr("fill", "none").attr("stroke", edgeColor3).attr("stroke-width", EDGE_STROKE_WIDTH2).attr("marker-end", `url(#${markerId})`).attr("class", "sitemap-edge");
|
|
13016
13601
|
}
|
|
@@ -13101,57 +13686,44 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
13101
13686
|
}
|
|
13102
13687
|
function renderLegend(parent, legendGroups, palette, isDark, activeTagGroup, fixedWidth, hiddenAttributes) {
|
|
13103
13688
|
if (legendGroups.length === 0) return;
|
|
13104
|
-
const
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
|
|
13111
|
-
|
|
13112
|
-
|
|
13113
|
-
|
|
13114
|
-
|
|
13115
|
-
|
|
13116
|
-
|
|
13117
|
-
|
|
13118
|
-
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
|
|
13122
|
-
|
|
13123
|
-
|
|
13124
|
-
|
|
13125
|
-
|
|
13126
|
-
|
|
13127
|
-
|
|
13128
|
-
|
|
13129
|
-
const
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13133
|
-
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);
|
|
13134
|
-
}
|
|
13135
|
-
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);
|
|
13136
|
-
if (isActive && fixedWidth != null) {
|
|
13137
|
-
const groupKey = group.name.toLowerCase();
|
|
13689
|
+
const groups = legendGroups.map((g) => ({
|
|
13690
|
+
name: g.name,
|
|
13691
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
13692
|
+
}));
|
|
13693
|
+
const isFixedMode = fixedWidth != null;
|
|
13694
|
+
const eyeAddonWidth = isFixedMode ? LEGEND_EYE_SIZE + LEGEND_EYE_GAP : 0;
|
|
13695
|
+
const legendConfig = {
|
|
13696
|
+
groups,
|
|
13697
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
13698
|
+
mode: "fixed",
|
|
13699
|
+
capsulePillAddonWidth: eyeAddonWidth
|
|
13700
|
+
};
|
|
13701
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
13702
|
+
const containerWidth = fixedWidth ?? legendGroups[0]?.x + (legendGroups[0]?.width ?? 200);
|
|
13703
|
+
const legendHandle = renderLegendD3(
|
|
13704
|
+
parent,
|
|
13705
|
+
legendConfig,
|
|
13706
|
+
legendState,
|
|
13707
|
+
palette,
|
|
13708
|
+
isDark,
|
|
13709
|
+
void 0,
|
|
13710
|
+
containerWidth
|
|
13711
|
+
);
|
|
13712
|
+
parent.selectAll("[data-legend-group]").classed("sitemap-legend-group", true);
|
|
13713
|
+
if (isFixedMode) {
|
|
13714
|
+
const computedLayout = legendHandle.getLayout();
|
|
13715
|
+
if (computedLayout.activeCapsule?.addonX != null) {
|
|
13716
|
+
const capsule = computedLayout.activeCapsule;
|
|
13717
|
+
const groupKey = capsule.groupName.toLowerCase();
|
|
13138
13718
|
const isHidden = hiddenAttributes?.has(groupKey) ?? false;
|
|
13139
|
-
const
|
|
13140
|
-
|
|
13141
|
-
|
|
13142
|
-
|
|
13143
|
-
|
|
13144
|
-
|
|
13145
|
-
|
|
13146
|
-
|
|
13147
|
-
const eyeShift = fixedWidth != null ? LEGEND_EYE_SIZE + LEGEND_EYE_GAP : 0;
|
|
13148
|
-
let entryX = pillXOff + pillW + 4 + eyeShift;
|
|
13149
|
-
for (const entry of group.entries) {
|
|
13150
|
-
const entryG = legendG.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
13151
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
13152
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
13153
|
-
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);
|
|
13154
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
13719
|
+
const activeGroupEl = parent.select(`[data-legend-group="${groupKey}"]`);
|
|
13720
|
+
if (!activeGroupEl.empty()) {
|
|
13721
|
+
const eyeX = capsule.addonX;
|
|
13722
|
+
const eyeY = (LEGEND_HEIGHT - LEGEND_EYE_SIZE) / 2;
|
|
13723
|
+
const hitPad = 6;
|
|
13724
|
+
const eyeG = activeGroupEl.append("g").attr("class", "sitemap-legend-eye").attr("data-legend-visibility", groupKey).style("cursor", "pointer").attr("opacity", isHidden ? 0.4 : 0.7);
|
|
13725
|
+
eyeG.append("rect").attr("x", eyeX - hitPad).attr("y", eyeY - hitPad).attr("width", LEGEND_EYE_SIZE + hitPad * 2).attr("height", LEGEND_EYE_SIZE + hitPad * 2).attr("fill", "transparent").attr("pointer-events", "all");
|
|
13726
|
+
eyeG.append("path").attr("d", isHidden ? EYE_CLOSED_PATH : EYE_OPEN_PATH).attr("transform", `translate(${eyeX}, ${eyeY})`).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1.2).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
13155
13727
|
}
|
|
13156
13728
|
}
|
|
13157
13729
|
}
|
|
@@ -13205,13 +13777,14 @@ async function renderSitemapForExport(content, theme, palette) {
|
|
|
13205
13777
|
const brandColor = theme === "transparent" ? "#888" : effectivePalette.textMuted;
|
|
13206
13778
|
return injectBranding2(svgHtml, brandColor);
|
|
13207
13779
|
}
|
|
13208
|
-
var DIAGRAM_PADDING2, MAX_SCALE2, TITLE_HEIGHT2, LABEL_FONT_SIZE2, META_FONT_SIZE2, META_LINE_HEIGHT4, HEADER_HEIGHT4, SEPARATOR_GAP4, EDGE_STROKE_WIDTH2, NODE_STROKE_WIDTH2, CARD_RADIUS2, CONTAINER_RADIUS2, CONTAINER_LABEL_FONT_SIZE2, CONTAINER_META_FONT_SIZE2, CONTAINER_META_LINE_HEIGHT4, CONTAINER_HEADER_HEIGHT2, ARROWHEAD_W, ARROWHEAD_H, EDGE_LABEL_FONT_SIZE, COLLAPSE_BAR_HEIGHT2, LEGEND_FIXED_GAP2, lineGenerator;
|
|
13780
|
+
var DIAGRAM_PADDING2, MAX_SCALE2, TITLE_HEIGHT2, LABEL_FONT_SIZE2, META_FONT_SIZE2, META_LINE_HEIGHT4, HEADER_HEIGHT4, SEPARATOR_GAP4, EDGE_STROKE_WIDTH2, NODE_STROKE_WIDTH2, CARD_RADIUS2, CONTAINER_RADIUS2, CONTAINER_LABEL_FONT_SIZE2, CONTAINER_META_FONT_SIZE2, CONTAINER_META_LINE_HEIGHT4, CONTAINER_HEADER_HEIGHT2, ARROWHEAD_W, ARROWHEAD_H, EDGE_LABEL_FONT_SIZE, COLLAPSE_BAR_HEIGHT2, LEGEND_FIXED_GAP2, lineGenerator, lineGeneratorLinear;
|
|
13209
13781
|
var init_renderer2 = __esm({
|
|
13210
13782
|
"src/sitemap/renderer.ts"() {
|
|
13211
13783
|
"use strict";
|
|
13212
13784
|
init_fonts();
|
|
13213
13785
|
init_color_utils();
|
|
13214
13786
|
init_legend_constants();
|
|
13787
|
+
init_legend_d3();
|
|
13215
13788
|
init_title_constants();
|
|
13216
13789
|
DIAGRAM_PADDING2 = 20;
|
|
13217
13790
|
MAX_SCALE2 = 3;
|
|
@@ -13235,6 +13808,7 @@ var init_renderer2 = __esm({
|
|
|
13235
13808
|
COLLAPSE_BAR_HEIGHT2 = 6;
|
|
13236
13809
|
LEGEND_FIXED_GAP2 = 8;
|
|
13237
13810
|
lineGenerator = d3Shape.line().x((d) => d.x).y((d) => d.y).curve(d3Shape.curveBasis);
|
|
13811
|
+
lineGeneratorLinear = d3Shape.line().x((d) => d.x).y((d) => d.y).curve(d3Shape.curveLinear);
|
|
13238
13812
|
}
|
|
13239
13813
|
});
|
|
13240
13814
|
|
|
@@ -13512,53 +14086,22 @@ function renderKanban(container, parsed, palette, isDark, _onNavigateToLine, exp
|
|
|
13512
14086
|
}
|
|
13513
14087
|
if (parsed.tagGroups.length > 0) {
|
|
13514
14088
|
const legendY = height - LEGEND_HEIGHT;
|
|
13515
|
-
|
|
13516
|
-
|
|
13517
|
-
|
|
13518
|
-
|
|
13519
|
-
|
|
13520
|
-
|
|
13521
|
-
}
|
|
13522
|
-
|
|
13523
|
-
|
|
13524
|
-
|
|
13525
|
-
|
|
13526
|
-
|
|
13527
|
-
|
|
13528
|
-
|
|
13529
|
-
|
|
13530
|
-
|
|
13531
|
-
capsuleContentWidth += LEGEND_DOT_R * 2 + 4 + entry.value.length * LEGEND_ENTRY_FONT_SIZE * 0.6 + 8;
|
|
13532
|
-
}
|
|
13533
|
-
}
|
|
13534
|
-
const capsuleWidth = capsuleContentWidth + capsulePad * 2;
|
|
13535
|
-
if (isActive) {
|
|
13536
|
-
legendContainer.append("rect").attr("x", legendX).attr("y", legendY).attr("width", capsuleWidth).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
13537
|
-
}
|
|
13538
|
-
const pillX = legendX + (isActive ? capsulePad : 0);
|
|
13539
|
-
const pillBg = isActive ? palette.bg : groupBg;
|
|
13540
|
-
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());
|
|
13541
|
-
if (isActive) {
|
|
13542
|
-
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);
|
|
13543
|
-
}
|
|
13544
|
-
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);
|
|
13545
|
-
if (isActive) {
|
|
13546
|
-
let entryX = pillX + pillWidth2 + 4;
|
|
13547
|
-
for (const entry of group.entries) {
|
|
13548
|
-
const entryG = legendContainer.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
13549
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", legendY + LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
13550
|
-
const entryTextX = entryX + LEGEND_DOT_R * 2 + 4;
|
|
13551
|
-
entryG.append("text").attr("x", entryTextX).attr(
|
|
13552
|
-
"y",
|
|
13553
|
-
legendY + LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1
|
|
13554
|
-
).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
13555
|
-
entryX = entryTextX + entry.value.length * LEGEND_ENTRY_FONT_SIZE * 0.6 + 8;
|
|
13556
|
-
}
|
|
13557
|
-
legendX += capsuleWidth + 12;
|
|
13558
|
-
} else {
|
|
13559
|
-
legendX += pillWidth2 + 12;
|
|
13560
|
-
}
|
|
13561
|
-
}
|
|
14089
|
+
const legendConfig = {
|
|
14090
|
+
groups: parsed.tagGroups,
|
|
14091
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
14092
|
+
mode: exportDims ? "inline" : "fixed"
|
|
14093
|
+
};
|
|
14094
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
14095
|
+
const legendG = svg.append("g").attr("class", "kanban-legend").attr("transform", `translate(${DIAGRAM_PADDING3},${legendY})`);
|
|
14096
|
+
renderLegendD3(
|
|
14097
|
+
legendG,
|
|
14098
|
+
legendConfig,
|
|
14099
|
+
legendState,
|
|
14100
|
+
palette,
|
|
14101
|
+
isDark,
|
|
14102
|
+
void 0,
|
|
14103
|
+
width - DIAGRAM_PADDING3 * 2
|
|
14104
|
+
);
|
|
13562
14105
|
}
|
|
13563
14106
|
const defaultColBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
13564
14107
|
const defaultColHeaderBg = isDark ? mix(palette.surface, palette.bg, 70) : mix(palette.surface, palette.bg, 50);
|
|
@@ -13653,6 +14196,7 @@ var init_renderer3 = __esm({
|
|
|
13653
14196
|
init_parser5();
|
|
13654
14197
|
init_mutations();
|
|
13655
14198
|
init_legend_constants();
|
|
14199
|
+
init_legend_d3();
|
|
13656
14200
|
init_title_constants();
|
|
13657
14201
|
DIAGRAM_PADDING3 = 20;
|
|
13658
14202
|
COLUMN_GAP = 16;
|
|
@@ -13848,14 +14392,9 @@ function collectClassTypes(parsed) {
|
|
|
13848
14392
|
if (c.color) continue;
|
|
13849
14393
|
present.add(c.modifier ?? "class");
|
|
13850
14394
|
}
|
|
13851
|
-
return CLASS_TYPE_ORDER.filter((k) => present.has(k)).map(
|
|
13852
|
-
|
|
13853
|
-
|
|
13854
|
-
let w = 0;
|
|
13855
|
-
for (const e of entries) {
|
|
13856
|
-
w += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.label, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
13857
|
-
}
|
|
13858
|
-
return w;
|
|
14395
|
+
return CLASS_TYPE_ORDER.filter((k) => present.has(k)).map(
|
|
14396
|
+
(k) => CLASS_TYPE_MAP[k]
|
|
14397
|
+
);
|
|
13859
14398
|
}
|
|
13860
14399
|
function classTypeKey(modifier) {
|
|
13861
14400
|
return modifier ?? "class";
|
|
@@ -13924,7 +14463,10 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
|
|
|
13924
14463
|
defs.append("marker").attr("id", "cd-arrow-depend").attr("viewBox", `0 0 ${AW} ${AH}`).attr("refX", AW).attr("refY", AH / 2).attr("markerWidth", AW).attr("markerHeight", AH).attr("orient", "auto").append("polyline").attr("points", `0,0 ${AW},${AH / 2} 0,${AH}`).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1.5);
|
|
13925
14464
|
defs.append("marker").attr("id", "cd-arrow-assoc").attr("viewBox", `0 0 ${AW} ${AH}`).attr("refX", AW).attr("refY", AH / 2).attr("markerWidth", AW).attr("markerHeight", AH).attr("orient", "auto").append("polyline").attr("points", `0,0 ${AW},${AH / 2} 0,${AH}`).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1.5);
|
|
13926
14465
|
if (parsed.title) {
|
|
13927
|
-
const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).style(
|
|
14466
|
+
const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).style(
|
|
14467
|
+
"cursor",
|
|
14468
|
+
onClickItem && parsed.titleLineNumber ? "pointer" : "default"
|
|
14469
|
+
).text(parsed.title);
|
|
13928
14470
|
if (parsed.titleLineNumber) {
|
|
13929
14471
|
titleEl.attr("data-line-number", parsed.titleLineNumber);
|
|
13930
14472
|
if (onClickItem) {
|
|
@@ -13938,32 +14480,33 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
|
|
|
13938
14480
|
}
|
|
13939
14481
|
const isLegendExpanded = legendActive !== false;
|
|
13940
14482
|
if (hasLegend) {
|
|
13941
|
-
const
|
|
13942
|
-
|
|
13943
|
-
|
|
13944
|
-
|
|
13945
|
-
|
|
13946
|
-
|
|
13947
|
-
|
|
13948
|
-
const legendG = svg.append("g").attr("class", "cd-legend").attr("data-legend-group", "type").attr("transform", `translate(${legendX}, ${legendY})`).style("cursor", "pointer");
|
|
13949
|
-
if (isLegendExpanded) {
|
|
13950
|
-
legendG.append("rect").attr("width", totalW).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
13951
|
-
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);
|
|
13952
|
-
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);
|
|
13953
|
-
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);
|
|
13954
|
-
let entryX = LEGEND_CAPSULE_PAD + pillWidth2 + LEGEND_ENTRY_TRAIL;
|
|
13955
|
-
for (const entry of legendEntries) {
|
|
13956
|
-
const color = palette.colors[entry.colorKey];
|
|
13957
|
-
const typeKey = CLASS_TYPE_ORDER.find((k) => CLASS_TYPE_MAP[k] === entry);
|
|
13958
|
-
const entryG = legendG.append("g").attr("data-legend-entry", typeKey);
|
|
13959
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", color);
|
|
13960
|
-
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);
|
|
13961
|
-
entryX += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(entry.label, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
14483
|
+
const legendGroups = [
|
|
14484
|
+
{
|
|
14485
|
+
name: LEGEND_GROUP_NAME,
|
|
14486
|
+
entries: legendEntries.map((entry) => ({
|
|
14487
|
+
value: entry.label,
|
|
14488
|
+
color: palette.colors[entry.colorKey]
|
|
14489
|
+
}))
|
|
13962
14490
|
}
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
14491
|
+
];
|
|
14492
|
+
const legendConfig = {
|
|
14493
|
+
groups: legendGroups,
|
|
14494
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
14495
|
+
mode: "fixed"
|
|
14496
|
+
};
|
|
14497
|
+
const legendState = {
|
|
14498
|
+
activeGroup: isLegendExpanded ? LEGEND_GROUP_NAME : null
|
|
14499
|
+
};
|
|
14500
|
+
const legendG = svg.append("g").attr("class", "cd-legend").attr("transform", `translate(0,${titleHeight})`);
|
|
14501
|
+
renderLegendD3(
|
|
14502
|
+
legendG,
|
|
14503
|
+
legendConfig,
|
|
14504
|
+
legendState,
|
|
14505
|
+
palette,
|
|
14506
|
+
isDark,
|
|
14507
|
+
void 0,
|
|
14508
|
+
width
|
|
14509
|
+
);
|
|
13967
14510
|
}
|
|
13968
14511
|
const contentG = svg.append("g").attr("transform", `translate(${offsetX}, ${offsetY}) scale(${scale})`);
|
|
13969
14512
|
for (const edge of layout.edges) {
|
|
@@ -14007,7 +14550,13 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
|
|
|
14007
14550
|
const colorOff = !!parsed.options?.["no-auto-color"];
|
|
14008
14551
|
const neutralize = hasLegend && !isLegendExpanded && !node.color;
|
|
14009
14552
|
const effectiveColor = neutralize ? palette.primary : node.color;
|
|
14010
|
-
const fill2 = nodeFill3(
|
|
14553
|
+
const fill2 = nodeFill3(
|
|
14554
|
+
palette,
|
|
14555
|
+
isDark,
|
|
14556
|
+
node.modifier,
|
|
14557
|
+
effectiveColor,
|
|
14558
|
+
colorOff
|
|
14559
|
+
);
|
|
14011
14560
|
const stroke2 = nodeStroke3(palette, node.modifier, effectiveColor, colorOff);
|
|
14012
14561
|
nodeG.append("rect").attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h).attr("rx", 3).attr("ry", 3).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", NODE_STROKE_WIDTH3);
|
|
14013
14562
|
let yPos = -h / 2;
|
|
@@ -14076,15 +14625,10 @@ function renderClassDiagramForExport(content, theme, palette) {
|
|
|
14076
14625
|
const exportWidth = layout.width + DIAGRAM_PADDING4 * 2;
|
|
14077
14626
|
const exportHeight = layout.height + DIAGRAM_PADDING4 * 2 + (parsed.title ? 40 : 0) + legendReserve;
|
|
14078
14627
|
return runInExportContainer(exportWidth, exportHeight, (container) => {
|
|
14079
|
-
renderClassDiagram(
|
|
14080
|
-
|
|
14081
|
-
|
|
14082
|
-
|
|
14083
|
-
palette,
|
|
14084
|
-
isDark,
|
|
14085
|
-
void 0,
|
|
14086
|
-
{ width: exportWidth, height: exportHeight }
|
|
14087
|
-
);
|
|
14628
|
+
renderClassDiagram(container, parsed, layout, palette, isDark, void 0, {
|
|
14629
|
+
width: exportWidth,
|
|
14630
|
+
height: exportHeight
|
|
14631
|
+
});
|
|
14088
14632
|
return extractExportSvg(container, theme);
|
|
14089
14633
|
});
|
|
14090
14634
|
}
|
|
@@ -14095,6 +14639,7 @@ var init_renderer4 = __esm({
|
|
|
14095
14639
|
init_fonts();
|
|
14096
14640
|
init_export_container();
|
|
14097
14641
|
init_legend_constants();
|
|
14642
|
+
init_legend_d3();
|
|
14098
14643
|
init_title_constants();
|
|
14099
14644
|
init_color_utils();
|
|
14100
14645
|
init_parser2();
|
|
@@ -14703,35 +15248,24 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
|
|
|
14703
15248
|
}
|
|
14704
15249
|
}
|
|
14705
15250
|
if (parsed.tagGroups.length > 0) {
|
|
14706
|
-
const LEGEND_PILL_H = LEGEND_HEIGHT - 6;
|
|
14707
|
-
const LEGEND_PILL_RX = Math.floor(LEGEND_PILL_H / 2);
|
|
14708
|
-
const LEGEND_GAP = 8;
|
|
14709
|
-
const legendG = svg.append("g").attr("class", "er-tag-legend");
|
|
14710
|
-
if (activeTagGroup) {
|
|
14711
|
-
legendG.attr("data-legend-active", activeTagGroup.toLowerCase());
|
|
14712
|
-
}
|
|
14713
|
-
let legendX = DIAGRAM_PADDING5;
|
|
14714
15251
|
const legendY = DIAGRAM_PADDING5 + titleHeight;
|
|
14715
|
-
|
|
14716
|
-
|
|
14717
|
-
|
|
14718
|
-
|
|
14719
|
-
|
|
14720
|
-
|
|
14721
|
-
|
|
14722
|
-
|
|
14723
|
-
|
|
14724
|
-
|
|
14725
|
-
|
|
14726
|
-
|
|
14727
|
-
|
|
14728
|
-
|
|
14729
|
-
|
|
14730
|
-
|
|
14731
|
-
|
|
14732
|
-
}
|
|
14733
|
-
legendX += LEGEND_GROUP_GAP;
|
|
14734
|
-
}
|
|
15252
|
+
const legendConfig = {
|
|
15253
|
+
groups: parsed.tagGroups,
|
|
15254
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
15255
|
+
mode: "fixed"
|
|
15256
|
+
};
|
|
15257
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
15258
|
+
const legendG = svg.append("g").attr("class", "er-tag-legend").attr("transform", `translate(0,${legendY})`);
|
|
15259
|
+
renderLegendD3(
|
|
15260
|
+
legendG,
|
|
15261
|
+
legendConfig,
|
|
15262
|
+
legendState,
|
|
15263
|
+
palette,
|
|
15264
|
+
isDark,
|
|
15265
|
+
void 0,
|
|
15266
|
+
viewW
|
|
15267
|
+
);
|
|
15268
|
+
legendG.selectAll("[data-legend-group]").classed("er-legend-group", true);
|
|
14735
15269
|
}
|
|
14736
15270
|
if (semanticRoles) {
|
|
14737
15271
|
const presentRoles = ROLE_ORDER.filter((role) => {
|
|
@@ -14741,55 +15275,35 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
|
|
|
14741
15275
|
return false;
|
|
14742
15276
|
});
|
|
14743
15277
|
if (presentRoles.length > 0) {
|
|
14744
|
-
const measureLabelW = (text, fontSize) => {
|
|
14745
|
-
const dummy = svg.append("text").attr("font-size", fontSize).attr("font-family", FONT_FAMILY).attr("visibility", "hidden").text(text);
|
|
14746
|
-
const measured = dummy.node()?.getComputedTextLength?.() ?? 0;
|
|
14747
|
-
dummy.remove();
|
|
14748
|
-
return measured > 0 ? measured : text.length * fontSize * 0.6;
|
|
14749
|
-
};
|
|
14750
|
-
const labelWidths = /* @__PURE__ */ new Map();
|
|
14751
|
-
for (const role of presentRoles) {
|
|
14752
|
-
labelWidths.set(
|
|
14753
|
-
role,
|
|
14754
|
-
measureLabelW(ROLE_LABELS[role], LEGEND_ENTRY_FONT_SIZE)
|
|
14755
|
-
);
|
|
14756
|
-
}
|
|
14757
|
-
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
14758
|
-
const groupName = "Role";
|
|
14759
|
-
const pillWidth2 = measureLegendText(groupName, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
14760
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
14761
|
-
let totalWidth;
|
|
14762
|
-
let entriesWidth2 = 0;
|
|
14763
|
-
if (semanticActive) {
|
|
14764
|
-
for (const role of presentRoles) {
|
|
14765
|
-
entriesWidth2 += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + labelWidths.get(role) + LEGEND_ENTRY_TRAIL;
|
|
14766
|
-
}
|
|
14767
|
-
totalWidth = LEGEND_CAPSULE_PAD * 2 + pillWidth2 + LEGEND_ENTRY_TRAIL + entriesWidth2;
|
|
14768
|
-
} else {
|
|
14769
|
-
totalWidth = pillWidth2;
|
|
14770
|
-
}
|
|
14771
|
-
const legendX = (viewW - totalWidth) / 2;
|
|
14772
15278
|
const legendY = DIAGRAM_PADDING5 + titleHeight;
|
|
14773
|
-
const
|
|
14774
|
-
|
|
14775
|
-
|
|
14776
|
-
|
|
14777
|
-
|
|
14778
|
-
|
|
14779
|
-
|
|
14780
|
-
for (const role of presentRoles) {
|
|
14781
|
-
const label = ROLE_LABELS[role];
|
|
14782
|
-
const roleColor = palette.colors[ROLE_COLORS[role]];
|
|
14783
|
-
const entryG = semanticLegendG.append("g").attr("data-legend-entry", role);
|
|
14784
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", roleColor);
|
|
14785
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
14786
|
-
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);
|
|
14787
|
-
entryX = textX + labelWidths.get(role) + LEGEND_ENTRY_TRAIL;
|
|
15279
|
+
const semanticGroups = [
|
|
15280
|
+
{
|
|
15281
|
+
name: "Role",
|
|
15282
|
+
entries: presentRoles.map((role) => ({
|
|
15283
|
+
value: ROLE_LABELS[role],
|
|
15284
|
+
color: palette.colors[ROLE_COLORS[role]]
|
|
15285
|
+
}))
|
|
14788
15286
|
}
|
|
14789
|
-
|
|
14790
|
-
|
|
14791
|
-
|
|
14792
|
-
|
|
15287
|
+
];
|
|
15288
|
+
const legendConfig = {
|
|
15289
|
+
groups: semanticGroups,
|
|
15290
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
15291
|
+
mode: "fixed"
|
|
15292
|
+
};
|
|
15293
|
+
const legendState = {
|
|
15294
|
+
activeGroup: semanticActive ? "Role" : null
|
|
15295
|
+
};
|
|
15296
|
+
const legendG = svg.append("g").attr("class", "er-semantic-legend").attr("transform", `translate(0,${legendY})`);
|
|
15297
|
+
renderLegendD3(
|
|
15298
|
+
legendG,
|
|
15299
|
+
legendConfig,
|
|
15300
|
+
legendState,
|
|
15301
|
+
palette,
|
|
15302
|
+
isDark,
|
|
15303
|
+
void 0,
|
|
15304
|
+
viewW
|
|
15305
|
+
);
|
|
15306
|
+
legendG.selectAll("[data-legend-group]").classed("er-legend-group", true);
|
|
14793
15307
|
}
|
|
14794
15308
|
}
|
|
14795
15309
|
}
|
|
@@ -14832,6 +15346,7 @@ var init_renderer5 = __esm({
|
|
|
14832
15346
|
init_palettes();
|
|
14833
15347
|
init_tag_groups();
|
|
14834
15348
|
init_legend_constants();
|
|
15349
|
+
init_legend_d3();
|
|
14835
15350
|
init_title_constants();
|
|
14836
15351
|
init_parser3();
|
|
14837
15352
|
init_layout4();
|
|
@@ -14856,6 +15371,17 @@ __export(layout_exports5, {
|
|
|
14856
15371
|
layoutBoxesAndLines: () => layoutBoxesAndLines
|
|
14857
15372
|
});
|
|
14858
15373
|
import dagre4 from "@dagrejs/dagre";
|
|
15374
|
+
function clipToRectBorder2(cx, cy, w, h, tx, ty) {
|
|
15375
|
+
const dx = tx - cx;
|
|
15376
|
+
const dy = ty - cy;
|
|
15377
|
+
if (dx === 0 && dy === 0) return { x: cx, y: cy };
|
|
15378
|
+
const hw = w / 2;
|
|
15379
|
+
const hh = h / 2;
|
|
15380
|
+
const sx = dx !== 0 ? hw / Math.abs(dx) : Infinity;
|
|
15381
|
+
const sy = dy !== 0 ? hh / Math.abs(dy) : Infinity;
|
|
15382
|
+
const s = Math.min(sx, sy);
|
|
15383
|
+
return { x: cx + dx * s, y: cy + dy * s };
|
|
15384
|
+
}
|
|
14859
15385
|
function computeNodeSize(_node) {
|
|
14860
15386
|
const PHI = 1.618;
|
|
14861
15387
|
const NODE_HEIGHT = 60;
|
|
@@ -15008,13 +15534,25 @@ function layoutBoxesAndLines(parsed, collapseInfo) {
|
|
|
15008
15534
|
const srcNode = g.node(edge.source);
|
|
15009
15535
|
const tgtNode = g.node(edge.target);
|
|
15010
15536
|
if (!srcNode || !tgtNode) continue;
|
|
15011
|
-
const
|
|
15012
|
-
|
|
15013
|
-
|
|
15014
|
-
|
|
15015
|
-
|
|
15016
|
-
|
|
15017
|
-
|
|
15537
|
+
const srcPt = clipToRectBorder2(
|
|
15538
|
+
srcNode.x,
|
|
15539
|
+
srcNode.y,
|
|
15540
|
+
srcNode.width,
|
|
15541
|
+
srcNode.height,
|
|
15542
|
+
tgtNode.x,
|
|
15543
|
+
tgtNode.y
|
|
15544
|
+
);
|
|
15545
|
+
const tgtPt = clipToRectBorder2(
|
|
15546
|
+
tgtNode.x,
|
|
15547
|
+
tgtNode.y,
|
|
15548
|
+
tgtNode.width,
|
|
15549
|
+
tgtNode.height,
|
|
15550
|
+
srcNode.x,
|
|
15551
|
+
srcNode.y
|
|
15552
|
+
);
|
|
15553
|
+
const midX = (srcPt.x + tgtPt.x) / 2;
|
|
15554
|
+
const midY = (srcPt.y + tgtPt.y) / 2;
|
|
15555
|
+
points = [srcPt, { x: midX, y: midY }, tgtPt];
|
|
15018
15556
|
} else {
|
|
15019
15557
|
const dagreEdge = g.edge(edge.source, edge.target, `e${i}`);
|
|
15020
15558
|
points = dagreEdge?.points ?? [];
|
|
@@ -15037,7 +15575,8 @@ function layoutBoxesAndLines(parsed, collapseInfo) {
|
|
|
15037
15575
|
labelY,
|
|
15038
15576
|
yOffset: edgeYOffsets[i],
|
|
15039
15577
|
parallelCount: edgeParallelCounts[i],
|
|
15040
|
-
metadata: edge.metadata
|
|
15578
|
+
metadata: edge.metadata,
|
|
15579
|
+
deferred: deferredSet.has(i) || void 0
|
|
15041
15580
|
});
|
|
15042
15581
|
}
|
|
15043
15582
|
let maxX = 0;
|
|
@@ -15307,12 +15846,8 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
15307
15846
|
const edgeG = diagramG.append("g").attr("class", "bl-edge-group").attr("data-line-number", String(le.lineNumber));
|
|
15308
15847
|
edgeGroups.set(i, edgeG);
|
|
15309
15848
|
const markerId = `bl-arrow-${color.replace("#", "")}`;
|
|
15310
|
-
const
|
|
15311
|
-
|
|
15312
|
-
(parsed.direction === "TB" ? lineGeneratorTB : lineGeneratorLR)(
|
|
15313
|
-
points
|
|
15314
|
-
) ?? ""
|
|
15315
|
-
).attr("fill", "none").attr("stroke", color).attr("stroke-width", EDGE_STROKE_WIDTH5).attr("marker-end", `url(#${markerId})`);
|
|
15849
|
+
const gen = le.deferred ? lineGeneratorLinear2 : parsed.direction === "TB" ? lineGeneratorTB : lineGeneratorLR;
|
|
15850
|
+
const path = edgeG.append("path").attr("class", "bl-edge").attr("d", gen(points) ?? "").attr("fill", "none").attr("stroke", color).attr("stroke-width", EDGE_STROKE_WIDTH5).attr("marker-end", `url(#${markerId})`);
|
|
15316
15851
|
if (le.bidirectional) {
|
|
15317
15852
|
const revId = `bl-arrow-rev-${color.replace("#", "")}`;
|
|
15318
15853
|
path.attr("marker-start", `url(#${revId})`);
|
|
@@ -15393,50 +15928,23 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
15393
15928
|
}
|
|
15394
15929
|
}
|
|
15395
15930
|
if (parsed.tagGroups.length > 0) {
|
|
15396
|
-
|
|
15397
|
-
|
|
15398
|
-
}
|
|
15399
|
-
|
|
15400
|
-
|
|
15401
|
-
|
|
15402
|
-
|
|
15403
|
-
|
|
15404
|
-
|
|
15405
|
-
|
|
15406
|
-
|
|
15407
|
-
|
|
15408
|
-
|
|
15409
|
-
|
|
15410
|
-
|
|
15411
|
-
|
|
15412
|
-
|
|
15413
|
-
}
|
|
15414
|
-
const legendX = Math.max(LEGEND_CAPSULE_PAD, (svgWidth - totalW) / 2);
|
|
15415
|
-
const legendY = titleOffset + 4;
|
|
15416
|
-
const legendG = svg.append("g").attr("transform", `translate(${legendX},${legendY})`);
|
|
15417
|
-
let x = 0;
|
|
15418
|
-
for (const tg of parsed.tagGroups) {
|
|
15419
|
-
const isActiveGroup = activeGroup?.toLowerCase() === tg.name.toLowerCase();
|
|
15420
|
-
const groupG = legendG.append("g").attr("class", "bl-legend-group").attr("data-legend-group", tg.name.toLowerCase()).style("cursor", "pointer");
|
|
15421
|
-
const nameW = measureLegendText(tg.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
15422
|
-
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);
|
|
15423
|
-
if (isActiveGroup) {
|
|
15424
|
-
tagPill.attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
15425
|
-
}
|
|
15426
|
-
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);
|
|
15427
|
-
x += nameW;
|
|
15428
|
-
if (isActiveGroup) {
|
|
15429
|
-
x += 6;
|
|
15430
|
-
for (const entry of tg.entries) {
|
|
15431
|
-
const entryColor = entry.color || palette.textMuted;
|
|
15432
|
-
const ew = measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE);
|
|
15433
|
-
const entryG = groupG.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
15434
|
-
entryG.append("circle").attr("cx", x + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entryColor);
|
|
15435
|
-
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);
|
|
15436
|
-
x += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + ew + LEGEND_ENTRY_TRAIL;
|
|
15437
|
-
}
|
|
15438
|
-
}
|
|
15439
|
-
x += LEGEND_GROUP_GAP;
|
|
15931
|
+
const legendConfig = {
|
|
15932
|
+
groups: parsed.tagGroups,
|
|
15933
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
15934
|
+
mode: "fixed"
|
|
15935
|
+
};
|
|
15936
|
+
const legendState = { activeGroup };
|
|
15937
|
+
const legendG = svg.append("g").attr("transform", `translate(0,${titleOffset + 4})`);
|
|
15938
|
+
renderLegendD3(
|
|
15939
|
+
legendG,
|
|
15940
|
+
legendConfig,
|
|
15941
|
+
legendState,
|
|
15942
|
+
palette,
|
|
15943
|
+
isDark,
|
|
15944
|
+
void 0,
|
|
15945
|
+
width
|
|
15946
|
+
);
|
|
15947
|
+
legendG.selectAll("[data-legend-group]").classed("bl-legend-group", true);
|
|
15440
15948
|
}
|
|
15441
15949
|
}
|
|
15442
15950
|
function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark, options) {
|
|
@@ -15444,12 +15952,13 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
|
|
|
15444
15952
|
exportDims: options?.exportDims
|
|
15445
15953
|
});
|
|
15446
15954
|
}
|
|
15447
|
-
var DIAGRAM_PADDING6, NODE_FONT_SIZE, MIN_NODE_FONT_SIZE, META_FONT_SIZE3, EDGE_LABEL_FONT_SIZE4, EDGE_STROKE_WIDTH5, NODE_STROKE_WIDTH5, NODE_RX, COLLAPSE_BAR_HEIGHT3, ARROWHEAD_W2, ARROWHEAD_H2, CHAR_WIDTH_RATIO, NODE_TEXT_PADDING, GROUP_RX, GROUP_LABEL_FONT_SIZE, lineGeneratorLR, lineGeneratorTB;
|
|
15955
|
+
var DIAGRAM_PADDING6, NODE_FONT_SIZE, MIN_NODE_FONT_SIZE, META_FONT_SIZE3, EDGE_LABEL_FONT_SIZE4, EDGE_STROKE_WIDTH5, NODE_STROKE_WIDTH5, NODE_RX, COLLAPSE_BAR_HEIGHT3, ARROWHEAD_W2, ARROWHEAD_H2, CHAR_WIDTH_RATIO, NODE_TEXT_PADDING, GROUP_RX, GROUP_LABEL_FONT_SIZE, lineGeneratorLR, lineGeneratorTB, lineGeneratorLinear2;
|
|
15448
15956
|
var init_renderer6 = __esm({
|
|
15449
15957
|
"src/boxes-and-lines/renderer.ts"() {
|
|
15450
15958
|
"use strict";
|
|
15451
15959
|
init_fonts();
|
|
15452
15960
|
init_legend_constants();
|
|
15961
|
+
init_legend_d3();
|
|
15453
15962
|
init_title_constants();
|
|
15454
15963
|
init_color_utils();
|
|
15455
15964
|
init_tag_groups();
|
|
@@ -15470,6 +15979,7 @@ var init_renderer6 = __esm({
|
|
|
15470
15979
|
GROUP_LABEL_FONT_SIZE = 14;
|
|
15471
15980
|
lineGeneratorLR = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveMonotoneX);
|
|
15472
15981
|
lineGeneratorTB = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveMonotoneY);
|
|
15982
|
+
lineGeneratorLinear2 = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveLinear);
|
|
15473
15983
|
}
|
|
15474
15984
|
});
|
|
15475
15985
|
|
|
@@ -17378,7 +17888,7 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
|
|
|
17378
17888
|
if (activeTagGroup) {
|
|
17379
17889
|
legendParent.attr("data-legend-active", activeTagGroup.toLowerCase());
|
|
17380
17890
|
}
|
|
17381
|
-
|
|
17891
|
+
renderLegend2(
|
|
17382
17892
|
legendParent,
|
|
17383
17893
|
layout,
|
|
17384
17894
|
palette,
|
|
@@ -17739,52 +18249,28 @@ function placeEdgeLabels(labels, edges, obstacleRects) {
|
|
|
17739
18249
|
placedRects.push({ x: lbl.x, y: lbl.y, w: lbl.bgW, h: lbl.bgH });
|
|
17740
18250
|
}
|
|
17741
18251
|
}
|
|
17742
|
-
function
|
|
17743
|
-
const
|
|
17744
|
-
|
|
17745
|
-
|
|
17746
|
-
|
|
17747
|
-
const
|
|
17748
|
-
|
|
17749
|
-
|
|
17750
|
-
|
|
17751
|
-
|
|
17752
|
-
|
|
17753
|
-
|
|
17754
|
-
|
|
17755
|
-
|
|
17756
|
-
|
|
17757
|
-
|
|
17758
|
-
|
|
17759
|
-
|
|
17760
|
-
|
|
17761
|
-
|
|
17762
|
-
|
|
17763
|
-
|
|
17764
|
-
const gY = fixedPositions != null ? 0 : group.y;
|
|
17765
|
-
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");
|
|
17766
|
-
if (isActive) {
|
|
17767
|
-
gEl.append("rect").attr("width", group.width).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
17768
|
-
}
|
|
17769
|
-
const pillX = isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
17770
|
-
const pillY = LEGEND_CAPSULE_PAD;
|
|
17771
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
17772
|
-
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);
|
|
17773
|
-
if (isActive) {
|
|
17774
|
-
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);
|
|
17775
|
-
}
|
|
17776
|
-
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);
|
|
17777
|
-
if (isActive) {
|
|
17778
|
-
let entryX = pillX + pillWidth2 + 4;
|
|
17779
|
-
for (const entry of group.entries) {
|
|
17780
|
-
const entryG = gEl.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
17781
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
17782
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
17783
|
-
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);
|
|
17784
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
17785
|
-
}
|
|
17786
|
-
}
|
|
17787
|
-
}
|
|
18252
|
+
function renderLegend2(parent, layout, palette, isDark, activeTagGroup, fixedWidth) {
|
|
18253
|
+
const groups = layout.legend.map((g) => ({
|
|
18254
|
+
name: g.name,
|
|
18255
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
18256
|
+
}));
|
|
18257
|
+
const legendConfig = {
|
|
18258
|
+
groups,
|
|
18259
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
18260
|
+
mode: "fixed"
|
|
18261
|
+
};
|
|
18262
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
18263
|
+
const containerWidth = fixedWidth ?? layout.width;
|
|
18264
|
+
renderLegendD3(
|
|
18265
|
+
parent,
|
|
18266
|
+
legendConfig,
|
|
18267
|
+
legendState,
|
|
18268
|
+
palette,
|
|
18269
|
+
isDark,
|
|
18270
|
+
void 0,
|
|
18271
|
+
containerWidth
|
|
18272
|
+
);
|
|
18273
|
+
parent.selectAll("[data-legend-group]").classed("c4-legend-group", true);
|
|
17788
18274
|
}
|
|
17789
18275
|
function renderC4Containers(container, parsed, layout, palette, isDark, onClickItem, exportDims, activeTagGroup) {
|
|
17790
18276
|
d3Selection7.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
@@ -17995,7 +18481,7 @@ function renderC4Containers(container, parsed, layout, palette, isDark, onClickI
|
|
|
17995
18481
|
if (activeTagGroup) {
|
|
17996
18482
|
legendParent.attr("data-legend-active", activeTagGroup.toLowerCase());
|
|
17997
18483
|
}
|
|
17998
|
-
|
|
18484
|
+
renderLegend2(
|
|
17999
18485
|
legendParent,
|
|
18000
18486
|
layout,
|
|
18001
18487
|
palette,
|
|
@@ -18123,6 +18609,7 @@ var init_renderer7 = __esm({
|
|
|
18123
18609
|
init_parser6();
|
|
18124
18610
|
init_layout6();
|
|
18125
18611
|
init_legend_constants();
|
|
18612
|
+
init_legend_d3();
|
|
18126
18613
|
init_title_constants();
|
|
18127
18614
|
DIAGRAM_PADDING7 = 20;
|
|
18128
18615
|
MAX_SCALE5 = 3;
|
|
@@ -21012,17 +21499,17 @@ function computeInfraLegendGroups(nodes, tagGroups, palette, edges) {
|
|
|
21012
21499
|
color: r.color,
|
|
21013
21500
|
key: r.name.toLowerCase().replace(/\s+/g, "-")
|
|
21014
21501
|
}));
|
|
21015
|
-
const
|
|
21016
|
-
let
|
|
21502
|
+
const pillWidth3 = measureLegendText("Capabilities", LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21503
|
+
let entriesWidth3 = 0;
|
|
21017
21504
|
for (const e of entries) {
|
|
21018
|
-
|
|
21505
|
+
entriesWidth3 += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
21019
21506
|
}
|
|
21020
21507
|
groups.push({
|
|
21021
21508
|
name: "Capabilities",
|
|
21022
21509
|
type: "role",
|
|
21023
21510
|
entries,
|
|
21024
|
-
width: LEGEND_CAPSULE_PAD * 2 +
|
|
21025
|
-
minifiedWidth:
|
|
21511
|
+
width: LEGEND_CAPSULE_PAD * 2 + pillWidth3 + 4 + entriesWidth3,
|
|
21512
|
+
minifiedWidth: pillWidth3
|
|
21026
21513
|
});
|
|
21027
21514
|
}
|
|
21028
21515
|
for (const tg of tagGroups) {
|
|
@@ -21037,113 +21524,88 @@ function computeInfraLegendGroups(nodes, tagGroups, palette, edges) {
|
|
|
21037
21524
|
}
|
|
21038
21525
|
}
|
|
21039
21526
|
if (entries.length === 0) continue;
|
|
21040
|
-
const
|
|
21041
|
-
let
|
|
21527
|
+
const pillWidth3 = measureLegendText(tg.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21528
|
+
let entriesWidth3 = 0;
|
|
21042
21529
|
for (const e of entries) {
|
|
21043
|
-
|
|
21530
|
+
entriesWidth3 += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
21044
21531
|
}
|
|
21045
21532
|
groups.push({
|
|
21046
21533
|
name: tg.name,
|
|
21047
21534
|
type: "tag",
|
|
21048
21535
|
tagKey: (tg.alias ?? tg.name).toLowerCase(),
|
|
21049
21536
|
entries,
|
|
21050
|
-
width: LEGEND_CAPSULE_PAD * 2 +
|
|
21051
|
-
minifiedWidth:
|
|
21537
|
+
width: LEGEND_CAPSULE_PAD * 2 + pillWidth3 + 4 + entriesWidth3,
|
|
21538
|
+
minifiedWidth: pillWidth3
|
|
21052
21539
|
});
|
|
21053
21540
|
}
|
|
21054
21541
|
return groups;
|
|
21055
21542
|
}
|
|
21056
|
-
function
|
|
21057
|
-
if (!playback) return 0;
|
|
21058
|
-
const pillWidth2 = measureLegendText("Playback", LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21059
|
-
if (!playback.expanded) return pillWidth2;
|
|
21060
|
-
let entriesW = 8;
|
|
21061
|
-
entriesW += LEGEND_PILL_FONT_SIZE * 0.8 + 6;
|
|
21062
|
-
for (const s of playback.speedOptions) {
|
|
21063
|
-
entriesW += measureLegendText(`${s}x`, LEGEND_ENTRY_FONT_SIZE) + SPEED_BADGE_H_PAD * 2 + SPEED_BADGE_GAP;
|
|
21064
|
-
}
|
|
21065
|
-
return LEGEND_CAPSULE_PAD * 2 + pillWidth2 + entriesW;
|
|
21066
|
-
}
|
|
21067
|
-
function renderLegend4(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback) {
|
|
21543
|
+
function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback) {
|
|
21068
21544
|
if (legendGroups.length === 0 && !playback) return;
|
|
21069
21545
|
const legendG = rootSvg.append("g").attr("transform", `translate(0, ${legendY})`);
|
|
21070
21546
|
if (activeGroup) {
|
|
21071
21547
|
legendG.attr("data-legend-active", activeGroup.toLowerCase());
|
|
21072
21548
|
}
|
|
21073
|
-
const
|
|
21074
|
-
|
|
21075
|
-
|
|
21076
|
-
|
|
21077
|
-
|
|
21549
|
+
const allGroups = legendGroups.map((g) => ({
|
|
21550
|
+
name: g.name,
|
|
21551
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
21552
|
+
}));
|
|
21553
|
+
if (playback) {
|
|
21554
|
+
allGroups.push({ name: "Playback", entries: [] });
|
|
21555
|
+
}
|
|
21556
|
+
const legendConfig = {
|
|
21557
|
+
groups: allGroups,
|
|
21558
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
21559
|
+
mode: "fixed",
|
|
21560
|
+
showEmptyGroups: true
|
|
21561
|
+
};
|
|
21562
|
+
const legendState = { activeGroup };
|
|
21563
|
+
renderLegendD3(
|
|
21564
|
+
legendG,
|
|
21565
|
+
legendConfig,
|
|
21566
|
+
legendState,
|
|
21567
|
+
palette,
|
|
21568
|
+
isDark,
|
|
21569
|
+
void 0,
|
|
21570
|
+
totalWidth
|
|
21571
|
+
);
|
|
21572
|
+
legendG.selectAll("[data-legend-group]").classed("infra-legend-group", true);
|
|
21078
21573
|
for (const group of legendGroups) {
|
|
21079
|
-
const
|
|
21080
|
-
const
|
|
21081
|
-
|
|
21082
|
-
|
|
21083
|
-
|
|
21084
|
-
|
|
21085
|
-
|
|
21086
|
-
}
|
|
21087
|
-
const pillXOff = isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
21088
|
-
const pillYOff = LEGEND_CAPSULE_PAD;
|
|
21089
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
21090
|
-
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);
|
|
21091
|
-
if (isActive) {
|
|
21092
|
-
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);
|
|
21093
|
-
}
|
|
21094
|
-
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);
|
|
21095
|
-
if (isActive) {
|
|
21096
|
-
let entryX = pillXOff + pillWidth2 + 4;
|
|
21097
|
-
for (const entry of group.entries) {
|
|
21098
|
-
const entryG = gEl.append("g").attr("class", "infra-legend-entry").attr("data-legend-entry", entry.key.toLowerCase()).attr("data-legend-color", entry.color).attr("data-legend-type", group.type).attr(
|
|
21574
|
+
const groupKey = group.name.toLowerCase();
|
|
21575
|
+
for (const entry of group.entries) {
|
|
21576
|
+
const entryEl = legendG.select(
|
|
21577
|
+
`[data-legend-group="${groupKey}"] [data-legend-entry="${entry.value.toLowerCase()}"]`
|
|
21578
|
+
);
|
|
21579
|
+
if (!entryEl.empty()) {
|
|
21580
|
+
entryEl.attr("data-legend-entry", entry.key.toLowerCase()).attr("data-legend-color", entry.color).attr("data-legend-type", group.type).attr(
|
|
21099
21581
|
"data-legend-tag-group",
|
|
21100
21582
|
group.type === "tag" ? group.tagKey ?? "" : null
|
|
21101
|
-
)
|
|
21102
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
21103
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
21104
|
-
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);
|
|
21105
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
21583
|
+
);
|
|
21106
21584
|
}
|
|
21107
21585
|
}
|
|
21108
|
-
cursorX += effectiveW(group) + LEGEND_GROUP_GAP;
|
|
21109
21586
|
}
|
|
21110
|
-
|
|
21111
|
-
|
|
21112
|
-
|
|
21113
|
-
|
|
21114
|
-
|
|
21115
|
-
const
|
|
21116
|
-
|
|
21117
|
-
|
|
21118
|
-
|
|
21119
|
-
|
|
21120
|
-
|
|
21121
|
-
const
|
|
21122
|
-
|
|
21123
|
-
|
|
21124
|
-
|
|
21125
|
-
|
|
21126
|
-
|
|
21127
|
-
|
|
21128
|
-
|
|
21129
|
-
|
|
21130
|
-
|
|
21131
|
-
|
|
21132
|
-
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);
|
|
21133
|
-
entryX += LEGEND_PILL_FONT_SIZE * 0.8 + 6;
|
|
21134
|
-
for (const s of playback.speedOptions) {
|
|
21135
|
-
const label = `${s}x`;
|
|
21136
|
-
const isActive = playback.speed === s;
|
|
21137
|
-
const slotW = measureLegendText(label, LEGEND_ENTRY_FONT_SIZE) + SPEED_BADGE_H_PAD * 2;
|
|
21138
|
-
const badgeH = LEGEND_ENTRY_FONT_SIZE + SPEED_BADGE_V_PAD * 2;
|
|
21139
|
-
const badgeY = (LEGEND_HEIGHT - badgeH) / 2;
|
|
21140
|
-
const speedG = pbG.append("g").attr("data-playback-action", "set-speed").attr("data-playback-value", String(s)).style("cursor", "pointer");
|
|
21141
|
-
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");
|
|
21142
|
-
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);
|
|
21143
|
-
entryX += slotW + SPEED_BADGE_GAP;
|
|
21144
|
-
}
|
|
21145
|
-
}
|
|
21146
|
-
cursorX += fullW + LEGEND_GROUP_GAP;
|
|
21587
|
+
const playbackEl = legendG.select('[data-legend-group="playback"]');
|
|
21588
|
+
if (!playbackEl.empty()) {
|
|
21589
|
+
playbackEl.classed("infra-playback-pill", true);
|
|
21590
|
+
}
|
|
21591
|
+
if (playback && playback.expanded && !playbackEl.empty()) {
|
|
21592
|
+
const pillWidth3 = measureLegendText("Playback", LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21593
|
+
let entryX = pillWidth3 + 8;
|
|
21594
|
+
const entryY = LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1;
|
|
21595
|
+
const ppLabel = playback.paused ? "\u25B6" : "\u23F8";
|
|
21596
|
+
playbackEl.append("text").attr("x", entryX).attr("y", entryY).attr("font-family", FONT_FAMILY).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("fill", palette.textMuted).attr("data-playback-action", "toggle-pause").style("cursor", "pointer").text(ppLabel);
|
|
21597
|
+
entryX += LEGEND_PILL_FONT_SIZE * 0.8 + 6;
|
|
21598
|
+
for (const s of playback.speedOptions) {
|
|
21599
|
+
const label = `${s}x`;
|
|
21600
|
+
const isSpeedActive = playback.speed === s;
|
|
21601
|
+
const slotW = measureLegendText(label, LEGEND_ENTRY_FONT_SIZE) + SPEED_BADGE_H_PAD * 2;
|
|
21602
|
+
const badgeH = LEGEND_ENTRY_FONT_SIZE + SPEED_BADGE_V_PAD * 2;
|
|
21603
|
+
const badgeY = (LEGEND_HEIGHT - badgeH) / 2;
|
|
21604
|
+
const speedG = playbackEl.append("g").attr("data-playback-action", "set-speed").attr("data-playback-value", String(s)).style("cursor", "pointer");
|
|
21605
|
+
speedG.append("rect").attr("x", entryX).attr("y", badgeY).attr("width", slotW).attr("height", badgeH).attr("rx", badgeH / 2).attr("fill", isSpeedActive ? palette.primary : "transparent");
|
|
21606
|
+
speedG.append("text").attr("x", entryX + slotW / 2).attr("y", entryY).attr("font-family", FONT_FAMILY).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("font-weight", isSpeedActive ? "600" : "400").attr("fill", isSpeedActive ? palette.bg : palette.textMuted).attr("text-anchor", "middle").text(label);
|
|
21607
|
+
entryX += slotW + SPEED_BADGE_GAP;
|
|
21608
|
+
}
|
|
21147
21609
|
}
|
|
21148
21610
|
}
|
|
21149
21611
|
function renderInfra(container, layout, palette, isDark, title, titleLineNumber, tagGroups, activeGroup, animate, playback, expandedNodeIds, exportMode, collapsedNodes) {
|
|
@@ -21274,7 +21736,7 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
21274
21736
|
"viewBox",
|
|
21275
21737
|
`0 0 ${containerWidth} ${LEGEND_HEIGHT + LEGEND_FIXED_GAP3}`
|
|
21276
21738
|
).attr("preserveAspectRatio", "xMidYMid meet").style("display", "block").style("pointer-events", "none");
|
|
21277
|
-
|
|
21739
|
+
renderLegend3(
|
|
21278
21740
|
legendSvg,
|
|
21279
21741
|
legendGroups,
|
|
21280
21742
|
containerWidth,
|
|
@@ -21286,7 +21748,7 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
21286
21748
|
);
|
|
21287
21749
|
legendSvg.selectAll(".infra-legend-group").style("pointer-events", "auto");
|
|
21288
21750
|
} else {
|
|
21289
|
-
|
|
21751
|
+
renderLegend3(
|
|
21290
21752
|
rootSvg,
|
|
21291
21753
|
legendGroups,
|
|
21292
21754
|
totalWidth,
|
|
@@ -21318,6 +21780,7 @@ var init_renderer8 = __esm({
|
|
|
21318
21780
|
init_compute();
|
|
21319
21781
|
init_layout8();
|
|
21320
21782
|
init_legend_constants();
|
|
21783
|
+
init_legend_d3();
|
|
21321
21784
|
init_title_constants();
|
|
21322
21785
|
NODE_FONT_SIZE3 = 13;
|
|
21323
21786
|
META_FONT_SIZE5 = 10;
|
|
@@ -22945,7 +23408,7 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
22945
23408
|
const isActive = activeGroupName?.toLowerCase() === group.name.toLowerCase();
|
|
22946
23409
|
const isSwimlane = currentSwimlaneGroup?.toLowerCase() === group.name.toLowerCase();
|
|
22947
23410
|
const showIcon = !legendViewMode && tagGroups.length > 0;
|
|
22948
|
-
const iconReserve = showIcon ? LEGEND_ICON_W : 0;
|
|
23411
|
+
const iconReserve = showIcon && isActive ? LEGEND_ICON_W : 0;
|
|
22949
23412
|
const pillW = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD + iconReserve;
|
|
22950
23413
|
let groupW = pillW;
|
|
22951
23414
|
if (isActive) {
|
|
@@ -22972,83 +23435,110 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
22972
23435
|
const legendX = (containerWidth - totalW) / 2;
|
|
22973
23436
|
const legendRow = svg.append("g").attr("class", "gantt-tag-legend-container").attr("transform", `translate(${legendX}, ${legendY})`);
|
|
22974
23437
|
let cursorX = 0;
|
|
22975
|
-
|
|
22976
|
-
const group = visibleGroups[i];
|
|
22977
|
-
const isActive = activeGroupName?.toLowerCase() === group.name.toLowerCase();
|
|
22978
|
-
const isSwimlane = currentSwimlaneGroup?.toLowerCase() === group.name.toLowerCase();
|
|
23438
|
+
if (visibleGroups.length > 0) {
|
|
22979
23439
|
const showIcon = !legendViewMode && tagGroups.length > 0;
|
|
22980
23440
|
const iconReserve = showIcon ? LEGEND_ICON_W : 0;
|
|
22981
|
-
const
|
|
22982
|
-
|
|
22983
|
-
|
|
22984
|
-
|
|
22985
|
-
|
|
23441
|
+
const legendGroups = visibleGroups.map((g) => {
|
|
23442
|
+
const key = g.name.toLowerCase();
|
|
23443
|
+
const entries = filteredEntries.get(key) ?? g.entries;
|
|
23444
|
+
return {
|
|
23445
|
+
name: g.name,
|
|
23446
|
+
entries: entries.map((e) => ({ value: e.value, color: e.color }))
|
|
23447
|
+
};
|
|
22986
23448
|
});
|
|
22987
|
-
|
|
22988
|
-
|
|
22989
|
-
|
|
22990
|
-
|
|
22991
|
-
|
|
22992
|
-
|
|
22993
|
-
|
|
22994
|
-
|
|
22995
|
-
}
|
|
22996
|
-
const
|
|
22997
|
-
|
|
22998
|
-
|
|
22999
|
-
|
|
23000
|
-
|
|
23001
|
-
|
|
23002
|
-
|
|
23003
|
-
|
|
23004
|
-
|
|
23005
|
-
if (onSwimlaneChange) {
|
|
23006
|
-
onSwimlaneChange(
|
|
23007
|
-
currentSwimlaneGroup?.toLowerCase() === group.name.toLowerCase() ? null : group.name
|
|
23008
|
-
);
|
|
23009
|
-
}
|
|
23010
|
-
});
|
|
23011
|
-
}
|
|
23012
|
-
if (isActive) {
|
|
23013
|
-
const tagKey = group.name.toLowerCase();
|
|
23014
|
-
const entries = filteredEntries.get(tagKey) ?? group.entries;
|
|
23015
|
-
let ex = pillXOff + pillW + LEGEND_CAPSULE_PAD + 4;
|
|
23016
|
-
for (const entry of entries) {
|
|
23017
|
-
const entryValue = entry.value.toLowerCase();
|
|
23018
|
-
const entryG = gEl.append("g").attr("class", "gantt-legend-entry").attr("data-line-number", String(entry.lineNumber)).style("cursor", "pointer");
|
|
23019
|
-
entryG.append("circle").attr("cx", ex + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
23020
|
-
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);
|
|
23021
|
-
entryG.on("mouseenter", () => {
|
|
23449
|
+
const legendConfig = {
|
|
23450
|
+
groups: legendGroups,
|
|
23451
|
+
position: {
|
|
23452
|
+
placement: "top-center",
|
|
23453
|
+
titleRelation: "below-title"
|
|
23454
|
+
},
|
|
23455
|
+
mode: "fixed",
|
|
23456
|
+
capsulePillAddonWidth: iconReserve
|
|
23457
|
+
};
|
|
23458
|
+
const legendState = { activeGroup: activeGroupName };
|
|
23459
|
+
const tagGroupsW = visibleGroups.reduce((s, _, i) => s + groupWidths[i], 0) + Math.max(0, (visibleGroups.length - 1) * LEGEND_GROUP_GAP);
|
|
23460
|
+
const tagGroupG = legendRow.append("g");
|
|
23461
|
+
const legendCallbacks = {
|
|
23462
|
+
onGroupToggle: onToggle,
|
|
23463
|
+
onEntryHover: (groupName, entryValue) => {
|
|
23464
|
+
const tagKey = groupName.toLowerCase();
|
|
23465
|
+
if (entryValue) {
|
|
23466
|
+
const ev = entryValue.toLowerCase();
|
|
23022
23467
|
chartG.selectAll(".gantt-task").each(function() {
|
|
23023
23468
|
const el = d3Selection10.select(this);
|
|
23024
|
-
|
|
23025
|
-
|
|
23469
|
+
el.attr(
|
|
23470
|
+
"opacity",
|
|
23471
|
+
el.attr(`data-tag-${tagKey}`) === ev ? 1 : FADE_OPACITY
|
|
23472
|
+
);
|
|
23026
23473
|
});
|
|
23027
23474
|
chartG.selectAll(".gantt-milestone").attr("opacity", FADE_OPACITY);
|
|
23028
23475
|
chartG.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
23029
23476
|
svg.selectAll(".gantt-task-label").each(function() {
|
|
23030
23477
|
const el = d3Selection10.select(this);
|
|
23031
|
-
|
|
23032
|
-
|
|
23478
|
+
el.attr(
|
|
23479
|
+
"opacity",
|
|
23480
|
+
el.attr(`data-tag-${tagKey}`) === ev ? 1 : FADE_OPACITY
|
|
23481
|
+
);
|
|
23033
23482
|
});
|
|
23034
23483
|
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
23035
23484
|
svg.selectAll(".gantt-lane-header").each(function() {
|
|
23036
23485
|
const el = d3Selection10.select(this);
|
|
23037
|
-
|
|
23038
|
-
|
|
23486
|
+
el.attr(
|
|
23487
|
+
"opacity",
|
|
23488
|
+
el.attr(`data-tag-${tagKey}`) === ev ? 1 : FADE_OPACITY
|
|
23489
|
+
);
|
|
23039
23490
|
});
|
|
23040
23491
|
chartG.selectAll(".gantt-lane-band, .gantt-lane-accent").attr("opacity", FADE_OPACITY);
|
|
23041
|
-
}
|
|
23492
|
+
} else {
|
|
23042
23493
|
if (criticalPathActive) {
|
|
23043
23494
|
applyCriticalPathHighlight(svg, chartG);
|
|
23044
23495
|
} else {
|
|
23045
23496
|
resetHighlightAll(svg, chartG);
|
|
23046
23497
|
}
|
|
23047
|
-
}
|
|
23048
|
-
|
|
23498
|
+
}
|
|
23499
|
+
},
|
|
23500
|
+
onGroupRendered: (groupName, groupEl, _isActive) => {
|
|
23501
|
+
const group = visibleGroups.find((g) => g.name === groupName);
|
|
23502
|
+
if (group) {
|
|
23503
|
+
groupEl.attr("data-tag-group", group.name).attr("data-line-number", String(group.lineNumber));
|
|
23504
|
+
}
|
|
23505
|
+
if (showIcon && _isActive) {
|
|
23506
|
+
const isSwimlane = currentSwimlaneGroup?.toLowerCase() === groupName.toLowerCase();
|
|
23507
|
+
const textW = measureLegendText(groupName, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
23508
|
+
const pillXOff = LEGEND_CAPSULE_PAD;
|
|
23509
|
+
const iconX = pillXOff + textW + 3;
|
|
23510
|
+
const iconY = (LEGEND_HEIGHT - 10) / 2;
|
|
23511
|
+
const iconEl = drawSwimlaneIcon(
|
|
23512
|
+
groupEl,
|
|
23513
|
+
iconX,
|
|
23514
|
+
iconY,
|
|
23515
|
+
isSwimlane,
|
|
23516
|
+
palette
|
|
23517
|
+
);
|
|
23518
|
+
iconEl.append("title").text(`Group by ${groupName}`);
|
|
23519
|
+
iconEl.style("cursor", "pointer").on("click", (event) => {
|
|
23520
|
+
event.stopPropagation();
|
|
23521
|
+
if (onSwimlaneChange) {
|
|
23522
|
+
onSwimlaneChange(
|
|
23523
|
+
currentSwimlaneGroup?.toLowerCase() === groupName.toLowerCase() ? null : groupName
|
|
23524
|
+
);
|
|
23525
|
+
}
|
|
23526
|
+
});
|
|
23527
|
+
}
|
|
23049
23528
|
}
|
|
23529
|
+
};
|
|
23530
|
+
renderLegendD3(
|
|
23531
|
+
tagGroupG,
|
|
23532
|
+
legendConfig,
|
|
23533
|
+
legendState,
|
|
23534
|
+
palette,
|
|
23535
|
+
isDark,
|
|
23536
|
+
legendCallbacks,
|
|
23537
|
+
tagGroupsW
|
|
23538
|
+
);
|
|
23539
|
+
for (let i = 0; i < visibleGroups.length; i++) {
|
|
23540
|
+
cursorX += groupWidths[i] + LEGEND_GROUP_GAP;
|
|
23050
23541
|
}
|
|
23051
|
-
cursorX += groupW + LEGEND_GROUP_GAP;
|
|
23052
23542
|
}
|
|
23053
23543
|
if (hasCriticalPath) {
|
|
23054
23544
|
const cpLineNum = optionLineNumbers["critical-path"];
|
|
@@ -23675,6 +24165,7 @@ var init_renderer9 = __esm({
|
|
|
23675
24165
|
init_tag_groups();
|
|
23676
24166
|
init_d3();
|
|
23677
24167
|
init_legend_constants();
|
|
24168
|
+
init_legend_d3();
|
|
23678
24169
|
init_title_constants();
|
|
23679
24170
|
BAR_H = 22;
|
|
23680
24171
|
ROW_GAP = 6;
|
|
@@ -24845,57 +25336,29 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
24845
25336
|
}
|
|
24846
25337
|
if (parsed.tagGroups.length > 0) {
|
|
24847
25338
|
const legendY = TOP_MARGIN + titleOffset;
|
|
24848
|
-
const
|
|
24849
|
-
|
|
24850
|
-
|
|
24851
|
-
if (tg.entries.length === 0) continue;
|
|
24852
|
-
const isActive = !!activeTagGroup && tg.name.toLowerCase() === activeTagGroup.toLowerCase();
|
|
24853
|
-
const pillWidth2 = measureLegendText(tg.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
24854
|
-
const entries = tg.entries.map((e) => ({
|
|
25339
|
+
const resolvedGroups = parsed.tagGroups.filter((tg) => tg.entries.length > 0).map((tg) => ({
|
|
25340
|
+
name: tg.name,
|
|
25341
|
+
entries: tg.entries.map((e) => ({
|
|
24855
25342
|
value: e.value,
|
|
24856
25343
|
color: resolveColor(e.color) ?? e.color
|
|
24857
|
-
}))
|
|
24858
|
-
|
|
24859
|
-
|
|
24860
|
-
|
|
24861
|
-
|
|
24862
|
-
|
|
24863
|
-
|
|
24864
|
-
|
|
24865
|
-
|
|
24866
|
-
|
|
24867
|
-
|
|
24868
|
-
|
|
24869
|
-
|
|
24870
|
-
|
|
24871
|
-
|
|
24872
|
-
|
|
24873
|
-
|
|
24874
|
-
|
|
24875
|
-
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");
|
|
24876
|
-
if (item.isActive) {
|
|
24877
|
-
gEl.append("rect").attr("width", item.totalWidth).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
24878
|
-
}
|
|
24879
|
-
const pillXOff = item.isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
24880
|
-
const pillYOff = LEGEND_CAPSULE_PAD;
|
|
24881
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
24882
|
-
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);
|
|
24883
|
-
if (item.isActive) {
|
|
24884
|
-
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);
|
|
24885
|
-
}
|
|
24886
|
-
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);
|
|
24887
|
-
if (item.isActive) {
|
|
24888
|
-
let entryX = pillXOff + item.pillWidth + 4;
|
|
24889
|
-
for (const entry of item.entries) {
|
|
24890
|
-
const entryG = gEl.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
24891
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
24892
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
24893
|
-
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);
|
|
24894
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
24895
|
-
}
|
|
24896
|
-
}
|
|
24897
|
-
legendX += item.totalWidth + LEGEND_GROUP_GAP;
|
|
24898
|
-
}
|
|
25344
|
+
}))
|
|
25345
|
+
}));
|
|
25346
|
+
const legendConfig = {
|
|
25347
|
+
groups: resolvedGroups,
|
|
25348
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
25349
|
+
mode: "fixed"
|
|
25350
|
+
};
|
|
25351
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
25352
|
+
const legendG = svg.append("g").attr("class", "sequence-legend").attr("transform", `translate(0,${legendY})`);
|
|
25353
|
+
renderLegendD3(
|
|
25354
|
+
legendG,
|
|
25355
|
+
legendConfig,
|
|
25356
|
+
legendState,
|
|
25357
|
+
palette,
|
|
25358
|
+
isDark,
|
|
25359
|
+
void 0,
|
|
25360
|
+
svgWidth
|
|
25361
|
+
);
|
|
24899
25362
|
}
|
|
24900
25363
|
for (const group of groups) {
|
|
24901
25364
|
if (group.participantIds.length === 0) continue;
|
|
@@ -25454,6 +25917,7 @@ var init_renderer10 = __esm({
|
|
|
25454
25917
|
init_parser();
|
|
25455
25918
|
init_tag_resolution();
|
|
25456
25919
|
init_legend_constants();
|
|
25920
|
+
init_legend_d3();
|
|
25457
25921
|
init_title_constants();
|
|
25458
25922
|
PARTICIPANT_GAP = 160;
|
|
25459
25923
|
PARTICIPANT_BOX_WIDTH = 120;
|
|
@@ -28114,7 +28578,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28114
28578
|
const LG_ENTRY_FONT_SIZE = LEGEND_ENTRY_FONT_SIZE;
|
|
28115
28579
|
const LG_ENTRY_DOT_GAP = LEGEND_ENTRY_DOT_GAP;
|
|
28116
28580
|
const LG_ENTRY_TRAIL = LEGEND_ENTRY_TRAIL;
|
|
28117
|
-
const LG_GROUP_GAP = LEGEND_GROUP_GAP;
|
|
28118
28581
|
const LG_ICON_W = 20;
|
|
28119
28582
|
const mainSvg = d3Selection13.select(container).select("svg");
|
|
28120
28583
|
const mainG = mainSvg.select("g");
|
|
@@ -28153,11 +28616,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28153
28616
|
(lg) => effectiveColorKey != null && lg.group.name.toLowerCase() === effectiveColorKey
|
|
28154
28617
|
) : legendGroups;
|
|
28155
28618
|
if (visibleGroups.length === 0) return;
|
|
28156
|
-
const totalW = visibleGroups.reduce((s, lg) => {
|
|
28157
|
-
const isActive = viewMode || currentActiveGroup != null && lg.group.name.toLowerCase() === currentActiveGroup.toLowerCase();
|
|
28158
|
-
return s + (isActive ? lg.expandedWidth : lg.minifiedWidth);
|
|
28159
|
-
}, 0) + (visibleGroups.length - 1) * LG_GROUP_GAP;
|
|
28160
|
-
let cx = (width - totalW) / 2;
|
|
28161
28619
|
const legendContainer = mainSvg.append("g").attr("class", "tl-tag-legend-container");
|
|
28162
28620
|
if (currentActiveGroup) {
|
|
28163
28621
|
legendContainer.attr(
|
|
@@ -28165,82 +28623,85 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28165
28623
|
currentActiveGroup.toLowerCase()
|
|
28166
28624
|
);
|
|
28167
28625
|
}
|
|
28168
|
-
|
|
28169
|
-
|
|
28170
|
-
|
|
28171
|
-
|
|
28172
|
-
|
|
28173
|
-
|
|
28174
|
-
|
|
28175
|
-
|
|
28176
|
-
|
|
28177
|
-
|
|
28178
|
-
|
|
28179
|
-
|
|
28180
|
-
|
|
28181
|
-
|
|
28182
|
-
|
|
28183
|
-
|
|
28184
|
-
|
|
28185
|
-
|
|
28186
|
-
|
|
28187
|
-
|
|
28188
|
-
|
|
28189
|
-
|
|
28190
|
-
|
|
28191
|
-
|
|
28192
|
-
|
|
28193
|
-
|
|
28194
|
-
|
|
28195
|
-
|
|
28196
|
-
|
|
28197
|
-
|
|
28626
|
+
const iconAddon = viewMode ? 0 : LG_ICON_W;
|
|
28627
|
+
const centralGroups = visibleGroups.map((lg) => ({
|
|
28628
|
+
name: lg.group.name,
|
|
28629
|
+
entries: lg.group.entries.map((e) => ({
|
|
28630
|
+
value: e.value,
|
|
28631
|
+
color: e.color
|
|
28632
|
+
}))
|
|
28633
|
+
}));
|
|
28634
|
+
const centralActive = viewMode ? effectiveColorKey : currentActiveGroup;
|
|
28635
|
+
const centralConfig = {
|
|
28636
|
+
groups: centralGroups,
|
|
28637
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
28638
|
+
mode: "fixed",
|
|
28639
|
+
capsulePillAddonWidth: iconAddon
|
|
28640
|
+
};
|
|
28641
|
+
const centralState = { activeGroup: centralActive };
|
|
28642
|
+
const centralCallbacks = viewMode ? {} : {
|
|
28643
|
+
onGroupToggle: (groupName) => {
|
|
28644
|
+
currentActiveGroup = currentActiveGroup === groupName.toLowerCase() ? null : groupName.toLowerCase();
|
|
28645
|
+
drawLegend2();
|
|
28646
|
+
recolorEvents2();
|
|
28647
|
+
onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
|
|
28648
|
+
},
|
|
28649
|
+
onEntryHover: (groupName, entryValue) => {
|
|
28650
|
+
const tagKey = groupName.toLowerCase();
|
|
28651
|
+
if (entryValue) {
|
|
28652
|
+
const tagVal = entryValue.toLowerCase();
|
|
28653
|
+
fadeToTagValue(mainG, tagKey, tagVal);
|
|
28654
|
+
mainSvg.selectAll("[data-legend-entry]").each(function() {
|
|
28655
|
+
const el = d3Selection13.select(this);
|
|
28656
|
+
const ev = el.attr("data-legend-entry");
|
|
28657
|
+
const eg = el.attr("data-tag-group") ?? el.node()?.closest?.("[data-tag-group]")?.getAttribute("data-tag-group");
|
|
28658
|
+
el.attr(
|
|
28659
|
+
"opacity",
|
|
28660
|
+
eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY2
|
|
28661
|
+
);
|
|
28662
|
+
});
|
|
28663
|
+
} else {
|
|
28664
|
+
fadeReset(mainG);
|
|
28665
|
+
mainSvg.selectAll("[data-legend-entry]").attr("opacity", 1);
|
|
28666
|
+
}
|
|
28667
|
+
},
|
|
28668
|
+
onGroupRendered: (groupName, groupEl, isActive) => {
|
|
28669
|
+
const groupKey = groupName.toLowerCase();
|
|
28670
|
+
groupEl.attr("data-tag-group", groupKey);
|
|
28671
|
+
if (isActive && !viewMode) {
|
|
28672
|
+
const isSwimActive = currentSwimlaneGroup != null && currentSwimlaneGroup.toLowerCase() === groupKey;
|
|
28673
|
+
const pillWidth3 = measureLegendText(groupName, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
|
|
28674
|
+
const pillXOff = LG_CAPSULE_PAD;
|
|
28675
|
+
const iconX = pillXOff + pillWidth3 + 5;
|
|
28198
28676
|
const iconY = (LG_HEIGHT - 10) / 2;
|
|
28199
|
-
const iconEl = drawSwimlaneIcon3(
|
|
28677
|
+
const iconEl = drawSwimlaneIcon3(
|
|
28678
|
+
groupEl,
|
|
28679
|
+
iconX,
|
|
28680
|
+
iconY,
|
|
28681
|
+
isSwimActive
|
|
28682
|
+
);
|
|
28200
28683
|
iconEl.attr("data-swimlane-toggle", groupKey).on("click", (event) => {
|
|
28201
28684
|
event.stopPropagation();
|
|
28202
28685
|
currentSwimlaneGroup = currentSwimlaneGroup === groupKey ? null : groupKey;
|
|
28203
|
-
onTagStateChange?.(
|
|
28686
|
+
onTagStateChange?.(
|
|
28687
|
+
currentActiveGroup,
|
|
28688
|
+
currentSwimlaneGroup
|
|
28689
|
+
);
|
|
28204
28690
|
relayout2();
|
|
28205
28691
|
});
|
|
28206
|
-
entryX = pillXOff + pillWidth2 + LG_ICON_W + 4;
|
|
28207
|
-
} else {
|
|
28208
|
-
entryX = pillXOff + pillWidth2 + 8;
|
|
28209
|
-
}
|
|
28210
|
-
for (const entry of lg.group.entries) {
|
|
28211
|
-
const tagKey = lg.group.name.toLowerCase();
|
|
28212
|
-
const tagVal = entry.value.toLowerCase();
|
|
28213
|
-
const entryG = gEl.append("g").attr("class", "tl-tag-legend-entry").attr("data-tag-group", tagKey).attr("data-legend-entry", tagVal);
|
|
28214
|
-
if (!viewMode) {
|
|
28215
|
-
entryG.style("cursor", "pointer").on("mouseenter", (event) => {
|
|
28216
|
-
event.stopPropagation();
|
|
28217
|
-
fadeToTagValue(mainG, tagKey, tagVal);
|
|
28218
|
-
mainSvg.selectAll(".tl-tag-legend-entry").each(function() {
|
|
28219
|
-
const el = d3Selection13.select(this);
|
|
28220
|
-
const ev = el.attr("data-legend-entry");
|
|
28221
|
-
if (ev === "__group__") return;
|
|
28222
|
-
const eg = el.attr("data-tag-group");
|
|
28223
|
-
el.attr(
|
|
28224
|
-
"opacity",
|
|
28225
|
-
eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY2
|
|
28226
|
-
);
|
|
28227
|
-
});
|
|
28228
|
-
}).on("mouseleave", (event) => {
|
|
28229
|
-
event.stopPropagation();
|
|
28230
|
-
fadeReset(mainG);
|
|
28231
|
-
mainSvg.selectAll(".tl-tag-legend-entry").attr("opacity", 1);
|
|
28232
|
-
}).on("click", (event) => {
|
|
28233
|
-
event.stopPropagation();
|
|
28234
|
-
});
|
|
28235
|
-
}
|
|
28236
|
-
entryG.append("circle").attr("cx", entryX + LG_DOT_R).attr("cy", LG_HEIGHT / 2).attr("r", LG_DOT_R).attr("fill", entry.color);
|
|
28237
|
-
const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
|
|
28238
|
-
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);
|
|
28239
|
-
entryX = textX + measureLegendText(entry.value, LG_ENTRY_FONT_SIZE) + LG_ENTRY_TRAIL;
|
|
28240
28692
|
}
|
|
28241
28693
|
}
|
|
28242
|
-
|
|
28243
|
-
}
|
|
28694
|
+
};
|
|
28695
|
+
const legendInnerG = legendContainer.append("g").attr("transform", `translate(0, ${legendY})`);
|
|
28696
|
+
renderLegendD3(
|
|
28697
|
+
legendInnerG,
|
|
28698
|
+
centralConfig,
|
|
28699
|
+
centralState,
|
|
28700
|
+
palette,
|
|
28701
|
+
isDark,
|
|
28702
|
+
centralCallbacks,
|
|
28703
|
+
width
|
|
28704
|
+
);
|
|
28244
28705
|
}, recolorEvents2 = function() {
|
|
28245
28706
|
const colorTG = currentActiveGroup ?? swimlaneTagGroup ?? null;
|
|
28246
28707
|
mainG.selectAll(".tl-event").each(function() {
|
|
@@ -28265,7 +28726,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28265
28726
|
};
|
|
28266
28727
|
var drawSwimlaneIcon2 = drawSwimlaneIcon3, relayout = relayout2, drawLegend = drawLegend2, recolorEvents = recolorEvents2;
|
|
28267
28728
|
const legendY = title ? 50 : 10;
|
|
28268
|
-
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
28269
28729
|
const legendGroups = parsed.timelineTagGroups.map((g) => {
|
|
28270
28730
|
const pillW = measureLegendText(g.name, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
|
|
28271
28731
|
const iconSpace = viewMode ? 8 : LG_ICON_W + 4;
|
|
@@ -29507,6 +29967,7 @@ var init_d3 = __esm({
|
|
|
29507
29967
|
init_parsing();
|
|
29508
29968
|
init_tag_groups();
|
|
29509
29969
|
init_legend_constants();
|
|
29970
|
+
init_legend_d3();
|
|
29510
29971
|
init_title_constants();
|
|
29511
29972
|
DEFAULT_CLOUD_OPTIONS = {
|
|
29512
29973
|
rotate: "none",
|
|
@@ -29661,11 +30122,26 @@ async function ensureDom() {
|
|
|
29661
30122
|
const { JSDOM } = await import("jsdom");
|
|
29662
30123
|
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
|
|
29663
30124
|
const win = dom.window;
|
|
29664
|
-
Object.defineProperty(globalThis, "document", {
|
|
29665
|
-
|
|
29666
|
-
|
|
29667
|
-
|
|
29668
|
-
Object.defineProperty(globalThis, "
|
|
30125
|
+
Object.defineProperty(globalThis, "document", {
|
|
30126
|
+
value: win.document,
|
|
30127
|
+
configurable: true
|
|
30128
|
+
});
|
|
30129
|
+
Object.defineProperty(globalThis, "window", {
|
|
30130
|
+
value: win,
|
|
30131
|
+
configurable: true
|
|
30132
|
+
});
|
|
30133
|
+
Object.defineProperty(globalThis, "navigator", {
|
|
30134
|
+
value: win.navigator,
|
|
30135
|
+
configurable: true
|
|
30136
|
+
});
|
|
30137
|
+
Object.defineProperty(globalThis, "HTMLElement", {
|
|
30138
|
+
value: win.HTMLElement,
|
|
30139
|
+
configurable: true
|
|
30140
|
+
});
|
|
30141
|
+
Object.defineProperty(globalThis, "SVGElement", {
|
|
30142
|
+
value: win.SVGElement,
|
|
30143
|
+
configurable: true
|
|
30144
|
+
});
|
|
29669
30145
|
}
|
|
29670
30146
|
async function render(content, options) {
|
|
29671
30147
|
const theme = options?.theme ?? "light";
|
|
@@ -29674,11 +30150,17 @@ async function render(content, options) {
|
|
|
29674
30150
|
const paletteColors = getPalette(paletteName)[theme === "dark" ? "dark" : "light"];
|
|
29675
30151
|
const chartType = parseDgmoChartType(content);
|
|
29676
30152
|
const category = chartType ? getRenderCategory(chartType) : null;
|
|
30153
|
+
const legendExportState = options?.legendState ? {
|
|
30154
|
+
activeTagGroup: options.legendState.activeGroup ?? null,
|
|
30155
|
+
hiddenAttributes: options.legendState.hiddenAttributes ? new Set(options.legendState.hiddenAttributes) : void 0
|
|
30156
|
+
} : void 0;
|
|
29677
30157
|
if (category === "data-chart") {
|
|
29678
|
-
return renderExtendedChartForExport(content, theme, paletteColors, {
|
|
30158
|
+
return renderExtendedChartForExport(content, theme, paletteColors, {
|
|
30159
|
+
branding
|
|
30160
|
+
});
|
|
29679
30161
|
}
|
|
29680
30162
|
await ensureDom();
|
|
29681
|
-
return renderForExport(content, theme, paletteColors,
|
|
30163
|
+
return renderForExport(content, theme, paletteColors, legendExportState, {
|
|
29682
30164
|
branding,
|
|
29683
30165
|
c4Level: options?.c4Level,
|
|
29684
30166
|
c4System: options?.c4System,
|
|
@@ -30401,6 +30883,8 @@ init_flowchart_renderer();
|
|
|
30401
30883
|
init_echarts();
|
|
30402
30884
|
init_legend_svg();
|
|
30403
30885
|
init_legend_constants();
|
|
30886
|
+
init_legend_d3();
|
|
30887
|
+
init_legend_layout();
|
|
30404
30888
|
init_d3();
|
|
30405
30889
|
init_renderer10();
|
|
30406
30890
|
init_colors();
|
|
@@ -31247,6 +31731,7 @@ export {
|
|
|
31247
31731
|
computeCardMove,
|
|
31248
31732
|
computeInfra,
|
|
31249
31733
|
computeInfraLegendGroups,
|
|
31734
|
+
computeLegendLayout,
|
|
31250
31735
|
computeScatterLabelGraphics,
|
|
31251
31736
|
computeTimeTicks,
|
|
31252
31737
|
contrastText,
|
|
@@ -31258,6 +31743,7 @@ export {
|
|
|
31258
31743
|
formatDgmoError,
|
|
31259
31744
|
getAvailablePalettes,
|
|
31260
31745
|
getExtendedChartLegendGroups,
|
|
31746
|
+
getLegendReservedHeight,
|
|
31261
31747
|
getPalette,
|
|
31262
31748
|
getRenderCategory,
|
|
31263
31749
|
getSeriesColors,
|
|
@@ -31346,7 +31832,9 @@ export {
|
|
|
31346
31832
|
renderInfra,
|
|
31347
31833
|
renderKanban,
|
|
31348
31834
|
renderKanbanForExport,
|
|
31835
|
+
renderLegendD3,
|
|
31349
31836
|
renderLegendSvg,
|
|
31837
|
+
renderLegendSvgFromConfig,
|
|
31350
31838
|
renderOrg,
|
|
31351
31839
|
renderOrgForExport,
|
|
31352
31840
|
renderQuadrant,
|