@flyingrobots/bijou 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 (191) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +91 -0
  3. package/dist/adapters/test/index.d.ts +20 -0
  4. package/dist/adapters/test/index.d.ts.map +1 -0
  5. package/dist/adapters/test/index.js +17 -0
  6. package/dist/adapters/test/index.js.map +1 -0
  7. package/dist/adapters/test/io.d.ts +15 -0
  8. package/dist/adapters/test/io.d.ts.map +1 -0
  9. package/dist/adapters/test/io.js +51 -0
  10. package/dist/adapters/test/io.js.map +1 -0
  11. package/dist/adapters/test/runtime.d.ts +10 -0
  12. package/dist/adapters/test/runtime.d.ts.map +1 -0
  13. package/dist/adapters/test/runtime.js +13 -0
  14. package/dist/adapters/test/runtime.js.map +1 -0
  15. package/dist/adapters/test/style.d.ts +3 -0
  16. package/dist/adapters/test/style.d.ts.map +1 -0
  17. package/dist/adapters/test/style.js +17 -0
  18. package/dist/adapters/test/style.js.map +1 -0
  19. package/dist/context.d.ts +5 -0
  20. package/dist/context.d.ts.map +1 -0
  21. package/dist/context.js +16 -0
  22. package/dist/context.js.map +1 -0
  23. package/dist/core/components/accordion.d.ts +14 -0
  24. package/dist/core/components/accordion.d.ts.map +1 -0
  25. package/dist/core/components/accordion.js +44 -0
  26. package/dist/core/components/accordion.js.map +1 -0
  27. package/dist/core/components/alert.d.ts +8 -0
  28. package/dist/core/components/alert.d.ts.map +1 -0
  29. package/dist/core/components/alert.js +50 -0
  30. package/dist/core/components/alert.js.map +1 -0
  31. package/dist/core/components/badge.d.ts +9 -0
  32. package/dist/core/components/badge.d.ts.map +1 -0
  33. package/dist/core/components/badge.js +37 -0
  34. package/dist/core/components/badge.js.map +1 -0
  35. package/dist/core/components/box.d.ts +19 -0
  36. package/dist/core/components/box.d.ts.map +1 -0
  37. package/dist/core/components/box.js +71 -0
  38. package/dist/core/components/box.js.map +1 -0
  39. package/dist/core/components/breadcrumb.d.ts +7 -0
  40. package/dist/core/components/breadcrumb.d.ts.map +1 -0
  41. package/dist/core/components/breadcrumb.js +32 -0
  42. package/dist/core/components/breadcrumb.js.map +1 -0
  43. package/dist/core/components/index.d.ts +35 -0
  44. package/dist/core/components/index.d.ts.map +1 -0
  45. package/dist/core/components/index.js +18 -0
  46. package/dist/core/components/index.js.map +1 -0
  47. package/dist/core/components/kbd.d.ts +6 -0
  48. package/dist/core/components/kbd.d.ts.map +1 -0
  49. package/dist/core/components/kbd.js +18 -0
  50. package/dist/core/components/kbd.js.map +1 -0
  51. package/dist/core/components/logo.d.ts +18 -0
  52. package/dist/core/components/logo.d.ts.map +1 -0
  53. package/dist/core/components/logo.js +66 -0
  54. package/dist/core/components/logo.js.map +1 -0
  55. package/dist/core/components/paginator.d.ts +9 -0
  56. package/dist/core/components/paginator.d.ts.map +1 -0
  57. package/dist/core/components/paginator.js +32 -0
  58. package/dist/core/components/paginator.js.map +1 -0
  59. package/dist/core/components/progress.d.ts +25 -0
  60. package/dist/core/components/progress.d.ts.map +1 -0
  61. package/dist/core/components/progress.js +146 -0
  62. package/dist/core/components/progress.js.map +1 -0
  63. package/dist/core/components/separator.d.ts +10 -0
  64. package/dist/core/components/separator.d.ts.map +1 -0
  65. package/dist/core/components/separator.js +32 -0
  66. package/dist/core/components/separator.js.map +1 -0
  67. package/dist/core/components/skeleton.d.ts +8 -0
  68. package/dist/core/components/skeleton.d.ts.map +1 -0
  69. package/dist/core/components/skeleton.js +20 -0
  70. package/dist/core/components/skeleton.js.map +1 -0
  71. package/dist/core/components/spinner.d.ts +15 -0
  72. package/dist/core/components/spinner.d.ts.map +1 -0
  73. package/dist/core/components/spinner.js +67 -0
  74. package/dist/core/components/spinner.js.map +1 -0
  75. package/dist/core/components/stepper.d.ts +10 -0
  76. package/dist/core/components/stepper.d.ts.map +1 -0
  77. package/dist/core/components/stepper.js +45 -0
  78. package/dist/core/components/stepper.js.map +1 -0
  79. package/dist/core/components/table.d.ts +15 -0
  80. package/dist/core/components/table.d.ts.map +1 -0
  81. package/dist/core/components/table.js +66 -0
  82. package/dist/core/components/table.js.map +1 -0
  83. package/dist/core/components/tabs.d.ts +12 -0
  84. package/dist/core/components/tabs.d.ts.map +1 -0
  85. package/dist/core/components/tabs.js +47 -0
  86. package/dist/core/components/tabs.js.map +1 -0
  87. package/dist/core/components/timeline.d.ts +14 -0
  88. package/dist/core/components/timeline.d.ts.map +1 -0
  89. package/dist/core/components/timeline.js +47 -0
  90. package/dist/core/components/timeline.js.map +1 -0
  91. package/dist/core/components/tree.d.ts +13 -0
  92. package/dist/core/components/tree.d.ts.map +1 -0
  93. package/dist/core/components/tree.js +65 -0
  94. package/dist/core/components/tree.js.map +1 -0
  95. package/dist/core/detect/index.d.ts +3 -0
  96. package/dist/core/detect/index.d.ts.map +1 -0
  97. package/dist/core/detect/index.js +2 -0
  98. package/dist/core/detect/index.js.map +1 -0
  99. package/dist/core/detect/tty.d.ts +14 -0
  100. package/dist/core/detect/tty.d.ts.map +1 -0
  101. package/dist/core/detect/tty.js +28 -0
  102. package/dist/core/detect/tty.js.map +1 -0
  103. package/dist/core/forms/confirm.d.ts +7 -0
  104. package/dist/core/forms/confirm.d.ts.map +1 -0
  105. package/dist/core/forms/confirm.js +32 -0
  106. package/dist/core/forms/confirm.js.map +1 -0
  107. package/dist/core/forms/group.d.ts +19 -0
  108. package/dist/core/forms/group.d.ts.map +1 -0
  109. package/dist/core/forms/group.js +21 -0
  110. package/dist/core/forms/group.js.map +1 -0
  111. package/dist/core/forms/index.d.ts +8 -0
  112. package/dist/core/forms/index.d.ts.map +1 -0
  113. package/dist/core/forms/index.js +6 -0
  114. package/dist/core/forms/index.js.map +1 -0
  115. package/dist/core/forms/input.d.ts +8 -0
  116. package/dist/core/forms/input.d.ts.map +1 -0
  117. package/dist/core/forms/input.js +42 -0
  118. package/dist/core/forms/input.js.map +1 -0
  119. package/dist/core/forms/multiselect.d.ts +7 -0
  120. package/dist/core/forms/multiselect.d.ts.map +1 -0
  121. package/dist/core/forms/multiselect.js +114 -0
  122. package/dist/core/forms/multiselect.js.map +1 -0
  123. package/dist/core/forms/select.d.ts +7 -0
  124. package/dist/core/forms/select.d.ts.map +1 -0
  125. package/dist/core/forms/select.js +100 -0
  126. package/dist/core/forms/select.js.map +1 -0
  127. package/dist/core/forms/types.d.ts +32 -0
  128. package/dist/core/forms/types.d.ts.map +1 -0
  129. package/dist/core/forms/types.js +2 -0
  130. package/dist/core/forms/types.js.map +1 -0
  131. package/dist/core/theme/dtcg.d.ts +25 -0
  132. package/dist/core/theme/dtcg.d.ts.map +1 -0
  133. package/dist/core/theme/dtcg.js +182 -0
  134. package/dist/core/theme/dtcg.js.map +1 -0
  135. package/dist/core/theme/extend.d.ts +7 -0
  136. package/dist/core/theme/extend.d.ts.map +1 -0
  137. package/dist/core/theme/extend.js +9 -0
  138. package/dist/core/theme/extend.js.map +1 -0
  139. package/dist/core/theme/gradient.d.ts +9 -0
  140. package/dist/core/theme/gradient.d.ts.map +1 -0
  141. package/dist/core/theme/gradient.js +40 -0
  142. package/dist/core/theme/gradient.js.map +1 -0
  143. package/dist/core/theme/index.d.ts +11 -0
  144. package/dist/core/theme/index.d.ts.map +1 -0
  145. package/dist/core/theme/index.js +13 -0
  146. package/dist/core/theme/index.js.map +1 -0
  147. package/dist/core/theme/presets.d.ts +22 -0
  148. package/dist/core/theme/presets.d.ts.map +1 -0
  149. package/dist/core/theme/presets.js +219 -0
  150. package/dist/core/theme/presets.js.map +1 -0
  151. package/dist/core/theme/resolve.d.ts +41 -0
  152. package/dist/core/theme/resolve.d.ts.map +1 -0
  153. package/dist/core/theme/resolve.js +80 -0
  154. package/dist/core/theme/resolve.js.map +1 -0
  155. package/dist/core/theme/styled.d.ts +4 -0
  156. package/dist/core/theme/styled.d.ts.map +1 -0
  157. package/dist/core/theme/styled.js +15 -0
  158. package/dist/core/theme/styled.js.map +1 -0
  159. package/dist/core/theme/tokens.d.ts +65 -0
  160. package/dist/core/theme/tokens.d.ts.map +1 -0
  161. package/dist/core/theme/tokens.js +8 -0
  162. package/dist/core/theme/tokens.js.map +1 -0
  163. package/dist/factory.d.ts +15 -0
  164. package/dist/factory.d.ts.map +1 -0
  165. package/dist/factory.js +33 -0
  166. package/dist/factory.js.map +1 -0
  167. package/dist/index.d.ts +8 -0
  168. package/dist/index.d.ts.map +1 -0
  169. package/dist/index.js +25 -0
  170. package/dist/index.js.map +1 -0
  171. package/dist/ports/context.d.ts +13 -0
  172. package/dist/ports/context.d.ts.map +1 -0
  173. package/dist/ports/context.js +2 -0
  174. package/dist/ports/context.js.map +1 -0
  175. package/dist/ports/index.d.ts +5 -0
  176. package/dist/ports/index.d.ts.map +1 -0
  177. package/dist/ports/index.js +2 -0
  178. package/dist/ports/index.js.map +1 -0
  179. package/dist/ports/io.d.ts +16 -0
  180. package/dist/ports/io.d.ts.map +1 -0
  181. package/dist/ports/io.js +2 -0
  182. package/dist/ports/io.js.map +1 -0
  183. package/dist/ports/runtime.d.ts +8 -0
  184. package/dist/ports/runtime.d.ts.map +1 -0
  185. package/dist/ports/runtime.js +2 -0
  186. package/dist/ports/runtime.js.map +1 -0
  187. package/dist/ports/style.d.ts +8 -0
  188. package/dist/ports/style.d.ts.map +1 -0
  189. package/dist/ports/style.js +2 -0
  190. package/dist/ports/style.js.map +1 -0
  191. package/package.json +68 -0
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Chain multiple form fields together, collecting results into an object.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * const result = await group({
7
+ * name: () => input({ title: 'Name', required: true }),
8
+ * role: () => select({ title: 'Role', options: [...] }),
9
+ * confirm: () => confirm({ title: 'Continue?' }),
10
+ * });
11
+ * ```
12
+ */
13
+ export async function group(fields) {
14
+ const values = {};
15
+ for (const key of Object.keys(fields)) {
16
+ const fieldFn = fields[key];
17
+ values[key] = await fieldFn();
18
+ }
19
+ return { values, cancelled: false };
20
+ }
21
+ //# sourceMappingURL=group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group.js","sourceRoot":"","sources":["../../../src/core/forms/group.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,MAAyC;IAEzC,MAAM,MAAM,GAAG,EAAO,CAAC;IAEvB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAmB,EAAE,CAAC;QACxD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,OAAO,EAAE,CAAC;IAChC,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AACtC,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type { ValidationResult, Validator, FieldOptions, SelectOption, SelectFieldOptions, ConfirmFieldOptions, GroupFieldResult, } from './types.js';
2
+ export { input } from './input.js';
3
+ export type { InputOptions } from './input.js';
4
+ export { select } from './select.js';
5
+ export { multiselect } from './multiselect.js';
6
+ export { confirm } from './confirm.js';
7
+ export { group } from './group.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/forms/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { input } from './input.js';
2
+ export { select } from './select.js';
3
+ export { multiselect } from './multiselect.js';
4
+ export { confirm } from './confirm.js';
5
+ export { group } from './group.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/forms/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { FieldOptions } from './types.js';
2
+ import type { BijouContext } from '../../ports/context.js';
3
+ export interface InputOptions extends FieldOptions<string> {
4
+ placeholder?: string;
5
+ ctx?: BijouContext;
6
+ }
7
+ export declare function input(options: InputOptions): Promise<string>;
8
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../src/core/forms/input.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D,MAAM,WAAW,YAAa,SAAQ,YAAY,CAAC,MAAM,CAAC;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB;AAED,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BlE"}
@@ -0,0 +1,42 @@
1
+ import { getDefaultContext } from '../../context.js';
2
+ export async function input(options) {
3
+ const ctx = options.ctx ?? getDefaultContext();
4
+ const mode = ctx.mode;
5
+ const noColor = ctx.theme.noColor;
6
+ const prompt = buildPrompt(options, mode, noColor, ctx);
7
+ const answer = await ctx.io.question(prompt);
8
+ const value = answer.trim() || options.defaultValue || '';
9
+ if (options.required && value === '') {
10
+ if (noColor || mode === 'accessible') {
11
+ ctx.io.write('This field is required.\n');
12
+ }
13
+ else {
14
+ ctx.io.write(ctx.style.styled(ctx.theme.theme.semantic.error, 'This field is required.') + '\n');
15
+ }
16
+ }
17
+ if (options.validate) {
18
+ const result = options.validate(value);
19
+ if (!result.valid && result.message) {
20
+ if (noColor) {
21
+ ctx.io.write(result.message + '\n');
22
+ }
23
+ else {
24
+ ctx.io.write(ctx.style.styled(ctx.theme.theme.semantic.error, result.message) + '\n');
25
+ }
26
+ }
27
+ }
28
+ return value;
29
+ }
30
+ function buildPrompt(options, mode, noColor, ctx) {
31
+ const defaultHint = options.defaultValue ? ` (${options.defaultValue})` : '';
32
+ if (mode === 'accessible')
33
+ return `Enter ${options.title.toLowerCase()}${defaultHint}: `;
34
+ if (mode === 'pipe')
35
+ return `${options.title}${defaultHint}: `;
36
+ if (noColor)
37
+ return `${options.title}${defaultHint}: `;
38
+ const label = ctx.style.styled(ctx.theme.theme.semantic.info, '? ') + ctx.style.bold(options.title);
39
+ const hint = options.defaultValue ? ctx.style.styled(ctx.theme.theme.semantic.muted, ` (${options.defaultValue})`) : '';
40
+ return `${label}${hint} `;
41
+ }
42
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../../../src/core/forms/input.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { SelectFieldOptions } from './types.js';
2
+ import type { BijouContext } from '../../ports/context.js';
3
+ export interface MultiselectOptions<T = string> extends SelectFieldOptions<T> {
4
+ ctx?: BijouContext;
5
+ }
6
+ export declare function multiselect<T = string>(options: MultiselectOptions<T>): Promise<T[]>;
7
+ //# sourceMappingURL=multiselect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multiselect.d.ts","sourceRoot":"","sources":["../../../src/core/forms/multiselect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAK3D,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,MAAM,CAAE,SAAQ,kBAAkB,CAAC,CAAC,CAAC;IAC3E,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB;AAED,wBAAsB,WAAW,CAAC,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAS1F"}
@@ -0,0 +1,114 @@
1
+ import { getDefaultContext } from '../../context.js';
2
+ export async function multiselect(options) {
3
+ const ctx = options.ctx ?? getDefaultContext();
4
+ const mode = ctx.mode;
5
+ if (mode === 'interactive' && ctx.runtime.stdinIsTTY) {
6
+ return interactiveMultiselect(options, ctx);
7
+ }
8
+ return numberedMultiselect(options, mode, ctx);
9
+ }
10
+ async function numberedMultiselect(options, mode, ctx) {
11
+ const noColor = ctx.theme.noColor;
12
+ const styledFn = (token, text) => ctx.style.styled(token, text);
13
+ if (noColor || mode === 'accessible') {
14
+ ctx.io.write(`${options.title}\n`);
15
+ }
16
+ else {
17
+ ctx.io.write(styledFn(ctx.theme.theme.semantic.info, '? ') + ctx.style.bold(options.title) + '\n');
18
+ }
19
+ for (let i = 0; i < options.options.length; i++) {
20
+ const opt = options.options[i];
21
+ const desc = opt.description ? ` \u2014 ${opt.description}` : '';
22
+ ctx.io.write(` ${i + 1}. ${opt.label}${desc}\n`);
23
+ }
24
+ const prompt = mode === 'accessible'
25
+ ? 'Enter numbers separated by commas: '
26
+ : 'Enter numbers (comma-separated): ';
27
+ const answer = await ctx.io.question(prompt);
28
+ const indices = answer.split(',')
29
+ .map((s) => parseInt(s.trim(), 10) - 1)
30
+ .filter((i) => i >= 0 && i < options.options.length);
31
+ return indices.map((i) => options.options[i].value);
32
+ }
33
+ async function interactiveMultiselect(options, ctx) {
34
+ const noColor = ctx.theme.noColor;
35
+ const t = ctx.theme;
36
+ const styledFn = (token, text) => ctx.style.styled(token, text);
37
+ let cursor = 0;
38
+ const selected = new Set();
39
+ function render() {
40
+ const label = noColor
41
+ ? `? ${options.title}`
42
+ : styledFn(t.theme.semantic.info, '? ') + ctx.style.bold(options.title);
43
+ ctx.io.write(`\x1b[?25l`);
44
+ ctx.io.write(`\r\x1b[K${label} ${styledFn(t.theme.semantic.muted, '(space to toggle, enter to confirm)')}\n`);
45
+ for (let i = 0; i < options.options.length; i++) {
46
+ const opt = options.options[i];
47
+ const isCurrent = i === cursor;
48
+ const isSelected = selected.has(i);
49
+ const prefix = isCurrent ? '\u276f' : ' ';
50
+ const check = isSelected ? '\u25c9' : '\u25cb';
51
+ const desc = opt.description ? styledFn(t.theme.semantic.muted, ` \u2014 ${opt.description}`) : '';
52
+ if (isCurrent && !noColor) {
53
+ ctx.io.write(`\x1b[K ${styledFn(t.theme.semantic.info, prefix)} ${styledFn(t.theme.semantic.info, check)} ${ctx.style.bold(opt.label)}${desc}\n`);
54
+ }
55
+ else if (isSelected && !noColor) {
56
+ ctx.io.write(`\x1b[K ${prefix} ${styledFn(t.theme.semantic.success, check)} ${opt.label}${desc}\n`);
57
+ }
58
+ else {
59
+ ctx.io.write(`\x1b[K ${prefix} ${check} ${opt.label}${desc}\n`);
60
+ }
61
+ }
62
+ }
63
+ function clearRender() {
64
+ const totalLines = options.options.length + 1;
65
+ ctx.io.write(`\x1b[${totalLines}A`);
66
+ }
67
+ function cleanup() {
68
+ clearRender();
69
+ const totalLines = options.options.length + 1;
70
+ for (let i = 0; i < totalLines; i++)
71
+ ctx.io.write(`\x1b[K\n`);
72
+ ctx.io.write(`\x1b[${totalLines}A`);
73
+ const selectedLabels = [...selected].sort().map((i) => options.options[i].label).join(', ');
74
+ const label = noColor
75
+ ? `? ${options.title} ${selectedLabels}`
76
+ : styledFn(t.theme.semantic.info, '? ') + ctx.style.bold(options.title) + ' ' + styledFn(t.theme.semantic.info, selectedLabels);
77
+ ctx.io.write(`\x1b[K${label}\n`);
78
+ ctx.io.write(`\x1b[?25h`);
79
+ }
80
+ render();
81
+ return new Promise((resolve) => {
82
+ const handle = ctx.io.rawInput((key) => {
83
+ if (key === '\x1b[A' || key === 'k') {
84
+ cursor = (cursor - 1 + options.options.length) % options.options.length;
85
+ clearRender();
86
+ render();
87
+ }
88
+ else if (key === '\x1b[B' || key === 'j') {
89
+ cursor = (cursor + 1) % options.options.length;
90
+ clearRender();
91
+ render();
92
+ }
93
+ else if (key === ' ') {
94
+ if (selected.has(cursor))
95
+ selected.delete(cursor);
96
+ else
97
+ selected.add(cursor);
98
+ clearRender();
99
+ render();
100
+ }
101
+ else if (key === '\r' || key === '\n') {
102
+ handle.dispose();
103
+ cleanup();
104
+ resolve([...selected].sort().map((i) => options.options[i].value));
105
+ }
106
+ else if (key === '\x03') {
107
+ handle.dispose();
108
+ cleanup();
109
+ resolve([]);
110
+ }
111
+ });
112
+ });
113
+ }
114
+ //# sourceMappingURL=multiselect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multiselect.js","sourceRoot":"","sources":["../../../src/core/forms/multiselect.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAMrD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAa,OAA8B;IAC1E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAC/C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IAEtB,IAAI,IAAI,KAAK,aAAa,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QACrD,OAAO,sBAAsB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,mBAAmB,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;AACjD,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAI,OAA8B,EAAE,IAAgB,EAAE,GAAiB;IACvG,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;IAClC,MAAM,QAAQ,GAAG,CAAC,KAAiB,EAAE,IAAY,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEpF,IAAI,OAAO,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QACrC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;IACrC,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACrG,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC;QAChC,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,KAAK,YAAY;QAClC,CAAC,CAAC,qCAAqC;QACvC,CAAC,CAAC,mCAAmC,CAAC;IAExC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;SAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;SACtC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC;AACvD,CAAC;AAED,KAAK,UAAU,sBAAsB,CAAI,OAA8B,EAAE,GAAiB;IACxF,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;IAClC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;IACpB,MAAM,QAAQ,GAAG,CAAC,KAAiB,EAAE,IAAY,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEpF,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAEnC,SAAS,MAAM;QACb,MAAM,KAAK,GAAG,OAAO;YACnB,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,EAAE;YACtB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1E,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC1B,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,qCAAqC,CAAC,IAAI,CAAC,CAAC;QAE/G,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAChD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC;YAChC,MAAM,SAAS,GAAG,CAAC,KAAK,MAAM,CAAC;YAC/B,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;YAC1C,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC/C,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACnG,IAAI,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC1B,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;YACrJ,CAAC;iBAAM,IAAI,UAAU,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,GAAG,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC;YACvG,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,MAAM,IAAI,KAAK,IAAI,GAAG,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,WAAW;QAClB,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QAC9C,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,UAAU,GAAG,CAAC,CAAC;IACtC,CAAC;IAED,SAAS,OAAO;QACd,WAAW,EAAE,CAAC;QACd,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC9D,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,UAAU,GAAG,CAAC,CAAC;QACpC,MAAM,cAAc,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7F,MAAM,KAAK,GAAG,OAAO;YACnB,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,IAAI,cAAc,EAAE;YACxC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAClI,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC;QACjC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM,EAAE,CAAC;IAET,OAAO,IAAI,OAAO,CAAM,CAAC,OAAO,EAAE,EAAE;QAClC,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAW,EAAE,EAAE;YAC7C,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;gBACpC,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;gBACxE,WAAW,EAAE,CAAC;gBAAC,MAAM,EAAE,CAAC;YAC1B,CAAC;iBAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;gBAC3C,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;gBAC/C,WAAW,EAAE,CAAC;gBAAC,MAAM,EAAE,CAAC;YAC1B,CAAC;iBAAM,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;gBACvB,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC;oBAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;;oBAAM,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC7E,WAAW,EAAE,CAAC;gBAAC,MAAM,EAAE,CAAC;YAC1B,CAAC;iBAAM,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBACxC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAAC,OAAO,EAAE,CAAC;gBAC5B,OAAO,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,CAAC;YACtE,CAAC;iBAAM,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBAC1B,MAAM,CAAC,OAAO,EAAE,CAAC;gBAAC,OAAO,EAAE,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { SelectFieldOptions } from './types.js';
2
+ import type { BijouContext } from '../../ports/context.js';
3
+ export interface SelectOptions<T = string> extends SelectFieldOptions<T> {
4
+ ctx?: BijouContext;
5
+ }
6
+ export declare function select<T = string>(options: SelectOptions<T>): Promise<T>;
7
+ //# sourceMappingURL=select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/core/forms/select.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,YAAY,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAK3D,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,MAAM,CAAE,SAAQ,kBAAkB,CAAC,CAAC,CAAC;IACtE,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB;AAED,wBAAsB,MAAM,CAAC,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAS9E"}
@@ -0,0 +1,100 @@
1
+ import { getDefaultContext } from '../../context.js';
2
+ export async function select(options) {
3
+ const ctx = options.ctx ?? getDefaultContext();
4
+ const mode = ctx.mode;
5
+ if (mode === 'interactive' && ctx.runtime.stdinIsTTY) {
6
+ return interactiveSelect(options, ctx);
7
+ }
8
+ return numberedSelect(options, mode, ctx);
9
+ }
10
+ async function numberedSelect(options, mode, ctx) {
11
+ const noColor = ctx.theme.noColor;
12
+ const styledFn = (token, text) => ctx.style.styled(token, text);
13
+ if (noColor || mode === 'accessible') {
14
+ ctx.io.write(`${options.title}\n`);
15
+ }
16
+ else {
17
+ ctx.io.write(styledFn(ctx.theme.theme.semantic.info, '? ') + ctx.style.bold(options.title) + '\n');
18
+ }
19
+ for (let i = 0; i < options.options.length; i++) {
20
+ const opt = options.options[i];
21
+ const num = ` ${i + 1}.`;
22
+ const desc = opt.description ? ` \u2014 ${opt.description}` : '';
23
+ ctx.io.write(`${num} ${opt.label}${desc}\n`);
24
+ }
25
+ const prompt = mode === 'accessible' ? 'Enter number: ' : '> ';
26
+ const answer = await ctx.io.question(prompt);
27
+ const idx = parseInt(answer.trim(), 10) - 1;
28
+ if (idx >= 0 && idx < options.options.length) {
29
+ return options.options[idx].value;
30
+ }
31
+ return options.defaultValue ?? options.options[0].value;
32
+ }
33
+ async function interactiveSelect(options, ctx) {
34
+ const noColor = ctx.theme.noColor;
35
+ const t = ctx.theme;
36
+ const styledFn = (token, text) => ctx.style.styled(token, text);
37
+ let cursor = 0;
38
+ function render() {
39
+ const label = noColor
40
+ ? `? ${options.title}`
41
+ : styledFn(t.theme.semantic.info, '? ') + ctx.style.bold(options.title);
42
+ ctx.io.write(`\x1b[?25l`);
43
+ ctx.io.write(`\r\x1b[K${label}\n`);
44
+ for (let i = 0; i < options.options.length; i++) {
45
+ const opt = options.options[i];
46
+ const isCurrent = i === cursor;
47
+ const prefix = isCurrent ? '\u276f' : ' ';
48
+ const desc = opt.description ? styledFn(t.theme.semantic.muted, ` \u2014 ${opt.description}`) : '';
49
+ if (isCurrent && !noColor) {
50
+ ctx.io.write(`\x1b[K ${styledFn(t.theme.semantic.info, prefix)} ${ctx.style.bold(opt.label)}${desc}\n`);
51
+ }
52
+ else {
53
+ ctx.io.write(`\x1b[K ${prefix} ${opt.label}${desc}\n`);
54
+ }
55
+ }
56
+ }
57
+ function clearRender() {
58
+ const totalLines = options.options.length + 1;
59
+ ctx.io.write(`\x1b[${totalLines}A`);
60
+ }
61
+ function cleanup() {
62
+ clearRender();
63
+ const totalLines = options.options.length + 1;
64
+ for (let i = 0; i < totalLines; i++)
65
+ ctx.io.write(`\x1b[K\n`);
66
+ ctx.io.write(`\x1b[${totalLines}A`);
67
+ const selected = options.options[cursor];
68
+ const label = noColor
69
+ ? `? ${options.title} ${selected.label}`
70
+ : styledFn(t.theme.semantic.info, '? ') + ctx.style.bold(options.title) + ' ' + styledFn(t.theme.semantic.info, selected.label);
71
+ ctx.io.write(`\x1b[K${label}\n`);
72
+ ctx.io.write(`\x1b[?25h`);
73
+ }
74
+ render();
75
+ return new Promise((resolve) => {
76
+ const handle = ctx.io.rawInput((key) => {
77
+ if (key === '\x1b[A' || key === 'k') {
78
+ cursor = (cursor - 1 + options.options.length) % options.options.length;
79
+ clearRender();
80
+ render();
81
+ }
82
+ else if (key === '\x1b[B' || key === 'j') {
83
+ cursor = (cursor + 1) % options.options.length;
84
+ clearRender();
85
+ render();
86
+ }
87
+ else if (key === '\r' || key === '\n') {
88
+ handle.dispose();
89
+ cleanup();
90
+ resolve(options.options[cursor].value);
91
+ }
92
+ else if (key === '\x03') {
93
+ handle.dispose();
94
+ cleanup();
95
+ resolve(options.defaultValue ?? options.options[0].value);
96
+ }
97
+ });
98
+ });
99
+ }
100
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../../src/core/forms/select.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAMrD,MAAM,CAAC,KAAK,UAAU,MAAM,CAAa,OAAyB;IAChE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAC/C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IAEtB,IAAI,IAAI,KAAK,aAAa,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QACrD,OAAO,iBAAiB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED,KAAK,UAAU,cAAc,CAAI,OAAyB,EAAE,IAAgB,EAAE,GAAiB;IAC7F,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;IAClC,MAAM,QAAQ,GAAG,CAAC,KAAiB,EAAE,IAAY,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEpF,IAAI,OAAO,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QACrC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;IACrC,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACrG,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC;QAChC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;QAC1B,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjE,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAE7C,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QAC7C,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAE,CAAC,KAAK,CAAC;IACrC,CAAC;IACD,OAAO,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC;AAC3D,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAI,OAAyB,EAAE,GAAiB;IAC9E,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;IAClC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;IACpB,MAAM,QAAQ,GAAG,CAAC,KAAiB,EAAE,IAAY,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEpF,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,SAAS,MAAM;QACb,MAAM,KAAK,GAAG,OAAO;YACnB,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,EAAE;YACtB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1E,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC1B,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC;QAEnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAChD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC;YAChC,MAAM,SAAS,GAAG,CAAC,KAAK,MAAM,CAAC;YAC/B,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;YAC1C,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACnG,IAAI,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC1B,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;YAC3G,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,MAAM,IAAI,GAAG,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,WAAW;QAClB,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QAC9C,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,UAAU,GAAG,CAAC,CAAC;IACtC,CAAC;IAED,SAAS,OAAO;QACd,WAAW,EAAE,CAAC;QACd,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC9D,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,UAAU,GAAG,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAoB,CAAC;QAC5D,MAAM,KAAK,GAAG,OAAO;YACnB,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,EAAE;YACxC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;QAClI,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC;QACjC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM,EAAE,CAAC;IAET,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,EAAE;QAChC,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAW,EAAE,EAAE;YAC7C,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;gBACpC,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;gBACxE,WAAW,EAAE,CAAC;gBAAC,MAAM,EAAE,CAAC;YAC1B,CAAC;iBAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;gBAC3C,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;gBAC/C,WAAW,EAAE,CAAC;gBAAC,MAAM,EAAE,CAAC;YAC1B,CAAC;iBAAM,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBACxC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAAC,OAAO,EAAE,CAAC;gBAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAE,CAAC,KAAK,CAAC,CAAC;YACvE,CAAC;iBAAM,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBAC1B,MAAM,CAAC,OAAO,EAAE,CAAC;gBAAC,OAAO,EAAE,CAAC;gBAAC,OAAO,CAAC,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC;YAC1F,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,32 @@
1
+ export interface ValidationResult {
2
+ valid: boolean;
3
+ message?: string;
4
+ }
5
+ export type Validator<T> = (value: T) => ValidationResult;
6
+ export interface FieldOptions<T> {
7
+ /** Prompt title shown to the user. */
8
+ title: string;
9
+ /** Default value. */
10
+ defaultValue?: T;
11
+ /** Whether the field is required. Default: false. */
12
+ required?: boolean;
13
+ /** Validation function. */
14
+ validate?: Validator<T>;
15
+ }
16
+ export interface SelectOption<T = string> {
17
+ label: string;
18
+ value: T;
19
+ description?: string;
20
+ }
21
+ export interface SelectFieldOptions<T = string> extends FieldOptions<T> {
22
+ options: SelectOption<T>[];
23
+ }
24
+ export interface ConfirmFieldOptions extends FieldOptions<boolean> {
25
+ /** Which option is the default. Default: true (yes). */
26
+ defaultValue?: boolean;
27
+ }
28
+ export interface GroupFieldResult<T extends Record<string, unknown>> {
29
+ values: T;
30
+ cancelled: boolean;
31
+ }
32
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/forms/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,gBAAgB,CAAC;AAE1D,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,YAAY,CAAC,EAAE,CAAC,CAAC;IACjB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,MAAM;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;IACT,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,MAAM,CAAE,SAAQ,YAAY,CAAC,CAAC,CAAC;IACrE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAoB,SAAQ,YAAY,CAAC,OAAO,CAAC;IAChE,wDAAwD;IACxD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACjE,MAAM,EAAE,CAAC,CAAC;IACV,SAAS,EAAE,OAAO,CAAC;CACpB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/forms/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ import type { Theme } from './tokens.js';
2
+ export interface DTCGToken {
3
+ $type?: string;
4
+ $value: unknown;
5
+ $description?: string;
6
+ }
7
+ export interface DTCGGroup {
8
+ [key: string]: DTCGToken | DTCGGroup;
9
+ }
10
+ export interface DTCGDocument {
11
+ [key: string]: DTCGToken | DTCGGroup;
12
+ }
13
+ export declare function fromDTCG(doc: DTCGDocument): Theme;
14
+ export declare function toDTCG(theme: Theme): DTCGDocument;
15
+ /** Load a single theme from a DTCG JSON file using the provided IOPort. */
16
+ export declare function loadTheme(io: {
17
+ readFile(path: string): string;
18
+ }, path: string): Theme;
19
+ /** Load all .json files from a directory and return them as a theme record. */
20
+ export declare function loadThemesFromDir(io: {
21
+ readDir(path: string): string[];
22
+ readFile(path: string): string;
23
+ joinPath(...s: string[]): string;
24
+ }, dirPath: string): Record<string, Theme>;
25
+ //# sourceMappingURL=dtcg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dtcg.d.ts","sourceRoot":"","sources":["../../../src/core/theme/dtcg.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EAQN,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;CACtC;AAED,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;CACtC;AAyGD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,YAAY,GAAG,KAAK,CA2BjD;AAgCD,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,YAAY,CAgBjD;AAID,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,CAIrF;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE;IAAE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAA;CAAE,EACzG,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAcvB"}
@@ -0,0 +1,182 @@
1
+ // --- Helpers ---
2
+ function hexToRgb(hex) {
3
+ const h = hex.replace('#', '');
4
+ return [
5
+ parseInt(h.slice(0, 2), 16),
6
+ parseInt(h.slice(2, 4), 16),
7
+ parseInt(h.slice(4, 6), 16),
8
+ ];
9
+ }
10
+ function rgbToHex(rgb) {
11
+ return '#' + rgb.map((c) => c.toString(16).padStart(2, '0')).join('');
12
+ }
13
+ function isDTCGToken(obj) {
14
+ return typeof obj === 'object' && obj !== null && '$value' in obj;
15
+ }
16
+ function resolveReference(ref, doc) {
17
+ // DTCG references look like "{color.primary}"
18
+ const path = ref.replace(/^\{|\}$/g, '').split('.');
19
+ let current = doc;
20
+ for (const segment of path) {
21
+ if (typeof current !== 'object' || current === null)
22
+ return undefined;
23
+ current = current[segment];
24
+ }
25
+ if (isDTCGToken(current))
26
+ return current.$value;
27
+ return current;
28
+ }
29
+ function resolveValue(value, doc, seen) {
30
+ if (typeof value === 'string' && value.startsWith('{') && value.endsWith('}')) {
31
+ const visitedRefs = seen ?? new Set();
32
+ if (visitedRefs.has(value)) {
33
+ throw new Error(`Circular reference detected: ${[...visitedRefs, value].join(' → ')}`);
34
+ }
35
+ visitedRefs.add(value);
36
+ const resolved = resolveReference(value, doc);
37
+ if (resolved === undefined) {
38
+ throw new Error(`Unresolvable reference: ${value}`);
39
+ }
40
+ return resolveValue(resolved, doc, visitedRefs);
41
+ }
42
+ return value;
43
+ }
44
+ function toTokenValue(value, doc) {
45
+ const resolved = resolveValue(value, doc);
46
+ if (typeof resolved === 'string') {
47
+ return { hex: resolved };
48
+ }
49
+ if (typeof resolved === 'object' && resolved !== null) {
50
+ const obj = resolved;
51
+ const hex = typeof obj['hex'] === 'string' ? obj['hex'] : '#000000';
52
+ const modifiers = Array.isArray(obj['modifiers'])
53
+ ? obj['modifiers']
54
+ : undefined;
55
+ return modifiers ? { hex, modifiers } : { hex };
56
+ }
57
+ return { hex: '#000000' };
58
+ }
59
+ function toGradientStops(value, doc) {
60
+ const resolved = resolveValue(value, doc);
61
+ if (!Array.isArray(resolved))
62
+ return [];
63
+ return resolved.map((stop) => {
64
+ const s = stop;
65
+ const pos = typeof s['pos'] === 'number' ? s['pos'] : 0;
66
+ const color = Array.isArray(s['color'])
67
+ ? s['color']
68
+ : typeof s['color'] === 'string'
69
+ ? hexToRgb(s['color'])
70
+ : [0, 0, 0];
71
+ return { pos, color };
72
+ });
73
+ }
74
+ // --- fromDTCG ---
75
+ function extractGroup(group, keys, doc) {
76
+ const result = {};
77
+ for (const key of keys) {
78
+ const token = group?.[key];
79
+ if (isDTCGToken(token)) {
80
+ result[key] = toTokenValue(token.$value, doc);
81
+ }
82
+ else {
83
+ result[key] = { hex: '#000000' };
84
+ }
85
+ }
86
+ return result;
87
+ }
88
+ const STATUS_KEYS = ['success', 'error', 'warning', 'info', 'pending', 'active', 'muted'];
89
+ const SEMANTIC_KEYS = ['success', 'error', 'warning', 'info', 'accent', 'muted', 'primary'];
90
+ const BORDER_KEYS = ['primary', 'secondary', 'success', 'warning', 'error', 'muted'];
91
+ const UI_KEYS = ['cursor', 'scrollThumb', 'scrollTrack', 'sectionHeader', 'logo', 'tableHeader', 'trackEmpty'];
92
+ const GRADIENT_KEYS = ['brand', 'progress'];
93
+ export function fromDTCG(doc) {
94
+ const name = typeof doc['name']?.$value === 'string'
95
+ ? doc['name'].$value
96
+ : 'imported';
97
+ const statusGroup = doc['status'];
98
+ const semanticGroup = doc['semantic'];
99
+ const borderGroup = doc['border'];
100
+ const uiGroup = doc['ui'];
101
+ const gradientGroup = doc['gradient'];
102
+ const status = extractGroup(statusGroup, STATUS_KEYS, doc);
103
+ const semantic = extractGroup(semanticGroup, SEMANTIC_KEYS, doc);
104
+ const border = extractGroup(borderGroup, BORDER_KEYS, doc);
105
+ const ui = extractGroup(uiGroup, UI_KEYS, doc);
106
+ const gradient = {};
107
+ for (const key of GRADIENT_KEYS) {
108
+ const token = gradientGroup?.[key];
109
+ if (isDTCGToken(token)) {
110
+ gradient[key] = toGradientStops(token.$value, doc);
111
+ }
112
+ else {
113
+ gradient[key] = [];
114
+ }
115
+ }
116
+ return { name, status, semantic, gradient, border, ui };
117
+ }
118
+ // --- toDTCG ---
119
+ function tokenToDTCG(token) {
120
+ if (token.modifiers && token.modifiers.length > 0) {
121
+ return {
122
+ $type: 'color',
123
+ $value: { hex: token.hex, modifiers: token.modifiers },
124
+ };
125
+ }
126
+ return { $type: 'color', $value: token.hex };
127
+ }
128
+ function gradientToDTCG(stops) {
129
+ return {
130
+ $type: 'gradient',
131
+ $value: stops.map((s) => ({
132
+ pos: s.pos,
133
+ color: rgbToHex(s.color),
134
+ })),
135
+ };
136
+ }
137
+ function recordToDTCGGroup(record) {
138
+ const group = {};
139
+ for (const [key, value] of Object.entries(record)) {
140
+ group[key] = tokenToDTCG(value);
141
+ }
142
+ return group;
143
+ }
144
+ export function toDTCG(theme) {
145
+ const doc = {};
146
+ doc['name'] = { $type: 'string', $value: theme.name };
147
+ doc['status'] = recordToDTCGGroup(theme.status);
148
+ doc['semantic'] = recordToDTCGGroup(theme.semantic);
149
+ doc['border'] = recordToDTCGGroup(theme.border);
150
+ doc['ui'] = recordToDTCGGroup(theme.ui);
151
+ const gradientDoc = {};
152
+ for (const [key, stops] of Object.entries(theme.gradient)) {
153
+ gradientDoc[key] = gradientToDTCG(stops);
154
+ }
155
+ doc['gradient'] = gradientDoc;
156
+ return doc;
157
+ }
158
+ // --- IO Helpers ---
159
+ /** Load a single theme from a DTCG JSON file using the provided IOPort. */
160
+ export function loadTheme(io, path) {
161
+ const content = io.readFile(path);
162
+ const doc = JSON.parse(content);
163
+ return fromDTCG(doc);
164
+ }
165
+ /** Load all .json files from a directory and return them as a theme record. */
166
+ export function loadThemesFromDir(io, dirPath) {
167
+ const files = io.readDir(dirPath);
168
+ const themes = {};
169
+ for (const file of files) {
170
+ if (file.endsWith('.json')) {
171
+ try {
172
+ const theme = loadTheme(io, io.joinPath(dirPath, file));
173
+ themes[theme.name] = theme;
174
+ }
175
+ catch {
176
+ // Skip malformed themes
177
+ }
178
+ }
179
+ }
180
+ return themes;
181
+ }
182
+ //# sourceMappingURL=dtcg.js.map