@outfitter/tui 0.2.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 (235) hide show
  1. package/README.md +250 -0
  2. package/dist/borders/index.d.ts +3 -0
  3. package/dist/borders/index.js +13 -0
  4. package/dist/box/index.d.ts +4 -0
  5. package/dist/box/index.js +10 -0
  6. package/dist/confirm.d.ts +37 -0
  7. package/dist/confirm.js +36 -0
  8. package/dist/demo/index.d.ts +77 -0
  9. package/dist/demo/index.js +142 -0
  10. package/dist/demo/registry.d.ts +6 -0
  11. package/dist/demo/registry.js +28 -0
  12. package/dist/demo/renderers/borders.d.ts +7 -0
  13. package/dist/demo/renderers/borders.js +14 -0
  14. package/dist/demo/renderers/box.d.ts +7 -0
  15. package/dist/demo/renderers/box.js +15 -0
  16. package/dist/demo/renderers/colors.d.ts +7 -0
  17. package/dist/demo/renderers/colors.js +15 -0
  18. package/dist/demo/renderers/indicators.d.ts +7 -0
  19. package/dist/demo/renderers/indicators.js +14 -0
  20. package/dist/demo/renderers/list.d.ts +7 -0
  21. package/dist/demo/renderers/list.js +16 -0
  22. package/dist/demo/renderers/markdown.d.ts +7 -0
  23. package/dist/demo/renderers/markdown.js +15 -0
  24. package/dist/demo/renderers/progress.d.ts +7 -0
  25. package/dist/demo/renderers/progress.js +14 -0
  26. package/dist/demo/renderers/spinner.d.ts +7 -0
  27. package/dist/demo/renderers/spinner.js +16 -0
  28. package/dist/demo/renderers/table.d.ts +7 -0
  29. package/dist/demo/renderers/table.js +16 -0
  30. package/dist/demo/renderers/text.d.ts +7 -0
  31. package/dist/demo/renderers/text.js +13 -0
  32. package/dist/demo/renderers/tree.d.ts +7 -0
  33. package/dist/demo/renderers/tree.js +15 -0
  34. package/dist/demo/section.d.ts +4 -0
  35. package/dist/demo/section.js +20 -0
  36. package/dist/demo/templates.d.ts +3 -0
  37. package/dist/demo/templates.js +10 -0
  38. package/dist/demo/types.d.ts +2 -0
  39. package/dist/demo/types.js +8 -0
  40. package/dist/index.d.ts +31 -0
  41. package/dist/index.js +77 -0
  42. package/dist/list/index.d.ts +3 -0
  43. package/dist/list/index.js +9 -0
  44. package/dist/preset/full.d.ts +12 -0
  45. package/dist/preset/full.js +37 -0
  46. package/dist/preset/standard.d.ts +9 -0
  47. package/dist/preset/standard.js +26 -0
  48. package/dist/prompt/confirm.d.ts +4 -0
  49. package/dist/prompt/confirm.js +9 -0
  50. package/dist/prompt/group.d.ts +4 -0
  51. package/dist/prompt/group.js +9 -0
  52. package/dist/prompt/index.d.ts +7 -0
  53. package/dist/prompt/index.js +32 -0
  54. package/dist/prompt/select.d.ts +4 -0
  55. package/dist/prompt/select.js +11 -0
  56. package/dist/prompt/text.d.ts +4 -0
  57. package/dist/prompt/text.js +11 -0
  58. package/dist/prompt/types.d.ts +3 -0
  59. package/dist/prompt/types.js +8 -0
  60. package/dist/prompt/validators.d.ts +2 -0
  61. package/dist/prompt/validators.js +8 -0
  62. package/dist/render/borders.d.ts +2 -0
  63. package/dist/render/borders.js +15 -0
  64. package/dist/render/box.d.ts +3 -0
  65. package/dist/render/box.js +20 -0
  66. package/dist/render/date.d.ts +2 -0
  67. package/dist/render/date.js +12 -0
  68. package/dist/render/format-relative.d.ts +2 -0
  69. package/dist/render/format-relative.js +8 -0
  70. package/dist/render/format.d.ts +2 -0
  71. package/dist/render/format.js +10 -0
  72. package/dist/render/heading.d.ts +3 -0
  73. package/dist/render/heading.js +11 -0
  74. package/dist/render/index.d.ts +31 -0
  75. package/dist/render/index.js +222 -0
  76. package/dist/render/indicators.d.ts +2 -0
  77. package/dist/render/indicators.js +16 -0
  78. package/dist/render/json.d.ts +2 -0
  79. package/dist/render/json.js +10 -0
  80. package/dist/render/layout.d.ts +5 -0
  81. package/dist/render/layout.js +22 -0
  82. package/dist/render/list.d.ts +2 -0
  83. package/dist/render/list.js +8 -0
  84. package/dist/render/markdown.d.ts +2 -0
  85. package/dist/render/markdown.js +8 -0
  86. package/dist/render/progress.d.ts +2 -0
  87. package/dist/render/progress.js +8 -0
  88. package/dist/render/separator.d.ts +3 -0
  89. package/dist/render/separator.js +11 -0
  90. package/dist/render/shapes.d.ts +2 -0
  91. package/dist/render/shapes.js +32 -0
  92. package/dist/render/spinner.d.ts +2 -0
  93. package/dist/render/spinner.js +12 -0
  94. package/dist/render/stack.d.ts +3 -0
  95. package/dist/render/stack.js +35 -0
  96. package/dist/render/table.d.ts +3 -0
  97. package/dist/render/table.js +9 -0
  98. package/dist/render/tree.d.ts +2 -0
  99. package/dist/render/tree.js +10 -0
  100. package/dist/render/types.d.ts +2 -0
  101. package/dist/render/types.js +1 -0
  102. package/dist/shared/@outfitter/tui-011579t8.d.ts +24 -0
  103. package/dist/shared/@outfitter/tui-06dntkse.js +146 -0
  104. package/dist/shared/@outfitter/tui-0awf316b.js +71 -0
  105. package/dist/shared/@outfitter/tui-0b85rht7.js +1 -0
  106. package/dist/shared/@outfitter/tui-0mpqnyc1.js +55 -0
  107. package/dist/shared/@outfitter/tui-1qh888th.d.ts +106 -0
  108. package/dist/shared/@outfitter/tui-1tk0kxa6.js +94 -0
  109. package/dist/shared/@outfitter/tui-1wggw2zj.d.ts +56 -0
  110. package/dist/shared/@outfitter/tui-2pwhzg55.js +123 -0
  111. package/dist/shared/@outfitter/tui-2tkva96b.d.ts +20 -0
  112. package/dist/shared/@outfitter/tui-2wfat6jb.js +22 -0
  113. package/dist/shared/@outfitter/tui-34q2aenf.d.ts +24 -0
  114. package/dist/shared/@outfitter/tui-37hjcqhb.d.ts +3 -0
  115. package/dist/shared/@outfitter/tui-3dyxg62j.d.ts +97 -0
  116. package/dist/shared/@outfitter/tui-3kza6p9k.d.ts +132 -0
  117. package/dist/shared/@outfitter/tui-43bnfxv9.js +30 -0
  118. package/dist/shared/@outfitter/tui-4yz7jcyq.js +214 -0
  119. package/dist/shared/@outfitter/tui-52ndmswq.js +23 -0
  120. package/dist/shared/@outfitter/tui-53ms1ba4.d.ts +41 -0
  121. package/dist/shared/@outfitter/tui-5dsn6d6d.js +86 -0
  122. package/dist/shared/@outfitter/tui-5pb72vf9.js +51 -0
  123. package/dist/shared/@outfitter/tui-6605wa2j.js +127 -0
  124. package/dist/shared/@outfitter/tui-6ptks7jj.js +19 -0
  125. package/dist/shared/@outfitter/tui-6svngg69.js +126 -0
  126. package/dist/shared/@outfitter/tui-733asbd8.js +37 -0
  127. package/dist/shared/@outfitter/tui-75bztyfp.d.ts +50 -0
  128. package/dist/shared/@outfitter/tui-83zaah9b.d.ts +17 -0
  129. package/dist/shared/@outfitter/tui-8ejx8gq5.d.ts +71 -0
  130. package/dist/shared/@outfitter/tui-8j1gbehy.d.ts +164 -0
  131. package/dist/shared/@outfitter/tui-8mypsnva.d.ts +74 -0
  132. package/dist/shared/@outfitter/tui-997aapz0.js +61 -0
  133. package/dist/shared/@outfitter/tui-9dbykt4g.d.ts +42 -0
  134. package/dist/shared/@outfitter/tui-9h1kdd98.d.ts +119 -0
  135. package/dist/shared/@outfitter/tui-9rj9yesd.js +118 -0
  136. package/dist/shared/@outfitter/tui-a65efhsk.d.ts +23 -0
  137. package/dist/shared/@outfitter/tui-a8nkrbds.js +1 -0
  138. package/dist/shared/@outfitter/tui-ajp1153q.d.ts +59 -0
  139. package/dist/shared/@outfitter/tui-ay1fv41j.d.ts +30 -0
  140. package/dist/shared/@outfitter/tui-azh1w4ak.js +67 -0
  141. package/dist/shared/@outfitter/tui-b14ry1j1.d.ts +53 -0
  142. package/dist/shared/@outfitter/tui-c56sxcm8.d.ts +87 -0
  143. package/dist/shared/@outfitter/tui-c6ft5w6q.d.ts +91 -0
  144. package/dist/shared/@outfitter/tui-cq7za0cz.js +62 -0
  145. package/dist/shared/@outfitter/tui-dh15zwg0.js +95 -0
  146. package/dist/shared/@outfitter/tui-esc46z2v.js +20 -0
  147. package/dist/shared/@outfitter/tui-f1mj6h6p.d.ts +2 -0
  148. package/dist/shared/@outfitter/tui-gcpz529w.js +122 -0
  149. package/dist/shared/@outfitter/tui-gqsdhmk9.d.ts +42 -0
  150. package/dist/shared/@outfitter/tui-hescagw2.js +32 -0
  151. package/dist/shared/@outfitter/tui-j2kd7eej.js +126 -0
  152. package/dist/shared/@outfitter/tui-j3bkjt2g.js +7 -0
  153. package/dist/shared/@outfitter/tui-jnn9d8cd.js +8 -0
  154. package/dist/shared/@outfitter/tui-jz5nws55.d.ts +51 -0
  155. package/dist/shared/@outfitter/tui-k3mby2kk.js +70 -0
  156. package/dist/shared/@outfitter/tui-kc4nxak0.js +20 -0
  157. package/dist/shared/@outfitter/tui-kcxv8txp.js +7 -0
  158. package/dist/shared/@outfitter/tui-kydbggmj.js +39 -0
  159. package/dist/shared/@outfitter/tui-mch672g9.js +30 -0
  160. package/dist/shared/@outfitter/tui-n9kxkdrh.js +82 -0
  161. package/dist/shared/@outfitter/tui-na4dnjpw.js +348 -0
  162. package/dist/shared/@outfitter/tui-ncaatp4j.js +25 -0
  163. package/dist/shared/@outfitter/tui-nce7fgtf.js +48 -0
  164. package/dist/shared/@outfitter/tui-ngz2fbdw.js +144 -0
  165. package/dist/shared/@outfitter/tui-nprd7g0d.js +52 -0
  166. package/dist/shared/@outfitter/tui-nr580mbv.js +272 -0
  167. package/dist/shared/@outfitter/tui-nr93tf31.d.ts +64 -0
  168. package/dist/shared/@outfitter/tui-pdwbbzwr.js +179 -0
  169. package/dist/shared/@outfitter/tui-qb07rtct.js +19 -0
  170. package/dist/shared/@outfitter/tui-qkyazctw.d.ts +36 -0
  171. package/dist/shared/@outfitter/tui-qn1rgz9v.d.ts +93 -0
  172. package/dist/shared/@outfitter/tui-qs3fhwp8.js +43 -0
  173. package/dist/shared/@outfitter/tui-r8hywf9m.d.ts +48 -0
  174. package/dist/shared/@outfitter/tui-rbbcc034.js +20 -0
  175. package/dist/shared/@outfitter/tui-rgkerz72.js +85 -0
  176. package/dist/shared/@outfitter/tui-rh52sycm.d.ts +45 -0
  177. package/dist/shared/@outfitter/tui-rr924x4z.d.ts +59 -0
  178. package/dist/shared/@outfitter/tui-rwpdjrt3.js +20 -0
  179. package/dist/shared/@outfitter/tui-rx9xq9s7.d.ts +26 -0
  180. package/dist/shared/@outfitter/tui-sk05ye6g.js +1 -0
  181. package/dist/shared/@outfitter/tui-sv2xmh3w.d.ts +26 -0
  182. package/dist/shared/@outfitter/tui-t1a9xgbd.js +111 -0
  183. package/dist/shared/@outfitter/tui-t9vd88jr.js +273 -0
  184. package/dist/shared/@outfitter/tui-tq1z78x0.js +11 -0
  185. package/dist/shared/@outfitter/tui-ts1f957s.d.ts +128 -0
  186. package/dist/shared/@outfitter/tui-ve0083wa.d.ts +61 -0
  187. package/dist/shared/@outfitter/tui-vt0wg6c4.js +54 -0
  188. package/dist/shared/@outfitter/tui-wfnnq0zq.d.ts +328 -0
  189. package/dist/shared/@outfitter/tui-x3yg0887.d.ts +223 -0
  190. package/dist/shared/@outfitter/tui-x9vvtfkk.js +20 -0
  191. package/dist/shared/@outfitter/tui-xbvz707j.js +20 -0
  192. package/dist/shared/@outfitter/tui-xbx6d4t7.js +1 -0
  193. package/dist/shared/@outfitter/tui-xph95b7h.js +67 -0
  194. package/dist/shared/@outfitter/tui-xqjx7d1f.js +135 -0
  195. package/dist/shared/@outfitter/tui-xrgrp99k.d.ts +112 -0
  196. package/dist/shared/@outfitter/tui-xzjv96ps.d.ts +300 -0
  197. package/dist/shared/@outfitter/tui-ykzs6v4v.d.ts +66 -0
  198. package/dist/shared/@outfitter/tui-yw9n5h6q.d.ts +54 -0
  199. package/dist/shared/@outfitter/tui-ywmakc6b.js +30 -0
  200. package/dist/shared/@outfitter/tui-z6nf9b9h.js +7 -0
  201. package/dist/shared/@outfitter/tui-zcspg6z6.d.ts +190 -0
  202. package/dist/shared/@outfitter/tui-zhbsnj7w.js +1 -0
  203. package/dist/streaming/ansi.d.ts +2 -0
  204. package/dist/streaming/ansi.js +8 -0
  205. package/dist/streaming/index.d.ts +4 -0
  206. package/dist/streaming/index.js +17 -0
  207. package/dist/streaming/spinner.d.ts +3 -0
  208. package/dist/streaming/spinner.js +10 -0
  209. package/dist/streaming/writer.d.ts +2 -0
  210. package/dist/streaming/writer.js +9 -0
  211. package/dist/table/index.d.ts +4 -0
  212. package/dist/table/index.js +10 -0
  213. package/dist/theme/context.d.ts +9 -0
  214. package/dist/theme/context.js +12 -0
  215. package/dist/theme/create.d.ts +8 -0
  216. package/dist/theme/create.js +10 -0
  217. package/dist/theme/index.d.ts +17 -0
  218. package/dist/theme/index.js +40 -0
  219. package/dist/theme/presets/bold.d.ts +8 -0
  220. package/dist/theme/presets/bold.js +10 -0
  221. package/dist/theme/presets/default.d.ts +8 -0
  222. package/dist/theme/presets/default.js +9 -0
  223. package/dist/theme/presets/index.d.ts +12 -0
  224. package/dist/theme/presets/index.js +22 -0
  225. package/dist/theme/presets/minimal.d.ts +8 -0
  226. package/dist/theme/presets/minimal.js +10 -0
  227. package/dist/theme/presets/rounded.d.ts +8 -0
  228. package/dist/theme/presets/rounded.js +10 -0
  229. package/dist/theme/resolve.d.ts +8 -0
  230. package/dist/theme/resolve.js +11 -0
  231. package/dist/theme/types.d.ts +7 -0
  232. package/dist/theme/types.js +1 -0
  233. package/dist/tree/index.d.ts +3 -0
  234. package/dist/tree/index.js +11 -0
  235. package/package.json +263 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Validator factories for prompt input validation.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ /**
7
+ * A validator function that returns an error message or undefined.
8
+ */
9
+ type Validator = (value: string) => string | undefined;
10
+ /**
11
+ * Collection of validator factory functions.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { validators } from "@outfitter/tui/prompt";
16
+ *
17
+ * const validate = validators.compose(
18
+ * validators.required(),
19
+ * validators.minLength(3),
20
+ * validators.email()
21
+ * );
22
+ *
23
+ * const error = validate("ab");
24
+ * // "Minimum 3 characters"
25
+ * ```
26
+ */
27
+ declare const validators: {
28
+ /**
29
+ * Requires a non-empty value.
30
+ *
31
+ * @param message - Custom error message
32
+ * @returns Validator function
33
+ */
34
+ required: (message?: string) => Validator;
35
+ /**
36
+ * Requires minimum character length.
37
+ *
38
+ * @param length - Minimum length
39
+ * @param message - Custom error message
40
+ * @returns Validator function
41
+ */
42
+ minLength: (length: number, message?: string) => Validator;
43
+ /**
44
+ * Requires maximum character length.
45
+ *
46
+ * @param length - Maximum length
47
+ * @param message - Custom error message
48
+ * @returns Validator function
49
+ */
50
+ maxLength: (length: number, message?: string) => Validator;
51
+ /**
52
+ * Requires value to match a regex pattern.
53
+ *
54
+ * @param regex - Pattern to match
55
+ * @param message - Error message when pattern doesn't match
56
+ * @returns Validator function
57
+ */
58
+ pattern: (regex: RegExp, message: string) => Validator;
59
+ /**
60
+ * Validates email format.
61
+ *
62
+ * @param message - Custom error message
63
+ * @returns Validator function
64
+ */
65
+ email: (message?: string) => Validator;
66
+ /**
67
+ * Composes multiple validators, returning the first error.
68
+ *
69
+ * @param fns - Validators to compose
70
+ * @returns Combined validator function
71
+ */
72
+ compose: (...fns: Validator[]) => Validator;
73
+ };
74
+ export { Validator, validators };
@@ -0,0 +1,61 @@
1
+ // @bun
2
+ import {
3
+ demoSection
4
+ } from "./tui-733asbd8.js";
5
+ import {
6
+ renderProgress
7
+ } from "./tui-qb07rtct.js";
8
+
9
+ // packages/tui/src/demo/renderers/progress.ts
10
+ function renderProgressDemo(config, _theme) {
11
+ const showCode = config.showCode ?? true;
12
+ const lines = [];
13
+ lines.push(demoSection("Basic Progress Bar"));
14
+ lines.push("");
15
+ if (showCode) {
16
+ lines.push('import { renderProgress } from "@outfitter/tui/render";');
17
+ lines.push("");
18
+ }
19
+ const percentages = [0, 25, 50, 75, 100];
20
+ for (const pct of percentages) {
21
+ const bar = renderProgress({ current: pct, total: 100 });
22
+ lines.push(`${pct.toString().padStart(3)}% ${bar}`);
23
+ }
24
+ lines.push("");
25
+ lines.push(demoSection("With Percentage Display"));
26
+ lines.push("");
27
+ if (showCode) {
28
+ lines.push("renderProgress({ current: 75, total: 100, showPercent: true })");
29
+ lines.push("");
30
+ }
31
+ lines.push(renderProgress({ current: 75, total: 100, showPercent: true }));
32
+ lines.push("");
33
+ lines.push(demoSection("Custom Width"));
34
+ lines.push("");
35
+ const widths = [10, 20, 30, 40];
36
+ for (const width of widths) {
37
+ if (showCode) {
38
+ lines.push(`renderProgress({ current: 50, total: 100, width: ${width} })`);
39
+ }
40
+ const bar = renderProgress({ current: 50, total: 100, width });
41
+ lines.push(` ${bar}`);
42
+ lines.push("");
43
+ }
44
+ lines.push(demoSection("Edge Cases"));
45
+ lines.push("");
46
+ lines.push("Empty (0%):");
47
+ lines.push(` ${renderProgress({ current: 0, total: 100 })}`);
48
+ lines.push("");
49
+ lines.push("Full (100%):");
50
+ lines.push(` ${renderProgress({ current: 100, total: 100 })}`);
51
+ lines.push("");
52
+ lines.push("Over 100% (capped):");
53
+ lines.push(` ${renderProgress({ current: 150, total: 100, showPercent: true })}`);
54
+ lines.push("");
55
+ lines.push("Negative (floored to 0%):");
56
+ lines.push(` ${renderProgress({ current: -10, total: 100, showPercent: true })}`);
57
+ return lines.join(`
58
+ `);
59
+ }
60
+
61
+ export { renderProgressDemo };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Formatting utilities for human-readable output.
3
+ *
4
+ * Provides functions to format durations and byte sizes.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ /**
9
+ * Formats milliseconds as human-readable duration.
10
+ *
11
+ * Converts milliseconds to a compact, human-friendly format using
12
+ * h (hours), m (minutes), s (seconds), or ms (milliseconds).
13
+ *
14
+ * @param ms - Duration in milliseconds
15
+ * @returns Human-friendly duration string
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * formatDuration(150) // "150ms"
20
+ * formatDuration(45000) // "45s"
21
+ * formatDuration(9015000) // "2h 30m 15s"
22
+ * ```
23
+ */
24
+ declare function formatDuration(ms: number): string;
25
+ /**
26
+ * Formats bytes as human-readable size.
27
+ *
28
+ * Converts bytes to a compact format using appropriate units
29
+ * (B, KB, MB, GB, TB). Uses 1024-based (binary) units.
30
+ *
31
+ * @param bytes - Size in bytes
32
+ * @returns Human-friendly size string
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * formatBytes(500) // "500 B"
37
+ * formatBytes(1536) // "1.5 KB"
38
+ * formatBytes(1073741824) // "1 GB"
39
+ * ```
40
+ */
41
+ declare function formatBytes(bytes: number): string;
42
+ export { formatDuration, formatBytes };
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Indicator primitives for CLI output.
3
+ *
4
+ * Provides status symbols, selection indicators, list bullets, and progress
5
+ * markers with unicode and ASCII fallback support.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ /**
10
+ * Categories of indicators available.
11
+ */
12
+ type IndicatorCategory = "status" | "marker" | "progress" | "triangle" | "special" | "directional" | "math";
13
+ /**
14
+ * An indicator with unicode and fallback representations.
15
+ */
16
+ interface IndicatorSet {
17
+ /** Unicode character for modern terminals */
18
+ unicode: string;
19
+ /** ASCII fallback for limited terminals */
20
+ fallback: string;
21
+ /** Optional semantic color name */
22
+ color?: string;
23
+ }
24
+ /**
25
+ * All available indicators organized by category.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * import { INDICATORS, getIndicator } from "@outfitter/tui/render";
30
+ *
31
+ * // Access directly
32
+ * console.log(INDICATORS.status.success.unicode); // "✔"
33
+ *
34
+ * // Or use helper
35
+ * console.log(getIndicator("status", "success")); // "✔" or "[ok]"
36
+ * ```
37
+ */
38
+ declare const INDICATORS: Record<IndicatorCategory, Record<string, IndicatorSet>>;
39
+ /**
40
+ * Detects if the terminal supports Unicode characters.
41
+ *
42
+ * Checks for:
43
+ * - CI environments (usually support unicode)
44
+ * - Windows Terminal / ConEmu
45
+ * - TERM containing xterm/vt100
46
+ * - Locale settings
47
+ *
48
+ * @returns true if unicode is likely supported
49
+ */
50
+ declare function isUnicodeSupported(): boolean;
51
+ /**
52
+ * Gets an indicator character with automatic unicode/fallback selection.
53
+ *
54
+ * @param category - The indicator category
55
+ * @param name - The indicator name within the category
56
+ * @param forceUnicode - Override unicode detection (useful for testing)
57
+ * @returns The appropriate character for the current terminal
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * // Automatic detection
62
+ * console.log(getIndicator("status", "success"));
63
+ *
64
+ * // Force unicode
65
+ * console.log(getIndicator("status", "success", true)); // "✔"
66
+ *
67
+ * // Force fallback
68
+ * console.log(getIndicator("status", "success", false)); // "[ok]"
69
+ * ```
70
+ */
71
+ declare function getIndicator(category: IndicatorCategory, name: string, forceUnicode?: boolean): string;
72
+ /**
73
+ * Progress indicator styles.
74
+ */
75
+ type ProgressStyle = "circle" | "vertical" | "horizontal" | "shade";
76
+ /**
77
+ * Gets a progress indicator based on current/max values.
78
+ *
79
+ * @param style - The progress style (circle, vertical, horizontal, shade)
80
+ * @param current - Current progress value
81
+ * @param max - Maximum progress value
82
+ * @param forceUnicode - Override unicode detection
83
+ * @returns The appropriate progress indicator character
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * // Circle progress at 50%
88
+ * getProgressIndicator("circle", 50, 100); // "◑"
89
+ *
90
+ * // Vertical block at 75%
91
+ * getProgressIndicator("vertical", 6, 8); // "▆"
92
+ *
93
+ * // Horizontal bar at 100%
94
+ * getProgressIndicator("horizontal", 1, 1); // "█"
95
+ * ```
96
+ */
97
+ declare function getProgressIndicator(style: ProgressStyle, current: number, max: number, forceUnicode?: boolean): string;
98
+ /**
99
+ * Severity levels for escalating indicators.
100
+ *
101
+ * Uses the diamond family: ◇ (minor) → ◆ (moderate) → ◈ (severe)
102
+ */
103
+ type SeverityLevel = "minor" | "moderate" | "severe";
104
+ /**
105
+ * Gets a severity indicator for the given level.
106
+ *
107
+ * @param level - The severity level
108
+ * @param forceUnicode - Override unicode detection
109
+ * @returns The appropriate severity indicator character
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * getSeverityIndicator("minor"); // "◇"
114
+ * getSeverityIndicator("moderate"); // "◆"
115
+ * getSeverityIndicator("severe"); // "◈"
116
+ * ```
117
+ */
118
+ declare function getSeverityIndicator(level: SeverityLevel, forceUnicode?: boolean): string;
119
+ export { IndicatorCategory, IndicatorSet, INDICATORS, isUnicodeSupported, getIndicator, ProgressStyle, getProgressIndicator, SeverityLevel, getSeverityIndicator };
@@ -0,0 +1,118 @@
1
+ // @bun
2
+ import {
3
+ demoSection,
4
+ demoSubsection
5
+ } from "./tui-733asbd8.js";
6
+ import {
7
+ INDICATORS,
8
+ getIndicator,
9
+ getProgressIndicator
10
+ } from "./tui-pdwbbzwr.js";
11
+
12
+ // packages/tui/src/demo/renderers/indicators.ts
13
+ function renderIndicatorsDemo(config, _theme) {
14
+ const showCode = config.showCode ?? true;
15
+ const lines = [];
16
+ lines.push(demoSection("Indicators"));
17
+ lines.push("");
18
+ if (showCode) {
19
+ lines.push('import { getIndicator, getProgressIndicator, INDICATORS } from "@outfitter/tui/render";');
20
+ lines.push("");
21
+ }
22
+ lines.push("Semantic indicators with Unicode and ASCII fallback support.");
23
+ lines.push("");
24
+ lines.push(demoSubsection("Status"));
25
+ lines.push("");
26
+ for (const [name, indicator] of Object.entries(INDICATORS.status)) {
27
+ const colorInfo = indicator.color ? ` (${indicator.color})` : "";
28
+ lines.push(` ${indicator.unicode} ${name.padEnd(10)} \u2192 ${indicator.fallback}${colorInfo}`);
29
+ }
30
+ lines.push("");
31
+ if (showCode) {
32
+ lines.push('getIndicator("status", "success") // ' + getIndicator("status", "success", true));
33
+ lines.push('getIndicator("status", "error") // ' + getIndicator("status", "error", true));
34
+ lines.push("");
35
+ }
36
+ lines.push(demoSubsection("Markers"));
37
+ lines.push("");
38
+ const markerGroups = {
39
+ Circles: [
40
+ "circle",
41
+ "circleOutline",
42
+ "circleDotted",
43
+ "circleSmall",
44
+ "circleDot",
45
+ "circleDotOutline"
46
+ ],
47
+ Squares: ["square", "squareOutline", "squareSmall", "squareSmallOutline"],
48
+ Lozenges: ["lozenge", "lozengeOutline"],
49
+ Checkboxes: ["checkbox", "checkboxChecked", "checkboxCross"],
50
+ Pointers: ["pointer", "pointerSmall", "dash"]
51
+ };
52
+ for (const [groupName, names] of Object.entries(markerGroups)) {
53
+ lines.push(` ${groupName}:`);
54
+ for (const name of names) {
55
+ const indicator = INDICATORS.marker[name];
56
+ if (indicator) {
57
+ lines.push(` ${indicator.unicode} ${name.padEnd(18)} \u2192 ${indicator.fallback}`);
58
+ }
59
+ }
60
+ lines.push("");
61
+ }
62
+ lines.push(demoSubsection("Progress"));
63
+ lines.push("");
64
+ lines.push(" Circle: \u25CB \u25D4 \u25D1 \u25D5 \u25CF");
65
+ lines.push(" Vertical: \u2581 \u2582 \u2583 \u2584 \u2585 \u2586 \u2587 \u2588");
66
+ lines.push(" Horizontal: \u258F \u258E \u258D \u258C \u258B \u258A \u2589 \u2588");
67
+ lines.push(" Shade: \u2591 \u2592 \u2593");
68
+ lines.push("");
69
+ if (showCode) {
70
+ lines.push("// Get progress indicator by percentage:");
71
+ lines.push('getProgressIndicator("circle", 50, 100) // ' + getProgressIndicator("circle", 50, 100, true));
72
+ lines.push('getProgressIndicator("vertical", 6, 8) // ' + getProgressIndicator("vertical", 6, 8, true));
73
+ lines.push('getProgressIndicator("horizontal", 4, 8) // ' + getProgressIndicator("horizontal", 4, 8, true));
74
+ lines.push('getProgressIndicator("shade", 100, 100) // ' + getProgressIndicator("shade", 100, 100, true));
75
+ lines.push("");
76
+ }
77
+ lines.push(demoSubsection("Triangles"));
78
+ lines.push("");
79
+ const triangleGroups = {
80
+ Up: ["up", "upSmall", "upOutline"],
81
+ Down: ["down", "downSmall", "downOutline"],
82
+ Left: ["left", "leftSmall", "leftOutline"],
83
+ Right: ["right", "rightSmall", "rightOutline"]
84
+ };
85
+ for (const [groupName, names] of Object.entries(triangleGroups)) {
86
+ const indicators = names.map((n) => INDICATORS.triangle[n]?.unicode ?? "").join(" ");
87
+ lines.push(` ${groupName.padEnd(6)} ${indicators}`);
88
+ }
89
+ lines.push("");
90
+ lines.push(demoSubsection("Special"));
91
+ lines.push("");
92
+ for (const [name, indicator] of Object.entries(INDICATORS.special)) {
93
+ lines.push(` ${indicator.unicode} ${name.padEnd(14)} \u2192 ${indicator.fallback}`);
94
+ }
95
+ lines.push("");
96
+ lines.push(demoSubsection("Directional"));
97
+ lines.push("");
98
+ for (const [name, indicator] of Object.entries(INDICATORS.directional)) {
99
+ lines.push(` ${indicator.unicode} ${name.padEnd(16)} \u2192 ${indicator.fallback}`);
100
+ }
101
+ lines.push("");
102
+ lines.push(demoSubsection("Math"));
103
+ lines.push("");
104
+ for (const [name, indicator] of Object.entries(INDICATORS.math)) {
105
+ lines.push(` ${indicator.unicode} ${name.padEnd(16)} \u2192 ${indicator.fallback}`);
106
+ }
107
+ lines.push("");
108
+ lines.push(demoSubsection("Usage"));
109
+ lines.push("");
110
+ lines.push("\u2022 getIndicator(category, name) \u2014 auto-detects Unicode support");
111
+ lines.push("\u2022 getProgressIndicator(style, current, max) \u2014 maps value to step");
112
+ lines.push("\u2022 INDICATORS[category][name] \u2014 direct access to unicode/fallback");
113
+ lines.push("\u2022 Status indicators include semantic color hints");
114
+ return lines.join(`
115
+ `);
116
+ }
117
+
118
+ export { renderIndicatorsDemo };
@@ -0,0 +1,23 @@
1
+ import { ConfirmPromptOptions, PromptResult } from "./tui-c56sxcm8";
2
+ /**
3
+ * Prompts for yes/no confirmation with Result wrapping.
4
+ *
5
+ * @param options - Confirm prompt options
6
+ * @returns Ok with boolean or Err with CancelledError
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { promptConfirm } from "@outfitter/tui/prompt";
11
+ *
12
+ * const result = await promptConfirm({
13
+ * message: "Are you sure you want to continue?",
14
+ * initialValue: false,
15
+ * });
16
+ *
17
+ * if (result.isOk() && result.value) {
18
+ * console.log("Continuing...");
19
+ * }
20
+ * ```
21
+ */
22
+ declare function promptConfirm(options: ConfirmPromptOptions): PromptResult<boolean>;
23
+ export { promptConfirm };
@@ -0,0 +1 @@
1
+ // @bun
@@ -0,0 +1,59 @@
1
+ import { GlyphPair, SemanticState, VisualTheme } from "./tui-8j1gbehy";
2
+ /**
3
+ * Resolves a glyph pair to a single character based on terminal capability.
4
+ *
5
+ * Uses terminal detection to choose between unicode and fallback characters.
6
+ * Can be overridden with the `forceUnicode` parameter.
7
+ *
8
+ * @param glyph - The glyph pair to resolve
9
+ * @param forceUnicode - Override terminal detection (true = unicode, false = fallback)
10
+ * @returns The appropriate character for the terminal
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const bullet: GlyphPair = { unicode: "•", fallback: "*" };
15
+ *
16
+ * // Auto-detect terminal capability
17
+ * resolveGlyph(bullet); // "•" or "*" based on terminal
18
+ *
19
+ * // Force unicode
20
+ * resolveGlyph(bullet, true); // "•"
21
+ *
22
+ * // Force fallback
23
+ * resolveGlyph(bullet, false); // "*"
24
+ * ```
25
+ */
26
+ declare function resolveGlyph(glyph: GlyphPair, forceUnicode?: boolean): string;
27
+ /**
28
+ * Resolves a semantic state to its visual marker character.
29
+ *
30
+ * Looks up the marker specification in the theme and returns the
31
+ * appropriate character. Supports both indicator-type markers (from
32
+ * the INDICATORS registry) and custom glyph pairs.
33
+ *
34
+ * @param theme - The visual theme containing marker definitions
35
+ * @param state - The semantic state to resolve
36
+ * @param forceUnicode - Override terminal detection
37
+ * @returns The marker character for the given state
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * import { defaultTheme, resolveStateMarker } from "@outfitter/tui/theme";
42
+ *
43
+ * // Resolve success marker (indicator-type)
44
+ * resolveStateMarker(defaultTheme, "success", true); // "✔"
45
+ * resolveStateMarker(defaultTheme, "success", false); // "[ok]"
46
+ *
47
+ * // Resolve with custom theme marker
48
+ * const theme = createVisualTheme({
49
+ * overrides: {
50
+ * markers: {
51
+ * current: { type: "custom", glyph: { unicode: "★", fallback: "*" } }
52
+ * }
53
+ * }
54
+ * });
55
+ * resolveStateMarker(theme, "current", true); // "★"
56
+ * ```
57
+ */
58
+ declare function resolveStateMarker(theme: VisualTheme, state: SemanticState, forceUnicode?: boolean): string;
59
+ export { resolveGlyph, resolveStateMarker };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Renders markdown to terminal with ANSI styling.
3
+ *
4
+ * Supports the following markdown elements:
5
+ * - Headings (`# Heading`) - rendered bold
6
+ * - Bold (`**text**` or `__text__`) - rendered bold
7
+ * - Italic (`*text*` or `_text_`) - rendered italic
8
+ * - Inline code (`` `code` ``) - rendered cyan
9
+ * - Code blocks (` ``` `) - rendered dim
10
+ *
11
+ * When colors are not supported, markdown syntax is stripped
12
+ * but text content is preserved.
13
+ *
14
+ * @param markdown - Markdown text to render
15
+ * @returns Terminal-formatted string with ANSI codes
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const md = `# Heading
20
+ *
21
+ * Some **bold** and *italic* text.
22
+ *
23
+ * Use \`npm install\` to install.
24
+ * `;
25
+ *
26
+ * console.log(renderMarkdown(md));
27
+ * ```
28
+ */
29
+ declare function renderMarkdown(markdown: string): string;
30
+ export { renderMarkdown };
@@ -0,0 +1,67 @@
1
+ // @bun
2
+ import {
3
+ getExample
4
+ } from "./tui-nprd7g0d.js";
5
+ import {
6
+ demoSection
7
+ } from "./tui-733asbd8.js";
8
+ import {
9
+ SPINNER_STYLE_META,
10
+ getSpinnerStyles
11
+ } from "./tui-nr580mbv.js";
12
+ import {
13
+ SPINNERS,
14
+ getSpinnerFrame,
15
+ renderSpinner
16
+ } from "./tui-5pb72vf9.js";
17
+
18
+ // packages/tui/src/demo/renderers/spinner.ts
19
+ function renderSpinnerDemo(config, theme) {
20
+ const showCode = config.showCode ?? true;
21
+ const showDescriptions = config.showDescriptions ?? true;
22
+ const lines = [];
23
+ lines.push(demoSection("Spinner Styles"));
24
+ lines.push("");
25
+ if (showCode) {
26
+ lines.push('import { renderSpinner, SPINNERS } from "@outfitter/tui/render";');
27
+ lines.push("");
28
+ }
29
+ const message = getExample("spinnerMessage", config.examples);
30
+ const styles = getSpinnerStyles();
31
+ for (const style of styles) {
32
+ const meta = SPINNER_STYLE_META[style];
33
+ const spinner = SPINNERS[style];
34
+ lines.push(`${meta.label.toUpperCase()} (${style})`);
35
+ if (showDescriptions) {
36
+ lines.push(theme.muted(meta.description));
37
+ }
38
+ const frameDisplay = spinner.frames.join(" ");
39
+ lines.push(` Frames: ${frameDisplay}`);
40
+ lines.push(` Interval: ${spinner.interval}ms`);
41
+ const output = renderSpinner(style, message);
42
+ lines.push(` Example: ${output}`);
43
+ lines.push("");
44
+ }
45
+ lines.push(demoSection("Usage"));
46
+ lines.push("");
47
+ if (showCode) {
48
+ lines.push("// Static render (for logs/non-TTY)");
49
+ lines.push(`renderSpinner("dots", "${message}");`);
50
+ lines.push("");
51
+ lines.push("// Get frame at specific time");
52
+ lines.push('getSpinnerFrame("dots", 0); // First frame');
53
+ lines.push('getSpinnerFrame("dots", 160); // Third frame');
54
+ lines.push("");
55
+ }
56
+ lines.push("Frame progression (dots style):");
57
+ const dotSpinner = SPINNERS.dots;
58
+ for (let i = 0;i < Math.min(5, dotSpinner.frames.length); i++) {
59
+ const elapsed = i * dotSpinner.interval;
60
+ const frame = getSpinnerFrame("dots", elapsed);
61
+ lines.push(` ${elapsed}ms \u2192 ${frame}`);
62
+ }
63
+ return lines.join(`
64
+ `);
65
+ }
66
+
67
+ export { renderSpinnerDemo };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Minimal writable stream interface.
3
+ */
4
+ interface WritableStream {
5
+ write(str: string): boolean;
6
+ isTTY?: boolean;
7
+ }
8
+ /**
9
+ * Options for creating a stream writer.
10
+ */
11
+ interface StreamWriterOptions {
12
+ /** Target stream (defaults to process.stdout) */
13
+ stream?: WritableStream;
14
+ }
15
+ /**
16
+ * Interface for managing in-place terminal output.
17
+ */
18
+ interface StreamWriter {
19
+ /** Write content (replaces current content) */
20
+ write(content: string): void;
21
+ /** Update content in place */
22
+ update(content: string): void;
23
+ /** Persist current content and move to new line */
24
+ persist(): void;
25
+ /** Clear current content */
26
+ clear(): void;
27
+ }
28
+ /**
29
+ * Creates a stream writer for in-place terminal updates.
30
+ *
31
+ * The writer tracks the number of lines written and can update them in place.
32
+ * In non-TTY mode, it falls back to simple line-by-line output.
33
+ *
34
+ * @param options - Writer configuration
35
+ * @returns StreamWriter instance
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * import { createStreamWriter } from "@outfitter/tui/streaming";
40
+ *
41
+ * const writer = createStreamWriter();
42
+ *
43
+ * writer.write("Processing...");
44
+ * // Do some work
45
+ * writer.update("Processing... 50%");
46
+ * // Do more work
47
+ * writer.update("Processing... 100%");
48
+ * writer.persist();
49
+ * writer.write("Done!");
50
+ * ```
51
+ */
52
+ declare function createStreamWriter(options?: StreamWriterOptions): StreamWriter;
53
+ export { WritableStream, StreamWriterOptions, StreamWriter, createStreamWriter };