class LogConsole extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this.entries = []; this.maxEntries = 100; } connectedCallback() { this.render(); } render() { this.shadowRoot.innerHTML = `
Waiting for process output...
`; this.contentEl = this.shadowRoot.getElementById('consoleContent'); } addEntry(text, type = 'info') { // Remove empty state if present if (this.entries.length === 0) { this.contentEl.innerHTML = ''; } const entry = document.createElement('div'); entry.className = 'entry'; const typeClass = `type-${type}`; // Parse timestamp if included in text let displayText = text; let timestamp = ''; if (text.startsWith('[') && text.includes(']')) { const match = text.match(/\[(.*?)\](.*)/); if (match) { timestamp = `[${match[1]}]`; displayText = match[2].trim(); } } entry.innerHTML = ` ${timestamp || new Date().toLocaleTimeString('en-US', { hour12: false })} ${this.escapeHtml(displayText)} `; this.contentEl.appendChild(entry); this.entries.push(entry); // Limit entries if (this.entries.length > this.maxEntries) { this.entries.shift().remove(); } // Auto-scroll to bottom this.contentEl.scrollTop = this.contentEl.scrollHeight; } clear() { this.entries = []; this.contentEl.innerHTML = '
Console cleared. Waiting for process output...
'; } escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } } customElements.define('log-console', LogConsole);