@bpmnkit/plugins 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.
Files changed (140) hide show
  1. package/README.md +153 -0
  2. package/dist/ai-bridge/css.d.ts +2 -0
  3. package/dist/ai-bridge/css.js +366 -0
  4. package/dist/ai-bridge/index.d.ts +44 -0
  5. package/dist/ai-bridge/index.js +132 -0
  6. package/dist/ai-bridge/panel.d.ts +27 -0
  7. package/dist/ai-bridge/panel.js +715 -0
  8. package/dist/ascii-view/css.d.ts +4 -0
  9. package/dist/ascii-view/css.js +83 -0
  10. package/dist/ascii-view/index.d.ts +25 -0
  11. package/dist/ascii-view/index.js +92 -0
  12. package/dist/command-palette/css.d.ts +4 -0
  13. package/dist/command-palette/css.js +157 -0
  14. package/dist/command-palette/index.d.ts +53 -0
  15. package/dist/command-palette/index.js +378 -0
  16. package/dist/command-palette-editor/index.d.ts +35 -0
  17. package/dist/command-palette-editor/index.js +60 -0
  18. package/dist/config-panel/css.d.ts +4 -0
  19. package/dist/config-panel/css.js +719 -0
  20. package/dist/config-panel/index.d.ts +36 -0
  21. package/dist/config-panel/index.js +73 -0
  22. package/dist/config-panel/renderer.d.ts +127 -0
  23. package/dist/config-panel/renderer.js +1162 -0
  24. package/dist/config-panel/types.d.ts +118 -0
  25. package/dist/config-panel/types.js +2 -0
  26. package/dist/config-panel-bpmn/index.d.ts +58 -0
  27. package/dist/config-panel-bpmn/index.js +1320 -0
  28. package/dist/config-panel-bpmn/template-engine.d.ts +17 -0
  29. package/dist/config-panel-bpmn/template-engine.js +307 -0
  30. package/dist/config-panel-bpmn/template-to-service-task.d.ts +30 -0
  31. package/dist/config-panel-bpmn/template-to-service-task.js +92 -0
  32. package/dist/config-panel-bpmn/template-types.d.ts +126 -0
  33. package/dist/config-panel-bpmn/template-types.js +6 -0
  34. package/dist/config-panel-bpmn/templates/generated.d.ts +3 -0
  35. package/dist/config-panel-bpmn/templates/generated.js +57865 -0
  36. package/dist/config-panel-bpmn/util.d.ts +46 -0
  37. package/dist/config-panel-bpmn/util.js +195 -0
  38. package/dist/dmn-editor/css.d.ts +3 -0
  39. package/dist/dmn-editor/css.js +667 -0
  40. package/dist/dmn-editor/dmn-editor.d.ts +34 -0
  41. package/dist/dmn-editor/dmn-editor.js +646 -0
  42. package/dist/dmn-editor/drd-canvas.d.ts +85 -0
  43. package/dist/dmn-editor/drd-canvas.js +1087 -0
  44. package/dist/dmn-editor/index.d.ts +3 -0
  45. package/dist/dmn-editor/index.js +2 -0
  46. package/dist/dmn-viewer/css.d.ts +3 -0
  47. package/dist/dmn-viewer/css.js +151 -0
  48. package/dist/dmn-viewer/dmn-viewer.d.ts +30 -0
  49. package/dist/dmn-viewer/dmn-viewer.js +160 -0
  50. package/dist/dmn-viewer/feel.d.ts +3 -0
  51. package/dist/dmn-viewer/feel.js +2 -0
  52. package/dist/dmn-viewer/index.d.ts +14 -0
  53. package/dist/dmn-viewer/index.js +12 -0
  54. package/dist/element-docs/content.d.ts +20 -0
  55. package/dist/element-docs/content.js +1032 -0
  56. package/dist/element-docs/index.d.ts +7 -0
  57. package/dist/element-docs/index.js +643 -0
  58. package/dist/feel-playground/css.d.ts +4 -0
  59. package/dist/feel-playground/css.js +292 -0
  60. package/dist/feel-playground/index.d.ts +4 -0
  61. package/dist/feel-playground/index.js +3 -0
  62. package/dist/feel-playground/playground-plugin.d.ts +14 -0
  63. package/dist/feel-playground/playground-plugin.js +292 -0
  64. package/dist/form-editor/css.d.ts +3 -0
  65. package/dist/form-editor/css.js +703 -0
  66. package/dist/form-editor/form-editor.d.ts +48 -0
  67. package/dist/form-editor/form-editor.js +1039 -0
  68. package/dist/form-editor/index.d.ts +3 -0
  69. package/dist/form-editor/index.js +2 -0
  70. package/dist/form-viewer/css.d.ts +3 -0
  71. package/dist/form-viewer/css.js +303 -0
  72. package/dist/form-viewer/form-viewer.d.ts +29 -0
  73. package/dist/form-viewer/form-viewer.js +376 -0
  74. package/dist/form-viewer/index.d.ts +12 -0
  75. package/dist/form-viewer/index.js +11 -0
  76. package/dist/history/checkpoint.d.ts +10 -0
  77. package/dist/history/checkpoint.js +92 -0
  78. package/dist/history/css.d.ts +2 -0
  79. package/dist/history/css.js +130 -0
  80. package/dist/history/history-panel.d.ts +12 -0
  81. package/dist/history/history-panel.js +142 -0
  82. package/dist/history/index.d.ts +5 -0
  83. package/dist/history/index.js +3 -0
  84. package/dist/main-menu/css.d.ts +4 -0
  85. package/dist/main-menu/css.js +272 -0
  86. package/dist/main-menu/index.d.ts +59 -0
  87. package/dist/main-menu/index.js +285 -0
  88. package/dist/minimap/css.d.ts +10 -0
  89. package/dist/minimap/css.js +54 -0
  90. package/dist/minimap/index.d.ts +38 -0
  91. package/dist/minimap/index.js +69 -0
  92. package/dist/minimap/minimap.d.ts +35 -0
  93. package/dist/minimap/minimap.js +166 -0
  94. package/dist/optimize/index.d.ts +21 -0
  95. package/dist/optimize/index.js +304 -0
  96. package/dist/process-runner/css.d.ts +2 -0
  97. package/dist/process-runner/css.js +467 -0
  98. package/dist/process-runner/index.d.ts +56 -0
  99. package/dist/process-runner/index.js +549 -0
  100. package/dist/storage/auto-save.d.ts +11 -0
  101. package/dist/storage/auto-save.js +44 -0
  102. package/dist/storage/css.d.ts +2 -0
  103. package/dist/storage/css.js +2 -0
  104. package/dist/storage/db.d.ts +99 -0
  105. package/dist/storage/db.js +116 -0
  106. package/dist/storage/dialog.d.ts +15 -0
  107. package/dist/storage/dialog.js +201 -0
  108. package/dist/storage/export.d.ts +3 -0
  109. package/dist/storage/export.js +137 -0
  110. package/dist/storage/index.d.ts +44 -0
  111. package/dist/storage/index.js +201 -0
  112. package/dist/storage/sidebar.d.ts +2 -0
  113. package/dist/storage/sidebar.js +2 -0
  114. package/dist/storage/storage-api.d.ts +76 -0
  115. package/dist/storage/storage-api.js +342 -0
  116. package/dist/storage/types.d.ts +44 -0
  117. package/dist/storage/types.js +2 -0
  118. package/dist/storage-tabs-bridge/index.d.ts +96 -0
  119. package/dist/storage-tabs-bridge/index.js +502 -0
  120. package/dist/tabs/css.d.ts +3 -0
  121. package/dist/tabs/css.js +642 -0
  122. package/dist/tabs/file-resolver.d.ts +71 -0
  123. package/dist/tabs/file-resolver.js +46 -0
  124. package/dist/tabs/index.d.ts +15 -0
  125. package/dist/tabs/index.js +13 -0
  126. package/dist/tabs/tabs-plugin.d.ts +250 -0
  127. package/dist/tabs/tabs-plugin.js +1119 -0
  128. package/dist/token-highlight/css.d.ts +2 -0
  129. package/dist/token-highlight/css.js +81 -0
  130. package/dist/token-highlight/index.d.ts +44 -0
  131. package/dist/token-highlight/index.js +164 -0
  132. package/dist/watermark/css.d.ts +10 -0
  133. package/dist/watermark/css.js +54 -0
  134. package/dist/watermark/index.d.ts +48 -0
  135. package/dist/watermark/index.js +64 -0
  136. package/dist/zoom-controls/css.d.ts +4 -0
  137. package/dist/zoom-controls/css.js +48 -0
  138. package/dist/zoom-controls/index.d.ts +36 -0
  139. package/dist/zoom-controls/index.js +111 -0
  140. package/package.json +121 -0
