/** A codex/bestiary/lorebook entry the game defines. Discovery state is tracked separately. */ export interface CodexEntryDef { id: string; name: string; category?: string; description?: string; /** Longer lore for a detail pane. */ lore?: string; /** Icon/image id or glyph the game renders; the engine never picks art. */ icon?: string; /** Hide name/description/lore until discovered (a spoiler-guarded entry). */ secret?: boolean; meta?: TMeta; } /** A definition plus its discovery state — what UI renders. */ export interface CodexEntryView extends CodexEntryDef { discovered: boolean; /** Discovery time from the injected clock, or null. */ discoveredAt: number | null; } /** Serializable discovery state — a save blob. */ export interface CodexSnapshot { /** Entry id → discovery timestamp. */ discovered: Record; } /** A codex/bestiary of defined entries with per-player discovery tracking. */ export interface Codex { /** Mark an entry discovered; returns the newly-discovered view, or null if unknown or already discovered. */ discover(id: string): CodexEntryView | null; isDiscovered(id: string): boolean; get(id: string): CodexEntryView | null; /** All entries (optionally filtered to a category) with discovery state, in definition order. Stable identity between changes. */ list(category?: string): readonly CodexEntryView[]; categories(): readonly string[]; discoveredCount(): number; total(): number; /** Fraction discovered, `[0, 1]`. */ completion(): number; subscribe(listener: () => void): () => void; snapshot(): CodexSnapshot; restore(snapshot: CodexSnapshot): void; } /** Options for {@link createCodex}. */ export interface CodexOptions { entries: readonly CodexEntryDef[]; /** Injected clock (ms). Default `Date.now`. */ now?: () => number; /** Fires when an entry is discovered for the first time — wire to a toast/notification. */ onDiscover?: (entry: CodexEntryView) => void; } /** * A codex / bestiary / lorebook: a fixed set of defined entries plus per-player * discovery tracking, with categories, secret masking, completion, an * `onDiscover` seam, and serializable `snapshot`/`restore`. The view `list()` * keeps a stable identity between changes so React reads it through * `useSyncExternalStore` without re-projecting each frame. * * @capability codex codex/bestiary/lorebook of defined entries with discovery tracking, categories, secret masking, completion, an onDiscover seam, and serializable state */ export declare function createCodex(options: CodexOptions): Codex;