@bpmnkit/canvas 0.0.8

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.
@@ -0,0 +1,171 @@
1
+ const NS = "http://www.w3.org/2000/svg";
2
+ function svgEl(tag) {
3
+ return document.createElementNS(NS, tag);
4
+ }
5
+ function attr(el, attrs) {
6
+ for (const [k, v] of Object.entries(attrs))
7
+ el.setAttribute(k, String(v));
8
+ }
9
+ /**
10
+ * A scaled-down overview of the BPMN diagram that shows the current viewport
11
+ * position as a highlighted rectangle.
12
+ *
13
+ * Clicking the minimap pans the canvas to that position.
14
+ */
15
+ export class Minimap {
16
+ _onNavigate;
17
+ _host;
18
+ _svg;
19
+ _shapesG;
20
+ _edgesG;
21
+ _viewportRect;
22
+ // Minimap-space transform from diagram-space coordinates
23
+ _scale = 1;
24
+ _offsetX = 0;
25
+ _offsetY = 0;
26
+ // Diagram bounding box
27
+ _diagramMinX = 0;
28
+ _diagramMinY = 0;
29
+ _diagramW = 1;
30
+ _diagramH = 1;
31
+ // Minimap pixel dimensions
32
+ _mmW = 160;
33
+ _mmH = 100;
34
+ constructor(container,
35
+ /** Invoked when the user clicks the minimap to request a viewport pan. */
36
+ _onNavigate) {
37
+ this._onNavigate = _onNavigate;
38
+ this._host = document.createElement("div");
39
+ this._host.className = "bpmn-minimap";
40
+ this._host.setAttribute("aria-hidden", "true");
41
+ this._svg = document.createElementNS(NS, "svg");
42
+ attr(this._svg, {
43
+ viewBox: `0 0 ${this._mmW} ${this._mmH}`,
44
+ preserveAspectRatio: "none",
45
+ });
46
+ this._host.appendChild(this._svg);
47
+ this._edgesG = svgEl("g");
48
+ this._shapesG = svgEl("g");
49
+ this._viewportRect = svgEl("rect");
50
+ attr(this._viewportRect, { class: "bpmn-minimap-viewport", rx: 1 });
51
+ this._svg.appendChild(this._edgesG);
52
+ this._svg.appendChild(this._shapesG);
53
+ this._svg.appendChild(this._viewportRect);
54
+ container.appendChild(this._host);
55
+ this._host.addEventListener("click", this._onClick);
56
+ }
57
+ /** Updates the minimap with shapes and edges from a newly loaded diagram. */
58
+ update(defs) {
59
+ this._edgesG.innerHTML = "";
60
+ this._shapesG.innerHTML = "";
61
+ const plane = defs.diagrams[0]?.plane;
62
+ if (!plane)
63
+ return;
64
+ // Compute diagram bounding box
65
+ let minX = Number.POSITIVE_INFINITY;
66
+ let minY = Number.POSITIVE_INFINITY;
67
+ let maxX = Number.NEGATIVE_INFINITY;
68
+ let maxY = Number.NEGATIVE_INFINITY;
69
+ for (const s of plane.shapes) {
70
+ minX = Math.min(minX, s.bounds.x);
71
+ minY = Math.min(minY, s.bounds.y);
72
+ maxX = Math.max(maxX, s.bounds.x + s.bounds.width);
73
+ maxY = Math.max(maxY, s.bounds.y + s.bounds.height);
74
+ }
75
+ for (const e of plane.edges) {
76
+ for (const wp of e.waypoints) {
77
+ minX = Math.min(minX, wp.x);
78
+ minY = Math.min(minY, wp.y);
79
+ maxX = Math.max(maxX, wp.x);
80
+ maxY = Math.max(maxY, wp.y);
81
+ }
82
+ }
83
+ if (!Number.isFinite(minX))
84
+ return;
85
+ const padding = 8;
86
+ const dW = maxX - minX;
87
+ const dH = maxY - minY;
88
+ const scaleX = (this._mmW - padding * 2) / dW;
89
+ const scaleY = (this._mmH - padding * 2) / dH;
90
+ this._scale = Math.min(scaleX, scaleY);
91
+ this._offsetX = padding + (this._mmW - padding * 2 - dW * this._scale) / 2 - minX * this._scale;
92
+ this._offsetY = padding + (this._mmH - padding * 2 - dH * this._scale) / 2 - minY * this._scale;
93
+ this._diagramMinX = minX;
94
+ this._diagramMinY = minY;
95
+ this._diagramW = dW;
96
+ this._diagramH = dH;
97
+ // Render simplified shapes (just rects/circles)
98
+ for (const s of plane.shapes) {
99
+ const x = s.bounds.x * this._scale + this._offsetX;
100
+ const y = s.bounds.y * this._scale + this._offsetY;
101
+ const w = s.bounds.width * this._scale;
102
+ const h = s.bounds.height * this._scale;
103
+ // Approximate shape type from size: very small square → event or gateway
104
+ const isSmall = w < 10;
105
+ if (isSmall) {
106
+ const circle = svgEl("circle");
107
+ attr(circle, {
108
+ cx: x + w / 2,
109
+ cy: y + h / 2,
110
+ r: Math.max(w / 2, 2),
111
+ class: "bpmn-minimap-shape",
112
+ });
113
+ this._shapesG.appendChild(circle);
114
+ }
115
+ else {
116
+ const rect = svgEl("rect");
117
+ attr(rect, {
118
+ x,
119
+ y,
120
+ width: Math.max(w, 1),
121
+ height: Math.max(h, 1),
122
+ rx: 1,
123
+ class: "bpmn-minimap-shape",
124
+ });
125
+ this._shapesG.appendChild(rect);
126
+ }
127
+ }
128
+ // Render simplified edges
129
+ for (const e of plane.edges) {
130
+ if (e.waypoints.length < 2)
131
+ continue;
132
+ const pts = e.waypoints
133
+ .map((wp) => `${wp.x * this._scale + this._offsetX},${wp.y * this._scale + this._offsetY}`)
134
+ .join(" ");
135
+ const poly = svgEl("polyline");
136
+ attr(poly, { points: pts, class: "bpmn-minimap-edge" });
137
+ this._edgesG.appendChild(poly);
138
+ }
139
+ }
140
+ /** Syncs the viewport indicator rectangle with the current pan/zoom state. */
141
+ syncViewport(state, svgWidth, svgHeight) {
142
+ // Visible diagram area in diagram coordinates
143
+ const left = -state.tx / state.scale;
144
+ const top = -state.ty / state.scale;
145
+ const visW = svgWidth / state.scale;
146
+ const visH = svgHeight / state.scale;
147
+ // Map to minimap coordinates
148
+ const mx = left * this._scale + this._offsetX;
149
+ const my = top * this._scale + this._offsetY;
150
+ const mw = visW * this._scale;
151
+ const mh = visH * this._scale;
152
+ attr(this._viewportRect, { x: mx, y: my, width: Math.max(mw, 2), height: Math.max(mh, 2) });
153
+ }
154
+ /** Removes the minimap from the DOM. */
155
+ destroy() {
156
+ this._host.removeEventListener("click", this._onClick);
157
+ this._host.remove();
158
+ }
159
+ _onClick = (e) => {
160
+ const rect = this._host.getBoundingClientRect();
161
+ const mmX = e.clientX - rect.left;
162
+ const mmY = e.clientY - rect.top;
163
+ // Convert minimap coordinates to diagram coordinates
164
+ const diagX = (mmX - this._offsetX) / this._scale;
165
+ const diagY = (mmY - this._offsetY) / this._scale;
166
+ // The requested diagram point should be centred in the SVG
167
+ // The caller determines the SVG size and computes the correct translation
168
+ this._onNavigate(diagX, diagY);
169
+ };
170
+ }
171
+ //# sourceMappingURL=minimap.js.map
@@ -0,0 +1,40 @@
1
+ import type { BpmnDefinitions } from "@bpmnkit/core";
2
+ import type { RenderedEdge, RenderedShape } from "./types.js";
3
+ /**
4
+ * Creates the SVG `<defs>` section for this canvas instance.
5
+ * Uses `instanceId` to make marker IDs unique per canvas, avoiding
6
+ * conflicts when multiple canvases are mounted on the same page.
7
+ */
8
+ export declare function createDefs(svg: SVGSVGElement, instanceId: string): string;
9
+ /**
10
+ * Creates and inserts an SVG dot-grid background pattern.
11
+ * The `<rect>` filling the entire viewport and the `<pattern>` definition
12
+ * are both inserted into the SVG. Returns the `<pattern>` element so the
13
+ * viewport controller can keep `patternTransform` in sync.
14
+ */
15
+ export declare function createGrid(svg: SVGSVGElement, instanceId: string): SVGPatternElement;
16
+ export interface RenderResult {
17
+ shapes: RenderedShape[];
18
+ edges: RenderedEdge[];
19
+ }
20
+ /**
21
+ * Renders a `BpmnDefinitions` model into SVG element groups, appending them
22
+ * to `edgesLayer` and `shapesLayer` respectively.
23
+ *
24
+ * Edges are placed below shapes (rendered first) so connection lines don't
25
+ * cover shape bodies. Shapes are rendered in DI order so container shapes
26
+ * (sub-processes) appear before their children.
27
+ */
28
+ export declare function render(defs: BpmnDefinitions, containersLayer: SVGGElement, edgesLayer: SVGGElement, shapesLayer: SVGGElement, labelsLayer: SVGGElement, markerId: string, instanceId: string): RenderResult;
29
+ export interface DiagramBounds {
30
+ minX: number;
31
+ minY: number;
32
+ maxX: number;
33
+ maxY: number;
34
+ }
35
+ /**
36
+ * Computes the bounding box of all shapes in the first DI diagram plane.
37
+ * Returns `null` if the diagram has no shapes.
38
+ */
39
+ export declare function computeDiagramBounds(defs: BpmnDefinitions): DiagramBounds | null;
40
+ //# sourceMappingURL=renderer.d.ts.map