@tldiagram/core-ui 1.87.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 (272) hide show
  1. package/dist/App.d.ts +1 -0
  2. package/dist/api/client.d.ts +143 -0
  3. package/dist/api/transport-vscode.d.ts +8 -0
  4. package/dist/api/transport.d.ts +1 -0
  5. package/dist/components/CodePreviewPanel-vscode.d.ts +7 -0
  6. package/dist/components/CodePreviewPanel.d.ts +9 -0
  7. package/dist/components/ConfirmDialog.d.ts +12 -0
  8. package/dist/components/ConnectorPanel.d.ts +21 -0
  9. package/dist/components/ContextBoundaryElement.d.ts +11 -0
  10. package/dist/components/ContextNeighborElement.d.ts +29 -0
  11. package/dist/components/ContextStraightConnector.d.ts +4 -0
  12. package/dist/components/CrossBranchControls.d.ts +9 -0
  13. package/dist/components/DependenciesOnboarding.d.ts +5 -0
  14. package/dist/components/DrawingCanvas.d.ts +39 -0
  15. package/dist/components/ElementLibrary-vscode.d.ts +7 -0
  16. package/dist/components/ElementLibrary.d.ts +22 -0
  17. package/dist/components/ElementNode.d.ts +36 -0
  18. package/dist/components/ElementPanel.d.ts +25 -0
  19. package/dist/components/ExploreOnboarding.d.ts +5 -0
  20. package/dist/components/ExplorePageOnboarding.d.ts +5 -0
  21. package/dist/components/ExportModal.d.ts +16 -0
  22. package/dist/components/FloatingEdge.d.ts +9 -0
  23. package/dist/components/GitSourceLinker.d.ts +8 -0
  24. package/dist/components/HeaderContext.d.ts +16 -0
  25. package/dist/components/Icons.d.ts +95 -0
  26. package/dist/components/ImportModal.d.ts +10 -0
  27. package/dist/components/InlineElementAdder.d.ts +17 -0
  28. package/dist/components/LayoutSection.d.ts +7 -0
  29. package/dist/components/LocalSourceLinker.d.ts +8 -0
  30. package/dist/components/MiniZoomOnboarding.d.ts +5 -0
  31. package/dist/components/NavBreadcrumb.d.ts +6 -0
  32. package/dist/components/NodeBody.d.ts +12 -0
  33. package/dist/components/NodeContainer.d.ts +8 -0
  34. package/dist/components/NodeHoverCard.d.ts +10 -0
  35. package/dist/components/PanelHeader.d.ts +8 -0
  36. package/dist/components/PanelUI.d.ts +3 -0
  37. package/dist/components/ProxyConnectorEdge.d.ts +4 -0
  38. package/dist/components/ProxyConnectorPanel.d.ts +9 -0
  39. package/dist/components/SafeBackground.d.ts +13 -0
  40. package/dist/components/ScrollIndicatorWrapper.d.ts +8 -0
  41. package/dist/components/SetChildModal.d.ts +10 -0
  42. package/dist/components/SetParentModal.d.ts +10 -0
  43. package/dist/components/SlidingPanel.d.ts +16 -0
  44. package/dist/components/TagUpsert.d.ts +8 -0
  45. package/dist/components/TopMenuBar.d.ts +8 -0
  46. package/dist/components/ViewBezierConnector.d.ts +4 -0
  47. package/dist/components/ViewDrawMenu.d.ts +22 -0
  48. package/dist/components/ViewEditorEdgeLabelLayout.d.ts +16 -0
  49. package/dist/components/ViewEditorOnboarding.d.ts +5 -0
  50. package/dist/components/ViewExplorer/TagManager/ColorPicker.d.ts +7 -0
  51. package/dist/components/ViewExplorer/TagManager/GroupNamingPopover.d.ts +10 -0
  52. package/dist/components/ViewExplorer/TagManager/LayerItem.d.ts +27 -0
  53. package/dist/components/ViewExplorer/TagManager/TagItem.d.ts +25 -0
  54. package/dist/components/ViewExplorer/TagManager/index.d.ts +21 -0
  55. package/dist/components/ViewExplorer/ViewNavigator.d.ts +11 -0
  56. package/dist/components/ViewExplorer/ViewSearch.d.ts +8 -0
  57. package/dist/components/ViewExplorer/ViewTree.d.ts +18 -0
  58. package/dist/components/ViewExplorer/index.d.ts +31 -0
  59. package/dist/components/ViewExplorer/types.d.ts +11 -0
  60. package/dist/components/ViewExplorer/utils.d.ts +6 -0
  61. package/dist/components/ViewExplorer-vscode.d.ts +6 -0
  62. package/dist/components/ViewFloatingMenu-vscode.d.ts +27 -0
  63. package/dist/components/ViewFloatingMenu.d.ts +39 -0
  64. package/dist/components/ViewGridNode.d.ts +29 -0
  65. package/dist/components/ViewHeaderButton.d.ts +11 -0
  66. package/dist/components/ViewPanel.d.ts +18 -0
  67. package/dist/components/ViewsGridOnboarding.d.ts +5 -0
  68. package/dist/components/ZUI/ZUICanvas.d.ts +18 -0
  69. package/dist/components/ZUI/index.d.ts +2 -0
  70. package/dist/components/ZUI/layout.d.ts +18 -0
  71. package/dist/components/ZUI/proxy.d.ts +25 -0
  72. package/dist/components/ZUI/renderer.d.ts +30 -0
  73. package/dist/components/ZUI/types.d.ts +140 -0
  74. package/dist/components/ZUI/useZUIInteraction.d.ts +21 -0
  75. package/dist/config/runtime-vscode.d.ts +22 -0
  76. package/dist/config/runtime.d.ts +5 -0
  77. package/dist/constants/colors.d.ts +27 -0
  78. package/dist/constants/diagramColors.d.ts +1 -0
  79. package/dist/context/ThemeContext.d.ts +27 -0
  80. package/dist/crossBranch/graph.d.ts +13 -0
  81. package/dist/crossBranch/resolve.d.ts +22 -0
  82. package/dist/crossBranch/settings.d.ts +6 -0
  83. package/dist/crossBranch/store.d.ts +11 -0
  84. package/dist/crossBranch/types.d.ts +96 -0
  85. package/dist/demo/DemoPage.d.ts +9 -0
  86. package/dist/demo/seed.d.ts +9 -0
  87. package/dist/demo/store.d.ts +137 -0
  88. package/dist/demo/viewEditor.d.ts +26 -0
  89. package/dist/favicon.svg +35 -0
  90. package/dist/hooks/useSafeFitView.d.ts +16 -0
  91. package/dist/index.css +1 -0
  92. package/dist/index.d.ts +115 -0
  93. package/dist/index.js +19966 -0
  94. package/dist/lib/vscodeBridge-vscode.d.ts +13 -0
  95. package/dist/lib/vscodeBridge.d.ts +5 -0
  96. package/dist/logo-120.png +0 -0
  97. package/dist/logo-bw.png +0 -0
  98. package/dist/logo-bw.svg +15 -0
  99. package/dist/logo-text.svg +51 -0
  100. package/dist/logo.svg +35 -0
  101. package/dist/pages/AppearanceSettings.d.ts +3 -0
  102. package/dist/pages/Dependencies.d.ts +1 -0
  103. package/dist/pages/InfiniteZoom.d.ts +7 -0
  104. package/dist/pages/Settings.d.ts +7 -0
  105. package/dist/pages/ViewEditor/components/EditorMenus.d.ts +24 -0
  106. package/dist/pages/ViewEditor/components/EditorOverlays.d.ts +30 -0
  107. package/dist/pages/ViewEditor/components/EmptyCanvasState.d.ts +7 -0
  108. package/dist/pages/ViewEditor/context.d.ts +13 -0
  109. package/dist/pages/ViewEditor/hooks/useCanvasInteractions.d.ts +201 -0
  110. package/dist/pages/ViewEditor/hooks/useDrawingEngine.d.ts +40 -0
  111. package/dist/pages/ViewEditor/hooks/useViewContextNeighbours.d.ts +20 -0
  112. package/dist/pages/ViewEditor/hooks/useViewData.d.ts +74 -0
  113. package/dist/pages/ViewEditor/index.d.ts +8 -0
  114. package/dist/pages/ViewEditor/utils.d.ts +14 -0
  115. package/dist/pages/Views.d.ts +6 -0
  116. package/dist/pages/ViewsGrid.d.ts +6 -0
  117. package/dist/pkg/importer/mermaid.d.ts +7 -0
  118. package/dist/pkg/importer/mermaid.test.d.ts +1 -0
  119. package/dist/platform/PlatformContext.d.ts +6 -0
  120. package/dist/platform/context.d.ts +3 -0
  121. package/dist/platform/local.d.ts +2 -0
  122. package/dist/platform/types.d.ts +17 -0
  123. package/dist/slots.d.ts +67 -0
  124. package/dist/theme.d.ts +2 -0
  125. package/dist/types/index.d.ts +193 -0
  126. package/dist/types/vscode-messages.d.ts +60 -0
  127. package/dist/utils/edgeDistribution.d.ts +34 -0
  128. package/dist/utils/githubApi.d.ts +4 -0
  129. package/dist/utils/githubCache.d.ts +17 -0
  130. package/dist/utils/ids.d.ts +2 -0
  131. package/dist/utils/technologyCatalog.d.ts +15 -0
  132. package/dist/utils/toast.d.ts +15 -0
  133. package/dist/utils/treesitter.d.ts +13 -0
  134. package/dist/utils/url.d.ts +12 -0
  135. package/package.json +159 -0
  136. package/src/App.tsx +141 -0
  137. package/src/api/client.ts +618 -0
  138. package/src/api/transport-vscode.ts +28 -0
  139. package/src/api/transport.ts +7 -0
  140. package/src/assets/logo-mark.svg +31 -0
  141. package/src/assets/logo-wordmark.svg +22 -0
  142. package/src/assets/logo.svg +35 -0
  143. package/src/components/CodePreviewPanel-vscode.tsx +85 -0
  144. package/src/components/CodePreviewPanel.tsx +384 -0
  145. package/src/components/ConfirmDialog.tsx +66 -0
  146. package/src/components/ConnectorPanel.tsx +403 -0
  147. package/src/components/ContextBoundaryElement.tsx +35 -0
  148. package/src/components/ContextNeighborElement.tsx +282 -0
  149. package/src/components/ContextStraightConnector.tsx +144 -0
  150. package/src/components/CrossBranchControls.tsx +105 -0
  151. package/src/components/DependenciesOnboarding.tsx +427 -0
  152. package/src/components/DrawingCanvas.tsx +391 -0
  153. package/src/components/ElementLibrary-vscode.tsx +9 -0
  154. package/src/components/ElementLibrary.tsx +512 -0
  155. package/src/components/ElementNode.tsx +1033 -0
  156. package/src/components/ElementPanel.tsx +928 -0
  157. package/src/components/ExploreOnboarding.tsx +347 -0
  158. package/src/components/ExplorePageOnboarding.tsx +383 -0
  159. package/src/components/ExportModal.tsx +132 -0
  160. package/src/components/FloatingEdge.tsx +115 -0
  161. package/src/components/GitSourceLinker.tsx +1053 -0
  162. package/src/components/HeaderContext.tsx +30 -0
  163. package/src/components/Icons.tsx +245 -0
  164. package/src/components/ImportModal.tsx +219 -0
  165. package/src/components/InlineElementAdder.tsx +216 -0
  166. package/src/components/LayoutSection.tsx +624 -0
  167. package/src/components/LocalSourceLinker.tsx +330 -0
  168. package/src/components/MiniZoomOnboarding.tsx +78 -0
  169. package/src/components/NavBreadcrumb.tsx +24 -0
  170. package/src/components/NodeBody.tsx +89 -0
  171. package/src/components/NodeContainer.tsx +58 -0
  172. package/src/components/NodeHoverCard.tsx +135 -0
  173. package/src/components/PanelHeader.tsx +36 -0
  174. package/src/components/PanelUI.tsx +24 -0
  175. package/src/components/ProxyConnectorEdge.tsx +169 -0
  176. package/src/components/ProxyConnectorPanel.tsx +130 -0
  177. package/src/components/SafeBackground.tsx +19 -0
  178. package/src/components/ScrollIndicatorWrapper.tsx +117 -0
  179. package/src/components/SetChildModal.tsx +191 -0
  180. package/src/components/SetParentModal.tsx +187 -0
  181. package/src/components/SlidingPanel.tsx +114 -0
  182. package/src/components/TagUpsert.tsx +142 -0
  183. package/src/components/TopMenuBar.tsx +380 -0
  184. package/src/components/ViewBezierConnector.tsx +143 -0
  185. package/src/components/ViewDrawMenu.tsx +270 -0
  186. package/src/components/ViewEditorEdgeLabelLayout.ts +189 -0
  187. package/src/components/ViewEditorOnboarding.tsx +445 -0
  188. package/src/components/ViewExplorer/TagManager/ColorPicker.tsx +49 -0
  189. package/src/components/ViewExplorer/TagManager/GroupNamingPopover.tsx +96 -0
  190. package/src/components/ViewExplorer/TagManager/LayerItem.tsx +228 -0
  191. package/src/components/ViewExplorer/TagManager/TagItem.tsx +242 -0
  192. package/src/components/ViewExplorer/TagManager/index.tsx +418 -0
  193. package/src/components/ViewExplorer/ViewNavigator.tsx +121 -0
  194. package/src/components/ViewExplorer/ViewSearch.tsx +33 -0
  195. package/src/components/ViewExplorer/ViewTree.tsx +98 -0
  196. package/src/components/ViewExplorer/index.tsx +384 -0
  197. package/src/components/ViewExplorer/types.ts +13 -0
  198. package/src/components/ViewExplorer/utils.ts +56 -0
  199. package/src/components/ViewExplorer-vscode.tsx +8 -0
  200. package/src/components/ViewFloatingMenu-vscode.tsx +248 -0
  201. package/src/components/ViewFloatingMenu.tsx +379 -0
  202. package/src/components/ViewGridNode.tsx +451 -0
  203. package/src/components/ViewHeaderButton.tsx +60 -0
  204. package/src/components/ViewPanel.tsx +162 -0
  205. package/src/components/ViewsGridOnboarding.tsx +400 -0
  206. package/src/components/ZUI/ZUICanvas.tsx +853 -0
  207. package/src/components/ZUI/index.ts +3 -0
  208. package/src/components/ZUI/layout.ts +323 -0
  209. package/src/components/ZUI/proxy.ts +278 -0
  210. package/src/components/ZUI/renderer.ts +1189 -0
  211. package/src/components/ZUI/types.ts +150 -0
  212. package/src/components/ZUI/useZUIInteraction.ts +720 -0
  213. package/src/config/runtime-vscode.ts +46 -0
  214. package/src/config/runtime.ts +30 -0
  215. package/src/constants/colors.ts +80 -0
  216. package/src/constants/diagramColors.ts +9 -0
  217. package/src/context/ThemeContext.tsx +158 -0
  218. package/src/crossBranch/graph.ts +207 -0
  219. package/src/crossBranch/resolve.ts +643 -0
  220. package/src/crossBranch/settings.ts +59 -0
  221. package/src/crossBranch/store.ts +71 -0
  222. package/src/crossBranch/types.ts +102 -0
  223. package/src/demo/DemoPage.tsx +184 -0
  224. package/src/demo/seed.ts +67 -0
  225. package/src/demo/store.ts +536 -0
  226. package/src/demo/viewEditor.ts +110 -0
  227. package/src/hooks/useSafeFitView.ts +60 -0
  228. package/src/index.css +309 -0
  229. package/src/index.ts +184 -0
  230. package/src/kafka-ss.png +0 -0
  231. package/src/lib/vscodeBridge-vscode.ts +27 -0
  232. package/src/lib/vscodeBridge.ts +7 -0
  233. package/src/main.tsx +46 -0
  234. package/src/pages/AppearanceSettings.tsx +135 -0
  235. package/src/pages/Dependencies.tsx +926 -0
  236. package/src/pages/InfiniteZoom.tsx +404 -0
  237. package/src/pages/Settings.tsx +91 -0
  238. package/src/pages/ViewEditor/EDGE_DISTRIBUTION.md +64 -0
  239. package/src/pages/ViewEditor/components/EditorMenus.tsx +112 -0
  240. package/src/pages/ViewEditor/components/EditorOverlays.tsx +172 -0
  241. package/src/pages/ViewEditor/components/EmptyCanvasState.tsx +42 -0
  242. package/src/pages/ViewEditor/context.tsx +21 -0
  243. package/src/pages/ViewEditor/hooks/useCanvasInteractions.ts +1349 -0
  244. package/src/pages/ViewEditor/hooks/useDrawingEngine.ts +127 -0
  245. package/src/pages/ViewEditor/hooks/useViewContextNeighbours.ts +501 -0
  246. package/src/pages/ViewEditor/hooks/useViewData.ts +491 -0
  247. package/src/pages/ViewEditor/index.tsx +1366 -0
  248. package/src/pages/ViewEditor/utils.ts +88 -0
  249. package/src/pages/Views.tsx +171 -0
  250. package/src/pages/ViewsGrid.tsx +1310 -0
  251. package/src/pkg/importer/mermaid.test.ts +141 -0
  252. package/src/pkg/importer/mermaid.ts +76 -0
  253. package/src/platform/PlatformContext.tsx +17 -0
  254. package/src/platform/context.ts +9 -0
  255. package/src/platform/local.tsx +15 -0
  256. package/src/platform/types.ts +19 -0
  257. package/src/slots.ts +92 -0
  258. package/src/styles/editor-panels.css +66 -0
  259. package/src/styles/theme.css +56 -0
  260. package/src/theme.ts +336 -0
  261. package/src/types/index.ts +234 -0
  262. package/src/types/offline-ambient.d.ts +14 -0
  263. package/src/types/vscode-messages.ts +32 -0
  264. package/src/utils/edgeDistribution.ts +103 -0
  265. package/src/utils/githubApi.ts +121 -0
  266. package/src/utils/githubCache.ts +108 -0
  267. package/src/utils/ids.ts +9 -0
  268. package/src/utils/technologyCatalog.ts +143 -0
  269. package/src/utils/toast.ts +100 -0
  270. package/src/utils/treesitter.ts +147 -0
  271. package/src/utils/url.ts +72 -0
  272. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,60 @@
