@bpmnkit/operate 0.0.8 → 0.0.9

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 CHANGED
@@ -1,5 +1,5 @@
1
1
  <div align="center">
2
- <img src="https://raw.githubusercontent.com/bpmnkit/monorepo/main/doc/logos/logo-2-gateway.svg" width="72" height="72" alt="BPMN Kit logo">
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/operate</h1>
4
4
  <p>Monitoring and operations frontend for Camunda 8 clusters — real-time SSE, zero dependencies</p>
5
5
 
@@ -117,3 +117,7 @@ interface OperateApi {
117
117
  ## License
118
118
 
119
119
  [MIT](https://github.com/bpmnkit/monorepo/blob/main/LICENSE) © BPMN Kit — made by [u11g](https://u11g.com)
120
+
121
+ <div align="center">
122
+ <a href="https://bpmnkit.com"><img src="https://bpmnkit.com/favicon.svg" width="32" height="32" alt="BPMN Kit"></a>
123
+ </div>
package/dist/css.js CHANGED
@@ -1064,6 +1064,235 @@ const OPERATE_CSS = `
1064
1064
  .op-kv-row { display: flex; gap: 12px; font-size: 12px; align-items: baseline; }
1065
1065
  .op-kv-key { color: var(--bpmnkit-fg-muted); min-width: 120px; flex-shrink: 0; font-weight: 500; }
1066
1066
  .op-kv-value { color: var(--bpmnkit-fg); font-family: monospace; word-break: break-all; }
1067
+
1068
+ /* ── Search view ─────────────────────────────────────────────────────────── */
1069
+ .op-search-view {
1070
+ display: flex;
1071
+ flex-direction: column;
1072
+ gap: 16px;
1073
+ height: auto;
1074
+ overflow-y: auto;
1075
+ }
1076
+ .op-search-tab-bar {
1077
+ display: flex;
1078
+ gap: 4px;
1079
+ border-bottom: 1px solid var(--bpmnkit-border);
1080
+ padding-bottom: 0;
1081
+ margin-bottom: -8px;
1082
+ }
1083
+ .op-search-tab {
1084
+ background: none;
1085
+ border: none;
1086
+ border-bottom: 2px solid transparent;
1087
+ padding: 8px 16px;
1088
+ font-size: 13px;
1089
+ font-weight: 600;
1090
+ color: var(--bpmnkit-fg-muted);
1091
+ cursor: pointer;
1092
+ font-family: var(--bpmnkit-font);
1093
+ transition: color 0.15s, border-color 0.15s;
1094
+ margin-bottom: -1px;
1095
+ }
1096
+ .op-search-tab:hover { color: var(--bpmnkit-fg); }
1097
+ .op-search-tab--active {
1098
+ color: var(--bpmnkit-fg);
1099
+ border-bottom-color: var(--bpmnkit-accent);
1100
+ }
1101
+ .op-search-pane {
1102
+ display: flex;
1103
+ flex-direction: column;
1104
+ gap: 16px;
1105
+ }
1106
+ .op-search-header {
1107
+ display: flex;
1108
+ align-items: center;
1109
+ gap: 12px;
1110
+ flex-wrap: wrap;
1111
+ }
1112
+ .op-search-title {
1113
+ font-size: 15px;
1114
+ font-weight: 600;
1115
+ color: var(--bpmnkit-fg);
1116
+ }
1117
+ .op-search-template-row {
1118
+ display: flex;
1119
+ align-items: center;
1120
+ gap: 8px;
1121
+ margin-left: auto;
1122
+ flex-wrap: wrap;
1123
+ }
1124
+ .op-search-template-label {
1125
+ font-size: 12px;
1126
+ color: var(--bpmnkit-fg-muted);
1127
+ white-space: nowrap;
1128
+ }
1129
+ .op-search-template-select {
1130
+ background: var(--bpmnkit-surface-2);
1131
+ color: var(--bpmnkit-fg);
1132
+ border: 1px solid var(--bpmnkit-border);
1133
+ border-radius: var(--bpmnkit-radius-sm);
1134
+ padding: 4px 8px;
1135
+ font-size: 12px;
1136
+ cursor: pointer;
1137
+ outline: none;
1138
+ font-family: var(--bpmnkit-font);
1139
+ max-width: 220px;
1140
+ }
1141
+ .op-search-template-select:focus { border-color: var(--bpmnkit-accent); }
1142
+ .op-search-builder {
1143
+ background: var(--bpmnkit-surface);
1144
+ border: 1px solid var(--bpmnkit-border);
1145
+ border-radius: var(--bpmnkit-radius);
1146
+ padding: 16px;
1147
+ display: flex;
1148
+ flex-direction: column;
1149
+ gap: 12px;
1150
+ }
1151
+ .op-search-conditions {
1152
+ display: flex;
1153
+ flex-direction: column;
1154
+ gap: 8px;
1155
+ }
1156
+ .op-search-empty-hint {
1157
+ font-size: 12px;
1158
+ color: var(--bpmnkit-fg-muted);
1159
+ font-style: italic;
1160
+ padding: 4px 0;
1161
+ }
1162
+ .op-search-cond-row {
1163
+ display: flex;
1164
+ align-items: center;
1165
+ gap: 8px;
1166
+ }
1167
+ .op-search-field-select {
1168
+ background: var(--bpmnkit-surface-2);
1169
+ color: var(--bpmnkit-fg);
1170
+ border: 1px solid var(--bpmnkit-border);
1171
+ border-radius: var(--bpmnkit-radius-sm);
1172
+ padding: 5px 8px;
1173
+ font-size: 12px;
1174
+ cursor: pointer;
1175
+ outline: none;
1176
+ font-family: var(--bpmnkit-font);
1177
+ min-width: 200px;
1178
+ }
1179
+ .op-search-field-select:focus { border-color: var(--bpmnkit-accent); }
1180
+ .op-search-value-input {
1181
+ flex: 1;
1182
+ background: var(--bpmnkit-surface-2);
1183
+ border: 1px solid var(--bpmnkit-border);
1184
+ border-radius: var(--bpmnkit-radius-sm);
1185
+ padding: 5px 10px;
1186
+ font-size: 12px;
1187
+ color: var(--bpmnkit-fg);
1188
+ outline: none;
1189
+ font-family: var(--bpmnkit-font);
1190
+ }
1191
+ .op-search-value-input:focus { border-color: var(--bpmnkit-accent); }
1192
+ .op-search-value-input::placeholder { color: var(--bpmnkit-fg-muted); }
1193
+ .op-search-value-select {
1194
+ flex: 1;
1195
+ background: var(--bpmnkit-surface-2);
1196
+ color: var(--bpmnkit-fg);
1197
+ border: 1px solid var(--bpmnkit-border);
1198
+ border-radius: var(--bpmnkit-radius-sm);
1199
+ padding: 5px 8px;
1200
+ font-size: 12px;
1201
+ cursor: pointer;
1202
+ outline: none;
1203
+ font-family: var(--bpmnkit-font);
1204
+ }
1205
+ .op-search-value-select:focus { border-color: var(--bpmnkit-accent); }
1206
+ .op-search-cond-remove {
1207
+ background: none;
1208
+ border: none;
1209
+ color: var(--bpmnkit-fg-muted);
1210
+ cursor: pointer;
1211
+ font-size: 13px;
1212
+ padding: 4px 6px;
1213
+ border-radius: var(--bpmnkit-radius-sm);
1214
+ line-height: 1;
1215
+ flex-shrink: 0;
1216
+ }
1217
+ .op-search-cond-remove:hover { color: var(--bpmnkit-danger, #e05252); background: var(--bpmnkit-surface-2); }
1218
+ .op-search-add-btn {
1219
+ align-self: flex-start;
1220
+ background: none;
1221
+ border: 1px dashed var(--bpmnkit-border);
1222
+ border-radius: var(--bpmnkit-radius-sm);
1223
+ padding: 5px 14px;
1224
+ font-size: 12px;
1225
+ color: var(--bpmnkit-fg-muted);
1226
+ cursor: pointer;
1227
+ font-family: var(--bpmnkit-font);
1228
+ transition: border-color 0.15s, color 0.15s;
1229
+ }
1230
+ .op-search-add-btn:hover { border-color: var(--bpmnkit-accent); color: var(--bpmnkit-accent); }
1231
+ .op-search-actions {
1232
+ display: flex;
1233
+ align-items: center;
1234
+ gap: 10px;
1235
+ padding-top: 4px;
1236
+ border-top: 1px solid var(--bpmnkit-border);
1237
+ }
1238
+ .op-search-status {
1239
+ font-size: 12px;
1240
+ color: var(--bpmnkit-danger, #e05252);
1241
+ flex: 1;
1242
+ }
1243
+ .op-search-results {
1244
+ display: flex;
1245
+ flex-direction: column;
1246
+ gap: 10px;
1247
+ }
1248
+ .op-search-results-heading {
1249
+ font-size: 13px;
1250
+ font-weight: 600;
1251
+ color: var(--bpmnkit-fg);
1252
+ padding-bottom: 6px;
1253
+ border-bottom: 1px solid var(--bpmnkit-border);
1254
+ }
1255
+ .op-search-var-value {
1256
+ font-family: var(--bpmnkit-font-mono);
1257
+ font-size: 11px;
1258
+ color: var(--bpmnkit-fg-muted);
1259
+ display: block;
1260
+ overflow: hidden;
1261
+ text-overflow: ellipsis;
1262
+ white-space: nowrap;
1263
+ max-width: 340px;
1264
+ }
1265
+ .op-search-tab--ai { color: var(--bpmnkit-accent); }
1266
+ .op-search-tab--ai:hover { color: var(--bpmnkit-accent-bright, #3b82f6); }
1267
+ .op-search-tab--ai.op-search-tab--active { color: var(--bpmnkit-accent); border-bottom-color: var(--bpmnkit-accent); }
1268
+ .op-ai-search-row {
1269
+ display: flex;
1270
+ gap: 8px;
1271
+ align-items: center;
1272
+ }
1273
+ .op-ai-search-input {
1274
+ flex: 1;
1275
+ background: var(--bpmnkit-surface-2);
1276
+ border: 1px solid var(--bpmnkit-border);
1277
+ border-radius: var(--bpmnkit-radius-sm);
1278
+ padding: 7px 12px;
1279
+ font-size: 13px;
1280
+ color: var(--bpmnkit-fg);
1281
+ outline: none;
1282
+ font-family: var(--bpmnkit-font);
1283
+ }
1284
+ .op-ai-search-input:focus { border-color: var(--bpmnkit-accent); }
1285
+ .op-ai-search-input::placeholder { color: var(--bpmnkit-fg-muted); }
1286
+ .op-ai-search-hint {
1287
+ font-size: 11px;
1288
+ color: var(--bpmnkit-fg-muted);
1289
+ }
1290
+ .op-ai-search-filter {
1291
+ font-size: 11px;
1292
+ color: var(--bpmnkit-fg-muted);
1293
+ font-family: var(--bpmnkit-font-mono);
1294
+ padding: 2px 0 6px;
1295
+ }
1067
1296
  `;
1068
1297
  export function injectOperateStyles() {
1069
1298
  injectStyle(OPERATE_STYLE_ID, OPERATE_CSS);
package/dist/operate.js CHANGED
@@ -21,6 +21,7 @@ import { createInstancesView } from "./views/instances.js";
21
21
  import { createJobsView } from "./views/jobs.js";
22
22
  import { createMessagesView } from "./views/messages.js";
23
23
  import { createNav } from "./views/nav.js";
24
+ import { createSearchView } from "./views/search.js";
24
25
  import { createTaskDetailView } from "./views/task-detail.js";
25
26
  import { createTasksView } from "./views/tasks.js";
26
27
  export function createOperate(options) {
@@ -28,7 +29,7 @@ export function createOperate(options) {
28
29
  injectOperateStyles();
29
30
  const { container, proxyUrl = "http://localhost:3033", pollInterval = 30_000, mock = false, } = options;
30
31
  let profile = options.profile ?? null;
31
- const initialTheme = loadPersistedTheme() ?? options.theme ?? "auto";
32
+ const initialTheme = loadPersistedTheme() ?? options.theme ?? "neon";
32
33
  // ── Root element ──────────────────────────────────────────────────────────
33
34
  const el = document.createElement("div");
34
35
  el.className = "op-root";
@@ -110,7 +111,10 @@ export function createOperate(options) {
110
111
  content.appendChild(viewEl);
111
112
  }
112
113
  function getTheme() {
113
- return el.getAttribute("data-theme") === "light" ? "light" : "dark";
114
+ const t = el.getAttribute("data-theme");
115
+ if (t === "light" || t === "neon")
116
+ return t;
117
+ return "dark";
114
118
  }
115
119
  router.on("/", () => {
116
120
  reconnectCurrent = () => {
@@ -274,6 +278,16 @@ export function createOperate(options) {
274
278
  const { el: vEl, destroy } = createMessagesView({ proxyUrl, profile, mock });
275
279
  showView(vEl, destroy);
276
280
  });
281
+ router.on("/search", () => {
282
+ reconnectCurrent = () => {
283
+ disconnectAll();
284
+ };
285
+ reconnectCurrent();
286
+ header.setTitle("Search");
287
+ nav.setActive("/search");
288
+ const { el: vEl, destroy } = createSearchView({ proxyUrl, profile, mock }, (path) => router.navigate(path));
289
+ showView(vEl, destroy);
290
+ });
277
291
  const stopRouter = router.start();
278
292
  // ── Public API ────────────────────────────────────────────────────────────
279
293
  return {
@@ -3,12 +3,12 @@ interface Config {
3
3
  proxyUrl: string;
4
4
  profile: string | null;
5
5
  mock: boolean;
6
- theme: "light" | "dark";
6
+ theme: "light" | "dark" | "neon";
7
7
  navigate?: (path: string) => void;
8
8
  }
9
9
  export declare function createDecisionDetailView(definitionKey: string, store: DecisionsStore, cfg: Config, onBack: () => void): {
10
10
  el: HTMLElement;
11
- setTheme(t: "light" | "dark"): void;
11
+ setTheme(t: "light" | "dark" | "neon"): void;
12
12
  destroy(): void;
13
13
  };
14
14
  export {};
@@ -103,7 +103,10 @@ export function createDecisionDetailView(definitionKey, store, cfg, onBack) {
103
103
  function loadEditor(xml) {
104
104
  editor?.destroy();
105
105
  editorWrap.innerHTML = "";
106
- editor = new DmnEditor({ container: editorWrap, theme: cfg.theme });
106
+ editor = new DmnEditor({
107
+ container: editorWrap,
108
+ theme: cfg.theme === "neon" ? "dark" : cfg.theme,
109
+ });
107
110
  editor.loadXML(xml).catch(() => { });
108
111
  }
109
112
  let xmlStarted = false;
@@ -156,7 +159,7 @@ export function createDecisionDetailView(definitionKey, store, cfg, onBack) {
156
159
  return {
157
160
  el,
158
161
  setTheme(t) {
159
- editor?.setTheme(t);
162
+ editor?.setTheme(t === "neon" ? "dark" : t);
160
163
  },
161
164
  destroy() {
162
165
  unsub();
@@ -3,12 +3,12 @@ interface Config {
3
3
  proxyUrl: string;
4
4
  profile: string | null;
5
5
  mock: boolean;
6
- theme: "light" | "dark";
6
+ theme: "light" | "dark" | "neon";
7
7
  navigate?: (path: string) => void;
8
8
  }
9
9
  export declare function createDefinitionDetailView(definitionKey: string, store: DefinitionsStore, cfg: Config, onBack: () => void): {
10
10
  el: HTMLElement;
11
- setTheme(t: "light" | "dark"): void;
11
+ setTheme(t: "light" | "dark" | "neon"): void;
12
12
  destroy(): void;
13
13
  };
14
14
  export {};
@@ -42,7 +42,7 @@ export function createDefinitionDetailView(definitionKey, store, cfg, onBack) {
42
42
  layout.appendChild(canvasWrap);
43
43
  const sidebar = document.createElement("div");
44
44
  sidebar.className = "op-detail-sidebar";
45
- sidebar.dataset.bpmnHudTheme = cfg.theme;
45
+ sidebar.dataset.bpmnkitHudTheme = cfg.theme;
46
46
  layout.appendChild(sidebar);
47
47
  const tabBar = document.createElement("div");
48
48
  tabBar.className = "op-detail-tabs";
@@ -328,7 +328,7 @@ export function createDefinitionDetailView(definitionKey, store, cfg, onBack) {
328
328
  el,
329
329
  setTheme(t) {
330
330
  canvas?.setTheme(t);
331
- sidebar.dataset.bpmnHudTheme = t;
331
+ sidebar.dataset.bpmnkitHudTheme = t;
332
332
  },
333
333
  destroy() {
334
334
  canvas?.destroy();
@@ -1,6 +1,6 @@
1
1
  import { type Theme } from "@bpmnkit/ui";
2
2
  import type { ProfileInfo } from "../types.js";
3
- export declare function createHeader(onProfileChange: (name: string) => void, onThemeChange: (theme: Theme, resolved: "light" | "dark") => void, initialTheme?: Theme): {
3
+ export declare function createHeader(onProfileChange: (name: string) => void, onThemeChange: (theme: Theme, resolved: "light" | "dark" | "neon") => void, initialTheme?: Theme): {
4
4
  el: HTMLElement;
5
5
  setTitle(title: string): void;
6
6
  setProfiles(profiles: ProfileInfo[], active: string | null): void;
@@ -1,5 +1,5 @@
1
1
  import { createThemeSwitcher } from "@bpmnkit/ui";
2
- export function createHeader(onProfileChange, onThemeChange, initialTheme = "auto") {
2
+ export function createHeader(onProfileChange, onThemeChange, initialTheme = "neon") {
3
3
  const el = document.createElement("header");
4
4
  el.className = "op-header";
5
5
  const title = document.createElement("h1");
@@ -3,7 +3,7 @@ interface Config {
3
3
  proxyUrl: string;
4
4
  profile: string | null;
5
5
  mock: boolean;
6
- theme: "light" | "dark";
6
+ theme: "light" | "dark" | "neon";
7
7
  navigate?: (path: string) => void;
8
8
  }
9
9
  export declare function createIncidentDetailView(incidentKey: string, store: IncidentsStore, cfg: Config, onBack: () => void): {
@@ -64,7 +64,7 @@ export function createIncidentDetailView(incidentKey, store, cfg, onBack) {
64
64
  // Sidebar pane
65
65
  const sidebar = document.createElement("div");
66
66
  sidebar.className = "op-detail-sidebar";
67
- sidebar.dataset.bpmnHudTheme = cfg.theme;
67
+ sidebar.dataset.bpmnkitHudTheme = cfg.theme;
68
68
  layout.appendChild(sidebar);
69
69
  // Tabs
70
70
  const tabNames = ["Details", "Properties", "AI Assist"];
@@ -4,12 +4,12 @@ interface Config {
4
4
  profile: string | null;
5
5
  interval: number;
6
6
  mock: boolean;
7
- theme: "light" | "dark";
7
+ theme: "light" | "dark" | "neon";
8
8
  navigate?: (path: string) => void;
9
9
  }
10
10
  export declare function createInstanceDetailView(instanceKey: string, instancesStore: InstancesStore, cfg: Config, onBack: () => void): {
11
11
  el: HTMLElement;
12
- setTheme(t: "light" | "dark"): void;
12
+ setTheme(t: "light" | "dark" | "neon"): void;
13
13
  destroy(): void;
14
14
  };
15
15
  export {};
@@ -163,7 +163,7 @@ export function createInstanceDetailView(instanceKey, instancesStore, cfg, onBac
163
163
  // Sidebar pane
164
164
  const sidebar = document.createElement("div");
165
165
  sidebar.className = "op-detail-sidebar";
166
- sidebar.dataset.bpmnHudTheme = cfg.theme;
166
+ sidebar.dataset.bpmnkitHudTheme = cfg.theme;
167
167
  layout.appendChild(sidebar);
168
168
  // Tabs in sidebar
169
169
  const tabs = ["Variables", "Incidents", "Properties"];
@@ -715,7 +715,7 @@ export function createInstanceDetailView(instanceKey, instancesStore, cfg, onBac
715
715
  el,
716
716
  setTheme(t) {
717
717
  canvas?.setTheme(t);
718
- sidebar.dataset.bpmnHudTheme = t;
718
+ sidebar.dataset.bpmnkitHudTheme = t;
719
719
  },
720
720
  destroy() {
721
721
  canvas?.destroy();
package/dist/views/nav.js CHANGED
@@ -8,6 +8,7 @@ const NAV_ITEMS = [
8
8
  { id: "/jobs", label: "Jobs", icon: IC_UI.jobs },
9
9
  { id: "/tasks", label: "Tasks", icon: IC_UI.tasks },
10
10
  { id: "/messages", label: "Messages", icon: IC_UI.messages },
11
+ { id: "/search", label: "Search", icon: IC_UI.search },
11
12
  ];
12
13
  export function createNav(onNavigate) {
13
14
  const el = document.createElement("nav");
@@ -0,0 +1,11 @@
1
+ interface Config {
2
+ proxyUrl: string;
3
+ profile: string | null;
4
+ mock: boolean;
5
+ }
6
+ export declare function createSearchView(cfg: Config, onNavigate: (path: string) => void): {
7
+ el: HTMLElement;
8
+ destroy(): void;
9
+ };
10
+ export {};
11
+ //# sourceMappingURL=search.d.ts.map