feat(journal): implement JournalInput with command autocomplete
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Journal completions — client-side loader for /__COMPLETIONS.json
|
||||
*
|
||||
* Fetches once on first call, caches the result. Call `invalidateCompletions()`
|
||||
* to force a re-fetch (e.g., when the content source changes).
|
||||
*/
|
||||
|
||||
import { createSignal } from "solid-js";
|
||||
|
||||
// ------------------- Types (mirrors CLI) -------------------
|
||||
|
||||
export interface DiceCompletion {
|
||||
label: string;
|
||||
notation: string;
|
||||
source: string;
|
||||
}
|
||||
|
||||
export interface LinkCompletion {
|
||||
path: string;
|
||||
label: string;
|
||||
section: string | null;
|
||||
}
|
||||
|
||||
export interface JournalCompletions {
|
||||
dice: DiceCompletion[];
|
||||
links: LinkCompletion[];
|
||||
}
|
||||
|
||||
// ------------------- Cache -------------------
|
||||
|
||||
let _cache: JournalCompletions = { dice: [], links: [] };
|
||||
let _loaded = false;
|
||||
|
||||
/** Thawed value signal; invalidate resets it. */
|
||||
const [completions, setCompletions] = createSignal<JournalCompletions>(_cache);
|
||||
|
||||
// ------------------- Fetch -------------------
|
||||
|
||||
async function load(): Promise<void> {
|
||||
try {
|
||||
const resp = await fetch("/__COMPLETIONS.json");
|
||||
if (resp.ok) {
|
||||
const data = await resp.json();
|
||||
_cache = {
|
||||
dice: Array.isArray(data.dice) ? data.dice : [],
|
||||
links: Array.isArray(data.links) ? data.links : [],
|
||||
};
|
||||
} else {
|
||||
_cache = { dice: [], links: [] };
|
||||
}
|
||||
} catch {
|
||||
_cache = { dice: [], links: [] };
|
||||
}
|
||||
_loaded = true;
|
||||
setCompletions(_cache);
|
||||
}
|
||||
|
||||
/** Ensure data is loaded (lazy, idempotent). */
|
||||
let _promise: Promise<void> | null = null;
|
||||
export function ensureCompletions(): Promise<void> {
|
||||
if (!_promise) _promise = load();
|
||||
return _promise;
|
||||
}
|
||||
|
||||
/** Force a re-fetch on next use. */
|
||||
export function invalidateCompletions(): void {
|
||||
_loaded = false;
|
||||
_promise = null;
|
||||
}
|
||||
|
||||
// ------------------- Hook -------------------
|
||||
|
||||
/**
|
||||
* Reactive completions data for the journal input.
|
||||
* Triggers a lazy fetch on first access; returns empty arrays while loading.
|
||||
*/
|
||||
export function useJournalCompletions(): JournalCompletions {
|
||||
if (!_loaded) {
|
||||
void ensureCompletions();
|
||||
}
|
||||
return completions();
|
||||
}
|
||||
Reference in New Issue
Block a user