@ashx-j/lunr-tui 0.2.16-dev.9.1 → 0.2.16

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 (39) hide show
  1. package/dist/components/box.d.ts +8 -3
  2. package/dist/components/box.d.ts.map +1 -1
  3. package/dist/components/box.js +27 -8
  4. package/dist/components/box.js.map +1 -1
  5. package/dist/components/editor.d.ts +0 -1
  6. package/dist/components/editor.d.ts.map +1 -1
  7. package/dist/components/editor.js +2 -3
  8. package/dist/components/editor.js.map +1 -1
  9. package/dist/components/input.d.ts.map +1 -1
  10. package/dist/components/input.js +4 -8
  11. package/dist/components/input.js.map +1 -1
  12. package/dist/components/markdown.d.ts.map +1 -1
  13. package/dist/components/markdown.js +2 -2
  14. package/dist/components/markdown.js.map +1 -1
  15. package/dist/components/text.d.ts.map +1 -1
  16. package/dist/components/text.js +2 -2
  17. package/dist/components/text.js.map +1 -1
  18. package/dist/components/truncated-text.d.ts.map +1 -1
  19. package/dist/components/truncated-text.js +4 -5
  20. package/dist/components/truncated-text.js.map +1 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/stdin-buffer.d.ts.map +1 -1
  26. package/dist/stdin-buffer.js +4 -7
  27. package/dist/stdin-buffer.js.map +1 -1
  28. package/dist/terminal.d.ts.map +1 -1
  29. package/dist/terminal.js +1 -2
  30. package/dist/terminal.js.map +1 -1
  31. package/dist/tui.d.ts +2 -9
  32. package/dist/tui.d.ts.map +1 -1
  33. package/dist/tui.js +30 -98
  34. package/dist/tui.js.map +1 -1
  35. package/dist/utils.d.ts +0 -4
  36. package/dist/utils.d.ts.map +1 -1
  37. package/dist/utils.js +0 -112
  38. package/dist/utils.js.map +1 -1
  39. package/package.json +1 -1
package/dist/tui.js CHANGED
@@ -9,7 +9,7 @@ import { isKeyRelease, matchesKey } from "./keys.js";
9
9
  import { MOUSE_TRACKING_DISABLE, MOUSE_TRACKING_ENABLE, parseMouseEvent } from "./mouse.js";
10
10
  import { isOsc11BackgroundColorResponse, parseOsc11BackgroundColor, parseTerminalColorSchemeReport, } from "./terminal-colors.js";
11
11
  import { deleteKittyImage, getCapabilities, isImageLine, setCellDimensions } from "./terminal-image.js";
12
- import { extractSegments, normalizeTerminalOutput, sanitizeTerminalOutput, sliceByColumn, sliceWithWidth, visibleWidth, } from "./utils.js";
12
+ import { extractSegments, normalizeTerminalOutput, sliceByColumn, sliceWithWidth, visibleWidth } from "./utils.js";
13
13
  const KITTY_SEQUENCE_PREFIX = "\x1b_G";
