mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 19:05:11 +00:00
Add padding to Text component and fix padding calculation
- Add paddingX and paddingY support to Text component (default 1, 1) - Fix padding calculation bug in both Text and Markdown - Right padding now correctly fills to terminal width - Remove unused Spacer import from chat-simple
This commit is contained in:
parent
5f19dd62c7
commit
9dab1192ad
3 changed files with 45 additions and 18 deletions
|
|
@ -111,8 +111,8 @@ export class Markdown implements Component {
|
|||
for (const line of wrappedLines) {
|
||||
// Calculate visible length (strip ANSI codes)
|
||||
const visibleLength = stripVTControlCharacters(line).length;
|
||||
// Right padding to fill to width (accounting for left padding)
|
||||
const rightPadLength = Math.max(0, width - visibleLength - this.paddingX * 2);
|
||||
// Right padding to fill to width (accounting for left padding and content)
|
||||
const rightPadLength = Math.max(0, width - this.paddingX - visibleLength);
|
||||
const rightPad = " ".repeat(rightPadLength);
|
||||
|
||||
// Add left padding, content, and right padding
|
||||
|
|
|
|||
|
|
@ -56,13 +56,26 @@ export class Container implements Component {
|
|||
* Text component - displays multi-line text with word wrapping
|
||||
*/
|
||||
export class Text implements Component {
|
||||
constructor(private text: string = "") {}
|
||||
private paddingX: number; // Left/right padding
|
||||
private paddingY: number; // Top/bottom padding
|
||||
|
||||
constructor(
|
||||
private text: string = "",
|
||||
paddingX: number = 1,
|
||||
paddingY: number = 1,
|
||||
) {
|
||||
this.paddingX = paddingX;
|
||||
this.paddingY = paddingY;
|
||||
}
|
||||
|
||||
setText(text: string): void {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
render(width: number): string[] {
|
||||
// Calculate available width for content (subtract horizontal padding)
|
||||
const contentWidth = Math.max(1, width - this.paddingX * 2);
|
||||
|
||||
if (!this.text) {
|
||||
return [""];
|
||||
}
|
||||
|
|
@ -71,7 +84,7 @@ export class Text implements Component {
|
|||
const textLines = this.text.split("\n");
|
||||
|
||||
for (const line of textLines) {
|
||||
if (line.length <= width) {
|
||||
if (line.length <= contentWidth) {
|
||||
lines.push(line);
|
||||
} else {
|
||||
// Word wrap
|
||||
|
|
@ -81,7 +94,7 @@ export class Text implements Component {
|
|||
for (const word of words) {
|
||||
if (currentLine.length === 0) {
|
||||
currentLine = word;
|
||||
} else if (currentLine.length + 1 + word.length <= width) {
|
||||
} else if (currentLine.length + 1 + word.length <= contentWidth) {
|
||||
currentLine += " " + word;
|
||||
} else {
|
||||
lines.push(currentLine);
|
||||
|
|
@ -95,7 +108,33 @@ export class Text implements Component {
|
|||
}
|
||||
}
|
||||
|
||||
return lines.length > 0 ? lines : [""];
|
||||
// Add padding to each line
|
||||
const leftPad = " ".repeat(this.paddingX);
|
||||
const paddedLines: string[] = [];
|
||||
|
||||
for (const line of lines) {
|
||||
const rightPadLength = Math.max(0, width - this.paddingX - line.length);
|
||||
const rightPad = " ".repeat(rightPadLength);
|
||||
paddedLines.push(leftPad + line + rightPad);
|
||||
}
|
||||
|
||||
// Add top padding (empty lines)
|
||||
const emptyLine = " ".repeat(width);
|
||||
const topPadding: string[] = [];
|
||||
for (let i = 0; i < this.paddingY; i++) {
|
||||
topPadding.push(emptyLine);
|
||||
}
|
||||
|
||||
// Add bottom padding (empty lines)
|
||||
const bottomPadding: string[] = [];
|
||||
for (let i = 0; i < this.paddingY; i++) {
|
||||
bottomPadding.push(emptyLine);
|
||||
}
|
||||
|
||||
// Combine top padding, content, and bottom padding
|
||||
const result = [...topPadding, ...paddedLines, ...bottomPadding];
|
||||
|
||||
return result.length > 0 ? result : [""];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import { CombinedAutocompleteProvider } from "../src/autocomplete.js";
|
|||
import { Editor } from "../src/components-new/editor.js";
|
||||
import { Loader } from "../src/components-new/loader.js";
|
||||
import { Markdown } from "../src/components-new/markdown.js";
|
||||
import { Spacer } from "../src/components-new/spacer.js";
|
||||
import { ProcessTerminal } from "../src/terminal.js";
|
||||
import { Text, TUI } from "../src/tui-new.js";
|
||||
|
||||
|
|
@ -74,31 +73,21 @@ editor.onSubmit = (value: string) => {
|
|||
}
|
||||
|
||||
if (trimmed) {
|
||||
// Mark as responding and disable submit
|
||||
isResponding = true;
|
||||
editor.disableSubmit = true;
|
||||
|
||||
// Add user message with custom gray background (similar to Claude.ai)
|
||||
const userMessage = new Markdown(value, undefined, undefined, { r: 52, g: 53, b: 65 });
|
||||
|
||||
// Insert before the editor (which is last)
|
||||
const children = tui.children;
|
||||
children.splice(children.length - 1, 0, userMessage);
|
||||
children.splice(children.length - 1, 0, new Spacer());
|
||||
|
||||
// Add loader
|
||||
const loader = new Loader(tui, "Thinking...");
|
||||
const loaderSpacer = new Spacer();
|
||||
children.splice(children.length - 1, 0, loader);
|
||||
children.splice(children.length - 1, 0, loaderSpacer);
|
||||
|
||||
tui.requestRender();
|
||||
|
||||
// Simulate a 1 second delay
|
||||
setTimeout(() => {
|
||||
// Remove loader and its spacer
|
||||
tui.removeChild(loader);
|
||||
tui.removeChild(loaderSpacer);
|
||||
|
||||
// Simulate a response
|
||||
const responses = [
|
||||
|
|
@ -116,7 +105,6 @@ editor.onSubmit = (value: string) => {
|
|||
// Add assistant message with no background (transparent)
|
||||
const botMessage = new Markdown(randomResponse);
|
||||
children.splice(children.length - 1, 0, botMessage);
|
||||
children.splice(children.length - 1, 0, new Spacer());
|
||||
|
||||
// Re-enable submit
|
||||
isResponding = false;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue