@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,142 +0,0 @@
1
- import type {
2
- InputSocketSpecJSON,
3
- NodeSpecJSON
4
- } from '@kiberon-labs/behave-graph';
5
- import { faCaretRight } from '@fortawesome/free-solid-svg-icons';
6
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
7
- import cx from 'classnames';
8
- import React from 'react';
9
- import { type Connection, Handle, Position, useReactFlow } from 'reactflow';
10
-
11
- import { colors, valueTypeColorMap } from '../util/colors.js';
12
- import { isValidConnection } from '../util/isValidConnection.js';
13
- import { AutoSizeInput } from './AutoSizeInput.js';
14
-
15
- export type InputSocketProps = {
16
- connected: boolean;
17
- value: any | undefined;
18
- onChange: (key: string, value: any) => void;
19
- specJSON: NodeSpecJSON[];
20
- } & InputSocketSpecJSON;
21
-
22
- const InputFieldForValue = ({
23
- choices,
24
- value,
25
- defaultValue,
26
- onChange,
27
- name,
28
- valueType
29
- }: Pick<
30
- InputSocketProps,
31
- 'choices' | 'value' | 'defaultValue' | 'name' | 'onChange' | 'valueType'
32
- >) => {
33
- const showChoices = choices?.length;
34
- //Stops 'undefined'
35
- const defaultSafeValue =
36
- defaultValue !== undefined ? String(defaultValue) : '';
37
- const inputVal = value !== undefined ? String(value) : defaultSafeValue;
38
-
39
- if (showChoices)
40
- return (
41
- <select
42
- className="bg-gray-600 disabled:bg-gray-700 py-1 px-2 nodrag"
43
- value={value ?? defaultValue ?? ''}
44
- onChange={(e) => onChange(name, e.currentTarget.value)}
45
- >
46
- <>
47
- {choices.map((choice) => (
48
- <option key={choice.text} value={choice.value}>
49
- {choice.text}
50
- </option>
51
- ))}
52
- </>
53
- </select>
54
- );
55
-
56
- return (
57
- <>
58
- {valueType === 'string' && (
59
- <AutoSizeInput
60
- type="text"
61
- className="bg-gray-600 disabled:bg-gray-700 py-1 px-2 nodrag"
62
- value={inputVal}
63
- onChange={(e) => onChange(name, e.currentTarget.value)}
64
- />
65
- )}
66
- {valueType === 'number' && (
67
- <AutoSizeInput
68
- type="number"
69
- className=" bg-gray-600 disabled:bg-gray-700 py-1 px-2 nodrag"
70
- value={inputVal}
71
- onChange={(e) => onChange(name, e.currentTarget.value)}
72
- />
73
- )}
74
- {valueType === 'float' && (
75
- <AutoSizeInput
76
- type="number"
77
- className=" bg-gray-600 disabled:bg-gray-700 py-1 px-2 nodrag"
78
- value={inputVal}
79
- onChange={(e) => onChange(name, e.currentTarget.value)}
80
- />
81
- )}
82
- {valueType === 'integer' && (
83
- <AutoSizeInput
84
- type="number"
85
- className=" bg-gray-600 disabled:bg-gray-700 py-1 px-2 nodrag"
86
- value={inputVal}
87
- onChange={(e) => onChange(name, e.currentTarget.value)}
88
- />
89
- )}
90
- {valueType === 'boolean' && (
91
- <input
92
- type="checkbox"
93
- className=" bg-gray-600 disabled:bg-gray-700 py-1 px-2 nodrag"
94
- value={inputVal}
95
- onChange={(e) => onChange(name, e.currentTarget.checked)}
96
- />
97
- )}
98
- </>
99
- );
100
- };
101
-
102
- const InputSocket: React.FC<InputSocketProps> = ({
103
- connected,
104
- specJSON,
105
- ...rest
106
- }) => {
107
- const { name, valueType } = rest;
108
- const instance = useReactFlow();
109
-
110
- const isFlowSocket = valueType === 'flow';
111
-
112
- let colorName = valueTypeColorMap[valueType];
113
- if (colorName === undefined) {
114
- colorName = 'red';
115
- }
116
-
117
- // @ts-ignore
118
- const [backgroundColor, borderColor] = colors[colorName];
119
- const showName = isFlowSocket === false || name !== 'flow';
120
-
121
- return (
122
- <div className="flex grow items-center justify-start h-7">
123
- {isFlowSocket && (
124
- <FontAwesomeIcon icon={faCaretRight} color="#ffffff" size="lg" />
125
- )}
126
- {showName && <div className="capitalize mr-2">{name}</div>}
127
-
128
- {!isFlowSocket && !connected && <InputFieldForValue {...rest} />}
129
- <Handle
130
- id={name}
131
- type="target"
132
- position={Position.Left}
133
- className={cx(borderColor, connected ? backgroundColor : 'bg-gray-800')}
134
- isValidConnection={(connection: Connection) =>
135
- isValidConnection(connection, instance, specJSON)
136
- }
137
- />
138
- </div>
139
- );
140
- };
141
-
142
- export default InputSocket;
@@ -1,68 +0,0 @@
1
- import type { NodeSpecJSON } from '@kiberon-labs/behave-graph';
2
- import React from 'react';
3
- import { useEdges, type NodeProps as FlowNodeProps } from 'reactflow';
4
-
5
- import { useChangeNodeData } from '../hooks/useChangeNodeData.js';
6
- import { isHandleConnected } from '../util/isHandleConnected.js';
7
- import InputSocket from './InputSocket.js';
8
- import NodeContainer from './NodeContainer.js';
9
- import OutputSocket from './OutputSocket.js';
10
-
11
- type NodeProps = FlowNodeProps & {
12
- spec: NodeSpecJSON;
13
- allSpecs: NodeSpecJSON[];
14
- };
15
-
16
- const getPairs = <T, U>(arr1: T[], arr2: U[]) => {
17
- const max = Math.max(arr1.length, arr2.length);
18
- const pairs = [];
19
- for (let i = 0; i < max; i++) {
20
- const pair: [T | undefined, U | undefined] = [arr1[i], arr2[i]];
21
- pairs.push(pair);
22
- }
23
- return pairs;
24
- };
25
-
26
- export const Node: React.FC<NodeProps> = ({
27
- id,
28
- data,
29
- spec,
30
- selected,
31
- allSpecs
32
- }: NodeProps) => {
33
- const edges = useEdges();
34
- const handleChange = useChangeNodeData(id);
35
- const pairs = getPairs(spec.inputs, spec.outputs);
36
- return (
37
- <NodeContainer
38
- title={spec.label}
39
- category={spec.category}
40
- selected={selected}
41
- >
42
- {pairs.map(([input, output], ix) => (
43
- <div
44
- key={ix}
45
- className="flex flex-row justify-between gap-8 relative px-2"
46
- // className={styles.container}
47
- >
48
- {input && (
49
- <InputSocket
50
- {...input}
51
- specJSON={allSpecs}
52
- value={data[input.name] ?? input.defaultValue}
53
- onChange={handleChange}
54
- connected={isHandleConnected(edges, id, input.name, 'target')}
55
- />
56
- )}
57
- {output && (
58
- <OutputSocket
59
- {...output}
60
- specJSON={allSpecs}
61
- connected={isHandleConnected(edges, id, output.name, 'source')}
62
- />
63
- )}
64
- </div>
65
- ))}
66
- </NodeContainer>
67
- );
68
- };
@@ -1,46 +0,0 @@
1
- import { NodeCategory, type NodeSpecJSON } from '@kiberon-labs/behave-graph';
2
- import cx from 'classnames';
3
- import React, { type PropsWithChildren } from 'react';
4
-
5
- import { categoryColorMap, colors } from '../util/colors.js';
6
-
7
- type NodeProps = {
8
- title: string;
9
- category?: NodeSpecJSON['category'];
10
- selected: boolean;
11
- };
12
-
13
- const NodeContainer: React.FC<PropsWithChildren<NodeProps>> = ({
14
- title,
15
- category = NodeCategory.None,
16
- selected,
17
- children
18
- }) => {
19
- let colorName = categoryColorMap[category];
20
- if (colorName === undefined) {
21
- colorName = 'red';
22
- }
23
- let [backgroundColor, borderColor, textColor] = colors[colorName];
24
- if (selected) {
25
- borderColor = 'border-gray-800';
26
- }
27
- return (
28
- <div
29
- className={cx(
30
- 'rounded text-white text-sm bg-gray-800 min-w-[120px]',
31
- selected && 'outline outline-1'
32
- )}
33
- >
34
- <div className={`${backgroundColor} ${textColor} px-2 py-1 rounded-t`}>
35
- {title}
36
- </div>
37
- <div
38
- className={`flex flex-col gap-2 py-2 border-l border-r border-b ${borderColor} `}
39
- >
40
- {children}
41
- </div>
42
- </div>
43
- );
44
- };
45
-
46
- export default NodeContainer;
@@ -1,77 +0,0 @@
1
- import { type NodeSpecJSON } from '@kiberon-labs/behave-graph';
2
- import React, { useState } from 'react';
3
- import { useReactFlow, type XYPosition } from 'reactflow';
4
-
5
- import { useOnPressKey } from '../hooks/useOnPressKey.js';
6
-
7
- export type NodePickerFilters = {
8
- handleType: 'source' | 'target';
9
- valueType: string;
10
- };
11
-
12
- type NodePickerProps = {
13
- position: XYPosition;
14
- filters?: NodePickerFilters;
15
- onPickNode: (type: string, position: XYPosition) => void;
16
- onClose: () => void;
17
- specJSON: NodeSpecJSON[] | undefined;
18
- };
19
-
20
- export const NodePicker: React.FC<NodePickerProps> = ({
21
- position,
22
- onPickNode,
23
- onClose,
24
- filters,
25
- specJSON
26
- }: NodePickerProps) => {
27
- const [search, setSearch] = useState('');
28
- const instance = useReactFlow();
29
-
30
- useOnPressKey('Escape', onClose);
31
-
32
- if (!specJSON) return null;
33
- let filtered = specJSON;
34
- if (filters !== undefined) {
35
- filtered = filtered?.filter((node) => {
36
- const sockets =
37
- filters?.handleType === 'source' ? node.outputs : node.inputs;
38
- return sockets.some((socket) => socket.valueType === filters?.valueType);
39
- });
40
- }
41
-
42
- filtered =
43
- filtered?.filter((node) => {
44
- const term = search.toLowerCase();
45
- return node.type.toLowerCase().includes(term);
46
- }) || [];
47
-
48
- return (
49
- <div
50
- className="node-picker absolute z-10 text-sm text-white bg-gray-800 border rounded border-gray-500"
51
- style={{ top: position.y, left: position.x }}
52
- >
53
- <div className="bg-gray-500 p-2">Add Node</div>
54
- <div className="p-2">
55
- <input
56
- type="text"
57
- autoFocus
58
- placeholder="Type to filter"
59
- className=" bg-gray-600 disabled:bg-gray-700 w-full py-1 px-2"
60
- value={search}
61
- onChange={(e) => setSearch(e.target.value)}
62
- />
63
- </div>
64
- <div className="max-h-48 overflow-y-scroll">
65
- {filtered.map(({ type }) => (
66
- <div
67
- key={type}
68
- className="p-2 cursor-pointer border-b border-gray-600"
69
- onClick={() => onPickNode(type, instance.project(position))}
70
- >
71
- {type}
72
- </div>
73
- ))}
74
- </div>
75
- </div>
76
- );
77
- };
@@ -1,58 +0,0 @@
1
- import type {
2
- NodeSpecJSON,
3
- OutputSocketSpecJSON
4
- } from '@kiberon-labs/behave-graph';
5
- import { faCaretRight } from '@fortawesome/free-solid-svg-icons';
6
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
7
- import cx from 'classnames';
8
- import React from 'react';
9
- import { type Connection, Handle, Position, useReactFlow } from 'reactflow';
10
-
11
- import { colors, valueTypeColorMap } from '../util/colors.js';
12
- import { isValidConnection } from '../util/isValidConnection.js';
13
-
14
- export type OutputSocketProps = {
15
- connected: boolean;
16
- specJSON: NodeSpecJSON[];
17
- } & OutputSocketSpecJSON;
18
-
19
- export default function OutputSocket({
20
- specJSON,
21
- connected,
22
- valueType,
23
- name
24
- }: OutputSocketProps) {
25
- const instance = useReactFlow();
26
- const isFlowSocket = valueType === 'flow';
27
- let colorName = valueTypeColorMap[valueType];
28
- if (colorName === undefined) {
29
- colorName = 'red';
30
- }
31
- // @ts-ignore
32
- const [backgroundColor, borderColor] = colors[colorName];
33
- const showName = isFlowSocket === false || name !== 'flow';
34
-
35
- return (
36
- <div className="flex grow items-center justify-end h-7">
37
- {showName && <div className="capitalize">{name}</div>}
38
- {isFlowSocket && (
39
- <FontAwesomeIcon
40
- icon={faCaretRight}
41
- color="#ffffff"
42
- size="lg"
43
- className="ml-1"
44
- />
45
- )}
46
-
47
- <Handle
48
- id={name}
49
- type="source"
50
- position={Position.Right}
51
- className={cx(borderColor, connected ? backgroundColor : 'bg-gray-800')}
52
- isValidConnection={(connection: Connection) =>
53
- isValidConnection(connection, instance, specJSON)
54
- }
55
- />
56
- </div>
57
- );
58
- }
@@ -1,40 +0,0 @@
1
- import React from 'react';
2
- import { useReactFlow } from 'reactflow';
3
-
4
- import { Modal } from './Modal.js';
5
-
6
- export type ClearModalProps = {
7
- open?: boolean;
8
- onClose: () => void;
9
- };
10
-
11
- export const ClearModal: React.FC<ClearModalProps> = ({
12
- open = false,
13
- onClose
14
- }) => {
15
- const instance = useReactFlow();
16
-
17
- const handleClear = () => {
18
- instance.setNodes([]);
19
- instance.setEdges([]);
20
- // TODO better way to call fit vew after edges render
21
- setTimeout(() => {
22
- instance.fitView();
23
- }, 100);
24
- onClose();
25
- };
26
-
27
- return (
28
- <Modal
29
- title="Clear Graph"
30
- actions={[
31
- { label: 'Cancel', onClick: onClose },
32
- { label: 'Clear', onClick: handleClear }
33
- ]}
34
- open={open}
35
- onClose={onClose}
36
- >
37
- <p>Are you sure?</p>
38
- </Modal>
39
- );
40
- };
@@ -1,36 +0,0 @@
1
- import React from 'react';
2
-
3
- import { Modal } from './Modal.js';
4
-
5
- export type HelpModalProps = {
6
- open?: boolean;
7
- onClose: () => void;
8
- };
9
-
10
- export const HelpModal: React.FC<HelpModalProps> = ({
11
- open = false,
12
- onClose
13
- }) => {
14
- return (
15
- <Modal
16
- title="Help"
17
- actions={[{ label: 'Close', onClick: onClose }]}
18
- open={open}
19
- onClose={onClose}
20
- >
21
- <p className="mb-2">Right click anywhere to add a new node.</p>
22
- <p className="mb-2">
23
- Drag a connection into empty space to add a new node and connect it to
24
- the source.
25
- </p>
26
- <p className="mb-2">
27
- Click and drag on a socket to connect to another socket of the same
28
- type.
29
- </p>
30
- <p>
31
- Left click to select nodes or connections, backspace to delete selected
32
- nodes or connections.
33
- </p>
34
- </Modal>
35
- );
36
- };
@@ -1,96 +0,0 @@
1
- import type { GraphJSON } from '@kiberon-labs/behave-graph';
2
- import React from 'react';
3
- import { useCallback, useEffect, useState } from 'react';
4
- import { useReactFlow } from 'reactflow';
5
-
6
- import { Modal } from './Modal.js';
7
-
8
- export type Examples = {
9
- [key: string]: GraphJSON;
10
- };
11
-
12
- export type LoadModalProps = {
13
- open?: boolean;
14
- onClose: () => void;
15
- setBehaviorGraph: (value: GraphJSON) => void;
16
- examples: Examples;
17
- };
18
-
19
- export const LoadModal: React.FC<LoadModalProps> = ({
20
- open = false,
21
- onClose,
22
- setBehaviorGraph,
23
- examples
24
- }) => {
25
- const [value, setValue] = useState<string>();
26
- const [selected, setSelected] = useState('');
27
-
28
- const instance = useReactFlow();
29
-
30
- useEffect(() => {
31
- if (selected) {
32
- setValue(JSON.stringify(examples[selected], null, 2));
33
- }
34
- }, [selected, examples]);
35
-
36
- const handleLoad = useCallback(() => {
37
- let graph;
38
- if (value !== undefined) {
39
- graph = JSON.parse(value) as GraphJSON;
40
- } else if (selected !== '') {
41
- graph = examples[selected];
42
- }
43
-
44
- if (graph === undefined) return;
45
-
46
- setBehaviorGraph(graph);
47
-
48
- // TODO better way to call fit vew after edges render
49
- setTimeout(() => {
50
- instance.fitView();
51
- }, 100);
52
-
53
- handleClose();
54
- }, [setBehaviorGraph, value, instance]);
55
-
56
- const handleClose = () => {
57
- setValue(undefined);
58
- setSelected('');
59
- onClose();
60
- };
61
-
62
- return (
63
- <Modal
64
- title="Load Graph"
65
- actions={[
66
- { label: 'Cancel', onClick: handleClose },
67
- { label: 'Load', onClick: handleLoad }
68
- ]}
69
- open={open}
70
- onClose={onClose}
71
- >
72
- <textarea
73
- autoFocus
74
- className="border border-gray-300 w-full p-2 h-32 align-top"
75
- placeholder="Paste JSON here"
76
- value={value}
77
- onChange={(e) => setValue(e.currentTarget.value)}
78
- ></textarea>
79
- <div className="p-4 text-center text-gray-800">or</div>
80
- <select
81
- className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded block w-full p-3"
82
- onChange={(e) => setSelected(e.target.value)}
83
- value={selected}
84
- >
85
- <option disabled value="">
86
- Select an example
87
- </option>
88
- {Object.keys(examples).map((key) => (
89
- <option key={key} value={key}>
90
- {key}
91
- </option>
92
- ))}
93
- </select>
94
- </Modal>
95
- );
96
- };
@@ -1,64 +0,0 @@
1
- import React from 'react';
2
- import type { PropsWithChildren } from 'react';
3
-
4
- import { useOnPressKey } from '../../hooks/useOnPressKey.js';
5
-
6
- export type ModalAction = {
7
- label: string;
8
- onClick: () => void;
9
- };
10
-
11
- export type ModalProps = {
12
- open?: boolean;
13
- onClose: () => void;
14
- title: string;
15
- actions: ModalAction[];
16
- };
17
-
18
- export const Modal: React.FC<PropsWithChildren<ModalProps>> = ({
19
- open = false,
20
- onClose,
21
- title,
22
- children,
23
- actions
24
- }) => {
25
- useOnPressKey('Escape', onClose);
26
-
27
- if (open === false) return null;
28
-
29
- const actionColors = {
30
- primary: 'bg-teal-400 hover:bg-teal-500',
31
- secondary: 'bg-gray-400 hover:bg-gray-500'
32
- };
33
-
34
- return (
35
- <>
36
- <div
37
- className="z-[19] fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full"
38
- onClick={onClose}
39
- ></div>
40
- <div className="z-20 relative top-20 mx-auto border w-96 shadow-lg bg-white text-sm rounded-md">
41
- <div className="p-3 border-b">
42
- <h2 className="text-lg text-center font-bold">{title}</h2>
43
- </div>
44
- <div className="p-3">{children}</div>
45
- <div className="flex gap-3 p-3 border-t">
46
- {actions.map((action, ix) => (
47
- <button
48
- key={ix}
49
- className={
50
- 'text-white p-2 w-full cursor-pointer ' +
51
- (ix === actions.length - 1
52
- ? actionColors.primary
53
- : actionColors.secondary)
54
- }
55
- onClick={action.onClick}
56
- >
57
- {action.label}
58
- </button>
59
- ))}
60
- </div>
61
- </div>
62
- </>
63
- );
64
- };
@@ -1,60 +0,0 @@
1
- import type { NodeSpecJSON } from '@kiberon-labs/behave-graph';
2
- import React from 'react';
3
- import { useMemo, useRef, useState } from 'react';
4
- import { useEdges, useNodes } from 'reactflow';
5
-
6
- import { flowToBehave } from '../../transformers/flowToBehave.js';
7
- import { Modal } from './Modal.js';
8
-
9
- export type SaveModalProps = {
10
- open?: boolean;
11
- onClose: () => void;
12
- specJson: NodeSpecJSON[];
13
- };
14
-
15
- export const SaveModal: React.FC<SaveModalProps> = ({
16
- open = false,
17
- onClose,
18
- specJson
19
- }) => {
20
- const ref = useRef<HTMLTextAreaElement>(null);
21
- const [copied, setCopied] = useState(false);
22
-
23
- const edges = useEdges();
24
- const nodes = useNodes();
25
-
26
- const flow = useMemo(
27
- () => flowToBehave(nodes, edges, specJson),
28
- [nodes, edges, specJson]
29
- );
30
-
31
- const jsonString = JSON.stringify(flow, null, 2);
32
-
33
- const handleCopy = () => {
34
- ref.current?.select();
35
- document.execCommand('copy');
36
- ref.current?.blur();
37
- setCopied(true);
38
- setInterval(() => {
39
- setCopied(false);
40
- }, 1000);
41
- };
42
-
43
- return (
44
- <Modal
45
- title="Save Graph"
46
- actions={[
47
- { label: 'Cancel', onClick: onClose },
48
- { label: copied ? 'Copied' : 'Copy', onClick: handleCopy }
49
- ]}
50
- open={open}
51
- onClose={onClose}
52
- >
53
- <textarea
54
- ref={ref}
55
- className="border border-gray-300 w-full p-2 h-32"
56
- defaultValue={jsonString}
57
- ></textarea>
58
- </Modal>
59
- );
60
- };