@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,400 @@
1
+ import { useEffect, useState } from 'react'
2
+ import { Box, Button, HStack, Text, VStack } from '@chakra-ui/react'
3
+
4
+ const STORAGE_KEY = `viewgrid_tutorial_v2_core`
5
+
6
+ interface Props {
7
+
8
+ hasViews: boolean
9
+ }
10
+
11
+ // ── SVG helpers ─────────────────────────────────────────────────────────────
12
+
13
+ function GridDots({ prefix }: { prefix: string }) {
14
+ return (
15
+ <>
16
+ {Array.from({ length: 7 }, (_, r) =>
17
+ Array.from({ length: 14 }, (_, c) => (
18
+ <circle
19
+ key={`${prefix}-${r}-${c}`}
20
+ cx={c * 20 + 10}
21
+ cy={r * 20 + 10}
22
+ r={0.8}
23
+ fill="#1E2D40"
24
+ />
25
+ )),
26
+ ).flat()}
27
+ </>
28
+ )
29
+ }
30
+
31
+ function GridCard({ x, y, name, label, stats, focused, wasd, cardClass, wasdClass, showConnect }: { x: number, y: number, name: string, label?: string, stats?: string, focused?: boolean, wasd?: string, cardClass?: string, wasdClass?: string, showConnect?: boolean }) {
32
+ const accent = '#63B3ED'
33
+ return (
34
+ <g transform={`translate(${x}, ${y})`} className={cardClass}>
35
+ <rect width="100" height="60" rx="6" fill="#1C2535" stroke={focused ? accent : 'rgba(255,255,255,0.14)'} strokeWidth="1" className="dg-card-rect" />
36
+ <rect width="100" height="24" rx="0" fill="color-mix(in srgb, rgba(28, 37, 53, 0.7), black 20%)" y="36" />
37
+ <text x="6" y="47" fill="#E2E8F0" fontSize="7" fontFamily="system-ui,sans-serif" fontWeight="600">{name}</text>
38
+ {label && <text x="6" y="55" fill={accent} fontSize="5" fontFamily="system-ui,sans-serif" fontWeight="bold" style={{ textTransform: 'uppercase' }}>{label}</text>}
39
+ {stats && <text x="94" y="55" textAnchor="end" fill="#718096" fontSize="5" fontFamily="system-ui,sans-serif">{stats}</text>}
40
+
41
+ {showConnect && (
42
+ <g transform="translate(86, 39)">
43
+ <rect width="8" height="8" rx="1.5" fill="rgba(255,255,255,0.1)" stroke={accent} strokeWidth="0.5" />
44
+ <path d="M2,4 L6,4 M4.5,2.5 L6,4 L4.5,5.5" fill="none" stroke={accent} strokeWidth="0.8" strokeLinecap="round" strokeLinejoin="round" />
45
+ </g>
46
+ )}
47
+
48
+ {wasd && (
49
+ <g transform="translate(42, -10)" className={wasdClass} style={{ transformOrigin: '8px 6px' }}>
50
+ <rect width="16" height="12" rx="3" fill="#1A202C" stroke={accent} strokeWidth="0.8" />
51
+ <text x="8" y="9" textAnchor="middle" fill="#E2E8F0" fontSize="7" fontFamily="system-ui,sans-serif" fontWeight="800">{wasd}</text>
52
+ </g>
53
+ )}
54
+ </g>
55
+ )
56
+ }
57
+
58
+ // Step 0 - Explore the Grid (WASD navigation)
59
+ function GridExploreIllustration() {
60
+ return (
61
+ <svg
62
+ viewBox="0 0 280 150"
63
+ xmlns="http://www.w3.org/2000/svg"
64
+ style={{ width: '100%', height: 'auto', borderRadius: 10, display: 'block', overflow: 'hidden' }}
65
+ >
66
+ <defs>
67
+ <style>{`
68
+ .dg-container {
69
+ animation: dgSlide 6s ease-in-out infinite;
70
+ }
71
+ @keyframes dgSlide {
72
+ 0%, 35% { transform: translateY(0); }
73
+ 50%, 85% { transform: translateY(70px); }
74
+ 95%, 100% { transform: translateY(0); }
75
+ }
76
+ .dg-focus-root .dg-card-rect {
77
+ animation: dgFocusRoot 6s ease-in-out infinite;
78
+ }
79
+ @keyframes dgFocusRoot {
80
+ 0%, 45% { stroke: rgba(255,255,255,0.14); stroke-width: 1; filter: none; }
81
+ 50%, 85% { stroke: #63B3ED; stroke-width: 2; filter: drop-shadow(0 0 6px rgba(99,179,237,0.5)); }
82
+ 95%, 100% { stroke: rgba(255,255,255,0.14); stroke-width: 1; filter: none; }
83
+ }
84
+ .dg-focus-api .dg-card-rect {
85
+ animation: dgFocusApi 6s ease-in-out infinite;
86
+ }
87
+ @keyframes dgFocusApi {
88
+ 0%, 35% { stroke: #63B3ED; stroke-width: 2; filter: drop-shadow(0 0 6px rgba(99,179,237,0.5)); }
89
+ 40%, 100% { stroke: rgba(255,255,255,0.14); stroke-width: 1; filter: none; }
90
+ }
91
+ .dg-w-flash {
92
+ animation: dgWFlash 6s ease-in-out infinite;
93
+ }
94
+ @keyframes dgWFlash {
95
+ 0%, 15% { opacity: 0.4; transform: scale(1); }
96
+ 22%, 35% { opacity: 1; transform: scale(1.15); filter: drop-shadow(0 0 8px #63B3ED); }
97
+ 42%, 100% { opacity: 0.4; transform: scale(1); }
98
+ }
99
+ `}</style>
100
+ </defs>
101
+ <rect width="280" height="150" fill="#0D1117" rx="8" />
102
+ <GridDots prefix="grid" />
103
+
104
+ <g className="dg-container">
105
+ {/* Parent View */}
106
+ <GridCard
107
+ x={90} y={5}
108
+ name="Root System" label="Context" stats="5n 3e"
109
+ wasd="W"
110
+ cardClass="dg-focus-root"
111
+ wasdClass="dg-w-flash"
112
+ />
113
+ {/* Current View (Initially centered at 75) */}
114
+ <GridCard
115
+ x={90} y={75}
116
+ name="API Gateway" label="Container" stats="8n 12e"
117
+ cardClass="dg-focus-api"
118
+ />
119
+ {/* Sibling View */}
120
+ <GridCard
121
+ x={210} y={75}
122
+ name="Analytics" label="Context" stats="2n 1e"
123
+ wasd="D"
124
+ wasdClass="dg-d-key"
125
+ />
126
+ </g>
127
+
128
+ <text x="140" y="141" textAnchor="middle" fill="#2D3748" fontSize="8" fontFamily="system-ui,sans-serif">navigate with WASD or arrow keys</text>
129
+ </svg>
130
+ )
131
+ }
132
+
133
+ // Step 1 - Build Hierarchy (+ buttons)
134
+ function HierarchyIllustration() {
135
+ return (
136
+ <svg
137
+ viewBox="0 0 280 150"
138
+ xmlns="http://www.w3.org/2000/svg"
139
+ style={{ width: '100%', height: 'auto', borderRadius: 10, display: 'block', overflow: 'hidden' }}
140
+ >
141
+ <defs>
142
+ <style>{`
143
+ .dg-plus-group { animation: dgPlusFade 6s infinite; }
144
+ @keyframes dgPlusFade {
145
+ 0%, 15%, 85%, 100% { opacity: 0; }
146
+ 20%, 80% { opacity: 1; }
147
+ }
148
+ .dg-hier-cursor {
149
+ animation: dgHierCursorMove 6s ease-in-out infinite;
150
+ }
151
+ @keyframes dgHierCursorMove {
152
+ 0%, 25% { transform: translate(220px, 120px); opacity: 0; }
153
+ 30% { opacity: 1; }
154
+ 45% { transform: translate(145px, 75px); opacity: 1; }
155
+ 50% { transform: translate(145px, 75px) scale(0.85); opacity: 1; }
156
+ 55%, 85% { transform: translate(145px, 75px) scale(1); opacity: 0; }
157
+ 100% { opacity: 0; }
158
+ }
159
+ .dg-new-card-hier {
160
+ animation: dgNewCardSnap 6s infinite;
161
+ }
162
+ @keyframes dgNewCardSnap {
163
+ 0%, 49% { opacity: 0; }
164
+ 50%, 100% { opacity: 1; }
165
+ }
166
+ `}</style>
167
+ </defs>
168
+ <rect width="280" height="150" fill="#0D1117" rx="8" />
169
+ <GridDots prefix="hier" />
170
+
171
+ {/* Primary card shifted left */}
172
+ <GridCard x={40} y={45} name="Auth Service" label="Container" stats="3n 4e" cardClass="dg-focus-api" />
173
+
174
+ {/* New card that appears on click */}
175
+ <GridCard x={150} y={45} name="User DB" label="Database" stats="0n" cardClass="dg-new-card-hier" />
176
+
177
+ <g className="dg-plus-group">
178
+ {/* Top + */}
179
+ <circle cx="90" cy="40" r="8" fill="#1F2937" stroke="#63B3ED" strokeWidth="1" />
180
+ <text x="90" y="43" textAnchor="middle" fill="#63B3ED" fontSize="10" fontFamily="system-ui,sans-serif">+</text>
181
+
182
+ {/* Bottom + */}
183
+ <circle cx="90" cy="110" r="8" fill="#1F2937" stroke="#63B3ED" strokeWidth="1" />
184
+ <text x="90" y="113" textAnchor="middle" fill="#63B3ED" fontSize="10" fontFamily="system-ui,sans-serif">+</text>
185
+
186
+ {/* Left + */}
187
+ <circle cx="35" cy="75" r="8" fill="#1F2937" stroke="#63B3ED" strokeWidth="1" />
188
+ <text x="35" y="78" textAnchor="middle" fill="#63B3ED" fontSize="10" fontFamily="system-ui,sans-serif">+</text>
189
+
190
+ {/* Right + (Being clicked) */}
191
+ <circle cx="145" cy="75" r="8" fill="#1F2937" stroke="#63B3ED" strokeWidth="1" />
192
+ <text x="145" y="78" textAnchor="middle" fill="#63B3ED" fontSize="10" fontFamily="system-ui,sans-serif">+</text>
193
+ </g>
194
+
195
+ {/* Cursor */}
196
+ <g className="dg-hier-cursor">
197
+ <path d="M0,0 L0,14 L4,10 L7,17 L9,16 L6,9 L11,9 Z" fill="white" stroke="#0D1117" strokeWidth="0.6" />
198
+ </g>
199
+
200
+ <text x="140" y="141" textAnchor="middle" fill="#2D3748" fontSize="8" fontFamily="system-ui,sans-serif">click the + buttons to build your hierarchy</text>
201
+ </svg>
202
+ )
203
+ }
204
+
205
+ // Step 2 - Connect & Organize
206
+ function ConnectIllustration() {
207
+ return (
208
+ <svg
209
+ viewBox="0 0 280 150"
210
+ xmlns="http://www.w3.org/2000/svg"
211
+ style={{ width: '100%', height: 'auto', borderRadius: 10, display: 'block', overflow: 'hidden' }}
212
+ >
213
+ <defs>
214
+ <style>{`
215
+ .dg-conn-arrow { animation: dgConnDraw 4s infinite; }
216
+ @keyframes dgConnDraw {
217
+ 0%, 25% { stroke-dashoffset: 100; opacity: 0; }
218
+ 45%, 85% { stroke-dashoffset: 0; opacity: 1; }
219
+ 95%, 100% { opacity: 0; }
220
+ }
221
+ `}</style>
222
+ <marker id="dg-head" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto">
223
+ <path d="M0,0 L0,6 L6,3 z" fill="#63B3ED" />
224
+ </marker>
225
+ </defs>
226
+ <rect width="280" height="150" fill="#0D1117" rx="8" />
227
+ <GridDots prefix="conn" />
228
+
229
+ {/* Activated card with connect button */}
230
+ <GridCard
231
+ x={30} y={45}
232
+ name="Database" label="Database" stats="1n"
233
+ showConnect
234
+ />
235
+
236
+ <GridCard x={150} y={45} name="Cache" label="Component" stats="0n" />
237
+
238
+ {/* Connection arrow starting from the connect button area of the first card (approx x=124, y=88 in svg space) */}
239
+ <path
240
+ d="M130 75 C 135 75, 140 75, 150 75"
241
+ stroke="#63B3ED"
242
+ strokeWidth="1.5"
243
+ strokeDasharray="100"
244
+ strokeDashoffset="100"
245
+ markerEnd="url(#dg-head)"
246
+ className="dg-conn-arrow"
247
+ />
248
+
249
+ <text x="140" y="141" textAnchor="middle" fill="#2D3748" fontSize="8" fontFamily="system-ui,sans-serif">link views together with the arrow icon</text>
250
+ </svg>
251
+ )
252
+ }
253
+
254
+ // ── Steps data ───────────────────────────────────────────────────────────────
255
+
256
+ const STEPS = [
257
+ {
258
+ title: 'Explore the Grid',
259
+ body: 'Your views are laid out in a visual grid showing their hierarchy. Navigate quickly between them using WASD or your arrow keys.',
260
+ visual: 'grid' as const,
261
+ },
262
+ {
263
+ title: 'Build Your Hierarchy',
264
+ body: 'Hover any view to reveal + buttons. Use them to instantly create new parent, child, or sibling views in your C4 map.',
265
+ visual: 'hierarchy' as const,
266
+ },
267
+ {
268
+ title: 'Connect & Organize',
269
+ body: 'Use the arrow icon to link views together. The ··· menu lets you rename, move between levels, or share your work.',
270
+ visual: 'connect' as const,
271
+ },
272
+ ]
273
+
274
+ // ── Main component ───────────────────────────────────────────────────────────
275
+
276
+ export default function ViewsGridOnboarding({ hasViews }: Props) {
277
+ const [visible, setVisible] = useState(false)
278
+ const [step, setStep] = useState(0)
279
+
280
+ useEffect(() => {
281
+ if (!hasViews) return
282
+ if (!localStorage.getItem(STORAGE_KEY)) {
283
+ setVisible(true)
284
+ }
285
+ }, [ hasViews])
286
+
287
+ const dismiss = () => {
288
+ localStorage.setItem(STORAGE_KEY, '1')
289
+ setVisible(false)
290
+ }
291
+
292
+ if (!visible) return null
293
+
294
+ const current = STEPS[step]
295
+ const isLast = step === STEPS.length - 1
296
+
297
+ return (
298
+ <Box
299
+ position="fixed"
300
+ inset={0}
301
+ zIndex={2000}
302
+ display="flex"
303
+ alignItems="center"
304
+ justifyContent="center"
305
+ pointerEvents="none"
306
+ >
307
+ {/* Backdrop */}
308
+ <Box
309
+ position="absolute"
310
+ inset={0}
311
+ bg="blackAlpha.700"
312
+ pointerEvents="auto"
313
+ onClick={dismiss}
314
+ />
315
+
316
+ {/* Tutorial card */}
317
+ <Box
318
+ position="relative"
319
+ w="380px"
320
+ bg="var(--bg-panel)"
321
+ border="1px solid"
322
+ borderColor="var(--border-main)"
323
+ borderRadius="16px"
324
+ p={6}
325
+ boxShadow="0 24px 60px rgba(0,0,0,0.6), 0 4px 16px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.04)"
326
+ pointerEvents="auto"
327
+ >
328
+ {/* Skip Tutorial */}
329
+ <Button
330
+ position="absolute"
331
+ top={3}
332
+ right={3}
333
+ size="xs"
334
+ variant="ghost"
335
+ color="gray.500"
336
+ _hover={{ color: 'gray.200', bg: 'whiteAlpha.100' }}
337
+ onClick={dismiss}
338
+ fontWeight="normal"
339
+ >
340
+ Skip Tutorial
341
+ </Button>
342
+
343
+ {/* Step indicator dots */}
344
+ <HStack justify="center" spacing={2} mb={5}>
345
+ {STEPS.map((_, i) => (
346
+ <Box
347
+ key={i}
348
+ w={i === step ? '18px' : '6px'}
349
+ h="6px"
350
+ rounded="full"
351
+ bg={i === step ? 'blue.400' : 'gray.600'}
352
+ transition="all 0.25s ease"
353
+ cursor="pointer"
354
+ onClick={() => setStep(i)}
355
+ _hover={{ bg: i === step ? 'blue.400' : 'gray.500' }}
356
+ />
357
+ ))}
358
+ </HStack>
359
+
360
+ {/* Visual + text content */}
361
+ <VStack spacing={4} textAlign="center">
362
+ {current.visual === 'grid' && <GridExploreIllustration />}
363
+ {current.visual === 'hierarchy' && <HierarchyIllustration />}
364
+ {current.visual === 'connect' && <ConnectIllustration />}
365
+
366
+ <VStack spacing={2}>
367
+ <Text fontWeight="bold" fontSize="lg" color="gray.100" lineHeight="short">
368
+ {current.title}
369
+ </Text>
370
+ <Text fontSize="sm" color="gray.400" lineHeight="tall" maxW="300px">
371
+ {current.body}
372
+ </Text>
373
+ </VStack>
374
+ </VStack>
375
+
376
+ {/* Navigation */}
377
+ <HStack mt={6} justify="space-between" align="center">
378
+ <Button
379
+ size="sm"
380
+ variant="ghost"
381
+ color="gray.500"
382
+ _hover={{ color: 'gray.300' }}
383
+ onClick={() => setStep(step - 1)}
384
+ visibility={step > 0 ? 'visible' : 'hidden'}
385
+ >
386
+ ← Back
387
+ </Button>
388
+ <Button
389
+ size="sm"
390
+ colorScheme="blue"
391
+ px={5}
392
+ onClick={isLast ? dismiss : () => setStep(step + 1)}
393
+ >
394
+ {isLast ? 'Got it' : 'Next →'}
395
+ </Button>
396
+ </HStack>
397
+ </Box>
398
+ </Box>
399
+ )
400
+ }