@bpmnkit/plugins 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/README.md +153 -0
  2. package/dist/ai-bridge/css.d.ts +2 -0
  3. package/dist/ai-bridge/css.js +366 -0
  4. package/dist/ai-bridge/index.d.ts +44 -0
  5. package/dist/ai-bridge/index.js +132 -0
  6. package/dist/ai-bridge/panel.d.ts +27 -0
  7. package/dist/ai-bridge/panel.js +715 -0
  8. package/dist/ascii-view/css.d.ts +4 -0
  9. package/dist/ascii-view/css.js +83 -0
  10. package/dist/ascii-view/index.d.ts +25 -0
  11. package/dist/ascii-view/index.js +92 -0
  12. package/dist/command-palette/css.d.ts +4 -0
  13. package/dist/command-palette/css.js +157 -0
  14. package/dist/command-palette/index.d.ts +53 -0
  15. package/dist/command-palette/index.js +378 -0
  16. package/dist/command-palette-editor/index.d.ts +35 -0
  17. package/dist/command-palette-editor/index.js +60 -0
  18. package/dist/config-panel/css.d.ts +4 -0
  19. package/dist/config-panel/css.js +719 -0
  20. package/dist/config-panel/index.d.ts +36 -0
  21. package/dist/config-panel/index.js +73 -0
  22. package/dist/config-panel/renderer.d.ts +127 -0
  23. package/dist/config-panel/renderer.js +1162 -0
  24. package/dist/config-panel/types.d.ts +118 -0
  25. package/dist/config-panel/types.js +2 -0
  26. package/dist/config-panel-bpmn/index.d.ts +58 -0
  27. package/dist/config-panel-bpmn/index.js +1320 -0
  28. package/dist/config-panel-bpmn/template-engine.d.ts +17 -0
  29. package/dist/config-panel-bpmn/template-engine.js +307 -0
  30. package/dist/config-panel-bpmn/template-to-service-task.d.ts +30 -0
  31. package/dist/config-panel-bpmn/template-to-service-task.js +92 -0
  32. package/dist/config-panel-bpmn/template-types.d.ts +126 -0
  33. package/dist/config-panel-bpmn/template-types.js +6 -0
  34. package/dist/config-panel-bpmn/templates/generated.d.ts +3 -0
  35. package/dist/config-panel-bpmn/templates/generated.js +57865 -0
  36. package/dist/config-panel-bpmn/util.d.ts +46 -0
  37. package/dist/config-panel-bpmn/util.js +195 -0
  38. package/dist/dmn-editor/css.d.ts +3 -0
  39. package/dist/dmn-editor/css.js +667 -0
  40. package/dist/dmn-editor/dmn-editor.d.ts +34 -0
  41. package/dist/dmn-editor/dmn-editor.js +646 -0
  42. package/dist/dmn-editor/drd-canvas.d.ts +85 -0
  43. package/dist/dmn-editor/drd-canvas.js +1087 -0
  44. package/dist/dmn-editor/index.d.ts +3 -0
  45. package/dist/dmn-editor/index.js +2 -0
  46. package/dist/dmn-viewer/css.d.ts +3 -0
  47. package/dist/dmn-viewer/css.js +151 -0
  48. package/dist/dmn-viewer/dmn-viewer.d.ts +30 -0
  49. package/dist/dmn-viewer/dmn-viewer.js +160 -0
  50. package/dist/dmn-viewer/feel.d.ts +3 -0
  51. package/dist/dmn-viewer/feel.js +2 -0
  52. package/dist/dmn-viewer/index.d.ts +14 -0
  53. package/dist/dmn-viewer/index.js +12 -0
  54. package/dist/element-docs/content.d.ts +20 -0
  55. package/dist/element-docs/content.js +1032 -0
  56. package/dist/element-docs/index.d.ts +7 -0
  57. package/dist/element-docs/index.js +643 -0
  58. package/dist/feel-playground/css.d.ts +4 -0
  59. package/dist/feel-playground/css.js +292 -0
  60. package/dist/feel-playground/index.d.ts +4 -0
  61. package/dist/feel-playground/index.js +3 -0
  62. package/dist/feel-playground/playground-plugin.d.ts +14 -0
  63. package/dist/feel-playground/playground-plugin.js +292 -0
  64. package/dist/form-editor/css.d.ts +3 -0
  65. package/dist/form-editor/css.js +703 -0
  66. package/dist/form-editor/form-editor.d.ts +48 -0
  67. package/dist/form-editor/form-editor.js +1039 -0
  68. package/dist/form-editor/index.d.ts +3 -0
  69. package/dist/form-editor/index.js +2 -0
  70. package/dist/form-viewer/css.d.ts +3 -0
  71. package/dist/form-viewer/css.js +303 -0
  72. package/dist/form-viewer/form-viewer.d.ts +29 -0
  73. package/dist/form-viewer/form-viewer.js +376 -0
  74. package/dist/form-viewer/index.d.ts +12 -0
  75. package/dist/form-viewer/index.js +11 -0
  76. package/dist/history/checkpoint.d.ts +10 -0
  77. package/dist/history/checkpoint.js +92 -0
  78. package/dist/history/css.d.ts +2 -0
  79. package/dist/history/css.js +130 -0
  80. package/dist/history/history-panel.d.ts +12 -0
  81. package/dist/history/history-panel.js +142 -0
  82. package/dist/history/index.d.ts +5 -0
  83. package/dist/history/index.js +3 -0
  84. package/dist/main-menu/css.d.ts +4 -0
  85. package/dist/main-menu/css.js +272 -0
  86. package/dist/main-menu/index.d.ts +59 -0
  87. package/dist/main-menu/index.js +285 -0
  88. package/dist/minimap/css.d.ts +10 -0
  89. package/dist/minimap/css.js +54 -0
  90. package/dist/minimap/index.d.ts +38 -0
  91. package/dist/minimap/index.js +69 -0
  92. package/dist/minimap/minimap.d.ts +35 -0
  93. package/dist/minimap/minimap.js +166 -0
  94. package/dist/optimize/index.d.ts +21 -0
  95. package/dist/optimize/index.js +304 -0
  96. package/dist/process-runner/css.d.ts +2 -0
  97. package/dist/process-runner/css.js +467 -0
  98. package/dist/process-runner/index.d.ts +56 -0
  99. package/dist/process-runner/index.js +549 -0
  100. package/dist/storage/auto-save.d.ts +11 -0
  101. package/dist/storage/auto-save.js +44 -0
  102. package/dist/storage/css.d.ts +2 -0
  103. package/dist/storage/css.js +2 -0
  104. package/dist/storage/db.d.ts +99 -0
  105. package/dist/storage/db.js +116 -0
  106. package/dist/storage/dialog.d.ts +15 -0
  107. package/dist/storage/dialog.js +201 -0
  108. package/dist/storage/export.d.ts +3 -0
  109. package/dist/storage/export.js +137 -0
  110. package/dist/storage/index.d.ts +44 -0
  111. package/dist/storage/index.js +201 -0
  112. package/dist/storage/sidebar.d.ts +2 -0
  113. package/dist/storage/sidebar.js +2 -0
  114. package/dist/storage/storage-api.d.ts +76 -0
  115. package/dist/storage/storage-api.js +342 -0
  116. package/dist/storage/types.d.ts +44 -0
  117. package/dist/storage/types.js +2 -0
  118. package/dist/storage-tabs-bridge/index.d.ts +96 -0
  119. package/dist/storage-tabs-bridge/index.js +502 -0
  120. package/dist/tabs/css.d.ts +3 -0
  121. package/dist/tabs/css.js +642 -0
  122. package/dist/tabs/file-resolver.d.ts +71 -0
  123. package/dist/tabs/file-resolver.js +46 -0
  124. package/dist/tabs/index.d.ts +15 -0
  125. package/dist/tabs/index.js +13 -0
  126. package/dist/tabs/tabs-plugin.d.ts +250 -0
  127. package/dist/tabs/tabs-plugin.js +1119 -0
  128. package/dist/token-highlight/css.d.ts +2 -0
  129. package/dist/token-highlight/css.js +81 -0
  130. package/dist/token-highlight/index.d.ts +44 -0
  131. package/dist/token-highlight/index.js +164 -0
  132. package/dist/watermark/css.d.ts +10 -0
  133. package/dist/watermark/css.js +54 -0
  134. package/dist/watermark/index.d.ts +48 -0
  135. package/dist/watermark/index.js +64 -0
  136. package/dist/zoom-controls/css.d.ts +4 -0
  137. package/dist/zoom-controls/css.js +48 -0
  138. package/dist/zoom-controls/index.d.ts +36 -0
  139. package/dist/zoom-controls/index.js +111 -0
  140. package/package.json +121 -0
