@kiberon-labs/behave-graph-flow 1.0.0 → 2.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 (314) hide show
  1. package/.fallowrc.json +16 -0
  2. package/.storybook/main.ts +32 -0
  3. package/.storybook/preview.ts +16 -0
  4. package/.storybook/styles.css +10 -0
  5. package/.storybook/vscode.css +814 -0
  6. package/.turbo/turbo-build.log +7 -0
  7. package/LICENSE +6 -0
  8. package/README.md +2 -2
  9. package/data/Polynomial.json +510 -0
  10. package/data/sequence.json +337 -0
  11. package/data/trigger-event.json +241 -0
  12. package/data/variable-change.json +210 -0
  13. package/dist/entry.css +4 -0
  14. package/dist/index.css +39 -0
  15. package/dist/index.css.map +1 -0
  16. package/dist/index.d.ts +2282 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +14873 -0
  19. package/dist/index.js.map +1 -0
  20. package/docs/notifications.md +246 -0
  21. package/docs/protocol.md +679 -0
  22. package/docs/specifics.md +191 -0
  23. package/package.json +85 -21
  24. package/postcss.config.ts +3 -4
  25. package/src/annotations/index.ts +32 -0
  26. package/src/components/FloatingToolbar/index.module.css +45 -0
  27. package/src/components/FloatingToolbar/index.tsx +256 -0
  28. package/src/components/Flow.tsx +276 -75
  29. package/src/components/contextMenus/NodePicker.module.css +274 -0
  30. package/src/components/contextMenus/NodePicker.tsx +481 -0
  31. package/src/components/contextMenus/edge.tsx +108 -0
  32. package/src/components/contextMenus/node.tsx +155 -0
  33. package/src/components/contextMenus/selection.tsx +77 -0
  34. package/src/components/controls/any/index.tsx +8 -0
  35. package/src/components/controls/boolean/index.tsx +13 -0
  36. package/src/components/controls/colorPicker/InputPopover.module.css +100 -0
  37. package/src/components/controls/colorPicker/InputPopover.tsx +31 -0
  38. package/src/components/controls/colorPicker/index.module.css +18 -0
  39. package/src/components/controls/colorPicker/index.tsx +61 -0
  40. package/src/components/controls/number/index.tsx +35 -0
  41. package/src/components/controls/string/index.tsx +16 -0
  42. package/src/components/edges/index.tsx +469 -0
  43. package/src/components/edges/offsetBezier.ts +134 -0
  44. package/src/components/hotKeys.tsx +20 -0
  45. package/src/components/layoutController/index.module.css +10 -0
  46. package/src/components/layoutController/index.tsx +117 -0
  47. package/src/components/layoutController/utils.ts +205 -0
  48. package/src/components/menubar/defaults.tsx +480 -0
  49. package/src/components/menubar/index.tsx +49 -0
  50. package/src/components/menubar/menuItem.module.css +16 -0
  51. package/src/components/menubar/menuItem.tsx +32 -0
  52. package/src/components/nodes/behave/Node.module.css +23 -0
  53. package/src/components/nodes/behave/Node.tsx +176 -0
  54. package/src/components/nodes/behave/NodeContainer.module.css +87 -0
  55. package/src/components/nodes/behave/NodeContainer.tsx +46 -0
  56. package/src/components/nodes/behave/index.tsx +14 -0
  57. package/src/components/nodes/comment/FormatToolbar.tsx +118 -0
  58. package/src/components/nodes/comment/comment.tsx +103 -0
  59. package/src/components/nodes/comment/styles.module.css +150 -0
  60. package/src/components/nodes/group/index.tsx +109 -0
  61. package/src/components/nodes/wrapper/index.tsx +73 -0
  62. package/src/components/nodes/wrapper/styles.module.css +113 -0
  63. package/src/components/notifications/NotificationProvider.tsx +81 -0
  64. package/src/components/notifications/index.ts +2 -0
  65. package/src/components/notifications/utils.ts +71 -0
  66. package/src/components/panels/alignment/index.module.css +20 -0
  67. package/src/components/panels/alignment/index.tsx +244 -0
  68. package/src/components/panels/base/index.tsx +5 -0
  69. package/src/components/panels/base/styles.module.css +12 -0
  70. package/src/components/panels/conversation/index.module.css +151 -0
  71. package/src/components/panels/conversation/index.tsx +162 -0
  72. package/src/components/panels/events/CustomEventsEditor.tsx +384 -0
  73. package/src/components/panels/events/EditEventPanel.tsx +315 -0
  74. package/src/components/panels/events/ManageEventsPanel.tsx +98 -0
  75. package/src/components/panels/events/index.tsx +23 -0
  76. package/src/components/panels/events/styles.module.css +236 -0
  77. package/src/components/panels/history/index.tsx +92 -0
  78. package/src/components/panels/history/styles.module.css +106 -0
  79. package/src/components/panels/keymaps/index.module.css +78 -0
  80. package/src/components/panels/keymaps/index.tsx +167 -0
  81. package/src/components/panels/layers/index.tsx +240 -0
  82. package/src/components/panels/layers/styles.module.css +110 -0
  83. package/src/components/panels/legend/index.module.css +6 -0
  84. package/src/components/panels/legend/index.tsx +76 -0
  85. package/src/components/panels/logs/index.module.css +212 -0
  86. package/src/components/panels/logs/index.tsx +288 -0
  87. package/src/components/panels/nodeInputs/InputControl.tsx +63 -0
  88. package/src/components/panels/nodeInputs/InputsGroup.tsx +64 -0
  89. package/src/components/panels/nodeInputs/MultipleNodesView.tsx +37 -0
  90. package/src/components/panels/nodeInputs/NodeSettings.tsx +92 -0
  91. package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +125 -0
  92. package/src/components/panels/nodeInputs/OutputsGroup.tsx +65 -0
  93. package/src/components/panels/nodeInputs/SocketGenerators.tsx +32 -0
  94. package/src/components/panels/nodeInputs/index.module.css +284 -0
  95. package/src/components/panels/nodeInputs/index.tsx +339 -0
  96. package/src/components/panels/nodeInputs/useNodeHandlers.ts +76 -0
  97. package/src/components/panels/nodeInputs/useNodeInputsData.ts +173 -0
  98. package/src/components/panels/nodePicker/index.tsx +115 -0
  99. package/src/components/panels/panel/index.module.css +66 -0
  100. package/src/components/panels/panel/index.tsx +88 -0
  101. package/src/components/panels/search/index.module.css +66 -0
  102. package/src/components/panels/search/index.tsx +215 -0
  103. package/src/components/panels/systemSettings/index.tsx +206 -0
  104. package/src/components/panels/systemSettings/styles.module.css +11 -0
  105. package/src/components/panels/traces/GridLines.tsx +38 -0
  106. package/src/components/panels/traces/TimeGrid.tsx +48 -0
  107. package/src/components/panels/traces/TraceLane.tsx +62 -0
  108. package/src/components/panels/traces/TraceTooltip.tsx +22 -0
  109. package/src/components/panels/traces/TracesHeader.tsx +56 -0
  110. package/src/components/panels/traces/index.module.css +166 -0
  111. package/src/components/panels/traces/index.tsx +294 -0
  112. package/src/components/panels/traces/types.ts +48 -0
  113. package/src/components/panels/traces/useDerivedSpans.ts +212 -0
  114. package/src/components/panels/traces/utils.ts +25 -0
  115. package/src/components/panels/variables/CreateVariableScreen.tsx +162 -0
  116. package/src/components/panels/variables/ManageVariablesScreen.tsx +144 -0
  117. package/src/components/panels/variables/index.tsx +125 -0
  118. package/src/components/panels/variables/styles.module.css +236 -0
  119. package/src/components/primitives/icon.module.css +45 -0
  120. package/src/components/primitives/icon.tsx +38 -0
  121. package/src/components/sockets/input/index.tsx +76 -0
  122. package/src/components/sockets/input/styles.module.css +27 -0
  123. package/src/components/sockets/output/index.tsx +61 -0
  124. package/src/components/sockets/output/styles.module.css +27 -0
  125. package/src/css/prosemirror.css +57 -0
  126. package/src/css/rc-dock.css +112 -0
  127. package/src/css/rc-menu.css +100 -0
  128. package/src/css/vars.css +14 -0
  129. package/src/css/vscode.css +13 -0
  130. package/src/entry.css +4 -0
  131. package/src/generators/CustomEventOnTriggeredGenerator.tsx +85 -0
  132. package/src/generators/SequenceGenerator.tsx +104 -0
  133. package/src/generators/SwitchOnIntegerGenerator.tsx +256 -0
  134. package/src/generators/SwitchOnStringGenerator.tsx +263 -0
  135. package/src/generators/registerDefaultGenerators.ts +34 -0
  136. package/src/hooks/useBehaveGraphFlow.ts +17 -16
  137. package/src/hooks/useDetachNodes.ts +39 -0
  138. package/src/hooks/useFlowHandlers.ts +115 -29
  139. package/src/hooks/useWasdPan.ts +188 -0
  140. package/src/index.css +146 -0
  141. package/src/index.ts +36 -18
  142. package/src/layout/dagre.tsx +119 -0
  143. package/src/layout/elk.ts +200 -0
  144. package/src/plugin/alignment/index.ts +81 -0
  145. package/src/plugin/docs/index.tsx +299 -0
  146. package/src/plugin/docs/panel/index.tsx +200 -0
  147. package/src/plugin/docs/panel/styles.module.css +174 -0
  148. package/src/plugin/graphrunner/actions.ts +253 -0
  149. package/src/plugin/graphrunner/buttons.tsx +87 -0
  150. package/src/plugin/graphrunner/client.ts +704 -0
  151. package/src/plugin/graphrunner/index.tsx +255 -0
  152. package/src/plugin/graphrunner/panel.tsx +386 -0
  153. package/src/plugin/graphrunner/runner.ts +358 -0
  154. package/src/plugin/graphrunner/session.ts +243 -0
  155. package/src/plugin/graphrunner/store.ts +206 -0
  156. package/src/plugin/graphrunner/styles.module.css +211 -0
  157. package/src/plugin/graphrunner/transport.ts +224 -0
  158. package/src/plugin/graphrunner/types.ts +672 -0
  159. package/src/plugin/graphrunner-local/execution-utils.ts +457 -0
  160. package/src/plugin/graphrunner-local/index.tsx +166 -0
  161. package/src/plugin/graphrunner-local/panel.tsx +231 -0
  162. package/src/plugin/graphrunner-local/store.ts +41 -0
  163. package/src/plugin/graphrunner-local/styles.module.css +101 -0
  164. package/src/plugin/graphrunner-local/transport.ts +1372 -0
  165. package/src/plugin/graphrunner-local/types.ts +10 -0
  166. package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +633 -0
  167. package/src/plugin/graphrunner-webworker/index.tsx +146 -0
  168. package/src/plugin/graphrunner-webworker/panel.tsx +173 -0
  169. package/src/plugin/graphrunner-webworker/store.ts +89 -0
  170. package/src/plugin/graphrunner-webworker/types.ts +17 -0
  171. package/src/plugin/graphrunner-webworker/worker-transport.ts +123 -0
  172. package/src/plugin/realtime/realtimeRunner.ts +570 -0
  173. package/src/specifics/CustomEventOnTriggeredSpecific.tsx +92 -0
  174. package/src/specifics/CustomEventTriggerSpecific.tsx +141 -0
  175. package/src/specifics/VariableGetSpecific.tsx +110 -0
  176. package/src/specifics/VariableSetSpecific.tsx +110 -0
  177. package/src/specifics/registerDefaultSpecifics.ts +5 -0
  178. package/src/store/actions.tsx +698 -0
  179. package/src/store/chat.ts +73 -0
  180. package/src/store/controls.tsx +62 -0
  181. package/src/store/documentation.tsx +69 -0
  182. package/src/store/events.tsx +116 -0
  183. package/src/store/flow.tsx +245 -0
  184. package/src/store/graphRunnerClient.ts +110 -0
  185. package/src/store/hotKeys.tsx +323 -0
  186. package/src/store/layers.ts +259 -0
  187. package/src/store/legend.tsx +76 -0
  188. package/src/store/logs.ts +28 -0
  189. package/src/store/menubar.ts +41 -0
  190. package/src/store/refs.ts +84 -0
  191. package/src/store/registry.ts +43 -0
  192. package/src/store/selection.ts +22 -0
  193. package/src/store/settings.ts +99 -0
  194. package/src/store/socketGenerator.tsx +54 -0
  195. package/src/store/specific.tsx +75 -0
  196. package/src/store/specs.tsx +35 -0
  197. package/src/store/tabs.ts +278 -0
  198. package/src/store/toolbar.tsx +45 -0
  199. package/src/store/traces.ts +240 -0
  200. package/src/store/variables.ts +37 -0
  201. package/src/system/graph.ts +134 -0
  202. package/src/system/index.ts +3 -0
  203. package/src/system/notifications.ts +98 -0
  204. package/src/system/plugin.ts +27 -0
  205. package/src/system/provider.tsx +22 -0
  206. package/src/system/pubsub.ts +323 -0
  207. package/src/system/system.ts +223 -0
  208. package/src/system/tabLoader.tsx +265 -0
  209. package/src/system/undoRedo.ts +103 -0
  210. package/src/transformers/Uigraph.ts +60 -0
  211. package/src/transformers/behaveToFlow.ts +16 -4
  212. package/src/transformers/flowToBehave.ts +32 -12
  213. package/src/types/NodeMetadata.ts +27 -0
  214. package/src/types/graph.ts +49 -0
  215. package/src/types/nodes.ts +45 -0
  216. package/src/types.ts +16 -0
  217. package/src/util/colors.ts +1 -29
  218. package/src/util/downloadJson.ts +18 -0
  219. package/src/util/extractNodeMetadata.ts +16 -0
  220. package/src/util/getPickerFilters.ts +1 -1
  221. package/src/util/isBehaveNode.ts +6 -0
  222. package/src/util/isValidConnection.ts +28 -15
  223. package/src/util/mergeSockets.ts +29 -0
  224. package/src/util/serializeVariables.ts +66 -0
  225. package/src/util/sockets.ts +43 -0
  226. package/stories/apex/layoutController/example-graph.worker.ts +39 -0
  227. package/stories/apex/layoutController/index.stories.tsx +48 -0
  228. package/stories/apex/layoutController/webworker.stories.tsx +103 -0
  229. package/stories/apex/menubar/menubar.stories.tsx +19 -0
  230. package/stories/components/colorpicker/index.stories.tsx +20 -0
  231. package/stories/components/contextMenus/edge.stories.tsx +32 -0
  232. package/stories/components/contextMenus/node.stories.tsx +26 -0
  233. package/stories/components/contextMenus/nodePicker.stories.tsx +115 -0
  234. package/stories/components/controls/any/index.stories.tsx +19 -0
  235. package/stories/components/controls/boolean/index.stories.tsx +19 -0
  236. package/stories/components/controls/colorPicker/index.stories.tsx +49 -0
  237. package/stories/components/controls/number/index.stories.tsx +19 -0
  238. package/stories/components/controls/string/index.stories.tsx +19 -0
  239. package/stories/components/nodes/behaveNode.stories.tsx +108 -0
  240. package/stories/components/nodes/comment.stories.tsx +106 -0
  241. package/stories/components/panels/alignment.stories.tsx +24 -0
  242. package/stories/components/panels/events.stories.tsx +38 -0
  243. package/stories/components/panels/graphRunner.stories.tsx +317 -0
  244. package/stories/components/panels/history.stories.tsx +37 -0
  245. package/stories/components/panels/keymaps.stories.tsx +21 -0
  246. package/stories/components/panels/legend.stories.tsx +37 -0
  247. package/stories/components/panels/logs.stories.tsx +24 -0
  248. package/stories/components/panels/nodeInputs.stories.tsx +21 -0
  249. package/stories/components/panels/nodePicker.stories.tsx +37 -0
  250. package/stories/components/panels/panel.stories.tsx +39 -0
  251. package/stories/components/panels/search.stories.tsx +24 -0
  252. package/stories/components/panels/systemSettings.stories.tsx +26 -0
  253. package/stories/components/panels/traces.stories.tsx +225 -0
  254. package/stories/components/panels/variables.stories.tsx +24 -0
  255. package/stories/defaults/defaultStoryProvider.tsx +167 -0
  256. package/stories/defaults/systemGenerator.ts +38 -0
  257. package/tests/components/edges/offsetBezier.test.ts +51 -0
  258. package/tests/components/layoutController/utils.test.ts +68 -0
  259. package/tests/components/panels/traces/utils.test.ts +52 -0
  260. package/tests/flowToBehave.test.ts +26 -4
  261. package/tests/notifications.test.ts +87 -0
  262. package/tests/saveLoad.test.ts +372 -0
  263. package/tests/util/calculateNewEdge.test.ts +98 -0
  264. package/tests/util/getSocketsByNodeTypeAndHandleType.test.ts +31 -0
  265. package/tests/util/hasPositionMetaData.test.ts +33 -0
  266. package/tests/util/isBehaveNode.test.ts +22 -0
  267. package/tests/util/isHandleConnected.test.ts +37 -0
  268. package/tests/util/mergeSockets.test.ts +43 -0
  269. package/tests/visual/README.md +64 -0
  270. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-alignment-chromium-win32.png +0 -0
  271. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-conversation-chromium-win32.png +0 -0
  272. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-events-chromium-win32.png +0 -0
  273. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-history-chromium-win32.png +0 -0
  274. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-keymaps-chromium-win32.png +0 -0
  275. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-layers-chromium-win32.png +0 -0
  276. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-legend-chromium-win32.png +0 -0
  277. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-logs-chromium-win32.png +0 -0
  278. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodeInputs-chromium-win32.png +0 -0
  279. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodePicker-chromium-win32.png +0 -0
  280. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-panel-chromium-win32.png +0 -0
  281. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-search-chromium-win32.png +0 -0
  282. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-systemSettings-chromium-win32.png +0 -0
  283. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-traces-chromium-win32.png +0 -0
  284. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-variables-chromium-win32.png +0 -0
  285. package/tests/visual/panels.visual.test.tsx +76 -0
  286. package/tsconfig.base.json +39 -0
  287. package/tsconfig.json +18 -59
  288. package/tsconfig.prod.json +23 -0
  289. package/tsdown.config.ts +15 -3
  290. package/typedoc.json +7 -7
  291. package/vite.config.js +7 -0
  292. package/vitest.config.ts +5 -2
  293. package/vitest.visual.config.ts +48 -0
  294. package/src/components/AutoSizeInput.tsx +0 -65
  295. package/src/components/Controls.tsx +0 -87
  296. package/src/components/InputSocket.tsx +0 -142
  297. package/src/components/Node.tsx +0 -68
  298. package/src/components/NodeContainer.tsx +0 -46
  299. package/src/components/NodePicker.tsx +0 -77
  300. package/src/components/OutputSocket.tsx +0 -58
  301. package/src/components/modals/ClearModal.tsx +0 -40
  302. package/src/components/modals/HelpModal.tsx +0 -36
  303. package/src/components/modals/LoadModal.tsx +0 -96
  304. package/src/components/modals/Modal.tsx +0 -64
  305. package/src/components/modals/SaveModal.tsx +0 -60
  306. package/src/hooks/useCustomNodeTypes.tsx +0 -31
  307. package/src/hooks/useGraphRunner.ts +0 -104
  308. package/src/hooks/useMergeMap.ts +0 -14
  309. package/src/hooks/useNodeSpecJson.ts +0 -20
  310. package/src/hooks/useQueriableDefinitions.ts +0 -22
  311. package/src/styles.css +0 -8
  312. package/tailwind.config.ts +0 -19
  313. package/tests/tsconfig.json +0 -10
  314. /package/src/{types.d.ts → types-declarations.d.ts} +0 -0
