@diagrammo/dgmo 0.5.1 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diagrammo/dgmo",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "DGMO diagram markup language — parser, renderer, and color system",
5
5
  "license": "MIT",
6
6
  "type": "module",
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
- let entryX = LG_CAPSULE_PAD + pillW + LG_ICON_W + 4;
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,16 +4214,27 @@ export function renderTimeline(
4212
4214
  // Remove previous legend
4213
4215
  mainSvg.selectAll('.tl-tag-legend-group').remove();
4214
4216
 
4217
+ // In view mode, only show the active color tag group (expanded, non-interactive)
4218
+ const visibleGroups = viewMode
4219
+ ? legendGroups.filter(
4220
+ (lg) =>
4221
+ currentActiveGroup != null &&
4222
+ lg.group.name.toLowerCase() === currentActiveGroup.toLowerCase()
4223
+ )
4224
+ : legendGroups;
4225
+
4226
+ if (visibleGroups.length === 0) return;
4227
+
4215
4228
  // Compute total width and center horizontally in SVG
4216
- const totalW = legendGroups.reduce((s, lg) => {
4229
+ const totalW = visibleGroups.reduce((s, lg) => {
4217
4230
  const isActive = currentActiveGroup != null &&
4218
4231
  lg.group.name.toLowerCase() === currentActiveGroup.toLowerCase();
4219
4232
  return s + (isActive ? lg.expandedWidth : lg.minifiedWidth);
4220
- }, 0) + (legendGroups.length - 1) * LG_GROUP_GAP;
4233
+ }, 0) + (visibleGroups.length - 1) * LG_GROUP_GAP;
4221
4234
 
4222
4235
  let cx = (width - totalW) / 2;
4223
4236
 
4224
- for (const lg of legendGroups) {
4237
+ for (const lg of visibleGroups) {
4225
4238
  const groupKey = lg.group.name.toLowerCase();
4226
4239
  const isActive = currentActiveGroup != null &&
4227
4240
  currentActiveGroup.toLowerCase() === groupKey;
@@ -4237,14 +4250,18 @@ export function renderTimeline(
4237
4250
  .attr('class', 'tl-tag-legend-group tl-tag-legend-entry')
4238
4251
  .attr('data-legend-group', groupKey)
4239
4252
  .attr('data-tag-group', groupKey)
4240
- .attr('data-legend-entry', '__group__')
4241
- .style('cursor', 'pointer')
4242
- .on('click', () => {
4243
- currentActiveGroup = currentActiveGroup === groupKey ? null : groupKey;
4244
- drawLegend();
4245
- recolorEvents();
4246
- onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
4247
- });
4253
+ .attr('data-legend-entry', '__group__');
4254
+
4255
+ if (!viewMode) {
4256
+ gEl
4257
+ .style('cursor', 'pointer')
4258
+ .on('click', () => {
4259
+ currentActiveGroup = currentActiveGroup === groupKey ? null : groupKey;
4260
+ drawLegend();
4261
+ recolorEvents();
4262
+ onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
4263
+ });
4264
+ }
4248
4265
 
4249
4266
  // Outer capsule background (active only)
4250
4267
  if (isActive) {
@@ -4294,20 +4311,25 @@ export function renderTimeline(
4294
4311
 
4295
4312
  // Entries + swimlane icon inside capsule (active only)
4296
4313
  if (isActive) {
4297
- // Swimlane icon right after the pill label, with breathing room
4298
- const iconX = pillXOff + pillWidth + 5;
4299
- const iconY = (LG_HEIGHT - 10) / 2; // vertically centered
4300
- const iconEl = drawSwimlaneIcon(gEl, iconX, iconY, isSwimActive);
4301
- iconEl
4302
- .attr('data-swimlane-toggle', groupKey)
4303
- .on('click', (event: MouseEvent) => {
4304
- event.stopPropagation();
4305
- currentSwimlaneGroup = currentSwimlaneGroup === groupKey ? null : groupKey;
4306
- onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
4307
- relayout();
4308
- });
4314
+ // Swimlane icon (skip in view mode non-interactive)
4315
+ let entryX: number;
4316
+ if (!viewMode) {
4317
+ const iconX = pillXOff + pillWidth + 5;
4318
+ const iconY = (LG_HEIGHT - 10) / 2; // vertically centered
4319
+ const iconEl = drawSwimlaneIcon(gEl, iconX, iconY, isSwimActive);
4320
+ iconEl
4321
+ .attr('data-swimlane-toggle', groupKey)
4322
+ .on('click', (event: MouseEvent) => {
4323
+ event.stopPropagation();
4324
+ currentSwimlaneGroup = currentSwimlaneGroup === groupKey ? null : groupKey;
4325
+ onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
4326
+ relayout();
4327
+ });
4328
+ entryX = pillXOff + pillWidth + LG_ICON_W + 4;
4329
+ } else {
4330
+ entryX = pillXOff + pillWidth + 8;
4331
+ }
4309
4332
 
4310
- let entryX = pillXOff + pillWidth + LG_ICON_W + 4;
4311
4333
  for (const entry of lg.group.entries) {
4312
4334
  const tagKey = lg.group.name.toLowerCase();
4313
4335
  const tagVal = entry.value.toLowerCase();
@@ -4315,29 +4337,32 @@ export function renderTimeline(
4315
4337
  const entryG = gEl.append('g')
4316
4338
  .attr('class', 'tl-tag-legend-entry')
4317
4339
  .attr('data-tag-group', tagKey)
4318
- .attr('data-legend-entry', tagVal)
4319
- .style('cursor', 'pointer')
4320
- .on('mouseenter', (event: MouseEvent) => {
4321
- event.stopPropagation();
4322
- fadeToTagValue(mainG, tagKey, tagVal);
4323
- // Also fade legend entries on the SVG level
4324
- mainSvg.selectAll<SVGGElement, unknown>('.tl-tag-legend-entry').each(function () {
4325
- const el = d3Selection.select(this);
4326
- const ev = el.attr('data-legend-entry');
4327
- if (ev === '__group__') return;
4328
- const eg = el.attr('data-tag-group');
4329
- el.attr('opacity', eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY);
4340
+ .attr('data-legend-entry', tagVal);
4341
+
4342
+ if (!viewMode) {
4343
+ entryG
4344
+ .style('cursor', 'pointer')
4345
+ .on('mouseenter', (event: MouseEvent) => {
4346
+ event.stopPropagation();
4347
+ fadeToTagValue(mainG, tagKey, tagVal);
4348
+ mainSvg.selectAll<SVGGElement, unknown>('.tl-tag-legend-entry').each(function () {
4349
+ const el = d3Selection.select(this);
4350
+ const ev = el.attr('data-legend-entry');
4351
+ if (ev === '__group__') return;
4352
+ const eg = el.attr('data-tag-group');
4353
+ el.attr('opacity', eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY);
4354
+ });
4355
+ })
4356
+ .on('mouseleave', (event: MouseEvent) => {
4357
+ event.stopPropagation();
4358
+ fadeReset(mainG);
4359
+ mainSvg.selectAll<SVGGElement, unknown>('.tl-tag-legend-entry')
4360
+ .attr('opacity', 1);
4361
+ })
4362
+ .on('click', (event: MouseEvent) => {
4363
+ event.stopPropagation();
4330
4364
  });
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
- });
4365
+ }
4341
4366
 
4342
4367
  entryG.append('circle')
4343
4368
  .attr('cx', entryX + LG_DOT_R)