@termuijs/ui 0.1.3 → 0.1.5

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.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Widget } from '@termuijs/widgets';
2
2
  export { Box, Gauge, List, LogView, ProgressBar, Sparkline, Spinner, StatusIndicator, Table, Text, TextInput, Widget } from '@termuijs/widgets';
3
- import { Style, Screen } from '@termuijs/core';
3
+ import { Style, Screen, KeyEvent } from '@termuijs/core';
4
4
 
5
5
  interface DividerOptions {
6
6
  char?: string;
@@ -282,4 +282,279 @@ declare class CommandPalette extends Widget {
282
282
  protected _renderSelf(screen: Screen): void;
283
283
  }
284
284
 
285
- export { type Command, CommandPalette, type CommandPaletteOptions, ConfirmDialog, type ConfirmDialogOptions, Divider, type DividerOptions, Form, type FormField, type FormOptions, Modal, type ModalOptions, MultiSelect, type MultiSelectOption, type MultiSelectOptions, Select, type SelectOption, type SelectOptions, Spacer, type Tab, Tabs, type TabsOptions, Toast, type ToastMessage, type ToastOptions, type ToastType, Tree, type TreeNode, type TreeOptions };
285
+ declare class NonInteractiveError extends Error {
286
+ constructor();
287
+ }
288
+ interface TextPromptOptions {
289
+ message: string;
290
+ placeholder?: string;
291
+ validate?: (value: string) => string | null;
292
+ default?: string;
293
+ }
294
+ interface ConfirmPromptOptions {
295
+ message: string;
296
+ default?: boolean;
297
+ }
298
+ interface SelectPromptOptions<T = string> {
299
+ message: string;
300
+ options: Array<{
301
+ label: string;
302
+ value: T;
303
+ }>;
304
+ default?: T;
305
+ }
306
+ declare function promptText(options: TextPromptOptions): Promise<string>;
307
+ declare function promptConfirm(options: ConfirmPromptOptions): Promise<boolean>;
308
+ declare function promptSelect<T = string>(options: SelectPromptOptions<T>): Promise<T>;
309
+ /**
310
+ * Imperative prompts for CLI scripts — no widget stack required.
311
+ *
312
+ * ```ts
313
+ * const name = await prompt.text({ message: 'Project name:', default: 'my-app' });
314
+ * const ok = await prompt.confirm({ message: 'Continue?', default: true });
315
+ * const pkg = await prompt.select({ message: 'Package manager:', options: [
316
+ * { label: 'pnpm', value: 'pnpm' },
317
+ * { label: 'npm', value: 'npm' },
318
+ * ]});
319
+ * ```
320
+ *
321
+ * Throws `NonInteractiveError` when stdin is not a TTY.
322
+ */
323
+ declare const prompt: {
324
+ readonly text: typeof promptText;
325
+ readonly confirm: typeof promptConfirm;
326
+ readonly select: typeof promptSelect;
327
+ };
328
+
329
+ interface Notification {
330
+ id: string;
331
+ message: string;
332
+ type: 'info' | 'success' | 'warning' | 'error';
333
+ durationMs?: number;
334
+ createdAt: number;
335
+ }
336
+ declare class NotificationStore {
337
+ private static _instance;
338
+ private _notifications;
339
+ private _subs;
340
+ static getInstance(): NotificationStore;
341
+ push(message: string, type?: Notification['type'], durationMs?: number): string;
342
+ dismiss(id: string): void;
343
+ dismissAll(): void;
344
+ subscribe(fn: (notifications: Notification[]) => void): () => void;
345
+ get notifications(): Notification[];
346
+ private _emit;
347
+ }
348
+ /** Global singleton accessor */
349
+ declare const notifications: NotificationStore;
350
+ declare function useNotifications(): {
351
+ notifications: Notification[];
352
+ push: (message: string, type?: Notification['type'], durationMs?: number) => string;
353
+ dismiss: (id: string) => void;
354
+ dismissAll: () => void;
355
+ };
356
+ interface NotificationCenterOptions {
357
+ position?: 'top-right' | 'bottom-right' | 'top-left' | 'bottom-left';
358
+ maxVisible?: number;
359
+ width?: number;
360
+ }
361
+ declare class NotificationCenter extends Widget {
362
+ private _position;
363
+ private _maxVisible;
364
+ private _notifWidth;
365
+ private _unsub?;
366
+ private _current;
367
+ constructor(options?: NotificationCenterOptions);
368
+ unmount(): void;
369
+ protected _renderSelf(screen: Screen): void;
370
+ }
371
+
372
+ interface PasswordInputOptions {
373
+ placeholder?: string;
374
+ maxLength?: number;
375
+ onChange?: (value: string) => void;
376
+ onSubmit?: (value: string) => void;
377
+ }
378
+ declare class PasswordInput extends Widget {
379
+ private _value;
380
+ private _cursorPos;
381
+ private _placeholder;
382
+ private _maxLength;
383
+ private _showText;
384
+ private _onChange?;
385
+ private _onSubmit?;
386
+ focusable: boolean;
387
+ private get _maskChar();
388
+ constructor(style?: Partial<Style>, options?: PasswordInputOptions);
389
+ /** The actual (unmasked) value. */
390
+ get value(): string;
391
+ set value(v: string);
392
+ /** Whether the text is currently visible (unmaksed). */
393
+ get showText(): boolean;
394
+ /** Toggle visibility of the actual text (Alt+V). */
395
+ toggleVisibility(): void;
396
+ insertChar(char: string): void;
397
+ deleteBack(): void;
398
+ deleteForward(): void;
399
+ moveCursorLeft(): void;
400
+ moveCursorRight(): void;
401
+ moveCursorHome(): void;
402
+ moveCursorEnd(): void;
403
+ submit(): void;
404
+ clear(): void;
405
+ /**
406
+ * Handle key events. Call this from your input loop.
407
+ * Alt+V — toggle visibility
408
+ * Other — standard text editing
409
+ */
410
+ handleKey(event: KeyEvent): void;
411
+ protected _renderSelf(screen: Screen): void;
412
+ }
413
+
414
+ interface NumberInputOptions {
415
+ placeholder?: string;
416
+ step?: number;
417
+ min?: number;
418
+ max?: number;
419
+ allowDecimal?: boolean;
420
+ onChange?: (value: number | null) => void;
421
+ onSubmit?: (value: number | null) => void;
422
+ }
423
+ declare class NumberInput extends Widget {
424
+ private _raw;
425
+ private _cursorPos;
426
+ private _placeholder;
427
+ private _step;
428
+ private _min;
429
+ private _max;
430
+ private _allowDecimal;
431
+ private _onChange?;
432
+ private _onSubmit?;
433
+ focusable: boolean;
434
+ constructor(style?: Partial<Style>, options?: NumberInputOptions);
435
+ /** The numeric value, or null if the field is empty / invalid. */
436
+ get numericValue(): number | null;
437
+ /** Raw text string (what the user typed). */
438
+ get rawValue(): string;
439
+ set rawValue(v: string);
440
+ private _clamp;
441
+ private _notify;
442
+ /** Accept only digits, '-' at position 0 (if min < 0), and (optionally) one '.'. */
443
+ private _isAllowed;
444
+ insertChar(char: string): void;
445
+ deleteBack(): void;
446
+ deleteForward(): void;
447
+ moveCursorLeft(): void;
448
+ moveCursorRight(): void;
449
+ moveCursorHome(): void;
450
+ moveCursorEnd(): void;
451
+ /** Increment value by step (↑ arrow). */
452
+ increment(): void;
453
+ /** Decrement value by step (↓ arrow). */
454
+ decrement(): void;
455
+ submit(): void;
456
+ clear(): void;
457
+ /**
458
+ * Handle key events. Call this from your input loop.
459
+ */
460
+ handleKey(event: KeyEvent): void;
461
+ protected _renderSelf(screen: Screen): void;
462
+ }
463
+
464
+ interface PathInputOptions {
465
+ placeholder?: string;
466
+ maxLength?: number;
467
+ cwd?: string;
468
+ maxCompletions?: number;
469
+ onChange?: (value: string) => void;
470
+ onSubmit?: (value: string) => void;
471
+ }
472
+ /**
473
+ * PathInput — filesystem path input with Tab-completion.
474
+ *
475
+ * @note height must be at least (maxCompletions + 2) to show completions.
476
+ * Default height of 3 shows up to 1 completion. If height is insufficient,
477
+ * the input line is still rendered but completions are hidden.
478
+ */
479
+ declare class PathInput extends Widget {
480
+ private _value;
481
+ private _cursorPos;
482
+ private _placeholder;
483
+ private _maxLength;
484
+ private _cwd;
485
+ private _maxCompletions;
486
+ private _completions;
487
+ private _completionIndex;
488
+ private _preCompletionValue;
489
+ private _showCompletions;
490
+ private _onChange?;
491
+ private _onSubmit?;
492
+ focusable: boolean;
493
+ constructor(style?: Partial<Style>, options?: PathInputOptions);
494
+ get value(): string;
495
+ set value(v: string);
496
+ get completions(): string[];
497
+ get isShowingCompletions(): boolean;
498
+ private _dismissCompletions;
499
+ /** Compute completions for the current value. Does NOT throw. */
500
+ private _computeCompletions;
501
+ /** Trigger tab-completion. */
502
+ triggerCompletion(): void;
503
+ insertChar(char: string): void;
504
+ deleteBack(): void;
505
+ deleteForward(): void;
506
+ moveCursorLeft(): void;
507
+ moveCursorRight(): void;
508
+ moveCursorHome(): void;
509
+ moveCursorEnd(): void;
510
+ submit(): void;
511
+ clear(): void;
512
+ /**
513
+ * Handle key events. Call this from your input loop.
514
+ * Tab — trigger/cycle completions
515
+ * Esc — dismiss completions
516
+ * Enter — submit current value
517
+ */
518
+ handleKey(event: KeyEvent): void;
519
+ protected _renderSelf(screen: Screen): void;
520
+ }
521
+
522
+ interface ShortcutBinding {
523
+ key: string;
524
+ description: string;
525
+ category?: string;
526
+ }
527
+ interface KeyboardShortcutsOptions {
528
+ /** Color for the key label boxes */
529
+ keyColor?: Style['fg'];
530
+ /** Color for category headings */
531
+ categoryColor?: Style['fg'];
532
+ /** Number of columns (default 2) */
533
+ columns?: number;
534
+ /** Show category headings (default true) */
535
+ showCategories?: boolean;
536
+ }
537
+ declare class KeyboardShortcuts extends Widget {
538
+ private _bindings;
539
+ private _keyColor;
540
+ private _categoryColor;
541
+ private _columns;
542
+ private _showCategories;
543
+ constructor(bindings: ShortcutBinding[], options?: KeyboardShortcutsOptions);
544
+ /** Replace all bindings and trigger a re-render. */
545
+ setBindings(bindings: ShortcutBinding[]): void;
546
+ /** Group bindings by category, preserving insertion order. */
547
+ private _groupBindings;
548
+ /**
549
+ * Render a key label in a bordered box style:
550
+ * ┌─────┐
551
+ * │ key │
552
+ * └─────┘
553
+ *
554
+ * We fit it on one line: [ key ] — box drawing characters or ASCII fallback.
555
+ */
556
+ private _renderKeyLabel;
557
+ protected _renderSelf(screen: Screen): void;
558
+ }
559
+
560
+ export { type Command, CommandPalette, type CommandPaletteOptions, ConfirmDialog, type ConfirmDialogOptions, type ConfirmPromptOptions, Divider, type DividerOptions, Form, type FormField, type FormOptions, KeyboardShortcuts, type KeyboardShortcutsOptions, Modal, type ModalOptions, MultiSelect, type MultiSelectOption, type MultiSelectOptions, NonInteractiveError, type Notification, NotificationCenter, type NotificationCenterOptions, NotificationStore, NumberInput, type NumberInputOptions, PasswordInput, type PasswordInputOptions, PathInput, type PathInputOptions, Select, type SelectOption, type SelectOptions, type SelectPromptOptions, type ShortcutBinding, Spacer, type Tab, Tabs, type TabsOptions, type TextPromptOptions, Toast, type ToastMessage, type ToastOptions, type ToastType, Tree, type TreeNode, type TreeOptions, notifications, prompt, useNotifications };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Widget } from '@termuijs/widgets';
2
2
  export { Box, Gauge, List, LogView, ProgressBar, Sparkline, Spinner, StatusIndicator, Table, Text, TextInput, Widget } from '@termuijs/widgets';
