@stephen-netu/design-system 0.1.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 (204) hide show
  1. package/README.md +66 -0
  2. package/package.json +130 -0
  3. package/src/b0-app-shell/clarification-overlay/ClarificationOverlay.svelte +221 -0
  4. package/src/b0-app-shell/clarification-overlay/index.ts +1 -0
  5. package/src/b0-app-shell/command-bar/CommandBar.svelte +565 -0
  6. package/src/b0-app-shell/index.ts +14 -0
  7. package/src/base.css +152 -0
  8. package/src/d0-data-viz/BarChart.svelte +236 -0
  9. package/src/d0-data-viz/CheckpointBar.svelte +574 -0
  10. package/src/d0-data-viz/CheckpointPill.svelte +297 -0
  11. package/src/d0-data-viz/MetricCard.svelte +159 -0
  12. package/src/d0-data-viz/SparkLine.svelte +66 -0
  13. package/src/d0-data-viz/StorageMap.svelte +182 -0
  14. package/src/d0-data-viz/Timeline.svelte +188 -0
  15. package/src/d0-data-viz/checkpoint-types.ts +162 -0
  16. package/src/d0-data-viz/d0-tokens.css +32 -0
  17. package/src/d0-data-viz/index.ts +58 -0
  18. package/src/d0-data-viz/storage-map-types.ts +142 -0
  19. package/src/d0-data-viz/theme-integration.ts +134 -0
  20. package/src/d0-data-viz/types.ts +53 -0
  21. package/src/demos/BspSizingInfographic.svelte +386 -0
  22. package/src/demos/BspZoneDemo.svelte +255 -0
  23. package/src/demos/ControlRoomDemo.svelte +570 -0
  24. package/src/demos/NodepadBlocksShowcase.svelte +189 -0
  25. package/src/demos/index.ts +7 -0
  26. package/src/editor/CodeEditor.svelte +188 -0
  27. package/src/editor/FindReplaceDialog.svelte +516 -0
  28. package/src/editor/MarkdownEditor.svelte +660 -0
  29. package/src/editor/index.ts +2 -0
  30. package/src/entity-graph-view/WorldView.svelte +171 -0
  31. package/src/entity-graph-view/index.ts +6 -0
  32. package/src/entity-graph-view/types.ts +364 -0
  33. package/src/epistemic/index.ts +2 -0
  34. package/src/epistemic/types.ts +134 -0
  35. package/src/epistemic/utils.ts +32 -0
  36. package/src/f0-forms/checkbox/Checkbox.svelte +158 -0
  37. package/src/f0-forms/field/FormField.svelte +91 -0
  38. package/src/f0-forms/index.ts +11 -0
  39. package/src/f0-forms/radio/RadioGroup.svelte +192 -0
  40. package/src/f0-forms/search/SearchBar.svelte +99 -0
  41. package/src/f0-forms/select/Select.svelte +198 -0
  42. package/src/f0-forms/textarea/TextArea.svelte +170 -0
  43. package/src/f0-forms/toggle/FormToggle.svelte +147 -0
  44. package/src/f0-forms/validation/validate.ts +47 -0
  45. package/src/fabric/ai/ChatPanel.svelte +648 -0
  46. package/src/fabric/ai/index.ts +11 -0
  47. package/src/fabric/data/index.ts +21 -0
  48. package/src/fabric/feedback/StatusBar.svelte +274 -0
  49. package/src/fabric/feedback/ToastContainer.svelte +122 -0
  50. package/src/fabric/feedback/index.ts +14 -0
  51. package/src/fabric/index.ts +37 -0
  52. package/src/fabric/input/CommandBar.svelte +79 -0
  53. package/src/fabric/input/KeyboardShortcuts.svelte +388 -0
  54. package/src/fabric/input/index.ts +12 -0
  55. package/src/fabric/layout/GlassBox.svelte +193 -0
  56. package/src/fabric/layout/KanbanBoard.svelte +158 -0
  57. package/src/fabric/layout/KanbanCard.svelte +226 -0
  58. package/src/fabric/layout/KanbanColumn.svelte +278 -0
  59. package/src/fabric/layout/index.ts +17 -0
  60. package/src/fabric/navigation/ActivityRail.svelte +271 -0
  61. package/src/fabric/navigation/index.ts +11 -0
  62. package/src/g0-geo/SovereignMap.svelte +149 -0
  63. package/src/g0-geo/index.ts +2 -0
  64. package/src/index.ts +68 -0
  65. package/src/l0-layout/block-writer/BlockConnectionLines.svelte +98 -0
  66. package/src/l0-layout/block-writer/BlockContent.svelte +213 -0
  67. package/src/l0-layout/block-writer/BlockHeader.svelte +230 -0
  68. package/src/l0-layout/block-writer/BlockItem.svelte +177 -0
  69. package/src/l0-layout/block-writer/BlockWriter.svelte +219 -0
  70. package/src/l0-layout/block-writer/block-writer-types.ts +63 -0
  71. package/src/l0-layout/block-writer/index.ts +24 -0
  72. package/src/l0-layout/block-writer/markdown.ts +110 -0
  73. package/src/l0-layout/chat-view/ChatViewLayout.svelte +61 -0
  74. package/src/l0-layout/epistemic/AllayDetailPanel.svelte +113 -0
  75. package/src/l0-layout/epistemic/AssayDetailPanel.svelte +164 -0
  76. package/src/l0-layout/epistemic/AvenueTrace.svelte +253 -0
  77. package/src/l0-layout/epistemic/KnowledgeDetailPanel.svelte +204 -0
  78. package/src/l0-layout/epistemic/ParadigmLens.svelte +170 -0
  79. package/src/l0-layout/epistemic/ProvenanceChain.svelte +164 -0
  80. package/src/l0-layout/epistemic/TrustView.svelte +195 -0
  81. package/src/l0-layout/epistemic/index.ts +7 -0
  82. package/src/l0-layout/grove/AccordCard.svelte +156 -0
  83. package/src/l0-layout/grove/GroveCard.svelte +197 -0
  84. package/src/l0-layout/grove/MemberBadge.svelte +96 -0
  85. package/src/l0-layout/grove/MemberList.svelte +59 -0
  86. package/src/l0-layout/grove/grove-types.ts +29 -0
  87. package/src/l0-layout/grove/index.ts +14 -0
  88. package/src/l0-layout/index.ts +45 -0
  89. package/src/l0-layout/kanban/KanbanBoard.svelte +71 -0
  90. package/src/l0-layout/kanban/KanbanCard.svelte +276 -0
  91. package/src/l0-layout/kanban/KanbanColumn.svelte +198 -0
  92. package/src/l0-layout/kanban/KanbanViewLayout.svelte +61 -0
  93. package/src/l0-layout/workspace/WorkspaceLayout.svelte +93 -0
  94. package/src/n0-node-graph/GraphEditor.svelte +342 -0
  95. package/src/n0-node-graph/GraphHistory.svelte +122 -0
  96. package/src/n0-node-graph/Node.svelte +269 -0
  97. package/src/n0-node-graph/NodeCanvas.svelte +187 -0
  98. package/src/n0-node-graph/NodeEdge.svelte +152 -0
  99. package/src/n0-node-graph/NodePalette.svelte +318 -0
  100. package/src/n0-node-graph/NodePort.svelte +128 -0
  101. package/src/n0-node-graph/index.ts +33 -0
  102. package/src/n0-node-graph/n0-tokens.css +29 -0
  103. package/src/n0-node-graph/node-port-types.ts +19 -0
  104. package/src/n0-node-graph/types.ts +96 -0
  105. package/src/n0-node-graph/validate.test.ts +722 -0
  106. package/src/n0-node-graph/validate.ts +371 -0
  107. package/src/n1-flow-canvas/FlowCanvas.svelte +202 -0
  108. package/src/n1-flow-canvas/graph-state.svelte.ts +95 -0
  109. package/src/n1-flow-canvas/index.ts +21 -0
  110. package/src/n1-flow-canvas/layout.ts +118 -0
  111. package/src/n1-flow-canvas/layout.worker.ts +128 -0
  112. package/src/n1-flow-canvas/types.ts +102 -0
  113. package/src/n1-flow-canvas/utils.ts +146 -0
  114. package/src/n2-manifold-disk/ManifoldDisk.svelte +314 -0
  115. package/src/n2-manifold-disk/index.ts +6 -0
  116. package/src/n2-manifold-disk/poincare.ts +184 -0
  117. package/src/n3-force-graph/ForceGraph.svelte +180 -0
  118. package/src/n3-force-graph/GraphTooltip.svelte +99 -0
  119. package/src/n3-force-graph/animated-edge.ts +107 -0
  120. package/src/n3-force-graph/health-node.ts +128 -0
  121. package/src/n3-force-graph/index.ts +31 -0
  122. package/src/n3-force-graph/types.ts +94 -0
  123. package/src/n4-adaptive-manifold/AdaptiveManifold.svelte +1165 -0
  124. package/src/n4-adaptive-manifold/DetailCard.svelte +212 -0
  125. package/src/n4-adaptive-manifold/SuggestionIndicator.svelte +91 -0
  126. package/src/n4-adaptive-manifold/classifier.ts +139 -0
  127. package/src/n4-adaptive-manifold/index.ts +45 -0
  128. package/src/n4-adaptive-manifold/n4-tokens.css +155 -0
  129. package/src/n4-adaptive-manifold/orchestrator.ts +301 -0
  130. package/src/n4-adaptive-manifold/phase-theme.ts +92 -0
  131. package/src/n4-adaptive-manifold/pinnacle-events.ts +135 -0
  132. package/src/n4-adaptive-manifold/providers/gravitational-provider.ts +191 -0
  133. package/src/n4-adaptive-manifold/providers/manifold-provider.ts +276 -0
  134. package/src/n4-adaptive-manifold/transition.ts +90 -0
  135. package/src/n4-adaptive-manifold/types.ts +313 -0
  136. package/src/p0-primitives/index.ts +6 -0
  137. package/src/p0-primitives/tokens/control-room.css +309 -0
  138. package/src/p0-primitives/tokens/index.ts +6 -0
  139. package/src/p0-primitives/tokens/tokens.css +140 -0
  140. package/src/p0-primitives/tokens/tokens.json +132 -0
  141. package/src/p0-primitives/types/index.ts +123 -0
  142. package/src/p0-primitives/types/plugin-types.ts +74 -0
  143. package/src/p0-primitives/utils/index.ts +39 -0
  144. package/src/platform/hud-protocol.ts +20 -0
  145. package/src/platform/index.ts +3 -0
  146. package/src/s0-state/create-store.ts +84 -0
  147. package/src/s0-state/derived.ts +41 -0
  148. package/src/s0-state/index.ts +6 -0
  149. package/src/showcase/Showcase.svelte +401 -0
  150. package/src/spatial/BspTilingCanvas.svelte +232 -0
  151. package/src/spatial/ForceCanvas.svelte +289 -0
  152. package/src/spatial/LodRenderer.svelte +334 -0
  153. package/src/spatial/SnapZoomCamera.svelte +185 -0
  154. package/src/spatial/ZoneTiler.svelte +311 -0
  155. package/src/spatial/camera-types.ts +45 -0
  156. package/src/spatial/content-proportional-bsp.ts +253 -0
  157. package/src/spatial/force-canvas-types.ts +102 -0
  158. package/src/spatial/index.ts +15 -0
  159. package/src/spatial/lod-types.ts +70 -0
  160. package/src/spatial/zone-tiler-types.ts +177 -0
  161. package/src/stores/vaultStore.svelte +14 -0
  162. package/src/t0-transport/connection.ts +34 -0
  163. package/src/t0-transport/error.ts +37 -0
  164. package/src/t0-transport/events.ts +50 -0
  165. package/src/t0-transport/index.ts +6 -0
  166. package/src/t0-transport/invoke.ts +30 -0
  167. package/src/tauri/index.ts +13 -0
  168. package/src/u0-primitives/allay-gauge/AllayGauge.svelte +90 -0
  169. package/src/u0-primitives/allay-gauge/index.ts +1 -0
  170. package/src/u0-primitives/animated-icon/AnimatedIcon.svelte +273 -0
  171. package/src/u0-primitives/animated-icon/README.md +53 -0
  172. package/src/u0-primitives/animated-icon/index.ts +31 -0
  173. package/src/u0-primitives/assay-badge/AssayBadge.svelte +121 -0
  174. package/src/u0-primitives/assay-badge/AssaySignalBar.svelte +83 -0
  175. package/src/u0-primitives/assay-badge/index.ts +2 -0
  176. package/src/u0-primitives/avatar/Avatar.svelte +177 -0
  177. package/src/u0-primitives/badge/Badge.svelte +149 -0
  178. package/src/u0-primitives/button/Button.svelte +304 -0
  179. package/src/u0-primitives/card/Card.svelte +182 -0
  180. package/src/u0-primitives/dropdown/Dropdown.svelte +305 -0
  181. package/src/u0-primitives/expert-badge/ExpertBadge.svelte +89 -0
  182. package/src/u0-primitives/expert-badge/index.ts +1 -0
  183. package/src/u0-primitives/index.ts +35 -0
  184. package/src/u0-primitives/input/Input.svelte +237 -0
  185. package/src/u0-primitives/modal/Modal.svelte +331 -0
  186. package/src/u0-primitives/modal/index.ts +1 -0
  187. package/src/u0-primitives/spinner/Spinner.svelte +129 -0
  188. package/src/u0-primitives/tabs/Tabs.svelte +225 -0
  189. package/src/u0-primitives/tabs/tabs-types.ts +11 -0
  190. package/src/u0-primitives/toggle/Toggle.svelte +161 -0
  191. package/src/u0-primitives/tooltip/Tooltip.svelte +234 -0
  192. package/src/v0-diagrams/DiagramPanel.svelte +68 -0
  193. package/src/v0-diagrams/MarkmapDiagram.svelte +56 -0
  194. package/src/v0-diagrams/MermaidDiagram.svelte +53 -0
  195. package/src/v0-diagrams/index.ts +4 -0
  196. package/src/v0-diagrams/types.ts +28 -0
  197. package/src/v0-diagrams/v0-tokens.css +6 -0
  198. package/src/vite-env.d.ts +7 -0
  199. package/src/x0-enchanted-blocks/ENCHANTED_BLOCKS_SPEC.md +457 -0
  200. package/src/x0-enchanted-blocks/components/EnchantedBlock.svelte +485 -0
  201. package/src/x0-enchanted-blocks/components/NodepadBlock.svelte +262 -0
  202. package/src/x0-enchanted-blocks/core/block-layout.ts +211 -0
  203. package/src/x0-enchanted-blocks/core/block-types.ts +227 -0
  204. package/src/x0-enchanted-blocks/index.ts +46 -0
