zard-cli 1.0.0-beta.9 → 1.1.0-alpha.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 (237) hide show
  1. package/README.md +60 -188
  2. package/commands/add/component-installer.d.ts +4 -1
  3. package/commands/add/component-installer.d.ts.map +1 -1
  4. package/commands/add/component-installer.js +33 -5
  5. package/commands/add/component-installer.js.map +1 -1
  6. package/commands/add/component-selector.d.ts +6 -0
  7. package/commands/add/component-selector.d.ts.map +1 -1
  8. package/commands/add/component-selector.js +9 -27
  9. package/commands/add/component-selector.js.map +1 -1
  10. package/commands/add/dark-mode-setup.d.ts +2 -0
  11. package/commands/add/dark-mode-setup.d.ts.map +1 -1
  12. package/commands/add/dark-mode-setup.js +5 -11
  13. package/commands/add/dark-mode-setup.js.map +1 -1
  14. package/commands/add/dependency-resolver.d.ts +1 -1
  15. package/commands/add/dependency-resolver.d.ts.map +1 -1
  16. package/commands/add/dependency-resolver.js +5 -6
  17. package/commands/add/dependency-resolver.js.map +1 -1
  18. package/commands/add/index.d.ts.map +1 -1
  19. package/commands/add/index.js +127 -85
  20. package/commands/add/index.js.map +1 -1
  21. package/commands/add/wizard.d.ts +31 -0
  22. package/commands/add/wizard.d.ts.map +1 -0
  23. package/commands/add/wizard.js +289 -0
  24. package/commands/add/wizard.js.map +1 -0
  25. package/commands/init/config-prompter.d.ts +59 -56
  26. package/commands/init/config-prompter.d.ts.map +1 -1
  27. package/commands/init/config-prompter.js +76 -74
  28. package/commands/init/config-prompter.js.map +1 -1
  29. package/commands/init/dependencies.d.ts +1 -8
  30. package/commands/init/dependencies.d.ts.map +1 -1
  31. package/commands/init/dependencies.js +36 -16
  32. package/commands/init/dependencies.js.map +1 -1
  33. package/commands/init/index.d.ts.map +1 -1
  34. package/commands/init/index.js +132 -86
  35. package/commands/init/index.js.map +1 -1
  36. package/commands/init/project-kind.d.ts +82 -0
  37. package/commands/init/project-kind.d.ts.map +1 -0
  38. package/commands/init/project-kind.js +166 -0
  39. package/commands/init/project-kind.js.map +1 -0
  40. package/commands/init/steps.d.ts +16 -0
  41. package/commands/init/steps.d.ts.map +1 -0
  42. package/commands/init/steps.js +151 -0
  43. package/commands/init/steps.js.map +1 -0
  44. package/commands/init/tailwind-setup.d.ts +9 -2
  45. package/commands/init/tailwind-setup.d.ts.map +1 -1
  46. package/commands/init/tailwind-setup.js +33 -9
  47. package/commands/init/tailwind-setup.js.map +1 -1
  48. package/commands/init/theme-loader.d.ts.map +1 -1
  49. package/commands/init/theme-loader.js +1 -3
  50. package/commands/init/theme-loader.js.map +1 -1
  51. package/commands/init/tsconfig-updater.d.ts +8 -1
  52. package/commands/init/tsconfig-updater.d.ts.map +1 -1
  53. package/commands/init/tsconfig-updater.js +30 -11
  54. package/commands/init/tsconfig-updater.js.map +1 -1
  55. package/commands/init/update-angular-config.d.ts.map +1 -1
  56. package/commands/init/update-angular-config.js +28 -47
  57. package/commands/init/update-angular-config.js.map +1 -1
  58. package/commands/init/vite-setup.d.ts +10 -0
  59. package/commands/init/vite-setup.d.ts.map +1 -0
  60. package/commands/init/vite-setup.js +60 -0
  61. package/commands/init/vite-setup.js.map +1 -0
  62. package/commands/init/wizard.d.ts +30 -0
  63. package/commands/init/wizard.d.ts.map +1 -0
  64. package/commands/init/wizard.js +560 -0
  65. package/commands/init/wizard.js.map +1 -0
  66. package/core/registry/registry-data.d.ts.map +1 -1
  67. package/core/registry/registry-data.js +359 -61
  68. package/core/registry/registry-data.js.map +1 -1
  69. package/core/themes/theme-definitions.d.ts +5 -5
  70. package/core/themes/theme-definitions.d.ts.map +1 -1
  71. package/core/themes/theme-definitions.js +15 -11
  72. package/core/themes/theme-definitions.js.map +1 -1
  73. package/index.js +40 -4
  74. package/index.js.map +1 -1
  75. package/package.json +58 -61
  76. package/ui/blocks.d.ts +70 -0
  77. package/ui/blocks.d.ts.map +1 -0
  78. package/ui/blocks.js +116 -0
  79. package/ui/blocks.js.map +1 -0
  80. package/ui/brand.d.ts +14 -0
  81. package/ui/brand.d.ts.map +1 -0
  82. package/ui/brand.js +35 -0
  83. package/ui/brand.js.map +1 -0
  84. package/ui/engine/animation/index.d.ts +39 -0
  85. package/ui/engine/animation/index.d.ts.map +1 -0
  86. package/ui/engine/animation/index.js +103 -0
  87. package/ui/engine/animation/index.js.map +1 -0
  88. package/ui/engine/ansi/index.d.ts +52 -0
  89. package/ui/engine/ansi/index.d.ts.map +1 -0
  90. package/ui/engine/ansi/index.js +117 -0
  91. package/ui/engine/ansi/index.js.map +1 -0
  92. package/ui/engine/components/index.d.ts +211 -0
  93. package/ui/engine/components/index.d.ts.map +1 -0
  94. package/ui/engine/components/index.js +109 -0
  95. package/ui/engine/components/index.js.map +1 -0
  96. package/ui/engine/cursor/index.d.ts +17 -0
  97. package/ui/engine/cursor/index.d.ts.map +1 -0
  98. package/ui/engine/cursor/index.js +41 -0
  99. package/ui/engine/cursor/index.js.map +1 -0
  100. package/ui/engine/diff/index.d.ts +27 -0
  101. package/ui/engine/diff/index.d.ts.map +1 -0
  102. package/ui/engine/diff/index.js +57 -0
  103. package/ui/engine/diff/index.js.map +1 -0
  104. package/ui/engine/events/index.d.ts +24 -0
  105. package/ui/engine/events/index.d.ts.map +1 -0
  106. package/ui/engine/events/index.js +60 -0
  107. package/ui/engine/events/index.js.map +1 -0
  108. package/ui/engine/focus/index.d.ts +25 -0
  109. package/ui/engine/focus/index.d.ts.map +1 -0
  110. package/ui/engine/focus/index.js +77 -0
  111. package/ui/engine/focus/index.js.map +1 -0
  112. package/ui/engine/frame/index.d.ts +48 -0
  113. package/ui/engine/frame/index.d.ts.map +1 -0
  114. package/ui/engine/frame/index.js +0 -0
  115. package/ui/engine/frame/index.js.map +1 -0
  116. package/ui/engine/index.d.ts +28 -0
  117. package/ui/engine/index.d.ts.map +1 -0
  118. package/ui/engine/index.js +28 -0
  119. package/ui/engine/index.js.map +1 -0
  120. package/ui/engine/input/index.d.ts +36 -0
  121. package/ui/engine/input/index.d.ts.map +1 -0
  122. package/ui/engine/input/index.js +224 -0
  123. package/ui/engine/input/index.js.map +1 -0
  124. package/ui/engine/layout/index.d.ts +42 -0
  125. package/ui/engine/layout/index.d.ts.map +1 -0
  126. package/ui/engine/layout/index.js +241 -0
  127. package/ui/engine/layout/index.js.map +1 -0
  128. package/ui/engine/renderer/index.d.ts +43 -0
  129. package/ui/engine/renderer/index.d.ts.map +1 -0
  130. package/ui/engine/renderer/index.js +619 -0
  131. package/ui/engine/renderer/index.js.map +1 -0
  132. package/ui/engine/scheduler/index.d.ts +22 -0
  133. package/ui/engine/scheduler/index.d.ts.map +1 -0
  134. package/ui/engine/scheduler/index.js +77 -0
  135. package/ui/engine/scheduler/index.js.map +1 -0
  136. package/ui/engine/screen/index.d.ts +39 -0
  137. package/ui/engine/screen/index.d.ts.map +1 -0
  138. package/ui/engine/screen/index.js +255 -0
  139. package/ui/engine/screen/index.js.map +1 -0
  140. package/ui/engine/terminal/index.d.ts +38 -0
  141. package/ui/engine/terminal/index.d.ts.map +1 -0
  142. package/ui/engine/terminal/index.js +104 -0
  143. package/ui/engine/terminal/index.js.map +1 -0
  144. package/ui/engine/testing/index.d.ts +27 -0
  145. package/ui/engine/testing/index.d.ts.map +1 -0
  146. package/ui/engine/testing/index.js +63 -0
  147. package/ui/engine/testing/index.js.map +1 -0
  148. package/ui/engine/theme/index.d.ts +27 -0
  149. package/ui/engine/theme/index.d.ts.map +1 -0
  150. package/ui/engine/theme/index.js +129 -0
  151. package/ui/engine/theme/index.js.map +1 -0
  152. package/ui/engine/utils/index.d.ts +12 -0
  153. package/ui/engine/utils/index.d.ts.map +1 -0
  154. package/ui/engine/utils/index.js +143 -0
  155. package/ui/engine/utils/index.js.map +1 -0
  156. package/ui/gate.d.ts +19 -0
  157. package/ui/gate.d.ts.map +1 -0
  158. package/ui/gate.js +36 -0
  159. package/ui/gate.js.map +1 -0
  160. package/ui/index.d.ts +18 -0
  161. package/ui/index.d.ts.map +1 -0
  162. package/ui/index.js +18 -0
  163. package/ui/index.js.map +1 -0
  164. package/ui/log-sink.d.ts +24 -0
  165. package/ui/log-sink.d.ts.map +1 -0
  166. package/ui/log-sink.js +35 -0
  167. package/ui/log-sink.js.map +1 -0
  168. package/ui/output.d.ts +14 -0
  169. package/ui/output.d.ts.map +1 -0
  170. package/ui/output.js +28 -0
  171. package/ui/output.js.map +1 -0
  172. package/ui/report.d.ts +30 -0
  173. package/ui/report.d.ts.map +1 -0
  174. package/ui/report.js +45 -0
  175. package/ui/report.js.map +1 -0
  176. package/ui/runner.d.ts +57 -0
  177. package/ui/runner.d.ts.map +1 -0
  178. package/ui/runner.js +119 -0
  179. package/ui/runner.js.map +1 -0
  180. package/ui/style.d.ts +24 -0
  181. package/ui/style.d.ts.map +1 -0
  182. package/ui/style.js +44 -0
  183. package/ui/style.js.map +1 -0
  184. package/ui/testing/fake-tty.d.ts +26 -0
  185. package/ui/testing/fake-tty.d.ts.map +1 -0
  186. package/ui/testing/fake-tty.js +61 -0
  187. package/ui/testing/fake-tty.js.map +1 -0
  188. package/ui/text-input.d.ts +30 -0
  189. package/ui/text-input.d.ts.map +1 -0
  190. package/ui/text-input.js +87 -0
  191. package/ui/text-input.js.map +1 -0
  192. package/ui/theme.d.ts +10 -0
  193. package/ui/theme.d.ts.map +1 -0
  194. package/ui/theme.js +20 -0
  195. package/ui/theme.js.map +1 -0
  196. package/utils/config.d.ts +48 -69
  197. package/utils/config.d.ts.map +1 -1
  198. package/utils/config.js +43 -7
  199. package/utils/config.js.map +1 -1
  200. package/utils/errors.d.ts +16 -0
  201. package/utils/errors.d.ts.map +1 -0
  202. package/utils/errors.js +31 -0
  203. package/utils/errors.js.map +1 -0
  204. package/utils/get-package-info.js +4 -4
  205. package/utils/get-package-info.js.map +1 -1
  206. package/utils/get-project-info.d.ts +30 -0
  207. package/utils/get-project-info.d.ts.map +1 -1
  208. package/utils/get-project-info.js +195 -6
  209. package/utils/get-project-info.js.map +1 -1
  210. package/utils/http-client.d.ts +8 -0
  211. package/utils/http-client.d.ts.map +1 -0
  212. package/utils/http-client.js +68 -0
  213. package/utils/http-client.js.map +1 -0
  214. package/utils/logger.d.ts +16 -1
  215. package/utils/logger.d.ts.map +1 -1
  216. package/utils/logger.js +104 -12
  217. package/utils/logger.js.map +1 -1
  218. package/utils/package-manager.d.ts +44 -1
  219. package/utils/package-manager.d.ts.map +1 -1
  220. package/utils/package-manager.js +210 -14
  221. package/utils/package-manager.js.map +1 -1
  222. package/utils/registry.d.ts +14 -2
  223. package/utils/registry.d.ts.map +1 -1
  224. package/utils/registry.js +52 -24
  225. package/utils/registry.js.map +1 -1
  226. package/utils/source-file.d.ts +40 -0
  227. package/utils/source-file.d.ts.map +1 -0
  228. package/utils/source-file.js +104 -0
  229. package/utils/source-file.js.map +1 -0
  230. package/utils/theme-selector.d.ts +1 -1
  231. package/utils/theme-selector.d.ts.map +1 -1
  232. package/utils/theme-selector.js +6 -6
  233. package/utils/theme-selector.js.map +1 -1
  234. package/utils/fetch-component.d.ts +0 -3
  235. package/utils/fetch-component.d.ts.map +0 -1
  236. package/utils/fetch-component.js +0 -75
  237. package/utils/fetch-component.js.map +0 -1
