@mariozechner/pi-tui 0.5.8 → 0.5.9

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/README.md CHANGED
@@ -1,13 +1,14 @@
1
1
  # @mariozechner/pi-tui
2
2
 
3
- Terminal UI framework with differential rendering for building interactive CLI applications.
3
+ Terminal UI framework with surgical differential rendering for building flicker-free interactive CLI applications.
4
4
 
5
5
  ## Features
6
6
 
7
- - **Differential Rendering**: Only re-renders content that has changed for optimal performance
8
- - **Interactive Components**: Text editor, autocomplete, selection lists, and markdown rendering
9
- - **Composable Architecture**: Container-based component system with proper lifecycle management
10
- - **Text Editor Autocomplete System**: File completion and slash commands with provider interface
7
+ - **Surgical Differential Rendering**: Three-strategy system that minimizes redraws to 1-2 lines for typical updates
8
+ - **Scrollback Buffer Preservation**: Correctly maintains terminal history when content exceeds viewport
9
+ - **Zero Flicker**: Components like text editors remain perfectly still while other parts update
10
+ - **Interactive Components**: Text editor with autocomplete, selection lists, markdown rendering
11
+ - **Composable Architecture**: Container-based component system with automatic lifecycle management
11
12
 
12
13
  ## Quick Start
13
14
 
@@ -35,7 +36,7 @@ editor.onSubmit = (text: string) => {
35
36
  if (text.trim()) {
36
37
  const message = new TextComponent(`💬 ${text}`);
37
38
  chatContainer.addChild(message);
38
- ui.requestRender();
39
+ // Note: Container automatically calls requestRender when children change
39
40
  }
40
41
  };
41
42
 
@@ -47,135 +48,63 @@ ui.start();
47
48
 
48
49
  ### TUI
49
50
 
50
- Main TUI manager that handles rendering, input, and component coordination.
51
+ Main TUI manager with surgical differential rendering that handles input and component lifecycle.
51
52
 
52
- **Methods:**
53
+ **Key Features:**
54
+ - **Three rendering strategies**: Automatically selects optimal approach
55
+ - Surgical: Updates only changed lines (1-2 lines typical)
56
+ - Partial: Re-renders from first change when structure shifts
57
+ - Full: Complete re-render when changes are above viewport
58
+ - **Performance metrics**: Built-in tracking via `getLinesRedrawn()` and `getAverageLinesRedrawn()`
59
+ - **Terminal abstraction**: Works with any Terminal interface implementation
53
60
 
54
- - `addChild(component)` - Add a component to the TUI
55
- - `removeChild(component)` - Remove a component from the TUI
56
- - `setFocus(component)` - Set which component receives keyboard input
57
- - `start()` - Start the TUI (enables raw mode)
58
- - `stop()` - Stop the TUI (disables raw mode)
59
- - `requestRender()` - Request a re-render on next tick
60
- - `configureLogging(config)` - Configure debug logging
61
- - `cleanupSentinels()` - Remove placeholder components after removal operations
62
- - `findComponent(component)` - Check if a component exists in the hierarchy (private)
63
- - `findInContainer(container, component)` - Search for component in container (private)
61
+ **Methods:**
62
+ - `addChild(component)` - Add a component
63
+ - `removeChild(component)` - Remove a component
64
+ - `setFocus(component)` - Set keyboard focus
65
+ - `start()` / `stop()` - Lifecycle management
66
+ - `requestRender()` - Queue re-render (automatically debounced)
67
+ - `configureLogging(config)` - Enable debug logging
64
68
 
65
69
  ### Container
66
70
 
67
- Component that manages child components with differential rendering.
68
-
69
- **Constructor:**
71
+ Component that manages child components. Automatically triggers re-renders when children change.
70
72
 
71
73
  ```typescript
72
- new Container(parentTui?: TUI | undefined)
74
+ const container = new Container();
75
+ container.addChild(new TextComponent("Child 1"));
76
+ container.removeChild(component);
77
+ container.clear();
73
78
  ```
74
79
 
75
- **Methods:**
76
-
77
- - `addChild(component)` - Add a child component
78
- - `removeChild(component)` - Remove a child component
79
- - `getChild(index)` - Get a specific child component
80
- - `getChildCount()` - Get the number of child components
81
- - `clear()` - Remove all child components
82
- - `setParentTui(tui)` - Set the parent TUI reference
83
- - `cleanupSentinels()` - Clean up removed component placeholders
84
- - `render(width)` - Render all child components (returns ContainerRenderResult)
85
-
86
80
  ### TextEditor
