/** * public/main.ts — esbuild entry point for the browser frontend. * * Bootstraps the multi-tab app: a tab bar (#tabs) + a utility toolbar (#toolbar) * over a stack of terminal panes (#term), each tab an independent TerminalSession. * The mobile key bar routes input to the active tab. * * Per-session terminal/WS/reconnect logic lives in terminal-session.ts; * tab management + persistence in tabs.ts. */ // @ts-ignore CSS side-effect import processed by esbuild (→ public/build/main.css). import '@xterm/xterm/css/xterm.css' import { mountKeybar } from './keybar.js' import { TabApp } from './tabs.js' import { mountSearch } from './search.js' import { mountQrConnect } from './qr.js' const paneHost = document.getElementById('term') const tabs = document.getElementById('tabs') const toolbar = document.getElementById('toolbar') if (!paneHost) throw new Error('#term element not found in DOM') if (!tabs) throw new Error('#tabs element not found in DOM') if (!toolbar) throw new Error('#toolbar element not found in DOM') const app = new TabApp(paneHost, tabs) // Key bar (mobile + desktop) sends to whichever tab is active. mountKeybar((data) => app.sendToActive(data)) // Toolbar utilities. mountSearch(toolbar, { find: (query, dir) => app.findInActive(query, dir), clear: () => app.clearActiveSearch(), }) mountQrConnect(toolbar) // PWA: register the service worker (installable + offline shell, M4). if ('serviceWorker' in navigator) { window.addEventListener('load', () => { void navigator.serviceWorker.register('./sw.js').catch(() => { // SW registration is best-effort; the app works without it. }) }) }