@kiberon-labs/behave-graph-flow 1.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 (378) hide show
  1. package/.fallowrc.json +16 -0
  2. package/.storybook/main.ts +32 -0
  3. package/.storybook/manager.ts +6 -0
  4. package/.storybook/preview.ts +64 -0
  5. package/.storybook/styles.css +16 -0
  6. package/.turbo/turbo-build.log +7 -0
  7. package/CHANGELOG.md +368 -0
  8. package/LICENSE +6 -0
  9. package/README.md +2 -2
  10. package/data/Polynomial.json +510 -0
  11. package/data/sequence.json +337 -0
  12. package/data/trigger-event.json +241 -0
  13. package/data/variable-change.json +210 -0
  14. package/dist/AnyControlImpl-Ds-CShIB.js +20 -0
  15. package/dist/AnyControlImpl-Ds-CShIB.js.map +1 -0
  16. package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js +166 -0
  17. package/dist/DocumentationBrowserPanelImpl-deZNzFX8.js.map +1 -0
  18. package/dist/entry.css +4 -0
  19. package/dist/index.css +42 -0
  20. package/dist/index.css.map +1 -0
  21. package/dist/index.d.ts +3597 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +18009 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/noteImpl-KkrrWgJd.js +242 -0
  26. package/dist/noteImpl-KkrrWgJd.js.map +1 -0
  27. package/dist/styles.module-CvmpDkZj.css +3 -0
  28. package/dist/styles.module-CvmpDkZj.css.map +1 -0
  29. package/dist/styles.module-DZxg8aW9.js +271 -0
  30. package/dist/styles.module-DZxg8aW9.js.map +1 -0
  31. package/dist/useChangeNodeData-ChQGK7AI.js +23 -0
  32. package/dist/useChangeNodeData-ChQGK7AI.js.map +1 -0
  33. package/docs/notifications.md +246 -0
  34. package/docs/protocol.md +702 -0
  35. package/docs/specifics.md +191 -0
  36. package/package.json +82 -22
  37. package/postcss.config.ts +3 -4
  38. package/src/annotations/index.ts +32 -0
  39. package/src/components/FloatingToolbar/index.module.css +37 -0
  40. package/src/components/FloatingToolbar/index.tsx +256 -0
  41. package/src/components/Flow.tsx +287 -75
  42. package/src/components/contextMenus/DynamicContextMenu.tsx +85 -0
  43. package/src/components/contextMenus/NodePicker.module.css +274 -0
  44. package/src/components/contextMenus/NodePicker.tsx +481 -0
  45. package/src/components/contextMenus/edge.tsx +22 -0
  46. package/src/components/contextMenus/node.tsx +15 -0
  47. package/src/components/contextMenus/selection.tsx +11 -0
  48. package/src/components/controls/any/AnyControlImpl.tsx +14 -0
  49. package/src/components/controls/any/index.tsx +19 -0
  50. package/src/components/controls/boolean/index.tsx +13 -0
  51. package/src/components/controls/colorPicker/InputPopover.module.css +100 -0
  52. package/src/components/controls/colorPicker/InputPopover.tsx +31 -0
  53. package/src/components/controls/colorPicker/index.module.css +18 -0
  54. package/src/components/controls/colorPicker/index.tsx +61 -0
  55. package/src/components/controls/number/index.tsx +35 -0
  56. package/src/components/controls/string/index.tsx +16 -0
  57. package/src/components/edges/index.tsx +475 -0
  58. package/src/components/edges/offsetBezier.ts +134 -0
  59. package/src/components/hotKeys.tsx +20 -0
  60. package/src/components/layoutController/index.module.css +13 -0
  61. package/src/components/layoutController/index.tsx +140 -0
  62. package/src/components/layoutController/utils.ts +248 -0
  63. package/src/components/menubar/defaults.tsx +516 -0
  64. package/src/components/menubar/index.tsx +49 -0
  65. package/src/components/menubar/menuItem.module.css +31 -0
  66. package/src/components/menubar/menuItem.tsx +65 -0
  67. package/src/components/nodes/behave/Node.module.css +23 -0
  68. package/src/components/nodes/behave/Node.tsx +176 -0
  69. package/src/components/nodes/behave/NodeContainer.module.css +88 -0
  70. package/src/components/nodes/behave/NodeContainer.tsx +46 -0
  71. package/src/components/nodes/behave/index.tsx +14 -0
  72. package/src/components/nodes/group/index.tsx +109 -0
  73. package/src/components/nodes/wrapper/index.tsx +73 -0
  74. package/src/components/nodes/wrapper/styles.module.css +87 -0
  75. package/src/components/notifications/NotificationProvider.tsx +81 -0
  76. package/src/components/notifications/index.ts +2 -0
  77. package/src/components/notifications/utils.ts +71 -0
  78. package/src/components/panels/alignment/index.module.css +10 -0
  79. package/src/components/panels/alignment/index.tsx +244 -0
  80. package/src/components/panels/base/index.tsx +5 -0
  81. package/src/components/panels/base/styles.module.css +12 -0
  82. package/src/components/panels/common/PanelHeader.module.css +24 -0
  83. package/src/components/panels/common/PanelHeader.tsx +22 -0
  84. package/src/components/panels/common/SectionTitle.module.css +13 -0
  85. package/src/components/panels/common/SectionTitle.tsx +10 -0
  86. package/src/components/panels/events/EditEventPanel.tsx +324 -0
  87. package/src/components/panels/events/ManageEventsPanel.tsx +101 -0
  88. package/src/components/panels/events/index.tsx +23 -0
  89. package/src/components/panels/events/styles.module.css +178 -0
  90. package/src/components/panels/graphProperties/index.tsx +125 -0
  91. package/src/components/panels/history/index.tsx +92 -0
  92. package/src/components/panels/history/styles.module.css +97 -0
  93. package/src/components/panels/keymaps/index.module.css +68 -0
  94. package/src/components/panels/keymaps/index.tsx +166 -0
  95. package/src/components/panels/layers/index.tsx +245 -0
  96. package/src/components/panels/layers/styles.module.css +107 -0
  97. package/src/components/panels/legend/index.module.css +6 -0
  98. package/src/components/panels/legend/index.tsx +76 -0
  99. package/src/components/panels/logs/index.module.css +218 -0
  100. package/src/components/panels/logs/index.tsx +288 -0
  101. package/src/components/panels/nodeInputs/InputControl.tsx +63 -0
  102. package/src/components/panels/nodeInputs/InputsGroup.tsx +65 -0
  103. package/src/components/panels/nodeInputs/MultipleNodesView.tsx +37 -0
  104. package/src/components/panels/nodeInputs/NodeSettings.tsx +92 -0
  105. package/src/components/panels/nodeInputs/NodeTitleEditor.tsx +125 -0
  106. package/src/components/panels/nodeInputs/OutputsGroup.tsx +55 -0
  107. package/src/components/panels/nodeInputs/SocketGenerators.tsx +32 -0
  108. package/src/components/panels/nodeInputs/index.module.css +308 -0
  109. package/src/components/panels/nodeInputs/index.tsx +349 -0
  110. package/src/components/panels/nodeInputs/useNodeHandlers.ts +76 -0
  111. package/src/components/panels/nodeInputs/useNodeInputsData.ts +153 -0
  112. package/src/components/panels/nodePicker/index.tsx +115 -0
  113. package/src/components/panels/panel/index.module.css +66 -0
  114. package/src/components/panels/panel/index.tsx +88 -0
  115. package/src/components/panels/search/index.module.css +16 -0
  116. package/src/components/panels/search/index.tsx +215 -0
  117. package/src/components/panels/systemSettings/ConversionsSettings.tsx +203 -0
  118. package/src/components/panels/systemSettings/index.tsx +251 -0
  119. package/src/components/panels/systemSettings/styles.module.css +138 -0
  120. package/src/components/panels/traces/GridLines.tsx +38 -0
  121. package/src/components/panels/traces/TimeGrid.tsx +48 -0
  122. package/src/components/panels/traces/TraceLane.tsx +62 -0
  123. package/src/components/panels/traces/TraceTooltip.tsx +22 -0
  124. package/src/components/panels/traces/TracesHeader.tsx +56 -0
  125. package/src/components/panels/traces/index.module.css +159 -0
  126. package/src/components/panels/traces/index.tsx +298 -0
  127. package/src/components/panels/traces/types.ts +48 -0
  128. package/src/components/panels/traces/useDerivedSpans.ts +307 -0
  129. package/src/components/panels/traces/utils.ts +33 -0
  130. package/src/components/panels/variables/CreateVariableScreen.tsx +162 -0
  131. package/src/components/panels/variables/ManageVariablesScreen.tsx +147 -0
  132. package/src/components/panels/variables/index.tsx +125 -0
  133. package/src/components/panels/variables/styles.module.css +149 -0
  134. package/src/components/primitives/icon.module.css +45 -0
  135. package/src/components/primitives/icon.tsx +38 -0
  136. package/src/components/sockets/input/index.tsx +83 -0
  137. package/src/components/sockets/input/styles.module.css +26 -0
  138. package/src/components/sockets/output/index.tsx +68 -0
  139. package/src/components/sockets/output/styles.module.css +22 -0
  140. package/src/css/notes.css +135 -0
  141. package/src/css/prosemirror.css +57 -0
  142. package/src/css/rc-dock.css +212 -0
  143. package/src/css/rc-menu.css +101 -0
  144. package/src/css/themes/kiberon.css +127 -0
  145. package/src/css/vars.css +198 -0
  146. package/src/css/vscode-elements.css +124 -0
  147. package/src/entry.css +4 -0
  148. package/src/generators/CallSubgraphGenerator.tsx +136 -0
  149. package/src/generators/CustomEventOnTriggeredGenerator.tsx +85 -0
  150. package/src/generators/GraphBoundaryGenerator.module.css +32 -0
  151. package/src/generators/GraphBoundaryGenerator.tsx +193 -0
  152. package/src/generators/SequenceGenerator.tsx +104 -0
  153. package/src/generators/SwitchOnIntegerGenerator.tsx +256 -0
  154. package/src/generators/SwitchOnStringGenerator.tsx +263 -0
  155. package/src/generators/callSubgraphSync.ts +126 -0
  156. package/src/generators/registerDefaultGenerators.ts +55 -0
  157. package/src/generators/registerDefaults.ts +26 -0
  158. package/src/hooks/useBehaveGraphFlow.ts +17 -16
  159. package/src/hooks/useFlowHandlers.ts +154 -30
  160. package/src/hooks/useWasdPan.ts +210 -0
  161. package/src/index.css +134 -0
  162. package/src/index.ts +53 -18
  163. package/src/manifest/contributionRegistry.ts +93 -0
  164. package/src/manifest/index.ts +4 -0
  165. package/src/manifest/loadManifest.ts +82 -0
  166. package/src/manifest/manifestPlugin.ts +29 -0
  167. package/src/manifest/passthroughValueType.ts +40 -0
  168. package/src/plugin/alignment/index.ts +91 -0
  169. package/src/plugin/autosave/controller.ts +366 -0
  170. package/src/plugin/autosave/index.tsx +114 -0
  171. package/src/plugin/autosave/panel/BackupPanel.tsx +141 -0
  172. package/src/plugin/autosave/panel/index.tsx +1 -0
  173. package/src/plugin/autosave/panel/styles.module.css +56 -0
  174. package/src/plugin/autosave/settings.ts +65 -0
  175. package/src/plugin/autosave/storage.ts +147 -0
  176. package/src/plugin/docs/index.tsx +297 -0
  177. package/src/plugin/docs/panel/DocumentationBrowserPanelImpl.tsx +200 -0
  178. package/src/plugin/docs/panel/index.tsx +21 -0
  179. package/src/plugin/docs/panel/styles.module.css +174 -0
  180. package/src/plugin/graphrunner/actions.ts +326 -0
  181. package/src/plugin/graphrunner/buttons.tsx +95 -0
  182. package/src/plugin/graphrunner/client.ts +707 -0
  183. package/src/plugin/graphrunner/index.tsx +184 -0
  184. package/src/plugin/graphrunner/panel.tsx +386 -0
  185. package/src/plugin/graphrunner/runController.ts +283 -0
  186. package/src/plugin/graphrunner/runner.ts +187 -0
  187. package/src/plugin/graphrunner/session.ts +243 -0
  188. package/src/plugin/graphrunner/store.ts +196 -0
  189. package/src/plugin/graphrunner/styles.module.css +171 -0
  190. package/src/plugin/graphrunner/transport.ts +250 -0
  191. package/src/plugin/graphrunner/types.ts +693 -0
  192. package/src/plugin/graphrunner-local/execution-utils.ts +637 -0
  193. package/src/plugin/graphrunner-local/index.tsx +172 -0
  194. package/src/plugin/graphrunner-local/panel.tsx +187 -0
  195. package/src/plugin/graphrunner-local/store.ts +41 -0
  196. package/src/plugin/graphrunner-local/styles.module.css +82 -0
  197. package/src/plugin/graphrunner-local/transport.ts +1339 -0
  198. package/src/plugin/graphrunner-local/types.ts +10 -0
  199. package/src/plugin/graphrunner-webworker/graph-executor.worker.ts +635 -0
  200. package/src/plugin/graphrunner-webworker/index.tsx +140 -0
  201. package/src/plugin/graphrunner-webworker/panel.tsx +173 -0
  202. package/src/plugin/graphrunner-webworker/store.ts +98 -0
  203. package/src/plugin/graphrunner-webworker/worker-transport.ts +123 -0
  204. package/src/plugin/kitchen-sink/index.ts +38 -0
  205. package/src/plugin/layout/dagre.ts +131 -0
  206. package/src/plugin/layout/elk.ts +216 -0
  207. package/src/plugin/layout/index.ts +80 -0
  208. package/src/plugin/notes/FormatToolbar.tsx +200 -0
  209. package/src/plugin/notes/index.tsx +191 -0
  210. package/src/plugin/notes/nodeActions.ts +100 -0
  211. package/src/plugin/notes/note.tsx +20 -0
  212. package/src/plugin/notes/noteImpl.tsx +89 -0
  213. package/src/plugin/realtime/realtimeRunner.ts +624 -0
  214. package/src/specifics/CustomEventOnTriggeredSpecific.tsx +92 -0
  215. package/src/specifics/CustomEventTriggerSpecific.tsx +141 -0
  216. package/src/specifics/VariableGetSpecific.tsx +110 -0
  217. package/src/specifics/VariableSetSpecific.tsx +110 -0
  218. package/src/store/actions.tsx +698 -0
  219. package/src/store/commands.ts +278 -0
  220. package/src/store/contextMenu.ts +192 -0
  221. package/src/store/controls.tsx +62 -0
  222. package/src/store/conversions.ts +47 -0
  223. package/src/store/documentation.tsx +69 -0
  224. package/src/store/events.tsx +116 -0
  225. package/src/store/flow.tsx +230 -0
  226. package/src/store/graphMeta.ts +39 -0
  227. package/src/store/hotKeys.tsx +364 -0
  228. package/src/store/layers.ts +259 -0
  229. package/src/store/legend.tsx +76 -0
  230. package/src/store/logs.ts +28 -0
  231. package/src/store/menubar.ts +41 -0
  232. package/src/store/refs.ts +84 -0
  233. package/src/store/registry.ts +51 -0
  234. package/src/store/selection.ts +22 -0
  235. package/src/store/settings.ts +99 -0
  236. package/src/store/settingsSchema.ts +210 -0
  237. package/src/store/socketGenerator.tsx +54 -0
  238. package/src/store/specific.tsx +75 -0
  239. package/src/store/specs.tsx +35 -0
  240. package/src/store/tabs.ts +282 -0
  241. package/src/store/toolbar.tsx +45 -0
  242. package/src/store/traces.ts +240 -0
  243. package/src/store/variables.ts +37 -0
  244. package/src/system/graph.ts +131 -0
  245. package/src/system/graphSession.ts +172 -0
  246. package/src/system/index.ts +6 -0
  247. package/src/system/notifications.ts +111 -0
  248. package/src/system/persistence.ts +82 -0
  249. package/src/system/plugin.ts +55 -0
  250. package/src/system/provider.tsx +86 -0
  251. package/src/system/pubsub.ts +323 -0
  252. package/src/system/system.ts +653 -0
  253. package/src/system/tabLoader.tsx +303 -0
  254. package/src/system/undoRedo.ts +103 -0
  255. package/src/transformers/Uigraph.ts +61 -0
  256. package/src/transformers/behaveToFlow.ts +16 -4
  257. package/src/transformers/contract.ts +87 -0
  258. package/src/transformers/flowToBehave.ts +40 -12
  259. package/src/types/NodeMetadata.ts +27 -0
  260. package/src/types/graph.ts +49 -0
  261. package/src/types/nodes.ts +50 -0
  262. package/src/types.ts +18 -0
  263. package/src/util/autoConvert.ts +200 -0
  264. package/src/util/colors.ts +1 -29
  265. package/src/util/downloadJson.ts +18 -0
  266. package/src/util/extractNodeMetadata.ts +16 -0
  267. package/src/util/getPickerFilters.ts +1 -1
  268. package/src/util/isBehaveNode.ts +6 -0
  269. package/src/util/isValidConnection.ts +51 -17
  270. package/src/util/mergeSockets.ts +29 -0
  271. package/src/util/serializeVariables.ts +66 -0
  272. package/src/util/sockets.ts +43 -0
  273. package/stories/apex/layoutController/example-graph.worker.ts +39 -0
  274. package/stories/apex/layoutController/index.stories.tsx +48 -0
  275. package/stories/apex/layoutController/webworker.stories.tsx +103 -0
  276. package/stories/apex/menubar/menubar.stories.tsx +19 -0
  277. package/stories/components/colorpicker/index.stories.tsx +20 -0
  278. package/stories/components/contextMenus/edge.stories.tsx +32 -0
  279. package/stories/components/contextMenus/node.stories.tsx +26 -0
  280. package/stories/components/contextMenus/nodePicker.stories.tsx +115 -0
  281. package/stories/components/controls/any/index.stories.tsx +19 -0
  282. package/stories/components/controls/boolean/index.stories.tsx +19 -0
  283. package/stories/components/controls/colorPicker/index.stories.tsx +49 -0
  284. package/stories/components/controls/number/index.stories.tsx +19 -0
  285. package/stories/components/controls/string/index.stories.tsx +19 -0
  286. package/stories/components/nodes/behaveNode.stories.tsx +108 -0
  287. package/stories/components/panels/alignment.stories.tsx +24 -0
  288. package/stories/components/panels/events.stories.tsx +38 -0
  289. package/stories/components/panels/graphRunner.stories.tsx +317 -0
  290. package/stories/components/panels/history.stories.tsx +37 -0
  291. package/stories/components/panels/keymaps.stories.tsx +21 -0
  292. package/stories/components/panels/legend.stories.tsx +37 -0
  293. package/stories/components/panels/logs.stories.tsx +24 -0
  294. package/stories/components/panels/nodeInputs.stories.tsx +21 -0
  295. package/stories/components/panels/nodePicker.stories.tsx +37 -0
  296. package/stories/components/panels/panel.stories.tsx +39 -0
  297. package/stories/components/panels/search.stories.tsx +24 -0
  298. package/stories/components/panels/systemSettings.stories.tsx +26 -0
  299. package/stories/components/panels/traces.stories.tsx +225 -0
  300. package/stories/components/panels/variables.stories.tsx +24 -0
  301. package/stories/defaults/defaultStoryProvider.tsx +170 -0
  302. package/stories/defaults/systemGenerator.ts +43 -0
  303. package/stories/plugins/notes.stories.tsx +100 -0
  304. package/tests/autoConvert.test.ts +329 -0
  305. package/tests/autosavePlugin.test.ts +204 -0
  306. package/tests/callSubgraphSync.test.ts +148 -0
  307. package/tests/commandRegistry.test.ts +137 -0
  308. package/tests/components/edges/offsetBezier.test.ts +51 -0
  309. package/tests/components/layoutController/utils.test.ts +68 -0
  310. package/tests/components/panels/traces/utils.test.ts +52 -0
  311. package/tests/contract.test.ts +51 -0
  312. package/tests/contractSerialize.test.ts +62 -0
  313. package/tests/deriveSpans.test.ts +71 -0
  314. package/tests/flowToBehave.test.ts +27 -4
  315. package/tests/hotkeys.test.ts +79 -0
  316. package/tests/keepAliveLifecycle.test.ts +167 -0
  317. package/tests/loadManifest.test.ts +113 -0
  318. package/tests/noteMarkdown.test.ts +65 -0
  319. package/tests/notesPlugin.test.ts +162 -0
  320. package/tests/notifications.test.ts +87 -0
  321. package/tests/persistence.test.ts +51 -0
  322. package/tests/saveLoad.test.ts +373 -0
  323. package/tests/settings.test.ts +178 -0
  324. package/tests/traceStore.test.ts +46 -0
  325. package/tests/util/calculateNewEdge.test.ts +98 -0
  326. package/tests/util/getSocketsByNodeTypeAndHandleType.test.ts +31 -0
  327. package/tests/util/hasPositionMetaData.test.ts +33 -0
  328. package/tests/util/isBehaveNode.test.ts +22 -0
  329. package/tests/util/isHandleConnected.test.ts +37 -0
  330. package/tests/util/mergeSockets.test.ts +43 -0
  331. package/tests/visual/README.md +64 -0
  332. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-alignment-chromium-win32.png +0 -0
  333. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-conversation-chromium-win32.png +0 -0
  334. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-events-chromium-win32.png +0 -0
  335. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-history-chromium-win32.png +0 -0
  336. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-keymaps-chromium-win32.png +0 -0
  337. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-layers-chromium-win32.png +0 -0
  338. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-legend-chromium-win32.png +0 -0
  339. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-localGraphRunner-chromium-win32.png +0 -0
  340. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-logs-chromium-win32.png +0 -0
  341. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodeInputs-chromium-win32.png +0 -0
  342. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-nodePicker-chromium-win32.png +0 -0
  343. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-panel-chromium-win32.png +0 -0
  344. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-search-chromium-win32.png +0 -0
  345. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-systemSettings-chromium-win32.png +0 -0
  346. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-traces-chromium-win32.png +0 -0
  347. package/tests/visual/__screenshots__/panels.visual.test.tsx/panel-variables-chromium-win32.png +0 -0
  348. package/tests/visual/panels.visual.test.tsx +76 -0
  349. package/tests/wasdPan.test.ts +71 -0
  350. package/tsconfig.base.json +39 -0
  351. package/tsconfig.json +18 -59
  352. package/tsconfig.prod.json +23 -0
  353. package/tsdown.config.ts +15 -3
  354. package/typedoc.json +7 -7
  355. package/vite.config.js +7 -0
  356. package/vitest.config.ts +5 -2
  357. package/vitest.visual.config.ts +55 -0
  358. package/src/components/AutoSizeInput.tsx +0 -65
  359. package/src/components/Controls.tsx +0 -87
  360. package/src/components/InputSocket.tsx +0 -142
  361. package/src/components/Node.tsx +0 -68
  362. package/src/components/NodeContainer.tsx +0 -46
  363. package/src/components/NodePicker.tsx +0 -77
  364. package/src/components/OutputSocket.tsx +0 -58
  365. package/src/components/modals/ClearModal.tsx +0 -40
  366. package/src/components/modals/HelpModal.tsx +0 -36
  367. package/src/components/modals/LoadModal.tsx +0 -96
  368. package/src/components/modals/Modal.tsx +0 -64
  369. package/src/components/modals/SaveModal.tsx +0 -60
  370. package/src/hooks/useCustomNodeTypes.tsx +0 -31
  371. package/src/hooks/useGraphRunner.ts +0 -104
  372. package/src/hooks/useMergeMap.ts +0 -14
  373. package/src/hooks/useNodeSpecJson.ts +0 -20
  374. package/src/hooks/useQueriableDefinitions.ts +0 -22
  375. package/src/styles.css +0 -8
  376. package/tailwind.config.ts +0 -19
  377. package/tests/tsconfig.json +0 -10
  378. /package/src/{types.d.ts → types-declarations.d.ts} +0 -0
