@flyingrobots/bijou 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/core/components/dag-edges.d.ts +78 -0
  2. package/dist/core/components/dag-edges.d.ts.map +1 -0
  3. package/dist/core/components/dag-edges.js +127 -0
  4. package/dist/core/components/dag-edges.js.map +1 -0
  5. package/dist/core/components/dag-layout.d.ts +37 -0
  6. package/dist/core/components/dag-layout.d.ts.map +1 -0
  7. package/dist/core/components/dag-layout.js +172 -0
  8. package/dist/core/components/dag-layout.js.map +1 -0
  9. package/dist/core/components/dag-render.d.ts +51 -0
  10. package/dist/core/components/dag-render.d.ts.map +1 -0
  11. package/dist/core/components/dag-render.js +440 -0
  12. package/dist/core/components/dag-render.js.map +1 -0
  13. package/dist/core/components/dag.d.ts.map +1 -1
  14. package/dist/core/components/dag.js +3 -648
  15. package/dist/core/components/dag.js.map +1 -1
  16. package/dist/core/components/markdown-parse.d.ts +69 -0
  17. package/dist/core/components/markdown-parse.d.ts.map +1 -0
  18. package/dist/core/components/markdown-parse.js +272 -0
  19. package/dist/core/components/markdown-parse.js.map +1 -0
  20. package/dist/core/components/markdown-render.d.ts +20 -0
  21. package/dist/core/components/markdown-render.d.ts.map +1 -0
  22. package/dist/core/components/markdown-render.js +135 -0
  23. package/dist/core/components/markdown-render.js.map +1 -0
  24. package/dist/core/components/markdown.d.ts.map +1 -1
  25. package/dist/core/components/markdown.js +6 -371
  26. package/dist/core/components/markdown.js.map +1 -1
  27. package/dist/core/forms/filter-interactive.d.ts +66 -0
  28. package/dist/core/forms/filter-interactive.d.ts.map +1 -0
  29. package/dist/core/forms/filter-interactive.js +241 -0
  30. package/dist/core/forms/filter-interactive.js.map +1 -0
  31. package/dist/core/forms/filter.d.ts +2 -32
  32. package/dist/core/forms/filter.d.ts.map +1 -1
  33. package/dist/core/forms/filter.js +2 -167
  34. package/dist/core/forms/filter.js.map +1 -1
  35. package/dist/core/forms/textarea-editor.d.ts +39 -0
  36. package/dist/core/forms/textarea-editor.d.ts.map +1 -0
  37. package/dist/core/forms/textarea-editor.js +210 -0
  38. package/dist/core/forms/textarea-editor.js.map +1 -0
  39. package/dist/core/forms/textarea.d.ts +2 -19
  40. package/dist/core/forms/textarea.d.ts.map +1 -1
  41. package/dist/core/forms/textarea.js +2 -195
  42. package/dist/core/forms/textarea.js.map +1 -1
  43. package/package.json +1 -1
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Interactive filter select UI with real-time search and vim-style modes.
3
+ *
4
+ * Starts in **normal mode** where `j`/`k` navigate and any printable character
5
+ * (except `j`/`k`) switches to insert mode and types the character. Press `/`
6
+ * to enter insert mode without typing. In **insert mode**, all keys are
7
+ * printable (including `j`/`k`), arrow keys navigate, and Escape returns to
8
+ * normal mode. Ctrl+C cancels from either mode; Escape in normal mode cancels.
9
+ */
10
+ import { formatFormTitle, terminalRenderer, createStyledFn, createBoldFn } from './form-utils.js';
11
+ /**
12
+ * Default case-insensitive substring matcher for filter options.
13
+ *
14
+ * Check the option label first, then fall back to keyword matches.
15
+ *
16
+ * @param query - User's search input.
17
+ * @param option - Option to test against.
18
+ * @returns `true` if the query matches the label or any keyword.
19
+ */
20
+ export function defaultMatch(query, option) {
21
+ const q = query.toLowerCase();
22
+ if (option.label.toLowerCase().includes(q))
23
+ return true;
24
+ if (option.keywords) {
25
+ return option.keywords.some((kw) => kw.toLowerCase().includes(q));
26
+ }
27
+ return false;
28
+ }
29
+ /**
30
+ * Render a keyboard-navigable filter select with vim-style normal/insert modes.
31
+ *
32
+ * Starts in normal mode: `j`/`k` navigate, `/` enters insert mode, any other
33
+ * printable enters insert mode and types the character. In insert mode, all keys
34
+ * are printable, arrow keys navigate, Escape returns to normal mode. Enter
35
+ * confirms from either mode, Ctrl+C cancels from either mode, Escape in normal
36
+ * mode cancels.
37
+ *
38
+ * @param options - Filter field configuration.
39
+ * @param ctx - Bijou context.
40
+ * @returns The value of the selected (or default/first) option.
41
+ */
42
+ export async function interactiveFilter(options, ctx) {
43
+ if (options.options.length === 0) {
44
+ throw new Error('[bijou] filter(): options array must contain at least one option');
45
+ }
46
+ const noColor = ctx.theme.noColor;
47
+ const t = ctx.theme;
48
+ const styledFn = createStyledFn(ctx);
49
+ const boldFn = createBoldFn(ctx);
50
+ const matchFn = options.match ?? defaultMatch;
51
+ const maxVisible = options.maxVisible ?? 7;
52
+ const term = terminalRenderer(ctx);
53
+ let mode = 'normal';
54
+ let query = '';
55
+ let cursor = 0;
56
+ let scrollOffset = 0;
57
+ let filtered = [...options.options];
58
+ function applyFilter() {
59
+ if (query === '') {
60
+ filtered = [...options.options];
61
+ }
62
+ else {
63
+ filtered = options.options.filter((opt) => matchFn(query, opt));
64
+ }
65
+ cursor = Math.min(cursor, Math.max(0, filtered.length - 1));
66
+ clampScroll();
67
+ }
68
+ function clampScroll() {
69
+ if (cursor < scrollOffset) {
70
+ scrollOffset = cursor;
71
+ }
72
+ else if (cursor >= scrollOffset + maxVisible) {
73
+ scrollOffset = cursor - maxVisible + 1;
74
+ }
75
+ scrollOffset = Math.max(0, Math.min(scrollOffset, Math.max(0, filtered.length - maxVisible)));
76
+ }
77
+ function visibleItems() {
78
+ return filtered.slice(scrollOffset, scrollOffset + maxVisible);
79
+ }
80
+ function renderLineCount() {
81
+ return 2 + Math.min(filtered.length, maxVisible) + 1; // header + filter input + items + status
82
+ }
83
+ function render() {
84
+ const label = formatFormTitle(options.title, ctx);
85
+ term.writeLine(label);
86
+ // Filter input with mode indicator (: normal, / insert)
87
+ const indicator = mode === 'insert' ? '/' : ':';
88
+ const filterDisplay = query || (options.placeholder ? styledFn(t.theme.semantic.muted, options.placeholder) : '');
89
+ ctx.io.write(`\x1b[K ${styledFn(t.theme.semantic.info, indicator)} ${filterDisplay}\n`);
90
+ // Visible items
91
+ const vis = visibleItems();
92
+ for (let i = 0; i < vis.length; i++) {
93
+ const opt = vis[i];
94
+ const isCurrent = scrollOffset + i === cursor;
95
+ const prefix = isCurrent ? '❯' : ' ';
96
+ if (isCurrent && !noColor) {
97
+ ctx.io.write(`\x1b[K ${styledFn(t.theme.semantic.info, prefix)} ${boldFn(opt.label)}\n`);
98
+ }
99
+ else {
100
+ ctx.io.write(`\x1b[K ${prefix} ${opt.label}\n`);
101
+ }
102
+ }
103
+ // Status
104
+ const status = `${filtered.length}/${options.options.length} items`;
105
+ ctx.io.write(`\x1b[K ${styledFn(t.theme.semantic.muted, status)}\n`);
106
+ }
107
+ function clearRender(lineCount) {
108
+ term.moveUp(lineCount);
109
+ }
110
+ function clearAndRerender(prevLineCount) {
111
+ clearRender(prevLineCount);
112
+ term.clearBlock(prevLineCount);
113
+ render();
114
+ }
115
+ function cleanup() {
116
+ const total = renderLineCount();
117
+ clearRender(total);
118
+ term.clearBlock(total);
119
+ const selected = filtered[cursor];
120
+ const selectedLabel = selected ? selected.label : '(none)';
121
+ const label = formatFormTitle(options.title, ctx) + ' ' + styledFn(t.theme.semantic.info, selectedLabel);
122
+ ctx.io.write(`\x1b[K${label}\n`);
123
+ term.showCursor();
124
+ }
125
+ term.hideCursor();
126
+ render();
127
+ // navigateUp/navigateDown use clearRender + render instead of clearAndRerender
128
+ // because render() uses per-line \x1b[K (clear-to-end-of-line), making a full
129
+ // clearBlock unnecessary for a simple cursor position change.
130
+ function navigateUp() {
131
+ if (filtered.length === 0)
132
+ return;
133
+ const prevLineCount = renderLineCount();
134
+ cursor = (cursor - 1 + filtered.length) % filtered.length;
135
+ clampScroll();
136
+ clearRender(prevLineCount);
137
+ render();
138
+ }
139
+ function navigateDown() {
140
+ if (filtered.length === 0)
141
+ return;
142
+ const prevLineCount = renderLineCount();
143
+ cursor = (cursor + 1) % filtered.length;
144
+ clampScroll();
145
+ clearRender(prevLineCount);
146
+ render();
147
+ }
148
+ function typeChar(ch) {
149
+ const prevLineCount = renderLineCount();
150
+ query += ch;
151
+ applyFilter();
152
+ clearAndRerender(prevLineCount);
153
+ }
154
+ // switchMode uses the same lightweight rerender pattern as navigate functions —
155
+ // only the mode indicator line changes, and render() clears each line with \x1b[K.
156
+ function switchMode(newMode) {
157
+ mode = newMode;
158
+ const prevLineCount = renderLineCount();
159
+ clearRender(prevLineCount);
160
+ render();
161
+ }
162
+ return new Promise((resolve) => {
163
+ const handle = ctx.io.rawInput((key) => {
164
+ // ── Mode-independent ───────────────────────────────────
165
+ if (key === '\r' || key === '\n') {
166
+ handle.dispose();
167
+ cleanup();
168
+ resolve(filtered[cursor]?.value ?? options.defaultValue ?? options.options[0].value);
169
+ return;
170
+ }
171
+ if (key === '\x03') {
172
+ // Ctrl+C — cancel from either mode
173
+ handle.dispose();
174
+ cleanup();
175
+ resolve(options.defaultValue ?? options.options[0].value);
176
+ return;
177
+ }
178
+ // ── Normal mode ────────────────────────────────────────
179
+ if (mode === 'normal') {
180
+ if (key === '\x1b') {
181
+ // Escape in normal mode — cancel
182
+ // TODO: bare \x1b may false-trigger on slow connections where escape
183
+ // sequences arrive as separate bytes. Timer-based disambiguation is a
184
+ // shared debt with textarea-editor.ts — unify in a future PR.
185
+ handle.dispose();
186
+ cleanup();
187
+ resolve(options.defaultValue ?? options.options[0].value);
188
+ return;
189
+ }
190
+ if (key === 'j' || key === '\x1b[B') {
191
+ navigateDown();
192
+ return;
193
+ }
194
+ if (key === 'k' || key === '\x1b[A') {
195
+ navigateUp();
196
+ return;
197
+ }
198
+ if (key === '/') {
199
+ // Enter insert mode without typing
200
+ switchMode('insert');
201
+ return;
202
+ }
203
+ // Any other printable — enter insert mode and type the char
204
+ if (key.length === 1 && key >= ' ') {
205
+ mode = 'insert';
206
+ typeChar(key);
207
+ return;
208
+ }
209
+ return;
210
+ }
211
+ // ── Insert mode ────────────────────────────────────────
212
+ if (key === '\x1b') {
213
+ // Escape in insert mode — return to normal
214
+ switchMode('normal');
215
+ return;
216
+ }
217
+ if (key === '\x1b[A') {
218
+ navigateUp();
219
+ return;
220
+ }
221
+ if (key === '\x1b[B') {
222
+ navigateDown();
223
+ return;
224
+ }
225
+ if (key === '\x7f' || key === '\b') {
226
+ if (query.length > 0) {
227
+ const prevLineCount = renderLineCount();
228
+ query = query.slice(0, -1);
229
+ applyFilter();
230
+ clearAndRerender(prevLineCount);
231
+ }
232
+ return;
233
+ }
234
+ // Printable character (all printable keys including j/k)
235
+ if (key.length === 1 && key >= ' ') {
236
+ typeChar(key);
237
+ }
238
+ });
239
+ });
240
+ }
241
+ //# sourceMappingURL=filter-interactive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-interactive.js","sourceRoot":"","sources":["../../../src/core/forms/filter-interactive.ts"],"names":[],"mappings":"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"}
@@ -1,35 +1,5 @@
1
- import type { FieldOptions } from './types.js';
2
- import type { BijouContext } from '../../ports/context.js';
3
- /**
4
- * Single option in a filterable select list.
5
- *
6
- * @typeParam T - Type of the option's value.
7
- */
8
- export interface FilterOption<T> {
9
- /** Display label shown in the option list. */
10
- label: string;
11
- /** Value returned when this option is selected. */
12
- value: T;
13
- /** Additional search keywords that match this option during filtering. */
14
- keywords?: string[];
15
- }
16
- /**
17
- * Options for the filterable select field.
18
- *
19
- * @typeParam T - Type of each option's value.
20
- */
21
- export interface FilterOptions<T> extends FieldOptions<T> {
22
- /** List of filterable options. */
23
- options: FilterOption<T>[];
24
- /** Placeholder text shown in the filter input when empty. */
25
- placeholder?: string;
26
- /** Maximum number of options visible at once. Default: 7. */
27
- maxVisible?: number;
28
- /** Custom match function for filtering. Defaults to case-insensitive label/keyword substring match. */
29
- match?: (query: string, option: FilterOption<T>) => boolean;
30
- /** Bijou context for IO, styling, and mode detection. */
31
- ctx?: BijouContext;
32
- }
1
+ export type { FilterOption, FilterOptions } from './filter-interactive.js';
2
+ import type { FilterOptions } from './filter-interactive.js';
33
3
  /**
34
4
  * Prompt the user to choose one item from a filterable list.
35
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../src/core/forms/filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAI3D;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,KAAK,EAAE,CAAC,CAAC;IACT,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,CAAE,SAAQ,YAAY,CAAC,CAAC,CAAC;IACvD,kCAAkC;IAClC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3B,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uGAAuG;IACvG,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC;IAC5D,yDAAyD;IACzD,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB;AAoBD;;;;;;;;;;;GAWG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAarE"}
1
+ {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../src/core/forms/filter.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;;;;;;;;;GAWG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAarE"}
@@ -1,23 +1,6 @@
1
1
  import { resolveCtx } from '../resolve-ctx.js';
2
- import { formatFormTitle, renderNumberedOptions, terminalRenderer, formDispatch, createStyledFn, createBoldFn } from './form-utils.js';
3
- /**
4
- * Default case-insensitive substring matcher for filter options.
5
- *
6
- * Check the option label first, then fall back to keyword matches.
7
- *
8
- * @param query - User's search input.
9
- * @param option - Option to test against.
10
- * @returns `true` if the query matches the label or any keyword.
11
- */
12
- function defaultMatch(query, option) {
13
- const q = query.toLowerCase();
14
- if (option.label.toLowerCase().includes(q))
15
- return true;
16
- if (option.keywords) {
17
- return option.keywords.some((kw) => kw.toLowerCase().includes(q));
18
- }
19
- return false;
20
- }
2
+ import { formatFormTitle, renderNumberedOptions, formDispatch } from './form-utils.js';
3
+ import { defaultMatch, interactiveFilter } from './filter-interactive.js';
21
4
  /**
22
5
  * Prompt the user to choose one item from a filterable list.
23
6
  *
@@ -69,152 +52,4 @@ async function fallbackFilter(options, ctx) {
69
52
  }
70
53
  return options.defaultValue ?? options.options[0].value;
71
54
  }
72
- /**
73
- * Render a keyboard-navigable filter select using raw terminal input.
74
- *
75
- * Typing narrows the visible options in real time. Arrow keys navigate,
76
- * Enter confirms, Backspace edits the query, Ctrl+C or Escape cancels.
77
- *
78
- * @param options - Filter field configuration.
79
- * @param ctx - Bijou context.
80
- * @returns The value of the selected (or default/first) option.
81
- */
82
- async function interactiveFilter(options, ctx) {
83
- const noColor = ctx.theme.noColor;
84
- const t = ctx.theme;
85
- const styledFn = createStyledFn(ctx);
86
- const boldFn = createBoldFn(ctx);
87
- const matchFn = options.match ?? defaultMatch;
88
- const maxVisible = options.maxVisible ?? 7;
89
- const term = terminalRenderer(ctx);
90
- let query = '';
91
- let cursor = 0;
92
- let filtered = [...options.options];
93
- function applyFilter() {
94
- if (query === '') {
95
- filtered = [...options.options];
96
- }
97
- else {
98
- filtered = options.options.filter((opt) => matchFn(query, opt));
99
- }
100
- cursor = Math.min(cursor, Math.max(0, filtered.length - 1));
101
- }
102
- function visibleItems() {
103
- return filtered.slice(0, maxVisible);
104
- }
105
- function renderLineCount() {
106
- return 2 + Math.min(filtered.length, maxVisible) + 1; // header + filter input + items + status
107
- }
108
- function render() {
109
- const label = formatFormTitle(options.title, ctx);
110
- term.hideCursor();
111
- term.writeLine(label);
112
- // Filter input
113
- const filterDisplay = query || (options.placeholder ? styledFn(t.theme.semantic.muted, options.placeholder) : '');
114
- ctx.io.write(`\x1b[K ${styledFn(t.theme.semantic.info, '/')} ${filterDisplay}\n`);
115
- // Visible items
116
- const vis = visibleItems();
117
- for (let i = 0; i < vis.length; i++) {
118
- const opt = vis[i];
119
- const isCurrent = i === cursor;
120
- const prefix = isCurrent ? '❯' : ' ';
121
- if (isCurrent && !noColor) {
122
- ctx.io.write(`\x1b[K ${styledFn(t.theme.semantic.info, prefix)} ${boldFn(opt.label)}\n`);
123
- }
124
- else {
125
- ctx.io.write(`\x1b[K ${prefix} ${opt.label}\n`);
126
- }
127
- }
128
- // Status
129
- const status = `${filtered.length}/${options.options.length} items`;
130
- ctx.io.write(`\x1b[K ${styledFn(t.theme.semantic.muted, status)}\n`);
131
- }
132
- function clearRender() {
133
- const total = renderLineCount();
134
- term.moveUp(total);
135
- }
136
- function clearAndRerender(prevLineCount) {
137
- term.moveUp(prevLineCount);
138
- term.clearBlock(prevLineCount);
139
- render();
140
- }
141
- function cleanup() {
142
- const total = renderLineCount();
143
- clearRender();
144
- term.clearBlock(total);
145
- const selected = filtered[cursor];
146
- const selectedLabel = selected ? selected.label : '(none)';
147
- const label = formatFormTitle(options.title, ctx) + ' ' + styledFn(t.theme.semantic.info, selectedLabel);
148
- ctx.io.write(`\x1b[K${label}\n`);
149
- term.showCursor();
150
- }
151
- render();
152
- return new Promise((resolve) => {
153
- const handle = ctx.io.rawInput((key) => {
154
- if (key === '\r' || key === '\n') {
155
- // Enter — select
156
- handle.dispose();
157
- cleanup();
158
- resolve(filtered[cursor]?.value ?? options.defaultValue ?? options.options[0].value);
159
- return;
160
- }
161
- if (key === '\x03' || key === '\x1b') {
162
- // Ctrl+C or Escape — cancel
163
- // Note: bare \x1b may false-trigger on slow connections where escape
164
- // sequences arrive as separate bytes. Timer-based disambiguation is a
165
- // separate future improvement.
166
- handle.dispose();
167
- cleanup();
168
- resolve(options.defaultValue ?? options.options[0].value);
169
- return;
170
- }
171
- if (key === '\x1b[A' || key === 'k') {
172
- // Up
173
- if (filtered.length === 0)
174
- return;
175
- cursor = (cursor - 1 + filtered.length) % filtered.length;
176
- clearRender();
177
- render();
178
- return;
179
- }
180
- if (key === '\x1b[B' || key === 'j') {
181
- // Down — but only when query is empty (j is a printable char for filtering)
182
- if (key === 'j' && query === '') {
183
- // Start filtering with 'j'
184
- query += key;
185
- applyFilter();
186
- clearRender();
187
- render();
188
- return;
189
- }
190
- if (key === '\x1b[B') {
191
- if (filtered.length === 0)
192
- return;
193
- cursor = (cursor + 1) % filtered.length;
194
- clearRender();
195
- render();
196
- return;
197
- }
198
- // j when query is non-empty — fall through to printable handler
199
- }
200
- if (key === '\x7f' || key === '\b') {
201
- // Backspace
202
- if (query.length > 0) {
203
- const prevLineCount = renderLineCount();
204
- query = query.slice(0, -1);
205
- applyFilter();
206
- clearAndRerender(prevLineCount);
207
- }
208
- return;
209
- }
210
- // Printable character (filter input)
211
- if (key.length === 1 && key >= ' ') {
212
- const prevLineCount = renderLineCount();
213
- query += key;
214
- applyFilter();
215
- clearAndRerender(prevLineCount);
216
- }
217
- });
218
- });
219
- }
220
55
  //# sourceMappingURL=filter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"filter.js","sourceRoot":"","sources":["../../../src/core/forms/filter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../../../src/core/forms/filter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAI1E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAI,OAAyB;IACvD,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC,YAAY,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAEpC,OAAO,YAAY,CACjB,GAAG,EACH,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC,CAAC,EACpC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAClC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,KAAK,UAAU,cAAc,CAAI,OAAyB,EAAE,GAAiB;IAC3E,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACzD,qBAAqB,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAE5C,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7E,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAE9B,8BAA8B;IAC9B,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;IACtC,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;IAED,uBAAuB;IACvB,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,YAAY,CAAC;QAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACrE,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC,KAAK,CAAC;IACpC,CAAC;IAED,OAAO,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Interactive textarea editor state machine.