package/ui/index.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Superfície pública da UI da CLI.
3
+ *
4
+ * Os comandos importam daqui — nunca de `./engine` diretamente — para que a
5
+ * troca ou atualização da engine fique contida nesta camada.
6
+ */
7
+ export * from './engine/index.js';
8
+ export * from './blocks.js';
9
+ export * from './brand.js';
10
+ export * from './gate.js';
11
+ export * from './log-sink.js';
12
+ export * from './output.js';
13
+ export * from './report.js';
14
+ export * from './runner.js';
15
+ export * from './style.js';
16
+ export * from './text-input.js';
17
+ export * from './theme.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Sink de mensagens — desvia a saída do logger enquanto a tela interativa está
3
+ * montada.
4
+ *
5
+ * Em alt-screen, qualquer `console.log` disparado por um módulo interno
6
+ * (tsconfig-updater, theme-loader, package manager…) rasgaria o frame que a
7
+ * engine acabou de pintar. Durante a captura as mensagens ficam retidas aqui e
8
+ * são reemitidas no histórico do terminal depois do unmount, junto do resumo.
9
+ */
10
+ export type LogLevel = 'info' | 'warn' | 'error' | 'success' | 'debug';
11
+ export interface LogRecord {
12
+ readonly level: LogLevel;
13
+ readonly message: string;
14
+ }
15
+ /** Passa a reter as mensagens do logger em vez de escrevê-las no terminal. */
16
+ export declare function beginCapture(): void;
17
+ /** Encerra a captura e devolve o que foi retido, na ordem em que chegou. */
18
+ export declare function endCapture(): LogRecord[];
19
+ export declare function isCapturing(): boolean;
20
+ /** Retém uma mensagem. Devolve false quando não há captura ativa. */
21
+ export declare function capture(level: LogLevel, message: string): boolean;
22
+ /** Mensagens retidas até agora, sem encerrar a captura (para exibir na UI). */
23
+ export declare function captured(): readonly LogRecord[];
24
+ //# sourceMappingURL=log-sink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-sink.d.ts","sourceRoot":"","sources":["../../src/ui/log-sink.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAEvE,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAID,8EAA8E;AAC9E,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,IAAI,SAAS,EAAE,CAIxC;AAED,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED,qEAAqE;AACrE,wBAAgB,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAIjE;AAED,+EAA+E;AAC/E,wBAAgB,QAAQ,IAAI,SAAS,SAAS,EAAE,CAE/C"}
package/ui/log-sink.js ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Sink de mensagens — desvia a saída do logger enquanto a tela interativa está
3
+ * montada.
4
+ *
5
+ * Em alt-screen, qualquer `console.log` disparado por um módulo interno
6
+ * (tsconfig-updater, theme-loader, package manager…) rasgaria o frame que a
7
+ * engine acabou de pintar. Durante a captura as mensagens ficam retidas aqui e
8
+ * são reemitidas no histórico do terminal depois do unmount, junto do resumo.
9
+ */
10
+ let buffer = null;
11
+ /** Passa a reter as mensagens do logger em vez de escrevê-las no terminal. */
12
+ export function beginCapture() {
13
+ buffer = [];
14
+ }
15
+ /** Encerra a captura e devolve o que foi retido, na ordem em que chegou. */
16
+ export function endCapture() {
17
+ const captured = buffer ?? [];
18
+ buffer = null;
19
+ return captured;
20
+ }
21
+ export function isCapturing() {
22
+ return buffer !== null;
23
+ }
24
+ /** Retém uma mensagem. Devolve false quando não há captura ativa. */
25
+ export function capture(level, message) {
26
+ if (buffer === null)
27
+ return false;
28
+ buffer.push({ level, message });
29
+ return true;
30
+ }
31
+ /** Mensagens retidas até agora, sem encerrar a captura (para exibir na UI). */
32
+ export function captured() {
33
+ return buffer ?? [];
34
+ }
35
+ //# sourceMappingURL=log-sink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-sink.js","sourceRoot":"","sources":["../../src/ui/log-sink.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,IAAI,MAAM,GAAuB,IAAI,CAAC;AAEtC,8EAA8E;AAC9E,MAAM,UAAU,YAAY;IAC1B,MAAM,GAAG,EAAE,CAAC;AACd,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,UAAU;IACxB,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,CAAC;IAC9B,MAAM,GAAG,IAAI,CAAC;IACd,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,MAAM,KAAK,IAAI,CAAC;AACzB,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,OAAO,CAAC,KAAe,EAAE,OAAe;IACtD,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAClC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IAChC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,QAAQ;IACtB,OAAO,MAAM,IAAI,EAAE,CAAC;AACtB,CAAC"}
package/ui/output.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Saída em linha — a única porta por onde a CLI escreve texto solto no
3
+ * terminal, fora da tela interativa.
4
+ *
5
+ * Concentrar a escrita aqui garante que o logger, o resumo final e as
6
+ * mensagens reemitidas do sink usem exatamente a mesma marcação de nível e a
7
+ * mesma paleta.
8
+ */
9
+ import { type LogRecord } from './log-sink.js';
10
+ export declare function writeLine(text?: string): void;
11
+ export declare function formatRecord(record: LogRecord): string;
12
+ /** Reemite no histórico do terminal as mensagens retidas durante a tela. */
13
+ export declare function flushRecords(records: readonly LogRecord[]): void;
14
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/ui/output.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,eAAe,CAAC;AAW9D,wBAAgB,SAAS,CAAC,IAAI,SAAK,GAAG,IAAI,CAEzC;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAEtD;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,GAAG,IAAI,CAEhE"}
package/ui/output.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Saída em linha — a única porta por onde a CLI escreve texto solto no
3
+ * terminal, fora da tela interativa.
4
+ *
5
+ * Concentrar a escrita aqui garante que o logger, o resumo final e as
6
+ * mensagens reemitidas do sink usem exatamente a mesma marcação de nível e a
7
+ * mesma paleta.
8
+ */
9
+ import { style } from './style.js';
10
+ const MARKS = {
11
+ info: text => `${style.primary('›')} ${text}`,
12
+ success: text => `${style.success('✔')} ${text}`,
13
+ warn: text => `${style.warning('⚠')} ${text}`,
14
+ error: text => `${style.danger('✖')} ${text}`,
15
+ debug: text => style.dim(`[debug] ${text}`),
16
+ };
17
+ export function writeLine(text = '') {
18
+ process.stdout.write(`${text}\n`);
19
+ }
20
+ export function formatRecord(record) {
21
+ return MARKS[record.level](record.message);
22
+ }
23
+ /** Reemite no histórico do terminal as mensagens retidas durante a tela. */
24
+ export function flushRecords(records) {
25
+ for (const record of records)
26
+ writeLine(formatRecord(record));
27
+ }
28
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/ui/output.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,MAAM,KAAK,GAA+C;IACxD,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE;IAC7C,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE;IAChD,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE;IAC7C,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE;IAC7C,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;CAC5C,CAAC;AAEF,MAAM,UAAU,SAAS,CAAC,IAAI,GAAG,EAAE;IACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAiB;IAC5C,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC7C,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,YAAY,CAAC,OAA6B;IACxD,KAAK,MAAM,MAAM,IAAI,OAAO;QAAE,SAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;AAChE,CAAC"}
package/ui/report.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Resumo pós-execução — o que permanece no histórico depois do alt-screen.
3
+ *
4
+ * Ao sair da tela cheia, tudo que o wizard desenhou desaparece. O que o usuário
5
+ * precisa reter (o que foi escrito, o que rodar em seguida, o que deu errado)
6
+ * é reimpresso aqui, no fluxo normal do terminal, onde continua rolável e
7
+ * copiável depois que o comando termina.
8
+ */
9
+ import { type LogRecord } from './log-sink.js';
10
+ export type ReportStatus = 'success' | 'cancelled' | 'error';
11
+ export interface ReportCommand {
12
+ readonly command: string;
13
+ /** Trecho final destacado, como o `[component]` de `zard-cli add`. */
14
+ readonly argument?: string;
15
+ }
16
+ export interface Report {
17
+ readonly status: ReportStatus;
18
+ /** Uma frase: o desfecho do comando. */
19
+ readonly headline: string;
20
+ /** Itens do que foi efetivamente feito. */
21
+ readonly items?: readonly string[];
22
+ /** Texto de apoio, exibido em tom secundário. */
23
+ readonly notes?: readonly string[];
24
+ /** Próximos passos sugeridos. */
25
+ readonly commands?: readonly ReportCommand[];
26
+ /** Mensagens retidas enquanto a tela estava montada. */
27
+ readonly logs?: readonly LogRecord[];
28
+ }
29
+ export declare function printReport(report: Report): void;
30
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/ui/report.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,iDAAiD;IACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,iCAAiC;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IAC7C,wDAAwD;IACxD,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;CACtC;AAQD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA+BhD"}
package/ui/report.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Resumo pós-execução — o que permanece no histórico depois do alt-screen.
3
+ *
4
+ * Ao sair da tela cheia, tudo que o wizard desenhou desaparece. O que o usuário
5
+ * precisa reter (o que foi escrito, o que rodar em seguida, o que deu errado)
6
+ * é reimpresso aqui, no fluxo normal do terminal, onde continua rolável e
7
+ * copiável depois que o comando termina.
8
+ */
9
+ import { flushRecords, writeLine } from './output.js';
10
+ import { style } from './style.js';
11
+ const HEADLINE = {
12
+ success: text => `${style.success('✔')} ${style.bold(text)}`,
13
+ cancelled: text => `${style.warning('■')} ${style.bold(text)}`,
14
+ error: text => `${style.danger('✖')} ${style.bold(text)}`,
15
+ };
16
+ export function printReport(report) {
17
+ writeLine();
18
+ writeLine(HEADLINE[report.status](report.headline));
19
+ if (report.logs?.length) {
20
+ writeLine();
21
+ flushRecords(report.logs);
22
+ }
23
+ if (report.items?.length) {
24
+ writeLine();
25
+ for (const item of report.items)
26
+ writeLine(` ${style.success('✔')} ${item}`);
27
+ }
28
+ if (report.notes?.length) {
29
+ writeLine();
30
+ for (const note of report.notes)
31
+ writeLine(` ${style.muted(note)}`);
32
+ }
33
+ if (report.commands?.length) {
34
+ writeLine();
35
+ for (const { command, argument } of report.commands) {
36
+ const suffix = argument ? ` ${style.primary(argument)}` : '';
37
+ writeLine(` ${style.foreground(command)}${suffix}`);
38
+ }
39
+ }
40
+ // Duas linhas, não uma: o prompt do shell volta logo abaixo e, colado, o
41
+ // último comando sugerido parece parte dele.
42
+ writeLine();
43
+ writeLine();
44
+ }
45
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/ui/report.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAwBnC,MAAM,QAAQ,GAAmD;IAC/D,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;IAC5D,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;IAC9D,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;CAC1D,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,SAAS,EAAE,CAAC;IACZ,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEpD,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QACxB,SAAS,EAAE,CAAC;QACZ,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QACzB,SAAS,EAAE,CAAC;QACZ,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK;YAAE,SAAS,CAAC,KAAK,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QACzB,SAAS,EAAE,CAAC;QACZ,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK;YAAE,SAAS,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;QAC5B,SAAS,EAAE,CAAC;QACZ,KAAK,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpD,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,SAAS,CAAC,KAAK,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,6CAA6C;IAC7C,SAAS,EAAE,CAAC;IACZ,SAAS,EAAE,CAAC;AACd,CAAC"}
package/ui/runner.d.ts ADDED
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Runner — a ponte entre o loop de frames da engine e o fluxo async da CLI.
3
+ *
4
+ * Os comandos são sequenciais (`const config = await promptForConfig(...)`),
5
+ * enquanto a engine é um laço de render dirigido por eventos. O runner concilia
6
+ * os dois: monta a tela, entrega o controle ao `onKey`/`run` e resolve uma
7
+ * Promise quando o fluxo chama `done()`.
8
+ *
9
+ * Três invariantes valem para qualquer wizard:
10
+ * 1. o terminal é restaurado em todos os caminhos de saída — inclusive erro,
11
+ * SIGINT e crash do processo;
12
+ * 2. sem TTY a tela nunca é montada: quem chamou recebe NonInteractiveError e
13
+ * segue pelo caminho headless;
14
+ * 3. o que o logger escreveria durante a montagem fica retido no sink e é
15
+ * reemitido depois, para não rasgar o frame.
16
+ */
17
+ import { type KeyEvent, type Node, type Screen } from './engine/index.js';
18
+ import { type LogRecord } from './log-sink.js';
19
+ /** Sinaliza que o comando precisa seguir sem UI interativa (CI, pipe, --yes). */
20
+ export declare class NonInteractiveError extends Error {
21
+ constructor(message?: string);
22
+ }
23
+ /** O usuário abandonou o wizard (Ctrl+C ou um passo que cancela o fluxo). */
24
+ export declare class WizardCancelledError extends Error {
25
+ constructor(message?: string);
26
+ }
27
+ export interface WizardContext<T> {
28
+ /** Encerra a tela e resolve o wizard com este valor. */
29
+ done(value: T): void;
30
+ /** Encerra a tela e rejeita com WizardCancelledError. */
31
+ cancel(message?: string): void;
32
+ /** Agenda um novo frame depois de alterar o estado. */
33
+ refresh(): void;
34
+ /** Acesso à tela para casos que precisam do scheduler ou das capacidades. */
35
+ readonly screen: Screen;
36
+ }
37
+ export interface WizardOptions<T> {
38
+ /** View pura reconstruída a cada frame. */
39
+ view: () => Node;
40
+ /** Teclas que a view trata por conta própria. */
41
+ onKey?: (event: KeyEvent, ctx: WizardContext<T>) => void;
42
+ /**
43
+ * Trabalho assíncrono executado com a tela viva — instalar pacotes, escrever
44
+ * arquivos. A UI continua animando enquanto a promise não resolve.
45
+ */
46
+ run?: (ctx: WizardContext<T>) => Promise<void> | void;
47
+ fps?: number;
48
+ }
49
+ export interface WizardResult<T> {
50
+ readonly value: T;
51
+ /** Mensagens que o logger reteve enquanto a tela estava montada. */
52
+ readonly logs: readonly LogRecord[];
53
+ }
54
+ /** true quando dá para montar a tela interativa (entrada e saída são um TTY). */
55
+ export declare function isInteractive(): boolean;
56
+ export declare function runWizard<T>(options: WizardOptions<T>): Promise<WizardResult<T>>;
57
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/ui/runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAgB,KAAK,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAA4B,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAIzE,iFAAiF;AACjF,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,SAAsC;CAI1D;AAED,6EAA6E;AAC7E,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,SAAyB;CAI7C;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,wDAAwD;IACxD,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IACrB,yDAAyD;IACzD,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,uDAAuD;IACvD,OAAO,IAAI,IAAI,CAAC;IAChB,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,iDAAiD;IACjD,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACzD;;;OAGG;IACH,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,CAAC;CACrC;AAED,iFAAiF;AACjF,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAsB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAmFtF"}
package/ui/runner.js ADDED
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Runner — a ponte entre o loop de frames da engine e o fluxo async da CLI.
3
+ *
4
+ * Os comandos são sequenciais (`const config = await promptForConfig(...)`),
5
+ * enquanto a engine é um laço de render dirigido por eventos. O runner concilia
6
+ * os dois: monta a tela, entrega o controle ao `onKey`/`run` e resolve uma
7
+ * Promise quando o fluxo chama `done()`.
8
+ *
9
+ * Três invariantes valem para qualquer wizard:
10
+ * 1. o terminal é restaurado em todos os caminhos de saída — inclusive erro,
11
+ * SIGINT e crash do processo;
12
+ * 2. sem TTY a tela nunca é montada: quem chamou recebe NonInteractiveError e
13
+ * segue pelo caminho headless;
14
+ * 3. o que o logger escreveria durante a montagem fica retido no sink e é
15
+ * reemitido depois, para não rasgar o frame.
16
+ */
17
+ import { createScreen } from './engine/index.js';
18
+ import { beginCapture, endCapture } from './log-sink.js';
19
+ import { flushRecords } from './output.js';
20
+ import { zardTheme } from './theme.js';
21
+ /** Sinaliza que o comando precisa seguir sem UI interativa (CI, pipe, --yes). */
22
+ export class NonInteractiveError extends Error {
23
+ constructor(message = 'This terminal is not interactive.') {
24
+ super(message);
25
+ this.name = 'NonInteractiveError';
26
+ }
27
+ }
28
+ /** O usuário abandonou o wizard (Ctrl+C ou um passo que cancela o fluxo). */
29
+ export class WizardCancelledError extends Error {
30
+ constructor(message = 'Operation cancelled.') {
31
+ super(message);
32
+ this.name = 'WizardCancelledError';
33
+ }
34
+ }
35
+ /** true quando dá para montar a tela interativa (entrada e saída são um TTY). */
36
+ export function isInteractive() {
37
+ return Boolean(process.stdout.isTTY && process.stdin.isTTY);
38
+ }
39
+ export async function runWizard(options) {
40
+ if (!isInteractive())
41
+ throw new NonInteractiveError();
42
+ const screen = createScreen({
43
+ theme: zardTheme,
44
+ fps: options.fps ?? 30,
45
+ // O teardown é nosso: interceptamos Ctrl+C para encerrar o wizard com uma
46
+ // mensagem, em vez de matar o processo direto de dentro da engine.
47
+ handleExitSignals: false,
48
+ });
49
+ let settled = false;
50
+ let teardownDone = false;
51
+ const teardown = () => {
52
+ if (teardownDone)
53
+ return;
54
+ teardownDone = true;
55
+ screen.unmount();
56
+ process.off('exit', teardown);
57
+ process.off('SIGINT', onSignal);
58
+ process.off('SIGTERM', onSignal);
59
+ };
60
+ // Rede de segurança: se o processo morrer com a tela montada, o terminal
61
+ // ainda volta ao normal (cursor visível, sem raw mode, fora do alt-screen).
62
+ function onSignal() {
63
+ teardown();
64
+ process.exit(130);
65
+ }
66
+ process.on('exit', teardown);
67
+ process.on('SIGINT', onSignal);
68
+ process.on('SIGTERM', onSignal);
69
+ beginCapture();
70
+ try {
71
+ const value = await new Promise((resolve, reject) => {
72
+ const settle = (fn) => {
73
+ if (settled)
74
+ return;
75
+ settled = true;
76
+ teardown();
77
+ fn();
78
+ };
79
+ const ctx = {
80
+ done: v => settle(() => resolve(v)),
81
+ cancel: message => settle(() => reject(new WizardCancelledError(message))),
82
+ refresh: () => screen.scheduler.requestRender(),
83
+ screen,
84
+ };
85
+ screen.setView(options.view);
86
+ screen.onKey(event => {
87
+ if (settled)
88
+ return;
89
+ if (event.ctrl && (event.key === 'c' || event.key === 'd')) {
90
+ ctx.cancel();
91
+ return;
92
+ }
93
+ options.onKey?.(event, ctx);
94
+ });
95
+ screen.mount();
96
+ if (options.run) {
97
+ void (async () => {
98
+ try {
99
+ await options.run?.(ctx);
100
+ }
101
+ catch (error) {
102
+ settle(() => reject(error));
103
+ }
104
+ })();
105
+ }
106
+ });
107
+ return { value, logs: endCapture() };
108
+ }
109
+ catch (error) {
110
+ // Última chance de mostrar o que foi retido: a tela já caiu e quem trata o
111
+ // erro acima só verá a mensagem da exceção.
112
+ flushRecords(endCapture());
113
+ throw error;
114
+ }
115
+ finally {
116
+ teardown();
117
+ }
118
+ }
119
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/ui/runner.ts"],"names":[],"mappings":"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"}
package/ui/style.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Estilo para saída em linha — o que a CLI escreve fora da tela interativa.
3
+ *
4
+ * Substitui o chalk usando o vocabulário ANSI da própria engine, o que mantém
5
+ * uma única fonte de verdade de cor: os mesmos tokens do tema valem para o
6
+ * wizard em alt-screen e para o texto que sobra no histórico do terminal.
7
+ */
8
+ /** Reavalia a capacidade de cor — usado em teste, quando o stdout é trocado. */
9
+ export declare function resetColorLevel(): void;
10
+ export declare const style: {
11
+ primary: (text: string) => string;
12
+ success: (text: string) => string;
13
+ warning: (text: string) => string;
14
+ danger: (text: string) => string;
15
+ muted: (text: string) => string;
16
+ foreground: (text: string) => string;
17
+ bold: (text: string) => string;
18
+ dim: (text: string) => string;
19
+ /** Destaque de nome de arquivo, comando ou caminho dentro de uma frase. */
20
+ code: (text: string) => string;
21
+ };
22
+ /** true quando o terminal aceita as caixas e glifos Unicode da UI. */
23
+ export declare function supportsUnicode(): boolean;
24
+ //# sourceMappingURL=style.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/ui/style.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH,gFAAgF;AAChF,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAWD,eAAO,MAAM,KAAK;oBACA,MAAM;oBACN,MAAM;oBACN,MAAM;mBACP,MAAM;kBACP,MAAM;uBACD,MAAM;iBACZ,MAAM;gBACP,MAAM;IAClB,2EAA2E;iBAC9D,MAAM;CACpB,CAAC;AAEF,sEAAsE;AACtE,wBAAgB,eAAe,IAAI,OAAO,CAEzC"}
package/ui/style.js ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Estilo para saída em linha — o que a CLI escreve fora da tela interativa.
3
+ *
4
+ * Substitui o chalk usando o vocabulário ANSI da própria engine, o que mantém
5
+ * uma única fonte de verdade de cor: os mesmos tokens do tema valem para o
6
+ * wizard em alt-screen e para o texto que sobra no histórico do terminal.
7
+ */
8
+ import { Attr, createSgrBuilder, createTerminal } from './engine/index.js';
9
+ import { zardTheme } from './theme.js';
10
+ let cachedLevel = null;
11
+ /** Nível de cor do terminal atual, resolvido uma única vez por processo. */
12
+ function colorLevel() {
13
+ cachedLevel ??= createTerminal().caps.colors;
14
+ return cachedLevel;
15
+ }
16
+ /** Reavalia a capacidade de cor — usado em teste, quando o stdout é trocado. */
17
+ export function resetColorLevel() {
18
+ cachedLevel = null;
19
+ }
20
+ function paint(text, token, attrs = Attr.None) {
21
+ const level = colorLevel();
22
+ if (level === 'none' || (token === undefined && attrs === Attr.None))
23
+ return text;
24
+ const sgr = createSgrBuilder();
25
+ const fg = zardTheme.resolve(token, level);
26
+ return sgr.transition(fg, { kind: 'default' }, attrs) + text + sgr.reset();
27
+ }
28
+ export const style = {
29
+ primary: (text) => paint(text, 'primary'),
30
+ success: (text) => paint(text, 'success'),
31
+ warning: (text) => paint(text, 'warning'),
32
+ danger: (text) => paint(text, 'danger'),
33
+ muted: (text) => paint(text, 'muted'),
34
+ foreground: (text) => paint(text, 'foreground'),
35
+ bold: (text) => paint(text, undefined, Attr.Bold),
36
+ dim: (text) => paint(text, undefined, Attr.Dim),
37
+ /** Destaque de nome de arquivo, comando ou caminho dentro de uma frase. */
38
+ code: (text) => paint(text, 'primary', Attr.Bold),
39
+ };
40
+ /** true quando o terminal aceita as caixas e glifos Unicode da UI. */
41
+ export function supportsUnicode() {
42
+ return createTerminal().caps.unicode;
43
+ }
44
+ //# sourceMappingURL=style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style.js","sourceRoot":"","sources":["../../src/ui/style.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,cAAc,EAAmB,MAAM,mBAAmB,CAAC;AAC5F,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,IAAI,WAAW,GAAsB,IAAI,CAAC;AAE1C,4EAA4E;AAC5E,SAAS,UAAU;IACjB,WAAW,KAAK,cAAc,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;IAC7C,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,eAAe;IAC7B,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAED,SAAS,KAAK,CAAC,IAAY,EAAE,KAAyB,EAAE,QAAc,IAAI,CAAC,IAAI;IAC7E,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;IAC3B,IAAI,KAAK,KAAK,MAAM,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAElF,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAC;IAC/B,MAAM,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3C,OAAO,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,KAAK,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;AAC7E,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC;IACjD,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC;IACjD,OAAO,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC;IACjD,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC;IAC/C,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC;IAC7C,UAAU,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,YAAY,CAAC;IACvD,IAAI,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;IACzD,GAAG,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC;IACvD,2EAA2E;IAC3E,IAAI,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;CAC1D,CAAC;AAEF,sEAAsE;AACtE,MAAM,UAAU,eAAe;IAC7B,OAAO,cAAc,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;AACvC,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Um TTY simulado para exercitar wizards sem um terminal real.
3
+ *
4
+ * `runWizard` se recusa a montar fora de um TTY — é o que protege o usuário de
5
+ * uma UI de tela cheia num pipe. Para testar o wizard em si, então, stdout vira
6
+ * um buffer e stdin um emissor onde injetamos bytes de teclado.
7
+ */
8
+ export interface FakeTty {
9
+ /** Tudo o que foi escrito, concatenado. */
10
+ output(): string;
11
+ isRawMode(): boolean;
12
+ /** Injeta bytes de teclado — `\r` para enter, `\x1b[B` para seta abaixo. */
13
+ press(bytes: string): void;
14
+ restore(): void;
15
+ }
16
+ export declare const KEY: {
17
+ readonly enter: "\r";
18
+ readonly up: "\u001B[A";
19
+ readonly down: "\u001B[B";
20
+ readonly left: "\u001B[D";
21
+ readonly right: "\u001B[C";
22
+ readonly backspace: "";
23
+ readonly escape: "\u001B";
24
+ };
25
+ export declare function fakeTty(): FakeTty;
26
+ //# sourceMappingURL=fake-tty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake-tty.d.ts","sourceRoot":"","sources":["../../../src/ui/testing/fake-tty.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,WAAW,OAAO;IACtB,2CAA2C;IAC3C,MAAM,IAAI,MAAM,CAAC;IACjB,SAAS,IAAI,OAAO,CAAC;IACrB,4EAA4E;IAC5E,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,eAAO,MAAM,GAAG;;;;;;;;CAQN,CAAC;AAEX,wBAAgB,OAAO,IAAI,OAAO,CAiDjC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Um TTY simulado para exercitar wizards sem um terminal real.
3
+ *
4
+ * `runWizard` se recusa a montar fora de um TTY — é o que protege o usuário de
5
+ * uma UI de tela cheia num pipe. Para testar o wizard em si, então, stdout vira
6
+ * um buffer e stdin um emissor onde injetamos bytes de teclado.
7
+ */
8
+ import { EventEmitter } from 'node:events';
9
+ export const KEY = {
10
+ enter: '\r',
11
+ up: '\x1b[A',
12
+ down: '\x1b[B',
13
+ left: '\x1b[D',
14
+ right: '\x1b[C',
15
+ backspace: '\x7f',
16
+ escape: '\x1b',
17
+ };
18
+ export function fakeTty() {
19
+ const written = [];
20
+ const originalWrite = process.stdout.write.bind(process.stdout);
21
+ const originalStdin = process.stdin;
22
+ const descriptors = {
23
+ isTTY: Object.getOwnPropertyDescriptor(process.stdout, 'isTTY'),
24
+ columns: Object.getOwnPropertyDescriptor(process.stdout, 'columns'),
25
+ rows: Object.getOwnPropertyDescriptor(process.stdout, 'rows'),
26
+ };
27
+ process.stdout.write = ((chunk) => {
28
+ written.push(String(chunk));
29
+ return true;
30
+ });
31
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
32
+ Object.defineProperty(process.stdout, 'columns', { value: 80, configurable: true });
33
+ Object.defineProperty(process.stdout, 'rows', { value: 24, configurable: true });
34
+ const stdin = new EventEmitter();
35
+ let rawMode = false;
36
+ stdin.isTTY = true;
37
+ stdin.setRawMode = value => {
38
+ rawMode = value;
39
+ };
40
+ stdin.resume = () => undefined;
41
+ stdin.pause = () => undefined;
42
+ Object.defineProperty(process, 'stdin', { value: stdin, configurable: true });
43
+ return {
44
+ output: () => written.join(''),
45
+ isRawMode: () => rawMode,
46
+ press: bytes => {
47
+ stdin.emit('data', Buffer.from(bytes, 'utf8'));
48
+ },
49
+ restore: () => {
50
+ process.stdout.write = originalWrite;
51
+ Object.defineProperty(process, 'stdin', { value: originalStdin, configurable: true });
52
+ for (const [key, descriptor] of Object.entries(descriptors)) {
53
+ if (descriptor)
54
+ Object.defineProperty(process.stdout, key, descriptor);
55
+ else
56
+ delete process.stdout[key];
57
+ }
58
+ },
59
+ };
60
+ }
61
+ //# sourceMappingURL=fake-tty.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake-tty.js","sourceRoot":"","sources":["../../../src/ui/testing/fake-tty.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Edição de uma linha de texto num campo do wizard.
3
+ *
4
+ * O campo aceitava só duas coisas — digitar no fim e apagar de trás para a
5
+ * frente. Quem quisesse trocar o meio de um alias (`@/shared/components` para
6
+ * `@app/shared/components`) apertava as setas, não via nada acontecer e ficava
7
+ * sem saída a não ser apagar tudo e redigitar. Aqui o cursor é de verdade:
8
+ * anda, insere no meio, apaga para os dois lados.
9
+ */
10
+ import type { KeyEvent } from '../ui/engine/index.js';
11
+ export interface TextInput {
12
+ readonly value: string;
13
+ /** Posição do cursor, em caracteres — nunca fora de `[0, comprimento]`. */
14
+ readonly caret: number;
15
+ /**
16
+ * true enquanto o campo ainda mostra a sugestão e o usuário não tocou nela:
17
+ * a primeira tecla digitada substitui a sugestão inteira, em vez de emendar
18
+ * nela. Mover o cursor ou apagar assume o valor e passa a editá-lo.
19
+ */
20
+ readonly pristine: boolean;
21
+ }
22
+ export declare function startInput(value: string): TextInput;
23
+ /**
24
+ * Aplica uma tecla ao campo.
25
+ *
26
+ * Devolve `null` quando a tecla não é de edição — `enter` e `escape` pertencem
27
+ * ao fluxo do wizard, e é ele quem decide o que fazer com elas.
28
+ */
29
+ export declare function editInput(state: TextInput, event: KeyEvent): TextInput | null;
30
+ //# sourceMappingURL=text-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-input.d.ts","sourceRoot":"","sources":["../../src/ui/text-input.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAEnD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI,CA0C7E"}