@kiberon-labs/behave-graph-flow 2.0.0 → 3.0.0

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 (251) hide show
  1. package/.storybook/manager.ts +6 -0
  2. package/.storybook/preview.ts +49 -1
  3. package/.storybook/styles.css +9 -3
  4. package/.turbo/turbo-build.log +1 -1
  5. package/CHANGELOG.md +368 -0
  6. package/dist/AnyControlImpl-Ds-CShIB.js +20 -0
  7. package/dist/AnyControlImpl-Ds-CShIB.js.map +1 -0
  8. package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js +166 -0
  9. package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js.map +1 -0
  10. package/dist/index.css +36 -33
  11. package/dist/index.css.map +1 -1
  12. package/dist/index.d.ts +1865 -550
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +14357 -11221
  15. package/dist/index.js.map +1 -1
  16. package/dist/noteImpl-KkrrWgJd.js +242 -0
  17. package/dist/noteImpl-KkrrWgJd.js.map +1 -0
  18. package/dist/styles.module-CvmpDkZj.css +3 -0
  19. package/dist/styles.module-CvmpDkZj.css.map +1 -0
  20. package/dist/styles.module-DZxg8aW9.js +271 -0
  21. package/dist/styles.module-DZxg8aW9.js.map +1 -0
  22. package/dist/useChangeNodeData-ChQGK7AI.js +23 -0
  23. package/dist/useChangeNodeData-ChQGK7AI.js.map +1 -0
  24. package/docs/protocol.md +43 -20
  25. package/package.json +5 -9
  26. package/src/components/FloatingToolbar/index.module.css +5 -13
  27. package/src/components/FloatingToolbar/index.tsx +9 -9
  28. package/src/components/Flow.tsx +34 -23
  29. package/src/components/contextMenus/DynamicContextMenu.tsx +85 -0
  30. package/src/components/contextMenus/NodePicker.module.css +13 -13
  31. package/src/components/contextMenus/edge.tsx +9 -95
  32. package/src/components/contextMenus/node.tsx +9 -149
  33. package/src/components/contextMenus/selection.tsx +5 -71
  34. package/src/components/controls/any/AnyControlImpl.tsx +14 -0
  35. package/src/components/controls/any/index.tsx +13 -2
  36. package/src/components/edges/index.tsx +75 -69
  37. package/src/components/layoutController/index.module.css +3 -0
  38. package/src/components/layoutController/index.tsx +24 -1
  39. package/src/components/layoutController/utils.ts +46 -3
  40. package/src/components/menubar/defaults.tsx +55 -19
  41. package/src/components/menubar/menuItem.module.css +18 -3
  42. package/src/components/menubar/menuItem.tsx +34 -1
  43. package/src/components/nodes/behave/NodeContainer.module.css +26 -25
  44. package/src/components/nodes/group/index.tsx +3 -3
  45. package/src/components/nodes/wrapper/styles.module.css +6 -32
  46. package/src/components/panels/alignment/index.module.css +0 -10
  47. package/src/components/panels/alignment/index.tsx +4 -4
  48. package/src/components/panels/base/styles.module.css +2 -2
  49. package/src/components/panels/common/PanelHeader.module.css +24 -0
  50. package/src/components/panels/common/PanelHeader.tsx +22 -0
  51. package/src/components/panels/common/SectionTitle.module.css +13 -0
  52. package/src/components/panels/common/SectionTitle.tsx +10 -0
  53. package/src/components/panels/events/EditEventPanel.tsx +14 -5
  54. package/src/components/panels/events/ManageEventsPanel.tsx +11 -8
  55. package/src/components/panels/events/styles.module.css +6 -64
  56. package/src/components/panels/graphProperties/index.tsx +125 -0
  57. package/src/components/panels/history/index.tsx +2 -2
  58. package/src/components/panels/history/styles.module.css +0 -9
  59. package/src/components/panels/keymaps/index.module.css +3 -13
  60. package/src/components/panels/keymaps/index.tsx +1 -2
  61. package/src/components/panels/layers/index.tsx +20 -15
  62. package/src/components/panels/layers/styles.module.css +9 -12
  63. package/src/components/panels/legend/index.tsx +1 -1
  64. package/src/components/panels/logs/index.module.css +25 -19
  65. package/src/components/panels/logs/index.tsx +7 -7
  66. package/src/components/panels/nodeInputs/InputsGroup.tsx +1 -0
  67. package/src/components/panels/nodeInputs/NodeSettings.tsx +2 -2
  68. package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +1 -1
  69. package/src/components/panels/nodeInputs/OutputsGroup.tsx +2 -12
  70. package/src/components/panels/nodeInputs/index.module.css +99 -75
  71. package/src/components/panels/nodeInputs/index.tsx +21 -11
  72. package/src/components/panels/nodeInputs/useNodeHandlers.ts +2 -2
  73. package/src/components/panels/nodeInputs/useNodeInputsData.ts +23 -43
  74. package/src/components/panels/nodePicker/index.tsx +8 -8
  75. package/src/components/panels/panel/index.module.css +7 -7
  76. package/src/components/panels/search/index.module.css +0 -50
  77. package/src/components/panels/search/index.tsx +2 -2
  78. package/src/components/panels/systemSettings/ConversionsSettings.tsx +203 -0
  79. package/src/components/panels/systemSettings/index.tsx +221 -176
  80. package/src/components/panels/systemSettings/styles.module.css +135 -8
  81. package/src/components/panels/traces/GridLines.tsx +1 -1
  82. package/src/components/panels/traces/TimeGrid.tsx +3 -3
  83. package/src/components/panels/traces/TraceLane.tsx +1 -1
  84. package/src/components/panels/traces/index.module.css +1 -8
  85. package/src/components/panels/traces/index.tsx +8 -4
  86. package/src/components/panels/traces/useDerivedSpans.ts +241 -146
  87. package/src/components/panels/traces/utils.ts +8 -0
  88. package/src/components/panels/variables/CreateVariableScreen.tsx +3 -3
  89. package/src/components/panels/variables/ManageVariablesScreen.tsx +12 -9
  90. package/src/components/panels/variables/index.tsx +2 -2
  91. package/src/components/panels/variables/styles.module.css +4 -91
  92. package/src/components/primitives/icon.module.css +4 -4
  93. package/src/components/sockets/input/index.tsx +9 -2
  94. package/src/components/sockets/input/styles.module.css +2 -3
  95. package/src/components/sockets/output/index.tsx +10 -3
  96. package/src/components/sockets/output/styles.module.css +1 -6
  97. package/src/css/notes.css +135 -0
  98. package/src/css/prosemirror.css +3 -3
  99. package/src/css/rc-dock.css +143 -43
  100. package/src/css/rc-menu.css +56 -55
  101. package/src/css/themes/kiberon.css +127 -0
  102. package/src/css/vars.css +197 -13
  103. package/src/css/vscode-elements.css +124 -0
  104. package/src/generators/CallSubgraphGenerator.tsx +136 -0
  105. package/src/generators/CustomEventOnTriggeredGenerator.tsx +2 -2
  106. package/src/generators/GraphBoundaryGenerator.module.css +32 -0
  107. package/src/generators/GraphBoundaryGenerator.tsx +193 -0
  108. package/src/generators/SequenceGenerator.tsx +2 -2
  109. package/src/generators/SwitchOnIntegerGenerator.tsx +2 -2
  110. package/src/generators/SwitchOnStringGenerator.tsx +2 -2
  111. package/src/generators/callSubgraphSync.ts +126 -0
  112. package/src/generators/registerDefaultGenerators.ts +21 -0
  113. package/src/generators/registerDefaults.ts +26 -0
  114. package/src/hooks/useBehaveGraphFlow.ts +2 -2
  115. package/src/hooks/useFlowHandlers.ts +47 -9
  116. package/src/hooks/useWasdPan.ts +26 -4
  117. package/src/index.css +4 -16
  118. package/src/index.ts +17 -0
  119. package/src/manifest/contributionRegistry.ts +93 -0
  120. package/src/manifest/index.ts +4 -0
  121. package/src/manifest/loadManifest.ts +82 -0
  122. package/src/manifest/manifestPlugin.ts +29 -0
  123. package/src/manifest/passthroughValueType.ts +40 -0
  124. package/src/plugin/alignment/index.ts +22 -12
  125. package/src/plugin/autosave/controller.ts +366 -0
  126. package/src/plugin/autosave/index.tsx +114 -0
  127. package/src/plugin/autosave/panel/BackupPanel.tsx +141 -0
  128. package/src/plugin/autosave/panel/index.tsx +1 -0
  129. package/src/plugin/autosave/panel/styles.module.css +56 -0
  130. package/src/plugin/autosave/settings.ts +65 -0
  131. package/src/plugin/autosave/storage.ts +147 -0
  132. package/src/plugin/docs/index.tsx +2 -4
  133. package/src/plugin/docs/panel/DocumentationBrowserPanelImpl.tsx +200 -0
  134. package/src/plugin/docs/panel/index.tsx +15 -194
  135. package/src/plugin/docs/panel/styles.module.css +8 -8
  136. package/src/plugin/graphrunner/actions.ts +258 -185
  137. package/src/plugin/graphrunner/buttons.tsx +34 -26
  138. package/src/plugin/graphrunner/client.ts +4 -1
  139. package/src/plugin/graphrunner/index.tsx +29 -100
  140. package/src/plugin/graphrunner/panel.tsx +2 -2
  141. package/src/plugin/graphrunner/runController.ts +283 -0
  142. package/src/plugin/graphrunner/runner.ts +21 -192
  143. package/src/plugin/graphrunner/store.ts +14 -24
  144. package/src/plugin/graphrunner/styles.module.css +17 -57
  145. package/src/plugin/graphrunner/transport.ts +26 -0
  146. package/src/plugin/graphrunner/types.ts +21 -0
  147. package/src/plugin/graphrunner-local/execution-utils.ts +260 -80
  148. package/src/plugin/graphrunner-local/index.tsx +8 -2
  149. package/src/plugin/graphrunner-local/panel.tsx +131 -175
  150. package/src/plugin/graphrunner-local/styles.module.css +57 -76
  151. package/src/plugin/graphrunner-local/transport.ts +151 -184
  152. package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +2 -0
  153. package/src/plugin/graphrunner-webworker/index.tsx +4 -10
  154. package/src/plugin/graphrunner-webworker/store.ts +9 -0
  155. package/src/plugin/kitchen-sink/index.ts +38 -0
  156. package/src/{layout/dagre.tsx → plugin/layout/dagre.ts} +17 -5
  157. package/src/{layout → plugin/layout}/elk.ts +22 -6
  158. package/src/plugin/layout/index.ts +80 -0
  159. package/src/plugin/notes/FormatToolbar.tsx +200 -0
  160. package/src/plugin/notes/index.tsx +191 -0
  161. package/src/plugin/notes/nodeActions.ts +100 -0
  162. package/src/plugin/notes/note.tsx +20 -0
  163. package/src/plugin/notes/noteImpl.tsx +89 -0
  164. package/src/plugin/realtime/realtimeRunner.ts +58 -4
  165. package/src/specifics/CustomEventOnTriggeredSpecific.tsx +2 -2
  166. package/src/specifics/CustomEventTriggerSpecific.tsx +2 -2
  167. package/src/specifics/VariableGetSpecific.tsx +2 -2
  168. package/src/specifics/VariableSetSpecific.tsx +2 -2
  169. package/src/store/actions.tsx +5 -5
  170. package/src/store/commands.ts +278 -0
  171. package/src/store/contextMenu.ts +192 -0
  172. package/src/store/conversions.ts +47 -0
  173. package/src/store/flow.tsx +23 -38
  174. package/src/store/graphMeta.ts +39 -0
  175. package/src/store/hotKeys.tsx +301 -260
  176. package/src/store/layers.ts +3 -3
  177. package/src/store/registry.ts +12 -4
  178. package/src/store/selection.ts +3 -3
  179. package/src/store/settings.ts +82 -82
  180. package/src/store/settingsSchema.ts +210 -0
  181. package/src/store/tabs.ts +5 -1
  182. package/src/store/traces.ts +3 -3
  183. package/src/system/graph.ts +11 -14
  184. package/src/system/graphSession.ts +172 -0
  185. package/src/system/index.ts +3 -0
  186. package/src/system/notifications.ts +13 -0
  187. package/src/system/persistence.ts +82 -0
  188. package/src/system/plugin.ts +28 -0
  189. package/src/system/provider.tsx +64 -0
  190. package/src/system/system.ts +518 -88
  191. package/src/system/tabLoader.tsx +70 -32
  192. package/src/system/undoRedo.ts +1 -1
  193. package/src/transformers/Uigraph.ts +5 -4
  194. package/src/transformers/contract.ts +87 -0
  195. package/src/transformers/flowToBehave.ts +13 -5
  196. package/src/types/nodes.ts +8 -3
  197. package/src/types.ts +2 -0
  198. package/src/util/autoConvert.ts +200 -0
  199. package/src/util/isValidConnection.ts +23 -2
  200. package/stories/defaults/defaultStoryProvider.tsx +17 -14
  201. package/stories/defaults/systemGenerator.ts +6 -1
  202. package/stories/{components/nodes/comment.stories.tsx → plugins/notes.stories.tsx} +24 -30
  203. package/tests/autoConvert.test.ts +329 -0
  204. package/tests/autosavePlugin.test.ts +204 -0
  205. package/tests/callSubgraphSync.test.ts +148 -0
  206. package/tests/commandRegistry.test.ts +137 -0
  207. package/tests/contract.test.ts +51 -0
  208. package/tests/contractSerialize.test.ts +62 -0
  209. package/tests/deriveSpans.test.ts +71 -0
  210. package/tests/flowToBehave.test.ts +2 -1
  211. package/tests/hotkeys.test.ts +79 -0
  212. package/tests/keepAliveLifecycle.test.ts +167 -0
  213. package/tests/loadManifest.test.ts +113 -0
  214. package/tests/noteMarkdown.test.ts +65 -0
  215. package/tests/notesPlugin.test.ts +162 -0
  216. package/tests/persistence.test.ts +51 -0
  217. package/tests/saveLoad.test.ts +7 -6
  218. package/tests/settings.test.ts +178 -0
  219. package/tests/traceStore.test.ts +46 -0
  220. package/tests/visual/README.md +2 -2
  221. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-conversation-chromium-win32.png +0 -0
  222. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-events-chromium-win32.png +0 -0
  223. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-history-chromium-win32.png +0 -0
  224. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-keymaps-chromium-win32.png +0 -0
  225. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-layers-chromium-win32.png +0 -0
  226. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-legend-chromium-win32.png +0 -0
  227. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-localGraphRunner-chromium-win32.png +0 -0
  228. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-logs-chromium-win32.png +0 -0
  229. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodeInputs-chromium-win32.png +0 -0
  230. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodePicker-chromium-win32.png +0 -0
  231. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-panel-chromium-win32.png +0 -0
  232. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-search-chromium-win32.png +0 -0
  233. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-systemSettings-chromium-win32.png +0 -0
  234. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-variables-chromium-win32.png +0 -0
  235. package/tests/visual/panels.visual.test.tsx +3 -3
  236. package/tests/wasdPan.test.ts +71 -0
  237. package/vitest.config.ts +1 -1
  238. package/vitest.visual.config.ts +7 -0
  239. package/.storybook/vscode.css +0 -814
  240. package/src/components/nodes/comment/FormatToolbar.tsx +0 -118
  241. package/src/components/nodes/comment/comment.tsx +0 -103
  242. package/src/components/nodes/comment/styles.module.css +0 -150
  243. package/src/components/panels/conversation/index.module.css +0 -151
  244. package/src/components/panels/conversation/index.tsx +0 -162
  245. package/src/components/panels/events/CustomEventsEditor.tsx +0 -384
  246. package/src/css/vscode.css +0 -13
  247. package/src/hooks/useDetachNodes.ts +0 -39
  248. package/src/plugin/graphrunner-webworker/types.ts +0 -17
  249. package/src/specifics/registerDefaultSpecifics.ts +0 -5
  250. package/src/store/chat.ts +0 -73
  251. package/src/store/graphRunnerClient.ts +0 -110