@@ -0,0 +1,99 @@
1
+ import type { FileContentRecord, FileRecord, ProjectMruRecord, ProjectRecord, WorkspaceRecord } from "./types.js";
2
+ export declare const db: {
3
+ workspaces: {
4
+ get(key: string): Promise<WorkspaceRecord | undefined>;
5
+ add(record: WorkspaceRecord): Promise<void>;
6
+ update(key: string, changes: Partial<WorkspaceRecord>): Promise<void>;
7
+ delete(key: string): Promise<void>;
8
+ orderBy(field: string): {
9
+ toArray: () => Promise<WorkspaceRecord[]>;
10
+ };
11
+ where(index: string): {
12
+ equals: (value: string) => {
13
+ toArray: () => Promise<WorkspaceRecord[]>;
14
+ sortBy: (field: string) => Promise<WorkspaceRecord[]>;
15
+ delete: () => Promise<void>;
16
+ };
17
+ };
18
+ filter: (pred: (item: WorkspaceRecord) => boolean) => {
19
+ toArray: () => Promise<WorkspaceRecord[]>;
20
+ };
21
+ };
22
+ projects: {
23
+ get(key: string): Promise<ProjectRecord | undefined>;
24
+ add(record: ProjectRecord): Promise<void>;
25
+ update(key: string, changes: Partial<ProjectRecord>): Promise<void>;
26
+ delete(key: string): Promise<void>;
27
+ orderBy(field: string): {
28
+ toArray: () => Promise<ProjectRecord[]>;
29
+ };
30
+ where(index: string): {
31
+ equals: (value: string) => {
32
+ toArray: () => Promise<ProjectRecord[]>;
33
+ sortBy: (field: string) => Promise<ProjectRecord[]>;
34
+ delete: () => Promise<void>;
35
+ };
36
+ };
37
+ filter: (pred: (item: ProjectRecord) => boolean) => {
38
+ toArray: () => Promise<ProjectRecord[]>;
39
+ };
40
+ };
41
+ files: {
42
+ get(key: string): Promise<FileRecord | undefined>;
43
+ add(record: FileRecord): Promise<void>;
44
+ update(key: string, changes: Partial<FileRecord>): Promise<void>;
45
+ delete(key: string): Promise<void>;
46
+ orderBy(field: string): {
47
+ toArray: () => Promise<FileRecord[]>;
48
+ };
49
+ where(index: string): {
50
+ equals: (value: string) => {
51
+ toArray: () => Promise<FileRecord[]>;
52
+ sortBy: (field: string) => Promise<FileRecord[]>;
53
+ delete: () => Promise<void>;
54
+ };
55
+ };
56
+ filter: (pred: (item: FileRecord) => boolean) => {
57
+ toArray: () => Promise<FileRecord[]>;
58
+ };
59
+ };
60
+ fileContents: {
61
+ get(key: string): Promise<FileContentRecord | undefined>;
62
+ add(record: FileContentRecord): Promise<void>;
63
+ update(key: string, changes: Partial<FileContentRecord>): Promise<void>;
64
+ delete(key: string): Promise<void>;
65
+ orderBy(field: string): {
66
+ toArray: () => Promise<FileContentRecord[]>;
67
+ };
68
+ where(index: string): {
69
+ equals: (value: string) => {
70
+ toArray: () => Promise<FileContentRecord[]>;
71
+ sortBy: (field: string) => Promise<FileContentRecord[]>;
72
+ delete: () => Promise<void>;
73
+ };
74
+ };
75
+ filter: (pred: (item: FileContentRecord) => boolean) => {
76
+ toArray: () => Promise<FileContentRecord[]>;
77
+ };
78
+ };
79
+ projectMru: {
80
+ get(key: string): Promise<ProjectMruRecord | undefined>;
81
+ add(record: ProjectMruRecord): Promise<void>;
82
+ update(key: string, changes: Partial<ProjectMruRecord>): Promise<void>;
83
+ delete(key: string): Promise<void>;
84
+ orderBy(field: string): {
85
+ toArray: () => Promise<ProjectMruRecord[]>;
86
+ };
87
+ where(index: string): {
88
+ equals: (value: string) => {
89
+ toArray: () => Promise<ProjectMruRecord[]>;
90
+ sortBy: (field: string) => Promise<ProjectMruRecord[]>;
91
+ delete: () => Promise<void>;
92
+ };
93
+ };
94
+ filter: (pred: (item: ProjectMruRecord) => boolean) => {
95
+ toArray: () => Promise<ProjectMruRecord[]>;
96
+ };
97
+ };
98
+ };
99
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1,116 @@
1
+ const DB_NAME = "bpmn-sdk-storage";
2
+ // Dexie 4.x internally stored version 10 for user-space version 1.
3
+ // Use 12 to add the projectMru object store.
4
+ const DB_VERSION = 12;
5
+ let _db = null;
6
+ function openDb() {
7
+ return new Promise((resolve, reject) => {
8
+ const r = indexedDB.open(DB_NAME, DB_VERSION);
9
+ r.onupgradeneeded = () => {
10
+ const d = r.result;
11
+ // Guard each store: Dexie may have already created them at version 10.
12
+ if (!d.objectStoreNames.contains("workspaces")) {
13
+ const ws = d.createObjectStore("workspaces", { keyPath: "id" });
14
+ ws.createIndex("name", "name");
15
+ }
16
+ if (!d.objectStoreNames.contains("projects")) {
17
+ const prj = d.createObjectStore("projects", { keyPath: "id" });
18
+ prj.createIndex("workspaceId", "workspaceId");
19
+ }
20
+ if (!d.objectStoreNames.contains("files")) {
21
+ const fl = d.createObjectStore("files", { keyPath: "id" });
22
+ fl.createIndex("projectId", "projectId");
23
+ fl.createIndex("workspaceId", "workspaceId");
24
+ }
25
+ if (!d.objectStoreNames.contains("fileContents")) {
26
+ d.createObjectStore("fileContents", { keyPath: "fileId" });
27
+ }
28
+ if (!d.objectStoreNames.contains("projectMru")) {
29
+ d.createObjectStore("projectMru", { keyPath: "projectId" });
30
+ }
31
+ };
32
+ r.onsuccess = () => {
33
+ _db = r.result;
34
+ resolve(_db);
35
+ };
36
+ r.onerror = () => reject(r.error);
37
+ });
38
+ }
39
+ function getDb() {
40
+ return _db !== null ? Promise.resolve(_db) : openDb();
41
+ }
42
+ function wrap(r) {
43
+ return new Promise((resolve, reject) => {
44
+ r.onsuccess = () => resolve(r.result);
45
+ r.onerror = () => reject(r.error);
46
+ });
47
+ }
48
+ function sorted(items, field) {
49
+ return [...items].sort((a, b) => {
50
+ const av = String(a[field] ?? "");
51
+ const bv = String(b[field] ?? "");
52
+ return av.localeCompare(bv);
53
+ });
54
+ }
55
+ function makeTable(name) {
56
+ async function fetchAll(index, value) {
57
+ const d = await getDb();
58
+ const os = d.transaction(name, "readonly").objectStore(name);
59
+ const r = index !== undefined && value !== undefined ? os.index(index).getAll(value) : os.getAll();
60
+ return wrap(r);
61
+ }
62
+ return {
63
+ async get(key) {
64
+ const d = await getDb();
65
+ return wrap(d.transaction(name, "readonly").objectStore(name).get(key));
66
+ },
67
+ async add(record) {
68
+ const d = await getDb();
69
+ await wrap(d.transaction(name, "readwrite").objectStore(name).add(record));
70
+ },
71
+ async update(key, changes) {
72
+ const d = await getDb();
73
+ const tx = d.transaction(name, "readwrite");
74
+ const os = tx.objectStore(name);
75
+ const current = await wrap(os.get(key));
76
+ if (current !== undefined) {
77
+ await wrap(os.put(Object.assign({}, current, changes)));
78
+ }
79
+ },
80
+ async delete(key) {
81
+ const d = await getDb();
82
+ await wrap(d.transaction(name, "readwrite").objectStore(name).delete(key));
83
+ },
84
+ orderBy(field) {
85
+ return {
86
+ toArray: () => fetchAll().then((items) => sorted(items, field)),
87
+ };
88
+ },
89
+ where(index) {
90
+ return {
91
+ equals: (value) => ({
92
+ toArray: () => fetchAll(index, value),
93
+ sortBy: (field) => fetchAll(index, value).then((items) => sorted(items, field)),
94
+ delete: async () => {
95
+ const d = await getDb();
96
+ const tx = d.transaction(name, "readwrite");
97
+ const os = tx.objectStore(name);
98
+ const keys = await wrap(os.index(index).getAllKeys(value));
99
+ await Promise.all(keys.map((k) => wrap(os.delete(k))));
100
+ },
101
+ }),
102
+ };
103
+ },
104
+ filter: (pred) => ({
105
+ toArray: () => fetchAll().then((items) => items.filter(pred)),
106
+ }),
107
+ };
108
+ }
109
+ export const db = {
110
+ workspaces: makeTable("workspaces"),
111
+ projects: makeTable("projects"),
112
+ files: makeTable("files"),
113
+ fileContents: makeTable("fileContents"),
114
+ projectMru: makeTable("projectMru"),
115
+ };
116
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1,15 @@
1
+ /** Shows a modal input dialog. Returns the trimmed value or null if cancelled. */
2
+ export declare function showInputDialog(opts: {
3
+ title: string;
4
+ defaultValue?: string;
5
+ placeholder?: string;
6
+ confirmLabel?: string;
7
+ }): Promise<string | null>;
8
+ /** Shows a modal confirmation dialog. Returns true if confirmed, false if cancelled. */
9
+ export declare function showConfirmDialog(opts: {
10
+ title: string;
11
+ message: string;
12
+ confirmLabel?: string;
13
+ danger?: boolean;
14
+ }): Promise<boolean>;
15
+ //# sourceMappingURL=dialog.d.ts.map
@@ -0,0 +1,201 @@
1
+ const STYLE_ID = "stor-dialog-styles";
2
+ function injectStyles() {
3
+ if (document.getElementById(STYLE_ID))
4
+ return;
5
+ const style = document.createElement("style");
6
+ style.id = STYLE_ID;
7
+ style.textContent = `
8
+ .stor-dialog-overlay {
9
+ position: fixed; inset: 0; z-index: 500;
10
+ background: rgba(0,0,0,0.5);
11
+ display: flex; align-items: center; justify-content: center;
12
+ }
13
+ .stor-dialog {
14
+ background: rgba(22, 22, 30, 0.97);
15
+ border: 1px solid rgba(255,255,255,0.12);
16
+ border-radius: 10px;
17
+ padding: 20px;
18
+ min-width: 300px; max-width: 90vw;
19
+ color: rgba(255,255,255,0.85);
20
+ font-family: system-ui, -apple-system, sans-serif;
21
+ box-shadow: 0 16px 48px rgba(0,0,0,0.6);
22
+ display: flex; flex-direction: column; gap: 12px;
23
+ }
24
+ .stor-dialog-title {
25
+ font-size: 14px; font-weight: 600;
26
+ color: rgba(255,255,255,0.95);
27
+ }
28
+ .stor-dialog-msg {
29
+ font-size: 13px; color: rgba(255,255,255,0.65); line-height: 1.4;
30
+ }
31
+ .stor-dialog-input {
32
+ width: 100%; padding: 6px 10px;
33
+ background: rgba(255,255,255,0.08);
34
+ border: 1px solid rgba(255,255,255,0.15);
35
+ border-radius: 6px;
36
+ color: rgba(255,255,255,0.9);
37
+ font-size: 13px;
38
+ outline: none;
39
+ box-sizing: border-box;
40
+ }
41
+ .stor-dialog-input:focus { border-color: rgba(60,120,220,0.6); }
42
+ .stor-dialog-actions { display: flex; gap: 8px; justify-content: flex-end; }
43
+ .stor-dialog-btn {
44
+ font-size: 13px; padding: 6px 14px; border-radius: 6px;
45
+ cursor: pointer; font-weight: 500;
46
+ border: 1px solid rgba(255,255,255,0.12);
47
+ background: rgba(255,255,255,0.06);
48
+ color: rgba(255,255,255,0.8);
49
+ }
50
+ .stor-dialog-btn:hover { background: rgba(255,255,255,0.1); }
51
+ .stor-dialog-btn--primary {
52
+ background: rgba(60,120,220,0.5);
53
+ border-color: rgba(60,120,220,0.7);
54
+ color: #fff;
55
+ }
56
+ .stor-dialog-btn--primary:hover { background: rgba(60,120,220,0.65); }
57
+ .stor-dialog-btn--danger {
58
+ background: rgba(200,40,40,0.5);
59
+ border-color: rgba(200,40,40,0.7);
60
+ color: #fff;
61
+ }
62
+ .stor-dialog-btn--danger:hover { background: rgba(200,40,40,0.65); }
63
+ /* Light theme */
64
+ [data-bpmnkit-hud-theme="light"] .stor-dialog {
65
+ background: rgba(252,252,254,0.98);
66
+ border-color: rgba(0,0,0,0.1);
67
+ color: rgba(0,0,0,0.8);
68
+ box-shadow: 0 8px 32px rgba(0,0,0,0.15);
69
+ }
70
+ [data-bpmnkit-hud-theme="light"] .stor-dialog-title { color: rgba(0,0,0,0.88); }
71
+ [data-bpmnkit-hud-theme="light"] .stor-dialog-msg { color: rgba(0,0,0,0.55); }
72
+ [data-bpmnkit-hud-theme="light"] .stor-dialog-input {
73
+ background: rgba(0,0,0,0.04);
74
+ border-color: rgba(0,0,0,0.15);
75
+ color: rgba(0,0,0,0.9);
76
+ }
77
+ [data-bpmnkit-hud-theme="light"] .stor-dialog-input:focus { border-color: rgba(0,80,200,0.4); }
78
+ [data-bpmnkit-hud-theme="light"] .stor-dialog-btn {
79
+ border-color: rgba(0,0,0,0.12);
80
+ background: rgba(0,0,0,0.04);
81
+ color: rgba(0,0,0,0.7);
82
+ }
83
+ [data-bpmnkit-hud-theme="light"] .stor-dialog-btn:hover { background: rgba(0,0,0,0.08); }
84
+ [data-bpmnkit-hud-theme="light"] .stor-dialog-btn--primary {
85
+ background: rgba(0,80,200,0.85);
86
+ border-color: rgba(0,80,200,0.9);
87
+ color: #fff;
88
+ }
89
+ [data-bpmnkit-hud-theme="light"] .stor-dialog-btn--primary:hover { background: rgba(0,80,200,1); }
90
+ [data-bpmnkit-hud-theme="light"] .stor-dialog-btn--danger {
91
+ background: rgba(180,30,30,0.85);
92
+ border-color: rgba(180,30,30,0.9);
93
+ color: #fff;
94
+ }
95
+ [data-bpmnkit-hud-theme="light"] .stor-dialog-btn--danger:hover { background: rgba(180,30,30,1); }
96
+ `;
97
+ document.head.appendChild(style);
98
+ }
99
+ /** Shows a modal input dialog. Returns the trimmed value or null if cancelled. */
100
+ export function showInputDialog(opts) {
101
+ return new Promise((resolve) => {
102
+ injectStyles();
103
+ const overlay = document.createElement("div");
104
+ overlay.className = "stor-dialog-overlay";
105
+ const dialog = document.createElement("div");
106
+ dialog.className = "stor-dialog";
107
+ const titleEl = document.createElement("div");
108
+ titleEl.className = "stor-dialog-title";
109
+ titleEl.textContent = opts.title;
110
+ const input = document.createElement("input");
111
+ input.type = "text";
112
+ input.className = "stor-dialog-input";
113
+ input.value = opts.defaultValue ?? "";
114
+ if (opts.placeholder)
115
+ input.placeholder = opts.placeholder;
116
+ const actions = document.createElement("div");
117
+ actions.className = "stor-dialog-actions";
118
+ const cancelBtn = document.createElement("button");
119
+ cancelBtn.className = "stor-dialog-btn";
120
+ cancelBtn.textContent = "Cancel";
121
+ const confirmBtn = document.createElement("button");
122
+ confirmBtn.className = "stor-dialog-btn stor-dialog-btn--primary";
123
+ confirmBtn.textContent = opts.confirmLabel ?? "OK";
124
+ function close(value) {
125
+ overlay.remove();
126
+ document.removeEventListener("keydown", handleKey);
127
+ resolve(value);
128
+ }
129
+ cancelBtn.addEventListener("click", () => close(null));
130
+ confirmBtn.addEventListener("click", () => close(input.value.trim() || null));
131
+ function handleKey(e) {
132
+ if (e.key === "Escape")
133
+ close(null);
134
+ else if (e.key === "Enter")
135
+ close(input.value.trim() || null);
136
+ }
137
+ document.addEventListener("keydown", handleKey);
138
+ overlay.addEventListener("click", (e) => {
139
+ if (e.target === overlay)
140
+ close(null);
141
+ });
142
+ actions.append(cancelBtn, confirmBtn);
143
+ dialog.append(titleEl, input, actions);
144
+ overlay.append(dialog);
145
+ document.body.append(overlay);
146
+ requestAnimationFrame(() => {
147
+ input.select();
148
+ input.focus();
149
+ });
150
+ });
151
+ }
152
+ /** Shows a modal confirmation dialog. Returns true if confirmed, false if cancelled. */
153
+ export function showConfirmDialog(opts) {
154
+ return new Promise((resolve) => {
155
+ injectStyles();
156
+ const overlay = document.createElement("div");
157
+ overlay.className = "stor-dialog-overlay";
158
+ const dialog = document.createElement("div");
159
+ dialog.className = "stor-dialog";
160
+ const titleEl = document.createElement("div");
161
+ titleEl.className = "stor-dialog-title";
162
+ titleEl.textContent = opts.title;
163
+ const msgEl = document.createElement("div");
164
+ msgEl.className = "stor-dialog-msg";
165
+ msgEl.textContent = opts.message;
166
+ const actions = document.createElement("div");
167
+ actions.className = "stor-dialog-actions";
168
+ const cancelBtn = document.createElement("button");
169
+ cancelBtn.className = "stor-dialog-btn";
170
+ cancelBtn.textContent = "Cancel";
171
+ const confirmBtn = document.createElement("button");
172
+ confirmBtn.className = opts.danger
173
+ ? "stor-dialog-btn stor-dialog-btn--danger"
174
+ : "stor-dialog-btn stor-dialog-btn--primary";
175
+ confirmBtn.textContent = opts.confirmLabel ?? "Confirm";
176
+ function close(result) {
177
+ overlay.remove();
178
+ document.removeEventListener("keydown", handleKey);
179
+ resolve(result);
180
+ }
181
+ cancelBtn.addEventListener("click", () => close(false));
182
+ confirmBtn.addEventListener("click", () => close(true));
183
+ function handleKey(e) {
184
+ if (e.key === "Escape")
185
+ close(false);
186
+ else if (e.key === "Enter")
187
+ close(true);
188
+ }
189
+ document.addEventListener("keydown", handleKey);
190
+ overlay.addEventListener("click", (e) => {
191
+ if (e.target === overlay)
192
+ close(false);
193
+ });
194
+ actions.append(cancelBtn, confirmBtn);
195
+ dialog.append(titleEl, msgEl, actions);
196
+ overlay.append(dialog);
197
+ document.body.append(overlay);
198
+ requestAnimationFrame(() => confirmBtn.focus());
199
+ });
200
+ }
201
+ //# sourceMappingURL=dialog.js.map
@@ -0,0 +1,3 @@
1
+ import type { StorageApi } from "./storage-api.js";
2
+ export declare function exportProjectAsZip(api: StorageApi): Promise<void>;
3
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1,137 @@
1
+ // ─── CRC-32 ───────────────────────────────────────────────────────────────────
2
+ const CRC_TABLE = (() => {
3
+ const t = new Uint32Array(256);
4
+ for (let i = 0; i < 256; i++) {
5
+ let c = i;
6
+ for (let j = 0; j < 8; j++) {
7
+ c = c & 1 ? (c >>> 1) ^ 0xedb88320 : c >>> 1;
8
+ }
9
+ t[i] = c;
10
+ }
11
+ return t;
12
+ })();
13
+ function crc32(data) {
14
+ let crc = 0xffffffff;
15
+ for (const byte of data) {
16
+ crc = (crc >>> 8) ^ (CRC_TABLE[(crc ^ byte) & 0xff] ?? 0);
17
+ }
18
+ return (crc ^ 0xffffffff) >>> 0;
19
+ }
20
+ function u16(view, off, v) {
21
+ view.setUint16(off, v, true);
22
+ }
23
+ function u32(view, off, v) {
24
+ view.setUint32(off, v, true);
25
+ }
26
+ function buildZip(files) {
27
+ const enc = new TextEncoder();
28
+ const entries = [];
29
+ const localParts = [];
30
+ let dataOffset = 0;
31
+ for (const file of files) {
32
+ const nameBytes = enc.encode(file.name);
33
+ const crc = crc32(file.data);
34
+ const headerLen = 30 + nameBytes.length;
35
+ const header = new Uint8Array(headerLen);
36
+ const v = new DataView(header.buffer);
37
+ u32(v, 0, 0x04034b50); // local file signature
38
+ u16(v, 4, 10); // version needed: 1.0
39
+ u16(v, 6, 0); // flags
40
+ u16(v, 8, 0); // STORE
41
+ u16(v, 10, 0); // last mod time
42
+ u16(v, 12, 0); // last mod date
43
+ u32(v, 14, crc);
44
+ u32(v, 18, file.data.length); // compressed size
45
+ u32(v, 22, file.data.length); // uncompressed size
46
+ u16(v, 26, nameBytes.length);
47
+ u16(v, 28, 0); // extra field length
48
+ header.set(nameBytes, 30);
49
+ entries.push({ nameBytes, data: file.data, crc, offset: dataOffset });
50
+ localParts.push(header, file.data);
51
+ dataOffset += headerLen + file.data.length;
52
+ }
53
+ // Central directory
54
+ const centralParts = [];
55
+ let centralSize = 0;
56
+ for (const e of entries) {
57
+ const len = 46 + e.nameBytes.length;
58
+ const cd = new Uint8Array(len);
59
+ const v = new DataView(cd.buffer);
60
+ u32(v, 0, 0x02014b50); // central dir signature
61
+ u16(v, 4, 20); // version made by
62
+ u16(v, 6, 10); // version needed
63
+ u16(v, 8, 0); // flags
64
+ u16(v, 10, 0); // STORE
65
+ u16(v, 12, 0); // last mod time
66
+ u16(v, 14, 0); // last mod date
67
+ u32(v, 16, e.crc);
68
+ u32(v, 20, e.data.length); // compressed size
69
+ u32(v, 24, e.data.length); // uncompressed size
70
+ u16(v, 28, e.nameBytes.length);
71
+ u16(v, 30, 0); // extra field length
72
+ u16(v, 32, 0); // file comment length
73
+ u16(v, 34, 0); // disk number start
74
+ u16(v, 36, 0); // internal file attributes
75
+ u32(v, 38, 0); // external file attributes
76
+ u32(v, 42, e.offset); // relative offset of local header
77
+ cd.set(e.nameBytes, 46);
78
+ centralParts.push(cd);
79
+ centralSize += len;
80
+ }
81
+ // End of central directory record
82
+ const eocd = new Uint8Array(22);
83
+ const ev = new DataView(eocd.buffer);
84
+ u32(ev, 0, 0x06054b50);
85
+ u16(ev, 4, 0);
86
+ u16(ev, 6, 0);
87
+ u16(ev, 8, entries.length);
88
+ u16(ev, 10, entries.length);
89
+ u32(ev, 12, centralSize);
90
+ u32(ev, 16, dataOffset);
91
+ u16(ev, 20, 0);
92
+ const totalSize = dataOffset + centralSize + 22;
93
+ const out = new Uint8Array(totalSize);
94
+ let pos = 0;
95
+ for (const part of [...localParts, ...centralParts, eocd]) {
96
+ out.set(part, pos);
97
+ pos += part.length;
98
+ }
99
+ return out;
100
+ }
101
+ // ─── File extension helper ────────────────────────────────────────────────────
102
+ function fileExt(type) {
103
+ if (type === "bpmn")
104
+ return ".bpmn";
105
+ if (type === "dmn")
106
+ return ".dmn";
107
+ return ".form";
108
+ }
109
+ // ─── Public ───────────────────────────────────────────────────────────────────
110
+ export async function exportProjectAsZip(api) {
111
+ const projectId = api.getCurrentProjectId();
112
+ if (!projectId)
113
+ return;
114
+ const projectName = api.getProjectName(projectId) ?? "project";
115
+ const files = await api.getFiles(projectId);
116
+ const enc = new TextEncoder();
117
+ const entries = [];
118
+ for (const file of files) {
119
+ const content = await api.getFileContent(file.id);
120
+ if (content === null)
121
+ continue;
122
+ const suffix = fileExt(file.type);
123
+ const filename = file.name.toLowerCase().endsWith(suffix) ? file.name : `${file.name}${suffix}`;
124
+ entries.push({ name: filename, data: enc.encode(content) });
125
+ }
126
+ if (entries.length === 0)
127
+ return;
128
+ const zip = buildZip(entries);
129
+ const blob = new Blob([zip.buffer], { type: "application/zip" });
130
+ const url = URL.createObjectURL(blob);
131
+ const a = document.createElement("a");
132
+ a.href = url;
133
+ a.download = `${projectName}.zip`;
134
+ a.click();
135
+ URL.revokeObjectURL(url);
136
+ }
137
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1,44 @@
1
+ import type { CanvasPlugin } from "@bpmnkit/canvas";
2
+ import type { MainMenuApi } from "../main-menu/index.js";
3
+ import { StorageApi, type StorageApiOptions } from "./storage-api.js";
4
+ import type { FileType } from "./types.js";
5
+ export type { FileType, WorkspaceRecord, ProjectRecord, FileRecord, FileContentRecord, } from "./types.js";
6
+ export { StorageApi } from "./storage-api.js";
7
+ export type { StorageApiOptions } from "./storage-api.js";
8
+ export { showInputDialog, showConfirmDialog } from "./dialog.js";
9
+ /** Options for {@link createStoragePlugin}. */
10
+ export interface StoragePluginOptions extends StorageApiOptions {
11
+ /** The main menu plugin instance (must have an `api` property). */
12
+ mainMenu: CanvasPlugin & {
13
+ api: MainMenuApi;
14
+ };
15
+ /** Returns the currently open tabs with their latest content. */
16
+ getOpenTabs(): Array<{
17
+ tabId: string;
18
+ name: string;
19
+ type: FileType;
20
+ content: string;
21
+ }>;
22
+ /** Title to restore when leaving a project. Defaults to "". */
23
+ initialTitle?: string;
24
+ /** Called when the user clicks "Leave" in the project info bar. */
25
+ onLeaveProject?: () => void;
26
+ /** Called after the IndexedDB caches have finished loading. Use this to refresh any UI that depends on storage data (e.g. the recent-projects dropdown). */
27
+ onReady?: () => void;
28
+ /**
29
+ * Called when the user renames the current file via the main menu.
30
+ * Update the corresponding tab's display name from this callback.
31
+ */
32
+ onRenameCurrentFile?: (fileId: string, name: string) => void;
33
+ }
34
+ /**
35
+ * Creates an IndexedDB-backed storage plugin.
36
+ *
37
+ * Integrates with the main menu plugin to provide workspace/project navigation
38
+ * via drill-down menus. Auto-saves BPMN changes with a 500 ms debounce.
39
+ * Persists the last-opened project across page refreshes.
40
+ */
41
+ export declare function createStoragePlugin(options: StoragePluginOptions): CanvasPlugin & {
42
+ api: StorageApi;
43
+ };
44
+ //# sourceMappingURL=index.d.ts.map