@crustjs/prompts 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +966 -0
- package/dist/index.js +1002 -0
- package/package.json +53 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,966 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of a fuzzy match against a single candidate.
|
|
3
|
+
*/
|
|
4
|
+
interface FuzzyMatchResult {
|
|
5
|
+
/** Whether the candidate matches the query */
|
|
6
|
+
readonly match: boolean;
|
|
7
|
+
/** Match quality score — higher is better. 0 if no match. */
|
|
8
|
+
readonly score: number;
|
|
9
|
+
/** Indices of matched characters in the candidate string */
|
|
10
|
+
readonly indices: readonly number[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A fuzzy-filtered item with its match metadata.
|
|
14
|
+
*/
|
|
15
|
+
interface FuzzyFilterResult<T> {
|
|
16
|
+
/** The original item */
|
|
17
|
+
readonly item: {
|
|
18
|
+
readonly label: string;
|
|
19
|
+
readonly value: T;
|
|
20
|
+
};
|
|
21
|
+
/** Match quality score */
|
|
22
|
+
readonly score: number;
|
|
23
|
+
/** Indices of matched characters in the label */
|
|
24
|
+
readonly indices: readonly number[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Test whether a query fuzzy-matches a candidate string.
|
|
28
|
+
*
|
|
29
|
+
* Each character in `query` must appear in `candidate` in order (but not
|
|
30
|
+
* necessarily contiguously). Matching is case-insensitive.
|
|
31
|
+
*
|
|
32
|
+
* The score rewards:
|
|
33
|
+
* - Consecutive matched characters (contiguity bonus)
|
|
34
|
+
* - Matches at the start of the string
|
|
35
|
+
* - Matches at word boundaries (after space, `-`, `_`, `.`)
|
|
36
|
+
*
|
|
37
|
+
* @param query - The search query
|
|
38
|
+
* @param candidate - The string to match against
|
|
39
|
+
* @returns Match result with boolean, score, and matched character indices
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* fuzzyMatch("abc", "alphabet cookie"); // { match: true, score: ..., indices: [0, 9, 10] }
|
|
44
|
+
* fuzzyMatch("xyz", "hello"); // { match: false, score: 0, indices: [] }
|
|
45
|
+
* fuzzyMatch("", "anything"); // { match: true, score: 0, indices: [] }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
declare function fuzzyMatch(query: string, candidate: string): FuzzyMatchResult;
|
|
49
|
+
/**
|
|
50
|
+
* Filter and sort a list of labeled items by fuzzy-matching against a query.
|
|
51
|
+
*
|
|
52
|
+
* Returns only items that match, sorted by score descending (best matches first).
|
|
53
|
+
* An empty query returns all items (each with score 0 and empty indices).
|
|
54
|
+
*
|
|
55
|
+
* @param query - The search query
|
|
56
|
+
* @param items - Array of items with `label` and `value` properties
|
|
57
|
+
* @returns Matched items sorted by score (highest first)
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* const results = fuzzyFilter("ts", [
|
|
62
|
+
* { label: "TypeScript", value: "ts" },
|
|
63
|
+
* { label: "JavaScript", value: "js" },
|
|
64
|
+
* { label: "Rust", value: "rs" },
|
|
65
|
+
* ]);
|
|
66
|
+
* // Returns TypeScript and Rust (both contain "t" then "s")
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
declare function fuzzyFilter<T>(query: string, items: readonly {
|
|
70
|
+
readonly label: string;
|
|
71
|
+
readonly value: T;
|
|
72
|
+
}[]): FuzzyFilterResult<T>[];
|
|
73
|
+
import { StyleFn } from "@crustjs/style";
|
|
74
|
+
/**
|
|
75
|
+
* Style slots for all prompt elements.
|
|
76
|
+
*
|
|
77
|
+
* Each slot is a `StyleFn` — a `(text: string) => string` function that
|
|
78
|
+
* applies ANSI styling. The theme controls the visual appearance of every
|
|
79
|
+
* prompt component.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* const theme: PromptTheme = {
|
|
84
|
+
* prefix: cyan,
|
|
85
|
+
* message: bold,
|
|
86
|
+
* placeholder: dim,
|
|
87
|
+
* // ...
|
|
88
|
+
* };
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
interface PromptTheme {
|
|
92
|
+
/** Prefix glyph before the prompt message (e.g., "?" or "◆") */
|
|
93
|
+
readonly prefix: StyleFn;
|
|
94
|
+
/** The prompt message text */
|
|
95
|
+
readonly message: StyleFn;
|
|
96
|
+
/** Placeholder text shown when input is empty */
|
|
97
|
+
readonly placeholder: StyleFn;
|
|
98
|
+
/** Cursor indicator in selection lists */
|
|
99
|
+
readonly cursor: StyleFn;
|
|
100
|
+
/** Selected / active item styling */
|
|
101
|
+
readonly selected: StyleFn;
|
|
102
|
+
/** Unselected / inactive item styling */
|
|
103
|
+
readonly unselected: StyleFn;
|
|
104
|
+
/** Validation error messages */
|
|
105
|
+
readonly error: StyleFn;
|
|
106
|
+
/** Success / confirmed value styling */
|
|
107
|
+
readonly success: StyleFn;
|
|
108
|
+
/** Hint text (e.g., keybinding hints, choice hints) */
|
|
109
|
+
readonly hint: StyleFn;
|
|
110
|
+
/** Spinner frame characters */
|
|
111
|
+
readonly spinner: StyleFn;
|
|
112
|
+
/** Matched characters in fuzzy filter results */
|
|
113
|
+
readonly filterMatch: StyleFn;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Partial version of `PromptTheme` for user overrides.
|
|
117
|
+
* Users only need to specify the slots they want to customize.
|
|
118
|
+
*/
|
|
119
|
+
type PartialPromptTheme = Partial<PromptTheme>;
|
|
120
|
+
/**
|
|
121
|
+
* A choice item for select, multiselect, and filter prompts.
|
|
122
|
+
*
|
|
123
|
+
* Accepts either a plain string (where `label === value`) or an object
|
|
124
|
+
* with explicit label, value, and optional hint.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```ts
|
|
128
|
+
* // String choices
|
|
129
|
+
* const colors: Choice<string>[] = ["red", "green", "blue"];
|
|
130
|
+
*
|
|
131
|
+
* // Object choices with typed values
|
|
132
|
+
* const ports: Choice<number>[] = [
|
|
133
|
+
* { label: "HTTP", value: 80 },
|
|
134
|
+
* { label: "HTTPS", value: 443, hint: "recommended" },
|
|
135
|
+
* ];
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
type Choice<T> = string | {
|
|
139
|
+
readonly label: string;
|
|
140
|
+
readonly value: T;
|
|
141
|
+
readonly hint?: string;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Result of a validation function.
|
|
145
|
+
* - `true` means valid
|
|
146
|
+
* - A `string` is the error message to display
|
|
147
|
+
*/
|
|
148
|
+
type ValidateResult = true | string;
|
|
149
|
+
/**
|
|
150
|
+
* Validation function for prompt values.
|
|
151
|
+
* May be synchronous or asynchronous.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```ts
|
|
155
|
+
* const validateEmail: ValidateFn<string> = (value) => {
|
|
156
|
+
* if (!value.includes("@")) return "Must be a valid email address";
|
|
157
|
+
* return true;
|
|
158
|
+
* };
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
type ValidateFn<T> = (value: T) => ValidateResult | Promise<ValidateResult>;
|
|
162
|
+
/**
|
|
163
|
+
* Calculate the scroll offset to keep the cursor within the visible viewport.
|
|
164
|
+
*
|
|
165
|
+
* Used by select, multiselect, and filter prompts to manage scrolling
|
|
166
|
+
* when the number of items exceeds the visible viewport.
|
|
167
|
+
*
|
|
168
|
+
* @param cursor - Current cursor position in the list
|
|
169
|
+
* @param scrollOffset - Current scroll offset
|
|
170
|
+
* @param totalItems - Total number of items in the list
|
|
171
|
+
* @param maxVisible - Maximum number of visible items in the viewport
|
|
172
|
+
* @returns The new scroll offset
|
|
173
|
+
*/
|
|
174
|
+
declare function calculateScrollOffset(cursor: number, scrollOffset: number, totalItems: number, maxVisible: number): number;
|
|
175
|
+
/**
|
|
176
|
+
* A normalized choice item with explicit label, value, and optional hint.
|
|
177
|
+
* This is the internal representation used by select, multiselect, and filter prompts.
|
|
178
|
+
*/
|
|
179
|
+
interface NormalizedChoice<T> {
|
|
180
|
+
readonly label: string;
|
|
181
|
+
readonly value: T;
|
|
182
|
+
readonly hint?: string;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Normalize an array of choices into a consistent `{ label, value, hint? }` format.
|
|
186
|
+
*
|
|
187
|
+
* String choices are converted to `{ label: str, value: str }`.
|
|
188
|
+
* Object choices are passed through as-is.
|
|
189
|
+
*
|
|
190
|
+
* @param choices - Array of string or object choices
|
|
191
|
+
* @returns Array of normalized choice objects
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```ts
|
|
195
|
+
* // String choices
|
|
196
|
+
* normalizeChoices(["red", "green", "blue"]);
|
|
197
|
+
* // => [{ label: "red", value: "red" }, { label: "green", value: "green" }, ...]
|
|
198
|
+
*
|
|
199
|
+
* // Object choices
|
|
200
|
+
* normalizeChoices([{ label: "HTTP", value: 80 }]);
|
|
201
|
+
* // => [{ label: "HTTP", value: 80 }]
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
declare function normalizeChoices<T>(choices: readonly Choice<T>[]): NormalizedChoice<T>[];
|
|
205
|
+
/**
|
|
206
|
+
* Default prompt theme with a polished, gum/clack-inspired aesthetic.
|
|
207
|
+
*
|
|
208
|
+
* Uses `@crustjs/style` color functions for ANSI output that respects
|
|
209
|
+
* terminal capability detection (NO_COLOR, non-TTY graceful degradation).
|
|
210
|
+
*/
|
|
211
|
+
declare const defaultTheme: PromptTheme;
|
|
212
|
+
/**
|
|
213
|
+
* Create a complete theme by merging partial overrides onto the default theme.
|
|
214
|
+
*
|
|
215
|
+
* Use this to build a reusable theme object, then apply it globally
|
|
216
|
+
* with {@link setTheme}.
|
|
217
|
+
*
|
|
218
|
+
* @param overrides - Partial theme slots to override. Only specified slots
|
|
219
|
+
* are replaced; all others retain their default values.
|
|
220
|
+
* @returns A complete `PromptTheme` with all slots defined.
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```ts
|
|
224
|
+
* import { createTheme, setTheme } from "@crustjs/prompts";
|
|
225
|
+
* import { magenta, cyan } from "@crustjs/style";
|
|
226
|
+
*
|
|
227
|
+
* const myTheme = createTheme({
|
|
228
|
+
* prefix: magenta,
|
|
229
|
+
* success: cyan,
|
|
230
|
+
* });
|
|
231
|
+
*
|
|
232
|
+
* // Apply globally so all prompts use it
|
|
233
|
+
* setTheme(myTheme);
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
declare function createTheme(overrides?: PartialPromptTheme): PromptTheme;
|
|
237
|
+
/**
|
|
238
|
+
* Set the global theme applied to all prompts.
|
|
239
|
+
*
|
|
240
|
+
* Accepts either a complete `PromptTheme` (e.g., from {@link createTheme})
|
|
241
|
+
* or a `PartialPromptTheme` with only the slots you want to override.
|
|
242
|
+
* Unspecified slots fall back to {@link defaultTheme}.
|
|
243
|
+
*
|
|
244
|
+
* Call with no arguments or `undefined` to clear the global theme.
|
|
245
|
+
*
|
|
246
|
+
* @param theme - Theme or partial overrides to apply globally.
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```ts
|
|
250
|
+
* import { setTheme } from "@crustjs/prompts";
|
|
251
|
+
* import { magenta, cyan } from "@crustjs/style";
|
|
252
|
+
*
|
|
253
|
+
* // Set once at app bootstrap
|
|
254
|
+
* setTheme({ prefix: magenta, success: cyan });
|
|
255
|
+
*
|
|
256
|
+
* // Clear the global theme
|
|
257
|
+
* setTheme();
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
declare function setTheme(theme?: PartialPromptTheme): void;
|
|
261
|
+
/**
|
|
262
|
+
* Get the current global theme with all slots resolved.
|
|
263
|
+
*
|
|
264
|
+
* Returns {@link defaultTheme} if no global theme has been set.
|
|
265
|
+
*
|
|
266
|
+
* @returns The complete resolved global `PromptTheme`.
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* ```ts
|
|
270
|
+
* import { getTheme, setTheme } from "@crustjs/prompts";
|
|
271
|
+
*
|
|
272
|
+
* setTheme({ prefix: magenta });
|
|
273
|
+
* const theme = getTheme();
|
|
274
|
+
* // theme.prefix === magenta
|
|
275
|
+
* // theme.message === bold (default)
|
|
276
|
+
* ```
|
|
277
|
+
*/
|
|
278
|
+
declare function getTheme(): PromptTheme;
|
|
279
|
+
/**
|
|
280
|
+
* Structured keypress event parsed from raw terminal input.
|
|
281
|
+
*/
|
|
282
|
+
interface KeypressEvent {
|
|
283
|
+
/** The character string for printable keys, or empty string for special keys */
|
|
284
|
+
readonly char: string;
|
|
285
|
+
/** Key name (e.g., "return", "backspace", "up", "down", "left", "right", "tab") */
|
|
286
|
+
readonly name: string;
|
|
287
|
+
/** Whether Ctrl was held */
|
|
288
|
+
readonly ctrl: boolean;
|
|
289
|
+
/** Whether Meta/Alt was held */
|
|
290
|
+
readonly meta: boolean;
|
|
291
|
+
/** Whether Shift was held */
|
|
292
|
+
readonly shift: boolean;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Symbol used internally to discriminate submit results from state updates.
|
|
296
|
+
* Using a symbol prevents collisions with user-defined state types.
|
|
297
|
+
*/
|
|
298
|
+
declare const SUBMIT: unique symbol;
|
|
299
|
+
/**
|
|
300
|
+
* A submit action wrapping the final value.
|
|
301
|
+
*/
|
|
302
|
+
interface SubmitResult<T> {
|
|
303
|
+
readonly [SUBMIT]: T;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Create a submit result to resolve the prompt with the given value.
|
|
307
|
+
*
|
|
308
|
+
* @param value - The value to resolve the prompt with
|
|
309
|
+
* @returns A submit action object
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```ts
|
|
313
|
+
* handleKey: (key, state) => {
|
|
314
|
+
* if (key.name === "return") return submit(state.value);
|
|
315
|
+
* return { ...state, value: state.value + key.char };
|
|
316
|
+
* }
|
|
317
|
+
* ```
|
|
318
|
+
*/
|
|
319
|
+
declare function submit<T>(value: T): SubmitResult<T>;
|
|
320
|
+
/**
|
|
321
|
+
* Result of a keypress handler.
|
|
322
|
+
* - Return updated state to continue the prompt
|
|
323
|
+
* - Return `submit(value)` to resolve the prompt with a value
|
|
324
|
+
*/
|
|
325
|
+
type HandleKeyResult<
|
|
326
|
+
S,
|
|
327
|
+
T
|
|
328
|
+
> = S | SubmitResult<T>;
|
|
329
|
+
/**
|
|
330
|
+
* Configuration for `runPrompt` — each prompt provides these functions
|
|
331
|
+
* to define its behavior.
|
|
332
|
+
*/
|
|
333
|
+
interface PromptConfig<
|
|
334
|
+
S,
|
|
335
|
+
T
|
|
336
|
+
> {
|
|
337
|
+
/** Render the current state to a string (may contain newlines) */
|
|
338
|
+
readonly render: (state: S, theme: PromptTheme) => string;
|
|
339
|
+
/** Handle a keypress event — return new state or `submit(value)` to resolve */
|
|
340
|
+
readonly handleKey: (key: KeypressEvent, state: S) => HandleKeyResult<S, T> | Promise<HandleKeyResult<S, T>>;
|
|
341
|
+
/** Initial state for the prompt */
|
|
342
|
+
readonly initialState: S;
|
|
343
|
+
/** Resolved theme for this prompt */
|
|
344
|
+
readonly theme: PromptTheme;
|
|
345
|
+
/**
|
|
346
|
+
* Optional: render the final submitted state.
|
|
347
|
+
* Called after submit with the final state and submitted value.
|
|
348
|
+
* If not provided, the last render output is left on screen.
|
|
349
|
+
*/
|
|
350
|
+
readonly renderSubmitted?: (state: S, value: T, theme: PromptTheme) => string;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Error thrown when a prompt requires an interactive TTY but none is available.
|
|
354
|
+
*/
|
|
355
|
+
declare class NonInteractiveError extends Error {
|
|
356
|
+
constructor(message?: string);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Error thrown when the user cancels a prompt with Ctrl+C.
|
|
360
|
+
*/
|
|
361
|
+
declare class CancelledError extends Error {
|
|
362
|
+
constructor(message?: string);
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Check that stdin is an interactive TTY.
|
|
366
|
+
* @throws {NonInteractiveError} when stdin is not a TTY
|
|
367
|
+
*/
|
|
368
|
+
declare function assertTTY(): void;
|
|
369
|
+
/**
|
|
370
|
+
* Run an interactive prompt with the given configuration.
|
|
371
|
+
*
|
|
372
|
+
* Manages the full terminal lifecycle:
|
|
373
|
+
* 1. Asserts stdin is a TTY
|
|
374
|
+
* 2. Enables raw mode and hides cursor
|
|
375
|
+
* 3. Renders initial state
|
|
376
|
+
* 4. Listens for keypress events, delegating to `handleKey`
|
|
377
|
+
* 5. Re-renders on state changes
|
|
378
|
+
* 6. On submit, renders final state, cleans up, and resolves
|
|
379
|
+
*
|
|
380
|
+
* Output is written to `process.stderr` so prompt UI doesn't pollute
|
|
381
|
+
* piped stdout.
|
|
382
|
+
*
|
|
383
|
+
* @param config - Prompt configuration (render, handleKey, initialState, theme)
|
|
384
|
+
* @returns Promise resolving to the user's submitted value
|
|
385
|
+
* @throws {NonInteractiveError} when stdin is not a TTY
|
|
386
|
+
*
|
|
387
|
+
* @example
|
|
388
|
+
* ```ts
|
|
389
|
+
* const value = await runPrompt({
|
|
390
|
+
* initialState: { value: "", submitted: false },
|
|
391
|
+
* theme: resolveTheme(),
|
|
392
|
+
* render: (state, theme) => `${theme.prefix("?")} Enter value: ${state.value}`,
|
|
393
|
+
* handleKey: (key, state) => {
|
|
394
|
+
* if (key.name === "return") return { submit: state.value };
|
|
395
|
+
* return { ...state, value: state.value + key.char };
|
|
396
|
+
* },
|
|
397
|
+
* });
|
|
398
|
+
* ```
|
|
399
|
+
*/
|
|
400
|
+
declare function runPrompt<
|
|
401
|
+
S,
|
|
402
|
+
T
|
|
403
|
+
>(config: PromptConfig<S, T>): Promise<T>;
|
|
404
|
+
/**
|
|
405
|
+
* Options for the {@link confirm} prompt.
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* ```ts
|
|
409
|
+
* const shouldContinue = await confirm({
|
|
410
|
+
* message: "Do you want to continue?",
|
|
411
|
+
* });
|
|
412
|
+
* ```
|
|
413
|
+
*
|
|
414
|
+
* @example
|
|
415
|
+
* ```ts
|
|
416
|
+
* const agreed = await confirm({
|
|
417
|
+
* message: "Accept terms?",
|
|
418
|
+
* active: "Agree",
|
|
419
|
+
* inactive: "Decline",
|
|
420
|
+
* default: false,
|
|
421
|
+
* });
|
|
422
|
+
* ```
|
|
423
|
+
*/
|
|
424
|
+
interface ConfirmOptions {
|
|
425
|
+
/** The prompt message displayed to the user */
|
|
426
|
+
readonly message: string;
|
|
427
|
+
/** Default value when the user presses Enter without toggling (defaults to `true`) */
|
|
428
|
+
readonly default?: boolean;
|
|
429
|
+
/** Initial value — if provided, the prompt is skipped and this value is returned immediately */
|
|
430
|
+
readonly initial?: boolean;
|
|
431
|
+
/** Label for the affirmative option (defaults to `"Yes"`) */
|
|
432
|
+
readonly active?: string;
|
|
433
|
+
/** Label for the negative option (defaults to `"No"`) */
|
|
434
|
+
readonly inactive?: string;
|
|
435
|
+
/** Per-prompt theme overrides */
|
|
436
|
+
readonly theme?: PartialPromptTheme;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Display an interactive yes/no confirmation prompt.
|
|
440
|
+
*
|
|
441
|
+
* Shows two side-by-side options (default: "Yes" / "No") that the user
|
|
442
|
+
* toggles with arrow keys, h/l, y/n, or Tab, then confirms with Enter.
|
|
443
|
+
*
|
|
444
|
+
* If `initial` is provided, the prompt is skipped and the value is returned
|
|
445
|
+
* immediately — useful for prefilling from CLI flags.
|
|
446
|
+
*
|
|
447
|
+
* @param options - Confirm prompt configuration
|
|
448
|
+
* @returns The user's boolean selection
|
|
449
|
+
* @throws {NonInteractiveError} when stdin is not a TTY and no `initial` is provided
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* ```ts
|
|
453
|
+
* const proceed = await confirm({
|
|
454
|
+
* message: "Do you want to continue?",
|
|
455
|
+
* });
|
|
456
|
+
* ```
|
|
457
|
+
*
|
|
458
|
+
* @example
|
|
459
|
+
* ```ts
|
|
460
|
+
* // Custom labels with default value
|
|
461
|
+
* const accepted = await confirm({
|
|
462
|
+
* message: "Accept the license?",
|
|
463
|
+
* active: "Accept",
|
|
464
|
+
* inactive: "Decline",
|
|
465
|
+
* default: false,
|
|
466
|
+
* });
|
|
467
|
+
* ```
|
|
468
|
+
*
|
|
469
|
+
* @example
|
|
470
|
+
* ```ts
|
|
471
|
+
* // Skip prompt when flag is provided
|
|
472
|
+
* const yes = await confirm({
|
|
473
|
+
* message: "Continue?",
|
|
474
|
+
* initial: flags.yes,
|
|
475
|
+
* });
|
|
476
|
+
* ```
|
|
477
|
+
*/
|
|
478
|
+
declare function confirm(options: ConfirmOptions): Promise<boolean>;
|
|
479
|
+
/**
|
|
480
|
+
* Options for the {@link filter} prompt.
|
|
481
|
+
*
|
|
482
|
+
* @example
|
|
483
|
+
* ```ts
|
|
484
|
+
* const lang = await filter({
|
|
485
|
+
* message: "Search for a language",
|
|
486
|
+
* choices: ["TypeScript", "JavaScript", "Rust", "Python", "Go"],
|
|
487
|
+
* });
|
|
488
|
+
* ```
|
|
489
|
+
*
|
|
490
|
+
* @example
|
|
491
|
+
* ```ts
|
|
492
|
+
* const pkg = await filter<{ name: string; version: string }>({
|
|
493
|
+
* message: "Find a package",
|
|
494
|
+
* choices: [
|
|
495
|
+
* { label: "react", value: { name: "react", version: "18.2" } },
|
|
496
|
+
* { label: "vue", value: { name: "vue", version: "3.3" } },
|
|
497
|
+
* ],
|
|
498
|
+
* placeholder: "Type to filter...",
|
|
499
|
+
* });
|
|
500
|
+
* ```
|
|
501
|
+
*/
|
|
502
|
+
interface FilterOptions<T> {
|
|
503
|
+
/** The prompt message displayed to the user */
|
|
504
|
+
readonly message: string;
|
|
505
|
+
/** List of choices — strings or `{ label, value, hint? }` objects */
|
|
506
|
+
readonly choices: readonly Choice<T>[];
|
|
507
|
+
/** Initial value — if provided, the prompt is skipped and this value is returned immediately */
|
|
508
|
+
readonly initial?: T;
|
|
509
|
+
/** Placeholder text shown when the query input is empty */
|
|
510
|
+
readonly placeholder?: string;
|
|
511
|
+
/** Maximum number of visible filtered results before scrolling (defaults to 10) */
|
|
512
|
+
readonly maxVisible?: number;
|
|
513
|
+
/** Per-prompt theme overrides */
|
|
514
|
+
readonly theme?: PartialPromptTheme;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Display an interactive fuzzy-filter prompt over a list of choices.
|
|
518
|
+
*
|
|
519
|
+
* Type to filter the list using fuzzy matching. Navigate filtered results
|
|
520
|
+
* with Up/Down arrows, confirm with Enter. Matched characters are
|
|
521
|
+
* highlighted in the results.
|
|
522
|
+
*
|
|
523
|
+
* If `initial` is provided, the prompt is skipped and the value is returned
|
|
524
|
+
* immediately — useful for prefilling from CLI flags.
|
|
525
|
+
*
|
|
526
|
+
* @param options - Filter prompt configuration
|
|
527
|
+
* @returns The value of the selected choice
|
|
528
|
+
* @throws {NonInteractiveError} when stdin is not a TTY and no `initial` is provided
|
|
529
|
+
*
|
|
530
|
+
* @example
|
|
531
|
+
* ```ts
|
|
532
|
+
* const lang = await filter({
|
|
533
|
+
* message: "Search for a language",
|
|
534
|
+
* choices: ["TypeScript", "JavaScript", "Rust", "Python", "Go"],
|
|
535
|
+
* });
|
|
536
|
+
* ```
|
|
537
|
+
*
|
|
538
|
+
* @example
|
|
539
|
+
* ```ts
|
|
540
|
+
* const pkg = await filter<{ name: string; version: string }>({
|
|
541
|
+
* message: "Find a package",
|
|
542
|
+
* choices: [
|
|
543
|
+
* { label: "react", value: { name: "react", version: "18.2" } },
|
|
544
|
+
* { label: "vue", value: { name: "vue", version: "3.3" } },
|
|
545
|
+
* ],
|
|
546
|
+
* placeholder: "Type to filter...",
|
|
547
|
+
* });
|
|
548
|
+
* ```
|
|
549
|
+
*
|
|
550
|
+
* @example
|
|
551
|
+
* ```ts
|
|
552
|
+
* // Skip prompt when flag is provided
|
|
553
|
+
* const tool = await filter({
|
|
554
|
+
* message: "Pick a tool",
|
|
555
|
+
* choices: ["prettier", "eslint", "biome"],
|
|
556
|
+
* initial: flags.tool,
|
|
557
|
+
* });
|
|
558
|
+
* ```
|
|
559
|
+
*/
|
|
560
|
+
declare function filter<T>(options: FilterOptions<T>): Promise<T>;
|
|
561
|
+
/**
|
|
562
|
+
* Options for the {@link input} prompt.
|
|
563
|
+
*
|
|
564
|
+
* @example
|
|
565
|
+
* ```ts
|
|
566
|
+
* const name = await input({
|
|
567
|
+
* message: "What is your name?",
|
|
568
|
+
* placeholder: "Enter your name",
|
|
569
|
+
* validate: (v) => v.length > 0 || "Name is required",
|
|
570
|
+
* });
|
|
571
|
+
* ```
|
|
572
|
+
*/
|
|
573
|
+
interface InputOptions {
|
|
574
|
+
/** The prompt message displayed to the user */
|
|
575
|
+
readonly message: string;
|
|
576
|
+
/** Placeholder text shown when the input is empty */
|
|
577
|
+
readonly placeholder?: string;
|
|
578
|
+
/** Default value used when the user submits an empty input */
|
|
579
|
+
readonly default?: string;
|
|
580
|
+
/** Initial value — if provided, the prompt is skipped and this value is returned immediately */
|
|
581
|
+
readonly initial?: string;
|
|
582
|
+
/** Validation function — return `true` for valid, or a string error message */
|
|
583
|
+
readonly validate?: ValidateFn<string>;
|
|
584
|
+
/** Per-prompt theme overrides */
|
|
585
|
+
readonly theme?: PartialPromptTheme;
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Display an interactive single-line text input prompt.
|
|
589
|
+
*
|
|
590
|
+
* Supports placeholder text, default values, validation with inline error
|
|
591
|
+
* display, and full cursor editing (insert, delete, arrow keys, home/end).
|
|
592
|
+
*
|
|
593
|
+
* If `initial` is provided, the prompt is skipped and the value is returned
|
|
594
|
+
* immediately — useful for prefilling from CLI flags.
|
|
595
|
+
*
|
|
596
|
+
* @param options - Input prompt configuration
|
|
597
|
+
* @returns The user's entered text
|
|
598
|
+
* @throws {NonInteractiveError} when stdin is not a TTY and no `initial` is provided
|
|
599
|
+
*
|
|
600
|
+
* @example
|
|
601
|
+
* ```ts
|
|
602
|
+
* const name = await input({
|
|
603
|
+
* message: "What is your name?",
|
|
604
|
+
* placeholder: "John Doe",
|
|
605
|
+
* validate: (v) => v.length > 0 || "Name cannot be empty",
|
|
606
|
+
* });
|
|
607
|
+
* ```
|
|
608
|
+
*
|
|
609
|
+
* @example
|
|
610
|
+
* ```ts
|
|
611
|
+
* // Skip prompt when flag is provided
|
|
612
|
+
* const name = await input({
|
|
613
|
+
* message: "Name?",
|
|
614
|
+
* initial: flags.name,
|
|
615
|
+
* });
|
|
616
|
+
* ```
|
|
617
|
+
*/
|
|
618
|
+
declare function input(options: InputOptions): Promise<string>;
|
|
619
|
+
/**
|
|
620
|
+
* Options for the {@link multiselect} prompt.
|
|
621
|
+
*
|
|
622
|
+
* @example
|
|
623
|
+
* ```ts
|
|
624
|
+
* const toppings = await multiselect({
|
|
625
|
+
* message: "Select toppings",
|
|
626
|
+
* choices: ["cheese", "pepperoni", "mushrooms", "olives"],
|
|
627
|
+
* });
|
|
628
|
+
* ```
|
|
629
|
+
*
|
|
630
|
+
* @example
|
|
631
|
+
* ```ts
|
|
632
|
+
* const features = await multiselect<string>({
|
|
633
|
+
* message: "Enable features",
|
|
634
|
+
* choices: [
|
|
635
|
+
* { label: "TypeScript", value: "ts", hint: "recommended" },
|
|
636
|
+
* { label: "ESLint", value: "eslint" },
|
|
637
|
+
* { label: "Prettier", value: "prettier" },
|
|
638
|
+
* ],
|
|
639
|
+
* default: ["ts"],
|
|
640
|
+
* required: true,
|
|
641
|
+
* });
|
|
642
|
+
* ```
|
|
643
|
+
*/
|
|
644
|
+
interface MultiselectOptions<T> {
|
|
645
|
+
/** The prompt message displayed to the user */
|
|
646
|
+
readonly message: string;
|
|
647
|
+
/** List of choices — strings or `{ label, value, hint? }` objects */
|
|
648
|
+
readonly choices: readonly Choice<T>[];
|
|
649
|
+
/** Default selected values — pre-selects matching choices */
|
|
650
|
+
readonly default?: readonly T[];
|
|
651
|
+
/** Initial value — if provided, the prompt is skipped and this value is returned immediately */
|
|
652
|
+
readonly initial?: readonly T[];
|
|
653
|
+
/** Whether at least one item must be selected (defaults to false) */
|
|
654
|
+
readonly required?: boolean;
|
|
655
|
+
/** Minimum number of selections required */
|
|
656
|
+
readonly min?: number;
|
|
657
|
+
/** Maximum number of selections allowed */
|
|
658
|
+
readonly max?: number;
|
|
659
|
+
/** Maximum number of visible choices before scrolling (defaults to 10) */
|
|
660
|
+
readonly maxVisible?: number;
|
|
661
|
+
/** Per-prompt theme overrides */
|
|
662
|
+
readonly theme?: PartialPromptTheme;
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Display an interactive checkbox-style multi-selection prompt.
|
|
666
|
+
*
|
|
667
|
+
* Navigate with Up/Down arrows (or k/j vim keys), toggle selection with Space,
|
|
668
|
+
* toggle all with 'a', invert selection with 'i', and confirm with Enter.
|
|
669
|
+
* When the list exceeds `maxVisible` items, the viewport scrolls with
|
|
670
|
+
* indicators showing more items above or below.
|
|
671
|
+
*
|
|
672
|
+
* If `initial` is provided, the prompt is skipped and the value is returned
|
|
673
|
+
* immediately -- useful for prefilling from CLI flags.
|
|
674
|
+
*
|
|
675
|
+
* @param options - Multiselect prompt configuration
|
|
676
|
+
* @returns Array of selected values
|
|
677
|
+
* @throws {NonInteractiveError} when stdin is not a TTY and no `initial` is provided
|
|
678
|
+
*
|
|
679
|
+
* @example
|
|
680
|
+
* ```ts
|
|
681
|
+
* const toppings = await multiselect({
|
|
682
|
+
* message: "Select toppings",
|
|
683
|
+
* choices: ["cheese", "pepperoni", "mushrooms", "olives"],
|
|
684
|
+
* });
|
|
685
|
+
* ```
|
|
686
|
+
*
|
|
687
|
+
* @example
|
|
688
|
+
* ```ts
|
|
689
|
+
* const features = await multiselect<string>({
|
|
690
|
+
* message: "Enable features",
|
|
691
|
+
* choices: [
|
|
692
|
+
* { label: "TypeScript", value: "ts", hint: "recommended" },
|
|
693
|
+
* { label: "ESLint", value: "eslint" },
|
|
694
|
+
* { label: "Prettier", value: "prettier" },
|
|
695
|
+
* ],
|
|
696
|
+
* default: ["ts"],
|
|
697
|
+
* required: true,
|
|
698
|
+
* });
|
|
699
|
+
* ```
|
|
700
|
+
*
|
|
701
|
+
* @example
|
|
702
|
+
* ```ts
|
|
703
|
+
* // Skip prompt when flags are provided
|
|
704
|
+
* const features = await multiselect({
|
|
705
|
+
* message: "Features?",
|
|
706
|
+
* choices: ["auth", "logging", "metrics"],
|
|
707
|
+
* initial: flags.features,
|
|
708
|
+
* });
|
|
709
|
+
* ```
|
|
710
|
+
*/
|
|
711
|
+
declare function multiselect<T>(options: MultiselectOptions<T>): Promise<T[]>;
|
|
712
|
+
/**
|
|
713
|
+
* Options for the {@link password} prompt.
|
|
714
|
+
*
|
|
715
|
+
* @example
|
|
716
|
+
* ```ts
|
|
717
|
+
* const secret = await password({
|
|
718
|
+
* message: "Enter your password:",
|
|
719
|
+
* validate: (v) => v.length >= 8 || "Password must be at least 8 characters",
|
|
720
|
+
* });
|
|
721
|
+
* ```
|
|
722
|
+
*/
|
|
723
|
+
interface PasswordOptions {
|
|
724
|
+
/** The prompt message displayed to the user */
|
|
725
|
+
readonly message: string;
|
|
726
|
+
/** Character used to mask the input (default: `"*"`) */
|
|
727
|
+
readonly mask?: string;
|
|
728
|
+
/** Validation function — return `true` for valid, or a string error message */
|
|
729
|
+
readonly validate?: ValidateFn<string>;
|
|
730
|
+
/** Initial value — if provided, the prompt is skipped and this value is returned immediately */
|
|
731
|
+
readonly initial?: string;
|
|
732
|
+
/** Per-prompt theme overrides */
|
|
733
|
+
readonly theme?: PartialPromptTheme;
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Display an interactive masked password input prompt.
|
|
737
|
+
*
|
|
738
|
+
* Characters are shown as the mask character (default `"*"`) as the user
|
|
739
|
+
* types. After submission, a fixed-length mask is displayed to prevent
|
|
740
|
+
* revealing the password length.
|
|
741
|
+
*
|
|
742
|
+
* Supports validation with inline error display and full cursor editing
|
|
743
|
+
* (insert, delete, arrow keys, home/end).
|
|
744
|
+
*
|
|
745
|
+
* If `initial` is provided, the prompt is skipped and the value is returned
|
|
746
|
+
* immediately — useful for prefilling from CLI flags.
|
|
747
|
+
*
|
|
748
|
+
* @param options - Password prompt configuration
|
|
749
|
+
* @returns The user's entered password
|
|
750
|
+
* @throws {NonInteractiveError} when stdin is not a TTY and no `initial` is provided
|
|
751
|
+
*
|
|
752
|
+
* @example
|
|
753
|
+
* ```ts
|
|
754
|
+
* const secret = await password({
|
|
755
|
+
* message: "Enter your password:",
|
|
756
|
+
* validate: (v) => v.length >= 8 || "Password must be at least 8 characters",
|
|
757
|
+
* });
|
|
758
|
+
* ```
|
|
759
|
+
*
|
|
760
|
+
* @example
|
|
761
|
+
* ```ts
|
|
762
|
+
* // Custom mask character
|
|
763
|
+
* const pin = await password({
|
|
764
|
+
* message: "Enter PIN:",
|
|
765
|
+
* mask: "●",
|
|
766
|
+
* });
|
|
767
|
+
* ```
|
|
768
|
+
*/
|
|
769
|
+
declare function password(options: PasswordOptions): Promise<string>;
|
|
770
|
+
/**
|
|
771
|
+
* Options for the {@link select} prompt.
|
|
772
|
+
*
|
|
773
|
+
* @example
|
|
774
|
+
* ```ts
|
|
775
|
+
* const color = await select({
|
|
776
|
+
* message: "Pick a color",
|
|
777
|
+
* choices: ["red", "green", "blue"],
|
|
778
|
+
* });
|
|
779
|
+
* ```
|
|
780
|
+
*
|
|
781
|
+
* @example
|
|
782
|
+
* ```ts
|
|
783
|
+
* const port = await select<number>({
|
|
784
|
+
* message: "Choose a port",
|
|
785
|
+
* choices: [
|
|
786
|
+
* { label: "HTTP", value: 80 },
|
|
787
|
+
* { label: "HTTPS", value: 443, hint: "recommended" },
|
|
788
|
+
* ],
|
|
789
|
+
* default: 443,
|
|
790
|
+
* });
|
|
791
|
+
* ```
|
|
792
|
+
*/
|
|
793
|
+
interface SelectOptions<T> {
|
|
794
|
+
/** The prompt message displayed to the user */
|
|
795
|
+
readonly message: string;
|
|
796
|
+
/** List of choices — strings or `{ label, value, hint? }` objects */
|
|
797
|
+
readonly choices: readonly Choice<T>[];
|
|
798
|
+
/** Default value — sets the initial cursor position to the matching choice */
|
|
799
|
+
readonly default?: T;
|
|
800
|
+
/** Initial value — if provided, the prompt is skipped and this value is returned immediately */
|
|
801
|
+
readonly initial?: T;
|
|
802
|
+
/** Maximum number of visible choices before scrolling (defaults to 10) */
|
|
803
|
+
readonly maxVisible?: number;
|
|
804
|
+
/** Per-prompt theme overrides */
|
|
805
|
+
readonly theme?: PartialPromptTheme;
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Display an interactive single-selection prompt from a list of choices.
|
|
809
|
+
*
|
|
810
|
+
* Navigate with Up/Down arrows (or k/j vim keys), confirm with Enter.
|
|
811
|
+
* When the list exceeds `maxVisible` items, the viewport scrolls with
|
|
812
|
+
* indicators showing more items above or below.
|
|
813
|
+
*
|
|
814
|
+
* If `initial` is provided, the prompt is skipped and the value is returned
|
|
815
|
+
* immediately -- useful for prefilling from CLI flags.
|
|
816
|
+
*
|
|
817
|
+
* @param options - Select prompt configuration
|
|
818
|
+
* @returns The value of the selected choice
|
|
819
|
+
* @throws {NonInteractiveError} when stdin is not a TTY and no `initial` is provided
|
|
820
|
+
*
|
|
821
|
+
* @example
|
|
822
|
+
* ```ts
|
|
823
|
+
* const color = await select({
|
|
824
|
+
* message: "Pick a color",
|
|
825
|
+
* choices: ["red", "green", "blue"],
|
|
826
|
+
* });
|
|
827
|
+
* ```
|
|
828
|
+
*
|
|
829
|
+
* @example
|
|
830
|
+
* ```ts
|
|
831
|
+
* const port = await select<number>({
|
|
832
|
+
* message: "Choose a port",
|
|
833
|
+
* choices: [
|
|
834
|
+
* { label: "HTTP", value: 80 },
|
|
835
|
+
* { label: "HTTPS", value: 443, hint: "recommended" },
|
|
836
|
+
* ],
|
|
837
|
+
* default: 443,
|
|
838
|
+
* });
|
|
839
|
+
* ```
|
|
840
|
+
*
|
|
841
|
+
* @example
|
|
842
|
+
* ```ts
|
|
843
|
+
* // Skip prompt when flag is provided
|
|
844
|
+
* const env = await select({
|
|
845
|
+
* message: "Environment?",
|
|
846
|
+
* choices: ["dev", "staging", "prod"],
|
|
847
|
+
* initial: flags.env,
|
|
848
|
+
* });
|
|
849
|
+
* ```
|
|
850
|
+
*/
|
|
851
|
+
declare function select<T>(options: SelectOptions<T>): Promise<T>;
|
|
852
|
+
/**
|
|
853
|
+
* Built-in spinner animation names or a custom frame configuration.
|
|
854
|
+
*
|
|
855
|
+
* Built-in spinners:
|
|
856
|
+
* - `"dots"` — Braille dot pattern (⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏)
|
|
857
|
+
* - `"line"` — Line rotation (-\\|/)
|
|
858
|
+
* - `"arc"` — Quarter circle rotation (◐◓◑◒)
|
|
859
|
+
* - `"bounce"` — Bouncing braille dot (⠁⠂⠄⡀⢀⠠⠐⠈)
|
|
860
|
+
*
|
|
861
|
+
* Or provide a custom `{ frames: string[]; interval: number }` object.
|
|
862
|
+
*/
|
|
863
|
+
type SpinnerType = "dots" | "line" | "arc" | "bounce" | {
|
|
864
|
+
readonly frames: readonly string[];
|
|
865
|
+
readonly interval: number;
|
|
866
|
+
};
|
|
867
|
+
/**
|
|
868
|
+
* Options for the {@link spinner} prompt.
|
|
869
|
+
*
|
|
870
|
+
* @example
|
|
871
|
+
* ```ts
|
|
872
|
+
* const data = await spinner({
|
|
873
|
+
* message: "Fetching data...",
|
|
874
|
+
* task: async () => {
|
|
875
|
+
* const res = await fetch("https://api.example.com/data");
|
|
876
|
+
* return res.json();
|
|
877
|
+
* },
|
|
878
|
+
* });
|
|
879
|
+
* ```
|
|
880
|
+
*/
|
|
881
|
+
interface SpinnerOptions<T> {
|
|
882
|
+
/** The message displayed alongside the spinner */
|
|
883
|
+
readonly message: string;
|
|
884
|
+
/** The async task to run while the spinner is displayed */
|
|
885
|
+
readonly task: () => Promise<T>;
|
|
886
|
+
/** Spinner animation style (defaults to `"dots"`) */
|
|
887
|
+
readonly spinner?: SpinnerType;
|
|
888
|
+
/** Per-prompt theme overrides */
|
|
889
|
+
readonly theme?: PartialPromptTheme;
|
|
890
|
+
}
|
|
891
|
+
/**
|
|
892
|
+
* Display a spinner animation while running an async task.
|
|
893
|
+
*
|
|
894
|
+
* The spinner renders to stderr so it doesn't interfere with piped stdout.
|
|
895
|
+
* On task completion, the spinner is replaced with a success (✔) or error (✖)
|
|
896
|
+
* indicator. If the task throws, the error is re-thrown after cleanup.
|
|
897
|
+
*
|
|
898
|
+
* Unlike other prompts, the spinner does **not** use raw mode or keypress
|
|
899
|
+
* handling — it is output-only and non-interactive.
|
|
900
|
+
*
|
|
901
|
+
* @param options - Spinner prompt configuration
|
|
902
|
+
* @returns The result of the async task
|
|
903
|
+
*
|
|
904
|
+
* @example
|
|
905
|
+
* ```ts
|
|
906
|
+
* const data = await spinner({
|
|
907
|
+
* message: "Loading data...",
|
|
908
|
+
* task: async () => {
|
|
909
|
+
* const res = await fetch("https://api.example.com/data");
|
|
910
|
+
* return res.json();
|
|
911
|
+
* },
|
|
912
|
+
* });
|
|
913
|
+
* ```
|
|
914
|
+
*
|
|
915
|
+
* @example
|
|
916
|
+
* ```ts
|
|
917
|
+
* // Custom spinner animation
|
|
918
|
+
* await spinner({
|
|
919
|
+
* message: "Building project...",
|
|
920
|
+
* task: async () => { await buildProject(); },
|
|
921
|
+
* spinner: "arc",
|
|
922
|
+
* });
|
|
923
|
+
* ```
|
|
924
|
+
*
|
|
925
|
+
* @example
|
|
926
|
+
* ```ts
|
|
927
|
+
* // Custom frames and interval
|
|
928
|
+
* await spinner({
|
|
929
|
+
* message: "Processing...",
|
|
930
|
+
* task: async () => { await processData(); },
|
|
931
|
+
* spinner: { frames: ["⊶", "⊷"], interval: 150 },
|
|
932
|
+
* });
|
|
933
|
+
* ```
|
|
934
|
+
*/
|
|
935
|
+
declare function spinner<T>(options: SpinnerOptions<T>): Promise<T>;
|
|
936
|
+
/** Thin vertical bar used as cursor indicator in text inputs */
|
|
937
|
+
declare const CURSOR_CHAR = "│";
|
|
938
|
+
/**
|
|
939
|
+
* The text + cursor fields that `handleTextEdit` reads and updates.
|
|
940
|
+
* Prompts embed these fields in their own state type.
|
|
941
|
+
*/
|
|
942
|
+
interface TextEditState {
|
|
943
|
+
readonly text: string;
|
|
944
|
+
readonly cursorPos: number;
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* Result of a text-edit operation.
|
|
948
|
+
* `null` means the key was not a text-editing key and the caller should
|
|
949
|
+
* handle it (e.g., Enter for submit, arrow-up/down for list navigation).
|
|
950
|
+
*/
|
|
951
|
+
type TextEditResult = TextEditState | null;
|
|
952
|
+
/**
|
|
953
|
+
* Handle common text-editing keypresses: backspace, delete, left, right,
|
|
954
|
+
* home, end, and printable character insertion.
|
|
955
|
+
*
|
|
956
|
+
* Returns the updated `{ text, cursorPos }` if the key was handled,
|
|
957
|
+
* or `null` if the key is not a text-editing key (so the caller can
|
|
958
|
+
* handle it for prompt-specific logic like submit or list navigation).
|
|
959
|
+
*
|
|
960
|
+
* @param key - The keypress event
|
|
961
|
+
* @param text - Current text content
|
|
962
|
+
* @param cursorPos - Current cursor position within the text
|
|
963
|
+
* @returns Updated text/cursor, or `null` if not a text-edit key
|
|
964
|
+
*/
|
|
965
|
+
declare function handleTextEdit(key: KeypressEvent, text: string, cursorPos: number): TextEditResult;
|
|
966
|
+
export { submit, spinner, setTheme, select, runPrompt, password, normalizeChoices, multiselect, input, handleTextEdit, getTheme, fuzzyMatch, fuzzyFilter, filter, defaultTheme, createTheme, confirm, calculateScrollOffset, assertTTY, ValidateResult, ValidateFn, TextEditState, TextEditResult, SubmitResult, SpinnerType, SpinnerOptions, SelectOptions, PromptTheme, PromptConfig, PasswordOptions, PartialPromptTheme, NormalizedChoice, NonInteractiveError, MultiselectOptions, KeypressEvent, InputOptions, HandleKeyResult, FuzzyMatchResult, FuzzyFilterResult, FilterOptions, ConfirmOptions, Choice, CancelledError, CURSOR_CHAR };
|