import { createContext, useContext } from 'react'; /** A page in the current pond, as the wikilink UI needs it (issue #46). */ export interface WikilinkTarget { slug: string; title: string; } /** How a wikilink node resolves its target for display and navigation. */ export interface WikilinkResolution { /** Current title of the target page, or null when it does not exist (phantom). */ title: string | null; exists: boolean; } export interface WikilinkContextValue { /** Pages of the current pond, for the `[[` autocomplete. */ targets: WikilinkTarget[]; /** Resolve a slug to its live title and existence. */ resolve: (slug: string) => WikilinkResolution; /** Pond slug, so a wikilink can build its navigation URL. */ pondSlug: string; /** Whether the editor is in edit mode (click behaviour differs from read mode). */ editable: boolean; } /** * Live pond context for wikilinks (issue #46). Provided by the page editor, * consumed by the wikilink NodeView (title resolution, phantom styling) and the * autocomplete popup. Defaults are inert so a wikilink still renders (as its * slug) if it is ever mounted without a provider. */ export const WikilinkContext = createContext({ targets: [], resolve: () => ({ title: null, exists: false }), pondSlug: '', editable: false, }); export function useWikilinks(): WikilinkContextValue { return useContext(WikilinkContext); } /** Builds a slug→title lookup and a resolver from a pond's page list. */ export function makeWikilinkResolver( targets: WikilinkTarget[], ): (slug: string) => WikilinkResolution { const bySlug = new Map(targets.map((t) => [t.slug, t.title])); return (slug) => { const title = bySlug.get(slug); return title !== undefined ? { title, exists: true } : { title: null, exists: false }; }; }