@diagrammo/dgmo 0.5.0 → 0.5.2
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 +146 -146
- package/dist/index.cjs +235 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +235 -66
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/d3.ts +308 -90
- package/src/sharing.ts +8 -0
package/dist/index.cjs
CHANGED
|
@@ -18495,9 +18495,18 @@ function parseD3(content, palette) {
|
|
|
18495
18495
|
continue;
|
|
18496
18496
|
}
|
|
18497
18497
|
if (key === "sort") {
|
|
18498
|
-
const v = line10.substring(colonIndex + 1).trim()
|
|
18499
|
-
|
|
18500
|
-
|
|
18498
|
+
const v = line10.substring(colonIndex + 1).trim();
|
|
18499
|
+
const vLower = v.toLowerCase();
|
|
18500
|
+
if (vLower === "time" || vLower === "group") {
|
|
18501
|
+
result.timelineSort = vLower;
|
|
18502
|
+
} else if (vLower === "tag" || vLower.startsWith("tag:")) {
|
|
18503
|
+
result.timelineSort = "tag";
|
|
18504
|
+
if (vLower.startsWith("tag:")) {
|
|
18505
|
+
const groupRef = v.substring(4).trim();
|
|
18506
|
+
if (groupRef) {
|
|
18507
|
+
result.timelineDefaultSwimlaneTG = groupRef;
|
|
18508
|
+
}
|
|
18509
|
+
}
|
|
18501
18510
|
}
|
|
18502
18511
|
continue;
|
|
18503
18512
|
}
|
|
@@ -18647,6 +18656,25 @@ function parseD3(content, palette) {
|
|
|
18647
18656
|
}
|
|
18648
18657
|
}
|
|
18649
18658
|
}
|
|
18659
|
+
if (result.timelineSort === "tag") {
|
|
18660
|
+
if (result.timelineTagGroups.length === 0) {
|
|
18661
|
+
warn(1, '"sort: tag" requires at least one tag group definition');
|
|
18662
|
+
result.timelineSort = "time";
|
|
18663
|
+
} else if (result.timelineDefaultSwimlaneTG) {
|
|
18664
|
+
const ref = result.timelineDefaultSwimlaneTG.toLowerCase();
|
|
18665
|
+
const match = result.timelineTagGroups.find(
|
|
18666
|
+
(g) => g.name.toLowerCase() === ref || g.alias?.toLowerCase() === ref
|
|
18667
|
+
);
|
|
18668
|
+
if (match) {
|
|
18669
|
+
result.timelineDefaultSwimlaneTG = match.name;
|
|
18670
|
+
} else {
|
|
18671
|
+
warn(1, `"sort: tag:${result.timelineDefaultSwimlaneTG}" \u2014 no tag group matches "${result.timelineDefaultSwimlaneTG}"`);
|
|
18672
|
+
result.timelineDefaultSwimlaneTG = result.timelineTagGroups[0].name;
|
|
18673
|
+
}
|
|
18674
|
+
} else {
|
|
18675
|
+
result.timelineDefaultSwimlaneTG = result.timelineTagGroups[0].name;
|
|
18676
|
+
}
|
|
18677
|
+
}
|
|
18650
18678
|
return result;
|
|
18651
18679
|
}
|
|
18652
18680
|
if (result.type === "venn") {
|
|
@@ -19405,7 +19433,7 @@ function buildEventTooltipHtml(ev) {
|
|
|
19405
19433
|
function buildEraTooltipHtml(era) {
|
|
19406
19434
|
return `<strong>${era.label}</strong><br>${formatDateLabel(era.startDate)} \u2192 ${formatDateLabel(era.endDate)}`;
|
|
19407
19435
|
}
|
|
19408
|
-
function renderTimeline(container, parsed, palette, isDark, onClickItem, exportDims, activeTagGroup) {
|
|
19436
|
+
function renderTimeline(container, parsed, palette, isDark, onClickItem, exportDims, activeTagGroup, swimlaneTagGroup, onTagStateChange, viewMode) {
|
|
19409
19437
|
d3Selection12.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
19410
19438
|
const {
|
|
19411
19439
|
timelineEvents,
|
|
@@ -19419,6 +19447,9 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19419
19447
|
orientation
|
|
19420
19448
|
} = parsed;
|
|
19421
19449
|
if (timelineEvents.length === 0) return;
|
|
19450
|
+
if (swimlaneTagGroup == null && timelineSort === "tag" && parsed.timelineDefaultSwimlaneTG) {
|
|
19451
|
+
swimlaneTagGroup = parsed.timelineDefaultSwimlaneTG;
|
|
19452
|
+
}
|
|
19422
19453
|
const tooltip = createTooltip(container, palette, isDark);
|
|
19423
19454
|
const width = exportDims?.width ?? container.clientWidth;
|
|
19424
19455
|
const height = exportDims?.height ?? container.clientHeight;
|
|
@@ -19432,9 +19463,47 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19432
19463
|
timelineGroups.forEach((grp, i) => {
|
|
19433
19464
|
groupColorMap.set(grp.name, grp.color ?? colors[i % colors.length]);
|
|
19434
19465
|
});
|
|
19466
|
+
let tagLanes = null;
|
|
19467
|
+
if (swimlaneTagGroup) {
|
|
19468
|
+
const tagKey = swimlaneTagGroup.toLowerCase();
|
|
19469
|
+
const tagGroup = parsed.timelineTagGroups.find(
|
|
19470
|
+
(g) => g.name.toLowerCase() === tagKey
|
|
19471
|
+
);
|
|
19472
|
+
if (tagGroup) {
|
|
19473
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
19474
|
+
const otherEvents = [];
|
|
19475
|
+
for (const ev of timelineEvents) {
|
|
19476
|
+
const val = ev.metadata[tagKey];
|
|
19477
|
+
if (val) {
|
|
19478
|
+
const list = buckets.get(val) ?? [];
|
|
19479
|
+
list.push(ev);
|
|
19480
|
+
buckets.set(val, list);
|
|
19481
|
+
} else {
|
|
19482
|
+
otherEvents.push(ev);
|
|
19483
|
+
}
|
|
19484
|
+
}
|
|
19485
|
+
const laneEntries = [...buckets.entries()].sort((a, b) => {
|
|
19486
|
+
const aMin = Math.min(
|
|
19487
|
+
...a[1].map((e) => parseTimelineDate(e.date))
|
|
19488
|
+
);
|
|
19489
|
+
const bMin = Math.min(
|
|
19490
|
+
...b[1].map((e) => parseTimelineDate(e.date))
|
|
19491
|
+
);
|
|
19492
|
+
return aMin - bMin;
|
|
19493
|
+
});
|
|
19494
|
+
tagLanes = laneEntries.map(([name, events]) => ({ name, events }));
|
|
19495
|
+
if (otherEvents.length > 0) {
|
|
19496
|
+
tagLanes.push({ name: "(Other)", events: otherEvents });
|
|
19497
|
+
}
|
|
19498
|
+
for (const entry of tagGroup.entries) {
|
|
19499
|
+
groupColorMap.set(entry.value, entry.color);
|
|
19500
|
+
}
|
|
19501
|
+
}
|
|
19502
|
+
}
|
|
19503
|
+
const effectiveColorTG = activeTagGroup ?? swimlaneTagGroup ?? null;
|
|
19435
19504
|
function eventColor(ev) {
|
|
19436
|
-
if (
|
|
19437
|
-
const tagColor = resolveTagColor(ev.metadata, parsed.timelineTagGroups,
|
|
19505
|
+
if (effectiveColorTG) {
|
|
19506
|
+
const tagColor = resolveTagColor(ev.metadata, parsed.timelineTagGroups, effectiveColorTG);
|
|
19438
19507
|
if (tagColor) return tagColor;
|
|
19439
19508
|
}
|
|
19440
19509
|
if (ev.group && groupColorMap.has(ev.group)) {
|
|
@@ -19538,12 +19607,28 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19538
19607
|
}
|
|
19539
19608
|
const tagLegendReserve = parsed.timelineTagGroups.length > 0 ? 36 : 0;
|
|
19540
19609
|
if (isVertical) {
|
|
19541
|
-
|
|
19542
|
-
|
|
19543
|
-
|
|
19544
|
-
|
|
19545
|
-
)
|
|
19546
|
-
|
|
19610
|
+
const useGroupedVertical = tagLanes != null || timelineSort === "group" && timelineGroups.length > 0;
|
|
19611
|
+
if (useGroupedVertical) {
|
|
19612
|
+
let laneNames;
|
|
19613
|
+
let laneEventsByName;
|
|
19614
|
+
if (tagLanes) {
|
|
19615
|
+
laneNames = tagLanes.map((l) => l.name);
|
|
19616
|
+
laneEventsByName = new Map(tagLanes.map((l) => [l.name, l.events]));
|
|
19617
|
+
} else {
|
|
19618
|
+
const groupNames = timelineGroups.map((gr) => gr.name);
|
|
19619
|
+
const ungroupedEvents = timelineEvents.filter(
|
|
19620
|
+
(ev) => ev.group === null || !groupNames.includes(ev.group)
|
|
19621
|
+
);
|
|
19622
|
+
laneNames = ungroupedEvents.length > 0 ? [...groupNames, "(Other)"] : groupNames;
|
|
19623
|
+
laneEventsByName = new Map(
|
|
19624
|
+
laneNames.map((name) => [
|
|
19625
|
+
name,
|
|
19626
|
+
timelineEvents.filter(
|
|
19627
|
+
(ev) => name === "(Other)" ? ev.group === null || !groupNames.includes(ev.group) : ev.group === name
|
|
19628
|
+
)
|
|
19629
|
+
])
|
|
19630
|
+
);
|
|
19631
|
+
}
|
|
19547
19632
|
const laneCount = laneNames.length;
|
|
19548
19633
|
const scaleMargin = timelineScale ? 40 : 0;
|
|
19549
19634
|
const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
|
|
@@ -19598,6 +19683,13 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19598
19683
|
formatDateLabel(latestEndDateStr)
|
|
19599
19684
|
);
|
|
19600
19685
|
}
|
|
19686
|
+
if (timelineSwimlanes || tagLanes) {
|
|
19687
|
+
laneNames.forEach((laneName, laneIdx) => {
|
|
19688
|
+
const laneX = laneIdx * laneWidth;
|
|
19689
|
+
const fillColor = laneIdx % 2 === 0 ? textColor : "transparent";
|
|
19690
|
+
g.append("rect").attr("class", "tl-swimlane").attr("data-group", laneName).attr("x", laneX).attr("y", 0).attr("width", laneWidth).attr("height", innerHeight).attr("fill", fillColor).attr("opacity", 0.06);
|
|
19691
|
+
});
|
|
19692
|
+
}
|
|
19601
19693
|
laneNames.forEach((laneName, laneIdx) => {
|
|
19602
19694
|
const laneX = laneIdx * laneWidth;
|
|
19603
19695
|
const laneColor = groupColorMap.get(laneName) ?? textColor;
|
|
@@ -19605,9 +19697,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19605
19697
|
const headerG = g.append("g").attr("class", "tl-lane-header").attr("data-group", laneName).style("cursor", "pointer").on("mouseenter", () => fadeToGroup(g, laneName)).on("mouseleave", () => fadeReset(g));
|
|
19606
19698
|
headerG.append("text").attr("x", laneCenter).attr("y", -15).attr("text-anchor", "middle").attr("fill", laneColor).attr("font-size", "12px").attr("font-weight", "600").text(laneName);
|
|
19607
19699
|
g.append("line").attr("x1", laneCenter).attr("y1", 0).attr("x2", laneCenter).attr("y2", innerHeight).attr("stroke", mutedColor).attr("stroke-width", 1).attr("stroke-dasharray", "4,4");
|
|
19608
|
-
const laneEvents =
|
|
19609
|
-
(ev) => laneName === "(Other)" ? ev.group === null || !groupNames.includes(ev.group) : ev.group === laneName
|
|
19610
|
-
);
|
|
19700
|
+
const laneEvents = laneEventsByName.get(laneName) ?? [];
|
|
19611
19701
|
for (const ev of laneEvents) {
|
|
19612
19702
|
const y = yScale(parseTimelineDate(ev.date));
|
|
19613
19703
|
const evG = g.append("g").attr("class", "tl-event").attr("data-group", laneName).attr("data-line-number", String(ev.lineNumber)).attr("data-date", String(parseTimelineDate(ev.date))).attr(
|
|
@@ -19625,10 +19715,11 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19625
19715
|
if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
|
|
19626
19716
|
});
|
|
19627
19717
|
setTagAttrs(evG, ev);
|
|
19718
|
+
const evColor = eventColor(ev);
|
|
19628
19719
|
if (ev.endDate) {
|
|
19629
19720
|
const y2 = yScale(parseTimelineDate(ev.endDate));
|
|
19630
19721
|
const rectH = Math.max(y2 - y, 4);
|
|
19631
|
-
let fill2 =
|
|
19722
|
+
let fill2 = evColor;
|
|
19632
19723
|
if (ev.uncertain) {
|
|
19633
19724
|
const gradientId = `uncertain-vg-${ev.lineNumber}`;
|
|
19634
19725
|
const defs = svg.select("defs").node() || svg.append("defs").node();
|
|
@@ -19642,7 +19733,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19642
19733
|
evG.append("rect").attr("x", laneCenter - 6).attr("y", y).attr("width", 12).attr("height", rectH).attr("rx", 4).attr("fill", fill2);
|
|
19643
19734
|
evG.append("text").attr("x", laneCenter + 14).attr("y", y + rectH / 2).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "10px").text(ev.label);
|
|
19644
19735
|
} else {
|
|
19645
|
-
evG.append("circle").attr("cx", laneCenter).attr("cy", y).attr("r", 4).attr("fill",
|
|
19736
|
+
evG.append("circle").attr("cx", laneCenter).attr("cy", y).attr("r", 4).attr("fill", evColor).attr("stroke", bgColor).attr("stroke-width", 1.5);
|
|
19646
19737
|
evG.append("text").attr("x", laneCenter + 10).attr("y", y).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "10px").text(ev.label);
|
|
19647
19738
|
}
|
|
19648
19739
|
}
|
|
@@ -19765,18 +19856,24 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19765
19856
|
}
|
|
19766
19857
|
const BAR_H = 22;
|
|
19767
19858
|
const GROUP_GAP = 12;
|
|
19768
|
-
|
|
19769
|
-
|
|
19770
|
-
|
|
19771
|
-
|
|
19772
|
-
|
|
19773
|
-
|
|
19774
|
-
|
|
19775
|
-
|
|
19776
|
-
|
|
19777
|
-
|
|
19778
|
-
)
|
|
19779
|
-
|
|
19859
|
+
const useGroupedHorizontal = tagLanes != null || timelineSort === "group" && timelineGroups.length > 0;
|
|
19860
|
+
if (useGroupedHorizontal) {
|
|
19861
|
+
let lanes;
|
|
19862
|
+
if (tagLanes) {
|
|
19863
|
+
lanes = tagLanes;
|
|
19864
|
+
} else {
|
|
19865
|
+
const groupNames = timelineGroups.map((gr) => gr.name);
|
|
19866
|
+
const ungroupedEvents = timelineEvents.filter(
|
|
19867
|
+
(ev) => ev.group === null || !groupNames.includes(ev.group)
|
|
19868
|
+
);
|
|
19869
|
+
const laneNames = ungroupedEvents.length > 0 ? [...groupNames, "(Other)"] : groupNames;
|
|
19870
|
+
lanes = laneNames.map((name) => ({
|
|
19871
|
+
name,
|
|
19872
|
+
events: timelineEvents.filter(
|
|
19873
|
+
(ev) => name === "(Other)" ? ev.group === null || !groupNames.includes(ev.group) : ev.group === name
|
|
19874
|
+
)
|
|
19875
|
+
}));
|
|
19876
|
+
}
|
|
19780
19877
|
const totalEventRows = lanes.reduce((s, l) => s + l.events.length, 0);
|
|
19781
19878
|
const scaleMargin = timelineScale ? 24 : 0;
|
|
19782
19879
|
const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
|
|
@@ -19836,7 +19933,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19836
19933
|
);
|
|
19837
19934
|
}
|
|
19838
19935
|
let curY = markerMargin;
|
|
19839
|
-
if (timelineSwimlanes) {
|
|
19936
|
+
if (timelineSwimlanes || tagLanes) {
|
|
19840
19937
|
let swimY = markerMargin;
|
|
19841
19938
|
lanes.forEach((lane, idx) => {
|
|
19842
19939
|
const laneSpan = lane.events.length * rowH;
|
|
@@ -19888,12 +19985,13 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19888
19985
|
if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
|
|
19889
19986
|
});
|
|
19890
19987
|
setTagAttrs(evG, ev);
|
|
19988
|
+
const evColor = eventColor(ev);
|
|
19891
19989
|
if (ev.endDate) {
|
|
19892
19990
|
const x2 = xScale(parseTimelineDate(ev.endDate));
|
|
19893
19991
|
const rectW = Math.max(x2 - x, 4);
|
|
19894
19992
|
const estLabelWidth = ev.label.length * 7 + 16;
|
|
19895
19993
|
const labelFitsInside = rectW >= estLabelWidth;
|
|
19896
|
-
let fill2 =
|
|
19994
|
+
let fill2 = evColor;
|
|
19897
19995
|
if (ev.uncertain) {
|
|
19898
19996
|
const gradientId = `uncertain-${ev.lineNumber}`;
|
|
19899
19997
|
const defs = svg.select("defs").node() || svg.append("defs").node();
|
|
@@ -19901,7 +19999,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19901
19999
|
{ offset: "0%", opacity: 1 },
|
|
19902
20000
|
{ offset: "80%", opacity: 1 },
|
|
19903
20001
|
{ offset: "100%", opacity: 0 }
|
|
19904
|
-
]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color",
|
|
20002
|
+
]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", evColor).attr("stop-opacity", (d) => d.opacity);
|
|
19905
20003
|
fill2 = `url(#${gradientId})`;
|
|
19906
20004
|
}
|
|
19907
20005
|
evG.append("rect").attr("x", x).attr("y", y - BAR_H / 2).attr("width", rectW).attr("height", BAR_H).attr("rx", 4).attr("fill", fill2);
|
|
@@ -19918,7 +20016,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
19918
20016
|
const wouldFlipLeft = x > innerWidth * 0.6;
|
|
19919
20017
|
const labelFitsLeft = x - 10 - estLabelWidth > 0;
|
|
19920
20018
|
const flipLeft = wouldFlipLeft && labelFitsLeft;
|
|
19921
|
-
evG.append("circle").attr("cx", x).attr("cy", y).attr("r", 5).attr("fill",
|
|
20019
|
+
evG.append("circle").attr("cx", x).attr("cy", y).attr("r", 5).attr("fill", evColor).attr("stroke", bgColor).attr("stroke-width", 1.5);
|
|
19922
20020
|
evG.append("text").attr("x", flipLeft ? x - 10 : x + 10).attr("y", y).attr("dy", "0.35em").attr("text-anchor", flipLeft ? "end" : "start").attr("fill", textColor).attr("font-size", "12px").text(ev.label);
|
|
19923
20021
|
}
|
|
19924
20022
|
});
|
|
@@ -20073,26 +20171,62 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
20073
20171
|
const LG_ENTRY_DOT_GAP = 4;
|
|
20074
20172
|
const LG_ENTRY_TRAIL = 8;
|
|
20075
20173
|
const LG_GROUP_GAP = 12;
|
|
20174
|
+
const LG_ICON_W = 20;
|
|
20076
20175
|
const mainSvg = d3Selection12.select(container).select("svg");
|
|
20077
20176
|
const mainG = mainSvg.select("g");
|
|
20078
20177
|
if (!mainSvg.empty() && !mainG.empty()) {
|
|
20079
|
-
let
|
|
20178
|
+
let drawSwimlaneIcon2 = function(parent, x, y, isSwimActive) {
|
|
20179
|
+
const iconG = parent.append("g").attr("class", "tl-swimlane-icon").attr("transform", `translate(${x}, ${y})`).style("cursor", "pointer");
|
|
20180
|
+
const barColor = isSwimActive ? palette.primary : palette.textMuted;
|
|
20181
|
+
const barOpacity = isSwimActive ? 1 : 0.35;
|
|
20182
|
+
const bars = [
|
|
20183
|
+
{ y: 0, w: 8 },
|
|
20184
|
+
{ y: 4, w: 12 },
|
|
20185
|
+
{ y: 8, w: 6 }
|
|
20186
|
+
];
|
|
20187
|
+
for (const bar of bars) {
|
|
20188
|
+
iconG.append("rect").attr("x", 0).attr("y", bar.y).attr("width", bar.w).attr("height", 2).attr("rx", 1).attr("fill", barColor).attr("opacity", barOpacity);
|
|
20189
|
+
}
|
|
20190
|
+
return iconG;
|
|
20191
|
+
}, relayout2 = function() {
|
|
20192
|
+
renderTimeline(
|
|
20193
|
+
container,
|
|
20194
|
+
parsed,
|
|
20195
|
+
palette,
|
|
20196
|
+
isDark,
|
|
20197
|
+
onClickItem,
|
|
20198
|
+
exportDims,
|
|
20199
|
+
currentActiveGroup,
|
|
20200
|
+
currentSwimlaneGroup,
|
|
20201
|
+
onTagStateChange,
|
|
20202
|
+
viewMode
|
|
20203
|
+
);
|
|
20204
|
+
}, drawLegend2 = function() {
|
|
20080
20205
|
mainSvg.selectAll(".tl-tag-legend-group").remove();
|
|
20081
|
-
const
|
|
20206
|
+
const visibleGroups = viewMode ? legendGroups.filter(
|
|
20207
|
+
(lg) => currentActiveGroup != null && lg.group.name.toLowerCase() === currentActiveGroup.toLowerCase()
|
|
20208
|
+
) : legendGroups;
|
|
20209
|
+
if (visibleGroups.length === 0) return;
|
|
20210
|
+
const totalW = visibleGroups.reduce((s, lg) => {
|
|
20082
20211
|
const isActive = currentActiveGroup != null && lg.group.name.toLowerCase() === currentActiveGroup.toLowerCase();
|
|
20083
20212
|
return s + (isActive ? lg.expandedWidth : lg.minifiedWidth);
|
|
20084
|
-
}, 0) + (
|
|
20213
|
+
}, 0) + (visibleGroups.length - 1) * LG_GROUP_GAP;
|
|
20085
20214
|
let cx = (width - totalW) / 2;
|
|
20086
|
-
for (const lg of
|
|
20087
|
-
const
|
|
20215
|
+
for (const lg of visibleGroups) {
|
|
20216
|
+
const groupKey = lg.group.name.toLowerCase();
|
|
20217
|
+
const isActive = currentActiveGroup != null && currentActiveGroup.toLowerCase() === groupKey;
|
|
20218
|
+
const isSwimActive = currentSwimlaneGroup != null && currentSwimlaneGroup.toLowerCase() === groupKey;
|
|
20088
20219
|
const pillLabel = lg.group.name;
|
|
20089
20220
|
const pillWidth = pillLabel.length * LG_PILL_FONT_W + LG_PILL_PAD;
|
|
20090
|
-
const gEl = mainSvg.append("g").attr("transform", `translate(${cx}, ${legendY})`).attr("class", "tl-tag-legend-group tl-tag-legend-entry").attr("data-legend-group",
|
|
20091
|
-
|
|
20092
|
-
|
|
20093
|
-
|
|
20094
|
-
|
|
20095
|
-
|
|
20221
|
+
const gEl = mainSvg.append("g").attr("transform", `translate(${cx}, ${legendY})`).attr("class", "tl-tag-legend-group tl-tag-legend-entry").attr("data-legend-group", groupKey).attr("data-tag-group", groupKey).attr("data-legend-entry", "__group__");
|
|
20222
|
+
if (!viewMode) {
|
|
20223
|
+
gEl.style("cursor", "pointer").on("click", () => {
|
|
20224
|
+
currentActiveGroup = currentActiveGroup === groupKey ? null : groupKey;
|
|
20225
|
+
drawLegend2();
|
|
20226
|
+
recolorEvents2();
|
|
20227
|
+
onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
|
|
20228
|
+
});
|
|
20229
|
+
}
|
|
20096
20230
|
if (isActive) {
|
|
20097
20231
|
gEl.append("rect").attr("width", lg.expandedWidth).attr("height", LG_HEIGHT).attr("rx", LG_HEIGHT / 2).attr("fill", groupBg);
|
|
20098
20232
|
}
|
|
@@ -20105,27 +20239,44 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
20105
20239
|
}
|
|
20106
20240
|
gEl.append("text").attr("x", pillXOff + pillWidth / 2).attr("y", LG_HEIGHT / 2 + LG_PILL_FONT_SIZE / 2 - 2).attr("font-size", LG_PILL_FONT_SIZE).attr("font-weight", "500").attr("font-family", FONT_FAMILY).attr("fill", isActive ? palette.text : palette.textMuted).attr("text-anchor", "middle").text(pillLabel);
|
|
20107
20241
|
if (isActive) {
|
|
20108
|
-
let entryX
|
|
20242
|
+
let entryX;
|
|
20243
|
+
if (!viewMode) {
|
|
20244
|
+
const iconX = pillXOff + pillWidth + 5;
|
|
20245
|
+
const iconY = (LG_HEIGHT - 10) / 2;
|
|
20246
|
+
const iconEl = drawSwimlaneIcon2(gEl, iconX, iconY, isSwimActive);
|
|
20247
|
+
iconEl.attr("data-swimlane-toggle", groupKey).on("click", (event) => {
|
|
20248
|
+
event.stopPropagation();
|
|
20249
|
+
currentSwimlaneGroup = currentSwimlaneGroup === groupKey ? null : groupKey;
|
|
20250
|
+
onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
|
|
20251
|
+
relayout2();
|
|
20252
|
+
});
|
|
20253
|
+
entryX = pillXOff + pillWidth + LG_ICON_W + 4;
|
|
20254
|
+
} else {
|
|
20255
|
+
entryX = pillXOff + pillWidth + 8;
|
|
20256
|
+
}
|
|
20109
20257
|
for (const entry of lg.group.entries) {
|
|
20110
20258
|
const tagKey = lg.group.name.toLowerCase();
|
|
20111
20259
|
const tagVal = entry.value.toLowerCase();
|
|
20112
|
-
const entryG = gEl.append("g").attr("class", "tl-tag-legend-entry").attr("data-tag-group", tagKey).attr("data-legend-entry", tagVal)
|
|
20113
|
-
|
|
20114
|
-
|
|
20115
|
-
|
|
20116
|
-
|
|
20117
|
-
|
|
20118
|
-
|
|
20119
|
-
|
|
20120
|
-
|
|
20260
|
+
const entryG = gEl.append("g").attr("class", "tl-tag-legend-entry").attr("data-tag-group", tagKey).attr("data-legend-entry", tagVal);
|
|
20261
|
+
if (!viewMode) {
|
|
20262
|
+
entryG.style("cursor", "pointer").on("mouseenter", (event) => {
|
|
20263
|
+
event.stopPropagation();
|
|
20264
|
+
fadeToTagValue(mainG, tagKey, tagVal);
|
|
20265
|
+
mainSvg.selectAll(".tl-tag-legend-entry").each(function() {
|
|
20266
|
+
const el = d3Selection12.select(this);
|
|
20267
|
+
const ev = el.attr("data-legend-entry");
|
|
20268
|
+
if (ev === "__group__") return;
|
|
20269
|
+
const eg = el.attr("data-tag-group");
|
|
20270
|
+
el.attr("opacity", eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY);
|
|
20271
|
+
});
|
|
20272
|
+
}).on("mouseleave", (event) => {
|
|
20273
|
+
event.stopPropagation();
|
|
20274
|
+
fadeReset(mainG);
|
|
20275
|
+
mainSvg.selectAll(".tl-tag-legend-entry").attr("opacity", 1);
|
|
20276
|
+
}).on("click", (event) => {
|
|
20277
|
+
event.stopPropagation();
|
|
20121
20278
|
});
|
|
20122
|
-
}
|
|
20123
|
-
event.stopPropagation();
|
|
20124
|
-
fadeReset(mainG);
|
|
20125
|
-
mainSvg.selectAll(".tl-tag-legend-entry").attr("opacity", 1);
|
|
20126
|
-
}).on("click", (event) => {
|
|
20127
|
-
event.stopPropagation();
|
|
20128
|
-
});
|
|
20279
|
+
}
|
|
20129
20280
|
entryG.append("circle").attr("cx", entryX + LG_DOT_R).attr("cy", LG_HEIGHT / 2).attr("r", LG_DOT_R).attr("fill", entry.color);
|
|
20130
20281
|
const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
|
|
20131
20282
|
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);
|
|
@@ -20135,17 +20286,18 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
20135
20286
|
cx += (isActive ? lg.expandedWidth : lg.minifiedWidth) + LG_GROUP_GAP;
|
|
20136
20287
|
}
|
|
20137
20288
|
}, recolorEvents2 = function() {
|
|
20289
|
+
const colorTG = currentActiveGroup ?? swimlaneTagGroup ?? null;
|
|
20138
20290
|
mainG.selectAll(".tl-event").each(function() {
|
|
20139
20291
|
const el = d3Selection12.select(this);
|
|
20140
20292
|
const lineNum = el.attr("data-line-number");
|
|
20141
20293
|
const ev = lineNum ? eventByLine.get(lineNum) : void 0;
|
|
20142
20294
|
if (!ev) return;
|
|
20143
20295
|
let color;
|
|
20144
|
-
if (
|
|
20296
|
+
if (colorTG) {
|
|
20145
20297
|
const tagColor = resolveTagColor(
|
|
20146
20298
|
ev.metadata,
|
|
20147
20299
|
parsed.timelineTagGroups,
|
|
20148
|
-
|
|
20300
|
+
colorTG
|
|
20149
20301
|
);
|
|
20150
20302
|
color = tagColor ?? (ev.group && groupColorMap.has(ev.group) ? groupColorMap.get(ev.group) : textColor);
|
|
20151
20303
|
} else {
|
|
@@ -20155,12 +20307,13 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
20155
20307
|
el.selectAll("circle:not(.tl-event-point-outline)").attr("fill", color);
|
|
20156
20308
|
});
|
|
20157
20309
|
};
|
|
20158
|
-
var drawLegend = drawLegend2, recolorEvents = recolorEvents2;
|
|
20310
|
+
var drawSwimlaneIcon = drawSwimlaneIcon2, relayout = relayout2, drawLegend = drawLegend2, recolorEvents = recolorEvents2;
|
|
20159
20311
|
const legendY = title ? 50 : 10;
|
|
20160
20312
|
const groupBg = isDark ? mix(palette.surface, palette.bg, 50) : mix(palette.surface, palette.bg, 30);
|
|
20161
20313
|
const legendGroups = parsed.timelineTagGroups.map((g) => {
|
|
20162
20314
|
const pillW = g.name.length * LG_PILL_FONT_W + LG_PILL_PAD;
|
|
20163
|
-
|
|
20315
|
+
const iconSpace = viewMode ? 8 : LG_ICON_W + 4;
|
|
20316
|
+
let entryX = LG_CAPSULE_PAD + pillW + iconSpace;
|
|
20164
20317
|
for (const entry of g.entries) {
|
|
20165
20318
|
const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
|
|
20166
20319
|
entryX = textX + entry.value.length * LG_ENTRY_FONT_W + LG_ENTRY_TRAIL;
|
|
@@ -20172,6 +20325,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
20172
20325
|
};
|
|
20173
20326
|
});
|
|
20174
20327
|
let currentActiveGroup = activeTagGroup ?? null;
|
|
20328
|
+
let currentSwimlaneGroup = swimlaneTagGroup ?? null;
|
|
20175
20329
|
const eventByLine = /* @__PURE__ */ new Map();
|
|
20176
20330
|
for (const ev of timelineEvents) {
|
|
20177
20331
|
eventByLine.set(String(ev.lineNumber), ev);
|
|
@@ -21146,7 +21300,16 @@ async function renderD3ForExport(content, theme, palette, orgExportState, option
|
|
|
21146
21300
|
} else if (parsed.type === "arc") {
|
|
21147
21301
|
renderArcDiagram(container, parsed, effectivePalette, isDark, void 0, dims);
|
|
21148
21302
|
} else if (parsed.type === "timeline") {
|
|
21149
|
-
renderTimeline(
|
|
21303
|
+
renderTimeline(
|
|
21304
|
+
container,
|
|
21305
|
+
parsed,
|
|
21306
|
+
effectivePalette,
|
|
21307
|
+
isDark,
|
|
21308
|
+
void 0,
|
|
21309
|
+
dims,
|
|
21310
|
+
orgExportState?.activeTagGroup,
|
|
21311
|
+
orgExportState?.swimlaneTagGroup
|
|
21312
|
+
);
|
|
21150
21313
|
} else if (parsed.type === "venn") {
|
|
21151
21314
|
renderVenn(container, parsed, effectivePalette, isDark, void 0, dims);
|
|
21152
21315
|
} else if (parsed.type === "quadrant") {
|
|
@@ -22173,6 +22336,9 @@ function encodeDiagramUrl(dsl, options) {
|
|
|
22173
22336
|
if (options?.viewState?.collapsedGroups?.length) {
|
|
22174
22337
|
hash += `&cg=${encodeURIComponent(options.viewState.collapsedGroups.join(","))}`;
|
|
22175
22338
|
}
|
|
22339
|
+
if (options?.viewState?.swimlaneTagGroup) {
|
|
22340
|
+
hash += `&swim=${encodeURIComponent(options.viewState.swimlaneTagGroup)}`;
|
|
22341
|
+
}
|
|
22176
22342
|
return { url: `${baseUrl}?${hash}#${hash}` };
|
|
22177
22343
|
}
|
|
22178
22344
|
function decodeDiagramUrl(hash) {
|
|
@@ -22196,6 +22362,9 @@ function decodeDiagramUrl(hash) {
|
|
|
22196
22362
|
if (key === "cg" && val) {
|
|
22197
22363
|
viewState.collapsedGroups = val.split(",").filter(Boolean);
|
|
22198
22364
|
}
|
|
22365
|
+
if (key === "swim" && val) {
|
|
22366
|
+
viewState.swimlaneTagGroup = val;
|
|
22367
|
+
}
|
|
22199
22368
|
}
|
|
22200
22369
|
if (payload.startsWith("dgmo=")) {
|
|
22201
22370
|
payload = payload.slice(5);
|