3
- import { Style, Screen } from '@termuijs/core';
3
+ import { Style, Screen, KeyEvent } from '@termuijs/core';
4
4
 
5
5
  interface DividerOptions {
6
6
  char?: string;
@@ -282,4 +282,279 @@ declare class CommandPalette extends Widget {
282
282
  protected _renderSelf(screen: Screen): void;
283
283
  }
284
284
 
285
- export { type Command, CommandPalette, type CommandPaletteOptions, ConfirmDialog, type ConfirmDialogOptions, Divider, type DividerOptions, Form, type FormField, type FormOptions, Modal, type ModalOptions, MultiSelect, type MultiSelectOption, type MultiSelectOptions, Select, type SelectOption, type SelectOptions, Spacer, type Tab, Tabs, type TabsOptions, Toast, type ToastMessage, type ToastOptions, type ToastType, Tree, type TreeNode, type TreeOptions };
285
+ declare class NonInteractiveError extends Error {
286
+ constructor();
287
+ }
288
+ interface TextPromptOptions {
289
+ message: string;
290
+ placeholder?: string;
291
+ validate?: (value: string) => string | null;
292
+ default?: string;
293
+ }
294
+ interface ConfirmPromptOptions {
295
+ message: string;
296
+ default?: boolean;
297
+ }
298
+ interface SelectPromptOptions<T = string> {
299
+ message: string;
300
+ options: Array<{
301
+ label: string;
302
+ value: T;
303
+ }>;
304
+ default?: T;
305
+ }
306
+ declare function promptText(options: TextPromptOptions): Promise<string>;
307
+ declare function promptConfirm(options: ConfirmPromptOptions): Promise<boolean>;
308
+ declare function promptSelect<T = string>(options: SelectPromptOptions<T>): Promise<T>;
309
+ /**
310
+ * Imperative prompts for CLI scripts — no widget stack required.
311
+ *
312
+ * ```ts
313
+ * const name = await prompt.text({ message: 'Project name:', default: 'my-app' });
314
+ * const ok = await prompt.confirm({ message: 'Continue?', default: true });
315
+ * const pkg = await prompt.select({ message: 'Package manager:', options: [
316
+ * { label: 'pnpm', value: 'pnpm' },
317
+ * { label: 'npm', value: 'npm' },
318
+ * ]});
319
+ * ```
320
+ *
321
+ * Throws `NonInteractiveError` when stdin is not a TTY.
322
+ */
323
+ declare const prompt: {
324
+ readonly text: typeof promptText;
325
+ readonly confirm: typeof promptConfirm;
326
+ readonly select: typeof promptSelect;
327
+ };
328
+
329
+ interface Notification {
330
+ id: string;
331
+ message: string;
332
+ type: 'info' | 'success' | 'warning' | 'error';
333
+ durationMs?: number;
334
+ createdAt: number;
335
+ }
336
+ declare class NotificationStore {
337
+ private static _instance;
338
+ private _notifications;
339
+ private _subs;
340
+ static getInstance(): NotificationStore;
341
+ push(message: string, type?: Notification['type'], durationMs?: number): string;
342
+ dismiss(id: string): void;
343
+ dismissAll(): void;
344
+ subscribe(fn: (notifications: Notification[]) => void): () => void;
345
+ get notifications(): Notification[];
346
+ private _emit;
347
+ }
348
+ /** Global singleton accessor */
349
+ declare const notifications: NotificationStore;
350
+ declare function useNotifications(): {
351
+ notifications: Notification[];
352
+ push: (message: string, type?: Notification['type'], durationMs?: number) => string;
353
+ dismiss: (id: string) => void;
354
+ dismissAll: () => void;
355
+ };
356
+ interface NotificationCenterOptions {
357
+ position?: 'top-right' | 'bottom-right' | 'top-left' | 'bottom-left';
358
+ maxVisible?: number;
359
+ width?: number;
360
+ }
361
+ declare class NotificationCenter extends Widget {
362
+ private _position;
363
+ private _maxVisible;
364
+ private _notifWidth;
365
+ private _unsub?;
366
+ private _current;
367
+ constructor(options?: NotificationCenterOptions);
368
+ unmount(): void;
369
+ protected _renderSelf(screen: Screen): void;
370
+ }
371
+
372
+ interface PasswordInputOptions {
373
+ placeholder?: string;
374
+ maxLength?: number;
375
+ onChange?: (value: string) => void;
376
+ onSubmit?: (value: string) => void;
377
+ }
378
+ declare class PasswordInput extends Widget {
379
+ private _value;
380
+ private _cursorPos;
381
+ private _placeholder;
382
+ private _maxLength;
383
+ private _showText;
384
+ private _onChange?;
385
+ private _onSubmit?;
386
+ focusable: boolean;
387
+ private get _maskChar();
388
+ constructor(style?: Partial<Style>, options?: PasswordInputOptions);
389
+ /** The actual (unmasked) value. */
390
+ get value(): string;
391
+ set value(v: string);
392
+ /** Whether the text is currently visible (unmaksed). */
393
+ get showText(): boolean;
394
+ /** Toggle visibility of the actual text (Alt+V). */
395
+ toggleVisibility(): void;
396
+ insertChar(char: string): void;
397
+ deleteBack(): void;
398
+ deleteForward(): void;
399
+ moveCursorLeft(): void;
400
+ moveCursorRight(): void;
401
+ moveCursorHome(): void;
402
+ moveCursorEnd(): void;
403
+ submit(): void;
404
+ clear(): void;
405
+ /**
406
+ * Handle key events. Call this from your input loop.
407
+ * Alt+V — toggle visibility
408
+ * Other — standard text editing
409
+ */
410
+ handleKey(event: KeyEvent): void;
411
+ protected _renderSelf(screen: Screen): void;
412
+ }
413
+
414
+ interface NumberInputOptions {
415
+ placeholder?: string;
416
+ step?: number;
417
+ min?: number;
418
+ max?: number;
419
+ allowDecimal?: boolean;
420
+ onChange?: (value: number | null) => void;
421
+ onSubmit?: (value: number | null) => void;
422
+ }
423
+ declare class NumberInput extends Widget {
424
+ private _raw;
425
+ private _cursorPos;
426
+ private _placeholder;
427
+ private _step;
428
+ private _min;
429
+ private _max;
430
+ private _allowDecimal;
431
+ private _onChange?;
432
+ private _onSubmit?;
433
+ focusable: boolean;
434
+ constructor(style?: Partial<Style>, options?: NumberInputOptions);
435
+ /** The numeric value, or null if the field is empty / invalid. */
436
+ get numericValue(): number | null;
437
+ /** Raw text string (what the user typed). */
438
+ get rawValue(): string;
439
+ set rawValue(v: string);
440
+ private _clamp;
441
+ private _notify;
442
+ /** Accept only digits, '-' at position 0 (if min < 0), and (optionally) one '.'. */
443
+ private _isAllowed;
444
+ insertChar(char: string): void;
445
+ deleteBack(): void;
446
+ deleteForward(): void;
447
+ moveCursorLeft(): void;
448
+ moveCursorRight(): void;
449
+ moveCursorHome(): void;
450
+ moveCursorEnd(): void;
451
+ /** Increment value by step (↑ arrow). */
452
+ increment(): void;
453
+ /** Decrement value by step (↓ arrow). */
454
+ decrement(): void;
455
+ submit(): void;
456
+ clear(): void;
457
+ /**
458
+ * Handle key events. Call this from your input loop.
459
+ */
460
+ handleKey(event: KeyEvent): void;
461
+ protected _renderSelf(screen: Screen): void;
462
+ }
463
+
464
+ interface PathInputOptions {
465
+ placeholder?: string;
466
+ maxLength?: number;
467
+ cwd?: string;
468
+ maxCompletions?: number;
469
+ onChange?: (value: string) => void;
470
+ onSubmit?: (value: string) => void;
471
+ }
472
+ /**
473
+ * PathInput — filesystem path input with Tab-completion.
474
+ *
475
+ * @note height must be at least (maxCompletions + 2) to show completions.
476
+ * Default height of 3 shows up to 1 completion. If height is insufficient,
477
+ * the input line is still rendered but completions are hidden.
478
+ */
479
+ declare class PathInput extends Widget {
480
+ private _value;
481
+ private _cursorPos;
482
+ private _placeholder;
483
+ private _maxLength;
484
+ private _cwd;
485
+ private _maxCompletions;
486
+ private _completions;
487
+ private _completionIndex;
488
+ private _preCompletionValue;
489
+ private _showCompletions;
490
+ private _onChange?;
491
+ private _onSubmit?;
492
+ focusable: boolean;
493
+ constructor(style?: Partial<Style>, options?: PathInputOptions);
494
+ get value(): string;
495
+ set value(v: string);
496
+ get completions(): string[];
497
+ get isShowingCompletions(): boolean;
498
+ private _dismissCompletions;
499
+ /** Compute completions for the current value. Does NOT throw. */
500
+ private _computeCompletions;
501
+ /** Trigger tab-completion. */
502
+ triggerCompletion(): void;
503
+ insertChar(char: string): void;
504
+ deleteBack(): void;
505
+ deleteForward(): void;
506
+ moveCursorLeft(): void;
507
+ moveCursorRight(): void;
508
+ moveCursorHome(): void;
509
+ moveCursorEnd(): void;
510
+ submit(): void;
511
+ clear(): void;
512
+ /**
513
+ * Handle key events. Call this from your input loop.
514
+ * Tab — trigger/cycle completions
515
+ * Esc — dismiss completions
516
+ * Enter — submit current value
517
+ */
518
+ handleKey(event: KeyEvent): void;
519
+ protected _renderSelf(screen: Screen): void;
520
+ }
521
+
522
+ interface ShortcutBinding {
523
+ key: string;
524
+ description: string;
525
+ category?: string;
526
+ }
527
+ interface KeyboardShortcutsOptions {
528
+ /** Color for the key label boxes */
529
+ keyColor?: Style['fg'];
530
+ /** Color for category headings */
531
+ categoryColor?: Style['fg'];
532
+ /** Number of columns (default 2) */
533
+ columns?: number;
534
+ /** Show category headings (default true) */
535
+ showCategories?: boolean;
536
+ }
537
+ declare class KeyboardShortcuts extends Widget {
538
+ private _bindings;
539
+ private _keyColor;
540
+ private _categoryColor;
541
+ private _columns;
542
+ private _showCategories;
543
+ constructor(bindings: ShortcutBinding[], options?: KeyboardShortcutsOptions);
544
+ /** Replace all bindings and trigger a re-render. */
545
+ setBindings(bindings: ShortcutBinding[]): void;
546
+ /** Group bindings by category, preserving insertion order. */
547
+ private _groupBindings;
548
+ /**
549
+ * Render a key label in a bordered box style:
550
+ * ┌─────┐
551
+ * │ key │
552
+ * └─────┘
553
+ *
554
+ * We fit it on one line: [ key ] — box drawing characters or ASCII fallback.
555
+ */
556
+ private _renderKeyLabel;
557
+ protected _renderSelf(screen: Screen): void;
558
+ }
559
+
560
+ export { type Command, CommandPalette, type CommandPaletteOptions, ConfirmDialog, type ConfirmDialogOptions, type ConfirmPromptOptions, Divider, type DividerOptions, Form, type FormField, type FormOptions, KeyboardShortcuts, type KeyboardShortcutsOptions, Modal, type ModalOptions, MultiSelect, type MultiSelectOption, type MultiSelectOptions, NonInteractiveError, type Notification, NotificationCenter, type NotificationCenterOptions, NotificationStore, NumberInput, type NumberInputOptions, PasswordInput, type PasswordInputOptions, PathInput, type PathInputOptions, Select, type SelectOption, type SelectOptions, type SelectPromptOptions, type ShortcutBinding, Spacer, type Tab, Tabs, type TabsOptions, type TextPromptOptions, Toast, type ToastMessage, type ToastOptions, type ToastType, Tree, type TreeNode, type TreeOptions, notifications, prompt, useNotifications };