14
14
  function parseKittyImageHeader(line) {
15
15
  const sequenceStart = line.indexOf(KITTY_SEQUENCE_PREFIX);
@@ -77,57 +77,29 @@ function isTermuxSession() {
77
77
  */
78
78
  export class Container {
79
79
  children = [];
80
- revision = 0;
81
- parents = new Set();
82
80
  addChild(component) {
83
81
  this.children.push(component);
84
- if (component instanceof Container)
85
- component.parents.add(this);
86
- this.markDirty();
87
82
  }
88
83
  removeChild(component) {
89
84
  const index = this.children.indexOf(component);
90
85
  if (index !== -1) {
91
86
  this.children.splice(index, 1);
92
- if (component instanceof Container && !this.children.includes(component))
93
- component.parents.delete(this);
94
- this.markDirty();
95
87
  }
96
88
  }
97
89
  clear() {
98
- for (const child of this.children) {
99
- if (child instanceof Container)
100
- child.parents.delete(this);
101
- }
102
90
  this.children = [];
103
- this.markDirty();
104
91
  }
105
92
  invalidate() {
106
- this.markDirty();
107
93
  for (const child of this.children) {
108
94
  child.invalidate?.();
109
95
  }
110
96
  }
111
- getRenderRevision() {
112
- return this.revision;
113
- }
114
- syncChildParents() {
115
- for (const child of this.children) {
116
- if (child instanceof Container)
117
- child.parents.add(this);
118
- }
119
- }
120
- markDirty() {
121
- this.revision++;
122
- for (const parent of this.parents)
123
- parent.markDirty();
124
- }
125
97
  render(width) {
126
98
  const lines = [];
127
99
  for (const child of this.children) {
128
100
  const childLines = child.render(width);
129
101
  for (const line of childLines) {
130
- lines.push(sanitizeTerminalOutput(line, isImageLine(line)));
102
+ lines.push(line);
131
103
  }
132
104
  }
133
105
  return lines;
@@ -190,6 +162,8 @@ export class TUI extends Container {
190
162
  lastChatScrollMax = 0;
191
163
  chatLaidOut = false;
192
164
  chatUsesGutter = false;
165
+ /** Bumped on non-scroll `requestRender` so offset-only paints can reuse chat layout. */
166
+ contentEpoch = 0;
193
167
  chatLayoutCache;
194
168
  alternateScreen = false;
195
169
  alternateScreenActive = false;
@@ -207,11 +181,6 @@ export class TUI extends Container {
207
181
  this.showHardwareCursor = showHardwareCursor;
208
182
  }
209
183
  }
210
- markDirty() {
211
- super.markDirty();
212
- if (this.started)
213
- this.queueRender(false);
214
- }
215
184
  get fullRedraws() {
216
185
  return this.fullRedrawCount;
217
186
  }
@@ -434,23 +403,6 @@ export class TUI extends Container {
434
403
  return -1;
435
404
  return this.children.indexOf(this.pinComponent);
436
405
  }
437
- captureChatComponentState(to) {
438
- return this.children.slice(0, to).map((component) => ({
439
- component,
440
- revision: component instanceof Container ? component.getRenderRevision() : 0,
441
- childCount: component instanceof Container ? component.children.length : undefined,
442
- firstChild: component instanceof Container ? component.children[0] : undefined,
443
- lastChild: component instanceof Container ? component.children[component.children.length - 1] : undefined,
444
- }));
445
- }
446
- chatComponentStateMatches(cached, current) {
447
- return (cached.length === current.length &&
448
- cached.every((state, index) => state.component === current[index]?.component &&
449
- state.revision === current[index]?.revision &&
450
- state.childCount === current[index]?.childCount &&
451
- state.firstChild === current[index]?.firstChild &&
452
- state.lastChild === current[index]?.lastChild));
453
- }
454
406
  collectChildLines(from, to, width, ranges) {
455
407
  const lines = [];
456
408
  for (let i = from; i < to; i++) {
@@ -471,7 +423,7 @@ export class TUI extends Container {
471
423
  }
472
424
  const start = lines.length;
473
425
  for (const line of child.render(width)) {
474
- lines.push(sanitizeTerminalOutput(line, isImageLine(line)));
426
+ lines.push(line);
475
427
  }
476
428
  ranges?.push({ component: child, start, end: lines.length });
477
429
  }
@@ -513,25 +465,17 @@ export class TUI extends Container {
513
465
  const viewH = Math.max(minView, rows - dockLines.length);
514
466
  this.lastChatViewportHeight = viewH;
515
467
  this.chatLaidOut = true;
516
- const canUseGutter = width >= 2;
517
- if (!canUseGutter)
518
- this.chatUsesGutter = false;
519
- let chatWidth = this.chatUsesGutter ? width - 1 : width;
468
+ let chatWidth = this.chatUsesGutter ? Math.max(1, width - 1) : width;
520
469
  let scrollLines;
521
470
  let ranges;
522
471
  let fromCache = false;
523
472
  const cache = this.chatLayoutCache;
524
- const componentState = this.captureChatComponentState(pinIndex);
525
- if (cache && cache.chatWidth === chatWidth && this.chatComponentStateMatches(cache.components, componentState)) {
473
+ if (cache && cache.epoch === this.contentEpoch && cache.chatWidth === chatWidth) {
526
474
  scrollLines = cache.scrollLines;
527
475
  ranges = cache.ranges;
528
476
  fromCache = true;
529
477
  }
530
478
  else {
531
- for (const state of componentState) {
532
- if (state.component instanceof Container)
533
- state.component.syncChildParents();
534
- }
535
479
  ranges = [];
536
480
  scrollLines = this.collectChildLines(0, pinIndex, chatWidth, ranges);
537
481
  }
@@ -544,17 +488,17 @@ export class TUI extends Container {
544
488
  fromCache = false;
545
489
  }
546
490
  }
547
- else if (canUseGutter && scrollLines.length > viewH) {
491
+ else if (scrollLines.length > viewH) {
548
492
  this.chatUsesGutter = true;
549
- chatWidth = width - 1;
493
+ chatWidth = Math.max(1, width - 1);
550
494
  ranges = [];
551
495
  scrollLines = this.collectChildLines(0, pinIndex, chatWidth, ranges);
552
496
  fromCache = false;
553
497
  }
554
498
  if (!fromCache) {
555
499
  this.chatLayoutCache = {
500
+ epoch: this.contentEpoch,
556
501
  chatWidth,
557
- components: this.captureChatComponentState(pinIndex),
558
502
  scrollLines,
559
503
  ranges,
560
504
  };
@@ -574,8 +518,7 @@ export class TUI extends Container {
574
518
  this.lastChatScrollMax = scrollLines.length - viewH;
575
519
  this.chatScrollOffset = Math.max(0, Math.min(this.chatScrollOffset, this.lastChatScrollMax));
576
520
  start = scrollLines.length - viewH - this.chatScrollOffset;
577
- if (this.chatScrollOffset > 0)
578
- start = this.snapStartToKittyImageHeader(scrollLines, start);
521
+ start = this.snapStartToKittyImageHeader(scrollLines, start);
579
522
  start = Math.max(0, start);
580
523
  this.lastChatStart = start;
581
524
  chatSlice = scrollLines.slice(start, start + viewH);
@@ -587,34 +530,26 @@ export class TUI extends Container {
587
530
  const thumbTop = this.lastChatScrollMax === 0
588
531
  ? viewH - thumbH
589
532
  : Math.round(travel * (1 - this.chatScrollOffset / this.lastChatScrollMax));
590
- if (this.chatUsesGutter) {
591
- this.chatScrollbar = {
592
- x: width,
593
- y0: 1,
594
- y1: viewH,
595
- viewH,
596
- scrollMax: this.lastChatScrollMax,
597
- thumbTop,
598
- thumbH,
599
- };
600
- const RESET = "\x1b[0m";
601
- const track = `${RESET}\x1b[2m│\x1b[0m`;
602
- const thumb = `${RESET}\x1b[1m█\x1b[0m`;
603
- for (let i = 0; i < chatSlice.length; i++) {
604
- const glyph = i >= thumbTop && i < thumbTop + thumbH ? thumb : track;
605
- chatSlice[i] = `${padToWidth(chatSlice[i] ?? "", chatWidth)}${glyph}`;
606
- }
607
- }
608
- else {
609
- this.chatScrollbar = undefined;
610
- this.scrollbarDrag = undefined;
533
+ this.chatScrollbar = {
534
+ x: width,
535
+ y0: 1,
536
+ y1: viewH,
537
+ viewH,
538
+ scrollMax: this.lastChatScrollMax,
539
+ thumbTop,
540
+ thumbH,
541
+ };
542
+ // Reset SGR so error/thinking colors cannot bleed into the gutter.
543
+ const RESET = "\x1b[0m";
544
+ const track = `${RESET}\x1b[2m│\x1b[0m`;
545
+ const thumb = `${RESET}\x1b[1m█\x1b[0m`;
546
+ for (let i = 0; i < chatSlice.length; i++) {
547
+ const glyph = i >= thumbTop && i < thumbTop + thumbH ? thumb : track;
548
+ chatSlice[i] = `${padToWidth(chatSlice[i] ?? "", chatWidth)}${glyph}`;
611
549
  }
612
550
  }
613
551
  this.lastChatSliceHeight = chatSlice.length;
614
- const frame = [...chatSlice, ...dockLines];
615
- if (width > 1)
616
- return frame;
617
- return frame.map((line) => (visibleWidth(line) > width ? sliceByColumn(line, 0, width, true) : line));
552
+ return [...chatSlice, ...dockLines];
618
553
  }
619
554
  /**
620
555
  * Show an overlay component with configurable positioning and sizing.
@@ -844,12 +779,9 @@ export class TUI extends Container {
844
779
  this.terminal.stop();
845
780
  }
846
781
  requestRender(force = false) {
847
- this.chatLayoutCache = undefined;
782
+ this.contentEpoch++;
848
783
  this.queueRender(force);
849
784
  }
850
- requestPaint() {
851
- this.queueRender(false);
852
- }
853
785
  requestRenderFromScroll() {
854
786
  this.queueRender(false);
855
787
  }
@@ -1335,7 +1267,7 @@ export class TUI extends Container {
1335
1267
  for (let i = 0; i < lines.length; i++) {
1336
1268
  const line = lines[i];
1337
1269
  if (!isImageLine(line)) {
1338
- lines[i] = normalizeTerminalOutput(sanitizeTerminalOutput(line)) + reset;
1270
+ lines[i] = normalizeTerminalOutput(line) + reset;
1339
1271
  }
1340
1272
  }
1341
1273
  return lines;