1
+ import { useCallback, type RefObject } from 'react'
2
+ import { useReactFlow } from 'reactflow'
3
+
4
+ const MIN_CONTAINER_WIDTH = 50
5
+ const MIN_CONTAINER_HEIGHT = 50
6
+ const NAN_CHECK_DELAY = 80
7
+
8
+ /**
9
+ * Wraps React Flow's fitView with protections against the d3-zoom NaN
10
+ * poisoning bug that occurs when the container is narrow at load time.
11
+ *
12
+ * Guards:
13
+ * 1. Container width - skips fitView if container is too narrow for d3-zoom
14
+ * to compute a valid transform.
15
+ * 2. Post-call NaN check - if the viewport is still NaN after the call,
16
+ * resets to a known-safe fallback.
17
+ *
18
+ * Returns `boolean`: true if fitView was attempted, false if skipped.
19
+ */
20
+ export function useSafeFitView(containerRef?: RefObject<HTMLElement | null>) {
21
+ const { fitView, getViewport, setViewport } = useReactFlow()
22
+
23
+ const safeFitView = useCallback(
24
+ (options?: Parameters<typeof fitView>[0]): boolean => {
25
+ // Guard: skip if container is too narrow/short for d3-zoom to compute valid transform
26
+ // Zero height causes d3-zoom to produce zoom=0, which leads to NaN in RF's DotPattern
27
+ if (containerRef?.current) {
28
+ const { clientWidth, clientHeight } = containerRef.current
29
+ if (clientWidth < MIN_CONTAINER_WIDTH || clientHeight < MIN_CONTAINER_HEIGHT) return false
30
+ }
31
+
32
+ const duration = options?.duration ?? 0
33
+ fitView({ ...options, duration })
34
+
35
+ // For instant transitions, check synchronously so the NaN never reaches a render.
36
+ if (duration === 0) {
37
+ const vp = getViewport()
38
+ if (Number.isNaN(vp.x) || Number.isNaN(vp.y) || Number.isNaN(vp.zoom)) {
39
+ setViewport({ x: 0, y: 0, zoom: 1 }, { duration: 0 })
40
+ return false
41
+ }
42
+ }
43
+
44
+ // Post-call validation: check viewport after transition completes
45
+ // and reset to a safe fallback if d3-zoom produced NaN
46
+ const checkDelay = Math.max(duration, NAN_CHECK_DELAY)
47
+ setTimeout(() => {
48
+ const vp = getViewport()
49
+ if (Number.isNaN(vp.x) || Number.isNaN(vp.y) || Number.isNaN(vp.zoom)) {
50
+ setViewport({ x: 0, y: 0, zoom: 1 }, { duration: 0 })
51
+ }
52
+ }, checkDelay)
53
+
54
+ return true
55
+ },
56
+ [fitView, getViewport, setViewport, containerRef],
57
+ )
58
+
59
+ return { safeFitView }
60
+ }
package/src/index.css ADDED
@@ -0,0 +1,309 @@
1
+ @import './styles/theme.css';
2
+
3
+ :root {
4
+ --theme-blue: var(--accent, #63b3ed);
5
+ /* alias - accent is set by AccentColorProvider */
6
+ --grad-brand: linear-gradient(135deg, #00c6ff 0%, #0072ff 100%);
7
+
8
+ /* ── Layout: top menu bar ─────────────────────────────────────────
9
+ --topbar-h / --topbar-h-mobile are the *content* heights of the bar.
10
+ --topbar-h-total / --topbar-h-mobile-total include env(safe-area-inset-top)
11
+ so both the fixed bar itself and the spacer below it absorb the iOS
12
+ status-bar height automatically. On a regular desktop browser the
13
+ inset resolves to 0px, so nothing changes. */
14
+ --topbar-h: 40px;
15
+ /* top bar content height – desktop (sm+) */
16
+ --topbar-h-mobile: 0px;
17
+ /* top bar content height – mobile (<sm) */
18
+ /* Total bar heights including iOS safe-area-inset-top */
19
+ --topbar-h-total: calc(var(--topbar-h) + env(safe-area-inset-top, 0px));
20
+ --topbar-h-mobile-total: calc(var(--topbar-h-mobile) + env(safe-area-inset-top, 0px));
21
+
22
+ --topbar-content-gap: 4px;
23
+ /* margin between bar & page content (mobile only) */
24
+ --topbar-float-top: 10px;
25
+ /* mobile floating icons: extra offset below bar */
26
+ --topbar-float-h: 38px;
27
+ /* mobile floating icons min-height */
28
+
29
+ /* ── Layout: bottom mobile nav ──────────────────────────────────── */
30
+ --bottomnav-h: 74px;
31
+ /* bottom nav bar height */
32
+ --bottomnav-container-h: 116px;
33
+ /* nav + FAB overflow area */
34
+ --bottomnav-fab-bottom: 22px;
35
+ /* FAB offset from bottom */
36
+ --bottomnav-fab-size: 74px;
37
+ /* FAB diameter */
38
+
39
+ /* ── Layout: react-flow mobile offsets (above bottom nav) ───────── */
40
+ --rf-controls-bottom: 80px;
41
+ --rf-minimap-bottom: 70px;
42
+ --rf-panel-bl-bottom: 82px;
43
+ }
44
+
45
+ .react-flow {
46
+ background-color: var(--bg-canvas);
47
+ }
48
+
49
+ .react-flow__edge-path {
50
+ stroke: var(--theme-blue);
51
+ stroke-width: 2;
52
+ opacity: 0.8;
53
+ }
54
+
55
+ .react-flow__edge.selected .react-flow__edge-path {
56
+ stroke-width: 3;
57
+ opacity: 1;
58
+ }
59
+
60
+ /* Keep React Flow reconnect endpoints interactive, but let the node slot handle
61
+ be the only visible endpoint marker. */
62
+ .react-flow__edge.selected .react-flow__edgeupdater {
63
+ fill: transparent;
64
+ stroke: transparent;
65
+ stroke-width: 0;
66
+ opacity: 0;
67
+ cursor: grab;
68
+ r: 10px;
69
+ }
70
+
71
+ /* Flowing dashes on hover indicate the edge is interactive / grabbable */
72
+ @keyframes edge-flow {
73
+ from {
74
+ stroke-dashoffset: 24;
75
+ }
76
+
77
+ to {
78
+ stroke-dashoffset: 0;
79
+ }
80
+ }
81
+
82
+ .react-flow__edge:hover:not(.selected) .react-flow__edge-path {
83
+ stroke-dasharray: 8 4;
84
+ animation: edge-flow 0.4s linear infinite;
85
+ opacity: 1;
86
+ }
87
+
88
+ .react-flow__edge-marker {
89
+ fill: var(--theme-blue);
90
+ }
91
+
92
+ .react-flow__controls button {
93
+ background-color: transparent;
94
+ border: none;
95
+ border-bottom: 1px solid rgba(255, 255, 255, 0.06);
96
+ border-radius: 0;
97
+ color: #cbd5e0;
98
+ fill: #cbd5e0;
99
+ transition: all 0.2s var(--chakra-transitions-easing-pop);
100
+ }
101
+
102
+ .react-flow__controls button:last-child {
103
+ border-bottom: none;
104
+ }
105
+
106
+ /* On small screens, lift controls and minimap above the bottom navigation + safe area */
107
+ @media (max-width: 768px) {
108
+ .react-flow__controls {
109
+ /* Fix: position fixed so controls escape any parent stacking context
110
+ and reliably sit above the mobile bottom nav / safe-area. */
111
+ position: fixed !important;
112
+ bottom: calc(env(safe-area-inset-bottom, 0px) + var(--rf-controls-bottom)) !important;
113
+ right: max(env(safe-area-inset-right, 0px), 1.25rem) !important;
114
+ z-index: 3000 !important;
115
+ margin: 0 !important;
116
+ }
117
+
118
+ .react-flow__minimap {
119
+ /* Keep minimap fixed to viewport so it doesn't get clipped by parent containers */
120
+ position: fixed !important;
121
+ bottom: calc(env(safe-area-inset-bottom, 0px) + var(--rf-minimap-bottom)) !important;
122
+ left: max(env(safe-area-inset-left, 0px), 1.25rem) !important;
123
+ z-index: 3000 !important;
124
+ /* Constrain size so the minimap never takes more than ~20% of viewport */
125
+ max-width: 20vw !important;
126
+ max-height: 20vh !important;
127
+ width: min(20vw, 220px) !important;
128
+ height: auto !important;
129
+ margin: 0 !important;
130
+ pointer-events: auto !important;
131
+ overflow: hidden;
132
+ }
133
+
134
+ /* Specific fix for the React Flow bottom-left panel (class="react-flow__panel bottom left") */
135
+ .react-flow__panel.bottom.left {
136
+ /* Lift the panel above common mobile bottom nav heights + safe area */
137
+ position: fixed !important;
138
+ bottom: calc(env(safe-area-inset-bottom, 0px) + var(--rf-panel-bl-bottom)) !important;
139
+ left: max(env(safe-area-inset-left, 0px), 1.25rem) !important;
140
+ pointer-events: auto !important;
141
+ z-index: 3001 !important;
142
+ margin: 0 !important;
143
+ }
144
+
145
+ /* Floating action menu (bottom-center) */
146
+ .react-flow__panel.bottom.center {
147
+ position: fixed !important;
148
+ bottom: calc(env(safe-area-inset-bottom, 0px) + var(--bottomnav-h)) !important;
149
+ left: 50% !important;
150
+ transform: translateX(-50%) !important;
151
+ z-index: 3001 !important;
152
+ }
153
+
154
+ /* Slight spacing between control buttons to improve touch targets */
155
+ .react-flow__controls button {
156
+ margin-bottom: 6px;
157
+ }
158
+ }
159
+
160
+ /* On desktop / iPad (viewport-fit=cover): lift bottom React Flow panels above
161
+ the home-indicator safe area. env() resolves to 0px on regular browsers so
162
+ this is a no-op there. The mobile block above already handles this via the
163
+ explicit calc() on its fixed-position bottom values. */
164
+ @media (min-width: 769px) {
165
+
166
+ /* Clear all margins for controls so the inline style='margin:1rem' on the
167
+ <Controls> JSX element doesn't push it above its intended bottom anchor.
168
+ Re-apply corner gap via right/bottom instead. */
169
+ .react-flow__controls {
170
+ margin: 0 !important;
171
+ bottom: calc(env(safe-area-inset-bottom, 0px) + 1rem) !important;
172
+ right: max(env(safe-area-inset-right, 0px), 1rem) !important;
173
+ }
174
+
175
+ .react-flow__minimap {
176
+ margin-bottom: calc(env(safe-area-inset-bottom, 0px) + 1rem) !important;
177
+ margin-left: max(env(safe-area-inset-left, 0px), 1rem) !important;
178
+ }
179
+
180
+ .react-flow__panel.bottom.left:not(.react-flow__controls) {
181
+ margin-bottom: calc(env(safe-area-inset-bottom, 0px) + 1rem) !important;
182
+ margin-left: max(env(safe-area-inset-left, 0px), 1rem) !important;
183
+ }
184
+
185
+ .react-flow__panel.bottom.right:not(.react-flow__controls) {
186
+ margin-bottom: calc(env(safe-area-inset-bottom, 0px) + 1rem) !important;
187
+ margin-right: max(env(safe-area-inset-right, 0px), 1rem) !important;
188
+ }
189
+ }
190
+
191
+ /* On narrower desktop / iPad (<1280px) the centered floating action bar overlaps
192
+ the bottom-left panel (ViewTree). Push the panel above the bar:
193
+ 1rem = bar's own bottom gap
194
+ ~40px = bar height (28px content + 8px vertical padding + 4px slack)
195
+ 8px = visual gap between panel and bar
196
+ margin-bottom is reset to 0 so it doesn't stack with the 769px+ rule above. */
197
+ @media (min-width: 769px) and (max-width: 1279px) {
198
+ .react-flow__panel.bottom.left:not(.react-flow__controls) {
199
+ bottom: calc(env(safe-area-inset-bottom, 0px) + var(--rf-panel-bl-bottom)) !important;
200
+ margin-bottom: 0 !important;
201
+ margin-left: max(env(safe-area-inset-left, 0px), 1rem) !important;
202
+ }
203
+
204
+ .react-flow__controls {
205
+ bottom: calc(env(safe-area-inset-bottom, 0px) + var(--rf-panel-bl-bottom)) !important;
206
+ right: max(env(safe-area-inset-right, 0px), 1rem) !important;
207
+ }
208
+
209
+ .react-flow__minimap {
210
+ bottom: calc(env(safe-area-inset-bottom, 0px) + var(--rf-panel-bl-bottom)) !important;
211
+ margin-bottom: 0 !important;
212
+ margin-left: max(env(safe-area-inset-left, 0px), 1rem) !important;
213
+ }
214
+ }
215
+
216
+ .react-flow__controls button:hover {
217
+ background-color: rgba(255, 255, 255, 0.06);
218
+ color: white;
219
+ fill: white;
220
+ }
221
+
222
+ .react-flow__minimap {
223
+ background-color: var(--bg-panel);
224
+ border: 1px solid #2d3748;
225
+ bottom: calc(env(safe-area-inset-bottom, 0px) + 1rem) !important;
226
+ /* Constrain minimap size globally so it does not exceed ~20% of the viewport */
227
+ max-width: 30vw !important;
228
+ max-height: 30vh !important;
229
+ width: min(30vw, 240px) !important;
230
+ height: auto !important;
231
+ overflow: hidden;
232
+ margin: 0.5rem !important;
233
+ pointer-events: auto !important;
234
+ }
235
+
236
+ /* Ensure the internal svg/canvas of the minimap scales to the container size */
237
+ .react-flow__minimap svg,
238
+ .react-flow__minimap canvas {
239
+ width: 100% !important;
240
+ height: 100% !important;
241
+ }
242
+
243
+ .react-flow__attribution {
244
+ display: none;
245
+ }
246
+
247
+ /* Widen the invisible edge interaction area so tapping edges is forgiving */
248
+ .react-flow__edge-interaction {
249
+ stroke-width: 24 !important;
250
+ }
251
+
252
+ /* Hide handles by default; reveal them on hover, during connection, or when already connected */
253
+ .react-flow__handle {
254
+ opacity: 0;
255
+ pointer-events: none;
256
+ transition: opacity 0.15s, width 0.15s, height 0.15s, box-shadow 0.15s, transform 0.15s;
257
+ }
258
+
259
+ .react-flow__handle.element-node-handle {
260
+ width: 8px;
261
+ height: 8px;
262
+ border: 1px solid rgba(255, 255, 255, 0.8);
263
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.28);
264
+ }
265
+
266
+ /* Expand the interactive hit area without affecting the visible circle */
267
+ .react-flow__handle::before {
268
+ content: '';
269
+ position: absolute;
270
+ inset: -14px;
271
+ border-radius: 50%;
272
+ }
273
+
274
+ .react-flow__handle.handle-connected {
275
+ opacity: 1;
276
+ pointer-events: all;
277
+ }
278
+
279
+ .react-flow__node:hover .react-flow__handle.element-node-handle.handle-active-slot,
280
+ .react-flow__node:hover .react-flow__handle.element-node-handle.handle-fallback-slot {
281
+ opacity: 1;
282
+ pointer-events: all;
283
+ }
284
+
285
+ /* When a node is selected: show handles at full size (matching edge-updater r=6px) */
286
+ .react-flow__node.selected .react-flow__handle.element-node-handle.handle-active-slot,
287
+ .react-flow__node.selected .react-flow__handle.element-node-handle.handle-fallback-slot {
288
+ opacity: 1;
289
+ pointer-events: all;
290
+ width: 12px;
291
+ height: 12px;
292
+ border: 1.5px solid rgba(255, 255, 255, 0.85);
293
+ box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.35);
294
+ }
295
+
296
+ .react-flow__handle.handle-selected-edge {
297
+ opacity: 1;
298
+ pointer-events: all;
299
+ width: 14px;
300
+ height: 14px;
301
+ border: 2px solid rgba(255, 255, 255, 0.9);
302
+ box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.38);
303
+ }
304
+
305
+ .react-flow:has(.react-flow__connection) .react-flow__handle.element-node-handle.handle-active-slot,
306
+ .react-flow:has(.react-flow__connection) .react-flow__handle.element-node-handle.handle-fallback-slot {
307
+ opacity: 1;
308
+ pointer-events: all;
309
+ }
package/src/index.ts ADDED
@@ -0,0 +1,184 @@
1
+ /**
2
+ * @tldiagram/core-ui the open-source core of the tlDiagram editor.
3
+ *
4
+ * This barrel file is the public API surface of the library.
5
+ * It re-exports pages, components, hooks, contexts, types, and utilities
6
+ * so that host applications (SaaS, CLI viewer, VS Code extension) can
7
+ * compose them with their own routing, API clients, and pro features.
8
+ */
9
+
10
+ // ─── Pages ───────────────────────────────────────────────────────────────────
11
+ export { default as ViewEditor } from './pages/ViewEditor'
12
+ export { default as ViewsPage } from './pages/Views'
13
+ export { default as ViewsGrid } from './pages/ViewsGrid'
14
+ export { default as Dependencies } from './pages/Dependencies'
15
+ export { default as InfiniteZoom, SharedInfiniteZoom } from './pages/InfiniteZoom'
16
+ export { default as Settings } from './pages/Settings'
17
+ export { default as AppearanceSettings } from './pages/AppearanceSettings'
18
+
19
+ // ─── UI Components ──────────────────────────────────────────────────────────
20
+ export { default as ElementNode } from './components/ElementNode'
21
+ export { default as ViewGridNode, type ViewGridNodeData } from './components/ViewGridNode'
22
+ export { default as ElementPanel, type ElementPanelProps } from './components/ElementPanel'
23
+ export { default as ConnectorPanel, type ConnectorPanelProps } from './components/ConnectorPanel'
24
+ export { default as ElementLibrary } from './components/ElementLibrary'
25
+ export { default as TopMenuBar } from './components/TopMenuBar'
26
+ export { default as ViewFloatingMenu } from './components/ViewFloatingMenu'
27
+ export type { ViewFloatingMenuProps } from './components/ViewFloatingMenu'
28
+ export { default as ViewBezierConnector } from './components/ViewBezierConnector'
29
+ export { default as ViewHeaderButton } from './components/ViewHeaderButton'
30
+ export { default as ViewPanel } from './components/ViewPanel'
31
+ export { default as ViewDrawMenu } from './components/ViewDrawMenu'
32
+ export { default as FloatingEdge } from './components/FloatingEdge'
33
+ export { default as ContextBoundaryElement } from './components/ContextBoundaryElement'
34
+ export { default as ContextNeighborElement } from './components/ContextNeighborElement'
35
+ export { default as ContextStraightConnector } from './components/ContextStraightConnector'
36
+ export { default as ProxyConnectorEdge } from './components/ProxyConnectorEdge'
37
+ export { default as ProxyConnectorPanel } from './components/ProxyConnectorPanel'
38
+ export { default as DrawingCanvas } from './components/DrawingCanvas'
39
+ export type { DrawingCanvasHandle, DrawingPath } from './components/DrawingCanvas'
40
+ export { default as InlineElementAdder } from './components/InlineElementAdder'
41
+ export { default as ExportModal } from './components/ExportModal'
42
+ export type { ExportOptions } from './components/ExportModal'
43
+ export { default as ImportModal } from './components/ImportModal'
44
+ export { default as ConfirmDialog } from './components/ConfirmDialog'
45
+ export { default as SlidingPanel } from './components/SlidingPanel'
46
+ export { default as PanelHeader } from './components/PanelHeader'
47
+ export { KbdHint } from './components/PanelUI'
48
+ export { default as TagUpsert } from './components/TagUpsert'
49
+ export { default as GitSourceLinker } from './components/GitSourceLinker'
50
+ export { default as LocalSourceLinker } from './components/LocalSourceLinker'
51
+ export { default as CodePreviewPanel } from './components/CodePreviewPanel'
52
+ export { SafeBackground } from './components/SafeBackground'
53
+ export { ElementBody as NodeBody } from './components/NodeBody'
54
+ export { ElementContainer as NodeContainer } from './components/NodeContainer'
55
+ export type { ElementContainerProps } from './components/NodeContainer'
56
+ export { default as NodeHoverCard } from './components/NodeHoverCard'
57
+ export { default as NavBreadcrumb } from './components/NavBreadcrumb'
58
+ export { default as ScrollIndicatorWrapper } from './components/ScrollIndicatorWrapper'
59
+ export { default as LayoutSection } from './components/LayoutSection'
60
+ export { default as CrossBranchControls } from './components/CrossBranchControls'
61
+
62
+ // Icons
63
+ export * from './components/Icons'
64
+
65
+ // ViewExplorer
66
+ export { default as ViewExplorer } from './components/ViewExplorer'
67
+ export * from './components/ViewExplorer/utils'
68
+ export type { NavItem, TreeNode } from './components/ViewExplorer/types'
69
+ export { ViewNavigator } from './components/ViewExplorer/ViewNavigator'
70
+ export { ViewSearch } from './components/ViewExplorer/ViewSearch'
71
+ export { ViewTree } from './components/ViewExplorer/ViewTree'
72
+ export { TagManager } from './components/ViewExplorer/TagManager'
73
+
74
+ // ViewEditor sub-components
75
+ export { ViewEditorContext, useViewEditorContext } from './pages/ViewEditor/context'
76
+
77
+ // Onboarding components
78
+ export { default as ViewEditorOnboarding } from './components/ViewEditorOnboarding'
79
+ export { default as DependenciesOnboarding } from './components/DependenciesOnboarding'
80
+ export { default as ViewsGridOnboarding } from './components/ViewsGridOnboarding'
81
+ export { default as ExploreOnboarding } from './components/ExploreOnboarding'
82
+ export { default as ExplorePageOnboarding } from './components/ExplorePageOnboarding'
83
+ export { default as MiniZoomOnboarding } from './components/MiniZoomOnboarding'
84
+
85
+ // ViewEditor edge label layout
86
+ export * from './components/ViewEditorEdgeLabelLayout'
87
+
88
+ // ─── ZUI ─────────────────────────────────────────────────────────────────────
89
+ export * from './components/ZUI'
90
+
91
+ // ─── Theme & Styles ──────────────────────────────────────────────────────────
92
+ export { default as theme } from './theme'
93
+
94
+ // ─── Contexts ────────────────────────────────────────────────────────────────
95
+ export { ThemeProvider, useAccentColor, useTheme } from './context/ThemeContext'
96
+ export { HeaderProvider, useSetHeader, useHeader } from './components/HeaderContext'
97
+
98
+ // ─── Types ───────────────────────────────────────────────────────────────────
99
+ export * from './types'
100
+
101
+ // ─── Platform ────────────────────────────────────────────────────────────────
102
+ export type { PlatformFeatures } from './platform/types'
103
+ export { platform as localPlatform } from './platform/local'
104
+ export { PlatformProvider } from './platform/PlatformContext'
105
+ export { usePlatform } from './platform/context'
106
+
107
+ // ─── API Contract ────────────────────────────────────────────────────────────
108
+ // The library ships with a reference stub client (offline/local mode).
109
+ // Host applications can provide their own implementation via the same interface.
110
+ export { api } from './api/client'
111
+ export type { DependenciesResponse } from './api/client'
112
+
113
+ // ─── Extension Slots ─────────────────────────────────────────────────────────
114
+ export type {
115
+ TopMenuBarSlots,
116
+ ElementPanelSlots,
117
+ ConnectorPanelSlots,
118
+ ViewFloatingMenuSlots,
119
+ ViewEditorSlots,
120
+ CoreUISlots,
121
+ } from './slots'
122
+
123
+ // ─── Types ───────────────────────────────────────────────────────────────────
124
+ export * from './types'
125
+
126
+ // ─── Hooks ───────────────────────────────────────────────────────────────────
127
+ export { useSafeFitView } from './hooks/useSafeFitView'
128
+
129
+ // ViewEditor hooks
130
+ export { useViewData } from './pages/ViewEditor/hooks/useViewData'
131
+ export { useDrawingEngine } from './pages/ViewEditor/hooks/useDrawingEngine'
132
+ export { useCanvasInteractions } from './pages/ViewEditor/hooks/useCanvasInteractions'
133
+ export { useViewContextNeighbours } from './pages/ViewEditor/hooks/useViewContextNeighbours'
134
+
135
+ // ViewEditor sub-components
136
+ export { EmptyCanvasState } from './pages/ViewEditor/components/EmptyCanvasState'
137
+ export { EditorOverlays } from './pages/ViewEditor/components/EditorOverlays'
138
+ export { ConnectorContextMenu, CanvasContextMenu } from './pages/ViewEditor/components/EditorMenus'
139
+
140
+ // ViewEditor utils
141
+ export * from './pages/ViewEditor/utils'
142
+
143
+ // ─── CrossBranch ─────────────────────────────────────────────────────────────
144
+ export * from './crossBranch/graph'
145
+ export * from './crossBranch/resolve'
146
+ export * from './crossBranch/settings'
147
+ export * from './crossBranch/store'
148
+ export * from './crossBranch/types'
149
+
150
+ // ─── Demo ────────────────────────────────────────────────────────────────────
151
+ export { default as DemoPage, DemoNavigator } from './demo/DemoPage'
152
+ export * from './demo/viewEditor'
153
+
154
+ // ─── Utilities ───────────────────────────────────────────────────────────────
155
+ export * from './utils/edgeDistribution'
156
+ export * from './utils/githubApi'
157
+ export * from './utils/githubCache'
158
+ export * from './utils/ids'
159
+ export * from './utils/technologyCatalog'
160
+ export { toast, ToastContainer } from './utils/toast'
161
+ export * from './utils/url'
162
+ export * from './utils/treesitter'
163
+
164
+ // ─── Constants ───────────────────────────────────────────────────────────────
165
+ export * from './constants/colors'
166
+ export * from './constants/diagramColors'
167
+
168
+ // ─── Config ──────────────────────────────────────────────────────────────────
169
+ export {
170
+ appBase,
171
+ routerBasename,
172
+ isNativeApp,
173
+ apiBase,
174
+ apiUrl,
175
+ } from './config/runtime'
176
+
177
+ // ─── Lib ─────────────────────────────────────────────────────────────────────
178
+ export { vscodeBridge } from './lib/vscodeBridge'
179
+
180
+ // ─── Importer ────────────────────────────────────────────────────────────────
181
+ export { parseMermaid as parseMermaidToElements, type ParsedImport } from './pkg/importer/mermaid'
182
+
183
+ // ─── VS Code Messages ────────────────────────────────────────────────────────
184
+ export * from './types/vscode-messages'
Binary file
@@ -0,0 +1,27 @@
1
+ import type { ExtensionToWebviewMessage, WebviewToExtensionMessage } from '../types/vscode-messages'
2
+
3
+ declare global {
4
+ interface Window {
5
+ __TLD_VSCODE__?: boolean
6
+ __TLD_VSCODE_API__?: {
7
+ postMessage: (msg: unknown) => void
8
+ }
9
+ }
10
+ }
11
+
12
+ const api = (window as Window).__TLD_VSCODE_API__
13
+
14
+ export const vscodeBridge = {
15
+ postMessage: (msg: WebviewToExtensionMessage) => {
16
+ api?.postMessage(msg)
17
+ },
18
+ onMessage: (handler: (msg: ExtensionToWebviewMessage) => void): (() => void) => {
19
+ const listener = (e: MessageEvent) => {
20
+ if (e.data && typeof e.data === 'object' && 'type' in e.data) {
21
+ handler(e.data as ExtensionToWebviewMessage)
22
+ }
23
+ }
24
+ window.addEventListener('message', listener)
25
+ return () => window.removeEventListener('message', listener)
26
+ },
27
+ }
@@ -0,0 +1,7 @@
1
+ import type { ExtensionToWebviewMessage, WebviewToExtensionMessage } from '../types/vscode-messages'
2
+
3
+ // No-op stub used in web/native builds. Swapped for vscodeBridge-vscode.ts in VS Code builds.
4
+ export const vscodeBridge = {
5
+ postMessage: (_msg: WebviewToExtensionMessage) => {},
6
+ onMessage: (_handler: (msg: ExtensionToWebviewMessage) => void): (() => void) => () => {},
7
+ }
package/src/main.tsx ADDED
@@ -0,0 +1,46 @@
1
+ import { StrictMode } from "react"
2
+ import { createRoot } from "react-dom/client"
3
+ import { ChakraProvider } from "@chakra-ui/react"
4
+ import { BrowserRouter } from "react-router-dom"
5
+ import App from "./App"
6
+ import theme from "./theme"
7
+ import { routerBasename } from "./config/runtime"
8
+ import { ToastContainer } from "./utils/toast"
9
+ import { PlatformProvider } from "./platform/PlatformContext"
10
+ import { platform as localPlatform } from "./platform/local"
11
+ import "./index.css"
12
+
13
+ if (typeof window !== "undefined") {
14
+ document.addEventListener(
15
+ "wheel",
16
+ (e) => {
17
+ if (e.ctrlKey) {
18
+ e.preventDefault()
19
+ }
20
+ },
21
+ { passive: false },
22
+ )
23
+
24
+ const preventGesture = (e: Event) => e.preventDefault()
25
+ document.addEventListener("gesturestart", preventGesture, { passive: false })
26
+ document.addEventListener("gesturechange", preventGesture, { passive: false })
27
+ }
28
+
29
+ createRoot(document.getElementById("root")!).render(
30
+ <StrictMode>
31
+ <ChakraProvider theme={theme}>
32
+ <PlatformProvider platform={localPlatform}>
33
+ <BrowserRouter
34
+ basename={routerBasename}
35
+ future={{
36
+ v7_startTransition: false,
37
+ v7_relativeSplatPath: true,
38
+ }}
39
+ >
40
+ <App />
41
+ </BrowserRouter>
42
+ <ToastContainer />
43
+ </PlatformProvider>
44
+ </ChakraProvider>
45
+ </StrictMode>,
46
+ )