feat(ui): static shell + router + api wrapper
Three-column grid (sidebar / main / right rail) with Cradle aesthetic: blackflame accent on Cinzel display headings + Cormorant Garamond body in cards, system UI for chrome. Hash-based router covers all entity routes plus search, inbox, sacred-valley. api.js stores OWNER_TOKEN in localStorage and prompts via a modal on 401. dom.js provides safe el() + mount() builders so no component ever assigns innerHTML from API data (the only exception is an explicit, scary-named html: opt-in for sanitizer output, used later by the markdown editor). state.js is a tiny event bus for shared chrome state (pending count). Components and views are loaded as ES modules — sidebar / topbar / rightrail + 9 view stubs that the later Phase E tasks fill in. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
20
public/state.js
Normal file
20
public/state.js
Normal file
@@ -0,0 +1,20 @@
|
||||
// Tiny event bus for cross-component state (pending count, agent toggle, etc.).
|
||||
// No reactive framework — just publish/subscribe with last-value semantics.
|
||||
|
||||
const subs = new Map(); // event → Set<fn>
|
||||
const last = new Map(); // event → last value
|
||||
|
||||
export function on(event, fn) {
|
||||
if (!subs.has(event)) subs.set(event, new Set());
|
||||
subs.get(event).add(fn);
|
||||
if (last.has(event)) fn(last.get(event));
|
||||
return () => subs.get(event).delete(fn);
|
||||
}
|
||||
|
||||
export function emit(event, value) {
|
||||
last.set(event, value);
|
||||
const set = subs.get(event);
|
||||
if (set) for (const fn of set) fn(value);
|
||||
}
|
||||
|
||||
export function get(event) { return last.get(event); }
|
||||
Reference in New Issue
Block a user