@hypercli/ui 0.1.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 (267) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -0
  3. package/dist/capabilities/index.d.ts +62 -0
  4. package/dist/capabilities/index.d.ts.map +1 -0
  5. package/dist/capabilities/index.js +182 -0
  6. package/dist/capabilities/index.js.map +1 -0
  7. package/dist/colors.d.ts +32 -0
  8. package/dist/colors.d.ts.map +1 -0
  9. package/dist/colors.js +40 -0
  10. package/dist/colors.js.map +1 -0
  11. package/dist/components/columns.d.ts +28 -0
  12. package/dist/components/columns.d.ts.map +1 -0
  13. package/dist/components/columns.js +70 -0
  14. package/dist/components/columns.js.map +1 -0
  15. package/dist/components/confirmPrompt.d.ts +38 -0
  16. package/dist/components/confirmPrompt.d.ts.map +1 -0
  17. package/dist/components/confirmPrompt.js +109 -0
  18. package/dist/components/confirmPrompt.js.map +1 -0
  19. package/dist/components/diff.d.ts +37 -0
  20. package/dist/components/diff.d.ts.map +1 -0
  21. package/dist/components/diff.js +36 -0
  22. package/dist/components/diff.js.map +1 -0
  23. package/dist/components/helpLayout.d.ts +59 -0
  24. package/dist/components/helpLayout.d.ts.map +1 -0
  25. package/dist/components/helpLayout.js +103 -0
  26. package/dist/components/helpLayout.js.map +1 -0
  27. package/dist/components/index.d.ts +38 -0
  28. package/dist/components/index.d.ts.map +1 -0
  29. package/dist/components/index.js +23 -0
  30. package/dist/components/index.js.map +1 -0
  31. package/dist/components/keyValue.d.ts +31 -0
  32. package/dist/components/keyValue.d.ts.map +1 -0
  33. package/dist/components/keyValue.js +36 -0
  34. package/dist/components/keyValue.js.map +1 -0
  35. package/dist/components/list.d.ts +30 -0
  36. package/dist/components/list.d.ts.map +1 -0
  37. package/dist/components/list.js +80 -0
  38. package/dist/components/list.js.map +1 -0
  39. package/dist/components/message.d.ts +33 -0
  40. package/dist/components/message.d.ts.map +1 -0
  41. package/dist/components/message.js +86 -0
  42. package/dist/components/message.js.map +1 -0
  43. package/dist/components/panel.d.ts +28 -0
  44. package/dist/components/panel.d.ts.map +1 -0
  45. package/dist/components/panel.js +30 -0
  46. package/dist/components/panel.js.map +1 -0
  47. package/dist/components/progressBar.d.ts +44 -0
  48. package/dist/components/progressBar.d.ts.map +1 -0
  49. package/dist/components/progressBar.js +154 -0
  50. package/dist/components/progressBar.js.map +1 -0
  51. package/dist/components/section.d.ts +22 -0
  52. package/dist/components/section.d.ts.map +1 -0
  53. package/dist/components/section.js +48 -0
  54. package/dist/components/section.js.map +1 -0
  55. package/dist/components/selectPrompt.d.ts +58 -0
  56. package/dist/components/selectPrompt.d.ts.map +1 -0
  57. package/dist/components/selectPrompt.js +206 -0
  58. package/dist/components/selectPrompt.js.map +1 -0
  59. package/dist/components/spinner.d.ts +38 -0
  60. package/dist/components/spinner.d.ts.map +1 -0
  61. package/dist/components/spinner.js +125 -0
  62. package/dist/components/spinner.js.map +1 -0
  63. package/dist/components/statusList.d.ts +22 -0
  64. package/dist/components/statusList.d.ts.map +1 -0
  65. package/dist/components/statusList.js +43 -0
  66. package/dist/components/statusList.js.map +1 -0
  67. package/dist/components/table.d.ts +39 -0
  68. package/dist/components/table.d.ts.map +1 -0
  69. package/dist/components/table.js +132 -0
  70. package/dist/components/table.js.map +1 -0
  71. package/dist/components/textPrompt.d.ts +43 -0
  72. package/dist/components/textPrompt.d.ts.map +1 -0
  73. package/dist/components/textPrompt.js +123 -0
  74. package/dist/components/textPrompt.js.map +1 -0
  75. package/dist/components/tree.d.ts +30 -0
  76. package/dist/components/tree.d.ts.map +1 -0
  77. package/dist/components/tree.js +49 -0
  78. package/dist/components/tree.js.map +1 -0
  79. package/dist/ds-index.d.ts +113 -0
  80. package/dist/ds-index.d.ts.map +1 -0
  81. package/dist/ds-index.js +112 -0
  82. package/dist/ds-index.js.map +1 -0
  83. package/dist/help.d.ts +32 -0
  84. package/dist/help.d.ts.map +1 -0
  85. package/dist/help.js +34 -0
  86. package/dist/help.js.map +1 -0
  87. package/dist/hyper-theme.d.ts +8 -0
  88. package/dist/hyper-theme.d.ts.map +1 -0
  89. package/dist/hyper-theme.js +30 -0
  90. package/dist/hyper-theme.js.map +1 -0
  91. package/dist/index.d.ts +50 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +39 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/md.d.ts +12 -0
  96. package/dist/md.d.ts.map +1 -0
  97. package/dist/md.js +19 -0
  98. package/dist/md.js.map +1 -0
  99. package/dist/messages.d.ts +20 -0
  100. package/dist/messages.d.ts.map +1 -0
  101. package/dist/messages.js +65 -0
  102. package/dist/messages.js.map +1 -0
  103. package/dist/palette.d.ts +20 -0
  104. package/dist/palette.d.ts.map +1 -0
  105. package/dist/palette.js +22 -0
  106. package/dist/palette.js.map +1 -0
  107. package/dist/primitives/align.d.ts +23 -0
  108. package/dist/primitives/align.d.ts.map +1 -0
  109. package/dist/primitives/align.js +40 -0
  110. package/dist/primitives/align.js.map +1 -0
  111. package/dist/primitives/badge.d.ts +24 -0
  112. package/dist/primitives/badge.d.ts.map +1 -0
  113. package/dist/primitives/badge.js +40 -0
  114. package/dist/primitives/badge.js.map +1 -0
  115. package/dist/primitives/border.d.ts +29 -0
  116. package/dist/primitives/border.d.ts.map +1 -0
  117. package/dist/primitives/border.js +100 -0
  118. package/dist/primitives/border.js.map +1 -0
  119. package/dist/primitives/context.d.ts +48 -0
  120. package/dist/primitives/context.d.ts.map +1 -0
  121. package/dist/primitives/context.js +64 -0
  122. package/dist/primitives/context.js.map +1 -0
  123. package/dist/primitives/divider.d.ts +25 -0
  124. package/dist/primitives/divider.d.ts.map +1 -0
  125. package/dist/primitives/divider.js +56 -0
  126. package/dist/primitives/divider.js.map +1 -0
  127. package/dist/primitives/indent.d.ts +16 -0
  128. package/dist/primitives/indent.d.ts.map +1 -0
  129. package/dist/primitives/indent.js +25 -0
  130. package/dist/primitives/indent.js.map +1 -0
  131. package/dist/primitives/index.d.ts +32 -0
  132. package/dist/primitives/index.d.ts.map +1 -0
  133. package/dist/primitives/index.js +22 -0
  134. package/dist/primitives/index.js.map +1 -0
  135. package/dist/primitives/line.d.ts +21 -0
  136. package/dist/primitives/line.d.ts.map +1 -0
  137. package/dist/primitives/line.js +29 -0
  138. package/dist/primitives/line.js.map +1 -0
  139. package/dist/primitives/markdown.d.ts +91 -0
  140. package/dist/primitives/markdown.d.ts.map +1 -0
  141. package/dist/primitives/markdown.js +62 -0
  142. package/dist/primitives/markdown.js.map +1 -0
  143. package/dist/primitives/pad.d.ts +24 -0
  144. package/dist/primitives/pad.d.ts.map +1 -0
  145. package/dist/primitives/pad.js +20 -0
  146. package/dist/primitives/pad.js.map +1 -0
  147. package/dist/primitives/stack.d.ts +22 -0
  148. package/dist/primitives/stack.d.ts.map +1 -0
  149. package/dist/primitives/stack.js +21 -0
  150. package/dist/primitives/stack.js.map +1 -0
  151. package/dist/primitives/styledText.d.ts +36 -0
  152. package/dist/primitives/styledText.d.ts.map +1 -0
  153. package/dist/primitives/styledText.js +42 -0
  154. package/dist/primitives/styledText.js.map +1 -0
  155. package/dist/primitives/symbol.d.ts +15 -0
  156. package/dist/primitives/symbol.d.ts.map +1 -0
  157. package/dist/primitives/symbol.js +18 -0
  158. package/dist/primitives/symbol.js.map +1 -0
  159. package/dist/primitives/truncate.d.ts +23 -0
  160. package/dist/primitives/truncate.d.ts.map +1 -0
  161. package/dist/primitives/truncate.js +99 -0
  162. package/dist/primitives/truncate.js.map +1 -0
  163. package/dist/primitives/wrap.d.ts +23 -0
  164. package/dist/primitives/wrap.d.ts.map +1 -0
  165. package/dist/primitives/wrap.js +30 -0
  166. package/dist/primitives/wrap.js.map +1 -0
  167. package/dist/render/ansi-utils.d.ts +49 -0
  168. package/dist/render/ansi-utils.d.ts.map +1 -0
  169. package/dist/render/ansi-utils.js +405 -0
  170. package/dist/render/ansi-utils.js.map +1 -0
  171. package/dist/render/index.d.ts +11 -0
  172. package/dist/render/index.d.ts.map +1 -0
  173. package/dist/render/index.js +11 -0
  174. package/dist/render/index.js.map +1 -0
  175. package/dist/render/sgr.d.ts +60 -0
  176. package/dist/render/sgr.d.ts.map +1 -0
  177. package/dist/render/sgr.js +191 -0
  178. package/dist/render/sgr.js.map +1 -0
  179. package/dist/render/strip.d.ts +24 -0
  180. package/dist/render/strip.d.ts.map +1 -0
  181. package/dist/render/strip.js +81 -0
  182. package/dist/render/strip.js.map +1 -0
  183. package/dist/render/width.d.ts +30 -0
  184. package/dist/render/width.d.ts.map +1 -0
  185. package/dist/render/width.js +149 -0
  186. package/dist/render/width.js.map +1 -0
  187. package/dist/shortcuts.d.ts +76 -0
  188. package/dist/shortcuts.d.ts.map +1 -0
  189. package/dist/shortcuts.js +117 -0
  190. package/dist/shortcuts.js.map +1 -0
  191. package/dist/styles.d.ts +43 -0
  192. package/dist/styles.d.ts.map +1 -0
  193. package/dist/styles.js +44 -0
  194. package/dist/styles.js.map +1 -0
  195. package/dist/symbols.d.ts +19 -0
  196. package/dist/symbols.d.ts.map +1 -0
  197. package/dist/symbols.js +21 -0
  198. package/dist/symbols.js.map +1 -0
  199. package/dist/test/compare.d.ts +28 -0
  200. package/dist/test/compare.d.ts.map +1 -0
  201. package/dist/test/compare.js +37 -0
  202. package/dist/test/compare.js.map +1 -0
  203. package/dist/test/index.d.ts +16 -0
  204. package/dist/test/index.d.ts.map +1 -0
  205. package/dist/test/index.js +14 -0
  206. package/dist/test/index.js.map +1 -0
  207. package/dist/test/mock.d.ts +50 -0
  208. package/dist/test/mock.d.ts.map +1 -0
  209. package/dist/test/mock.js +135 -0
  210. package/dist/test/mock.js.map +1 -0
  211. package/dist/test/render.d.ts +29 -0
  212. package/dist/test/render.d.ts.map +1 -0
  213. package/dist/test/render.js +87 -0
  214. package/dist/test/render.js.map +1 -0
  215. package/dist/test/snapshot.d.ts +16 -0
  216. package/dist/test/snapshot.d.ts.map +1 -0
  217. package/dist/test/snapshot.js +216 -0
  218. package/dist/test/snapshot.js.map +1 -0
  219. package/dist/theme/builtins.d.ts +10 -0
  220. package/dist/theme/builtins.d.ts.map +1 -0
  221. package/dist/theme/builtins.js +102 -0
  222. package/dist/theme/builtins.js.map +1 -0
  223. package/dist/theme/engine.d.ts +51 -0
  224. package/dist/theme/engine.d.ts.map +1 -0
  225. package/dist/theme/engine.js +123 -0
  226. package/dist/theme/engine.js.map +1 -0
  227. package/dist/theme/index.d.ts +10 -0
  228. package/dist/theme/index.d.ts.map +1 -0
  229. package/dist/theme/index.js +12 -0
  230. package/dist/theme/index.js.map +1 -0
  231. package/dist/theme/merge.d.ts +24 -0
  232. package/dist/theme/merge.d.ts.map +1 -0
  233. package/dist/theme/merge.js +66 -0
  234. package/dist/theme/merge.js.map +1 -0
  235. package/dist/theme/types.d.ts +44 -0
  236. package/dist/theme/types.d.ts.map +1 -0
  237. package/dist/theme/types.js +8 -0
  238. package/dist/theme/types.js.map +1 -0
  239. package/dist/theme.d.ts +9 -0
  240. package/dist/theme.d.ts.map +1 -0
  241. package/dist/theme.js +53 -0
  242. package/dist/theme.js.map +1 -0
  243. package/dist/tokens/defaults.d.ts +13 -0
  244. package/dist/tokens/defaults.d.ts.map +1 -0
  245. package/dist/tokens/defaults.js +248 -0
  246. package/dist/tokens/defaults.js.map +1 -0
  247. package/dist/tokens/index.d.ts +10 -0
  248. package/dist/tokens/index.d.ts.map +1 -0
  249. package/dist/tokens/index.js +10 -0
  250. package/dist/tokens/index.js.map +1 -0
  251. package/dist/tokens/resolver.d.ts +100 -0
  252. package/dist/tokens/resolver.d.ts.map +1 -0
  253. package/dist/tokens/resolver.js +138 -0
  254. package/dist/tokens/resolver.js.map +1 -0
  255. package/dist/tokens/types.d.ts +265 -0
  256. package/dist/tokens/types.d.ts.map +1 -0
  257. package/dist/tokens/types.js +10 -0
  258. package/dist/tokens/types.js.map +1 -0
  259. package/dist/tokens.d.ts +26 -0
  260. package/dist/tokens.d.ts.map +1 -0
  261. package/dist/tokens.js +30 -0
  262. package/dist/tokens.js.map +1 -0
  263. package/dist/types.d.ts +38 -0
  264. package/dist/types.d.ts.map +1 -0
  265. package/dist/types.js +11 -0
  266. package/dist/types.js.map +1 -0
  267. package/package.json +78 -0