87
81
 
88
- Interactive multiline text editor with cursor support and comprehensive keyboard shortcuts.
89
-
90
- **Constructor:**
82
+ Interactive multiline text editor with autocomplete support.
91
83
 
92
84
  ```typescript
93
- new TextEditor(config?: TextEditorConfig)
94
- ```
95
-
96
- **Configuration:**
97
-
98
- ```typescript
99
- interface TextEditorConfig {
100
- // Configuration options for text editor
101
- }
102
-
103
- editor.configure(config: Partial<TextEditorConfig>)
85
+ const editor = new TextEditor();
86
+ editor.setText("Initial text");
87
+ editor.onSubmit = (text) => console.log("Submitted:", text);
88
+ editor.setAutocompleteProvider(provider);
104
89
  ```
105
90
 
106
- **Properties:**
107
-
108
- - `onSubmit?: (text: string) => void` - Callback when user presses Enter
109
- - `onChange?: (text: string) => void` - Callback when text content changes
110
-
111
- **Methods:**
112
-
113
- - `getText()` - Get current text content
114
- - `setText(text)` - Set text content and move cursor to end
115
- - `setAutocompleteProvider(provider)` - Set autocomplete provider for Tab completion
116
- - `render(width)` - Render the editor with current state
117
- - `handleInput(data)` - Process keyboard input
118
-
119
- **Keyboard Shortcuts:**
120
-
121
- **Navigation:**
122
-
123
- - `Arrow Keys` - Move cursor
124
- - `Home` / `Ctrl+A` - Move to start of line
125
- - `End` / `Ctrl+E` - Move to end of line
126
-
127
- **Editing:**
128
-
129
- - `Backspace` - Delete character before cursor
130
- - `Delete` / `Fn+Backspace` - Delete character at cursor
131
- - `Ctrl+K` - Delete current line
132
- - `Enter` - Submit text (calls onSubmit)
133
- - `Shift+Enter` / `Option+Enter` - Add new line
134
- - `Tab` - Trigger autocomplete
135
-
136
- **Autocomplete (when active):**
137
-
138
- - `Tab` - Apply selected completion
139
- - `Arrow Up/Down` - Navigate suggestions
140
- - `Escape` - Cancel autocomplete
141
- - `Enter` - Cancel autocomplete and submit
142
-
143
- **Paste Detection:**
144
-
145
- - Automatically handles multi-line paste
146
- - Converts tabs to 4 spaces
147
- - Filters non-printable characters
91
+ **Key Bindings:**
92
+ - `Enter` - Submit text
93
+ - `Shift+Enter` - New line
94
+ - `Tab` - Autocomplete
95
+ - `Ctrl+K` - Delete line
96
+ - `Ctrl+A/E` - Start/end of line
97
+ - Arrow keys, Backspace, Delete work as expected
148
98
 
149
99
  ### TextComponent
150
100
 
151
- Simple text component with automatic text wrapping and differential rendering.
152
-
153
- **Constructor:**
101
+ Simple text display with automatic word wrapping.
154
102
 
155
103
  ```typescript
156
- new TextComponent(text: string, padding?: Padding)
157
-
158
- interface Padding {
159
- top?: number;
160
- bottom?: number;
161
- left?: number;
162
- right?: number;
163
- }
104
+ const text = new TextComponent("Hello World", { top: 1, bottom: 1 });
105
+ text.setText("Updated text");
164
106
  ```
165
107
 
166
- **Methods:**
167
-
168
- - `setText(text)` - Update the text content
169
- - `getText()` - Get current text content
170
- - `render(width)` - Render with word wrapping
171
-
172
- **Features:**
173
-
174
- - Automatic text wrapping to fit terminal width
175
- - Configurable padding on all sides
176
- - Preserves line breaks in source text
177
- - Uses differential rendering to avoid unnecessary updates
178
-
179
108
  ### MarkdownComponent
180
109
 
181
110
  Renders markdown content with syntax highlighting and proper formatting.
