@outfitter/cli 0.1.0-rc.2 → 0.1.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 (250) hide show
  1. package/README.md +21 -32
  2. package/dist/actions.d.ts +12 -1
  3. package/dist/actions.js +170 -3
  4. package/dist/borders/index.d.ts +3 -0
  5. package/dist/borders/index.js +13 -0
  6. package/dist/box/index.d.ts +4 -0
  7. package/dist/box/index.js +13 -0
  8. package/dist/cli.js +1 -1
  9. package/dist/colors/index.d.ts +3 -0
  10. package/dist/colors/index.js +18 -0
  11. package/dist/command.d.ts +40 -3
  12. package/dist/command.js +45 -3
  13. package/dist/demo/index.d.ts +78 -0
  14. package/dist/demo/index.js +148 -0
  15. package/dist/demo/registry.d.ts +7 -0
  16. package/dist/demo/registry.js +28 -0
  17. package/dist/demo/renderers/borders.d.ts +7 -0
  18. package/dist/demo/renderers/borders.js +17 -0
  19. package/dist/demo/renderers/box.d.ts +7 -0
  20. package/dist/demo/renderers/box.js +18 -0
  21. package/dist/demo/renderers/colors.d.ts +7 -0
  22. package/dist/demo/renderers/colors.js +18 -0
  23. package/dist/demo/renderers/indicators.d.ts +7 -0
  24. package/dist/demo/renderers/indicators.js +17 -0
  25. package/dist/demo/renderers/list.d.ts +7 -0
  26. package/dist/demo/renderers/list.js +19 -0
  27. package/dist/demo/renderers/markdown.d.ts +7 -0
  28. package/dist/demo/renderers/markdown.js +18 -0
  29. package/dist/demo/renderers/progress.d.ts +7 -0
  30. package/dist/demo/renderers/progress.js +17 -0
  31. package/dist/demo/renderers/spinner.d.ts +7 -0
  32. package/dist/demo/renderers/spinner.js +19 -0
  33. package/dist/demo/renderers/table.d.ts +7 -0
  34. package/dist/demo/renderers/table.js +19 -0
  35. package/dist/demo/renderers/text.d.ts +7 -0
  36. package/dist/demo/renderers/text.js +16 -0
  37. package/dist/demo/renderers/tree.d.ts +7 -0
  38. package/dist/demo/renderers/tree.js +18 -0
  39. package/dist/demo/section.d.ts +5 -0
  40. package/dist/demo/section.js +23 -0
  41. package/dist/demo/templates.d.ts +4 -0
  42. package/dist/demo/templates.js +10 -0
  43. package/dist/demo/types.d.ts +3 -0
  44. package/dist/demo/types.js +8 -0
  45. package/dist/index.d.ts +5 -8
  46. package/dist/index.js +9 -43
  47. package/dist/input.d.ts +163 -2
  48. package/dist/input.js +425 -11
  49. package/dist/list/index.d.ts +3 -0
  50. package/dist/list/index.js +9 -0
  51. package/dist/output.js +1 -1
  52. package/dist/pagination.d.ts +62 -2
  53. package/dist/pagination.js +84 -6
  54. package/dist/preset/full.d.ts +14 -0
  55. package/dist/preset/full.js +41 -0
  56. package/dist/preset/standard.d.ts +11 -0
  57. package/dist/preset/standard.js +30 -0
  58. package/dist/prompt/confirm.d.ts +4 -0
  59. package/dist/prompt/confirm.js +9 -0
  60. package/dist/prompt/group.d.ts +4 -0
  61. package/dist/prompt/group.js +9 -0
  62. package/dist/prompt/index.d.ts +7 -0
  63. package/dist/prompt/index.js +32 -0
  64. package/dist/prompt/select.d.ts +4 -0
  65. package/dist/prompt/select.js +11 -0
  66. package/dist/prompt/text.d.ts +4 -0
  67. package/dist/prompt/text.js +11 -0
  68. package/dist/prompt/types.d.ts +3 -0
  69. package/dist/prompt/types.js +8 -0
  70. package/dist/prompt/validators.d.ts +2 -0
  71. package/dist/prompt/validators.js +8 -0
  72. package/dist/render/borders.d.ts +2 -0
  73. package/dist/render/borders.js +15 -0
  74. package/dist/render/box.d.ts +3 -0
  75. package/dist/render/box.js +23 -0
  76. package/dist/render/colors.d.ts +1 -1
  77. package/dist/render/colors.js +6 -3
  78. package/dist/render/date.js +1 -1
  79. package/dist/render/format-relative.js +1 -1
  80. package/dist/render/format.js +1 -1
  81. package/dist/render/heading.d.ts +3 -0
  82. package/dist/render/heading.js +14 -0
  83. package/dist/render/index.d.ts +26 -7
  84. package/dist/render/index.js +160 -26
  85. package/dist/render/indicators.d.ts +2 -0
  86. package/dist/render/indicators.js +14 -0
  87. package/dist/render/json.js +1 -1
  88. package/dist/render/layout.d.ts +5 -0
  89. package/dist/render/layout.js +25 -0
  90. package/dist/render/list.d.ts +2 -2
  91. package/dist/render/list.js +2 -2
  92. package/dist/render/markdown.js +4 -4
  93. package/dist/render/progress.js +1 -1
  94. package/dist/render/separator.d.ts +3 -0
  95. package/dist/render/separator.js +14 -0
  96. package/dist/render/shapes.js +10 -9
  97. package/dist/render/spinner.d.ts +2 -0
  98. package/dist/render/spinner.js +12 -0
  99. package/dist/render/stack.d.ts +3 -0
  100. package/dist/render/stack.js +38 -0
  101. package/dist/render/table.d.ts +2 -1
  102. package/dist/render/table.js +6 -5
  103. package/dist/render/text.d.ts +1 -1
  104. package/dist/render/text.js +7 -4
  105. package/dist/render/tree.d.ts +2 -2
  106. package/dist/render/tree.js +5 -3
  107. package/dist/render/types.d.ts +2 -0
  108. package/dist/render/types.js +1 -0
  109. package/dist/shared/@outfitter/cli-0ggcy7fa.js +20 -0
  110. package/dist/shared/@outfitter/cli-0psys2vm.js +7 -0
  111. package/dist/shared/@outfitter/cli-1bghjef6.js +352 -0
  112. package/dist/shared/@outfitter/cli-1kwbnt86.d.ts +45 -0
  113. package/dist/shared/@outfitter/cli-2g8bx1aq.d.ts +50 -0
  114. package/dist/shared/@outfitter/cli-34fqr7bp.js +37 -0
  115. package/dist/shared/@outfitter/cli-3b7ed3rm.d.ts +97 -0
  116. package/dist/shared/@outfitter/cli-3dxmmy4c.d.ts +20 -0
  117. package/dist/shared/@outfitter/cli-3f12z5kf.d.ts +83 -0
  118. package/dist/shared/@outfitter/cli-3t2zaenc.d.ts +59 -0
  119. package/dist/shared/@outfitter/{cli-dds0qqvm.d.ts → cli-4cb5g831.d.ts} +2 -0
  120. package/dist/shared/@outfitter/cli-4w2a1rfy.d.ts +23 -0
  121. package/dist/shared/@outfitter/cli-4x6pqnez.js +20 -0
  122. package/dist/shared/@outfitter/cli-671sxkhj.js +146 -0
  123. package/dist/shared/@outfitter/cli-6bztk73z.d.ts +51 -0
  124. package/dist/shared/@outfitter/cli-6fxffp8k.js +1 -0
  125. package/dist/shared/@outfitter/cli-6j9qynm8.js +118 -0
  126. package/dist/shared/@outfitter/cli-6m988kh0.d.ts +61 -0
  127. package/dist/shared/@outfitter/cli-74ba31gz.js +134 -0
  128. package/dist/shared/@outfitter/cli-7gnrb8cr.js +214 -0
  129. package/dist/shared/@outfitter/cli-7nm6edvh.d.ts +17 -0
  130. package/dist/shared/@outfitter/cli-85fg2vr5.js +123 -0
  131. package/dist/shared/@outfitter/cli-8a8xrzhy.js +20 -0
  132. package/dist/shared/@outfitter/cli-8bwaw3pz.js +7 -0
  133. package/dist/shared/@outfitter/cli-8rx4g3s5.d.ts +41 -0
  134. package/dist/shared/@outfitter/cli-8xsmsbbd.d.ts +223 -0
  135. package/dist/shared/@outfitter/cli-96b2p4td.d.ts +56 -0
  136. package/dist/shared/@outfitter/cli-9khk3cbq.d.ts +190 -0
  137. package/dist/shared/@outfitter/cli-9mtjjykw.js +67 -0
  138. package/dist/shared/@outfitter/{cli-ag0w4pk0.js → cli-9nbyj2bt.js} +60 -21
  139. package/dist/shared/@outfitter/{cli-azzk8a1d.js → cli-afhjqmg3.js} +7 -3
  140. package/dist/shared/@outfitter/cli-an9j0h80.js +117 -0
  141. package/dist/shared/@outfitter/cli-ay411nbr.js +122 -0
  142. package/dist/shared/@outfitter/cli-b0tzqgnf.d.ts +132 -0
  143. package/dist/shared/@outfitter/cli-b5c2k0d7.js +39 -0
  144. package/dist/shared/@outfitter/cli-b5epywry.js +1 -0
  145. package/dist/shared/@outfitter/cli-bcmcaz1b.js +23 -0
  146. package/dist/shared/@outfitter/cli-bf3vma4q.js +61 -0
  147. package/dist/shared/@outfitter/cli-cf1xexgn.d.ts +53 -0
  148. package/dist/shared/@outfitter/cli-cs45xd6q.js +59 -0
  149. package/dist/shared/@outfitter/cli-d7jpshq5.d.ts +128 -0
  150. package/dist/shared/@outfitter/{cli-jbj78ac5.js → cli-d9ad0rqj.js} +6 -1
  151. package/dist/shared/@outfitter/cli-daw296mv.js +61 -0
  152. package/dist/shared/@outfitter/cli-e5ms1y0x.d.ts +91 -0
  153. package/dist/shared/@outfitter/cli-e73v3qqy.d.ts +93 -0
  154. package/dist/shared/@outfitter/cli-en6zn6sj.js +1 -0
  155. package/dist/shared/@outfitter/cli-ep2cvtk8.js +48 -0
  156. package/dist/shared/@outfitter/cli-f75h8e94.js +7 -0
  157. package/dist/shared/@outfitter/cli-fakncnjp.d.ts +106 -0
  158. package/dist/shared/@outfitter/cli-feb5j90n.js +94 -0
  159. package/dist/shared/@outfitter/cli-h20jc0bs.d.ts +66 -0
  160. package/dist/shared/@outfitter/cli-hnpbqmc8.d.ts +328 -0
  161. package/dist/shared/@outfitter/cli-j4n8gaf3.js +95 -0
  162. package/dist/shared/@outfitter/cli-jejfypgf.js +85 -0
  163. package/dist/shared/@outfitter/{cli-wqc652mx.js → cli-jhcdwvpn.js} +8 -8
  164. package/dist/shared/@outfitter/{cli-v9mjsvjh.js → cli-jjemfdta.js} +13 -46
  165. package/dist/shared/@outfitter/cli-kc84wmch.js +267 -0
  166. package/dist/shared/@outfitter/cli-ktqme80d.js +7 -0
  167. package/dist/shared/@outfitter/cli-mq0jp15z.js +1 -0
  168. package/dist/shared/@outfitter/cli-mymyavvj.d.ts +26 -0
  169. package/dist/shared/@outfitter/cli-n17gt1dz.js +19 -0
  170. package/dist/shared/@outfitter/cli-n9dbh0hp.js +51 -0
  171. package/dist/shared/@outfitter/cli-nvvc92c8.js +128 -0
  172. package/dist/shared/@outfitter/cli-p1m5dhrs.js +169 -0
  173. package/dist/shared/@outfitter/cli-p38sfxyk.js +25 -0
  174. package/dist/shared/@outfitter/cli-p3dqm1vd.js +22 -0
  175. package/dist/shared/@outfitter/cli-p9j1phge.js +20 -0
  176. package/dist/shared/@outfitter/cli-pkxmzavm.js +62 -0
  177. package/dist/shared/@outfitter/cli-q8r6jarq.d.ts +24 -0
  178. package/dist/shared/@outfitter/{cli-2y3kxew8.d.ts → cli-qj83y5wj.d.ts} +22 -9
  179. package/dist/shared/@outfitter/cli-qjfc3j11.d.ts +112 -0
  180. package/dist/shared/@outfitter/cli-qp4cbhqr.js +70 -0
  181. package/dist/shared/@outfitter/cli-s0kkx9m1.d.ts +164 -0
  182. package/dist/shared/@outfitter/cli-snxj55n6.js +43 -0
  183. package/dist/shared/@outfitter/cli-swwxvjvm.d.ts +24 -0
  184. package/dist/shared/@outfitter/cli-sx67mmfx.d.ts +98 -0
  185. package/dist/shared/@outfitter/cli-tarpsa8a.js +30 -0
  186. package/dist/shared/@outfitter/cli-thvzhjd1.js +126 -0
  187. package/dist/shared/@outfitter/cli-tqewy503.d.ts +36 -0
  188. package/dist/shared/@outfitter/cli-tvw1xrdj.js +20 -0
  189. package/dist/shared/@outfitter/cli-v1tzwxkt.js +32 -0
  190. package/dist/shared/@outfitter/cli-vd60dj65.js +1 -0
  191. package/dist/shared/@outfitter/cli-vp88gxev.js +279 -0
  192. package/dist/shared/@outfitter/cli-vstbkzky.d.ts +74 -0
  193. package/dist/shared/@outfitter/cli-vtg0sqk2.d.ts +54 -0
  194. package/dist/shared/@outfitter/cli-w5y3xepp.js +20 -0
  195. package/dist/shared/@outfitter/cli-x4cavvc0.js +1 -0
  196. package/dist/shared/@outfitter/cli-xep6v2c0.js +52 -0
  197. package/dist/shared/@outfitter/cli-xg5y5fhk.js +86 -0
  198. package/dist/shared/@outfitter/{cli-n51t773m.d.ts → cli-xsaheemc.d.ts} +44 -4
  199. package/dist/shared/@outfitter/cli-xvqtqjxk.js +82 -0
  200. package/dist/shared/@outfitter/cli-y25tt8nc.d.ts +48 -0
  201. package/dist/streaming/ansi.d.ts +2 -0
  202. package/dist/streaming/ansi.js +8 -0
  203. package/dist/streaming/index.d.ts +4 -0
  204. package/dist/streaming/index.js +17 -0
  205. package/dist/streaming/spinner.d.ts +3 -0
  206. package/dist/streaming/spinner.js +10 -0
  207. package/dist/streaming/writer.d.ts +2 -0
  208. package/dist/streaming/writer.js +9 -0
  209. package/dist/table/index.d.ts +4 -0
  210. package/dist/table/index.js +13 -0
  211. package/dist/terminal/detection.js +5 -2
  212. package/dist/terminal/index.js +6 -2
  213. package/dist/theme/context.d.ts +9 -0
  214. package/dist/theme/context.js +14 -0
  215. package/dist/theme/create.d.ts +8 -0
  216. package/dist/theme/create.js +12 -0
  217. package/dist/theme/index.d.ts +17 -0
  218. package/dist/theme/index.js +42 -0
  219. package/dist/theme/presets/bold.d.ts +8 -0
  220. package/dist/theme/presets/bold.js +12 -0
  221. package/dist/theme/presets/default.d.ts +8 -0
  222. package/dist/theme/presets/default.js +11 -0
  223. package/dist/theme/presets/index.d.ts +12 -0
  224. package/dist/theme/presets/index.js +24 -0
  225. package/dist/theme/presets/minimal.d.ts +8 -0
  226. package/dist/theme/presets/minimal.js +12 -0
  227. package/dist/theme/presets/rounded.d.ts +8 -0
  228. package/dist/theme/presets/rounded.js +12 -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/dist/types.js +1 -1
  236. package/package.json +168 -54
  237. package/dist/shared/@outfitter/cli-2vs2gxa8.js +0 -429
  238. package/dist/shared/@outfitter/cli-2yq94zst.d.ts +0 -39
  239. package/dist/shared/@outfitter/cli-6xc869x1.js +0 -26
  240. package/dist/shared/@outfitter/cli-7km1e58p.js +0 -85
  241. package/dist/shared/@outfitter/cli-8r0bnyyx.js +0 -43
  242. package/dist/shared/@outfitter/cli-afecwfrn.d.ts +0 -13
  243. package/dist/shared/@outfitter/cli-bt423m6y.js +0 -4
  244. package/dist/shared/@outfitter/cli-d4fegbad.d.ts +0 -66
  245. package/dist/shared/@outfitter/cli-e0ecw3x1.js +0 -64
  246. package/dist/shared/@outfitter/cli-fheaaa6b.js +0 -25
  247. package/dist/shared/@outfitter/cli-j361wp3g.d.ts +0 -41
  248. package/dist/shared/@outfitter/cli-p0m2fc51.js +0 -172
  249. package/dist/shared/@outfitter/cli-tyajr8qa.d.ts +0 -63
  250. package/dist/shared/@outfitter/cli-zs6jy1am.d.ts +0 -164
