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
@@ -0,0 +1,529 @@
1
+ /**
2
+ * QuickToolbar — floating action bar above selected node
3
+ *
4
+ * Shows contextual SVG buttons when a single node is selected:
5
+ * Delete, Duplicate, Mute.
6
+ * Positioned above the node and follows zoom/pan transform.
7
+ *
8
+ * @module symbiote-node/toolbar/QuickToolbar
9
+ */
10
+
11
+ import Symbiote from '@symbiotejs/symbiote';
12
+ import { ensureMaterialSymbols } from '../../icons/MaterialSymbols.js';
13
+ import {
14
+ bringOverlayToFront,
15
+ mountOverlayToDocument,
16
+ restoreOverlayHome,
17
+ } from '../../ui/overlay-stack.js';
18
+ import '../../control/Button/Button.js';
19
+ import { template } from './QuickToolbar.tpl.js';
20
+ import { styles } from './QuickToolbar.css.js';
21
+ import { translate } from '../../locale/index.js';
22
+
23
+ /**
24
+ * @typedef {object} ToolbarAction
25
+ * @property {string} id - Action identifier
26
+ * @property {string} icon - Material Symbols icon name
27
+ * @property {string} label - Tooltip text
28
+ */
29
+
30
+ /** @type {ToolbarAction[]} */
31
+ const ACTIONS = [
32
+ { id: 'duplicate', icon: 'content_copy', label: translate('toolbar.duplicate') },
33
+ { id: 'mute', icon: 'visibility_off', label: translate('toolbar.mute') },
34
+ { id: 'delete', icon: 'delete', label: translate('toolbar.delete') },
35
+ ];
36
+ const ICONS = [
37
+ 'code',
38
+ 'content_copy',
39
+ 'delete',
40
+ 'hub',
41
+ 'login',
42
+ 'visibility',
43
+ 'visibility_off',
44
+ ];
45
+
46
+ export class QuickToolbar extends Symbiote {
47
+ init$ = {
48
+ items: ACTIONS,
49
+ visible: false,
50
+ hasTitle: false,
51
+ nodeTitle: '',
52
+ enterSubgraphTitle: translate('toolbar.enterSubgraph'),
53
+ exploreConnectionsTitle: translate('toolbar.exploreConnections'),
54
+ viewCodeTitle: translate('toolbar.viewCode'),
55
+ duplicateTitle: translate('toolbar.duplicate'),
56
+ muteTitle: translate('toolbar.mute'),
57
+ deleteTitle: translate('toolbar.delete'),
58
+ onBtnClick: (/** @type {Event} */ e) => {
59
+ let btn = e.target.closest('[data-action]');
60
+ if (!btn) return;
61
+ let action = btn.getAttribute('data-action');
62
+ if (this._onAction) this._onAction(action, this._nodeId);
63
+ },
64
+ };
65
+
66
+ /** @type {string|null} */
67
+ _nodeId = null;
68
+
69
+ /** @type {function|null} */
70
+ _onAction = null;
71
+
72
+ /** @type {HTMLElement|null} */
73
+ _nodeEl = null;
74
+
75
+ /** @type {number} */
76
+ _hideTimer = 0;
77
+
78
+ /** @type {boolean} */
79
+ _hoverInside = false;
80
+
81
+ /** @type {boolean} */
82
+ _sticky = false;
83
+
84
+ /** @type {boolean} */
85
+ _hoverEventsBound = false;
86
+
87
+ /** @type {boolean} */
88
+ _viewportEventsBound = false;
89
+
90
+ /** @type {number} */
91
+ _positionFrame = 0;
92
+
93
+ _onViewportChange = () => {
94
+ this.#requestPositionUpdate();
95
+ };
96
+
97
+ _onWheel = (/** @type {WheelEvent} */ e) => {
98
+ this.#forwardWheelToCanvas(e);
99
+ };
100
+
101
+ /** @type {number} Toolbar height + gap */
102
+ static OFFSET_Y = 48;
103
+
104
+ /** @type {number} Gap between the toolbar block and the node */
105
+ static GAP_Y = 6;
106
+
107
+ /** @type {number} Delay that lets the pointer cross the node-toolbar gap */
108
+ static HIDE_DELAY = 160;
109
+
110
+ /** @type {number} */
111
+ static TOOLBAR_EDGE_INSET = 16;
112
+
113
+ /** @type {{ zoom: number, panX: number, panY: number }} */
114
+ _transform = { zoom: 1, panX: 0, panY: 0 };
115
+
116
+ /**
117
+ * Show toolbar above a node
118
+ * @param {string} nodeId
119
+ * @param {HTMLElement} nodeEl - The graph-node element
120
+ * @param {{ sticky?: boolean }} [options]
121
+ */
122
+ show(nodeId, nodeEl, options = {}) {
123
+ this.cancelHide();
124
+ this._nodeId = nodeId;
125
+ this._nodeEl = nodeEl;
126
+ this._sticky = Boolean(options.sticky);
127
+ let themeSource = nodeEl.closest?.('node-canvas') || nodeEl;
128
+ mountOverlayToDocument(this, themeSource);
129
+ this.#syncTitle(nodeEl);
130
+ this.#updateIcons(nodeEl);
131
+ let enterBtn = this.querySelector('[data-action="enter"]');
132
+ if (enterBtn) {
133
+ enterBtn.hidden = nodeEl.getAttribute('node-type') !== 'subgraph';
134
+ }
135
+ this.$.visible = true;
136
+ this.toggleAttribute('hidden', false);
137
+ bringOverlayToFront(this);
138
+
139
+ this.#fitToolbarWidth();
140
+ this.#positionAtNode(nodeEl);
141
+ requestAnimationFrame(() => {
142
+ if (this._nodeEl !== nodeEl) return;
143
+ this.#fitToolbarWidth();
144
+ this.#positionAtNode(nodeEl);
145
+ });
146
+ }
147
+
148
+ /** Hide toolbar */
149
+ hide() {
150
+ this.cancelHide();
151
+ this.#cancelPositionUpdate();
152
+ this._nodeId = null;
153
+ this._nodeEl = null;
154
+ this._sticky = false;
155
+ this._hoverInside = false;
156
+ this.$.visible = false;
157
+ this.$.hasTitle = false;
158
+ this.$.nodeTitle = '';
159
+ this.toggleAttribute('data-has-title', false);
160
+ this.style.removeProperty('--sn-toolbar-fit-width');
161
+ this.style.removeProperty('--sn-toolbar-scale');
162
+ restoreOverlayHome(this);
163
+ }
164
+
165
+ renderCallback() {
166
+ ensureMaterialSymbols(ICONS);
167
+ if (!this._hoverEventsBound) {
168
+ this.addEventListener('pointerenter', () => {
169
+ this._hoverInside = true;
170
+ this.cancelHide();
171
+ bringOverlayToFront(this);
172
+ });
173
+ this.addEventListener('pointerleave', () => {
174
+ this._hoverInside = false;
175
+ this.scheduleHide();
176
+ });
177
+ this.addEventListener('wheel', this._onWheel, { passive: false });
178
+ this._hoverEventsBound = true;
179
+ }
180
+ if (!this._viewportEventsBound && typeof window !== 'undefined') {
181
+ window.addEventListener('resize', this._onViewportChange, { passive: true });
182
+ window.addEventListener('scroll', this._onViewportChange, { passive: true, capture: true });
183
+ this._viewportEventsBound = true;
184
+ }
185
+ this.sub('visible', (val) => {
186
+ this.toggleAttribute('hidden', !val);
187
+ });
188
+ }
189
+
190
+ destroyCallback() {
191
+ this.#cancelPositionUpdate();
192
+ if (this._viewportEventsBound && typeof window !== 'undefined') {
193
+ window.removeEventListener('resize', this._onViewportChange);
194
+ window.removeEventListener('scroll', this._onViewportChange, { capture: true });
195
+ this._viewportEventsBound = false;
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Keep the toolbar visible while the pointer travels from a node into it.
201
+ * @param {number} [delay]
202
+ * @param {string|null} [nodeId]
203
+ */
204
+ scheduleHide(delay = QuickToolbar.HIDE_DELAY, nodeId = this._nodeId) {
205
+ this.cancelHide();
206
+ let activeNodeId = nodeId;
207
+ if (typeof setTimeout !== 'function') {
208
+ if (!this._hoverInside && !this._sticky) this.hide();
209
+ return;
210
+ }
211
+ this._hideTimer = setTimeout(() => {
212
+ this._hideTimer = 0;
213
+ if (this._nodeId !== activeNodeId) return;
214
+ if (this._hoverInside || this._sticky) return;
215
+ this.hide();
216
+ }, delay);
217
+ }
218
+
219
+ cancelHide() {
220
+ if (!this._hideTimer) return;
221
+ clearTimeout(this._hideTimer);
222
+ this._hideTimer = 0;
223
+ }
224
+
225
+ /**
226
+ * Update position to follow node movement
227
+ * @param {HTMLElement} nodeEl
228
+ */
229
+ updatePosition(nodeEl) {
230
+ if (!this._nodeId) return;
231
+ this.#positionAtNode(nodeEl);
232
+ }
233
+
234
+ #requestPositionUpdate() {
235
+ if (!this._nodeId || !this._nodeEl || !this.$.visible || this.hidden) return;
236
+ if (this._positionFrame) return;
237
+
238
+ if (typeof requestAnimationFrame !== 'function') {
239
+ this.#positionAtNode(this._nodeEl);
240
+ return;
241
+ }
242
+
243
+ this._positionFrame = requestAnimationFrame(() => {
244
+ this._positionFrame = 0;
245
+ if (!this._nodeId || !this._nodeEl || !this.$.visible || this.hidden) return;
246
+ this.#positionAtNode(this._nodeEl);
247
+ });
248
+ }
249
+
250
+ #cancelPositionUpdate() {
251
+ if (!this._positionFrame) return;
252
+ if (typeof cancelAnimationFrame === 'function') {
253
+ cancelAnimationFrame(this._positionFrame);
254
+ }
255
+ this._positionFrame = 0;
256
+ }
257
+
258
+ /**
259
+ * Portaled toolbars live outside node-canvas, so wheel events no longer
260
+ * bubble into the canvas zoom/scroll handlers unless we route them back.
261
+ * @param {WheelEvent} e
262
+ */
263
+ #forwardWheelToCanvas(e) {
264
+ if (!this.hasAttribute('data-overlay-portal') || !this._nodeEl) return;
265
+
266
+ let canvas = this._nodeEl.closest?.('node-canvas');
267
+ if (!canvas) return;
268
+
269
+ e.preventDefault();
270
+ e.stopPropagation();
271
+
272
+ if (canvas.hasAttribute?.('data-flow-scroll') && !e.ctrlKey && !e.metaKey && !e.altKey) {
273
+ if (typeof canvas.scrollBy === 'function') {
274
+ canvas.scrollBy({ left: e.deltaX || 0, top: e.deltaY || 0, behavior: 'auto' });
275
+ } else {
276
+ canvas.scrollLeft += e.deltaX || 0;
277
+ canvas.scrollTop += e.deltaY || 0;
278
+ }
279
+ this.#requestPositionUpdate();
280
+ return;
281
+ }
282
+
283
+ let target = canvas.ref?.canvasContainer || canvas.querySelector?.('.canvas-container') || canvas;
284
+ let forwarded = this.#cloneWheelEvent(e);
285
+ if (forwarded) {
286
+ target.dispatchEvent(forwarded);
287
+ this.#requestPositionUpdate();
288
+ }
289
+ }
290
+
291
+ /**
292
+ * @param {WheelEvent} e
293
+ * @returns {WheelEvent|Event|null}
294
+ */
295
+ #cloneWheelEvent(e) {
296
+ let init = {
297
+ bubbles: true,
298
+ cancelable: true,
299
+ composed: true,
300
+ deltaX: e.deltaX || 0,
301
+ deltaY: e.deltaY || 0,
302
+ deltaZ: e.deltaZ || 0,
303
+ deltaMode: e.deltaMode || 0,
304
+ clientX: e.clientX || 0,
305
+ clientY: e.clientY || 0,
306
+ screenX: e.screenX || 0,
307
+ screenY: e.screenY || 0,
308
+ ctrlKey: Boolean(e.ctrlKey),
309
+ shiftKey: Boolean(e.shiftKey),
310
+ altKey: Boolean(e.altKey),
311
+ metaKey: Boolean(e.metaKey),
312
+ buttons: e.buttons || 0,
313
+ };
314
+
315
+ if (typeof WheelEvent === 'function') {
316
+ return new WheelEvent('wheel', init);
317
+ }
318
+
319
+ let doc = this.ownerDocument;
320
+ if (typeof doc?.createEvent !== 'function') return null;
321
+
322
+ let event = doc.createEvent('Event');
323
+ event.initEvent('wheel', true, true);
324
+ Object.defineProperties(event, Object.fromEntries(
325
+ Object.entries(init).map(([key, value]) => [key, { value }])
326
+ ));
327
+ return event;
328
+ }
329
+
330
+ /**
331
+ * Position toolbar centered above a node in screen-space.
332
+ * @param {HTMLElement} nodeEl
333
+ */
334
+ #positionAtNode(nodeEl) {
335
+ let toolbarEl = this.querySelector('.toolbar');
336
+ let toolbarHeight = toolbarEl?.offsetHeight || (QuickToolbar.OFFSET_Y - QuickToolbar.GAP_Y);
337
+ let nodeRect = nodeEl.getBoundingClientRect?.();
338
+ let containerRect = this.parentElement?.getBoundingClientRect?.();
339
+ let scale = this.#resolveNodeVisualScale(nodeEl, nodeRect);
340
+ let offsetY = (toolbarHeight + QuickToolbar.GAP_Y) * scale;
341
+
342
+ this.style.setProperty('--sn-toolbar-scale', String(scale));
343
+
344
+ if (nodeRect && containerRect) {
345
+ if (this.hasAttribute('data-overlay-portal')) {
346
+ let x = nodeRect.left + nodeRect.width / 2;
347
+ let toolbarWidth = (toolbarEl?.offsetWidth || 0) * scale;
348
+ let viewportWidth = this.ownerDocument?.documentElement?.clientWidth || window.innerWidth || 0;
349
+ let edgeInset = QuickToolbar.TOOLBAR_EDGE_INSET;
350
+ if (toolbarWidth && viewportWidth) {
351
+ if (viewportWidth > toolbarWidth + edgeInset * 2) {
352
+ x = Math.min(
353
+ Math.max(x, edgeInset + toolbarWidth / 2),
354
+ viewportWidth - edgeInset - toolbarWidth / 2
355
+ );
356
+ } else {
357
+ x = viewportWidth / 2;
358
+ }
359
+ }
360
+ let y = nodeRect.top - offsetY;
361
+ this.style.transform = `translate(${x}px, ${y}px)`;
362
+ return;
363
+ }
364
+
365
+ let x = nodeRect.left - containerRect.left + nodeRect.width / 2;
366
+ let y = nodeRect.top - containerRect.top - offsetY;
367
+ this.style.transform = `translate(${x}px, ${y}px)`;
368
+ return;
369
+ }
370
+
371
+ let w = nodeEl.offsetWidth || nodeEl._cachedW || 180;
372
+ let pos = nodeEl._position || { x: 0, y: 0 };
373
+ let x = pos.x + w / 2;
374
+ let y = pos.y - offsetY;
375
+ this.style.transform = `translate(${x}px, ${y}px)`;
376
+ }
377
+
378
+ /**
379
+ * Match the screen-space toolbar to the visual scale of a transformed node.
380
+ * @param {HTMLElement} nodeEl
381
+ * @param {DOMRect|undefined} nodeRect
382
+ * @returns {number}
383
+ */
384
+ #resolveNodeVisualScale(nodeEl, nodeRect) {
385
+ let rectWidth = nodeRect?.width || 0;
386
+ let baseWidth = nodeEl.offsetWidth || nodeEl._cachedW || 0;
387
+ let scale = baseWidth > 0 && rectWidth > 0
388
+ ? rectWidth / baseWidth
389
+ : this._transform?.zoom || 1;
390
+
391
+ if (!Number.isFinite(scale) || scale <= 0) return 1;
392
+ return Math.max(0.05, Math.min(scale, 8));
393
+ }
394
+
395
+ /**
396
+ * Show the node title inside the toolbar only when the node has no visible own header.
397
+ * @param {HTMLElement} nodeEl
398
+ */
399
+ #syncTitle(nodeEl) {
400
+ let title = nodeEl.getAttribute('node-label') || nodeEl.querySelector('.sn-node-label')?.textContent?.trim() || '';
401
+ let hasOwnHeader = !nodeEl.hasAttribute('data-header-hidden') && !nodeEl.hasAttribute('data-svg-shape');
402
+ let hasTitle = Boolean(title && !hasOwnHeader);
403
+
404
+ this.$.hasTitle = hasTitle;
405
+ this.$.nodeTitle = hasTitle ? title : '';
406
+ this.toggleAttribute('data-has-title', hasTitle);
407
+
408
+ let titleRow = this.querySelector('.toolbar-title');
409
+ let titleText = this.querySelector('.toolbar-title-text');
410
+ if (titleText) titleText.textContent = this.$.nodeTitle;
411
+ if (titleRow) titleRow.hidden = !hasTitle;
412
+ }
413
+
414
+ #fitToolbarWidth() {
415
+ let toolbarEl = this.querySelector('.toolbar');
416
+ if (!toolbarEl) return;
417
+ this.style.removeProperty('--sn-toolbar-fit-width');
418
+ if (!this.$.hasTitle) return;
419
+
420
+ let titleText = this.querySelector('.toolbar-title-text');
421
+ let titleRow = this.querySelector('.toolbar-title');
422
+ if (!titleText || !titleRow || !titleText.textContent) return;
423
+
424
+ let toolbarStyle = getComputedStyle(toolbarEl);
425
+ let titleStyle = getComputedStyle(titleText);
426
+ let rowStyle = getComputedStyle(titleRow);
427
+ let viewportWidth = this.ownerDocument?.documentElement?.clientWidth || window.innerWidth || 0;
428
+ let maxWidth = Number.parseFloat(toolbarStyle.maxInlineSize);
429
+ if (!Number.isFinite(maxWidth) || maxWidth <= 0) {
430
+ maxWidth = Math.max(0, viewportWidth - QuickToolbar.TOOLBAR_EDGE_INSET * 2);
431
+ }
432
+
433
+ let minWidth = Number.parseFloat(getComputedStyle(this).getPropertyValue('--sn-toolbar-title-min-width'));
434
+ if (!Number.isFinite(minWidth) || minWidth <= 0) minWidth = 0;
435
+
436
+ let actionWidth = this.#measureActionWidth();
437
+ let paddingX =
438
+ Number.parseFloat(rowStyle.paddingLeft) +
439
+ Number.parseFloat(rowStyle.paddingRight) +
440
+ Number.parseFloat(rowStyle.borderLeftWidth) +
441
+ Number.parseFloat(rowStyle.borderRightWidth);
442
+ if (!Number.isFinite(paddingX)) paddingX = 0;
443
+
444
+ let lineHeight = Number.parseFloat(titleStyle.lineHeight);
445
+ if (!Number.isFinite(lineHeight) || lineHeight <= 0) {
446
+ lineHeight = Number.parseFloat(titleStyle.fontSize) * 1.35;
447
+ }
448
+ let maxLines = Number.parseInt(getComputedStyle(this).getPropertyValue('--sn-toolbar-title-lines'), 10);
449
+ if (!Number.isFinite(maxLines) || maxLines < 1) maxLines = 2;
450
+
451
+ let measuredTextWidth = this.#measureTitleTextWidth(titleText.textContent, titleStyle, lineHeight, maxLines, Math.max(1, maxWidth - paddingX));
452
+ let nextWidth = Math.ceil(Math.max(measuredTextWidth + paddingX, actionWidth, minWidth));
453
+ nextWidth = Math.min(nextWidth, maxWidth);
454
+ this.style.setProperty('--sn-toolbar-fit-width', `${nextWidth}px`);
455
+ }
456
+
457
+ #measureActionWidth() {
458
+ let actions = this.querySelector('.toolbar-actions');
459
+ if (!actions) return 0;
460
+
461
+ let style = getComputedStyle(actions);
462
+ let gap = Number.parseFloat(style.columnGap || style.gap);
463
+ if (!Number.isFinite(gap)) gap = 0;
464
+ let width = Number.parseFloat(style.paddingLeft) + Number.parseFloat(style.paddingRight);
465
+ if (!Number.isFinite(width)) width = 0;
466
+
467
+ let visibleItems = Array.from(actions.children).filter((item) => !item.hidden);
468
+ visibleItems.forEach((item, index) => {
469
+ width += item.getBoundingClientRect?.().width || item.offsetWidth || 0;
470
+ if (index > 0) width += gap;
471
+ });
472
+
473
+ return Math.ceil(width);
474
+ }
475
+
476
+ #measureTitleTextWidth(text, titleStyle, lineHeight, maxLines, maxContentWidth) {
477
+ let doc = this.ownerDocument;
478
+ let probe = doc.createElement('div');
479
+ probe.textContent = text;
480
+ probe.style.position = 'fixed';
481
+ probe.style.left = '-10000px';
482
+ probe.style.top = '0';
483
+ probe.style.visibility = 'hidden';
484
+ probe.style.pointerEvents = 'none';
485
+ probe.style.contain = 'layout style paint';
486
+ probe.style.boxSizing = 'content-box';
487
+ probe.style.fontFamily = titleStyle.fontFamily;
488
+ probe.style.fontSize = titleStyle.fontSize;
489
+ probe.style.fontStyle = titleStyle.fontStyle;
490
+ probe.style.fontWeight = titleStyle.fontWeight;
491
+ probe.style.letterSpacing = titleStyle.letterSpacing;
492
+ probe.style.lineHeight = titleStyle.lineHeight;
493
+ probe.style.whiteSpace = 'normal';
494
+ probe.style.overflowWrap = 'anywhere';
495
+ probe.style.textWrap = 'balance';
496
+ doc.body.appendChild(probe);
497
+
498
+ let low = 1;
499
+ let high = Math.max(1, maxContentWidth);
500
+ let allowedHeight = lineHeight * maxLines + 1;
501
+ for (let i = 0; i < 10; i += 1) {
502
+ let mid = (low + high) / 2;
503
+ probe.style.width = `${mid}px`;
504
+ if (probe.scrollHeight <= allowedHeight) {
505
+ high = mid;
506
+ } else {
507
+ low = mid;
508
+ }
509
+ }
510
+ probe.remove();
511
+ return high;
512
+ }
513
+
514
+ /**
515
+ * Update toggle icons based on node state
516
+ * @param {HTMLElement} nodeEl
517
+ */
518
+ #updateIcons(nodeEl) {
519
+ let isMuted = nodeEl.hasAttribute('data-muted');
520
+
521
+ let muteBtn = this.querySelector('[data-action="mute"] .tb-icon');
522
+
523
+ if (muteBtn) muteBtn.textContent = isMuted ? 'visibility' : 'visibility_off';
524
+ }
525
+ }
526
+
527
+ QuickToolbar.template = template;
528
+ QuickToolbar.rootStyles = styles;
529
+ QuickToolbar.reg('quick-toolbar');
@@ -0,0 +1,34 @@
1
+ /**
2
+ * QuickToolbar template
3
+ * @module symbiote-node/toolbar/QuickToolbar.tpl
4
+ */
5
+ import { html } from '@symbiotejs/symbiote';
6
+
7
+ export let template = html`
8
+ <div class="toolbar" ${{ onclick: 'onBtnClick' }}>
9
+ <div class="toolbar-title" ref="titleRow" ${{ hidden: '!hasTitle' }}>
10
+ <span class="toolbar-title-text" ref="titleText" ${{ textContent: 'nodeTitle' }}></span>
11
+ </div>
12
+ <div class="toolbar-actions">
13
+ <sn-button class="tb-btn tb-btn--enter" variant="icon" data-action="enter" ${{ title: 'enterSubgraphTitle' }} hidden>
14
+ <span class="material-symbols-outlined tb-icon">login</span>
15
+ </sn-button>
16
+ <sn-button class="tb-btn" variant="icon" data-action="explore" ${{ title: 'exploreConnectionsTitle' }}>
17
+ <span class="material-symbols-outlined tb-icon">hub</span>
18
+ </sn-button>
19
+ <sn-button class="tb-btn" variant="icon" data-action="view-code" ${{ title: 'viewCodeTitle' }}>
20
+ <span class="material-symbols-outlined tb-icon">code</span>
21
+ </sn-button>
22
+ <sn-button class="tb-btn" variant="icon" data-action="duplicate" ${{ title: 'duplicateTitle' }}>
23
+ <span class="material-symbols-outlined tb-icon">content_copy</span>
24
+ </sn-button>
25
+
26
+ <sn-button class="tb-btn" variant="icon" data-action="mute" ${{ title: 'muteTitle' }}>
27
+ <span class="material-symbols-outlined tb-icon">visibility_off</span>
28
+ </sn-button>
29
+ <sn-button class="tb-btn tb-btn--danger" variant="icon" data-action="delete" ${{ title: 'deleteTitle' }}>
30
+ <span class="material-symbols-outlined tb-icon">delete</span>
31
+ </sn-button>
32
+ </div>
33
+ </div>
34
+ `;
@@ -0,0 +1,112 @@
1
+ export default /*css*/ `
2
+ :host,
3
+ sn-tree-panel {
4
+ display: flex;
5
+ flex-direction: column;
6
+ height: 100%;
7
+ overflow: hidden;
8
+ font-family: var(--sn-font);
9
+ font-size: var(--sn-tree-panel-font-size);
10
+ }
11
+
12
+ :host([hidden]),
13
+ sn-tree-panel[hidden] {
14
+ display: none !important;
15
+ }
16
+
17
+ .sn-tree-panel-title {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: var(--sn-tree-panel-title-gap);
21
+ padding: var(--sn-tree-panel-title-padding);
22
+ border-bottom: 1px solid var(--sn-node-border);
23
+ color: var(--sn-text-dim);
24
+ font-size: var(--sn-tree-panel-title-size);
25
+ font-weight: var(--sn-tree-panel-title-weight);
26
+ text-transform: uppercase;
27
+ }
28
+
29
+ .sn-tree-panel-title-icon,
30
+ .sn-tree-panel-toolbar-icon {
31
+ font-size: var(--sn-tree-panel-icon-size);
32
+ }
33
+
34
+ .sn-tree-panel-toolbar {
35
+ display: flex;
36
+ gap: var(--sn-tree-panel-toolbar-gap);
37
+ padding: var(--sn-tree-panel-toolbar-padding);
38
+ border-bottom: 1px solid var(--sn-node-border);
39
+ }
40
+
41
+ .sn-tree-panel-filter {
42
+ flex: 1;
43
+ min-width: 0;
44
+ padding: var(--sn-tree-panel-input-padding);
45
+ border: 1px solid var(--sn-node-border);
46
+ border-radius: var(--sn-tree-panel-input-radius);
47
+ outline: none;
48
+ background: var(--sn-bg);
49
+ color: var(--sn-text);
50
+ font-family: inherit;
51
+ font-size: var(--sn-tree-panel-input-size);
52
+ }
53
+
54
+ .sn-tree-panel-filter:focus {
55
+ border-color: var(--sn-node-selected);
56
+ }
57
+
58
+ .sn-tree-panel-collapse {
59
+ --sn-button-icon-size: auto;
60
+ --sn-button-icon-font-size: var(--sn-tree-panel-icon-size);
61
+ --sn-button-padding: var(--sn-tree-panel-collapse-padding);
62
+ --sn-button-border: var(--sn-node-border);
63
+ --sn-button-radius: var(--sn-tree-panel-input-radius);
64
+ --sn-button-bg: var(--sn-bg);
65
+ --sn-button-hover-bg: var(--sn-node-hover);
66
+ --sn-button-hover-border: var(--sn-node-border);
67
+ --sn-button-color: var(--sn-text);
68
+ --sn-button-focus-ring: var(--sn-effect-focus-ring);
69
+ color: var(--sn-text);
70
+ transition: background 100ms ease;
71
+ }
72
+
73
+ .sn-tree-panel-content {
74
+ flex: 1;
75
+ overflow-y: auto;
76
+ padding: var(--sn-tree-panel-content-padding);
77
+ }
78
+
79
+ .sn-tree-panel-placeholder {
80
+ padding: var(--sn-tree-panel-placeholder-padding);
81
+ color: var(--sn-text-dim);
82
+ font-size: var(--sn-tree-panel-placeholder-size);
83
+ }
84
+
85
+ .sn-tree-panel-placeholder[hidden] {
86
+ display: none;
87
+ }
88
+
89
+ sn-tree-view {
90
+ --sn-tree-gap: var(--sn-tree-panel-gap, var(--sn-tree-gap));
91
+ --sn-tree-indent: var(--sn-tree-panel-indent, var(--sn-tree-indent));
92
+ --sn-tree-row-min-height: var(--sn-tree-panel-row-min-height, var(--sn-tree-row-height));
93
+ --sn-tree-row-padding-block: var(--sn-tree-panel-row-padding-block, var(--sn-tree-row-padding-block));
94
+ --sn-tree-row-radius: var(--sn-tree-panel-row-radius, var(--sn-tree-row-radius));
95
+ --sn-tree-row-hover-bg: var(--sn-node-hover);
96
+ --sn-tree-row-selected-bg: var(--sn-node-selected-soft, var(--sn-node-hover));
97
+ --sn-tree-row-selected-border: transparent;
98
+ --sn-tree-label-color: var(--sn-text-dim);
99
+ --sn-tree-label-size: var(--sn-tree-panel-label-size, var(--sn-tree-label-size));
100
+ --sn-tree-label-weight: var(--sn-tree-panel-label-weight, var(--sn-tree-label-weight));
101
+ --sn-tree-muted-color: var(--sn-text-dim);
102
+ --sn-tree-icon-size: var(--sn-tree-panel-icon-size, var(--sn-tree-icon-size));
103
+ --sn-tree-badge-radius: var(--sn-tree-panel-badge-radius, var(--sn-tree-badge-radius));
104
+ --sn-tree-badge-bg: var(--sn-node-hover);
105
+ --sn-tree-badge-color: var(--sn-text-dim);
106
+ --sn-tree-badge-size: var(--sn-tree-panel-badge-size, var(--sn-tree-badge-size));
107
+ }
108
+
109
+ sn-tree-view[hidden] {
110
+ display: none;
111
+ }
112
+ `;