@@ -328,219 +257,83 @@ interface SlashCommand {
328
257
  - `shouldTriggerFileCompletion()` - Check if file completion should trigger
329
258
  - `applyCompletion()` - Apply selected completion
330
259
 
331
- ## Differential Rendering
332
-
333
- The core concept: components return `{lines: string[], changed: boolean, keepLines?: number}`:
334
-
335
- - `lines`: All lines the component should display
336
- - `changed`: Whether the component has changed since last render
337
- - `keepLines`: (Containers only) How many lines from the beginning are unchanged
338
-
339
- **How it works:**
340
-
341
- 1. TUI calculates total unchanged lines from top (`keepLines`)
342
- 2. Moves cursor up by `(totalLines - keepLines)` positions
343
- 3. Clears from cursor position down with `\x1b[0J`
344
- 4. Prints only the changing lines: `result.lines.slice(keepLines)`
345
-
346
- This approach minimizes screen updates and provides smooth performance even with large amounts of text.
347
-
348
- **Important:** Don't add extra cursor positioning after printing - it interferes with terminal scrolling and causes rendering artifacts.
260
+ ## Surgical Differential Rendering
349
261
 
350
- ## Advanced Examples
262
+ The TUI uses a three-strategy rendering system that minimizes redraws to only what's necessary:
351
263
 
352
- ### Chat Application with Autocomplete
264
+ ### Rendering Strategies
353
265
 
354
- ```typescript
355
- import { TUI, Container, TextEditor, MarkdownComponent, CombinedAutocompleteProvider } from "@mariozechner/pi-tui";
266
+ 1. **Surgical Updates** (most common)
267
+ - When: Only content changes, same line counts, all changes in viewport
268
+ - Action: Updates only specific changed lines (typically 1-2 lines)
269
+ - Example: Loading spinner animation, updating status text
356
270
 
357
- const ui = new TUI();
358
- const chatHistory = new Container();
359
- const editor = new TextEditor();
271
+ 2. **Partial Re-render**
272
+ - When: Line count changes or structural changes within viewport
273
+ - Action: Clears from first change to end of screen, re-renders tail
274
+ - Example: Adding new messages to a chat, expanding text editor
360
275
 
361
- // Set up autocomplete with slash commands
362
- const autocompleteProvider = new CombinedAutocompleteProvider([
363
- { name: "clear", description: "Clear chat history" },
364
- { name: "help", description: "Show help information" },
365
- {
366
- name: "attach",
367
- description: "Attach a file",
368
- getArgumentCompletions: (prefix) => {
369
- // Return file suggestions for attach command
370
- return null; // Use default file completion
371
- },
372
- },
373
- ]);
374
-
375
- editor.setAutocompleteProvider(autocompleteProvider);
376
-
377
- editor.onSubmit = (text) => {
378
- // Handle slash commands
379
- if (text.startsWith("/")) {
380
- const [command, ...args] = text.slice(1).split(" ");
381
- if (command === "clear") {
382
- chatHistory.clear();
383
- return;
384
- }
385
- if (command === "help") {
386
- const help = new MarkdownComponent(`
387
- ## Available Commands
388
- - \`/clear\` - Clear chat history
389
- - \`/help\` - Show this help
390
- - \`/attach <file>\` - Attach a file
391
- `);
392
- chatHistory.addChild(help);
393
- ui.requestRender();
394
- return;
395
- }
396
- }
276
+ 3. **Full Re-render**
277
+ - When: Changes occur above the viewport (in scrollback buffer)
278
+ - Action: Clears scrollback and screen, renders everything fresh
279
+ - Example: Content exceeds viewport and early components change
397
280
 
398
- // Regular message
399
- const message = new MarkdownComponent(`**You:** ${text}`);
400
- chatHistory.addChild(message);
281
+ ### How Components Participate
401
282
 
402
- // Add AI response (simulated)
403
- setTimeout(() => {
404
- const response = new MarkdownComponent(`**AI:** Response to "${text}"`);
405
- chatHistory.addChild(response);
406
- ui.requestRender();
407
- }, 1000);
408
- };
409
-
410
- ui.addChild(chatHistory);
411
- ui.addChild(editor);
412
- ui.setFocus(editor);
413
- ui.start();
414
- ```
415
-
416
- ### File Browser
283
+ Components implement the simple `Component` interface:
417
284
 
418
285
  ```typescript