3
+ *
4
+ * Renders a scrollable multi-line editor with cursor navigation,
5
+ * optional line numbers, placeholder text, and max-length guard.
6
+ * Ctrl+D submits; Ctrl+C or Escape cancels.
7
+ */
8
+ import type { FieldOptions } from './types.js';
9
+ import type { BijouContext } from '../../ports/context.js';
10
+ /**
11
+ * Options for the multi-line textarea field.
12
+ */
13
+ export interface TextareaOptions extends FieldOptions<string> {
14
+ /** Placeholder text shown when the textarea is empty. */
15
+ placeholder?: string;
16
+ /** Maximum character count (including newlines). */
17
+ maxLength?: number;
18
+ /** Display line numbers in the gutter. Default: false. */
19
+ showLineNumbers?: boolean;
20
+ /** Visible editor height in lines. Default: 6. */
21
+ height?: number;
22
+ /** Render width in columns. Default: 80. */
23
+ width?: number;
24
+ /** Bijou context for IO, styling, and mode detection. */
25
+ ctx?: BijouContext;
26
+ }
27
+ /**
28
+ * Render a full interactive textarea editor using raw terminal input.
29
+ *
30
+ * Supports arrow-key cursor movement, scrolling, line wrapping,
31
+ * optional line numbers, placeholder text, and a max-length guard.
32
+ * Ctrl+D submits; Ctrl+C or Escape cancels.
33
+ *
34
+ * @param options - Textarea field configuration.
35
+ * @param ctx - Bijou context.
36
+ * @returns The entered text (newline-joined), or the default value on cancel.
37
+ */
38
+ export declare function interactiveTextarea(options: TextareaOptions, ctx: BijouContext): Promise<string>;
39
+ //# sourceMappingURL=textarea-editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textarea-editor.d.ts","sourceRoot":"","sources":["../../../src/core/forms/textarea-editor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,YAAY,CAAC,MAAM,CAAC;IAC3D,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,GAAG,CAAC,EAAE,YAAY,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAsMtG"}