@@ -0,0 +1,26 @@
1
+ import type { System } from '@/system/system';
2
+ import { registerDefaultSocketGenerators } from './registerDefaultGenerators';
3
+ import { setupCallSubgraphSync } from './callSubgraphSync';
4
+
5
+ /** Editors that already had their built-in content registered. */
6
+ const initialized = new WeakSet<System>();
7
+
8
+ /**
9
+ * Register the editor's built-in content , the default socket generators and the
10
+ * call-subgraph contract sync , on an editor instance.
11
+ *
12
+ * Idempotent per editor: safe to call from every graph-canvas mount (multiple
13
+ * tabs) without double-registering. The default content is editor-lifetime; the
14
+ * subgraph sync's per-session subscriptions clean themselves up on session
15
+ * dispose.
16
+ *
17
+ * A host that wants a blank or fully custom editor can simply not rely on the
18
+ * canvas's auto-call and register its own content instead.
19
+ */
20
+ export function registerDefaults(editor: System): void {
21
+ if (initialized.has(editor)) return;
22
+ initialized.add(editor);
23
+
24
+ registerDefaultSocketGenerators(editor);
25
+ setupCallSubgraphSync(editor);
26
+ }
@@ -1,16 +1,11 @@
1
1
  import type { GraphJSON, NodeSpecJSON } from '@kiberon-labs/behave-graph';