@@ -1,37 +1,112 @@
1
- import type { GraphJSON, IRegistry } from '@kiberon-labs/behave-graph';
2
- import React from 'react';
3
- import { Background, BackgroundVariant, ReactFlow } from 'reactflow';
1
+ import React, {
2
+ useCallback,
3
+ useEffect,
4
+ useMemo,
5
+ useRef,
6
+ useState
7
+ } from 'react';
8
+ import {
9
+ Background,
10
+ BackgroundVariant,
11
+ type Edge as ReactFlowEdge,
12
+ MiniMap,
13
+ ReactFlow,
14
+ type Node as ReactFlowNode,
15
+ type ReactFlowInstance
16
+ } from 'reactflow';
4
17
 
5
18
  import { useBehaveGraphFlow } from '../hooks/useBehaveGraphFlow.js';
6
19
  import { useFlowHandlers } from '../hooks/useFlowHandlers.js';
7
- import { useGraphRunner } from '../hooks/useGraphRunner.js';
8
- import { useNodeSpecJson } from '../hooks/useNodeSpecJson.js';
9
- import CustomControls from './Controls.js';
10
- import { type Examples } from './modals/LoadModal.js';
11
- import { NodePicker } from './NodePicker.js';
12
-
13
- type FlowProps = {
14
- initialGraph: GraphJSON;
15
- registry: IRegistry;
16
- examples: Examples;
20
+ import { useWasdPan } from '../hooks/useWasdPan.js';
21
+ import { useSystem } from '@/system/provider.js';
22
+ import { useStore } from 'zustand';
23
+ import {
24
+ NodeContextMenu,
25
+ type INodeContextMenuProps
26
+ } from './contextMenus/node.js';
27
+ import {
28
+ EdgeContextMenu,
29
+ type IEdgeContextMenuProps
30
+ } from './contextMenus/edge.js';
31
+ import {
32
+ SelectionContextMenu,
33
+ type ISelectionContextMenuProps
34
+ } from './contextMenus/selection.js';
35
+ import { registerDefaultSocketGenerators } from '@/generators/registerDefaultGenerators';
36
+ import { FloatingToolbar } from './FloatingToolbar';
37
+ import { layerId } from '@/annotations';
38
+
39
+ const REACTFLOW_NODE = 'react-flow__node';
40
+
41
+ const getAnnotatedLayerId = (node: ReactFlowNode): string | undefined => {
42
+ if (!node.data || typeof node.data !== 'object') return undefined;
43
+ const record = node.data as { annotations?: Record<string, unknown> };
44
+ const value = record.annotations?.[layerId];
45
+ return typeof value === 'string' ? value : undefined;
17
46
  };
18
47
 
19
- export const Flow: React.FC<FlowProps> = ({
20
- initialGraph: graph,
21
- registry,
22
- examples
23
- }) => {
24
- const specJson = useNodeSpecJson(registry);
48
+ const isNodeVisibleInLayers = (
49
+ node: ReactFlowNode,
50
+ params: {
51
+ layers: Record<string, { visible: boolean }>;
52
+ nodeLayers: Record<string, string>;
53
+ defaultLayerId: string;
54
+ }
55
+ ): boolean => {
56
+ const mappedLayerId =
57
+ params.nodeLayers[node.id] ??
58
+ getAnnotatedLayerId(node) ??
59
+ params.defaultLayerId;
60
+ const layer =
61
+ params.layers[mappedLayerId] ?? params.layers[params.defaultLayerId];
62
+ return layer?.visible !== false;
63
+ };
25
64
 
26
- const {
27
- nodes,
28
- edges,
29
- onNodesChange,
30
- onEdgesChange,
31
- graphJson,
32
- setGraphJson,
33
- nodeTypes
34
- } = useBehaveGraphFlow({
65
+ export const Flow: React.FC = () => {
66
+ const system = useSystem();
67
+ const getGraphJson = useStore(system.flowStore, (x) => x.getGraph);
68
+ const specJson = useStore(system.specStore, (x) => x.specs);
69
+ const showGrid = useStore(system.systemSettings, (x) => x.showGrid);
70
+ const showMinimap = useStore(system.systemSettings, (x) => x.showMinimap);
71
+ const snapToGrid = useStore(system.systemSettings, (x) => x.snapGrid);
72
+ const gridSize = useStore(system.systemSettings, (x) => x.gridSize);
73
+ const edgeTypes = useStore(system.flowStore, (x) => x.edgeTypes);
74
+ const nodeTypes = useStore(system.flowStore, (x) => x.nodeTypes);
75
+ const layers = useStore(system.layerStore, (x) => x.layers);
76
+ const nodeLayers = useStore(system.layerStore, (x) => x.nodeLayers);
77
+ const defaultLayerId = useStore(system.layerStore, (x) => x.defaultLayerId);
78
+
79
+ const ref = useRef<HTMLDivElement>(null);
80
+ const setRef = useStore(system.refStore, (x) => x.setRef);
81
+
82
+ const getReactFlowInstance = useCallback(
83
+ () => system.refStore.getState().getRef('reactflow'),
84
+ [system.refStore]
85
+ );
86
+
87
+ useWasdPan({ getReactFlowInstance });
88
+
89
+ // Set reactflow ref
90
+ const setReactflowRef = React.useCallback(
91
+ (reactFlowInstance: ReactFlowInstance) => {
92
+ if (reactFlowInstance) {
93
+ setRef('reactflow', reactFlowInstance);
94
+ }
95
+ },
96
+ [setRef]
97
+ );
98
+
99
+ const graph = useMemo(() => getGraphJson(), []);
100
+
101
+ useEffect(() => {
102
+ const cleanupGenerators = registerDefaultSocketGenerators(system);
103
+
104
+ return () => {
105
+ cleanupGenerators();
106
+ };
107
+ }, [system]);
108
+
109
+ const { nodes, edges, onNodesChange, onEdgesChange } = useBehaveGraphFlow({
35
110
  initialGraphJson: graph,
36
111
  specJson
37
112
  });
@@ -41,11 +116,7 @@ export const Flow: React.FC<FlowProps> = ({
41
116
  handleStartConnect,
42
117
  handleStopConnect,
43
118
  handlePaneClick,
44
- handlePaneContextMenu,
45
- nodePickerVisibility,
46
- handleAddNode,
47
- closeNodePicker,
48
- nodePickFilters
119
+ handlePaneContextMenu
49
120
  } = useFlowHandlers({
50
121
  nodes,
51
122
  onEdgesChange,
@@ -53,49 +124,179 @@ export const Flow: React.FC<FlowProps> = ({
53
124
  specJSON: specJson
54
125
  });
55
126
 
56
- const { togglePlay, playing } = useGraphRunner({
57
- graphJson,
58
- registry
59
- });
127
+ const [menu, setMenu] = useState<INodeContextMenuProps | null>(null);
128
+ const [edgeMenu, setEdgeMenu] = useState<IEdgeContextMenuProps | null>(null);
129
+ const [selectionMenu, setSelectionMenu] =
130
+ useState<ISelectionContextMenuProps | null>(null);
131
+ const onNodeContextMenu = useCallback(
132
+ (event: React.MouseEvent<Element, MouseEvent>) => {
133
+ // Prevent native context menu from showing
134
+ event.preventDefault();
135
+ setEdgeMenu(null);
136
+ setSelectionMenu(null);
137
+ const offset = ref.current?.getBoundingClientRect();
138
+ //Keep ascending till we find the .react-flow__node
139
+ let target = event.target as HTMLElement | null;
140
+ let nodeID = null;
141
+ while (target && !target.classList.contains(REACTFLOW_NODE)) {
142
+ target = target.parentElement;
143
+ }
144
+ if (target) {
145
+ nodeID = target.getAttribute('data-id');
146
+ }
147
+ setMenu({
148
+ //We should be safe here as reactflow only triggers this on nodes
149
+ nodeID: nodeID!,
150
+ top: event.clientY - (offset?.top ?? 0),
151
+ left: event.clientX - (offset?.left ?? 0)
152
+ });
153
+ },
154
+ [setMenu, setEdgeMenu]
155
+ );
156
+
157
+ const onEdgeContextMenu = useCallback(
158
+ (event: React.MouseEvent, edge: any) => {
159
+ event.preventDefault();
160
+ event.stopPropagation();
161
+ setMenu(null);
162
+ setSelectionMenu(null);
163
+ const offset = ref.current?.getBoundingClientRect();
164
+ setEdgeMenu({
165
+ edgeID: edge.id,
166
+ sourceID: edge.source,
167
+ targetID: edge.target,
168
+ top: event.clientY - (offset?.top ?? 0),
169
+ left: event.clientX - (offset?.left ?? 0)
170
+ });
171
+ },
172
+ [setEdgeMenu, setMenu]
173
+ );
174
+
175
+ const onSelectionContextMenu = useCallback(
176
+ (event: React.MouseEvent) => {
177
+ event.preventDefault();
178
+ event.stopPropagation();
179
+ setMenu(null);
180
+ setEdgeMenu(null);
181
+ const offset = ref.current?.getBoundingClientRect();
182
+ setSelectionMenu({
183
+ top: event.clientY - (offset?.top ?? 0),
184
+ left: event.clientX - (offset?.left ?? 0)
185
+ });
186
+ },
187
+ [setMenu, setEdgeMenu, setSelectionMenu]
188
+ );
189
+
190
+ const snapGrid = useMemo(() => {
191
+ return [gridSize, gridSize] as [number, number];
192
+ }, [gridSize]);
193
+
194
+ const onPaneClick = useCallback(() => {
195
+ setMenu(null);
196
+ setEdgeMenu(null);
197
+ setSelectionMenu(null);
198
+ handlePaneClick();
199
+ }, [setMenu, setEdgeMenu, setSelectionMenu, handlePaneClick]);
200
+
201
+ const renderedNodes = useMemo(() => {
202
+ return nodes.map((node) => {
203
+ const mappedLayerId =
204
+ nodeLayers[node.id] ?? getAnnotatedLayerId(node) ?? defaultLayerId;
205
+ const layer = layers[mappedLayerId] ?? layers[defaultLayerId];
206
+ if (!layer) return node;
207
+
208
+ return {
209
+ ...node,
210
+ hidden: !layer.visible,
211
+ style: {
212
+ ...(node.style ?? {}),
213
+ opacity: layer.opacity
214
+ }
215
+ };
216
+ });
217
+ }, [defaultLayerId, layers, nodeLayers, nodes]);
218
+
219
+ const renderedEdges = useMemo(() => {
220
+ const nodesById = new Map<string, ReactFlowNode>();
221
+ nodes.forEach((node) => {
222
+ nodesById.set(node.id, node);
223
+ });
224
+
225
+ return edges.map((edge: ReactFlowEdge) => {
226
+ const sourceNode = nodesById.get(edge.source);
227
+ const targetNode = nodesById.get(edge.target);
228
+
229
+ // If either endpoint is missing just leave the edge as-is
230
+ if (!sourceNode || !targetNode) return edge;
231
+
232
+ const sourceVisible = isNodeVisibleInLayers(sourceNode, {
233
+ layers,
234
+ nodeLayers,
235
+ defaultLayerId
236
+ });
237
+ const targetVisible = isNodeVisibleInLayers(targetNode, {
238
+ layers,
239
+ nodeLayers,
240
+ defaultLayerId
241
+ });
242
+
243
+ const shouldHide = !sourceVisible || !targetVisible;
244
+
245
+ // Return as hidden when an endpoint node is in a hidden layer.
246
+ // Using `hidden` rather than filtering so ReactFlow still tracks the
247
+ // connection and handles continue to render as connected.
248
+ if (shouldHide === edge.hidden) return edge;
249
+ return { ...edge, hidden: shouldHide };
250
+ });
251
+ }, [defaultLayerId, edges, layers, nodeLayers, nodes]);
60
252
 
61
253
  return (
62
- <ReactFlow
63
- nodeTypes={nodeTypes}
64
- nodes={nodes}
65
- edges={edges}
66
- onNodesChange={onNodesChange}
67
- onEdgesChange={onEdgesChange}
68
- onConnect={onConnect}
69
- // @ts-ignore
70
- onConnectStart={handleStartConnect}
71
- // @ts-ignore
72
- onConnectEnd={handleStopConnect}
73
- fitView
74
- fitViewOptions={{ maxZoom: 1 }}
75
- onPaneClick={handlePaneClick}
76
- onPaneContextMenu={handlePaneContextMenu}
77
- >
78
- <CustomControls
79
- playing={playing}
80
- togglePlay={togglePlay}
81
- setBehaviorGraph={setGraphJson}
82
- examples={examples}
83
- specJson={specJson}
84
- />
85
- <Background
86
- variant={BackgroundVariant.Lines}
87
- color="#2a2b2d"
88
- style={{ backgroundColor: '#1E1F22' }}
89
- />
90
- {nodePickerVisibility && (
91
- <NodePicker
92
- position={nodePickerVisibility}
93
- filters={nodePickFilters}
94
- onPickNode={handleAddNode}
95
- onClose={closeNodePicker}
96
- specJSON={specJson}
97
- />
98
- )}
99
- </ReactFlow>
254
+ <>
255
+ <ReactFlow
256
+ style={{ flex: 1 }}
257
+ ref={ref}
258
+ onInit={setReactflowRef}
259
+ nodeTypes={nodeTypes}
260
+ edgeTypes={edgeTypes}
261
+ elevateEdgesOnSelect={true}
262
+ nodes={renderedNodes}
263
+ edges={renderedEdges}
264
+ onSelectionContextMenu={onSelectionContextMenu}
265
+ onNodeContextMenu={onNodeContextMenu}
266
+ // @ts-ignore
267
+ onEdgeContextMenu={onEdgeContextMenu}
268
+ maxZoom={Infinity}
269
+ minZoom={-Infinity}
270
+ onNodesChange={onNodesChange}
271
+ onEdgesChange={onEdgesChange}
272
+ onConnect={onConnect}
273
+ // @ts-ignore
274
+ onConnectStart={handleStartConnect}
275
+ // @ts-ignore
276
+ onConnectEnd={handleStopConnect}
277
+ snapToGrid={snapToGrid}
278
+ snapGrid={snapGrid}
279
+ fitView
280
+ //TODO. Reconsier this prop for performance
281
+ onlyRenderVisibleElements={true}
282
+ onPaneClick={onPaneClick}
283
+ onPaneContextMenu={handlePaneContextMenu}
284
+ proOptions={{ hideAttribution: true }}
285
+ >
286
+ {showGrid && (
287
+ <Background
288
+ variant={BackgroundVariant.Lines}
289
+ gap={90}
290
+ color="#373737"
291
+ style={{ backgroundColor: 'var(--colors-bgCanvas)' }}
292
+ />
293
+ )}
294
+ {showMinimap && <MiniMap />}
295
+ {menu && <NodeContextMenu {...menu} />}
296
+ {edgeMenu && <EdgeContextMenu {...edgeMenu} />}
297
+ {selectionMenu && <SelectionContextMenu {...selectionMenu} />}
298
+ <FloatingToolbar />
299
+ </ReactFlow>
300
+ </>
100
301
  );
101
302
  };
@@ -0,0 +1,274 @@
1
+ .container {
2
+ position: relative;
3
+ width: 100%;
4
+ height: 100%;
5
+ display: flex;
6
+ flex-direction: column;
7
+ color: var(--colors-fg);
8
+ background: var(--colors-bgCanvas);
9
+ overflow: hidden;
10
+ }
11
+
12
+ .grid {
13
+ display: flex;
14
+ overflow: auto;
15
+ flex: 1
16
+ }
17
+
18
+ .sidebar {
19
+ border-right: 1px solid var(--vscode-input-border, var(--colors-borderSubtle));
20
+ background: var(--colors-bgPanel);
21
+ display: flex;
22
+ flex-direction: column;
23
+ width: 100px;
24
+ }
25
+
26
+
27
+ .sidebarList {
28
+ overflow: auto;
29
+ padding: 0.25rem;
30
+ }
31
+
32
+ .sidebarItem {
33
+ display: flex;
34
+ align-items: center;
35
+ gap: 0.5rem;
36
+ padding: 0.15rem 0.5rem;
37
+ border-radius: 0.25rem;
38
+ cursor: pointer;
39
+ user-select: none;
40
+ font-size: 0.8em;
41
+ }
42
+
43
+ .sidebarItem:hover {
44
+ background: var(--vscode-button-hoverBackground, #026ec1);
45
+ }
46
+
47
+ .sidebarItemActive {
48
+ background: var(--vscode-button-secondaryBackground, #313131);
49
+ color: var(--vscode-list-activeSelectionForeground);
50
+ }
51
+
52
+ .main {
53
+ display: flex;
54
+ flex: 1;
55
+ flex-direction: column;
56
+ min-width: 0;
57
+ }
58
+
59
+ .topbar {
60
+ display: flex;
61
+ align-items: center;
62
+ gap: 0.5rem;
63
+ padding: 0.5rem;
64
+ border-bottom: 1px solid var(--vscode-input-border, var(--colors-borderSubtle));
65
+ }
66
+
67
+ .search {
68
+ flex: 1;
69
+ display: flex;
70
+ min-width: 0;
71
+ }
72
+
73
+ .viewToggles {
74
+ display: flex;
75
+ gap: 0.25rem;
76
+ }
77
+
78
+ .content {
79
+ padding: 0.25rem 0.5rem;
80
+ flex: 1;
81
+ overflow-y: scroll;
82
+ }
83
+
84
+ .groupTitle {
85
+ padding: 0.25rem 0.25rem;
86
+ font-weight: 600;
87
+ opacity: 0.9;
88
+ }
89
+
90
+ .list {
91
+ display: flex;
92
+ flex-direction: column;
93
+ gap: 0.25rem;
94
+ }
95
+
96
+ .nodeRow {
97
+ display: grid;
98
+ grid-template-columns: 28px 1fr auto;
99
+ gap: 0.25rem;
100
+ align-items: center;
101
+ padding: 0.15rem 0.5rem;
102
+ border-radius: 0.25rem;
103
+ cursor: pointer;
104
+ }
105
+
106
+ .gridView {
107
+ display: grid;
108
+ grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
109
+ gap: 0.5rem;
110
+ }
111
+
112
+ .nodeRow:hover {
113
+ background: var(--vscode-button-hoverBackground, #026ec1);
114
+ }
115
+
116
+ .infoButton {
117
+ opacity: 0;
118
+ transition: opacity 0.2s;
119
+ padding: 0.25rem;
120
+ display: flex;
121
+ align-items: center;
122
+ justify-content: center;
123
+ cursor: pointer;
124
+ border-radius: 0.25rem;
125
+ background: transparent;
126
+ border: none;
127
+ color: var(--colors-fg);
128
+ }
129
+
130
+ .infoButton:hover {
131
+ background: var(--vscode-button-secondaryBackground, #313131);
132
+ opacity: 1 !important;
133
+ }
134
+
135
+ .nodeRow:hover .infoButton {
136
+ opacity: 0.7;
137
+ }
138
+
139
+ .infoButton svg {
140
+ width: 16px;
141
+ height: 16px;
142
+ }
143
+
144
+ .thumb {
145
+ width: 28px;
146
+ height: 28px;
147
+ border-radius: 0.25rem;
148
+ border: 1px solid var(--vscode-input-border, var(--colors-borderSubtle));
149
+ background: var(--colors-bgCanvas);
150
+ overflow: hidden;
151
+ display: flex;
152
+ align-items: center;
153
+ justify-content: center;
154
+ flex: 0 0 auto;
155
+ }
156
+
157
+ .thumb img {
158
+ width: 100%;
159
+ height: 100%;
160
+ object-fit: cover;
161
+ }
162
+
163
+ .icon {
164
+ width: 100%;
165
+ height: 100%;
166
+ display: flex;
167
+ align-items: center;
168
+ justify-content: center;
169
+ }
170
+
171
+ .icon svg {
172
+ width: 100%;
173
+ height: 100%;
174
+ }
175
+
176
+ .nodeText {
177
+ min-width: 0;
178
+ display: flex;
179
+ flex-direction: column;
180
+ }
181
+
182
+ .nodeTitle {
183
+ font-size: 0.9rem;
184
+ line-height: 1.2rem;
185
+ white-space: nowrap;
186
+ overflow: hidden;
187
+ text-overflow: ellipsis;
188
+ }
189
+
190
+ .gridView .nodeTitle {
191
+ font-size: 0.75rem;
192
+ }
193
+
194
+ .nodeSub {
195
+ font-size: 0.75rem;
196
+ opacity: 0.75;
197
+ white-space: nowrap;
198
+ overflow: hidden;
199
+ text-overflow: ellipsis;
200
+ }
201
+
202
+ .tags {
203
+ display: flex;
204
+ flex-wrap: wrap;
205
+ gap: 0.25rem;
206
+ margin-top: 0.25rem;
207
+ }
208
+
209
+ .tag {
210
+ font-size: 0.65rem;
211
+ padding: 0.1rem 0.35rem;
212
+ border-radius: 0.25rem;
213
+ background: var(--vscode-badge-background, #4d4d4d);
214
+ color: var(--vscode-badge-foreground, #ffffff);
215
+ opacity: 0.85;
216
+ }
217
+
218
+ .card {
219
+ border-radius: 0.25rem;
220
+ cursor: pointer;
221
+ overflow: hidden;
222
+ background: var(--colors-bgCanvas);
223
+ }
224
+
225
+ .card:hover {
226
+ background: var(--vscode-button-hoverBackground, #026ec1);
227
+ }
228
+
229
+ .cardInner {
230
+ display: grid;
231
+ grid-template-columns: 56px 1fr;
232
+ gap: 0.15rem;
233
+ padding: 0.5rem;
234
+ align-items: center;
235
+ }
236
+
237
+ .gridView .cardInner {
238
+ grid-template-columns: 1fr;
239
+ text-align: center;
240
+ display: flex;
241
+ flex-direction: column;
242
+ }
243
+
244
+ .cardThumb {
245
+ width: 56px;
246
+ height: 56px;
247
+ border-radius: 0.25rem;
248
+ border: 1px solid var(--vscode-input-border, var(--colors-borderSubtle));
249
+ overflow: hidden;
250
+ display: flex;
251
+ align-items: center;
252
+ justify-content: center;
253
+ }
254
+
255
+ .cardThumb img {
256
+ width: 100%;
257
+ height: 100%;
258
+ object-fit: cover;
259
+ }
260
+
261
+ .footer {
262
+ padding: 0.35rem 0.5rem;
263
+ border-top: 1px solid var(--vscode-input-border, var(--colors-borderSubtle));
264
+ font-size: 0.75rem;
265
+ opacity: 0.8;
266
+ display: flex;
267
+ justify-content: space-between;
268
+ gap: 0.5rem;
269
+ }
270
+
271
+ .empty {
272
+ padding: 1rem;
273
+ opacity: 0.8;
274
+ }