Spaces:
Running
Running
| class CustomTerminal extends HTMLElement { | |
| connectedCallback() { | |
| const title = this.getAttribute('title') || 'NEXUS TERMINAL'; | |
| const lines = this.getAttribute('lines') || '5'; | |
| const autoScroll = this.hasAttribute('auto-scroll'); | |
| this.attachShadow({ mode: 'open' }); | |
| this.shadowRoot.innerHTML = ` | |
| <style> | |
| :host { | |
| display: block; | |
| font-family: 'Courier New', monospace; | |
| } | |
| .terminal { | |
| background: #0a0a0a; | |
| border: 1px solid #222; | |
| border-radius: 8px; | |
| overflow: hidden; | |
| } | |
| .terminal-header { | |
| background: #111; | |
| padding: 0.75rem 1rem; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| border-bottom: 1px solid #222; | |
| } | |
| .dot { | |
| width: 12px; | |
| height: 12px; | |
| border-radius: 50%; | |
| } | |
| .dot-red { background: #ff5f57; } | |
| .dot-yellow { background: #febc2e; } | |
| .dot-green { background: #28c840; } | |
| .terminal-title { | |
| flex: 1; | |
| text-align: center; | |
| color: #666; | |
| font-size: 0.75rem; | |
| text-transform: uppercase; | |
| letter-spacing: 0.1em; | |
| } | |
| .terminal-body { | |
| padding: 1rem; | |
| height: ${lines * 24 + 32}px; | |
| overflow-y: auto; | |
| background: linear-gradient(180deg, #0a0a0a 0%, #050505 100%); | |
| } | |
| .terminal-line { | |
| margin: 0.25rem 0; | |
| font-size: 0.875rem; | |
| line-height: 1.5; | |
| } | |
| .line-prefix { | |
| color: #b026ff; | |
| } | |
| .line-content { | |
| color: #00ff9d; | |
| } | |
| .line-error { | |
| color: #ff003c; | |
| } | |
| .line-info { | |
| color: #00f3ff; | |
| } | |
| .line-system { | |
| color: #666; | |
| } | |
| .cursor { | |
| display: inline-block; | |
| width: 8px; | |
| height: 16px; | |
| background: #00ff9d; | |
| animation: blink 1s step-end infinite; | |
| vertical-align: middle; | |
| } | |
| @keyframes blink { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0; } | |
| } | |
| ::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: #0a0a0a; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #222; | |
| border-radius: 3px; | |
| } | |
| </style> | |
| <div class="terminal"> | |
| <div class="terminal-header"> | |
| <div class="dot dot-red"></div> | |
| <div class="dot dot-yellow"></div> | |
| <div class="dot dot-green"></div> | |
| <span class="terminal-title">${title}</span> | |
| </div> | |
| <div class="terminal-body" id="terminal-body"> | |
| <div class="terminal-line"> | |
| <span class="line-prefix">nexus@overdrive:~$</span> | |
| <span class="line-content"> initializing autonomous systems...</span> | |
| </div> | |
| <div class="terminal-line"> | |
| <span class="line-prefix">nexus@overdrive:~$</span> | |
| <span class="line-info"> β neural network online</span> | |
| </div> | |
| <div class="terminal-line"> | |
| <span class="line-prefix">nexus@overdrive:~$</span> | |
| <span class="line-info"> β quantum processors connected</span> | |
| </div> | |
| <div class="terminal-line"> | |
| <span class="line-prefix">nexus@overdrive:~$</span> | |
| <span class="line-system"> awaiting input...<span class="cursor"></span></span> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| addLine(content, type = 'default') { | |
| const body = this.shadowRoot.getElementById('terminal-body'); | |
| const prefix = this.getAttribute('prefix') || 'nexus@overdrive:~$'; | |
| const typeClass = { | |
| default: 'line-content', | |
| error: 'line-error', | |
| info: 'line-info', | |
| system: 'line-system' | |
| }[type] || 'line-content'; | |
| // Remove cursor from last line | |
| const lastLine = body.lastElementChild; | |
| if (lastLine) { | |
| const cursor = lastLine.querySelector('.cursor'); | |
| if (cursor) cursor.remove(); | |
| } | |
| // Add new line | |
| const line = document.createElement('div'); | |
| line.className = 'terminal-line'; | |
| line.innerHTML = ` | |
| <span class="line-prefix">${prefix}</span> | |
| <span class="${typeClass}"> ${content}</span> | |
| `; | |
| body.appendChild(line); | |
| // Add cursor to new line | |
| const cursorLine = document.createElement('div'); | |
| cursorLine.className = 'terminal-line'; | |
| cursorLine.innerHTML = `<span class="line-prefix">${prefix}</span><span class="line-system"> awaiting input...<span class="cursor"></span></span>`; | |
| body.appendChild(cursorLine); | |
| // Auto scroll | |
| if (this.hasAttribute('auto-scroll')) { | |
| body.scrollTop = body.scrollHeight; | |
| } | |
| } | |
| clear() { | |
| const body = this.shadowRoot.getElementById('terminal-body'); | |
| body.innerHTML = ''; | |
| } | |
| } | |
| customElements.define('custom-terminal', CustomTerminal); |