@f5-sales-demo/pi-tui 20.2.4 → 20.2.7

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 (3) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +244 -244
  3. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -41,6 +41,7 @@
41
41
  - Autocomplete fuzzy discovery now accepts optional SearchDb instance for faster searches
42
42
 
43
43
  ## [13.16.0] - 2026-03-27
44
+
44
45
  ### Changed
45
46
 
46
47
  - Updated tab replacement in editor text sanitization to respect configured tab width setting
@@ -56,6 +57,7 @@
56
57
  - Fixed editor consuming user-rebound copy keys, preventing custom keybindings from working in the editor
57
58
 
58
59
  ## [13.14.1] - 2026-03-21
60
+
59
61
  ### Added
60
62
 
61
63
  - Added Ctrl+_ as an additional default shortcut for undo
@@ -76,17 +78,20 @@
76
78
  - Fixed paste marker expansion to handle special regex replacement tokens ($1, $2, $&, $$, $`, $') literally in pasted content
77
79
 
78
80
  ## [13.11.0] - 2026-03-12
81
+
79
82
  ### Fixed
80
83
 
81
84
  - Fixed OSC 11 background color detection to correctly handle partial escape sequences that arrive mid-buffer, preventing user input from being swallowed
82
85
  - Fixed race condition where overlapping OSC 11 queries would be incorrectly cancelled by DA1 sentinels from previous queries
83
86
 
84
87
  ## [13.7.5] - 2026-03-04
88
+
85
89
  ### Changed
86
90
 
87
91
  - Extracted word navigation logic into reusable `moveWordLeft` and `moveWordRight` utility functions for consistent cursor movement across components
88
92
 
89
93
  ## [13.6.2] - 2026-03-03
94
+
90
95
  ### Fixed
91
96
 
92
97
  - Fixed cursor positioning when content shrinks to empty without clearOnShrink enabled
@@ -96,6 +101,7 @@
96
101
  ### Fixed
97
102
 
98
103
  - Fixed viewport repaint scrollback accounting during resize oscillation to avoid double-scrolling on height shrink and added exact-row scrollback assertions in overlay regression coverage ([#228](https://github.com/can1357/oh-my-pi/issues/228), [#234](https://github.com/can1357/oh-my-pi/issues/234))
104
+
99
105
  ## [13.5.3] - 2026-03-01
100
106
 
101
107
  ### Fixed
@@ -105,6 +111,7 @@
105
111
  - Fixed cursor positioning instability when appending content under external cursor relocation by using absolute screen addressing instead of relative cursor movement
106
112
 
107
113
  ## [13.5.2] - 2026-03-01
114
+
108
115
  ### Breaking Changes
109
116
 
110
117
  - Removed `getMermaidImage` callback from MarkdownTheme; replaced with `getMermaidAscii` that accepts ASCII string instead of image data
@@ -115,6 +122,7 @@
115
122
  - Mermaid diagrams now render as ASCII text instead of terminal graphics protocol images
116
123
 
117
124
  ## [13.5.1] - 2026-03-01
125
+
118
126
  ### Fixed
119
127
 
120
128
  - Fixed viewport shift handling to prevent stale content when mixed updates remap screen rows
@@ -142,6 +150,7 @@
142
150
 
143
151
  - Fixed stale/duplicated terminal cursor dedup state by synchronizing `#lastCursorSequence` in all render write paths (hard reset, viewport repaint, deleted-lines clear path, append fast path, and differential path).
144
152
  - Fixed scroll overshoot on `stop()` when content fills the viewport by clamping target row movement to valid screen rows.
153
+
145
154
  ## [13.4.0] - 2026-03-01
146
155
 
147
156
  ### Added
@@ -163,6 +172,7 @@
163
172
  - Restored terminal image protocol override and fallback detection for image rendering, including `PI_FORCE_IMAGE_PROTOCOL` support and Kitty fallback for screen/tmux/ghostty-style TERM environments.
164
173
 
165
174
  ## [13.3.8] - 2026-02-28
175
+
166
176
  ### Breaking Changes
167
177
 
168
178
  - Changed mermaid hash type from string to bigint in `getMermaidImage` callback and `extractMermaidBlocks` return type
@@ -184,6 +194,7 @@
184
194
  - Fixed stale viewport rows appearing when terminal height increases by triggering full re-render on height changes
185
195
 
186
196
  ## [12.18.0] - 2026-02-21
197
+
187
198
  ### Fixed
188
199
 
189
200
  - Fixed viewport synchronization issue by clearing scrollback when terminal state becomes desynced during full re-renders
@@ -212,18 +223,21 @@
212
223
  - Fixed incremental stale-row clearing to use erase-below semantics in synchronized output, reducing leftover-line artifacts after shrink operations.
213
224
 
214
225
  ## [12.9.0] - 2026-02-17
226
+
215
227
  ### Added
216
228
 
217
229
  - Exported `getTerminalId()` function to get a stable identifier for the current terminal, with support for TTY device paths and terminal multiplexers
218
230
  - Exported `getTtyPath()` function to resolve the TTY device path for stdin via POSIX `ttyname(3)`
219
231
 
220
232
  ## [12.5.0] - 2026-02-15
233
+
221
234
  ### Added
222
235
 
223
236
  - Added `cursorOverride` and `cursorOverrideWidth` properties to customize the end-of-text cursor glyph with ANSI-styled strings
224
237
  - Added `getUseTerminalCursor()` method to query the terminal cursor mode setting
225
238
 
226
239
  ## [11.10.0] - 2026-02-10
240
+
227
241
  ### Added
228
242
 
229
243
  - Added `hint` property to autocomplete items to display dim ghost text after cursor when item is selected
@@ -236,6 +250,7 @@
236
250
  - Updated editor to render inline hint text as dim ghost text after cursor when autocomplete suggestions are active or provider supplies hints
237
251
 
238
252
  ## [11.8.0] - 2026-02-10
253
+
239
254
  ### Added
240
255
 
241
256
  - Added Alt+Y keybinding to cycle through kill ring entries (yank-pop)
@@ -252,6 +267,7 @@
252
267
  - Changed undo coalescing in Input component to group consecutive word typing into single undo units
253
268
 
254
269
  ## [11.4.1] - 2026-02-06
270
+
255
271
  ### Fixed
256
272
 
257
273
  - Fixed terminal scrolling when displaying overlays after rendering large content, preventing hundreds of blank lines from being output
@@ -344,6 +360,7 @@
344
360
  - Fixed handling of private use Unicode codepoints (U+E000 to U+F8FF) in Kitty key decoding to prevent invalid character interpretation
345
361
 
346
362
  ## [9.7.0] - 2026-02-01
363
+
347
364
  ### Breaking Changes
348
365
 
349
366
  - Removed `Key` helper object from public API; use string literals like `"ctrl+c"` instead of `Key.ctrl("c")`
@@ -355,6 +372,7 @@
355
372
  - Simplified `isKeyRelease()` and `isKeyRepeat()` to use regex pattern matching instead of string inclusion checks
356
373
 
357
374
  ## [9.6.2] - 2026-02-01
375
+
358
376
  ### Changed
359
377
 
360
378
  - Renamed `EllipsisKind` enum to `Ellipsis` for clearer API naming
@@ -368,6 +386,7 @@
368
386
  - Removed `extractAnsiCode` function from public API
369
387
 
370
388
  ## [9.6.1] - 2026-02-01
389
+
371
390
  ### Changed
372
391
 
373
392
  - Improved performance of key ID parsing with optimized cache lookup strategy
@@ -378,12 +397,14 @@
378
397
  - Removed `visibleWidth` benchmark file in favor of Kitty sequence benchmarking
379
398
 
380
399
  ## [9.5.0] - 2026-02-01
400
+
381
401
  ### Changed
382
402
 
383
403
  - Improved fuzzy file search performance by using native implementation instead of spawning external process
384
404
  - Replaced external `fd` binary with native fuzzy path search for `@`-prefixed autocomplete
385
405
 
386
406
  ## [9.4.0] - 2026-01-31
407
+
387
408
  ### Added
388
409
 
389
410
  - Exported `padding` utility function for creating space-padded strings efficiently
@@ -395,59 +416,74 @@
395
416
  ## [9.2.2] - 2026-01-31
396
417
 
397
418
  ### Added
419
+
398
420
  - Added setAutocompleteMaxVisible() configuration (3-20 items)
399
421
  - Added image detection to terminal capabilities (containsImage method)
400
422
  - Added stdin monitoring to detect stalled input events and log warnings
401
423
 
402
424
  ### Changed
425
+
403
426
  - Improved blockquote rendering with text wrapping in Markdown component
404
427
  - Restructured terminal capabilities from interface-based to class-based model
405
428
  - Improved table column width calculation with word-aware wrapping
406
429
  - Refactored text utilities to use native WASM implementations for strings >256 chars with JS fast path
407
430
 
408
431
  ### Fixed
432
+
409
433
  - Simplified terminal write error handling to mark terminal as dead on any write failure
410
434
  - Fixed multi-line strings in renderOutputBlock causing width overflow
411
435
  - Fixed slash command autocomplete applying stale completion when typing quickly
412
436
 
413
437
  ### Removed
438
+
414
439
  - Removed TUI layout engine exports from public API (BoxNode, ColumnNode, LayoutNode, etc.)
415
440
 
416
441
  ## [8.12.7] - 2026-01-29
417
442
 
418
443
  ### Fixed
444
+
419
445
  - Fixed slash command autocomplete applying stale completion when typing quickly
420
446
 
421
447
  ## [8.4.1] - 2026-01-25
422
448
 
423
449
  ### Added
450
+
424
451
  - Added fuzzy match function for autocomplete suggestions
452
+
425
453
  ## [8.4.0] - 2026-01-25
426
454
 
427
455
  ### Changed
456
+
428
457
  - Added Ctrl+Backspace as a delete-word-backward keybinding and improved modified backspace matching
429
458
 
430
459
  ### Fixed
460
+
431
461
  - Terminal gracefully handles write failures by marking dead instead of exiting the process
432
462
  - Reserved cursor space for zero padding and corrected end-of-line cursor rendering to prevent wrap glitches
433
463
  - Corrected editor end-of-line cursor rendering assertion to use includes() instead of endsWith()
464
+
434
465
  ## [8.2.0] - 2026-01-24
435
466
 
436
467
  ### Added
468
+
437
469
  - Added mermaid diagram rendering engine (renderMermaidToPng) with mmdc CLI integration
438
470
  - Added terminal graphics encoding (iTerm2/Kitty) for mermaid diagrams with automatic width scaling
439
471
  - Added mermaid block extraction and deduplication utilities (extractMermaidBlocks)
440
472
 
441
473
  ### Changed
474
+
442
475
  - Updated TypeScript configuration for better publish-time configuration handling with tsconfig.publish.json
443
476
  - Migrated file system operations from synchronous to asynchronous APIs in autocomplete provider for non-blocking I/O
444
477
  - Migrated node module imports from named to namespace imports across all packages for consistency with project guidelines
445
478
 
446
479
  ### Fixed
480
+
447
481
  - Fixed crash when terminal becomes unavailable (EIO errors) by exiting gracefully instead of throwing
448
482
  - Fixed potential errors during emergency terminal restore when terminal is already dead
449
483
  - Fixed autocomplete race condition by tracking request ID to prevent stale suggestion results
484
+
450
485
  ## [6.8.3] - 2026-01-21
486
+
451
487
  ### Added
452
488
 
453
489
  - Added undo support in the editor via `Ctrl+-`
@@ -503,6 +539,7 @@
503
539
  - Fixed Alt+letter key combinations for better recognition
504
540
 
505
541
  ## [5.3.1] - 2026-01-15
542
+
506
543
  ### Fixed
507
544
 
508
545
  - Fixed rendering issues on Windows by preventing re-entrant renders
@@ -532,27 +569,32 @@
532
569
  ## [4.7.0] - 2026-01-12
533
570
 
534
571
  ### Fixed
572
+
535
573
  - Remove trailing space padding from Text, Markdown, and TruncatedText components when no background color is set (fixes copied text including unwanted whitespace)
536
574
 
537
575
  ## [4.6.0] - 2026-01-12
538
576
 
539
577
  ### Added
578
+
540
579
  - Add fuzzy matching module (`fuzzyMatch`, `fuzzyFilter`) for command autocomplete
541
580
  - Add `getExpandedText()` to editor for expanding paste markers
542
581
  - Add backslash+enter newline fallback for terminals without Kitty protocol
543
582
 
544
583
  ### Fixed
584
+
545
585
  - Remove Kitty protocol query timeout that caused shift+enter delays
546
586
  - Add bracketed paste check to prevent false key release/repeat detection
547
587
  - Rendering optimizations: only re-render changed lines
548
588
  - Refactor input component to use keybindings manager
549
589
 
550
590
  ## [4.4.4] - 2026-01-11
591
+
551
592
  ### Fixed
552
593
 
553
594
  - Fixed Ctrl+Enter sequences to insert new lines in the editor
554
595
 
555
596
  ## [4.2.1] - 2026-01-11
597
+
556
598
  ### Changed
557
599
 
558
600
  - Improved file autocomplete to show directory listing when typing `@` with no query, and fall back to prefix matching when fuzzy search returns no results
@@ -563,11 +605,13 @@
563
605
  - Fixed `fd` tool detection to automatically find `fd` or `fdfind` in PATH when not explicitly configured
564
606
 
565
607
  ## [4.1.0] - 2026-01-10
608
+
566
609
  ### Added
567
610
 
568
611
  - Added persistent prompt history storage support via `setHistoryStorage()` method, allowing history to be saved and restored across sessions
569
612
 
570
613
  ## [4.0.0] - 2026-01-10
614
+
571
615
  ### Added
572
616
 
573
617
  - `EditorComponent` interface for custom editor implementations
@@ -598,6 +642,7 @@
598
642
  - Fixed text wrapping allowing long whitespace tokens to exceed line width
599
643
 
600
644
  ## [3.20.0] - 2026-01-06
645
+
601
646
  ### Added
602
647
 
603
648
  - Added `isCapsLock` helper function for detecting Caps Lock key press via Kitty protocol
@@ -629,6 +674,7 @@
629
674
  - Added support for custom spinner frames in the Loader component
630
675
 
631
676
  ## [3.9.1337] - 2026-01-04
677
+
632
678
  ### Added
633
679
 
634
680
  - Added `setTopBorder()` method to Editor component for displaying custom status content in the top border
@@ -641,6 +687,7 @@
641
687
  - Changed cursor style from block to thin blinking bar (▏) at end of line
642
688
 
643
689
  ## [1.500.0] - 2026-01-03
690
+
644
691
  ### Added
645
692
 
646
693
  - Added `getText()` method to Text component for retrieving current text content
package/README.md CHANGED
@@ -29,8 +29,8 @@ tui.addChild(new Text("Welcome to my app!"));
29
29
 
30
30
  const editor = new Editor(editorTheme);
31
31
  editor.onSubmit = (text) => {
32
- console.log("Submitted:", text);
33
- tui.addChild(new Text(`You said: ${text}`));
32
+ console.log("Submitted:", text);
33
+ tui.addChild(new Text(`You said: ${text}`));
34
34
  };
35
35
  tui.addChild(editor);
36
36
 
@@ -62,9 +62,9 @@ All components implement:
62
62
 
63
63
  ```typescript
64
64
  interface Component {
65
- render(width: number): string[];
66
- handleInput?(data: string): void;
67
- invalidate?(): void;
65
+ render(width: number): string[];
66
+ handleInput?(data: string): void;
67
+ invalidate?(): void;
68
68
  }
69
69
  ```
70
70
 
@@ -92,9 +92,9 @@ Container that applies padding and background color to all children.
92
92
 
93
93
  ```typescript
94
94
  const box = new Box(
95
- 1, // paddingX (default: 1)
96
- 1, // paddingY (default: 1)
97
- (text) => chalk.bgGray(text), // optional background function
95
+ 1, // paddingX (default: 1)
96
+ 1, // paddingY (default: 1)
97
+ (text) => chalk.bgGray(text), // optional background function
98
98
  );
99
99
  box.addChild(new Text("Content"));
100
100
  box.setBgFn((text) => chalk.bgBlue(text)); // Change background dynamically
@@ -106,10 +106,10 @@ Displays multi-line text with word wrapping and padding.
106
106
 
107
107
  ```typescript
108
108
  const text = new Text(
109
- "Hello World", // text content
110
- 1, // paddingX (default: 1)
111
- 1, // paddingY (default: 1)
112
- (text) => chalk.bgGray(text), // optional background function
109
+ "Hello World", // text content
110
+ 1, // paddingX (default: 1)
111
+ 1, // paddingY (default: 1)
112
+ (text) => chalk.bgGray(text), // optional background function
113
113
  );
114
114
  text.setText("Updated text");
115
115
  text.setCustomBgFn((text) => chalk.bgBlue(text));
@@ -121,9 +121,9 @@ Single-line text that truncates to fit viewport width. Useful for status lines a
121
121
 
122
122
  ```typescript
123
123
  const truncated = new TruncatedText(
124
- "This is a very long line that will be truncated...",
125
- 0, // paddingX (default: 0)
126
- 0, // paddingY (default: 0)
124
+ "This is a very long line that will be truncated...",
125
+ 0, // paddingX (default: 0)
126
+ 0, // paddingY (default: 0)
127
127
  );
128
128
  ```
129
129
 
@@ -155,51 +155,51 @@ Multi-line text editor with autocomplete, file completion, and paste handling.
155
155
 
156
156
  ```typescript
157
157
  interface SymbolTheme {
158
- cursor: string;
159
- ellipsis: string;
160
- boxRound: {
161
- topLeft: string;
162
- topRight: string;
163
- bottomLeft: string;
164
- bottomRight: string;
165
- horizontal: string;
166
- vertical: string;
167
- };
168
- boxSharp: {
169
- topLeft: string;
170
- topRight: string;
171
- bottomLeft: string;
172
- bottomRight: string;
173
- horizontal: string;
174
- vertical: string;
175
- teeDown: string;
176
- teeUp: string;
177
- teeLeft: string;
178
- teeRight: string;
179
- cross: string;
180
- };
181
- table: {
182
- topLeft: string;
183
- topRight: string;
184
- bottomLeft: string;
185
- bottomRight: string;
186
- horizontal: string;
187
- vertical: string;
188
- teeDown: string;
189
- teeUp: string;
190
- teeLeft: string;
191
- teeRight: string;
192
- cross: string;
193
- };
194
- quoteBorder: string;
195
- hrChar: string;
196
- spinnerFrames: string[];
158
+ cursor: string;
159
+ ellipsis: string;
160
+ boxRound: {
161
+ topLeft: string;
162
+ topRight: string;
163
+ bottomLeft: string;
164
+ bottomRight: string;
165
+ horizontal: string;
166
+ vertical: string;
167
+ };
168
+ boxSharp: {
169
+ topLeft: string;
170
+ topRight: string;
171
+ bottomLeft: string;
172
+ bottomRight: string;
173
+ horizontal: string;
174
+ vertical: string;
175
+ teeDown: string;
176
+ teeUp: string;
177
+ teeLeft: string;
178
+ teeRight: string;
179
+ cross: string;
180
+ };
181
+ table: {
182
+ topLeft: string;
183
+ topRight: string;
184
+ bottomLeft: string;
185
+ bottomRight: string;
186
+ horizontal: string;
187
+ vertical: string;
188
+ teeDown: string;
189
+ teeUp: string;
190
+ teeLeft: string;
191
+ teeRight: string;
192
+ cross: string;
193
+ };
194
+ quoteBorder: string;
195
+ hrChar: string;
196
+ spinnerFrames: string[];
197
197
  }
198
198
 
199
199
  interface EditorTheme {
200
- borderColor: (str: string) => string;
201
- selectList: SelectListTheme;
202
- symbols: SymbolTheme;
200
+ borderColor: (str: string) => string;
201
+ selectList: SelectListTheme;
202
+ symbols: SymbolTheme;
203
203
  }
204
204
 
205
205
  const editor = new Editor(theme);
@@ -236,40 +236,40 @@ Renders markdown with syntax highlighting and theming support.
236
236
 
237
237
  ```typescript
238
238
  interface MarkdownTheme {
239
- heading: (text: string) => string;
240
- link: (text: string) => string;
241
- linkUrl: (text: string) => string;
242
- code: (text: string) => string;
243
- codeBlock: (text: string) => string;
244
- codeBlockBorder: (text: string) => string;
245
- quote: (text: string) => string;
246
- quoteBorder: (text: string) => string;
247
- hr: (text: string) => string;
248
- listBullet: (text: string) => string;
249
- bold: (text: string) => string;
250
- italic: (text: string) => string;
251
- strikethrough: (text: string) => string;
252
- underline: (text: string) => string;
253
- highlightCode?: (code: string, lang?: string) => string[];
254
- symbols: SymbolTheme;
239
+ heading: (text: string) => string;
240
+ link: (text: string) => string;
241
+ linkUrl: (text: string) => string;
242
+ code: (text: string) => string;
243
+ codeBlock: (text: string) => string;
244
+ codeBlockBorder: (text: string) => string;
245
+ quote: (text: string) => string;
246
+ quoteBorder: (text: string) => string;
247
+ hr: (text: string) => string;
248
+ listBullet: (text: string) => string;
249
+ bold: (text: string) => string;
250
+ italic: (text: string) => string;
251
+ strikethrough: (text: string) => string;
252
+ underline: (text: string) => string;
253
+ highlightCode?: (code: string, lang?: string) => string[];
254
+ symbols: SymbolTheme;
255
255
  }
256
256
 
257
257
  interface DefaultTextStyle {
258
- color?: (text: string) => string;
259
- bgColor?: (text: string) => string;
260
- bold?: boolean;
261
- italic?: boolean;
262
- strikethrough?: boolean;
263
- underline?: boolean;
258
+ color?: (text: string) => string;
259
+ bgColor?: (text: string) => string;
260
+ bold?: boolean;
261
+ italic?: boolean;
262
+ strikethrough?: boolean;
263
+ underline?: boolean;
264
264
  }
265
265
 
266
266
  const md = new Markdown(
267
- "# Hello\n\nSome **bold** text",
268
- 1, // paddingX
269
- 1, // paddingY
270
- theme, // MarkdownTheme
271
- defaultStyle, // optional DefaultTextStyle
272
- 2, // optional code block indent (spaces)
267
+ "# Hello\n\nSome **bold** text",
268
+ 1, // paddingX
269
+ 1, // paddingY
270
+ theme, // MarkdownTheme
271
+ defaultStyle, // optional DefaultTextStyle
272
+ 2, // optional code block indent (spaces)
273
273
  );
274
274
  md.setText("Updated markdown");
275
275
  ```
@@ -288,10 +288,10 @@ Animated loading spinner.
288
288
 
289
289
  ```typescript
290
290
  const loader = new Loader(
291
- tui, // TUI instance for render updates
292
- (s) => chalk.cyan(s), // spinner color function
293
- (s) => chalk.gray(s), // message color function
294
- "Loading...", // message (default: "Loading...")
291
+ tui, // TUI instance for render updates
292
+ (s) => chalk.cyan(s), // spinner color function
293
+ (s) => chalk.gray(s), // message color function
294
+ "Loading...", // message (default: "Loading...")
295
295
  );
296
296
  loader.start();
297
297
  loader.setMessage("Still loading...");
@@ -304,10 +304,10 @@ Extends Loader with Escape key handling and an AbortSignal for cancelling async
304
304
 
305
305
  ```typescript
306
306
  const loader = new CancellableLoader(
307
- tui, // TUI instance for render updates
308
- (s) => chalk.cyan(s), // spinner color function
309
- (s) => chalk.gray(s), // message color function
310
- "Working...", // message
307
+ tui, // TUI instance for render updates
308
+ (s) => chalk.cyan(s), // spinner color function
309
+ (s) => chalk.gray(s), // message color function
310
+ "Working...", // message
311
311
  );
312
312
  loader.onAbort = () => done(null); // Called when user presses Escape
313
313
  doAsyncWork(loader.signal).then(done);
@@ -325,27 +325,27 @@ Interactive selection list with keyboard navigation.
325
325
 
326
326
  ```typescript
327
327
  interface SelectItem {
328
- value: string;
329
- label: string;
330
- description?: string;
328
+ value: string;
329
+ label: string;
330
+ description?: string;
331
331
  }
332
332
 
333
333
  interface SelectListTheme {
334
- selectedPrefix: (text: string) => string;
335
- selectedText: (text: string) => string;
336
- description: (text: string) => string;
337
- scrollInfo: (text: string) => string;
338
- noMatch: (text: string) => string;
339
- symbols: SymbolTheme;
334
+ selectedPrefix: (text: string) => string;
335
+ selectedText: (text: string) => string;
336
+ description: (text: string) => string;
337
+ scrollInfo: (text: string) => string;
338
+ noMatch: (text: string) => string;
339
+ symbols: SymbolTheme;
340
340
  }
341
341
 
342
342
  const list = new SelectList(
343
- [
344
- { value: "opt1", label: "Option 1", description: "First option" },
345
- { value: "opt2", label: "Option 2", description: "Second option" },
346
- ],
347
- 5, // maxVisible
348
- theme, // SelectListTheme
343
+ [
344
+ { value: "opt1", label: "Option 1", description: "First option" },
345
+ { value: "opt2", label: "Option 2", description: "Second option" },
346
+ ],
347
+ 5, // maxVisible
348
+ theme, // SelectListTheme
349
349
  );
350
350
 
351
351
  list.onSelect = (item) => console.log("Selected:", item);
@@ -366,31 +366,31 @@ Settings panel with value cycling and submenus.
366
366
 
367
367
  ```typescript
368
368
  interface SettingItem {
369
- id: string;
370
- label: string;
371
- description?: string;
372
- currentValue: string;
373
- values?: string[]; // If provided, Enter/Space cycles through these
374
- submenu?: (currentValue: string, done: (selectedValue?: string) => void) => Component;
369
+ id: string;
370
+ label: string;
371
+ description?: string;
372
+ currentValue: string;
373
+ values?: string[]; // If provided, Enter/Space cycles through these
374
+ submenu?: (currentValue: string, done: (selectedValue?: string) => void) => Component;
375
375
  }
376
376
 
377
377
  interface SettingsListTheme {
378
- label: (text: string, selected: boolean) => string;
379
- value: (text: string, selected: boolean) => string;
380
- description: (text: string) => string;
381
- cursor: string;
382
- hint: (text: string) => string;
378
+ label: (text: string, selected: boolean) => string;
379
+ value: (text: string, selected: boolean) => string;
380
+ description: (text: string) => string;
381
+ cursor: string;
382
+ hint: (text: string) => string;
383
383
  }
384
384
 
385
385
  const settings = new SettingsList(
386
- [
387
- { id: "theme", label: "Theme", currentValue: "dark", values: ["dark", "light"] },
388
- { id: "model", label: "Model", currentValue: "gpt-4", submenu: (val, done) => modelSelector },
389
- ],
390
- 10, // maxVisible
391
- theme, // SettingsListTheme
392
- (id, newValue) => console.log(`${id} changed to ${newValue}`),
393
- () => console.log("Cancelled"),
386
+ [
387
+ { id: "theme", label: "Theme", currentValue: "dark", values: ["dark", "light"] },
388
+ { id: "model", label: "Model", currentValue: "gpt-4", submenu: (val, done) => modelSelector },
389
+ ],
390
+ 10, // maxVisible
391
+ theme, // SettingsListTheme
392
+ (id, newValue) => console.log(`${id} changed to ${newValue}`),
393
+ () => console.log("Cancelled"),
394
394
  );
395
395
  settings.updateValue("theme", "light");
396
396
  ```
@@ -415,20 +415,20 @@ Renders images inline for terminals that support the Kitty graphics protocol (Ki
415
415
 
416
416
  ```typescript
417
417
  interface ImageTheme {
418
- fallbackColor: (str: string) => string;
418
+ fallbackColor: (str: string) => string;
419
419
  }
420
420
 
421
421
  interface ImageOptions {
422
- maxWidthCells?: number;
423
- maxHeightCells?: number;
424
- filename?: string;
422
+ maxWidthCells?: number;
423
+ maxHeightCells?: number;
424
+ filename?: string;
425
425
  }
426
426
 
427
427
  const image = new Image(
428
- base64Data, // base64-encoded image data
429
- "image/png", // MIME type
430
- theme, // ImageTheme
431
- options, // optional ImageOptions
428
+ base64Data, // base64-encoded image data
429
+ "image/png", // MIME type
430
+ theme, // ImageTheme
431
+ options, // optional ImageOptions
432
432
  );
433
433
  tui.addChild(image);
434
434
  ```
@@ -446,12 +446,12 @@ import { CombinedAutocompleteProvider } from "@f5-sales-demo/pi-tui";
446
446
  import { getProjectDir } from "@f5-sales-demo/pi-utils";
447
447
 
448
448
  const provider = new CombinedAutocompleteProvider(
449
- [
450
- { name: "help", description: "Show help" },
451
- { name: "clear", description: "Clear screen" },
452
- { name: "delete", description: "Delete last message" },
453
- ],
454
- getProjectDir(), // base path for file completion
449
+ [
450
+ { name: "help", description: "Show help" },
451
+ { name: "clear", description: "Clear screen" },
452
+ { name: "delete", description: "Delete last message" },
453
+ ],
454
+ getProjectDir(), // base path for file completion
455
455
  );
456
456
 
457
457
  editor.setAutocompleteProvider(provider);
@@ -470,38 +470,38 @@ Helper functions for detecting keyboard input (supports Kitty keyboard protocol)
470
470
 
471
471
  ```typescript
472
472
  import {
473
- isEnter,
474
- isEscape,
475
- isTab,
476
- isShiftTab,
477
- isArrowUp,
478
- isArrowDown,
479
- isArrowLeft,
480
- isArrowRight,
481
- isCtrlA,
482
- isCtrlC,
483
- isCtrlE,
484
- isCtrlK,
485
- isCtrlO,
486
- isCtrlP,
487
- isCtrlLeft,
488
- isCtrlRight,
489
- isAltLeft,
490
- isAltRight,
491
- isShiftEnter,
492
- isAltEnter,
493
- isShiftCtrlO,
494
- isShiftCtrlD,
495
- isShiftCtrlP,
496
- isBackspace,
497
- isDelete,
498
- isHome,
499
- isEnd,
500
- // ... and more
473
+ isEnter,
474
+ isEscape,
475
+ isTab,
476
+ isShiftTab,
477
+ isArrowUp,
478
+ isArrowDown,
479
+ isArrowLeft,
480
+ isArrowRight,
481
+ isCtrlA,
482
+ isCtrlC,
483
+ isCtrlE,
484
+ isCtrlK,
485
+ isCtrlO,
486
+ isCtrlP,
487
+ isCtrlLeft,
488
+ isCtrlRight,
489
+ isAltLeft,
490
+ isAltRight,
491
+ isShiftEnter,
492
+ isAltEnter,
493
+ isShiftCtrlO,
494
+ isShiftCtrlD,
495
+ isShiftCtrlP,
496
+ isBackspace,
497
+ isDelete,
498
+ isHome,
499
+ isEnd,
500
+ // ... and more
501
501
  } from "@f5-sales-demo/pi-tui";
502
502
 
503
503
  if (isCtrlC(data)) {
504
- process.exit(0);
504
+ process.exit(0);
505
505
  }
506
506
  ```
507
507
 
@@ -521,17 +521,17 @@ The TUI works with any object implementing the `Terminal` interface:
521
521
 
522
522
  ```typescript
523
523
  interface Terminal {
524
- start(onInput: (data: string) => void, onResize: () => void): void;
525
- stop(): void;
526
- write(data: string): void;
527
- get columns(): number;
528
- get rows(): number;
529
- moveBy(lines: number): void;
530
- hideCursor(): void;
531
- showCursor(): void;
532
- clearLine(): void;
533
- clearFromCursor(): void;
534
- clearScreen(): void;
524
+ start(onInput: (data: string) => void, onResize: () => void): void;
525
+ stop(): void;
526
+ write(data: string): void;
527
+ get columns(): number;
528
+ get rows(): number;
529
+ moveBy(lines: number): void;
530
+ hideCursor(): void;
531
+ showCursor(): void;
532
+ clearLine(): void;
533
+ clearFromCursor(): void;
534
+ clearScreen(): void;
535
535
  }
536
536
  ```
537
537
 
@@ -572,30 +572,30 @@ import { isEnter, isEscape, isArrowUp, isArrowDown, isCtrlC, isTab, isBackspace
572
572
  import type { Component } from "@f5-sales-demo/pi-tui";
573
573
 
574
574
  class MyInteractiveComponent implements Component {
575
- private selectedIndex = 0;
576
- private items = ["Option 1", "Option 2", "Option 3"];
577
-
578
- onSelect?: (index: number) => void;
579
- onCancel?: () => void;
580
-
581
- handleInput(data: string): void {
582
- if (isArrowUp(data)) {
583
- this.selectedIndex = Math.max(0, this.selectedIndex - 1);
584
- } else if (isArrowDown(data)) {
585
- this.selectedIndex = Math.min(this.items.length - 1, this.selectedIndex + 1);
586
- } else if (isEnter(data)) {
587
- this.onSelect?.(this.selectedIndex);
588
- } else if (isEscape(data) || isCtrlC(data)) {
589
- this.onCancel?.();
590
- }
591
- }
592
-
593
- render(width: number): string[] {
594
- return this.items.map((item, i) => {
595
- const prefix = i === this.selectedIndex ? "> " : " ";
596
- return truncateToWidth(prefix + item, width);
597
- });
598
- }
575
+ private selectedIndex = 0;
576
+ private items = ["Option 1", "Option 2", "Option 3"];
577
+
578
+ onSelect?: (index: number) => void;
579
+ onCancel?: () => void;
580
+
581
+ handleInput(data: string): void {
582
+ if (isArrowUp(data)) {
583
+ this.selectedIndex = Math.max(0, this.selectedIndex - 1);
584
+ } else if (isArrowDown(data)) {
585
+ this.selectedIndex = Math.min(this.items.length - 1, this.selectedIndex + 1);
586
+ } else if (isEnter(data)) {
587
+ this.onSelect?.(this.selectedIndex);
588
+ } else if (isEscape(data) || isCtrlC(data)) {
589
+ this.onCancel?.();
590
+ }
591
+ }
592
+
593
+ render(width: number): string[] {
594
+ return this.items.map((item, i) => {
595
+ const prefix = i === this.selectedIndex ? "> " : " ";
596
+ return truncateToWidth(prefix + item, width);
597
+ });
598
+ }
599
599
  }
600
600
  ```
601
601
 
@@ -608,25 +608,25 @@ import { visibleWidth, truncateToWidth } from "@f5-sales-demo/pi-tui";
608
608
  import type { Component } from "@f5-sales-demo/pi-tui";
609
609
 
610
610
  class MyComponent implements Component {
611
- private text: string;
612
-
613
- constructor(text: string) {
614
- this.text = text;
615
- }
616
-
617
- render(width: number): string[] {
618
- // Option 1: Truncate long lines
619
- return [truncateToWidth(this.text, width)];
620
-
621
- // Option 2: Check and pad to exact width
622
- const line = this.text;
623
- const visible = visibleWidth(line);
624
- if (visible > width) {
625
- return [truncateToWidth(line, width)];
626
- }
627
- // Pad to exact width (optional, for backgrounds)
628
- return [line + " ".repeat(width - visible)];
629
- }
611
+ private text: string;
612
+
613
+ constructor(text: string) {
614
+ this.text = text;
615
+ }
616
+
617
+ render(width: number): string[] {
618
+ // Option 1: Truncate long lines
619
+ return [truncateToWidth(this.text, width)];
620
+
621
+ // Option 2: Check and pad to exact width
622
+ const line = this.text;
623
+ const visible = visibleWidth(line);
624
+ if (visible > width) {
625
+ return [truncateToWidth(line, width)];
626
+ }
627
+ // Pad to exact width (optional, for backgrounds)
628
+ return [line + " ".repeat(width - visible)];
629
+ }
630
630
  }
631
631
  ```
632
632
 
@@ -652,26 +652,26 @@ For performance, components should cache their rendered output and only re-rende
652
652
 
653
653
  ```typescript
654
654
  class CachedComponent implements Component {
655
- private text: string;
656
- private cachedWidth?: number;
657
- private cachedLines?: string[];
658
-
659
- render(width: number): string[] {
660
- if (this.cachedLines && this.cachedWidth === width) {
661
- return this.cachedLines;
662
- }
663
-
664
- const lines = [truncateToWidth(this.text, width)];
665
-
666
- this.cachedWidth = width;
667
- this.cachedLines = lines;
668
- return lines;
669
- }
670
-
671
- invalidate(): void {
672
- this.cachedWidth = undefined;
673
- this.cachedLines = undefined;
674
- }
655
+ private text: string;
656
+ private cachedWidth?: number;
657
+ private cachedLines?: string[];
658
+
659
+ render(width: number): string[] {
660
+ if (this.cachedLines && this.cachedWidth === width) {
661
+ return this.cachedLines;
662
+ }
663
+
664
+ const lines = [truncateToWidth(this.text, width)];
665
+
666
+ this.cachedWidth = width;
667
+ this.cachedLines = lines;
668
+ return lines;
669
+ }
670
+
671
+ invalidate(): void {
672
+ this.cachedWidth = undefined;
673
+ this.cachedLines = undefined;
674
+ }
675
675
  }
676
676
  ```
677
677
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@f5-sales-demo/pi-tui",
4
- "version": "20.2.4",
4
+ "version": "20.2.7",
5
5
  "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
6
6
  "homepage": "https://github.com/f5-sales-demo/xcsh",
7
7
  "author": "Can Boluk",
@@ -37,8 +37,8 @@
37
37
  "fmt": "biome format --write ."
38
38
  },
39
39
  "dependencies": {
40
- "@f5-sales-demo/pi-natives": "20.2.4",
41
- "@f5-sales-demo/pi-utils": "20.2.4",
40
+ "@f5-sales-demo/pi-natives": "20.2.7",
41
+ "@f5-sales-demo/pi-utils": "20.2.7",
42
42
  "marked": "^18.0"
43
43
  },
44
44
  "devDependencies": {