@@ -0,0 +1,2 @@
1
+ export declare function injectTokenHighlightStyles(): void;
2
+ //# sourceMappingURL=css.d.ts.map
@@ -0,0 +1,81 @@
1
+ const STYLE_ID = "bpmnkit-token-highlight-v1";
2
+ const CSS = `
3
+ @keyframes bpmnkit-token-pulse {
4
+ 0%, 100% { filter: drop-shadow(0 0 4px rgba(245, 158, 11, 0.9)); }
5
+ 50% { filter: drop-shadow(0 0 10px rgba(245, 158, 11, 0.25)); }
6
+ }
7
+ @keyframes bpmnkit-token-flow {
8
+ to { stroke-dashoffset: -12; }
9
+ }
10
+
11
+ /* ── Active shapes (token is here) ─────────────────────────────────────── */
12
+ .bpmnkit-token-active {
13
+ animation: bpmnkit-token-pulse 1.4s ease-in-out infinite;
14
+ }
15
+ .bpmnkit-token-active .bpmnkit-shape-body,
16
+ .bpmnkit-token-active .bpmnkit-event-body,
17
+ .bpmnkit-token-active .bpmnkit-end-body,
18
+ .bpmnkit-token-active .bpmnkit-gw-body {
19
+ stroke: #f59e0b !important;
20
+ stroke-width: 2.5 !important;
21
+ fill: rgba(245, 158, 11, 0.12) !important;
22
+ }
23
+
24
+ /* ── Visited shapes (token has passed through) ──────────────────────────── */
25
+ .bpmnkit-token-visited .bpmnkit-shape-body,
26
+ .bpmnkit-token-visited .bpmnkit-event-body,
27
+ .bpmnkit-token-visited .bpmnkit-end-body,
28
+ .bpmnkit-token-visited .bpmnkit-gw-body {
29
+ stroke: #10b981 !important;
30
+ stroke-width: 2 !important;
31
+ fill: rgba(16, 185, 129, 0.08) !important;
32
+ }
33
+
34
+ /* ── Active edges (token is moving along this flow) ─────────────────────── */
35
+ .bpmnkit-token-edge-active .bpmnkit-edge-path {
36
+ stroke: #f59e0b !important;
37
+ stroke-width: 2.5 !important;
38
+ stroke-dasharray: 8 4;
39
+ animation: bpmnkit-token-flow 0.5s linear infinite;
40
+ }
41
+ .bpmnkit-token-edge-active .bpmnkit-arrow-fill {
42
+ fill: #f59e0b !important;
43
+ }
44
+
45
+ /* ── Visited edges ───────────────────────────────────────────────────────── */
46
+ .bpmnkit-token-edge-visited .bpmnkit-edge-path {
47
+ stroke: #10b981 !important;
48
+ stroke-width: 2 !important;
49
+ }
50
+ .bpmnkit-token-edge-visited .bpmnkit-arrow-fill {
51
+ fill: #10b981 !important;
52
+ }
53
+
54
+ /* ── Error shapes (gateway with no matching condition) ───────────────────── */
55
+ @keyframes bpmnkit-token-error-pulse {
56
+ 0%, 100% { filter: drop-shadow(0 0 5px rgba(239, 68, 68, 0.95)); }
57
+ 50% { filter: drop-shadow(0 0 12px rgba(239, 68, 68, 0.3)); }
58
+ }
59
+ .bpmnkit-token-error {
60
+ animation: bpmnkit-token-error-pulse 0.9s ease-in-out 3;
61
+ }
62
+ .bpmnkit-token-error .bpmnkit-shape-body,
63
+ .bpmnkit-token-error .bpmnkit-event-body,
64
+ .bpmnkit-token-error .bpmnkit-end-body,
65
+ .bpmnkit-token-error .bpmnkit-gw-body {
66
+ stroke: #ef4444 !important;
67
+ stroke-width: 2.5 !important;
68
+ fill: rgba(239, 68, 68, 0.12) !important;
69
+ }
70
+ `;
71
+ export function injectTokenHighlightStyles() {
72
+ if (typeof document === "undefined")
73
+ return;
74
+ if (document.getElementById(STYLE_ID) !== null)
75
+ return;
76
+ const style = document.createElement("style");
77
+ style.id = STYLE_ID;
78
+ style.textContent = CSS;
79
+ document.head.appendChild(style);
80
+ }
81
+ //# sourceMappingURL=css.js.map
@@ -0,0 +1,44 @@
1
+ import type { CanvasPlugin } from "@bpmnkit/canvas";
2
+ /**
3
+ * Minimal interface satisfied by `ProcessInstance` from `@bpmnkit/engine`.
4
+ * Using structural typing keeps this plugin free of an engine dependency.
5
+ */
6
+ export interface InstanceLike {
7
+ onChange(callback: (event: Record<string, unknown>) => void): () => void;
8
+ }
9
+ export interface TokenHighlightApi {
10
+ /**
11
+ * Subscribe to a `ProcessInstance` and automatically update highlights as
12
+ * the engine emits events. Returns an unsubscribe function.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const highlight = createTokenHighlightPlugin();
17
+ * const canvas = new BpmnCanvas({ container, plugins: [highlight] });
18
+ * canvas.load(xml);
19
+ *
20
+ * const instance = engine.start("Process_1", { amount: 100 });
21
+ * const stop = highlight.api.trackInstance(instance);
22
+ * // later: stop() to detach
23
+ * ```
24
+ */
25
+ trackInstance(instance: InstanceLike): () => void;
26
+ /**
27
+ * Manually set the full list of element IDs that currently hold a token.
28
+ * Replaces any previously active set.
29
+ */
30
+ setActive(elementIds: string[]): void;
31
+ /**
32
+ * Mark additional element IDs as visited (token has passed through).
33
+ * Additive — does not clear previously visited elements.
34
+ */
35
+ addVisited(elementIds: string[]): void;
36
+ /** Mark an element as failed (e.g. exclusive gateway with no matching condition). Shown in red. */
37
+ setError(elementId: string): void;
38
+ /** Remove all token highlights from the canvas. */
39
+ clear(): void;
40
+ }
41
+ export declare function createTokenHighlightPlugin(): CanvasPlugin & {
42
+ api: TokenHighlightApi;
43
+ };
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,164 @@
1
+ import { injectTokenHighlightStyles } from "./css";
2
+ // ── Plugin factory ─────────────────────────────────────────────────────────────
3
+ export function createTokenHighlightPlugin() {
4
+ let canvasApi = null;
5
+ /** Element IDs that currently hold a live token. */
6
+ const activeIds = new Set();
7
+ /** Element IDs that a token has already passed through. */
8
+ const visitedIds = new Set();
9
+ /** Element IDs that have failed (e.g. unmatched gateway condition). */
10
+ const errorIds = new Set();
11
+ /** flowId → { sourceRef, targetRef } — populated from diagram:load/change. */
12
+ const flowIndex = new Map();
13
+ const unsubs = [];
14
+ // ── Helpers ──────────────────────────────────────────────────────────────
15
+ function shapeEl(id) {
16
+ const el = canvasApi?.viewportEl.querySelector(`[data-bpmnkit-id="${id}"]`);
17
+ return el instanceof SVGGElement ? el : undefined;
18
+ }
19
+ function edgeEl(id) {
20
+ const el = canvasApi?.viewportEl.querySelector(`[data-bpmnkit-id="${id}"]`);
21
+ return el instanceof SVGGElement ? el : undefined;
22
+ }
23
+ function applyHighlights() {
24
+ const api = canvasApi;
25
+ if (api === null)
26
+ return;
27
+ // Strip all plugin classes — query the viewport so subprocess children are included
28
+ const vp = api.viewportEl;
29
+ for (const el of vp.querySelectorAll(".bpmnkit-token-active,.bpmnkit-token-visited,.bpmnkit-token-error")) {
30
+ el.classList.remove("bpmnkit-token-active", "bpmnkit-token-visited", "bpmnkit-token-error");
31
+ }
32
+ for (const el of vp.querySelectorAll(".bpmnkit-token-edge-active,.bpmnkit-token-edge-visited")) {
33
+ el.classList.remove("bpmnkit-token-edge-active", "bpmnkit-token-edge-visited");
34
+ }
35
+ // Visited shapes
36
+ for (const id of visitedIds) {
37
+ shapeEl(id)?.classList.add("bpmnkit-token-visited");
38
+ }
39
+ // Active shapes (added after visited so they override on the same element)
40
+ for (const id of activeIds) {
41
+ const el = shapeEl(id);
42
+ if (el !== undefined) {
43
+ el.classList.remove("bpmnkit-token-visited");
44
+ el.classList.add("bpmnkit-token-active");
45
+ }
46
+ }
47
+ // Error shapes (highest priority — override active/visited)
48
+ for (const id of errorIds) {
49
+ const el = shapeEl(id);
50
+ if (el !== undefined) {
51
+ el.classList.remove("bpmnkit-token-active", "bpmnkit-token-visited");
52
+ el.classList.add("bpmnkit-token-error");
53
+ }
54
+ }
55
+ // Edge highlights
56
+ // • active edge : source visited, target active (token just left source, entering target)
57
+ // • visited edge : source visited, target visited (token has fully traversed this edge)
58
+ // This correctly handles exclusive gateways: only the taken branch's target enters
59
+ // visited/active, so only the taken edge is highlighted.
60
+ for (const [flowId, { sourceRef, targetRef }] of flowIndex) {
61
+ const el = edgeEl(flowId);
62
+ if (el === undefined)
63
+ continue;
64
+ const srcVisited = visitedIds.has(sourceRef);
65
+ if (!srcVisited)
66
+ continue;
67
+ if (activeIds.has(targetRef)) {
68
+ el.classList.add("bpmnkit-token-edge-active");
69
+ }
70
+ else if (visitedIds.has(targetRef)) {
71
+ el.classList.add("bpmnkit-token-edge-visited");
72
+ }
73
+ }
74
+ }
75
+ function indexFlows(defs) {
76
+ flowIndex.clear();
77
+ for (const proc of defs.processes) {
78
+ for (const flow of proc.sequenceFlows) {
79
+ flowIndex.set(flow.id, { sourceRef: flow.sourceRef, targetRef: flow.targetRef });
80
+ }
81
+ // Sub-processes
82
+ for (const el of proc.flowElements) {
83
+ if (el.type === "subProcess" ||
84
+ el.type === "transaction" ||
85
+ el.type === "adHocSubProcess" ||
86
+ el.type === "eventSubProcess") {
87
+ for (const flow of el.sequenceFlows) {
88
+ flowIndex.set(flow.id, { sourceRef: flow.sourceRef, targetRef: flow.targetRef });
89
+ }
90
+ }
91
+ }
92
+ }
93
+ }
94
+ // ── TokenHighlightApi ─────────────────────────────────────────────────────
95
+ const api = {
96
+ trackInstance(instance) {
97
+ return instance.onChange((evt) => {
98
+ const type = evt.type;
99
+ const elementId = evt.elementId;
100
+ if (typeof type !== "string")
101
+ return;
102
+ if (type === "element:entering" && typeof elementId === "string") {
103
+ activeIds.add(elementId);
104
+ applyHighlights();
105
+ }
106
+ else if (type === "element:left" && typeof elementId === "string") {
107
+ activeIds.delete(elementId);
108
+ visitedIds.add(elementId);
109
+ applyHighlights();
110
+ }
111
+ else if (type === "process:completed" || type === "process:failed") {
112
+ activeIds.clear();
113
+ applyHighlights();
114
+ }
115
+ });
116
+ },
117
+ setActive(elementIds) {
118
+ activeIds.clear();
119
+ for (const id of elementIds)
120
+ activeIds.add(id);
121
+ applyHighlights();
122
+ },
123
+ addVisited(elementIds) {
124
+ for (const id of elementIds)
125
+ visitedIds.add(id);
126
+ applyHighlights();
127
+ },
128
+ setError(elementId) {
129
+ errorIds.add(elementId);
130
+ applyHighlights();
131
+ },
132
+ clear() {
133
+ activeIds.clear();
134
+ visitedIds.clear();
135
+ errorIds.clear();
136
+ applyHighlights();
137
+ },
138
+ };
139
+ // ── CanvasPlugin ──────────────────────────────────────────────────────────
140
+ return {
141
+ name: "token-highlight",
142
+ api,
143
+ install(canvasApiArg) {
144
+ canvasApi = canvasApiArg;
145
+ injectTokenHighlightStyles();
146
+ const onAny = canvasApiArg.on;
147
+ unsubs.push(canvasApiArg.on("diagram:load", (defs) => {
148
+ indexFlows(defs);
149
+ api.clear();
150
+ }), canvasApiArg.on("diagram:clear", () => {
151
+ flowIndex.clear();
152
+ api.clear();
153
+ }), onAny("diagram:change", (defs) => {
154
+ indexFlows(defs);
155
+ }));
156
+ },
157
+ uninstall() {
158
+ for (const off of unsubs)
159
+ off();
160
+ canvasApi = null;
161
+ },
162
+ };
163
+ }
164
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,10 @@
1
+ /** ID used to prevent duplicate style injection. */
2
+ export declare const WATERMARK_STYLE_ID = "bpmnkit-watermark-styles-v1";
3
+ /** CSS for the watermark plugin, injected once into `<head>`. */
4
+ export declare const WATERMARK_CSS = "\n.bpmnkit-watermark {\n position: absolute;\n bottom: 8px;\n right: 8px;\n display: flex;\n align-items: center;\n gap: 8px;\n pointer-events: auto;\n z-index: 10;\n}\n.bpmnkit-watermark-link {\n font-size: 11px;\n color: var(--bpmnkit-overlay-text, rgba(60, 60, 60, 0.7));\n text-decoration: none;\n font-family: system-ui, sans-serif;\n opacity: 0.7;\n transition: opacity 0.15s;\n}\n.bpmnkit-watermark-link:hover {\n opacity: 1;\n text-decoration: underline;\n}\n.bpmnkit-watermark-logo {\n display: flex;\n align-items: center;\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n}\n.bpmnkit-watermark-logo > svg {\n width: 100%;\n height: 100%;\n display: block;\n}\n";
5
+ /**
6
+ * Injects the watermark stylesheet into `<head>` if not already present.
7
+ * Safe to call multiple times — only one `<style>` tag is ever inserted.
8
+ */
9
+ export declare function injectWatermarkStyles(): void;
10
+ //# sourceMappingURL=css.d.ts.map
@@ -0,0 +1,54 @@
1
+ /** ID used to prevent duplicate style injection. */
2
+ export const WATERMARK_STYLE_ID = "bpmnkit-watermark-styles-v1";
3
+ /** CSS for the watermark plugin, injected once into `<head>`. */
4
+ export const WATERMARK_CSS = `
5
+ .bpmnkit-watermark {
6
+ position: absolute;
7
+ bottom: 8px;
8
+ right: 8px;
9
+ display: flex;
10
+ align-items: center;
11
+ gap: 8px;
12
+ pointer-events: auto;
13
+ z-index: 10;
14
+ }
15
+ .bpmnkit-watermark-link {
16
+ font-size: 11px;
17
+ color: var(--bpmnkit-overlay-text, rgba(60, 60, 60, 0.7));
18
+ text-decoration: none;
19
+ font-family: system-ui, sans-serif;
20
+ opacity: 0.7;
21
+ transition: opacity 0.15s;
22
+ }
23
+ .bpmnkit-watermark-link:hover {
24
+ opacity: 1;
25
+ text-decoration: underline;
26
+ }
27
+ .bpmnkit-watermark-logo {
28
+ display: flex;
29
+ align-items: center;
30
+ width: 20px;
31
+ height: 20px;
32
+ flex-shrink: 0;
33
+ }
34
+ .bpmnkit-watermark-logo > svg {
35
+ width: 100%;
36
+ height: 100%;
37
+ display: block;
38
+ }
39
+ `;
40
+ /**
41
+ * Injects the watermark stylesheet into `<head>` if not already present.
42
+ * Safe to call multiple times — only one `<style>` tag is ever inserted.
43
+ */
44
+ export function injectWatermarkStyles() {
45
+ if (typeof document === "undefined")
46
+ return;
47
+ if (document.getElementById(WATERMARK_STYLE_ID))
48
+ return;
49
+ const style = document.createElement("style");
50
+ style.id = WATERMARK_STYLE_ID;
51
+ style.textContent = WATERMARK_CSS;
52
+ document.head.appendChild(style);
53
+ }
54
+ //# sourceMappingURL=css.js.map
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @bpmnkit/canvas-plugin-watermark — bottom-right attribution bar for `@bpmnkit/canvas`.
3
+ *
4
+ * Renders configurable links and an optional logo in the bottom-right corner.
5
+ * Links are left of the logo; the logo is always the rightmost element.
6
+ *
7
+ * ## Usage
8
+ * ```typescript
9
+ * import { BpmnCanvas } from "@bpmnkit/canvas";
10
+ * import { createWatermarkPlugin } from "@bpmnkit/canvas-plugin-watermark";
11
+ *
12
+ * const canvas = new BpmnCanvas({
13
+ * container,
14
+ * plugins: [
15
+ * createWatermarkPlugin({
16
+ * links: [{ label: "GitHub", url: "https://github.com/example/repo" }],
17
+ * logo: myLogoSvgString,
18
+ * }),
19
+ * ],
20
+ * });
21
+ * ```
22
+ *
23
+ * @packageDocumentation
24
+ */
25
+ import type { CanvasPlugin } from "@bpmnkit/canvas";
26
+ export { WATERMARK_CSS, WATERMARK_STYLE_ID, injectWatermarkStyles } from "./css.js";
27
+ /** A single navigable link rendered in the watermark bar. */
28
+ export interface WatermarkLink {
29
+ label: string;
30
+ url: string;
31
+ }
32
+ /** Options for {@link createWatermarkPlugin}. */
33
+ export interface WatermarkOptions {
34
+ /** Links to display, in order from left to right. */
35
+ links?: WatermarkLink[];
36
+ /**
37
+ * Square SVG markup string for the logo, rendered rightmost.
38
+ * Must be a self-contained `<svg>` element.
39
+ */
40
+ logo?: string;
41
+ }
42
+ /**
43
+ * Creates a watermark plugin instance.
44
+ *
45
+ * Each call returns a fresh plugin — pass one instance per canvas.
46
+ */
47
+ export declare function createWatermarkPlugin(options?: WatermarkOptions): CanvasPlugin;
48
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @bpmnkit/canvas-plugin-watermark — bottom-right attribution bar for `@bpmnkit/canvas`.
3
+ *
4
+ * Renders configurable links and an optional logo in the bottom-right corner.
5
+ * Links are left of the logo; the logo is always the rightmost element.
6
+ *
7
+ * ## Usage
8
+ * ```typescript
9
+ * import { BpmnCanvas } from "@bpmnkit/canvas";
10
+ * import { createWatermarkPlugin } from "@bpmnkit/canvas-plugin-watermark";
11
+ *
12
+ * const canvas = new BpmnCanvas({
13
+ * container,
14
+ * plugins: [
15
+ * createWatermarkPlugin({
16
+ * links: [{ label: "GitHub", url: "https://github.com/example/repo" }],
17
+ * logo: myLogoSvgString,
18
+ * }),
19
+ * ],
20
+ * });
21
+ * ```
22
+ *
23
+ * @packageDocumentation
24
+ */
25
+ import { injectWatermarkStyles } from "./css.js";
26
+ export { WATERMARK_CSS, WATERMARK_STYLE_ID, injectWatermarkStyles } from "./css.js";
27
+ /**
28
+ * Creates a watermark plugin instance.
29
+ *
30
+ * Each call returns a fresh plugin — pass one instance per canvas.
31
+ */
32
+ export function createWatermarkPlugin(options = {}) {
33
+ let host = null;
34
+ return {
35
+ name: "watermark",
36
+ install(api) {
37
+ injectWatermarkStyles();
38
+ host = document.createElement("div");
39
+ host.className = "bpmnkit-watermark";
40
+ host.setAttribute("aria-label", "Attribution");
41
+ for (const link of options.links ?? []) {
42
+ const a = document.createElement("a");
43
+ a.className = "bpmnkit-watermark-link";
44
+ a.href = link.url;
45
+ a.target = "_blank";
46
+ a.rel = "noopener noreferrer";
47
+ a.textContent = link.label;
48
+ host.appendChild(a);
49
+ }
50
+ if (options.logo) {
51
+ const logoDiv = document.createElement("div");
52
+ logoDiv.className = "bpmnkit-watermark-logo";
53
+ logoDiv.innerHTML = options.logo;
54
+ host.appendChild(logoDiv);
55
+ }
56
+ api.container.appendChild(host);
57
+ },
58
+ uninstall() {
59
+ host?.remove();
60
+ host = null;
61
+ },
62
+ };
63
+ }
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,4 @@
1
+ export declare const ZOOM_CONTROLS_STYLE_ID = "bpmnkit-zoom-controls-styles-v1";
2
+ export declare const ZOOM_CONTROLS_CSS = "\n.bpmnkit-controls {\n position: absolute;\n bottom: 12px;\n left: 12px;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n.bpmnkit-control-btn {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n line-height: 1;\n font-size: 16px;\n font-family: system-ui, sans-serif;\n background: var(--bpmnkit-overlay-bg, rgba(248, 249, 250, 0.92));\n border: 1px solid var(--bpmnkit-overlay-border, rgba(0, 0, 0, 0.12));\n border-radius: 4px;\n color: var(--bpmnkit-text, #333333);\n cursor: pointer;\n transition: background 0.1s, color 0.1s;\n}\n.bpmnkit-control-btn:hover {\n background: var(--bpmnkit-highlight, var(--bpmnkit-accent, #1a56db));\n color: #fff;\n border-color: transparent;\n}\n.bpmnkit-control-btn:focus {\n outline: 2px solid var(--bpmnkit-focus, var(--bpmnkit-accent, #1a56db));\n outline-offset: 1px;\n}\n";
3
+ export declare function injectZoomControlsStyles(): void;
4
+ //# sourceMappingURL=css.d.ts.map
@@ -0,0 +1,48 @@
1
+ export const ZOOM_CONTROLS_STYLE_ID = "bpmnkit-zoom-controls-styles-v1";
2
+ export const ZOOM_CONTROLS_CSS = `
3
+ .bpmnkit-controls {
4
+ position: absolute;
5
+ bottom: 12px;
6
+ left: 12px;
7
+ display: flex;
8
+ flex-direction: column;
9
+ gap: 2px;
10
+ }
11
+ .bpmnkit-control-btn {
12
+ width: 28px;
13
+ height: 28px;
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: center;
17
+ padding: 0;
18
+ line-height: 1;
19
+ font-size: 16px;
20
+ font-family: system-ui, sans-serif;
21
+ background: var(--bpmnkit-overlay-bg, rgba(248, 249, 250, 0.92));
22
+ border: 1px solid var(--bpmnkit-overlay-border, rgba(0, 0, 0, 0.12));
23
+ border-radius: 4px;
24
+ color: var(--bpmnkit-text, #333333);
25
+ cursor: pointer;
26
+ transition: background 0.1s, color 0.1s;
27
+ }
28
+ .bpmnkit-control-btn:hover {
29
+ background: var(--bpmnkit-highlight, var(--bpmnkit-accent, #1a56db));
30
+ color: #fff;
31
+ border-color: transparent;
32
+ }
33
+ .bpmnkit-control-btn:focus {
34
+ outline: 2px solid var(--bpmnkit-focus, var(--bpmnkit-accent, #1a56db));
35
+ outline-offset: 1px;
36
+ }
37
+ `;
38
+ export function injectZoomControlsStyles() {
39
+ if (typeof document === "undefined")
40
+ return;
41
+ if (document.getElementById(ZOOM_CONTROLS_STYLE_ID))
42
+ return;
43
+ const style = document.createElement("style");
44
+ style.id = ZOOM_CONTROLS_STYLE_ID;
45
+ style.textContent = ZOOM_CONTROLS_CSS;
46
+ document.head.appendChild(style);
47
+ }
48
+ //# sourceMappingURL=css.js.map
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @bpmnkit/canvas-plugin-zoom-controls — zoom controls plugin for `@bpmnkit/canvas`.
3
+ *
4
+ * Adds +, −, and fit-diagram buttons in the bottom-left corner of the canvas.
5
+ *
6
+ * ## Usage
7
+ * ```typescript
8
+ * import { BpmnCanvas } from "@bpmnkit/canvas";
9
+ * import { createZoomControlsPlugin } from "@bpmnkit/canvas-plugin-zoom-controls";
10
+ *
11
+ * const canvas = new BpmnCanvas({
12
+ * container: document.getElementById("app")!,
13
+ * xml: myBpmnXml,
14
+ * plugins: [createZoomControlsPlugin()],
15
+ * });
16
+ * ```
17
+ *
18
+ * @packageDocumentation
19
+ */
20
+ import type { CanvasPlugin } from "@bpmnkit/canvas";
21
+ export { ZOOM_CONTROLS_CSS, ZOOM_CONTROLS_STYLE_ID, injectZoomControlsStyles } from "./css.js";
22
+ /**
23
+ * Creates a zoom controls plugin instance.
24
+ *
25
+ * Each call returns a fresh plugin — pass one instance per canvas.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const canvas = new BpmnCanvas({
30
+ * container,
31
+ * plugins: [createZoomControlsPlugin()],
32
+ * });
33
+ * ```
34
+ */
35
+ export declare function createZoomControlsPlugin(): CanvasPlugin;
36
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @bpmnkit/canvas-plugin-zoom-controls — zoom controls plugin for `@bpmnkit/canvas`.
3
+ *
4
+ * Adds +, −, and fit-diagram buttons in the bottom-left corner of the canvas.
5
+ *
6
+ * ## Usage
7
+ * ```typescript
8
+ * import { BpmnCanvas } from "@bpmnkit/canvas";
9
+ * import { createZoomControlsPlugin } from "@bpmnkit/canvas-plugin-zoom-controls";
10
+ *
11
+ * const canvas = new BpmnCanvas({
12
+ * container: document.getElementById("app")!,
13
+ * xml: myBpmnXml,
14
+ * plugins: [createZoomControlsPlugin()],
15
+ * });
16
+ * ```
17
+ *
18
+ * @packageDocumentation
19
+ */
20
+ import { injectZoomControlsStyles } from "./css.js";
21
+ export { ZOOM_CONTROLS_CSS, ZOOM_CONTROLS_STYLE_ID, injectZoomControlsStyles } from "./css.js";
22
+ const MIN_SCALE = 0.05;
23
+ const MAX_SCALE = 10;
24
+ const FIT_PADDING = 40;
25
+ /**
26
+ * Creates a zoom controls plugin instance.
27
+ *
28
+ * Each call returns a fresh plugin — pass one instance per canvas.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const canvas = new BpmnCanvas({
33
+ * container,
34
+ * plugins: [createZoomControlsPlugin()],
35
+ * });
36
+ * ```
37
+ */
38
+ export function createZoomControlsPlugin() {
39
+ let controlsEl = null;
40
+ return {
41
+ name: "zoom-controls",
42
+ install(api) {
43
+ injectZoomControlsStyles();
44
+ function zoomAt(factor) {
45
+ const { tx, ty, scale } = api.getViewport();
46
+ const cx = api.svg.clientWidth / 2;
47
+ const cy = api.svg.clientHeight / 2;
48
+ const newScale = Math.min(Math.max(scale * factor, MIN_SCALE), MAX_SCALE);
49
+ const ratio = newScale / scale;
50
+ api.setViewport({
51
+ tx: cx - (cx - tx) * ratio,
52
+ ty: cy - (cy - ty) * ratio,
53
+ scale: newScale,
54
+ });
55
+ }
56
+ function fitView() {
57
+ const shapes = api.getShapes();
58
+ if (shapes.length === 0)
59
+ return;
60
+ let minX = Number.POSITIVE_INFINITY;
61
+ let minY = Number.POSITIVE_INFINITY;
62
+ let maxX = Number.NEGATIVE_INFINITY;
63
+ let maxY = Number.NEGATIVE_INFINITY;
64
+ for (const s of shapes) {
65
+ const b = s.shape.bounds;
66
+ if (b.x < minX)
67
+ minX = b.x;
68
+ if (b.y < minY)
69
+ minY = b.y;
70
+ if (b.x + b.width > maxX)
71
+ maxX = b.x + b.width;
72
+ if (b.y + b.height > maxY)
73
+ maxY = b.y + b.height;
74
+ }
75
+ const svgW = api.svg.clientWidth;
76
+ const svgH = api.svg.clientHeight;
77
+ const dw = maxX - minX;
78
+ const dh = maxY - minY;
79
+ const scale = Math.min((svgW - FIT_PADDING * 2) / dw, (svgH - FIT_PADDING * 2) / dh, 2);
80
+ api.setViewport({
81
+ tx: (svgW - dw * scale) / 2 - minX * scale,
82
+ ty: (svgH - dh * scale) / 2 - minY * scale,
83
+ scale,
84
+ });
85
+ }
86
+ const controls = document.createElement("div");
87
+ controls.className = "bpmnkit-controls";
88
+ controls.setAttribute("aria-label", "Zoom controls");
89
+ const makeBtn = (label, title, onClick) => {
90
+ const btn = document.createElement("button");
91
+ btn.className = "bpmnkit-control-btn";
92
+ btn.type = "button";
93
+ btn.textContent = label;
94
+ btn.setAttribute("aria-label", title);
95
+ btn.title = title;
96
+ btn.addEventListener("click", onClick);
97
+ return btn;
98
+ };
99
+ controls.appendChild(makeBtn("+", "Zoom in", () => zoomAt(1.25)));
100
+ controls.appendChild(makeBtn("−", "Zoom out", () => zoomAt(0.8)));
101
+ controls.appendChild(makeBtn("⊡", "Fit diagram", fitView));
102
+ api.container.appendChild(controls);
103
+ controlsEl = controls;
104
+ },
105
+ uninstall() {
106
+ controlsEl?.remove();
107
+ controlsEl = null;
108
+ },
109
+ };
110
+ }
111
+ //# sourceMappingURL=index.js.map