@@ -0,0 +1,352 @@
1
+ // @bun
2
+ import {
3
+ TREE_GUIDES
4
+ } from "./cli-b5c2k0d7.js";
5
+ import {
6
+ getIndicator,
7
+ isUnicodeSupported
8
+ } from "./cli-p1m5dhrs.js";
9
+ import {
10
+ joinHorizontal,
11
+ joinVertical
12
+ } from "./cli-671sxkhj.js";
13
+ import {
14
+ exports_box,
15
+ init_box,
16
+ renderBox
17
+ } from "./cli-vp88gxev.js";
18
+ import {
19
+ getStringWidth,
20
+ init_text
21
+ } from "./cli-jjemfdta.js";
22
+ import {
23
+ __toCommonJS
24
+ } from "./cli-v1tzwxkt.js";
25
+
26
+ // packages/cli/src/render/stack.ts
27
+ init_box();
28
+ init_text();
29
+ var DELIMITERS = {
30
+ space: { unicode: " ", fallback: " " },
31
+ bullet: { unicode: "\u2022", fallback: "*" },
32
+ dot: { unicode: "\xB7", fallback: "." },
33
+ pipe: { unicode: "\u2502", fallback: "|" },
34
+ arrow: { unicode: "\u2192", fallback: "->" },
35
+ slash: { unicode: "/", fallback: "/" },
36
+ colon: { unicode: ":", fallback: ":" }
37
+ };
38
+ function getDelimiter(name, forceUnicode) {
39
+ const delimiter = DELIMITERS[name];
40
+ const useUnicode = forceUnicode ?? isUnicodeSupported();
41
+ return useUnicode ? delimiter.unicode : delimiter.fallback;
42
+ }
43
+ function getMarker(nameOrChar, forceUnicode) {
44
+ const knownMarkers = [
45
+ "circleDot",
46
+ "circleOutline",
47
+ "circle",
48
+ "checkbox",
49
+ "checkboxChecked",
50
+ "pointer",
51
+ "dash"
52
+ ];
53
+ if (knownMarkers.includes(nameOrChar)) {
54
+ return getIndicator("marker", nameOrChar, forceUnicode);
55
+ }
56
+ return nameOrChar;
57
+ }
58
+ var DEFAULT_STACK_THEME = {
59
+ markers: {
60
+ default: "circleOutline",
61
+ current: "circleDot",
62
+ focused: "pointer",
63
+ checked: "checkboxChecked",
64
+ disabled: "dash"
65
+ },
66
+ delimiter: "bullet",
67
+ guide: "single"
68
+ };
69
+ function isRenderable(value) {
70
+ return typeof value === "object" && value !== null && "output" in value && "width" in value && "height" in value && typeof value.output === "string" && typeof value.width === "number" && typeof value.height === "number";
71
+ }
72
+ function isDelimiterName(value) {
73
+ return value in DELIMITERS;
74
+ }
75
+ function resolveDelimiter(delimiter) {
76
+ if (delimiter === undefined) {
77
+ return getDelimiter("space");
78
+ }
79
+ if (isDelimiterName(delimiter)) {
80
+ return getDelimiter(delimiter);
81
+ }
82
+ return delimiter;
83
+ }
84
+ function normalizeItem(item) {
85
+ if (typeof item === "string") {
86
+ return { content: item };
87
+ }
88
+ if (isRenderable(item)) {
89
+ return { content: item.output };
90
+ }
91
+ return item;
92
+ }
93
+ function shouldShowMarker(item) {
94
+ return item.state !== undefined || item.marker !== undefined;
95
+ }
96
+ function resolveMarker(item, theme) {
97
+ if (!shouldShowMarker(item)) {
98
+ return { marker: "", show: false };
99
+ }
100
+ if (item.marker !== undefined) {
101
+ return { marker: getMarker(item.marker), show: true };
102
+ }
103
+ const state = item.state ?? "default";
104
+ const markerName = theme.markers[state];
105
+ return { marker: getMarker(markerName), show: true };
106
+ }
107
+ function getContentLines(content) {
108
+ if (typeof content === "string") {
109
+ return content.split(`
110
+ `);
111
+ }
112
+ return content;
113
+ }
114
+ function applyStyle(content, style) {
115
+ return style ? style(content) : content;
116
+ }
117
+ function hstack(items, options) {
118
+ if (items.length === 0)
119
+ return "";
120
+ const normalizedItems = items.map(normalizeItem);
121
+ const delimiter = resolveDelimiter(options?.delimiter);
122
+ const gap = options?.gap ?? 0;
123
+ const align = options?.align ?? "top";
124
+ const gapStr = " ".repeat(gap);
125
+ const fullDelimiter = `${gapStr}${delimiter}${gapStr}`;
126
+ const contentStrings = normalizedItems.map((item) => {
127
+ const lines = getContentLines(item.content);
128
+ const styledLines = lines.map((line) => applyStyle(line, item.style));
129
+ return styledLines.join(`
130
+ `);
131
+ });
132
+ const isMultiLine = contentStrings.some((s) => s.includes(`
133
+ `));
134
+ if (!isMultiLine) {
135
+ return contentStrings.join(fullDelimiter);
136
+ }
137
+ const blocks = contentStrings.map((content, idx) => {
138
+ if (idx === contentStrings.length - 1) {
139
+ return content;
140
+ }
141
+ const lines = content.split(`
142
+ `);
143
+ return lines.map((line) => line + fullDelimiter).join(`
144
+ `);
145
+ });
146
+ return joinHorizontal(blocks, { gap: 0, align });
147
+ }
148
+ function createHStack(items, options) {
149
+ const output = hstack(items, options);
150
+ const lines = output.split(`
151
+ `);
152
+ const width = Math.max(...lines.map(getStringWidth));
153
+ return {
154
+ output,
155
+ width,
156
+ height: lines.length
157
+ };
158
+ }
159
+ function vstackItem(header, body, options) {
160
+ const content = body && body.length > 0 ? [header, ...body] : [header];
161
+ const result = {
162
+ content,
163
+ state: options?.state ?? "default"
164
+ };
165
+ if (options?.marker !== undefined) {
166
+ result.marker = options.marker;
167
+ }
168
+ if (options?.compact !== undefined) {
169
+ result.compact = options.compact;
170
+ }
171
+ if (options?.style !== undefined) {
172
+ result.style = options.style;
173
+ }
174
+ return result;
175
+ }
176
+ var GUIDE_CHARS = {
177
+ single: "\u2502",
178
+ heavy: "\u2503",
179
+ double: "\u2551",
180
+ rounded: "\u2502"
181
+ };
182
+ function renderPlainMode(items, theme, gap) {
183
+ const lines = [];
184
+ for (const item of items) {
185
+ const { marker, show } = resolveMarker(item, theme);
186
+ const contentLines = getContentLines(item.content);
187
+ const prefix = show ? `${marker} ` : "";
188
+ const firstLine = contentLines[0];
189
+ if (firstLine !== undefined) {
190
+ const styled = applyStyle(firstLine, item.style);
191
+ lines.push(`${prefix}${styled}`);
192
+ }
193
+ const indent = show ? " " : "";
194
+ for (let i = 1;i < contentLines.length; i++) {
195
+ const line = contentLines[i];
196
+ if (line !== undefined) {
197
+ const styled = applyStyle(line, item.style);
198
+ lines.push(`${indent}${styled}`);
199
+ }
200
+ }
201
+ }
202
+ return joinVertical(lines, { gap });
203
+ }
204
+ function renderGuideMode(items, theme, guideStyle) {
205
+ const lines = [];
206
+ const guideChar = GUIDE_CHARS[guideStyle];
207
+ for (let itemIdx = 0;itemIdx < items.length; itemIdx++) {
208
+ const item = items[itemIdx];
209
+ if (!item)
210
+ continue;
211
+ const { marker, show } = resolveMarker(item, theme);
212
+ const contentLines = getContentLines(item.content);
213
+ const isLastItem = itemIdx === items.length - 1;
214
+ const displayMarker = show ? marker : getMarker(theme.markers.default);
215
+ const firstLine = contentLines[0];
216
+ if (firstLine !== undefined) {
217
+ const styled = applyStyle(firstLine, item.style);
218
+ lines.push(`${displayMarker} ${styled}`);
219
+ }
220
+ for (let i = 1;i < contentLines.length; i++) {
221
+ const line = contentLines[i];
222
+ if (line !== undefined) {
223
+ const styled = applyStyle(line, item.style);
224
+ lines.push(`${guideChar} ${styled}`);
225
+ }
226
+ }
227
+ if (!isLastItem) {
228
+ lines.push(guideChar);
229
+ }
230
+ }
231
+ return lines.join(`
232
+ `);
233
+ }
234
+ function renderTreeMode(items, guideStyle) {
235
+ const lines = [];
236
+ const guides = TREE_GUIDES[guideStyle];
237
+ for (let itemIdx = 0;itemIdx < items.length; itemIdx++) {
238
+ const item = items[itemIdx];
239
+ if (!item)
240
+ continue;
241
+ const contentLines = getContentLines(item.content);
242
+ const isLastItem = itemIdx === items.length - 1;
243
+ const connector = isLastItem ? guides.end : guides.fork;
244
+ const continuation = isLastItem ? " " : guides.vertical;
245
+ const firstLine = contentLines[0];
246
+ if (firstLine !== undefined) {
247
+ const styled = applyStyle(firstLine, item.style);
248
+ lines.push(`${connector}${styled}`);
249
+ }
250
+ for (let i = 1;i < contentLines.length; i++) {
251
+ const line = contentLines[i];
252
+ if (line !== undefined) {
253
+ const styled = applyStyle(line, item.style);
254
+ lines.push(`${continuation}${styled}`);
255
+ }
256
+ }
257
+ }
258
+ return lines.join(`
259
+ `);
260
+ }
261
+ function renderBoxedMode(items, gap) {
262
+ const boxes = [];
263
+ for (const item of items) {
264
+ const contentLines = getContentLines(item.content);
265
+ const styled = contentLines.map((line) => applyStyle(line, item.style));
266
+ boxes.push(renderBox(styled));
267
+ }
268
+ return joinVertical(boxes, { gap });
269
+ }
270
+ function renderCompactMode(items, theme) {
271
+ const lines = [];
272
+ for (const item of items) {
273
+ const { marker, show } = resolveMarker(item, theme);
274
+ const displayMarker = show ? marker : getMarker(theme.markers.default);
275
+ let displayText;
276
+ if (item.compact) {
277
+ displayText = item.compact;
278
+ } else {
279
+ const contentLines = getContentLines(item.content);
280
+ displayText = contentLines[0] ?? "";
281
+ }
282
+ const styled = applyStyle(displayText, item.style);
283
+ lines.push(`${displayMarker} ${styled}`);
284
+ }
285
+ return lines.join(`
286
+ `);
287
+ }
288
+ function vstack(items, options) {
289
+ if (items.length === 0)
290
+ return "";
291
+ const normalizedItems = items.map(normalizeItem);
292
+ const mode = options?.mode ?? "guide";
293
+ const gap = options?.gap ?? 0;
294
+ const theme = {
295
+ ...DEFAULT_STACK_THEME,
296
+ ...options?.theme,
297
+ markers: {
298
+ ...DEFAULT_STACK_THEME.markers,
299
+ ...options?.theme?.markers
300
+ }
301
+ };
302
+ const guideStyle = options?.guide ?? theme.guide ?? "single";
303
+ switch (mode) {
304
+ case "plain":
305
+ return renderPlainMode(normalizedItems, theme, gap);
306
+ case "guide":
307
+ return renderGuideMode(normalizedItems, theme, guideStyle);
308
+ case "tree":
309
+ return renderTreeMode(normalizedItems, guideStyle);
310
+ case "boxed":
311
+ return renderBoxedMode(normalizedItems, gap);
312
+ case "compact":
313
+ return renderCompactMode(normalizedItems, theme);
314
+ default: {
315
+ const _exhaustive = mode;
316
+ return _exhaustive;
317
+ }
318
+ }
319
+ }
320
+ function createVStack(items, options) {
321
+ const output = vstack(items, options);
322
+ const lines = output.split(`
323
+ `);
324
+ const width = Math.max(...lines.map(getStringWidth), 0);
325
+ return {
326
+ output,
327
+ width,
328
+ height: lines.length
329
+ };
330
+ }
331
+ function boxify(content, options) {
332
+ const { createBox: makeBox } = (init_box(), __toCommonJS(exports_box));
333
+ const boxContent = isRenderable(content) ? content.output : content;
334
+ const boxOptions = {
335
+ border: options?.border ?? "single"
336
+ };
337
+ if (options?.title !== undefined) {
338
+ boxOptions.title = options.title;
339
+ }
340
+ if (options?.padding !== undefined) {
341
+ boxOptions.padding = options.padding;
342
+ }
343
+ return makeBox(boxContent, boxOptions);
344
+ }
345
+ function unbox(content) {
346
+ if (isRenderable(content)) {
347
+ return content.output;
348
+ }
349
+ return content;
350
+ }
351
+
352
+ export { DELIMITERS, getDelimiter, getMarker, DEFAULT_STACK_THEME, isRenderable, hstack, createHStack, vstackItem, vstack, createVStack, boxify, unbox };
@@ -0,0 +1,45 @@
1
+ import { WidthMode } from "./cli-2g8bx1aq";
2
+ /**
3
+ * Width mode for separators.
4
+ *
5
+ * Separators only support "text", "full", and numeric widths.
6
+ * Container-relative modes require context, which separators don't use.
7
+ */
8
+ type SeparatorWidthMode = Extract<WidthMode, "text" | "full" | number>;
9
+ /**
10
+ * Separator style for dividers.
11
+ * Single characters repeat to fill width.
12
+ * Two-character patterns (like "- ") alternate to create dashed effect.
13
+ */
14
+ type DividerStyle = "─" | "━" | "═" | "- " | "· ";
15
+ /**
16
+ * Options for rendering a separator.
17
+ */
18
+ interface SeparatorOptions {
19
+ /** Separator style (default: "─") */
20
+ style?: DividerStyle;
21
+ /** Width mode (default: 40) */
22
+ width?: SeparatorWidthMode;
23
+ }
24
+ /**
25
+ * Renders a horizontal separator line.
26
+ *
27
+ * @param options - Rendering options
28
+ * @returns Formatted separator string
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * import { renderSeparator } from "@outfitter/cli/render";
33
+ *
34
+ * console.log(renderSeparator());
35
+ * // ────────────────────────────────────────
36
+ *
37
+ * console.log(renderSeparator({ style: "━", width: 20 }));
38
+ * // ━━━━━━━━━━━━━━━━━━━━
39
+ *
40
+ * console.log(renderSeparator({ style: "- ", width: 20 }));
41
+ * // - - - - - - - - - -
42
+ * ```
43
+ */
44
+ declare function renderSeparator(options?: SeparatorOptions): string;
45
+ export { DividerStyle, SeparatorOptions, renderSeparator };
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Shared types for render utilities.
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ /**
7
+ * Width mode for layout calculations.
8
+ *
9
+ * - `"text"` - Fit to text content (returns 0 to indicate no width constraint)
10
+ * - `"full"` - Full terminal width
11
+ * - `"container"` - Available container width (requires LayoutContext)
12
+ * - `number` - Fixed character width
13
+ * - `"${number}%"` - Percentage of container/terminal width
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * import { resolveWidth } from "@outfitter/cli/render";
18
+ *
19
+ * resolveWidth("full"); // → terminal width (e.g., 120)
20
+ * resolveWidth(50); // → 50
21
+ * resolveWidth("50%"); // → half of terminal width
22
+ * resolveWidth("container", ctx); // → context width
23
+ * ```
24
+ */
25
+ type WidthMode = "text" | "full" | "container" | number | `${number}%`;
26
+ /**
27
+ * Layout context for container-aware width calculations.
28
+ *
29
+ * Provides width information to nested components so they can size
30
+ * themselves relative to their container. Create contexts with
31
+ * `createLayoutContext()` and pass them through component hierarchies.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * import { createLayoutContext, resolveWidth } from "@outfitter/cli/render";
36
+ *
37
+ * const outerCtx = createLayoutContext({ width: 80, padding: 1 });
38
+ * // outerCtx.width = 76 (80 - 4 overhead)
39
+ *
40
+ * const innerWidth = resolveWidth("50%", outerCtx);
41
+ * // innerWidth = 38 (50% of 76)
42
+ * ```
43
+ */
44
+ interface LayoutContext {
45
+ /** Available content width in characters */
46
+ readonly width: number;
47
+ /** Parent context for chained calculations */
48
+ readonly parent?: LayoutContext;
49
+ }
50
+ export { WidthMode, LayoutContext };
@@ -0,0 +1,37 @@
1
+ // @bun
2
+ import {
3
+ renderHeading
4
+ } from "./cli-xvqtqjxk.js";
5
+ import {
6
+ joinVertical
7
+ } from "./cli-671sxkhj.js";
8
+
9
+ // packages/cli/src/demo/section.ts
10
+ function demoSection(title, options) {
11
+ return renderHeading(title, {
12
+ separator: options?.separator ?? "\u2500",
13
+ case: options?.case ?? "title"
14
+ });
15
+ }
16
+ function demoSubsection(title, options) {
17
+ return renderHeading(title, {
18
+ separator: options?.separator ?? "\u2500",
19
+ case: options?.case ?? "title"
20
+ });
21
+ }
22
+ function codeBlock(lines, show = true) {
23
+ if (!show)
24
+ return [];
25
+ return lines;
26
+ }
27
+ function description(text, theme, show = true) {
28
+ if (!show)
29
+ return [];
30
+ return [theme.muted(text)];
31
+ }
32
+ function demoContent(blocks, gap = 1) {
33
+ const filtered = blocks.filter((b) => b !== "");
34
+ return joinVertical(filtered, { gap });
35
+ }
36
+
37
+ export { demoSection, demoSubsection, codeBlock, description, demoContent };
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Tree rendering utilities.
3
+ *
4
+ * Renders hierarchical data as ASCII trees with box-drawing characters.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ /**
9
+ * Available tree guide styles.
10
+ *
11
+ * - `single`: Standard Unicode box-drawing (default)
12
+ * - `heavy`: Thick/bold box-drawing characters
13
+ * - `double`: Double-line box-drawing characters
14
+ * - `rounded`: Rounded corners (╰ instead of └)
15
+ */
16
+ type TreeGuideStyle = "single" | "heavy" | "double" | "rounded";
17
+ /**
18
+ * Tree guide character sets for different visual styles.
19
+ */
20
+ declare const TREE_GUIDES: Record<TreeGuideStyle, {
21
+ vertical: string;
22
+ fork: string;
23
+ end: string;
24
+ }>;
25
+ /**
26
+ * Options for customizing tree rendering.
27
+ */
28
+ interface TreeOptions {
29
+ /**
30
+ * Guide style for tree branches.
31
+ * @default "single"
32
+ */
33
+ guide?: TreeGuideStyle;
34
+ /**
35
+ * Maximum depth to render (1 = root children only).
36
+ * @default undefined (unlimited)
37
+ */
38
+ maxDepth?: number;
39
+ /**
40
+ * Custom function to render node labels.
41
+ * Receives the key, value, and current depth.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * renderLabel: (key, value, depth) => {
46
+ * if (value && typeof value === "object") {
47
+ * return `📁 ${key}/`;
48
+ * }
49
+ * return `📄 ${key}`;
50
+ * }
51
+ * ```
52
+ */
53
+ renderLabel?: (key: string, value: unknown, depth: number) => string;
54
+ }
55
+ /**
56
+ * Renders hierarchical data as a tree with unicode box-drawing characters.
57
+ *
58
+ * Uses unicode characters for tree structure.
59
+ * Nested objects are rendered as child nodes; leaf values (null, primitives)
60
+ * are rendered as terminal nodes.
61
+ *
62
+ * @param tree - Hierarchical object to render
63
+ * @param options - Customization options
64
+ * @returns Formatted tree string with box-drawing characters
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * const tree = {
69
+ * src: {
70
+ * components: {
71
+ * Button: null,
72
+ * Input: null,
73
+ * },
74
+ * utils: null,
75
+ * },
76
+ * tests: null,
77
+ * };
78
+ *
79
+ * console.log(renderTree(tree));
80
+ * // ├── src
81
+ * // │ ├── components
82
+ * // │ │ ├── Button
83
+ * // │ │ └── Input
84
+ * // │ └── utils
85
+ * // └── tests
86
+ *
87
+ * console.log(renderTree(tree, { guide: "rounded" }));
88
+ * // ├── src
89
+ * // │ ├── components
90
+ * // │ │ ├── Button
91
+ * // │ │ ╰── Input
92
+ * // │ ╰── utils
93
+ * // ╰── tests
94
+ * ```
95
+ */
96
+ declare function renderTree(tree: Record<string, unknown>, options?: TreeOptions): string;
97
+ export { TreeGuideStyle, TREE_GUIDES, TreeOptions, renderTree };
@@ -0,0 +1,20 @@
1
+ import { VisualTheme } from "./cli-s0kkx9m1";
2
+ /**
3
+ * Default visual theme.
4
+ *
5
+ * Features:
6
+ * - Single-line box-drawing borders (┌─┐)
7
+ * - Standard status indicators
8
+ * - Bullet delimiters
9
+ * - Dots spinner
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { defaultTheme } from "@outfitter/cli/theme/presets";
14
+ *
15
+ * // Use default styling
16
+ * const box = renderBox("Hello", { border: defaultTheme.border });
17
+ * ```
18
+ */
19
+ declare const defaultTheme: VisualTheme;
20
+ export { defaultTheme };
@@ -0,0 +1,83 @@
1
+ import { Validator } from "./cli-vstbkzky";
2
+ import { Result } from "better-result";
3
+ /**
4
+ * Error returned when user cancels a prompt.
5
+ */
6
+ interface CancelledError {
7
+ type: "cancelled";
8
+ message: string;
9
+ }
10
+ /**
11
+ * Creates a cancelled error.
12
+ */
13
+ declare function createCancelledError(message?: string): CancelledError;
14
+ /**
15
+ * Options for text prompts.
16
+ */
17
+ interface TextPromptOptions {
18
+ /** Prompt message to display */
19
+ message: string;
20
+ /** Placeholder text */
21
+ placeholder?: string;
22
+ /** Default value */
23
+ defaultValue?: string;
24
+ /** Validation function */
25
+ validate?: Validator;
26
+ }
27
+ /**
28
+ * Options for password prompts.
29
+ */
30
+ interface PasswordPromptOptions {
31
+ /** Prompt message to display */
32
+ message: string;
33
+ /** Validation function */
34
+ validate?: Validator;
35
+ /** Mask character (default: •) */
36
+ mask?: string;
37
+ }
38
+ /**
39
+ * Options for select prompts.
40
+ */
41
+ interface SelectPromptOptions<T> {
42
+ /** Prompt message to display */
43
+ message: string;
44
+ /** Available options */
45
+ options: Array<{
46
+ value: T;
47
+ label: string;
48
+ hint?: string;
49
+ }>;
50
+ /** Initial selected index */
51
+ initialValue?: T;
52
+ }
53
+ /**
54
+ * Options for multi-select prompts.
55
+ */
56
+ interface MultiSelectPromptOptions<T> {
57
+ /** Prompt message to display */
58
+ message: string;
59
+ /** Available options */
60
+ options: Array<{
61
+ value: T;
62
+ label: string;
63
+ hint?: string;
64
+ }>;
65
+ /** Initially selected values */
66
+ initialValues?: T[];
67
+ /** Require at least one selection */
68
+ required?: boolean;
69
+ }
70
+ /**
71
+ * Options for confirm prompts.
72
+ */
73
+ interface ConfirmPromptOptions {
74
+ /** Prompt message to display */
75
+ message: string;
76
+ /** Initial value */
77
+ initialValue?: boolean;
78
+ }
79
+ /**
80
+ * Type alias for prompt results.
81
+ */
82
+ type PromptResult<T> = Promise<Result<T, CancelledError>>;
83
+ export { CancelledError, createCancelledError, TextPromptOptions, PasswordPromptOptions, SelectPromptOptions, MultiSelectPromptOptions, ConfirmPromptOptions, PromptResult };