@transitrix/diagrams 1.12.1 → 1.13.0

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.
@@ -13,7 +13,7 @@
13
13
  import { layoutGoalTree } from '../goals/layout.js';
14
14
  import type { GoalTree, GoalTreeLayout, LaidOutEdge } from '../goals/types.js';
15
15
  import { displayGoalId } from '../goals/parse-canonical.js';
16
- import { horizontalCubicEdgePath, DEFAULT_EDGE_CURVATURE } from '../edge-path.js';
16
+ import { previewEdgePath, DEFAULT_EDGE_CURVATURE, type EdgeStyle } from '../edge-path.js';
17
17
  import { parseNodeSizePreset, resolveGoalsNodeSize, type NodeSizePreset } from '../node-size-presets.js';
18
18
  import { generateSvgEmbedCss, type ThemeId } from '../theme/index.js';
19
19
  import { emitCenteredTextSvg, layoutCenteredEntityText } from './entity-text-layout.js';
@@ -28,6 +28,7 @@ export interface RenderGoalsOptions {
28
28
  treeName?: string;
29
29
  curvature?: number;
30
30
  entryCurvature?: number;
31
+ edgeStyle?: EdgeStyle;
31
32
  nodeSizePreset?: NodeSizePreset;
32
33
  }
33
34
 
@@ -37,7 +38,7 @@ export interface RenderGoalsOptions {
37
38
  * with the shared theme CSS embedded so the output is self-contained.
38
39
  */
39
40
  export function renderGoalsSvg(tree: GoalTree, options: RenderGoalsOptions = {}): string {
40
- const { treeName = '', curvature = DEFAULT_EDGE_CURVATURE, entryCurvature, nodeSizePreset = 'normal' } = options;
41
+ const { treeName = '', curvature = DEFAULT_EDGE_CURVATURE, entryCurvature, edgeStyle, nodeSizePreset = 'normal' } = options;
41
42
  const nodeSize = resolveGoalsNodeSize(parseNodeSizePreset(nodeSizePreset));
42
43
 
43
44
  const layout: GoalTreeLayout = layoutGoalTree(tree, {
@@ -55,12 +56,13 @@ export function renderGoalsSvg(tree: GoalTree, options: RenderGoalsOptions = {})
55
56
  ? `<text class="text-header" x="${PAD}" y="${PAD - 6}">${escXml(`Goal tree — ${treeName}`)}</text>`
56
57
  : '';
57
58
 
58
- return renderGoalsLayoutSvg(layout, { curvature, entryCurvature, title, embedCssTheme: 'transitrix' });
59
+ return renderGoalsLayoutSvg(layout, { curvature, entryCurvature, edgeStyle, title, embedCssTheme: 'transitrix' });
59
60
  }
60
61
 
61
62
  export interface RenderGoalsLayoutOptions {
62
63
  curvature?: number;
63
64
  entryCurvature?: number;
65
+ edgeStyle?: EdgeStyle;
64
66
  /** Extra vertical space reserved at the top of the canvas (e.g. for a title block). */
65
67
  topInset?: number;
66
68
  /** Raw SVG injected immediately after `<defs>` — a header line or a full title block. */
@@ -78,7 +80,7 @@ export interface RenderGoalsLayoutOptions {
78
80
  * and the export path own styling).
79
81
  */
80
82
  export function renderGoalsLayoutSvg(layout: GoalTreeLayout, options: RenderGoalsLayoutOptions = {}): string {
81
- const { curvature = DEFAULT_EDGE_CURVATURE, entryCurvature, topInset = 0, title = '', embedCssTheme } = options;
83
+ const { curvature = DEFAULT_EDGE_CURVATURE, entryCurvature, edgeStyle, topInset = 0, title = '', embedCssTheme } = options;
82
84
 
83
85
  const w = layout.bounds.width + PAD * 2;
84
86
  const h = layout.bounds.height + PAD * 2 + topInset;
@@ -95,7 +97,7 @@ export function renderGoalsLayoutSvg(layout: GoalTreeLayout, options: RenderGoal
95
97
  const sy = s.y + oy + s.height / 2;
96
98
  const tx = t.x + ox;
97
99
  const ty = t.y + oy + t.height / 2;
98
- return horizontalCubicEdgePath(sx, sy, tx, ty, curvature, entryCurvature);
100
+ return previewEdgePath(sx, sy, tx, ty, edgeStyle, curvature, entryCurvature);
99
101
  }
100
102
 
101
103
  const edgeSvg = layout.edges
@@ -122,7 +124,11 @@ export function renderGoalsLayoutSvg(layout: GoalTreeLayout, options: RenderGoal
122
124
  idMaxLines: 1,
123
125
  });
124
126
  const textSvg = emitCenteredTextSvg(specs, x + n.width / 2, escXml);
127
+ const titleParts = [escXml(labelText), escXml(idText)];
128
+ if (n.data.level !== undefined) titleParts.push(`level ${n.data.level}`);
129
+ const titleContent = titleParts.join(' — ');
125
130
  return `<g>
131
+ <title>${titleContent}</title>
126
132
  <rect class="diagram-node level-${level}" x="${x}" y="${y}" width="${n.width}" height="${n.height}" rx="${ENTITY_NODE_RX}"/>
127
133
  ${textSvg}
128
134
  </g>`;