@plures/design-dojo 0.5.2 → 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,130 @@
1
+ <!--
2
+ ListItem — A single item in a List.
3
+
4
+ TUI mode: monospace font, "› " prefix on highlighted items, dark-gray highlight.
5
+ GUI mode: bullet prefix, hover state, accent color highlight.
6
+ -->
7
+ <script lang="ts">
8
+ import { useTui } from "../useTui.js";
9
+ import type { Snippet } from "svelte";
10
+
11
+ interface Props {
12
+ tui?: boolean;
13
+ highlighted?: boolean;
14
+ /** Bullet character. Defaults: "•" (GUI), highlight-aware "› "/" " (TUI). */
15
+ prefix?: string;
16
+ onclick?: (e: MouseEvent) => void;
17
+ children: Snippet;
18
+ }
19
+
20
+ let { tui = false, highlighted = false, prefix, onclick, children }: Props = $props();
21
+
22
+ const getTuiCtx = useTui();
23
+ const isTui = $derived(tui || getTuiCtx());
24
+ const bulletText = $derived(
25
+ isTui ? (highlighted ? "› " : " ") : (prefix ?? "•"),
26
+ );
27
+ </script>
28
+
29
+ <li
30
+ class="list-item"
31
+ class:tui={isTui}
32
+ class:highlighted
33
+ role="option"
34
+ aria-selected={highlighted}
35
+ tabindex={onclick ? 0 : undefined}
36
+ {onclick}
37
+ onkeydown={onclick
38
+ ? (e) => {
39
+ if (e.key === "Enter" || e.key === " ") {
40
+ e.preventDefault();
41
+ (e.currentTarget as HTMLElement).click();
42
+ }
43
+ }
44
+ : undefined}
45
+ >
46
+ <span class="prefix" aria-hidden="true">{bulletText}</span>
47
+ <span class="label">{@render children()}</span>
48
+ </li>
49
+
50
+ <style>
51
+ .list-item {
52
+ display: flex;
53
+ align-items: baseline;
54
+ padding: var(--space-1, 4px) var(--space-3, 12px);
55
+ border-radius: var(--radius-sm, 6px);
56
+ cursor: default;
57
+ list-style: none;
58
+ color: var(--color-text, #e8e8e8);
59
+ font-size: var(--text-sm, 14px);
60
+ line-height: var(--leading-normal, 1.5);
61
+ transition: background 0.15s ease;
62
+ user-select: none;
63
+ }
64
+
65
+ .list-item[tabindex] {
66
+ cursor: pointer;
67
+ outline: none;
68
+ }
69
+
70
+ .list-item[tabindex]:focus-visible {
71
+ box-shadow: 0 0 0 2px var(--color-accent, #6366f1);
72
+ }
73
+
74
+ .list-item:hover {
75
+ background: var(--alpha-10, rgba(255, 255, 255, 0.1));
76
+ }
77
+
78
+ .list-item.highlighted {
79
+ background: rgba(99, 102, 241, 0.15);
80
+ color: var(--color-accent-hover, #818cf8);
81
+ }
82
+
83
+ .prefix {
84
+ color: var(--color-text-muted, #888);
85
+ font-size: var(--text-xs, 12px);
86
+ flex-shrink: 0;
87
+ margin-right: var(--space-2, 8px);
88
+ }
89
+
90
+ .list-item.highlighted .prefix {
91
+ color: var(--color-accent, #6366f1);
92
+ }
93
+
94
+ .label {
95
+ flex: 1;
96
+ }
97
+
98
+ /* ===== TUI mode ===== */
99
+ .list-item.tui {
100
+ font-family: var(--font-mono, monospace);
101
+ border-radius: var(--tui-radius, 0px);
102
+ padding: 0 var(--space-1, 4px);
103
+ background: transparent;
104
+ color: var(--tui-text, #e0e0e0);
105
+ transition: none;
106
+ font-size: var(--text-sm, 14px);
107
+ }
108
+
109
+ .list-item.tui:hover {
110
+ background: transparent;
111
+ }
112
+
113
+ .list-item.tui.highlighted {
114
+ background: var(--tui-highlight, #533483);
115
+ color: var(--tui-accent, #00d4ff);
116
+ }
117
+
118
+ .list-item.tui[tabindex]:focus-visible {
119
+ outline: 1px solid var(--tui-accent, #00d4ff);
120
+ outline-offset: -1px;
121
+ box-shadow: none;
122
+ }
123
+
124
+ .list-item.tui .prefix {
125
+ color: inherit;
126
+ font-size: inherit;
127
+ white-space: pre;
128
+ margin-right: 0;
129
+ }
130
+ </style>
@@ -0,0 +1,12 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ tui?: boolean;
4
+ highlighted?: boolean;
5
+ /** Bullet character. Defaults: "•" (GUI), highlight-aware "› "/" " (TUI). */
6
+ prefix?: string;
7
+ onclick?: (e: MouseEvent) => void;
8
+ children: Snippet;
9
+ }
10
+ declare const ListItem: import("svelte").Component<Props, {}, "">;
11
+ type ListItem = ReturnType<typeof ListItem>;
12
+ export default ListItem;
@@ -0,0 +1,241 @@
1
+ <!--
2
+ Table — Data table with column headers and row selection.
3
+
4
+ Maps to ratatui::widgets::Table in TUI mode.
5
+
6
+ Usage:
7
+ <Table {columns} {rows} selected={rowIndex} onselect={handleSelect} />
8
+
9
+ TUI mode: box-drawing borders (╔╦╗╠╬╣╚╩╝), bold accent header,
10
+ reversed-color selection (white-on-dark → dark-on-white).
11
+ GUI mode: styled HTML table — sticky header, hover rows, border-collapse,
12
+ accent-tinted selection highlight.
13
+ -->
14
+ <script lang="ts">
15
+ import { useTui } from "../useTui.js";
16
+
17
+ interface Column {
18
+ key: string;
19
+ label: string;
20
+ /** Column width in characters (TUI) or multiples of 8 px (GUI). */
21
+ width?: number;
22
+ }
23
+
24
+ interface Props {
25
+ tui?: boolean;
26
+ columns: Column[];
27
+ rows: Array<Record<string, string>>;
28
+ selected?: number;
29
+ class?: string;
30
+ onselect?: (index: number) => void;
31
+ }
32
+
33
+ let {
34
+ tui = false,
35
+ columns,
36
+ rows,
37
+ selected = -1,
38
+ class: className = "",
39
+ onselect,
40
+ }: Props = $props();
41
+
42
+ const getTuiCtx = useTui();
43
+ const isTui = $derived(tui || getTuiCtx());
44
+
45
+ // Compute per-column character widths for TUI rendering.
46
+ const colWidths = $derived(
47
+ columns.map((col) => {
48
+ const maxData = rows.reduce(
49
+ (max, row) => Math.max(max, (row[col.key] ?? "").length),
50
+ 0,
51
+ );
52
+ return col.width ?? Math.max(col.label.length, maxData, 3);
53
+ }),
54
+ );
55
+
56
+ /** One space of padding on each side of a cell value. */
57
+ const CELL_PADDING = 2;
58
+
59
+ function hLine(
60
+ widths: number[],
61
+ left: string,
62
+ cross: string,
63
+ right: string,
64
+ ): string {
65
+ return left + widths.map((w) => "═".repeat(w + CELL_PADDING)).join(cross) + right;
66
+ }
67
+
68
+ function cellRow(cells: string[], widths: number[]): string {
69
+ return (
70
+ "║" +
71
+ cells.map((cell, i) => " " + cell.padEnd(widths[i]) + " ").join("║") +
72
+ "║"
73
+ );
74
+ }
75
+
76
+ const topBorder = $derived(hLine(colWidths, "╔", "╦", "╗"));
77
+ const headerRow = $derived(cellRow(columns.map((c) => c.label), colWidths));
78
+ const sepBorder = $derived(hLine(colWidths, "╠", "╬", "╣"));
79
+ const bottomBorder = $derived(hLine(colWidths, "╚", "╩", "╝"));
80
+
81
+ function handleKeyDown(e: KeyboardEvent, index: number) {
82
+ if (e.key === "Enter" || e.key === " ") {
83
+ e.preventDefault();
84
+ onselect?.(index);
85
+ }
86
+ }
87
+ </script>
88
+
89
+ {#if isTui}
90
+ <div class="tui-table {className}" role="grid" aria-label="table">
91
+ <div class="tui-border" aria-hidden="true">{topBorder}</div>
92
+ <div class="tui-header" role="row">{headerRow}</div>
93
+ <div class="tui-border" aria-hidden="true">{sepBorder}</div>
94
+ {#each rows as row, i}
95
+ {@const cells = columns.map((c) => row[c.key] ?? "")}
96
+ <div
97
+ class="tui-row"
98
+ class:selected={i === selected}
99
+ role="row"
100
+ aria-selected={i === selected}
101
+ tabindex="0"
102
+ onclick={() => onselect?.(i)}
103
+ onkeydown={(e) => handleKeyDown(e, i)}
104
+ >{cellRow(cells, colWidths)}</div>
105
+ {/each}
106
+ <div class="tui-border" aria-hidden="true">{bottomBorder}</div>
107
+ </div>
108
+ {:else}
109
+ <div class="table-wrap {className}">
110
+ <table class="table" role="grid">
111
+ <thead>
112
+ <tr>
113
+ {#each columns as col}
114
+ <th style:width={col.width ? `${col.width * 8}px` : undefined}
115
+ >{col.label}</th
116
+ >
117
+ {/each}
118
+ </tr>
119
+ </thead>
120
+ <tbody>
121
+ {#each rows as row, i}
122
+ <tr
123
+ class:selected={i === selected}
124
+ aria-selected={i === selected}
125
+ tabindex="0"
126
+ onclick={() => onselect?.(i)}
127
+ onkeydown={(e) => handleKeyDown(e, i)}
128
+ >
129
+ {#each columns as col}
130
+ <td>{row[col.key] ?? ""}</td>
131
+ {/each}
132
+ </tr>
133
+ {/each}
134
+ </tbody>
135
+ </table>
136
+ </div>
137
+ {/if}
138
+
139
+ <style>
140
+ /* ===== GUI Table ===== */
141
+ .table-wrap {
142
+ overflow-x: auto;
143
+ border: 1px solid var(--color-border, #2a2a2a);
144
+ border-radius: var(--radius-md, 10px);
145
+ scrollbar-width: thin;
146
+ scrollbar-color: var(--color-border, #2a2a2a) transparent;
147
+ }
148
+
149
+ .table {
150
+ width: 100%;
151
+ border-collapse: collapse;
152
+ font-size: var(--text-sm, 14px);
153
+ color: var(--color-text, #e8e8e8);
154
+ }
155
+
156
+ thead {
157
+ position: sticky;
158
+ top: 0;
159
+ z-index: 1;
160
+ background: var(--surface-2, #1e1e1e);
161
+ }
162
+
163
+ th {
164
+ padding: var(--space-2, 8px) var(--space-3, 12px);
165
+ text-align: left;
166
+ font-weight: 600;
167
+ font-size: var(--text-xs, 12px);
168
+ text-transform: uppercase;
169
+ letter-spacing: 0.05em;
170
+ color: var(--color-text-muted, #888);
171
+ border-bottom: 1px solid var(--color-border, #2a2a2a);
172
+ white-space: nowrap;
173
+ }
174
+
175
+ td {
176
+ padding: var(--space-2, 8px) var(--space-3, 12px);
177
+ border-bottom: 1px solid var(--color-border, #2a2a2a);
178
+ vertical-align: middle;
179
+ }
180
+
181
+ tbody tr {
182
+ cursor: pointer;
183
+ outline: none;
184
+ transition: background 0.12s ease;
185
+ }
186
+
187
+ tbody tr:last-child td {
188
+ border-bottom: none;
189
+ }
190
+
191
+ tbody tr:hover {
192
+ background: var(--alpha-5, rgba(255, 255, 255, 0.05));
193
+ }
194
+
195
+ tbody tr.selected {
196
+ background: rgba(99, 102, 241, 0.12);
197
+ }
198
+
199
+ tbody tr.selected td {
200
+ color: var(--color-accent-hover, #818cf8);
201
+ }
202
+
203
+ tbody tr:focus-visible {
204
+ box-shadow: inset 0 0 0 2px var(--color-accent, #6366f1);
205
+ }
206
+
207
+ /* ===== TUI Table ===== */
208
+ .tui-table {
209
+ font-family: var(--font-mono, monospace);
210
+ font-size: var(--text-sm, 14px);
211
+ color: var(--tui-text, #e0e0e0);
212
+ background: var(--tui-surface, #16213e);
213
+ display: inline-block;
214
+ white-space: pre;
215
+ line-height: 1.4;
216
+ }
217
+
218
+ .tui-border {
219
+ color: var(--tui-border, #0f3460);
220
+ }
221
+
222
+ .tui-header {
223
+ color: var(--tui-accent, #00d4ff);
224
+ font-weight: bold;
225
+ }
226
+
227
+ .tui-row {
228
+ cursor: pointer;
229
+ outline: none;
230
+ }
231
+
232
+ .tui-row:focus-visible {
233
+ outline: 1px solid var(--tui-accent, #00d4ff);
234
+ outline-offset: -1px;
235
+ }
236
+
237
+ .tui-row.selected {
238
+ background: var(--tui-text, #e0e0e0);
239
+ color: var(--tui-bg, #1a1a2e);
240
+ }
241
+ </style>
@@ -0,0 +1,17 @@
1
+ interface Column {
2
+ key: string;
3
+ label: string;
4
+ /** Column width in characters (TUI) or multiples of 8 px (GUI). */
5
+ width?: number;
6
+ }
7
+ interface Props {
8
+ tui?: boolean;
9
+ columns: Column[];
10
+ rows: Array<Record<string, string>>;
11
+ selected?: number;
12
+ class?: string;
13
+ onselect?: (index: number) => void;
14
+ }
15
+ declare const Table: import("svelte").Component<Props, {}, "">;
16
+ type Table = ReturnType<typeof Table>;
17
+ export default Table;
@@ -0,0 +1,3 @@
1
+ export { default as Table } from "./Table.svelte";
2
+ export { default as List } from "./List.svelte";
3
+ export { default as ListItem } from "./ListItem.svelte";
@@ -0,0 +1,3 @@
1
+ export { default as Table } from "./Table.svelte";
2
+ export { default as List } from "./List.svelte";
3
+ export { default as ListItem } from "./ListItem.svelte";
@@ -0,0 +1,48 @@
1
+ <script lang="ts">
2
+ export interface AccordionItem { id: string; title: string; content: string }
3
+ interface Props {
4
+ items: AccordionItem[];
5
+ single?: boolean;
6
+ openIds?: string[];
7
+ tui?: boolean;
8
+ className?: string;
9
+ }
10
+ let { items, single = false, openIds = [], tui = false, className = "" }: Props = $props();
11
+
12
+ function toggle(id: string) {
13
+ if (openIds.includes(id)) openIds = openIds.filter((x) => x !== id);
14
+ else if (single) openIds = [id];
15
+ else openIds = [...openIds, id];
16
+ }
17
+ </script>
18
+
19
+ <div class="accordion {className}" class:tui={tui}>
20
+ {#each items as item}
21
+ <section class="item">
22
+ <button class="trigger" onclick={() => toggle(item.id)} aria-expanded={openIds.includes(item.id)}>
23
+ <span>{item.title}</span>
24
+ <span class="chev" class:open={openIds.includes(item.id)}>▾</span>
25
+ </button>
26
+ {#if openIds.includes(item.id)}
27
+ <div class="panel">{item.content}</div>
28
+ {/if}
29
+ </section>
30
+ {/each}
31
+ </div>
32
+
33
+ <style>
34
+ .accordion { display: grid; gap: var(--space-2); }
35
+ .item { border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; background: var(--surface-1); }
36
+ .trigger {
37
+ width: 100%; border: 0; background: transparent; color: var(--color-text); padding: var(--space-3);
38
+ display: flex; align-items: center; justify-content: space-between; font-size: var(--text-sm); font-weight: 600; cursor: pointer;
39
+ }
40
+ .trigger:hover { background: var(--alpha-5); }
41
+ .trigger:focus-visible { outline: 1px solid var(--color-accent); outline-offset: -1px; }
42
+ .panel { padding: 0 var(--space-3) var(--space-3); color: var(--color-text-muted); font-size: var(--text-sm); }
43
+ .chev { transition: transform 150ms ease; }
44
+ .chev.open { transform: rotate(180deg); }
45
+
46
+ .accordion.tui .item { background: var(--tui-surface, #16213e); border-color: var(--tui-border, #0f3460); }
47
+ .accordion.tui .trigger, .accordion.tui .panel { color: var(--tui-text, #e0e0e0); font-family: var(--font-mono, monospace); }
48
+ </style>
@@ -0,0 +1,15 @@
1
+ export interface AccordionItem {
2
+ id: string;
3
+ title: string;
4
+ content: string;
5
+ }
6
+ interface Props {
7
+ items: AccordionItem[];
8
+ single?: boolean;
9
+ openIds?: string[];
10
+ tui?: boolean;
11
+ className?: string;
12
+ }
13
+ declare const Accordion: import("svelte").Component<Props, {}, "">;
14
+ type Accordion = ReturnType<typeof Accordion>;
15
+ export default Accordion;
@@ -0,0 +1,60 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { useTui } from "../useTui.js";
4
+
5
+ type Variant = "default" | "neutral" | "info" | "success" | "warning" | "danger" | "accent" | "muted" | "outline" | "ghost";
6
+ type Size = "sm" | "md" | "lg";
7
+
8
+ interface Props {
9
+ variant?: Variant;
10
+ size?: Size;
11
+ pill?: boolean;
12
+ tui?: boolean;
13
+ className?: string;
14
+ children?: Snippet;
15
+ }
16
+
17
+ let { variant = "default", size = "md", pill = true, tui = false, className = "", children }: Props = $props();
18
+ const getTuiCtx = useTui();
19
+ const isTui = $derived(tui || getTuiCtx());
20
+ </script>
21
+
22
+ <span class="badge v-{variant} s-{size} {className}" class:pill class:tui={isTui}>
23
+ {@render children?.()}
24
+ </span>
25
+
26
+ <style>
27
+ .badge {
28
+ display: inline-flex;
29
+ align-items: center;
30
+ gap: var(--space-1);
31
+ border-radius: var(--radius-md);
32
+ border: 1px solid transparent;
33
+ background: var(--surface-2);
34
+ color: var(--color-text);
35
+ font-weight: 600;
36
+ letter-spacing: .02em;
37
+ }
38
+ .s-sm { min-block-size: var(--space-4); padding: 0 var(--space-2); font-size: var(--text-xs); }
39
+ .s-md { min-block-size: calc(var(--space-4) + 2px); padding: 0 var(--space-2); font-size: var(--text-xs); }
40
+ .s-lg { min-block-size: var(--space-5); padding: 0 var(--space-3); font-size: var(--text-sm); }
41
+ .pill { border-radius: var(--radius-full); }
42
+
43
+ .v-default { background: var(--surface-2); color: var(--color-text); }
44
+ .v-neutral { background: var(--surface-1); color: var(--color-text-muted); border-color: var(--color-border); }
45
+ .v-info { background: color-mix(in oklab, var(--color-info) 18%, var(--surface-1)); color: var(--color-info); }
46
+ .v-success { background: color-mix(in oklab, var(--color-success) 18%, var(--surface-1)); color: var(--color-success); }
47
+ .v-warning { background: color-mix(in oklab, var(--color-warning) 18%, var(--surface-1)); color: var(--color-warning); }
48
+ .v-danger { background: color-mix(in oklab, var(--color-danger) 18%, var(--surface-1)); color: var(--color-danger); }
49
+ .v-accent { background: color-mix(in oklab, var(--color-accent) 20%, var(--surface-1)); color: var(--color-accent-hover); }
50
+ .v-muted { background: transparent; color: var(--color-text-subtle); border-color: var(--color-border); }
51
+ .v-outline { background: transparent; color: var(--color-text); border-color: var(--color-border); }
52
+ .v-ghost { background: transparent; color: var(--color-text-muted); }
53
+
54
+ .tui {
55
+ background: var(--tui-surface, #16213e);
56
+ color: var(--tui-text, #e0e0e0);
57
+ border-color: var(--tui-border, #0f3460);
58
+ font-family: var(--font-mono, monospace);
59
+ }
60
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from "svelte";
2
+ type Variant = "default" | "neutral" | "info" | "success" | "warning" | "danger" | "accent" | "muted" | "outline" | "ghost";
3
+ type Size = "sm" | "md" | "lg";
4
+ interface Props {
5
+ variant?: Variant;
6
+ size?: Size;
7
+ pill?: boolean;
8
+ tui?: boolean;
9
+ className?: string;
10
+ children?: Snippet;
11
+ }
12
+ declare const Badge: import("svelte").Component<Props, {}, "">;
13
+ type Badge = ReturnType<typeof Badge>;
14
+ export default Badge;
@@ -0,0 +1,52 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { useTui } from "../useTui.js";
4
+
5
+ type Tone = "info" | "tip" | "warning" | "error";
6
+ interface Props {
7
+ tone?: Tone;
8
+ title?: string;
9
+ tui?: boolean;
10
+ className?: string;
11
+ children?: Snippet;
12
+ }
13
+
14
+ let { tone = "info", title = "", tui = false, className = "", children }: Props = $props();
15
+ const getTuiCtx = useTui();
16
+ const isTui = $derived(tui || getTuiCtx());
17
+ const icon = $derived(tone === "warning" ? "⚠" : tone === "error" ? "⛔" : tone === "tip" ? "💡" : "ℹ");
18
+ </script>
19
+
20
+ <aside class="callout tone-{tone} {className}" class:tui={isTui} role="status">
21
+ <span class="icon" aria-hidden="true">{icon}</span>
22
+ <div class="body">
23
+ {#if title}<div class="title">{title}</div>{/if}
24
+ <div class="content">{@render children?.()}</div>
25
+ </div>
26
+ </aside>
27
+
28
+ <style>
29
+ .callout {
30
+ display: grid;
31
+ grid-template-columns: auto 1fr;
32
+ gap: var(--space-2);
33
+ border: 1px solid var(--color-border);
34
+ border-radius: var(--radius-md);
35
+ padding: var(--space-3);
36
+ background: var(--surface-1);
37
+ }
38
+ .icon { font-size: var(--text-base); line-height: 1; margin-top: 2px; }
39
+ .title { color: var(--color-text); font-weight: 700; font-size: var(--text-sm); margin-bottom: var(--space-1); }
40
+ .content { color: var(--color-text-muted); font-size: var(--text-sm); }
41
+ .tone-info { border-left: var(--space-1) solid var(--color-info); }
42
+ .tone-tip { border-left: var(--space-1) solid var(--color-accent); }
43
+ .tone-warning { border-left: var(--space-1) solid var(--color-warning); }
44
+ .tone-error { border-left: var(--space-1) solid var(--color-danger); }
45
+
46
+ .callout.tui {
47
+ background: var(--tui-surface, #16213e);
48
+ border-color: var(--tui-border, #0f3460);
49
+ color: var(--tui-text, #e0e0e0);
50
+ font-family: var(--font-mono, monospace);
51
+ }
52
+ </style>
@@ -0,0 +1,12 @@
1
+ import type { Snippet } from "svelte";
2
+ type Tone = "info" | "tip" | "warning" | "error";
3
+ interface Props {
4
+ tone?: Tone;
5
+ title?: string;
6
+ tui?: boolean;
7
+ className?: string;
8
+ children?: Snippet;
9
+ }
10
+ declare const Callout: import("svelte").Component<Props, {}, "">;
11
+ type Callout = ReturnType<typeof Callout>;
12
+ export default Callout;
@@ -0,0 +1,47 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import { useTui } from "../useTui.js";
4
+
5
+ interface Props {
6
+ title: string;
7
+ description?: string;
8
+ loading?: boolean;
9
+ tui?: boolean;
10
+ className?: string;
11
+ children?: Snippet;
12
+ }
13
+
14
+ let { title, description = "", loading = false, tui = false, className = "", children }: Props = $props();
15
+ const getTuiCtx = useTui();
16
+ const isTui = $derived(tui || getTuiCtx());
17
+ </script>
18
+
19
+ <div class="empty {className}" class:tui={isTui} role="status" aria-live="polite">
20
+ <div class="glyph" aria-hidden="true">{loading ? "◌" : "∅"}</div>
21
+ <div class="title">{loading ? "Loading…" : title}</div>
22
+ {#if description}<div class="desc">{description}</div>{/if}
23
+ {@render children?.()}
24
+ </div>
25
+
26
+ <style>
27
+ .empty {
28
+ border: 1px dashed var(--color-border);
29
+ border-radius: var(--radius-lg);
30
+ padding: var(--space-6);
31
+ text-align: center;
32
+ display: grid;
33
+ gap: var(--space-2);
34
+ justify-items: center;
35
+ background: color-mix(in oklab, var(--surface-1) 90%, transparent);
36
+ }
37
+ .glyph { color: var(--color-text-subtle); font-size: var(--text-2xl); }
38
+ .title { color: var(--color-text); font-size: var(--text-base); font-weight: 600; }
39
+ .desc { color: var(--color-text-muted); font-size: var(--text-sm); max-inline-size: 44ch; }
40
+
41
+ .empty.tui {
42
+ background: var(--tui-surface, #16213e);
43
+ border-color: var(--tui-border, #0f3460);
44
+ color: var(--tui-text, #e0e0e0);
45
+ font-family: var(--font-mono, monospace);
46
+ }
47
+ </style>
@@ -0,0 +1,12 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ title: string;
4
+ description?: string;
5
+ loading?: boolean;
6
+ tui?: boolean;
7
+ className?: string;
8
+ children?: Snippet;
9
+ }
10
+ declare const EmptyState: import("svelte").Component<Props, {}, "">;
11
+ type EmptyState = ReturnType<typeof EmptyState>;
12
+ export default EmptyState;