@diagrammo/dgmo 0.8.9 → 0.8.11
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 +245 -672
- package/dist/editor.cjs.map +1 -1
- package/dist/editor.d.cts +2 -3
- package/dist/editor.d.ts +2 -3
- package/dist/editor.js.map +1 -1
- package/dist/index.cjs +1623 -800
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +153 -1
- package/dist/index.d.ts +153 -1
- package/dist/index.js +1619 -802
- 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 +14 -17
- 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 +34 -138
- package/src/c4/layout.ts +31 -10
- package/src/c4/renderer.ts +25 -138
- package/src/class/renderer.ts +185 -186
- package/src/d3.ts +194 -222
- package/src/echarts.ts +56 -57
- package/src/editor/index.ts +1 -2
- package/src/er/renderer.ts +52 -245
- package/src/gantt/renderer.ts +140 -182
- package/src/gantt/resolver.ts +19 -14
- package/src/index.ts +23 -1
- package/src/infra/renderer.ts +91 -244
- package/src/kanban/renderer.ts +29 -133
- package/src/label-layout.ts +286 -0
- package/src/org/renderer.ts +103 -170
- package/src/render.ts +39 -9
- package/src/sequence/parser.ts +4 -0
- package/src/sequence/renderer.ts +47 -154
- package/src/sitemap/layout.ts +180 -38
- package/src/sitemap/parser.ts +64 -23
- package/src/sitemap/renderer.ts +73 -161
- package/src/utils/arrows.ts +1 -1
- package/src/utils/legend-constants.ts +6 -0
- package/src/utils/legend-d3.ts +400 -0
- package/src/utils/legend-layout.ts +491 -0
- package/src/utils/legend-svg.ts +28 -2
- package/src/utils/legend-types.ts +166 -0
- package/src/utils/parsing.ts +1 -1
- package/src/utils/tag-groups.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -122,6 +122,183 @@ var init_branding = __esm({
|
|
|
122
122
|
}
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
+
// src/label-layout.ts
|
|
126
|
+
function rectsOverlap(a, b) {
|
|
127
|
+
return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
|
|
128
|
+
}
|
|
129
|
+
function rectCircleOverlap(rect, circle) {
|
|
130
|
+
const nearestX = Math.max(rect.x, Math.min(circle.cx, rect.x + rect.w));
|
|
131
|
+
const nearestY = Math.max(rect.y, Math.min(circle.cy, rect.y + rect.h));
|
|
132
|
+
const dx = nearestX - circle.cx;
|
|
133
|
+
const dy = nearestY - circle.cy;
|
|
134
|
+
return dx * dx + dy * dy < circle.r * circle.r;
|
|
135
|
+
}
|
|
136
|
+
function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius, fontSize) {
|
|
137
|
+
const labelHeight = fontSize + 4;
|
|
138
|
+
const stepSize = labelHeight + 2;
|
|
139
|
+
const minGap = pointRadius + 4;
|
|
140
|
+
const pointCircles = points.map((p) => ({
|
|
141
|
+
cx: p.cx,
|
|
142
|
+
cy: p.cy,
|
|
143
|
+
r: pointRadius
|
|
144
|
+
}));
|
|
145
|
+
const placedLabels = [];
|
|
146
|
+
const results = [];
|
|
147
|
+
for (let i = 0; i < points.length; i++) {
|
|
148
|
+
const pt = points[i];
|
|
149
|
+
const labelWidth = pt.label.length * fontSize * CHAR_WIDTH_RATIO + 8;
|
|
150
|
+
let best = null;
|
|
151
|
+
const directions = [
|
|
152
|
+
{
|
|
153
|
+
// Above
|
|
154
|
+
gen: (offset) => {
|
|
155
|
+
const lx = pt.cx - labelWidth / 2;
|
|
156
|
+
const ly = pt.cy - offset - labelHeight;
|
|
157
|
+
if (ly < chartBounds.top || lx < chartBounds.left || lx + labelWidth > chartBounds.right)
|
|
158
|
+
return null;
|
|
159
|
+
return {
|
|
160
|
+
rect: { x: lx, y: ly, w: labelWidth, h: labelHeight },
|
|
161
|
+
textX: pt.cx,
|
|
162
|
+
textY: ly + labelHeight / 2,
|
|
163
|
+
anchor: "middle"
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
// Below
|
|
169
|
+
gen: (offset) => {
|
|
170
|
+
const lx = pt.cx - labelWidth / 2;
|
|
171
|
+
const ly = pt.cy + offset;
|
|
172
|
+
if (ly + labelHeight > chartBounds.bottom || lx < chartBounds.left || lx + labelWidth > chartBounds.right)
|
|
173
|
+
return null;
|
|
174
|
+
return {
|
|
175
|
+
rect: { x: lx, y: ly, w: labelWidth, h: labelHeight },
|
|
176
|
+
textX: pt.cx,
|
|
177
|
+
textY: ly + labelHeight / 2,
|
|
178
|
+
anchor: "middle"
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
// Right
|
|
184
|
+
gen: (offset) => {
|
|
185
|
+
const lx = pt.cx + offset;
|
|
186
|
+
const ly = pt.cy - labelHeight / 2;
|
|
187
|
+
if (lx + labelWidth > chartBounds.right || ly < chartBounds.top || ly + labelHeight > chartBounds.bottom)
|
|
188
|
+
return null;
|
|
189
|
+
return {
|
|
190
|
+
rect: { x: lx, y: ly, w: labelWidth, h: labelHeight },
|
|
191
|
+
textX: lx,
|
|
192
|
+
textY: pt.cy,
|
|
193
|
+
anchor: "start"
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
// Left
|
|
199
|
+
gen: (offset) => {
|
|
200
|
+
const lx = pt.cx - offset - labelWidth;
|
|
201
|
+
const ly = pt.cy - labelHeight / 2;
|
|
202
|
+
if (lx < chartBounds.left || ly < chartBounds.top || ly + labelHeight > chartBounds.bottom)
|
|
203
|
+
return null;
|
|
204
|
+
return {
|
|
205
|
+
rect: { x: lx, y: ly, w: labelWidth, h: labelHeight },
|
|
206
|
+
textX: lx + labelWidth,
|
|
207
|
+
textY: pt.cy,
|
|
208
|
+
anchor: "end"
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
];
|
|
213
|
+
for (const { gen } of directions) {
|
|
214
|
+
for (let offset = minGap; ; offset += stepSize) {
|
|
215
|
+
const cand = gen(offset);
|
|
216
|
+
if (!cand) break;
|
|
217
|
+
let collision = false;
|
|
218
|
+
for (const pl of placedLabels) {
|
|
219
|
+
if (rectsOverlap(cand.rect, pl)) {
|
|
220
|
+
collision = true;
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (!collision) {
|
|
225
|
+
for (const circle of pointCircles) {
|
|
226
|
+
if (rectCircleOverlap(cand.rect, circle)) {
|
|
227
|
+
collision = true;
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (!collision) {
|
|
233
|
+
for (const obs of obstacles) {
|
|
234
|
+
if (rectsOverlap(cand.rect, obs)) {
|
|
235
|
+
collision = true;
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (!collision) {
|
|
241
|
+
const dist = offset;
|
|
242
|
+
if (!best || dist < best.dist) {
|
|
243
|
+
best = {
|
|
244
|
+
rect: cand.rect,
|
|
245
|
+
textX: cand.textX,
|
|
246
|
+
textY: cand.textY,
|
|
247
|
+
anchor: cand.anchor,
|
|
248
|
+
dist
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (!best) {
|
|
256
|
+
const lx = pt.cx - labelWidth / 2;
|
|
257
|
+
const ly = pt.cy - minGap - labelHeight;
|
|
258
|
+
best = {
|
|
259
|
+
rect: { x: lx, y: ly, w: labelWidth, h: labelHeight },
|
|
260
|
+
textX: pt.cx,
|
|
261
|
+
textY: ly + labelHeight / 2,
|
|
262
|
+
anchor: "middle",
|
|
263
|
+
dist: minGap
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
placedLabels.push(best.rect);
|
|
267
|
+
let connectorLine;
|
|
268
|
+
if (best.dist > minGap + stepSize) {
|
|
269
|
+
const dx = best.textX - pt.cx;
|
|
270
|
+
const dy = best.textY - pt.cy;
|
|
271
|
+
const angle = Math.atan2(dy, dx);
|
|
272
|
+
const x1 = pt.cx + Math.cos(angle) * pointRadius;
|
|
273
|
+
const y1 = pt.cy + Math.sin(angle) * pointRadius;
|
|
274
|
+
const x2 = Math.max(
|
|
275
|
+
best.rect.x,
|
|
276
|
+
Math.min(pt.cx, best.rect.x + best.rect.w)
|
|
277
|
+
);
|
|
278
|
+
const y2 = Math.max(
|
|
279
|
+
best.rect.y,
|
|
280
|
+
Math.min(pt.cy, best.rect.y + best.rect.h)
|
|
281
|
+
);
|
|
282
|
+
connectorLine = { x1, y1, x2, y2 };
|
|
283
|
+
}
|
|
284
|
+
results.push({
|
|
285
|
+
label: pt.label,
|
|
286
|
+
x: best.textX,
|
|
287
|
+
y: best.textY,
|
|
288
|
+
anchor: best.anchor,
|
|
289
|
+
connectorLine
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return results;
|
|
293
|
+
}
|
|
294
|
+
var CHAR_WIDTH_RATIO;
|
|
295
|
+
var init_label_layout = __esm({
|
|
296
|
+
"src/label-layout.ts"() {
|
|
297
|
+
"use strict";
|
|
298
|
+
CHAR_WIDTH_RATIO = 0.6;
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
|
|
125
302
|
// src/colors.ts
|
|
126
303
|
function resolveColor(color, palette) {
|
|
127
304
|
if (color.startsWith("#")) return null;
|
|
@@ -1792,7 +1969,7 @@ function measureLegendText(text, fontSize) {
|
|
|
1792
1969
|
}
|
|
1793
1970
|
return w;
|
|
1794
1971
|
}
|
|
1795
|
-
var LEGEND_HEIGHT, LEGEND_PILL_PAD, LEGEND_PILL_FONT_SIZE, LEGEND_CAPSULE_PAD, LEGEND_DOT_R, LEGEND_ENTRY_FONT_SIZE, LEGEND_ENTRY_DOT_GAP, LEGEND_ENTRY_TRAIL, LEGEND_GROUP_GAP, LEGEND_EYE_SIZE, LEGEND_EYE_GAP, LEGEND_ICON_W, CHAR_W, DEFAULT_W, EYE_OPEN_PATH, EYE_CLOSED_PATH;
|
|
1972
|
+
var LEGEND_HEIGHT, LEGEND_PILL_PAD, LEGEND_PILL_FONT_SIZE, LEGEND_CAPSULE_PAD, LEGEND_DOT_R, LEGEND_ENTRY_FONT_SIZE, LEGEND_ENTRY_DOT_GAP, LEGEND_ENTRY_TRAIL, LEGEND_GROUP_GAP, LEGEND_EYE_SIZE, LEGEND_EYE_GAP, LEGEND_ICON_W, LEGEND_MAX_ENTRY_ROWS, CHAR_W, DEFAULT_W, EYE_OPEN_PATH, EYE_CLOSED_PATH;
|
|
1796
1973
|
var init_legend_constants = __esm({
|
|
1797
1974
|
"src/utils/legend-constants.ts"() {
|
|
1798
1975
|
"use strict";
|
|
@@ -1808,6 +1985,7 @@ var init_legend_constants = __esm({
|
|
|
1808
1985
|
LEGEND_EYE_SIZE = 14;
|
|
1809
1986
|
LEGEND_EYE_GAP = 6;
|
|
1810
1987
|
LEGEND_ICON_W = 20;
|
|
1988
|
+
LEGEND_MAX_ENTRY_ROWS = 3;
|
|
1811
1989
|
CHAR_W = {
|
|
1812
1990
|
" ": 0.28,
|
|
1813
1991
|
"!": 0.28,
|
|
@@ -1901,6 +2079,492 @@ var init_legend_constants = __esm({
|
|
|
1901
2079
|
}
|
|
1902
2080
|
});
|
|
1903
2081
|
|
|
2082
|
+
// src/utils/legend-layout.ts
|
|
2083
|
+
function pillWidth(name) {
|
|
2084
|
+
return measureLegendText(name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
2085
|
+
}
|
|
2086
|
+
function entriesWidth(entries) {
|
|
2087
|
+
let w = 0;
|
|
2088
|
+
for (const e of entries) {
|
|
2089
|
+
w += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
2090
|
+
}
|
|
2091
|
+
return w;
|
|
2092
|
+
}
|
|
2093
|
+
function entryWidth(value) {
|
|
2094
|
+
return LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
2095
|
+
}
|
|
2096
|
+
function controlWidth(control) {
|
|
2097
|
+
let w = CONTROL_PILL_PAD;
|
|
2098
|
+
if (control.label) {
|
|
2099
|
+
w += measureLegendText(control.label, CONTROL_FONT_SIZE);
|
|
2100
|
+
if (control.icon) w += CONTROL_ICON_GAP;
|
|
2101
|
+
}
|
|
2102
|
+
if (control.icon) w += 14;
|
|
2103
|
+
if (control.children) {
|
|
2104
|
+
for (const child of control.children) {
|
|
2105
|
+
w += measureLegendText(child.label, CONTROL_FONT_SIZE) + 12;
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
return w;
|
|
2109
|
+
}
|
|
2110
|
+
function capsuleWidth(name, entries, containerWidth, addonWidth = 0) {
|
|
2111
|
+
const pw = pillWidth(name);
|
|
2112
|
+
const maxCapsuleW = containerWidth;
|
|
2113
|
+
const baseW = LEGEND_CAPSULE_PAD * 2 + pw + 4 + addonWidth;
|
|
2114
|
+
const ew = entriesWidth(entries);
|
|
2115
|
+
const singleRowW = baseW + ew;
|
|
2116
|
+
if (singleRowW <= maxCapsuleW) {
|
|
2117
|
+
return {
|
|
2118
|
+
width: singleRowW,
|
|
2119
|
+
entryRows: 1,
|
|
2120
|
+
moreCount: 0,
|
|
2121
|
+
visibleEntries: entries.length
|
|
2122
|
+
};
|
|
2123
|
+
}
|
|
2124
|
+
const rowWidth = maxCapsuleW - LEGEND_CAPSULE_PAD * 2;
|
|
2125
|
+
let row = 1;
|
|
2126
|
+
let rowX = pw + 4;
|
|
2127
|
+
let visible = 0;
|
|
2128
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2129
|
+
const ew2 = entryWidth(entries[i].value);
|
|
2130
|
+
if (rowX + ew2 > rowWidth && rowX > pw + 4) {
|
|
2131
|
+
row++;
|
|
2132
|
+
rowX = 0;
|
|
2133
|
+
if (row > LEGEND_MAX_ENTRY_ROWS) {
|
|
2134
|
+
return {
|
|
2135
|
+
width: maxCapsuleW,
|
|
2136
|
+
entryRows: LEGEND_MAX_ENTRY_ROWS,
|
|
2137
|
+
moreCount: entries.length - visible,
|
|
2138
|
+
visibleEntries: visible
|
|
2139
|
+
};
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
rowX += ew2;
|
|
2143
|
+
visible++;
|
|
2144
|
+
}
|
|
2145
|
+
return {
|
|
2146
|
+
width: maxCapsuleW,
|
|
2147
|
+
entryRows: row,
|
|
2148
|
+
moreCount: 0,
|
|
2149
|
+
visibleEntries: entries.length
|
|
2150
|
+
};
|
|
2151
|
+
}
|
|
2152
|
+
function computeLegendLayout(config, state, containerWidth) {
|
|
2153
|
+
const { groups, controls: configControls, mode } = config;
|
|
2154
|
+
const isExport = mode === "inline";
|
|
2155
|
+
const activeGroupName = state.activeGroup?.toLowerCase() ?? null;
|
|
2156
|
+
if (isExport && !activeGroupName) {
|
|
2157
|
+
return {
|
|
2158
|
+
height: 0,
|
|
2159
|
+
width: 0,
|
|
2160
|
+
rows: [],
|
|
2161
|
+
controls: [],
|
|
2162
|
+
pills: [],
|
|
2163
|
+
activeCapsule: void 0
|
|
2164
|
+
};
|
|
2165
|
+
}
|
|
2166
|
+
const visibleGroups = config.showEmptyGroups ? groups : groups.filter((g) => g.entries.length > 0);
|
|
2167
|
+
if (visibleGroups.length === 0 && (!configControls || configControls.length === 0)) {
|
|
2168
|
+
return {
|
|
2169
|
+
height: 0,
|
|
2170
|
+
width: 0,
|
|
2171
|
+
rows: [],
|
|
2172
|
+
controls: [],
|
|
2173
|
+
pills: [],
|
|
2174
|
+
activeCapsule: void 0
|
|
2175
|
+
};
|
|
2176
|
+
}
|
|
2177
|
+
const controlLayouts = [];
|
|
2178
|
+
let totalControlsW = 0;
|
|
2179
|
+
if (configControls && !isExport) {
|
|
2180
|
+
for (const ctrl of configControls) {
|
|
2181
|
+
const w = controlWidth(ctrl);
|
|
2182
|
+
controlLayouts.push({
|
|
2183
|
+
id: ctrl.id,
|
|
2184
|
+
x: 0,
|
|
2185
|
+
// positioned later
|
|
2186
|
+
y: 0,
|
|
2187
|
+
width: w,
|
|
2188
|
+
height: LEGEND_HEIGHT,
|
|
2189
|
+
icon: ctrl.icon,
|
|
2190
|
+
label: ctrl.label,
|
|
2191
|
+
exportBehavior: ctrl.exportBehavior,
|
|
2192
|
+
children: ctrl.children?.map((c) => ({
|
|
2193
|
+
id: c.id,
|
|
2194
|
+
label: c.label,
|
|
2195
|
+
x: 0,
|
|
2196
|
+
y: 0,
|
|
2197
|
+
width: measureLegendText(c.label, CONTROL_FONT_SIZE) + 12,
|
|
2198
|
+
isActive: c.isActive
|
|
2199
|
+
}))
|
|
2200
|
+
});
|
|
2201
|
+
totalControlsW += w + CONTROL_GAP;
|
|
2202
|
+
}
|
|
2203
|
+
if (totalControlsW > 0) totalControlsW -= CONTROL_GAP;
|
|
2204
|
+
} else if (configControls && isExport) {
|
|
2205
|
+
for (const ctrl of configControls) {
|
|
2206
|
+
if (ctrl.exportBehavior === "strip") continue;
|
|
2207
|
+
const w = controlWidth(ctrl);
|
|
2208
|
+
controlLayouts.push({
|
|
2209
|
+
id: ctrl.id,
|
|
2210
|
+
x: 0,
|
|
2211
|
+
y: 0,
|
|
2212
|
+
width: w,
|
|
2213
|
+
height: LEGEND_HEIGHT,
|
|
2214
|
+
icon: ctrl.icon,
|
|
2215
|
+
label: ctrl.label,
|
|
2216
|
+
exportBehavior: ctrl.exportBehavior,
|
|
2217
|
+
children: ctrl.children?.map((c) => ({
|
|
2218
|
+
id: c.id,
|
|
2219
|
+
label: c.label,
|
|
2220
|
+
x: 0,
|
|
2221
|
+
y: 0,
|
|
2222
|
+
width: measureLegendText(c.label, CONTROL_FONT_SIZE) + 12,
|
|
2223
|
+
isActive: c.isActive
|
|
2224
|
+
}))
|
|
2225
|
+
});
|
|
2226
|
+
totalControlsW += w + CONTROL_GAP;
|
|
2227
|
+
}
|
|
2228
|
+
if (totalControlsW > 0) totalControlsW -= CONTROL_GAP;
|
|
2229
|
+
}
|
|
2230
|
+
const controlsSpace = totalControlsW > 0 ? totalControlsW + LEGEND_GROUP_GAP * 2 : 0;
|
|
2231
|
+
const groupAvailW = containerWidth - controlsSpace;
|
|
2232
|
+
const pills = [];
|
|
2233
|
+
let activeCapsule;
|
|
2234
|
+
for (const g of visibleGroups) {
|
|
2235
|
+
const isActive = activeGroupName === g.name.toLowerCase();
|
|
2236
|
+
if (isExport && !isActive) continue;
|
|
2237
|
+
if (isActive) {
|
|
2238
|
+
activeCapsule = buildCapsuleLayout(
|
|
2239
|
+
g,
|
|
2240
|
+
containerWidth,
|
|
2241
|
+
config.capsulePillAddonWidth ?? 0
|
|
2242
|
+
);
|
|
2243
|
+
} else {
|
|
2244
|
+
const pw = pillWidth(g.name);
|
|
2245
|
+
pills.push({
|
|
2246
|
+
groupName: g.name,
|
|
2247
|
+
x: 0,
|
|
2248
|
+
y: 0,
|
|
2249
|
+
width: pw,
|
|
2250
|
+
height: LEGEND_HEIGHT,
|
|
2251
|
+
isActive: false
|
|
2252
|
+
});
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
const rows = layoutRows(
|
|
2256
|
+
activeCapsule,
|
|
2257
|
+
pills,
|
|
2258
|
+
controlLayouts,
|
|
2259
|
+
groupAvailW,
|
|
2260
|
+
containerWidth,
|
|
2261
|
+
totalControlsW
|
|
2262
|
+
);
|
|
2263
|
+
const height = rows.length * LEGEND_HEIGHT;
|
|
2264
|
+
const width = containerWidth;
|
|
2265
|
+
return {
|
|
2266
|
+
height,
|
|
2267
|
+
width,
|
|
2268
|
+
rows,
|
|
2269
|
+
activeCapsule,
|
|
2270
|
+
controls: controlLayouts,
|
|
2271
|
+
pills
|
|
2272
|
+
};
|
|
2273
|
+
}
|
|
2274
|
+
function buildCapsuleLayout(group, containerWidth, addonWidth = 0) {
|
|
2275
|
+
const pw = pillWidth(group.name);
|
|
2276
|
+
const info = capsuleWidth(
|
|
2277
|
+
group.name,
|
|
2278
|
+
group.entries,
|
|
2279
|
+
containerWidth,
|
|
2280
|
+
addonWidth
|
|
2281
|
+
);
|
|
2282
|
+
const pill = {
|
|
2283
|
+
groupName: group.name,
|
|
2284
|
+
x: LEGEND_CAPSULE_PAD,
|
|
2285
|
+
y: LEGEND_CAPSULE_PAD,
|
|
2286
|
+
width: pw,
|
|
2287
|
+
height: LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2,
|
|
2288
|
+
isActive: true
|
|
2289
|
+
};
|
|
2290
|
+
const entries = [];
|
|
2291
|
+
let ex = LEGEND_CAPSULE_PAD + pw + 4 + addonWidth;
|
|
2292
|
+
let ey = 0;
|
|
2293
|
+
let rowX = ex;
|
|
2294
|
+
const maxRowW = containerWidth - LEGEND_CAPSULE_PAD * 2;
|
|
2295
|
+
let currentRow = 0;
|
|
2296
|
+
for (let i = 0; i < info.visibleEntries; i++) {
|
|
2297
|
+
const entry = group.entries[i];
|
|
2298
|
+
const ew = entryWidth(entry.value);
|
|
2299
|
+
if (rowX + ew > maxRowW && rowX > ex && i > 0) {
|
|
2300
|
+
currentRow++;
|
|
2301
|
+
rowX = 0;
|
|
2302
|
+
ey = currentRow * LEGEND_HEIGHT;
|
|
2303
|
+
if (currentRow === 0) ex = LEGEND_CAPSULE_PAD + pw + 4;
|
|
2304
|
+
}
|
|
2305
|
+
const dotCx = rowX + LEGEND_DOT_R;
|
|
2306
|
+
const dotCy = ey + LEGEND_HEIGHT / 2;
|
|
2307
|
+
const textX = rowX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
2308
|
+
const textY = ey + LEGEND_HEIGHT / 2;
|
|
2309
|
+
entries.push({
|
|
2310
|
+
value: entry.value,
|
|
2311
|
+
color: entry.color,
|
|
2312
|
+
x: rowX,
|
|
2313
|
+
y: ey,
|
|
2314
|
+
dotCx,
|
|
2315
|
+
dotCy,
|
|
2316
|
+
textX,
|
|
2317
|
+
textY
|
|
2318
|
+
});
|
|
2319
|
+
rowX += ew;
|
|
2320
|
+
}
|
|
2321
|
+
const totalRows = info.entryRows;
|
|
2322
|
+
const capsuleH = totalRows * LEGEND_HEIGHT;
|
|
2323
|
+
return {
|
|
2324
|
+
groupName: group.name,
|
|
2325
|
+
x: 0,
|
|
2326
|
+
y: 0,
|
|
2327
|
+
width: info.width,
|
|
2328
|
+
height: capsuleH,
|
|
2329
|
+
pill,
|
|
2330
|
+
entries,
|
|
2331
|
+
moreCount: info.moreCount > 0 ? info.moreCount : void 0,
|
|
2332
|
+
addonX: addonWidth > 0 ? LEGEND_CAPSULE_PAD + pw + 4 : void 0
|
|
2333
|
+
};
|
|
2334
|
+
}
|
|
2335
|
+
function layoutRows(activeCapsule, pills, controls, groupAvailW, containerWidth, totalControlsW) {
|
|
2336
|
+
const rows = [];
|
|
2337
|
+
const groupItems = [];
|
|
2338
|
+
if (activeCapsule) groupItems.push(activeCapsule);
|
|
2339
|
+
groupItems.push(...pills);
|
|
2340
|
+
let currentRowItems = [];
|
|
2341
|
+
let currentRowW = 0;
|
|
2342
|
+
let rowY = 0;
|
|
2343
|
+
for (const item of groupItems) {
|
|
2344
|
+
const itemW = item.width + LEGEND_GROUP_GAP;
|
|
2345
|
+
if (currentRowW + item.width > groupAvailW && currentRowItems.length > 0) {
|
|
2346
|
+
centerRowItems(currentRowItems, containerWidth, totalControlsW);
|
|
2347
|
+
rows.push({ y: rowY, items: currentRowItems });
|
|
2348
|
+
rowY += LEGEND_HEIGHT;
|
|
2349
|
+
currentRowItems = [];
|
|
2350
|
+
currentRowW = 0;
|
|
2351
|
+
}
|
|
2352
|
+
item.x = currentRowW;
|
|
2353
|
+
item.y = rowY;
|
|
2354
|
+
currentRowItems.push(item);
|
|
2355
|
+
currentRowW += itemW;
|
|
2356
|
+
}
|
|
2357
|
+
if (controls.length > 0) {
|
|
2358
|
+
let cx = containerWidth;
|
|
2359
|
+
for (let i = controls.length - 1; i >= 0; i--) {
|
|
2360
|
+
cx -= controls[i].width;
|
|
2361
|
+
controls[i].x = cx;
|
|
2362
|
+
controls[i].y = 0;
|
|
2363
|
+
cx -= CONTROL_GAP;
|
|
2364
|
+
}
|
|
2365
|
+
if (rows.length > 0) {
|
|
2366
|
+
rows[0].items.push(...controls);
|
|
2367
|
+
} else if (currentRowItems.length > 0) {
|
|
2368
|
+
currentRowItems.push(...controls);
|
|
2369
|
+
} else {
|
|
2370
|
+
currentRowItems.push(...controls);
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
if (currentRowItems.length > 0) {
|
|
2374
|
+
centerRowItems(currentRowItems, containerWidth, totalControlsW);
|
|
2375
|
+
rows.push({ y: rowY, items: currentRowItems });
|
|
2376
|
+
}
|
|
2377
|
+
if (rows.length === 0) {
|
|
2378
|
+
rows.push({ y: 0, items: [] });
|
|
2379
|
+
}
|
|
2380
|
+
return rows;
|
|
2381
|
+
}
|
|
2382
|
+
function centerRowItems(items, containerWidth, totalControlsW) {
|
|
2383
|
+
const groupItems = items.filter((it) => "groupName" in it);
|
|
2384
|
+
if (groupItems.length === 0) return;
|
|
2385
|
+
const totalGroupW = groupItems.reduce((s, it) => s + it.width, 0) + (groupItems.length - 1) * LEGEND_GROUP_GAP;
|
|
2386
|
+
const availW = containerWidth - (totalControlsW > 0 ? totalControlsW + LEGEND_GROUP_GAP * 2 : 0);
|
|
2387
|
+
const offset = Math.max(0, (availW - totalGroupW) / 2);
|
|
2388
|
+
let x = offset;
|
|
2389
|
+
for (const item of groupItems) {
|
|
2390
|
+
item.x = x;
|
|
2391
|
+
x += item.width + LEGEND_GROUP_GAP;
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
function getLegendReservedHeight(config, state, containerWidth) {
|
|
2395
|
+
const layout = computeLegendLayout(config, state, containerWidth);
|
|
2396
|
+
return layout.height;
|
|
2397
|
+
}
|
|
2398
|
+
var CONTROL_PILL_PAD, CONTROL_FONT_SIZE, CONTROL_ICON_GAP, CONTROL_GAP;
|
|
2399
|
+
var init_legend_layout = __esm({
|
|
2400
|
+
"src/utils/legend-layout.ts"() {
|
|
2401
|
+
"use strict";
|
|
2402
|
+
init_legend_constants();
|
|
2403
|
+
CONTROL_PILL_PAD = 16;
|
|
2404
|
+
CONTROL_FONT_SIZE = 11;
|
|
2405
|
+
CONTROL_ICON_GAP = 4;
|
|
2406
|
+
CONTROL_GAP = 8;
|
|
2407
|
+
}
|
|
2408
|
+
});
|
|
2409
|
+
|
|
2410
|
+
// src/utils/legend-d3.ts
|
|
2411
|
+
function renderLegendD3(container, config, state, palette, isDark, callbacks, containerWidth) {
|
|
2412
|
+
const width = containerWidth ?? parseFloat(container.attr("width") || "800");
|
|
2413
|
+
let currentState = { ...state };
|
|
2414
|
+
let currentLayout;
|
|
2415
|
+
const legendG = container.append("g").attr("class", "dgmo-legend");
|
|
2416
|
+
function render2() {
|
|
2417
|
+
currentLayout = computeLegendLayout(config, currentState, width);
|
|
2418
|
+
legendG.selectAll("*").remove();
|
|
2419
|
+
if (currentLayout.height === 0) return;
|
|
2420
|
+
if (currentState.activeGroup) {
|
|
2421
|
+
legendG.attr(
|
|
2422
|
+
"data-legend-active",
|
|
2423
|
+
currentState.activeGroup.toLowerCase()
|
|
2424
|
+
);
|
|
2425
|
+
} else {
|
|
2426
|
+
legendG.attr("data-legend-active", null);
|
|
2427
|
+
}
|
|
2428
|
+
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
2429
|
+
const pillBorder = mix(palette.textMuted, palette.bg, 50);
|
|
2430
|
+
if (currentLayout.activeCapsule) {
|
|
2431
|
+
renderCapsule(
|
|
2432
|
+
legendG,
|
|
2433
|
+
currentLayout.activeCapsule,
|
|
2434
|
+
palette,
|
|
2435
|
+
groupBg,
|
|
2436
|
+
pillBorder,
|
|
2437
|
+
isDark,
|
|
2438
|
+
callbacks
|
|
2439
|
+
);
|
|
2440
|
+
}
|
|
2441
|
+
for (const pill of currentLayout.pills) {
|
|
2442
|
+
renderPill(legendG, pill, palette, groupBg, callbacks);
|
|
2443
|
+
}
|
|
2444
|
+
for (const ctrl of currentLayout.controls) {
|
|
2445
|
+
renderControl(
|
|
2446
|
+
legendG,
|
|
2447
|
+
ctrl,
|
|
2448
|
+
palette,
|
|
2449
|
+
groupBg,
|
|
2450
|
+
pillBorder,
|
|
2451
|
+
isDark,
|
|
2452
|
+
config.controls
|
|
2453
|
+
);
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
render2();
|
|
2457
|
+
return {
|
|
2458
|
+
setState(newState) {
|
|
2459
|
+
currentState = { ...newState };
|
|
2460
|
+
render2();
|
|
2461
|
+
},
|
|
2462
|
+
destroy() {
|
|
2463
|
+
legendG.remove();
|
|
2464
|
+
},
|
|
2465
|
+
getHeight() {
|
|
2466
|
+
return currentLayout?.height ?? 0;
|
|
2467
|
+
},
|
|
2468
|
+
getLayout() {
|
|
2469
|
+
return currentLayout;
|
|
2470
|
+
}
|
|
2471
|
+
};
|
|
2472
|
+
}
|
|
2473
|
+
function renderCapsule(parent, capsule, palette, groupBg, pillBorder, _isDark, callbacks) {
|
|
2474
|
+
const g = parent.append("g").attr("transform", `translate(${capsule.x},${capsule.y})`).attr("data-legend-group", capsule.groupName.toLowerCase()).style("cursor", "pointer");
|
|
2475
|
+
g.append("rect").attr("width", capsule.width).attr("height", capsule.height).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
2476
|
+
const pill = capsule.pill;
|
|
2477
|
+
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);
|
|
2478
|
+
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);
|
|
2479
|
+
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);
|
|
2480
|
+
for (const entry of capsule.entries) {
|
|
2481
|
+
const entryG = g.append("g").attr("data-legend-entry", entry.value.toLowerCase()).attr("data-series-name", entry.value).style("cursor", "pointer");
|
|
2482
|
+
entryG.append("circle").attr("cx", entry.dotCx).attr("cy", entry.dotCy).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
2483
|
+
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);
|
|
2484
|
+
if (callbacks?.onEntryHover) {
|
|
2485
|
+
const groupName = capsule.groupName;
|
|
2486
|
+
const entryValue = entry.value;
|
|
2487
|
+
const onHover = callbacks.onEntryHover;
|
|
2488
|
+
entryG.on("mouseenter", () => onHover(groupName, entryValue)).on("mouseleave", () => onHover(groupName, null));
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2491
|
+
if (capsule.moreCount) {
|
|
2492
|
+
const lastEntry = capsule.entries[capsule.entries.length - 1];
|
|
2493
|
+
const moreX = lastEntry ? lastEntry.textX + measureLegendText(lastEntry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_DOT_GAP * 2 : pill.x + pill.width + 8;
|
|
2494
|
+
const moreY = lastEntry?.textY ?? LEGEND_HEIGHT / 2;
|
|
2495
|
+
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`);
|
|
2496
|
+
}
|
|
2497
|
+
if (callbacks?.onGroupToggle) {
|
|
2498
|
+
const cb = callbacks.onGroupToggle;
|
|
2499
|
+
const name = capsule.groupName;
|
|
2500
|
+
g.on("click", () => cb(name));
|
|
2501
|
+
}
|
|
2502
|
+
if (callbacks?.onGroupRendered) {
|
|
2503
|
+
callbacks.onGroupRendered(capsule.groupName, g, true);
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
function renderPill(parent, pill, palette, groupBg, callbacks) {
|
|
2507
|
+
const g = parent.append("g").attr("transform", `translate(${pill.x},${pill.y})`).attr("data-legend-group", pill.groupName.toLowerCase()).style("cursor", "pointer");
|
|
2508
|
+
g.append("rect").attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", groupBg);
|
|
2509
|
+
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);
|
|
2510
|
+
if (callbacks?.onGroupToggle) {
|
|
2511
|
+
const cb = callbacks.onGroupToggle;
|
|
2512
|
+
const name = pill.groupName;
|
|
2513
|
+
g.on("click", () => cb(name));
|
|
2514
|
+
}
|
|
2515
|
+
if (callbacks?.onGroupRendered) {
|
|
2516
|
+
callbacks.onGroupRendered(pill.groupName, g, false);
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
function renderControl(parent, ctrl, palette, _groupBg, pillBorder, _isDark, configControls) {
|
|
2520
|
+
const g = parent.append("g").attr("transform", `translate(${ctrl.x},${ctrl.y})`).attr("data-legend-control", ctrl.id).style("cursor", "pointer");
|
|
2521
|
+
if (ctrl.exportBehavior === "strip") {
|
|
2522
|
+
g.attr("data-export-ignore", "true");
|
|
2523
|
+
}
|
|
2524
|
+
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);
|
|
2525
|
+
let textX = ctrl.width / 2;
|
|
2526
|
+
if (ctrl.icon && ctrl.label) {
|
|
2527
|
+
const iconG = g.append("g").attr("transform", `translate(8,${(ctrl.height - 14) / 2})`);
|
|
2528
|
+
iconG.html(ctrl.icon);
|
|
2529
|
+
textX = 8 + 14 + LEGEND_ENTRY_DOT_GAP + measureLegendText(ctrl.label, LEGEND_PILL_FONT_SIZE) / 2;
|
|
2530
|
+
}
|
|
2531
|
+
if (ctrl.label) {
|
|
2532
|
+
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);
|
|
2533
|
+
}
|
|
2534
|
+
if (ctrl.children) {
|
|
2535
|
+
let cx = ctrl.width + 4;
|
|
2536
|
+
for (const child of ctrl.children) {
|
|
2537
|
+
const childG = g.append("g").attr("transform", `translate(${cx},0)`).style("cursor", "pointer");
|
|
2538
|
+
childG.append("rect").attr("width", child.width).attr("height", ctrl.height).attr("rx", ctrl.height / 2).attr(
|
|
2539
|
+
"fill",
|
|
2540
|
+
child.isActive ? palette.primary ?? palette.text : "none"
|
|
2541
|
+
).attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
2542
|
+
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);
|
|
2543
|
+
const configCtrl2 = configControls?.find((c) => c.id === ctrl.id);
|
|
2544
|
+
const configChild = configCtrl2?.children?.find((c) => c.id === child.id);
|
|
2545
|
+
if (configChild?.onClick) {
|
|
2546
|
+
const onClick = configChild.onClick;
|
|
2547
|
+
childG.on("click", () => onClick());
|
|
2548
|
+
}
|
|
2549
|
+
cx += child.width + 4;
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
const configCtrl = configControls?.find((c) => c.id === ctrl.id);
|
|
2553
|
+
if (configCtrl?.onClick) {
|
|
2554
|
+
const onClick = configCtrl.onClick;
|
|
2555
|
+
g.on("click", () => onClick());
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
var init_legend_d3 = __esm({
|
|
2559
|
+
"src/utils/legend-d3.ts"() {
|
|
2560
|
+
"use strict";
|
|
2561
|
+
init_legend_constants();
|
|
2562
|
+
init_legend_layout();
|
|
2563
|
+
init_color_utils();
|
|
2564
|
+
init_fonts();
|
|
2565
|
+
}
|
|
2566
|
+
});
|
|
2567
|
+
|
|
1904
2568
|
// src/utils/title-constants.ts
|
|
1905
2569
|
var TITLE_FONT_SIZE, TITLE_FONT_WEIGHT, TITLE_Y, TITLE_OFFSET;
|
|
1906
2570
|
var init_title_constants = __esm({
|
|
@@ -2946,7 +3610,8 @@ function parseSequenceDgmo(content) {
|
|
|
2946
3610
|
if (top.block.type === "if") {
|
|
2947
3611
|
const branch = {
|
|
2948
3612
|
label: elseIfMatch[1].trim(),
|
|
2949
|
-
children: []
|
|
3613
|
+
children: [],
|
|
3614
|
+
lineNumber
|
|
2950
3615
|
};
|
|
2951
3616
|
if (!top.block.elseIfBranches) top.block.elseIfBranches = [];
|
|
2952
3617
|
top.block.elseIfBranches.push(branch);
|
|
@@ -2969,6 +3634,7 @@ function parseSequenceDgmo(content) {
|
|
|
2969
3634
|
if (top.block.type === "if") {
|
|
2970
3635
|
top.inElse = true;
|
|
2971
3636
|
top.activeElseIfBranch = void 0;
|
|
3637
|
+
top.block.elseLineNumber = lineNumber;
|
|
2972
3638
|
}
|
|
2973
3639
|
}
|
|
2974
3640
|
continue;
|
|
@@ -4830,10 +5496,10 @@ var init_chart = __esm({
|
|
|
4830
5496
|
function esc(s) {
|
|
4831
5497
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
4832
5498
|
}
|
|
4833
|
-
function
|
|
5499
|
+
function pillWidth2(name) {
|
|
4834
5500
|
return measureLegendText(name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
4835
5501
|
}
|
|
4836
|
-
function
|
|
5502
|
+
function entriesWidth2(entries) {
|
|
4837
5503
|
let w = 0;
|
|
4838
5504
|
for (const e of entries) {
|
|
4839
5505
|
w += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
@@ -4841,9 +5507,9 @@ function entriesWidth(entries) {
|
|
|
4841
5507
|
return w;
|
|
4842
5508
|
}
|
|
4843
5509
|
function groupTotalWidth(name, entries, isActive) {
|
|
4844
|
-
const pw =
|
|
5510
|
+
const pw = pillWidth2(name);
|
|
4845
5511
|
if (!isActive) return pw;
|
|
4846
|
-
return LEGEND_CAPSULE_PAD * 2 + pw + 4 +
|
|
5512
|
+
return LEGEND_CAPSULE_PAD * 2 + pw + 4 + entriesWidth2(entries);
|
|
4847
5513
|
}
|
|
4848
5514
|
function renderLegendSvg(groups, options) {
|
|
4849
5515
|
if (groups.length === 0) return { svg: "", height: 0, width: 0 };
|
|
@@ -4851,7 +5517,7 @@ function renderLegendSvg(groups, options) {
|
|
|
4851
5517
|
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
4852
5518
|
const items = groups.filter((g) => g.entries.length > 0).map((g) => {
|
|
4853
5519
|
const isActive = !!activeGroup && g.name.toLowerCase() === activeGroup.toLowerCase();
|
|
4854
|
-
const pw =
|
|
5520
|
+
const pw = pillWidth2(g.name);
|
|
4855
5521
|
const tw = groupTotalWidth(g.name, g.entries, isActive);
|
|
4856
5522
|
return { group: g, isActive, pillWidth: pw, totalWidth: tw };
|
|
4857
5523
|
});
|
|
@@ -4905,6 +5571,19 @@ function renderLegendSvg(groups, options) {
|
|
|
4905
5571
|
const svg = `<g${classAttr}${activeAttr}>${parts.join("")}</g>`;
|
|
4906
5572
|
return { svg, height: LEGEND_HEIGHT, width: totalWidth };
|
|
4907
5573
|
}
|
|
5574
|
+
function renderLegendSvgFromConfig(config, state, palette, containerWidth) {
|
|
5575
|
+
return renderLegendSvg(config.groups, {
|
|
5576
|
+
palette: {
|
|
5577
|
+
bg: palette.bg,
|
|
5578
|
+
surface: palette.surface,
|
|
5579
|
+
text: palette.text,
|
|
5580
|
+
textMuted: palette.textMuted
|
|
5581
|
+
},
|
|
5582
|
+
isDark: palette.isDark,
|
|
5583
|
+
containerWidth,
|
|
5584
|
+
activeGroup: state.activeGroup
|
|
5585
|
+
});
|
|
5586
|
+
}
|
|
4908
5587
|
var init_legend_svg = __esm({
|
|
4909
5588
|
"src/utils/legend-svg.ts"() {
|
|
4910
5589
|
"use strict";
|
|
@@ -5349,7 +6028,8 @@ function buildExtendedChartOption(parsed, palette, isDark) {
|
|
|
5349
6028
|
}
|
|
5350
6029
|
const { textColor, axisLineColor, gridOpacity, colors, titleConfig } = buildChartCommons(parsed, palette, isDark);
|
|
5351
6030
|
if (parsed.type === "sankey") {
|
|
5352
|
-
|
|
6031
|
+
const bg = isDark ? palette.surface : palette.bg;
|
|
6032
|
+
return buildSankeyOption(parsed, textColor, colors, bg, titleConfig);
|
|
5353
6033
|
}
|
|
5354
6034
|
if (parsed.type === "chord") {
|
|
5355
6035
|
const bg = isDark ? palette.surface : palette.bg;
|
|
@@ -5392,7 +6072,7 @@ function buildExtendedChartOption(parsed, palette, isDark) {
|
|
|
5392
6072
|
titleConfig
|
|
5393
6073
|
);
|
|
5394
6074
|
}
|
|
5395
|
-
function buildSankeyOption(parsed, textColor, colors, titleConfig) {
|
|
6075
|
+
function buildSankeyOption(parsed, textColor, colors, bg, titleConfig) {
|
|
5396
6076
|
const nodeSet = /* @__PURE__ */ new Set();
|
|
5397
6077
|
if (parsed.links) {
|
|
5398
6078
|
for (const link of parsed.links) {
|
|
@@ -5400,12 +6080,15 @@ function buildSankeyOption(parsed, textColor, colors, titleConfig) {
|
|
|
5400
6080
|
nodeSet.add(link.target);
|
|
5401
6081
|
}
|
|
5402
6082
|
}
|
|
5403
|
-
const
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
6083
|
+
const tintNode = (c) => mix(c, bg, 75);
|
|
6084
|
+
const tintLink = (c) => mix(c, bg, 45);
|
|
6085
|
+
const nodeColorMap = /* @__PURE__ */ new Map();
|
|
6086
|
+
const nodes = Array.from(nodeSet).map((name, index) => {
|
|
6087
|
+
const raw = parsed.nodeColors?.[name] ?? colors[index % colors.length];
|
|
6088
|
+
const tinted = tintNode(raw);
|
|
6089
|
+
nodeColorMap.set(name, tintLink(raw));
|
|
6090
|
+
return { name, itemStyle: { color: tinted } };
|
|
6091
|
+
});
|
|
5409
6092
|
return {
|
|
5410
6093
|
...CHART_BASE,
|
|
5411
6094
|
title: titleConfig,
|
|
@@ -5428,11 +6111,13 @@ function buildSankeyOption(parsed, textColor, colors, titleConfig) {
|
|
|
5428
6111
|
source: link.source,
|
|
5429
6112
|
target: link.target,
|
|
5430
6113
|
value: link.value,
|
|
5431
|
-
|
|
6114
|
+
lineStyle: {
|
|
6115
|
+
color: link.color ? tintLink(link.color) : nodeColorMap.get(link.source)
|
|
6116
|
+
}
|
|
5432
6117
|
})),
|
|
5433
6118
|
lineStyle: {
|
|
5434
|
-
|
|
5435
|
-
|
|
6119
|
+
curveness: 0.5,
|
|
6120
|
+
opacity: 0.6
|
|
5436
6121
|
},
|
|
5437
6122
|
label: {
|
|
5438
6123
|
color: textColor,
|
|
@@ -5689,16 +6374,6 @@ function getExtendedChartLegendGroups(parsed, colors) {
|
|
|
5689
6374
|
}
|
|
5690
6375
|
return [];
|
|
5691
6376
|
}
|
|
5692
|
-
function rectsOverlap(a, b) {
|
|
5693
|
-
return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
|
|
5694
|
-
}
|
|
5695
|
-
function rectCircleOverlap(rect, circle) {
|
|
5696
|
-
const nearestX = Math.max(rect.x, Math.min(circle.cx, rect.x + rect.w));
|
|
5697
|
-
const nearestY = Math.max(rect.y, Math.min(circle.cy, rect.y + rect.h));
|
|
5698
|
-
const dx = nearestX - circle.cx;
|
|
5699
|
-
const dy = nearestY - circle.cy;
|
|
5700
|
-
return dx * dx + dy * dy < circle.r * circle.r;
|
|
5701
|
-
}
|
|
5702
6377
|
function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize, bg) {
|
|
5703
6378
|
const labelHeight = fontSize + 4;
|
|
5704
6379
|
const stepSize = labelHeight + 2;
|
|
@@ -6075,12 +6750,17 @@ function buildHeatmapOption(parsed, palette, isDark, textColor, axisLineColor, t
|
|
|
6075
6750
|
maxValue = Math.max(maxValue, value);
|
|
6076
6751
|
});
|
|
6077
6752
|
});
|
|
6753
|
+
const CHAR_WIDTH7 = 7;
|
|
6754
|
+
const ESTIMATED_CHART_WIDTH = 900;
|
|
6755
|
+
const longestCol = Math.max(...columns.map((c) => c.length), 0);
|
|
6756
|
+
const slotWidth = columns.length > 0 ? ESTIMATED_CHART_WIDTH / columns.length : Infinity;
|
|
6757
|
+
const needsRotation = longestCol * CHAR_WIDTH7 > slotWidth * 0.85;
|
|
6078
6758
|
return {
|
|
6079
6759
|
...CHART_BASE,
|
|
6080
6760
|
title: titleConfig,
|
|
6081
6761
|
grid: {
|
|
6082
6762
|
left: "3%",
|
|
6083
|
-
right: "
|
|
6763
|
+
right: "3%",
|
|
6084
6764
|
bottom: "3%",
|
|
6085
6765
|
top: parsed.title ? "15%" : "5%",
|
|
6086
6766
|
containLabel: true
|
|
@@ -6088,6 +6768,7 @@ function buildHeatmapOption(parsed, palette, isDark, textColor, axisLineColor, t
|
|
|
6088
6768
|
xAxis: {
|
|
6089
6769
|
type: "category",
|
|
6090
6770
|
data: columns,
|
|
6771
|
+
position: "top",
|
|
6091
6772
|
splitArea: {
|
|
6092
6773
|
show: true
|
|
6093
6774
|
},
|
|
@@ -6096,12 +6777,19 @@ function buildHeatmapOption(parsed, palette, isDark, textColor, axisLineColor, t
|
|
|
6096
6777
|
},
|
|
6097
6778
|
axisLabel: {
|
|
6098
6779
|
color: textColor,
|
|
6099
|
-
fontSize:
|
|
6780
|
+
fontSize: 12,
|
|
6781
|
+
interval: 0,
|
|
6782
|
+
...needsRotation && {
|
|
6783
|
+
rotate: -45,
|
|
6784
|
+
width: 200,
|
|
6785
|
+
overflow: "none"
|
|
6786
|
+
}
|
|
6100
6787
|
}
|
|
6101
6788
|
},
|
|
6102
6789
|
yAxis: {
|
|
6103
6790
|
type: "category",
|
|
6104
6791
|
data: rowLabels,
|
|
6792
|
+
inverse: true,
|
|
6105
6793
|
splitArea: {
|
|
6106
6794
|
show: true
|
|
6107
6795
|
},
|
|
@@ -6110,16 +6798,14 @@ function buildHeatmapOption(parsed, palette, isDark, textColor, axisLineColor, t
|
|
|
6110
6798
|
},
|
|
6111
6799
|
axisLabel: {
|
|
6112
6800
|
color: textColor,
|
|
6113
|
-
fontSize:
|
|
6801
|
+
fontSize: 12,
|
|
6802
|
+
interval: 0
|
|
6114
6803
|
}
|
|
6115
6804
|
},
|
|
6116
6805
|
visualMap: {
|
|
6806
|
+
show: false,
|
|
6117
6807
|
min: minValue,
|
|
6118
6808
|
max: maxValue,
|
|
6119
|
-
calculable: true,
|
|
6120
|
-
orient: "vertical",
|
|
6121
|
-
right: "2%",
|
|
6122
|
-
top: "center",
|
|
6123
6809
|
inRange: {
|
|
6124
6810
|
color: [
|
|
6125
6811
|
mix(palette.primary, bg, 30),
|
|
@@ -6127,9 +6813,6 @@ function buildHeatmapOption(parsed, palette, isDark, textColor, axisLineColor, t
|
|
|
6127
6813
|
mix(palette.colors.yellow, bg, 30),
|
|
6128
6814
|
mix(palette.colors.orange, bg, 30)
|
|
6129
6815
|
]
|
|
6130
|
-
},
|
|
6131
|
-
textStyle: {
|
|
6132
|
-
color: textColor
|
|
6133
6816
|
}
|
|
6134
6817
|
},
|
|
6135
6818
|
series: [
|
|
@@ -6147,9 +6830,8 @@ function buildHeatmapOption(parsed, palette, isDark, textColor, axisLineColor, t
|
|
|
6147
6830
|
fontWeight: "bold"
|
|
6148
6831
|
},
|
|
6149
6832
|
emphasis: {
|
|
6150
|
-
|
|
6151
|
-
}
|
|
6152
|
-
blur: BLUR_DIM
|
|
6833
|
+
disabled: true
|
|
6834
|
+
}
|
|
6153
6835
|
}
|
|
6154
6836
|
]
|
|
6155
6837
|
};
|
|
@@ -7003,6 +7685,7 @@ var init_echarts = __esm({
|
|
|
7003
7685
|
init_fonts();
|
|
7004
7686
|
init_branding();
|
|
7005
7687
|
init_legend_svg();
|
|
7688
|
+
init_label_layout();
|
|
7006
7689
|
init_palettes();
|
|
7007
7690
|
init_color_utils();
|
|
7008
7691
|
init_chart();
|
|
@@ -8357,7 +9040,12 @@ __export(parser_exports7, {
|
|
|
8357
9040
|
function parseArrowLine(trimmed, palette) {
|
|
8358
9041
|
const bareMatch = trimmed.match(BARE_ARROW_RE);
|
|
8359
9042
|
if (bareMatch) {
|
|
8360
|
-
|
|
9043
|
+
const rawTarget = bareMatch[1].trim();
|
|
9044
|
+
const groupMatch = rawTarget.match(/^\[(.+)\]$/);
|
|
9045
|
+
return {
|
|
9046
|
+
target: groupMatch ? groupMatch[1].trim() : rawTarget,
|
|
9047
|
+
targetIsGroup: !!groupMatch
|
|
9048
|
+
};
|
|
8361
9049
|
}
|
|
8362
9050
|
const arrowMatch = trimmed.match(ARROW_RE);
|
|
8363
9051
|
if (arrowMatch) {
|
|
@@ -8366,8 +9054,14 @@ function parseArrowLine(trimmed, palette) {
|
|
|
8366
9054
|
if (label && !color) {
|
|
8367
9055
|
color = inferArrowColor(label);
|
|
8368
9056
|
}
|
|
8369
|
-
const
|
|
8370
|
-
|
|
9057
|
+
const rawTarget = arrowMatch[3].trim();
|
|
9058
|
+
const groupMatch = rawTarget.match(/^\[(.+)\]$/);
|
|
9059
|
+
return {
|
|
9060
|
+
label,
|
|
9061
|
+
color,
|
|
9062
|
+
target: groupMatch ? groupMatch[1].trim() : rawTarget,
|
|
9063
|
+
targetIsGroup: !!groupMatch
|
|
9064
|
+
};
|
|
8371
9065
|
}
|
|
8372
9066
|
return null;
|
|
8373
9067
|
}
|
|
@@ -8429,6 +9123,7 @@ function parseSitemap(content, palette) {
|
|
|
8429
9123
|
const aliasMap = /* @__PURE__ */ new Map();
|
|
8430
9124
|
const indentStack = [];
|
|
8431
9125
|
const labelToNode = /* @__PURE__ */ new Map();
|
|
9126
|
+
const labelToContainer = /* @__PURE__ */ new Map();
|
|
8432
9127
|
const deferredArrows = [];
|
|
8433
9128
|
for (let i = 0; i < lines.length; i++) {
|
|
8434
9129
|
const line10 = lines[i];
|
|
@@ -8530,6 +9225,7 @@ function parseSitemap(content, palette) {
|
|
|
8530
9225
|
deferredArrows.push({
|
|
8531
9226
|
sourceNode: source,
|
|
8532
9227
|
targetLabel: arrowInfo.target,
|
|
9228
|
+
targetIsGroup: arrowInfo.targetIsGroup,
|
|
8533
9229
|
label: arrowInfo.label,
|
|
8534
9230
|
color: arrowInfo.color,
|
|
8535
9231
|
lineNumber
|
|
@@ -8563,6 +9259,7 @@ function parseSitemap(content, palette) {
|
|
|
8563
9259
|
color
|
|
8564
9260
|
};
|
|
8565
9261
|
attachNode2(node, indent, indentStack, result);
|
|
9262
|
+
labelToContainer.set(label.toLowerCase(), node);
|
|
8566
9263
|
} else if (metadataMatch && indentStack.length > 0) {
|
|
8567
9264
|
const rawKey = metadataMatch[1].trim().toLowerCase();
|
|
8568
9265
|
const key = aliasMap.get(rawKey) ?? rawKey;
|
|
@@ -8603,22 +9300,41 @@ function parseSitemap(content, palette) {
|
|
|
8603
9300
|
}
|
|
8604
9301
|
for (const arrow of deferredArrows) {
|
|
8605
9302
|
const targetKey = arrow.targetLabel.toLowerCase();
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
9303
|
+
if (arrow.targetIsGroup) {
|
|
9304
|
+
const targetContainer = labelToContainer.get(targetKey);
|
|
9305
|
+
if (!targetContainer) {
|
|
9306
|
+
const allLabels = Array.from(labelToContainer.keys());
|
|
9307
|
+
let msg = `Group '[${arrow.targetLabel}]' not found`;
|
|
9308
|
+
const hint = suggest(targetKey, allLabels);
|
|
9309
|
+
if (hint) msg += `. ${hint}`;
|
|
9310
|
+
pushError(arrow.lineNumber, msg);
|
|
9311
|
+
continue;
|
|
9312
|
+
}
|
|
9313
|
+
result.edges.push({
|
|
9314
|
+
sourceId: arrow.sourceNode.id,
|
|
9315
|
+
targetId: targetContainer.id,
|
|
9316
|
+
label: arrow.label,
|
|
9317
|
+
color: arrow.color,
|
|
9318
|
+
lineNumber: arrow.lineNumber
|
|
9319
|
+
});
|
|
9320
|
+
} else {
|
|
9321
|
+
const targetNode = labelToNode.get(targetKey);
|
|
9322
|
+
if (!targetNode) {
|
|
9323
|
+
const allLabels = Array.from(labelToNode.keys());
|
|
9324
|
+
let msg = `Arrow target "${arrow.targetLabel}" not found`;
|
|
9325
|
+
const hint = suggest(targetKey, allLabels);
|
|
9326
|
+
if (hint) msg += `. ${hint}`;
|
|
9327
|
+
pushError(arrow.lineNumber, msg);
|
|
9328
|
+
continue;
|
|
9329
|
+
}
|
|
9330
|
+
result.edges.push({
|
|
9331
|
+
sourceId: arrow.sourceNode.id,
|
|
9332
|
+
targetId: targetNode.id,
|
|
9333
|
+
label: arrow.label,
|
|
9334
|
+
color: arrow.color,
|
|
9335
|
+
lineNumber: arrow.lineNumber
|
|
9336
|
+
});
|
|
8614
9337
|
}
|
|
8615
|
-
result.edges.push({
|
|
8616
|
-
sourceId: arrow.sourceNode.id,
|
|
8617
|
-
targetId: targetNode.id,
|
|
8618
|
-
label: arrow.label,
|
|
8619
|
-
color: arrow.color,
|
|
8620
|
-
lineNumber: arrow.lineNumber
|
|
8621
|
-
});
|
|
8622
9338
|
}
|
|
8623
9339
|
if (result.tagGroups.length > 0) {
|
|
8624
9340
|
const allNodes = [];
|
|
@@ -10332,6 +11048,7 @@ function parseBoxesAndLines(content) {
|
|
|
10332
11048
|
const nodeLabels = /* @__PURE__ */ new Set();
|
|
10333
11049
|
const groupLabels = /* @__PURE__ */ new Set();
|
|
10334
11050
|
let lastNodeLabel = null;
|
|
11051
|
+
let lastSourceIsGroup = false;
|
|
10335
11052
|
const groupStack = [];
|
|
10336
11053
|
let contentStarted = false;
|
|
10337
11054
|
let currentTagGroup = null;
|
|
@@ -10570,6 +11287,8 @@ function parseBoxesAndLines(content) {
|
|
|
10570
11287
|
};
|
|
10571
11288
|
groupLabels.add(label);
|
|
10572
11289
|
groupStack.push({ group, indent, depth: currentDepth });
|
|
11290
|
+
lastNodeLabel = label;
|
|
11291
|
+
lastSourceIsGroup = true;
|
|
10573
11292
|
continue;
|
|
10574
11293
|
}
|
|
10575
11294
|
if (trimmed.includes("->") || trimmed.includes("<->")) {
|
|
@@ -10587,7 +11306,8 @@ function parseBoxesAndLines(content) {
|
|
|
10587
11306
|
);
|
|
10588
11307
|
continue;
|
|
10589
11308
|
}
|
|
10590
|
-
|
|
11309
|
+
const sourcePrefix = lastSourceIsGroup ? `[${lastNodeLabel}]` : lastNodeLabel;
|
|
11310
|
+
edgeText = `${sourcePrefix} ${trimmed}`;
|
|
10591
11311
|
}
|
|
10592
11312
|
const edge = parseEdgeLine(
|
|
10593
11313
|
edgeText,
|
|
@@ -10610,6 +11330,7 @@ function parseBoxesAndLines(content) {
|
|
|
10610
11330
|
continue;
|
|
10611
11331
|
}
|
|
10612
11332
|
lastNodeLabel = node.label;
|
|
11333
|
+
lastSourceIsGroup = false;
|
|
10613
11334
|
const gs = currentGroupState();
|
|
10614
11335
|
const isGroupChild = gs && indent > gs.indent;
|
|
10615
11336
|
if (nodeLabels.has(node.label)) {
|
|
@@ -10637,14 +11358,42 @@ function parseBoxesAndLines(content) {
|
|
|
10637
11358
|
const gs = groupStack.pop();
|
|
10638
11359
|
result.groups.push(gs.group);
|
|
10639
11360
|
}
|
|
11361
|
+
const validEdges = [];
|
|
10640
11362
|
for (const edge of result.edges) {
|
|
10641
|
-
|
|
11363
|
+
let valid = true;
|
|
11364
|
+
if (edge.source.startsWith("__group_")) {
|
|
11365
|
+
const label = edge.source.slice("__group_".length);
|
|
11366
|
+
const found = [...groupLabels].some(
|
|
11367
|
+
(g) => g.toLowerCase() === label.toLowerCase()
|
|
11368
|
+
);
|
|
11369
|
+
if (!found) {
|
|
11370
|
+
result.diagnostics.push(
|
|
11371
|
+
makeDgmoError(edge.lineNumber, `Group '[${label}]' not found`)
|
|
11372
|
+
);
|
|
11373
|
+
valid = false;
|
|
11374
|
+
}
|
|
11375
|
+
} else {
|
|
10642
11376
|
ensureNode(edge.source, edge.lineNumber);
|
|
10643
11377
|
}
|
|
10644
|
-
if (
|
|
11378
|
+
if (edge.target.startsWith("__group_")) {
|
|
11379
|
+
const label = edge.target.slice("__group_".length);
|
|
11380
|
+
const found = [...groupLabels].some(
|
|
11381
|
+
(g) => g.toLowerCase() === label.toLowerCase()
|
|
11382
|
+
);
|
|
11383
|
+
if (!found) {
|
|
11384
|
+
result.diagnostics.push(
|
|
11385
|
+
makeDgmoError(edge.lineNumber, `Group '[${label}]' not found`)
|
|
11386
|
+
);
|
|
11387
|
+
valid = false;
|
|
11388
|
+
}
|
|
11389
|
+
} else {
|
|
10645
11390
|
ensureNode(edge.target, edge.lineNumber);
|
|
10646
11391
|
}
|
|
11392
|
+
if (valid) {
|
|
11393
|
+
validEdges.push(edge);
|
|
11394
|
+
}
|
|
10647
11395
|
}
|
|
11396
|
+
result.edges = validEdges;
|
|
10648
11397
|
if (result.tagGroups.length > 0) {
|
|
10649
11398
|
injectDefaultTagMetadata(result.nodes, result.tagGroups);
|
|
10650
11399
|
validateTagValues(result.nodes, result.tagGroups, pushWarning, suggest);
|
|
@@ -10673,10 +11422,14 @@ function parseNodeLine(trimmed, lineNum, aliasMap, _diagnostics) {
|
|
|
10673
11422
|
description
|
|
10674
11423
|
};
|
|
10675
11424
|
}
|
|
11425
|
+
function resolveEndpoint(name) {
|
|
11426
|
+
const m = name.match(/^\[(.+)\]$/);
|
|
11427
|
+
return m ? groupId2(m[1].trim()) : name;
|
|
11428
|
+
}
|
|
10676
11429
|
function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
10677
11430
|
const biLabeledMatch = trimmed.match(/^(.+?)\s*<-(.+)->\s*(.+)$/);
|
|
10678
11431
|
if (biLabeledMatch) {
|
|
10679
|
-
const source2 = biLabeledMatch[1].trim();
|
|
11432
|
+
const source2 = resolveEndpoint(biLabeledMatch[1].trim());
|
|
10680
11433
|
const label = biLabeledMatch[2].trim();
|
|
10681
11434
|
let rest2 = biLabeledMatch[3].trim();
|
|
10682
11435
|
let metadata2 = {};
|
|
@@ -10697,7 +11450,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10697
11450
|
}
|
|
10698
11451
|
return {
|
|
10699
11452
|
source: source2,
|
|
10700
|
-
target: rest2,
|
|
11453
|
+
target: resolveEndpoint(rest2),
|
|
10701
11454
|
label: label || void 0,
|
|
10702
11455
|
bidirectional: true,
|
|
10703
11456
|
lineNumber: lineNum,
|
|
@@ -10706,7 +11459,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10706
11459
|
}
|
|
10707
11460
|
const biIdx = trimmed.indexOf("<->");
|
|
10708
11461
|
if (biIdx >= 0) {
|
|
10709
|
-
const source2 = trimmed.slice(0, biIdx).trim();
|
|
11462
|
+
const source2 = resolveEndpoint(trimmed.slice(0, biIdx).trim());
|
|
10710
11463
|
let rest2 = trimmed.slice(biIdx + 3).trim();
|
|
10711
11464
|
let metadata2 = {};
|
|
10712
11465
|
const pipeIdx2 = rest2.indexOf("|");
|
|
@@ -10726,7 +11479,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10726
11479
|
}
|
|
10727
11480
|
return {
|
|
10728
11481
|
source: source2,
|
|
10729
|
-
target: rest2,
|
|
11482
|
+
target: resolveEndpoint(rest2),
|
|
10730
11483
|
bidirectional: true,
|
|
10731
11484
|
lineNumber: lineNum,
|
|
10732
11485
|
metadata: metadata2
|
|
@@ -10734,7 +11487,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10734
11487
|
}
|
|
10735
11488
|
const labeledMatch = trimmed.match(/^(.+?)\s+-(.+)->\s*(.+)$/);
|
|
10736
11489
|
if (labeledMatch) {
|
|
10737
|
-
const source2 = labeledMatch[1].trim();
|
|
11490
|
+
const source2 = resolveEndpoint(labeledMatch[1].trim());
|
|
10738
11491
|
const label = labeledMatch[2].trim();
|
|
10739
11492
|
let rest2 = labeledMatch[3].trim();
|
|
10740
11493
|
if (label) {
|
|
@@ -10756,7 +11509,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10756
11509
|
}
|
|
10757
11510
|
return {
|
|
10758
11511
|
source: source2,
|
|
10759
|
-
target: rest2,
|
|
11512
|
+
target: resolveEndpoint(rest2),
|
|
10760
11513
|
label,
|
|
10761
11514
|
bidirectional: false,
|
|
10762
11515
|
lineNumber: lineNum,
|
|
@@ -10766,7 +11519,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10766
11519
|
}
|
|
10767
11520
|
const arrowIdx = trimmed.indexOf("->");
|
|
10768
11521
|
if (arrowIdx < 0) return null;
|
|
10769
|
-
const source = trimmed.slice(0, arrowIdx).trim();
|
|
11522
|
+
const source = resolveEndpoint(trimmed.slice(0, arrowIdx).trim());
|
|
10770
11523
|
let rest = trimmed.slice(arrowIdx + 2).trim();
|
|
10771
11524
|
if (!source || !rest) {
|
|
10772
11525
|
diagnostics.push(
|
|
@@ -10787,7 +11540,7 @@ function parseEdgeLine(trimmed, lineNum, aliasMap, diagnostics) {
|
|
|
10787
11540
|
}
|
|
10788
11541
|
return {
|
|
10789
11542
|
source,
|
|
10790
|
-
target: rest,
|
|
11543
|
+
target: resolveEndpoint(rest),
|
|
10791
11544
|
bidirectional: false,
|
|
10792
11545
|
lineNumber: lineNum,
|
|
10793
11546
|
metadata
|
|
@@ -11102,14 +11855,14 @@ function computeLegendGroups(tagGroups, showEyeIcons, usedValuesByGroup) {
|
|
|
11102
11855
|
const usedValues = usedValuesByGroup?.get(group.name.toLowerCase());
|
|
11103
11856
|
const visibleEntries = usedValues ? group.entries.filter((e) => usedValues.has(e.value.toLowerCase())) : group.entries;
|
|
11104
11857
|
if (visibleEntries.length === 0) continue;
|
|
11105
|
-
const
|
|
11106
|
-
const minPillWidth =
|
|
11107
|
-
let
|
|
11858
|
+
const pillWidth3 = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD2;
|
|
11859
|
+
const minPillWidth = pillWidth3;
|
|
11860
|
+
let entriesWidth3 = 0;
|
|
11108
11861
|
for (const entry of visibleEntries) {
|
|
11109
|
-
|
|
11862
|
+
entriesWidth3 += LEGEND_DOT_R2 * 2 + LEGEND_ENTRY_DOT_GAP2 + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL2;
|
|
11110
11863
|
}
|
|
11111
11864
|
const eyeSpace = showEyeIcons ? LEGEND_EYE_SIZE2 + LEGEND_EYE_GAP2 : 0;
|
|
11112
|
-
const
|
|
11865
|
+
const capsuleWidth2 = LEGEND_CAPSULE_PAD2 * 2 + pillWidth3 + 4 + eyeSpace + entriesWidth3;
|
|
11113
11866
|
groups.push({
|
|
11114
11867
|
name: group.name,
|
|
11115
11868
|
alias: group.alias,
|
|
@@ -11119,7 +11872,7 @@ function computeLegendGroups(tagGroups, showEyeIcons, usedValuesByGroup) {
|
|
|
11119
11872
|
})),
|
|
11120
11873
|
x: 0,
|
|
11121
11874
|
y: 0,
|
|
11122
|
-
width:
|
|
11875
|
+
width: capsuleWidth2,
|
|
11123
11876
|
height: LEGEND_HEIGHT2,
|
|
11124
11877
|
minifiedWidth: minPillWidth,
|
|
11125
11878
|
minifiedHeight: LEGEND_HEIGHT2
|
|
@@ -12060,66 +12813,77 @@ function renderOrg(container, parsed, layout, palette, isDark, onClickItem, expo
|
|
|
12060
12813
|
}
|
|
12061
12814
|
}
|
|
12062
12815
|
if (fixedLegend || legendOnly || exportDims && hasLegend) {
|
|
12063
|
-
const
|
|
12064
|
-
|
|
12065
|
-
|
|
12066
|
-
|
|
12067
|
-
|
|
12068
|
-
|
|
12069
|
-
|
|
12070
|
-
|
|
12071
|
-
|
|
12072
|
-
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12078
|
-
|
|
12079
|
-
|
|
12080
|
-
|
|
12081
|
-
|
|
12082
|
-
|
|
12816
|
+
const groups = layout.legend.map((g) => ({
|
|
12817
|
+
name: g.name,
|
|
12818
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
12819
|
+
}));
|
|
12820
|
+
const eyeAddonWidth = fixedLegend ? LEGEND_EYE_SIZE + LEGEND_EYE_GAP : 0;
|
|
12821
|
+
const legendParentBase = fixedLegend ? svg.append("g").attr("class", "org-legend-fixed").attr("transform", `translate(0, ${DIAGRAM_PADDING + titleReserve})`) : contentG.append("g");
|
|
12822
|
+
let legendHandle;
|
|
12823
|
+
if (legendOnly) {
|
|
12824
|
+
for (const lg of layout.legend) {
|
|
12825
|
+
const singleConfig = {
|
|
12826
|
+
groups: [
|
|
12827
|
+
{
|
|
12828
|
+
name: lg.name,
|
|
12829
|
+
entries: lg.entries.map((e) => ({
|
|
12830
|
+
value: e.value,
|
|
12831
|
+
color: e.color
|
|
12832
|
+
}))
|
|
12833
|
+
}
|
|
12834
|
+
],
|
|
12835
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
12836
|
+
mode: "fixed"
|
|
12837
|
+
};
|
|
12838
|
+
const singleState = { activeGroup: lg.name };
|
|
12839
|
+
const groupG = legendParentBase.append("g").attr("transform", `translate(${lg.x}, ${lg.y})`);
|
|
12840
|
+
renderLegendD3(
|
|
12841
|
+
groupG,
|
|
12842
|
+
singleConfig,
|
|
12843
|
+
singleState,
|
|
12844
|
+
palette,
|
|
12845
|
+
isDark,
|
|
12846
|
+
void 0,
|
|
12847
|
+
lg.width
|
|
12848
|
+
);
|
|
12849
|
+
groupG.selectAll("[data-legend-group]").classed("org-legend-group", true);
|
|
12850
|
+
}
|
|
12851
|
+
legendHandle = null;
|
|
12852
|
+
} else {
|
|
12853
|
+
const legendConfig = {
|
|
12854
|
+
groups,
|
|
12855
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
12856
|
+
mode: "fixed",
|
|
12857
|
+
capsulePillAddonWidth: eyeAddonWidth
|
|
12858
|
+
};
|
|
12859
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
12860
|
+
legendHandle = renderLegendD3(
|
|
12861
|
+
legendParentBase,
|
|
12862
|
+
legendConfig,
|
|
12863
|
+
legendState,
|
|
12864
|
+
palette,
|
|
12865
|
+
isDark,
|
|
12866
|
+
void 0,
|
|
12867
|
+
fixedLegend ? width : layout.width
|
|
12868
|
+
);
|
|
12869
|
+
legendParentBase.selectAll("[data-legend-group]").classed("org-legend-group", true);
|
|
12083
12870
|
}
|
|
12084
|
-
|
|
12085
|
-
const
|
|
12086
|
-
|
|
12087
|
-
|
|
12088
|
-
|
|
12089
|
-
const gX = fixedPositions?.get(group.name) ?? group.x;
|
|
12090
|
-
const gY = fixedPositions ? 0 : group.y;
|
|
12091
|
-
const gEl = legendParent.append("g").attr("transform", `translate(${gX}, ${gY})`).attr("class", "org-legend-group").attr("data-legend-group", group.name.toLowerCase()).style("cursor", legendOnly ? "default" : "pointer");
|
|
12092
|
-
if (isActive) {
|
|
12093
|
-
gEl.append("rect").attr("width", group.width).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
12094
|
-
}
|
|
12095
|
-
const pillXOff = isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
12096
|
-
const pillYOff = LEGEND_CAPSULE_PAD;
|
|
12097
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
12098
|
-
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", isActive ? palette.bg : groupBg);
|
|
12099
|
-
if (isActive) {
|
|
12100
|
-
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
12101
|
-
}
|
|
12102
|
-
gEl.append("text").attr("x", pillXOff + pillWidth2 / 2).attr("y", LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(pillLabel);
|
|
12103
|
-
if (isActive && fixedLegend) {
|
|
12104
|
-
const groupKey = group.name.toLowerCase();
|
|
12871
|
+
if (fixedLegend && legendHandle) {
|
|
12872
|
+
const computedLayout = legendHandle.getLayout();
|
|
12873
|
+
if (computedLayout.activeCapsule?.addonX != null) {
|
|
12874
|
+
const capsule = computedLayout.activeCapsule;
|
|
12875
|
+
const groupKey = capsule.groupName.toLowerCase();
|
|
12105
12876
|
const isHidden = hiddenAttributes?.has(groupKey) ?? false;
|
|
12106
|
-
const
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
for (const entry of group.entries) {
|
|
12117
|
-
const entryG = gEl.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
12118
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
12119
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
12120
|
-
const entryLabel = entry.value;
|
|
12121
|
-
entryG.append("text").attr("x", textX).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entryLabel);
|
|
12122
|
-
entryX = textX + measureLegendText(entryLabel, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
12877
|
+
const activeGroupEl = legendParentBase.select(
|
|
12878
|
+
`[data-legend-group="${groupKey}"]`
|
|
12879
|
+
);
|
|
12880
|
+
if (!activeGroupEl.empty()) {
|
|
12881
|
+
const eyeX = capsule.addonX;
|
|
12882
|
+
const eyeY = (LEGEND_HEIGHT - LEGEND_EYE_SIZE) / 2;
|
|
12883
|
+
const hitPad = 6;
|
|
12884
|
+
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);
|
|
12885
|
+
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");
|
|
12886
|
+
eyeG.append("path").attr("d", isHidden ? EYE_CLOSED_PATH : EYE_OPEN_PATH).attr("transform", `translate(${eyeX}, ${eyeY})`).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1.2).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
12123
12887
|
}
|
|
12124
12888
|
}
|
|
12125
12889
|
}
|
|
@@ -12153,6 +12917,7 @@ var init_renderer = __esm({
|
|
|
12153
12917
|
init_parser4();
|
|
12154
12918
|
init_layout();
|
|
12155
12919
|
init_legend_constants();
|
|
12920
|
+
init_legend_d3();
|
|
12156
12921
|
init_title_constants();
|
|
12157
12922
|
DIAGRAM_PADDING = 20;
|
|
12158
12923
|
MAX_SCALE = 3;
|
|
@@ -12182,6 +12947,17 @@ __export(layout_exports2, {
|
|
|
12182
12947
|
layoutSitemap: () => layoutSitemap
|
|
12183
12948
|
});
|
|
12184
12949
|
import dagre from "@dagrejs/dagre";
|
|
12950
|
+
function clipToRectBorder(cx, cy, w, h, tx, ty) {
|
|
12951
|
+
const dx = tx - cx;
|
|
12952
|
+
const dy = ty - cy;
|
|
12953
|
+
if (dx === 0 && dy === 0) return { x: cx, y: cy };
|
|
12954
|
+
const hw = w / 2;
|
|
12955
|
+
const hh = h / 2;
|
|
12956
|
+
const sx = dx !== 0 ? hw / Math.abs(dx) : Infinity;
|
|
12957
|
+
const sy = dy !== 0 ? hh / Math.abs(dy) : Infinity;
|
|
12958
|
+
const s = Math.min(sx, sy);
|
|
12959
|
+
return { x: cx + dx * s, y: cy + dy * s };
|
|
12960
|
+
}
|
|
12185
12961
|
function filterMetadata2(metadata, hiddenAttributes) {
|
|
12186
12962
|
if (!hiddenAttributes || hiddenAttributes.size === 0) return metadata;
|
|
12187
12963
|
const filtered = {};
|
|
@@ -12198,7 +12974,10 @@ function computeCardWidth2(label, meta) {
|
|
|
12198
12974
|
const lineChars = key.length + 2 + value.length;
|
|
12199
12975
|
if (lineChars > maxChars) maxChars = lineChars;
|
|
12200
12976
|
}
|
|
12201
|
-
return Math.max(
|
|
12977
|
+
return Math.max(
|
|
12978
|
+
MIN_CARD_WIDTH2,
|
|
12979
|
+
Math.ceil(maxChars * CHAR_WIDTH2) + CARD_H_PAD2 * 2
|
|
12980
|
+
);
|
|
12202
12981
|
}
|
|
12203
12982
|
function computeCardHeight2(meta) {
|
|
12204
12983
|
const metaCount = Object.keys(meta).length;
|
|
@@ -12207,7 +12986,12 @@ function computeCardHeight2(meta) {
|
|
|
12207
12986
|
}
|
|
12208
12987
|
function resolveNodeColor2(node, tagGroups, activeGroupName) {
|
|
12209
12988
|
if (node.color) return node.color;
|
|
12210
|
-
return resolveTagColor(
|
|
12989
|
+
return resolveTagColor(
|
|
12990
|
+
node.metadata,
|
|
12991
|
+
tagGroups,
|
|
12992
|
+
activeGroupName,
|
|
12993
|
+
node.isContainer
|
|
12994
|
+
);
|
|
12211
12995
|
}
|
|
12212
12996
|
function computeLegendGroups2(tagGroups, usedValuesByGroup) {
|
|
12213
12997
|
const groups = [];
|
|
@@ -12216,21 +13000,21 @@ function computeLegendGroups2(tagGroups, usedValuesByGroup) {
|
|
|
12216
13000
|
const usedValues = usedValuesByGroup?.get(group.name.toLowerCase());
|
|
12217
13001
|
const visibleEntries = usedValues ? group.entries.filter((e) => usedValues.has(e.value.toLowerCase())) : group.entries;
|
|
12218
13002
|
if (visibleEntries.length === 0) continue;
|
|
12219
|
-
const
|
|
12220
|
-
const minPillWidth =
|
|
12221
|
-
let
|
|
13003
|
+
const pillWidth3 = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD3;
|
|
13004
|
+
const minPillWidth = pillWidth3;
|
|
13005
|
+
let entriesWidth3 = 0;
|
|
12222
13006
|
for (const entry of visibleEntries) {
|
|
12223
|
-
|
|
13007
|
+
entriesWidth3 += LEGEND_DOT_R3 * 2 + LEGEND_ENTRY_DOT_GAP3 + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL3;
|
|
12224
13008
|
}
|
|
12225
13009
|
const eyeSpace = LEGEND_EYE_SIZE3 + LEGEND_EYE_GAP3;
|
|
12226
|
-
const
|
|
13010
|
+
const capsuleWidth2 = LEGEND_CAPSULE_PAD3 * 2 + pillWidth3 + 4 + eyeSpace + entriesWidth3;
|
|
12227
13011
|
groups.push({
|
|
12228
13012
|
name: group.name,
|
|
12229
13013
|
alias: group.alias,
|
|
12230
13014
|
entries: visibleEntries.map((e) => ({ value: e.value, color: e.color })),
|
|
12231
13015
|
x: 0,
|
|
12232
13016
|
y: 0,
|
|
12233
|
-
width:
|
|
13017
|
+
width: capsuleWidth2,
|
|
12234
13018
|
height: LEGEND_HEIGHT3,
|
|
12235
13019
|
minifiedWidth: minPillWidth,
|
|
12236
13020
|
minifiedHeight: LEGEND_HEIGHT3
|
|
@@ -12250,10 +13034,20 @@ function flattenNodes(nodes, parentContainerId, parentPageId, hiddenCounts, hidd
|
|
|
12250
13034
|
parentPageId,
|
|
12251
13035
|
meta,
|
|
12252
13036
|
fullMeta: { ...node.metadata },
|
|
12253
|
-
width: Math.max(
|
|
13037
|
+
width: Math.max(
|
|
13038
|
+
MIN_CARD_WIDTH2,
|
|
13039
|
+
node.label.length * CHAR_WIDTH2 + CARD_H_PAD2 * 2
|
|
13040
|
+
),
|
|
12254
13041
|
height: labelHeight + CONTAINER_PAD_BOTTOM2
|
|
12255
13042
|
});
|
|
12256
|
-
flattenNodes(
|
|
13043
|
+
flattenNodes(
|
|
13044
|
+
node.children,
|
|
13045
|
+
node.id,
|
|
13046
|
+
parentPageId,
|
|
13047
|
+
hiddenCounts,
|
|
13048
|
+
hiddenAttributes,
|
|
13049
|
+
result
|
|
13050
|
+
);
|
|
12257
13051
|
} else {
|
|
12258
13052
|
result.push({
|
|
12259
13053
|
sitemapNode: node,
|
|
@@ -12265,14 +13059,28 @@ function flattenNodes(nodes, parentContainerId, parentPageId, hiddenCounts, hidd
|
|
|
12265
13059
|
height: computeCardHeight2(meta)
|
|
12266
13060
|
});
|
|
12267
13061
|
if (node.children.length > 0) {
|
|
12268
|
-
flattenNodes(
|
|
13062
|
+
flattenNodes(
|
|
13063
|
+
node.children,
|
|
13064
|
+
parentContainerId,
|
|
13065
|
+
node.id,
|
|
13066
|
+
hiddenCounts,
|
|
13067
|
+
hiddenAttributes,
|
|
13068
|
+
result
|
|
13069
|
+
);
|
|
12269
13070
|
}
|
|
12270
13071
|
}
|
|
12271
13072
|
}
|
|
12272
13073
|
}
|
|
12273
13074
|
function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, expandAllLegend) {
|
|
12274
13075
|
if (parsed.roots.length === 0) {
|
|
12275
|
-
return {
|
|
13076
|
+
return {
|
|
13077
|
+
nodes: [],
|
|
13078
|
+
edges: [],
|
|
13079
|
+
containers: [],
|
|
13080
|
+
legend: [],
|
|
13081
|
+
width: 0,
|
|
13082
|
+
height: 0
|
|
13083
|
+
};
|
|
12276
13084
|
}
|
|
12277
13085
|
const allNodes = [];
|
|
12278
13086
|
const collect = (node) => {
|
|
@@ -12280,9 +13088,20 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12280
13088
|
for (const child of node.children) collect(child);
|
|
12281
13089
|
};
|
|
12282
13090
|
for (const root of parsed.roots) collect(root);
|
|
12283
|
-
injectDefaultTagMetadata(
|
|
13091
|
+
injectDefaultTagMetadata(
|
|
13092
|
+
allNodes,
|
|
13093
|
+
parsed.tagGroups,
|
|
13094
|
+
(e) => e.isContainer
|
|
13095
|
+
);
|
|
12284
13096
|
const flatNodes = [];
|
|
12285
|
-
flattenNodes(
|
|
13097
|
+
flattenNodes(
|
|
13098
|
+
parsed.roots,
|
|
13099
|
+
null,
|
|
13100
|
+
null,
|
|
13101
|
+
hiddenCounts,
|
|
13102
|
+
hiddenAttributes,
|
|
13103
|
+
flatNodes
|
|
13104
|
+
);
|
|
12286
13105
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
12287
13106
|
for (const flat of flatNodes) {
|
|
12288
13107
|
nodeMap.set(flat.sitemapNode.id, flat);
|
|
@@ -12344,14 +13163,29 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12344
13163
|
g.setParent(flat.sitemapNode.id, flat.parentContainerId);
|
|
12345
13164
|
}
|
|
12346
13165
|
}
|
|
13166
|
+
const expandedContainerIds = /* @__PURE__ */ new Set();
|
|
13167
|
+
for (const cid of containerIds) {
|
|
13168
|
+
if (!collapsedContainerIds.has(cid)) {
|
|
13169
|
+
expandedContainerIds.add(cid);
|
|
13170
|
+
}
|
|
13171
|
+
}
|
|
13172
|
+
const deferredEdgeIndices = [];
|
|
12347
13173
|
for (let i = 0; i < parsed.edges.length; i++) {
|
|
12348
13174
|
const edge = parsed.edges[i];
|
|
12349
|
-
if (g.hasNode(edge.sourceId)
|
|
12350
|
-
|
|
13175
|
+
if (!g.hasNode(edge.sourceId) || !g.hasNode(edge.targetId)) continue;
|
|
13176
|
+
if (expandedContainerIds.has(edge.sourceId) || expandedContainerIds.has(edge.targetId)) {
|
|
13177
|
+
deferredEdgeIndices.push(i);
|
|
13178
|
+
continue;
|
|
13179
|
+
}
|
|
13180
|
+
g.setEdge(
|
|
13181
|
+
edge.sourceId,
|
|
13182
|
+
edge.targetId,
|
|
13183
|
+
{
|
|
12351
13184
|
label: edge.label ?? "",
|
|
12352
13185
|
minlen: 1
|
|
12353
|
-
},
|
|
12354
|
-
|
|
13186
|
+
},
|
|
13187
|
+
`e${i}`
|
|
13188
|
+
);
|
|
12355
13189
|
}
|
|
12356
13190
|
dagre.layout(g);
|
|
12357
13191
|
const layoutNodes = [];
|
|
@@ -12419,19 +13253,52 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12419
13253
|
});
|
|
12420
13254
|
}
|
|
12421
13255
|
}
|
|
13256
|
+
const deferredSet = new Set(deferredEdgeIndices);
|
|
12422
13257
|
const layoutEdges = [];
|
|
12423
13258
|
for (let i = 0; i < parsed.edges.length; i++) {
|
|
12424
13259
|
const edge = parsed.edges[i];
|
|
12425
13260
|
if (!g.hasNode(edge.sourceId) || !g.hasNode(edge.targetId)) continue;
|
|
12426
|
-
|
|
12427
|
-
if (
|
|
13261
|
+
let points;
|
|
13262
|
+
if (deferredSet.has(i)) {
|
|
13263
|
+
const srcNode = g.node(edge.sourceId);
|
|
13264
|
+
const tgtNode = g.node(edge.targetId);
|
|
13265
|
+
if (!srcNode || !tgtNode) continue;
|
|
13266
|
+
const srcPt = clipToRectBorder(
|
|
13267
|
+
srcNode.x,
|
|
13268
|
+
srcNode.y,
|
|
13269
|
+
srcNode.width,
|
|
13270
|
+
srcNode.height,
|
|
13271
|
+
tgtNode.x,
|
|
13272
|
+
tgtNode.y
|
|
13273
|
+
);
|
|
13274
|
+
const tgtPt = clipToRectBorder(
|
|
13275
|
+
tgtNode.x,
|
|
13276
|
+
tgtNode.y,
|
|
13277
|
+
tgtNode.width,
|
|
13278
|
+
tgtNode.height,
|
|
13279
|
+
srcNode.x,
|
|
13280
|
+
srcNode.y
|
|
13281
|
+
);
|
|
13282
|
+
const midX = (srcPt.x + tgtPt.x) / 2;
|
|
13283
|
+
const midY = (srcPt.y + tgtPt.y) / 2;
|
|
13284
|
+
points = [srcPt, { x: midX, y: midY }, tgtPt];
|
|
13285
|
+
} else {
|
|
13286
|
+
const edgeData = g.edge({
|
|
13287
|
+
v: edge.sourceId,
|
|
13288
|
+
w: edge.targetId,
|
|
13289
|
+
name: `e${i}`
|
|
13290
|
+
});
|
|
13291
|
+
if (!edgeData) continue;
|
|
13292
|
+
points = edgeData.points ?? [];
|
|
13293
|
+
}
|
|
12428
13294
|
layoutEdges.push({
|
|
12429
13295
|
sourceId: edge.sourceId,
|
|
12430
13296
|
targetId: edge.targetId,
|
|
12431
|
-
points
|
|
13297
|
+
points,
|
|
12432
13298
|
label: edge.label,
|
|
12433
13299
|
color: edge.color,
|
|
12434
|
-
lineNumber: edge.lineNumber
|
|
13300
|
+
lineNumber: edge.lineNumber,
|
|
13301
|
+
deferred: deferredSet.has(i) || void 0
|
|
12435
13302
|
});
|
|
12436
13303
|
}
|
|
12437
13304
|
{
|
|
@@ -12592,7 +13459,9 @@ function layoutSitemap(parsed, hiddenCounts, activeTagGroup, hiddenAttributes, e
|
|
|
12592
13459
|
usedValuesByGroup.set(key, used);
|
|
12593
13460
|
}
|
|
12594
13461
|
const legendGroups = computeLegendGroups2(parsed.tagGroups, usedValuesByGroup);
|
|
12595
|
-
const visibleGroups = activeTagGroup != null ? legendGroups.filter(
|
|
13462
|
+
const visibleGroups = activeTagGroup != null ? legendGroups.filter(
|
|
13463
|
+
(g2) => g2.name.toLowerCase() === activeTagGroup.toLowerCase()
|
|
13464
|
+
) : legendGroups;
|
|
12596
13465
|
const allExpanded = expandAllLegend && activeTagGroup == null;
|
|
12597
13466
|
const effectiveW = (g2) => activeTagGroup != null || allExpanded ? g2.width : g2.minifiedWidth;
|
|
12598
13467
|
if (visibleGroups.length > 0) {
|
|
@@ -12908,7 +13777,8 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
12908
13777
|
const edgeG = contentG.append("g").attr("class", "sitemap-edge-group").attr("data-line-number", String(edge.lineNumber));
|
|
12909
13778
|
const edgeColor3 = edge.color ?? palette.textMuted;
|
|
12910
13779
|
const markerId = edge.color ? `sm-arrow-${edge.color.replace("#", "")}` : "sm-arrow";
|
|
12911
|
-
const
|
|
13780
|
+
const gen = edge.deferred ? lineGeneratorLinear : lineGenerator;
|
|
13781
|
+
const pathD = gen(edge.points);
|
|
12912
13782
|
if (pathD) {
|
|
12913
13783
|
edgeG.append("path").attr("d", pathD).attr("fill", "none").attr("stroke", edgeColor3).attr("stroke-width", EDGE_STROKE_WIDTH2).attr("marker-end", `url(#${markerId})`).attr("class", "sitemap-edge");
|
|
12914
13784
|
}
|
|
@@ -12992,64 +13862,51 @@ function renderSitemap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
12992
13862
|
palette,
|
|
12993
13863
|
isDark,
|
|
12994
13864
|
activeTagGroup,
|
|
12995
|
-
width,
|
|
12996
|
-
hiddenAttributes
|
|
12997
|
-
);
|
|
12998
|
-
}
|
|
12999
|
-
}
|
|
13000
|
-
function renderLegend(parent, legendGroups, palette, isDark, activeTagGroup, fixedWidth, hiddenAttributes) {
|
|
13001
|
-
if (legendGroups.length === 0) return;
|
|
13002
|
-
const visibleGroups = activeTagGroup != null ? legendGroups.filter(
|
|
13003
|
-
(g) => g.name.toLowerCase() === activeTagGroup.toLowerCase()
|
|
13004
|
-
) : legendGroups;
|
|
13005
|
-
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
13006
|
-
let fixedPositions;
|
|
13007
|
-
if (fixedWidth != null && visibleGroups.length > 0) {
|
|
13008
|
-
fixedPositions = /* @__PURE__ */ new Map();
|
|
13009
|
-
const effectiveW = (g) => activeTagGroup != null ? g.width : g.minifiedWidth;
|
|
13010
|
-
const totalW = visibleGroups.reduce((s, g) => s + effectiveW(g), 0) + (visibleGroups.length - 1) * LEGEND_GROUP_GAP;
|
|
13011
|
-
let cx = (fixedWidth - totalW) / 2;
|
|
13012
|
-
for (const g of visibleGroups) {
|
|
13013
|
-
fixedPositions.set(g.name, cx);
|
|
13014
|
-
cx += effectiveW(g) + LEGEND_GROUP_GAP;
|
|
13015
|
-
}
|
|
13865
|
+
width,
|
|
13866
|
+
hiddenAttributes
|
|
13867
|
+
);
|
|
13016
13868
|
}
|
|
13017
|
-
|
|
13018
|
-
|
|
13019
|
-
|
|
13020
|
-
|
|
13021
|
-
|
|
13022
|
-
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
|
|
13026
|
-
|
|
13027
|
-
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
|
|
13869
|
+
}
|
|
13870
|
+
function renderLegend(parent, legendGroups, palette, isDark, activeTagGroup, fixedWidth, hiddenAttributes) {
|
|
13871
|
+
if (legendGroups.length === 0) return;
|
|
13872
|
+
const groups = legendGroups.map((g) => ({
|
|
13873
|
+
name: g.name,
|
|
13874
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
13875
|
+
}));
|
|
13876
|
+
const isFixedMode = fixedWidth != null;
|
|
13877
|
+
const eyeAddonWidth = isFixedMode ? LEGEND_EYE_SIZE + LEGEND_EYE_GAP : 0;
|
|
13878
|
+
const legendConfig = {
|
|
13879
|
+
groups,
|
|
13880
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
13881
|
+
mode: "fixed",
|
|
13882
|
+
capsulePillAddonWidth: eyeAddonWidth
|
|
13883
|
+
};
|
|
13884
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
13885
|
+
const containerWidth = fixedWidth ?? legendGroups[0]?.x + (legendGroups[0]?.width ?? 200);
|
|
13886
|
+
const legendHandle = renderLegendD3(
|
|
13887
|
+
parent,
|
|
13888
|
+
legendConfig,
|
|
13889
|
+
legendState,
|
|
13890
|
+
palette,
|
|
13891
|
+
isDark,
|
|
13892
|
+
void 0,
|
|
13893
|
+
containerWidth
|
|
13894
|
+
);
|
|
13895
|
+
parent.selectAll("[data-legend-group]").classed("sitemap-legend-group", true);
|
|
13896
|
+
if (isFixedMode) {
|
|
13897
|
+
const computedLayout = legendHandle.getLayout();
|
|
13898
|
+
if (computedLayout.activeCapsule?.addonX != null) {
|
|
13899
|
+
const capsule = computedLayout.activeCapsule;
|
|
13900
|
+
const groupKey = capsule.groupName.toLowerCase();
|
|
13036
13901
|
const isHidden = hiddenAttributes?.has(groupKey) ?? false;
|
|
13037
|
-
const
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
const eyeShift = fixedWidth != null ? LEGEND_EYE_SIZE + LEGEND_EYE_GAP : 0;
|
|
13046
|
-
let entryX = pillXOff + pillW + 4 + eyeShift;
|
|
13047
|
-
for (const entry of group.entries) {
|
|
13048
|
-
const entryG = legendG.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
13049
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
13050
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
13051
|
-
entryG.append("text").attr("x", textX).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
13052
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
13902
|
+
const activeGroupEl = parent.select(`[data-legend-group="${groupKey}"]`);
|
|
13903
|
+
if (!activeGroupEl.empty()) {
|
|
13904
|
+
const eyeX = capsule.addonX;
|
|
13905
|
+
const eyeY = (LEGEND_HEIGHT - LEGEND_EYE_SIZE) / 2;
|
|
13906
|
+
const hitPad = 6;
|
|
13907
|
+
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);
|
|
13908
|
+
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");
|
|
13909
|
+
eyeG.append("path").attr("d", isHidden ? EYE_CLOSED_PATH : EYE_OPEN_PATH).attr("transform", `translate(${eyeX}, ${eyeY})`).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1.2).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
13053
13910
|
}
|
|
13054
13911
|
}
|
|
13055
13912
|
}
|
|
@@ -13103,13 +13960,14 @@ async function renderSitemapForExport(content, theme, palette) {
|
|
|
13103
13960
|
const brandColor = theme === "transparent" ? "#888" : effectivePalette.textMuted;
|
|
13104
13961
|
return injectBranding2(svgHtml, brandColor);
|
|
13105
13962
|
}
|
|
13106
|
-
var DIAGRAM_PADDING2, MAX_SCALE2, TITLE_HEIGHT2, LABEL_FONT_SIZE2, META_FONT_SIZE2, META_LINE_HEIGHT4, HEADER_HEIGHT4, SEPARATOR_GAP4, EDGE_STROKE_WIDTH2, NODE_STROKE_WIDTH2, CARD_RADIUS2, CONTAINER_RADIUS2, CONTAINER_LABEL_FONT_SIZE2, CONTAINER_META_FONT_SIZE2, CONTAINER_META_LINE_HEIGHT4, CONTAINER_HEADER_HEIGHT2, ARROWHEAD_W, ARROWHEAD_H, EDGE_LABEL_FONT_SIZE, COLLAPSE_BAR_HEIGHT2, LEGEND_FIXED_GAP2, lineGenerator;
|
|
13963
|
+
var DIAGRAM_PADDING2, MAX_SCALE2, TITLE_HEIGHT2, LABEL_FONT_SIZE2, META_FONT_SIZE2, META_LINE_HEIGHT4, HEADER_HEIGHT4, SEPARATOR_GAP4, EDGE_STROKE_WIDTH2, NODE_STROKE_WIDTH2, CARD_RADIUS2, CONTAINER_RADIUS2, CONTAINER_LABEL_FONT_SIZE2, CONTAINER_META_FONT_SIZE2, CONTAINER_META_LINE_HEIGHT4, CONTAINER_HEADER_HEIGHT2, ARROWHEAD_W, ARROWHEAD_H, EDGE_LABEL_FONT_SIZE, COLLAPSE_BAR_HEIGHT2, LEGEND_FIXED_GAP2, lineGenerator, lineGeneratorLinear;
|
|
13107
13964
|
var init_renderer2 = __esm({
|
|
13108
13965
|
"src/sitemap/renderer.ts"() {
|
|
13109
13966
|
"use strict";
|
|
13110
13967
|
init_fonts();
|
|
13111
13968
|
init_color_utils();
|
|
13112
13969
|
init_legend_constants();
|
|
13970
|
+
init_legend_d3();
|
|
13113
13971
|
init_title_constants();
|
|
13114
13972
|
DIAGRAM_PADDING2 = 20;
|
|
13115
13973
|
MAX_SCALE2 = 3;
|
|
@@ -13133,6 +13991,7 @@ var init_renderer2 = __esm({
|
|
|
13133
13991
|
COLLAPSE_BAR_HEIGHT2 = 6;
|
|
13134
13992
|
LEGEND_FIXED_GAP2 = 8;
|
|
13135
13993
|
lineGenerator = d3Shape.line().x((d) => d.x).y((d) => d.y).curve(d3Shape.curveBasis);
|
|
13994
|
+
lineGeneratorLinear = d3Shape.line().x((d) => d.x).y((d) => d.y).curve(d3Shape.curveLinear);
|
|
13136
13995
|
}
|
|
13137
13996
|
});
|
|
13138
13997
|
|
|
@@ -13395,8 +14254,7 @@ function computeLayout(parsed, _palette) {
|
|
|
13395
14254
|
currentX += cl.width + COLUMN_GAP;
|
|
13396
14255
|
}
|
|
13397
14256
|
const totalWidth = currentX - COLUMN_GAP + DIAGRAM_PADDING3;
|
|
13398
|
-
const
|
|
13399
|
-
const totalHeight = startY + maxColumnHeight + DIAGRAM_PADDING3 + legendSpace;
|
|
14257
|
+
const totalHeight = startY + maxColumnHeight + DIAGRAM_PADDING3;
|
|
13400
14258
|
return { columns: columnLayouts, totalWidth, totalHeight };
|
|
13401
14259
|
}
|
|
13402
14260
|
function renderKanban(container, parsed, palette, isDark, _onNavigateToLine, exportDims, activeTagGroup) {
|
|
@@ -13409,54 +14267,25 @@ function renderKanban(container, parsed, palette, isDark, _onNavigateToLine, exp
|
|
|
13409
14267
|
svg.append("text").attr("class", "chart-title").attr("data-line-number", parsed.titleLineNumber ?? 0).attr("x", DIAGRAM_PADDING3).attr("y", DIAGRAM_PADDING3 + TITLE_FONT_SIZE).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).attr("fill", palette.text).text(parsed.title);
|
|
13410
14268
|
}
|
|
13411
14269
|
if (parsed.tagGroups.length > 0) {
|
|
13412
|
-
const
|
|
13413
|
-
|
|
13414
|
-
const
|
|
13415
|
-
const
|
|
13416
|
-
|
|
13417
|
-
|
|
13418
|
-
|
|
13419
|
-
}
|
|
13420
|
-
|
|
13421
|
-
|
|
13422
|
-
|
|
13423
|
-
|
|
13424
|
-
|
|
13425
|
-
|
|
13426
|
-
|
|
13427
|
-
|
|
13428
|
-
|
|
13429
|
-
|
|
13430
|
-
|
|
13431
|
-
}
|
|
13432
|
-
const capsuleWidth = capsuleContentWidth + capsulePad * 2;
|
|
13433
|
-
if (isActive) {
|
|
13434
|
-
legendContainer.append("rect").attr("x", legendX).attr("y", legendY).attr("width", capsuleWidth).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
13435
|
-
}
|
|
13436
|
-
const pillX = legendX + (isActive ? capsulePad : 0);
|
|
13437
|
-
const pillBg = isActive ? palette.bg : groupBg;
|
|
13438
|
-
legendContainer.append("rect").attr("x", pillX).attr("y", legendY + capsulePad).attr("width", pillWidth2).attr("height", LEGEND_HEIGHT - capsulePad * 2).attr("rx", (LEGEND_HEIGHT - capsulePad * 2) / 2).attr("fill", pillBg).attr("class", "kanban-legend-group").attr("data-legend-group", group.name.toLowerCase());
|
|
13439
|
-
if (isActive) {
|
|
13440
|
-
legendContainer.append("rect").attr("x", pillX).attr("y", legendY + capsulePad).attr("width", pillWidth2).attr("height", LEGEND_HEIGHT - capsulePad * 2).attr("rx", (LEGEND_HEIGHT - capsulePad * 2) / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
13441
|
-
}
|
|
13442
|
-
legendContainer.append("text").attr("x", pillX + pillWidth2 / 2).attr("y", legendY + LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(group.name);
|
|
13443
|
-
if (isActive) {
|
|
13444
|
-
let entryX = pillX + pillWidth2 + 4;
|
|
13445
|
-
for (const entry of group.entries) {
|
|
13446
|
-
const entryG = legendContainer.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
13447
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", legendY + LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
13448
|
-
const entryTextX = entryX + LEGEND_DOT_R * 2 + 4;
|
|
13449
|
-
entryG.append("text").attr("x", entryTextX).attr(
|
|
13450
|
-
"y",
|
|
13451
|
-
legendY + LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1
|
|
13452
|
-
).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
13453
|
-
entryX = entryTextX + entry.value.length * LEGEND_ENTRY_FONT_SIZE * 0.6 + 8;
|
|
13454
|
-
}
|
|
13455
|
-
legendX += capsuleWidth + 12;
|
|
13456
|
-
} else {
|
|
13457
|
-
legendX += pillWidth2 + 12;
|
|
13458
|
-
}
|
|
13459
|
-
}
|
|
14270
|
+
const titleTextWidth = parsed.title ? measureLegendText(parsed.title, TITLE_FONT_SIZE) + 16 : 0;
|
|
14271
|
+
const legendX = DIAGRAM_PADDING3 + titleTextWidth;
|
|
14272
|
+
const legendY = DIAGRAM_PADDING3 + (TITLE_FONT_SIZE - LEGEND_HEIGHT) / 2;
|
|
14273
|
+
const legendConfig = {
|
|
14274
|
+
groups: parsed.tagGroups,
|
|
14275
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
14276
|
+
mode: exportDims ? "inline" : "fixed"
|
|
14277
|
+
};
|
|
14278
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
14279
|
+
const legendG = svg.append("g").attr("class", "kanban-legend").attr("transform", `translate(${legendX},${legendY})`);
|
|
14280
|
+
renderLegendD3(
|
|
14281
|
+
legendG,
|
|
14282
|
+
legendConfig,
|
|
14283
|
+
legendState,
|
|
14284
|
+
palette,
|
|
14285
|
+
isDark,
|
|
14286
|
+
void 0,
|
|
14287
|
+
width - legendX - DIAGRAM_PADDING3
|
|
14288
|
+
);
|
|
13460
14289
|
}
|
|
13461
14290
|
const defaultColBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
13462
14291
|
const defaultColHeaderBg = isDark ? mix(palette.surface, palette.bg, 70) : mix(palette.surface, palette.bg, 50);
|
|
@@ -13551,6 +14380,7 @@ var init_renderer3 = __esm({
|
|
|
13551
14380
|
init_parser5();
|
|
13552
14381
|
init_mutations();
|
|
13553
14382
|
init_legend_constants();
|
|
14383
|
+
init_legend_d3();
|
|
13554
14384
|
init_title_constants();
|
|
13555
14385
|
DIAGRAM_PADDING3 = 20;
|
|
13556
14386
|
COLUMN_GAP = 16;
|
|
@@ -13746,14 +14576,9 @@ function collectClassTypes(parsed) {
|
|
|
13746
14576
|
if (c.color) continue;
|
|
13747
14577
|
present.add(c.modifier ?? "class");
|
|
13748
14578
|
}
|
|
13749
|
-
return CLASS_TYPE_ORDER.filter((k) => present.has(k)).map(
|
|
13750
|
-
|
|
13751
|
-
|
|
13752
|
-
let w = 0;
|
|
13753
|
-
for (const e of entries) {
|
|
13754
|
-
w += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.label, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
13755
|
-
}
|
|
13756
|
-
return w;
|
|
14579
|
+
return CLASS_TYPE_ORDER.filter((k) => present.has(k)).map(
|
|
14580
|
+
(k) => CLASS_TYPE_MAP[k]
|
|
14581
|
+
);
|
|
13757
14582
|
}
|
|
13758
14583
|
function classTypeKey(modifier) {
|
|
13759
14584
|
return modifier ?? "class";
|
|
@@ -13822,7 +14647,10 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
|
|
|
13822
14647
|
defs.append("marker").attr("id", "cd-arrow-depend").attr("viewBox", `0 0 ${AW} ${AH}`).attr("refX", AW).attr("refY", AH / 2).attr("markerWidth", AW).attr("markerHeight", AH).attr("orient", "auto").append("polyline").attr("points", `0,0 ${AW},${AH / 2} 0,${AH}`).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1.5);
|
|
13823
14648
|
defs.append("marker").attr("id", "cd-arrow-assoc").attr("viewBox", `0 0 ${AW} ${AH}`).attr("refX", AW).attr("refY", AH / 2).attr("markerWidth", AW).attr("markerHeight", AH).attr("orient", "auto").append("polyline").attr("points", `0,0 ${AW},${AH / 2} 0,${AH}`).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1.5);
|
|
13824
14649
|
if (parsed.title) {
|
|
13825
|
-
const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).style(
|
|
14650
|
+
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(
|
|
14651
|
+
"cursor",
|
|
14652
|
+
onClickItem && parsed.titleLineNumber ? "pointer" : "default"
|
|
14653
|
+
).text(parsed.title);
|
|
13826
14654
|
if (parsed.titleLineNumber) {
|
|
13827
14655
|
titleEl.attr("data-line-number", parsed.titleLineNumber);
|
|
13828
14656
|
if (onClickItem) {
|
|
@@ -13836,32 +14664,33 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
|
|
|
13836
14664
|
}
|
|
13837
14665
|
const isLegendExpanded = legendActive !== false;
|
|
13838
14666
|
if (hasLegend) {
|
|
13839
|
-
const
|
|
13840
|
-
|
|
13841
|
-
|
|
13842
|
-
|
|
13843
|
-
|
|
13844
|
-
|
|
13845
|
-
|
|
13846
|
-
const legendG = svg.append("g").attr("class", "cd-legend").attr("data-legend-group", "type").attr("transform", `translate(${legendX}, ${legendY})`).style("cursor", "pointer");
|
|
13847
|
-
if (isLegendExpanded) {
|
|
13848
|
-
legendG.append("rect").attr("width", totalW).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
13849
|
-
legendG.append("rect").attr("x", LEGEND_CAPSULE_PAD).attr("y", LEGEND_CAPSULE_PAD).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", palette.bg);
|
|
13850
|
-
legendG.append("rect").attr("x", LEGEND_CAPSULE_PAD).attr("y", LEGEND_CAPSULE_PAD).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
13851
|
-
legendG.append("text").attr("x", LEGEND_CAPSULE_PAD + pillWidth2 / 2).attr("y", LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", palette.text).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).text(LEGEND_GROUP_NAME);
|
|
13852
|
-
let entryX = LEGEND_CAPSULE_PAD + pillWidth2 + LEGEND_ENTRY_TRAIL;
|
|
13853
|
-
for (const entry of legendEntries) {
|
|
13854
|
-
const color = palette.colors[entry.colorKey];
|
|
13855
|
-
const typeKey = CLASS_TYPE_ORDER.find((k) => CLASS_TYPE_MAP[k] === entry);
|
|
13856
|
-
const entryG = legendG.append("g").attr("data-legend-entry", typeKey);
|
|
13857
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", color);
|
|
13858
|
-
entryG.append("text").attr("x", entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).attr("font-family", FONT_FAMILY).text(entry.label);
|
|
13859
|
-
entryX += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(entry.label, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
14667
|
+
const legendGroups = [
|
|
14668
|
+
{
|
|
14669
|
+
name: LEGEND_GROUP_NAME,
|
|
14670
|
+
entries: legendEntries.map((entry) => ({
|
|
14671
|
+
value: entry.label,
|
|
14672
|
+
color: palette.colors[entry.colorKey]
|
|
14673
|
+
}))
|
|
13860
14674
|
}
|
|
13861
|
-
|
|
13862
|
-
|
|
13863
|
-
|
|
13864
|
-
|
|
14675
|
+
];
|
|
14676
|
+
const legendConfig = {
|
|
14677
|
+
groups: legendGroups,
|
|
14678
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
14679
|
+
mode: "fixed"
|
|
14680
|
+
};
|
|
14681
|
+
const legendState = {
|
|
14682
|
+
activeGroup: isLegendExpanded ? LEGEND_GROUP_NAME : null
|
|
14683
|
+
};
|
|
14684
|
+
const legendG = svg.append("g").attr("class", "cd-legend").attr("transform", `translate(0,${titleHeight})`);
|
|
14685
|
+
renderLegendD3(
|
|
14686
|
+
legendG,
|
|
14687
|
+
legendConfig,
|
|
14688
|
+
legendState,
|
|
14689
|
+
palette,
|
|
14690
|
+
isDark,
|
|
14691
|
+
void 0,
|
|
14692
|
+
width
|
|
14693
|
+
);
|
|
13865
14694
|
}
|
|
13866
14695
|
const contentG = svg.append("g").attr("transform", `translate(${offsetX}, ${offsetY}) scale(${scale})`);
|
|
13867
14696
|
for (const edge of layout.edges) {
|
|
@@ -13905,7 +14734,13 @@ function renderClassDiagram(container, parsed, layout, palette, isDark, onClickI
|
|
|
13905
14734
|
const colorOff = !!parsed.options?.["no-auto-color"];
|
|
13906
14735
|
const neutralize = hasLegend && !isLegendExpanded && !node.color;
|
|
13907
14736
|
const effectiveColor = neutralize ? palette.primary : node.color;
|
|
13908
|
-
const fill2 = nodeFill3(
|
|
14737
|
+
const fill2 = nodeFill3(
|
|
14738
|
+
palette,
|
|
14739
|
+
isDark,
|
|
14740
|
+
node.modifier,
|
|
14741
|
+
effectiveColor,
|
|
14742
|
+
colorOff
|
|
14743
|
+
);
|
|
13909
14744
|
const stroke2 = nodeStroke3(palette, node.modifier, effectiveColor, colorOff);
|
|
13910
14745
|
nodeG.append("rect").attr("x", -w / 2).attr("y", -h / 2).attr("width", w).attr("height", h).attr("rx", 3).attr("ry", 3).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", NODE_STROKE_WIDTH3);
|
|
13911
14746
|
let yPos = -h / 2;
|
|
@@ -13974,15 +14809,10 @@ function renderClassDiagramForExport(content, theme, palette) {
|
|
|
13974
14809
|
const exportWidth = layout.width + DIAGRAM_PADDING4 * 2;
|
|
13975
14810
|
const exportHeight = layout.height + DIAGRAM_PADDING4 * 2 + (parsed.title ? 40 : 0) + legendReserve;
|
|
13976
14811
|
return runInExportContainer(exportWidth, exportHeight, (container) => {
|
|
13977
|
-
renderClassDiagram(
|
|
13978
|
-
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
palette,
|
|
13982
|
-
isDark,
|
|
13983
|
-
void 0,
|
|
13984
|
-
{ width: exportWidth, height: exportHeight }
|
|
13985
|
-
);
|
|
14812
|
+
renderClassDiagram(container, parsed, layout, palette, isDark, void 0, {
|
|
14813
|
+
width: exportWidth,
|
|
14814
|
+
height: exportHeight
|
|
14815
|
+
});
|
|
13986
14816
|
return extractExportSvg(container, theme);
|
|
13987
14817
|
});
|
|
13988
14818
|
}
|
|
@@ -13993,6 +14823,7 @@ var init_renderer4 = __esm({
|
|
|
13993
14823
|
init_fonts();
|
|
13994
14824
|
init_export_container();
|
|
13995
14825
|
init_legend_constants();
|
|
14826
|
+
init_legend_d3();
|
|
13996
14827
|
init_title_constants();
|
|
13997
14828
|
init_color_utils();
|
|
13998
14829
|
init_parser2();
|
|
@@ -14601,35 +15432,24 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
|
|
|
14601
15432
|
}
|
|
14602
15433
|
}
|
|
14603
15434
|
if (parsed.tagGroups.length > 0) {
|
|
14604
|
-
const LEGEND_PILL_H = LEGEND_HEIGHT - 6;
|
|
14605
|
-
const LEGEND_PILL_RX = Math.floor(LEGEND_PILL_H / 2);
|
|
14606
|
-
const LEGEND_GAP = 8;
|
|
14607
|
-
const legendG = svg.append("g").attr("class", "er-tag-legend");
|
|
14608
|
-
if (activeTagGroup) {
|
|
14609
|
-
legendG.attr("data-legend-active", activeTagGroup.toLowerCase());
|
|
14610
|
-
}
|
|
14611
|
-
let legendX = DIAGRAM_PADDING5;
|
|
14612
15435
|
const legendY = DIAGRAM_PADDING5 + titleHeight;
|
|
14613
|
-
|
|
14614
|
-
|
|
14615
|
-
|
|
14616
|
-
|
|
14617
|
-
|
|
14618
|
-
|
|
14619
|
-
|
|
14620
|
-
|
|
14621
|
-
|
|
14622
|
-
|
|
14623
|
-
|
|
14624
|
-
|
|
14625
|
-
|
|
14626
|
-
|
|
14627
|
-
|
|
14628
|
-
|
|
14629
|
-
|
|
14630
|
-
}
|
|
14631
|
-
legendX += LEGEND_GROUP_GAP;
|
|
14632
|
-
}
|
|
15436
|
+
const legendConfig = {
|
|
15437
|
+
groups: parsed.tagGroups,
|
|
15438
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
15439
|
+
mode: "fixed"
|
|
15440
|
+
};
|
|
15441
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
15442
|
+
const legendG = svg.append("g").attr("class", "er-tag-legend").attr("transform", `translate(0,${legendY})`);
|
|
15443
|
+
renderLegendD3(
|
|
15444
|
+
legendG,
|
|
15445
|
+
legendConfig,
|
|
15446
|
+
legendState,
|
|
15447
|
+
palette,
|
|
15448
|
+
isDark,
|
|
15449
|
+
void 0,
|
|
15450
|
+
viewW
|
|
15451
|
+
);
|
|
15452
|
+
legendG.selectAll("[data-legend-group]").classed("er-legend-group", true);
|
|
14633
15453
|
}
|
|
14634
15454
|
if (semanticRoles) {
|
|
14635
15455
|
const presentRoles = ROLE_ORDER.filter((role) => {
|
|
@@ -14639,55 +15459,35 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
|
|
|
14639
15459
|
return false;
|
|
14640
15460
|
});
|
|
14641
15461
|
if (presentRoles.length > 0) {
|
|
14642
|
-
const measureLabelW = (text, fontSize) => {
|
|
14643
|
-
const dummy = svg.append("text").attr("font-size", fontSize).attr("font-family", FONT_FAMILY).attr("visibility", "hidden").text(text);
|
|
14644
|
-
const measured = dummy.node()?.getComputedTextLength?.() ?? 0;
|
|
14645
|
-
dummy.remove();
|
|
14646
|
-
return measured > 0 ? measured : text.length * fontSize * 0.6;
|
|
14647
|
-
};
|
|
14648
|
-
const labelWidths = /* @__PURE__ */ new Map();
|
|
14649
|
-
for (const role of presentRoles) {
|
|
14650
|
-
labelWidths.set(
|
|
14651
|
-
role,
|
|
14652
|
-
measureLabelW(ROLE_LABELS[role], LEGEND_ENTRY_FONT_SIZE)
|
|
14653
|
-
);
|
|
14654
|
-
}
|
|
14655
|
-
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
14656
|
-
const groupName = "Role";
|
|
14657
|
-
const pillWidth2 = measureLegendText(groupName, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
14658
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
14659
|
-
let totalWidth;
|
|
14660
|
-
let entriesWidth2 = 0;
|
|
14661
|
-
if (semanticActive) {
|
|
14662
|
-
for (const role of presentRoles) {
|
|
14663
|
-
entriesWidth2 += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + labelWidths.get(role) + LEGEND_ENTRY_TRAIL;
|
|
14664
|
-
}
|
|
14665
|
-
totalWidth = LEGEND_CAPSULE_PAD * 2 + pillWidth2 + LEGEND_ENTRY_TRAIL + entriesWidth2;
|
|
14666
|
-
} else {
|
|
14667
|
-
totalWidth = pillWidth2;
|
|
14668
|
-
}
|
|
14669
|
-
const legendX = (viewW - totalWidth) / 2;
|
|
14670
15462
|
const legendY = DIAGRAM_PADDING5 + titleHeight;
|
|
14671
|
-
const
|
|
14672
|
-
|
|
14673
|
-
|
|
14674
|
-
|
|
14675
|
-
|
|
14676
|
-
|
|
14677
|
-
|
|
14678
|
-
for (const role of presentRoles) {
|
|
14679
|
-
const label = ROLE_LABELS[role];
|
|
14680
|
-
const roleColor = palette.colors[ROLE_COLORS[role]];
|
|
14681
|
-
const entryG = semanticLegendG.append("g").attr("data-legend-entry", role);
|
|
14682
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", roleColor);
|
|
14683
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
14684
|
-
entryG.append("text").attr("x", textX).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).attr("font-family", FONT_FAMILY).text(label);
|
|
14685
|
-
entryX = textX + labelWidths.get(role) + LEGEND_ENTRY_TRAIL;
|
|
15463
|
+
const semanticGroups = [
|
|
15464
|
+
{
|
|
15465
|
+
name: "Role",
|
|
15466
|
+
entries: presentRoles.map((role) => ({
|
|
15467
|
+
value: ROLE_LABELS[role],
|
|
15468
|
+
color: palette.colors[ROLE_COLORS[role]]
|
|
15469
|
+
}))
|
|
14686
15470
|
}
|
|
14687
|
-
|
|
14688
|
-
|
|
14689
|
-
|
|
14690
|
-
|
|
15471
|
+
];
|
|
15472
|
+
const legendConfig = {
|
|
15473
|
+
groups: semanticGroups,
|
|
15474
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
15475
|
+
mode: "fixed"
|
|
15476
|
+
};
|
|
15477
|
+
const legendState = {
|
|
15478
|
+
activeGroup: semanticActive ? "Role" : null
|
|
15479
|
+
};
|
|
15480
|
+
const legendG = svg.append("g").attr("class", "er-semantic-legend").attr("transform", `translate(0,${legendY})`);
|
|
15481
|
+
renderLegendD3(
|
|
15482
|
+
legendG,
|
|
15483
|
+
legendConfig,
|
|
15484
|
+
legendState,
|
|
15485
|
+
palette,
|
|
15486
|
+
isDark,
|
|
15487
|
+
void 0,
|
|
15488
|
+
viewW
|
|
15489
|
+
);
|
|
15490
|
+
legendG.selectAll("[data-legend-group]").classed("er-legend-group", true);
|
|
14691
15491
|
}
|
|
14692
15492
|
}
|
|
14693
15493
|
}
|
|
@@ -14730,6 +15530,7 @@ var init_renderer5 = __esm({
|
|
|
14730
15530
|
init_palettes();
|
|
14731
15531
|
init_tag_groups();
|
|
14732
15532
|
init_legend_constants();
|
|
15533
|
+
init_legend_d3();
|
|
14733
15534
|
init_title_constants();
|
|
14734
15535
|
init_parser3();
|
|
14735
15536
|
init_layout4();
|
|
@@ -14754,6 +15555,17 @@ __export(layout_exports5, {
|
|
|
14754
15555
|
layoutBoxesAndLines: () => layoutBoxesAndLines
|
|
14755
15556
|
});
|
|
14756
15557
|
import dagre4 from "@dagrejs/dagre";
|
|
15558
|
+
function clipToRectBorder2(cx, cy, w, h, tx, ty) {
|
|
15559
|
+
const dx = tx - cx;
|
|
15560
|
+
const dy = ty - cy;
|
|
15561
|
+
if (dx === 0 && dy === 0) return { x: cx, y: cy };
|
|
15562
|
+
const hw = w / 2;
|
|
15563
|
+
const hh = h / 2;
|
|
15564
|
+
const sx = dx !== 0 ? hw / Math.abs(dx) : Infinity;
|
|
15565
|
+
const sy = dy !== 0 ? hh / Math.abs(dy) : Infinity;
|
|
15566
|
+
const s = Math.min(sx, sy);
|
|
15567
|
+
return { x: cx + dx * s, y: cy + dy * s };
|
|
15568
|
+
}
|
|
14757
15569
|
function computeNodeSize(_node) {
|
|
14758
15570
|
const PHI = 1.618;
|
|
14759
15571
|
const NODE_HEIGHT = 60;
|
|
@@ -14906,13 +15718,25 @@ function layoutBoxesAndLines(parsed, collapseInfo) {
|
|
|
14906
15718
|
const srcNode = g.node(edge.source);
|
|
14907
15719
|
const tgtNode = g.node(edge.target);
|
|
14908
15720
|
if (!srcNode || !tgtNode) continue;
|
|
14909
|
-
const
|
|
14910
|
-
|
|
14911
|
-
|
|
14912
|
-
|
|
14913
|
-
|
|
14914
|
-
|
|
14915
|
-
|
|
15721
|
+
const srcPt = clipToRectBorder2(
|
|
15722
|
+
srcNode.x,
|
|
15723
|
+
srcNode.y,
|
|
15724
|
+
srcNode.width,
|
|
15725
|
+
srcNode.height,
|
|
15726
|
+
tgtNode.x,
|
|
15727
|
+
tgtNode.y
|
|
15728
|
+
);
|
|
15729
|
+
const tgtPt = clipToRectBorder2(
|
|
15730
|
+
tgtNode.x,
|
|
15731
|
+
tgtNode.y,
|
|
15732
|
+
tgtNode.width,
|
|
15733
|
+
tgtNode.height,
|
|
15734
|
+
srcNode.x,
|
|
15735
|
+
srcNode.y
|
|
15736
|
+
);
|
|
15737
|
+
const midX = (srcPt.x + tgtPt.x) / 2;
|
|
15738
|
+
const midY = (srcPt.y + tgtPt.y) / 2;
|
|
15739
|
+
points = [srcPt, { x: midX, y: midY }, tgtPt];
|
|
14916
15740
|
} else {
|
|
14917
15741
|
const dagreEdge = g.edge(edge.source, edge.target, `e${i}`);
|
|
14918
15742
|
points = dagreEdge?.points ?? [];
|
|
@@ -14935,7 +15759,8 @@ function layoutBoxesAndLines(parsed, collapseInfo) {
|
|
|
14935
15759
|
labelY,
|
|
14936
15760
|
yOffset: edgeYOffsets[i],
|
|
14937
15761
|
parallelCount: edgeParallelCounts[i],
|
|
14938
|
-
metadata: edge.metadata
|
|
15762
|
+
metadata: edge.metadata,
|
|
15763
|
+
deferred: deferredSet.has(i) || void 0
|
|
14939
15764
|
});
|
|
14940
15765
|
}
|
|
14941
15766
|
let maxX = 0;
|
|
@@ -15001,7 +15826,7 @@ function fitTextToNode(label, nodeWidth, nodeHeight) {
|
|
|
15001
15826
|
const maxTextWidth = nodeWidth - NODE_TEXT_PADDING * 2;
|
|
15002
15827
|
const lineHeight = 1.3;
|
|
15003
15828
|
for (let fontSize = NODE_FONT_SIZE; fontSize >= MIN_NODE_FONT_SIZE; fontSize--) {
|
|
15004
|
-
const charWidth2 = fontSize *
|
|
15829
|
+
const charWidth2 = fontSize * CHAR_WIDTH_RATIO2;
|
|
15005
15830
|
const maxCharsPerLine = Math.floor(maxTextWidth / charWidth2);
|
|
15006
15831
|
const maxLines = Math.floor((nodeHeight - 8) / (fontSize * lineHeight));
|
|
15007
15832
|
if (maxCharsPerLine < 2 || maxLines < 1) continue;
|
|
@@ -15053,7 +15878,7 @@ function fitTextToNode(label, nodeWidth, nodeHeight) {
|
|
|
15053
15878
|
}
|
|
15054
15879
|
if (hardLines.length <= maxLines) return { lines: hardLines, fontSize };
|
|
15055
15880
|
}
|
|
15056
|
-
const charWidth = MIN_NODE_FONT_SIZE *
|
|
15881
|
+
const charWidth = MIN_NODE_FONT_SIZE * CHAR_WIDTH_RATIO2;
|
|
15057
15882
|
const maxChars = Math.floor((nodeWidth - NODE_TEXT_PADDING * 2) / charWidth);
|
|
15058
15883
|
const truncated = label.length > maxChars ? label.slice(0, maxChars - 1) + "\u2026" : label;
|
|
15059
15884
|
return { lines: [truncated], fontSize: MIN_NODE_FONT_SIZE };
|
|
@@ -15205,18 +16030,14 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
15205
16030
|
const edgeG = diagramG.append("g").attr("class", "bl-edge-group").attr("data-line-number", String(le.lineNumber));
|
|
15206
16031
|
edgeGroups.set(i, edgeG);
|
|
15207
16032
|
const markerId = `bl-arrow-${color.replace("#", "")}`;
|
|
15208
|
-
const
|
|
15209
|
-
|
|
15210
|
-
(parsed.direction === "TB" ? lineGeneratorTB : lineGeneratorLR)(
|
|
15211
|
-
points
|
|
15212
|
-
) ?? ""
|
|
15213
|
-
).attr("fill", "none").attr("stroke", color).attr("stroke-width", EDGE_STROKE_WIDTH5).attr("marker-end", `url(#${markerId})`);
|
|
16033
|
+
const gen = le.deferred ? lineGeneratorLinear2 : parsed.direction === "TB" ? lineGeneratorTB : lineGeneratorLR;
|
|
16034
|
+
const path = edgeG.append("path").attr("class", "bl-edge").attr("d", gen(points) ?? "").attr("fill", "none").attr("stroke", color).attr("stroke-width", EDGE_STROKE_WIDTH5).attr("marker-end", `url(#${markerId})`);
|
|
15214
16035
|
if (le.bidirectional) {
|
|
15215
16036
|
const revId = `bl-arrow-rev-${color.replace("#", "")}`;
|
|
15216
16037
|
path.attr("marker-start", `url(#${revId})`);
|
|
15217
16038
|
}
|
|
15218
16039
|
if (le.label && le.labelX != null && le.labelY != null) {
|
|
15219
|
-
const lw = le.label.length * EDGE_LABEL_FONT_SIZE4 *
|
|
16040
|
+
const lw = le.label.length * EDGE_LABEL_FONT_SIZE4 * CHAR_WIDTH_RATIO2;
|
|
15220
16041
|
labelPositions.push({
|
|
15221
16042
|
x: le.labelX,
|
|
15222
16043
|
y: le.labelY + le.yOffset,
|
|
@@ -15274,7 +16095,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
15274
16095
|
const descY = labelY + lineH / 2 + gap + META_FONT_SIZE3 / 2;
|
|
15275
16096
|
nodeG.append("text").attr("x", 0).attr("y", labelY).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", NODE_FONT_SIZE).attr("font-weight", "600").attr("fill", colors.text).text(node.label);
|
|
15276
16097
|
const maxChars = Math.floor(
|
|
15277
|
-
(ln.width - NODE_TEXT_PADDING * 2) / (META_FONT_SIZE3 *
|
|
16098
|
+
(ln.width - NODE_TEXT_PADDING * 2) / (META_FONT_SIZE3 * CHAR_WIDTH_RATIO2)
|
|
15278
16099
|
);
|
|
15279
16100
|
const desc = node.description.length > maxChars ? node.description.slice(0, maxChars - 1) + "\u2026" : node.description;
|
|
15280
16101
|
const descEl = nodeG.append("text").attr("x", 0).attr("y", descY).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", META_FONT_SIZE3).attr("fill", palette.textMuted).text(desc);
|
|
@@ -15291,50 +16112,23 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
15291
16112
|
}
|
|
15292
16113
|
}
|
|
15293
16114
|
if (parsed.tagGroups.length > 0) {
|
|
15294
|
-
|
|
15295
|
-
|
|
15296
|
-
}
|
|
15297
|
-
|
|
15298
|
-
|
|
15299
|
-
|
|
15300
|
-
|
|
15301
|
-
|
|
15302
|
-
|
|
15303
|
-
|
|
15304
|
-
|
|
15305
|
-
|
|
15306
|
-
|
|
15307
|
-
|
|
15308
|
-
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
}
|
|
15312
|
-
const legendX = Math.max(LEGEND_CAPSULE_PAD, (svgWidth - totalW) / 2);
|
|
15313
|
-
const legendY = titleOffset + 4;
|
|
15314
|
-
const legendG = svg.append("g").attr("transform", `translate(${legendX},${legendY})`);
|
|
15315
|
-
let x = 0;
|
|
15316
|
-
for (const tg of parsed.tagGroups) {
|
|
15317
|
-
const isActiveGroup = activeGroup?.toLowerCase() === tg.name.toLowerCase();
|
|
15318
|
-
const groupG = legendG.append("g").attr("class", "bl-legend-group").attr("data-legend-group", tg.name.toLowerCase()).style("cursor", "pointer");
|
|
15319
|
-
const nameW = measureLegendText(tg.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
15320
|
-
const tagPill = groupG.append("rect").attr("x", x).attr("y", 0).attr("width", nameW).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
15321
|
-
if (isActiveGroup) {
|
|
15322
|
-
tagPill.attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
15323
|
-
}
|
|
15324
|
-
groupG.append("text").attr("x", x + nameW / 2).attr("y", LEGEND_HEIGHT / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", 500).attr("fill", isActiveGroup ? palette.text : palette.textMuted).attr("pointer-events", "none").text(tg.name);
|
|
15325
|
-
x += nameW;
|
|
15326
|
-
if (isActiveGroup) {
|
|
15327
|
-
x += 6;
|
|
15328
|
-
for (const entry of tg.entries) {
|
|
15329
|
-
const entryColor = entry.color || palette.textMuted;
|
|
15330
|
-
const ew = measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE);
|
|
15331
|
-
const entryG = groupG.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
15332
|
-
entryG.append("circle").attr("cx", x + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entryColor);
|
|
15333
|
-
entryG.append("text").attr("x", x + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP).attr("y", LEGEND_HEIGHT / 2).attr("dominant-baseline", "central").attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
15334
|
-
x += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + ew + LEGEND_ENTRY_TRAIL;
|
|
15335
|
-
}
|
|
15336
|
-
}
|
|
15337
|
-
x += LEGEND_GROUP_GAP;
|
|
16115
|
+
const legendConfig = {
|
|
16116
|
+
groups: parsed.tagGroups,
|
|
16117
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
16118
|
+
mode: "fixed"
|
|
16119
|
+
};
|
|
16120
|
+
const legendState = { activeGroup };
|
|
16121
|
+
const legendG = svg.append("g").attr("transform", `translate(0,${titleOffset + 4})`);
|
|
16122
|
+
renderLegendD3(
|
|
16123
|
+
legendG,
|
|
16124
|
+
legendConfig,
|
|
16125
|
+
legendState,
|
|
16126
|
+
palette,
|
|
16127
|
+
isDark,
|
|
16128
|
+
void 0,
|
|
16129
|
+
width
|
|
16130
|
+
);
|
|
16131
|
+
legendG.selectAll("[data-legend-group]").classed("bl-legend-group", true);
|
|
15338
16132
|
}
|
|
15339
16133
|
}
|
|
15340
16134
|
function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark, options) {
|
|
@@ -15342,12 +16136,13 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
|
|
|
15342
16136
|
exportDims: options?.exportDims
|
|
15343
16137
|
});
|
|
15344
16138
|
}
|
|
15345
|
-
var DIAGRAM_PADDING6, NODE_FONT_SIZE, MIN_NODE_FONT_SIZE, META_FONT_SIZE3, EDGE_LABEL_FONT_SIZE4, EDGE_STROKE_WIDTH5, NODE_STROKE_WIDTH5, NODE_RX, COLLAPSE_BAR_HEIGHT3, ARROWHEAD_W2, ARROWHEAD_H2,
|
|
16139
|
+
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_RATIO2, NODE_TEXT_PADDING, GROUP_RX, GROUP_LABEL_FONT_SIZE, lineGeneratorLR, lineGeneratorTB, lineGeneratorLinear2;
|
|
15346
16140
|
var init_renderer6 = __esm({
|
|
15347
16141
|
"src/boxes-and-lines/renderer.ts"() {
|
|
15348
16142
|
"use strict";
|
|
15349
16143
|
init_fonts();
|
|
15350
16144
|
init_legend_constants();
|
|
16145
|
+
init_legend_d3();
|
|
15351
16146
|
init_title_constants();
|
|
15352
16147
|
init_color_utils();
|
|
15353
16148
|
init_tag_groups();
|
|
@@ -15362,12 +16157,13 @@ var init_renderer6 = __esm({
|
|
|
15362
16157
|
COLLAPSE_BAR_HEIGHT3 = 4;
|
|
15363
16158
|
ARROWHEAD_W2 = 5;
|
|
15364
16159
|
ARROWHEAD_H2 = 4;
|
|
15365
|
-
|
|
16160
|
+
CHAR_WIDTH_RATIO2 = 0.6;
|
|
15366
16161
|
NODE_TEXT_PADDING = 12;
|
|
15367
16162
|
GROUP_RX = 8;
|
|
15368
16163
|
GROUP_LABEL_FONT_SIZE = 14;
|
|
15369
16164
|
lineGeneratorLR = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveMonotoneX);
|
|
15370
16165
|
lineGeneratorTB = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveMonotoneY);
|
|
16166
|
+
lineGeneratorLinear2 = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveLinear);
|
|
15371
16167
|
}
|
|
15372
16168
|
});
|
|
15373
16169
|
|
|
@@ -15433,7 +16229,7 @@ function reduceCrossings(g, edgeList, nodeGroupMap) {
|
|
|
15433
16229
|
}
|
|
15434
16230
|
const nodeGeometry = /* @__PURE__ */ new Map();
|
|
15435
16231
|
for (const name of g.nodes()) {
|
|
15436
|
-
const pos = g
|
|
16232
|
+
const pos = gNode(g, name);
|
|
15437
16233
|
if (pos)
|
|
15438
16234
|
nodeGeometry.set(name, {
|
|
15439
16235
|
y: pos.y,
|
|
@@ -15443,14 +16239,14 @@ function reduceCrossings(g, edgeList, nodeGroupMap) {
|
|
|
15443
16239
|
}
|
|
15444
16240
|
const rankMap = /* @__PURE__ */ new Map();
|
|
15445
16241
|
for (const name of g.nodes()) {
|
|
15446
|
-
const pos = g
|
|
16242
|
+
const pos = gNode(g, name);
|
|
15447
16243
|
if (!pos) continue;
|
|
15448
16244
|
const rankY = Math.round(pos.y);
|
|
15449
16245
|
if (!rankMap.has(rankY)) rankMap.set(rankY, []);
|
|
15450
16246
|
rankMap.get(rankY).push(name);
|
|
15451
16247
|
}
|
|
15452
16248
|
for (const [, rankNodes] of rankMap) {
|
|
15453
|
-
rankNodes.sort((a, b) => g
|
|
16249
|
+
rankNodes.sort((a, b) => gNode(g, a).x - gNode(g, b).x);
|
|
15454
16250
|
}
|
|
15455
16251
|
let anyMoved = false;
|
|
15456
16252
|
for (const [, rankNodes] of rankMap) {
|
|
@@ -15477,10 +16273,10 @@ function reduceCrossings(g, edgeList, nodeGroupMap) {
|
|
|
15477
16273
|
}
|
|
15478
16274
|
for (const partition of partitions) {
|
|
15479
16275
|
if (partition.length < 2) continue;
|
|
15480
|
-
const xSlots = partition.map((name) => g
|
|
16276
|
+
const xSlots = partition.map((name) => gNode(g, name).x).sort((a, b) => a - b);
|
|
15481
16277
|
const basePositions = /* @__PURE__ */ new Map();
|
|
15482
16278
|
for (const name of g.nodes()) {
|
|
15483
|
-
const pos = g
|
|
16279
|
+
const pos = gNode(g, name);
|
|
15484
16280
|
if (pos) basePositions.set(name, pos.x);
|
|
15485
16281
|
}
|
|
15486
16282
|
const currentPenalty = computeEdgePenalty(
|
|
@@ -15558,7 +16354,7 @@ function reduceCrossings(g, edgeList, nodeGroupMap) {
|
|
|
15558
16354
|
}
|
|
15559
16355
|
if (bestPerm.some((name, i) => name !== partition[i])) {
|
|
15560
16356
|
for (let i = 0; i < bestPerm.length; i++) {
|
|
15561
|
-
g
|
|
16357
|
+
gNode(g, bestPerm[i]).x = xSlots[i];
|
|
15562
16358
|
const rankIdx = rankNodes.indexOf(partition[i]);
|
|
15563
16359
|
if (rankIdx >= 0) rankNodes[rankIdx] = bestPerm[i];
|
|
15564
16360
|
}
|
|
@@ -15568,10 +16364,10 @@ function reduceCrossings(g, edgeList, nodeGroupMap) {
|
|
|
15568
16364
|
}
|
|
15569
16365
|
if (anyMoved) {
|
|
15570
16366
|
for (const edge of edgeList) {
|
|
15571
|
-
const edgeData = g
|
|
16367
|
+
const edgeData = gEdge(g, edge.source, edge.target);
|
|
15572
16368
|
if (!edgeData) continue;
|
|
15573
|
-
const srcPos = g
|
|
15574
|
-
const tgtPos = g
|
|
16369
|
+
const srcPos = gNode(g, edge.source);
|
|
16370
|
+
const tgtPos = gNode(g, edge.target);
|
|
15575
16371
|
if (!srcPos || !tgtPos) continue;
|
|
15576
16372
|
const srcBottom = { x: srcPos.x, y: srcPos.y + srcPos.height / 2 };
|
|
15577
16373
|
const tgtTop = { x: tgtPos.x, y: tgtPos.y - tgtPos.height / 2 };
|
|
@@ -17015,11 +17811,13 @@ function layoutC4Deployment(parsed, activeTagGroup) {
|
|
|
17015
17811
|
height: totalHeight
|
|
17016
17812
|
};
|
|
17017
17813
|
}
|
|
17018
|
-
var CHAR_WIDTH5, MIN_NODE_WIDTH, MAX_NODE_WIDTH, TYPE_LABEL_HEIGHT, DIVIDER_GAP, NAME_HEIGHT, DESC_LINE_HEIGHT, DESC_CHAR_WIDTH, CARD_V_PAD3, CARD_H_PAD3, META_LINE_HEIGHT5, META_CHAR_WIDTH, MARGIN4, BOUNDARY_PAD, GROUP_BOUNDARY_PAD, LEGEND_HEIGHT4, LEGEND_PILL_PAD4, LEGEND_DOT_R4, LEGEND_ENTRY_DOT_GAP4, LEGEND_ENTRY_TRAIL4, LEGEND_CAPSULE_PAD4, EDGE_NODE_COLLISION_WEIGHT, META_EXCLUDE_KEYS;
|
|
17814
|
+
var gNode, gEdge, CHAR_WIDTH5, MIN_NODE_WIDTH, MAX_NODE_WIDTH, TYPE_LABEL_HEIGHT, DIVIDER_GAP, NAME_HEIGHT, DESC_LINE_HEIGHT, DESC_CHAR_WIDTH, CARD_V_PAD3, CARD_H_PAD3, META_LINE_HEIGHT5, META_CHAR_WIDTH, MARGIN4, BOUNDARY_PAD, GROUP_BOUNDARY_PAD, LEGEND_HEIGHT4, LEGEND_PILL_PAD4, LEGEND_DOT_R4, LEGEND_ENTRY_DOT_GAP4, LEGEND_ENTRY_TRAIL4, LEGEND_CAPSULE_PAD4, EDGE_NODE_COLLISION_WEIGHT, META_EXCLUDE_KEYS;
|
|
17019
17815
|
var init_layout6 = __esm({
|
|
17020
17816
|
"src/c4/layout.ts"() {
|
|
17021
17817
|
"use strict";
|
|
17022
17818
|
init_legend_constants();
|
|
17819
|
+
gNode = (g, name) => g.node(name);
|
|
17820
|
+
gEdge = (g, v, w) => g.edge(v, w);
|
|
17023
17821
|
CHAR_WIDTH5 = 8;
|
|
17024
17822
|
MIN_NODE_WIDTH = 160;
|
|
17025
17823
|
MAX_NODE_WIDTH = 260;
|
|
@@ -17276,7 +18074,7 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
|
|
|
17276
18074
|
if (activeTagGroup) {
|
|
17277
18075
|
legendParent.attr("data-legend-active", activeTagGroup.toLowerCase());
|
|
17278
18076
|
}
|
|
17279
|
-
|
|
18077
|
+
renderLegend2(
|
|
17280
18078
|
legendParent,
|
|
17281
18079
|
layout,
|
|
17282
18080
|
palette,
|
|
@@ -17637,52 +18435,28 @@ function placeEdgeLabels(labels, edges, obstacleRects) {
|
|
|
17637
18435
|
placedRects.push({ x: lbl.x, y: lbl.y, w: lbl.bgW, h: lbl.bgH });
|
|
17638
18436
|
}
|
|
17639
18437
|
}
|
|
17640
|
-
function
|
|
17641
|
-
const
|
|
17642
|
-
|
|
17643
|
-
|
|
17644
|
-
|
|
17645
|
-
const
|
|
17646
|
-
|
|
17647
|
-
|
|
17648
|
-
|
|
17649
|
-
|
|
17650
|
-
|
|
17651
|
-
|
|
17652
|
-
|
|
17653
|
-
|
|
17654
|
-
|
|
17655
|
-
|
|
17656
|
-
|
|
17657
|
-
|
|
17658
|
-
|
|
17659
|
-
|
|
17660
|
-
|
|
17661
|
-
|
|
17662
|
-
const gY = fixedPositions != null ? 0 : group.y;
|
|
17663
|
-
const gEl = parent.append("g").attr("transform", `translate(${gX}, ${gY})`).attr("class", "c4-legend-group").attr("data-legend-group", group.name.toLowerCase()).style("cursor", "pointer");
|
|
17664
|
-
if (isActive) {
|
|
17665
|
-
gEl.append("rect").attr("width", group.width).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
17666
|
-
}
|
|
17667
|
-
const pillX = isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
17668
|
-
const pillY = LEGEND_CAPSULE_PAD;
|
|
17669
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
17670
|
-
gEl.append("rect").attr("x", pillX).attr("y", pillY).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", isActive ? palette.bg : groupBg);
|
|
17671
|
-
if (isActive) {
|
|
17672
|
-
gEl.append("rect").attr("x", pillX).attr("y", pillY).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
17673
|
-
}
|
|
17674
|
-
gEl.append("text").attr("x", pillX + pillWidth2 / 2).attr("y", LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(pillLabel);
|
|
17675
|
-
if (isActive) {
|
|
17676
|
-
let entryX = pillX + pillWidth2 + 4;
|
|
17677
|
-
for (const entry of group.entries) {
|
|
17678
|
-
const entryG = gEl.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
17679
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
17680
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
17681
|
-
entryG.append("text").attr("x", textX).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
17682
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
17683
|
-
}
|
|
17684
|
-
}
|
|
17685
|
-
}
|
|
18438
|
+
function renderLegend2(parent, layout, palette, isDark, activeTagGroup, fixedWidth) {
|
|
18439
|
+
const groups = layout.legend.map((g) => ({
|
|
18440
|
+
name: g.name,
|
|
18441
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
18442
|
+
}));
|
|
18443
|
+
const legendConfig = {
|
|
18444
|
+
groups,
|
|
18445
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
18446
|
+
mode: "fixed"
|
|
18447
|
+
};
|
|
18448
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
18449
|
+
const containerWidth = fixedWidth ?? layout.width;
|
|
18450
|
+
renderLegendD3(
|
|
18451
|
+
parent,
|
|
18452
|
+
legendConfig,
|
|
18453
|
+
legendState,
|
|
18454
|
+
palette,
|
|
18455
|
+
isDark,
|
|
18456
|
+
void 0,
|
|
18457
|
+
containerWidth
|
|
18458
|
+
);
|
|
18459
|
+
parent.selectAll("[data-legend-group]").classed("c4-legend-group", true);
|
|
17686
18460
|
}
|
|
17687
18461
|
function renderC4Containers(container, parsed, layout, palette, isDark, onClickItem, exportDims, activeTagGroup) {
|
|
17688
18462
|
d3Selection7.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
@@ -17893,7 +18667,7 @@ function renderC4Containers(container, parsed, layout, palette, isDark, onClickI
|
|
|
17893
18667
|
if (activeTagGroup) {
|
|
17894
18668
|
legendParent.attr("data-legend-active", activeTagGroup.toLowerCase());
|
|
17895
18669
|
}
|
|
17896
|
-
|
|
18670
|
+
renderLegend2(
|
|
17897
18671
|
legendParent,
|
|
17898
18672
|
layout,
|
|
17899
18673
|
palette,
|
|
@@ -18021,6 +18795,7 @@ var init_renderer7 = __esm({
|
|
|
18021
18795
|
init_parser6();
|
|
18022
18796
|
init_layout6();
|
|
18023
18797
|
init_legend_constants();
|
|
18798
|
+
init_legend_d3();
|
|
18024
18799
|
init_title_constants();
|
|
18025
18800
|
DIAGRAM_PADDING7 = 20;
|
|
18026
18801
|
MAX_SCALE5 = 3;
|
|
@@ -20910,17 +21685,17 @@ function computeInfraLegendGroups(nodes, tagGroups, palette, edges) {
|
|
|
20910
21685
|
color: r.color,
|
|
20911
21686
|
key: r.name.toLowerCase().replace(/\s+/g, "-")
|
|
20912
21687
|
}));
|
|
20913
|
-
const
|
|
20914
|
-
let
|
|
21688
|
+
const pillWidth3 = measureLegendText("Capabilities", LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21689
|
+
let entriesWidth3 = 0;
|
|
20915
21690
|
for (const e of entries) {
|
|
20916
|
-
|
|
21691
|
+
entriesWidth3 += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
20917
21692
|
}
|
|
20918
21693
|
groups.push({
|
|
20919
21694
|
name: "Capabilities",
|
|
20920
21695
|
type: "role",
|
|
20921
21696
|
entries,
|
|
20922
|
-
width: LEGEND_CAPSULE_PAD * 2 +
|
|
20923
|
-
minifiedWidth:
|
|
21697
|
+
width: LEGEND_CAPSULE_PAD * 2 + pillWidth3 + 4 + entriesWidth3,
|
|
21698
|
+
minifiedWidth: pillWidth3
|
|
20924
21699
|
});
|
|
20925
21700
|
}
|
|
20926
21701
|
for (const tg of tagGroups) {
|
|
@@ -20935,113 +21710,88 @@ function computeInfraLegendGroups(nodes, tagGroups, palette, edges) {
|
|
|
20935
21710
|
}
|
|
20936
21711
|
}
|
|
20937
21712
|
if (entries.length === 0) continue;
|
|
20938
|
-
const
|
|
20939
|
-
let
|
|
21713
|
+
const pillWidth3 = measureLegendText(tg.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21714
|
+
let entriesWidth3 = 0;
|
|
20940
21715
|
for (const e of entries) {
|
|
20941
|
-
|
|
21716
|
+
entriesWidth3 += LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP + measureLegendText(e.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
20942
21717
|
}
|
|
20943
21718
|
groups.push({
|
|
20944
21719
|
name: tg.name,
|
|
20945
21720
|
type: "tag",
|
|
20946
21721
|
tagKey: (tg.alias ?? tg.name).toLowerCase(),
|
|
20947
21722
|
entries,
|
|
20948
|
-
width: LEGEND_CAPSULE_PAD * 2 +
|
|
20949
|
-
minifiedWidth:
|
|
21723
|
+
width: LEGEND_CAPSULE_PAD * 2 + pillWidth3 + 4 + entriesWidth3,
|
|
21724
|
+
minifiedWidth: pillWidth3
|
|
20950
21725
|
});
|
|
20951
21726
|
}
|
|
20952
21727
|
return groups;
|
|
20953
21728
|
}
|
|
20954
|
-
function
|
|
20955
|
-
if (!playback) return 0;
|
|
20956
|
-
const pillWidth2 = measureLegendText("Playback", LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
20957
|
-
if (!playback.expanded) return pillWidth2;
|
|
20958
|
-
let entriesW = 8;
|
|
20959
|
-
entriesW += LEGEND_PILL_FONT_SIZE * 0.8 + 6;
|
|
20960
|
-
for (const s of playback.speedOptions) {
|
|
20961
|
-
entriesW += measureLegendText(`${s}x`, LEGEND_ENTRY_FONT_SIZE) + SPEED_BADGE_H_PAD * 2 + SPEED_BADGE_GAP;
|
|
20962
|
-
}
|
|
20963
|
-
return LEGEND_CAPSULE_PAD * 2 + pillWidth2 + entriesW;
|
|
20964
|
-
}
|
|
20965
|
-
function renderLegend4(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback) {
|
|
21729
|
+
function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback) {
|
|
20966
21730
|
if (legendGroups.length === 0 && !playback) return;
|
|
20967
21731
|
const legendG = rootSvg.append("g").attr("transform", `translate(0, ${legendY})`);
|
|
20968
21732
|
if (activeGroup) {
|
|
20969
21733
|
legendG.attr("data-legend-active", activeGroup.toLowerCase());
|
|
20970
21734
|
}
|
|
20971
|
-
const
|
|
20972
|
-
|
|
20973
|
-
|
|
20974
|
-
|
|
20975
|
-
|
|
21735
|
+
const allGroups = legendGroups.map((g) => ({
|
|
21736
|
+
name: g.name,
|
|
21737
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
21738
|
+
}));
|
|
21739
|
+
if (playback) {
|
|
21740
|
+
allGroups.push({ name: "Playback", entries: [] });
|
|
21741
|
+
}
|
|
21742
|
+
const legendConfig = {
|
|
21743
|
+
groups: allGroups,
|
|
21744
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
21745
|
+
mode: "fixed",
|
|
21746
|
+
showEmptyGroups: true
|
|
21747
|
+
};
|
|
21748
|
+
const legendState = { activeGroup };
|
|
21749
|
+
renderLegendD3(
|
|
21750
|
+
legendG,
|
|
21751
|
+
legendConfig,
|
|
21752
|
+
legendState,
|
|
21753
|
+
palette,
|
|
21754
|
+
isDark,
|
|
21755
|
+
void 0,
|
|
21756
|
+
totalWidth
|
|
21757
|
+
);
|
|
21758
|
+
legendG.selectAll("[data-legend-group]").classed("infra-legend-group", true);
|
|
20976
21759
|
for (const group of legendGroups) {
|
|
20977
|
-
const
|
|
20978
|
-
const
|
|
20979
|
-
|
|
20980
|
-
|
|
20981
|
-
|
|
20982
|
-
|
|
20983
|
-
|
|
20984
|
-
}
|
|
20985
|
-
const pillXOff = isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
20986
|
-
const pillYOff = LEGEND_CAPSULE_PAD;
|
|
20987
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
20988
|
-
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", isActive ? palette.bg : groupBg);
|
|
20989
|
-
if (isActive) {
|
|
20990
|
-
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", pillWidth2).attr("height", pillH).attr("rx", pillH / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
20991
|
-
}
|
|
20992
|
-
gEl.append("text").attr("x", pillXOff + pillWidth2 / 2).attr("y", LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-family", FONT_FAMILY).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(pillLabel);
|
|
20993
|
-
if (isActive) {
|
|
20994
|
-
let entryX = pillXOff + pillWidth2 + 4;
|
|
20995
|
-
for (const entry of group.entries) {
|
|
20996
|
-
const entryG = gEl.append("g").attr("class", "infra-legend-entry").attr("data-legend-entry", entry.key.toLowerCase()).attr("data-legend-color", entry.color).attr("data-legend-type", group.type).attr(
|
|
21760
|
+
const groupKey = group.name.toLowerCase();
|
|
21761
|
+
for (const entry of group.entries) {
|
|
21762
|
+
const entryEl = legendG.select(
|
|
21763
|
+
`[data-legend-group="${groupKey}"] [data-legend-entry="${entry.value.toLowerCase()}"]`
|
|
21764
|
+
);
|
|
21765
|
+
if (!entryEl.empty()) {
|
|
21766
|
+
entryEl.attr("data-legend-entry", entry.key.toLowerCase()).attr("data-legend-color", entry.color).attr("data-legend-type", group.type).attr(
|
|
20997
21767
|
"data-legend-tag-group",
|
|
20998
21768
|
group.type === "tag" ? group.tagKey ?? "" : null
|
|
20999
|
-
)
|
|
21000
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
21001
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
21002
|
-
entryG.append("text").attr("x", textX).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-family", FONT_FAMILY).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
21003
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
21769
|
+
);
|
|
21004
21770
|
}
|
|
21005
21771
|
}
|
|
21006
|
-
cursorX += effectiveW(group) + LEGEND_GROUP_GAP;
|
|
21007
21772
|
}
|
|
21008
|
-
|
|
21009
|
-
|
|
21010
|
-
|
|
21011
|
-
|
|
21012
|
-
|
|
21013
|
-
const
|
|
21014
|
-
|
|
21015
|
-
|
|
21016
|
-
|
|
21017
|
-
|
|
21018
|
-
|
|
21019
|
-
const
|
|
21020
|
-
|
|
21021
|
-
|
|
21022
|
-
|
|
21023
|
-
|
|
21024
|
-
|
|
21025
|
-
|
|
21026
|
-
|
|
21027
|
-
|
|
21028
|
-
|
|
21029
|
-
|
|
21030
|
-
pbG.append("text").attr("x", entryX).attr("y", entryY).attr("font-family", FONT_FAMILY).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("fill", palette.textMuted).attr("data-playback-action", "toggle-pause").style("cursor", "pointer").text(ppLabel);
|
|
21031
|
-
entryX += LEGEND_PILL_FONT_SIZE * 0.8 + 6;
|
|
21032
|
-
for (const s of playback.speedOptions) {
|
|
21033
|
-
const label = `${s}x`;
|
|
21034
|
-
const isActive = playback.speed === s;
|
|
21035
|
-
const slotW = measureLegendText(label, LEGEND_ENTRY_FONT_SIZE) + SPEED_BADGE_H_PAD * 2;
|
|
21036
|
-
const badgeH = LEGEND_ENTRY_FONT_SIZE + SPEED_BADGE_V_PAD * 2;
|
|
21037
|
-
const badgeY = (LEGEND_HEIGHT - badgeH) / 2;
|
|
21038
|
-
const speedG = pbG.append("g").attr("data-playback-action", "set-speed").attr("data-playback-value", String(s)).style("cursor", "pointer");
|
|
21039
|
-
speedG.append("rect").attr("x", entryX).attr("y", badgeY).attr("width", slotW).attr("height", badgeH).attr("rx", badgeH / 2).attr("fill", isActive ? palette.primary : "transparent");
|
|
21040
|
-
speedG.append("text").attr("x", entryX + slotW / 2).attr("y", entryY).attr("font-family", FONT_FAMILY).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("font-weight", isActive ? "600" : "400").attr("fill", isActive ? palette.bg : palette.textMuted).attr("text-anchor", "middle").text(label);
|
|
21041
|
-
entryX += slotW + SPEED_BADGE_GAP;
|
|
21042
|
-
}
|
|
21043
|
-
}
|
|
21044
|
-
cursorX += fullW + LEGEND_GROUP_GAP;
|
|
21773
|
+
const playbackEl = legendG.select('[data-legend-group="playback"]');
|
|
21774
|
+
if (!playbackEl.empty()) {
|
|
21775
|
+
playbackEl.classed("infra-playback-pill", true);
|
|
21776
|
+
}
|
|
21777
|
+
if (playback && playback.expanded && !playbackEl.empty()) {
|
|
21778
|
+
const pillWidth3 = measureLegendText("Playback", LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
21779
|
+
let entryX = pillWidth3 + 8;
|
|
21780
|
+
const entryY = LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1;
|
|
21781
|
+
const ppLabel = playback.paused ? "\u25B6" : "\u23F8";
|
|
21782
|
+
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);
|
|
21783
|
+
entryX += LEGEND_PILL_FONT_SIZE * 0.8 + 6;
|
|
21784
|
+
for (const s of playback.speedOptions) {
|
|
21785
|
+
const label = `${s}x`;
|
|
21786
|
+
const isSpeedActive = playback.speed === s;
|
|
21787
|
+
const slotW = measureLegendText(label, LEGEND_ENTRY_FONT_SIZE) + SPEED_BADGE_H_PAD * 2;
|
|
21788
|
+
const badgeH = LEGEND_ENTRY_FONT_SIZE + SPEED_BADGE_V_PAD * 2;
|
|
21789
|
+
const badgeY = (LEGEND_HEIGHT - badgeH) / 2;
|
|
21790
|
+
const speedG = playbackEl.append("g").attr("data-playback-action", "set-speed").attr("data-playback-value", String(s)).style("cursor", "pointer");
|
|
21791
|
+
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");
|
|
21792
|
+
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);
|
|
21793
|
+
entryX += slotW + SPEED_BADGE_GAP;
|
|
21794
|
+
}
|
|
21045
21795
|
}
|
|
21046
21796
|
}
|
|
21047
21797
|
function renderInfra(container, layout, palette, isDark, title, titleLineNumber, tagGroups, activeGroup, animate, playback, expandedNodeIds, exportMode, collapsedNodes) {
|
|
@@ -21172,7 +21922,7 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
21172
21922
|
"viewBox",
|
|
21173
21923
|
`0 0 ${containerWidth} ${LEGEND_HEIGHT + LEGEND_FIXED_GAP3}`
|
|
21174
21924
|
).attr("preserveAspectRatio", "xMidYMid meet").style("display", "block").style("pointer-events", "none");
|
|
21175
|
-
|
|
21925
|
+
renderLegend3(
|
|
21176
21926
|
legendSvg,
|
|
21177
21927
|
legendGroups,
|
|
21178
21928
|
containerWidth,
|
|
@@ -21184,7 +21934,7 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
21184
21934
|
);
|
|
21185
21935
|
legendSvg.selectAll(".infra-legend-group").style("pointer-events", "auto");
|
|
21186
21936
|
} else {
|
|
21187
|
-
|
|
21937
|
+
renderLegend3(
|
|
21188
21938
|
rootSvg,
|
|
21189
21939
|
legendGroups,
|
|
21190
21940
|
totalWidth,
|
|
@@ -21216,6 +21966,7 @@ var init_renderer8 = __esm({
|
|
|
21216
21966
|
init_compute();
|
|
21217
21967
|
init_layout8();
|
|
21218
21968
|
init_legend_constants();
|
|
21969
|
+
init_legend_d3();
|
|
21219
21970
|
init_title_constants();
|
|
21220
21971
|
NODE_FONT_SIZE3 = 13;
|
|
21221
21972
|
META_FONT_SIZE5 = 10;
|
|
@@ -22843,7 +23594,7 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
22843
23594
|
const isActive = activeGroupName?.toLowerCase() === group.name.toLowerCase();
|
|
22844
23595
|
const isSwimlane = currentSwimlaneGroup?.toLowerCase() === group.name.toLowerCase();
|
|
22845
23596
|
const showIcon = !legendViewMode && tagGroups.length > 0;
|
|
22846
|
-
const iconReserve = showIcon ? LEGEND_ICON_W : 0;
|
|
23597
|
+
const iconReserve = showIcon && isActive ? LEGEND_ICON_W : 0;
|
|
22847
23598
|
const pillW = measureLegendText(group.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD + iconReserve;
|
|
22848
23599
|
let groupW = pillW;
|
|
22849
23600
|
if (isActive) {
|
|
@@ -22870,83 +23621,110 @@ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargi
|
|
|
22870
23621
|
const legendX = (containerWidth - totalW) / 2;
|
|
22871
23622
|
const legendRow = svg.append("g").attr("class", "gantt-tag-legend-container").attr("transform", `translate(${legendX}, ${legendY})`);
|
|
22872
23623
|
let cursorX = 0;
|
|
22873
|
-
|
|
22874
|
-
const group = visibleGroups[i];
|
|
22875
|
-
const isActive = activeGroupName?.toLowerCase() === group.name.toLowerCase();
|
|
22876
|
-
const isSwimlane = currentSwimlaneGroup?.toLowerCase() === group.name.toLowerCase();
|
|
23624
|
+
if (visibleGroups.length > 0) {
|
|
22877
23625
|
const showIcon = !legendViewMode && tagGroups.length > 0;
|
|
22878
23626
|
const iconReserve = showIcon ? LEGEND_ICON_W : 0;
|
|
22879
|
-
const
|
|
22880
|
-
|
|
22881
|
-
|
|
22882
|
-
|
|
22883
|
-
|
|
23627
|
+
const legendGroups = visibleGroups.map((g) => {
|
|
23628
|
+
const key = g.name.toLowerCase();
|
|
23629
|
+
const entries = filteredEntries.get(key) ?? g.entries;
|
|
23630
|
+
return {
|
|
23631
|
+
name: g.name,
|
|
23632
|
+
entries: entries.map((e) => ({ value: e.value, color: e.color }))
|
|
23633
|
+
};
|
|
22884
23634
|
});
|
|
22885
|
-
|
|
22886
|
-
|
|
22887
|
-
|
|
22888
|
-
|
|
22889
|
-
|
|
22890
|
-
|
|
22891
|
-
|
|
22892
|
-
|
|
22893
|
-
}
|
|
22894
|
-
const
|
|
22895
|
-
|
|
22896
|
-
|
|
22897
|
-
|
|
22898
|
-
|
|
22899
|
-
|
|
22900
|
-
|
|
22901
|
-
|
|
22902
|
-
|
|
22903
|
-
if (onSwimlaneChange) {
|
|
22904
|
-
onSwimlaneChange(
|
|
22905
|
-
currentSwimlaneGroup?.toLowerCase() === group.name.toLowerCase() ? null : group.name
|
|
22906
|
-
);
|
|
22907
|
-
}
|
|
22908
|
-
});
|
|
22909
|
-
}
|
|
22910
|
-
if (isActive) {
|
|
22911
|
-
const tagKey = group.name.toLowerCase();
|
|
22912
|
-
const entries = filteredEntries.get(tagKey) ?? group.entries;
|
|
22913
|
-
let ex = pillXOff + pillW + LEGEND_CAPSULE_PAD + 4;
|
|
22914
|
-
for (const entry of entries) {
|
|
22915
|
-
const entryValue = entry.value.toLowerCase();
|
|
22916
|
-
const entryG = gEl.append("g").attr("class", "gantt-legend-entry").attr("data-line-number", String(entry.lineNumber)).style("cursor", "pointer");
|
|
22917
|
-
entryG.append("circle").attr("cx", ex + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
22918
|
-
entryG.append("text").attr("x", ex + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 2).attr("text-anchor", "start").attr("font-size", `${LEGEND_ENTRY_FONT_SIZE}px`).attr("fill", palette.textMuted).text(entry.value);
|
|
22919
|
-
entryG.on("mouseenter", () => {
|
|
23635
|
+
const legendConfig = {
|
|
23636
|
+
groups: legendGroups,
|
|
23637
|
+
position: {
|
|
23638
|
+
placement: "top-center",
|
|
23639
|
+
titleRelation: "below-title"
|
|
23640
|
+
},
|
|
23641
|
+
mode: "fixed",
|
|
23642
|
+
capsulePillAddonWidth: iconReserve
|
|
23643
|
+
};
|
|
23644
|
+
const legendState = { activeGroup: activeGroupName };
|
|
23645
|
+
const tagGroupsW = visibleGroups.reduce((s, _, i) => s + groupWidths[i], 0) + Math.max(0, (visibleGroups.length - 1) * LEGEND_GROUP_GAP);
|
|
23646
|
+
const tagGroupG = legendRow.append("g");
|
|
23647
|
+
const legendCallbacks = {
|
|
23648
|
+
onGroupToggle: onToggle,
|
|
23649
|
+
onEntryHover: (groupName, entryValue) => {
|
|
23650
|
+
const tagKey = groupName.toLowerCase();
|
|
23651
|
+
if (entryValue) {
|
|
23652
|
+
const ev = entryValue.toLowerCase();
|
|
22920
23653
|
chartG.selectAll(".gantt-task").each(function() {
|
|
22921
23654
|
const el = d3Selection10.select(this);
|
|
22922
|
-
|
|
22923
|
-
|
|
23655
|
+
el.attr(
|
|
23656
|
+
"opacity",
|
|
23657
|
+
el.attr(`data-tag-${tagKey}`) === ev ? 1 : FADE_OPACITY
|
|
23658
|
+
);
|
|
22924
23659
|
});
|
|
22925
23660
|
chartG.selectAll(".gantt-milestone").attr("opacity", FADE_OPACITY);
|
|
22926
23661
|
chartG.selectAll(".gantt-group-bar, .gantt-group-summary").attr("opacity", FADE_OPACITY);
|
|
22927
23662
|
svg.selectAll(".gantt-task-label").each(function() {
|
|
22928
23663
|
const el = d3Selection10.select(this);
|
|
22929
|
-
|
|
22930
|
-
|
|
23664
|
+
el.attr(
|
|
23665
|
+
"opacity",
|
|
23666
|
+
el.attr(`data-tag-${tagKey}`) === ev ? 1 : FADE_OPACITY
|
|
23667
|
+
);
|
|
22931
23668
|
});
|
|
22932
23669
|
svg.selectAll(".gantt-group-label").attr("opacity", FADE_OPACITY);
|
|
22933
23670
|
svg.selectAll(".gantt-lane-header").each(function() {
|
|
22934
23671
|
const el = d3Selection10.select(this);
|
|
22935
|
-
|
|
22936
|
-
|
|
23672
|
+
el.attr(
|
|
23673
|
+
"opacity",
|
|
23674
|
+
el.attr(`data-tag-${tagKey}`) === ev ? 1 : FADE_OPACITY
|
|
23675
|
+
);
|
|
22937
23676
|
});
|
|
22938
23677
|
chartG.selectAll(".gantt-lane-band, .gantt-lane-accent").attr("opacity", FADE_OPACITY);
|
|
22939
|
-
}
|
|
23678
|
+
} else {
|
|
22940
23679
|
if (criticalPathActive) {
|
|
22941
23680
|
applyCriticalPathHighlight(svg, chartG);
|
|
22942
23681
|
} else {
|
|
22943
23682
|
resetHighlightAll(svg, chartG);
|
|
22944
23683
|
}
|
|
22945
|
-
}
|
|
22946
|
-
|
|
23684
|
+
}
|
|
23685
|
+
},
|
|
23686
|
+
onGroupRendered: (groupName, groupEl, _isActive) => {
|
|
23687
|
+
const group = visibleGroups.find((g) => g.name === groupName);
|
|
23688
|
+
if (group) {
|
|
23689
|
+
groupEl.attr("data-tag-group", group.name).attr("data-line-number", String(group.lineNumber));
|
|
23690
|
+
}
|
|
23691
|
+
if (showIcon && _isActive) {
|
|
23692
|
+
const isSwimlane = currentSwimlaneGroup?.toLowerCase() === groupName.toLowerCase();
|
|
23693
|
+
const textW = measureLegendText(groupName, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
23694
|
+
const pillXOff = LEGEND_CAPSULE_PAD;
|
|
23695
|
+
const iconX = pillXOff + textW + 3;
|
|
23696
|
+
const iconY = (LEGEND_HEIGHT - 10) / 2;
|
|
23697
|
+
const iconEl = drawSwimlaneIcon(
|
|
23698
|
+
groupEl,
|
|
23699
|
+
iconX,
|
|
23700
|
+
iconY,
|
|
23701
|
+
isSwimlane,
|
|
23702
|
+
palette
|
|
23703
|
+
);
|
|
23704
|
+
iconEl.append("title").text(`Group by ${groupName}`);
|
|
23705
|
+
iconEl.style("cursor", "pointer").on("click", (event) => {
|
|
23706
|
+
event.stopPropagation();
|
|
23707
|
+
if (onSwimlaneChange) {
|
|
23708
|
+
onSwimlaneChange(
|
|
23709
|
+
currentSwimlaneGroup?.toLowerCase() === groupName.toLowerCase() ? null : groupName
|
|
23710
|
+
);
|
|
23711
|
+
}
|
|
23712
|
+
});
|
|
23713
|
+
}
|
|
22947
23714
|
}
|
|
23715
|
+
};
|
|
23716
|
+
renderLegendD3(
|
|
23717
|
+
tagGroupG,
|
|
23718
|
+
legendConfig,
|
|
23719
|
+
legendState,
|
|
23720
|
+
palette,
|
|
23721
|
+
isDark,
|
|
23722
|
+
legendCallbacks,
|
|
23723
|
+
tagGroupsW
|
|
23724
|
+
);
|
|
23725
|
+
for (let i = 0; i < visibleGroups.length; i++) {
|
|
23726
|
+
cursorX += groupWidths[i] + LEGEND_GROUP_GAP;
|
|
22948
23727
|
}
|
|
22949
|
-
cursorX += groupW + LEGEND_GROUP_GAP;
|
|
22950
23728
|
}
|
|
22951
23729
|
if (hasCriticalPath) {
|
|
22952
23730
|
const cpLineNum = optionLineNumbers["critical-path"];
|
|
@@ -23573,6 +24351,7 @@ var init_renderer9 = __esm({
|
|
|
23573
24351
|
init_tag_groups();
|
|
23574
24352
|
init_d3();
|
|
23575
24353
|
init_legend_constants();
|
|
24354
|
+
init_legend_d3();
|
|
23576
24355
|
init_title_constants();
|
|
23577
24356
|
BAR_H = 22;
|
|
23578
24357
|
ROW_GAP = 6;
|
|
@@ -24743,57 +25522,29 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
24743
25522
|
}
|
|
24744
25523
|
if (parsed.tagGroups.length > 0) {
|
|
24745
25524
|
const legendY = TOP_MARGIN + titleOffset;
|
|
24746
|
-
const
|
|
24747
|
-
|
|
24748
|
-
|
|
24749
|
-
if (tg.entries.length === 0) continue;
|
|
24750
|
-
const isActive = !!activeTagGroup && tg.name.toLowerCase() === activeTagGroup.toLowerCase();
|
|
24751
|
-
const pillWidth2 = measureLegendText(tg.name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
24752
|
-
const entries = tg.entries.map((e) => ({
|
|
25525
|
+
const resolvedGroups = parsed.tagGroups.filter((tg) => tg.entries.length > 0).map((tg) => ({
|
|
25526
|
+
name: tg.name,
|
|
25527
|
+
entries: tg.entries.map((e) => ({
|
|
24753
25528
|
value: e.value,
|
|
24754
25529
|
color: resolveColor(e.color) ?? e.color
|
|
24755
|
-
}))
|
|
24756
|
-
|
|
24757
|
-
|
|
24758
|
-
|
|
24759
|
-
|
|
24760
|
-
|
|
24761
|
-
|
|
24762
|
-
|
|
24763
|
-
|
|
24764
|
-
|
|
24765
|
-
|
|
24766
|
-
|
|
24767
|
-
|
|
24768
|
-
|
|
24769
|
-
|
|
24770
|
-
|
|
24771
|
-
|
|
24772
|
-
|
|
24773
|
-
const gEl = legendContainer.append("g").attr("transform", `translate(${legendX}, ${legendY})`).attr("class", "sequence-legend-group").attr("data-legend-group", item.group.name.toLowerCase()).style("cursor", "pointer");
|
|
24774
|
-
if (item.isActive) {
|
|
24775
|
-
gEl.append("rect").attr("width", item.totalWidth).attr("height", LEGEND_HEIGHT).attr("rx", LEGEND_HEIGHT / 2).attr("fill", groupBg);
|
|
24776
|
-
}
|
|
24777
|
-
const pillXOff = item.isActive ? LEGEND_CAPSULE_PAD : 0;
|
|
24778
|
-
const pillYOff = LEGEND_CAPSULE_PAD;
|
|
24779
|
-
const pillH = LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2;
|
|
24780
|
-
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", item.pillWidth).attr("height", pillH).attr("rx", pillH / 2).attr("fill", item.isActive ? palette.bg : groupBg);
|
|
24781
|
-
if (item.isActive) {
|
|
24782
|
-
gEl.append("rect").attr("x", pillXOff).attr("y", pillYOff).attr("width", item.pillWidth).attr("height", pillH).attr("rx", pillH / 2).attr("fill", "none").attr("stroke", mix(palette.textMuted, palette.bg, 50)).attr("stroke-width", 0.75);
|
|
24783
|
-
}
|
|
24784
|
-
gEl.append("text").attr("x", pillXOff + item.pillWidth / 2).attr("y", LEGEND_HEIGHT / 2 + LEGEND_PILL_FONT_SIZE / 2 - 2).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", "500").attr("fill", item.isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(item.group.name);
|
|
24785
|
-
if (item.isActive) {
|
|
24786
|
-
let entryX = pillXOff + item.pillWidth + 4;
|
|
24787
|
-
for (const entry of item.entries) {
|
|
24788
|
-
const entryG = gEl.append("g").attr("data-legend-entry", entry.value.toLowerCase()).style("cursor", "pointer");
|
|
24789
|
-
entryG.append("circle").attr("cx", entryX + LEGEND_DOT_R).attr("cy", LEGEND_HEIGHT / 2).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
24790
|
-
const textX = entryX + LEGEND_DOT_R * 2 + LEGEND_ENTRY_DOT_GAP;
|
|
24791
|
-
entryG.append("text").attr("x", textX).attr("y", LEGEND_HEIGHT / 2 + LEGEND_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).text(entry.value);
|
|
24792
|
-
entryX = textX + measureLegendText(entry.value, LEGEND_ENTRY_FONT_SIZE) + LEGEND_ENTRY_TRAIL;
|
|
24793
|
-
}
|
|
24794
|
-
}
|
|
24795
|
-
legendX += item.totalWidth + LEGEND_GROUP_GAP;
|
|
24796
|
-
}
|
|
25530
|
+
}))
|
|
25531
|
+
}));
|
|
25532
|
+
const legendConfig = {
|
|
25533
|
+
groups: resolvedGroups,
|
|
25534
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
25535
|
+
mode: "fixed"
|
|
25536
|
+
};
|
|
25537
|
+
const legendState = { activeGroup: activeTagGroup ?? null };
|
|
25538
|
+
const legendG = svg.append("g").attr("class", "sequence-legend").attr("transform", `translate(0,${legendY})`);
|
|
25539
|
+
renderLegendD3(
|
|
25540
|
+
legendG,
|
|
25541
|
+
legendConfig,
|
|
25542
|
+
legendState,
|
|
25543
|
+
palette,
|
|
25544
|
+
isDark,
|
|
25545
|
+
void 0,
|
|
25546
|
+
svgWidth
|
|
25547
|
+
);
|
|
24797
25548
|
}
|
|
24798
25549
|
for (const group of groups) {
|
|
24799
25550
|
if (group.participantIds.length === 0) continue;
|
|
@@ -24870,7 +25621,8 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
24870
25621
|
for (const branch of el.elseIfBranches) {
|
|
24871
25622
|
elseIfBranchData.push({
|
|
24872
25623
|
label: branch.label,
|
|
24873
|
-
indices: collectMsgIndices(branch.children)
|
|
25624
|
+
indices: collectMsgIndices(branch.children),
|
|
25625
|
+
lineNumber: branch.lineNumber
|
|
24874
25626
|
});
|
|
24875
25627
|
}
|
|
24876
25628
|
}
|
|
@@ -24931,14 +25683,16 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
24931
25683
|
x1: frameX,
|
|
24932
25684
|
y1: dividerY,
|
|
24933
25685
|
x2: frameX + frameW,
|
|
24934
|
-
y2: dividerY
|
|
25686
|
+
y2: dividerY,
|
|
25687
|
+
blockLine: branchData.lineNumber
|
|
24935
25688
|
});
|
|
24936
25689
|
deferredLabels.push({
|
|
24937
25690
|
x: frameX + 6,
|
|
24938
25691
|
y: dividerY + 14,
|
|
24939
25692
|
text: `else if ${branchData.label}`,
|
|
24940
25693
|
bold: false,
|
|
24941
|
-
italic: true
|
|
25694
|
+
italic: true,
|
|
25695
|
+
blockLine: branchData.lineNumber
|
|
24942
25696
|
});
|
|
24943
25697
|
}
|
|
24944
25698
|
}
|
|
@@ -24956,14 +25710,16 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
24956
25710
|
x1: frameX,
|
|
24957
25711
|
y1: dividerY,
|
|
24958
25712
|
x2: frameX + frameW,
|
|
24959
|
-
y2: dividerY
|
|
25713
|
+
y2: dividerY,
|
|
25714
|
+
blockLine: el.elseLineNumber
|
|
24960
25715
|
});
|
|
24961
25716
|
deferredLabels.push({
|
|
24962
25717
|
x: frameX + 6,
|
|
24963
25718
|
y: dividerY + 14,
|
|
24964
25719
|
text: "else",
|
|
24965
25720
|
bold: false,
|
|
24966
|
-
italic: true
|
|
25721
|
+
italic: true,
|
|
25722
|
+
blockLine: el.elseLineNumber
|
|
24967
25723
|
});
|
|
24968
25724
|
}
|
|
24969
25725
|
}
|
|
@@ -25009,7 +25765,9 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
25009
25765
|
}
|
|
25010
25766
|
});
|
|
25011
25767
|
for (const ln of deferredLines) {
|
|
25012
|
-
svg.append("line").attr("x1", ln.x1).attr("y1", ln.y1).attr("x2", ln.x2).attr("y2", ln.y2).attr("stroke", palette.textMuted).attr("stroke-width", 1).attr("stroke-dasharray", "2 3");
|
|
25768
|
+
const line10 = svg.append("line").attr("x1", ln.x1).attr("y1", ln.y1).attr("x2", ln.x2).attr("y2", ln.y2).attr("stroke", palette.textMuted).attr("stroke-width", 1).attr("stroke-dasharray", "2 3").attr("class", "block-divider");
|
|
25769
|
+
if (ln.blockLine !== void 0)
|
|
25770
|
+
line10.attr("data-block-line", String(ln.blockLine));
|
|
25013
25771
|
}
|
|
25014
25772
|
for (const lbl of deferredLabels) {
|
|
25015
25773
|
const t = svg.append("text").attr("x", lbl.x).attr("y", lbl.y).attr("fill", palette.text).attr("font-size", 11).attr("class", "block-label").text(lbl.text);
|
|
@@ -25352,6 +26110,7 @@ var init_renderer10 = __esm({
|
|
|
25352
26110
|
init_parser();
|
|
25353
26111
|
init_tag_resolution();
|
|
25354
26112
|
init_legend_constants();
|
|
26113
|
+
init_legend_d3();
|
|
25355
26114
|
init_title_constants();
|
|
25356
26115
|
PARTICIPANT_GAP = 160;
|
|
25357
26116
|
PARTICIPANT_BOX_WIDTH = 120;
|
|
@@ -27832,7 +28591,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
27832
28591
|
}
|
|
27833
28592
|
evG.append("rect").attr("x", x).attr("y", y - BAR_H2 / 2).attr("width", rectW).attr("height", BAR_H2).attr("rx", 4).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", 2);
|
|
27834
28593
|
if (labelFitsInside) {
|
|
27835
|
-
evG.append("text").attr("x", x + 8).attr("y", y).attr("dy", "0.35em").attr("text-anchor", "start").attr("fill", textColor).attr("font-size", "
|
|
28594
|
+
evG.append("text").attr("x", x + 8).attr("y", y).attr("dy", "0.35em").attr("text-anchor", "start").attr("fill", textColor).attr("font-size", "13px").text(ev.label);
|
|
27836
28595
|
} else {
|
|
27837
28596
|
const wouldFlipLeft = x + rectW > innerWidth * 0.6;
|
|
27838
28597
|
const labelFitsLeft = x - 6 - estLabelWidth > 0;
|
|
@@ -27986,7 +28745,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
27986
28745
|
}
|
|
27987
28746
|
evG.append("rect").attr("x", x).attr("y", y - BAR_H2 / 2).attr("width", rectW).attr("height", BAR_H2).attr("rx", 4).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", 2);
|
|
27988
28747
|
if (labelFitsInside) {
|
|
27989
|
-
evG.append("text").attr("x", x + 8).attr("y", y).attr("dy", "0.35em").attr("text-anchor", "start").attr("fill", textColor).attr("font-size", "
|
|
28748
|
+
evG.append("text").attr("x", x + 8).attr("y", y).attr("dy", "0.35em").attr("text-anchor", "start").attr("fill", textColor).attr("font-size", "13px").text(ev.label);
|
|
27990
28749
|
} else {
|
|
27991
28750
|
const wouldFlipLeft = x + rectW > innerWidth * 0.6;
|
|
27992
28751
|
const labelFitsLeft = x - 6 - estLabelWidth > 0;
|
|
@@ -28012,7 +28771,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28012
28771
|
const LG_ENTRY_FONT_SIZE = LEGEND_ENTRY_FONT_SIZE;
|
|
28013
28772
|
const LG_ENTRY_DOT_GAP = LEGEND_ENTRY_DOT_GAP;
|
|
28014
28773
|
const LG_ENTRY_TRAIL = LEGEND_ENTRY_TRAIL;
|
|
28015
|
-
const LG_GROUP_GAP = LEGEND_GROUP_GAP;
|
|
28016
28774
|
const LG_ICON_W = 20;
|
|
28017
28775
|
const mainSvg = d3Selection13.select(container).select("svg");
|
|
28018
28776
|
const mainG = mainSvg.select("g");
|
|
@@ -28051,11 +28809,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28051
28809
|
(lg) => effectiveColorKey != null && lg.group.name.toLowerCase() === effectiveColorKey
|
|
28052
28810
|
) : legendGroups;
|
|
28053
28811
|
if (visibleGroups.length === 0) return;
|
|
28054
|
-
const totalW = visibleGroups.reduce((s, lg) => {
|
|
28055
|
-
const isActive = viewMode || currentActiveGroup != null && lg.group.name.toLowerCase() === currentActiveGroup.toLowerCase();
|
|
28056
|
-
return s + (isActive ? lg.expandedWidth : lg.minifiedWidth);
|
|
28057
|
-
}, 0) + (visibleGroups.length - 1) * LG_GROUP_GAP;
|
|
28058
|
-
let cx = (width - totalW) / 2;
|
|
28059
28812
|
const legendContainer = mainSvg.append("g").attr("class", "tl-tag-legend-container");
|
|
28060
28813
|
if (currentActiveGroup) {
|
|
28061
28814
|
legendContainer.attr(
|
|
@@ -28063,82 +28816,85 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28063
28816
|
currentActiveGroup.toLowerCase()
|
|
28064
28817
|
);
|
|
28065
28818
|
}
|
|
28066
|
-
|
|
28067
|
-
|
|
28068
|
-
|
|
28069
|
-
|
|
28070
|
-
|
|
28071
|
-
|
|
28072
|
-
|
|
28073
|
-
|
|
28074
|
-
|
|
28075
|
-
|
|
28076
|
-
|
|
28077
|
-
|
|
28078
|
-
|
|
28079
|
-
|
|
28080
|
-
|
|
28081
|
-
|
|
28082
|
-
|
|
28083
|
-
|
|
28084
|
-
|
|
28085
|
-
|
|
28086
|
-
|
|
28087
|
-
|
|
28088
|
-
|
|
28089
|
-
|
|
28090
|
-
|
|
28091
|
-
|
|
28092
|
-
|
|
28093
|
-
|
|
28094
|
-
|
|
28095
|
-
|
|
28819
|
+
const iconAddon = viewMode ? 0 : LG_ICON_W;
|
|
28820
|
+
const centralGroups = visibleGroups.map((lg) => ({
|
|
28821
|
+
name: lg.group.name,
|
|
28822
|
+
entries: lg.group.entries.map((e) => ({
|
|
28823
|
+
value: e.value,
|
|
28824
|
+
color: e.color
|
|
28825
|
+
}))
|
|
28826
|
+
}));
|
|
28827
|
+
const centralActive = viewMode ? effectiveColorKey : currentActiveGroup;
|
|
28828
|
+
const centralConfig = {
|
|
28829
|
+
groups: centralGroups,
|
|
28830
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
28831
|
+
mode: "fixed",
|
|
28832
|
+
capsulePillAddonWidth: iconAddon
|
|
28833
|
+
};
|
|
28834
|
+
const centralState = { activeGroup: centralActive };
|
|
28835
|
+
const centralCallbacks = viewMode ? {} : {
|
|
28836
|
+
onGroupToggle: (groupName) => {
|
|
28837
|
+
currentActiveGroup = currentActiveGroup === groupName.toLowerCase() ? null : groupName.toLowerCase();
|
|
28838
|
+
drawLegend2();
|
|
28839
|
+
recolorEvents2();
|
|
28840
|
+
onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
|
|
28841
|
+
},
|
|
28842
|
+
onEntryHover: (groupName, entryValue) => {
|
|
28843
|
+
const tagKey = groupName.toLowerCase();
|
|
28844
|
+
if (entryValue) {
|
|
28845
|
+
const tagVal = entryValue.toLowerCase();
|
|
28846
|
+
fadeToTagValue(mainG, tagKey, tagVal);
|
|
28847
|
+
mainSvg.selectAll("[data-legend-entry]").each(function() {
|
|
28848
|
+
const el = d3Selection13.select(this);
|
|
28849
|
+
const ev = el.attr("data-legend-entry");
|
|
28850
|
+
const eg = el.attr("data-tag-group") ?? el.node()?.closest?.("[data-tag-group]")?.getAttribute("data-tag-group");
|
|
28851
|
+
el.attr(
|
|
28852
|
+
"opacity",
|
|
28853
|
+
eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY2
|
|
28854
|
+
);
|
|
28855
|
+
});
|
|
28856
|
+
} else {
|
|
28857
|
+
fadeReset(mainG);
|
|
28858
|
+
mainSvg.selectAll("[data-legend-entry]").attr("opacity", 1);
|
|
28859
|
+
}
|
|
28860
|
+
},
|
|
28861
|
+
onGroupRendered: (groupName, groupEl, isActive) => {
|
|
28862
|
+
const groupKey = groupName.toLowerCase();
|
|
28863
|
+
groupEl.attr("data-tag-group", groupKey);
|
|
28864
|
+
if (isActive && !viewMode) {
|
|
28865
|
+
const isSwimActive = currentSwimlaneGroup != null && currentSwimlaneGroup.toLowerCase() === groupKey;
|
|
28866
|
+
const pillWidth3 = measureLegendText(groupName, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
|
|
28867
|
+
const pillXOff = LG_CAPSULE_PAD;
|
|
28868
|
+
const iconX = pillXOff + pillWidth3 + 5;
|
|
28096
28869
|
const iconY = (LG_HEIGHT - 10) / 2;
|
|
28097
|
-
const iconEl = drawSwimlaneIcon3(
|
|
28870
|
+
const iconEl = drawSwimlaneIcon3(
|
|
28871
|
+
groupEl,
|
|
28872
|
+
iconX,
|
|
28873
|
+
iconY,
|
|
28874
|
+
isSwimActive
|
|
28875
|
+
);
|
|
28098
28876
|
iconEl.attr("data-swimlane-toggle", groupKey).on("click", (event) => {
|
|
28099
28877
|
event.stopPropagation();
|
|
28100
28878
|
currentSwimlaneGroup = currentSwimlaneGroup === groupKey ? null : groupKey;
|
|
28101
|
-
onTagStateChange?.(
|
|
28879
|
+
onTagStateChange?.(
|
|
28880
|
+
currentActiveGroup,
|
|
28881
|
+
currentSwimlaneGroup
|
|
28882
|
+
);
|
|
28102
28883
|
relayout2();
|
|
28103
28884
|
});
|
|
28104
|
-
entryX = pillXOff + pillWidth2 + LG_ICON_W + 4;
|
|
28105
|
-
} else {
|
|
28106
|
-
entryX = pillXOff + pillWidth2 + 8;
|
|
28107
|
-
}
|
|
28108
|
-
for (const entry of lg.group.entries) {
|
|
28109
|
-
const tagKey = lg.group.name.toLowerCase();
|
|
28110
|
-
const tagVal = entry.value.toLowerCase();
|
|
28111
|
-
const entryG = gEl.append("g").attr("class", "tl-tag-legend-entry").attr("data-tag-group", tagKey).attr("data-legend-entry", tagVal);
|
|
28112
|
-
if (!viewMode) {
|
|
28113
|
-
entryG.style("cursor", "pointer").on("mouseenter", (event) => {
|
|
28114
|
-
event.stopPropagation();
|
|
28115
|
-
fadeToTagValue(mainG, tagKey, tagVal);
|
|
28116
|
-
mainSvg.selectAll(".tl-tag-legend-entry").each(function() {
|
|
28117
|
-
const el = d3Selection13.select(this);
|
|
28118
|
-
const ev = el.attr("data-legend-entry");
|
|
28119
|
-
if (ev === "__group__") return;
|
|
28120
|
-
const eg = el.attr("data-tag-group");
|
|
28121
|
-
el.attr(
|
|
28122
|
-
"opacity",
|
|
28123
|
-
eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY2
|
|
28124
|
-
);
|
|
28125
|
-
});
|
|
28126
|
-
}).on("mouseleave", (event) => {
|
|
28127
|
-
event.stopPropagation();
|
|
28128
|
-
fadeReset(mainG);
|
|
28129
|
-
mainSvg.selectAll(".tl-tag-legend-entry").attr("opacity", 1);
|
|
28130
|
-
}).on("click", (event) => {
|
|
28131
|
-
event.stopPropagation();
|
|
28132
|
-
});
|
|
28133
|
-
}
|
|
28134
|
-
entryG.append("circle").attr("cx", entryX + LG_DOT_R).attr("cy", LG_HEIGHT / 2).attr("r", LG_DOT_R).attr("fill", entry.color);
|
|
28135
|
-
const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
|
|
28136
|
-
entryG.append("text").attr("x", textX).attr("y", LG_HEIGHT / 2 + LG_ENTRY_FONT_SIZE / 2 - 1).attr("font-size", LG_ENTRY_FONT_SIZE).attr("font-family", FONT_FAMILY).attr("fill", palette.textMuted).text(entry.value);
|
|
28137
|
-
entryX = textX + measureLegendText(entry.value, LG_ENTRY_FONT_SIZE) + LG_ENTRY_TRAIL;
|
|
28138
28885
|
}
|
|
28139
28886
|
}
|
|
28140
|
-
|
|
28141
|
-
}
|
|
28887
|
+
};
|
|
28888
|
+
const legendInnerG = legendContainer.append("g").attr("transform", `translate(0, ${legendY})`);
|
|
28889
|
+
renderLegendD3(
|
|
28890
|
+
legendInnerG,
|
|
28891
|
+
centralConfig,
|
|
28892
|
+
centralState,
|
|
28893
|
+
palette,
|
|
28894
|
+
isDark,
|
|
28895
|
+
centralCallbacks,
|
|
28896
|
+
width
|
|
28897
|
+
);
|
|
28142
28898
|
}, recolorEvents2 = function() {
|
|
28143
28899
|
const colorTG = currentActiveGroup ?? swimlaneTagGroup ?? null;
|
|
28144
28900
|
mainG.selectAll(".tl-event").each(function() {
|
|
@@ -28163,7 +28919,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28163
28919
|
};
|
|
28164
28920
|
var drawSwimlaneIcon2 = drawSwimlaneIcon3, relayout = relayout2, drawLegend = drawLegend2, recolorEvents = recolorEvents2;
|
|
28165
28921
|
const legendY = title ? 50 : 10;
|
|
28166
|
-
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
28167
28922
|
const legendGroups = parsed.timelineTagGroups.map((g) => {
|
|
28168
28923
|
const pillW = measureLegendText(g.name, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
|
|
28169
28924
|
const iconSpace = viewMode ? 8 : LG_ICON_W + 4;
|
|
@@ -28358,7 +29113,7 @@ function regionCentroid(circles, inside) {
|
|
|
28358
29113
|
}
|
|
28359
29114
|
function renderVenn(container, parsed, palette, isDark, onClickItem, exportDims) {
|
|
28360
29115
|
const { vennSets, vennOverlaps, title } = parsed;
|
|
28361
|
-
if (vennSets.length < 2) return;
|
|
29116
|
+
if (vennSets.length < 2 || vennSets.length > 3) return;
|
|
28362
29117
|
const init2 = initD3Chart(container, palette, exportDims);
|
|
28363
29118
|
if (!init2) return;
|
|
28364
29119
|
const { svg, width, height, textColor, colors } = init2;
|
|
@@ -28414,7 +29169,9 @@ function renderVenn(container, parsed, palette, isDark, onClickItem, exportDims)
|
|
|
28414
29169
|
marginBottom
|
|
28415
29170
|
).map((c) => ({ ...c, y: c.y + titleHeight }));
|
|
28416
29171
|
const scaledR = circles[0].r;
|
|
28417
|
-
svg.append("style").text(
|
|
29172
|
+
svg.append("style").text(
|
|
29173
|
+
"circle:focus, circle:focus-visible { outline-solid: none !important; }"
|
|
29174
|
+
);
|
|
28418
29175
|
renderChartTitle(
|
|
28419
29176
|
svg,
|
|
28420
29177
|
title,
|
|
@@ -28596,7 +29353,7 @@ function renderVenn(container, parsed, palette, isDark, onClickItem, exportDims)
|
|
|
28596
29353
|
}
|
|
28597
29354
|
const hoverGroup = svg.append("g");
|
|
28598
29355
|
circles.forEach((c, i) => {
|
|
28599
|
-
hoverGroup.append("circle").attr("cx", c.x).attr("cy", c.y).attr("r", c.r).attr("fill", "transparent").attr("stroke", "none").attr("class", "venn-hit-target").attr("data-line-number", String(vennSets[i].lineNumber)).style("cursor", onClickItem ? "pointer" : "default").style("outline", "none").on("mouseenter", () => {
|
|
29356
|
+
hoverGroup.append("circle").attr("cx", c.x).attr("cy", c.y).attr("r", c.r).attr("fill", "transparent").attr("stroke", "none").attr("class", "venn-hit-target").attr("data-line-number", String(vennSets[i].lineNumber)).style("cursor", onClickItem ? "pointer" : "default").style("outline-solid", "none").on("mouseenter", () => {
|
|
28600
29357
|
showRegionOverlay([i]);
|
|
28601
29358
|
}).on("mouseleave", () => {
|
|
28602
29359
|
hideAllOverlays();
|
|
@@ -28634,7 +29391,7 @@ function renderVenn(container, parsed, palette, isDark, onClickItem, exportDims)
|
|
|
28634
29391
|
const declaredOv = vennOverlaps.find(
|
|
28635
29392
|
(ov) => ov.sets.length === sets.length && ov.sets.every((s, k) => s === sets[k])
|
|
28636
29393
|
);
|
|
28637
|
-
hoverGroup.append("circle").attr("cx", centroid.x).attr("cy", centroid.y).attr("r", overlayR).attr("fill", "transparent").attr("stroke", "none").attr("class", "venn-hit-target").attr("data-line-number", declaredOv ? String(declaredOv.lineNumber) : "").style("cursor", onClickItem && declaredOv ? "pointer" : "default").style("outline", "none").on("mouseenter", () => {
|
|
29394
|
+
hoverGroup.append("circle").attr("cx", centroid.x).attr("cy", centroid.y).attr("r", overlayR).attr("fill", "transparent").attr("stroke", "none").attr("class", "venn-hit-target").attr("data-line-number", declaredOv ? String(declaredOv.lineNumber) : "").style("cursor", onClickItem && declaredOv ? "pointer" : "default").style("outline-solid", "none").on("mouseenter", () => {
|
|
28638
29395
|
showRegionOverlay(idxs);
|
|
28639
29396
|
}).on("mouseleave", () => {
|
|
28640
29397
|
hideAllOverlays();
|
|
@@ -28768,8 +29525,8 @@ function renderQuadrant(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28768
29525
|
const LABEL_MAX_FONT = 48;
|
|
28769
29526
|
const LABEL_MIN_FONT = 14;
|
|
28770
29527
|
const LABEL_PAD2 = 40;
|
|
28771
|
-
const
|
|
28772
|
-
const estTextWidth = (text, fontSize) => text.length * fontSize *
|
|
29528
|
+
const CHAR_WIDTH_RATIO3 = 0.6;
|
|
29529
|
+
const estTextWidth = (text, fontSize) => text.length * fontSize * CHAR_WIDTH_RATIO3;
|
|
28773
29530
|
const quadrantLabelLayout = (text, qw2, qh2) => {
|
|
28774
29531
|
const availW = qw2 - LABEL_PAD2;
|
|
28775
29532
|
const availH = qh2 - LABEL_PAD2;
|
|
@@ -28913,16 +29670,45 @@ function renderQuadrant(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28913
29670
|
if (x < 0.5 && y < 0.5) return "bottom-left";
|
|
28914
29671
|
return "bottom-right";
|
|
28915
29672
|
};
|
|
29673
|
+
const POINT_RADIUS = 6;
|
|
29674
|
+
const POINT_LABEL_FONT_SIZE = 12;
|
|
29675
|
+
const quadrantLabelObstacles = quadrantDefsWithLabel.map((d) => {
|
|
29676
|
+
const layout = labelLayouts.get(d.label.text);
|
|
29677
|
+
const totalW = Math.max(...layout.lines.map((l) => l.length)) * layout.fontSize * CHAR_WIDTH_RATIO3;
|
|
29678
|
+
const totalH = layout.lines.length * layout.fontSize * 1.2;
|
|
29679
|
+
return {
|
|
29680
|
+
x: d.labelX - totalW / 2,
|
|
29681
|
+
y: d.labelY - totalH / 2,
|
|
29682
|
+
w: totalW,
|
|
29683
|
+
h: totalH
|
|
29684
|
+
};
|
|
29685
|
+
});
|
|
29686
|
+
const pointPixels = quadrantPoints.map((point) => ({
|
|
29687
|
+
label: point.label,
|
|
29688
|
+
cx: xScale(point.x),
|
|
29689
|
+
cy: yScale(point.y)
|
|
29690
|
+
}));
|
|
29691
|
+
const placedPointLabels = computeQuadrantPointLabels(
|
|
29692
|
+
pointPixels,
|
|
29693
|
+
{ left: 0, top: 0, right: chartWidth, bottom: chartHeight },
|
|
29694
|
+
quadrantLabelObstacles,
|
|
29695
|
+
POINT_RADIUS,
|
|
29696
|
+
POINT_LABEL_FONT_SIZE
|
|
29697
|
+
);
|
|
28916
29698
|
const pointsG = chartG.append("g").attr("class", "points");
|
|
28917
|
-
quadrantPoints.forEach((point) => {
|
|
29699
|
+
quadrantPoints.forEach((point, i) => {
|
|
28918
29700
|
const cx = xScale(point.x);
|
|
28919
29701
|
const cy = yScale(point.y);
|
|
28920
29702
|
const quadrant = getPointQuadrant(point.x, point.y);
|
|
28921
29703
|
const quadDef = quadrantDefs.find((d) => d.position === quadrant);
|
|
28922
29704
|
const pointColor = quadDef?.label?.color ?? defaultColors[quadDef?.colorIdx ?? 0];
|
|
29705
|
+
const placed = placedPointLabels[i];
|
|
28923
29706
|
const pointG = pointsG.append("g").attr("class", "point-group").attr("data-line-number", String(point.lineNumber));
|
|
28924
|
-
|
|
28925
|
-
|
|
29707
|
+
if (placed.connectorLine) {
|
|
29708
|
+
pointG.append("line").attr("x1", placed.connectorLine.x1).attr("y1", placed.connectorLine.y1).attr("x2", placed.connectorLine.x2).attr("y2", placed.connectorLine.y2).attr("stroke", pointColor).attr("stroke-width", 1).attr("opacity", 0.5);
|
|
29709
|
+
}
|
|
29710
|
+
pointG.append("circle").attr("cx", cx).attr("cy", cy).attr("r", POINT_RADIUS).attr("fill", "#ffffff").attr("stroke", pointColor).attr("stroke-width", 2);
|
|
29711
|
+
pointG.append("text").attr("x", placed.x).attr("y", placed.y).attr("text-anchor", placed.anchor).attr("dominant-baseline", "central").attr("fill", textColor).attr("font-size", `${POINT_LABEL_FONT_SIZE}px`).attr("font-weight", "700").style("text-shadow", `0 1px 2px ${shadowColor}`).text(point.label);
|
|
28926
29712
|
const tipHtml = `<strong>${point.label}</strong><br>x: ${point.x.toFixed(2)}, y: ${point.y.toFixed(2)}`;
|
|
28927
29713
|
pointG.style("cursor", onClickItem ? "pointer" : "default").on("mouseenter", (event) => {
|
|
28928
29714
|
showTooltip(tooltip, tipHtml, event);
|
|
@@ -28931,7 +29717,7 @@ function renderQuadrant(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
28931
29717
|
showTooltip(tooltip, tipHtml, event);
|
|
28932
29718
|
}).on("mouseleave", () => {
|
|
28933
29719
|
hideTooltip(tooltip);
|
|
28934
|
-
pointG.select("circle").attr("r",
|
|
29720
|
+
pointG.select("circle").attr("r", POINT_RADIUS);
|
|
28935
29721
|
}).on("click", () => {
|
|
28936
29722
|
if (onClickItem && point.lineNumber) onClickItem(point.lineNumber);
|
|
28937
29723
|
});
|
|
@@ -29398,6 +30184,7 @@ var init_d3 = __esm({
|
|
|
29398
30184
|
"use strict";
|
|
29399
30185
|
init_fonts();
|
|
29400
30186
|
init_branding();
|
|
30187
|
+
init_label_layout();
|
|
29401
30188
|
init_colors();
|
|
29402
30189
|
init_palettes();
|
|
29403
30190
|
init_color_utils();
|
|
@@ -29405,6 +30192,7 @@ var init_d3 = __esm({
|
|
|
29405
30192
|
init_parsing();
|
|
29406
30193
|
init_tag_groups();
|
|
29407
30194
|
init_legend_constants();
|
|
30195
|
+
init_legend_d3();
|
|
29408
30196
|
init_title_constants();
|
|
29409
30197
|
DEFAULT_CLOUD_OPTIONS = {
|
|
29410
30198
|
rotate: "none",
|
|
@@ -29559,11 +30347,26 @@ async function ensureDom() {
|
|
|
29559
30347
|
const { JSDOM } = await import("jsdom");
|
|
29560
30348
|
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
|
|
29561
30349
|
const win = dom.window;
|
|
29562
|
-
Object.defineProperty(globalThis, "document", {
|
|
29563
|
-
|
|
29564
|
-
|
|
29565
|
-
|
|
29566
|
-
Object.defineProperty(globalThis, "
|
|
30350
|
+
Object.defineProperty(globalThis, "document", {
|
|
30351
|
+
value: win.document,
|
|
30352
|
+
configurable: true
|
|
30353
|
+
});
|
|
30354
|
+
Object.defineProperty(globalThis, "window", {
|
|
30355
|
+
value: win,
|
|
30356
|
+
configurable: true
|
|
30357
|
+
});
|
|
30358
|
+
Object.defineProperty(globalThis, "navigator", {
|
|
30359
|
+
value: win.navigator,
|
|
30360
|
+
configurable: true
|
|
30361
|
+
});
|
|
30362
|
+
Object.defineProperty(globalThis, "HTMLElement", {
|
|
30363
|
+
value: win.HTMLElement,
|
|
30364
|
+
configurable: true
|
|
30365
|
+
});
|
|
30366
|
+
Object.defineProperty(globalThis, "SVGElement", {
|
|
30367
|
+
value: win.SVGElement,
|
|
30368
|
+
configurable: true
|
|
30369
|
+
});
|
|
29567
30370
|
}
|
|
29568
30371
|
async function render(content, options) {
|
|
29569
30372
|
const theme = options?.theme ?? "light";
|
|
@@ -29572,11 +30375,17 @@ async function render(content, options) {
|
|
|
29572
30375
|
const paletteColors = getPalette(paletteName)[theme === "dark" ? "dark" : "light"];
|
|
29573
30376
|
const chartType = parseDgmoChartType(content);
|
|
29574
30377
|
const category = chartType ? getRenderCategory(chartType) : null;
|
|
30378
|
+
const legendExportState = options?.legendState ? {
|
|
30379
|
+
activeTagGroup: options.legendState.activeGroup ?? null,
|
|
30380
|
+
hiddenAttributes: options.legendState.hiddenAttributes ? new Set(options.legendState.hiddenAttributes) : void 0
|
|
30381
|
+
} : void 0;
|
|
29575
30382
|
if (category === "data-chart") {
|
|
29576
|
-
return renderExtendedChartForExport(content, theme, paletteColors, {
|
|
30383
|
+
return renderExtendedChartForExport(content, theme, paletteColors, {
|
|
30384
|
+
branding
|
|
30385
|
+
});
|
|
29577
30386
|
}
|
|
29578
30387
|
await ensureDom();
|
|
29579
|
-
return renderForExport(content, theme, paletteColors,
|
|
30388
|
+
return renderForExport(content, theme, paletteColors, legendExportState, {
|
|
29580
30389
|
branding,
|
|
29581
30390
|
c4Level: options?.c4Level,
|
|
29582
30391
|
c4System: options?.c4System,
|
|
@@ -30299,6 +31108,8 @@ init_flowchart_renderer();
|
|
|
30299
31108
|
init_echarts();
|
|
30300
31109
|
init_legend_svg();
|
|
30301
31110
|
init_legend_constants();
|
|
31111
|
+
init_legend_d3();
|
|
31112
|
+
init_legend_layout();
|
|
30302
31113
|
init_d3();
|
|
30303
31114
|
init_renderer10();
|
|
30304
31115
|
init_colors();
|
|
@@ -31145,10 +31956,12 @@ export {
|
|
|
31145
31956
|
computeCardMove,
|
|
31146
31957
|
computeInfra,
|
|
31147
31958
|
computeInfraLegendGroups,
|
|
31959
|
+
computeLegendLayout,
|
|
31148
31960
|
computeScatterLabelGraphics,
|
|
31149
31961
|
computeTimeTicks,
|
|
31150
31962
|
contrastText,
|
|
31151
31963
|
decodeDiagramUrl,
|
|
31964
|
+
draculaPalette,
|
|
31152
31965
|
encodeDiagramUrl,
|
|
31153
31966
|
extractDiagramSymbols,
|
|
31154
31967
|
extractTagDeclarations,
|
|
@@ -31156,6 +31969,7 @@ export {
|
|
|
31156
31969
|
formatDgmoError,
|
|
31157
31970
|
getAvailablePalettes,
|
|
31158
31971
|
getExtendedChartLegendGroups,
|
|
31972
|
+
getLegendReservedHeight,
|
|
31159
31973
|
getPalette,
|
|
31160
31974
|
getRenderCategory,
|
|
31161
31975
|
getSeriesColors,
|
|
@@ -31191,6 +32005,7 @@ export {
|
|
|
31191
32005
|
looksLikeSitemap,
|
|
31192
32006
|
looksLikeState,
|
|
31193
32007
|
makeDgmoError,
|
|
32008
|
+
monokaiPalette,
|
|
31194
32009
|
mute,
|
|
31195
32010
|
nord,
|
|
31196
32011
|
nordPalette,
|
|
@@ -31244,7 +32059,9 @@ export {
|
|
|
31244
32059
|
renderInfra,
|
|
31245
32060
|
renderKanban,
|
|
31246
32061
|
renderKanbanForExport,
|
|
32062
|
+
renderLegendD3,
|
|
31247
32063
|
renderLegendSvg,
|
|
32064
|
+
renderLegendSvgFromConfig,
|
|
31248
32065
|
renderOrg,
|
|
31249
32066
|
renderOrgForExport,
|
|
31250
32067
|
renderQuadrant,
|