@bpmnkit/plugins 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/ai-bridge/index.d.ts +2 -0
- package/dist/ai-bridge/index.js +5 -0
- package/dist/ai-bridge/panel.d.ts +1 -0
- package/dist/ai-bridge/panel.js +8 -1
- package/dist/command-palette/css.d.ts +1 -1
- package/dist/command-palette/css.js +69 -0
- package/dist/command-palette/index.d.ts +29 -0
- package/dist/command-palette/index.js +382 -52
- package/dist/command-palette-editor/index.d.ts +15 -10
- package/dist/command-palette-editor/index.js +96 -12
- package/dist/main-menu/css.d.ts +1 -1
- package/dist/main-menu/css.js +31 -0
- package/dist/main-menu/index.js +2 -0
- package/dist/storage/index.d.ts +7 -1
- package/dist/storage/index.js +1 -1
- package/dist/storage-tabs-bridge/index.d.ts +6 -1
- package/dist/storage-tabs-bridge/index.js +1 -0
- package/dist/tabs/css.js +67 -0
- package/dist/tabs/tabs-plugin.js +109 -20
- package/dist/token-highlight/css.js +4 -0
- package/dist/token-highlight/index.js +56 -15
- package/package.json +6 -6
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @bpmnkit/canvas-plugin-command-palette-editor — editor extension for the
|
|
3
|
-
* command palette plugin. Adds one command per BPMN element type.
|
|
3
|
+
* command palette plugin. Adds one command per BPMN element type. When
|
|
4
|
+
* executed, shows a second-step picker listing candidate source nodes to
|
|
5
|
+
* connect after. Falls back to `setTool` (free-click placement) when the
|
|
6
|
+
* diagram is empty.
|
|
4
7
|
*
|
|
5
8
|
* Must be used together with `@bpmnkit/canvas-plugin-command-palette`.
|
|
6
9
|
*
|
|
@@ -11,9 +14,7 @@
|
|
|
11
14
|
*
|
|
12
15
|
* let editorRef: BpmnEditor | null = null;
|
|
13
16
|
* const palette = createCommandPalettePlugin({ ... });
|
|
14
|
-
* const paletteEditor = createCommandPaletteEditorPlugin(palette, (
|
|
15
|
-
* editorRef?.setTool(tool);
|
|
16
|
-
* });
|
|
17
|
+
* const paletteEditor = createCommandPaletteEditorPlugin(palette, () => editorRef);
|
|
17
18
|
* const editor = new BpmnEditor({ container, xml, plugins: [palette, paletteEditor] });
|
|
18
19
|
* editorRef = editor;
|
|
19
20
|
* ```
|
|
@@ -27,33 +28,116 @@ const ELEMENT_COMMANDS = ELEMENT_GROUPS.flatMap((group) => group.types.map((type
|
|
|
27
28
|
title: `Add ${ELEMENT_TYPE_LABELS[type]}`,
|
|
28
29
|
description: group.title,
|
|
29
30
|
})));
|
|
31
|
+
// BPMN element types that cannot have outgoing sequence flows
|
|
32
|
+
const NO_OUTGOING_TYPES = new Set([
|
|
33
|
+
"endEvent",
|
|
34
|
+
"messageEndEvent",
|
|
35
|
+
"escalationEndEvent",
|
|
36
|
+
"errorEndEvent",
|
|
37
|
+
"compensationEndEvent",
|
|
38
|
+
"signalEndEvent",
|
|
39
|
+
"terminateEndEvent",
|
|
40
|
+
"textAnnotation",
|
|
41
|
+
]);
|
|
42
|
+
// Only gateways may have more than one outgoing sequence flow.
|
|
43
|
+
// Every other connectable element is limited to one outgoing flow.
|
|
44
|
+
const MULTI_OUTGOING_TYPES = new Set([
|
|
45
|
+
"exclusiveGateway",
|
|
46
|
+
"parallelGateway",
|
|
47
|
+
"inclusiveGateway",
|
|
48
|
+
"eventBasedGateway",
|
|
49
|
+
"complexGateway",
|
|
50
|
+
]);
|
|
51
|
+
// ── Candidate helpers ─────────────────────────────────────────────────────────
|
|
52
|
+
function getCandidates(api) {
|
|
53
|
+
return api
|
|
54
|
+
.getShapes()
|
|
55
|
+
.filter((s) => {
|
|
56
|
+
const el = s.flowElement;
|
|
57
|
+
if (el == null)
|
|
58
|
+
return false;
|
|
59
|
+
if (NO_OUTGOING_TYPES.has(el.type))
|
|
60
|
+
return false;
|
|
61
|
+
// Non-gateway elements can only have one outgoing flow
|
|
62
|
+
if (!MULTI_OUTGOING_TYPES.has(el.type) && el.outgoing.length >= 1)
|
|
63
|
+
return false;
|
|
64
|
+
return true;
|
|
65
|
+
})
|
|
66
|
+
.sort((a, b) => {
|
|
67
|
+
// Prefer leaf nodes (no outgoing) — most natural append targets
|
|
68
|
+
const aOut = a.flowElement?.outgoing.length ?? 0;
|
|
69
|
+
const bOut = b.flowElement?.outgoing.length ?? 0;
|
|
70
|
+
return aOut - bOut;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function candidateLabel(s) {
|
|
74
|
+
const el = s.flowElement;
|
|
75
|
+
if (!el)
|
|
76
|
+
return s.id;
|
|
77
|
+
const typeLabel = ELEMENT_TYPE_LABELS[el.type] ?? el.type;
|
|
78
|
+
return el.name ? el.name : typeLabel;
|
|
79
|
+
}
|
|
80
|
+
function candidateDescription(s) {
|
|
81
|
+
const el = s.flowElement;
|
|
82
|
+
if (!el)
|
|
83
|
+
return undefined;
|
|
84
|
+
const typeLabel = ELEMENT_TYPE_LABELS[el.type] ?? el.type;
|
|
85
|
+
const out = el.outgoing.length;
|
|
86
|
+
if (el.name) {
|
|
87
|
+
return out > 0 ? `${typeLabel} · ${out} outgoing` : typeLabel;
|
|
88
|
+
}
|
|
89
|
+
return out > 0 ? `${out} outgoing` : undefined;
|
|
90
|
+
}
|
|
30
91
|
// ── Factory ───────────────────────────────────────────────────────────────────
|
|
31
92
|
/**
|
|
32
93
|
* Creates the editor command palette extension plugin.
|
|
33
94
|
*
|
|
34
|
-
* @param palette
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* editor (e.g. `editor.setTool`). May reference the editor lazily — it is
|
|
38
|
-
* only called when the user executes a command, well after construction.
|
|
95
|
+
* @param palette The base command palette plugin.
|
|
96
|
+
* @param getEditor Lazy getter returning the editor instance (or null before
|
|
97
|
+
* it is created). Called only when the user executes a command.
|
|
39
98
|
*/
|
|
40
|
-
export function createCommandPaletteEditorPlugin(palette,
|
|
99
|
+
export function createCommandPaletteEditorPlugin(palette, getEditor) {
|
|
100
|
+
let _api = null;
|
|
41
101
|
let _deregister = null;
|
|
42
102
|
return {
|
|
43
103
|
name: "command-palette-editor",
|
|
44
|
-
install(
|
|
104
|
+
install(api) {
|
|
105
|
+
_api = api;
|
|
45
106
|
_deregister = palette.addCommands(ELEMENT_COMMANDS.map((cmd) => ({
|
|
46
107
|
id: `create:${cmd.type}`,
|
|
47
108
|
title: cmd.title,
|
|
48
109
|
description: cmd.description,
|
|
49
110
|
action() {
|
|
50
|
-
|
|
111
|
+
const candidates = _api ? getCandidates(_api) : [];
|
|
112
|
+
if (candidates.length === 0) {
|
|
113
|
+
// Empty diagram — fall back to tool mode so the user can
|
|
114
|
+
// click anywhere to place the element.
|
|
115
|
+
getEditor()?.setTool(`create:${cmd.type}`);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// Step 2: pick a connection target.
|
|
119
|
+
palette.pushView(candidates.map((s) => ({
|
|
120
|
+
id: `connect:${s.id}:${cmd.type}`,
|
|
121
|
+
title: candidateLabel(s),
|
|
122
|
+
description: candidateDescription(s),
|
|
123
|
+
action() {
|
|
124
|
+
// Step 3: enter a label, then insert.
|
|
125
|
+
const typeLabel = ELEMENT_TYPE_LABELS[cmd.type] ?? cmd.type;
|
|
126
|
+
palette.pushView([], {
|
|
127
|
+
placeholder: `Label for new ${typeLabel} (optional)\u2026`,
|
|
128
|
+
onConfirm(label) {
|
|
129
|
+
getEditor()?.addConnectedElement(s.id, cmd.type, label.trim() || undefined);
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
},
|
|
133
|
+
})), { placeholder: "Connect after which element?" });
|
|
51
134
|
},
|
|
52
135
|
})));
|
|
53
136
|
},
|
|
54
137
|
uninstall() {
|
|
55
138
|
_deregister?.();
|
|
56
139
|
_deregister = null;
|
|
140
|
+
_api = null;
|
|
57
141
|
},
|
|
58
142
|
};
|
|
59
143
|
}
|
package/dist/main-menu/css.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const MAIN_MENU_STYLE_ID = "bpmnkit-main-menu-styles-v2";
|
|
2
|
-
export declare const MAIN_MENU_CSS = "\n.bpmnkit-main-menu-panel {\n position: absolute;\n top: 0;\n right: 0;\n height: 36px;\n display: flex;\n align-items: center;\n gap: 3px;\n padding: 0 6px;\n background: #f0f4f8;\n border: none;\n border-left: 1px solid #d0d0d0;\n border-radius: 0;\n box-shadow: none;\n z-index: 10000;\n}\n[data-theme=\"dark\"] .bpmnkit-main-menu-panel {\n background: var(--bpmnkit-surface-2, #1e1e2e);\n border-left-color: #313244;\n}\n.bpmnkit-canvas-host:has(.bpmnkit-main-menu-panel:not([style*=\"none\"])) .bpmnkit-tabs {\n padding-right: 160px;\n}\n.bpmnkit-main-menu-title {\n padding: 0 6px;\n font-size: 12px;\n font-weight: 600;\n font-family: system-ui, sans-serif;\n color: var(--bpmnkit-text, #333333);\n white-space: nowrap;\n user-select: none;\n opacity: 0.75;\n}\n.bpmnkit-main-menu-sep {\n width: 1px;\n height: 16px;\n background: var(--bpmnkit-overlay-border, var(--bpmnkit-panel-border, rgba(0, 0, 0, 0.08)));\n flex-shrink: 0;\n}\n.bpmnkit-menu-btn {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 4px;\n color: var(--bpmnkit-text, #333333);\n cursor: pointer;\n padding: 0;\n flex-shrink: 0;\n transition: background 0.1s;\n}\n.bpmnkit-menu-btn:hover {\n background: var(--bpmnkit-overlay-border, var(--bpmnkit-panel-border, rgba(0, 0, 0, 0.08)));\n}\n.bpmnkit-menu-btn svg {\n width: 16px;\n height: 16px;\n pointer-events: none;\n}\n.bpmnkit-menu-dropdown {\n position: fixed;\n display: none;\n flex-direction: column;\n background: var(--bpmnkit-overlay-bg, rgba(248, 249, 250, 0.96));\n border: 1px solid var(--bpmnkit-overlay-border, var(--bpmnkit-panel-border, rgba(0, 0, 0, 0.08)));\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n z-index: 10001;\n min-width: 220px;\n overflow: hidden;\n}\n.bpmnkit-menu-dropdown.open { display: flex; }\n.bpmnkit-menu-level {\n display: flex;\n flex-direction: column;\n gap: 1px;\n padding: 4px;\n position: relative;\n z-index: 1;\n}\n@keyframes bpmnkit-menu-in-right {\n from { opacity: 0; transform: translateX(20px); }\n to { opacity: 1; transform: translateX(0); }\n}\n@keyframes bpmnkit-menu-in-left {\n from { opacity: 0; transform: translateX(-20px); }\n to { opacity: 1; transform: translateX(0); }\n}\n@keyframes bpmnkit-menu-out-left {\n from { opacity: 1; transform: translateX(0); }\n to { opacity: 0; transform: translateX(-20px); }\n}\n@keyframes bpmnkit-menu-out-right {\n from { opacity: 1; transform: translateX(0); }\n to { opacity: 0; transform: translateX(20px); }\n}\n.bpmnkit-menu-level--in-right { animation: bpmnkit-menu-in-right 180ms ease-out forwards; }\n.bpmnkit-menu-level--in-left { animation: bpmnkit-menu-in-left 180ms ease-out forwards; }\n.bpmnkit-menu-level--out-left { animation: bpmnkit-menu-out-left 150ms ease-in forwards; }\n.bpmnkit-menu-level--out-right { animation: bpmnkit-menu-out-right 150ms ease-in forwards; }\n.bpmnkit-menu-drop-label {\n padding: 3px 8px 1px;\n font-size: 10px;\n font-weight: 600;\n font-family: system-ui, sans-serif;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--bpmnkit-text, #333333);\n opacity: 0.45;\n}\n.bpmnkit-menu-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n background: transparent;\n border: none;\n border-radius: 5px;\n color: var(--bpmnkit-text, #333333);\n cursor: pointer;\n font-family: system-ui, sans-serif;\n font-size: 12px;\n text-align: left;\n width: 100%;\n transition: background 0.1s;\n}\n.bpmnkit-menu-item:hover {\n background: var(--bpmnkit-overlay-border, rgba(0, 0, 0, 0.06));\n}\n.bpmnkit-menu-item-check {\n width: 12px;\n height: 12px;\n flex-shrink: 0;\n color: var(--bpmnkit-highlight, var(--bpmnkit-accent, #1a56db));\n}\n.bpmnkit-menu-item-icon {\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n opacity: 0.65;\n}\n.bpmnkit-menu-item-label {\n flex: 1;\n}\n.bpmnkit-menu-item-arrow {\n width: 12px;\n height: 12px;\n flex-shrink: 0;\n opacity: 0.45;\n}\n.bpmnkit-menu-item-icon svg,\n.bpmnkit-menu-item-check svg,\n.bpmnkit-menu-item-arrow svg {\n width: 100%;\n height: 100%;\n}\n.bpmnkit-menu-back-row {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 2px 4px;\n}\n.bpmnkit-menu-back-btn {\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 4px;\n color: var(--bpmnkit-text, #333333);\n cursor: pointer;\n padding: 0;\n flex-shrink: 0;\n transition: background 0.1s;\n}\n.bpmnkit-menu-back-btn:hover {\n background: var(--bpmnkit-overlay-border, rgba(0, 0, 0, 0.06));\n}\n.bpmnkit-menu-back-btn svg {\n width: 12px;\n height: 12px;\n pointer-events: none;\n}\n.bpmnkit-menu-level-title {\n font-size: 12px;\n font-weight: 600;\n font-family: system-ui, sans-serif;\n color: var(--bpmnkit-text, #333333);\n flex: 1;\n}\n.bpmnkit-menu-info-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 5px 8px;\n font-family: system-ui, sans-serif;\n font-size: 12px;\n color: var(--bpmnkit-text, #333333);\n opacity: 0.75;\n}\n.bpmnkit-menu-info-text {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bpmnkit-menu-info-action {\n flex-shrink: 0;\n border: 1px solid var(--bpmnkit-overlay-border, var(--bpmnkit-panel-border, rgba(0, 0, 0, 0.08)));\n border-radius: 4px;\n background: transparent;\n color: var(--bpmnkit-text, #333333);\n cursor: pointer;\n padding: 2px 7px;\n font-size: 11px;\n font-family: system-ui, sans-serif;\n transition: background 0.1s;\n}\n.bpmnkit-menu-info-action:hover {\n background: var(--bpmnkit-overlay-border, rgba(0, 0, 0, 0.06));\n}\n.bpmnkit-menu-drop-sep {\n height: 1px;\n background: var(--bpmnkit-overlay-border, rgba(0,0,0,0.1));\n margin: 3px 4px;\n}\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-dropdown {\n background: var(--bpmnkit-panel-bg, rgba(13,13,22,0.92));\n border-color: var(--bpmnkit-panel-border, rgba(255, 255, 255, 0.08));\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);\n}\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-item,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-back-btn,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-level-title,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-info-row,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-info-action,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-drop-label {\n color: rgba(205, 214, 244, 0.9);\n}\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-item:hover,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-back-btn:hover,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-info-action:hover {\n background: rgba(255, 255, 255, 0.08);\n}\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-info-action {\n border-color: rgba(255, 255, 255, 0.15);\n}\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-drop-sep {\n background: var(--bpmnkit-panel-border, rgba(255, 255, 255, 0.08));\n}\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-item-check {\n color: var(--bpmnkit-accent-bright, #89b4fa);\n}\n";
|
|
2
|
+
export declare const MAIN_MENU_CSS = "\n.bpmnkit-main-menu-panel {\n position: absolute;\n top: 0;\n right: 0;\n height: 36px;\n display: flex;\n align-items: center;\n gap: 3px;\n padding: 0 6px;\n background: #f0f4f8;\n border: none;\n border-left: 1px solid #d0d0d0;\n border-radius: 0;\n box-shadow: none;\n z-index: 10000;\n}\n[data-theme=\"dark\"] .bpmnkit-main-menu-panel {\n background: var(--bpmnkit-surface-2, #1e1e2e);\n border-left-color: #313244;\n}\n[data-theme=\"neon\"] .bpmnkit-main-menu-panel {\n background: oklch(7% 0.035 280);\n border-left-color: oklch(65% 0.28 280 / 0.2);\n}\n.bpmnkit-canvas-host:has(.bpmnkit-main-menu-panel:not([style*=\"none\"])) .bpmnkit-tabs {\n padding-right: 160px;\n}\n.bpmnkit-main-menu-title {\n padding: 0 6px;\n font-size: 12px;\n font-weight: 600;\n font-family: system-ui, sans-serif;\n color: var(--bpmnkit-text, #333333);\n white-space: nowrap;\n user-select: none;\n opacity: 0.75;\n}\n.bpmnkit-main-menu-sep {\n width: 1px;\n height: 16px;\n background: var(--bpmnkit-overlay-border, var(--bpmnkit-panel-border, rgba(0, 0, 0, 0.08)));\n flex-shrink: 0;\n}\n.bpmnkit-menu-btn {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 4px;\n color: var(--bpmnkit-text, #333333);\n cursor: pointer;\n padding: 0;\n flex-shrink: 0;\n transition: background 0.1s;\n}\n.bpmnkit-menu-btn:hover {\n background: var(--bpmnkit-overlay-border, var(--bpmnkit-panel-border, rgba(0, 0, 0, 0.08)));\n}\n.bpmnkit-menu-btn svg {\n width: 16px;\n height: 16px;\n pointer-events: none;\n}\n.bpmnkit-menu-dropdown {\n position: fixed;\n display: none;\n flex-direction: column;\n background: var(--bpmnkit-overlay-bg, rgba(248, 249, 250, 0.96));\n border: 1px solid var(--bpmnkit-overlay-border, var(--bpmnkit-panel-border, rgba(0, 0, 0, 0.08)));\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\n z-index: 10001;\n min-width: 220px;\n overflow: hidden;\n}\n.bpmnkit-menu-dropdown.open { display: flex; }\n.bpmnkit-menu-level {\n display: flex;\n flex-direction: column;\n gap: 1px;\n padding: 4px;\n position: relative;\n z-index: 1;\n}\n@keyframes bpmnkit-menu-in-right {\n from { opacity: 0; transform: translateX(20px); }\n to { opacity: 1; transform: translateX(0); }\n}\n@keyframes bpmnkit-menu-in-left {\n from { opacity: 0; transform: translateX(-20px); }\n to { opacity: 1; transform: translateX(0); }\n}\n@keyframes bpmnkit-menu-out-left {\n from { opacity: 1; transform: translateX(0); }\n to { opacity: 0; transform: translateX(-20px); }\n}\n@keyframes bpmnkit-menu-out-right {\n from { opacity: 1; transform: translateX(0); }\n to { opacity: 0; transform: translateX(20px); }\n}\n.bpmnkit-menu-level--in-right { animation: bpmnkit-menu-in-right 180ms ease-out forwards; }\n.bpmnkit-menu-level--in-left { animation: bpmnkit-menu-in-left 180ms ease-out forwards; }\n.bpmnkit-menu-level--out-left { animation: bpmnkit-menu-out-left 150ms ease-in forwards; }\n.bpmnkit-menu-level--out-right { animation: bpmnkit-menu-out-right 150ms ease-in forwards; }\n.bpmnkit-menu-drop-label {\n padding: 3px 8px 1px;\n font-size: 10px;\n font-weight: 600;\n font-family: system-ui, sans-serif;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--bpmnkit-text, #333333);\n opacity: 0.45;\n}\n.bpmnkit-menu-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n background: transparent;\n border: none;\n border-radius: 5px;\n color: var(--bpmnkit-text, #333333);\n cursor: pointer;\n font-family: system-ui, sans-serif;\n font-size: 12px;\n text-align: left;\n width: 100%;\n transition: background 0.1s;\n}\n.bpmnkit-menu-item:hover {\n background: var(--bpmnkit-overlay-border, rgba(0, 0, 0, 0.06));\n}\n.bpmnkit-menu-item-check {\n width: 12px;\n height: 12px;\n flex-shrink: 0;\n color: var(--bpmnkit-highlight, var(--bpmnkit-accent, #1a56db));\n}\n.bpmnkit-menu-item-icon {\n width: 14px;\n height: 14px;\n flex-shrink: 0;\n opacity: 0.65;\n}\n.bpmnkit-menu-item-label {\n flex: 1;\n}\n.bpmnkit-menu-item-arrow {\n width: 12px;\n height: 12px;\n flex-shrink: 0;\n opacity: 0.45;\n}\n.bpmnkit-menu-item-icon svg,\n.bpmnkit-menu-item-check svg,\n.bpmnkit-menu-item-arrow svg {\n width: 100%;\n height: 100%;\n}\n.bpmnkit-menu-back-row {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 2px 4px;\n}\n.bpmnkit-menu-back-btn {\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 4px;\n color: var(--bpmnkit-text, #333333);\n cursor: pointer;\n padding: 0;\n flex-shrink: 0;\n transition: background 0.1s;\n}\n.bpmnkit-menu-back-btn:hover {\n background: var(--bpmnkit-overlay-border, rgba(0, 0, 0, 0.06));\n}\n.bpmnkit-menu-back-btn svg {\n width: 12px;\n height: 12px;\n pointer-events: none;\n}\n.bpmnkit-menu-level-title {\n font-size: 12px;\n font-weight: 600;\n font-family: system-ui, sans-serif;\n color: var(--bpmnkit-text, #333333);\n flex: 1;\n}\n.bpmnkit-menu-info-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 5px 8px;\n font-family: system-ui, sans-serif;\n font-size: 12px;\n color: var(--bpmnkit-text, #333333);\n opacity: 0.75;\n}\n.bpmnkit-menu-info-text {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.bpmnkit-menu-info-action {\n flex-shrink: 0;\n border: 1px solid var(--bpmnkit-overlay-border, var(--bpmnkit-panel-border, rgba(0, 0, 0, 0.08)));\n border-radius: 4px;\n background: transparent;\n color: var(--bpmnkit-text, #333333);\n cursor: pointer;\n padding: 2px 7px;\n font-size: 11px;\n font-family: system-ui, sans-serif;\n transition: background 0.1s;\n}\n.bpmnkit-menu-info-action:hover {\n background: var(--bpmnkit-overlay-border, rgba(0, 0, 0, 0.06));\n}\n.bpmnkit-menu-drop-sep {\n height: 1px;\n background: var(--bpmnkit-overlay-border, rgba(0,0,0,0.1));\n margin: 3px 4px;\n}\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-dropdown {\n background: var(--bpmnkit-panel-bg, rgba(13,13,22,0.92));\n border-color: var(--bpmnkit-panel-border, rgba(255, 255, 255, 0.08));\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);\n}\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-item,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-back-btn,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-level-title,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-info-row,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-info-action,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-drop-label {\n color: rgba(205, 214, 244, 0.9);\n}\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-item:hover,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-back-btn:hover,\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-info-action:hover {\n background: rgba(255, 255, 255, 0.08);\n}\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-info-action {\n border-color: rgba(255, 255, 255, 0.15);\n}\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-drop-sep {\n background: var(--bpmnkit-panel-border, rgba(255, 255, 255, 0.08));\n}\n[data-bpmnkit-hud-theme=\"dark\"] .bpmnkit-menu-item-check {\n color: var(--bpmnkit-accent-bright, #89b4fa);\n}\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-dropdown {\n background: oklch(8% 0.03 270 / 0.96);\n border-color: oklch(65% 0.28 280 / 0.2);\n box-shadow: 0 4px 20px oklch(0% 0 0 / 0.6), 0 0 0 1px oklch(65% 0.28 280 / 0.1);\n}\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-item,\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-back-btn,\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-level-title,\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-info-row,\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-info-action,\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-drop-label {\n color: oklch(73% 0.16 280);\n}\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-item:hover,\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-back-btn:hover,\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-info-action:hover {\n background: oklch(65% 0.28 280 / 0.1);\n}\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-info-action {\n border-color: oklch(65% 0.28 280 / 0.2);\n}\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-drop-sep {\n background: oklch(65% 0.28 280 / 0.15);\n}\n[data-bpmnkit-hud-theme=\"neon\"] .bpmnkit-menu-item-check {\n color: oklch(72% 0.18 185);\n}\n";
|
|
3
3
|
export declare function injectMainMenuStyles(): void;
|
|
4
4
|
//# sourceMappingURL=css.d.ts.map
|
package/dist/main-menu/css.js
CHANGED
|
@@ -20,6 +20,10 @@ export const MAIN_MENU_CSS = `
|
|
|
20
20
|
background: var(--bpmnkit-surface-2, #1e1e2e);
|
|
21
21
|
border-left-color: #313244;
|
|
22
22
|
}
|
|
23
|
+
[data-theme="neon"] .bpmnkit-main-menu-panel {
|
|
24
|
+
background: oklch(7% 0.035 280);
|
|
25
|
+
border-left-color: oklch(65% 0.28 280 / 0.2);
|
|
26
|
+
}
|
|
23
27
|
.bpmnkit-canvas-host:has(.bpmnkit-main-menu-panel:not([style*="none"])) .bpmnkit-tabs {
|
|
24
28
|
padding-right: 160px;
|
|
25
29
|
}
|
|
@@ -258,6 +262,33 @@ export const MAIN_MENU_CSS = `
|
|
|
258
262
|
[data-bpmnkit-hud-theme="dark"] .bpmnkit-menu-item-check {
|
|
259
263
|
color: var(--bpmnkit-accent-bright, #89b4fa);
|
|
260
264
|
}
|
|
265
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-dropdown {
|
|
266
|
+
background: oklch(8% 0.03 270 / 0.96);
|
|
267
|
+
border-color: oklch(65% 0.28 280 / 0.2);
|
|
268
|
+
box-shadow: 0 4px 20px oklch(0% 0 0 / 0.6), 0 0 0 1px oklch(65% 0.28 280 / 0.1);
|
|
269
|
+
}
|
|
270
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-item,
|
|
271
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-back-btn,
|
|
272
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-level-title,
|
|
273
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-info-row,
|
|
274
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-info-action,
|
|
275
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-drop-label {
|
|
276
|
+
color: oklch(73% 0.16 280);
|
|
277
|
+
}
|
|
278
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-item:hover,
|
|
279
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-back-btn:hover,
|
|
280
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-info-action:hover {
|
|
281
|
+
background: oklch(65% 0.28 280 / 0.1);
|
|
282
|
+
}
|
|
283
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-info-action {
|
|
284
|
+
border-color: oklch(65% 0.28 280 / 0.2);
|
|
285
|
+
}
|
|
286
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-drop-sep {
|
|
287
|
+
background: oklch(65% 0.28 280 / 0.15);
|
|
288
|
+
}
|
|
289
|
+
[data-bpmnkit-hud-theme="neon"] .bpmnkit-menu-item-check {
|
|
290
|
+
color: oklch(72% 0.18 185);
|
|
291
|
+
}
|
|
261
292
|
`;
|
|
262
293
|
export function injectMainMenuStyles() {
|
|
263
294
|
if (typeof document === "undefined")
|
package/dist/main-menu/index.js
CHANGED
|
@@ -15,12 +15,14 @@ const CHECK_ICON = '<svg viewBox="0 0 12 12" fill="none" stroke="currentColor" s
|
|
|
15
15
|
const MOON_ICON = '<svg viewBox="0 0 16 16" fill="currentColor"><path d="M13 9.5a6 6 0 1 1-7.5-7.5 7 7 0 0 0 7.5 7.5z"/></svg>';
|
|
16
16
|
const SUN_ICON = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><circle cx="8" cy="8" r="2.8"/><line x1="8" y1="1.5" x2="8" y2="3"/><line x1="8" y1="13" x2="8" y2="14.5"/><line x1="1.5" y1="8" x2="3" y2="8"/><line x1="13" y1="8" x2="14.5" y2="8"/><line x1="3.3" y1="3.3" x2="4.4" y2="4.4"/><line x1="11.6" y1="11.6" x2="12.7" y2="12.7"/><line x1="3.3" y1="12.7" x2="4.4" y2="11.6"/><line x1="11.6" y1="4.4" x2="12.7" y2="3.3"/></svg>';
|
|
17
17
|
const AUTO_ICON = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><circle cx="8" cy="8" r="5.5"/><path d="M8 8V3.5"/><path d="M8 8l3.2 2"/></svg>';
|
|
18
|
+
const NEON_ICON = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9.5,1.5 5.5,8 8.5,8 6.5,14.5 10.5,8 7.5,8 9.5,1.5"/></svg>';
|
|
18
19
|
const BACK_ICON = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polyline points="10,3 5,8 10,13"/></svg>';
|
|
19
20
|
const ARROW_ICON = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><polyline points="6,3 11,8 6,13"/></svg>';
|
|
20
21
|
const THEMES = [
|
|
21
22
|
{ value: "dark", label: "Dark", icon: MOON_ICON },
|
|
22
23
|
{ value: "light", label: "Light", icon: SUN_ICON },
|
|
23
24
|
{ value: "auto", label: "System", icon: AUTO_ICON },
|
|
25
|
+
{ value: "neon", label: "Neon", icon: NEON_ICON },
|
|
24
26
|
];
|
|
25
27
|
/**
|
|
26
28
|
* Creates a main menu plugin instance.
|
package/dist/storage/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CanvasPlugin } from "@bpmnkit/canvas";
|
|
2
|
-
import type { MainMenuApi } from "../main-menu/index.js";
|
|
2
|
+
import type { MainMenuApi, MenuItem } from "../main-menu/index.js";
|
|
3
3
|
import { StorageApi, type StorageApiOptions } from "./storage-api.js";
|
|
4
4
|
import type { FileType } from "./types.js";
|
|
5
5
|
export type { FileType, WorkspaceRecord, ProjectRecord, FileRecord, FileContentRecord, } from "./types.js";
|
|
@@ -30,6 +30,12 @@ export interface StoragePluginOptions extends StorageApiOptions {
|
|
|
30
30
|
* Update the corresponding tab's display name from this callback.
|
|
31
31
|
*/
|
|
32
32
|
onRenameCurrentFile?: (fileId: string, name: string) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Optional items prepended to the dynamic menu items on every open.
|
|
35
|
+
* Use this to inject context-sensitive items (e.g. mobile edit actions)
|
|
36
|
+
* without being overridden by storage change events.
|
|
37
|
+
*/
|
|
38
|
+
prependItems?: () => MenuItem[];
|
|
33
39
|
}
|
|
34
40
|
/**
|
|
35
41
|
* Creates an IndexedDB-backed storage plugin.
|
package/dist/storage/index.js
CHANGED
|
@@ -107,7 +107,7 @@ export function createStoragePlugin(options) {
|
|
|
107
107
|
}
|
|
108
108
|
function buildDynamicItems() {
|
|
109
109
|
const currentProjectId = storageApi.getCurrentProjectId();
|
|
110
|
-
const items = [];
|
|
110
|
+
const items = [...(options.prependItems?.() ?? [])];
|
|
111
111
|
if (currentProjectId) {
|
|
112
112
|
items.push({
|
|
113
113
|
type: "info",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import type { CanvasPlugin } from "@bpmnkit/canvas";
|
|
14
14
|
import type { CommandPalettePlugin } from "../command-palette/index.js";
|
|
15
|
-
import type { MainMenuApi } from "../main-menu/index.js";
|
|
15
|
+
import type { MainMenuApi, MenuItem } from "../main-menu/index.js";
|
|
16
16
|
import type { StorageApi } from "../storage/index.js";
|
|
17
17
|
import { InMemoryFileResolver } from "../tabs/index.js";
|
|
18
18
|
import type { TabConfig, TabsApi, WelcomeExample, WelcomeSection } from "../tabs/index.js";
|
|
@@ -81,6 +81,11 @@ export interface StorageTabsBridgeOptions {
|
|
|
81
81
|
* Use this to disable editing UI (toolbar buttons, sidebar) while raw mode is active.
|
|
82
82
|
*/
|
|
83
83
|
onRawModeChange?: (active: boolean) => void;
|
|
84
|
+
/**
|
|
85
|
+
* Optional items prepended to the dynamic menu items on every menu open.
|
|
86
|
+
* Composed with storage items so they survive storage change events.
|
|
87
|
+
*/
|
|
88
|
+
prependItems?: () => MenuItem[];
|
|
84
89
|
}
|
|
85
90
|
export interface StorageTabsBridgeResult {
|
|
86
91
|
tabsPlugin: CanvasPlugin & {
|
|
@@ -131,6 +131,7 @@ export function createStorageTabsBridge(options) {
|
|
|
131
131
|
mainMenu: options.mainMenu,
|
|
132
132
|
getOpenTabs: () => tabsPlugin.api.getAllTabContent(),
|
|
133
133
|
initialTitle: options.initialTitle,
|
|
134
|
+
prependItems: options.prependItems,
|
|
134
135
|
onLeaveProject() {
|
|
135
136
|
tabsPlugin.api.closeAllTabs();
|
|
136
137
|
tabIdToStorageFileId.clear();
|
package/dist/tabs/css.js
CHANGED
|
@@ -52,6 +52,22 @@ export const TABS_CSS = `
|
|
|
52
52
|
--tab-type-form: #a6e3a1;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
.bpmnkit-tabs[data-theme="neon"] {
|
|
56
|
+
--tabs-bg: oklch(7% 0.035 280);
|
|
57
|
+
--tabs-border: oklch(65% 0.28 280 / 0.2);
|
|
58
|
+
--tab-fg: oklch(60% 0.12 280);
|
|
59
|
+
--tab-active-bg: oklch(5% 0.025 270);
|
|
60
|
+
--tab-active-fg: oklch(88% 0.02 270);
|
|
61
|
+
--tab-active-border: oklch(72% 0.18 185);
|
|
62
|
+
--tab-hover-bg: oklch(65% 0.28 280 / 0.08);
|
|
63
|
+
--tab-close-hover: oklch(65% 0.28 280 / 0.12);
|
|
64
|
+
--tab-warn-fg: oklch(75% 0.15 60);
|
|
65
|
+
--tab-type-bpmn: oklch(73% 0.16 280);
|
|
66
|
+
--tab-type-dmn: oklch(70% 0.18 300);
|
|
67
|
+
--tab-type-feel: oklch(75% 0.15 60);
|
|
68
|
+
--tab-type-form: oklch(72% 0.18 185);
|
|
69
|
+
}
|
|
70
|
+
|
|
55
71
|
/* ── Play mode: hide tab groups, show only center slot ───────────────── */
|
|
56
72
|
|
|
57
73
|
.bpmnkit-tabs.bpmnkit-play-mode .bpmnkit-tab {
|
|
@@ -203,6 +219,18 @@ export const TABS_CSS = `
|
|
|
203
219
|
--welcome-btn-secondary-border: rgba(255,255,255,0.12);
|
|
204
220
|
}
|
|
205
221
|
|
|
222
|
+
.bpmnkit-welcome[data-theme="neon"] {
|
|
223
|
+
--welcome-bg: oklch(5% 0.025 270);
|
|
224
|
+
--welcome-icon: oklch(72% 0.18 185);
|
|
225
|
+
--welcome-title: oklch(88% 0.02 270);
|
|
226
|
+
--welcome-sub: oklch(55% 0.06 280);
|
|
227
|
+
--welcome-btn-primary-bg: oklch(55% 0.22 280);
|
|
228
|
+
--welcome-btn-primary-fg: oklch(95% 0.01 270);
|
|
229
|
+
--welcome-btn-secondary-bg: oklch(65% 0.28 280 / 0.08);
|
|
230
|
+
--welcome-btn-secondary-fg: oklch(73% 0.16 280);
|
|
231
|
+
--welcome-btn-secondary-border: oklch(65% 0.28 280 / 0.25);
|
|
232
|
+
}
|
|
233
|
+
|
|
206
234
|
.bpmnkit-welcome-inner {
|
|
207
235
|
display: flex;
|
|
208
236
|
flex-direction: column;
|
|
@@ -431,6 +459,12 @@ export const TABS_CSS = `
|
|
|
431
459
|
border-top: none;
|
|
432
460
|
}
|
|
433
461
|
|
|
462
|
+
.bpmnkit-tab-dropdown[data-theme="neon"] {
|
|
463
|
+
background: oklch(7% 0.035 280);
|
|
464
|
+
border: 1px solid oklch(65% 0.28 280 / 0.2);
|
|
465
|
+
border-top: none;
|
|
466
|
+
}
|
|
467
|
+
|
|
434
468
|
.bpmnkit-tab-drop-item {
|
|
435
469
|
display: flex;
|
|
436
470
|
align-items: center;
|
|
@@ -471,6 +505,17 @@ export const TABS_CSS = `
|
|
|
471
505
|
color: #cdd6f4;
|
|
472
506
|
}
|
|
473
507
|
|
|
508
|
+
.bpmnkit-tab-dropdown[data-theme="neon"] .bpmnkit-tab-drop-item {
|
|
509
|
+
color: oklch(60% 0.12 280);
|
|
510
|
+
}
|
|
511
|
+
.bpmnkit-tab-dropdown[data-theme="neon"] .bpmnkit-tab-drop-item:hover {
|
|
512
|
+
background: oklch(65% 0.28 280 / 0.08);
|
|
513
|
+
}
|
|
514
|
+
.bpmnkit-tab-dropdown[data-theme="neon"] .bpmnkit-tab-drop-item.active {
|
|
515
|
+
background: oklch(5% 0.025 270);
|
|
516
|
+
color: oklch(88% 0.02 270);
|
|
517
|
+
}
|
|
518
|
+
|
|
474
519
|
.bpmnkit-tab-drop-name {
|
|
475
520
|
flex: 1;
|
|
476
521
|
overflow: hidden;
|
|
@@ -527,6 +572,20 @@ export const TABS_CSS = `
|
|
|
527
572
|
--cd-ghost-hover: rgba(255,255,255,0.05);
|
|
528
573
|
}
|
|
529
574
|
|
|
575
|
+
.bpmnkit-close-dialog[data-theme="neon"] {
|
|
576
|
+
--cd-bg: oklch(9% 0.025 270);
|
|
577
|
+
--cd-border: oklch(65% 0.28 280 / 0.2);
|
|
578
|
+
--cd-title: oklch(88% 0.02 270);
|
|
579
|
+
--cd-body: oklch(65% 0.1 280);
|
|
580
|
+
--cd-primary-bg: oklch(55% 0.22 280);
|
|
581
|
+
--cd-primary-fg: oklch(95% 0.01 270);
|
|
582
|
+
--cd-secondary-bg: oklch(65% 0.28 280 / 0.08);
|
|
583
|
+
--cd-secondary-fg: oklch(73% 0.16 280);
|
|
584
|
+
--cd-secondary-hover: oklch(65% 0.28 280 / 0.14);
|
|
585
|
+
--cd-ghost-fg: oklch(50% 0.08 280);
|
|
586
|
+
--cd-ghost-hover: oklch(65% 0.28 280 / 0.06);
|
|
587
|
+
}
|
|
588
|
+
|
|
530
589
|
.bpmnkit-close-dialog-title {
|
|
531
590
|
font-size: 14px;
|
|
532
591
|
font-weight: 600;
|
|
@@ -592,6 +651,7 @@ export const TABS_CSS = `
|
|
|
592
651
|
}
|
|
593
652
|
|
|
594
653
|
.bpmnkit-raw-pane[data-theme="light"] { --raw-bg: #f8f9fa; }
|
|
654
|
+
.bpmnkit-raw-pane[data-theme="neon"] { --raw-bg: oklch(5% 0.025 270); }
|
|
595
655
|
|
|
596
656
|
.bpmnkit-raw-copy-btn {
|
|
597
657
|
position: absolute;
|
|
@@ -614,6 +674,12 @@ export const TABS_CSS = `
|
|
|
614
674
|
border-color: rgba(0,0,0,0.15);
|
|
615
675
|
}
|
|
616
676
|
.bpmnkit-raw-pane[data-theme="light"] .bpmnkit-raw-copy-btn:hover { background: rgba(0,0,0,0.12); }
|
|
677
|
+
.bpmnkit-raw-pane[data-theme="neon"] .bpmnkit-raw-copy-btn {
|
|
678
|
+
background: oklch(65% 0.28 280 / 0.1);
|
|
679
|
+
color: oklch(73% 0.16 280);
|
|
680
|
+
border-color: oklch(65% 0.28 280 / 0.2);
|
|
681
|
+
}
|
|
682
|
+
.bpmnkit-raw-pane[data-theme="neon"] .bpmnkit-raw-copy-btn:hover { background: oklch(65% 0.28 280 / 0.18); }
|
|
617
683
|
|
|
618
684
|
.bpmnkit-raw-content {
|
|
619
685
|
margin: 0;
|
|
@@ -628,6 +694,7 @@ export const TABS_CSS = `
|
|
|
628
694
|
}
|
|
629
695
|
|
|
630
696
|
.bpmnkit-raw-pane[data-theme="light"] .bpmnkit-raw-content { --raw-fg: #374151; }
|
|
697
|
+
.bpmnkit-raw-pane[data-theme="neon"] .bpmnkit-raw-content { --raw-fg: oklch(73% 0.16 280); }
|
|
631
698
|
|
|
632
699
|
`.trim();
|
|
633
700
|
const STYLE_ID = "bpmn-sdk-tabs-css";
|
package/dist/tabs/tabs-plugin.js
CHANGED
|
@@ -84,7 +84,7 @@ export function createTabsPlugin(options = {}) {
|
|
|
84
84
|
const bpmnProcessNames = new Map();
|
|
85
85
|
/** Tracks the last-activated tab ID per type group. */
|
|
86
86
|
const groupActiveId = new Map();
|
|
87
|
-
/** Which type group's dropdown is currently open, if any. */
|
|
87
|
+
/** Which type group's dropdown is currently open, if any. "mobile" means the unified mobile dropdown. */
|
|
88
88
|
let openDropdownType = null;
|
|
89
89
|
let outsideClickHandler = null;
|
|
90
90
|
// --- Close-confirmation dialog ---
|
|
@@ -449,6 +449,59 @@ export function createTabsPlugin(options = {}) {
|
|
|
449
449
|
openDropdown(type, group, anchorEl);
|
|
450
450
|
}
|
|
451
451
|
}
|
|
452
|
+
function openMobileDropdown(anchorEl) {
|
|
453
|
+
if (!dropdownEl)
|
|
454
|
+
return;
|
|
455
|
+
dropdownEl.innerHTML = "";
|
|
456
|
+
dropdownEl.dataset.theme = theme;
|
|
457
|
+
for (const type of GROUP_TYPES) {
|
|
458
|
+
const group = tabs.filter((t) => t.config.type === type);
|
|
459
|
+
for (const tab of group) {
|
|
460
|
+
const item = document.createElement("div");
|
|
461
|
+
item.className = "bpmnkit-tab-drop-item";
|
|
462
|
+
if (tab.id === activeId)
|
|
463
|
+
item.classList.add("active");
|
|
464
|
+
const badge = document.createElement("span");
|
|
465
|
+
badge.className = `bpmnkit-tab-type ${type}`;
|
|
466
|
+
badge.textContent = type.toUpperCase();
|
|
467
|
+
item.appendChild(badge);
|
|
468
|
+
const nameSpan = document.createElement("span");
|
|
469
|
+
nameSpan.className = "bpmnkit-tab-drop-name";
|
|
470
|
+
nameSpan.textContent = tab.config.name ?? tab.id;
|
|
471
|
+
item.appendChild(nameSpan);
|
|
472
|
+
if (!isProjectMode) {
|
|
473
|
+
const closeBtn = document.createElement("span");
|
|
474
|
+
closeBtn.className = "bpmnkit-tab-close";
|
|
475
|
+
closeBtn.textContent = "×";
|
|
476
|
+
closeBtn.addEventListener("click", (e) => {
|
|
477
|
+
e.stopPropagation();
|
|
478
|
+
closeDropdownEl();
|
|
479
|
+
requestClose(tab);
|
|
480
|
+
});
|
|
481
|
+
item.appendChild(closeBtn);
|
|
482
|
+
}
|
|
483
|
+
item.addEventListener("click", () => {
|
|
484
|
+
groupActiveId.set(type, tab.id);
|
|
485
|
+
api.setActiveTab(tab.id);
|
|
486
|
+
closeDropdownEl();
|
|
487
|
+
});
|
|
488
|
+
dropdownEl.appendChild(item);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
const rect = anchorEl.getBoundingClientRect();
|
|
492
|
+
dropdownEl.style.top = `${rect.bottom}px`;
|
|
493
|
+
dropdownEl.style.left = `${rect.left}px`;
|
|
494
|
+
dropdownEl.classList.add("open");
|
|
495
|
+
openDropdownType = "mobile";
|
|
496
|
+
}
|
|
497
|
+
function toggleMobileDropdown(anchorEl) {
|
|
498
|
+
if (openDropdownType === "mobile") {
|
|
499
|
+
closeDropdownEl();
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
openMobileDropdown(anchorEl);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
452
505
|
// --- Tab bar rendering ---
|
|
453
506
|
function requestClose(tab) {
|
|
454
507
|
if (isProjectMode)
|
|
@@ -465,29 +518,63 @@ export function createTabsPlugin(options = {}) {
|
|
|
465
518
|
/**
|
|
466
519
|
* Rebuilds the tab bar from scratch.
|
|
467
520
|
* At most three group tabs are rendered (one per type: BPMN, DMN, Form).
|
|
521
|
+
* On narrow viewports (≤600px) a single unified tab is shown instead.
|
|
468
522
|
*/
|
|
469
523
|
function renderTabBar() {
|
|
470
524
|
if (!tabBar)
|
|
471
525
|
return;
|
|
472
526
|
tabBar.innerHTML = "";
|
|
473
|
-
|
|
474
|
-
const
|
|
475
|
-
if (
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
527
|
+
if (window.innerWidth <= 600 && tabs.length > 0) {
|
|
528
|
+
const activeTab = tabs.find((t) => t.id === activeId);
|
|
529
|
+
if (activeTab) {
|
|
530
|
+
createMobileTabEl(activeTab);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
for (const type of GROUP_TYPES) {
|
|
535
|
+
const group = tabs.filter((t) => t.config.type === type);
|
|
536
|
+
if (group.length === 0)
|
|
537
|
+
continue;
|
|
538
|
+
// Ensure groupActiveId[type] points to a valid tab in this group
|
|
539
|
+
if (!group.some((t) => t.id === groupActiveId.get(type))) {
|
|
540
|
+
const first = group[0];
|
|
541
|
+
if (first)
|
|
542
|
+
groupActiveId.set(type, first.id);
|
|
543
|
+
}
|
|
544
|
+
const isGroupActive = group.some((t) => t.id === activeId);
|
|
545
|
+
createGroupTabEl(type, group, isGroupActive);
|
|
482
546
|
}
|
|
483
|
-
const isGroupActive = group.some((t) => t.id === activeId);
|
|
484
|
-
createGroupTabEl(type, group, isGroupActive);
|
|
485
547
|
}
|
|
486
548
|
// Center slot must be re-appended after innerHTML clear
|
|
487
549
|
if (centerSlotEl)
|
|
488
550
|
tabBar.appendChild(centerSlotEl);
|
|
489
551
|
updateRawModeBtn();
|
|
490
552
|
}
|
|
553
|
+
function createMobileTabEl(activeTab) {
|
|
554
|
+
const el = document.createElement("div");
|
|
555
|
+
el.className = "bpmnkit-tab active";
|
|
556
|
+
const typeBadge = document.createElement("span");
|
|
557
|
+
typeBadge.className = `bpmnkit-tab-type ${activeTab.config.type}`;
|
|
558
|
+
typeBadge.textContent = activeTab.config.type.toUpperCase();
|
|
559
|
+
el.appendChild(typeBadge);
|
|
560
|
+
const nameEl = document.createElement("span");
|
|
561
|
+
nameEl.className = "bpmnkit-tab-name";
|
|
562
|
+
nameEl.textContent = activeTab.config.name ?? activeTab.config.type;
|
|
563
|
+
el.appendChild(nameEl);
|
|
564
|
+
if (tabs.length > 1) {
|
|
565
|
+
const chevron = document.createElement("span");
|
|
566
|
+
chevron.className = "bpmnkit-tab-chevron";
|
|
567
|
+
chevron.innerHTML =
|
|
568
|
+
'<svg viewBox="0 0 10 6" fill="currentColor"><path d="M0 0l5 6 5-6z"/></svg>';
|
|
569
|
+
el.appendChild(chevron);
|
|
570
|
+
}
|
|
571
|
+
el.addEventListener("click", () => {
|
|
572
|
+
if (tabs.length > 1) {
|
|
573
|
+
toggleMobileDropdown(el);
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
tabBar?.appendChild(el);
|
|
577
|
+
}
|
|
491
578
|
function createGroupTabEl(type, group, isGroupActive) {
|
|
492
579
|
const el = document.createElement("div");
|
|
493
580
|
el.className = `bpmnkit-tab${isGroupActive ? " active" : ""}`;
|
|
@@ -552,7 +639,7 @@ export function createTabsPlugin(options = {}) {
|
|
|
552
639
|
contentArea?.appendChild(pane);
|
|
553
640
|
tab.pane = pane;
|
|
554
641
|
if (tab.config.type === "dmn") {
|
|
555
|
-
const editor = new DmnEditor({ container: pane, theme });
|
|
642
|
+
const editor = new DmnEditor({ container: pane, theme: theme === "neon" ? "dark" : theme });
|
|
556
643
|
tab.dmnEditor = editor;
|
|
557
644
|
const xml = Dmn.export(tab.config.defs);
|
|
558
645
|
void editor.loadXML(xml);
|
|
@@ -572,7 +659,7 @@ export function createTabsPlugin(options = {}) {
|
|
|
572
659
|
});
|
|
573
660
|
}
|
|
574
661
|
else if (tab.config.type === "form") {
|
|
575
|
-
const editor = new FormEditor({ container: pane, theme });
|
|
662
|
+
const editor = new FormEditor({ container: pane, theme: theme === "neon" ? "dark" : theme });
|
|
576
663
|
tab.formEditor = editor;
|
|
577
664
|
const schema = JSON.parse(Form.export(tab.config.form));
|
|
578
665
|
void editor.loadSchema(schema);
|
|
@@ -601,8 +688,9 @@ export function createTabsPlugin(options = {}) {
|
|
|
601
688
|
// shows through. pointer-events are set to none in setActiveTab.
|
|
602
689
|
}
|
|
603
690
|
function applyThemeToTab(tab) {
|
|
604
|
-
|
|
605
|
-
tab.
|
|
691
|
+
const editorTheme = theme === "neon" ? "dark" : theme;
|
|
692
|
+
tab.dmnEditor?.setTheme(editorTheme);
|
|
693
|
+
tab.formEditor?.setTheme(editorTheme);
|
|
606
694
|
}
|
|
607
695
|
function showWarning(tab, show) {
|
|
608
696
|
tab.hasWarning = show;
|
|
@@ -919,9 +1007,10 @@ export function createTabsPlugin(options = {}) {
|
|
|
919
1007
|
install(cApi) {
|
|
920
1008
|
canvasApi = cApi;
|
|
921
1009
|
injectTabsStyles();
|
|
922
|
-
// Detect theme from canvas (canvas sets data-theme="dark"
|
|
1010
|
+
// Detect theme from canvas (canvas sets data-theme="dark"/"neon"; absence means light)
|
|
923
1011
|
const container = cApi.container;
|
|
924
|
-
|
|
1012
|
+
const initialTheme = container.dataset.theme;
|
|
1013
|
+
theme = initialTheme === "dark" || initialTheme === "neon" ? initialTheme : "light";
|
|
925
1014
|
// Expand container to be position:relative for absolute children
|
|
926
1015
|
if (getComputedStyle(container).position === "static") {
|
|
927
1016
|
container.style.position = "relative";
|
|
@@ -1048,10 +1137,10 @@ export function createTabsPlugin(options = {}) {
|
|
|
1048
1137
|
}
|
|
1049
1138
|
offDiagramChange = anyOn("diagram:change", onDiagramUpdate);
|
|
1050
1139
|
anyOn("diagram:load", onDiagramUpdate);
|
|
1051
|
-
// Listen for theme changes (canvas
|
|
1140
|
+
// Listen for theme changes (canvas sets data-theme="dark"/"neon"; absence means light)
|
|
1052
1141
|
const observer = new MutationObserver(() => {
|
|
1053
1142
|
const t = container.dataset.theme;
|
|
1054
|
-
theme = t === "dark"
|
|
1143
|
+
theme = t === "dark" || t === "neon" ? t : "light";
|
|
1055
1144
|
if (tabBar)
|
|
1056
1145
|
tabBar.dataset.theme = theme;
|
|
1057
1146
|
if (welcomeEl)
|
|
@@ -13,6 +13,8 @@ const CSS = `
|
|
|
13
13
|
animation: bpmnkit-token-pulse 1.4s ease-in-out infinite;
|
|
14
14
|
}
|
|
15
15
|
.bpmnkit-token-active .bpmnkit-shape-body,
|
|
16
|
+
.bpmnkit-token-active .bpmnkit-callactivity-body,
|
|
17
|
+
.bpmnkit-token-active .bpmnkit-eventsubprocess-body,
|
|
16
18
|
.bpmnkit-token-active .bpmnkit-event-body,
|
|
17
19
|
.bpmnkit-token-active .bpmnkit-end-body,
|
|
18
20
|
.bpmnkit-token-active .bpmnkit-gw-body {
|
|
@@ -23,6 +25,8 @@ const CSS = `
|
|
|
23
25
|
|
|
24
26
|
/* ── Visited shapes (token has passed through) ──────────────────────────── */
|
|
25
27
|
.bpmnkit-token-visited .bpmnkit-shape-body,
|
|
28
|
+
.bpmnkit-token-visited .bpmnkit-callactivity-body,
|
|
29
|
+
.bpmnkit-token-visited .bpmnkit-eventsubprocess-body,
|
|
26
30
|
.bpmnkit-token-visited .bpmnkit-event-body,
|
|
27
31
|
.bpmnkit-token-visited .bpmnkit-end-body,
|
|
28
32
|
.bpmnkit-token-visited .bpmnkit-gw-body {
|