@mdxui/terminal 2.0.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 (191) hide show
  1. package/README.md +571 -0
  2. package/dist/ansi-css-Sk5mWtdK.d.ts +119 -0
  3. package/dist/ansi-css-V6JIHGsM.d.ts +119 -0
  4. package/dist/ansi-css-_3eSEU9d.d.ts +119 -0
  5. package/dist/chunk-3EFDH7PK.js +5235 -0
  6. package/dist/chunk-3RG5ZIWI.js +10 -0
  7. package/dist/chunk-3X5IR6WE.js +884 -0
  8. package/dist/chunk-4FV5ZDCE.js +5236 -0
  9. package/dist/chunk-4OVMSF2J.js +243 -0
  10. package/dist/chunk-63FEETIS.js +4048 -0
  11. package/dist/chunk-B43KP7XJ.js +884 -0
  12. package/dist/chunk-BMTJXWUV.js +655 -0
  13. package/dist/chunk-C3SVH4N7.js +882 -0
  14. package/dist/chunk-EVWR7Y47.js +874 -0
  15. package/dist/chunk-F6A5VWUC.js +1285 -0
  16. package/dist/chunk-FD7KW7GE.js +882 -0
  17. package/dist/chunk-GBQ6UD6I.js +655 -0
  18. package/dist/chunk-GMDD3M6U.js +5227 -0
  19. package/dist/chunk-JBHRXOXM.js +1058 -0
  20. package/dist/chunk-JFOO3EYO.js +1182 -0
  21. package/dist/chunk-JQ5H3WXL.js +1291 -0
  22. package/dist/chunk-JQD5NASE.js +234 -0
  23. package/dist/chunk-KRHJP5R7.js +592 -0
  24. package/dist/chunk-KWF6WVJE.js +962 -0
  25. package/dist/chunk-LHYQVN3H.js +1038 -0
  26. package/dist/chunk-M3TLQLGC.js +1032 -0
  27. package/dist/chunk-MVW4Q5OP.js +240 -0
  28. package/dist/chunk-NXCZSWLU.js +1294 -0
  29. package/dist/chunk-O25TNRO6.js +607 -0
  30. package/dist/chunk-PNECDA2I.js +884 -0
  31. package/dist/chunk-QIHWRLJR.js +962 -0
  32. package/dist/chunk-QW5YMQ7K.js +882 -0
  33. package/dist/chunk-R5U7XKVJ.js +16 -0
  34. package/dist/chunk-RP2MVQLR.js +962 -0
  35. package/dist/chunk-TP6RXGXA.js +1087 -0
  36. package/dist/chunk-TQQSTITZ.js +655 -0
  37. package/dist/chunk-X24GWXQV.js +1281 -0
  38. package/dist/components/index.d.ts +802 -0
  39. package/dist/components/index.js +149 -0
  40. package/dist/data/index.d.ts +2554 -0
  41. package/dist/data/index.js +51 -0
  42. package/dist/forms/index.d.ts +1596 -0
  43. package/dist/forms/index.js +464 -0
  44. package/dist/index-CQRFZntR.d.ts +867 -0
  45. package/dist/index.d.ts +579 -0
  46. package/dist/index.js +786 -0
  47. package/dist/interactive-D0JkWosD.d.ts +217 -0
  48. package/dist/keyboard/index.d.ts +2 -0
  49. package/dist/keyboard/index.js +43 -0
  50. package/dist/renderers/index.d.ts +546 -0
  51. package/dist/renderers/index.js +2157 -0
  52. package/dist/storybook/index.d.ts +396 -0
  53. package/dist/storybook/index.js +641 -0
  54. package/dist/theme/index.d.ts +1339 -0
  55. package/dist/theme/index.js +123 -0
  56. package/dist/types-Bxu5PAgA.d.ts +710 -0
  57. package/dist/types-CIlop5Ji.d.ts +701 -0
  58. package/dist/types-Ca8p_p5X.d.ts +710 -0
  59. package/package.json +90 -0
  60. package/src/__tests__/components/data/card.test.ts +458 -0
  61. package/src/__tests__/components/data/list.test.ts +473 -0
  62. package/src/__tests__/components/data/metrics.test.ts +541 -0
  63. package/src/__tests__/components/data/table.test.ts +448 -0
  64. package/src/__tests__/components/input/field.test.ts +555 -0
  65. package/src/__tests__/components/input/form.test.ts +870 -0
  66. package/src/__tests__/components/input/search.test.ts +1238 -0
  67. package/src/__tests__/components/input/select.test.ts +658 -0
  68. package/src/__tests__/components/navigation/breadcrumb.test.ts +923 -0
  69. package/src/__tests__/components/navigation/command-palette.test.ts +1095 -0
  70. package/src/__tests__/components/navigation/sidebar.test.ts +1018 -0
  71. package/src/__tests__/components/navigation/tabs.test.ts +995 -0
  72. package/src/__tests__/components.test.tsx +1197 -0
  73. package/src/__tests__/core/compiler.test.ts +986 -0
  74. package/src/__tests__/core/parser.test.ts +785 -0
  75. package/src/__tests__/core/tier-switcher.test.ts +1103 -0
  76. package/src/__tests__/core/types.test.ts +1398 -0
  77. package/src/__tests__/data/collections.test.ts +1337 -0
  78. package/src/__tests__/data/db.test.ts +1265 -0
  79. package/src/__tests__/data/reactive.test.ts +1010 -0
  80. package/src/__tests__/data/sync.test.ts +1614 -0
  81. package/src/__tests__/errors.test.ts +660 -0
  82. package/src/__tests__/forms/integration.test.ts +444 -0
  83. package/src/__tests__/integration.test.ts +905 -0
  84. package/src/__tests__/keyboard.test.ts +1791 -0
  85. package/src/__tests__/renderer.test.ts +489 -0
  86. package/src/__tests__/renderers/ansi-css.test.ts +948 -0
  87. package/src/__tests__/renderers/ansi.test.ts +1366 -0
  88. package/src/__tests__/renderers/ascii.test.ts +1360 -0
  89. package/src/__tests__/renderers/interactive.test.ts +2353 -0
  90. package/src/__tests__/renderers/markdown.test.ts +1483 -0
  91. package/src/__tests__/renderers/text.test.ts +1369 -0
  92. package/src/__tests__/renderers/unicode.test.ts +1307 -0
  93. package/src/__tests__/theme.test.ts +639 -0
  94. package/src/__tests__/utils/assertions.ts +685 -0
  95. package/src/__tests__/utils/index.ts +115 -0
  96. package/src/__tests__/utils/test-renderer.ts +381 -0
  97. package/src/__tests__/utils/utils.test.ts +560 -0
  98. package/src/components/containers/card.ts +56 -0
  99. package/src/components/containers/dialog.ts +53 -0
  100. package/src/components/containers/index.ts +9 -0
  101. package/src/components/containers/panel.ts +59 -0
  102. package/src/components/feedback/badge.ts +40 -0
  103. package/src/components/feedback/index.ts +8 -0
  104. package/src/components/feedback/spinner.ts +23 -0
  105. package/src/components/helpers.ts +81 -0
  106. package/src/components/index.ts +153 -0
  107. package/src/components/layout/breadcrumb.ts +31 -0
  108. package/src/components/layout/index.ts +10 -0
  109. package/src/components/layout/list.ts +29 -0
  110. package/src/components/layout/sidebar.ts +79 -0
  111. package/src/components/layout/table.ts +62 -0
  112. package/src/components/primitives/box.ts +95 -0
  113. package/src/components/primitives/button.ts +54 -0
  114. package/src/components/primitives/index.ts +11 -0
  115. package/src/components/primitives/input.ts +88 -0
  116. package/src/components/primitives/select.ts +97 -0
  117. package/src/components/primitives/text.ts +60 -0
  118. package/src/components/render.ts +155 -0
  119. package/src/components/templates/app.ts +43 -0
  120. package/src/components/templates/index.ts +8 -0
  121. package/src/components/templates/site.ts +54 -0
  122. package/src/components/types.ts +777 -0
  123. package/src/core/compiler.ts +718 -0
  124. package/src/core/parser.ts +127 -0
  125. package/src/core/tier-switcher.ts +607 -0
  126. package/src/core/types.ts +672 -0
  127. package/src/data/collection.ts +316 -0
  128. package/src/data/collections.ts +50 -0
  129. package/src/data/context.tsx +174 -0
  130. package/src/data/db.ts +127 -0
  131. package/src/data/hooks.ts +532 -0
  132. package/src/data/index.ts +138 -0
  133. package/src/data/reactive.ts +1225 -0
  134. package/src/data/saas-collections.ts +375 -0
  135. package/src/data/sync.ts +1213 -0
  136. package/src/data/types.ts +660 -0
  137. package/src/forms/converters.ts +512 -0
  138. package/src/forms/index.ts +133 -0
  139. package/src/forms/schemas.ts +403 -0
  140. package/src/forms/types.ts +476 -0
  141. package/src/index.ts +542 -0
  142. package/src/keyboard/focus.ts +748 -0
  143. package/src/keyboard/index.ts +96 -0
  144. package/src/keyboard/integration.ts +371 -0
  145. package/src/keyboard/manager.ts +377 -0
  146. package/src/keyboard/presets.ts +90 -0
  147. package/src/renderers/ansi-css.ts +576 -0
  148. package/src/renderers/ansi.ts +802 -0
  149. package/src/renderers/ascii.ts +680 -0
  150. package/src/renderers/breadcrumb.ts +480 -0
  151. package/src/renderers/command-palette.ts +802 -0
  152. package/src/renderers/components/field.ts +210 -0
  153. package/src/renderers/components/form.ts +327 -0
  154. package/src/renderers/components/index.ts +21 -0
  155. package/src/renderers/components/search.ts +449 -0
  156. package/src/renderers/components/select.ts +222 -0
  157. package/src/renderers/index.ts +101 -0
  158. package/src/renderers/interactive/component-handlers.ts +622 -0
  159. package/src/renderers/interactive/cursor-manager.ts +147 -0
  160. package/src/renderers/interactive/focus-manager.ts +279 -0
  161. package/src/renderers/interactive/index.ts +661 -0
  162. package/src/renderers/interactive/input-handler.ts +164 -0
  163. package/src/renderers/interactive/keyboard-handler.ts +212 -0
  164. package/src/renderers/interactive/mouse-handler.ts +167 -0
  165. package/src/renderers/interactive/state-manager.ts +109 -0
  166. package/src/renderers/interactive/types.ts +338 -0
  167. package/src/renderers/interactive-string.ts +299 -0
  168. package/src/renderers/interactive.ts +59 -0
  169. package/src/renderers/markdown.ts +950 -0
  170. package/src/renderers/sidebar.ts +549 -0
  171. package/src/renderers/tabs.ts +682 -0
  172. package/src/renderers/text.ts +791 -0
  173. package/src/renderers/unicode.ts +917 -0
  174. package/src/renderers/utils.ts +942 -0
  175. package/src/router/adapters.ts +383 -0
  176. package/src/router/types.ts +140 -0
  177. package/src/router/utils.ts +452 -0
  178. package/src/schemas.ts +205 -0
  179. package/src/storybook/index.ts +91 -0
  180. package/src/storybook/interactive-decorator.tsx +659 -0
  181. package/src/storybook/keyboard-simulator.ts +501 -0
  182. package/src/theme/ansi-codes.ts +80 -0
  183. package/src/theme/box-drawing.ts +132 -0
  184. package/src/theme/color-convert.ts +254 -0
  185. package/src/theme/color-support.ts +321 -0
  186. package/src/theme/index.ts +134 -0
  187. package/src/theme/strip-ansi.ts +50 -0
  188. package/src/theme/tailwind-map.ts +469 -0
  189. package/src/theme/text-styles.ts +206 -0
  190. package/src/theme/theme-system.ts +568 -0
  191. package/src/types.ts +103 -0
