// UI mode: easy (level 1). Nothing here parses commands; every button calls executeCommand. class UIEasyMode { constructor() { this.commands = {}; this.terminal = null; } requirements() { return { met: true, missing: [] }; } getHelpInfo() { return {}; } registerCommands() {} init(terminal) { this.terminal = terminal; if (!terminal.uiShell) return; terminal.uiShell.registerMode({ id: 'easy', label: 'Easy', level: 1, icon: '🌱', tagline: 'Just ask. No commands.', mount: (api) => this.mount(api) }); } mount(api) { api.injectCSS('easy', ` body[data-ui-mode="easy"] { font-family: system-ui, -apple-system, "Segoe UI", sans-serif; } /* padding-bottom 34px, not 0: #ui-foot is absolutely positioned and 34px tall, and the shorthand reset the bottom padding the base sheet reserves, so the footer sat on top of the composer. */ body[data-ui-mode="easy"] #ui-root { display: flex; flex-direction: column; padding: 14px 14px 34px; gap: 12px; } #easy-top { flex: 0 0 auto; } #easy-top h1 { font-size: 1.25em; margin: 0 0 4px; font-weight: 600; } #easy-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 12px; } #easy-actions .wx11-btn { display: flex; align-items: center; gap: 10px; font-size: 1em; min-height: 62px; } #easy-actions .ico { font-size: 1.5em; line-height: 1; } #easy-chat { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; } #easy-chat .output-line { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 12px; padding: 10px 12px; font-family: inherit; font-size: .95em; line-height: 1.45; white-space: pre-wrap; word-break: break-word; } #easy-chat .output-line.error { border-color: var(--error-color); } #easy-chat .output-line.success { border-color: var(--accent-color); } #easy-composer { flex: 0 0 auto; display: flex; gap: 8px; align-items: flex-end; } #easy-composer #input-area { flex: 1 1 auto; display: flex; gap: 6px; align-items: flex-end; } #easy-composer .prompt-label { display: none; } #easy-composer #command-input { font-size: 1em; min-height: 48px; font-family: inherit; width: 100%; } #easy-composer #autocomplete-dropdown { display: none; } @media (max-width: 600px) { #easy-actions { grid-template-columns: 1fr; } } `); const root = api.root; root.innerHTML = ''; const top = api.el('div', { id: 'easy-top' }); top.appendChild(api.el('h1', { text: 'Hi β€” what do you want to do?' })); top.appendChild(api.el('div', { class: 'wx11-dim', text: 'Tap a card, or just type below in plain language.' })); const styleBtn = api.el('button', { class: 'wx11-btn', text: '⇄ Change view' }); styleBtn.style.cssText = 'margin-top:10px;width:100%;text-align:center'; styleBtn.addEventListener('click', () => api.exec('ui picker')); top.appendChild(styleBtn); const actions = api.el('div', { id: 'easy-actions' }); const cards = [ { ico: 'πŸ€–', label: 'Ask the AI', run: () => api.exec('ai "hello β€” what can you help me with?"') }, { ico: 'πŸ“', label: 'My files', run: () => api.exec('ls') }, { ico: 'πŸŽ“', label: 'Learn', run: () => api.exec('course') }, { ico: 'βš™οΈ', label: 'Settings', run: () => api.exec('config') } ]; cards.forEach(c => { const b = api.el('button', { class: 'wx11-btn' }); b.appendChild(api.el('span', { class: 'ico', text: c.ico })); b.appendChild(api.el('span', { text: c.label })); b.addEventListener('click', c.run); actions.appendChild(b); }); top.appendChild(actions); const chat = api.el('div', { id: 'easy-chat' }); const composer = api.el('div', { id: 'easy-composer' }); root.appendChild(top); root.appendChild(chat); root.appendChild(composer); // one output stream: the real terminal is restyled into bubbles inside #easy-chat api.attach(chat, api.stock.output); api.attach(composer, api.stock.input); const field = document.getElementById('command-input'); if (field) field.placeholder = 'Ask anything…'; return () => { const f = document.getElementById('command-input'); if (f) f.placeholder = 'Type a command...'; }; } }