@bpmnkit/editor 0.0.11 → 0.0.13
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 +5 -1
- package/dist/css.d.ts +1 -1
- package/dist/css.js +40 -6
- package/dist/dock.js +28 -0
- package/dist/editor.d.ts +3 -2
- package/dist/editor.js +21 -10
- package/dist/hud.d.ts +5 -0
- package/dist/hud.js +12 -4
- package/dist/state-machine.d.ts +11 -0
- package/dist/state-machine.js +208 -164
- package/dist/types.d.ts +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="https://
|
|
2
|
+
<a href="https://bpmnkit.com"><img src="https://bpmnkit.com/favicon.svg" width="72" height="72" alt="BPMN Kit logo"></a>
|
|
3
3
|
<h1>@bpmnkit/editor</h1>
|
|
4
4
|
<p>Full-featured interactive BPMN editor with undo/redo, HUD, and side-dock UI</p>
|
|
5
5
|
|
|
@@ -123,3 +123,7 @@ interface SideDock {
|
|
|
123
123
|
## License
|
|
124
124
|
|
|
125
125
|
[MIT](https://github.com/bpmnkit/monorepo/blob/main/LICENSE) © BPMN Kit — made by [u11g](https://u11g.com)
|
|
126
|
+
|
|
127
|
+
<div align="center">
|
|
128
|
+
<a href="https://bpmnkit.com"><img src="https://bpmnkit.com/favicon.svg" width="32" height="32" alt="BPMN Kit"></a>
|
|
129
|
+
</div>
|
package/dist/css.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare function injectEditorStyles(): void;
|
|
|
9
9
|
/** CSS for the editor HUD — panels, buttons, dropdowns, group picker.
|
|
10
10
|
* Dark theme is the default. Light theme is activated by setting
|
|
11
11
|
* `data-bpmnkit-hud-theme="light"` on `document.body`. */
|
|
12
|
-
export declare const HUD_CSS = "\n/* \u2500\u2500 HUD base \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.hud { position: absolute; z-index: 100; }\n\n/* \u2500\u2500 Dark theme (default) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.panel {\n display: flex; align-items: center; gap: 2px; padding: 4px;\n background: var(--bpmnkit-panel-bg, rgba(13, 13, 22, 0.92));\n backdrop-filter: blur(10px);\n border: 1px solid var(--bpmnkit-panel-border, rgba(255, 255, 255, 0.08));\n border-radius: 10px;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);\n}\n\n/* \u2500\u2500 HUD positions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#hud-top-center { top: 0; left: 50%; transform: translateX(-50%); height: 36px; }\n#hud-bottom-left { bottom: 10px; left: 10px; }\n#hud-bottom-center { bottom: 10px; left: 50%; transform: translateX(-50%); }\n#ctx-toolbar { display: none; transform: translateX(-50%); }\n#cfg-toolbar { display: none; transform: translate(-50%, -100%); }\n\n/* \u2500\u2500 Top center: strip floating card, merge into tab bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#hud-top-center.panel {\n background: transparent;\n backdrop-filter: none;\n border: none;\n border-radius: 0;\n box-shadow: none;\n padding: 0 2px;\n /* Pass clicks through the transparent background to the tab bar center slot. */\n pointer-events: none;\n}\n#hud-top-center.panel > * {\n pointer-events: auto;\n}\n\n/* \u2500\u2500 Icon buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.hud-btn {\n display: flex; align-items: center; justify-content: center;\n width: 32px; height: 32px;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 6px;\n color: var(--bpmnkit-fg-muted, rgba(255,255,255,0.6));\n cursor: pointer;\n transition: background 0.1s, color 0.1s, border-color 0.1s;\n padding: 0; flex-shrink: 0;\n}\n.hud-btn:hover { background: rgba(255,255,255,0.08); color: var(--bpmnkit-fg, #cdd6f4); }\n.hud-btn.active { background: rgba(255,255,255,0.12); color: #fff; border-color: rgba(255,255,255,0.2); }\n.hud-btn:disabled { opacity: 0.28; cursor: default; }\n.hud-btn:disabled:hover { background: transparent; color: rgba(255,255,255,0.6); }\n.hud-btn svg { width: 16px; height: 16px; pointer-events: none; }\n\n/* \u2500\u2500 Group button: small chevron at bottom-right corner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.hud-btn[data-group] { position: relative; }\n.hud-btn[data-group]::after {\n content: '';\n position: absolute; bottom: 3px; right: 3px;\n width: 0; height: 0;\n border-left: 3px solid transparent;\n border-top: 3px solid currentColor;\n opacity: 0.55;\n}\n\n/* \u2500\u2500 Tool groups container \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#tool-groups { display: flex; align-items: center; gap: 2px; }\n\n/* \u2500\u2500 Separator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.hud-sep { width: 1px; height: 20px; background: var(--bpmnkit-panel-border, rgba(255, 255, 255, 0.08)); margin: 0 2px; flex-shrink: 0; }\n\n/* \u2500\u2500 Zoom widget \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#btn-zoom-current {\n padding: 0 10px; height: 32px;\n background: transparent; border: 1px solid transparent; border-radius: 7px;\n color: rgba(255,255,255,0.6); cursor: pointer;\n font-size: 12px; font-weight: 600;\n transition: background 0.1s, color 0.1s;\n white-space: nowrap;\n}\n#btn-zoom-current:hover { background: rgba(255,255,255,0.08); color: #fff; }\n\n#zoom-expanded { display: none; align-items: center; gap: 2px; }\n#zoom-expanded.open { display: flex; }\n\n#btn-zoom-pct {\n padding: 0 8px; height: 30px;\n background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.1); border-radius: 6px;\n color: rgba(255,255,255,0.75); cursor: pointer;\n font-size: 12px; font-weight: 600;\n transition: background 0.1s, color 0.1s;\n white-space: nowrap; min-width: 60px; text-align: center;\n}\n#btn-zoom-pct:hover { background: rgba(255,255,255,0.12); color: #fff; }\n\n/* \u2500\u2500 Dropdown menus \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.dropdown {\n position: absolute; display: none; flex-direction: column;\n gap: 1px; padding: 4px;\n background: var(--bpmnkit-panel-bg, rgba(13, 13, 22, 0.92));\n backdrop-filter: blur(12px);\n border: 1px solid var(--bpmnkit-panel-border, rgba(255, 255, 255, 0.08));\n border-radius: 9px;\n box-shadow: 0 6px 24px rgba(0,0,0,0.5);\n z-index: 200; min-width: 150px;\n}\n.dropdown.open { display: flex; }\n\n.drop-item {\n display: flex; align-items: center; gap: 8px;\n padding: 7px 10px;\n border: none; background: transparent;\n color: rgba(255,255,255,0.75); cursor: pointer;\n border-radius: 6px; font-size: 12px; text-align: left; width: 100%;\n transition: background 0.1s;\n}\n.drop-item:hover { background: rgba(255,255,255,0.08); color: #fff; }\n.drop-item .di-check { width: 14px; height: 14px; flex-shrink: 0; color: var(--bpmnkit-accent, #6b9df7); }\n.drop-item .di-icon { width: 14px; height: 14px; flex-shrink: 0; opacity: 0.7; }\n.drop-item svg { width: 14px; height: 14px; }\n.drop-sep { height: 1px; background: rgba(255,255,255,0.08); margin: 3px 0; }\n.drop-label {\n padding: 4px 10px 2px;\n font-size: 10px; font-weight: 600; letter-spacing: 0.06em;\n color: rgba(255,255,255,0.3); text-transform: uppercase;\n}\n\n/* \u2500\u2500 Group element picker \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.group-picker {\n position: absolute;\n display: flex; flex-direction: row;\n gap: 2px; padding: 4px;\n background: var(--bpmnkit-panel-bg, rgba(13, 13, 22, 0.92));\n backdrop-filter: blur(12px);\n border: 1px solid var(--bpmnkit-panel-border, rgba(255, 255, 255, 0.08));\n border-radius: 9px;\n box-shadow: 0 6px 24px rgba(0,0,0,0.5);\n z-index: 300;\n}\n.group-picker-label {\n padding: 2px 6px 4px;\n font-size: 10px; font-weight: 600; letter-spacing: 0.05em;\n color: rgba(255,255,255,0.3); text-transform: uppercase;\n white-space: nowrap; align-self: center;\n border-right: 1px solid rgba(255,255,255,0.08);\n margin-right: 2px;\n}\n\n/* \u2500\u2500 Light theme overrides \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n[data-bpmnkit-hud-theme=\"light\"] .panel {\n background: var(--bpmnkit-panel-bg, rgba(255,255,255,0.92));\n border-color: var(--bpmnkit-panel-border, rgba(0,0,0,0.08));\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n}\n[data-bpmnkit-hud-theme=\"light\"] #hud-top-center.panel {\n background: transparent;\n backdrop-filter: none;\n border: none;\n box-shadow: none;\n}\n[data-bpmnkit-hud-theme=\"light\"] .hud-btn { color: var(--bpmnkit-fg-muted, #6666a0); }\n[data-bpmnkit-hud-theme=\"light\"] .hud-btn:hover { background: rgba(0,0,0,0.06); color: var(--bpmnkit-fg, #1a1a2e); }\n[data-bpmnkit-hud-theme=\"light\"] .hud-btn.active { background: rgba(0,0,0,0.08); color: var(--bpmnkit-fg, #1a1a2e); border-color: rgba(0,0,0,0.15); }\n[data-bpmnkit-hud-theme=\"light\"] .hud-btn:disabled:hover { background: transparent; color: var(--bpmnkit-fg-muted, #6666a0); }\n[data-bpmnkit-hud-theme=\"light\"] .hud-sep { background: var(--bpmnkit-panel-border, rgba(0,0,0,0.08)); }\n[data-bpmnkit-hud-theme=\"light\"] #btn-zoom-current { color: var(--bpmnkit-fg-muted, #6666a0); }\n[data-bpmnkit-hud-theme=\"light\"] #btn-zoom-current:hover { background: rgba(0,0,0,0.06); color: var(--bpmnkit-fg, #1a1a2e); }\n[data-bpmnkit-hud-theme=\"light\"] #btn-zoom-pct {\n background: rgba(0,0,0,0.04); border-color: rgba(0,0,0,0.1); color: var(--bpmnkit-fg-muted, #6666a0);\n}\n[data-bpmnkit-hud-theme=\"light\"] #btn-zoom-pct:hover { background: rgba(0,0,0,0.08); color: var(--bpmnkit-fg, #1a1a2e); }\n[data-bpmnkit-hud-theme=\"light\"] .dropdown {\n background: var(--bpmnkit-panel-bg, rgba(255,255,255,0.92));\n border-color: var(--bpmnkit-panel-border, rgba(0,0,0,0.08));\n box-shadow: 0 6px 24px rgba(0,0,0,0.15);\n}\n[data-bpmnkit-hud-theme=\"light\"] .drop-item { color: var(--bpmnkit-fg-muted, #6666a0); }\n[data-bpmnkit-hud-theme=\"light\"] .drop-item:hover { background: rgba(0,0,0,0.05); color: var(--bpmnkit-fg, #1a1a2e); }\n[data-bpmnkit-hud-theme=\"light\"] .drop-sep { background: var(--bpmnkit-border, #d0d0e8); }\n[data-bpmnkit-hud-theme=\"light\"] .drop-label { color: rgba(0,0,0,0.35); }\n[data-bpmnkit-hud-theme=\"light\"] .group-picker {\n background: var(--bpmnkit-panel-bg, rgba(255,255,255,0.92));\n border-color: var(--bpmnkit-panel-border, rgba(0,0,0,0.08));\n box-shadow: 0 6px 24px rgba(0,0,0,0.15);\n}\n[data-bpmnkit-hud-theme=\"light\"] .group-picker-label {\n color: rgba(0,0,0,0.35);\n border-right-color: rgba(0,0,0,0.08);\n}\n\n/* \u2500\u2500 Reference link button (wider text variant of hud-btn) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.ref-link-btn {\n height: 32px; padding: 0 8px;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 6px;\n color: rgba(255, 255, 255, 0.6);\n cursor: pointer;\n font-size: 12px;\n max-width: 160px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex-shrink: 0;\n transition: background 0.1s, color 0.1s;\n align-self: center;\n}\n.ref-link-btn:hover { background: rgba(255,255,255,0.08); color: #fff; }\n[data-bpmnkit-hud-theme=\"light\"] .ref-link-btn { color: var(--bpmnkit-fg-muted, #6666a0); }\n[data-bpmnkit-hud-theme=\"light\"] .ref-link-btn:hover { background: rgba(0,0,0,0.06); color: var(--bpmnkit-fg, #1a1a2e); }\n\n/* \u2500\u2500 Color swatches \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.bpmnkit-color-swatches { display: flex; gap: 4px; padding: 2px 4px; align-items: center; }\n.bpmnkit-color-swatch {\n width: 16px; height: 16px; border-radius: 50%; cursor: pointer;\n border: 2px solid transparent; flex-shrink: 0;\n transition: transform 0.1s;\n padding: 0;\n}\n.bpmnkit-color-swatch:hover { transform: scale(1.2); }\n.bpmnkit-color-swatch.active { border-color: rgba(255,255,255,0.8); }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-color-swatch.active { border-color: rgba(0,0,0,0.5); }\n.bpmnkit-color-swatch--default {\n background: transparent; border-color: rgba(255,255,255,0.25);\n position: relative; overflow: hidden;\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-color-swatch--default { border-color: rgba(0,0,0,0.2); }\n.bpmnkit-color-swatch--default::after {\n content: ''; position: absolute;\n top: 1px; left: 50%; transform: translateX(-50%) rotate(-45deg);\n width: 1.5px; height: calc(100% - 2px);\n background: rgba(200,50,50,0.65); border-radius: 1px;\n}\n\n/* \u2500\u2500 Contextual Ask-AI button (tinted blue) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.ctx-ask-ai-btn { color: var(--bpmnkit-accent-bright, #89b4fa); opacity: 0.8; }\n.ctx-ask-ai-btn:hover { background: rgba(76, 142, 247, 0.15); color: #a8c8ff; opacity: 1; }\n[data-bpmnkit-hud-theme=\"light\"] .ctx-ask-ai-btn { color: var(--bpmnkit-accent, #1a56db); opacity: 0.7; }\n[data-bpmnkit-hud-theme=\"light\"] .ctx-ask-ai-btn:hover { background: var(--bpmnkit-accent-subtle, rgba(26,86,219,0.12)); color: var(--bpmnkit-accent, #1a56db); opacity: 1; }\n\n/* \u2500\u2500 New-diagram onboarding overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#bpmnkit-empty-state {\n position: absolute; z-index: 50;\n top: 36px; left: 0; bottom: 0; right: 0;\n display: flex; align-items: center; justify-content: center;\n background: var(--bpmnkit-bg, #0d0d16);\n}\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-empty-state { background: var(--bpmnkit-bg, #f4f4f8); }\n\n.bpmnkit-onboard-inner {\n display: flex; flex-direction: column; align-items: center;\n gap: 28px; padding: 24px; max-width: 580px; width: 100%;\n}\n.bpmnkit-onboard-header { text-align: center; }\n.bpmnkit-onboard-title {\n color: rgba(255,255,255,0.82); font-size: 16px; font-weight: 600; margin: 0 0 7px;\n}\n.bpmnkit-onboard-sub {\n color: rgba(255,255,255,0.36); font-size: 13px; margin: 0;\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-title { color: rgba(0,0,0,0.72); }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-sub { color: rgba(0,0,0,0.38); }\n\n.bpmnkit-onboard-actions { display: flex; gap: 10px; width: 100%; }\n\n.bpmnkit-onboard-btn {\n flex: 1; display: flex; flex-direction: column; align-items: flex-start;\n gap: 10px; padding: 16px 14px;\n background: rgba(255,255,255,0.04);\n border: 1px solid rgba(255,255,255,0.07);\n border-radius: 10px; cursor: pointer; text-align: left;\n color: inherit; transition: background 0.15s, border-color 0.15s;\n}\n.bpmnkit-onboard-btn:hover {\n background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.14);\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn {\n background: rgba(0,0,0,0.03); border-color: rgba(0,0,0,0.08);\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn:hover {\n background: rgba(0,0,0,0.06); border-color: rgba(0,0,0,0.14);\n}\n\n.bpmnkit-onboard-btn-icon {\n display: flex; align-items: center; justify-content: center;\n width: 32px; height: 32px; border-radius: 8px;\n background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.65); flex-shrink: 0;\n}\n.bpmnkit-onboard-btn-icon svg { width: 16px; height: 16px; pointer-events: none; }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn-icon {\n background: rgba(0,0,0,0.07); color: rgba(0,0,0,0.55);\n}\n\n.bpmnkit-onboard-btn--ai .bpmnkit-onboard-btn-icon {\n background: rgba(76,142,247,0.18); color: #8ab8ff;\n}\n.bpmnkit-onboard-btn--ai:hover { border-color: rgba(76,142,247,0.3); }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn--ai .bpmnkit-onboard-btn-icon {\n background: rgba(26,86,219,0.1); color: #1a56db;\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn--ai:hover { border-color: rgba(26,86,219,0.28); }\n\n.bpmnkit-onboard-btn-label { display: flex; flex-direction: column; gap: 3px; }\n.bpmnkit-onboard-btn-title {\n font-size: 13px; font-weight: 600; color: rgba(255,255,255,0.8); margin: 0;\n}\n.bpmnkit-onboard-btn-desc {\n font-size: 11px; color: rgba(255,255,255,0.32); margin: 0; line-height: 1.4;\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn-title { color: rgba(0,0,0,0.72); }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn-desc { color: rgba(0,0,0,0.36); }\n\n.bpmnkit-onboard-links { display: flex; gap: 16px; flex-wrap: wrap; justify-content: center; }\n.bpmnkit-onboard-links a {\n color: rgba(255,255,255,0.22); font-size: 11px; text-decoration: none; transition: color 0.1s;\n}\n.bpmnkit-onboard-links a:hover { color: rgba(255,255,255,0.55); }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-links a { color: rgba(0,0,0,0.25); }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-links a:hover { color: rgba(0,0,0,0.6); }\n\n@media (max-width: 520px) {\n .bpmnkit-onboard-actions { flex-direction: column; }\n .bpmnkit-onboard-btn { flex-direction: row; align-items: center; gap: 12px; }\n .bpmnkit-onboard-btn-label { flex-direction: column; }\n}\n\n/* \u2500\u2500 Top-center overflow guard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#hud-top-center {\n max-width: calc(100% - 24px);\n overflow-x: auto; overflow-y: visible;\n scrollbar-width: none;\n}\n#hud-top-center::-webkit-scrollbar { display: none; }\n\n/* \u2500\u2500 Push HUD toolbar down when simulation banner is visible \u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.bpmnkit-sim-active #hud-top-center { top: 36px; }\n\n/* \u2500\u2500 Simulation active banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#bpmnkit-sim-banner {\n position: absolute;\n top: 0; left: 0; right: 0;\n z-index: 150;\n display: flex; align-items: center; justify-content: center; gap: 12px;\n padding: 7px 16px;\n background: rgba(217, 119, 6, 0.18);\n border-bottom: 1px solid rgba(217, 119, 6, 0.35);\n backdrop-filter: blur(6px);\n font-size: 12px; font-weight: 500;\n color: rgba(255, 193, 87, 0.95);\n pointer-events: auto;\n}\n#bpmnkit-sim-banner.hidden { display: none; }\n#bpmnkit-sim-banner-exit {\n padding: 3px 10px; border-radius: 5px;\n background: rgba(217, 119, 6, 0.22);\n border: 1px solid rgba(217, 119, 6, 0.4);\n color: inherit; cursor: pointer; font-size: 11px; font-weight: 600;\n transition: background 0.1s;\n}\n#bpmnkit-sim-banner-exit:hover { background: rgba(217, 119, 6, 0.35); }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-sim-banner {\n background: rgba(254, 243, 199, 0.95);\n border-bottom-color: rgba(217, 119, 6, 0.25);\n color: #92400e;\n}\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-sim-banner-exit {\n background: rgba(217, 119, 6, 0.1); border-color: rgba(217, 119, 6, 0.3);\n}\n\n/* \u2500\u2500 Context menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#bpmnkit-ctx-menu { min-width: 160px; }\n\n/* \u2500\u2500 Element search bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#bpmnkit-search-bar {\n position: absolute;\n top: 44px; left: 50%; transform: translateX(-50%);\n z-index: 120;\n display: flex; align-items: center; gap: 6px;\n padding: 5px 10px;\n background: rgba(22, 22, 30, 0.92);\n backdrop-filter: blur(10px);\n border: 1px solid rgba(255,255,255,0.15);\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0,0,0,0.4);\n}\n#bpmnkit-search-bar.hidden { display: none; }\n#bpmnkit-search-input {\n width: 220px; padding: 3px 6px;\n background: transparent; border: none;\n color: #fff; font-size: 13px; outline: none;\n}\n#bpmnkit-search-input::placeholder { color: rgba(255,255,255,0.35); }\n#bpmnkit-search-count {\n font-size: 11px; color: rgba(255,255,255,0.45); white-space: nowrap; min-width: 40px;\n}\n#bpmnkit-search-close {\n background: transparent; border: none; color: rgba(255,255,255,0.4);\n cursor: pointer; font-size: 16px; line-height: 1; padding: 0 2px;\n}\n#bpmnkit-search-close:hover { color: #fff; }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-search-bar {\n background: rgba(252, 252, 254, 0.96);\n border-color: var(--bpmnkit-panel-border, rgba(0,0,0,0.08));\n box-shadow: 0 4px 16px rgba(0,0,0,0.12);\n}\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-search-input { color: rgba(0,0,0,0.9); }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-search-input::placeholder { color: rgba(0,0,0,0.3); }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-search-count { color: rgba(0,0,0,0.4); }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-search-close { color: rgba(0,0,0,0.35); }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-search-close:hover { color: rgba(0,0,0,0.8); }\n\n/* \u2500\u2500 Keyboard shortcuts modal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#bpmnkit-shortcuts-modal {\n position: absolute; inset: 0; z-index: 200;\n display: flex; align-items: center; justify-content: center;\n background: rgba(0,0,0,0.55);\n backdrop-filter: blur(4px);\n}\n#bpmnkit-shortcuts-modal.hidden { display: none; }\n#bpmnkit-shortcuts-inner {\n background: var(--bpmnkit-surface-2, #1e1e2e);\n border: 1px solid var(--bpmnkit-panel-border, rgba(255,255,255,0.08));\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0,0,0,0.5);\n padding: 20px 24px;\n min-width: 320px; max-width: 480px;\n color: rgba(255,255,255,0.85);\n}\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-shortcuts-inner {\n background: var(--bpmnkit-surface, #fff);\n border-color: var(--bpmnkit-panel-border, rgba(0,0,0,0.08));\n box-shadow: 0 8px 32px rgba(0,0,0,0.15);\n color: rgba(0,0,0,0.8);\n}\n#bpmnkit-shortcuts-inner h3 { margin: 0 0 14px; font-size: 14px; font-weight: 700; }\n.bpmnkit-sc-row {\n display: flex; justify-content: space-between; align-items: center;\n padding: 5px 0; border-bottom: 1px solid rgba(255,255,255,0.06); font-size: 12px;\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-sc-row { border-bottom-color: rgba(0,0,0,0.06); }\n.bpmnkit-sc-row:last-child { border-bottom: none; }\n.bpmnkit-sc-key {\n font-family: var(--font-mono, monospace);\n background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.12);\n border-radius: 4px; padding: 1px 6px; font-size: 11px;\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-sc-key {\n background: rgba(0,0,0,0.06); border-color: rgba(0,0,0,0.12); color: rgba(0,0,0,0.7);\n}\n#bpmnkit-shortcuts-close {\n display: block; margin: 14px auto 0; padding: 6px 20px;\n background: var(--bpmnkit-surface-2, rgba(255,255,255,0.08)); border: 1px solid var(--bpmnkit-panel-border, rgba(255,255,255,0.08));\n border-radius: 6px; color: rgba(255,255,255,0.7); cursor: pointer; font-size: 12px;\n transition: background 0.1s;\n}\n#bpmnkit-shortcuts-close:hover { background: rgba(255,255,255,0.14); color: #fff; }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-shortcuts-close {\n background: var(--bpmnkit-surface-2, rgba(0,0,0,0.05)); border-color: var(--bpmnkit-border, #d0d0e8); color: rgba(0,0,0,0.6);\n}\n\n/* \u2500\u2500 Mobile: collapsible center toolbars \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#btn-bc-toggle, #btn-tc-toggle { display: none; }\n\n@media (max-width: 600px) {\n #btn-bc-toggle, #btn-tc-toggle { display: flex; }\n\n /* Collapsed: hide all children except the toggle button */\n #hud-bottom-center:not(.expanded) > *:not(#btn-bc-toggle) { display: none; }\n #hud-top-center:not(.expanded) > *:not(#btn-tc-toggle) { display: none; }\n\n /* Expanded: highlight the toggle button as a close affordance */\n #hud-bottom-center.expanded #btn-bc-toggle,\n #hud-top-center.expanded #btn-tc-toggle {\n background: rgba(255,255,255,0.08); color: #fff;\n }\n [data-bpmnkit-hud-theme=\"light\"] #hud-bottom-center.expanded #btn-bc-toggle,\n [data-bpmnkit-hud-theme=\"light\"] #hud-top-center.expanded #btn-tc-toggle {\n background: rgba(0,0,0,0.06); color: rgba(0,0,0,0.9);\n }\n}\n\n/* Hide bottom toolbar on welcome screen */\n.bpmnkit-welcome-active #hud-bottom-center { display: none !important; }\n";
|
|
12
|
+
export declare const HUD_CSS = "\n/* \u2500\u2500 HUD base \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.hud { position: absolute; z-index: 100; }\n\n/* \u2500\u2500 Dark theme (default) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.panel {\n display: flex; align-items: center; gap: 2px; padding: 4px;\n background: var(--bpmnkit-panel-bg, rgba(13, 13, 22, 0.92));\n backdrop-filter: blur(10px);\n border: 1px solid var(--bpmnkit-panel-border, rgba(255, 255, 255, 0.08));\n border-radius: 10px;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);\n}\n\n/* \u2500\u2500 HUD positions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#hud-top-center { top: 0; left: 50%; transform: translateX(-50%); height: 36px; }\n#hud-bottom-left { bottom: 10px; left: 10px; }\n#hud-bottom-center { bottom: 10px; left: 50%; transform: translateX(-50%); }\n#ctx-toolbar { display: none; transform: translateX(-50%); }\n#cfg-toolbar { display: none; transform: translate(-50%, -100%); }\n\n/* \u2500\u2500 Top center: strip floating card, merge into tab bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#hud-top-center.panel {\n background: transparent;\n backdrop-filter: none;\n border: none;\n border-radius: 0;\n box-shadow: none;\n padding: 0 2px;\n /* Pass clicks through the transparent background to the tab bar center slot. */\n pointer-events: none;\n}\n#hud-top-center.panel > * {\n pointer-events: auto;\n}\n\n/* \u2500\u2500 Icon buttons \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.hud-btn {\n display: flex; align-items: center; justify-content: center;\n width: 32px; height: 32px;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 6px;\n color: var(--bpmnkit-fg-muted, rgba(255,255,255,0.6));\n cursor: pointer;\n transition: background 0.1s, color 0.1s, border-color 0.1s;\n padding: 0; flex-shrink: 0;\n}\n.hud-btn:hover { background: rgba(255,255,255,0.08); color: var(--bpmnkit-fg, #cdd6f4); }\n.hud-btn.active { background: rgba(255,255,255,0.12); color: #fff; border-color: rgba(255,255,255,0.2); }\n.hud-btn:disabled { opacity: 0.28; cursor: default; }\n.hud-btn:disabled:hover { background: transparent; color: rgba(255,255,255,0.6); }\n.hud-btn svg { width: 16px; height: 16px; pointer-events: none; }\n\n/* \u2500\u2500 Group button: small chevron at bottom-right corner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.hud-btn[data-group] { position: relative; }\n.hud-btn[data-group]::after {\n content: '';\n position: absolute; bottom: 3px; right: 3px;\n width: 0; height: 0;\n border-left: 3px solid transparent;\n border-top: 3px solid currentColor;\n opacity: 0.55;\n}\n\n/* \u2500\u2500 Tool groups container \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#tool-groups { display: flex; align-items: center; gap: 2px; }\n\n/* \u2500\u2500 Separator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.hud-sep { width: 1px; height: 20px; background: var(--bpmnkit-panel-border, rgba(255, 255, 255, 0.08)); margin: 0 2px; flex-shrink: 0; }\n\n/* \u2500\u2500 Zoom widget \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#btn-zoom-current {\n padding: 0 10px; height: 32px;\n background: transparent; border: 1px solid transparent; border-radius: 7px;\n color: rgba(255,255,255,0.6); cursor: pointer;\n font-size: 12px; font-weight: 600;\n transition: background 0.1s, color 0.1s;\n white-space: nowrap;\n}\n#btn-zoom-current:hover { background: rgba(255,255,255,0.08); color: #fff; }\n\n#zoom-expanded { display: none; align-items: center; gap: 2px; }\n#zoom-expanded.open { display: flex; }\n\n#btn-zoom-pct {\n padding: 0 8px; height: 30px;\n background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.1); border-radius: 6px;\n color: rgba(255,255,255,0.75); cursor: pointer;\n font-size: 12px; font-weight: 600;\n transition: background 0.1s, color 0.1s;\n white-space: nowrap; min-width: 60px; text-align: center;\n}\n#btn-zoom-pct:hover { background: rgba(255,255,255,0.12); color: #fff; }\n\n/* \u2500\u2500 Dropdown menus \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.dropdown {\n position: absolute; display: none; flex-direction: column;\n gap: 1px; padding: 4px;\n background: var(--bpmnkit-panel-bg, rgba(13, 13, 22, 0.92));\n backdrop-filter: blur(12px);\n border: 1px solid var(--bpmnkit-panel-border, rgba(255, 255, 255, 0.08));\n border-radius: 9px;\n box-shadow: 0 6px 24px rgba(0,0,0,0.5);\n z-index: 200; min-width: 150px;\n}\n.dropdown.open { display: flex; }\n\n.drop-item {\n display: flex; align-items: center; gap: 8px;\n padding: 7px 10px;\n border: none; background: transparent;\n color: rgba(255,255,255,0.75); cursor: pointer;\n border-radius: 6px; font-size: 12px; text-align: left; width: 100%;\n transition: background 0.1s;\n}\n.drop-item:hover { background: rgba(255,255,255,0.08); color: #fff; }\n.drop-item .di-check { width: 14px; height: 14px; flex-shrink: 0; color: var(--bpmnkit-accent, #6b9df7); }\n.drop-item .di-icon { width: 14px; height: 14px; flex-shrink: 0; opacity: 0.7; }\n.drop-item svg { width: 14px; height: 14px; }\n.drop-sep { height: 1px; background: rgba(255,255,255,0.08); margin: 3px 0; }\n.drop-label {\n padding: 4px 10px 2px;\n font-size: 10px; font-weight: 600; letter-spacing: 0.06em;\n color: rgba(255,255,255,0.3); text-transform: uppercase;\n}\n\n/* \u2500\u2500 Group element picker \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.group-picker {\n position: absolute;\n display: flex; flex-direction: row;\n gap: 2px; padding: 4px;\n background: var(--bpmnkit-panel-bg, rgba(13, 13, 22, 0.92));\n backdrop-filter: blur(12px);\n border: 1px solid var(--bpmnkit-panel-border, rgba(255, 255, 255, 0.08));\n border-radius: 9px;\n box-shadow: 0 6px 24px rgba(0,0,0,0.5);\n z-index: 300;\n}\n.group-picker-label {\n padding: 2px 6px 4px;\n font-size: 10px; font-weight: 600; letter-spacing: 0.05em;\n color: rgba(255,255,255,0.3); text-transform: uppercase;\n white-space: nowrap; align-self: center;\n border-right: 1px solid rgba(255,255,255,0.08);\n margin-right: 2px;\n}\n\n/* \u2500\u2500 Light theme overrides \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n[data-bpmnkit-hud-theme=\"light\"] .panel {\n background: var(--bpmnkit-panel-bg, rgba(255,255,255,0.92));\n border-color: var(--bpmnkit-panel-border, rgba(0,0,0,0.08));\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n}\n[data-bpmnkit-hud-theme=\"light\"] #hud-top-center.panel {\n background: transparent;\n backdrop-filter: none;\n border: none;\n box-shadow: none;\n}\n[data-bpmnkit-hud-theme=\"light\"] .hud-btn { color: var(--bpmnkit-fg-muted, #6666a0); }\n[data-bpmnkit-hud-theme=\"light\"] .hud-btn:hover { background: rgba(0,0,0,0.06); color: var(--bpmnkit-fg, #1a1a2e); }\n[data-bpmnkit-hud-theme=\"light\"] .hud-btn.active { background: rgba(0,0,0,0.08); color: var(--bpmnkit-fg, #1a1a2e); border-color: rgba(0,0,0,0.15); }\n[data-bpmnkit-hud-theme=\"light\"] .hud-btn:disabled:hover { background: transparent; color: var(--bpmnkit-fg-muted, #6666a0); }\n[data-bpmnkit-hud-theme=\"light\"] .hud-sep { background: var(--bpmnkit-panel-border, rgba(0,0,0,0.08)); }\n[data-bpmnkit-hud-theme=\"light\"] #btn-zoom-current { color: var(--bpmnkit-fg-muted, #6666a0); }\n[data-bpmnkit-hud-theme=\"light\"] #btn-zoom-current:hover { background: rgba(0,0,0,0.06); color: var(--bpmnkit-fg, #1a1a2e); }\n[data-bpmnkit-hud-theme=\"light\"] #btn-zoom-pct {\n background: rgba(0,0,0,0.04); border-color: rgba(0,0,0,0.1); color: var(--bpmnkit-fg-muted, #6666a0);\n}\n[data-bpmnkit-hud-theme=\"light\"] #btn-zoom-pct:hover { background: rgba(0,0,0,0.08); color: var(--bpmnkit-fg, #1a1a2e); }\n[data-bpmnkit-hud-theme=\"light\"] .dropdown {\n background: var(--bpmnkit-panel-bg, rgba(255,255,255,0.92));\n border-color: var(--bpmnkit-panel-border, rgba(0,0,0,0.08));\n box-shadow: 0 6px 24px rgba(0,0,0,0.15);\n}\n[data-bpmnkit-hud-theme=\"light\"] .drop-item { color: var(--bpmnkit-fg-muted, #6666a0); }\n[data-bpmnkit-hud-theme=\"light\"] .drop-item:hover { background: rgba(0,0,0,0.05); color: var(--bpmnkit-fg, #1a1a2e); }\n[data-bpmnkit-hud-theme=\"light\"] .drop-sep { background: var(--bpmnkit-border, #d0d0e8); }\n[data-bpmnkit-hud-theme=\"light\"] .drop-label { color: rgba(0,0,0,0.35); }\n[data-bpmnkit-hud-theme=\"light\"] .group-picker {\n background: var(--bpmnkit-panel-bg, rgba(255,255,255,0.92));\n border-color: var(--bpmnkit-panel-border, rgba(0,0,0,0.08));\n box-shadow: 0 6px 24px rgba(0,0,0,0.15);\n}\n[data-bpmnkit-hud-theme=\"light\"] .group-picker-label {\n color: rgba(0,0,0,0.35);\n border-right-color: rgba(0,0,0,0.08);\n}\n\n/* \u2500\u2500 Neon theme overrides \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n[data-bpmnkit-hud-theme=\"neon\"] .panel {\n background: oklch(8% 0.03 270 / 0.96);\n border-color: oklch(65% 0.28 280 / 0.2);\n box-shadow: 0 2px 16px oklch(65% 0.28 280 / 0.12), 0 0 0 1px oklch(65% 0.28 280 / 0.1);\n}\n[data-bpmnkit-hud-theme=\"neon\"] #hud-top-center.panel {\n background: transparent; backdrop-filter: none; border: none; box-shadow: none;\n}\n[data-bpmnkit-hud-theme=\"neon\"] .hud-btn { color: oklch(65% 0.1 280); }\n[data-bpmnkit-hud-theme=\"neon\"] .hud-btn:hover { background: oklch(65% 0.28 280 / 0.12); color: oklch(88% 0.02 270); }\n[data-bpmnkit-hud-theme=\"neon\"] .hud-btn.active { background: oklch(65% 0.28 280 / 0.18); color: oklch(73% 0.16 280); border-color: oklch(65% 0.28 280 / 0.35); }\n[data-bpmnkit-hud-theme=\"neon\"] .hud-sep { background: oklch(65% 0.28 280 / 0.15); }\n[data-bpmnkit-hud-theme=\"neon\"] .dropdown {\n background: oklch(8% 0.03 270 / 0.97);\n border-color: oklch(65% 0.28 280 / 0.2);\n box-shadow: 0 6px 24px oklch(0% 0 0 / 0.6), 0 0 0 1px oklch(65% 0.28 280 / 0.1);\n}\n[data-bpmnkit-hud-theme=\"neon\"] .drop-item { color: oklch(65% 0.1 280); }\n[data-bpmnkit-hud-theme=\"neon\"] .drop-item:hover { background: oklch(65% 0.28 280 / 0.1); color: oklch(88% 0.02 270); }\n[data-bpmnkit-hud-theme=\"neon\"] .drop-sep { background: oklch(65% 0.28 280 / 0.15); }\n[data-bpmnkit-hud-theme=\"neon\"] .drop-label { color: oklch(50% 0.06 280); }\n[data-bpmnkit-hud-theme=\"neon\"] .group-picker {\n background: oklch(8% 0.03 270 / 0.97);\n border-color: oklch(65% 0.28 280 / 0.2);\n box-shadow: 0 6px 24px oklch(0% 0 0 / 0.6);\n}\n[data-bpmnkit-hud-theme=\"neon\"] .group-picker-label { color: oklch(50% 0.06 280); border-right-color: oklch(65% 0.28 280 / 0.15); }\n\n/* \u2500\u2500 Reference link button (wider text variant of hud-btn) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.ref-link-btn {\n height: 32px; padding: 0 8px;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 6px;\n color: rgba(255, 255, 255, 0.6);\n cursor: pointer;\n font-size: 12px;\n max-width: 160px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex-shrink: 0;\n transition: background 0.1s, color 0.1s;\n align-self: center;\n}\n.ref-link-btn:hover { background: rgba(255,255,255,0.08); color: #fff; }\n[data-bpmnkit-hud-theme=\"light\"] .ref-link-btn { color: var(--bpmnkit-fg-muted, #6666a0); }\n[data-bpmnkit-hud-theme=\"light\"] .ref-link-btn:hover { background: rgba(0,0,0,0.06); color: var(--bpmnkit-fg, #1a1a2e); }\n\n/* \u2500\u2500 Color swatches \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.bpmnkit-color-swatches { display: flex; gap: 4px; padding: 2px 4px; align-items: center; }\n.bpmnkit-color-swatch {\n width: 16px; height: 16px; border-radius: 50%; cursor: pointer;\n border: 2px solid transparent; flex-shrink: 0;\n transition: transform 0.1s;\n padding: 0;\n}\n.bpmnkit-color-swatch:hover { transform: scale(1.2); }\n.bpmnkit-color-swatch.active { border-color: rgba(255,255,255,0.8); }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-color-swatch.active { border-color: rgba(0,0,0,0.5); }\n.bpmnkit-color-swatch--default {\n background: transparent; border-color: rgba(255,255,255,0.25);\n position: relative; overflow: hidden;\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-color-swatch--default { border-color: rgba(0,0,0,0.2); }\n.bpmnkit-color-swatch--default::after {\n content: ''; position: absolute;\n top: 1px; left: 50%; transform: translateX(-50%) rotate(-45deg);\n width: 1.5px; height: calc(100% - 2px);\n background: rgba(200,50,50,0.65); border-radius: 1px;\n}\n\n/* \u2500\u2500 Contextual Ask-AI button (tinted blue) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.ctx-ask-ai-btn { color: var(--bpmnkit-accent-bright, #89b4fa); opacity: 0.8; }\n.ctx-ask-ai-btn:hover { background: rgba(76, 142, 247, 0.15); color: #a8c8ff; opacity: 1; }\n[data-bpmnkit-hud-theme=\"light\"] .ctx-ask-ai-btn { color: var(--bpmnkit-accent, #1a56db); opacity: 0.7; }\n[data-bpmnkit-hud-theme=\"light\"] .ctx-ask-ai-btn:hover { background: var(--bpmnkit-accent-subtle, rgba(26,86,219,0.12)); color: var(--bpmnkit-accent, #1a56db); opacity: 1; }\n\n/* \u2500\u2500 New-diagram onboarding overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#bpmnkit-empty-state {\n position: absolute; z-index: 50;\n top: 36px; left: 0; bottom: 0; right: 0;\n display: flex; align-items: center; justify-content: center;\n background: var(--bpmnkit-bg, #0d0d16);\n}\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-empty-state { background: var(--bpmnkit-bg, #f4f4f8); }\n\n.bpmnkit-onboard-inner {\n display: flex; flex-direction: column; align-items: center;\n gap: 28px; padding: 24px; max-width: 580px; width: 100%;\n}\n.bpmnkit-onboard-header { text-align: center; }\n.bpmnkit-onboard-title {\n color: rgba(255,255,255,0.82); font-size: 16px; font-weight: 600; margin: 0 0 7px;\n}\n.bpmnkit-onboard-sub {\n color: rgba(255,255,255,0.36); font-size: 13px; margin: 0;\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-title { color: rgba(0,0,0,0.72); }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-sub { color: rgba(0,0,0,0.38); }\n\n.bpmnkit-onboard-actions { display: flex; gap: 10px; width: 100%; }\n\n.bpmnkit-onboard-btn {\n flex: 1; display: flex; flex-direction: column; align-items: flex-start;\n gap: 10px; padding: 16px 14px;\n background: rgba(255,255,255,0.04);\n border: 1px solid rgba(255,255,255,0.07);\n border-radius: 10px; cursor: pointer; text-align: left;\n color: inherit; transition: background 0.15s, border-color 0.15s;\n}\n.bpmnkit-onboard-btn:hover {\n background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.14);\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn {\n background: rgba(0,0,0,0.03); border-color: rgba(0,0,0,0.08);\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn:hover {\n background: rgba(0,0,0,0.06); border-color: rgba(0,0,0,0.14);\n}\n\n.bpmnkit-onboard-btn-icon {\n display: flex; align-items: center; justify-content: center;\n width: 32px; height: 32px; border-radius: 8px;\n background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.65); flex-shrink: 0;\n}\n.bpmnkit-onboard-btn-icon svg { width: 16px; height: 16px; pointer-events: none; }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn-icon {\n background: rgba(0,0,0,0.07); color: rgba(0,0,0,0.55);\n}\n\n.bpmnkit-onboard-btn--ai .bpmnkit-onboard-btn-icon {\n background: rgba(76,142,247,0.18); color: #8ab8ff;\n}\n.bpmnkit-onboard-btn--ai:hover { border-color: rgba(76,142,247,0.3); }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn--ai .bpmnkit-onboard-btn-icon {\n background: rgba(26,86,219,0.1); color: #1a56db;\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn--ai:hover { border-color: rgba(26,86,219,0.28); }\n\n.bpmnkit-onboard-btn-label { display: flex; flex-direction: column; gap: 3px; }\n.bpmnkit-onboard-btn-title {\n font-size: 13px; font-weight: 600; color: rgba(255,255,255,0.8); margin: 0;\n}\n.bpmnkit-onboard-btn-desc {\n font-size: 11px; color: rgba(255,255,255,0.32); margin: 0; line-height: 1.4;\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn-title { color: rgba(0,0,0,0.72); }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-btn-desc { color: rgba(0,0,0,0.36); }\n\n.bpmnkit-onboard-links { display: flex; gap: 16px; flex-wrap: wrap; justify-content: center; }\n.bpmnkit-onboard-links a {\n color: rgba(255,255,255,0.22); font-size: 11px; text-decoration: none; transition: color 0.1s;\n}\n.bpmnkit-onboard-links a:hover { color: rgba(255,255,255,0.55); }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-links a { color: rgba(0,0,0,0.25); }\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-onboard-links a:hover { color: rgba(0,0,0,0.6); }\n\n@media (max-width: 520px) {\n .bpmnkit-onboard-actions { flex-direction: column; }\n .bpmnkit-onboard-btn { flex-direction: row; align-items: center; gap: 12px; }\n .bpmnkit-onboard-btn-label { flex-direction: column; }\n}\n\n/* \u2500\u2500 Top-center overflow guard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#hud-top-center {\n max-width: calc(100% - 24px);\n overflow-x: auto; overflow-y: visible;\n scrollbar-width: none;\n}\n#hud-top-center::-webkit-scrollbar { display: none; }\n\n/* \u2500\u2500 Push HUD toolbar down when simulation banner is visible \u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.bpmnkit-sim-active #hud-top-center { top: 36px; }\n\n/* \u2500\u2500 Simulation active banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#bpmnkit-sim-banner {\n position: absolute;\n top: 0; left: 0; right: 0;\n z-index: 150;\n display: flex; align-items: center; justify-content: center; gap: 12px;\n padding: 7px 16px;\n background: rgba(217, 119, 6, 0.18);\n border-bottom: 1px solid rgba(217, 119, 6, 0.35);\n backdrop-filter: blur(6px);\n font-size: 12px; font-weight: 500;\n color: rgba(255, 193, 87, 0.95);\n pointer-events: auto;\n}\n#bpmnkit-sim-banner.hidden { display: none; }\n#bpmnkit-sim-banner-exit {\n padding: 3px 10px; border-radius: 5px;\n background: rgba(217, 119, 6, 0.22);\n border: 1px solid rgba(217, 119, 6, 0.4);\n color: inherit; cursor: pointer; font-size: 11px; font-weight: 600;\n transition: background 0.1s;\n}\n#bpmnkit-sim-banner-exit:hover { background: rgba(217, 119, 6, 0.35); }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-sim-banner {\n background: rgba(254, 243, 199, 0.95);\n border-bottom-color: rgba(217, 119, 6, 0.25);\n color: #92400e;\n}\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-sim-banner-exit {\n background: rgba(217, 119, 6, 0.1); border-color: rgba(217, 119, 6, 0.3);\n}\n\n/* \u2500\u2500 Context menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#bpmnkit-ctx-menu { min-width: 160px; }\n\n/* \u2500\u2500 Element search bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#bpmnkit-search-bar {\n position: absolute;\n top: 44px; left: 50%; transform: translateX(-50%);\n z-index: 120;\n display: flex; align-items: center; gap: 6px;\n padding: 5px 10px;\n background: rgba(22, 22, 30, 0.92);\n backdrop-filter: blur(10px);\n border: 1px solid rgba(255,255,255,0.15);\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0,0,0,0.4);\n}\n#bpmnkit-search-bar.hidden { display: none; }\n#bpmnkit-search-input {\n width: 220px; padding: 3px 6px;\n background: transparent; border: none;\n color: #fff; font-size: 13px; outline: none;\n}\n#bpmnkit-search-input::placeholder { color: rgba(255,255,255,0.35); }\n#bpmnkit-search-count {\n font-size: 11px; color: rgba(255,255,255,0.45); white-space: nowrap; min-width: 40px;\n}\n#bpmnkit-search-close {\n background: transparent; border: none; color: rgba(255,255,255,0.4);\n cursor: pointer; font-size: 16px; line-height: 1; padding: 0 2px;\n}\n#bpmnkit-search-close:hover { color: #fff; }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-search-bar {\n background: rgba(252, 252, 254, 0.96);\n border-color: var(--bpmnkit-panel-border, rgba(0,0,0,0.08));\n box-shadow: 0 4px 16px rgba(0,0,0,0.12);\n}\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-search-input { color: rgba(0,0,0,0.9); }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-search-input::placeholder { color: rgba(0,0,0,0.3); }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-search-count { color: rgba(0,0,0,0.4); }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-search-close { color: rgba(0,0,0,0.35); }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-search-close:hover { color: rgba(0,0,0,0.8); }\n\n/* \u2500\u2500 Keyboard shortcuts modal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#bpmnkit-shortcuts-modal {\n position: absolute; inset: 0; z-index: 200;\n display: flex; align-items: center; justify-content: center;\n background: rgba(0,0,0,0.55);\n backdrop-filter: blur(4px);\n}\n#bpmnkit-shortcuts-modal.hidden { display: none; }\n#bpmnkit-shortcuts-inner {\n background: var(--bpmnkit-surface-2, #1e1e2e);\n border: 1px solid var(--bpmnkit-panel-border, rgba(255,255,255,0.08));\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0,0,0,0.5);\n padding: 20px 24px;\n min-width: 320px; max-width: 480px;\n color: rgba(255,255,255,0.85);\n}\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-shortcuts-inner {\n background: var(--bpmnkit-surface, #fff);\n border-color: var(--bpmnkit-panel-border, rgba(0,0,0,0.08));\n box-shadow: 0 8px 32px rgba(0,0,0,0.15);\n color: rgba(0,0,0,0.8);\n}\n#bpmnkit-shortcuts-inner h3 { margin: 0 0 14px; font-size: 14px; font-weight: 700; }\n.bpmnkit-sc-row {\n display: flex; justify-content: space-between; align-items: center;\n padding: 5px 0; border-bottom: 1px solid rgba(255,255,255,0.06); font-size: 12px;\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-sc-row { border-bottom-color: rgba(0,0,0,0.06); }\n.bpmnkit-sc-row:last-child { border-bottom: none; }\n.bpmnkit-sc-key {\n font-family: var(--font-mono, monospace);\n background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.12);\n border-radius: 4px; padding: 1px 6px; font-size: 11px;\n}\n[data-bpmnkit-hud-theme=\"light\"] .bpmnkit-sc-key {\n background: rgba(0,0,0,0.06); border-color: rgba(0,0,0,0.12); color: rgba(0,0,0,0.7);\n}\n#bpmnkit-shortcuts-close {\n display: block; margin: 14px auto 0; padding: 6px 20px;\n background: var(--bpmnkit-surface-2, rgba(255,255,255,0.08)); border: 1px solid var(--bpmnkit-panel-border, rgba(255,255,255,0.08));\n border-radius: 6px; color: rgba(255,255,255,0.7); cursor: pointer; font-size: 12px;\n transition: background 0.1s;\n}\n#bpmnkit-shortcuts-close:hover { background: rgba(255,255,255,0.14); color: #fff; }\n[data-bpmnkit-hud-theme=\"light\"] #bpmnkit-shortcuts-close {\n background: var(--bpmnkit-surface-2, rgba(0,0,0,0.05)); border-color: var(--bpmnkit-border, #d0d0e8); color: rgba(0,0,0,0.6);\n}\n\n/* \u2500\u2500 Mobile: collapsible center toolbars \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n#btn-bc-toggle, #btn-tc-toggle { display: none; }\n\n@media (max-width: 600px) {\n #hud-top-center { display: none !important; }\n #hud-bottom-left { display: none !important; }\n\n #hud-bottom-center {\n left: 10px;\n transform: none;\n }\n\n #btn-bc-toggle { display: flex; }\n\n /* Collapsed: hide all children except the toggle button */\n #hud-bottom-center:not(.expanded) > *:not(#btn-bc-toggle) { display: none; }\n\n /* Expanded: highlight the toggle button as a close affordance */\n #hud-bottom-center.expanded #btn-bc-toggle {\n background: rgba(255,255,255,0.08); color: #fff;\n }\n [data-bpmnkit-hud-theme=\"light\"] #hud-bottom-center.expanded #btn-bc-toggle {\n background: rgba(0,0,0,0.06); color: rgba(0,0,0,0.9);\n }\n}\n\n/* Hide bottom toolbar on welcome screen */\n.bpmnkit-welcome-active #hud-bottom-center { display: none !important; }\n";
|
|
13
13
|
/** Injects the HUD stylesheet into `<head>` if not already present. */
|
|
14
14
|
export declare function injectHudStyles(): void;
|
|
15
15
|
//# sourceMappingURL=css.d.ts.map
|
package/dist/css.js
CHANGED
|
@@ -414,6 +414,35 @@ export const HUD_CSS = `
|
|
|
414
414
|
border-right-color: rgba(0,0,0,0.08);
|
|
415
415
|
}
|
|
416
416
|
|
|
417
|
+
/* ── Neon theme overrides ────────────────────────────────────────── */
|
|
418
|
+
[data-bpmnkit-hud-theme="neon"] .panel {
|
|
419
|
+
background: oklch(8% 0.03 270 / 0.96);
|
|
420
|
+
border-color: oklch(65% 0.28 280 / 0.2);
|
|
421
|
+
box-shadow: 0 2px 16px oklch(65% 0.28 280 / 0.12), 0 0 0 1px oklch(65% 0.28 280 / 0.1);
|
|
422
|
+
}
|
|
423
|
+
[data-bpmnkit-hud-theme="neon"] #hud-top-center.panel {
|
|
424
|
+
background: transparent; backdrop-filter: none; border: none; box-shadow: none;
|
|
425
|
+
}
|
|
426
|
+
[data-bpmnkit-hud-theme="neon"] .hud-btn { color: oklch(65% 0.1 280); }
|
|
427
|
+
[data-bpmnkit-hud-theme="neon"] .hud-btn:hover { background: oklch(65% 0.28 280 / 0.12); color: oklch(88% 0.02 270); }
|
|
428
|
+
[data-bpmnkit-hud-theme="neon"] .hud-btn.active { background: oklch(65% 0.28 280 / 0.18); color: oklch(73% 0.16 280); border-color: oklch(65% 0.28 280 / 0.35); }
|
|
429
|
+
[data-bpmnkit-hud-theme="neon"] .hud-sep { background: oklch(65% 0.28 280 / 0.15); }
|
|
430
|
+
[data-bpmnkit-hud-theme="neon"] .dropdown {
|
|
431
|
+
background: oklch(8% 0.03 270 / 0.97);
|
|
432
|
+
border-color: oklch(65% 0.28 280 / 0.2);
|
|
433
|
+
box-shadow: 0 6px 24px oklch(0% 0 0 / 0.6), 0 0 0 1px oklch(65% 0.28 280 / 0.1);
|
|
434
|
+
}
|
|
435
|
+
[data-bpmnkit-hud-theme="neon"] .drop-item { color: oklch(65% 0.1 280); }
|
|
436
|
+
[data-bpmnkit-hud-theme="neon"] .drop-item:hover { background: oklch(65% 0.28 280 / 0.1); color: oklch(88% 0.02 270); }
|
|
437
|
+
[data-bpmnkit-hud-theme="neon"] .drop-sep { background: oklch(65% 0.28 280 / 0.15); }
|
|
438
|
+
[data-bpmnkit-hud-theme="neon"] .drop-label { color: oklch(50% 0.06 280); }
|
|
439
|
+
[data-bpmnkit-hud-theme="neon"] .group-picker {
|
|
440
|
+
background: oklch(8% 0.03 270 / 0.97);
|
|
441
|
+
border-color: oklch(65% 0.28 280 / 0.2);
|
|
442
|
+
box-shadow: 0 6px 24px oklch(0% 0 0 / 0.6);
|
|
443
|
+
}
|
|
444
|
+
[data-bpmnkit-hud-theme="neon"] .group-picker-label { color: oklch(50% 0.06 280); border-right-color: oklch(65% 0.28 280 / 0.15); }
|
|
445
|
+
|
|
417
446
|
/* ── Reference link button (wider text variant of hud-btn) ──────── */
|
|
418
447
|
.ref-link-btn {
|
|
419
448
|
height: 32px; padding: 0 8px;
|
|
@@ -688,19 +717,24 @@ export const HUD_CSS = `
|
|
|
688
717
|
#btn-bc-toggle, #btn-tc-toggle { display: none; }
|
|
689
718
|
|
|
690
719
|
@media (max-width: 600px) {
|
|
691
|
-
#
|
|
720
|
+
#hud-top-center { display: none !important; }
|
|
721
|
+
#hud-bottom-left { display: none !important; }
|
|
722
|
+
|
|
723
|
+
#hud-bottom-center {
|
|
724
|
+
left: 10px;
|
|
725
|
+
transform: none;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
#btn-bc-toggle { display: flex; }
|
|
692
729
|
|
|
693
730
|
/* Collapsed: hide all children except the toggle button */
|
|
694
731
|
#hud-bottom-center:not(.expanded) > *:not(#btn-bc-toggle) { display: none; }
|
|
695
|
-
#hud-top-center:not(.expanded) > *:not(#btn-tc-toggle) { display: none; }
|
|
696
732
|
|
|
697
733
|
/* Expanded: highlight the toggle button as a close affordance */
|
|
698
|
-
#hud-bottom-center.expanded #btn-bc-toggle
|
|
699
|
-
#hud-top-center.expanded #btn-tc-toggle {
|
|
734
|
+
#hud-bottom-center.expanded #btn-bc-toggle {
|
|
700
735
|
background: rgba(255,255,255,0.08); color: #fff;
|
|
701
736
|
}
|
|
702
|
-
[data-bpmnkit-hud-theme="light"] #hud-bottom-center.expanded #btn-bc-toggle
|
|
703
|
-
[data-bpmnkit-hud-theme="light"] #hud-top-center.expanded #btn-tc-toggle {
|
|
737
|
+
[data-bpmnkit-hud-theme="light"] #hud-bottom-center.expanded #btn-bc-toggle {
|
|
704
738
|
background: rgba(0,0,0,0.06); color: rgba(0,0,0,0.9);
|
|
705
739
|
}
|
|
706
740
|
}
|
package/dist/dock.js
CHANGED
|
@@ -100,6 +100,30 @@ const DOCK_CSS = `
|
|
|
100
100
|
[data-bpmnkit-hud-theme="light"] .bpmnkit-side-dock__info-value { color: rgba(0,0,0,0.75); }
|
|
101
101
|
[data-bpmnkit-hud-theme="light"] .bpmnkit-side-dock__info-row { border-bottom-color: rgba(0,0,0,0.06); }
|
|
102
102
|
[data-bpmnkit-hud-theme="light"] .bpmnkit-side-dock__empty-hint { color: rgba(0,0,0,0.25); }
|
|
103
|
+
/* Neon theme */
|
|
104
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-side-dock {
|
|
105
|
+
background: oklch(6% 0.04 280);
|
|
106
|
+
border-left: 1px solid oklch(65% 0.28 280 / 0.35);
|
|
107
|
+
box-shadow: -8px 0 40px oklch(0% 0 0 / 0.8), -1px 0 20px oklch(65% 0.28 280 / 0.12);
|
|
108
|
+
}
|
|
109
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-side-dock__collapse-handle {
|
|
110
|
+
background: oklch(6% 0.04 280);
|
|
111
|
+
border-color: oklch(65% 0.28 280 / 0.35);
|
|
112
|
+
color: oklch(65% 0.28 280 / 0.6);
|
|
113
|
+
}
|
|
114
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-side-dock__collapse-handle:hover {
|
|
115
|
+
background: oklch(12% 0.04 270 / 0.99);
|
|
116
|
+
color: oklch(73% 0.16 280);
|
|
117
|
+
}
|
|
118
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-side-dock__tab-strip { border-bottom-color: oklch(65% 0.28 280 / 0.25); }
|
|
119
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-side-dock__tab { color: oklch(50% 0.1 280); }
|
|
120
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-side-dock__tab:hover { color: oklch(73% 0.16 280); }
|
|
121
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-side-dock__tab.active { color: oklch(72% 0.18 185); border-bottom-color: oklch(72% 0.18 185); }
|
|
122
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-side-dock__resize-handle:hover { background: oklch(65% 0.28 280 / 0.25); }
|
|
123
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-side-dock__info-label { color: oklch(50% 0.06 280); }
|
|
124
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-side-dock__info-value { color: oklch(73% 0.16 280); }
|
|
125
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-side-dock__info-row { border-bottom-color: oklch(65% 0.28 280 / 0.1); }
|
|
126
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-side-dock__empty-hint { color: oklch(45% 0.08 280); }
|
|
103
127
|
`;
|
|
104
128
|
function injectDockStyles() {
|
|
105
129
|
if (document.getElementById(DOCK_STYLE_ID))
|
|
@@ -223,6 +247,10 @@ export function createSideDock() {
|
|
|
223
247
|
catch {
|
|
224
248
|
// localStorage unavailable — use defaults
|
|
225
249
|
}
|
|
250
|
+
// Force collapse on narrow viewports (mobile)
|
|
251
|
+
if (window.innerWidth <= 600) {
|
|
252
|
+
_collapsed = true;
|
|
253
|
+
}
|
|
226
254
|
if (_collapsed) {
|
|
227
255
|
el.classList.add("bpmnkit-side-dock--collapsed");
|
|
228
256
|
setDocWidth(0);
|
package/dist/editor.d.ts
CHANGED
|
@@ -69,7 +69,7 @@ export declare class BpmnEditor {
|
|
|
69
69
|
fitView(padding?: number): void;
|
|
70
70
|
/** The host element that receives the `data-theme` attribute. */
|
|
71
71
|
get container(): HTMLElement;
|
|
72
|
-
getTheme(): "light" | "dark";
|
|
72
|
+
getTheme(): "light" | "dark" | "neon";
|
|
73
73
|
setTheme(theme: Theme): void;
|
|
74
74
|
zoomIn(): void;
|
|
75
75
|
zoomOut(): void;
|
|
@@ -111,7 +111,7 @@ export declare class BpmnEditor {
|
|
|
111
111
|
* using smart placement (right → bottom → top, avoids overlaps).
|
|
112
112
|
* Returns the new element's id.
|
|
113
113
|
*/
|
|
114
|
-
addConnectedElement(sourceId: string, type: CreateShapeType): string | null;
|
|
114
|
+
addConnectedElement(sourceId: string, type: CreateShapeType, name?: string): string | null;
|
|
115
115
|
private _smartPlaceBounds;
|
|
116
116
|
private _overlapsAny;
|
|
117
117
|
/**
|
|
@@ -151,6 +151,7 @@ export declare class BpmnEditor {
|
|
|
151
151
|
private readonly _onPointerDown;
|
|
152
152
|
private readonly _onPointerMove;
|
|
153
153
|
private readonly _onPointerUp;
|
|
154
|
+
private readonly _onPointerCancel;
|
|
154
155
|
private readonly _onDblClick;
|
|
155
156
|
private readonly _onKeyDown;
|
|
156
157
|
private _hitTest;
|
package/dist/editor.js
CHANGED
|
@@ -244,11 +244,11 @@ export class BpmnEditor {
|
|
|
244
244
|
injectEditorStyles();
|
|
245
245
|
this._id = String(_instanceCounter++);
|
|
246
246
|
// Resolve initial theme — localStorage overrides the options.theme when persistTheme is on
|
|
247
|
-
let initialTheme = options.theme ?? "
|
|
247
|
+
let initialTheme = options.theme ?? "neon";
|
|
248
248
|
if (options.persistTheme) {
|
|
249
249
|
try {
|
|
250
250
|
const stored = localStorage.getItem("bpmnkit-theme");
|
|
251
|
-
if (stored === "dark" || stored === "light" || stored === "auto") {
|
|
251
|
+
if (stored === "dark" || stored === "light" || stored === "auto" || stored === "neon") {
|
|
252
252
|
initialTheme = stored;
|
|
253
253
|
}
|
|
254
254
|
}
|
|
@@ -426,6 +426,7 @@ export class BpmnEditor {
|
|
|
426
426
|
this._svg.addEventListener("pointerdown", this._onPointerDown);
|
|
427
427
|
this._svg.addEventListener("pointermove", this._onPointerMove);
|
|
428
428
|
this._svg.addEventListener("pointerup", this._onPointerUp);
|
|
429
|
+
this._svg.addEventListener("pointercancel", this._onPointerCancel);
|
|
429
430
|
this._svg.addEventListener("dblclick", this._onDblClick);
|
|
430
431
|
// ── Plugins ───────────────────────────────────────────────────
|
|
431
432
|
if (options.plugins) {
|
|
@@ -500,7 +501,7 @@ export class BpmnEditor {
|
|
|
500
501
|
this._stateMachine.setMode({ mode: "pan" });
|
|
501
502
|
}
|
|
502
503
|
else {
|
|
503
|
-
this.setTool("
|
|
504
|
+
this.setTool("default");
|
|
504
505
|
}
|
|
505
506
|
}
|
|
506
507
|
setTool(tool) {
|
|
@@ -512,7 +513,10 @@ export class BpmnEditor {
|
|
|
512
513
|
this._overlay.setAlignmentGuides([]);
|
|
513
514
|
this._setCreateEdgeDropHighlight(null);
|
|
514
515
|
this._ghostSnapCenter = null;
|
|
515
|
-
if (tool === "
|
|
516
|
+
if (tool === "default") {
|
|
517
|
+
this._stateMachine.setMode({ mode: "default", sub: { name: "idle", hoveredId: null } });
|
|
518
|
+
}
|
|
519
|
+
else if (tool === "select") {
|
|
516
520
|
this._stateMachine.setMode({ mode: "select", sub: { name: "idle", hoveredId: null } });
|
|
517
521
|
}
|
|
518
522
|
else if (tool === "pan") {
|
|
@@ -594,7 +598,10 @@ export class BpmnEditor {
|
|
|
594
598
|
return this._host;
|
|
595
599
|
}
|
|
596
600
|
getTheme() {
|
|
597
|
-
|
|
601
|
+
const t = this._host.getAttribute("data-theme");
|
|
602
|
+
if (t === "dark" || t === "neon")
|
|
603
|
+
return t;
|
|
604
|
+
return "light";
|
|
598
605
|
}
|
|
599
606
|
setTheme(theme) {
|
|
600
607
|
this._theme = theme;
|
|
@@ -654,6 +661,7 @@ export class BpmnEditor {
|
|
|
654
661
|
this._svg.removeEventListener("pointerdown", this._onPointerDown);
|
|
655
662
|
this._svg.removeEventListener("pointermove", this._onPointerMove);
|
|
656
663
|
this._svg.removeEventListener("pointerup", this._onPointerUp);
|
|
664
|
+
this._svg.removeEventListener("pointercancel", this._onPointerCancel);
|
|
657
665
|
this._svg.removeEventListener("dblclick", this._onDblClick);
|
|
658
666
|
this._host.removeEventListener("keydown", this._onKeyDown);
|
|
659
667
|
for (const plugin of this._plugins)
|
|
@@ -1066,7 +1074,7 @@ export class BpmnEditor {
|
|
|
1066
1074
|
* using smart placement (right → bottom → top, avoids overlaps).
|
|
1067
1075
|
* Returns the new element's id.
|
|
1068
1076
|
*/
|
|
1069
|
-
addConnectedElement(sourceId, type) {
|
|
1077
|
+
addConnectedElement(sourceId, type, name) {
|
|
1070
1078
|
if (!this._defs)
|
|
1071
1079
|
return null;
|
|
1072
1080
|
const srcShape = this._shapes.find((s) => s.id === sourceId);
|
|
@@ -1088,7 +1096,7 @@ export class BpmnEditor {
|
|
|
1088
1096
|
}
|
|
1089
1097
|
const newBounds = this._smartPlaceBounds(srcBounds, sourceId, w, h);
|
|
1090
1098
|
const obstacles = this._shapes.filter((s) => s.id !== sourceId).map((s) => s.shape.bounds);
|
|
1091
|
-
const r1 = createShape(this._defs, type, newBounds);
|
|
1099
|
+
const r1 = createShape(this._defs, type, newBounds, name);
|
|
1092
1100
|
const waypoints = computeWaypointsAvoiding(srcBounds, newBounds, obstacles);
|
|
1093
1101
|
const r2 = createConnection(r1.defs, sourceId, r1.id, waypoints);
|
|
1094
1102
|
this._selectedIds = [r1.id];
|
|
@@ -1737,6 +1745,9 @@ export class BpmnEditor {
|
|
|
1737
1745
|
const hit = this._hitTest(e.clientX, e.clientY);
|
|
1738
1746
|
this._stateMachine.onPointerUp(e, diag, hit);
|
|
1739
1747
|
};
|
|
1748
|
+
_onPointerCancel = (_e) => {
|
|
1749
|
+
this._stateMachine.cancel();
|
|
1750
|
+
};
|
|
1740
1751
|
_onDblClick = (e) => {
|
|
1741
1752
|
const rect = this._svg.getBoundingClientRect();
|
|
1742
1753
|
const diag = screenToDiagram(e.clientX, e.clientY, this._viewport.state, rect);
|
|
@@ -1935,11 +1946,11 @@ export class BpmnEditor {
|
|
|
1935
1946
|
? "dark"
|
|
1936
1947
|
: "light"
|
|
1937
1948
|
: theme;
|
|
1938
|
-
if (resolved === "
|
|
1939
|
-
this._host.
|
|
1949
|
+
if (resolved === "light") {
|
|
1950
|
+
this._host.removeAttribute("data-theme");
|
|
1940
1951
|
}
|
|
1941
1952
|
else {
|
|
1942
|
-
this._host.
|
|
1953
|
+
this._host.setAttribute("data-theme", resolved);
|
|
1943
1954
|
}
|
|
1944
1955
|
}
|
|
1945
1956
|
_installPlugin(plugin) {
|
package/dist/hud.d.ts
CHANGED
|
@@ -75,6 +75,11 @@ export interface HudOptions {
|
|
|
75
75
|
* Called when the user clicks "Exit" in the simulation active banner.
|
|
76
76
|
*/
|
|
77
77
|
onExitSimulation?: () => void;
|
|
78
|
+
/**
|
|
79
|
+
* Called when the user presses the sidebar toggle shortcut (Ctrl+\).
|
|
80
|
+
* Typically toggles the side dock open/closed.
|
|
81
|
+
*/
|
|
82
|
+
onToggleSidebar?: () => void;
|
|
78
83
|
}
|
|
79
84
|
export declare function initEditorHud(editor: BpmnEditor, options?: HudOptions): {
|
|
80
85
|
setActive(active: boolean): void;
|
package/dist/hud.js
CHANGED
|
@@ -61,6 +61,7 @@ const SHORTCUTS = [
|
|
|
61
61
|
["Ctrl+F", "Find element"],
|
|
62
62
|
["Ctrl+K", "Command palette"],
|
|
63
63
|
["Ctrl+E", "File switcher"],
|
|
64
|
+
["Ctrl+\\", "Toggle sidebar"],
|
|
64
65
|
["H", "Hand tool"],
|
|
65
66
|
["V", "Select tool"],
|
|
66
67
|
["Escape", "Deselect / cancel"],
|
|
@@ -138,7 +139,6 @@ export function initEditorHud(editor, options = {}) {
|
|
|
138
139
|
}
|
|
139
140
|
// Tool selector — bottom center
|
|
140
141
|
const btnSelect = hudBtn("btn-select", "Select (V)");
|
|
141
|
-
btnSelect.classList.add("active");
|
|
142
142
|
const btnPan = hudBtn("btn-pan", "Hand (H)");
|
|
143
143
|
const btnSpace = hudBtn("btn-space", "Space tool");
|
|
144
144
|
const toolGroupsEl = document.createElement("div");
|
|
@@ -235,7 +235,7 @@ export function initEditorHud(editor, options = {}) {
|
|
|
235
235
|
editor.container.append(hudTopCenter, hudBottomLeft, hudBottomCenter, cfgToolbar, ctxToolbar, zoomMenuEl, moreMenuEl, labelPosMenuEl, refMenuEl, ctxMenuEl, simBannerEl, searchBarEl, shortcutsModal);
|
|
236
236
|
// ── Theme ──────────────────────────────────────────────────────────────────
|
|
237
237
|
const syncHudTheme = () => {
|
|
238
|
-
document.body.dataset.
|
|
238
|
+
document.body.dataset.bpmnkitHudTheme = editor.getTheme();
|
|
239
239
|
};
|
|
240
240
|
syncHudTheme();
|
|
241
241
|
const themeObs = new MutationObserver(syncHudTheme);
|
|
@@ -514,12 +514,16 @@ export function initEditorHud(editor, options = {}) {
|
|
|
514
514
|
}
|
|
515
515
|
}
|
|
516
516
|
}
|
|
517
|
+
let _currentTool = "default";
|
|
518
|
+
editor.on("editor:tool", (tool) => {
|
|
519
|
+
_currentTool = tool;
|
|
520
|
+
});
|
|
517
521
|
btnSelect.addEventListener("click", () => {
|
|
518
|
-
editor.setTool("select");
|
|
522
|
+
editor.setTool(_currentTool === "select" ? "default" : "select");
|
|
519
523
|
collapseOnMobile(hudBottomCenter);
|
|
520
524
|
});
|
|
521
525
|
btnPan.addEventListener("click", () => {
|
|
522
|
-
editor.setTool("pan");
|
|
526
|
+
editor.setTool(_currentTool === "pan" ? "default" : "pan");
|
|
523
527
|
collapseOnMobile(hudBottomCenter);
|
|
524
528
|
});
|
|
525
529
|
btnSpace.addEventListener("click", () => {
|
|
@@ -1619,6 +1623,10 @@ export function initEditorHud(editor, options = {}) {
|
|
|
1619
1623
|
e.preventDefault();
|
|
1620
1624
|
shortcutsModal.classList.remove("hidden");
|
|
1621
1625
|
}
|
|
1626
|
+
if ((e.ctrlKey || e.metaKey) && e.key === "\\") {
|
|
1627
|
+
e.preventDefault();
|
|
1628
|
+
options.onToggleSidebar?.();
|
|
1629
|
+
}
|
|
1622
1630
|
});
|
|
1623
1631
|
// ── Close zoom widget on outside click ─────────────────────────────────────
|
|
1624
1632
|
document.addEventListener("pointerdown", (e) => {
|
package/dist/state-machine.d.ts
CHANGED
|
@@ -98,6 +98,9 @@ type SpaceSub = {
|
|
|
98
98
|
axis: "h" | "v" | null;
|
|
99
99
|
};
|
|
100
100
|
export type EditorMode = {
|
|
101
|
+
mode: "default";
|
|
102
|
+
sub: SelectSub;
|
|
103
|
+
} | {
|
|
101
104
|
mode: "select";
|
|
102
105
|
sub: SelectSub;
|
|
103
106
|
} | {
|
|
@@ -162,12 +165,20 @@ export declare class EditorStateMachine {
|
|
|
162
165
|
private readonly _cb;
|
|
163
166
|
private _mode;
|
|
164
167
|
constructor(_cb: Callbacks);
|
|
168
|
+
/** Creates an idle state preserving the current base mode ("default" or "select"). */
|
|
169
|
+
private _idle;
|
|
170
|
+
/**
|
|
171
|
+
* Wraps a sub-state with the current base mode so that "default" and "select"
|
|
172
|
+
* mode operations return to the same mode when they complete.
|
|
173
|
+
*/
|
|
174
|
+
private _withSub;
|
|
165
175
|
get mode(): EditorMode;
|
|
166
176
|
setMode(mode: EditorMode): void;
|
|
167
177
|
onPointerDown(e: PointerEvent, diag: DiagPoint, hit: HitResult): void;
|
|
168
178
|
onPointerMove(e: PointerEvent, diag: DiagPoint, hit: HitResult): void;
|
|
169
179
|
onPointerUp(_e: PointerEvent, diag: DiagPoint, hit: HitResult): void;
|
|
170
180
|
onDblClick(_e: MouseEvent, _diag: DiagPoint, hit: HitResult): void;
|
|
181
|
+
cancel(): void;
|
|
171
182
|
onKeyDown(e: KeyboardEvent): void;
|
|
172
183
|
}
|
|
173
184
|
export {};
|
package/dist/state-machine.js
CHANGED
|
@@ -11,10 +11,21 @@ function screenDist(ax, ay, bx, by) {
|
|
|
11
11
|
*/
|
|
12
12
|
export class EditorStateMachine {
|
|
13
13
|
_cb;
|
|
14
|
-
_mode = { mode: "
|
|
14
|
+
_mode = { mode: "default", sub: { name: "idle", hoveredId: null } };
|
|
15
15
|
constructor(_cb) {
|
|
16
16
|
this._cb = _cb;
|
|
17
17
|
}
|
|
18
|
+
/** Creates an idle state preserving the current base mode ("default" or "select"). */
|
|
19
|
+
_idle() {
|
|
20
|
+
return this._withSub({ name: "idle", hoveredId: null });
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Wraps a sub-state with the current base mode so that "default" and "select"
|
|
24
|
+
* mode operations return to the same mode when they complete.
|
|
25
|
+
*/
|
|
26
|
+
_withSub(sub) {
|
|
27
|
+
return this._mode.mode === "default" ? { mode: "default", sub } : { mode: "select", sub };
|
|
28
|
+
}
|
|
18
29
|
get mode() {
|
|
19
30
|
return this._mode;
|
|
20
31
|
}
|
|
@@ -24,11 +35,11 @@ export class EditorStateMachine {
|
|
|
24
35
|
// ── Pointer down ─────────────────────────────────────────────────
|
|
25
36
|
onPointerDown(e, diag, hit) {
|
|
26
37
|
const mode = this._mode;
|
|
27
|
-
// Create mode: place shape and revert to
|
|
38
|
+
// Create mode: place shape and revert to default
|
|
28
39
|
if (mode.mode === "create") {
|
|
29
40
|
this._cb.commitCreate(mode.elementType, diag);
|
|
30
|
-
this._mode = { mode: "
|
|
31
|
-
this._cb.setTool("
|
|
41
|
+
this._mode = { mode: "default", sub: { name: "idle", hoveredId: null } };
|
|
42
|
+
this._cb.setTool("default");
|
|
32
43
|
return;
|
|
33
44
|
}
|
|
34
45
|
// Space mode: lock viewport and begin drag
|
|
@@ -43,6 +54,17 @@ export class EditorStateMachine {
|
|
|
43
54
|
// Pan mode: viewport handles this
|
|
44
55
|
if (mode.mode === "pan")
|
|
45
56
|
return;
|
|
57
|
+
// Default mode: canvas click without Shift → track for selection clear on pointer-up, but don't lock
|
|
58
|
+
// viewport so panning still works naturally. Shift falls through to rubber-band.
|
|
59
|
+
if (mode.mode === "default" && hit.type === "canvas" && !e.shiftKey) {
|
|
60
|
+
this._mode = this._withSub({
|
|
61
|
+
name: "pointing-canvas",
|
|
62
|
+
origin: diag,
|
|
63
|
+
screenX: e.clientX,
|
|
64
|
+
screenY: e.clientY,
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
46
68
|
// If already in connecting mode (entered from contextual toolbar), a click commits or cancels
|
|
47
69
|
if (mode.sub.name === "connecting") {
|
|
48
70
|
this._cb.lockViewport(false);
|
|
@@ -52,7 +74,7 @@ export class EditorStateMachine {
|
|
|
52
74
|
else {
|
|
53
75
|
this._cb.cancelConnect();
|
|
54
76
|
}
|
|
55
|
-
this._mode =
|
|
77
|
+
this._mode = this._idle();
|
|
56
78
|
return;
|
|
57
79
|
}
|
|
58
80
|
// In label-editing mode: clicking elsewhere commits label (via blur) — do nothing here
|
|
@@ -67,32 +89,26 @@ export class EditorStateMachine {
|
|
|
67
89
|
if (!shape)
|
|
68
90
|
return;
|
|
69
91
|
this._cb.lockViewport(true);
|
|
70
|
-
this._mode = {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
screenY: e.clientY,
|
|
79
|
-
},
|
|
80
|
-
};
|
|
92
|
+
this._mode = this._withSub({
|
|
93
|
+
name: "pointing-handle",
|
|
94
|
+
origin: diag,
|
|
95
|
+
id: hit.shapeId,
|
|
96
|
+
handle: hit.handle,
|
|
97
|
+
screenX: e.clientX,
|
|
98
|
+
screenY: e.clientY,
|
|
99
|
+
});
|
|
81
100
|
break;
|
|
82
101
|
}
|
|
83
102
|
case "port": {
|
|
84
103
|
this._cb.lockViewport(true);
|
|
85
|
-
this._mode = {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
screenY: e.clientY,
|
|
94
|
-
},
|
|
95
|
-
};
|
|
104
|
+
this._mode = this._withSub({
|
|
105
|
+
name: "pointing-port",
|
|
106
|
+
origin: diag,
|
|
107
|
+
sourceId: hit.shapeId,
|
|
108
|
+
port: hit.port,
|
|
109
|
+
screenX: e.clientX,
|
|
110
|
+
screenY: e.clientY,
|
|
111
|
+
});
|
|
96
112
|
break;
|
|
97
113
|
}
|
|
98
114
|
case "shape": {
|
|
@@ -102,95 +118,78 @@ export class EditorStateMachine {
|
|
|
102
118
|
? selectedIds.filter((id) => id !== hit.id)
|
|
103
119
|
: [...selectedIds, hit.id];
|
|
104
120
|
this._cb.setSelection(newIds);
|
|
105
|
-
this._mode = {
|
|
121
|
+
this._mode = this._withSub({ name: "idle", hoveredId: hit.id });
|
|
106
122
|
}
|
|
107
123
|
else {
|
|
108
124
|
if (!selectedIds.includes(hit.id)) {
|
|
109
125
|
this._cb.setSelection([hit.id]);
|
|
110
126
|
}
|
|
111
|
-
this._mode = {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
screenY: e.clientY,
|
|
119
|
-
},
|
|
120
|
-
};
|
|
127
|
+
this._mode = this._withSub({
|
|
128
|
+
name: "pointing-shape",
|
|
129
|
+
origin: diag,
|
|
130
|
+
id: hit.id,
|
|
131
|
+
screenX: e.clientX,
|
|
132
|
+
screenY: e.clientY,
|
|
133
|
+
});
|
|
121
134
|
}
|
|
122
135
|
break;
|
|
123
136
|
}
|
|
124
137
|
case "edge": {
|
|
125
138
|
this._cb.setEdgeSelected(hit.id);
|
|
126
|
-
this._mode =
|
|
139
|
+
this._mode = this._idle();
|
|
127
140
|
break;
|
|
128
141
|
}
|
|
129
142
|
case "edge-segment": {
|
|
130
143
|
this._cb.lockViewport(true);
|
|
131
|
-
this._mode = {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
screenY: e.clientY,
|
|
142
|
-
},
|
|
143
|
-
};
|
|
144
|
+
this._mode = this._withSub({
|
|
145
|
+
name: "pointing-edge-segment",
|
|
146
|
+
edgeId: hit.id,
|
|
147
|
+
segIdx: hit.segIdx,
|
|
148
|
+
isHoriz: hit.isHoriz,
|
|
149
|
+
projPt: hit.projPt,
|
|
150
|
+
origin: diag,
|
|
151
|
+
screenX: e.clientX,
|
|
152
|
+
screenY: e.clientY,
|
|
153
|
+
});
|
|
144
154
|
break;
|
|
145
155
|
}
|
|
146
156
|
case "edge-waypoint": {
|
|
147
157
|
this._cb.lockViewport(true);
|
|
148
|
-
this._mode = {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
screenY: e.clientY,
|
|
157
|
-
},
|
|
158
|
-
};
|
|
158
|
+
this._mode = this._withSub({
|
|
159
|
+
name: "pointing-edge-waypoint",
|
|
160
|
+
edgeId: hit.id,
|
|
161
|
+
wpIdx: hit.wpIdx,
|
|
162
|
+
pt: hit.pt,
|
|
163
|
+
screenX: e.clientX,
|
|
164
|
+
screenY: e.clientY,
|
|
165
|
+
});
|
|
159
166
|
break;
|
|
160
167
|
}
|
|
161
168
|
case "edge-endpoint": {
|
|
162
169
|
this._cb.lockViewport(true);
|
|
163
|
-
this._mode = {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
screenY: e.clientY,
|
|
172
|
-
},
|
|
173
|
-
};
|
|
170
|
+
this._mode = this._withSub({
|
|
171
|
+
name: "pointing-edge-endpoint",
|
|
172
|
+
edgeId: hit.edgeId,
|
|
173
|
+
isStart: hit.isStart,
|
|
174
|
+
origin: diag,
|
|
175
|
+
screenX: e.clientX,
|
|
176
|
+
screenY: e.clientY,
|
|
177
|
+
});
|
|
174
178
|
break;
|
|
175
179
|
}
|
|
176
180
|
case "canvas": {
|
|
177
181
|
if (e.shiftKey) {
|
|
178
182
|
this._cb.lockViewport(true);
|
|
179
|
-
this._mode = {
|
|
180
|
-
mode: "select",
|
|
181
|
-
sub: { name: "rubber-band", origin: diag, current: diag },
|
|
182
|
-
};
|
|
183
|
+
this._mode = this._withSub({ name: "rubber-band", origin: diag, current: diag });
|
|
183
184
|
}
|
|
184
185
|
else {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
},
|
|
193
|
-
};
|
|
186
|
+
// Only reachable in explicit "select" mode (default mode canvas+no-shift returned early)
|
|
187
|
+
this._mode = this._withSub({
|
|
188
|
+
name: "pointing-canvas",
|
|
189
|
+
origin: diag,
|
|
190
|
+
screenX: e.clientX,
|
|
191
|
+
screenY: e.clientY,
|
|
192
|
+
});
|
|
194
193
|
}
|
|
195
194
|
break;
|
|
196
195
|
}
|
|
@@ -212,7 +211,7 @@ export class EditorStateMachine {
|
|
|
212
211
|
this._cb.previewSpace(sub.origin, diag, axis);
|
|
213
212
|
return;
|
|
214
213
|
}
|
|
215
|
-
if (mode.mode !== "select") {
|
|
214
|
+
if (mode.mode !== "select" && mode.mode !== "default") {
|
|
216
215
|
if (mode.mode === "create") {
|
|
217
216
|
// Ghost create: update overlay (editor reads state.mode to update ghost)
|
|
218
217
|
}
|
|
@@ -224,7 +223,7 @@ export class EditorStateMachine {
|
|
|
224
223
|
const hoveredId = hit.type === "shape" ? hit.id : null;
|
|
225
224
|
if (hoveredId !== sub.hoveredId) {
|
|
226
225
|
this._cb.setHovered(hoveredId);
|
|
227
|
-
this._mode = {
|
|
226
|
+
this._mode = this._withSub({ name: "idle", hoveredId });
|
|
228
227
|
}
|
|
229
228
|
if (hit.type === "edge-segment") {
|
|
230
229
|
this._cb.showEdgeHoverDot(hit.projPt);
|
|
@@ -244,10 +243,7 @@ export class EditorStateMachine {
|
|
|
244
243
|
const dist = screenDist(e.clientX, e.clientY, sub.screenX, sub.screenY);
|
|
245
244
|
if (dist > DRAG_THRESHOLD) {
|
|
246
245
|
this._cb.lockViewport(true);
|
|
247
|
-
this._mode = {
|
|
248
|
-
mode: "select",
|
|
249
|
-
sub: { name: "translating", origin: sub.origin, last: diag },
|
|
250
|
-
};
|
|
246
|
+
this._mode = this._withSub({ name: "translating", origin: sub.origin, last: diag });
|
|
251
247
|
const dx = diag.x - sub.origin.x;
|
|
252
248
|
const dy = diag.y - sub.origin.y;
|
|
253
249
|
this._cb.previewTranslate(dx, dy);
|
|
@@ -257,7 +253,7 @@ export class EditorStateMachine {
|
|
|
257
253
|
case "translating": {
|
|
258
254
|
const dx = diag.x - sub.origin.x;
|
|
259
255
|
const dy = diag.y - sub.origin.y;
|
|
260
|
-
this._mode = {
|
|
256
|
+
this._mode = this._withSub({ ...sub, last: diag });
|
|
261
257
|
this._cb.previewTranslate(dx, dy);
|
|
262
258
|
break;
|
|
263
259
|
}
|
|
@@ -269,54 +265,49 @@ export class EditorStateMachine {
|
|
|
269
265
|
if (!shape)
|
|
270
266
|
break;
|
|
271
267
|
const newBounds = applyResize(shape.shape.bounds, sub.handle, diag.x, diag.y);
|
|
272
|
-
this._mode = {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
current: diag,
|
|
280
|
-
},
|
|
281
|
-
};
|
|
268
|
+
this._mode = this._withSub({
|
|
269
|
+
name: "resizing",
|
|
270
|
+
id: sub.id,
|
|
271
|
+
handle: sub.handle,
|
|
272
|
+
original: shape.shape.bounds,
|
|
273
|
+
current: diag,
|
|
274
|
+
});
|
|
282
275
|
this._cb.previewResize(newBounds);
|
|
283
276
|
}
|
|
284
277
|
break;
|
|
285
278
|
}
|
|
286
279
|
case "resizing": {
|
|
287
280
|
const newBounds = applyResize(sub.original, sub.handle, diag.x, diag.y);
|
|
288
|
-
this._mode = {
|
|
281
|
+
this._mode = this._withSub({ ...sub, current: diag });
|
|
289
282
|
this._cb.previewResize(newBounds);
|
|
290
283
|
break;
|
|
291
284
|
}
|
|
292
285
|
case "pointing-port": {
|
|
293
286
|
const dist = screenDist(e.clientX, e.clientY, sub.screenX, sub.screenY);
|
|
294
287
|
if (dist > DRAG_THRESHOLD) {
|
|
295
|
-
this._mode = {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
288
|
+
this._mode = this._withSub({
|
|
289
|
+
name: "connecting",
|
|
290
|
+
sourceId: sub.sourceId,
|
|
291
|
+
ghostEnd: diag,
|
|
292
|
+
});
|
|
299
293
|
this._cb.previewConnect(diag);
|
|
300
294
|
}
|
|
301
295
|
break;
|
|
302
296
|
}
|
|
303
297
|
case "connecting": {
|
|
304
|
-
this._mode = {
|
|
298
|
+
this._mode = this._withSub({ ...sub, ghostEnd: diag });
|
|
305
299
|
this._cb.previewConnect(diag);
|
|
306
300
|
break;
|
|
307
301
|
}
|
|
308
302
|
case "pointing-edge-endpoint": {
|
|
309
303
|
const dist = screenDist(e.clientX, e.clientY, sub.screenX, sub.screenY);
|
|
310
304
|
if (dist > DRAG_THRESHOLD) {
|
|
311
|
-
this._mode = {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
origin: sub.origin,
|
|
318
|
-
},
|
|
319
|
-
};
|
|
305
|
+
this._mode = this._withSub({
|
|
306
|
+
name: "dragging-edge-endpoint",
|
|
307
|
+
edgeId: sub.edgeId,
|
|
308
|
+
isStart: sub.isStart,
|
|
309
|
+
origin: sub.origin,
|
|
310
|
+
});
|
|
320
311
|
this._cb.previewEndpointMove(sub.edgeId, sub.isStart, diag);
|
|
321
312
|
}
|
|
322
313
|
break;
|
|
@@ -328,15 +319,12 @@ export class EditorStateMachine {
|
|
|
328
319
|
case "pointing-edge-segment": {
|
|
329
320
|
const dist = screenDist(e.clientX, e.clientY, sub.screenX, sub.screenY);
|
|
330
321
|
if (dist > DRAG_THRESHOLD) {
|
|
331
|
-
this._mode = {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
origin: sub.origin,
|
|
338
|
-
},
|
|
339
|
-
};
|
|
322
|
+
this._mode = this._withSub({
|
|
323
|
+
name: "dragging-edge-waypoint-new",
|
|
324
|
+
edgeId: sub.edgeId,
|
|
325
|
+
segIdx: sub.segIdx,
|
|
326
|
+
origin: sub.origin,
|
|
327
|
+
});
|
|
340
328
|
this._cb.previewWaypointInsert(sub.edgeId, sub.segIdx, diag);
|
|
341
329
|
}
|
|
342
330
|
break;
|
|
@@ -348,15 +336,12 @@ export class EditorStateMachine {
|
|
|
348
336
|
case "pointing-edge-waypoint": {
|
|
349
337
|
const dist = screenDist(e.clientX, e.clientY, sub.screenX, sub.screenY);
|
|
350
338
|
if (dist > DRAG_THRESHOLD) {
|
|
351
|
-
this._mode = {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
origin: sub.pt,
|
|
358
|
-
},
|
|
359
|
-
};
|
|
339
|
+
this._mode = this._withSub({
|
|
340
|
+
name: "dragging-edge-waypoint",
|
|
341
|
+
edgeId: sub.edgeId,
|
|
342
|
+
wpIdx: sub.wpIdx,
|
|
343
|
+
origin: sub.pt,
|
|
344
|
+
});
|
|
360
345
|
this._cb.previewWaypointMove(sub.edgeId, sub.wpIdx, diag);
|
|
361
346
|
}
|
|
362
347
|
break;
|
|
@@ -366,20 +351,23 @@ export class EditorStateMachine {
|
|
|
366
351
|
break;
|
|
367
352
|
}
|
|
368
353
|
case "rubber-band": {
|
|
369
|
-
this._mode = {
|
|
354
|
+
this._mode = this._withSub({ ...sub, current: diag });
|
|
370
355
|
this._cb.previewRubberBand(sub.origin, diag);
|
|
371
356
|
break;
|
|
372
357
|
}
|
|
373
358
|
case "pointing-canvas": {
|
|
374
|
-
// Transition to rubber-band when drag threshold exceeded (no Shift required)
|
|
375
359
|
const dist = screenDist(e.clientX, e.clientY, sub.screenX, sub.screenY);
|
|
376
360
|
if (dist > DRAG_THRESHOLD) {
|
|
377
|
-
this.
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
361
|
+
if (this._mode.mode === "default") {
|
|
362
|
+
// Default mode canvas drag → pan. Return to idle so pointer-up doesn't clear selection.
|
|
363
|
+
this._mode = this._idle();
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
// Select mode canvas drag → rubber-band
|
|
367
|
+
this._cb.lockViewport(true);
|
|
368
|
+
this._mode = this._withSub({ name: "rubber-band", origin: sub.origin, current: diag });
|
|
369
|
+
this._cb.previewRubberBand(sub.origin, diag);
|
|
370
|
+
}
|
|
383
371
|
}
|
|
384
372
|
break;
|
|
385
373
|
}
|
|
@@ -399,13 +387,21 @@ export class EditorStateMachine {
|
|
|
399
387
|
}
|
|
400
388
|
return;
|
|
401
389
|
}
|
|
402
|
-
|
|
390
|
+
// Pan mode: deselect tool on short click (no actual pan)
|
|
391
|
+
if (mode.mode === "pan") {
|
|
392
|
+
if (!this._cb.viewportDidPan()) {
|
|
393
|
+
this._mode = { mode: "default", sub: { name: "idle", hoveredId: null } };
|
|
394
|
+
this._cb.setTool("default");
|
|
395
|
+
}
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
if (mode.mode !== "select" && mode.mode !== "default")
|
|
403
399
|
return;
|
|
404
400
|
const sub = mode.sub;
|
|
405
401
|
switch (sub.name) {
|
|
406
402
|
case "pointing-shape": {
|
|
407
403
|
this._cb.setSelection([sub.id]);
|
|
408
|
-
this._mode = {
|
|
404
|
+
this._mode = this._withSub({ name: "idle", hoveredId: sub.id });
|
|
409
405
|
break;
|
|
410
406
|
}
|
|
411
407
|
case "translating": {
|
|
@@ -413,24 +409,24 @@ export class EditorStateMachine {
|
|
|
413
409
|
const dy = diag.y - sub.origin.y;
|
|
414
410
|
this._cb.lockViewport(false);
|
|
415
411
|
this._cb.commitTranslate(dx, dy);
|
|
416
|
-
this._mode =
|
|
412
|
+
this._mode = this._idle();
|
|
417
413
|
break;
|
|
418
414
|
}
|
|
419
415
|
case "pointing-handle": {
|
|
420
416
|
this._cb.lockViewport(false);
|
|
421
|
-
this._mode =
|
|
417
|
+
this._mode = this._idle();
|
|
422
418
|
break;
|
|
423
419
|
}
|
|
424
420
|
case "resizing": {
|
|
425
421
|
const newBounds = applyResize(sub.original, sub.handle, diag.x, diag.y);
|
|
426
422
|
this._cb.lockViewport(false);
|
|
427
423
|
this._cb.commitResize(sub.id, newBounds);
|
|
428
|
-
this._mode =
|
|
424
|
+
this._mode = this._idle();
|
|
429
425
|
break;
|
|
430
426
|
}
|
|
431
427
|
case "pointing-port": {
|
|
432
428
|
this._cb.lockViewport(false);
|
|
433
|
-
this._mode =
|
|
429
|
+
this._mode = this._idle();
|
|
434
430
|
break;
|
|
435
431
|
}
|
|
436
432
|
case "connecting": {
|
|
@@ -441,7 +437,7 @@ export class EditorStateMachine {
|
|
|
441
437
|
else {
|
|
442
438
|
this._cb.cancelConnect();
|
|
443
439
|
}
|
|
444
|
-
this._mode =
|
|
440
|
+
this._mode = this._idle();
|
|
445
441
|
break;
|
|
446
442
|
}
|
|
447
443
|
case "rubber-band": {
|
|
@@ -459,50 +455,52 @@ export class EditorStateMachine {
|
|
|
459
455
|
})
|
|
460
456
|
.map((s) => s.id);
|
|
461
457
|
this._cb.setSelection(ids);
|
|
462
|
-
this._mode =
|
|
458
|
+
this._mode = this._idle();
|
|
463
459
|
break;
|
|
464
460
|
}
|
|
465
461
|
case "pointing-edge-endpoint": {
|
|
466
462
|
this._cb.lockViewport(false);
|
|
467
|
-
this._mode =
|
|
463
|
+
this._mode = this._idle();
|
|
468
464
|
break;
|
|
469
465
|
}
|
|
470
466
|
case "dragging-edge-endpoint": {
|
|
471
467
|
this._cb.lockViewport(false);
|
|
472
468
|
this._cb.commitEndpointMove(sub.edgeId, sub.isStart, diag);
|
|
473
|
-
this._mode =
|
|
469
|
+
this._mode = this._idle();
|
|
474
470
|
break;
|
|
475
471
|
}
|
|
476
472
|
case "pointing-edge-segment": {
|
|
477
473
|
this._cb.lockViewport(false);
|
|
478
474
|
// Tap without drag: select the edge
|
|
479
475
|
this._cb.setEdgeSelected(sub.edgeId);
|
|
480
|
-
this._mode =
|
|
476
|
+
this._mode = this._idle();
|
|
481
477
|
break;
|
|
482
478
|
}
|
|
483
479
|
case "dragging-edge-waypoint-new": {
|
|
484
480
|
this._cb.lockViewport(false);
|
|
485
481
|
this._cb.commitWaypointInsert(sub.edgeId, sub.segIdx, diag);
|
|
486
|
-
this._mode =
|
|
482
|
+
this._mode = this._idle();
|
|
487
483
|
break;
|
|
488
484
|
}
|
|
489
485
|
case "pointing-edge-waypoint": {
|
|
490
486
|
this._cb.lockViewport(false);
|
|
491
487
|
this._cb.setEdgeSelected(sub.edgeId);
|
|
492
|
-
this._mode =
|
|
488
|
+
this._mode = this._idle();
|
|
493
489
|
break;
|
|
494
490
|
}
|
|
495
491
|
case "dragging-edge-waypoint": {
|
|
496
492
|
this._cb.lockViewport(false);
|
|
497
493
|
this._cb.commitWaypointMove(sub.edgeId, sub.wpIdx, diag);
|
|
498
|
-
this._mode =
|
|
494
|
+
this._mode = this._idle();
|
|
499
495
|
break;
|
|
500
496
|
}
|
|
501
497
|
case "pointing-canvas": {
|
|
502
498
|
if (!this._cb.viewportDidPan()) {
|
|
503
499
|
this._cb.setSelection([]);
|
|
504
500
|
}
|
|
505
|
-
|
|
501
|
+
// Return to default mode after canvas click
|
|
502
|
+
this._mode = { mode: "default", sub: { name: "idle", hoveredId: null } };
|
|
503
|
+
this._cb.setTool("default");
|
|
506
504
|
break;
|
|
507
505
|
}
|
|
508
506
|
default:
|
|
@@ -516,13 +514,59 @@ export class EditorStateMachine {
|
|
|
516
514
|
this._cb.startLabelEdit(hit.id);
|
|
517
515
|
}
|
|
518
516
|
}
|
|
517
|
+
// ── Cancel (pointercancel / system gesture) ───────────────────────
|
|
518
|
+
cancel() {
|
|
519
|
+
const mode = this._mode;
|
|
520
|
+
if (mode.mode === "space") {
|
|
521
|
+
if (mode.sub.name === "dragging") {
|
|
522
|
+
this._cb.lockViewport(false);
|
|
523
|
+
this._cb.cancelSpace();
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
else if (mode.mode === "select" || mode.mode === "default") {
|
|
527
|
+
const sub = mode.sub;
|
|
528
|
+
if (sub.name === "translating") {
|
|
529
|
+
this._cb.cancelTranslate();
|
|
530
|
+
this._cb.lockViewport(false);
|
|
531
|
+
}
|
|
532
|
+
else if (sub.name === "rubber-band") {
|
|
533
|
+
this._cb.cancelRubberBand();
|
|
534
|
+
this._cb.lockViewport(false);
|
|
535
|
+
}
|
|
536
|
+
else if (sub.name === "pointing-handle" ||
|
|
537
|
+
sub.name === "resizing" ||
|
|
538
|
+
sub.name === "pointing-port") {
|
|
539
|
+
this._cb.lockViewport(false);
|
|
540
|
+
}
|
|
541
|
+
else if (sub.name === "connecting") {
|
|
542
|
+
this._cb.cancelConnect();
|
|
543
|
+
this._cb.lockViewport(false);
|
|
544
|
+
}
|
|
545
|
+
else if (sub.name === "pointing-edge-endpoint" || sub.name === "dragging-edge-endpoint") {
|
|
546
|
+
this._cb.cancelEndpointMove();
|
|
547
|
+
this._cb.lockViewport(false);
|
|
548
|
+
}
|
|
549
|
+
else if (sub.name === "pointing-edge-segment" || sub.name === "pointing-edge-waypoint") {
|
|
550
|
+
this._cb.lockViewport(false);
|
|
551
|
+
}
|
|
552
|
+
else if (sub.name === "dragging-edge-waypoint-new") {
|
|
553
|
+
this._cb.cancelWaypointInsert();
|
|
554
|
+
this._cb.lockViewport(false);
|
|
555
|
+
}
|
|
556
|
+
else if (sub.name === "dragging-edge-waypoint") {
|
|
557
|
+
this._cb.cancelWaypointMove();
|
|
558
|
+
this._cb.lockViewport(false);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
this._mode = { mode: "default", sub: { name: "idle", hoveredId: null } };
|
|
562
|
+
}
|
|
519
563
|
// ── Key down ──────────────────────────────────────────────────────
|
|
520
564
|
onKeyDown(e) {
|
|
521
565
|
const mode = this._mode;
|
|
522
566
|
if (mode.mode === "create" && e.key === "Escape") {
|
|
523
567
|
e.preventDefault();
|
|
524
|
-
this._mode = { mode: "
|
|
525
|
-
this._cb.setTool("
|
|
568
|
+
this._mode = { mode: "default", sub: { name: "idle", hoveredId: null } };
|
|
569
|
+
this._cb.setTool("default");
|
|
526
570
|
return;
|
|
527
571
|
}
|
|
528
572
|
if (mode.mode === "space" && e.key === "Escape") {
|
|
@@ -534,7 +578,7 @@ export class EditorStateMachine {
|
|
|
534
578
|
this._mode = { mode: "space", sub: { name: "idle" } };
|
|
535
579
|
return;
|
|
536
580
|
}
|
|
537
|
-
if (mode.mode !== "select")
|
|
581
|
+
if (mode.mode !== "select" && mode.mode !== "default")
|
|
538
582
|
return;
|
|
539
583
|
const sub = mode.sub;
|
|
540
584
|
if (e.key === "Escape") {
|
|
@@ -567,7 +611,7 @@ export class EditorStateMachine {
|
|
|
567
611
|
this._cb.cancelWaypointMove();
|
|
568
612
|
}
|
|
569
613
|
this._cb.setSelection([]);
|
|
570
|
-
this._mode =
|
|
614
|
+
this._mode = this._idle();
|
|
571
615
|
return;
|
|
572
616
|
}
|
|
573
617
|
if (e.key === "Delete" || e.key === "Backspace") {
|
package/dist/types.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { BpmnDefinitions } from "@bpmnkit/core";
|
|
|
3
3
|
export type CreateShapeType = "startEvent" | "messageStartEvent" | "timerStartEvent" | "conditionalStartEvent" | "signalStartEvent" | "endEvent" | "messageEndEvent" | "escalationEndEvent" | "errorEndEvent" | "compensationEndEvent" | "signalEndEvent" | "terminateEndEvent" | "intermediateThrowEvent" | "intermediateCatchEvent" | "messageCatchEvent" | "messageThrowEvent" | "timerCatchEvent" | "escalationThrowEvent" | "conditionalCatchEvent" | "linkCatchEvent" | "linkThrowEvent" | "compensationThrowEvent" | "signalCatchEvent" | "signalThrowEvent" | "task" | "serviceTask" | "userTask" | "scriptTask" | "sendTask" | "receiveTask" | "businessRuleTask" | "manualTask" | "callActivity" | "subProcess" | "adHocSubProcess" | "transaction" | "exclusiveGateway" | "parallelGateway" | "inclusiveGateway" | "eventBasedGateway" | "complexGateway" | "textAnnotation";
|
|
4
4
|
/** Element types that support resize handles. */
|
|
5
5
|
export declare const RESIZABLE_TYPES: ReadonlySet<string>;
|
|
6
|
-
export type Tool = "select" | "pan" | "space" | `create:${CreateShapeType}`;
|
|
6
|
+
export type Tool = "default" | "select" | "pan" | "space" | `create:${CreateShapeType}`;
|
|
7
7
|
export type HandleDir = "nw" | "n" | "ne" | "e" | "se" | "s" | "sw" | "w";
|
|
8
8
|
export type PortDir = "top" | "right" | "bottom" | "left";
|
|
9
9
|
export type EditorOptions = CanvasOptions & {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bpmnkit/editor",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"dist/**/*.d.ts"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@bpmnkit/canvas": "0.0.
|
|
21
|
-
"@bpmnkit/core": "0.0.
|
|
20
|
+
"@bpmnkit/canvas": "0.0.13",
|
|
21
|
+
"@bpmnkit/core": "0.0.13"
|
|
22
22
|
},
|
|
23
23
|
"description": "Full-featured interactive BPMN editor with undo/redo, HUD, and side-dock UI",
|
|
24
24
|
"keywords": [
|