@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
@@ -0,0 +1,50 @@
1
+ /**
2
+ * ANSI Stripping Utilities
3
+ *
4
+ * Functions for removing ANSI escape codes from text and
5
+ * calculating visible text length.
6
+ *
7
+ * @module
8
+ */
9
+
10
+ /**
11
+ * Strips all ANSI escape codes from text.
12
+ *
13
+ * Useful for getting the visible content of styled text or
14
+ * calculating accurate string lengths.
15
+ *
16
+ * @param text - Text potentially containing ANSI escape codes
17
+ * @returns Plain text with all ANSI codes removed, or empty string for null/undefined
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * const styled = bold(fg('cyan', 'Hello'))
22
+ * const plain = stripAnsi(styled) // 'Hello'
23
+ * ```
24
+ */
25
+ export function stripAnsi(text: string): string {
26
+ if (!text || typeof text !== 'string') {
27
+ return ''
28
+ }
29
+ // eslint-disable-next-line no-control-regex
30
+ return text.replace(/\x1b\[[0-9;]*m/g, '')
31
+ }
32
+
33
+ /**
34
+ * Calculates the visible length of text (excluding ANSI codes).
35
+ *
36
+ * Essential for terminal UI layout calculations where you need
37
+ * to know how many characters will actually be displayed.
38
+ *
39
+ * @param text - Text potentially containing ANSI escape codes
40
+ * @returns Number of visible characters
41
+ *
42
+ * @example
43
+ * ```tsx
44
+ * const styled = bold(fg('cyan', 'Hello'))
45
+ * const len = visibleLength(styled) // 5
46
+ * ```
47
+ */
48
+ export function visibleLength(text: string): number {
49
+ return stripAnsi(text).length
50
+ }
@@ -0,0 +1,469 @@
1
+ /**
2
+ * Tailwind CSS to ANSI Color Mapping
3
+ *
4
+ * Converts Tailwind CSS class names to ANSI escape sequences for terminal output.
5
+ * Supports text colors, background colors, and font styles.
6
+ *
7
+ * @module
8
+ */
9
+
10
+ import { ANSI } from './ansi-codes'
11
+ import { hexToAnsi } from './color-convert'
12
+
13
+ // ============================================================================
14
+ // Tailwind Color Palette
15
+ // ============================================================================
16
+
17
+ /**
18
+ * Tailwind color hex values for all standard colors and shades.
19
+ */
20
+ export const TAILWIND_COLORS: Record<string, Record<string, string>> = {
21
+ gray: {
22
+ '50': '#f9fafb',
23
+ '100': '#f3f4f6',
24
+ '200': '#e5e7eb',
25
+ '300': '#d1d5db',
26
+ '400': '#9ca3af',
27
+ '500': '#6b7280',
28
+ '600': '#4b5563',
29
+ '700': '#374151',
30
+ '800': '#1f2937',
31
+ '900': '#111827',
32
+ '950': '#030712',
33
+ },
34
+ slate: {
35
+ '50': '#f8fafc',
36
+ '100': '#f1f5f9',
37
+ '200': '#e2e8f0',
38
+ '300': '#cbd5e1',
39
+ '400': '#94a3b8',
40
+ '500': '#64748b',
41
+ '600': '#475569',
42
+ '700': '#334155',
43
+ '800': '#1e293b',
44
+ '900': '#0f172a',
45
+ '950': '#020617',
46
+ },
47
+ zinc: {
48
+ '50': '#fafafa',
49
+ '100': '#f4f4f5',
50
+ '200': '#e4e4e7',
51
+ '300': '#d4d4d8',
52
+ '400': '#a1a1aa',
53
+ '500': '#71717a',
54
+ '600': '#52525b',
55
+ '700': '#3f3f46',
56
+ '800': '#27272a',
57
+ '900': '#18181b',
58
+ '950': '#09090b',
59
+ },
60
+ neutral: {
61
+ '50': '#fafafa',
62
+ '100': '#f5f5f5',
63
+ '200': '#e5e5e5',
64
+ '300': '#d4d4d4',
65
+ '400': '#a3a3a3',
66
+ '500': '#737373',
67
+ '600': '#525252',
68
+ '700': '#404040',
69
+ '800': '#262626',
70
+ '900': '#171717',
71
+ '950': '#0a0a0a',
72
+ },
73
+ stone: {
74
+ '50': '#fafaf9',
75
+ '100': '#f5f5f4',
76
+ '200': '#e7e5e4',
77
+ '300': '#d6d3d1',
78
+ '400': '#a8a29e',
79
+ '500': '#78716c',
80
+ '600': '#57534e',
81
+ '700': '#44403c',
82
+ '800': '#292524',
83
+ '900': '#1c1917',
84
+ '950': '#0c0a09',
85
+ },
86
+ red: {
87
+ '50': '#fef2f2',
88
+ '100': '#fee2e2',
89
+ '200': '#fecaca',
90
+ '300': '#fca5a5',
91
+ '400': '#f87171',
92
+ '500': '#ef4444',
93
+ '600': '#dc2626',
94
+ '700': '#b91c1c',
95
+ '800': '#991b1b',
96
+ '900': '#7f1d1d',
97
+ '950': '#450a0a',
98
+ },
99
+ orange: {
100
+ '50': '#fff7ed',
101
+ '100': '#ffedd5',
102
+ '200': '#fed7aa',
103
+ '300': '#fdba74',
104
+ '400': '#fb923c',
105
+ '500': '#f97316',
106
+ '600': '#ea580c',
107
+ '700': '#c2410c',
108
+ '800': '#9a3412',
109
+ '900': '#7c2d12',
110
+ '950': '#431407',
111
+ },
112
+ amber: {
113
+ '50': '#fffbeb',
114
+ '100': '#fef3c7',
115
+ '200': '#fde68a',
116
+ '300': '#fcd34d',
117
+ '400': '#fbbf24',
118
+ '500': '#f59e0b',
119
+ '600': '#d97706',
120
+ '700': '#b45309',
121
+ '800': '#92400e',
122
+ '900': '#78350f',
123
+ '950': '#451a03',
124
+ },
125
+ yellow: {
126
+ '50': '#fefce8',
127
+ '100': '#fef9c3',
128
+ '200': '#fef08a',
129
+ '300': '#fde047',
130
+ '400': '#facc15',
131
+ '500': '#eab308',
132
+ '600': '#ca8a04',
133
+ '700': '#a16207',
134
+ '800': '#854d0e',
135
+ '900': '#713f12',
136
+ '950': '#422006',
137
+ },
138
+ lime: {
139
+ '50': '#f7fee7',
140
+ '100': '#ecfccb',
141
+ '200': '#d9f99d',
142
+ '300': '#bef264',
143
+ '400': '#a3e635',
144
+ '500': '#84cc16',
145
+ '600': '#65a30d',
146
+ '700': '#4d7c0f',
147
+ '800': '#3f6212',
148
+ '900': '#365314',
149
+ '950': '#1a2e05',
150
+ },
151
+ green: {
152
+ '50': '#f0fdf4',
153
+ '100': '#dcfce7',
154
+ '200': '#bbf7d0',
155
+ '300': '#86efac',
156
+ '400': '#4ade80',
157
+ '500': '#22c55e',
158
+ '600': '#16a34a',
159
+ '700': '#15803d',
160
+ '800': '#166534',
161
+ '900': '#14532d',
162
+ '950': '#052e16',
163
+ },
164
+ emerald: {
165
+ '50': '#ecfdf5',
166
+ '100': '#d1fae5',
167
+ '200': '#a7f3d0',
168
+ '300': '#6ee7b7',
169
+ '400': '#34d399',
170
+ '500': '#10b981',
171
+ '600': '#059669',
172
+ '700': '#047857',
173
+ '800': '#065f46',
174
+ '900': '#064e3b',
175
+ '950': '#022c22',
176
+ },
177
+ teal: {
178
+ '50': '#f0fdfa',
179
+ '100': '#ccfbf1',
180
+ '200': '#99f6e4',
181
+ '300': '#5eead4',
182
+ '400': '#2dd4bf',
183
+ '500': '#14b8a6',
184
+ '600': '#0d9488',
185
+ '700': '#0f766e',
186
+ '800': '#115e59',
187
+ '900': '#134e4a',
188
+ '950': '#042f2e',
189
+ },
190
+ cyan: {
191
+ '50': '#ecfeff',
192
+ '100': '#cffafe',
193
+ '200': '#a5f3fc',
194
+ '300': '#67e8f9',
195
+ '400': '#22d3ee',
196
+ '500': '#06b6d4',
197
+ '600': '#0891b2',
198
+ '700': '#0e7490',
199
+ '800': '#155e75',
200
+ '900': '#164e63',
201
+ '950': '#083344',
202
+ },
203
+ sky: {
204
+ '50': '#f0f9ff',
205
+ '100': '#e0f2fe',
206
+ '200': '#bae6fd',
207
+ '300': '#7dd3fc',
208
+ '400': '#38bdf8',
209
+ '500': '#0ea5e9',
210
+ '600': '#0284c7',
211
+ '700': '#0369a1',
212
+ '800': '#075985',
213
+ '900': '#0c4a6e',
214
+ '950': '#082f49',
215
+ },
216
+ blue: {
217
+ '50': '#eff6ff',
218
+ '100': '#dbeafe',
219
+ '200': '#bfdbfe',
220
+ '300': '#93c5fd',
221
+ '400': '#60a5fa',
222
+ '500': '#3b82f6',
223
+ '600': '#2563eb',
224
+ '700': '#1d4ed8',
225
+ '800': '#1e40af',
226
+ '900': '#1e3a8a',
227
+ '950': '#172554',
228
+ },
229
+ indigo: {
230
+ '50': '#eef2ff',
231
+ '100': '#e0e7ff',
232
+ '200': '#c7d2fe',
233
+ '300': '#a5b4fc',
234
+ '400': '#818cf8',
235
+ '500': '#6366f1',
236
+ '600': '#4f46e5',
237
+ '700': '#4338ca',
238
+ '800': '#3730a3',
239
+ '900': '#312e81',
240
+ '950': '#1e1b4b',
241
+ },
242
+ violet: {
243
+ '50': '#f5f3ff',
244
+ '100': '#ede9fe',
245
+ '200': '#ddd6fe',
246
+ '300': '#c4b5fd',
247
+ '400': '#a78bfa',
248
+ '500': '#8b5cf6',
249
+ '600': '#7c3aed',
250
+ '700': '#6d28d9',
251
+ '800': '#5b21b6',
252
+ '900': '#4c1d95',
253
+ '950': '#2e1065',
254
+ },
255
+ purple: {
256
+ '50': '#faf5ff',
257
+ '100': '#f3e8ff',
258
+ '200': '#e9d5ff',
259
+ '300': '#d8b4fe',
260
+ '400': '#c084fc',
261
+ '500': '#a855f7',
262
+ '600': '#9333ea',
263
+ '700': '#7e22ce',
264
+ '800': '#6b21a8',
265
+ '900': '#581c87',
266
+ '950': '#3b0764',
267
+ },
268
+ fuchsia: {
269
+ '50': '#fdf4ff',
270
+ '100': '#fae8ff',
271
+ '200': '#f5d0fe',
272
+ '300': '#f0abfc',
273
+ '400': '#e879f9',
274
+ '500': '#d946ef',
275
+ '600': '#c026d3',
276
+ '700': '#a21caf',
277
+ '800': '#86198f',
278
+ '900': '#701a75',
279
+ '950': '#4a044e',
280
+ },
281
+ pink: {
282
+ '50': '#fdf2f8',
283
+ '100': '#fce7f3',
284
+ '200': '#fbcfe8',
285
+ '300': '#f9a8d4',
286
+ '400': '#f472b6',
287
+ '500': '#ec4899',
288
+ '600': '#db2777',
289
+ '700': '#be185d',
290
+ '800': '#9d174d',
291
+ '900': '#831843',
292
+ '950': '#500724',
293
+ },
294
+ rose: {
295
+ '50': '#fff1f2',
296
+ '100': '#ffe4e6',
297
+ '200': '#fecdd3',
298
+ '300': '#fda4af',
299
+ '400': '#fb7185',
300
+ '500': '#f43f5e',
301
+ '600': '#e11d48',
302
+ '700': '#be123c',
303
+ '800': '#9f1239',
304
+ '900': '#881337',
305
+ '950': '#4c0519',
306
+ },
307
+ }
308
+
309
+ /**
310
+ * Pre-calculated ANSI 256 color codes for specific Tailwind colors.
311
+ *
312
+ * ANSI 256 uses:
313
+ * - 0-15: Standard colors (black, red, green, etc.)
314
+ * - 16-231: 6x6x6 color cube (216 colors)
315
+ * - 232-255: Grayscale ramp (24 shades)
316
+ *
317
+ * These mappings were derived by:
318
+ * 1. Looking up Tailwind hex values from TAILWIND_PALETTE
319
+ * 2. Converting to RGB and finding nearest ANSI 256 code
320
+ *
321
+ * Color cube formula: 16 + (36 * r) + (6 * g) + b
322
+ * where r, g, b are in range [0, 5] (6 levels each)
323
+ *
324
+ * Examples:
325
+ * - blue-500 (#3b82f6) → RGB(59,130,246) → nearest: 33 (blue from standard palette)
326
+ * - red-600 (#dc2626) → RGB(220,38,38) → nearest: 160 (red from cube)
327
+ * - gray-800 (#1f2937) → RGB(31,41,55) → nearest: 238 (grayscale)
328
+ */
329
+ const TAILWIND_TO_ANSI_256: Record<string, number> = {
330
+ 'blue-500': 33, // #3b82f6 - bright blue
331
+ 'red-600': 160, // #dc2626 - dark red
332
+ 'green-400': 71, // #4ade80 - light green
333
+ 'yellow-500': 220, // #eab308 - golden yellow
334
+ 'purple-600': 128, // #9333ea - purple
335
+ 'gray-800': 238, // #1f2937 - dark gray (grayscale)
336
+ }
337
+
338
+ // ============================================================================
339
+ // Public API
340
+ // ============================================================================
341
+
342
+ /**
343
+ * Converts a single Tailwind CSS class to an ANSI 256 escape sequence.
344
+ *
345
+ * Supports:
346
+ * - Text colors: `text-{color}-{shade}`, `text-white`, `text-black`
347
+ * - Background colors: `bg-{color}-{shade}`
348
+ * - Font styles: `font-bold`, `italic`, `underline`, `line-through`
349
+ *
350
+ * @param className - A single Tailwind CSS class name
351
+ * @returns ANSI escape sequence, or empty string if class is not recognized
352
+ *
353
+ * @example
354
+ * ```tsx
355
+ * const blue = tailwindToAnsi('text-blue-500')
356
+ * const bold = tailwindToAnsi('font-bold')
357
+ * console.log(`${blue}${bold}Styled text${ANSI.reset}`)
358
+ * ```
359
+ */
360
+ export function tailwindToAnsi(className: string): string {
361
+ // Handle text styles
362
+ if (className === 'font-bold') return ANSI.bold
363
+ if (className === 'italic') return ANSI.italic
364
+ if (className === 'underline') return ANSI.underline
365
+ if (className === 'line-through') return ANSI.strikethrough
366
+
367
+ // Handle text-white and text-black
368
+ if (className === 'text-white') return '\x1b[38;5;15m'
369
+ if (className === 'text-black') return '\x1b[38;5;0m'
370
+
371
+ // Parse Tailwind color class: text-{color}-{shade} or bg-{color}-{shade}
372
+ const textMatch = className.match(/^text-(\w+)-(\d+)$/)
373
+ const bgMatch = className.match(/^bg-(\w+)-(\d+)$/)
374
+
375
+ if (textMatch) {
376
+ const [, color, shade] = textMatch
377
+ const colorKey = `${color}-${shade}`
378
+
379
+ // Check for pre-calculated values first
380
+ if (TAILWIND_TO_ANSI_256[colorKey]) {
381
+ return `\x1b[38;5;${TAILWIND_TO_ANSI_256[colorKey]}m`
382
+ }
383
+
384
+ // Look up in color palette and convert
385
+ if (TAILWIND_COLORS[color]?.[shade]) {
386
+ return hexToAnsi(TAILWIND_COLORS[color][shade])
387
+ }
388
+ }
389
+
390
+ if (bgMatch) {
391
+ const [, color, shade] = bgMatch
392
+ const colorKey = `${color}-${shade}`
393
+
394
+ // Check for pre-calculated values first
395
+ if (TAILWIND_TO_ANSI_256[colorKey]) {
396
+ return `\x1b[48;5;${TAILWIND_TO_ANSI_256[colorKey]}m`
397
+ }
398
+
399
+ // Look up in color palette and convert
400
+ if (TAILWIND_COLORS[color]?.[shade]) {
401
+ return hexToAnsi(TAILWIND_COLORS[color][shade], { background: true })
402
+ }
403
+ }
404
+
405
+ // Unknown class
406
+ return ''
407
+ }
408
+
409
+ /**
410
+ * Legacy Tailwind class map for tailwindToTerminal
411
+ */
412
+ const legacyTailwindToAnsi: Record<string, string> = {
413
+ // Text colors
414
+ 'text-primary': ANSI.cyan,
415
+ 'text-secondary': ANSI.blue,
416
+ 'text-muted': ANSI.brightBlack,
417
+ 'text-success': ANSI.green,
418
+ 'text-warning': ANSI.yellow,
419
+ 'text-error': ANSI.red,
420
+ 'text-destructive': ANSI.red,
421
+
422
+ // Font styles
423
+ 'font-bold': ANSI.bold,
424
+ 'font-medium': ANSI.bold,
425
+ italic: ANSI.italic,
426
+ underline: ANSI.underline,
427
+
428
+ // Background colors
429
+ 'bg-primary': ANSI.bgCyan,
430
+ 'bg-secondary': ANSI.bgBlue,
431
+ 'bg-muted': ANSI.bgBlack,
432
+ 'bg-destructive': ANSI.bgRed,
433
+ }
434
+
435
+ /**
436
+ * Converts multiple Tailwind CSS classes to ANSI escape codes.
437
+ *
438
+ * Takes a space-separated string of Tailwind classes and returns
439
+ * the combined ANSI escape codes.
440
+ *
441
+ * @deprecated Use {@link tailwindToAnsi} for single classes,
442
+ * or use the theme system for semantic colors.
443
+ *
444
+ * @param classes - Space-separated Tailwind class names
445
+ * @returns Combined ANSI escape codes
446
+ *
447
+ * @example
448
+ * ```tsx
449
+ * const codes = tailwindToTerminal('text-primary font-bold')
450
+ * console.log(`${codes}Styled text${ANSI.reset}`)
451
+ * ```
452
+ */
453
+ export function tailwindToTerminal(classes: string): string {
454
+ // Handle null/undefined/empty input
455
+ if (!classes || typeof classes !== 'string') {
456
+ return ''
457
+ }
458
+
459
+ const parts = classes.split(' ').filter(Boolean)
460
+ const ansiCodes: string[] = []
461
+
462
+ for (const cls of parts) {
463
+ if (legacyTailwindToAnsi[cls]) {
464
+ ansiCodes.push(legacyTailwindToAnsi[cls])
465
+ }
466
+ }
467
+
468
+ return ansiCodes.join('')
469
+ }