@sayknow-cli/tui 0.6.3 → 0.6.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/CHANGELOG.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
- ## [0.6.3] - 2026-09-25
5
+ ## [0.6.5] - 2026-09-26
6
6
 
7
7
  ## [0.5.12] - 2026-09-15
8
8
  ### Fixed
@@ -70,6 +70,12 @@ export declare class Editor implements Component, Focusable {
70
70
  setBorderStyle(borderStyle: EditorBorderStyle): void;
71
71
  setClosedBorderBox(closedBorderBox: boolean): void;
72
72
  setPromptGutter(promptGutter: string | undefined): void;
73
+ /**
74
+ * Borderless rail: draw `glyph` in the current `borderColor` at the start of
75
+ * every input row (not just the first), followed by one space. Takes
76
+ * precedence over `setPromptGutter` and is ignored while the border is visible.
77
+ */
78
+ setRailGutter(glyph: string | undefined): void;
73
79
  setInputPrefix(inputPrefix: string | undefined): void;
74
80
  setPlaceholder(placeholder: string | undefined): void;
75
81
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@sayknow-cli/tui",
4
- "version": "0.6.3",
4
+ "version": "0.6.5",
5
5
  "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
6
6
  "homepage": "https://sayknow-cli.com",
7
7
  "author": "jaybeyond",
@@ -38,8 +38,8 @@
38
38
  "fmt": "biome format --write ."
39
39
  },
40
40
  "dependencies": {
41
- "@sayknow-cli/natives": "0.6.3",
42
- "@sayknow-cli/utils": "0.6.3",
41
+ "@sayknow-cli/natives": "0.6.5",
42
+ "@sayknow-cli/utils": "0.6.5",
43
43
  "lru-cache": "11.3.6",
44
44
  "marked": "^18.0.3"
45
45
  },
@@ -427,6 +427,7 @@ export class Editor implements Component, Focusable {
427
427
  /** Display width of the cursorOverride glyph (needed because override may contain ANSI escapes). */
428
428
  cursorOverrideWidth: number | undefined;
429
429
  #promptGutter: string | undefined;
430
+ #railGutter: string | undefined;
430
431
  #inputPrefix: string | undefined;
431
432
  #inputPrefixWidth = 0;
432
433
  #placeholder: string | undefined;
@@ -567,6 +568,16 @@ export class Editor implements Component, Focusable {
567
568
  this.#invalidateLayoutCache();
568
569
  }
569
570
 
571
+ /**
572
+ * Borderless rail: draw `glyph` in the current `borderColor` at the start of
573
+ * every input row (not just the first), followed by one space. Takes
574
+ * precedence over `setPromptGutter` and is ignored while the border is visible.
575
+ */
576
+ setRailGutter(glyph: string | undefined): void {
577
+ this.#railGutter = glyph;
578
+ this.#invalidateLayoutCache();
579
+ }
580
+
570
581
  setInputPrefix(inputPrefix: string | undefined): void {
571
582
  this.#inputPrefix = inputPrefix;
572
583
  this.#inputPrefixWidth = inputPrefix ? visibleWidth(inputPrefix) : 0;
@@ -732,21 +743,32 @@ export class Editor implements Component, Focusable {
732
743
  }
733
744
 
734
745
  #getPromptGutterWidth(width: number, paddingX: number): number {
735
- if (this.#borderVisible || !this.#promptGutter) return 0;
746
+ if (this.#borderVisible) return 0;
747
+ const gutterWidth = this.#railGutter
748
+ ? visibleWidth(this.#railGutter) + 1
749
+ : this.#promptGutter
750
+ ? visibleWidth(this.#promptGutter)
751
+ : 0;
752
+ if (gutterWidth === 0) return 0;
736
753
  const chromeWidth = 2 * this.#getHorizontalChromeWidth(paddingX);
737
754
  const availableWidth = Math.max(0, width - chromeWidth);
738
- return Math.min(visibleWidth(this.#promptGutter), availableWidth);
755
+ return Math.min(gutterWidth, availableWidth);
739
756
  }
740
757
 
741
758
  #getPromptGutter(
742
759
  width: number,
743
760
  paddingX: number,
744
761
  ): { firstLine: string; continuation: string; width: number } | undefined {
745
- if (this.#borderVisible || !this.#promptGutter) return undefined;
762
+ if (this.#borderVisible || !(this.#railGutter || this.#promptGutter)) return undefined;
746
763
  const gutterWidth = this.#getPromptGutterWidth(width, paddingX);
747
764
  if (gutterWidth === 0) return undefined;
765
+ if (this.#railGutter) {
766
+ // Colored at render time so mode/thinking border colors reach the rail.
767
+ const rail = this.borderColor(sliceByColumn(`${this.#railGutter} `, 0, gutterWidth, true));
768
+ return { firstLine: rail, continuation: rail, width: gutterWidth };
769
+ }
748
770
  return {
749
- firstLine: sliceByColumn(this.#promptGutter, 0, gutterWidth, true),
771
+ firstLine: sliceByColumn(this.#promptGutter ?? "", 0, gutterWidth, true),
750
772
  continuation: padding(gutterWidth),
751
773
  width: gutterWidth,
752
774
  };
@@ -1559,6 +1581,7 @@ export class Editor implements Component, Focusable {
1559
1581
  inputPrefixWidth: this.#inputPrefixWidth,
1560
1582
  placeholder: this.#placeholder,
1561
1583
  promptGutter: this.#promptGutter,
1584
+ railGutter: this.#railGutter,
1562
1585
  useTerminalCursor: this.#useTerminalCursor,
1563
1586
  cursorOverride: this.cursorOverride,
1564
1587
  cursorOverrideWidth: this.cursorOverrideWidth,