@@ -0,0 +1,161 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ checked?: boolean;
6
+ disabled?: boolean;
7
+ size?: 'sm' | 'md' | 'lg';
8
+ class?: string;
9
+ onchange?: (checked: boolean) => void;
10
+ label?: Snippet;
11
+ }
12
+
13
+ let {
14
+ checked = $bindable(false),
15
+ disabled = false,
16
+ size = 'md',
17
+ class: className = '',
18
+ onchange,
19
+ label
20
+ }: Props = $props();
21
+
22
+ function toggle() {
23
+ if (!disabled) {
24
+ checked = !checked;
25
+ onchange?.(checked);
26
+ }
27
+ }
28
+
29
+ function handleKeydown(e: KeyboardEvent) {
30
+ if (e.key === 'Enter' || e.key === ' ') {
31
+ e.preventDefault();
32
+ toggle();
33
+ }
34
+ }
35
+ </script>
36
+
37
+ <!-- svelte-ignore a11y_interactive_supports_focus -->
38
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
39
+ <label class="ds-toggle-wrapper size-{size} {className}" class:is-disabled={disabled}>
40
+ <div
41
+ class="ds-toggle-track"
42
+ class:is-checked={checked}
43
+ role="switch"
44
+ aria-checked={checked}
45
+ tabindex={disabled ? -1 : 0}
46
+ onkeydown={handleKeydown}
47
+ onclick={(e) => { e.preventDefault(); toggle(); }}
48
+ >
49
+ <div class="ds-toggle-thumb"></div>
50
+ </div>
51
+
52
+ {#if label}
53
+ <span class="ds-toggle-label">
54
+ {@render label()}
55
+ </span>
56
+ {/if}
57
+ </label>
58
+
59
+ <style>
60
+ .ds-toggle-wrapper {
61
+ display: inline-flex;
62
+ align-items: center;
63
+ gap: var(--space-3);
64
+ cursor: pointer;
65
+ user-select: none;
66
+ }
67
+
68
+ .ds-toggle-wrapper.is-disabled {
69
+ cursor: not-allowed;
70
+ opacity: 0.5;
71
+ }
72
+
73
+ .ds-toggle-track {
74
+ position: relative;
75
+ background: var(--color-bg-panel-elevated);
76
+ border: 1px solid var(--border-default);
77
+ border-radius: var(--radius-full);
78
+ transition: all var(--transition-normal);
79
+ box-shadow: inset 0 1px 3px rgba(0,0,0,0.2);
80
+ }
81
+
82
+ /* Track Focus */
83
+ .ds-toggle-track:focus-visible {
84
+ outline: 2px solid var(--color-accent);
85
+ outline-offset: 2px;
86
+ }
87
+
88
+ .ds-toggle-thumb {
89
+ position: absolute;
90
+ top: 2px;
91
+ left: 2px;
92
+ background: var(--color-text-secondary);
93
+ border-radius: var(--radius-full);
94
+ transition: all var(--transition-bounce);
95
+ box-shadow: 0 1px 3px rgba(0,0,0,0.3);
96
+ }
97
+
98
+ /* Checked State */
99
+ .ds-toggle-track.is-checked {
100
+ background: var(--color-accent);
101
+ border-color: var(--color-accent-hover);
102
+ box-shadow: inset 0 1px 2px rgba(0,0,0,0.3), 0 0 8px var(--color-accent-subtle);
103
+ }
104
+
105
+ .ds-toggle-track.is-checked .ds-toggle-thumb {
106
+ background: #fff;
107
+ }
108
+
109
+ /* Label */
110
+ .ds-toggle-label {
111
+ font-family: var(--font-sans);
112
+ color: var(--color-text-primary);
113
+ }
114
+
115
+ /* --- Sizes --- */
116
+
117
+ .size-sm .ds-toggle-track {
118
+ width: 2rem;
119
+ height: 1.125rem;
120
+ }
121
+ .size-sm .ds-toggle-thumb {
122
+ width: 0.875rem;
123
+ height: 0.875rem;
124
+ }
125
+ .size-sm .ds-toggle-track.is-checked .ds-toggle-thumb {
126
+ transform: translateX(0.875rem);
127
+ }
128
+ .size-sm .ds-toggle-label {
129
+ font-size: var(--text-xs);
130
+ }
131
+
132
+ .size-md .ds-toggle-track {
133
+ width: 2.75rem;
134
+ height: 1.5rem;
135
+ }
136
+ .size-md .ds-toggle-thumb {
137
+ width: 1.25rem;
138
+ height: 1.25rem;
139
+ }
140
+ .size-md .ds-toggle-track.is-checked .ds-toggle-thumb {
141
+ transform: translateX(1.25rem);
142
+ }
143
+ .size-md .ds-toggle-label {
144
+ font-size: var(--text-sm);
145
+ }
146
+
147
+ .size-lg .ds-toggle-track {
148
+ width: 3.5rem;
149
+ height: 2rem;
150
+ }
151
+ .size-lg .ds-toggle-thumb {
152
+ width: 1.75rem;
153
+ height: 1.75rem;
154
+ }
155
+ .size-lg .ds-toggle-track.is-checked .ds-toggle-thumb {
156
+ transform: translateX(1.5rem);
157
+ }
158
+ .size-lg .ds-toggle-label {
159
+ font-size: var(--text-base);
160
+ }
161
+ </style>
@@ -0,0 +1,234 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { onDestroy } from 'svelte';
4
+
5
+ interface Props {
6
+ content: string | Snippet;
7
+ position?: 'top' | 'right' | 'bottom' | 'left';
8
+ delayMs?: number;
9
+ class?: string;
10
+ trigger: Snippet;
11
+ }
12
+
13
+ let {
14
+ content,
15
+ position = 'top',
16
+ delayMs = 300,
17
+ class: className = '',
18
+ trigger
19
+ }: Props = $props();
20
+
21
+ let isHovered = $state(false);
22
+ let isFocused = $state(false);
23
+ let isVisible = $state(false);
24
+ let timeoutId: number | undefined;
25
+ const tooltipId = `tooltip-${Math.random().toString(36).slice(2, 9)}`;
26
+
27
+ let showTooltip = $derived(isHovered || isFocused);
28
+
29
+ // Handle delay
30
+ $effect(() => {
31
+ if (showTooltip) {
32
+ if (timeoutId) clearTimeout(timeoutId);
33
+ timeoutId = window.setTimeout(() => {
34
+ isVisible = true;
35
+ }, delayMs);
36
+ } else {
37
+ if (timeoutId) clearTimeout(timeoutId);
38
+ isVisible = false;
39
+ }
40
+ });
41
+
42
+ onDestroy(() => {
43
+ if (timeoutId) clearTimeout(timeoutId);
44
+ });
45
+
46
+ function handleMouseEnter() { isHovered = true; }
47
+ function handleMouseLeave() { isHovered = false; }
48
+ function handleFocus() { isFocused = true; }
49
+ function handleBlur() { isFocused = false; }
50
+ function handleKeydown(e: KeyboardEvent) {
51
+ if (e.key === 'Escape' && isVisible) {
52
+ isHovered = false;
53
+ isFocused = false;
54
+ e.stopPropagation();
55
+ }
56
+ }
57
+ </script>
58
+
59
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
60
+ <div
61
+ class="ds-tooltip-wrapper {className}"
62
+ aria-describedby={isVisible ? tooltipId : undefined}
63
+ onmouseenter={handleMouseEnter}
64
+ onmouseleave={handleMouseLeave}
65
+ onfocusin={handleFocus}
66
+ onfocusout={handleBlur}
67
+ onkeydown={handleKeydown}
68
+ >
69
+ {@render trigger()}
70
+
71
+ {#if isVisible}
72
+ <div
73
+ id={tooltipId}
74
+ class="ds-tooltip-content pos-{position}"
75
+ role="tooltip"
76
+ >
77
+ <div class="ds-tooltip-arrow pos-{position}"></div>
78
+ <div class="ds-tooltip-inner">
79
+ {#if typeof content === 'string'}
80
+ {content}
81
+ {:else}
82
+ {@render content()}
83
+ {/if}
84
+ </div>
85
+ </div>
86
+ {/if}
87
+ </div>
88
+
89
+ <style>
90
+ .ds-tooltip-wrapper {
91
+ position: relative;
92
+ display: inline-block;
93
+ }
94
+
95
+ .ds-tooltip-content {
96
+ position: absolute;
97
+ z-index: 9999;
98
+ width: max-content;
99
+ max-width: 250px;
100
+ background: var(--color-bg-panel-elevated);
101
+ border: 1px solid var(--border-default);
102
+ box-shadow: var(--shadow-lg), 0 0 0 1px rgba(0,0,0,0.5);
103
+ border-radius: var(--radius-md);
104
+ animation: ds-fade-in var(--transition-fast) ease-out;
105
+ pointer-events: none; /* Don't interfere with mouse */
106
+ }
107
+
108
+ .ds-tooltip-inner {
109
+ padding: var(--space-2) var(--space-3);
110
+ color: var(--color-text-primary);
111
+ font-family: var(--font-sans);
112
+ font-size: var(--text-xs);
113
+ line-height: 1.4;
114
+ text-align: center;
115
+ }
116
+
117
+ /* Arrow Base */
118
+ .ds-tooltip-arrow {
119
+ position: absolute;
120
+ width: 0;
121
+ height: 0;
122
+ border-style: solid;
123
+ border-color: transparent;
124
+ }
125
+
126
+ /* Position: Top */
127
+ .pos-top {
128
+ bottom: calc(100% + var(--space-2));
129
+ left: 50%;
130
+ transform: translateX(-50%);
131
+ }
132
+
133
+ .ds-tooltip-arrow.pos-top {
134
+ bottom: -5px;
135
+ left: 50%;
136
+ transform: translateX(-50%);
137
+ border-width: 5px 5px 0 5px;
138
+ border-top-color: var(--border-default);
139
+ }
140
+
141
+ .ds-tooltip-arrow.pos-top::after {
142
+ content: '';
143
+ position: absolute;
144
+ top: -5px;
145
+ left: -4px;
146
+ border-style: solid;
147
+ border-width: 4px 4px 0 4px;
148
+ border-color: transparent;
149
+ border-top-color: var(--color-bg-panel-elevated);
150
+ }
151
+
152
+ /* Position: Bottom */
153
+ .pos-bottom {
154
+ top: calc(100% + var(--space-2));
155
+ left: 50%;
156
+ transform: translateX(-50%);
157
+ }
158
+
159
+ .ds-tooltip-arrow.pos-bottom {
160
+ top: -5px;
161
+ left: 50%;
162
+ transform: translateX(-50%);
163
+ border-width: 0 5px 5px 5px;
164
+ border-bottom-color: var(--border-default);
165
+ }
166
+
167
+ .ds-tooltip-arrow.pos-bottom::after {
168
+ content: '';
169
+ position: absolute;
170
+ bottom: -5px;
171
+ left: -4px;
172
+ border-style: solid;
173
+ border-width: 0 4px 4px 4px;
174
+ border-color: transparent;
175
+ border-bottom-color: var(--color-bg-panel-elevated);
176
+ }
177
+
178
+ /* Position: Right */
179
+ .pos-right {
180
+ top: 50%;
181
+ left: calc(100% + var(--space-2));
182
+ transform: translateY(-50%);
183
+ }
184
+
185
+ .ds-tooltip-arrow.pos-right {
186
+ left: -5px;
187
+ top: 50%;
188
+ transform: translateY(-50%);
189
+ border-width: 5px 5px 5px 0;
190
+ border-right-color: var(--border-default);
191
+ }
192
+
193
+ .ds-tooltip-arrow.pos-right::after {
194
+ content: '';
195
+ position: absolute;
196
+ right: -5px;
197
+ top: -4px;
198
+ border-style: solid;
199
+ border-width: 4px 4px 4px 0;
200
+ border-color: transparent;
201
+ border-right-color: var(--color-bg-panel-elevated);
202
+ }
203
+
204
+ /* Position: Left */
205
+ .pos-left {
206
+ top: 50%;
207
+ right: calc(100% + var(--space-2));
208
+ transform: translateY(-50%);
209
+ }
210
+
211
+ .ds-tooltip-arrow.pos-left {
212
+ right: -5px;
213
+ top: 50%;
214
+ transform: translateY(-50%);
215
+ border-width: 5px 0 5px 5px;
216
+ border-left-color: var(--border-default);
217
+ }
218
+
219
+ .ds-tooltip-arrow.pos-left::after {
220
+ content: '';
221
+ position: absolute;
222
+ left: -5px;
223
+ top: -4px;
224
+ border-style: solid;
225
+ border-width: 4px 0 4px 4px;
226
+ border-color: transparent;
227
+ border-left-color: var(--color-bg-panel-elevated);
228
+ }
229
+
230
+ @keyframes ds-fade-in {
231
+ from { opacity: 0; }
232
+ to { opacity: 1; }
233
+ }
234
+ </style>
@@ -0,0 +1,68 @@
1
+ <script lang="ts">
2
+ import { Tabs, type Tab } from '@kos/design-system/u0-primitives';
3
+ import MermaidDiagram from './MermaidDiagram.svelte';
4
+ import MarkmapDiagram from './MarkmapDiagram.svelte';
5
+ import type { DiagramPanelItem, RenderOptions } from './types';
6
+
7
+ let { items, layout = 'tabs', options = {} }: {
8
+ items: DiagramPanelItem[];
9
+ layout?: 'tabs' | 'grid';
10
+ options?: RenderOptions;
11
+ } = $props();
12
+
13
+ function renderDiagram(item: DiagramPanelItem) {
14
+ if (item.spec.type === 'mermaid') {
15
+ return MermaidDiagram;
16
+ } else if (item.spec.type === 'markmap') {
17
+ return MarkmapDiagram;
18
+ }
19
+ return null;
20
+ }
21
+
22
+ let tabs: Tab[] = $derived(items.map(i => ({
23
+ id: i.id,
24
+ label: i.spec.title ?? i.id
25
+ })));
26
+
27
+ let activeTabId = $state('');
28
+ let activeItem = $derived(items.find(i => i.id === activeTabId) ?? null);
29
+ let ActiveComponent = $derived(activeItem ? renderDiagram(activeItem) : null);
30
+ </script>
31
+
32
+ {#if layout === 'tabs'}
33
+ <div class="v0-diagram-tabs">
34
+ <Tabs {tabs} bind:activeId={activeTabId} />
35
+ <div class="v0-diagram-panel">
36
+ {#if ActiveComponent && activeItem}
37
+ <ActiveComponent spec={activeItem.spec} options={activeItem.options ?? options} />
38
+ {/if}
39
+ </div>
40
+ </div>
41
+ {:else}
42
+ <div class="v0-diagram-grid">
43
+ {#each items as item (item.id)}
44
+ {@const Component = renderDiagram(item)}
45
+ {#if Component}
46
+ <Component spec={item.spec} options={item.options ?? options} />
47
+ {/if}
48
+ {/each}
49
+ </div>
50
+ {/if}
51
+
52
+ <style>
53
+ .v0-diagram-tabs {
54
+ display: flex;
55
+ flex-direction: column;
56
+ gap: var(--space-3);
57
+ }
58
+
59
+ .v0-diagram-panel {
60
+ min-height: 200px;
61
+ }
62
+
63
+ .v0-diagram-grid {
64
+ display: grid;
65
+ grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
66
+ gap: var(--space-4);
67
+ }
68
+ </style>
@@ -0,0 +1,56 @@
1
+ <script lang="ts">
2
+ import { Transformer } from 'markmap-lib';
3
+ import { Markmap } from 'markmap-view';
4
+ import type { DiagramSpec, RenderOptions } from './types';
5
+
6
+ let { spec, options = {} }: {
7
+ spec: DiagramSpec;
8
+ options?: RenderOptions;
9
+ } = $props();
10
+
11
+ let svgEl: SVGSVGElement;
12
+ let markmapInstance: Markmap | null = null;
13
+
14
+ $effect(() => {
15
+ if (!svgEl) return;
16
+
17
+ const transformer = new Transformer();
18
+ const { root } = transformer.transform(spec.source);
19
+
20
+ if (markmapInstance) {
21
+ markmapInstance.destroy();
22
+ }
23
+
24
+ markmapInstance = Markmap.create(svgEl, {}, root);
25
+ });
26
+ </script>
27
+
28
+ <div class="v0-diagram v0-diagram--markmap">
29
+ {#if spec.title}
30
+ <h4 class="v0-diagram-title">{spec.title}</h4>
31
+ {/if}
32
+ <svg bind:this={svgEl}
33
+ width={options.width ?? 600}
34
+ height={options.height ?? 400}
35
+ />
36
+ </div>
37
+
38
+ <style>
39
+ .v0-diagram {
40
+ background: var(--v0-diagram-bg);
41
+ border: 1px solid var(--v0-diagram-border);
42
+ border-radius: var(--radius-lg);
43
+ padding: var(--v0-diagram-padding);
44
+ overflow: auto;
45
+ }
46
+ .v0-diagram-title {
47
+ color: var(--v0-diagram-title-color);
48
+ font-family: var(--font-mono);
49
+ font-size: var(--text-sm);
50
+ margin-bottom: var(--space-3);
51
+ }
52
+ :global(.v0-diagram--markmap svg) {
53
+ max-width: 100%;
54
+ height: auto;
55
+ }
56
+ </style>
@@ -0,0 +1,53 @@
1
+ <script lang="ts">
2
+ import mermaid from 'mermaid';
3
+ import type { DiagramSpec, RenderOptions } from './types';
4
+
5
+ mermaid.initialize({
6
+ securityLevel: 'strict',
7
+ startOnLoad: false,
8
+ });
9
+
10
+ let { spec, options = {} }: {
11
+ spec: DiagramSpec;
12
+ options?: RenderOptions;
13
+ } = $props();
14
+
15
+ let svgContent = $state('');
16
+
17
+ $effect(() => {
18
+ renderDiagram(spec, options);
19
+ });
20
+
21
+ async function renderDiagram(s: DiagramSpec, opts: RenderOptions) {
22
+ const id = `mermaid-${crypto.randomUUID()}`;
23
+ const { svg } = await mermaid.render(id, s.source);
24
+ svgContent = svg;
25
+ }
26
+ </script>
27
+
28
+ <div class="v0-diagram v0-diagram--mermaid">
29
+ {#if spec.title}
30
+ <h4 class="v0-diagram-title">{spec.title}</h4>
31
+ {/if}
32
+ {@html svgContent}
33
+ </div>
34
+
35
+ <style>
36
+ .v0-diagram {
37
+ background: var(--v0-diagram-bg);
38
+ border: 1px solid var(--v0-diagram-border);
39
+ border-radius: var(--radius-lg);
40
+ padding: var(--v0-diagram-padding);
41
+ overflow: auto;
42
+ }
43
+ .v0-diagram-title {
44
+ color: var(--v0-diagram-title-color);
45
+ font-family: var(--font-mono);
46
+ font-size: var(--text-sm);
47
+ margin-bottom: var(--space-3);
48
+ }
49
+ :global(.v0-diagram--mermaid svg) {
50
+ max-width: 100%;
51
+ height: auto;
52
+ }
53
+ </style>
@@ -0,0 +1,4 @@
1
+ export type { DiagramSpec, DiagramType, DiagramProvenance, RenderOptions, DiagramPanelItem } from './types';
2
+ export { default as MarkmapDiagram } from './MarkmapDiagram.svelte';
3
+ export { default as MermaidDiagram } from './MermaidDiagram.svelte';
4
+ export { default as DiagramPanel } from './DiagramPanel.svelte';
@@ -0,0 +1,28 @@
1
+ export type DiagramType = 'mermaid' | 'markmap';
2
+
3
+ export interface DiagramSpec {
4
+ type: DiagramType;
5
+ source: string;
6
+ title?: string;
7
+ provenance?: DiagramProvenance;
8
+ }
9
+
10
+ export interface DiagramProvenance {
11
+ sourceFile: string;
12
+ sourceHash: string;
13
+ generationSeq: number;
14
+ sacsRefreshSeq: number;
15
+ }
16
+
17
+ export interface RenderOptions {
18
+ theme?: 'dark' | 'light';
19
+ width?: number;
20
+ height?: number;
21
+ padding?: number;
22
+ }
23
+
24
+ export interface DiagramPanelItem {
25
+ id: string;
26
+ spec: DiagramSpec;
27
+ options?: RenderOptions;
28
+ }
@@ -0,0 +1,6 @@
1
+ :root {
2
+ --v0-diagram-bg: var(--color-bg-panel);
3
+ --v0-diagram-border: var(--border-subtle);
4
+ --v0-diagram-title-color: var(--color-text-secondary);
5
+ --v0-diagram-padding: var(--space-4);
6
+ }
@@ -0,0 +1,7 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ // Allow dynamic CSS imports (used by SovereignMap for Leaflet styles).
4
+ declare module '*.css' {
5
+ const content: Record<string, string>;
6
+ export default content;
7
+ }