symbiote-ui 0.3.0-alpha.4

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 (322) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/LICENSE +21 -0
  3. package/README.md +76 -0
  4. package/canvas/AutoLayout.js +731 -0
  5. package/canvas/Breadcrumb/Breadcrumb.css.js +75 -0
  6. package/canvas/Breadcrumb/Breadcrumb.js +96 -0
  7. package/canvas/Breadcrumb/Breadcrumb.tpl.js +7 -0
  8. package/canvas/CanvasConnectionRenderer.js +971 -0
  9. package/canvas/CanvasGraph/CanvasGraph.css.js +29 -0
  10. package/canvas/CanvasGraph/CanvasGraph.js +1697 -0
  11. package/canvas/CanvasGraph/CanvasGraphDrawState.js +280 -0
  12. package/canvas/CanvasGraph/CanvasGraphGeometry.js +194 -0
  13. package/canvas/CanvasViewport.js +550 -0
  14. package/canvas/ConnectionRenderer.js +1283 -0
  15. package/canvas/FlowSimulator.js +326 -0
  16. package/canvas/ForceLayout.js +226 -0
  17. package/canvas/ForceWorker.js +1303 -0
  18. package/canvas/FrameManager.js +223 -0
  19. package/canvas/GraphExplorerShell/GraphExplorerShell.css.js +136 -0
  20. package/canvas/GraphExplorerShell/GraphExplorerShell.js +129 -0
  21. package/canvas/GraphExplorerShell/GraphExplorerShell.tpl.js +12 -0
  22. package/canvas/GraphTabs/GraphTabs.css.js +101 -0
  23. package/canvas/GraphTabs/GraphTabs.js +189 -0
  24. package/canvas/GraphTabs/GraphTabs.tpl.js +12 -0
  25. package/canvas/LODManager.js +88 -0
  26. package/canvas/Minimap/Minimap.css.js +73 -0
  27. package/canvas/Minimap/Minimap.js +210 -0
  28. package/canvas/Minimap/Minimap.tpl.js +7 -0
  29. package/canvas/NodeCanvas/NodeCanvas.css.js +398 -0
  30. package/canvas/NodeCanvas/NodeCanvas.js +1499 -0
  31. package/canvas/NodeCanvas/NodeCanvas.tpl.js +22 -0
  32. package/canvas/NodeSearch/NodeSearch.css.js +97 -0
  33. package/canvas/NodeSearch/NodeSearch.js +140 -0
  34. package/canvas/NodeSearch/NodeSearch.tpl.js +25 -0
  35. package/canvas/NodeViewManager.js +748 -0
  36. package/canvas/PcbRouteDiagnostics.js +463 -0
  37. package/canvas/PcbRouter.js +1127 -0
  38. package/canvas/PinExpansion.js +134 -0
  39. package/canvas/PseudoConnection.js +84 -0
  40. package/canvas/SelectionSync.js +163 -0
  41. package/canvas/SubgraphManager.js +203 -0
  42. package/canvas/SubgraphRouter.js +452 -0
  43. package/canvas/ViewportActions.js +473 -0
  44. package/canvas/graph-explorer.js +339 -0
  45. package/canvas/graph-layout.js +148 -0
  46. package/canvas/graph-model.js +68 -0
  47. package/canvas/html-in-canvas.js +202 -0
  48. package/canvas/project-graph-builder.js +440 -0
  49. package/canvas/project-graph-model.js +183 -0
  50. package/chat/ChatComposer/ChatComposer.css.js +652 -0
  51. package/chat/ChatComposer/ChatComposer.js +304 -0
  52. package/chat/ChatList/ChatList.css.js +102 -0
  53. package/chat/ChatList/ChatList.js +99 -0
  54. package/chat/ChatList/ChatList.tpl.js +20 -0
  55. package/chat/ChatListItem/ChatListItem.css.js +117 -0
  56. package/chat/ChatListItem/ChatListItem.js +32 -0
  57. package/chat/ChatListItem/ChatListItem.tpl.js +17 -0
  58. package/chat/ChatMessageItem/ChatMessageItem.css.js +628 -0
  59. package/chat/ChatMessageItem/ChatMessageItem.js +156 -0
  60. package/chat/ChatSidebar/ChatSidebar.css.js +150 -0
  61. package/chat/ChatSidebar/ChatSidebar.js +230 -0
  62. package/chat/ChatSidebar/ChatSidebar.tpl.js +18 -0
  63. package/chat/ChatSidebar/constants.js +11 -0
  64. package/chat/ChatSidebarItem/ChatSidebarItem.css.js +445 -0
  65. package/chat/ChatSidebarItem/ChatSidebarItem.js +304 -0
  66. package/chat/ChatTranscript/ChatTranscript.css.js +90 -0
  67. package/chat/ChatTranscript/ChatTranscript.js +244 -0
  68. package/chat/chat-context.js +123 -0
  69. package/chat/message-model.js +156 -0
  70. package/cli.js +20 -0
  71. package/control/Button/Button.css.js +93 -0
  72. package/control/Button/Button.js +78 -0
  73. package/control/Button/Button.tpl.js +3 -0
  74. package/control/Field/Field.css.js +91 -0
  75. package/control/Field/Field.js +17 -0
  76. package/control/Field/Field.tpl.js +3 -0
  77. package/core/Connection.js +47 -0
  78. package/core/Editor.js +449 -0
  79. package/core/Frame.js +33 -0
  80. package/core/GraphMermaid.js +348 -0
  81. package/core/GraphText.js +228 -0
  82. package/core/Node.js +145 -0
  83. package/core/Portal.js +106 -0
  84. package/core/Socket.js +187 -0
  85. package/core/SubgraphNode.js +121 -0
  86. package/core/base-path.js +55 -0
  87. package/core/dom-utils.js +14 -0
  88. package/core/index.js +18 -0
  89. package/core/local-cache.js +26 -0
  90. package/core/state-sync.js +227 -0
  91. package/custom-elements.json +6380 -0
  92. package/discover.js +240 -0
  93. package/display/Badge/Badge.css.js +44 -0
  94. package/display/Badge/Badge.js +17 -0
  95. package/display/Badge/Badge.tpl.js +3 -0
  96. package/display/Banner/Banner.css.js +61 -0
  97. package/display/Banner/Banner.js +17 -0
  98. package/display/Banner/Banner.tpl.js +3 -0
  99. package/display/CodeBlock/CodeBlock.css.js +194 -0
  100. package/display/CodeBlock/CodeBlock.js +220 -0
  101. package/display/CodeBlock/CodeBlock.tpl.js +11 -0
  102. package/display/DataTable/DataTable.css.js +101 -0
  103. package/display/DataTable/DataTable.js +136 -0
  104. package/display/DataTable/DataTable.tpl.js +13 -0
  105. package/display/EmptyState/EmptyState.css.js +33 -0
  106. package/display/EmptyState/EmptyState.js +17 -0
  107. package/display/EmptyState/EmptyState.tpl.js +3 -0
  108. package/display/EventFeed/EventFeed.css.js +145 -0
  109. package/display/EventFeed/EventFeed.js +64 -0
  110. package/display/EventFeed/EventFeed.tpl.js +14 -0
  111. package/display/EventFeed/EventFeedItem.js +116 -0
  112. package/display/EventFeed/EventFeedItem.tpl.js +22 -0
  113. package/display/LoadingOverlay/LoadingOverlay.css.js +91 -0
  114. package/display/LoadingOverlay/LoadingOverlay.js +48 -0
  115. package/display/LoadingOverlay/LoadingOverlay.tpl.js +12 -0
  116. package/display/Metric/Metric.css.js +60 -0
  117. package/display/Metric/Metric.js +17 -0
  118. package/display/Metric/Metric.tpl.js +6 -0
  119. package/display/OutputGraphPreview/OutputGraphPreview.css.js +122 -0
  120. package/display/OutputGraphPreview/OutputGraphPreview.js +89 -0
  121. package/display/OutputGraphPreview/OutputGraphPreview.tpl.js +13 -0
  122. package/display/OutputListPreview/OutputListPreview.css.js +109 -0
  123. package/display/OutputListPreview/OutputListPreview.js +77 -0
  124. package/display/OutputListPreview/OutputListPreview.tpl.js +13 -0
  125. package/display/SourceEditor/SourceEditor.css.js +39 -0
  126. package/display/SourceEditor/SourceEditor.js +129 -0
  127. package/display/SourceEditor/SourceEditor.tpl.js +10 -0
  128. package/display/SourceViewer/SourceViewer.css.js +80 -0
  129. package/display/SourceViewer/SourceViewer.js +418 -0
  130. package/display/SourceViewer/SourceViewer.tpl.js +17 -0
  131. package/display/StatusRibbon/StatusRibbon.css.js +73 -0
  132. package/display/StatusRibbon/StatusRibbon.js +87 -0
  133. package/display/StatusRibbon/StatusRibbon.tpl.js +7 -0
  134. package/display/event-feed-adapter.js +72 -0
  135. package/display/format-utils.js +29 -0
  136. package/display/highlight.js +659 -0
  137. package/display/icons.js +37 -0
  138. package/display/markdown-formatter.js +60 -0
  139. package/display/network-approval-page.js +487 -0
  140. package/display/output-preview.js +261 -0
  141. package/effects/CellBg/CellBg.css.js +33 -0
  142. package/effects/CellBg/CellBg.js +410 -0
  143. package/effects/CellBg/CellBg.tpl.js +5 -0
  144. package/graph/canvas-adapter.js +223 -0
  145. package/graph/graph-algorithms.js +31 -0
  146. package/graph/index.js +46 -0
  147. package/graph/model.js +176 -0
  148. package/graph/project-graph-build.js +66 -0
  149. package/graph/project-graph-metadata.js +253 -0
  150. package/graph/project-package.js +128 -0
  151. package/graph/project-runtime.js +116 -0
  152. package/graph/project-transaction.js +284 -0
  153. package/graph/skeleton-utils.js +84 -0
  154. package/graph/theme-contract.js +36 -0
  155. package/graph/transaction-parser.js +56 -0
  156. package/icons/MaterialSymbols.js +69 -0
  157. package/icons/material-symbols-outlined-400.ttf +0 -0
  158. package/icons/material-symbols.css +24 -0
  159. package/index.js +95 -0
  160. package/inspector/InspectorPanel/InspectorPanel.css.js +375 -0
  161. package/inspector/InspectorPanel/InspectorPanel.js +368 -0
  162. package/inspector/InspectorPanel/InspectorPanel.tpl.js +96 -0
  163. package/inspector/TemplatePreview/TemplatePreview.css.js +104 -0
  164. package/inspector/TemplatePreview/TemplatePreview.js +145 -0
  165. package/inspector/TemplatePreview/TemplatePreview.tpl.js +33 -0
  166. package/interactions/ConnectFlow.js +304 -0
  167. package/interactions/Drag.js +104 -0
  168. package/interactions/Selector.js +133 -0
  169. package/interactions/SnapGrid.js +66 -0
  170. package/interactions/Zoom.js +139 -0
  171. package/layout/ActionZone/ActionZone.css.js +88 -0
  172. package/layout/ActionZone/ActionZone.js +261 -0
  173. package/layout/ActionZone/ActionZone.tpl.js +11 -0
  174. package/layout/CrossLayoutPortalBridge/CrossLayoutPortalBridge.js +255 -0
  175. package/layout/Layout/Layout.css.js +91 -0
  176. package/layout/Layout/Layout.js +637 -0
  177. package/layout/Layout/Layout.tpl.js +27 -0
  178. package/layout/LayoutNode/LayoutNode.css.js +302 -0
  179. package/layout/LayoutNode/LayoutNode.js +509 -0
  180. package/layout/LayoutNode/LayoutNode.tpl.js +39 -0
  181. package/layout/LayoutPreview/LayoutPreview.css.js +46 -0
  182. package/layout/LayoutPreview/LayoutPreview.js +102 -0
  183. package/layout/LayoutPreview/LayoutPreview.tpl.js +6 -0
  184. package/layout/LayoutRouter/LayoutRouter.js +274 -0
  185. package/layout/LayoutRouter/SectionRegistry.js +135 -0
  186. package/layout/LayoutRouter/routerSync.js +250 -0
  187. package/layout/LayoutSidebar/LayoutSidebar.css.js +411 -0
  188. package/layout/LayoutSidebar/LayoutSidebar.js +368 -0
  189. package/layout/LayoutSidebar/LayoutSidebar.tpl.js +26 -0
  190. package/layout/LayoutSidebar/SidebarSection.css.js +20 -0
  191. package/layout/LayoutSidebar/SidebarSection.js +184 -0
  192. package/layout/LayoutSidebar/SidebarSection.tpl.js +22 -0
  193. package/layout/LayoutTree.js +373 -0
  194. package/layout/PanelMenu/PanelMenu.css.js +43 -0
  195. package/layout/PanelMenu/PanelMenu.js +95 -0
  196. package/layout/PanelMenu/PanelMenu.tpl.js +17 -0
  197. package/layout/ProjectTabs/ProjectTabs.css.js +188 -0
  198. package/layout/ProjectTabs/ProjectTabs.js +77 -0
  199. package/layout/ProjectTabs/ProjectTabs.tpl.js +15 -0
  200. package/layout/index.js +40 -0
  201. package/list/ListDetailShell/ListDetailShell.css.js +128 -0
  202. package/list/ListDetailShell/ListDetailShell.js +72 -0
  203. package/list/ListDetailShell/ListDetailShell.tpl.js +36 -0
  204. package/list/ListItem/ListItem.css.js +111 -0
  205. package/list/ListItem/ListItem.js +66 -0
  206. package/list/ListItem/ListItem.tpl.js +18 -0
  207. package/locale/index.js +503 -0
  208. package/manifest/component-registry.js +2446 -0
  209. package/manifest/graph-schema.js +285 -0
  210. package/manifest/index.js +6 -0
  211. package/manifest/project-schema-catalog.js +246 -0
  212. package/manifest/rule-catalog.js +201 -0
  213. package/manifest/theme-catalog.js +2149 -0
  214. package/manifest/ui-schema-catalog.js +334 -0
  215. package/menu/ContextMenu/ContextMenu.css.js +61 -0
  216. package/menu/ContextMenu/ContextMenu.js +82 -0
  217. package/menu/ContextMenu/ContextMenu.tpl.js +19 -0
  218. package/navigation/QuickOpen/QuickOpen.css.js +92 -0
  219. package/navigation/QuickOpen/QuickOpen.js +185 -0
  220. package/navigation/QuickOpen/QuickOpen.tpl.js +15 -0
  221. package/navigation/quick-open-utils.js +101 -0
  222. package/node/CtrlItem/CtrlItem.css.js +41 -0
  223. package/node/CtrlItem/CtrlItem.js +24 -0
  224. package/node/CtrlItem/CtrlItem.tpl.js +17 -0
  225. package/node/GraphFrame/GraphFrame.css.js +66 -0
  226. package/node/GraphFrame/GraphFrame.js +32 -0
  227. package/node/GraphFrame/GraphFrame.tpl.js +13 -0
  228. package/node/GraphNode/GraphNode.css.js +815 -0
  229. package/node/GraphNode/GraphNode.js +173 -0
  230. package/node/GraphNode/GraphNode.tpl.js +33 -0
  231. package/node/NodeCallout/NodeCallout.css.js +91 -0
  232. package/node/NodeCallout/NodeCallout.js +281 -0
  233. package/node/NodeCallout/NodeCallout.tpl.js +8 -0
  234. package/node/NodeSocket/NodeSocket.css.js +68 -0
  235. package/node/NodeSocket/NodeSocket.js +26 -0
  236. package/node/NodeSocket/NodeSocket.tpl.js +7 -0
  237. package/node/PortItem/PortItem.css.js +93 -0
  238. package/node/PortItem/PortItem.js +87 -0
  239. package/node/PortItem/PortItem.tpl.js +10 -0
  240. package/package.json +165 -0
  241. package/palette/PaletteBrowser/PaletteBrowser.css.js +143 -0
  242. package/palette/PaletteBrowser/PaletteBrowser.js +152 -0
  243. package/palette/PaletteBrowser/PaletteBrowser.tpl.js +23 -0
  244. package/plugins/History.js +408 -0
  245. package/plugins/Readonly.js +60 -0
  246. package/rules/symbiote-3x.json +170 -0
  247. package/schemas/component-descriptor-v1.json +91 -0
  248. package/schemas/component-descriptor-v2.json +145 -0
  249. package/schemas/graph-model-v1.json +179 -0
  250. package/schemas/graph-v1.json +91 -0
  251. package/schemas/project-package-v1.json +102 -0
  252. package/schemas/project-transaction-v1.json +114 -0
  253. package/schemas/runtime-ui-v1.json +80 -0
  254. package/schemas/theme-rule-block-v1.json +73 -0
  255. package/shapes/CircleShape.js +79 -0
  256. package/shapes/CommentShape.js +35 -0
  257. package/shapes/DiamondShape.js +130 -0
  258. package/shapes/NodeShape.js +79 -0
  259. package/shapes/PillShape.js +91 -0
  260. package/shapes/RectShape.js +84 -0
  261. package/shapes/SVGShape.js +525 -0
  262. package/shapes/index.js +63 -0
  263. package/surface/Card/Card.css.js +57 -0
  264. package/surface/Card/Card.js +17 -0
  265. package/surface/Card/Card.tpl.js +3 -0
  266. package/themes/Palette.js +30 -0
  267. package/themes/Skin.js +113 -0
  268. package/themes/Theme.js +82 -0
  269. package/themes/carbon.js +135 -0
  270. package/themes/dark.js +140 -0
  271. package/themes/default-dark.js +714 -0
  272. package/themes/default-provider.css +635 -0
  273. package/themes/default-provider.js +718 -0
  274. package/themes/ebook.js +136 -0
  275. package/themes/grey.js +137 -0
  276. package/themes/light.js +139 -0
  277. package/themes/neon.js +138 -0
  278. package/themes/pcb.js +273 -0
  279. package/themes/synthwave.js +138 -0
  280. package/tokens/base.json +29 -0
  281. package/tokens/themes/carbon.json +11 -0
  282. package/tokens/themes/dark.json +12 -0
  283. package/tokens/themes/default-dark.json +1543 -0
  284. package/tokens/themes/default-provider.json +1543 -0
  285. package/tokens/themes/ebook.json +11 -0
  286. package/tokens/themes/grey.json +11 -0
  287. package/tokens/themes/light.json +12 -0
  288. package/tokens/themes/neon.json +11 -0
  289. package/tokens/themes/pcb.json +11 -0
  290. package/tokens/themes/synthwave.json +11 -0
  291. package/toolbar/QuickToolbar/QuickToolbar.css.js +152 -0
  292. package/toolbar/QuickToolbar/QuickToolbar.js +529 -0
  293. package/toolbar/QuickToolbar/QuickToolbar.tpl.js +34 -0
  294. package/tree/TreePanel/TreePanel.css.js +112 -0
  295. package/tree/TreePanel/TreePanel.js +147 -0
  296. package/tree/TreePanel/TreePanel.tpl.js +18 -0
  297. package/tree/TreeView/TreeView.css.js +122 -0
  298. package/tree/TreeView/TreeView.js +365 -0
  299. package/tree/TreeView/TreeView.tpl.js +10 -0
  300. package/ui/dialogs.js +221 -0
  301. package/ui/host-adapters.js +114 -0
  302. package/ui/index.js +660 -0
  303. package/ui/locale.js +50 -0
  304. package/ui/overlay-stack.js +89 -0
  305. package/ui/shared-styles.js +26 -0
  306. package/webmcp.js +37 -0
  307. package/xr/deep-graph.js +646 -0
  308. package/xr/emulation.js +198 -0
  309. package/xr/gesture.js +228 -0
  310. package/xr/html-canvas-renderer.js +472 -0
  311. package/xr/index.js +15 -0
  312. package/xr/layout-projection.js +1046 -0
  313. package/xr/panel-frame.js +128 -0
  314. package/xr/panel-host.js +267 -0
  315. package/xr/pointer.js +258 -0
  316. package/xr/scene-controller.js +242 -0
  317. package/xr/spatial-scene.js +212 -0
  318. package/xr/theme-bridge.js +105 -0
  319. package/xr/three-webxr-adapter.js +3439 -0
  320. package/xr/webgl-layer-renderer.js +419 -0
  321. package/xr/webxr.js +679 -0
  322. package/xr/workbench.js +516 -0
