// Page-side runtime (design §11). P4 establishes the shell-bridge and // uses it to follow the system color scheme. Real widget loading / edit // mode / layout persistence arrive in P5+. interface PendingCall { resolve(value: unknown): void; reject(err: Error): void; } interface DashShellInternal { call(method: string, args?: unknown): Promise; _resolve(id: number, value: unknown): void; _reject(id: number, error: string): void; _onSignal(name: string, payload: unknown): void; } declare global { interface Window { __dashShell__?: DashShellInternal; webkit?: { messageHandlers: { shellCall: { postMessage(data: string): void } } }; } } const pending = new Map(); let nextId = 1; const dashShell: DashShellInternal = { call(method: string, args?: unknown): Promise { return new Promise((resolve, reject) => { const id = nextId++; pending.set(id, { resolve: resolve as (v: unknown) => void, reject }); try { window.webkit!.messageHandlers.shellCall.postMessage( JSON.stringify({ id, method, args }), ); } catch (e) { pending.delete(id); reject(e instanceof Error ? e : new Error(String(e))); } }); }, _resolve(id, value) { const p = pending.get(id); if (!p) return; pending.delete(id); p.resolve(value); }, _reject(id, err) { const p = pending.get(id); if (!p) return; pending.delete(id); p.reject(new Error(err)); }, _onSignal(name, payload) { window.dispatchEvent(new CustomEvent(`dashward:${name}`, { detail: payload })); }, }; window.__dashShell__ = dashShell; // Theme: ask once on load, then follow ThemeChanged from the shell. function applyTheme(theme: unknown): void { if (typeof theme !== 'string') return; document.documentElement.dataset.theme = theme; } dashShell .call('getTheme') .then(applyTheme) .catch(e => console.warn('[dashward] getTheme failed:', e)); window.addEventListener('dashward:ThemeChanged', evt => { applyTheme((evt as CustomEvent).detail); }); // Remove the boot diagnostic now that runtime.js is executing. document.getElementById('boot')?.remove(); // Placeholder card so the dashboard workspace is visually distinct. const grid = document.getElementById('grid'); if (grid) { const placeholder = document.createElement('section'); placeholder.className = 'placeholder'; placeholder.innerHTML = `

Dashward

P4 — shell bridge online.

Theme follows system. Widgets land in P5.

`; grid.appendChild(placeholder); } console.info('[dashward-runtime] P4 bridge mounted'); export {};