diff --git a/desktop/src/app/components/apps/text-editor/text-editor.component.html b/desktop/src/app/components/apps/text-editor/text-editor.component.html new file mode 100644 index 0000000..09721b2 --- /dev/null +++ b/desktop/src/app/components/apps/text-editor/text-editor.component.html @@ -0,0 +1,23 @@ +
+ +
+ +
+ {{ fileName() }} + + Ln {{ cursorLine() }}, Col {{ cursorCol() }} +
+ + + +
diff --git a/desktop/src/app/components/apps/text-editor/text-editor.component.scss b/desktop/src/app/components/apps/text-editor/text-editor.component.scss new file mode 100644 index 0000000..416b3f6 --- /dev/null +++ b/desktop/src/app/components/apps/text-editor/text-editor.component.scss @@ -0,0 +1,84 @@ +:host { + display: block; + width: 100%; + height: 100%; +} + +.text-editor { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + background: #1e1e1e; +} + +.editor-toolbar { + display: flex; + align-items: center; + height: 32px; + padding: 0 8px; + background: #2d2d2d; + border-bottom: 1px solid #404040; + gap: 4px; + flex-shrink: 0; +} + +.toolbar-btn { + display: flex; + align-items: center; + gap: 4px; + height: 26px; + padding: 0 8px; + border: none; + background: transparent; + color: #ccc; + font-size: 12px; + cursor: pointer; + border-radius: 4px; + + &:hover { + background: rgba(255, 255, 255, 0.08); + } +} + +.toolbar-separator { + width: 1px; + height: 20px; + background: #555; +} + +.file-name { + font-size: 12px; + color: #999; + margin-left: 4px; +} + +.spacer { + flex: 1; +} + +.cursor-info { + font-size: 11px; + color: #888; + font-family: 'Consolas', monospace; +} + +.editor-area { + flex: 1; + width: 100%; + resize: none; + border: none; + outline: none; + padding: 12px 16px; + background: #1e1e1e; + color: #d4d4d4; + font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace; + font-size: 14px; + line-height: 1.6; + tab-size: 2; + box-sizing: border-box; + + &::placeholder { + color: #555; + } +} diff --git a/desktop/src/app/components/apps/text-editor/text-editor.component.ts b/desktop/src/app/components/apps/text-editor/text-editor.component.ts new file mode 100644 index 0000000..eec83cb --- /dev/null +++ b/desktop/src/app/components/apps/text-editor/text-editor.component.ts @@ -0,0 +1,46 @@ +import { Component, signal } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +@Component({ + selector: 'app-text-editor', + standalone: true, + imports: [CommonModule], + templateUrl: './text-editor.component.html', + styleUrl: './text-editor.component.scss', +}) +export class TextEditorComponent { + readonly content = signal(''); + readonly fileName = signal('untitled.txt'); + readonly showSaveDialog = signal(false); + + /** Cursor position. */ + readonly cursorLine = signal(1); + readonly cursorCol = signal(1); + + onInput(event: Event): void { + const textarea = event.target as HTMLTextAreaElement; + this.content.set(textarea.value); + this.updateCursorPosition(textarea); + } + + onKeyUp(event: Event): void { + this.updateCursorPosition(event.target as HTMLTextAreaElement); + } + + private updateCursorPosition(textarea: HTMLTextAreaElement): void { + const val = textarea.value.substring(0, textarea.selectionStart); + const lines = val.split('\n'); + this.cursorLine.set(lines.length); + this.cursorCol.set(lines[lines.length - 1].length + 1); + } + + newFile(): void { + this.content.set(''); + this.fileName.set('untitled.txt'); + } + + saveFile(): void { + // In a real implementation this would save to the server's virtual filesystem. + this.showSaveDialog.set(false); + } +}