package/README.md ADDED
@@ -0,0 +1,571 @@
1
+ # @mdxui/terminal
2
+
3
+ Universal UI renderer for MDXUI - same components render to terminal, web, and AI agents.
4
+
5
+ > **Alpha Status**: This package is under active development. Some features are experimental or incomplete. APIs may change.
6
+
7
+ **Multi-tier rendering**: Components output to TEXT, MARKDOWN, ASCII, UNICODE, ANSI, or Interactive based on context. AI agents get structured Markdown via MCP. Humans get rich TUIs. UX designers preview in Storybook.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pnpm add @mdxui/terminal
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```tsx
18
+ import { CLI, Box, Text } from '@mdxui/terminal'
19
+
20
+ async function main() {
21
+ const cli = await CLI()
22
+ cli.render(
23
+ <Box border="single">
24
+ <Text color="cyan">Hello Terminal!</Text>
25
+ </Box>
26
+ )
27
+ }
28
+
29
+ main()
30
+ ```
31
+
32
+ ## Architecture Overview
33
+
34
+ The terminal package implements a **UINode-based rendering architecture** that decouples component definitions from their output format. This enables the same semantic UI tree to render appropriately across different environments.
35
+
36
+ ```
37
+ ┌─────────────────────────────────────────────────────────────┐
38
+ │ Input Sources │
39
+ ├─────────────────────────────────────────────────────────────┤
40
+ │ JSX Components │ JSON/API Responses │
41
+ │ <Dashboard> │ { type: 'dashboard', ... } │
42
+ │ <Metrics /> │ │
43
+ │ </Dashboard> │ │
44
+ └────────────┬─────────────┴──────────────┬───────────────────┘
45
+ │ │
46
+ ▼ ▼
47
+ ┌───────────────┐ ┌───────────────┐
48
+ │ compileJSX() │ │ parseUINode() │
49
+ │ JSX Compiler │ │ JSON Parser │
50
+ └───────┬───────┘ └───────┬───────┘
51
+ │ │
52
+ └────────────┬───────────────┘
53
+
54
+ ┌───────────────────────┐
55
+ │ UINode │
56
+ │ Universal UI Tree │
57
+ │ (type, props, data, │
58
+ │ children, key) │
59
+ └───────────┬───────────┘
60
+
61
+ ┌─────────┬───────────┼───────────┬─────────┬─────────────┐
62
+ ▼ ▼ ▼ ▼ ▼ ▼
63
+ ┌───────┐ ┌───────┐ ┌─────────┐ ┌─────────┐ ┌──────┐ ┌─────────────┐
64
+ │ TEXT │ │ MD │ │ ASCII │ │ UNICODE │ │ ANSI │ │ INTERACTIVE │
65
+ │Tier 1 │ │Tier 2 │ │ Tier 3 │ │ Tier 4 │ │Tier 5│ │ Tier 6 │
66
+ └───────┘ └───────┘ └─────────┘ └─────────┘ └──────┘ └─────────────┘
67
+ ```
68
+
69
+ ### Core Types
70
+
71
+ ```typescript
72
+ // The universal UI tree node
73
+ interface UINode {
74
+ type: string // Component type ('text', 'box', 'table', etc.)
75
+ props: Record<string, unknown> // Component configuration
76
+ children?: UINode[] // Nested components
77
+ data?: unknown // Bound query data for data-driven components
78
+ key?: string // React-style reconciliation key
79
+ }
80
+
81
+ // Rendering capability level
82
+ type RenderTier = 'text' | 'markdown' | 'ascii' | 'unicode' | 'ansi' | 'interactive'
83
+
84
+ // Context passed during rendering
85
+ interface RenderContext {
86
+ tier: RenderTier
87
+ width: number // Terminal width in columns
88
+ height: number // Terminal height in rows
89
+ depth: number // Current nesting depth
90
+ theme: ThemeTokens // Semantic color tokens
91
+ interactive: boolean
92
+ }
93
+ ```
94
+
95
+ ## Package Exports
96
+
97
+ The package provides several entry points for different use cases:
98
+
99
+ | Entry Point | Description |
100
+ |-------------|-------------|
101
+ | `@mdxui/terminal` | Main entry - CLI API, components, hooks, compiler, parser |
102
+ | `@mdxui/terminal/renderers` | All tier renderers (text, markdown, ascii, unicode, ansi, interactive) |
103
+ | `@mdxui/terminal/data` | Data layer with TanStack DB-like API |
104
+ | `@mdxui/terminal/components` | Terminal UI components |
105
+ | `@mdxui/terminal/keyboard` | Keyboard and focus management |
106
+ | `@mdxui/terminal/theme` | Theme utilities and color support |
107
+ | `@mdxui/terminal/storybook` | Storybook integration helpers |
108
+
109
+ ## The 6 Render Tiers
110
+
111
+ | Tier | Use Case | Capabilities | Example Output |
112
+ |------|----------|--------------|----------------|
113
+ | **text** | Logs, piping, CI | Plain text only | `Users: 1234, API Calls: 45K` |
114
+ | **markdown** | AI agents, MCP | Tables, links, formatting | `\| Users \| 1,234 \| +12% \|` |
115
+ | **ascii** | Legacy terminals | ASCII box drawing (`+`, `-`, `\|`) | `+------+-------+` |
116
+ | **unicode** | Modern terminals | Unicode box drawing | `┌──────┬───────┐` |
117
+ | **ansi** | Full terminal | Colors, bold, dim | Colored output with ANSI escapes |
118
+ | **interactive** | Human TUI | Keyboard, focus, real-time | Full interactive application |
119
+
120
+ ### Using Renderers
121
+
122
+ Import renderers from the dedicated entry point:
123
+
124
+ ```typescript
125
+ import {
126
+ renderText,
127
+ renderMarkdown,
128
+ renderASCII,
129
+ renderUnicode,
130
+ renderANSI,
131
+ createInteractiveRenderer
132
+ } from '@mdxui/terminal/renderers'
133
+
134
+ // Compile JSX to UINode tree
135
+ import { compileJSX } from '@mdxui/terminal'
136
+ const uiTree = compileJSX(<Dashboard metrics={data} />)
137
+
138
+ // Render to different tiers
139
+ const textOutput = renderText(uiTree) // Tier 1: Plain text
140
+ const mdOutput = renderMarkdown(uiTree) // Tier 2: Markdown
141
+ const asciiOutput = renderASCII(uiTree) // Tier 3: ASCII art
142
+ const unicodeOutput = renderUnicode(uiTree) // Tier 4: Unicode
143
+ const ansiOutput = renderANSI(uiTree) // Tier 5: ANSI colors
144
+ // Tier 6: Interactive requires a renderer instance
145
+ ```
146
+
147
+ ## JSX Compiler
148
+
149
+ The compiler converts React JSX trees into UINode trees. It handles:
150
+
151
+ - Fragment flattening
152
+ - Null/undefined/boolean child filtering (React semantics)
153
+ - Key preservation for list reconciliation
154
+ - Deep tree support via iterative compilation
155
+
156
+ ```typescript
157
+ import { compileJSX, compileJSXDeep } from '@mdxui/terminal'
158
+
159
+ // Standard compilation (recursive)
160
+ const node = compileJSX(
161
+ <Box padding={2}>
162
+ <Text bold>Hello</Text>
163
+ <Text>World</Text>
164
+ </Box>
165
+ )
166
+ // Result:
167
+ // {
168
+ // type: 'Box',
169
+ // props: { padding: 2 },
170
+ // children: [
171
+ // { type: 'Text', props: { bold: true }, children: ['Hello'] },
172
+ // { type: 'Text', props: {}, children: ['World'] }
173
+ // ]
174
+ // }
175
+
176
+ // For very deep trees (>1000 levels), use iterative version
177
+ const deepNode = compileJSXDeep(veryDeepElement)
178
+ ```
179
+
180
+ ## JSON Parser
181
+
182
+ Parse JSON strings or objects into validated UINode trees with Zod schemas.
183
+
184
+ ```typescript
185
+ import { parseUINode, ParseError } from '@mdxui/terminal'
186
+
187
+ // Parse JSON string
188
+ const node = parseUINode('{"type":"text","props":{"content":"Hello"}}')
189
+
190
+ // Parse object (validates structure)
191
+ const node = parseUINode({
192
+ type: 'table',
193
+ props: { columns: [{ key: 'name', header: 'Name' }] },
194
+ data: [{ name: 'Alice' }, { name: 'Bob' }]
195
+ })
196
+
197
+ // Handle validation errors
198
+ try {
199
+ parseUINode({ props: {} }) // Missing 'type'
200
+ } catch (error) {
201
+ if (error instanceof ParseError) {
202
+ console.error('Invalid UINode:', error.message)
203
+ }
204
+ }
205
+ ```
206
+
207
+ ## Renderer Examples
208
+
209
+ ### Text Renderer (Tier 1)
210
+
211
+ Plain text output with no formatting. Ideal for logs, CI output, or piping.
212
+
213
+ ```typescript
214
+ import { renderText } from '@mdxui/terminal/renderers'
215
+
216
+ const output = renderText({
217
+ type: 'dashboard',
218
+ props: { title: 'Metrics' },
219
+ children: [
220
+ { type: 'text', props: { content: 'Active Users: 1,234' } }
221
+ ]
222
+ })
223
+ // Output:
224
+ // Metrics
225
+ //
226
+ // Active Users: 1,234
227
+ ```
228
+
229
+ ### Markdown Renderer (Tier 2)
230
+
231
+ Structured markdown for AI agents consuming via MCP. Tables, links, and formatting preserved.
232
+
233
+ ```typescript
234
+ import { renderMarkdown } from '@mdxui/terminal/renderers'
235
+
236
+ const output = renderMarkdown({
237
+ type: 'table',
238
+ props: {
239
+ columns: [
240
+ { key: 'name', header: 'Name' },
241
+ { key: 'value', header: 'Value' }
242
+ ],
243
+ data: [
244
+ { name: 'Users', value: '1,234' },
245
+ { name: 'Revenue', value: '$45K' }
246
+ ]
247
+ }
248
+ })
249
+ // Output:
250
+ // | Name | Value |
251
+ // | --- | --- |
252
+ // | Users | 1,234 |
253
+ // | Revenue | $45K |
254
+ ```
255
+
256
+ ### ASCII Renderer (Tier 3)
257
+
258
+ Pure ASCII characters for maximum compatibility. No unicode, no ANSI codes.
259
+
260
+ ```typescript
261
+ import { renderASCII } from '@mdxui/terminal/renderers'
262
+
263
+ const output = renderASCII({
264
+ type: 'box',
265
+ props: { border: 'single' },
266
+ children: [{ type: 'text', props: { content: 'Hello' } }]
267
+ })
268
+ // Output:
269
+ // +-------+
270
+ // | Hello |
271
+ // +-------+
272
+ ```
273
+
274
+ ### Unicode Renderer (Tier 4)
275
+
276
+ Beautiful box-drawing characters for modern terminals. No colors.
277
+
278
+ ```typescript
279
+ import { renderUnicode } from '@mdxui/terminal/renderers'
280
+
281
+ const output = renderUnicode({
282
+ type: 'box',
283
+ props: { border: 'rounded' },
284
+ children: [{ type: 'text', props: { content: 'Hello' } }]
285
+ })
286
+ // Output:
287
+ // ╭───────╮
288
+ // │ Hello │
289
+ // ╰───────╯
290
+ ```
291
+
292
+ ### ANSI Renderer (Tier 5)
293
+
294
+ Full color support with 16, 256, or truecolor modes. Supports theming and color degradation.
295
+
296
+ ```typescript
297
+ import { renderANSI } from '@mdxui/terminal/renderers'
298
+
299
+ const output = renderANSI(
300
+ { type: 'text', props: { content: 'Error!', color: 'red', bold: true } },
301
+ { colorSupport: 'truecolor', theme: 'dark' }
302
+ )
303
+ // Output: Bold red text with ANSI escape codes
304
+ ```
305
+
306
+ ### Interactive Renderer (Tier 6)
307
+
308
+ Full TUI with keyboard navigation, focus management, and real-time updates.
309
+
310
+ ```typescript
311
+ import { createInteractiveRenderer } from '@mdxui/terminal/renderers'
312
+
313
+ const renderer = await createInteractiveRenderer({
314
+ vimBindings: true,
315
+ wrapFocus: true
316
+ })
317
+
318
+ // Register focusable elements
319
+ renderer.registerFocusable('btn-1', { tabIndex: 0, onActivate: handleClick })
320
+
321
+ // Handle keyboard input
322
+ renderer.onKeyPress('enter', () => console.log('Pressed!'))
323
+
324
+ // Start the TUI
325
+ renderer.start()
326
+ ```
327
+
328
+ ## Supported Components
329
+
330
+ ### Primitives
331
+
332
+ | Component | Description | Key Props |
333
+ |-----------|-------------|-----------|
334
+ | `text` | Styled text | `content`, `bold`, `italic`, `color` |
335
+ | `box` | Container with borders | `border`, `padding`, `width`, `height` |
336
+ | `list` | Bullet or numbered list | `items`, `numbered`, `bullet` |
337
+ | `table` | Data table | `columns`, `data`, `headers`, `rows` |
338
+ | `code` | Code block | `code`, `language` |
339
+ | `link` | Hyperlink | `text`, `href` |
340
+ | `button` | Interactive button | `label`, `hotkey`, `action` |
341
+
342
+ ### Layout
343
+
344
+ | Component | Description | Key Props |
345
+ |-----------|-------------|-----------|
346
+ | `panel` | Titled panel | `title`, `collapsible`, `collapsed` |
347
+ | `card` | Content card | `title`, `border` |
348
+ | `sidebar` | Navigation sidebar | `nav`, `sections` |
349
+ | `breadcrumb` | Navigation path | `items`, `separator` |
350
+ | `dialog` | Modal dialog | `open`, `title`, `actions` |
351
+
352
+ ### Data Display
353
+
354
+ | Component | Description | Key Props |
355
+ |-----------|-------------|-----------|
356
+ | `metrics` | Metric cards | `metrics: [{ label, value, trend }]` |
357
+ | `badge` | Status badge | `variant`, `children` |
358
+ | `progress` | Progress bar | `value`, `max`, `width` |
359
+ | `spinner` | Loading indicator | `label`, `frame` |
360
+
361
+ ### Page Templates
362
+
363
+ | Component | Description |
364
+ |-----------|-------------|
365
+ | `dashboard` | Dashboard with metrics and panels |
366
+ | `settings` | Settings page with sections |
367
+ | `hero` | Landing page hero section |
368
+ | `features` | Feature showcase |
369
+ | `pricing` | Pricing tiers |
370
+ | `faq` | FAQ accordion |
371
+ | `footer` | Page footer |
372
+
373
+ ## Data Layer
374
+
375
+ The data layer provides reactive data management with offline support, available via `@mdxui/terminal/data`.
376
+
377
+ ```typescript
378
+ import {
379
+ createDB,
380
+ createCollection,
381
+ createDOSync,
382
+ DBProvider,
383
+ useQuery,
384
+ useMutation
385
+ } from '@mdxui/terminal/data'
386
+ import { z } from 'zod'
387
+
388
+ // Define schema
389
+ const UserSchema = z.object({
390
+ id: z.string(),
391
+ name: z.string(),
392
+ email: z.string().email(),
393
+ role: z.enum(['admin', 'user', 'guest'])
394
+ })
395
+
396
+ // Create collection
397
+ const usersCollection = createCollection({
398
+ name: 'users',
399
+ schema: UserSchema
400
+ })
401
+
402
+ // Create database with Durable Objects sync
403
+ const db = createDB({
404
+ collections: [usersCollection],
405
+ sync: createDOSync({
406
+ namespaceUrl: 'https://api.example.com/do/workspace',
407
+ reconnect: { enabled: true, maxAttempts: 10 }
408
+ })
409
+ })
410
+
411
+ // Use in React components
412
+ function UserList() {
413
+ const { data, isLoading } = useQuery({
414
+ from: 'users',
415
+ where: { role: 'admin' }
416
+ })
417
+
418
+ const { mutate } = useMutation({
419
+ collection: 'users',
420
+ operation: 'insert'
421
+ })
422
+
423
+ if (isLoading) return <Spinner label="Loading users..." />
424
+
425
+ return (
426
+ <Table
427
+ columns={[
428
+ { key: 'name', header: 'Name' },
429
+ { key: 'email', header: 'Email' },
430
+ { key: 'role', header: 'Role' }
431
+ ]}
432
+ data={data}
433
+ />
434
+ )
435
+ }
436
+ ```
437
+
438
+ ### Built-in SaaS Collections
439
+
440
+ Pre-defined schemas for common SaaS patterns:
441
+
442
+ ```typescript
443
+ import {
444
+ UsersCollection,
445
+ APIKeysCollection,
446
+ WebhooksCollection,
447
+ TeamsCollection,
448
+ UsageCollection
449
+ } from '@mdxui/terminal/data'
450
+
451
+ const db = createDB({
452
+ collections: [
453
+ UsersCollection(),
454
+ APIKeysCollection(),
455
+ WebhooksCollection(),
456
+ TeamsCollection(),
457
+ UsageCollection()
458
+ ]
459
+ })
460
+ ```
461
+
462
+ ### Sync Adapter Features
463
+
464
+ The `createDOSync` adapter provides:
465
+
466
+ - **WebSocket connection management** with automatic reconnection
467
+ - **Exponential backoff** with jitter to prevent thundering herd
468
+ - **Offline mutation queue** - changes are queued when offline and synced on reconnect
469
+ - **Connection state observable** for UI feedback
470
+ - **Conflict resolution strategies** - server-wins, client-wins, merge, throw, or custom
471
+
472
+ ```typescript
473
+ const sync = createDOSync({
474
+ namespaceUrl: 'https://api.example.com/do/workspace',
475
+ authToken: 'jwt-token',
476
+ reconnect: {
477
+ enabled: true,
478
+ maxAttempts: 10,
479
+ initialDelay: 1000,
480
+ maxDelay: 30000
481
+ },
482
+ conflictResolution: 'server-wins',
483
+ requestTimeout: 10000
484
+ })
485
+
486
+ // Monitor connection state
487
+ sync.onConnectionStateChange((state) => {
488
+ // 'disconnected' | 'connecting' | 'connected' | 'reconnecting'
489
+ updateStatusIndicator(state)
490
+ })
491
+
492
+ // Check pending changes
493
+ const { count, oldestAt } = sync.getQueueStats()
494
+ if (count > 0) {
495
+ showPendingBanner(`${count} changes pending`)
496
+ }
497
+ ```
498
+
499
+ ## Terminal Hooks
500
+
501
+ | Hook | Status | Description |
502
+ |------|--------|-------------|
503
+ | `useTerminalSize` | Implemented | Returns terminal dimensions (uses @opentui/react with fallbacks) |
504
+ | `useTerminal` | Implemented | Returns terminal context including dimensions and color support |
505
+ | `useFocus` | Implemented | Focus management via `@mdxui/terminal/keyboard` |
506
+ | `useTheme` | Implemented | Access current theme and colors |
507
+ | `useKeyboard` | Implemented | Low-level keyboard event handling |
508
+ | `createKeyboardManager` | Implemented | Create keyboard managers with presets (VIM_BINDINGS, COMMON_BINDINGS) |
509
+
510
+ ## API Reference
511
+
512
+ ### Compiler
513
+
514
+ ```typescript
515
+ // Compile JSX to UINode (recursive)
516
+ function compileJSX(element: React.ReactElement): UINode
517
+
518
+ // Compile JSX to UINode (iterative, for deep trees)
519
+ function compileJSXDeep(element: React.ReactElement): UINode
520
+ ```
521
+
522
+ ### Parser
523
+
524
+ ```typescript
525
+ // Parse JSON string or object to UINode
526
+ function parseUINode(input: string | unknown): UINode
527
+
528
+ // Parse JSON string only
529
+ function parseUINodeFromJSON(json: string): UINode
530
+
531
+ // Error class for parse failures
532
+ class ParseError extends Error {}
533
+ ```
534
+
535
+ ### Renderers (from `@mdxui/terminal/renderers`)
536
+
537
+ ```typescript
538
+ // Text tier
539
+ function renderText(node: UINode, options?: TextRenderOptions): string
540
+
541
+ // Markdown tier
542
+ function renderMarkdown(node: UINode, options?: MarkdownRenderOptions): string
543
+
544
+ // ASCII tier
545
+ function renderASCII(node: UINode, context?: RenderContext): string
546
+
547
+ // Unicode tier
548
+ function renderUnicode(node: UINode, context?: RenderContext): string
549
+
550
+ // ANSI tier
551
+ function renderANSI(node: UINode, options?: ANSIRenderOptions): string
552
+
553
+ // Interactive tier
554
+ function createInteractiveRenderer(config?: InteractiveRendererConfig): Promise<InteractiveRenderer>
555
+ ```
556
+
557
+ ### Zod Schemas
558
+
559
+ ```typescript
560
+ import { UINodeSchema, RenderTierSchema, ThemeTokensSchema, RenderContextSchema } from '@mdxui/terminal'
561
+
562
+ // Validate a UINode
563
+ const result = UINodeSchema.safeParse(data)
564
+ if (result.success) {
565
+ const node: UINode = result.data
566
+ }
567
+ ```
568
+
569
+ ## License
570
+
571
+ MIT
@@ -0,0 +1,119 @@
1
+ import { U as UINode } from './types-Ca8p_p5X.js';
2
+
3
+ /**
4
+ * Text Renderer - Plain text output without formatting
5
+ *
6
+ * The TEXT renderer is the first tier in the Universal Terminal UI's
7
+ * multi-tier rendering architecture. It outputs plain text without any
8
+ * formatting markers, colors, or special characters.
9
+ *
10
+ * Text Tier (tier 1 of 6):
11
+ * - Simple content only, no bold/italic/code markers
12
+ * - Tables rendered as key=value lines (one per line)
13
+ * - Lists rendered as bullet points (- item)
14
+ * - Metrics rendered as "Label: value" format
15
+ * - Nested structures indented (2 spaces per level)
16
+ * - Dashboard layout as labeled sections with separators
17
+ * - All special characters and formatting stripped
18
+ */
19
+
20
+ /**
21
+ * Text render options
22
+ */
23
+ interface TextRenderOptions {
24
+ /** Current indentation level */
25
+ indent?: number;
26
+ }
27
+ /**
28
+ * Renders a UINode tree to a plain text string.
29
+ *
30
+ * @param node - The UINode tree to render
31
+ * @param options - Optional rendering configuration
32
+ * @returns Plain text string
33
+ */
34
+ declare function renderText(node: UINode, options?: TextRenderOptions): string;
35
+
36
+ /**
37
+ * ANSI to CSS Converter
38
+ *
39
+ * Converts ANSI escape codes to CSS styles for web rendering.
40
+ * This enables browser-based terminal emulators to display styled output.
41
+ *
42
+ * Supports:
43
+ * - 16 basic colors (30-37, 40-47)
44
+ * - Bright colors (90-97, 100-107)
45
+ * - 256-color mode (38;5;n and 48;5;n)
46
+ * - True color / 24-bit RGB (38;2;r;g;b and 48;2;r;g;b)
47
+ * - Text styles (bold, dim, italic, underline, strikethrough, inverse)
48
+ * - Reset codes (0, 22, 23, 24, 39, 49)
49
+ *
50
+ * @module
51
+ */
52
+ /**
53
+ * CSS style properties for a styled text span
54
+ */
55
+ interface CSSStyleProperties {
56
+ color?: string;
57
+ backgroundColor?: string;
58
+ fontWeight?: 'bold' | 'normal';
59
+ fontStyle?: 'italic' | 'normal';
60
+ textDecoration?: 'underline' | 'line-through' | 'none';
61
+ opacity?: number;
62
+ }
63
+ /**
64
+ * A span of text with associated CSS styles
65
+ */
66
+ interface StyledSpan {
67
+ text: string;
68
+ style: CSSStyleProperties;
69
+ }
70
+ /**
71
+ * Result of parsing ANSI string to CSS
72
+ */
73
+ interface ANSIToCSSResult {
74
+ spans: StyledSpan[];
75
+ plainText: string;
76
+ }
77
+ /**
78
+ * Converts ANSI-escaped string to CSS-styled spans.
79
+ *
80
+ * @param ansiString - String containing ANSI escape codes
81
+ * @returns Object with spans array and plain text
82
+ *
83
+ * @example
84
+ * ```ts
85
+ * const result = ansiToCSS('\x1b[31mRed text\x1b[0m')
86
+ * // result.spans[0].style.color === 'red'
87
+ * // result.plainText === 'Red text'
88
+ * ```
89
+ */
90
+ declare function ansiToCSS(ansiString: string): ANSIToCSSResult;
91
+ /**
92
+ * Converts a styled span to an inline CSS style string.
93
+ *
94
+ * @param span - A styled span object
95
+ * @returns CSS inline style string (e.g., "color: red; font-weight: bold")
96
+ */
97
+ declare function spanToInlineStyle(span: StyledSpan): string;
98
+ /**
99
+ * Converts ANSI-escaped string to HTML with styled span elements.
100
+ *
101
+ * @param ansiString - String containing ANSI escape codes
102
+ * @returns HTML string with styled spans
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * const html = ansiToHTML('\x1b[31mRed text\x1b[0m')
107
+ * // html === '<span style="color: red">Red text</span>'
108
+ * ```
109
+ */
110
+ declare function ansiToHTML(ansiString: string): string;
111
+ /**
112
+ * Parses ANSI string to array of styled spans for React rendering.
113
+ *
114
+ * @param ansiString - String containing ANSI escape codes
115
+ * @returns Array of styled spans with React-compatible style objects
116
+ */
117
+ declare function parseAnsiToSpans(ansiString: string): StyledSpan[];
118
+
119
+ export { type ANSIToCSSResult as A, type CSSStyleProperties as C, type StyledSpan as S, type TextRenderOptions as T, ansiToCSS as a, ansiToHTML as b, parseAnsiToSpans as p, renderText as r, spanToInlineStyle as s };