@diagrammo/dgmo 0.8.10 → 0.8.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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 +491 -125
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +489 -125
- package/dist/index.js.map +1 -1
- package/gallery/fixtures/er.dgmo +36 -0
- package/gallery/fixtures/kanban.dgmo +27 -0
- package/package.json +14 -17
- package/src/boxes-and-lines/parser.ts +2 -0
- package/src/boxes-and-lines/renderer.ts +13 -5
- package/src/c4/layout.ts +31 -10
- package/src/c4/parser.ts +5 -1
- package/src/completion.ts +17 -2
- package/src/d3.ts +220 -102
- package/src/echarts.ts +57 -58
- package/src/editor/index.ts +1 -2
- package/src/er/parser.ts +5 -1
- package/src/gantt/parser.ts +8 -0
- package/src/gantt/renderer.ts +6 -7
- package/src/gantt/resolver.ts +19 -14
- package/src/gantt/types.ts +1 -0
- package/src/index.ts +2 -0
- package/src/infra/parser.ts +4 -0
- package/src/kanban/parser.ts +4 -1
- package/src/kanban/renderer.ts +11 -8
- package/src/label-layout.ts +286 -0
- package/src/org/parser.ts +3 -0
- package/src/sequence/parser.ts +6 -0
- package/src/sequence/renderer.ts +24 -9
- package/src/sharing.ts +15 -5
- package/src/sitemap/parser.ts +2 -0
- package/src/utils/arrows.ts +1 -1
- package/src/utils/legend-layout.ts +8 -8
- package/src/utils/legend-svg.ts +2 -2
- package/src/utils/legend-types.ts +0 -3
- package/src/utils/parsing.ts +1 -1
- package/src/utils/tag-groups.ts +65 -1
package/src/d3.ts
CHANGED
|
@@ -5,6 +5,7 @@ import * as d3Array from 'd3-array';
|
|
|
5
5
|
import cloud from 'd3-cloud';
|
|
6
6
|
import { FONT_FAMILY } from './fonts';
|
|
7
7
|
import { injectBranding } from './branding';
|
|
8
|
+
import { computeQuadrantPointLabels, type LabelRect } from './label-layout';
|
|
8
9
|
|
|
9
10
|
// ============================================================
|
|
10
11
|
// Types
|
|
@@ -19,22 +20,22 @@ export type VisualizationType =
|
|
|
19
20
|
| 'quadrant'
|
|
20
21
|
| 'sequence';
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
interface D3DataItem {
|
|
23
24
|
label: string;
|
|
24
25
|
values: number[];
|
|
25
26
|
color: string | null;
|
|
26
27
|
lineNumber: number;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
interface WordCloudWord {
|
|
30
31
|
text: string;
|
|
31
32
|
weight: number;
|
|
32
33
|
lineNumber: number;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
type WordCloudRotate = 'none' | 'mixed' | 'angled';
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
interface WordCloudOptions {
|
|
38
39
|
rotate: WordCloudRotate;
|
|
39
40
|
max: number;
|
|
40
41
|
minSize: number;
|
|
@@ -56,7 +57,7 @@ export interface ArcLink {
|
|
|
56
57
|
lineNumber: number;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
type ArcOrder = 'appearance' | 'name' | 'group' | 'degree';
|
|
60
61
|
|
|
61
62
|
export interface ArcNodeGroup {
|
|
62
63
|
name: string;
|
|
@@ -65,9 +66,9 @@ export interface ArcNodeGroup {
|
|
|
65
66
|
lineNumber: number;
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
|
|
69
|
+
type TimelineSort = 'time' | 'group' | 'tag';
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
interface TimelineEvent {
|
|
71
72
|
date: string;
|
|
72
73
|
endDate: string | null;
|
|
73
74
|
label: string;
|
|
@@ -77,13 +78,13 @@ export interface TimelineEvent {
|
|
|
77
78
|
uncertain?: boolean;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
|
|
81
|
+
interface TimelineGroup {
|
|
81
82
|
name: string;
|
|
82
83
|
color: string | null;
|
|
83
84
|
lineNumber: number;
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
|
|
87
|
+
interface TimelineEra {
|
|
87
88
|
startDate: string;
|
|
88
89
|
endDate: string;
|
|
89
90
|
label: string;
|
|
@@ -91,40 +92,40 @@ export interface TimelineEra {
|
|
|
91
92
|
lineNumber: number;
|
|
92
93
|
}
|
|
93
94
|
|
|
94
|
-
|
|
95
|
+
interface TimelineMarker {
|
|
95
96
|
date: string;
|
|
96
97
|
label: string;
|
|
97
98
|
color: string | null;
|
|
98
99
|
lineNumber: number;
|
|
99
100
|
}
|
|
100
101
|
|
|
101
|
-
|
|
102
|
+
interface VennSet {
|
|
102
103
|
name: string;
|
|
103
104
|
alias: string | null;
|
|
104
105
|
color: string | null;
|
|
105
106
|
lineNumber: number;
|
|
106
107
|
}
|
|
107
108
|
|
|
108
|
-
|
|
109
|
+
interface VennOverlap {
|
|
109
110
|
sets: string[];
|
|
110
111
|
label: string | null;
|
|
111
112
|
lineNumber: number;
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
|
|
115
|
+
interface QuadrantLabel {
|
|
115
116
|
text: string;
|
|
116
117
|
color: string | null;
|
|
117
118
|
lineNumber: number;
|
|
118
119
|
}
|
|
119
120
|
|
|
120
|
-
|
|
121
|
+
interface QuadrantPoint {
|
|
121
122
|
label: string;
|
|
122
123
|
x: number;
|
|
123
124
|
y: number;
|
|
124
125
|
lineNumber: number;
|
|
125
126
|
}
|
|
126
127
|
|
|
127
|
-
|
|
128
|
+
interface QuadrantLabels {
|
|
128
129
|
topRight: QuadrantLabel | null;
|
|
129
130
|
topLeft: QuadrantLabel | null;
|
|
130
131
|
bottomLeft: QuadrantLabel | null;
|
|
@@ -192,7 +193,9 @@ import {
|
|
|
192
193
|
import {
|
|
193
194
|
matchTagBlockHeading,
|
|
194
195
|
validateTagValues,
|
|
196
|
+
validateTagGroupNames,
|
|
195
197
|
resolveTagColor,
|
|
198
|
+
resolveActiveTagGroup,
|
|
196
199
|
stripDefaultModifier,
|
|
197
200
|
} from './utils/tag-groups';
|
|
198
201
|
import type { TagGroup } from './utils/tag-groups';
|
|
@@ -1476,6 +1479,9 @@ export function parseVisualization(
|
|
|
1476
1479
|
result.diagnostics.push(makeDgmoError(line, msg, 'warning')),
|
|
1477
1480
|
suggest
|
|
1478
1481
|
);
|
|
1482
|
+
validateTagGroupNames(result.timelineTagGroups, (line, msg) =>
|
|
1483
|
+
result.diagnostics.push(makeDgmoError(line, msg, 'warning'))
|
|
1484
|
+
);
|
|
1479
1485
|
for (const group of result.timelineTagGroups) {
|
|
1480
1486
|
if (!group.defaultValue) continue;
|
|
1481
1487
|
const key = group.name.toLowerCase();
|
|
@@ -3404,6 +3410,78 @@ function buildEraTooltipHtml(era: TimelineEra): string {
|
|
|
3404
3410
|
// Timeline Renderer
|
|
3405
3411
|
// ============================================================
|
|
3406
3412
|
|
|
3413
|
+
/**
|
|
3414
|
+
* Renders timeline group legend as pills (colored dot + text in rounded rect),
|
|
3415
|
+
* matching the centralized legend pill style.
|
|
3416
|
+
*/
|
|
3417
|
+
function renderTimelineGroupLegend(
|
|
3418
|
+
g: d3Selection.Selection<SVGGElement, unknown, null, undefined>,
|
|
3419
|
+
groups: TimelineGroup[],
|
|
3420
|
+
groupColorMap: Map<string, string>,
|
|
3421
|
+
textColor: string,
|
|
3422
|
+
palette: PaletteColors,
|
|
3423
|
+
isDark: boolean,
|
|
3424
|
+
legendY: number,
|
|
3425
|
+
onHover: (name: string) => void,
|
|
3426
|
+
onLeave: () => void
|
|
3427
|
+
): void {
|
|
3428
|
+
const PILL_H = 22;
|
|
3429
|
+
const DOT_R = 4;
|
|
3430
|
+
const DOT_GAP = 4;
|
|
3431
|
+
const PAD_X = 10;
|
|
3432
|
+
const FONT_SIZE = 11;
|
|
3433
|
+
const GAP = 8;
|
|
3434
|
+
const pillBg = isDark
|
|
3435
|
+
? mix(palette.surface, palette.bg, 50)
|
|
3436
|
+
: mix(palette.surface, palette.bg, 30);
|
|
3437
|
+
|
|
3438
|
+
let legendX = 0;
|
|
3439
|
+
for (const grp of groups) {
|
|
3440
|
+
const color = groupColorMap.get(grp.name) ?? textColor;
|
|
3441
|
+
const textW = measureLegendText(grp.name, FONT_SIZE);
|
|
3442
|
+
const pillW = PAD_X + DOT_R * 2 + DOT_GAP + textW + PAD_X;
|
|
3443
|
+
|
|
3444
|
+
const itemG = g
|
|
3445
|
+
.append('g')
|
|
3446
|
+
.attr('class', 'tl-legend-item')
|
|
3447
|
+
.attr('data-group', grp.name)
|
|
3448
|
+
.style('cursor', 'pointer')
|
|
3449
|
+
.on('mouseenter', () => onHover(grp.name))
|
|
3450
|
+
.on('mouseleave', () => onLeave());
|
|
3451
|
+
|
|
3452
|
+
// Pill background
|
|
3453
|
+
itemG
|
|
3454
|
+
.append('rect')
|
|
3455
|
+
.attr('x', legendX)
|
|
3456
|
+
.attr('y', legendY - PILL_H / 2)
|
|
3457
|
+
.attr('width', pillW)
|
|
3458
|
+
.attr('height', PILL_H)
|
|
3459
|
+
.attr('rx', PILL_H / 2)
|
|
3460
|
+
.attr('fill', pillBg);
|
|
3461
|
+
|
|
3462
|
+
// Colored dot
|
|
3463
|
+
itemG
|
|
3464
|
+
.append('circle')
|
|
3465
|
+
.attr('cx', legendX + PAD_X + DOT_R)
|
|
3466
|
+
.attr('cy', legendY)
|
|
3467
|
+
.attr('r', DOT_R)
|
|
3468
|
+
.attr('fill', color);
|
|
3469
|
+
|
|
3470
|
+
// Label text
|
|
3471
|
+
itemG
|
|
3472
|
+
.append('text')
|
|
3473
|
+
.attr('x', legendX + PAD_X + DOT_R * 2 + DOT_GAP)
|
|
3474
|
+
.attr('y', legendY)
|
|
3475
|
+
.attr('dy', '0.35em')
|
|
3476
|
+
.attr('fill', textColor)
|
|
3477
|
+
.attr('font-size', `${FONT_SIZE}px`)
|
|
3478
|
+
.attr('font-family', FONT_FAMILY)
|
|
3479
|
+
.text(grp.name);
|
|
3480
|
+
|
|
3481
|
+
legendX += pillW + GAP;
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3484
|
+
|
|
3407
3485
|
/**
|
|
3408
3486
|
* Renders a timeline chart into the given container using D3.
|
|
3409
3487
|
* Supports horizontal (default) and vertical orientation.
|
|
@@ -4037,38 +4115,19 @@ export function renderTimeline(
|
|
|
4037
4115
|
);
|
|
4038
4116
|
}
|
|
4039
4117
|
|
|
4040
|
-
// Group legend
|
|
4118
|
+
// Group legend (pill style)
|
|
4041
4119
|
if (timelineGroups.length > 0) {
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
itemG
|
|
4055
|
-
.append('circle')
|
|
4056
|
-
.attr('cx', legendX)
|
|
4057
|
-
.attr('cy', legendY)
|
|
4058
|
-
.attr('r', 5)
|
|
4059
|
-
.attr('fill', color);
|
|
4060
|
-
|
|
4061
|
-
itemG
|
|
4062
|
-
.append('text')
|
|
4063
|
-
.attr('x', legendX + 10)
|
|
4064
|
-
.attr('y', legendY)
|
|
4065
|
-
.attr('dy', '0.35em')
|
|
4066
|
-
.attr('fill', textColor)
|
|
4067
|
-
.attr('font-size', '11px')
|
|
4068
|
-
.text(grp.name);
|
|
4069
|
-
|
|
4070
|
-
legendX += grp.name.length * 7 + 30;
|
|
4071
|
-
}
|
|
4120
|
+
renderTimelineGroupLegend(
|
|
4121
|
+
g,
|
|
4122
|
+
timelineGroups,
|
|
4123
|
+
groupColorMap,
|
|
4124
|
+
textColor,
|
|
4125
|
+
palette,
|
|
4126
|
+
isDark,
|
|
4127
|
+
-55,
|
|
4128
|
+
(name) => fadeToGroup(g, name),
|
|
4129
|
+
() => fadeReset(g)
|
|
4130
|
+
);
|
|
4072
4131
|
}
|
|
4073
4132
|
|
|
4074
4133
|
g.append('line')
|
|
@@ -4525,8 +4584,7 @@ export function renderTimeline(
|
|
|
4525
4584
|
.attr('dy', '0.35em')
|
|
4526
4585
|
.attr('text-anchor', 'start')
|
|
4527
4586
|
.attr('fill', textColor)
|
|
4528
|
-
.attr('font-size', '
|
|
4529
|
-
.attr('font-weight', '700')
|
|
4587
|
+
.attr('font-size', '13px')
|
|
4530
4588
|
.text(ev.label);
|
|
4531
4589
|
} else {
|
|
4532
4590
|
// Text outside bar - check if it fits on left or must go right
|
|
@@ -4656,38 +4714,20 @@ export function renderTimeline(
|
|
|
4656
4714
|
);
|
|
4657
4715
|
}
|
|
4658
4716
|
|
|
4659
|
-
// Group legend at top-left
|
|
4717
|
+
// Group legend at top-left (pill style)
|
|
4660
4718
|
if (timelineGroups.length > 0) {
|
|
4661
|
-
let legendX = 0;
|
|
4662
4719
|
const legendY = timelineScale ? -75 : -55;
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
.append('circle')
|
|
4675
|
-
.attr('cx', legendX)
|
|
4676
|
-
.attr('cy', legendY)
|
|
4677
|
-
.attr('r', 5)
|
|
4678
|
-
.attr('fill', color);
|
|
4679
|
-
|
|
4680
|
-
itemG
|
|
4681
|
-
.append('text')
|
|
4682
|
-
.attr('x', legendX + 10)
|
|
4683
|
-
.attr('y', legendY)
|
|
4684
|
-
.attr('dy', '0.35em')
|
|
4685
|
-
.attr('fill', textColor)
|
|
4686
|
-
.attr('font-size', '11px')
|
|
4687
|
-
.text(grp.name);
|
|
4688
|
-
|
|
4689
|
-
legendX += grp.name.length * 7 + 30;
|
|
4690
|
-
}
|
|
4720
|
+
renderTimelineGroupLegend(
|
|
4721
|
+
g,
|
|
4722
|
+
timelineGroups,
|
|
4723
|
+
groupColorMap,
|
|
4724
|
+
textColor,
|
|
4725
|
+
palette,
|
|
4726
|
+
isDark,
|
|
4727
|
+
legendY,
|
|
4728
|
+
(name) => fadeToGroup(g, name),
|
|
4729
|
+
() => fadeReset(g)
|
|
4730
|
+
);
|
|
4691
4731
|
}
|
|
4692
4732
|
|
|
4693
4733
|
sorted.forEach((ev, i) => {
|
|
@@ -4815,8 +4855,7 @@ export function renderTimeline(
|
|
|
4815
4855
|
.attr('dy', '0.35em')
|
|
4816
4856
|
.attr('text-anchor', 'start')
|
|
4817
4857
|
.attr('fill', textColor)
|
|
4818
|
-
.attr('font-size', '
|
|
4819
|
-
.attr('font-weight', '700')
|
|
4858
|
+
.attr('font-size', '13px')
|
|
4820
4859
|
.text(ev.label);
|
|
4821
4860
|
} else {
|
|
4822
4861
|
// Text outside bar - check if it fits on left or must go right
|
|
@@ -5461,7 +5500,7 @@ export function renderVenn(
|
|
|
5461
5500
|
exportDims?: D3ExportDimensions
|
|
5462
5501
|
): void {
|
|
5463
5502
|
const { vennSets, vennOverlaps, title } = parsed;
|
|
5464
|
-
if (vennSets.length < 2) return;
|
|
5503
|
+
if (vennSets.length < 2 || vennSets.length > 3) return;
|
|
5465
5504
|
|
|
5466
5505
|
const init = initD3Chart(container, palette, exportDims);
|
|
5467
5506
|
if (!init) return;
|
|
@@ -5539,7 +5578,9 @@ export function renderVenn(
|
|
|
5539
5578
|
// Suppress WebKit focus ring on interactive SVG elements
|
|
5540
5579
|
svg
|
|
5541
5580
|
.append('style')
|
|
5542
|
-
.text(
|
|
5581
|
+
.text(
|
|
5582
|
+
'circle:focus, circle:focus-visible { outline-solid: none !important; }'
|
|
5583
|
+
);
|
|
5543
5584
|
|
|
5544
5585
|
// Title
|
|
5545
5586
|
renderChartTitle(
|
|
@@ -5870,7 +5911,7 @@ export function renderVenn(
|
|
|
5870
5911
|
.attr('class', 'venn-hit-target')
|
|
5871
5912
|
.attr('data-line-number', String(vennSets[i].lineNumber))
|
|
5872
5913
|
.style('cursor', onClickItem ? 'pointer' : 'default')
|
|
5873
|
-
.style('outline', 'none')
|
|
5914
|
+
.style('outline-solid', 'none')
|
|
5874
5915
|
.on('mouseenter', () => {
|
|
5875
5916
|
showRegionOverlay([i]);
|
|
5876
5917
|
})
|
|
@@ -5926,7 +5967,7 @@ export function renderVenn(
|
|
|
5926
5967
|
.attr('class', 'venn-hit-target')
|
|
5927
5968
|
.attr('data-line-number', declaredOv ? String(declaredOv.lineNumber) : '')
|
|
5928
5969
|
.style('cursor', onClickItem && declaredOv ? 'pointer' : 'default')
|
|
5929
|
-
.style('outline', 'none')
|
|
5970
|
+
.style('outline-solid', 'none')
|
|
5930
5971
|
.on('mouseenter', () => {
|
|
5931
5972
|
showRegionOverlay(idxs);
|
|
5932
5973
|
})
|
|
@@ -6416,40 +6457,88 @@ export function renderQuadrant(
|
|
|
6416
6457
|
return 'bottom-right';
|
|
6417
6458
|
};
|
|
6418
6459
|
|
|
6460
|
+
// Build obstacle rects from quadrant watermark labels for collision avoidance
|
|
6461
|
+
const POINT_RADIUS = 6;
|
|
6462
|
+
const POINT_LABEL_FONT_SIZE = 12;
|
|
6463
|
+
const quadrantLabelObstacles: LabelRect[] = quadrantDefsWithLabel.map((d) => {
|
|
6464
|
+
const layout = labelLayouts.get(d.label!.text)!;
|
|
6465
|
+
const totalW =
|
|
6466
|
+
Math.max(...layout.lines.map((l) => l.length)) *
|
|
6467
|
+
layout.fontSize *
|
|
6468
|
+
CHAR_WIDTH_RATIO;
|
|
6469
|
+
const totalH = layout.lines.length * layout.fontSize * 1.2;
|
|
6470
|
+
return {
|
|
6471
|
+
x: d.labelX - totalW / 2,
|
|
6472
|
+
y: d.labelY - totalH / 2,
|
|
6473
|
+
w: totalW,
|
|
6474
|
+
h: totalH,
|
|
6475
|
+
};
|
|
6476
|
+
});
|
|
6477
|
+
|
|
6478
|
+
// Compute collision-free label positions for all points
|
|
6479
|
+
const pointPixels = quadrantPoints.map((point) => ({
|
|
6480
|
+
label: point.label,
|
|
6481
|
+
cx: xScale(point.x),
|
|
6482
|
+
cy: yScale(point.y),
|
|
6483
|
+
}));
|
|
6484
|
+
|
|
6485
|
+
const placedPointLabels = computeQuadrantPointLabels(
|
|
6486
|
+
pointPixels,
|
|
6487
|
+
{ left: 0, top: 0, right: chartWidth, bottom: chartHeight },
|
|
6488
|
+
quadrantLabelObstacles,
|
|
6489
|
+
POINT_RADIUS,
|
|
6490
|
+
POINT_LABEL_FONT_SIZE
|
|
6491
|
+
);
|
|
6492
|
+
|
|
6419
6493
|
// Draw data points (circles and labels)
|
|
6420
6494
|
const pointsG = chartG.append('g').attr('class', 'points');
|
|
6421
6495
|
|
|
6422
|
-
quadrantPoints.forEach((point) => {
|
|
6496
|
+
quadrantPoints.forEach((point, i) => {
|
|
6423
6497
|
const cx = xScale(point.x);
|
|
6424
6498
|
const cy = yScale(point.y);
|
|
6425
6499
|
const quadrant = getPointQuadrant(point.x, point.y);
|
|
6426
6500
|
const quadDef = quadrantDefs.find((d) => d.position === quadrant);
|
|
6427
6501
|
const pointColor =
|
|
6428
6502
|
quadDef?.label?.color ?? defaultColors[quadDef?.colorIdx ?? 0];
|
|
6503
|
+
const placed = placedPointLabels[i];
|
|
6429
6504
|
|
|
6430
6505
|
const pointG = pointsG
|
|
6431
6506
|
.append('g')
|
|
6432
6507
|
.attr('class', 'point-group')
|
|
6433
6508
|
.attr('data-line-number', String(point.lineNumber));
|
|
6434
6509
|
|
|
6510
|
+
// Connector line (drawn first so it renders behind circle and label)
|
|
6511
|
+
if (placed.connectorLine) {
|
|
6512
|
+
pointG
|
|
6513
|
+
.append('line')
|
|
6514
|
+
.attr('x1', placed.connectorLine.x1)
|
|
6515
|
+
.attr('y1', placed.connectorLine.y1)
|
|
6516
|
+
.attr('x2', placed.connectorLine.x2)
|
|
6517
|
+
.attr('y2', placed.connectorLine.y2)
|
|
6518
|
+
.attr('stroke', pointColor)
|
|
6519
|
+
.attr('stroke-width', 1)
|
|
6520
|
+
.attr('opacity', 0.5);
|
|
6521
|
+
}
|
|
6522
|
+
|
|
6435
6523
|
// Circle with white fill and colored border for visibility on opaque quadrants
|
|
6436
6524
|
pointG
|
|
6437
6525
|
.append('circle')
|
|
6438
6526
|
.attr('cx', cx)
|
|
6439
6527
|
.attr('cy', cy)
|
|
6440
|
-
.attr('r',
|
|
6528
|
+
.attr('r', POINT_RADIUS)
|
|
6441
6529
|
.attr('fill', '#ffffff')
|
|
6442
6530
|
.attr('stroke', pointColor)
|
|
6443
6531
|
.attr('stroke-width', 2);
|
|
6444
6532
|
|
|
6445
|
-
// Label
|
|
6533
|
+
// Label at computed position
|
|
6446
6534
|
pointG
|
|
6447
6535
|
.append('text')
|
|
6448
|
-
.attr('x',
|
|
6449
|
-
.attr('y',
|
|
6450
|
-
.attr('text-anchor',
|
|
6536
|
+
.attr('x', placed.x)
|
|
6537
|
+
.attr('y', placed.y)
|
|
6538
|
+
.attr('text-anchor', placed.anchor)
|
|
6539
|
+
.attr('dominant-baseline', 'central')
|
|
6451
6540
|
.attr('fill', textColor)
|
|
6452
|
-
.attr('font-size',
|
|
6541
|
+
.attr('font-size', `${POINT_LABEL_FONT_SIZE}px`)
|
|
6453
6542
|
.attr('font-weight', '700')
|
|
6454
6543
|
.style('text-shadow', `0 1px 2px ${shadowColor}`)
|
|
6455
6544
|
.text(point.label);
|
|
@@ -6468,7 +6557,7 @@ export function renderQuadrant(
|
|
|
6468
6557
|
})
|
|
6469
6558
|
.on('mouseleave', () => {
|
|
6470
6559
|
hideTooltip(tooltip);
|
|
6471
|
-
pointG.select('circle').attr('r',
|
|
6560
|
+
pointG.select('circle').attr('r', POINT_RADIUS);
|
|
6472
6561
|
})
|
|
6473
6562
|
.on('click', () => {
|
|
6474
6563
|
if (onClickItem && point.lineNumber) onClickItem(point.lineNumber);
|
|
@@ -6609,8 +6698,11 @@ export async function renderForExport(
|
|
|
6609
6698
|
|
|
6610
6699
|
// Apply interactive collapse state when provided
|
|
6611
6700
|
const collapsedNodes = orgExportState?.collapsedNodes;
|
|
6612
|
-
const activeTagGroup =
|
|
6613
|
-
|
|
6701
|
+
const activeTagGroup = resolveActiveTagGroup(
|
|
6702
|
+
orgParsed.tagGroups,
|
|
6703
|
+
orgParsed.options['active-tag'],
|
|
6704
|
+
orgExportState?.activeTagGroup ?? options?.tagGroup
|
|
6705
|
+
);
|
|
6614
6706
|
const hiddenAttributes = orgExportState?.hiddenAttributes;
|
|
6615
6707
|
|
|
6616
6708
|
const { parsed: effectiveParsed, hiddenCounts } =
|
|
@@ -6660,8 +6752,11 @@ export async function renderForExport(
|
|
|
6660
6752
|
|
|
6661
6753
|
// Apply interactive collapse state when provided
|
|
6662
6754
|
const collapsedNodes = orgExportState?.collapsedNodes;
|
|
6663
|
-
const activeTagGroup =
|
|
6664
|
-
|
|
6755
|
+
const activeTagGroup = resolveActiveTagGroup(
|
|
6756
|
+
sitemapParsed.tagGroups,
|
|
6757
|
+
sitemapParsed.options['active-tag'],
|
|
6758
|
+
orgExportState?.activeTagGroup ?? options?.tagGroup
|
|
6759
|
+
);
|
|
6665
6760
|
const hiddenAttributes = orgExportState?.hiddenAttributes;
|
|
6666
6761
|
|
|
6667
6762
|
const { parsed: effectiveParsed, hiddenCounts } =
|
|
@@ -6718,7 +6813,11 @@ export async function renderForExport(
|
|
|
6718
6813
|
theme === 'dark',
|
|
6719
6814
|
undefined,
|
|
6720
6815
|
undefined,
|
|
6721
|
-
|
|
6816
|
+
resolveActiveTagGroup(
|
|
6817
|
+
kanbanParsed.tagGroups,
|
|
6818
|
+
kanbanParsed.options['active-tag'],
|
|
6819
|
+
options?.tagGroup
|
|
6820
|
+
)
|
|
6722
6821
|
);
|
|
6723
6822
|
return finalizeSvgExport(container, theme, effectivePalette, options);
|
|
6724
6823
|
}
|
|
@@ -6775,7 +6874,11 @@ export async function renderForExport(
|
|
|
6775
6874
|
theme === 'dark',
|
|
6776
6875
|
undefined,
|
|
6777
6876
|
{ width: exportWidth, height: exportHeight },
|
|
6778
|
-
|
|
6877
|
+
resolveActiveTagGroup(
|
|
6878
|
+
erParsed.tagGroups,
|
|
6879
|
+
erParsed.options['active-tag'],
|
|
6880
|
+
options?.tagGroup
|
|
6881
|
+
)
|
|
6779
6882
|
);
|
|
6780
6883
|
return finalizeSvgExport(container, theme, effectivePalette, options);
|
|
6781
6884
|
}
|
|
@@ -6803,7 +6906,10 @@ export async function renderForExport(
|
|
|
6803
6906
|
blLayout,
|
|
6804
6907
|
effectivePalette,
|
|
6805
6908
|
theme === 'dark',
|
|
6806
|
-
{
|
|
6909
|
+
{
|
|
6910
|
+
exportDims: { width: exportWidth, height: exportHeight },
|
|
6911
|
+
activeTagGroup: options?.tagGroup,
|
|
6912
|
+
}
|
|
6807
6913
|
);
|
|
6808
6914
|
return finalizeSvgExport(container, theme, effectivePalette, options);
|
|
6809
6915
|
}
|
|
@@ -6860,7 +6966,11 @@ export async function renderForExport(
|
|
|
6860
6966
|
theme === 'dark',
|
|
6861
6967
|
undefined,
|
|
6862
6968
|
{ width: exportWidth, height: exportHeight },
|
|
6863
|
-
|
|
6969
|
+
resolveActiveTagGroup(
|
|
6970
|
+
c4Parsed.tagGroups,
|
|
6971
|
+
c4Parsed.options['active-tag'],
|
|
6972
|
+
options?.tagGroup
|
|
6973
|
+
)
|
|
6864
6974
|
);
|
|
6865
6975
|
return finalizeSvgExport(container, theme, effectivePalette, options);
|
|
6866
6976
|
}
|
|
@@ -6902,7 +7012,11 @@ export async function renderForExport(
|
|
|
6902
7012
|
|
|
6903
7013
|
const infraComputed = computeInfra(infraParsed);
|
|
6904
7014
|
const infraLayout = layoutInfra(infraComputed);
|
|
6905
|
-
const activeTagGroup =
|
|
7015
|
+
const activeTagGroup = resolveActiveTagGroup(
|
|
7016
|
+
infraParsed.tagGroups,
|
|
7017
|
+
infraParsed.options['active-tag'],
|
|
7018
|
+
options?.tagGroup
|
|
7019
|
+
);
|
|
6906
7020
|
|
|
6907
7021
|
const titleOffset = infraParsed.title ? 40 : 0;
|
|
6908
7022
|
const legendGroups = computeInfraLegendGroups(
|
|
@@ -7055,7 +7169,11 @@ export async function renderForExport(
|
|
|
7055
7169
|
isDark,
|
|
7056
7170
|
undefined,
|
|
7057
7171
|
dims,
|
|
7058
|
-
|
|
7172
|
+
resolveActiveTagGroup(
|
|
7173
|
+
parsed.timelineTagGroups,
|
|
7174
|
+
undefined,
|
|
7175
|
+
orgExportState?.activeTagGroup ?? options?.tagGroup
|
|
7176
|
+
),
|
|
7059
7177
|
orgExportState?.swimlaneTagGroup
|
|
7060
7178
|
);
|
|
7061
7179
|
} else if (parsed.type === 'venn') {
|