419
- import { TUI, SelectList } from "@mariozechner/pi-tui";
420
- import { readdirSync, statSync } from "fs";
421
- import { join } from "path";
422
-
423
- const ui = new TUI();
424
- let currentPath = process.cwd();
425
-
426
- function createFileList(path: string) {
427
- const entries = readdirSync(path).map((entry) => {
428
- const fullPath = join(path, entry);
429
- const isDir = statSync(fullPath).isDirectory();
430
- return {
431
- value: entry,
432
- label: entry,
433
- description: isDir ? "directory" : "file",
434
- };
435
- });
436
-
437
- // Add parent directory option
438
- if (path !== "/") {
439
- entries.unshift({
440
- value: "..",
441
- label: "..",
442
- description: "parent directory",
443
- });
444
- }
445
-
446
- return entries;
286
+ interface ComponentRenderResult {
287
+ lines: string[]; // The lines to display
288
+ changed: boolean; // Whether content changed since last render
447
289
  }
448
290
 
449
- function showDirectory(path: string) {
450
- ui.clear();
451
-
452
- const entries = createFileList(path);
453
- const fileList = new SelectList(entries, 10);
454
-
455
- fileList.onSelect = (item) => {
456
- if (item.value === "..") {
457
- currentPath = join(currentPath, "..");
458
- showDirectory(currentPath);
459
- } else if (item.description === "directory") {
460
- currentPath = join(currentPath, item.value);
461
- showDirectory(currentPath);
462
- } else {
463
- console.log(`Selected file: ${join(currentPath, item.value)}`);
464
- ui.stop();
465
- }
466
- };
467
-
468
- ui.addChild(fileList);
469
- ui.setFocus(fileList);
291
+ interface Component {
292
+ readonly id: number; // Unique ID for tracking
293
+ render(width: number): ComponentRenderResult;
294
+ handleInput?(keyData: string): void;
470
295
  }
471
-
472
- showDirectory(currentPath);
473
- ui.start();
474
296
  ```
475
297
 
476
- ### Multi-Component Layout
298
+ The TUI tracks component IDs and line positions to determine the optimal strategy automatically.
477
299
 
478
- ```typescript
479
- import { TUI, Container, TextComponent, TextEditor, MarkdownComponent } from "@mariozechner/pi-tui";
300
+ ### Performance Metrics
480
301
 
481
- const ui = new TUI();
482
-
483
- // Create layout containers
484
- const header = new TextComponent("📝 Advanced TUI Demo", { bottom: 1 });
485
- const mainContent = new Container();
486
- const sidebar = new Container();
487
- const footer = new TextComponent("Press Ctrl+C to exit", { top: 1 });
302
+ Monitor rendering efficiency:
488
303
 
489
- // Sidebar content
490
- sidebar.addChild(new TextComponent("📁 Files:", { bottom: 1 }));
491
- sidebar.addChild(new TextComponent("- config.json"));
492
- sidebar.addChild(new TextComponent("- README.md"));
493
- sidebar.addChild(new TextComponent("- package.json"));
494
-
495
- // Main content area
496
- const chatArea = new Container();
497
- const inputArea = new TextEditor();
304
+ ```typescript
305
+ const ui = new TUI();
306
+ // After some rendering...
307
+ console.log(`Total lines redrawn: ${ui.getLinesRedrawn()}`);
308
+ console.log(`Average per render: ${ui.getAverageLinesRedrawn()}`);
309
+ ```
498
310
 
499
- // Add welcome message
500
- chatArea.addChild(
501
- new MarkdownComponent(`
502
- # Welcome to the TUI Demo
311
+ Typical performance: 1-2 lines redrawn for animations, 0 for static content.
503
312
 
504
- This demonstrates multiple components working together:
313
+ ## Examples
505
314
 
506
- - **Header**: Static title with padding
507
- - **Sidebar**: File list (simulated)
508
- - **Chat Area**: Scrollable message history
509
- - **Input**: Interactive text editor
510
- - **Footer**: Status information
315
+ Run the example applications in the `test/` directory:
511
316
 
512
- Try typing a message and pressing Enter!
513
- `),
514
- );
317
+ ```bash
318
+ # Chat application with slash commands and autocomplete
319
+ npx tsx test/chat-app.ts
515
320
 
516
- inputArea.onSubmit = (text) => {
517
- if (text.trim()) {
518
- const message = new MarkdownComponent(`
519
- **${new Date().toLocaleTimeString()}:** ${text}
520
- `);
521
- chatArea.addChild(message);
522
- ui.requestRender();
523
- }
524
- };
321
+ # File browser with navigation
322
+ npx tsx test/file-browser.ts
525
323
 
526
- // Build layout
527
- mainContent.addChild(chatArea);
528
- mainContent.addChild(inputArea);
324
+ # Multi-component layout demo
325
+ npx tsx test/multi-layout.ts
529
326
 
530
- ui.addChild(header);
531
- ui.addChild(mainContent);
532
- ui.addChild(footer);
533
- ui.setFocus(inputArea);
327
+ # Performance benchmark with animation
328
+ npx tsx test/bench.ts
329
+ ```
534
330
 
535
- // Configure debug logging
536
- ui.configureLogging({
537
- enabled: true,
538
- level: "info",
539
- logFile: "tui-debug.log",
540
- });
331
+ ### Example Descriptions
541
332
 
542
- ui.start();
543
- ```
333
+ - **chat-app.ts** - Chat interface with slash commands (/clear, /help, /attach) and autocomplete
334
+ - **file-browser.ts** - Interactive file browser with directory navigation
335
+ - **multi-layout.ts** - Complex layout with header, sidebar, main content, and footer
336
+ - **bench.ts** - Performance test with animation showing surgical rendering efficiency
544
337
 
545
338
  ## Interfaces and Types
546
339
 
@@ -618,28 +411,161 @@ interface SelectItem {
618
411
  }
619
412
  ```
620
413
 
621
- ## Development
414
+ ## Testing
415
+
416
+ ### Running Tests
622
417
 
623
418
  ```bash
624
- # Install dependencies (from monorepo root)
625
- npm install
419
+ # Run all tests
420
+ npm test
626
421
 
627
- # Build the package
628
- npm run build
422
+ # Run specific test file
423
+ npm test -- test/tui-rendering.test.ts
629
424
 
630
- # Run type checking
631
- npm run check
425
+ # Run tests matching a pattern
426
+ npm test -- --test-name-pattern="preserves existing"
632
427
  ```
633
428
 
634
- **Testing:**
635
- Create a test file and run it with tsx:
429
+ ### Test Infrastructure
430
+
431
+ The TUI uses a **VirtualTerminal** for testing that provides accurate terminal emulation via `@xterm/headless`:
432
+
433
+ ```typescript
434
+ import { VirtualTerminal } from "./test/virtual-terminal.js";
435
+ import { TUI, TextComponent } from "../src/index.js";
436
+
437
+ test("my TUI test", async () => {
438
+ const terminal = new VirtualTerminal(80, 24);
439
+ const ui = new TUI(terminal);
440
+ ui.start();
441
+
442
+ ui.addChild(new TextComponent("Hello"));
443
+
444
+ // Wait for render
445
+ await new Promise(resolve => process.nextTick(resolve));
446
+
447
+ // Get rendered output
448
+ const viewport = await terminal.flushAndGetViewport();
449
+ assert.strictEqual(viewport[0], "Hello");
450
+
451
+ ui.stop();
452
+ });
453
+ ```
454
+
455
+ ### Writing a New Test
456
+
457
+ 1. **Create test file** in `test/` directory with `.test.ts` extension
458
+ 2. **Use VirtualTerminal** for accurate terminal emulation
459
+ 3. **Key testing patterns**:
460
+
461
+ ```typescript
462
+ import { test, describe } from "node:test";
463
+ import assert from "node:assert";
464
+ import { VirtualTerminal } from "./virtual-terminal.js";
465
+ import { TUI, Container, TextComponent } from "../src/index.js";
466
+
467
+ describe("My Feature", () => {
468
+ test("should handle dynamic content", async () => {
469
+ const terminal = new VirtualTerminal(80, 24);
470
+ const ui = new TUI(terminal);
471
+ ui.start();
472
+
473
+ // Setup components
474
+ const container = new Container();
475
+ ui.addChild(container);
476
+
477
+ // Initial render
478
+ await new Promise(resolve => process.nextTick(resolve));
479
+ await terminal.flush();
480
+
481
+ // Check viewport (visible content)
482
+ let viewport = terminal.getViewport();
483
+ assert.strictEqual(viewport.length, 24);
484
+
485
+ // Check scrollback buffer (all content including history)
486
+ let scrollBuffer = terminal.getScrollBuffer();
487
+
488
+ // Simulate user input
489
+ terminal.sendInput("Hello");
490
+
491
+ // Wait for processing
492
+ await new Promise(resolve => process.nextTick(resolve));
493
+ await terminal.flush();
494
+
495
+ // Verify changes
496
+ viewport = terminal.getViewport();
497
+ // ... assertions
498
+
499
+ ui.stop();
500
+ });
501
+ });
502
+ ```
503
+
504
+ ### VirtualTerminal API
505
+
506
+ - `new VirtualTerminal(columns, rows)` - Create terminal with dimensions
507
+ - `write(data)` - Write ANSI sequences to terminal
508
+ - `sendInput(data)` - Simulate keyboard input
509
+ - `flush()` - Wait for all writes to complete
510
+ - `getViewport()` - Get visible lines (what user sees)
511
+ - `getScrollBuffer()` - Get all lines including scrollback
512
+ - `flushAndGetViewport()` - Convenience method
513
+ - `getCursorPosition()` - Get cursor row/column
514
+ - `resize(columns, rows)` - Resize terminal
515
+
516
+ ### Testing Best Practices
517
+
518
+ 1. **Always flush after renders**: Terminal writes are async
519
+ ```typescript
520
+ await new Promise(resolve => process.nextTick(resolve));
521
+ await terminal.flush();
522
+ ```
523
+
524
+ 2. **Test both viewport and scrollback**: Ensure content preservation
525
+ ```typescript
526
+ const viewport = terminal.getViewport(); // Visible content
527
+ const scrollBuffer = terminal.getScrollBuffer(); // All content
528
+ ```
529
+
530
+ 3. **Use exact string matching**: Don't trim() - whitespace matters
531
+ ```typescript
532
+ assert.strictEqual(viewport[0], "Expected text"); // Good
533
+ assert.strictEqual(viewport[0].trim(), "Expected"); // Bad
534
+ ```
535
+
536
+ 4. **Test rendering strategies**: Verify surgical vs partial vs full
537
+ ```typescript
538
+ const beforeLines = ui.getLinesRedrawn();
539
+ // Make change...
540
+ const afterLines = ui.getLinesRedrawn();
541
+ assert.strictEqual(afterLines - beforeLines, 1); // Only 1 line changed
542
+ ```
543
+
544
+ ### Performance Testing
545
+
546
+ Use `test/bench.ts` as a template for performance testing:
636
547
 
637
548
  ```bash
638
- # From packages/tui directory
639
- npx tsx test/demo.ts
549
+ npx tsx test/bench.ts
640
550
  ```
641
551
 
642
- Special input keywords for simulation: "TAB", "ENTER", "SPACE", "ESC"
552
+ Monitor real-time performance metrics:
553
+ - Render count and timing
554
+ - Lines redrawn per render
555
+ - Visual verification of flicker-free updates
556
+
557
+ ## Development
558
+
559
+ ```bash
560
+ # Install dependencies (from monorepo root)
561
+ npm install
562
+
563
+ # Run type checking
564
+ npm run check
565
+
566
+ # Run tests
567
+ npm test
568
+ ```
643
569
 
644
570
  **Debugging:**
645
571
  Enable logging to see detailed component behavior:
@@ -651,5 +577,3 @@ ui.configureLogging({
651
577
  logFile: "tui-debug.log",
652
578
  });
653
579
  ```
654
-
655
- Check the log file to debug rendering issues, input handling, and component lifecycle.
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../src/autocomplete.ts"],"names":[],"mappings":"AAwFA,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,sBAAsB,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAAC;CAC3E;AAED,MAAM,WAAW,oBAAoB;IAGpC,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QACF,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC;KACf,GAAG,IAAI,CAAC;IAIT,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QACF,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;CACF;AAGD,qBAAa,4BAA6B,YAAW,oBAAoB;IACxE,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,GAAE,CAAC,YAAY,GAAG,gBAAgB,CAAC,EAAO,EAAE,QAAQ,GAAE,MAAsB;IAKhG,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IA+EvD,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IA6D7D,OAAO,CAAC,iBAAiB;IA0CzB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,kBAAkB;IA0J1B,uBAAuB,CACtB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAoCvD,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;CAW5F"}
1
+ {"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../src/autocomplete.ts"],"names":[],"mappings":"AAuFA,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,sBAAsB,CAAC,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAAC;CAC3E;AAED,MAAM,WAAW,oBAAoB;IAGpC,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QACF,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC;KACf,GAAG,IAAI,CAAC;IAIT,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QACF,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;CACF;AAGD,qBAAa,4BAA6B,YAAW,oBAAoB;IACxE,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,GAAE,CAAC,YAAY,GAAG,gBAAgB,CAAC,EAAO,EAAE,QAAQ,GAAE,MAAsB;IAKhG,cAAc,CACb,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAqEvD,eAAe,CACd,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,MAAM,GACZ;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IA6D7D,OAAO,CAAC,iBAAiB;IA0CzB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,kBAAkB;IAwI1B,uBAAuB,CACtB,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GACf;QAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAyBvD,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;CAW5F"}