package/core/Portal.js ADDED
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Portal — Named Reroutes for wireless connections
3
+ *
4
+ * Provides virtual sender/receiver pairs that act as invisible
5
+ * connections. PortalManager tracks named channels and resolves
6
+ * portal connections during graph evaluation.
7
+ *
8
+ * Usage:
9
+ * const pm = new PortalManager();
10
+ * pm.addSender('channelA', node1, 'output');
11
+ * pm.addReceiver('channelA', node2, 'input');
12
+ * pm.getConnections(); // returns virtual connections
13
+ *
14
+ * @module symbiote-node/core/Portal
15
+ */
16
+
17
+ /**
18
+ * PortalManager — manages named reroute channels
19
+ */
20
+ export class PortalManager {
21
+ /** @type {Map<string, { senders: Array<{nodeId: string, portKey: string}>, receivers: Array<{nodeId: string, portKey: string}> }>} */
22
+ #channels = new Map();
23
+
24
+ /**
25
+ * Register a sender portal
26
+ * @param {string} channel - Named channel
27
+ * @param {string} nodeId - Source node ID
28
+ * @param {string} portKey - Output port key
29
+ */
30
+ addSender(channel, nodeId, portKey) {
31
+ if (!this.#channels.has(channel)) {
32
+ this.#channels.set(channel, { senders: [], receivers: [] });
33
+ }
34
+ this.#channels.get(channel).senders.push({ nodeId, portKey });
35
+ }
36
+
37
+ /**
38
+ * Register a receiver portal
39
+ * @param {string} channel - Named channel
40
+ * @param {string} nodeId - Target node ID
41
+ * @param {string} portKey - Input port key
42
+ */
43
+ addReceiver(channel, nodeId, portKey) {
44
+ if (!this.#channels.has(channel)) {
45
+ this.#channels.set(channel, { senders: [], receivers: [] });
46
+ }
47
+ this.#channels.get(channel).receivers.push({ nodeId, portKey });
48
+ }
49
+
50
+ /**
51
+ * Remove all portals for a node
52
+ * @param {string} nodeId
53
+ */
54
+ removeNode(nodeId) {
55
+ for (const [, ch] of this.#channels) {
56
+ ch.senders = ch.senders.filter((s) => s.nodeId !== nodeId);
57
+ ch.receivers = ch.receivers.filter((r) => r.nodeId !== nodeId);
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Get all virtual connections from portal channels
63
+ * @returns {Array<{ from: string, out: string, to: string, in: string, channel: string }>}
64
+ */
65
+ getConnections() {
66
+ let result = [];
67
+ for (const [channel, ch] of this.#channels) {
68
+ for (const sender of ch.senders) {
69
+ for (const receiver of ch.receivers) {
70
+ result.push({
71
+ from: sender.nodeId,
72
+ out: sender.portKey,
73
+ to: receiver.nodeId,
74
+ in: receiver.portKey,
75
+ channel,
76
+ });
77
+ }
78
+ }
79
+ }
80
+ return result;
81
+ }
82
+
83
+ /**
84
+ * Get all channel names
85
+ * @returns {string[]}
86
+ */
87
+ getChannels() {
88
+ return [...this.#channels.keys()];
89
+ }
90
+
91
+ /**
92
+ * Get channel info
93
+ * @param {string} channel
94
+ * @returns {{ senders: Array, receivers: Array }|undefined}
95
+ */
96
+ getChannel(channel) {
97
+ return this.#channels.get(channel);
98
+ }
99
+
100
+ /** Clear all portals */
101
+ clear() {
102
+ this.#channels.clear();
103
+ }
104
+ }
105
+
106
+ export { PortalManager as default };
package/core/Socket.js ADDED
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Socket — typed port connector
3
+ *
4
+ * Defines the type and visual identity of a connection endpoint.
5
+ * Compatible with symbiote-node SocketTypes system.
6
+ *
7
+ * @module symbiote-node/core/Socket
8
+ */
9
+
10
+ let _uid = 0;
11
+
12
+ /**
13
+ * Generate unique ID with prefix
14
+ * @param {string} prefix
15
+ * @returns {string}
16
+ */
17
+ export function uid(prefix = 'id') {
18
+ return `${prefix}_${(++_uid).toString(36)}_${Date.now().toString(36)}`;
19
+ }
20
+
21
+ /**
22
+ * Socket type — defines connection endpoint type
23
+ */
24
+ export class Socket {
25
+ /**
26
+ * @param {string} name - Socket type name (e.g. 'number', 'string', 'any')
27
+ * @param {object} [options]
28
+ * @param {string} [options.color] - CSS color for visual
29
+ */
30
+ constructor(name, options = {}) {
31
+ /** @type {string} */
32
+ this.name = name;
33
+
34
+ /** @type {string} */
35
+ this.color = options.color || 'var(--clr-3)';
36
+ }
37
+
38
+ /**
39
+ * Check if this socket is compatible with another
40
+ * @param {Socket} other
41
+ * @returns {boolean}
42
+ */
43
+ isCompatibleWith(other) {
44
+ if (this.name === 'any' || other.name === 'any') return true;
45
+ return this.name === other.name;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Port — represents an input or output endpoint on a node
51
+ */
52
+ export class Port {
53
+ /**
54
+ * @param {Socket} socket - Socket type
55
+ * @param {string} [label] - Display label
56
+ * @param {boolean} [multipleConnections=false] - Allow multiple connections
57
+ */
58
+ constructor(socket, label, multipleConnections = false) {
59
+ /** @type {string} */
60
+ this.id = uid('port');
61
+
62
+ /** @type {Socket} */
63
+ this.socket = socket;
64
+
65
+ /** @type {string|undefined} */
66
+ this.label = label;
67
+
68
+ /** @type {boolean} */
69
+ this.multipleConnections = multipleConnections;
70
+
71
+ /** @type {number} */
72
+ this.index = 0;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Input port — accepts incoming connections
78
+ */
79
+ export class Input extends Port {
80
+ /**
81
+ * @param {Socket} socket
82
+ * @param {string} [label]
83
+ * @param {boolean} [multipleConnections=false]
84
+ */
85
+ constructor(socket, label, multipleConnections = false) {
86
+ super(socket, label, multipleConnections);
87
+
88
+ /** @type {Control|null} */
89
+ this.control = null;
90
+
91
+ /** @type {boolean} */
92
+ this.showControl = true;
93
+ }
94
+
95
+ /**
96
+ * Add embedded control to this input
97
+ * @param {Control} control
98
+ */
99
+ addControl(control) {
100
+ if (this.control) throw new Error('control already added for this input');
101
+ this.control = control;
102
+ }
103
+
104
+ /**
105
+ * Remove embedded control
106
+ */
107
+ removeControl() {
108
+ this.control = null;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Output port — provides outgoing connections
114
+ */
115
+ export class Output extends Port {
116
+ /**
117
+ * @param {Socket} socket
118
+ * @param {string} [label]
119
+ * @param {boolean} [multipleConnections=true]
120
+ */
121
+ constructor(socket, label, multipleConnections = true) {
122
+ super(socket, label, multipleConnections);
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Control — embeddable UI widget inside a node
128
+ */
129
+ export class Control {
130
+ constructor() {
131
+ /** @type {string} */
132
+ this.id = uid('ctrl');
133
+
134
+ /** @type {number} */
135
+ this.index = 0;
136
+
137
+ /** @type {function|undefined} */
138
+ this._onChange = undefined;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * InputControl — text or number input widget
144
+ */
145
+ export class InputControl extends Control {
146
+ /**
147
+ * @param {'text'|'number'|'textarea'|'select'|'boolean'} type
148
+ * @param {object} [options]
149
+ * @param {boolean} [options.readonly=false]
150
+ * @param {string|number|boolean} [options.initial]
151
+ * @param {string} [options.label] - Display label
152
+ * @param {string[]} [options.options] - Options for select type
153
+ * @param {function} [options.change] - Callback on value change
154
+ */
155
+ constructor(type, options = {}) {
156
+ super();
157
+
158
+ /** @type {'text'|'number'|'textarea'|'select'|'boolean'} */
159
+ this.type = type;
160
+
161
+ /** @type {boolean} */
162
+ this.readonly = options.readonly || false;
163
+
164
+ /** @type {string|number|boolean|undefined} */
165
+ this.value = options.initial;
166
+
167
+ /** @type {string} */
168
+ this.label = options.label || '';
169
+
170
+ /** @type {string[]} */
171
+ this.options = options.options || [];
172
+
173
+ /** @type {function|undefined} */
174
+ this._onChange = options.change;
175
+ }
176
+
177
+ /**
178
+ * Set control value
179
+ * @param {string|number|boolean} value
180
+ */
181
+ setValue(value) {
182
+ this.value = value;
183
+ if (this._onChange) this._onChange(value);
184
+ }
185
+ }
186
+
187
+ export { Socket as default };
@@ -0,0 +1,121 @@
1
+ /**
2
+ * SubgraphNode — Node containing an embedded graph
3
+ *
4
+ * Extends Node with an inner NodeEditor that holds a sub-pipeline.
5
+ * Ports are auto-generated from exposed inner nodes.
6
+ * Supports drill-down navigation via SubgraphManager.
7
+ *
8
+ * @module symbiote-node/core/SubgraphNode
9
+ */
10
+
11
+ import { Node } from './Node.js';
12
+ import { NodeEditor } from './Editor.js';
13
+ import { Socket, Input, Output } from './Socket.js';
14
+
15
+ export class SubgraphNode extends Node {
16
+ /** @type {NodeEditor} */
17
+ innerEditor;
18
+
19
+ /** @type {Object<string, { x: number, y: number }>} */
20
+ innerPositions = {};
21
+
22
+ /** @type {{ panX: number, panY: number, zoom: number }} */
23
+ innerTransform = { panX: 0, panY: 0, zoom: 1 };
24
+
25
+ /**
26
+ * @param {string} label - Display name
27
+ * @param {object} [options={}]
28
+ * @param {string} [options.category='subgraph']
29
+ * @param {string} [options.icon='account_tree']
30
+ */
31
+ constructor(label, options = {}) {
32
+ super(label, {
33
+ type: 'subgraph',
34
+ category: options.category ?? 'subgraph',
35
+ icon: options.icon ?? 'account_tree',
36
+ shape: 'rect',
37
+ ...options,
38
+ });
39
+
40
+ this.innerEditor = new NodeEditor();
41
+ this._isSubgraph = true;
42
+ }
43
+
44
+ /**
45
+ * Sync external ports with inner graph exposed nodes.
46
+ * Inner nodes with `_exposed: 'input'` become subgraph inputs.
47
+ * Inner nodes with `_exposed: 'output'` become subgraph outputs.
48
+ */
49
+ syncPorts() {
50
+
51
+ for (const key of Object.keys(this.inputs)) {
52
+ if (key.startsWith('sg_')) this.removeInput(key);
53
+ }
54
+ for (const key of Object.keys(this.outputs)) {
55
+ if (key.startsWith('sg_')) this.removeOutput(key);
56
+ }
57
+
58
+ let anySocket = new Socket('any', { color: '#94a3b8' });
59
+
60
+
61
+ for (const innerNode of this.innerEditor.getNodes()) {
62
+ if (innerNode._exposed === 'input') {
63
+ for (const [key, output] of Object.entries(innerNode.outputs)) {
64
+ let portKey = `sg_${innerNode.id}_${key}`;
65
+ this.addInput(portKey, new Input(output.socket ?? anySocket, innerNode.label ?? key));
66
+ }
67
+ }
68
+ if (innerNode._exposed === 'output') {
69
+ for (const [key, input] of Object.entries(innerNode.inputs)) {
70
+ let portKey = `sg_${innerNode.id}_${key}`;
71
+ this.addOutput(portKey, new Output(input.socket ?? anySocket, innerNode.label ?? key));
72
+ }
73
+ }
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Get inner editor
79
+ * @returns {NodeEditor}
80
+ */
81
+ getInnerEditor() {
82
+ return this.innerEditor;
83
+ }
84
+
85
+ /**
86
+ * Save inner node positions
87
+ * @param {Object<string, { x: number, y: number }>} positions
88
+ */
89
+ setInnerPositions(positions) {
90
+ this.innerPositions = { ...positions };
91
+ }
92
+
93
+ /**
94
+ * Save inner viewport transform
95
+ * @param {{ panX: number, panY: number, zoom: number }} transform
96
+ */
97
+ setInnerTransform(transform) {
98
+ this.innerTransform = { ...transform };
99
+ }
100
+
101
+ /**
102
+ * Serialize subgraph node including inner graph
103
+ * @returns {object}
104
+ */
105
+ toJSON() {
106
+ return {
107
+ id: this.id,
108
+ type: 'subgraph',
109
+ label: this.label,
110
+ category: this.category,
111
+ innerGraph: this.innerEditor.toJSON(
112
+ Object.fromEntries(
113
+ Object.entries(this.innerPositions).map(([id, pos]) => [id, [pos.x, pos.y]])
114
+ )
115
+ ),
116
+ innerTransform: this.innerTransform,
117
+ };
118
+ }
119
+ }
120
+
121
+ export { SubgraphNode as default };
@@ -0,0 +1,55 @@
1
+ const apiPrefixes = ['/api/', '/ws/']
2
+
3
+ export function getAppBasePath() {
4
+ const baseEl = document.querySelector('base[href]')
5
+ if (!baseEl) return ''
6
+ const baseUrl = new URL(baseEl.href, window.location.href)
7
+ if (baseUrl.origin !== window.location.origin) return ''
8
+ const path = baseUrl.pathname.replace(/\/$/, '')
9
+ return path === '' || path === '/' ? '' : path
10
+ }
11
+
12
+ export function withAppBasePath(value, protocol = window.location.protocol) {
13
+ const basePath = getAppBasePath()
14
+ if (!basePath || typeof value !== 'string') return value
15
+
16
+ if (apiPrefixes.some((prefix) => value.startsWith(prefix))) {
17
+ return `${basePath}${value}`
18
+ }
19
+
20
+ if (value.startsWith(`${window.location.origin}/`)) {
21
+ const url = new URL(value)
22
+ if (apiPrefixes.some((prefix) => url.pathname.startsWith(prefix))) {
23
+ url.pathname = `${basePath}${url.pathname}`
24
+ return url.toString()
25
+ }
26
+ }
27
+
28
+ if ((protocol === 'ws:' || protocol === 'wss:') && /^wss?:\/\//.test(value)) {
29
+ const url = new URL(value)
30
+ if (url.host === window.location.host && apiPrefixes.some((prefix) => url.pathname.startsWith(prefix))) {
31
+ url.pathname = `${basePath}${url.pathname}`
32
+ return url.toString()
33
+ }
34
+ }
35
+
36
+ return value
37
+ }
38
+
39
+ const nativeFetch = window.fetch.bind(window)
40
+ window.fetch = (input, init) => {
41
+ if (typeof input === 'string') {
42
+ return nativeFetch(withAppBasePath(input), init)
43
+ }
44
+ if (input instanceof URL) {
45
+ return nativeFetch(new URL(withAppBasePath(input.toString())), init)
46
+ }
47
+ return nativeFetch(input, init)
48
+ }
49
+
50
+ const NativeWebSocket = window.WebSocket
51
+ window.WebSocket = class PortalWebSocket extends NativeWebSocket {
52
+ constructor(url, protocols) {
53
+ super(withAppBasePath(String(url), new URL(String(url), window.location.href).protocol), protocols)
54
+ }
55
+ }
@@ -0,0 +1,14 @@
1
+ export function waitForElementApi(element, methodName, timeoutMs = 2000) {
2
+ if (!element || typeof element[methodName] === 'function') return Promise.resolve(element);
3
+ return new Promise((resolve) => {
4
+ let startedAt = Date.now();
5
+ function check() {
6
+ if (typeof element[methodName] === 'function' || Date.now() - startedAt >= timeoutMs) {
7
+ resolve(element);
8
+ return;
9
+ }
10
+ requestAnimationFrame(check);
11
+ }
12
+ check();
13
+ });
14
+ }
package/core/index.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Node-safe core API for symbiote-node.
3
+ *
4
+ * This entrypoint must not import browser custom elements or Symbiote UI modules.
5
+ */
6
+
7
+ export { NodeEditor } from './Editor.js';
8
+ export { Node } from './Node.js';
9
+ export { Connection } from './Connection.js';
10
+ export { Frame } from './Frame.js';
11
+ export { Socket, Port, Input, Output, Control, InputControl, uid } from './Socket.js';
12
+ export { editorToText, textToGraph, textToEditor } from './GraphText.js';
13
+ export { editorToMermaid, mermaidToGraph } from './GraphMermaid.js';
14
+ export { PortalManager } from './Portal.js';
15
+ export { SubgraphNode } from './SubgraphNode.js';
16
+ export { readJsonCache, writeJsonCache, readStringCache, writeStringCache } from './local-cache.js';
17
+ export { waitForElementApi } from './dom-utils.js';
18
+ export { createStateSync } from './state-sync.js';
@@ -0,0 +1,26 @@
1
+ export function readJsonCache(key) {
2
+ if (typeof localStorage === 'undefined') return undefined
3
+ let raw = localStorage.getItem(key)
4
+ if (raw == null) return undefined
5
+ try {
6
+ return JSON.parse(raw)
7
+ } catch {
8
+ return undefined
9
+ }
10
+ }
11
+
12
+ export function writeJsonCache(key, value) {
13
+ if (typeof localStorage === 'undefined') return
14
+ localStorage.setItem(key, JSON.stringify(value))
15
+ }
16
+
17
+ export function readStringCache(key) {
18
+ if (typeof localStorage === 'undefined') return undefined
19
+ return localStorage.getItem(key) ?? undefined
20
+ }
21
+
22
+ export function writeStringCache(key, value) {
23
+ if (typeof localStorage === 'undefined') return
24
+ if (value == null) localStorage.removeItem(key)
25
+ else localStorage.setItem(key, String(value))
26
+ }