2
2
  import { useCallback, useEffect, useState } from 'react';
3
- import { useEdgesState, useNodesState } from 'reactflow';
4
-
5
3
  import { behaveToFlow } from '../transformers/behaveToFlow.js';
6
4
  import { flowToBehave } from '../transformers/flowToBehave.js';
7
5
  import { autoLayout } from '../util/autoLayout.js';
8
6
  import { hasPositionMetaData } from '../util/hasPositionMetaData.js';
9
- import { useCustomNodeTypes } from './useCustomNodeTypes.js';
10
-
11
- export const fetchBehaviorGraphJson = async (url: string) =>
12
- // eslint-disable-next-line unicorn/no-await-expression-member
13
- (await (await fetch(url)).json()) as GraphJSON;
7
+ import { useGraph } from '@/system/provider.js';
8
+ import { useStore } from 'zustand';
14
9
 
15
10
  /**
16
11
  * Hook that returns the nodes and edges for react-flow, and the graphJson for the behave-graph.
@@ -27,8 +22,19 @@ export const useBehaveGraphFlow = ({
27
22
  specJson: NodeSpecJSON[] | undefined;
28
23
  }) => {
29
24
  const [graphJson, setStoredGraphJson] = useState<GraphJSON | undefined>();
30
- const [nodes, setNodes, onNodesChange] = useNodesState([]);
31
- const [edges, setEdges, onEdgesChange] = useEdgesState([]);
25
+ const sys = useGraph();
26
+
27
+ const {
28
+ nodes,
29
+ setNodes,
30
+ applyNodeChanges: onNodesChange
31
+ } = useStore(sys.nodeStore);
32
+
33
+ const {
34
+ edges,
35
+ setEdges,
36
+ applyEdgeChanges: onEdgesChange
37
+ } = useStore(sys.edgeStore);
32
38
 
33
39
  const setGraphJson = useCallback(
34
40
  (graphJson: GraphJSON) => {
@@ -55,21 +61,16 @@ export const useBehaveGraphFlow = ({
55
61
  useEffect(() => {
56
62
  if (!specJson) return;
57
63
  // when nodes and edges are updated, update the graph json with the flow to behave behavior
58
- const graphJson = flowToBehave(nodes, edges, specJson);
64
+ const graphJson = flowToBehave(sys, nodes, edges, specJson);
59
65
  setStoredGraphJson(graphJson);
60
66
  }, [nodes, edges, specJson]);
61
67
 
62
- const nodeTypes = useCustomNodeTypes({
63
- specJson
64
- });
65
-
66
68
  return {
67
69
  nodes,
68
70
  edges,
69
71
  onEdgesChange,
70
72
  onNodesChange,
71
73
  setGraphJson,
72
- graphJson,
73
- nodeTypes
74
+ graphJson
74
75
  };
75
76
  };
@@ -7,6 +7,7 @@ import {
7
7
  } from 'react';
8
8
  import type {
9
9
  Connection,
10
+ ConnectionStatus,
10
11
  Node,
11
12
  OnConnectStartParams,
12
13
  XYPosition
@@ -14,8 +15,16 @@ import type {
14
15
  import { v4 as uuidv4 } from 'uuid';
15
16
 
16
17
  import { calculateNewEdge } from '../util/calculateNewEdge.js';
18
+ import { buildConverterInsertion } from '../util/autoConvert.js';
17
19
  import { getNodePickerFilters } from '../util/getPickerFilters.js';
18
20
  import { useBehaveGraphFlow } from './useBehaveGraphFlow.js';
21
+ import { useGraph } from '@/system/provider.js';
22
+ import type { ExtendedNodeSpecJSON } from '@/components/contextMenus/NodePicker.js';
23
+ import {
24
+ addFloatingTab,
25
+ findTabInLayout,
26
+ removeTabFromLayout
27
+ } from '@/components/layoutController/utils.js';
19
28
 
20
29
  type BehaveGraphFlow = ReturnType<typeof useBehaveGraphFlow>;
21
30
 
@@ -48,16 +57,53 @@ export const useFlowHandlers = ({
48
57
  nodes: Node[];
49
58
  specJSON: NodeSpecJSON[] | undefined;
50
59
  }) => {
60
+ const sys = useGraph();
51
61
  const [lastConnectStart, setLastConnectStart] =
52
62
  useState<OnConnectStartParams>();
53
63
  const [nodePickerVisibility, setNodePickerVisibility] =
54
64
  useState<XYPosition>();
55
-
56
65
  const onConnect = useCallback(
57
66
  (connection: Connection) => {
58
67
  if (connection.source === null) return;
59
68
  if (connection.target === null) return;
60
69
 
70
+ // Auto-convert: if the value types differ but a converter node exists,
71
+ // splice the converter in between instead of a direct edge.
72
+ const autoConvert = sys.editor.systemSettings.getState().autoConvert;
73
+ if (autoConvert && specJSON) {
74
+ const insertion = buildConverterInsertion(
75
+ connection,
76
+ sys.nodeStore.getState().nodes,
77
+ specJSON,
78
+ sys.editor.conversionStore.getState().conversions
79
+ );
80
+ if (insertion) {
81
+ const { node, edges: convEdges } = insertion;
82
+ sys.undoManager.execute({
83
+ name: 'Auto-convert connection',
84
+ execute: () => {
85
+ sys.nodeStore.getState().addNode(node);
86
+ sys.edgeStore
87
+ .getState()
88
+ .setEdges([...sys.edgeStore.getState().edges, ...convEdges]);
89
+ convEdges.forEach((e) => sys.pubsub.publish('edge:added', e));
90
+ },
91
+ undo: () => {
92
+ const ids = new Set(convEdges.map((e) => e.id));
93
+ sys.nodeStore
94
+ .getState()
95
+ .setNodes((ns) => ns.filter((n) => n.id !== node.id));
96
+ sys.edgeStore
97
+ .getState()
98
+ .setEdges(
99
+ sys.edgeStore.getState().edges.filter((e) => !ids.has(e.id))
100
+ );
101
+ }
102
+ });
103
+ return;
104
+ }
105
+ }
106
+
61
107
  const newEdge = {
62
108
  id: uuidv4(),
63
109
  source: connection.source,
@@ -65,6 +111,7 @@ export const useFlowHandlers = ({
65
111
  sourceHandle: connection.sourceHandle,
66
112
  targetHandle: connection.targetHandle
67
113
  };
114
+ sys.pubsub.publish('edge:added', newEdge);
68
115
  onEdgesChange([
69
116
  {
70
117
  type: 'add',
@@ -72,29 +119,46 @@ export const useFlowHandlers = ({
72
119
  }
73
120
  ]);
74
121
  },
75
- [onEdgesChange]
122
+ [onEdgesChange, sys, specJSON]
76
123
  );
77
124
 
78
125
  const closeNodePicker = useCallback(() => {
79
126
  setLastConnectStart(undefined);
80
127
  setNodePickerVisibility(undefined);
81
- }, []);
128
+
129
+ // Close the nodepicker panel from rc-dock
130
+ const currentLayout = sys.editor.tabStore.getState().layout;
131
+ const newLayout = removeTabFromLayout(currentLayout, 'nodepicker');
132
+ sys.editor.tabStore.getState().setLayout(newLayout);
133
+ }, [sys]);
82
134
 
83
135
  const handleAddNode = useCallback(
84
- (nodeType: string, position: XYPosition) => {
136
+ (spec: ExtendedNodeSpecJSON, position: XYPosition) => {
85
137
  closeNodePicker();
86
138
  const newNode = {
87
139
  id: uuidv4(),
88
- type: nodeType,
140
+ type: spec.nodeType ?? 'behaveNode',
89
141
  position,
90
- data: {}
142
+ data: {
143
+ configuration: {},
144
+ type: spec.type,
145
+ ports: {}
146
+ }
91
147
  };
92
- onNodesChange([
93
- {
94
- type: 'add',
95
- item: newNode
148
+
149
+ sys.undoManager.execute({
150
+ name: `Add node (${spec.type})`,
151
+ execute: () => {
152
+ sys.nodeStore.getState().addNode(newNode);
153
+ },
154
+ undo: () => {
155
+ sys.nodeStore
156
+ .getState()
157
+ .setNodes((existing) =>
158
+ existing.filter((n) => n.id !== newNode.id)
159
+ );
96
160
  }
97
- ]);
161
+ });
98
162
 
99
163
  if (lastConnectStart === undefined) return;
100
164
 
@@ -109,7 +173,7 @@ export const useFlowHandlers = ({
109
173
  type: 'add',
110
174
  item: calculateNewEdge(
111
175
  originNode,
112
- nodeType,
176
+ spec.type,
113
177
  newNode.id,
114
178
  lastConnectStart,
115
179
  specJSON
@@ -134,30 +198,90 @@ export const useFlowHandlers = ({
134
198
  []
135
199
  );
136
200
 
137
- const handleStopConnect = useCallback((e: MouseEvent) => {
138
- const element = e.target as HTMLElement;
139
- console.log(
140
- 'here',
141
- element.classList,
142
- element.classList.contains('react-flow__pane')
143
- );
144
- if (element.classList.contains('react-flow__pane')) {
145
- console.log('setting node picker');
146
- setNodePickerVisibility({ x: e.clientX, y: e.clientY });
147
- } else {
148
- setLastConnectStart(undefined);
149
- }
150
- }, []);
201
+ const handleStopConnect = useCallback(
202
+ (e: MouseEvent, _connectionState: ConnectionStatus) => {
203
+ const element = e.target as HTMLElement;
204
+ if (element.classList.contains('react-flow__pane')) {
205
+ const screenPos = { x: e.clientX, y: e.clientY };
206
+ setNodePickerVisibility(screenPos);
207
+
208
+ // Store screen position for NodePickerPanel to use
209
+ sys.refStore.getState().setRef('nodePickerPosition', screenPos);
210
+
211
+ // Open as floating rc-dock panel
212
+ const currentLayout = sys.editor.tabStore.getState().layout;
213
+
214
+ // Close existing nodepicker if open
215
+ const existingPanel = findTabInLayout(currentLayout, 'nodepicker');
216
+ let layoutToUse = currentLayout;
217
+ if (existingPanel) {
218
+ layoutToUse = removeTabFromLayout(currentLayout, 'nodepicker');
219
+ }
220
+
221
+ // Create new floating panel with minimal tab data
222
+ // The actual content will be loaded by tabLoader
223
+ const tabData = {
224
+ id: 'nodepicker',
225
+ group: 'headless'
226
+ };
227
+
228
+ const newLayout = addFloatingTab(layoutToUse, tabData, {
229
+ left: e.clientX,
230
+ top: e.clientY,
231
+ width: 600,
232
+ height: 500
233
+ });
234
+
235
+ sys.editor.tabStore.getState().setLayout(newLayout);
236
+ } else {
237
+ setLastConnectStart(undefined);
238
+ }
239
+ },
240
+ [sys]
241
+ );
151
242
 
152
243
  const handlePaneClick = useCallback(
153
244
  () => closeNodePicker(),
154
245
  [closeNodePicker]
155
246
  );
156
247
 
157
- const handlePaneContextMenu = useCallback((e: ReactMouseEvent) => {
158
- e.preventDefault();
159
- setNodePickerVisibility({ x: e.clientX, y: e.clientY });
160
- }, []);
248
+ const handlePaneContextMenu = useCallback(
249
+ (e: ReactMouseEvent) => {
250
+ e.preventDefault();
251
+ const screenPos = { x: e.clientX, y: e.clientY };
252
+ setNodePickerVisibility(screenPos);
253
+
254
+ // Store screen position for NodePickerPanel to use
255
+ sys.refStore.getState().setRef('nodePickerPosition', screenPos);
256
+
257
+ // Open as floating rc-dock panel
258
+ const currentLayout = sys.editor.tabStore.getState().layout;
259
+
260
+ // Close existing nodepicker if open
261
+ const existingPanel = findTabInLayout(currentLayout, 'nodepicker');
262
+ let layoutToUse = currentLayout;
263
+ if (existingPanel) {
264
+ layoutToUse = removeTabFromLayout(currentLayout, 'nodepicker');
265
+ }
266
+
267
+ // Create new floating panel with minimal tab data
268
+ // The actual content will be loaded by tabLoader
269
+ const tabData = {
270
+ id: 'nodepicker',
271
+ group: 'headless'
272
+ };
273
+
274
+ const newLayout = addFloatingTab(layoutToUse, tabData, {
275
+ left: e.clientX,
276
+ top: e.clientY,
277
+ width: 600,
278
+ height: 500
279
+ });
280
+
281
+ sys.editor.tabStore.getState().setLayout(newLayout);
282
+ },
283
+ [sys]
284
+ );
161
285
 
162
286
  const nodePickFilters = useNodePickFilters({
163
287
  nodes,
@@ -0,0 +1,210 @@
1
+ import { useCallback, useEffect, useRef } from 'react';
2
+ import type { ReactFlowInstance } from 'reactflow';
3
+
4
+ export type UseWasdPanOptions = {
5
+ getReactFlowInstance: () => ReactFlowInstance | undefined;
6
+ speed?: number;
7
+ speedWithShift?: number;
8
+ dtCapSeconds?: number;
9
+ enabled?: boolean;
10
+ };
11
+
12
+ const isEditableElement = (element: HTMLElement): boolean => {
13
+ const tag = element.tagName?.toLowerCase();
14
+ // Contenteditable surfaces (e.g. the notes plugin's prosemirror editor) are
15
+ // divs, so checking the tag alone is not enough — WASD must type, not pan.
16
+ return (
17
+ tag === 'input' ||
18
+ tag === 'textarea' ||
19
+ tag === 'select' ||
20
+ element.isContentEditable
21
+ );
22
+ };
23
+
24
+ export const isEventFromEditable = (event: KeyboardEvent) => {
25
+ // Events from inside a web component are retargeted: at the window listener
26
+ // `event.target` is the custom-element host (e.g. the conversation panel's
27
+ // <vscode-textfield>), not the <input> in its shadow DOM. composedPath()
28
+ // exposes the real target chain, so walk it and check every element.
29
+ const path =
30
+ typeof event.composedPath === 'function' ? event.composedPath() : [];
31
+ if (path.length > 0) {
32
+ return path.some(
33
+ (node) => node instanceof HTMLElement && isEditableElement(node)
34
+ );
35
+ }
36
+ const target = event.target as HTMLElement | null;
37
+ if (!target) return false;
38
+ return isEditableElement(target);
39
+ };
40
+
41
+ export const useWasdPan = ({
42
+ getReactFlowInstance,
43
+ speed = 650,
44
+ speedWithShift = 1400,
45
+ dtCapSeconds = 0.05,
46
+ enabled = true
47
+ }: UseWasdPanOptions) => {
48
+ const wasdRef = useRef({
49
+ w: false,
50
+ a: false,
51
+ s: false,
52
+ d: false,
53
+ shift: false
54
+ });
55
+ const rafRef = useRef<number | null>(null);
56
+ const lastFrameRef = useRef<number | null>(null);
57
+
58
+ const cancelPanLoop = useCallback(() => {
59
+ if (rafRef.current != null) {
60
+ cancelAnimationFrame(rafRef.current);
61
+ rafRef.current = null;
62
+ }
63
+ lastFrameRef.current = null;
64
+ }, []);
65
+
66
+ const startPanLoop = useCallback(() => {
67
+ if (rafRef.current != null) return;
68
+
69
+ const tick = (now: number) => {
70
+ const last = lastFrameRef.current;
71
+ lastFrameRef.current = now;
72
+ const dtMs = last == null ? 0 : now - last;
73
+ const dt = Math.min(dtCapSeconds, dtMs / 1000);
74
+
75
+ const state = wasdRef.current;
76
+ const any = state.w || state.a || state.s || state.d;
77
+ const reactFlowInstance = getReactFlowInstance();
78
+
79
+ if (!enabled || !any) {
80
+ cancelPanLoop();
81
+ return;
82
+ }
83
+
84
+ // The reactflow ref can be temporarily unavailable during re-mounts.
85
+ // If we cancel here while the user is still holding a key, we might never
86
+ // restart because we ignore keydown repeats.
87
+ if (!reactFlowInstance) {
88
+ rafRef.current = requestAnimationFrame(tick);
89
+ return;
90
+ }
91
+
92
+ const appliedSpeed = state.shift ? speedWithShift : speed;
93
+ const step = appliedSpeed * dt;
94
+
95
+ let dx = 0;
96
+ let dy = 0;
97
+ if (state.a) dx += step;
98
+ if (state.d) dx -= step;
99
+ if (state.w) dy += step;
100
+ if (state.s) dy -= step;
101
+
102
+ if (dx !== 0 || dy !== 0) {
103
+ const viewport = reactFlowInstance.getViewport();
104
+ reactFlowInstance.setViewport({
105
+ ...viewport,
106
+ x: viewport.x + dx,
107
+ y: viewport.y + dy
108
+ });
109
+ }
110
+
111
+ rafRef.current = requestAnimationFrame(tick);
112
+ };
113
+
114
+ rafRef.current = requestAnimationFrame(tick);
115
+ }, [
116
+ cancelPanLoop,
117
+ dtCapSeconds,
118
+ enabled,
119
+ getReactFlowInstance,
120
+ speed,
121
+ speedWithShift
122
+ ]);
123
+
124
+ useEffect(() => {
125
+ if (!enabled) {
126
+ wasdRef.current = {
127
+ w: false,
128
+ a: false,
129
+ s: false,
130
+ d: false,
131
+ shift: false
132
+ };
133
+ cancelPanLoop();
134
+ return;
135
+ }
136
+
137
+ const onKeyDown = (event: KeyboardEvent) => {
138
+ if (isEventFromEditable(event)) return;
139
+ if (event.ctrlKey || event.metaKey || event.altKey) return;
140
+
141
+ const key = event.key?.toLowerCase();
142
+ if (
143
+ key !== 'w' &&
144
+ key !== 'a' &&
145
+ key !== 's' &&
146
+ key !== 'd' &&
147
+ key !== 'shift'
148
+ ) {
149
+ return;
150
+ }
151
+
152
+ if (key === 'shift') {
153
+ wasdRef.current.shift = true;
154
+ return;
155
+ }
156
+
157
+ event.preventDefault();
158
+ event.stopPropagation();
159
+
160
+ if (key === 'w') wasdRef.current.w = true;
161
+ if (key === 'a') wasdRef.current.a = true;
162
+ if (key === 's') wasdRef.current.s = true;
163
+ if (key === 'd') wasdRef.current.d = true;
164
+
165
+ startPanLoop();
166
+ };
167
+
168
+ const onKeyUp = (event: KeyboardEvent) => {
169
+ const key = event.key?.toLowerCase();
170
+ if (key === 'shift') {
171
+ wasdRef.current.shift = false;
172
+ return;
173
+ }
174
+
175
+ if (key === 'w') wasdRef.current.w = false;
176
+ if (key === 'a') wasdRef.current.a = false;
177
+ if (key === 's') wasdRef.current.s = false;
178
+ if (key === 'd') wasdRef.current.d = false;
179
+
180
+ const state = wasdRef.current;
181
+ if (!(state.w || state.a || state.s || state.d)) {
182
+ cancelPanLoop();
183
+ }
184
+ };
185
+
186
+ const onBlur = () => {
187
+ wasdRef.current = {
188
+ w: false,
189
+ a: false,
190
+ s: false,
191
+ d: false,
192
+ shift: false
193
+ };
194
+ cancelPanLoop();
195
+ };
196
+
197
+ window.addEventListener('keydown', onKeyDown, { capture: true });
198
+ window.addEventListener('keyup', onKeyUp, { capture: true });
199
+ window.addEventListener('blur', onBlur);
200
+
201
+ return () => {
202
+ window.removeEventListener('keydown', onKeyDown, {
203
+ capture: true
204
+ });
205
+ window.removeEventListener('keyup', onKeyUp, { capture: true });
206
+ window.removeEventListener('blur', onBlur);
207
+ cancelPanLoop();
208
+ };
209
+ }, [cancelPanLoop, enabled, startPanLoop]);
210
+ };
package/src/index.css ADDED
@@ -0,0 +1,134 @@
1
+ @import "reactflow/dist/style.css";
2
+ @import 'rc-menu/assets/index.css';
3
+ @import "rc-dock/dist/rc-dock-dark.css";
4
+
5
+ @import "./css/vars.css";
6
+ @import "./css/themes/kiberon.css";
7
+ @import "./css/vscode-elements.css";
8
+ @import "./css/rc-dock.css";
9
+ @import "./css/rc-menu.css";
10
+ @import "./css/prosemirror.css";
11
+ @import "./css/notes.css";
12
+
13
+ *{
14
+ box-sizing: border-box;
15
+ }
16
+
17
+ .reactflow {
18
+ background: #262626;
19
+ color: var(--colors-fg);
20
+ position: static !important;
21
+ }
22
+
23
+
24
+ .react-flow__node {
25
+ display: flex;
26
+
27
+ &.filtered {
28
+ opacity: 0.25 !important;
29
+ }
30
+ }
31
+
32
+ .react-flow__edge-default {
33
+ fill: none;
34
+ }
35
+
36
+ .react-flow__handle>* {
37
+ /* Don't allow blocking of the handle */
38
+ user-select: none;
39
+ pointer-events: none;
40
+ flex: 1;
41
+ }
42
+
43
+ .react-flow__handle {
44
+ display: flex;
45
+ align-items: center;
46
+ font-size: 8px;
47
+ width: 16px;
48
+ height: 16px;
49
+ border-radius: 4px;
50
+ }
51
+
52
+ .react-flow__handle-left {
53
+
54
+ left: -12px;
55
+ }
56
+
57
+ .react-flow__handle-right {
58
+
59
+ right: -12px;
60
+ }
61
+
62
+ .dock-content-holder {
63
+ color: var(--colors-fg);
64
+ }
65
+
66
+ /* rc-menu styling lives in css/rc-menu.css */
67
+
68
+
69
+ .container {
70
+ display: flex;
71
+ flex-direction: row;
72
+ justify-content: space-between;
73
+ gap: 2rem;
74
+ position: relative;
75
+ padding: 0 0.5rem;
76
+ }
77
+
78
+
79
+ .dock-tab {
80
+ display: flex;
81
+ align-items: center;
82
+ }
83
+
84
+ .dock-top .dock-bar {
85
+ border-bottom: none;
86
+ }
87
+
88
+ .dock-panel.dock-style-main .dock-bar {
89
+ border-bottom-color: var(--color-neutral-stroke-subtle);
90
+ }
91
+
92
+ .dock-content-holder {
93
+ scrollbar-color: var(--color-neutral-canvas-subtle-bg) transparent;
94
+ scrollbar-width: thin;
95
+ border-bottom: var(--component-border-width-md) solid var(--color-neutral-stroke-subtle);
96
+ }
97
+
98
+ .dock-top .dock-ink-bar {
99
+ background: var(--colors-bgCanvas);
100
+ z-index: 0;
101
+ height: 100%;
102
+ border-radius: var(--component-radii-sm);
103
+ }
104
+
105
+
106
+ /* Dark scrollbars for all elements */
107
+ * {
108
+ scrollbar-width: thin;
109
+ scrollbar-color: #4a4a4a #262626;
110
+ }
111
+
112
+ /* Webkit browsers (Chrome, Safari, Edge) */
113
+ *::-webkit-scrollbar {
114
+ width: 8px;
115
+ height: 8px;
116
+ }
117
+
118
+ *::-webkit-scrollbar-track {
119
+ background: #262626;
120
+ border-radius: 4px;
121
+ }
122
+
123
+ *::-webkit-scrollbar-thumb {
124
+ background: #4a4a4a;
125
+ border-radius: 4px;
126
+ }
127
+
128
+ *::-webkit-scrollbar-thumb:hover {
129
+ background: #5a5a5a;
130
+ }
131
+
132
+ *::-webkit-scrollbar-corner {
133
+ background: #262626;
134
+ }