@@ -0,0 +1,206 @@
1
+ /**
2
+ * SelectPrompt Component
3
+ *
4
+ * Prompts the user to select a single option from a list.
5
+ * Uses raw mode to capture keystrokes for arrow navigation.
6
+ * Falls back to numbered list input in non-TTY environments.
7
+ */
8
+ import * as readline from "node:readline";
9
+ import { getContext, styledText, symbol } from "../primitives/index.js";
10
+ /**
11
+ * Formats the select question line.
12
+ * Returns: `? message` with `?` in accent color.
13
+ */
14
+ export function formatSelectQuestion(message) {
15
+ const q = styledText("?", { color: "accent", bold: true });
16
+ return `${q} ${message}`;
17
+ }
18
+ /**
19
+ * Formats the submitted answer line.
20
+ * Returns: `checkmark message selected-label`.
21
+ */
22
+ export function formatSelectAnswer(message, selectedLabel) {
23
+ const icon = styledText(symbol("success"), { color: "success" });
24
+ const label = styledText(selectedLabel, { dim: true });
25
+ return `${icon} ${message} ${label}`;
26
+ }
27
+ /**
28
+ * Renders the option list for display.
29
+ * Returns an array of formatted option lines.
30
+ */
31
+ export function renderOptions(options, activeIndex, scrollOffset, maxVisible) {
32
+ const ctx = getContext();
33
+ const lines = [];
34
+ const visible = options.slice(scrollOffset, scrollOffset + maxVisible);
35
+ for (let i = 0; i < visible.length; i++) {
36
+ const option = visible[i];
37
+ const realIndex = scrollOffset + i;
38
+ const isActive = realIndex === activeIndex;
39
+ if (option.disabled) {
40
+ const pointer = " ";
41
+ const label = styledText(option.label, { dim: true });
42
+ const disabled = styledText("(disabled)", { dim: true });
43
+ lines.push(`${pointer}${label} ${disabled}`);
44
+ }
45
+ else if (isActive) {
46
+ const pointer = styledText(symbol("pointer"), { color: "accent" });
47
+ const label = styledText(option.label, { color: "accent" });
48
+ const hint = option.hint ? ` ${styledText(option.hint, { dim: true })}` : "";
49
+ lines.push(`${pointer} ${label}${hint}`);
50
+ }
51
+ else {
52
+ const pointer = " ";
53
+ lines.push(`${pointer}${option.label}`);
54
+ }
55
+ }
56
+ // Scroll indicators
57
+ if (scrollOffset > 0) {
58
+ const arrow = styledText(symbol("arrowUp"), { dim: true });
59
+ lines[0] = `${lines[0]} ${arrow}`;
60
+ }
61
+ if (scrollOffset + maxVisible < options.length) {
62
+ const arrow = styledText(symbol("arrowDown"), { dim: true });
63
+ lines[lines.length - 1] = `${lines[lines.length - 1]} ${arrow}`;
64
+ }
65
+ return lines;
66
+ }
67
+ /**
68
+ * Find the next non-disabled index in a direction.
69
+ */
70
+ function findNextEnabled(options, from, direction) {
71
+ let index = from;
72
+ const len = options.length;
73
+ for (let attempts = 0; attempts < len; attempts++) {
74
+ index = (index + direction + len) % len;
75
+ if (!options[index].disabled)
76
+ return index;
77
+ }
78
+ return from; // All disabled, stay put
79
+ }
80
+ /**
81
+ * Prompts the user to select a single option from a list using arrow-key navigation.
82
+ * Falls back to numbered list input in non-TTY environments.
83
+ *
84
+ * @typeParam T - The value type of the selectable options.
85
+ * @param options - Select prompt configuration.
86
+ * @returns The value of the selected option.
87
+ */
88
+ export function selectPrompt(options) {
89
+ const ctx = getContext();
90
+ const stream = process.stderr;
91
+ const maxVisible = options.maxVisible ?? 10;
92
+ const isTTY = !!process.stdin.isTTY;
93
+ // Find first non-disabled option
94
+ let activeIndex = options.options.findIndex((o) => !o.disabled);
95
+ if (activeIndex === -1) {
96
+ return Promise.reject(new Error("All options are disabled"));
97
+ }
98
+ let scrollOffset = 0;
99
+ function adjustScroll() {
100
+ if (activeIndex < scrollOffset) {
101
+ scrollOffset = activeIndex;
102
+ }
103
+ else if (activeIndex >= scrollOffset + maxVisible) {
104
+ scrollOffset = activeIndex - maxVisible + 1;
105
+ }
106
+ }
107
+ return new Promise((resolve, reject) => {
108
+ if (!isTTY) {
109
+ // Non-TTY: numbered list fallback
110
+ stream.write(`${options.message}\n`);
111
+ options.options.forEach((opt, i) => {
112
+ const disabled = opt.disabled ? " (disabled)" : "";
113
+ stream.write(` ${i + 1}. ${opt.label}${disabled}\n`);
114
+ });
115
+ stream.write("Enter number: ");
116
+ const rl = readline.createInterface({
117
+ input: process.stdin,
118
+ terminal: false,
119
+ });
120
+ rl.once("line", (line) => {
121
+ rl.close();
122
+ const num = Number.parseInt(line.trim(), 10);
123
+ if (Number.isNaN(num) || num < 1 || num > options.options.length) {
124
+ reject(new Error(`Invalid selection: "${line.trim()}"`));
125
+ return;
126
+ }
127
+ const selected = options.options[num - 1];
128
+ if (selected.disabled) {
129
+ reject(new Error(`Option "${selected.label}" is disabled`));
130
+ return;
131
+ }
132
+ resolve(selected.value);
133
+ });
134
+ return;
135
+ }
136
+ // Interactive TTY mode with raw keypress handling
137
+ const question = formatSelectQuestion(options.message);
138
+ let renderedLines = 0;
139
+ function render() {
140
+ // Clear previously rendered lines
141
+ if (renderedLines > 0) {
142
+ for (let i = 0; i < renderedLines; i++) {
143
+ stream.write("\x1b[A"); // move up
144
+ }
145
+ stream.write("\r\x1b[J"); // clear from cursor to end
146
+ }
147
+ adjustScroll();
148
+ const lines = renderOptions(options.options, activeIndex, scrollOffset, maxVisible);
149
+ stream.write(`${question}\n`);
150
+ for (const line of lines) {
151
+ stream.write(`${line}\n`);
152
+ }
153
+ renderedLines = lines.length + 1; // +1 for the question line
154
+ }
155
+ // Hide cursor
156
+ stream.write("\x1b[?25l");
157
+ render();
158
+ // Enable raw mode for keypress capture
159
+ process.stdin.setRawMode(true);
160
+ process.stdin.resume();
161
+ const onData = (data) => {
162
+ const key = data.toString();
163
+ // Ctrl+C
164
+ if (key === "\x03") {
165
+ cleanup();
166
+ stream.write("\x1b[?25h");
167
+ reject(new Error("Prompt cancelled"));
168
+ return;
169
+ }
170
+ // Enter
171
+ if (key === "\r" || key === "\n") {
172
+ cleanup();
173
+ // Clear the rendered options
174
+ if (renderedLines > 0) {
175
+ for (let i = 0; i < renderedLines; i++) {
176
+ stream.write("\x1b[A");
177
+ }
178
+ stream.write("\r\x1b[J");
179
+ }
180
+ const selected = options.options[activeIndex];
181
+ stream.write(`${formatSelectAnswer(options.message, selected.label)}\n`);
182
+ stream.write("\x1b[?25h");
183
+ resolve(selected.value);
184
+ return;
185
+ }
186
+ // Arrow keys (escape sequences)
187
+ if (key === "\x1b[A" || key === "k") {
188
+ // Up
189
+ activeIndex = findNextEnabled(options.options, activeIndex, -1);
190
+ render();
191
+ }
192
+ else if (key === "\x1b[B" || key === "j") {
193
+ // Down
194
+ activeIndex = findNextEnabled(options.options, activeIndex, 1);
195
+ render();
196
+ }
197
+ };
198
+ function cleanup() {
199
+ process.stdin.removeListener("data", onData);
200
+ process.stdin.setRawMode(false);
201
+ process.stdin.pause();
202
+ }
203
+ process.stdin.on("data", onData);
204
+ });
205
+ }
206
+ //# sourceMappingURL=selectPrompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectPrompt.js","sourceRoot":"","sources":["../../src/components/selectPrompt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Spinner Component
3
+ *
4
+ * An animated spinner indicator for indeterminate operations.
5
+ * Manages terminal output directly via process.stderr.write and cursor control.
6
+ * Gracefully degrades in non-TTY/CI environments to static line output.
7
+ */
8
+ /** Options for creating a spinner. */
9
+ export type SpinnerOptions = {
10
+ /** Initial spinner label text. */
11
+ text?: string;
12
+ /** Spinner animation style. Defaults to `'dots'`. */
13
+ style?: "dots" | "line" | "arc";
14
+ /** Output stream for spinner rendering. Defaults to `process.stderr`. */
15
+ stream?: NodeJS.WriteStream;
16
+ };
17
+ /** Handle for controlling a running spinner. */
18
+ export type SpinnerHandle = {
19
+ /** Start the spinner animation, optionally setting the label text. */
20
+ start(text?: string): void;
21
+ /** Update the spinner label text. */
22
+ update(text: string): void;
23
+ /** Stop the spinner, optionally showing a final message. */
24
+ stop(finalText?: string): void;
25
+ /** Stop with a success icon and optional message. */
26
+ succeed(text?: string): void;
27
+ /** Stop with a failure icon and optional message. */
28
+ fail(text?: string): void;
29
+ };
30
+ /**
31
+ * Creates an animated spinner for indeterminate operations.
32
+ * Gracefully degrades to static output in non-TTY/CI environments.
33
+ *
34
+ * @param options - Spinner configuration.
35
+ * @returns A handle to control the spinner lifecycle.
36
+ */
37
+ export declare function spinner(options?: SpinnerOptions): SpinnerHandle;
38
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/components/spinner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,sCAAsC;AACtC,MAAM,MAAM,cAAc,GAAG;IAC5B,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;IAChC,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;CAC5B,CAAC;AAEF,gDAAgD;AAChD,MAAM,MAAM,aAAa,GAAG;IAC3B,sEAAsE;IACtE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,qCAAqC;IACrC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,4DAA4D;IAC5D,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,qDAAqD;IACrD,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,qDAAqD;IACrD,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,aAAa,CAgI/D"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Spinner Component
3
+ *
4
+ * An animated spinner indicator for indeterminate operations.
5
+ * Manages terminal output directly via process.stderr.write and cursor control.
6
+ * Gracefully degrades in non-TTY/CI environments to static line output.
7
+ */
8
+ import { getContext, styledText, symbol } from "../primitives/index.js";
9
+ import { stripAnsi } from "../render/index.js";
10
+ /**
11
+ * Creates an animated spinner for indeterminate operations.
12
+ * Gracefully degrades to static output in non-TTY/CI environments.
13
+ *
14
+ * @param options - Spinner configuration.
15
+ * @returns A handle to control the spinner lifecycle.
16
+ */
17
+ export function spinner(options) {
18
+ const ctx = getContext();
19
+ const stream = options?.stream ?? process.stderr;
20
+ const style = options?.style ?? "dots";
21
+ let currentText = options?.text ?? "";
22
+ let frameIndex = 0;
23
+ let timer = null;
24
+ let startTime = null;
25
+ let running = false;
26
+ const spinnerKey = `spinner${style.charAt(0).toUpperCase()}${style.slice(1)}`;
27
+ const frames = ctx.tokens.motion[spinnerKey];
28
+ const interval = ctx.tokens.motion.spinnerInterval;
29
+ const isTTY = !!stream.isTTY;
30
+ const isInteractive = isTTY && !ctx.capabilities.isCI;
31
+ function clearLine() {
32
+ // Clear current line: move to column 0, clear to end of line
33
+ stream.write("\r\x1b[K");
34
+ }
35
+ function renderFrame() {
36
+ const frame = frames[frameIndex % frames.length];
37
+ frameIndex++;
38
+ clearLine();
39
+ const frameStyled = styledText(frame, { color: "accent" });
40
+ stream.write(`${frameStyled} ${currentText}`);
41
+ }
42
+ function formatDuration(ms) {
43
+ if (ms < 1000)
44
+ return `${ms}ms`;
45
+ const s = (ms / 1000).toFixed(1);
46
+ return `${s}s`;
47
+ }
48
+ const handle = {
49
+ start(text) {
50
+ if (running)
51
+ return;
52
+ running = true;
53
+ if (text !== undefined)
54
+ currentText = text;
55
+ startTime = Date.now();
56
+ if (!isInteractive) {
57
+ // Non-TTY/CI: static output
58
+ const prefix = ctx.capabilities.unicode ? symbol("running") : "[..]";
59
+ stream.write(`${prefix} ${currentText}\n`);
60
+ return;
61
+ }
62
+ // Hide cursor
63
+ stream.write("\x1b[?25l");
64
+ frameIndex = 0;
65
+ renderFrame();
66
+ timer = setInterval(renderFrame, interval);
67
+ },
68
+ update(text) {
69
+ currentText = text;
70
+ if (!isInteractive) {
71
+ const prefix = ctx.capabilities.unicode ? symbol("running") : "[..]";
72
+ stream.write(`${prefix} ${text}\n`);
73
+ return;
74
+ }
75
+ // Next renderFrame tick will pick up the new text
76
+ },
77
+ stop(finalText) {
78
+ if (!running)
79
+ return;
80
+ running = false;
81
+ if (timer) {
82
+ clearInterval(timer);
83
+ timer = null;
84
+ }
85
+ if (!isInteractive) {
86
+ if (finalText) {
87
+ stream.write(`${finalText}\n`);
88
+ }
89
+ return;
90
+ }
91
+ clearLine();
92
+ if (finalText) {
93
+ stream.write(`${finalText}\n`);
94
+ }
95
+ // Show cursor
96
+ stream.write("\x1b[?25h");
97
+ },
98
+ succeed(text) {
99
+ const finalText = text ?? currentText;
100
+ const elapsed = startTime !== null ? Date.now() - startTime : 0;
101
+ const icon = styledText(symbol("success"), { color: "success" });
102
+ const duration = styledText(` ${formatDuration(elapsed)}`, { dim: true });
103
+ if (!isInteractive) {
104
+ const prefix = ctx.capabilities.unicode ? symbol("success") : "[OK]";
105
+ stream.write(`${prefix} ${finalText}${duration}\n`);
106
+ running = false;
107
+ return;
108
+ }
109
+ handle.stop(`${icon} ${finalText}${duration}`);
110
+ },
111
+ fail(text) {
112
+ const finalText = text ?? currentText;
113
+ const icon = styledText(symbol("error"), { color: "error" });
114
+ if (!isInteractive) {
115
+ const prefix = ctx.capabilities.unicode ? symbol("error") : "[FAIL]";
116
+ stream.write(`${prefix} ${finalText}\n`);
117
+ running = false;
118
+ return;
119
+ }
120
+ handle.stop(`${icon} ${finalText}`);
121
+ },
122
+ };
123
+ return handle;
124
+ }
125
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/components/spinner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * statusList Component (Static)
3
+ *
4
+ * Renders a list of items with status icons and optional detail text.
5
+ */
6
+ /** A single item in a status list. */
7
+ export type StatusListItem = {
8
+ /** Display text for this item. */
9
+ text: string;
10
+ /** Current status, determining the icon and color. */
11
+ status: "pending" | "running" | "success" | "error" | "warning" | "skipped";
12
+ /** Optional detail text shown inline (if short) or on the next line (if long). */
13
+ detail?: string;
14
+ };
15
+ /**
16
+ * Renders a list of items with status-mapped icons and colors.
17
+ *
18
+ * @param items - The status list items to render.
19
+ * @returns The formatted status list as a multi-line string.
20
+ */
21
+ export declare function statusList(items: StatusListItem[]): string;
22
+ //# sourceMappingURL=statusList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statusList.d.ts","sourceRoot":"","sources":["../../src/components/statusList.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,sCAAsC;AACtC,MAAM,MAAM,cAAc,GAAG;IAC5B,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IAC5E,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAWF;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,CAyB1D"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * statusList Component (Static)
3
+ *
4
+ * Renders a list of items with status icons and optional detail text.
5
+ */
6
+ import { getContext, indent, stack, styledText, symbol } from "../primitives/index.js";
7
+ const STATUS_COLOR_MAP = {
8
+ success: "success",
9
+ error: "error",
10
+ warning: "warning",
11
+ running: "info",
12
+ pending: "fgMuted",
13
+ skipped: "fgMuted",
14
+ };
15
+ /**
16
+ * Renders a list of items with status-mapped icons and colors.
17
+ *
18
+ * @param items - The status list items to render.
19
+ * @returns The formatted status list as a multi-line string.
20
+ */
21
+ export function statusList(items) {
22
+ const ctx = getContext();
23
+ const iconGap = " ".repeat(ctx.tokens.space.iconGap);
24
+ const lines = [];
25
+ for (const item of items) {
26
+ const icon = symbol(item.status);
27
+ const color = STATUS_COLOR_MAP[item.status];
28
+ const text = styledText(item.text, { color });
29
+ let line = icon + iconGap + text;
30
+ if (item.detail) {
31
+ // If detail is short (< 40 chars), show inline; otherwise on next line indented
32
+ if (item.detail.length < 40) {
33
+ line += ` ${styledText(`(${item.detail})`, { dim: true })}`;
34
+ }
35
+ else {
36
+ line += `\n${indent(styledText(item.detail, { dim: true }), 1)}`;
37
+ }
38
+ }
39
+ lines.push(line);
40
+ }
41
+ return stack(lines);
42
+ }
43
+ //# sourceMappingURL=statusList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statusList.js","sourceRoot":"","sources":["../../src/components/statusList.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAavF,MAAM,gBAAgB,GAAwD;IAC7E,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;CAClB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAAuB;IACjD,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;IACzB,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACrD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAE9C,IAAI,IAAI,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI,CAAC;QAEjC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,gFAAgF;YAChF,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;gBAC7B,IAAI,IAAI,IAAI,UAAU,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YAC7D,CAAC;iBAAM,CAAC;gBACP,IAAI,IAAI,KAAK,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YAClE,CAAC;QACF,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC;AACrB,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * table Component
3
+ *
4
+ * Renders tabular data in multiple variants: minimal, borderless, grid, outer.
5
+ */
6
+ /** Definition of a single table column. */
7
+ export type TableColumn = {
8
+ /** Property key used to look up values in each data row. */
9
+ key: string;
10
+ /** Display header text. Defaults to the `key`. */
11
+ header?: string;
12
+ /** Cell text alignment. Defaults to `'left'`. */
13
+ align?: "left" | "right" | "center";
14
+ /** Fixed column width in characters, or `'auto'` to fit content. */
15
+ width?: number | "auto";
16
+ /** Maximum column width. Only effective when `truncate` is enabled. */
17
+ maxWidth?: number;
18
+ /** Whether to truncate cell text that exceeds `maxWidth`. */
19
+ truncate?: boolean;
20
+ };
21
+ /** Options for rendering a table. */
22
+ export type TableOptions = {
23
+ /** Column definitions describing the table structure. */
24
+ columns: TableColumn[];
25
+ /** Row data as an array of records keyed by column `key`. */
26
+ data: Array<Record<string, unknown>>;
27
+ /** Table rendering variant. Defaults to `'minimal'`. */
28
+ variant?: "minimal" | "grid" | "borderless" | "outer";
29
+ /** Text to display when `data` is empty. Defaults to `''`. */
30
+ emptyText?: string;
31
+ };
32
+ /**
33
+ * Renders tabular data in aligned columns with multiple visual variants.
34
+ *
35
+ * @param options - Table configuration.
36
+ * @returns The formatted table as a multi-line string.
37
+ */
38
+ export declare function table(options: TableOptions): string;
39
+ //# sourceMappingURL=table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/components/table.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,2CAA2C;AAC3C,MAAM,MAAM,WAAW,GAAG;IACzB,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC;IACZ,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IACpC,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,qCAAqC;AACrC,MAAM,MAAM,YAAY,GAAG;IAC1B,yDAAyD;IACzD,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,6DAA6D;IAC7D,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrC,wDAAwD;IACxD,OAAO,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,YAAY,GAAG,OAAO,CAAC;IACtD,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAmJnD"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * table Component
3
+ *
4
+ * Renders tabular data in multiple variants: minimal, borderless, grid, outer.
5
+ */
6
+ import { getContext, styledText } from "../primitives/index.js";
7
+ import { ansiPad, ansiTruncate, stringWidth } from "../render/index.js";
8
+ /**
9
+ * Renders tabular data in aligned columns with multiple visual variants.
10
+ *
11
+ * @param options - Table configuration.
12
+ * @returns The formatted table as a multi-line string.
13
+ */
14
+ export function table(options) {
15
+ const ctx = getContext();
16
+ const variant = options.variant ?? "minimal";
17
+ const gutter = ctx.tokens.space.gutter;
18
+ const chars = ctx.tokens.border.chars;
19
+ const columns = options.columns;
20
+ const data = options.data;
21
+ // Handle empty data
22
+ if (data.length === 0) {
23
+ return options.emptyText ?? "";
24
+ }
25
+ // Convert data to cell strings
26
+ const cellData = data.map((row) => columns.map((col) => {
27
+ const val = row[col.key];
28
+ return val === null || val === undefined ? "" : String(val);
29
+ }));
30
+ // Calculate column widths
31
+ const colWidths = columns.map((col, i) => {
32
+ if (typeof col.width === "number")
33
+ return col.width;
34
+ // Auto: max of header width and all data widths
35
+ let max = stringWidth(col.header ?? col.key);
36
+ for (const row of cellData) {
37
+ const w = stringWidth(row[i]);
38
+ if (w > max)
39
+ max = w;
40
+ }
41
+ if (col.maxWidth && max > col.maxWidth) {
42
+ max = col.maxWidth;
43
+ }
44
+ return max;
45
+ });
46
+ // Format cell content (truncate + align)
47
+ function formatCell(text, colIndex) {
48
+ const col = columns[colIndex];
49
+ const width = colWidths[colIndex];
50
+ let result = text;
51
+ if (col.truncate && col.maxWidth) {
52
+ const currentW = stringWidth(result);
53
+ if (currentW > width) {
54
+ result = ansiTruncate(result, width, ctx.tokens.symbol.ellipsis);
55
+ }
56
+ }
57
+ return ansiPad(result, width, col.align ?? "left");
58
+ }
59
+ // Build header cells
60
+ const headerCells = columns.map((col, i) => {
61
+ const headerText = col.header ?? col.key;
62
+ const formatted = ansiPad(headerText, colWidths[i], col.align ?? "left");
63
+ return styledText(formatted, { bold: true });
64
+ });
65
+ // Build data rows
66
+ const dataRows = cellData.map((row) => row.map((cell, i) => formatCell(cell, i)));
67
+ const lines = [];
68
+ const gutterStr = " ".repeat(gutter);
69
+ if (variant === "minimal") {
70
+ lines.push(headerCells.join(gutterStr));
71
+ // Divider under headers
72
+ const dividerParts = colWidths.map((w) => chars.horizontal.repeat(w));
73
+ lines.push(dividerParts.join(gutterStr));
74
+ for (const row of dataRows) {
75
+ lines.push(row.join(gutterStr));
76
+ }
77
+ }
78
+ else if (variant === "borderless") {
79
+ lines.push(headerCells.join(gutterStr));
80
+ for (const row of dataRows) {
81
+ lines.push(row.join(gutterStr));
82
+ }
83
+ }
84
+ else if (variant === "grid") {
85
+ const sep = chars.vertical;
86
+ const innerWidth = colWidths.reduce((s, w) => s + w, 0) + (columns.length - 1) * 3; // " | " between columns
87
+ // Top border
88
+ const topParts = colWidths.map((w) => chars.horizontal.repeat(w));
89
+ lines.push(chars.topLeft +
90
+ topParts.join(chars.horizontal + chars.teeDown + chars.horizontal) +
91
+ chars.topRight);
92
+ // Header row
93
+ lines.push(`${sep} ${headerCells.join(` ${sep} `)} ${sep}`);
94
+ // Header divider
95
+ const hDivParts = colWidths.map((w) => chars.horizontal.repeat(w));
96
+ lines.push(chars.teeRight +
97
+ hDivParts.join(chars.horizontal + chars.cross + chars.horizontal) +
98
+ chars.teeLeft);
99
+ // Data rows with dividers between them
100
+ for (let i = 0; i < dataRows.length; i++) {
101
+ lines.push(`${sep} ${dataRows[i].join(` ${sep} `)} ${sep}`);
102
+ if (i < dataRows.length - 1) {
103
+ lines.push(chars.teeRight +
104
+ hDivParts.join(chars.horizontal + chars.cross + chars.horizontal) +
105
+ chars.teeLeft);
106
+ }
107
+ }
108
+ // Bottom border
109
+ lines.push(chars.bottomLeft +
110
+ topParts.join(chars.horizontal + chars.teeUp + chars.horizontal) +
111
+ chars.bottomRight);
112
+ }
113
+ else if (variant === "outer") {
114
+ const sep = chars.vertical;
115
+ // Top border
116
+ const topParts = colWidths.map((w) => chars.horizontal.repeat(w));
117
+ const innerHWidth = colWidths.reduce((s, w) => s + w, 0) + (columns.length - 1) * gutter;
118
+ lines.push(chars.topLeft + chars.horizontal.repeat(innerHWidth + 2) + chars.topRight);
119
+ // Header row
120
+ lines.push(`${sep} ${headerCells.join(gutterStr)} ${sep}`);
121
+ // Header divider
122
+ lines.push(`${sep} ${colWidths.map((w) => chars.horizontal.repeat(w)).join(gutterStr)} ${sep}`);
123
+ // Data rows
124
+ for (const row of dataRows) {
125
+ lines.push(`${sep} ${row.join(gutterStr)} ${sep}`);
126
+ }
127
+ // Bottom border
128
+ lines.push(chars.bottomLeft + chars.horizontal.repeat(innerHWidth + 2) + chars.bottomRight);
129
+ }
130
+ return lines.join("\n");
131
+ }
132
+ //# sourceMappingURL=table.js.map