mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-20 03:00:29 +00:00
Initial monorepo setup with npm workspaces and dual TypeScript configuration
- Set up npm workspaces for three packages: pi-tui, pi-agent, and pi (pods) - Implemented dual TypeScript configuration: - Root tsconfig.json with path mappings for development and type checking - Package-specific tsconfig.build.json for clean production builds - Configured lockstep versioning with sync script for inter-package dependencies - Added comprehensive documentation for development and publishing workflows - All packages at version 0.5.0 ready for npm publishing
This commit is contained in:
commit
a74c5da112
63 changed files with 14558 additions and 0 deletions
104
packages/tui/src/text-component.ts
Normal file
104
packages/tui/src/text-component.ts
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
import type { Component, ComponentRenderResult, Padding } from "./tui.js";
|
||||
|
||||
export class TextComponent implements Component {
|
||||
private text: string;
|
||||
private lastRenderedLines: string[] = [];
|
||||
private padding: Required<Padding>;
|
||||
|
||||
constructor(text: string, padding?: Padding) {
|
||||
this.text = text;
|
||||
this.padding = {
|
||||
top: padding?.top ?? 0,
|
||||
bottom: padding?.bottom ?? 0,
|
||||
left: padding?.left ?? 0,
|
||||
right: padding?.right ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
render(width: number): ComponentRenderResult {
|
||||
// Calculate available width after horizontal padding
|
||||
const availableWidth = Math.max(1, width - this.padding.left - this.padding.right);
|
||||
const leftPadding = " ".repeat(this.padding.left);
|
||||
|
||||
// First split by newlines to preserve line breaks
|
||||
const textLines = this.text.split("\n");
|
||||
const lines: string[] = [];
|
||||
|
||||
// Add top padding
|
||||
for (let i = 0; i < this.padding.top; i++) {
|
||||
lines.push("");
|
||||
}
|
||||
|
||||
// Process each line for word wrapping
|
||||
for (const textLine of textLines) {
|
||||
if (textLine.length === 0) {
|
||||
// Preserve empty lines with padding
|
||||
lines.push(leftPadding);
|
||||
} else {
|
||||
// Word wrapping with ANSI-aware length calculation
|
||||
const words = textLine.split(" ");
|
||||
let currentLine = "";
|
||||
let currentVisibleLength = 0;
|
||||
|
||||
for (const word of words) {
|
||||
const wordVisibleLength = this.getVisibleLength(word);
|
||||
const spaceLength = currentLine ? 1 : 0;
|
||||
|
||||
if (currentVisibleLength + spaceLength + wordVisibleLength <= availableWidth) {
|
||||
currentLine += (currentLine ? " " : "") + word;
|
||||
currentVisibleLength += spaceLength + wordVisibleLength;
|
||||
} else {
|
||||
if (currentLine) {
|
||||
lines.push(leftPadding + currentLine);
|
||||
}
|
||||
currentLine = word;
|
||||
currentVisibleLength = wordVisibleLength;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentLine) {
|
||||
lines.push(leftPadding + currentLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add bottom padding
|
||||
for (let i = 0; i < this.padding.bottom; i++) {
|
||||
lines.push("");
|
||||
}
|
||||
|
||||
const newLines = lines.length > 0 ? lines : [""];
|
||||
|
||||
// Check if content changed
|
||||
const changed = !this.arraysEqual(newLines, this.lastRenderedLines);
|
||||
|
||||
// Always cache the current rendered lines
|
||||
this.lastRenderedLines = [...newLines];
|
||||
|
||||
return {
|
||||
lines: newLines,
|
||||
changed,
|
||||
};
|
||||
}
|
||||
|
||||
setText(text: string): void {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
getText(): string {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
private arraysEqual(a: string[], b: string[]): boolean {
|
||||
if (a.length !== b.length) return false;
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private getVisibleLength(str: string): number {
|
||||
// Remove ANSI escape codes and count visible characters
|
||||
return (str || "").replace(/\x1b\[[0-9;]*m/g, "").length;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue