@plures/design-dojo 0.5.3 → 0.7.1

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 (250) hide show
  1. package/dist/app/CanvasBreadcrumb.svelte +146 -0
  2. package/dist/app/CanvasBreadcrumb.svelte.d.ts +19 -0
  3. package/dist/app/CanvasBreadcrumb.types.js +1 -0
  4. package/dist/app/ChatInput.svelte +296 -0
  5. package/dist/app/ChatInput.svelte.d.ts +15 -0
  6. package/dist/app/ChatView.svelte +542 -0
  7. package/dist/app/ChatView.svelte.d.ts +19 -0
  8. package/dist/app/ChatView.types.js +1 -0
  9. package/dist/app/ConversationGraph.svelte +471 -0
  10. package/dist/app/ConversationGraph.svelte.d.ts +20 -0
  11. package/dist/app/FirstRunWizard.svelte +542 -0
  12. package/dist/app/FirstRunWizard.svelte.d.ts +10 -0
  13. package/dist/app/FirstRunWizard.types.js +1 -0
  14. package/dist/app/MemorySidebar.svelte +258 -0
  15. package/dist/app/MemorySidebar.svelte.d.ts +9 -0
  16. package/dist/app/MemorySidebar.types.js +1 -0
  17. package/dist/app/PeerStatusPanel.svelte +464 -0
  18. package/dist/app/PeerStatusPanel.svelte.d.ts +16 -0
  19. package/dist/app/ProcedureCanvas.svelte +994 -0
  20. package/dist/app/ProcedureCanvas.svelte.d.ts +12 -0
  21. package/dist/app/ProcedureCanvas.types.js +1 -0
  22. package/dist/app/ProcedureEditor.svelte +494 -0
  23. package/dist/app/ProcedureEditor.svelte.d.ts +11 -0
  24. package/dist/app/ProcedureEditor.types.js +1 -0
  25. package/dist/app/ProcedureInspector.svelte +520 -0
  26. package/dist/app/ProcedureInspector.svelte.d.ts +15 -0
  27. package/dist/app/ProcedureNode.svelte +283 -0
  28. package/dist/app/ProcedureNode.svelte.d.ts +26 -0
  29. package/dist/app/Realm.types.js +1 -0
  30. package/dist/app/RealmIndicator.svelte +81 -0
  31. package/dist/app/RealmIndicator.svelte.d.ts +10 -0
  32. package/dist/app/RealmSwitcher.svelte +354 -0
  33. package/dist/app/RealmSwitcher.svelte.d.ts +16 -0
  34. package/dist/app/SemanticConversation.types.js +1 -0
  35. package/dist/app/SemanticSearchInput.svelte +630 -0
  36. package/dist/app/SemanticSearchInput.svelte.d.ts +20 -0
  37. package/dist/app/SemanticSearchInput.types.js +1 -0
  38. package/dist/app/SemanticTimeline.svelte +426 -0
  39. package/dist/app/SemanticTimeline.svelte.d.ts +13 -0
  40. package/dist/app/SettingsPanel.svelte +330 -0
  41. package/dist/app/SettingsPanel.svelte.d.ts +12 -0
  42. package/dist/app/SettingsPanel.types.js +1 -0
  43. package/dist/app/SubCanvas.svelte +457 -0
  44. package/dist/app/SubCanvas.svelte.d.ts +48 -0
  45. package/dist/app/SubCanvas.types.js +1 -0
  46. package/dist/app/Sync.types.js +1 -0
  47. package/dist/app/SyncIndicator.svelte +219 -0
  48. package/dist/app/SyncIndicator.svelte.d.ts +15 -0
  49. package/dist/app/SyncTimeline.svelte +299 -0
  50. package/dist/app/SyncTimeline.svelte.d.ts +12 -0
  51. package/dist/app/TagCloud.svelte +287 -0
  52. package/dist/app/TagCloud.svelte.d.ts +12 -0
  53. package/dist/app/WorkModeToggle.svelte +188 -0
  54. package/dist/app/WorkModeToggle.svelte.d.ts +17 -0
  55. package/dist/data/List.svelte +104 -0
  56. package/dist/data/List.svelte.d.ts +18 -0
  57. package/dist/data/ListItem.svelte +130 -0
  58. package/dist/data/ListItem.svelte.d.ts +12 -0
  59. package/dist/data/Table.svelte +241 -0
  60. package/dist/data/Table.svelte.d.ts +17 -0
  61. package/dist/data/index.d.ts +3 -0
  62. package/dist/data/index.js +3 -0
  63. package/dist/disclosure/Accordion.svelte +48 -0
  64. package/dist/disclosure/Accordion.svelte.d.ts +15 -0
  65. package/dist/feedback/Badge.svelte +60 -0
  66. package/dist/feedback/Badge.svelte.d.ts +14 -0
  67. package/dist/feedback/Callout.svelte +52 -0
  68. package/dist/feedback/Callout.svelte.d.ts +12 -0
  69. package/dist/feedback/EmptyState.svelte +47 -0
  70. package/dist/feedback/EmptyState.svelte.d.ts +12 -0
  71. package/dist/feedback/ProgressBar.svelte +95 -0
  72. package/dist/feedback/ProgressBar.svelte.d.ts +16 -0
  73. package/dist/forms/FileUpload.svelte +99 -0
  74. package/dist/forms/FileUpload.svelte.d.ts +18 -0
  75. package/dist/forms/RadioGroup.svelte +84 -0
  76. package/dist/forms/RadioGroup.svelte.d.ts +19 -0
  77. package/dist/icons/NerdFont.svelte +44 -0
  78. package/dist/icons/NerdFont.svelte.d.ts +13 -0
  79. package/dist/icons/index.d.ts +1 -0
  80. package/dist/icons/index.js +1 -0
  81. package/dist/index.d.ts +76 -0
  82. package/dist/index.js +70 -6212
  83. package/dist/layout/Box.svelte +207 -0
  84. package/dist/layout/Box.svelte.d.ts +22 -0
  85. package/dist/layout/Sidebar.svelte +210 -0
  86. package/dist/layout/Sidebar.svelte.d.ts +22 -0
  87. package/dist/layout/SplitPane.svelte +64 -0
  88. package/dist/layout/SplitPane.svelte.d.ts +12 -0
  89. package/dist/layout/StatusBar.svelte +83 -0
  90. package/dist/layout/StatusBar.svelte.d.ts +12 -0
  91. package/dist/layout/StatusBarItem.svelte +146 -0
  92. package/dist/layout/StatusBarItem.svelte.d.ts +15 -0
  93. package/dist/layout/StatusBarSpacer.svelte +38 -0
  94. package/dist/layout/StatusBarSpacer.svelte.d.ts +3 -0
  95. package/dist/layout/Tabs.svelte +254 -0
  96. package/dist/layout/Tabs.svelte.d.ts +21 -0
  97. package/dist/layout/Tabs.types.js +1 -0
  98. package/dist/layout/TitleBar.svelte +422 -0
  99. package/dist/layout/TitleBar.svelte.d.ts +22 -0
  100. package/dist/layout/index.d.ts +9 -0
  101. package/dist/layout/index.js +8 -0
  102. package/dist/motion/index.d.ts +1 -0
  103. package/dist/motion/index.js +1 -0
  104. package/dist/motion/spring.js +116 -0
  105. package/dist/overlays/ContextMenu.svelte +268 -0
  106. package/dist/overlays/ContextMenu.svelte.d.ts +17 -0
  107. package/dist/overlays/Dialog.svelte +264 -0
  108. package/dist/overlays/Dialog.svelte.d.ts +20 -0
  109. package/dist/overlays/Menu.svelte +274 -0
  110. package/dist/overlays/Menu.svelte.d.ts +26 -0
  111. package/dist/overlays/Menu.types.js +1 -0
  112. package/dist/overlays/Popover.svelte +158 -0
  113. package/dist/overlays/Popover.svelte.d.ts +21 -0
  114. package/dist/overlays/Toast.svelte +179 -0
  115. package/dist/overlays/Toast.svelte.d.ts +19 -0
  116. package/dist/overlays/Tooltip.svelte +114 -0
  117. package/dist/overlays/Tooltip.svelte.d.ts +17 -0
  118. package/dist/overlays/index.d.ts +7 -0
  119. package/dist/overlays/index.js +6 -0
  120. package/dist/primitives/Button.svelte +217 -0
  121. package/dist/primitives/Button.svelte.d.ts +13 -0
  122. package/dist/primitives/ContextMenu.svelte +242 -0
  123. package/dist/primitives/ContextMenu.svelte.d.ts +18 -0
  124. package/dist/primitives/ContextMenu.types.js +1 -0
  125. package/dist/primitives/Input.svelte +468 -0
  126. package/dist/primitives/Input.svelte.d.ts +21 -0
  127. package/dist/primitives/MarkdownEditor.svelte +781 -0
  128. package/dist/primitives/MarkdownEditor.svelte.d.ts +21 -0
  129. package/dist/primitives/MarkdownEditor.types.js +1 -0
  130. package/dist/primitives/SearchInput.svelte +623 -0
  131. package/dist/primitives/SearchInput.svelte.d.ts +24 -0
  132. package/dist/primitives/Select.svelte +336 -0
  133. package/dist/primitives/Select.svelte.d.ts +18 -0
  134. package/dist/primitives/Text.svelte +177 -0
  135. package/dist/primitives/Text.svelte.d.ts +26 -0
  136. package/dist/primitives/Toggle.svelte +138 -0
  137. package/dist/primitives/Toggle.svelte.d.ts +9 -0
  138. package/dist/primitives/index.d.ts +9 -0
  139. package/dist/primitives/index.js +7 -0
  140. package/dist/primitives/search-input-types.js +1 -0
  141. package/dist/surfaces/ChatPane.svelte +520 -0
  142. package/dist/surfaces/ChatPane.svelte.d.ts +15 -0
  143. package/dist/surfaces/ChatPane.types.js +1 -0
  144. package/dist/surfaces/GlassPanel.svelte +118 -0
  145. package/dist/surfaces/GlassPanel.svelte.d.ts +19 -0
  146. package/dist/surfaces/Pane.svelte +172 -0
  147. package/dist/surfaces/Pane.svelte.d.ts +25 -0
  148. package/dist/surfaces/index.d.ts +4 -0
  149. package/dist/surfaces/index.js +3 -0
  150. package/dist/telemetry/correlation.js +26 -0
  151. package/dist/telemetry/index.d.ts +4 -4
  152. package/dist/telemetry/index.js +20 -101
  153. package/dist/telemetry/sampling.js +58 -0
  154. package/dist/telemetry/tracer.d.ts +16 -1
  155. package/dist/telemetry/tracer.js +112 -0
  156. package/dist/tokens.css +123 -0
  157. package/dist/tui-tokens.css +36 -0
  158. package/dist/useTui.js +31 -0
  159. package/package.json +32 -22
  160. package/dist/design-dojo.css +0 -1
  161. package/dist/enforce/index.d.ts +0 -75
  162. package/dist/enforce/known-components.d.ts +0 -7
  163. package/dist/enforce/rules/no-local-components.d.ts +0 -29
  164. package/dist/enforce/rules/prefer-design-dojo-imports.d.ts +0 -27
  165. package/dist/enforce.js +0 -132
  166. package/dist/lib/app/CanvasBreadcrumb.svelte.d.ts +0 -1
  167. package/dist/lib/app/ChatInput.svelte.d.ts +0 -1
  168. package/dist/lib/app/ChatView.svelte.d.ts +0 -1
  169. package/dist/lib/app/ConversationGraph.svelte.d.ts +0 -1
  170. package/dist/lib/app/FirstRunWizard.svelte.d.ts +0 -1
  171. package/dist/lib/app/MemorySidebar.svelte.d.ts +0 -1
  172. package/dist/lib/app/PeerStatusPanel.svelte.d.ts +0 -1
  173. package/dist/lib/app/ProcedureCanvas.svelte.d.ts +0 -1
  174. package/dist/lib/app/ProcedureEditor.svelte.d.ts +0 -1
  175. package/dist/lib/app/ProcedureInspector.svelte.d.ts +0 -1
  176. package/dist/lib/app/ProcedureNode.svelte.d.ts +0 -1
  177. package/dist/lib/app/RealmIndicator.svelte.d.ts +0 -1
  178. package/dist/lib/app/RealmSwitcher.svelte.d.ts +0 -1
  179. package/dist/lib/app/SemanticSearchInput.svelte.d.ts +0 -1
  180. package/dist/lib/app/SemanticTimeline.svelte.d.ts +0 -1
  181. package/dist/lib/app/SettingsPanel.svelte.d.ts +0 -1
  182. package/dist/lib/app/SubCanvas.svelte.d.ts +0 -1
  183. package/dist/lib/app/SyncIndicator.svelte.d.ts +0 -1
  184. package/dist/lib/app/SyncTimeline.svelte.d.ts +0 -1
  185. package/dist/lib/app/TagCloud.svelte.d.ts +0 -1
  186. package/dist/lib/app/WorkModeToggle.svelte.d.ts +0 -1
  187. package/dist/lib/data/List.svelte.d.ts +0 -1
  188. package/dist/lib/data/ListItem.svelte.d.ts +0 -1
  189. package/dist/lib/data/Table.svelte.d.ts +0 -1
  190. package/dist/lib/data/index.d.ts +0 -3
  191. package/dist/lib/disclosure/Accordion.svelte.d.ts +0 -1
  192. package/dist/lib/feedback/Badge.svelte.d.ts +0 -1
  193. package/dist/lib/feedback/Callout.svelte.d.ts +0 -1
  194. package/dist/lib/feedback/EmptyState.svelte.d.ts +0 -1
  195. package/dist/lib/feedback/ProgressBar.svelte.d.ts +0 -1
  196. package/dist/lib/forms/FileUpload.svelte.d.ts +0 -1
  197. package/dist/lib/forms/RadioGroup.svelte.d.ts +0 -1
  198. package/dist/lib/icons/NerdFont.svelte.d.ts +0 -1
  199. package/dist/lib/icons/index.d.ts +0 -1
  200. package/dist/lib/index.d.ts +0 -76
  201. package/dist/lib/layout/Box.svelte.d.ts +0 -1
  202. package/dist/lib/layout/Sidebar.svelte.d.ts +0 -1
  203. package/dist/lib/layout/SplitPane.svelte.d.ts +0 -1
  204. package/dist/lib/layout/StatusBar.svelte.d.ts +0 -1
  205. package/dist/lib/layout/StatusBarItem.svelte.d.ts +0 -1
  206. package/dist/lib/layout/StatusBarSpacer.svelte.d.ts +0 -1
  207. package/dist/lib/layout/Tabs.svelte.d.ts +0 -1
  208. package/dist/lib/layout/TitleBar.svelte.d.ts +0 -1
  209. package/dist/lib/layout/index.d.ts +0 -9
  210. package/dist/lib/motion/index.d.ts +0 -1
  211. package/dist/lib/overlays/ContextMenu.svelte.d.ts +0 -1
  212. package/dist/lib/overlays/Dialog.svelte.d.ts +0 -1
  213. package/dist/lib/overlays/Menu.svelte.d.ts +0 -1
  214. package/dist/lib/overlays/Popover.svelte.d.ts +0 -1
  215. package/dist/lib/overlays/Toast.svelte.d.ts +0 -1
  216. package/dist/lib/overlays/Tooltip.svelte.d.ts +0 -1
  217. package/dist/lib/overlays/index.d.ts +0 -7
  218. package/dist/lib/primitives/Button.svelte.d.ts +0 -1
  219. package/dist/lib/primitives/ContextMenu.svelte.d.ts +0 -1
  220. package/dist/lib/primitives/Input.svelte.d.ts +0 -1
  221. package/dist/lib/primitives/MarkdownEditor.svelte.d.ts +0 -1
  222. package/dist/lib/primitives/SearchInput.svelte.d.ts +0 -1
  223. package/dist/lib/primitives/Select.svelte.d.ts +0 -1
  224. package/dist/lib/primitives/Text.svelte.d.ts +0 -1
  225. package/dist/lib/primitives/Toggle.svelte.d.ts +0 -1
  226. package/dist/lib/primitives/index.d.ts +0 -9
  227. package/dist/lib/surfaces/ChatPane.svelte.d.ts +0 -1
  228. package/dist/lib/surfaces/GlassPanel.svelte.d.ts +0 -1
  229. package/dist/lib/surfaces/Pane.svelte.d.ts +0 -1
  230. package/dist/lib/surfaces/index.d.ts +0 -4
  231. /package/dist/{lib/app → app}/CanvasBreadcrumb.types.d.ts +0 -0
  232. /package/dist/{lib/app → app}/ChatView.types.d.ts +0 -0
  233. /package/dist/{lib/app → app}/FirstRunWizard.types.d.ts +0 -0
  234. /package/dist/{lib/app → app}/MemorySidebar.types.d.ts +0 -0
  235. /package/dist/{lib/app → app}/ProcedureCanvas.types.d.ts +0 -0
  236. /package/dist/{lib/app → app}/ProcedureEditor.types.d.ts +0 -0
  237. /package/dist/{lib/app → app}/Realm.types.d.ts +0 -0
  238. /package/dist/{lib/app → app}/SemanticConversation.types.d.ts +0 -0
  239. /package/dist/{lib/app → app}/SemanticSearchInput.types.d.ts +0 -0
  240. /package/dist/{lib/app → app}/SettingsPanel.types.d.ts +0 -0
  241. /package/dist/{lib/app → app}/SubCanvas.types.d.ts +0 -0
  242. /package/dist/{lib/app → app}/Sync.types.d.ts +0 -0
  243. /package/dist/{lib/layout → layout}/Tabs.types.d.ts +0 -0
  244. /package/dist/{lib/motion → motion}/spring.d.ts +0 -0
  245. /package/dist/{lib/overlays → overlays}/Menu.types.d.ts +0 -0
  246. /package/dist/{lib/primitives → primitives}/ContextMenu.types.d.ts +0 -0
  247. /package/dist/{lib/primitives → primitives}/MarkdownEditor.types.d.ts +0 -0
  248. /package/dist/{lib/primitives → primitives}/search-input-types.d.ts +0 -0
  249. /package/dist/{lib/surfaces → surfaces}/ChatPane.types.d.ts +0 -0
  250. /package/dist/{lib/useTui.d.ts → useTui.d.ts} +0 -0
@@ -0,0 +1,146 @@
1
+ <!--
2
+ StatusBarItem — A single item in a StatusBar.
3
+
4
+ Shows an optional label and a value with color coding.
5
+ In TUI mode, renders with terminal-safe colors and │ separators between items.
6
+ The separator is added via CSS ::before — hidden on :first-child automatically.
7
+ -->
8
+ <script lang="ts">
9
+ import { useTui } from "../useTui.js";
10
+
11
+ interface Props {
12
+ /** Optional label shown before the value */
13
+ label?: string;
14
+ /** The value to display */
15
+ value: string;
16
+ /** Color theme for the value */
17
+ color?: "default" | "accent" | "success" | "warning" | "error";
18
+ /** Inverse colors for vim-style mode indicator */
19
+ highlight?: boolean;
20
+ /** Show a visual separator after this item (GUI mode) */
21
+ separator?: boolean;
22
+ }
23
+
24
+ let { label, value, color = "default", highlight = false, separator = false }: Props = $props();
25
+
26
+ const getTuiCtx = useTui();
27
+ const isTui = $derived(getTuiCtx());
28
+ </script>
29
+
30
+ <span
31
+ class="status-item"
32
+ class:tui={isTui}
33
+ class:highlight
34
+ class:has-separator={!isTui && separator}
35
+ data-color={color}
36
+ >
37
+ {#if isTui}
38
+ <span class="tui-content" class:reversed={highlight}>
39
+ {#if label}<span class="tui-label">{label}: </span>{/if}<span class="tui-value">{value}</span>
40
+ </span>
41
+ {:else}
42
+ {#if label}<span class="gui-label">{label}</span>{/if}
43
+ <span class="gui-value">{value}</span>
44
+ {/if}
45
+ </span>
46
+
47
+ <style>
48
+ /* ===== Shared ===== */
49
+ .status-item {
50
+ display: inline-flex;
51
+ align-items: center;
52
+ gap: var(--space-1, 4px);
53
+ padding: 0 var(--space-2, 8px);
54
+ font-size: var(--text-xs, 12px);
55
+ height: 100%;
56
+ white-space: nowrap;
57
+ flex-shrink: 0;
58
+ }
59
+
60
+ /* ===== GUI mode ===== */
61
+ .gui-label {
62
+ color: var(--color-text-muted, #888888);
63
+ font-size: var(--text-xs, 12px);
64
+ }
65
+
66
+ .gui-label::after {
67
+ content: ":";
68
+ margin-right: var(--space-1, 4px);
69
+ }
70
+
71
+ /* GUI value colors */
72
+ .status-item[data-color="default"] .gui-value { color: var(--color-text, #e8e8e8); }
73
+ .status-item[data-color="accent"] .gui-value { color: var(--color-accent, #6366f1); }
74
+ .status-item[data-color="success"] .gui-value { color: var(--color-success, #22c55e); }
75
+ .status-item[data-color="warning"] .gui-value { color: var(--color-warning, #f59e0b); }
76
+ .status-item[data-color="error"] .gui-value { color: var(--color-danger, #ef4444); }
77
+
78
+ /* GUI highlight: inverse colors */
79
+ .status-item.highlight:not(.tui) {
80
+ background: var(--color-accent, #6366f1);
81
+ color: white;
82
+ border-radius: var(--radius-sm, 6px);
83
+ }
84
+
85
+ /* GUI separator: vertical rule after the item */
86
+ .status-item.has-separator:not(.tui)::after {
87
+ content: "";
88
+ display: inline-block;
89
+ width: 1px;
90
+ height: 16px;
91
+ background: var(--color-border, #2a2a2a);
92
+ margin-left: var(--space-2, 8px);
93
+ }
94
+
95
+ /* ===== TUI mode ===== */
96
+ .status-item.tui {
97
+ padding: 0;
98
+ gap: 0;
99
+ font-family: var(--font-mono, monospace);
100
+ font-size: inherit;
101
+ height: auto;
102
+ align-items: stretch;
103
+ }
104
+
105
+ /* Separator: │ before each TUI item, hidden on first child */
106
+ .status-item.tui::before {
107
+ content: "│";
108
+ color: var(--tui-border, #0f3460);
109
+ user-select: none;
110
+ align-self: center;
111
+ }
112
+
113
+ .status-item.tui:first-child::before {
114
+ content: "";
115
+ }
116
+
117
+ .tui-content {
118
+ display: inline-flex;
119
+ align-items: center;
120
+ padding: 0 var(--space-1, 4px);
121
+ align-self: center;
122
+ }
123
+
124
+ .tui-label {
125
+ color: var(--tui-text-dim, #888888);
126
+ }
127
+
128
+ /* TUI value colors */
129
+ .status-item.tui[data-color="default"] .tui-value { color: var(--tui-text, #e0e0e0); }
130
+ .status-item.tui[data-color="accent"] .tui-value { color: var(--tui-accent, #00d4ff); }
131
+ .status-item.tui[data-color="success"] .tui-value { color: var(--tui-success, #00ff88); }
132
+ .status-item.tui[data-color="warning"] .tui-value { color: var(--tui-warning, #ffaa00); }
133
+ .status-item.tui[data-color="error"] .tui-value { color: var(--tui-error, #ff4444); }
134
+
135
+ /* TUI highlight: reversed colors (vim-style mode indicator) */
136
+ .tui-content.reversed {
137
+ background: var(--tui-text, #e0e0e0);
138
+ color: var(--tui-bg, #1a1a2e);
139
+ }
140
+
141
+ /* Override data-color value rules with higher specificity for the reversed state */
142
+ .status-item.tui.highlight[data-color] .tui-value,
143
+ .status-item.tui.highlight[data-color] .tui-label {
144
+ color: var(--tui-bg, #1a1a2e);
145
+ }
146
+ </style>
@@ -0,0 +1,15 @@
1
+ interface Props {
2
+ /** Optional label shown before the value */
3
+ label?: string;
4
+ /** The value to display */
5
+ value: string;
6
+ /** Color theme for the value */
7
+ color?: "default" | "accent" | "success" | "warning" | "error";
8
+ /** Inverse colors for vim-style mode indicator */
9
+ highlight?: boolean;
10
+ /** Show a visual separator after this item (GUI mode) */
11
+ separator?: boolean;
12
+ }
13
+ declare const StatusBarItem: import("svelte").Component<Props, {}, "">;
14
+ type StatusBarItem = ReturnType<typeof StatusBarItem>;
15
+ export default StatusBarItem;
@@ -0,0 +1,38 @@
1
+ <!--
2
+ StatusBarSpacer — Fills remaining horizontal space in a StatusBar.
3
+
4
+ GUI mode: flex: 1 (greedy fill).
5
+ TUI mode: flex: 1 fill with │ separator before it (hidden if first child).
6
+ -->
7
+ <script lang="ts">
8
+ import { useTui } from "../useTui.js";
9
+
10
+ const getTuiCtx = useTui();
11
+ const isTui = $derived(getTuiCtx());
12
+ </script>
13
+
14
+ <span class="status-spacer" class:tui={isTui} aria-hidden="true"></span>
15
+
16
+ <style>
17
+ .status-spacer {
18
+ flex: 1;
19
+ }
20
+
21
+ /* ===== TUI mode ===== */
22
+ .status-spacer.tui {
23
+ display: inline-flex;
24
+ align-items: stretch;
25
+ }
26
+
27
+ /* Separator: │ before the spacer, hidden if it is the first child */
28
+ .status-spacer.tui::before {
29
+ content: "│";
30
+ color: var(--tui-border, #0f3460);
31
+ user-select: none;
32
+ align-self: center;
33
+ }
34
+
35
+ .status-spacer.tui:first-child::before {
36
+ content: "";
37
+ }
38
+ </style>
@@ -0,0 +1,3 @@
1
+ declare const StatusBarSpacer: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type StatusBarSpacer = ReturnType<typeof StatusBarSpacer>;
3
+ export default StatusBarSpacer;
@@ -0,0 +1,254 @@
1
+ <!--
2
+ Tabs — Horizontal tab bar with panel switching.
3
+
4
+ GUI mode: styled tab strip with indicator underline.
5
+ TUI mode: box-drawing tab headers, active tab highlighted with accent color.
6
+ -->
7
+ <script lang="ts">
8
+ import { useTui } from "../useTui.js";
9
+ import type { Snippet } from "svelte";
10
+ import type { Tab } from "./Tabs.types.js";
11
+
12
+ export type { Tab };
13
+
14
+ interface Props {
15
+ /** Tab definitions. */
16
+ tabs: Tab[];
17
+ /** Currently active tab key. */
18
+ activeTab?: string;
19
+ /** Called when the user selects a tab. */
20
+ ontabchange?: (key: string) => void;
21
+ /** Enable TUI mode. */
22
+ tui?: boolean;
23
+ /** Tab panel content — receives the active tab key. */
24
+ children?: Snippet<[{ activeTab: string }]>;
25
+ }
26
+
27
+ let {
28
+ tabs,
29
+ activeTab = $bindable(tabs[0]?.key ?? ""),
30
+ ontabchange,
31
+ tui = false,
32
+ children,
33
+ }: Props = $props();
34
+
35
+ const getTuiCtx = useTui();
36
+ const isTui = $derived(tui || getTuiCtx());
37
+
38
+ function createId(prefix: string) {
39
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
40
+ return `${prefix}-${crypto.randomUUID()}`;
41
+ }
42
+ if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
43
+ const array = new Uint32Array(1);
44
+ crypto.getRandomValues(array);
45
+ return `${prefix}-${array[0].toString(36)}`;
46
+ }
47
+ return `${prefix}-${Date.now().toString(36)}`;
48
+ }
49
+
50
+ const tablistId = createId("tabs");
51
+
52
+ // Refs to each tab button for programmatic focus (roving tabindex)
53
+ let tabEls: Array<HTMLButtonElement | undefined> = $state([]);
54
+
55
+ function select(key: string) {
56
+ activeTab = key;
57
+ ontabchange?.(key);
58
+ }
59
+
60
+ function focusTabByKey(key: string) {
61
+ const idx = tabs.findIndex((t) => t.key === key);
62
+ tabEls[idx]?.focus();
63
+ }
64
+
65
+ function handleKeydown(e: KeyboardEvent, index: number) {
66
+ const enabled = tabs.filter((t) => !t.disabled);
67
+ const cur = enabled.findIndex((t) => t.key === tabs[index].key);
68
+ if (e.key === "ArrowRight") {
69
+ e.preventDefault();
70
+ const next = enabled[(cur + 1) % enabled.length];
71
+ if (next) { select(next.key); focusTabByKey(next.key); }
72
+ } else if (e.key === "ArrowLeft") {
73
+ e.preventDefault();
74
+ const prev = enabled[(cur - 1 + enabled.length) % enabled.length];
75
+ if (prev) { select(prev.key); focusTabByKey(prev.key); }
76
+ } else if (e.key === "Home") {
77
+ e.preventDefault();
78
+ if (enabled[0]) { select(enabled[0].key); focusTabByKey(enabled[0].key); }
79
+ } else if (e.key === "End") {
80
+ e.preventDefault();
81
+ const last = enabled[enabled.length - 1];
82
+ if (last) { select(last.key); focusTabByKey(last.key); }
83
+ }
84
+ }
85
+ </script>
86
+
87
+ <div class="tabs" class:tabs--tui={isTui}>
88
+ <!-- Tab strip -->
89
+ <div class="tablist" role="tablist" id={tablistId}>
90
+ {#if isTui}
91
+ {#each tabs as tab, i}
92
+ <button
93
+ type="button"
94
+ class="tui-tab"
95
+ class:active={tab.key === activeTab}
96
+ class:disabled={tab.disabled}
97
+ role="tab"
98
+ aria-selected={tab.key === activeTab}
99
+ aria-disabled={tab.disabled}
100
+ tabindex={tab.key === activeTab ? 0 : -1}
101
+ id={`${tablistId}-${tab.key}`}
102
+ aria-controls={`${tablistId}-panel-${tab.key}`}
103
+ bind:this={tabEls[i]}
104
+ onclick={() => !tab.disabled && select(tab.key)}
105
+ onkeydown={(e) => handleKeydown(e, i)}
106
+ >
107
+ {#if tab.icon}<span aria-hidden="true">{tab.icon}</span>{/if}
108
+ {tab.label}
109
+ </button>
110
+ {/each}
111
+ {:else}
112
+ {#each tabs as tab, i}
113
+ <button
114
+ type="button"
115
+ class="tab"
116
+ class:tab--active={tab.key === activeTab}
117
+ class:tab--disabled={tab.disabled}
118
+ role="tab"
119
+ aria-selected={tab.key === activeTab}
120
+ aria-disabled={tab.disabled}
121
+ tabindex={tab.key === activeTab ? 0 : -1}
122
+ id={`${tablistId}-${tab.key}`}
123
+ aria-controls={`${tablistId}-panel-${tab.key}`}
124
+ bind:this={tabEls[i]}
125
+ onclick={() => !tab.disabled && select(tab.key)}
126
+ onkeydown={(e) => handleKeydown(e, i)}
127
+ >
128
+ {#if tab.icon}<span class="tab-icon" aria-hidden="true">{tab.icon}</span>{/if}
129
+ {tab.label}
130
+ </button>
131
+ {/each}
132
+ {/if}
133
+ </div>
134
+
135
+ <!-- Tab panel -->
136
+ {#if children}
137
+ <div
138
+ class="tabpanel"
139
+ class:tabpanel--tui={isTui}
140
+ role="tabpanel"
141
+ id={`${tablistId}-panel-${activeTab}`}
142
+ aria-labelledby={`${tablistId}-${activeTab}`}
143
+ >
144
+ {@render children({ activeTab })}
145
+ </div>
146
+ {/if}
147
+ </div>
148
+
149
+ <style>
150
+ .tabs {
151
+ display: flex;
152
+ flex-direction: column;
153
+ min-width: 0;
154
+ }
155
+
156
+ /* ===== GUI mode ===== */
157
+ .tablist {
158
+ display: flex;
159
+ border-bottom: 1px solid var(--color-border, #2a2a2a);
160
+ gap: var(--space-1, 4px);
161
+ }
162
+
163
+ .tab {
164
+ position: relative;
165
+ background: none;
166
+ border: none;
167
+ cursor: pointer;
168
+ padding: var(--space-2, 8px) var(--space-4, 16px);
169
+ font-size: var(--text-sm, 14px);
170
+ font-family: inherit;
171
+ color: var(--color-text-muted, #888);
172
+ border-radius: var(--radius-sm, 6px) var(--radius-sm, 6px) 0 0;
173
+ outline: none;
174
+ transition: color 0.15s ease;
175
+ white-space: nowrap;
176
+ display: flex;
177
+ align-items: center;
178
+ gap: var(--space-1, 4px);
179
+ }
180
+
181
+ .tab:hover:not(.tab--disabled) { color: var(--color-text, #e8e8e8); }
182
+
183
+ .tab--active {
184
+ color: var(--color-accent, #6366f1);
185
+ font-weight: 500;
186
+ }
187
+
188
+ .tab--active::after {
189
+ content: "";
190
+ position: absolute;
191
+ bottom: -1px;
192
+ left: 0;
193
+ right: 0;
194
+ height: 2px;
195
+ background: var(--color-accent, #6366f1);
196
+ border-radius: 2px 2px 0 0;
197
+ }
198
+
199
+ .tab--disabled { opacity: 0.4; cursor: not-allowed; }
200
+
201
+ .tab:focus-visible {
202
+ outline: var(--focus-ring-width, 3px) solid var(--color-focus-ring, #818cf8);
203
+ outline-offset: var(--focus-ring-offset, 2px);
204
+ }
205
+
206
+ .tab-icon { font-size: 14px; }
207
+
208
+ .tabpanel {
209
+ padding: var(--space-4, 16px);
210
+ flex: 1;
211
+ overflow: auto;
212
+ }
213
+
214
+ /* ===== TUI mode ===== */
215
+ .tabs--tui .tablist {
216
+ border-bottom: 1px solid var(--tui-border, #0f3460);
217
+ gap: 0;
218
+ }
219
+
220
+ .tui-tab {
221
+ background: none;
222
+ border: 1px solid var(--tui-border, #0f3460);
223
+ border-bottom: none;
224
+ color: var(--tui-text-dim, #888888);
225
+ font-family: var(--font-mono, monospace);
226
+ font-size: var(--text-sm, 14px);
227
+ cursor: pointer;
228
+ padding: 2px var(--space-3, 12px);
229
+ outline: none;
230
+ display: flex;
231
+ align-items: center;
232
+ gap: var(--space-1, 4px);
233
+ white-space: nowrap;
234
+ }
235
+
236
+ .tui-tab.active {
237
+ background: var(--tui-surface, #16213e);
238
+ color: var(--tui-accent, #00d4ff);
239
+ border-color: var(--tui-accent, #00d4ff);
240
+ }
241
+
242
+ .tui-tab.disabled { opacity: 0.4; cursor: not-allowed; }
243
+
244
+ .tui-tab:focus-visible { outline: 1px solid var(--tui-accent, #00d4ff); }
245
+
246
+ .tabpanel--tui {
247
+ background: var(--tui-surface, #16213e);
248
+ color: var(--tui-text, #e0e0e0);
249
+ font-family: var(--font-mono, monospace);
250
+ border: 1px solid var(--tui-border, #0f3460);
251
+ border-top: none;
252
+ padding: var(--space-3, 12px);
253
+ }
254
+ </style>
@@ -0,0 +1,21 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { Tab } from "./Tabs.types.js";
3
+ interface Props {
4
+ /** Tab definitions. */
5
+ tabs: Tab[];
6
+ /** Currently active tab key. */
7
+ activeTab?: string;
8
+ /** Called when the user selects a tab. */
9
+ ontabchange?: (key: string) => void;
10
+ /** Enable TUI mode. */
11
+ tui?: boolean;
12
+ /** Tab panel content — receives the active tab key. */
13
+ children?: Snippet<[{
14
+ activeTab: string;
15
+ }]>;
16
+ }
17
+ declare const Tabs: import("svelte").Component<Props, {
18
+ Tab: typeof Tab;
19
+ }, "activeTab">;
20
+ type Tabs = ReturnType<typeof Tabs>;
21
+ export default Tabs;
@@ -0,0 +1 @@
1
+ export {};