@@ -53,18 +53,21 @@ export interface IWindowButton {
53
53
  name: string;
54
54
  icon?: JSX.Element;
55
55
  content: JSX.Element;
56
+ /** Command id whose shortcut is shown next to this item. */
57
+ commandId?: string;
56
58
  }
57
59
  /**
58
60
  * A simple button that toggles a window panel
59
61
  * @param param0
60
62
  * @returns
61
63
  */
62
- export const windowButton = ({
64
+ const windowButton = ({
63
65
  name,
64
66
  id,
65
67
  title,
66
68
  icon,
67
- content
69
+ content,
70
+ commandId
68
71
  }: IWindowButton): IMenuItem => ({
69
72
  name: name,
70
73
  render: function Toggle() {
@@ -99,7 +102,12 @@ export const windowButton = ({
99
102
  }
100
103
  };
101
104
  return (
102
- <MenuItemElement onClick={onToggle} key={title} icon={icon}>
105
+ <MenuItemElement
106
+ onClick={onToggle}
107
+ key={title}
108
+ icon={icon}
109
+ commandId={commandId}
110
+ >
103
111
  {title}
104
112
  </MenuItemElement>
105
113
  );
@@ -114,9 +122,15 @@ export const defaultMenuDataFactory = (): IMenu => ({
114
122
  items: [
115
123
  {
116
124
  name: 'newGraph',
117
- render: (rest) => {
125
+ render: function NewGraph(rest) {
126
+ const system = useSystem();
118
127
  return (
119
- <MenuItemElement key="new" icon={<PagePlusIn />} {...rest}>
128
+ <MenuItemElement
129
+ key="new"
130
+ icon={<PagePlusIn />}
131
+ onClick={() => system.newGraph()}
132
+ {...rest}
133
+ >
120
134
  New Graph
121
135
  </MenuItemElement>
122
136
  );
@@ -194,7 +208,7 @@ export const defaultMenuDataFactory = (): IMenu => ({
194
208
  const system = useSystem();
195
209
 
196
210
  const onSave = () => {
197
- system.actionStore.getState().actions.save();
211
+ void system.runCommand('editor.save');
198
212
  };
199
213
 
200
214
  return (
@@ -202,6 +216,7 @@ export const defaultMenuDataFactory = (): IMenu => ({
202
216
  key={'saveUI'}
203
217
  icon={<Download />}
204
218
  onClick={onSave}
219
+ commandId="editor.save"
205
220
  {...rest}
206
221
  >
207
222
  Save Graph
@@ -285,10 +300,11 @@ export const defaultMenuDataFactory = (): IMenu => ({
285
300
  const canUndo = useStore(sys.undoManager.store, (s) => s.canUndo);
286
301
  return (
287
302
  <MenuItemElement
288
- onClick={() => canUndo && sys.undoManager.undo()}
303
+ onClick={() => canUndo && sys.runCommand('editor.undo')}
289
304
  disabled={!canUndo}
290
305
  key={key}
291
306
  icon={<Undo />}
307
+ commandId="editor.undo"
292
308
  {...rest}
293
309
  >
294
310
  Undo
@@ -304,10 +320,11 @@ export const defaultMenuDataFactory = (): IMenu => ({
304
320
  const canRedo = useStore(sys.undoManager.store, (s) => s.canRedo);
305
321
  return (
306
322
  <MenuItemElement
307
- onClick={() => canRedo && sys.undoManager.redo()}
323
+ onClick={() => canRedo && sys.runCommand('editor.redo')}
308
324
  disabled={!canRedo}
309
325
  key={key}
310
326
  icon={<Redo />}
327
+ commandId="editor.redo"
311
328
  {...rest}
312
329
  >
313
330
  Redo
@@ -326,26 +343,45 @@ export const defaultMenuDataFactory = (): IMenu => ({
326
343
  },
327
344
  {
328
345
  name: 'copy',
329
- render: ({ key, ...rest }) => (
330
- <MenuItemElement key={key} icon={<Redo />} {...rest}>
331
- Copy
332
- </MenuItemElement>
333
- )
346
+ render: function Copy({ key, ...rest }) {
347
+ const sys = useSystem();
348
+ return (
349
+ <MenuItemElement
350
+ key={key}
351
+ icon={<Redo />}
352
+ onClick={() => sys.runCommand('selection.copy')}
353
+ commandId="selection.copy"
354
+ {...rest}
355
+ >
356
+ Copy
357
+ </MenuItemElement>
358
+ );
359
+ }
334
360
  },
335
361
  {
336
362
  name: 'paste',
337
- render: ({ key, ...rest }) => (
338
- <MenuItemElement key={key} icon={<Redo />} {...rest}>
339
- Paste
340
- </MenuItemElement>
341
- )
363
+ render: function Paste({ key, ...rest }) {
364
+ const sys = useSystem();
365
+ return (
366
+ <MenuItemElement
367
+ key={key}
368
+ icon={<Redo />}
369
+ onClick={() => void sys.runCommand('selection.paste')}
370
+ commandId="selection.paste"
371
+ {...rest}
372
+ >
373
+ Paste
374
+ </MenuItemElement>
375
+ );
376
+ }
342
377
  },
343
378
  new Seperator(),
344
379
  windowButton({
345
380
  name: 'find',
346
381
  id: 'find',
347
382
  title: 'Find',
348
- content: <SearchPanel />
383
+ content: <SearchPanel />,
384
+ commandId: 'editor.find'
349
385
  })
350
386
  ]
351
387
  },
@@ -7,10 +7,25 @@
7
7
  }
8
8
 
9
9
  .inner {
10
- padding-left: 0.5rem;
11
- padding-right: 0.5rem;
12
- padding: 0.25rem;
10
+ padding: 0.25rem 0.5rem;
13
11
  border-radius: 0.25rem;
14
12
  width: 100%;
15
13
  min-width: 300px;
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: space-between;
17
+ gap: 1.5rem;
18
+ }
19
+
20
+ .label {
21
+ flex: 1 1 auto;
22
+ min-width: 0;
23
+ }
24
+
25
+ .keybinding {
26
+ flex: 0 0 auto;
27
+ font-size: 0.85em;
28
+ opacity: 0.6;
29
+ font-variant-numeric: tabular-nums;
30
+ white-space: nowrap;
16
31
  }
@@ -1,30 +1,63 @@
1
1
  import { Item } from 'rc-menu';
2
2
  import React from 'react';
3
+ import { useStore } from 'zustand';
4
+ import { useSystem } from '@/system';
3
5
 
4
6
  import styles from './menuItem.module.css';
5
7
 
6
8
  export type IMenuItemElement = React.ComponentProps<typeof Item> & {
7
9
  icon?: React.ReactNode;
10
+ /**
11
+ * Explicit shortcut hint (e.g. `'Ctrl+S'`). Overrides the auto-detected one.
12
+ */
13
+ keybinding?: string;
14
+ /**
15
+ * Command id this item runs. When provided, the shortcut hint is detected
16
+ * automatically from the live keymap, so a menu item shows its shortcut just
17
+ * by naming the command it dispatches.
18
+ */
19
+ commandId?: string;
8
20
  /**
9
21
  * Needed to hack into the inner part of the menu item
10
22
  */
11
23
  inner?: (children: React.ReactNode) => React.ReactNode;
12
24
  };
13
25
 
26
+ /** Right-aligned shortcut hint resolved live from the command's keymap binding. */
27
+ const KeybindingHint = ({ commandId }: { commandId: string }) => {
28
+ const sys = useSystem();
29
+ const hint = useStore(sys.hotKeyStore, (s) =>
30
+ s.getCommandKeybinding(commandId)
31
+ );
32
+ if (!hint) return null;
33
+ return <span className={styles.keybinding}>{hint}</span>;
34
+ };
35
+
14
36
  /**
15
37
  * You must provide a unique key for each item
16
38
  */
17
39
  export const MenuItemElement = ({
18
40
  inner = (children: React.ReactNode) => children,
19
41
  children,
42
+ keybinding,
43
+ commandId,
20
44
  ...rest
21
45
  }: IMenuItemElement) => {
46
+ const hint = keybinding ? (
47
+ <span className={styles.keybinding}>{keybinding}</span>
48
+ ) : commandId ? (
49
+ <KeybindingHint commandId={commandId} />
50
+ ) : null;
51
+
22
52
  return (
23
53
  // @ts-expect-error This is the correct attribute
24
54
  <Item selectable={'false'} {...rest}>
25
55
  {inner(
26
56
  <div className={styles.root}>
27
- <div className={styles.inner}>{children}</div>
57
+ <div className={styles.inner}>
58
+ <span className={styles.label}>{children}</span>
59
+ {hint}
60
+ </div>
28
61
  </div>
29
62
  )}
30
63
  </Item>
@@ -1,35 +1,35 @@
1
1
  .container {
2
2
  min-width: 120px;
3
- border-radius: 4px;
3
+ border-radius: var(--ds-node-radius, 4px);
4
4
 
5
- color: var(--vscode-editorWidget-foreground, var(--vscode-foreground));
6
- font-size: 0.8125rem;
7
- background-color: #2b2b2b;
5
+ color: var(--ds-widget-fg, var(--ds-fg));
6
+ font-size: var(--fs-body, 0.8125rem);
7
+ background-color: var(--ds-widget-bg, #2b2b2b);
8
8
 
9
- border: 1px solid var(--vscode-editorWidget-border, var(--vscode-input-border, rgba(128, 128, 128, 0.35)));
9
+ border: 1px solid var(--ds-border-subtle, var(--ds-input-border, rgba(128, 128, 128, 0.35)));
10
10
  box-sizing: border-box;
11
11
 
12
- --node-accent: var(--vscode-focusBorder, #0078d4);
12
+ --node-accent: var(--ds-focus-border, #0078d4);
13
13
  }
14
14
 
15
15
  .selected {
16
- box-shadow: 0 0 0 1px var(--vscode-focusBorder, #0078d4);
16
+ box-shadow: 0 0 0 1px var(--ds-focus-border, #0078d4);
17
17
  }
18
18
 
19
19
  .header {
20
20
  display: flex;
21
21
  align-items: center;
22
- min-height: 24px;
22
+ min-height: 22px;
23
23
 
24
- padding: 4px 8px;
24
+ padding: 3px 8px;
25
25
 
26
- background-color: var(--vscode-sideBarSectionHeader-background, var(--vscode-editorWidget-background, var(--vscode-editor-background)));
27
- border-bottom: 1px solid var(--vscode-editorWidget-border, var(--vscode-input-border, rgba(128, 128, 128, 0.35)));
26
+ background-color: var(--ds-section-header-bg, var(--ds-widget-bg, var(--ds-editor-bg)));
27
+ border-bottom: 1px solid var(--ds-border-subtle, var(--ds-input-border, rgba(128, 128, 128, 0.35)));
28
28
 
29
- border-top-left-radius: 4px;
30
- border-top-right-radius: 4px;
29
+ border-top-left-radius: var(--ds-node-radius, 4px);
30
+ border-top-right-radius: var(--ds-node-radius, 4px);
31
31
 
32
- border-left: 5px solid var(--node-accent);
32
+ border-left: 3px solid var(--node-accent);
33
33
  }
34
34
 
35
35
  .title {
@@ -37,7 +37,7 @@
37
37
  min-width: 0;
38
38
  font-weight: 600;
39
39
  letter-spacing: 0.01em;
40
- color: var(--vscode-foreground);
40
+ color: var(--ds-fg);
41
41
  white-space: nowrap;
42
42
  overflow: hidden;
43
43
  text-overflow: ellipsis;
@@ -48,40 +48,41 @@
48
48
  display: flex;
49
49
  align-items: center;
50
50
  gap: 4px;
51
- margin-left: 5em;
51
+ margin-left: auto;
52
+ padding-left: 8px;
52
53
  }
53
54
 
54
55
  .content {
55
56
  display: flex;
56
57
  flex-direction: column;
57
- padding-top: 6px;
58
- padding-bottom: 6px;
58
+ padding-top: 4px;
59
+ padding-bottom: 4px;
59
60
  }
60
61
 
61
62
  .red {
62
- --node-accent: #d16969;
63
+ --node-accent: var(--ds-node-red, #d16969);
63
64
  }
64
65
 
65
66
  .green {
66
- --node-accent: #89d185;
67
+ --node-accent: var(--ds-node-green, #89d185);
67
68
  }
68
69
 
69
70
  .lime {
70
- --node-accent: #b5cea8;
71
+ --node-accent: var(--ds-node-lime, #b5cea8);
71
72
  }
72
73
 
73
74
  .purple {
74
- --node-accent: #c586c0;
75
+ --node-accent: var(--ds-node-purple, #c586c0);
75
76
  }
76
77
 
77
78
  .blue {
78
- --node-accent: #4fc1ff;
79
+ --node-accent: var(--ds-node-blue, #4fc1ff);
79
80
  }
80
81
 
81
82
  .gray {
82
- --node-accent: var(--vscode-descriptionForeground, #cccccc);
83
+ --node-accent: var(--ds-fg-muted, #cccccc);
83
84
  }
84
85
 
85
86
  .white {
86
- --node-accent: var(--vscode-foreground, #cccccc);
87
+ --node-accent: var(--ds-fg, #cccccc);
87
88
  }
@@ -7,7 +7,7 @@ import {
7
7
  import { NodeResizer } from '@reactflow/node-resizer';
8
8
  import { useCallback, type ComponentType } from 'react';
9
9
  import { VscodeButton } from '@vscode-elements/react-elements';
10
- import { useSystem } from '@/system/provider';
10
+ import { useGraph } from '@/system/provider';
11
11
  import type { IGroupNode } from '@/types/nodes';
12
12
 
13
13
  const lineStyle = { borderColor: 'white' };
@@ -15,7 +15,7 @@ const padding = 25;
15
15
 
16
16
  function GroupNode(props: NodeProps<IGroupNode['data']>) {
17
17
  const { id, data } = props;
18
- const system = useSystem();
18
+ const system = useGraph();
19
19
  const { minWidth, minHeight, hasChildNodes } = useStore((store) => {
20
20
  const childNodes = Array.from(store.nodeInternals.values()).filter(
21
21
  (n) => n.parentId === id
@@ -70,7 +70,7 @@ function GroupNode(props: NodeProps<IGroupNode['data']>) {
70
70
  style={{
71
71
  width: '32px',
72
72
  height: '28px',
73
- border: '1px solid var(--vscode-input-border)',
73
+ border: '1px solid var(--ds-input-border)',
74
74
  borderRadius: '4px',
75
75
  cursor: 'pointer',
76
76
  backgroundColor: 'transparent'
@@ -1,20 +1,9 @@
1
- .collapserContainer {
2
- height: 0;
3
- overflow: hidden;
4
- }
5
-
6
- .collapserContent {
7
- position: relative;
8
- padding: var(--component-spacing-xs);
9
- padding-bottom: var(--component-spacing-md);
10
- }
11
-
12
1
  .nodeWrapper {
13
2
  position: relative;
14
3
  box-shadow: var(--shadows-contextMenu);
15
4
  border-radius: var(--component-radii-md);
16
5
  background: var(--color-neutral-canvas-default-bg);
17
- border: 2px solid var(--color-neutral-stroke-subtle);
6
+ border: 1px solid var(--color-neutral-stroke-subtle);
18
7
  flex: 1;
19
8
  display: flex;
20
9
  }
@@ -26,8 +15,8 @@
26
15
  }
27
16
 
28
17
  .nodeWrapper.executing {
29
- border-color: var(--vscode-focusBorder);
30
- box-shadow: 0 0 8px var(--vscode-focusBorder);
18
+ border-color: var(--ds-focus-border);
19
+ box-shadow: 0 0 8px var(--ds-focus-border);
31
20
  animation: pulse-border 1s ease-in-out infinite;
32
21
  }
33
22
 
@@ -37,7 +26,7 @@
37
26
 
38
27
  .nodeWrapper.pinned {
39
28
  cursor: not-allowed;
40
- border-color: var(--vscode-editorWarning-foreground);
29
+ border-color: var(--ds-warning);
41
30
  }
42
31
 
43
32
  .smallIcon {
@@ -49,18 +38,14 @@
49
38
 
50
39
  0%,
51
40
  100% {
52
- box-shadow: 0 0 8px var(--vscode-focusBorder);
41
+ box-shadow: 0 0 8px var(--ds-focus-border);
53
42
  }
54
43
 
55
44
  50% {
56
- box-shadow: 0 0 16px var(--vscode-focusBorder);
45
+ box-shadow: 0 0 16px var(--ds-focus-border);
57
46
  }
58
47
  }
59
48
 
60
- .nodeContent {
61
- flex: 1;
62
- }
63
-
64
49
  .icons {
65
50
  display: flex;
66
51
  }
@@ -100,14 +85,3 @@
100
85
  color: var(--color-neutral-canvas-minimal-fg-subtle);
101
86
  }
102
87
 
103
- .descriptionIcon {
104
- display: flex;
105
- align-items: center;
106
- color: var(--vscode-descriptionForeground);
107
- opacity: 0.7;
108
- cursor: help;
109
- }
110
-
111
- .descriptionIcon:hover {
112
- opacity: 1;
113
- }
@@ -1,13 +1,3 @@
1
- .root {
2
- display: flex;
3
- flex-direction: column;
4
- flex: 1;
5
- height: 100%;
6
- width: 100%;
7
- padding: 0.25rem;
8
- overflow: auto;
9
- }
10
-
11
1
  .content {
12
2
  display: flex;
13
3
  flex-direction: column;
@@ -14,8 +14,8 @@ import {
14
14
  CompAlignTopSolid
15
15
  } from 'iconoir-react';
16
16
  import { VscodeButton } from '@vscode-elements/react-elements';
17
- import { useSystem } from '@/system/provider';
18
- import type { System } from '@/system';
17
+ import { useActiveGraph } from '@/system/provider';
18
+ import type { GraphSession } from '@/system';
19
19
  import styles from './index.module.css';
20
20
  import { BasePanel } from '../base';
21
21
 
@@ -38,7 +38,7 @@ const partitionSelectedNodes = (nodes: Node[]) => {
38
38
  };
39
39
 
40
40
  const handleChange =
41
- (system: System) => (updater: (selectedNodes: Node[]) => void) => {
41
+ (system: GraphSession) => (updater: (selectedNodes: Node[]) => void) => {
42
42
  const { nodes, setNodes } = system.nodeStore.getState();
43
43
 
44
44
  const { selectedNodes, unselectedNodes } = partitionSelectedNodes(nodes);
@@ -130,7 +130,7 @@ export const distribute =
130
130
  };
131
131
 
132
132
  export function AlignmentPanel() {
133
- const graphEditor = useSystem();
133
+ const graphEditor = useActiveGraph()!;
134
134
  const updateNodes = handleChange(graphEditor);
135
135
 
136
136
  return (
@@ -7,6 +7,6 @@
7
7
  padding: 0.5rem;
8
8
  gap: 0.25rem;
9
9
  overflow: auto;
10
- background-color: var(--vscode-tab-inactiveBackground,#181818);
11
- color: var(--vscode-editor-foreground);
10
+ background-color: var(--ds-tab-inactive-bg,#181818);
11
+ color: var(--ds-editor-fg);
12
12
  }
@@ -0,0 +1,24 @@
1
+ .header {
2
+ display: flex;
3
+ align-items: center;
4
+ justify-content: space-between;
5
+ gap: 0.5rem;
6
+ padding: 0.25rem 0;
7
+ flex-shrink: 0;
8
+ }
9
+
10
+ .title {
11
+ font-size: var(--fs-section, 0.7rem);
12
+ font-weight: 600;
13
+ text-transform: uppercase;
14
+ letter-spacing: 0.06em;
15
+ color: var(--ds-fg);
16
+ opacity: 0.65;
17
+ }
18
+
19
+ .actions {
20
+ display: flex;
21
+ align-items: center;
22
+ gap: 4px;
23
+ flex-shrink: 0;
24
+ }
@@ -0,0 +1,22 @@
1
+ import type React from 'react';
2
+ import styles from './PanelHeader.module.css';
3
+
4
+ /**
5
+ * A panel section header row: a compact uppercase title (matching SectionTitle)
6
+ * on the left with an optional actions slot (e.g. a "+" button) on the right.
7
+ * Shared so Variables, Events and similar panels render identical chrome.
8
+ */
9
+ export const PanelHeader = ({
10
+ title,
11
+ actions
12
+ }: {
13
+ title: React.ReactNode;
14
+ actions?: React.ReactNode;
15
+ }) => {
16
+ return (
17
+ <div className={styles.header}>
18
+ <span className={styles.title}>{title}</span>
19
+ {actions ? <div className={styles.actions}>{actions}</div> : null}
20
+ </div>
21
+ );
22
+ };
@@ -0,0 +1,13 @@
1
+ .title {
2
+ font-size: var(--fs-section, 0.7rem);
3
+ font-weight: 600;
4
+ text-transform: uppercase;
5
+ letter-spacing: 0.06em;
6
+ color: var(--ds-fg);
7
+ opacity: 0.65;
8
+ margin: var(--space-3, 0.75rem) 0 var(--space-1, 0.25rem);
9
+ }
10
+
11
+ .title:first-child {
12
+ margin-top: 0;
13
+ }
@@ -0,0 +1,10 @@
1
+ import type React from 'react';
2
+ import styles from './SectionTitle.module.css';
3
+
4
+ /**
5
+ * Compact uppercase section header, shared across panels so every panel renders
6
+ * its groups with the same VSCode-settings-style chrome.
7
+ */
8
+ export const SectionTitle = ({ children }: { children: React.ReactNode }) => {
9
+ return <div className={styles.title}>{children}</div>;
10
+ };
@@ -8,7 +8,7 @@ import {
8
8
  VscodeTextfield
9
9
  } from '@vscode-elements/react-elements';
10
10
 
11
- import { useSystem } from '@/system';
11
+ import { useActiveGraph } from '@/system';
12
12
  import { BasePanel } from '../base';
13
13
  import styles from './styles.module.css';
14
14
  import type { ExtendedCustomEventJSON } from '@/store/events';
@@ -28,13 +28,13 @@ export const EditEventPanel: React.FC<EditEventPanelProps> = ({
28
28
  eventUiId,
29
29
  onBack
30
30
  }) => {
31
- const system = useSystem();
31
+ const system = useActiveGraph()!;
32
32
 
33
33
  const rawEvents = useStore(system.eventsStore, (s) => s.customEvents);
34
34
 
35
35
  const controls = useStore(system.controlStore, (s) => s.controls);
36
36
  const defaultControl = useStore(system.controlStore, (s) => s.defaultControl);
37
- const registry = useStore(system.registry);
37
+ const registry = useStore(system.editor.registry);
38
38
 
39
39
  const valueTypeOptions = useMemo(
40
40
  () => Object.keys(controls).sort((a, b) => a.localeCompare(b)),
@@ -138,8 +138,17 @@ export const EditEventPanel: React.FC<EditEventPanelProps> = ({
138
138
  if (!draftEvent) {
139
139
  return (
140
140
  <BasePanel>
141
- <div className="h-full w-full flex items-center justify-center p-4">
142
- <div className="text-gray-500 text-center">
141
+ <div
142
+ style={{
143
+ height: '100%',
144
+ width: '100%',
145
+ display: 'flex',
146
+ alignItems: 'center',
147
+ justifyContent: 'center',
148
+ padding: '16px'
149
+ }}
150
+ >
151
+ <div style={{ color: 'var(--ds-fg-muted)', textAlign: 'center' }}>
143
152
  Select an event to edit
144
153
  </div>
145
154
  </div>
@@ -7,11 +7,12 @@ import {
7
7
  } from '@vscode-elements/react-elements';
8
8
  import { Plus, Edit } from 'iconoir-react';
9
9
 
10
- import { useSystem } from '@/system';
10
+ import { useActiveGraph } from '@/system';
11
11
  import styles from './styles.module.css';
12
12
  import { BasePanel } from '../base';
13
13
  import type { GraphJSON } from '@kiberon-labs/behave-graph';
14
14
  import { Icon } from '@/components/primitives/icon';
15
+ import { PanelHeader } from '../common/PanelHeader';
15
16
 
16
17
  type CustomEventJSON = NonNullable<GraphJSON['customEvents']>[number];
17
18
 
@@ -29,7 +30,7 @@ interface ManageEventsPanelProps {
29
30
  export const ManageEventsPanel: React.FC<ManageEventsPanelProps> = ({
30
31
  onSelectEvent
31
32
  }) => {
32
- const system = useSystem();
33
+ const system = useActiveGraph()!;
33
34
  const rawEvents = useStore(system.eventsStore, (s) => s.customEvents);
34
35
 
35
36
  const persistedEvents = useMemo(() => Object.values(rawEvents), [rawEvents]);
@@ -49,12 +50,14 @@ export const ManageEventsPanel: React.FC<ManageEventsPanelProps> = ({
49
50
  return (
50
51
  <BasePanel>
51
52
  <div className={styles.root}>
52
- <div className={styles.header}>
53
- <h2 className={styles.headerTitle}>Custom Events</h2>
54
- <Icon title="New event" onClick={addNewEvent}>
55
- <Plus />
56
- </Icon>
57
- </div>
53
+ <PanelHeader
54
+ title="Custom Events"
55
+ actions={
56
+ <Icon title="New event" onClick={addNewEvent}>
57
+ <Plus />
58
+ </Icon>
59
+ }
60
+ />
58
61
  <VscodeDivider />
59
62
  <div className={styles.content}>
60
63
  {persistedEvents.length === 0 ? (