@diagrammo/dgmo 0.5.1 → 0.5.3
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 +123 -123
- package/dist/index.cjs +58 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +58 -40
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/d3.ts +85 -54
package/package.json
CHANGED
package/src/d3.ts
CHANGED
|
@@ -2817,7 +2817,8 @@ export function renderTimeline(
|
|
|
2817
2817
|
exportDims?: D3ExportDimensions,
|
|
2818
2818
|
activeTagGroup?: string | null,
|
|
2819
2819
|
swimlaneTagGroup?: string | null,
|
|
2820
|
-
onTagStateChange?: (activeTagGroup: string | null, swimlaneTagGroup: string | null) => void
|
|
2820
|
+
onTagStateChange?: (activeTagGroup: string | null, swimlaneTagGroup: string | null) => void,
|
|
2821
|
+
viewMode?: boolean
|
|
2821
2822
|
): void {
|
|
2822
2823
|
d3Selection.select(container).selectAll(':not([data-d3-tooltip])').remove();
|
|
2823
2824
|
|
|
@@ -4151,8 +4152,9 @@ export function renderTimeline(
|
|
|
4151
4152
|
};
|
|
4152
4153
|
const legendGroups: LegendGroup[] = parsed.timelineTagGroups.map((g) => {
|
|
4153
4154
|
const pillW = g.name.length * LG_PILL_FONT_W + LG_PILL_PAD;
|
|
4154
|
-
// Expanded: pill + icon + entries
|
|
4155
|
-
|
|
4155
|
+
// Expanded: pill + icon (unless viewMode) + entries
|
|
4156
|
+
const iconSpace = viewMode ? 8 : LG_ICON_W + 4;
|
|
4157
|
+
let entryX = LG_CAPSULE_PAD + pillW + iconSpace;
|
|
4156
4158
|
for (const entry of g.entries) {
|
|
4157
4159
|
const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
|
|
4158
4160
|
entryX = textX + entry.value.length * LG_ENTRY_FONT_W + LG_ENTRY_TRAIL;
|
|
@@ -4204,7 +4206,7 @@ export function renderTimeline(
|
|
|
4204
4206
|
function relayout() {
|
|
4205
4207
|
renderTimeline(
|
|
4206
4208
|
container, parsed, palette, isDark, onClickItem, exportDims,
|
|
4207
|
-
currentActiveGroup, currentSwimlaneGroup, onTagStateChange
|
|
4209
|
+
currentActiveGroup, currentSwimlaneGroup, onTagStateChange, viewMode
|
|
4208
4210
|
);
|
|
4209
4211
|
}
|
|
4210
4212
|
|
|
@@ -4212,19 +4214,36 @@ export function renderTimeline(
|
|
|
4212
4214
|
// Remove previous legend
|
|
4213
4215
|
mainSvg.selectAll('.tl-tag-legend-group').remove();
|
|
4214
4216
|
|
|
4217
|
+
// Effective color source: explicit color group > swimlane group
|
|
4218
|
+
const effectiveColorKey = (currentActiveGroup ?? currentSwimlaneGroup)?.toLowerCase() ?? null;
|
|
4219
|
+
|
|
4220
|
+
// In view mode, only show the color-driving tag group (expanded, non-interactive).
|
|
4221
|
+
// Skip the swimlane group if it's separate from the color group (lane headers already label it).
|
|
4222
|
+
const visibleGroups = viewMode
|
|
4223
|
+
? legendGroups.filter(
|
|
4224
|
+
(lg) =>
|
|
4225
|
+
effectiveColorKey != null &&
|
|
4226
|
+
lg.group.name.toLowerCase() === effectiveColorKey
|
|
4227
|
+
)
|
|
4228
|
+
: legendGroups;
|
|
4229
|
+
|
|
4230
|
+
if (visibleGroups.length === 0) return;
|
|
4231
|
+
|
|
4215
4232
|
// Compute total width and center horizontally in SVG
|
|
4216
|
-
const totalW =
|
|
4217
|
-
const isActive =
|
|
4218
|
-
|
|
4233
|
+
const totalW = visibleGroups.reduce((s, lg) => {
|
|
4234
|
+
const isActive = viewMode ||
|
|
4235
|
+
(currentActiveGroup != null &&
|
|
4236
|
+
lg.group.name.toLowerCase() === currentActiveGroup.toLowerCase());
|
|
4219
4237
|
return s + (isActive ? lg.expandedWidth : lg.minifiedWidth);
|
|
4220
|
-
}, 0) + (
|
|
4238
|
+
}, 0) + (visibleGroups.length - 1) * LG_GROUP_GAP;
|
|
4221
4239
|
|
|
4222
4240
|
let cx = (width - totalW) / 2;
|
|
4223
4241
|
|
|
4224
|
-
for (const lg of
|
|
4242
|
+
for (const lg of visibleGroups) {
|
|
4225
4243
|
const groupKey = lg.group.name.toLowerCase();
|
|
4226
|
-
const isActive =
|
|
4227
|
-
currentActiveGroup
|
|
4244
|
+
const isActive = viewMode ||
|
|
4245
|
+
(currentActiveGroup != null &&
|
|
4246
|
+
currentActiveGroup.toLowerCase() === groupKey);
|
|
4228
4247
|
const isSwimActive = currentSwimlaneGroup != null &&
|
|
4229
4248
|
currentSwimlaneGroup.toLowerCase() === groupKey;
|
|
4230
4249
|
|
|
@@ -4237,14 +4256,18 @@ export function renderTimeline(
|
|
|
4237
4256
|
.attr('class', 'tl-tag-legend-group tl-tag-legend-entry')
|
|
4238
4257
|
.attr('data-legend-group', groupKey)
|
|
4239
4258
|
.attr('data-tag-group', groupKey)
|
|
4240
|
-
.attr('data-legend-entry', '__group__')
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4259
|
+
.attr('data-legend-entry', '__group__');
|
|
4260
|
+
|
|
4261
|
+
if (!viewMode) {
|
|
4262
|
+
gEl
|
|
4263
|
+
.style('cursor', 'pointer')
|
|
4264
|
+
.on('click', () => {
|
|
4265
|
+
currentActiveGroup = currentActiveGroup === groupKey ? null : groupKey;
|
|
4266
|
+
drawLegend();
|
|
4267
|
+
recolorEvents();
|
|
4268
|
+
onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
|
|
4269
|
+
});
|
|
4270
|
+
}
|
|
4248
4271
|
|
|
4249
4272
|
// Outer capsule background (active only)
|
|
4250
4273
|
if (isActive) {
|
|
@@ -4294,20 +4317,25 @@ export function renderTimeline(
|
|
|
4294
4317
|
|
|
4295
4318
|
// Entries + swimlane icon inside capsule (active only)
|
|
4296
4319
|
if (isActive) {
|
|
4297
|
-
// Swimlane icon
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4320
|
+
// Swimlane icon (skip in view mode — non-interactive)
|
|
4321
|
+
let entryX: number;
|
|
4322
|
+
if (!viewMode) {
|
|
4323
|
+
const iconX = pillXOff + pillWidth + 5;
|
|
4324
|
+
const iconY = (LG_HEIGHT - 10) / 2; // vertically centered
|
|
4325
|
+
const iconEl = drawSwimlaneIcon(gEl, iconX, iconY, isSwimActive);
|
|
4326
|
+
iconEl
|
|
4327
|
+
.attr('data-swimlane-toggle', groupKey)
|
|
4328
|
+
.on('click', (event: MouseEvent) => {
|
|
4329
|
+
event.stopPropagation();
|
|
4330
|
+
currentSwimlaneGroup = currentSwimlaneGroup === groupKey ? null : groupKey;
|
|
4331
|
+
onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
|
|
4332
|
+
relayout();
|
|
4333
|
+
});
|
|
4334
|
+
entryX = pillXOff + pillWidth + LG_ICON_W + 4;
|
|
4335
|
+
} else {
|
|
4336
|
+
entryX = pillXOff + pillWidth + 8;
|
|
4337
|
+
}
|
|
4309
4338
|
|
|
4310
|
-
let entryX = pillXOff + pillWidth + LG_ICON_W + 4;
|
|
4311
4339
|
for (const entry of lg.group.entries) {
|
|
4312
4340
|
const tagKey = lg.group.name.toLowerCase();
|
|
4313
4341
|
const tagVal = entry.value.toLowerCase();
|
|
@@ -4315,29 +4343,32 @@ export function renderTimeline(
|
|
|
4315
4343
|
const entryG = gEl.append('g')
|
|
4316
4344
|
.attr('class', 'tl-tag-legend-entry')
|
|
4317
4345
|
.attr('data-tag-group', tagKey)
|
|
4318
|
-
.attr('data-legend-entry', tagVal)
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4346
|
+
.attr('data-legend-entry', tagVal);
|
|
4347
|
+
|
|
4348
|
+
if (!viewMode) {
|
|
4349
|
+
entryG
|
|
4350
|
+
.style('cursor', 'pointer')
|
|
4351
|
+
.on('mouseenter', (event: MouseEvent) => {
|
|
4352
|
+
event.stopPropagation();
|
|
4353
|
+
fadeToTagValue(mainG, tagKey, tagVal);
|
|
4354
|
+
mainSvg.selectAll<SVGGElement, unknown>('.tl-tag-legend-entry').each(function () {
|
|
4355
|
+
const el = d3Selection.select(this);
|
|
4356
|
+
const ev = el.attr('data-legend-entry');
|
|
4357
|
+
if (ev === '__group__') return;
|
|
4358
|
+
const eg = el.attr('data-tag-group');
|
|
4359
|
+
el.attr('opacity', eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY);
|
|
4360
|
+
});
|
|
4361
|
+
})
|
|
4362
|
+
.on('mouseleave', (event: MouseEvent) => {
|
|
4363
|
+
event.stopPropagation();
|
|
4364
|
+
fadeReset(mainG);
|
|
4365
|
+
mainSvg.selectAll<SVGGElement, unknown>('.tl-tag-legend-entry')
|
|
4366
|
+
.attr('opacity', 1);
|
|
4367
|
+
})
|
|
4368
|
+
.on('click', (event: MouseEvent) => {
|
|
4369
|
+
event.stopPropagation();
|
|
4330
4370
|
});
|
|
4331
|
-
|
|
4332
|
-
.on('mouseleave', (event: MouseEvent) => {
|
|
4333
|
-
event.stopPropagation();
|
|
4334
|
-
fadeReset(mainG);
|
|
4335
|
-
mainSvg.selectAll<SVGGElement, unknown>('.tl-tag-legend-entry')
|
|
4336
|
-
.attr('opacity', 1);
|
|
4337
|
-
})
|
|
4338
|
-
.on('click', (event: MouseEvent) => {
|
|
4339
|
-
event.stopPropagation(); // don't toggle group
|
|
4340
|
-
});
|
|
4371
|
+
}
|
|
4341
4372
|
|
|
4342
4373
|
entryG.append('circle')
|
|
4343
4374
|
.attr('cx', entryX + LG_DOT_R)
|