@bpmnkit/canvas 0.0.30 → 0.0.31
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/README.md +1 -1
- package/dist/canvas.d.ts +4 -3
- package/dist/canvas.js +33 -18
- package/dist/keyboard.d.ts +5 -0
- package/dist/keyboard.js +20 -0
- package/dist/renderer.js +3 -2
- package/dist/scene.d.ts +9 -0
- package/dist/scene.js +31 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](https://github.com/bpmnkit/monorepo)
|
|
10
10
|
[](https://github.com/bpmnkit/monorepo)
|
|
11
11
|
|
|
12
|
-
[Website](https://bpmnkit.com) · [Documentation](https://
|
|
12
|
+
[Website](https://bpmnkit.com) · [Documentation](https://bpmnkit.com/docs) · [GitHub](https://github.com/bpmnkit/monorepo) · [Changelog](https://github.com/bpmnkit/monorepo/blob/main/packages/canvas/CHANGELOG.md)
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
15
|
---
|
package/dist/canvas.d.ts
CHANGED
|
@@ -237,9 +237,10 @@ export declare class BpmnCanvas {
|
|
|
237
237
|
private _updateBreadcrumb;
|
|
238
238
|
/**
|
|
239
239
|
* Resolves the BPMN element id under a pointer/mouse event, or `null`.
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
240
|
+
* The event target answers directly for most moves; `elementFromPoint`
|
|
241
|
+
* (which forces a layout and hit-test flush) is only consulted when native
|
|
242
|
+
* SVG hit-testing handed us the root `<svg>`, as it does in some flex/scroll
|
|
243
|
+
* containers.
|
|
243
244
|
*/
|
|
244
245
|
private _elementIdForEvent;
|
|
245
246
|
/** Diagram-coordinate bounds of a shape (from DI) or edge (waypoint bbox). */
|
package/dist/canvas.js
CHANGED
|
@@ -445,7 +445,9 @@ export class BpmnCanvas {
|
|
|
445
445
|
this._scene.updateElement(id);
|
|
446
446
|
this._shapes = this._scene.getShapes();
|
|
447
447
|
this._edges = this._scene.getEdges();
|
|
448
|
-
this.
|
|
448
|
+
const updated = this._scene.getElement(id);
|
|
449
|
+
if (updated && "shape" in updated)
|
|
450
|
+
this._keyboard.updateShape(updated);
|
|
449
451
|
this._overlays.reposition();
|
|
450
452
|
}
|
|
451
453
|
/** Zooms in by 25% centred on the canvas. */
|
|
@@ -765,32 +767,45 @@ export class BpmnCanvas {
|
|
|
765
767
|
}
|
|
766
768
|
/**
|
|
767
769
|
* Resolves the BPMN element id under a pointer/mouse event, or `null`.
|
|
768
|
-
*
|
|
769
|
-
*
|
|
770
|
-
*
|
|
770
|
+
* The event target answers directly for most moves; `elementFromPoint`
|
|
771
|
+
* (which forces a layout and hit-test flush) is only consulted when native
|
|
772
|
+
* SVG hit-testing handed us the root `<svg>`, as it does in some flex/scroll
|
|
773
|
+
* containers.
|
|
771
774
|
*/
|
|
772
775
|
_elementIdForEvent(e) {
|
|
776
|
+
const fromTarget = e.target?.closest("[data-bpmnkit-id]");
|
|
777
|
+
if (fromTarget)
|
|
778
|
+
return fromTarget.getAttribute("data-bpmnkit-id");
|
|
773
779
|
const fromPoint = document.elementFromPoint(e.clientX, e.clientY);
|
|
774
|
-
|
|
775
|
-
e.target?.closest("[data-bpmnkit-id]");
|
|
776
|
-
return target?.getAttribute("data-bpmnkit-id") ?? null;
|
|
780
|
+
return fromPoint?.closest("[data-bpmnkit-id]")?.getAttribute("data-bpmnkit-id") ?? null;
|
|
777
781
|
}
|
|
778
782
|
/** Diagram-coordinate bounds of a shape (from DI) or edge (waypoint bbox). */
|
|
779
783
|
_diagramBounds(id) {
|
|
780
|
-
const
|
|
781
|
-
if (
|
|
782
|
-
|
|
784
|
+
const el = this._scene.getElement(id);
|
|
785
|
+
if (!el)
|
|
786
|
+
return null;
|
|
787
|
+
if ("shape" in el) {
|
|
788
|
+
const { x, y, width, height } = el.shape.bounds;
|
|
783
789
|
return { x, y, width, height };
|
|
784
790
|
}
|
|
785
|
-
const
|
|
786
|
-
if (
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
791
|
+
const waypoints = el.edge.waypoints;
|
|
792
|
+
if (waypoints.length === 0)
|
|
793
|
+
return null;
|
|
794
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
795
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
796
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
797
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
798
|
+
for (const w of waypoints) {
|
|
799
|
+
if (w.x < minX)
|
|
800
|
+
minX = w.x;
|
|
801
|
+
if (w.y < minY)
|
|
802
|
+
minY = w.y;
|
|
803
|
+
if (w.x > maxX)
|
|
804
|
+
maxX = w.x;
|
|
805
|
+
if (w.y > maxY)
|
|
806
|
+
maxY = w.y;
|
|
792
807
|
}
|
|
793
|
-
return
|
|
808
|
+
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
794
809
|
}
|
|
795
810
|
_applyTheme(theme) {
|
|
796
811
|
const resolved = theme === "auto"
|
package/dist/keyboard.d.ts
CHANGED
|
@@ -30,6 +30,11 @@ export declare class KeyboardHandler {
|
|
|
30
30
|
constructor(_container: HTMLElement, _viewport: ViewportController, _onFit: () => void, _onActivate: (id: string) => void, _onFocus: (id: string) => void, _onBlur: () => void);
|
|
31
31
|
/** Updates the navigable shape list after a diagram (re)load. */
|
|
32
32
|
setShapes(shapes: RenderedShape[]): void;
|
|
33
|
+
/**
|
|
34
|
+
* Swaps in the re-rendered graphics of one shape after an incremental
|
|
35
|
+
* update, keeping focus position and avoiding a DOM read per shape.
|
|
36
|
+
*/
|
|
37
|
+
updateShape(shape: RenderedShape): void;
|
|
33
38
|
/** Removes all keyboard event listeners. */
|
|
34
39
|
destroy(): void;
|
|
35
40
|
private _focusShape;
|
package/dist/keyboard.js
CHANGED
|
@@ -42,6 +42,26 @@ export class KeyboardHandler {
|
|
|
42
42
|
this._shapes = shapes.filter((s) => s.element.getAttribute("tabindex") === "-1");
|
|
43
43
|
this._focusIndex = -1;
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Swaps in the re-rendered graphics of one shape after an incremental
|
|
47
|
+
* update, keeping focus position and avoiding a DOM read per shape.
|
|
48
|
+
*/
|
|
49
|
+
updateShape(shape) {
|
|
50
|
+
const focusable = shape.element.getAttribute("tabindex") === "-1";
|
|
51
|
+
const index = this._shapes.findIndex((s) => s.id === shape.id);
|
|
52
|
+
if (index === -1) {
|
|
53
|
+
if (focusable)
|
|
54
|
+
this._shapes.push(shape);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (focusable)
|
|
58
|
+
this._shapes[index] = shape;
|
|
59
|
+
else {
|
|
60
|
+
this._shapes.splice(index, 1);
|
|
61
|
+
if (this._focusIndex >= this._shapes.length)
|
|
62
|
+
this._focusIndex = -1;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
45
65
|
/** Removes all keyboard event listeners. */
|
|
46
66
|
destroy() {
|
|
47
67
|
this._container.removeEventListener("keydown", this._onKeyDown);
|
package/dist/renderer.js
CHANGED
|
@@ -763,8 +763,9 @@ function renderEdge(edge, flow, instanceId, isDefault, isConditional, waypoints)
|
|
|
763
763
|
if (waypoints.length < 2)
|
|
764
764
|
return g;
|
|
765
765
|
const path = svgEl("path");
|
|
766
|
+
const d = waypointsToRoundedPath(waypoints);
|
|
766
767
|
const pathAttrs = {
|
|
767
|
-
d
|
|
768
|
+
d,
|
|
768
769
|
class: "bpmnkit-edge-path",
|
|
769
770
|
"marker-end": `url(#${ids.arrow})`,
|
|
770
771
|
};
|
|
@@ -777,7 +778,7 @@ function renderEdge(edge, flow, instanceId, isDefault, isConditional, waypoints)
|
|
|
777
778
|
// Wide transparent stroke so the edge is easy to click
|
|
778
779
|
const hitPath = svgEl("path");
|
|
779
780
|
attr(hitPath, {
|
|
780
|
-
d
|
|
781
|
+
d,
|
|
781
782
|
fill: "none",
|
|
782
783
|
stroke: "transparent",
|
|
783
784
|
"stroke-width": "12",
|
package/dist/scene.d.ts
CHANGED
|
@@ -23,6 +23,15 @@ export declare class Scene {
|
|
|
23
23
|
private _defs;
|
|
24
24
|
private _plane;
|
|
25
25
|
private _drillableIds;
|
|
26
|
+
/**
|
|
27
|
+
* Model index and docking geometry, built once per {@link render}. The
|
|
28
|
+
* model is expected to be mutated in place between incremental updates
|
|
29
|
+
* (the scene already keeps `_defs`/`_plane` by reference), so rebuilding the
|
|
30
|
+
* whole index for every single-element update was pure waste.
|
|
31
|
+
*/
|
|
32
|
+
private _ctx;
|
|
33
|
+
private readonly _shapeById;
|
|
34
|
+
private readonly _edgeById;
|
|
26
35
|
constructor(_layers: SceneLayers, _instanceId: string);
|
|
27
36
|
/** Renders a plane from scratch, replacing any current content. */
|
|
28
37
|
render(defs: BpmnDefinitions, plane: BpmnDiPlane, drillableIds?: ReadonlySet<string>): void;
|
package/dist/scene.js
CHANGED
|
@@ -15,6 +15,15 @@ export class Scene {
|
|
|
15
15
|
_defs = null;
|
|
16
16
|
_plane = null;
|
|
17
17
|
_drillableIds = new Set();
|
|
18
|
+
/**
|
|
19
|
+
* Model index and docking geometry, built once per {@link render}. The
|
|
20
|
+
* model is expected to be mutated in place between incremental updates
|
|
21
|
+
* (the scene already keeps `_defs`/`_plane` by reference), so rebuilding the
|
|
22
|
+
* whole index for every single-element update was pure waste.
|
|
23
|
+
*/
|
|
24
|
+
_ctx = null;
|
|
25
|
+
_shapeById = new Map();
|
|
26
|
+
_edgeById = new Map();
|
|
18
27
|
constructor(_layers, _instanceId) {
|
|
19
28
|
this._layers = _layers;
|
|
20
29
|
this._instanceId = _instanceId;
|
|
@@ -25,6 +34,11 @@ export class Scene {
|
|
|
25
34
|
this._defs = defs;
|
|
26
35
|
this._plane = plane;
|
|
27
36
|
this._drillableIds = drillableIds;
|
|
37
|
+
this._ctx = null;
|
|
38
|
+
for (const shape of plane.shapes)
|
|
39
|
+
this._shapeById.set(shape.bpmnElement, shape);
|
|
40
|
+
for (const edge of plane.edges)
|
|
41
|
+
this._edgeById.set(edge.bpmnElement, edge);
|
|
28
42
|
const ctx = this._context();
|
|
29
43
|
for (const edge of plane.edges) {
|
|
30
44
|
const g = renderEdgeGroup(edge, ctx);
|
|
@@ -50,6 +64,9 @@ export class Scene {
|
|
|
50
64
|
this._layers.shapes.replaceChildren();
|
|
51
65
|
this._layers.labels.replaceChildren();
|
|
52
66
|
this._registry.clear();
|
|
67
|
+
this._shapeById.clear();
|
|
68
|
+
this._edgeById.clear();
|
|
69
|
+
this._ctx = null;
|
|
53
70
|
}
|
|
54
71
|
/** Returns the registered shape or edge for an id, or `undefined`. */
|
|
55
72
|
getElement(id) {
|
|
@@ -96,7 +113,7 @@ export class Scene {
|
|
|
96
113
|
.split(/\s+/)
|
|
97
114
|
.filter(Boolean);
|
|
98
115
|
if (entry.kind === "edge") {
|
|
99
|
-
const edge = this.
|
|
116
|
+
const edge = this._edgeById.get(id);
|
|
100
117
|
if (!edge)
|
|
101
118
|
return;
|
|
102
119
|
const g = renderEdgeGroup(edge, ctx);
|
|
@@ -106,9 +123,17 @@ export class Scene {
|
|
|
106
123
|
this._registry.set(id, { rendered: { id, element: g, edge }, label: null, kind: "edge" });
|
|
107
124
|
return;
|
|
108
125
|
}
|
|
109
|
-
const shape = this.
|
|
126
|
+
const shape = this._shapeById.get(id);
|
|
110
127
|
if (!shape)
|
|
111
128
|
return;
|
|
129
|
+
// A moved or resized shape must dock its edges against its new bounds.
|
|
130
|
+
const geom = ctx.geomById.get(id);
|
|
131
|
+
if (geom) {
|
|
132
|
+
geom.x = shape.bounds.x;
|
|
133
|
+
geom.y = shape.bounds.y;
|
|
134
|
+
geom.width = shape.bounds.width;
|
|
135
|
+
geom.height = shape.bounds.height;
|
|
136
|
+
}
|
|
112
137
|
const { group, layer, label, rendered } = renderShapeGroup(shape, ctx);
|
|
113
138
|
for (const c of oldClasses)
|
|
114
139
|
group.classList.add(c);
|
|
@@ -131,10 +156,13 @@ export class Scene {
|
|
|
131
156
|
this._registry.delete(id);
|
|
132
157
|
}
|
|
133
158
|
_context() {
|
|
159
|
+
if (this._ctx)
|
|
160
|
+
return this._ctx;
|
|
134
161
|
if (!this._defs || !this._plane) {
|
|
135
162
|
throw new Error("Scene has no rendered plane");
|
|
136
163
|
}
|
|
137
|
-
|
|
164
|
+
this._ctx = buildRenderContext(this._defs, this._plane, this._drillableIds, this._instanceId);
|
|
165
|
+
return this._ctx;
|
|
138
166
|
}
|
|
139
167
|
}
|
|
140
168
|
//# sourceMappingURL=scene.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bpmnkit/canvas",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.31",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"dist/**/*.d.ts"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@bpmnkit/core": "0.
|
|
20
|
+
"@bpmnkit/core": "0.2.0"
|
|
21
21
|
},
|
|
22
22
|
"description": "Zero-dependency SVG BPMN viewer with pan/zoom, theming, and a plugin API",
|
|
23
23
|
"keywords": [
|