@sphynxoid/stepwise 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/use-steps.ts","../src/use-step-player.ts","../src/use-guided-tour.ts","../src/use-chapters.ts","../src/flatten.ts","../src/use-global-keys.ts","../src/use-discoveries.ts","../src/use-focus-trap.ts","../src/use-prefers-reduced-motion.ts","../src/glossary.tsx","../src/cn.ts","../src/theme.ts","../src/components.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nexport interface UseStepsOptions {\n /** Initial focus. Clamped. Defaults to 0. */\n initialIndex?: number;\n /** Fired whenever the focus index changes. */\n onChange?: (index: number) => void;\n}\n\nexport interface StepsCore {\n /** Number of steps in the sequence. */\n count: number;\n /** Clamped focus: 0..count-1, or -1 when the sequence is empty. */\n index: number;\n atStart: boolean;\n atEnd: boolean;\n canNext: boolean;\n canPrev: boolean;\n /** Clamped jump. No-op on an empty sequence. */\n go: (index: number) => void;\n /** Clamped forward step. */\n next: () => void;\n /** Clamped backward step. */\n prev: () => void;\n /** Jump to the first step. */\n first: () => void;\n}\n\n/**\n * The core primitive every stepwise machine composes: a clamped cursor over an\n * ordered sequence. Frames in a trace, chapters in a lesson, lessons in a\n * notebook, and tour steps are all the same thing at this layer — timers,\n * effects, and scroll-tracking are policies layered on top by consumers.\n *\n * All callbacks are referentially stable; `count` may change dynamically (a\n * new timeline, a mounted window) and the cursor re-clamps automatically.\n */\nexport function useSteps<T>(items: readonly T[] | number, opts?: UseStepsOptions): StepsCore {\n const count = typeof items === \"number\" ? items : items.length;\n const countRef = useRef(count);\n countRef.current = count;\n const onChangeRef = useRef(opts?.onChange);\n onChangeRef.current = opts?.onChange;\n\n const [cursor, setCursor] = useState(() => {\n const initial = opts?.initialIndex ?? 0;\n return count === 0 ? -1 : Math.max(0, Math.min(initial, count - 1));\n });\n\n const index = count === 0 ? -1 : Math.max(0, Math.min(cursor, count - 1));\n const indexRef = useRef(index);\n indexRef.current = index;\n\n // Re-clamp when the sequence shrinks.\n useEffect(() => {\n if (count === 0) {\n if (cursor !== -1) setCursor(-1);\n } else if (cursor < 0 || cursor > count - 1) {\n setCursor(Math.max(0, Math.min(cursor, count - 1)));\n }\n }, [count, cursor]);\n\n const go = useCallback((i: number) => {\n const c = countRef.current;\n if (c === 0) return;\n const clamped = Math.max(0, Math.min(i, c - 1));\n if (clamped === indexRef.current) return;\n indexRef.current = clamped;\n setCursor(clamped);\n onChangeRef.current?.(clamped);\n }, []);\n\n const next = useCallback(() => {\n go(indexRef.current + 1);\n }, [go]);\n\n const prev = useCallback(() => {\n go(indexRef.current - 1);\n }, [go]);\n\n const first = useCallback(() => {\n go(0);\n }, [go]);\n\n return useMemo(\n () => ({\n count,\n index,\n atStart: index <= 0,\n atEnd: count > 0 && index >= count - 1,\n canNext: count > 0 && index < count - 1,\n canPrev: count > 0 && index > 0,\n go,\n next,\n prev,\n first,\n }),\n [count, index, go, next, prev, first]\n );\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useSteps } from \"./use-steps\";\nimport type { PlayerEngine } from \"./types\";\n\nexport interface StepPlayerOptions {\n /** Number of frames in the current timeline (0 = no timeline loaded). */\n total: number;\n /** Delay per frame at 1× speed (built-in timer engine). */\n baseDelayMs?: number;\n /** Start playing immediately (used when a timeline exists on first render). */\n autoPlay?: boolean;\n /**\n * Alternate frame source (GSAP timeline, scroll progress, …). Replaces the\n * built-in timer. Memoize the engine per timeline — identity changes\n * reconnect it.\n */\n engine?: PlayerEngine;\n /**\n * Deep-link the current frame into the URL hash (`#<key>=<index>`), opt-in.\n * The initial hash is honored once on mount.\n */\n syncHash?: string;\n /**\n * Fired once when playback runs to the final frame on its own (built-in\n * timer or engine `onEnd`). Cleared by any cursor movement (seek/step/\n * reset/new timeline) — the next full playthrough fires it again.\n */\n onEnd?: () => void;\n}\n\nexport interface StepPlayer {\n /** Total frames in the current timeline. */\n total: number;\n /** Raw frame counter; -1 means \"no timeline / before first frame\". */\n frame: number;\n /** Frame clamped into [0, total-1]; -1 when there is nothing to show. */\n index: number;\n playing: boolean;\n speed: number;\n /** Position flag: the cursor is parked on the final frame (seek counts too). */\n atEnd: boolean;\n /**\n * Completion state: playback ran to the final frame on its own and nothing\n * has moved the cursor since. Unlike `atEnd`, a seek to the last frame does\n * not set it — `toggle()` at `ended` replays from frame 0.\n */\n ended: boolean;\n /** Jump to frame 0 and play. */\n start: () => void;\n /** Clear the player (frame = -1, paused). */\n reset: () => void;\n seek: (frame: number) => void;\n /** Step forward; pauses first. `onEmpty` fires when there is no timeline. */\n next: (onEmpty?: () => void) => void;\n /** Step backward; pauses first. */\n prev: () => void;\n /** Play/pause; replays from 0 at the end. `onEmpty` fires when there is no timeline. */\n toggle: (onEmpty?: () => void) => void;\n setPlaying: (playing: boolean) => void;\n setSpeed: (speed: number) => void;\n}\n\nexport function useStepPlayer({ total, baseDelayMs = 900, autoPlay = false, engine, syncHash, onEnd }: StepPlayerOptions): StepPlayer {\n const core = useSteps(total);\n const [started, setStarted] = useState(autoPlay && total > 0);\n const [playing, setPlaying] = useState(autoPlay && total > 0);\n const [speed, setSpeed] = useState(1);\n const [ended, setEnded] = useState(false);\n const endedRef = useRef(false);\n const onEndRef = useRef(onEnd);\n onEndRef.current = onEnd;\n\n // Completion transitions are idempotent: adapters may repeat `onEnd`\n // (the port allows it); the option callback fires once per run.\n const markEnded = useCallback(() => {\n if (endedRef.current) return;\n endedRef.current = true;\n setEnded(true);\n onEndRef.current?.();\n }, []);\n\n const clearEnded = useCallback(() => {\n if (!endedRef.current) return;\n endedRef.current = false;\n setEnded(false);\n }, []);\n\n const index = started && core.index >= 0 ? core.index : -1;\n const atEnd = total > 0 && index >= 0 && index >= total - 1;\n\n const engineRef = useRef(engine);\n engineRef.current = engine;\n const totalRef = useRef(total);\n totalRef.current = total;\n const engineApiRef = useRef<{\n play?(): void;\n pause?(): void;\n seek?(frame: number): void;\n rate?(rate: number): void;\n }>({});\n\n // Engine lifecycle — reconnect only when the engine identity changes.\n useEffect(() => {\n if (!engine) return;\n const handle = engine.connect({\n get total() {\n return totalRef.current;\n },\n onFrame: (f) => core.go(f),\n onEnd: () => {\n markEnded();\n setPlaying(false);\n },\n });\n engineApiRef.current = {\n play: () => handle.play(),\n pause: () => handle.pause(),\n seek: (f) => handle.seek(f),\n rate: (r) => handle.setRate(r),\n };\n return () => {\n engineApiRef.current = {};\n handle.disconnect();\n };\n // `core` identity churns with the index; the connect API reads live state\n // via refs — only the engine identity may reconnect.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [engine]);\n\n const start = useCallback(() => {\n setStarted(true);\n setPlaying(true);\n clearEnded();\n core.first();\n if (engineRef.current) {\n engineApiRef.current.seek?.(0);\n engineApiRef.current.play?.();\n }\n }, [core]);\n\n const reset = useCallback(() => {\n setStarted(false);\n setPlaying(false);\n clearEnded();\n if (engineRef.current) engineApiRef.current.pause?.();\n }, [clearEnded]);\n\n const seek = useCallback(\n (f: number) => {\n if (total === 0) return;\n setStarted(true);\n setPlaying(false);\n clearEnded();\n core.go(Math.max(0, Math.min(f, total - 1)));\n if (engineRef.current) {\n engineApiRef.current.pause?.();\n engineApiRef.current.seek?.(f);\n }\n },\n [total, core, clearEnded]\n );\n\n const next = useCallback(\n (onEmpty?: () => void) => {\n setPlaying(false);\n if (total === 0) {\n onEmpty?.();\n return;\n }\n setStarted(true);\n clearEnded();\n core.next();\n if (engineRef.current) {\n engineApiRef.current.pause?.();\n engineApiRef.current.seek?.(Math.min(core.index + 1, total - 1));\n }\n },\n [total, core, clearEnded]\n );\n\n const prev = useCallback(() => {\n setPlaying(false);\n clearEnded();\n core.prev();\n if (engineRef.current) {\n engineApiRef.current.pause?.();\n engineApiRef.current.seek?.(Math.max(0, core.index - 1));\n }\n }, [core, clearEnded]);\n\n const toggle = useCallback(\n (onEmpty?: () => void) => {\n if (total === 0) {\n onEmpty?.();\n return;\n }\n if (!playing && atEnd) {\n setStarted(true);\n setPlaying(true);\n clearEnded();\n core.first();\n if (engineRef.current) {\n engineApiRef.current.seek?.(0);\n engineApiRef.current.play?.();\n }\n return;\n }\n const nextPlaying = !playing;\n setPlaying(nextPlaying);\n setStarted(true);\n if (engineRef.current) {\n if (nextPlaying) engineApiRef.current.play?.();\n else engineApiRef.current.pause?.();\n }\n },\n [total, playing, atEnd, core, clearEnded]\n );\n\n const changeSpeed = useCallback((s: number) => {\n setSpeed(s);\n if (engineRef.current) engineApiRef.current.rate?.(s);\n }, []);\n\n // A new timeline wipes completion — the next playthrough ends it fresh.\n useEffect(() => {\n clearEnded();\n }, [total, clearEnded]);\n\n // Built-in timer loop — skipped entirely when a custom engine takes over.\n useEffect(() => {\n if (engineRef.current) return;\n if (!playing || !started || total === 0) return;\n if (core.index >= total - 1) {\n markEnded();\n setPlaying(false);\n return;\n }\n const id = setTimeout(() => core.next(), baseDelayMs / speed);\n return () => clearTimeout(id);\n }, [playing, started, core, total, speed, baseDelayMs, markEnded]);\n\n // Deep-linking: honor #<key>=<index> on mount and external hash edits only.\n // The hash values the player itself writes are ignored, and readHash never\n // re-runs on render churn (stable deps; go reached through a ref) — reading\n // a lagging hash during playback would ping-pong the cursor.\n const hashKey = syncHash;\n const coreGoRef = useRef(core.go);\n coreGoRef.current = core.go;\n const lastWrittenHash = useRef(\"\");\n const readHash = useCallback(() => {\n if (!hashKey || typeof window === \"undefined\" || total === 0) return;\n const hash = window.location.hash;\n if (hash === lastWrittenHash.current) return;\n const match = hash.match(new RegExp(`[#&]${hashKey}=(\\\\d+)`));\n if (!match) return;\n const f = Number(match[1]);\n if (Number.isFinite(f) && f >= 0 && f < total) {\n setStarted(true);\n coreGoRef.current(f);\n }\n }, [hashKey, total]);\n\n useEffect(() => {\n readHash();\n const onHashChange = () => readHash();\n window.addEventListener(\"hashchange\", onHashChange);\n return () => window.removeEventListener(\"hashchange\", onHashChange);\n }, [readHash]);\n\n useEffect(() => {\n if (!syncHash || index < 0 || typeof window === \"undefined\") return;\n const next = `#${syncHash}=${index}`;\n if (window.location.hash !== next) {\n lastWrittenHash.current = next;\n window.history.replaceState(null, \"\", next);\n }\n }, [syncHash, index]);\n\n return useMemo(\n () => ({\n total,\n frame: index,\n index,\n playing,\n speed,\n atEnd,\n ended,\n start,\n reset,\n seek,\n next,\n prev,\n toggle,\n setPlaying,\n setSpeed: changeSpeed,\n }),\n [total, index, playing, speed, atEnd, ended, start, reset, seek, next, prev, toggle, changeSpeed]\n );\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useSteps } from \"./use-steps\";\nimport type { TourDriver, TourStepInput } from \"./types\";\n\nexport interface GuidedTour {\n /** Active step index, or null when the tour is not running. */\n index: number | null;\n current: TourStepInput | null;\n active: boolean;\n /**\n * True while the active step's `gate` returns false: `next()` is a no-op\n * until the gate opens. Present the `blocked` state (disable Next, pulse\n * the waitHint) so the user knows what is being waited on.\n */\n blocked: boolean;\n start: () => void;\n end: () => void;\n next: () => void;\n back: () => void;\n goto: (index: number) => void;\n /** Jump to the step with this id. No-op when the id is unknown. */\n gotoId: (id: string) => void;\n}\n\nexport interface GuidedTourOptions {\n /**\n * Alternate presenter (driver.js, Shepherd, …). When set, the hook drives it\n * imperatively — show/hide per step, with transition controls wired — and\n * the app should not render the built-in TourSpotlight/TourCard. Without a\n * driver, the app renders the built-in presentation itself.\n */\n driver?: TourDriver;\n}\n\n/**\n * Tour state whose steps are effects over app state: `onEnter` fires whenever\n * the active step changes, reading the latest `steps` via ref so closures stay\n * fresh without re-triggering the effect on every render. Composed on\n * useSteps — a tour is a step sequence whose `next` past the end exits.\n *\n * On top of the linear cursor, steps may declare `when` (skip on arrival),\n * `gate` (block `next` until true), and `next` (edge override by step id) —\n * a small state machine where states are steps, edges are `next` functions,\n * and guards are gates. The cursor itself stays a cursor: skipped steps are\n * never landed on, and skipped/gated behavior is evaluated at transition\n * time, not on every render.\n */\nexport function useGuidedTour(steps: TourStepInput[], opts?: GuidedTourOptions): GuidedTour {\n const [running, setRunning] = useState(false);\n const runningRef = useRef(running);\n runningRef.current = running;\n const core = useSteps(steps.length);\n const stepsRef = useRef(steps);\n stepsRef.current = steps;\n const driverRef = useRef(opts?.driver);\n driverRef.current = opts?.driver;\n // core.go is referentially stable; reach it through a ref so the callbacks\n // below (and the driver effect) don't churn with the cursor.\n const coreGoRef = useRef(core.go);\n coreGoRef.current = core.go;\n\n const isSkipped = useCallback(\n (i: number) => stepsRef.current[i]?.when?.() === false,\n []\n );\n\n /**\n * Land on `start` when eligible; otherwise walk in `dir` past skipped\n * steps. Forward exhaustion (or an all-skipped tour) returns null, which\n * ends the run; backward exhaustion restarts at the first eligible step.\n */\n const settle = useCallback(\n (start: number, dir: 1 | -1): number | null => {\n const len = stepsRef.current.length;\n let i = start;\n while (i >= 0 && i < len && isSkipped(i)) i += dir;\n if (i >= 0 && i < len) return i;\n if (dir === 1) return null;\n for (let j = 0; j < len; j++) if (!isSkipped(j)) return j;\n return null;\n },\n [isSkipped]\n );\n\n /** Enter the tour at (or, past skipped steps in direction `dir`) index `i`. */\n const arrive = useCallback(\n (i: number, dir: 1 | -1) => {\n const target = settle(i, dir);\n if (target === null) {\n setRunning(false);\n return;\n }\n setRunning(true);\n coreGoRef.current(target);\n },\n [settle]\n );\n\n const goTo = useCallback(\n (i: number) => {\n if (stepsRef.current.length === 0) return;\n arrive(Math.max(0, Math.min(i, stepsRef.current.length - 1)), 1);\n },\n [arrive]\n );\n\n const goToId = useCallback(\n (id: string) => {\n const i = stepsRef.current.findIndex((s) => s.id === id);\n if (i >= 0) goTo(i);\n },\n [goTo]\n );\n\n const index = running ? core.index : null;\n\n useEffect(() => {\n if (!running) return;\n stepsRef.current[core.index]?.onEnter?.();\n }, [running, core.index]);\n\n // Custom driver lifecycle — show the active step, hide on end/unmount.\n useEffect(() => {\n const driver = driverRef.current;\n if (!driver) return;\n if (!running) {\n driver.hide();\n return;\n }\n const step = stepsRef.current[core.index];\n if (!step) {\n driver.hide();\n return;\n }\n driver.show(step, {\n index: core.index,\n total: stepsRef.current.length,\n next: () => goTo(core.index + 1),\n back: () => goTo(core.index - 1),\n end: () => setRunning(false),\n });\n }, [running, core.index, goTo, core]);\n\n // Hide the driver if the tour unmounts mid-step.\n useEffect(() => () => driverRef.current?.hide(), []);\n\n const start = useCallback(() => {\n if (stepsRef.current.length === 0) return;\n arrive(0, 1);\n }, [arrive]);\n\n const end = useCallback(() => setRunning(false), []);\n\n /** Edge target of step i: explicit next() id resolved to an index, else i+1. */\n const resolveNext = useCallback((i: number): number => {\n const list = stepsRef.current;\n const edge = list[i]?.next?.();\n if (edge != null) {\n const t = list.findIndex((s) => s.id === edge);\n if (t >= 0) return t;\n }\n return i + 1;\n }, []);\n\n const next = useCallback(() => {\n if (!runningRef.current) return;\n const i = core.index;\n // A closed gate blocks the advance — the app surfaces `blocked`.\n if (stepsRef.current[i]?.gate?.() === false) return;\n const target = resolveNext(i);\n if (target > stepsRef.current.length - 1) {\n setRunning(false); // linear past the end — the tour exits\n return;\n }\n arrive(target, 1);\n }, [core, arrive, resolveNext]);\n\n const back = useCallback(() => {\n if (!runningRef.current) return;\n const i = core.index;\n if (i <= 0) return;\n arrive(i - 1, -1);\n }, [core, arrive]);\n\n const current = running ? (stepsRef.current[core.index] ?? null) : null;\n const blocked = current?.gate?.() === false;\n return { index, current, active: running, blocked, start, end, next, back, goto: goTo, gotoId: goToId };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useSteps } from \"./use-steps\";\nimport { flattenChapters } from \"./flatten\";\nimport type { Chapter } from \"./types\";\n\nexport interface ChaptersApi {\n /** Index of the chapter currently in view (flattened order). */\n active: number;\n goTo: (index: number) => void;\n next: () => void;\n prev: () => void;\n}\n\nexport { flattenChapters };\n\n/**\n * Scroll-tracked chapter navigation for multi-section pages. Active = the\n * section containing the viewport center: a chapter becomes active when it\n * reaches the middle of the screen, not the moment its top scrolls past an\n * offset. Sections are resolved by DOM id; give each section CSS scroll-mt\n * so `goTo`'s scrollIntoView clears any sticky header. Composed on useSteps —\n * the scroll position is an external input driving the cursor.\n */\nexport function useChapters(chapters: Chapter[]): ChaptersApi {\n const [mounted, setMounted] = useState(false);\n const flat = useMemo(() => flattenChapters(chapters), [chapters]);\n const flatRef = useRef(flat);\n flatRef.current = flat;\n const [active, setActive] = useState(0);\n const activeRef = useRef(0);\n activeRef.current = active;\n\n const core = useSteps(flat.length, { initialIndex: 0 });\n // core.go is referentially stable; the tracker reaches it through a ref so\n // the effect below never depends on the core identity (which churns with\n // the index).\n const coreGoRef = useRef(core.go);\n coreGoRef.current = core.go;\n\n // Scroll → cursor (external input drives the sequence). Depending only on\n // `mounted` (+ the chapter count) matters: if this effect re-ran on every\n // cursor change, a programmatic goTo would be snapped back to the rect-\n // derived chapter before the smooth scroll has moved the viewport.\n useEffect(() => {\n if (!mounted) return;\n let raf = 0;\n const update = () => {\n raf = 0;\n const flat = flatRef.current;\n const mid = window.innerHeight / 2;\n let best = -1;\n for (let i = 0; i < flat.length; i++) {\n const el = document.getElementById(flat[i].chapter.id);\n if (!el) continue;\n const rect = el.getBoundingClientRect();\n if (rect.top <= mid && rect.bottom >= mid) best = i;\n }\n if (best === -1) {\n // No section contains the center (tall gap or beyond the ends): keep\n // the deepest section whose top is above center, else the first.\n for (let i = 0; i < flat.length; i++) {\n const el = document.getElementById(flat[i].chapter.id);\n if (el && el.getBoundingClientRect().top <= mid) best = i;\n }\n if (best === -1) best = 0;\n }\n if (best !== activeRef.current) {\n setActive(best);\n coreGoRef.current(best);\n }\n };\n const onScroll = () => {\n if (!raf) raf = requestAnimationFrame(update);\n };\n update();\n window.addEventListener(\"scroll\", onScroll, { passive: true });\n window.addEventListener(\"resize\", onScroll);\n return () => {\n window.removeEventListener(\"scroll\", onScroll);\n window.removeEventListener(\"resize\", onScroll);\n if (raf) cancelAnimationFrame(raf);\n };\n }, [mounted, flat.length]);\n\n useEffect(() => setMounted(true), []);\n\n const goTo = useCallback((i: number) => {\n const entry = flatRef.current[i];\n if (!entry) return;\n setActive(i);\n coreGoRef.current(i);\n const el = document.getElementById(entry.chapter.id);\n if (!el) return;\n el.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n }, []);\n\n const next = useCallback(() => {\n if (activeRef.current < flatRef.current.length - 1) goTo(activeRef.current + 1);\n }, [goTo]);\n const prev = useCallback(() => {\n if (activeRef.current > 0) goTo(activeRef.current - 1);\n }, [goTo]);\n\n return { active: core.index, goTo, next, prev };\n}\n","import type { Chapter } from \"./types\";\n\nexport interface FlatChapter {\n chapter: Chapter;\n depth: number;\n /** Index of this entry's top-level ancestor within the flat list (itself at depth 0). */\n rootIndex: number;\n /** Index of the immediate parent within the flat list; -1 at depth 0. */\n parentIndex: number;\n}\n\n/** Depth-first flattening — reading order for prev/next and scroll tracking. */\nexport function flattenChapters(chapters: Chapter[], depth = 0): FlatChapter[] {\n const out: FlatChapter[] = [];\n const walk = (list: Chapter[], depth: number, parentIndex: number, rootIndex: number) => {\n for (const chapter of list) {\n const index = out.length;\n const effectiveRoot = depth === 0 ? index : rootIndex;\n out.push({ chapter, depth, rootIndex: effectiveRoot, parentIndex });\n if (chapter.children?.length) walk(chapter.children, depth + 1, index, effectiveRoot);\n }\n };\n walk(chapters, depth, -1, -1);\n return out;\n}\n","\"use client\";\n\nimport { useEffect, useRef } from \"react\";\n\nexport type KeyMap = Record<string, (e: KeyboardEvent) => void>;\n\nconst DEFAULT_IGNORED_TAGS = [\"INPUT\", \"TEXTAREA\", \"SELECT\", \"BUTTON\"];\n\nexport interface GlobalKeysOptions {\n /** Element tags that swallow keys (except Escape). Defaults to form controls and buttons. */\n ignoreTags?: string[];\n /** Gate: bindings fire only while enabled. Boolean or function — checked per event. */\n enabled?: boolean | (() => boolean);\n}\n\n/**\n * Bind global keyboard shortcuts. Keys are matched against `event.key`\n * (exact first, then lowercase). Handlers fire with preventDefault applied;\n * Escape always fires, even from ignored targets, and is never prevented.\n */\nexport function useGlobalKeys(map: KeyMap, opts?: GlobalKeysOptions): void {\n const mapRef = useRef(map);\n mapRef.current = map;\n const ignoreRef = useRef<Set<string>>(new Set(opts?.ignoreTags ?? DEFAULT_IGNORED_TAGS));\n const enabledRef = useRef(opts?.enabled ?? true);\n enabledRef.current = opts?.enabled ?? true;\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n const gate = enabledRef.current;\n const enabled = typeof gate === \"function\" ? gate() : gate;\n if (!enabled && e.key !== \"Escape\") return;\n const tag = (e.target as HTMLElement | null)?.tagName;\n if (e.key !== \"Escape\" && tag && ignoreRef.current.has(tag)) return;\n const fn = mapRef.current[e.key] ?? mapRef.current[e.key.toLowerCase()];\n if (!fn) return;\n if (e.key !== \"Escape\") e.preventDefault();\n fn(e);\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, []);\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\n// Discovery ledger: which named things (features, tutorials, chapters) has\n// this user already seen? A set of opaque id strings plus a persistence seam.\n// The id scheme belongs to the consumer — encode versions in the id\n// (\"sort:v2\") to re-show improved tours.\n\nexport interface DiscoveryStore {\n /** All discovered ids (best-effort; corrupted/absent storage reads as empty). */\n read(): string[];\n /** Persist the full set (write-through, not a delta). */\n write(ids: string[]): void;\n}\n\n/** localStorage-backed store — the default. Survives reloads, per-browser. */\nexport function localStorageStore(key = \"stepwise.discoveries\"): DiscoveryStore {\n return {\n read() {\n if (typeof window === \"undefined\") return [];\n try {\n const parsed = JSON.parse(window.localStorage.getItem(key) ?? \"[]\");\n return Array.isArray(parsed) ? parsed.filter((x): x is string => typeof x === \"string\") : [];\n } catch {\n return [];\n }\n },\n write(ids) {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(key, JSON.stringify(ids));\n } catch {\n // private mode / quota exceeded — discovery state is best-effort\n }\n },\n };\n}\n\n/**\n * Cookie-backed store — only when the SERVER must know during SSR (e.g. to\n * render \"NEW\" badges without a hydration flash). Costs request bytes; prefer\n * localStorage otherwise. Values are JSON-encoded and URI-escaped.\n */\nexport function cookieStore(key = \"stepwise.discoveries\"): DiscoveryStore {\n const read = (): string[] => {\n if (typeof document === \"undefined\") return [];\n const match = document.cookie.match(new RegExp(`(?:^|;\\\\s*)${key}=([^;]*)`));\n if (!match) return [];\n try {\n const parsed = JSON.parse(decodeURIComponent(match[1]));\n return Array.isArray(parsed) ? parsed.filter((x): x is string => typeof x === \"string\") : [];\n } catch {\n return [];\n }\n };\n return {\n read,\n write(ids) {\n if (typeof document === \"undefined\") return;\n document.cookie = `${key}=${encodeURIComponent(JSON.stringify(ids))}; max-age=31536000; path=/; SameSite=Lax`;\n },\n };\n}\n\n/** In-memory store — tests, storybook, SSR fallbacks, \"always show\" previews. */\nexport function memoryStore(seed: string[] = []): DiscoveryStore {\n let ids = [...seed];\n return {\n read: () => [...ids],\n write(next) {\n ids = [...next];\n },\n };\n}\n\nexport interface DiscoveriesOptions {\n /**\n * Storage seam. Defaults to localStorage. Swap in cookieStore when SSR\n * markup must know, or your own store (backend sync for cross-device).\n */\n store?: DiscoveryStore;\n /** Storage key used by the built-in stores. */\n key?: string;\n}\n\nexport interface Discoveries {\n /** Discovered ids. Empty until hydration — gate triggers on `ready`. */\n discovered: Set<string>;\n /** False during SSR and before the first client hydration pass. */\n ready: boolean;\n /** Ref-backed check for event handlers; prefer `discovered.has` in render. */\n isDiscovered: (id: string) => boolean;\n /** Record ids as discovered and persist the merged set. */\n markDiscovered: (id: string | string[]) => void;\n /** Forget everything (debug / \"show me the tour again\"). */\n reset: () => void;\n}\n\n/**\n * A persisted set of discovered ids, hydrated after mount (SSR-safe: the\n * server renders the undiscovered state, the client corrects it in an\n * effect — same pattern as usePrefersReducedMotion). Compose with\n * useGuidedTour: `pending = features.filter(f => !discovered.has(f.id))`,\n * auto-start the first pending tour, `markDiscovered` on completion.\n */\nexport function useDiscoveries(opts?: DiscoveriesOptions): Discoveries {\n // The default store is built once (key captured at first call); an\n // explicitly passed store always wins and may change identity per render.\n const defaultStoreRef = useRef<DiscoveryStore | null>(null);\n const storeRef = useRef<DiscoveryStore | null>(null);\n if (opts?.store) {\n storeRef.current = opts.store;\n } else {\n if (!defaultStoreRef.current) defaultStoreRef.current = localStorageStore(opts?.key);\n storeRef.current = defaultStoreRef.current;\n }\n\n const [ids, setIds] = useState<Set<string>>(() => new Set());\n const [ready, setReady] = useState(false);\n const idsRef = useRef(ids);\n idsRef.current = ids;\n\n useEffect(() => {\n setIds(new Set(storeRef.current!.read()));\n setReady(true);\n }, []);\n\n const markDiscovered = useCallback((id: string | string[]) => {\n const additions = Array.isArray(id) ? id : [id];\n const merged = new Set(idsRef.current);\n let changed = false;\n for (const x of additions) {\n if (!merged.has(x)) {\n merged.add(x);\n changed = true;\n }\n }\n if (!changed) return;\n idsRef.current = merged;\n setIds(merged);\n storeRef.current!.write([...merged]);\n }, []);\n\n const reset = useCallback(() => {\n const empty = new Set<string>();\n idsRef.current = empty;\n setIds(empty);\n storeRef.current!.write([]);\n }, []);\n\n const isDiscovered = useCallback((id: string) => idsRef.current.has(id), []);\n\n return useMemo(\n () => ({ discovered: ids, ready, isDiscovered, markDiscovered, reset }),\n [ids, ready, isDiscovered, markDiscovered, reset]\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef } from \"react\";\n\n/**\n * Traps Tab focus inside `ref.current` while `active`, focuses the container\n * on activation, and restores the previously focused element on release.\n * Returns a ref to attach to the focusable container (tabIndex={-1}).\n */\nexport function useFocusTrap(active: boolean) {\n const ref = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (!active) return;\n const container = ref.current;\n if (!container) return;\n const previous = document.activeElement as HTMLElement | null;\n\n container.focus({ preventScroll: true });\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Tab\") return;\n const focusables = Array.from(\n container.querySelectorAll<HTMLElement>(\n 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex=\"-1\"])'\n )\n ).filter((el) => el.offsetParent !== null || el === container);\n if (focusables.length === 0) return;\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const current = document.activeElement as HTMLElement | null;\n if (e.shiftKey && (current === first || !container.contains(current))) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && (current === last || !container.contains(current))) {\n e.preventDefault();\n first.focus();\n }\n };\n\n document.addEventListener(\"keydown\", onKey, true);\n return () => {\n document.removeEventListener(\"keydown\", onKey, true);\n previous?.focus({ preventScroll: true });\n };\n }, [active]);\n\n return ref;\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\n/**\n * True when the user asks the OS to reduce motion. Consumers should disable\n * transitions, smooth scrolls, and entry animations when this is true.\n * SSR-safe: false on the server, corrected after mount.\n */\nexport function usePrefersReducedMotion(): boolean {\n const [reduced, setReduced] = useState(false);\n\n useEffect(() => {\n const mq = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n setReduced(mq.matches);\n const onChange = (e: MediaQueryListEvent) => setReduced(e.matches);\n mq.addEventListener(\"change\", onChange);\n return () => mq.removeEventListener(\"change\", onChange);\n }, []);\n\n return reduced;\n}\n","\"use client\";\n\nimport {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useId,\r\n useLayoutEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\nimport { createPortal } from \"react-dom\";\r\nimport { cn } from \"./cn\";\r\nimport { defaultTheme, type StepwiseTheme } from \"./theme\";\n\n// Glossary + Paradox-style recursive tooltips. Define entries once, reference\n// them inline with <Term id=\"…\">; definitions are ReactNode, so they may\n// contain further <Term>s — chains stack outward and are depth-capped\n// (mutual references terminate at MAX_DEPTH).\n\nexport interface GlossaryEntry {\n id: string;\n /** Display name, shown as the tooltip's heading. */\n term: string;\n /** Body — may embed <Term> references for nested tooltips. */\n definition: ReactNode;\n}\n\nconst MAX_DEPTH = 4;\nconst CARD_WIDTH = 288; // w-72\nconst OPEN_DELAY_MS = 60;\nconst CLOSE_GRACE_MS = 120;\n\ninterface GlossaryContextValue {\r\n byId: Map<string, GlossaryEntry>;\r\n /** Original declaration order — the auto-appendix renders this. */\r\n entries: GlossaryEntry[];\r\n /** Theme for the tooltip card; injectable per provider. */\r\n theme: StepwiseTheme;\r\n}\r\n\r\nconst GlossaryContext = createContext<GlossaryContextValue | null>(null);\r\nconst DepthContext = createContext(0);\r\nconst AppendixContext = createContext(false);\r\n\r\nexport function GlossaryProvider({\r\n entries,\r\n theme = defaultTheme,\r\n children,\r\n}: {\r\n entries: GlossaryEntry[];\r\n /** Styling for tooltip cards (see StepwiseTheme). */\r\n theme?: StepwiseTheme;\r\n children: ReactNode;\r\n}) {\r\n const value = useMemo(\r\n () => ({ byId: new Map(entries.map((e) => [e.id, e])), entries, theme }),\r\n [entries, theme]\r\n );\r\n return <GlossaryContext.Provider value={value}>{children}</GlossaryContext.Provider>;\r\n}\n\nexport function Term({ id, children, className }: { id: string; children?: ReactNode; className?: string }) {\n const ctx = useContext(GlossaryContext);\n const depth = useContext(DepthContext);\n const entry = ctx?.byId.get(id);\n\n const [open, setOpen] = useState(false);\n const [pos, setPos] = useState<{ left: number; top: number } | null>(null);\n const openRef = useRef(false);\n const wrapperRef = useRef<HTMLSpanElement | null>(null);\n const triggerRef = useRef<HTMLSpanElement | null>(null);\n const cardRef = useRef<HTMLSpanElement | null>(null);\n const openTimer = useRef(0);\n const closeTimer = useRef(0);\n const tipId = useId();\n\n const display = children ?? entry?.term ?? id;\n\n const closeNow = useCallback(() => {\n window.clearTimeout(openTimer.current);\n window.clearTimeout(closeTimer.current);\n openRef.current = false;\n setOpen(false);\n }, []);\n\n const openNow = useCallback((focusCard = false) => {\n window.clearTimeout(closeTimer.current);\n window.clearTimeout(openTimer.current);\n openRef.current = true;\n setOpen(true);\n if (focusCard) {\n requestAnimationFrame(() => cardRef.current?.focus({ preventScroll: true }));\n }\n }, []);\n\n const scheduleOpen = useCallback(() => {\n window.clearTimeout(closeTimer.current);\n if (openRef.current) return;\n window.clearTimeout(openTimer.current);\n openTimer.current = window.setTimeout(() => openNow(), OPEN_DELAY_MS);\n }, [openNow]);\n\n const scheduleClose = useCallback(() => {\n window.clearTimeout(openTimer.current);\n window.clearTimeout(closeTimer.current);\n closeTimer.current = window.setTimeout(closeNow, CLOSE_GRACE_MS);\n }, [closeNow]);\n\n // Position: below the trigger by default, flipped above when there is no\r\n // room beneath, horizontally clamped inside the viewport. Runs as a layout\r\n // effect so the card is measured before paint (no flash), then tracked on\r\n // scroll + resize, rAF-throttled.\r\n useLayoutEffect(() => {\r\n if (!open) {\r\n setPos(null);\r\n return;\r\n }\r\n let raf = 0;\r\n const update = () => {\r\n raf = 0;\r\n const trigger = triggerRef.current;\r\n const card = cardRef.current;\r\n if (!trigger) return;\r\n const r = trigger.getBoundingClientRect();\r\n const margin = 8;\r\n const gap = 8;\r\n const cw = card?.offsetWidth ?? CARD_WIDTH;\r\n const ch = card?.offsetHeight ?? 160;\r\n let top = r.bottom + gap;\r\n if (top + ch > window.innerHeight - margin) {\r\n // Not enough room below — flip above the trigger.\r\n top = r.top - gap - ch;\r\n if (top < margin) top = margin; // no room either way: pin to the top\r\n }\r\n let left = r.left;\r\n left = Math.max(margin, Math.min(left, window.innerWidth - cw - margin));\r\n setPos({ left, top });\r\n };\r\n const onMove = () => {\r\n if (!raf) raf = requestAnimationFrame(update);\r\n };\r\n update();\r\n window.addEventListener(\"scroll\", onMove, { passive: true });\r\n window.addEventListener(\"resize\", onMove);\r\n return () => {\r\n window.removeEventListener(\"scroll\", onMove);\r\n window.removeEventListener(\"resize\", onMove);\r\n if (raf) cancelAnimationFrame(raf);\r\n };\r\n }, [open]);\n\n // Outside pointer closes (touch + click-away); Escape closes from anywhere\n // inside the tooltip subtree.\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: PointerEvent) => {\n const target = e.target as Node;\n if (wrapperRef.current?.contains(target)) return;\n if (cardRef.current?.contains(target)) return;\n closeNow();\n };\n document.addEventListener(\"pointerdown\", onPointerDown);\n return () => document.removeEventListener(\"pointerdown\", onPointerDown);\n }, [open, closeNow]);\n\n // Timer cleanup.\n useEffect(() => () => {\n window.clearTimeout(openTimer.current);\n window.clearTimeout(closeTimer.current);\n }, []);\n\n const capped = depth >= MAX_DEPTH;\r\n const inAppendix = useContext(AppendixContext);\r\n const interactive = !capped && !inAppendix;\r\n const t = ctx?.theme ?? defaultTheme;\n\n // Inside a glossary appendix, references become anchor links to the entry's\n // row instead of nested tooltips.\n if (inAppendix) {\n const linked = ctx?.byId.get(id);\n if (!linked) return <span className={className}>{display}</span>;\n return (\n <a\n href={`#glossary-${linked.id}`}\n title={linked.term}\n className={cn(\"text-accent underline underline-offset-4 hover:text-primary\", className)}\n >\n {display}\n </a>\n );\n }\n\n const triggerProps = interactive\n ? {\n role: \"button\" as const,\n tabIndex: 0,\n \"aria-expanded\": open,\n \"aria-describedby\": open ? tipId : undefined,\n onMouseEnter: scheduleOpen,\n onMouseLeave: scheduleClose,\n onFocus: () => openNow(),\n onBlur: (e: React.FocusEvent) => {\n const next = e.relatedTarget as Node | null;\n if (next && (wrapperRef.current?.contains(next) || cardRef.current?.contains(next))) return;\n scheduleClose();\n },\n onClick: () => openNow(),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.stopPropagation();\n closeNow();\n } else if ((e.key === \"Enter\" || e.key === \" \") && !open) {\n e.preventDefault();\n openNow(true);\n }\n },\n }\n : {};\n\n // Unknown id or no provider: render plain text. All hooks above ran\n // unconditionally — this branch only affects markup.\n if (!ctx || !entry) {\n return <span className={cn(\"text-foreground/85\", className)}>{display}</span>;\n }\n\n return (\n <span\n ref={wrapperRef}\n className=\"relative inline\"\n onMouseEnter={interactive ? scheduleOpen : undefined}\n onMouseLeave={interactive ? scheduleClose : undefined}\n >\n <span\n ref={triggerRef}\n {...triggerProps}\n className={cn(\n \"border-b border-dotted\",\n interactive ? \"border-primary/50 text-foreground/85 hover:text-primary focus-visible:text-primary cursor-help\" : \"text-foreground/70\",\n className\n )}\n >\n {display}\n </span>\n {open &&\r\n createPortal(\r\n <DepthContext.Provider value={depth + 1}>\r\n <span\r\n ref={cardRef}\r\n role=\"tooltip\"\r\n id={tipId}\r\n tabIndex={-1}\r\n onKeyDown={(e) => {\r\n if (e.key === \"Escape\") {\r\n e.stopPropagation();\r\n closeNow();\r\n triggerRef.current?.focus({ preventScroll: true });\r\n }\r\n }}\r\n onMouseEnter={interactive ? () => window.clearTimeout(closeTimer.current) : undefined}\r\n onMouseLeave={interactive ? scheduleClose : undefined}\r\n className={cn(\r\n \"fixed z-50 block w-72 max-w-[calc(100vw-1rem)] rounded-sm p-3 shadow-2xl outline-none motion-reduce:transition-none\",\r\n \"transition-opacity duration-150\",\r\n t.surface,\r\n \"border-white/15 bg-popover\",\r\n pos === null && \"invisible\"\r\n )}\r\n style={\r\n pos\r\n ? { left: pos.left, top: pos.top, maxHeight: \"min(60vh, 20rem)\", overflowY: \"auto\" }\r\n : { visibility: \"hidden\" }\r\n }\r\n >\r\n <span className=\"mb-1 block font-mono text-[11px] uppercase tracking-widest text-primary/90\">\r\n {entry.term}\r\n </span>\r\n <span className=\"block text-[11px] font-mono leading-relaxed text-foreground/70\">\r\n {entry.definition}\r\n </span>\r\n </span>\r\n </DepthContext.Provider>,\r\n document.body\r\n )}\n </span>\n );\n}\n\n/**\r\n * The glossary appendix: every entry rendered as an anchored row, placed\r\n * after the last chapter. Entries default to the provider's declarations —\r\n * define them once and the appendix follows automatically; pass `entries`\r\n * explicitly to override or to render without a provider. Inside it, <Term>\r\n * references resolve to in-page anchor links instead of tooltips.\r\n *\r\n * Customization hooks: `intro`/`footer` render arbitrary nodes around the\r\n * grid, `renderEntry` replaces the whole row renderer, `className` and\r\n * `entryClassName` style the section and each row. Opt out of the appendix\r\n * entirely by not rendering it.\r\n */\r\nexport function GlossaryAppendix({\r\n entries,\r\n title = \"Glossary\",\r\n intro,\r\n footer,\r\n columns = 2,\r\n bare = false,\r\n className,\r\n entryClassName,\r\n renderEntry,\r\n}: {\r\n /** Override the row list; defaults to the provider's entries. */\r\n entries?: GlossaryEntry[];\r\n title?: string;\r\n /** Rendered between the title and the grid — an introduction, usage notes, scope, … */\r\n intro?: ReactNode;\r\n /** Rendered after the grid. */\r\n footer?: ReactNode;\r\n columns?: 1 | 2;\r\n /** Omit the section chrome (title/border) — the host provides its own. */\r\n bare?: boolean;\r\n className?: string;\r\n entryClassName?: string;\r\n /** Replace the default row renderer entirely. */\r\n renderEntry?: (entry: GlossaryEntry) => ReactNode;\r\n}) {\r\n const ctxEntries = useContext(GlossaryContext)?.entries;\r\n const theme = useContext(GlossaryContext)?.theme ?? defaultTheme;\r\n const list = entries ?? ctxEntries;\r\n\r\n if (!list || list.length === 0) return null;\r\n\r\n const grid = (\r\n <div\r\n className={cn(\r\n \"grid grid-cols-1 gap-x-10 gap-y-8\",\r\n columns === 2 ? \"xl:grid-cols-2\" : \"grid-cols-1\"\r\n )}\r\n >\r\n {list.map((entry) =>\r\n renderEntry ? (\r\n <div key={entry.id} id={`glossary-${entry.id}`} className=\"scroll-mt-40\">\r\n {renderEntry(entry)}\r\n </div>\r\n ) : (\r\n <div key={entry.id} id={`glossary-${entry.id}`} className={cn(\"scroll-mt-40\", entryClassName)}>\r\n <h3 className=\"font-mono text-[11px] uppercase tracking-widest text-primary/90 mb-1.5\">\r\n {entry.term}\r\n </h3>\r\n <div className=\"text-[12px] font-mono text-foreground/60 leading-relaxed [&_strong]:text-foreground/80\">\r\n {entry.definition}\r\n </div>\r\n </div>\r\n )\r\n )}\r\n </div>\r\n );\r\n\r\n const body = (\r\n <>\r\n {intro && (\r\n <div className=\"mb-8 text-[12px] font-mono text-foreground/55 leading-relaxed max-w-3xl [&_a]:text-accent [&_a]:underline [&_a]:underline-offset-4\">\r\n {intro}\r\n </div>\r\n )}\r\n {grid}\r\n {footer && <div className=\"mt-8\">{footer}</div>}\r\n </>\r\n );\r\n\r\n if (bare) {\r\n return <AppendixContext.Provider value={true}>{body}</AppendixContext.Provider>;\r\n }\r\n return (\r\n <AppendixContext.Provider value={true}>\r\n <section aria-label={title} className={cn(\"mt-16 border-t border-white/10 pt-10\", className)}>\r\n <p className={cn(\"text-[11px] font-mono uppercase tracking-widest mb-6\", theme.muted)}>{title}</p>\r\n {body}\r\n </section>\r\n </AppendixContext.Provider>\r\n );\r\n}\n\r\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import type { StepTone } from \"./types\";\n\n// Optional styled layer. The hooks are headless; these Tailwind classes are\n// the DEFAULTS the styled components ship with, overridable per component\n// via the `theme` prop — swap in any design system without touching the kit.\n//\n// The tokens cover every non-CSS-variable color the components hardcode\n// (white/black overlays, borders, code backgrounds), so a consumer theme can\n// flip the whole kit — not just the buttons — for light hosts.\n\nexport interface StepwiseTheme {\n /** Timeline-segment styling per tone. */\n toneSegment: Record<StepTone, string>;\n /** Step-kind chip styling per tone. */\n toneChip: Record<StepTone, string>;\n /** Shared structural classes for internal buttons. */\n buttonBase: string;\n /** Per-variant appearance for internal buttons. */\n buttonVariants: Record<\"ghost\" | \"outline\" | \"primary\", string>;\n /**\n * Panel chrome for nav bars, cards, dialogs, and tooltip popovers.\n * Components pass their own border/background overrides after this token,\n * so it stays a base, not a contract.\n */\n surface: string;\n /** Full-screen dimmed backdrop behind modal surfaces. */\n overlay: string;\n /** Code block frame — its own background, border, and type scale. */\n codeBlock: string;\n /** Comment / dimmed lines inside the code block. */\n codeMuted: string;\n /** Keyboard chip (ShortcutsDialog). */\n kbd: string;\n /** Ring + rounding around the tour spotlight target. */\n spotlight: string;\n /** Dimmed meta text — counters, hints, empty states. */\n muted: string;\n}\n\nexport const defaultTheme: StepwiseTheme = {\n toneSegment: {\n neutral: \"bg-white/10\",\n accent: \"bg-accent/70\",\n good: \"bg-primary\",\n bad: \"bg-destructive/70\",\n write: \"bg-foreground/30\",\n idle: \"bg-white/5\",\n },\n toneChip: {\n neutral: \"text-foreground/50 border-white/10\",\n accent: \"text-accent border-accent/40\",\n good: \"text-primary border-primary/40\",\n bad: \"text-destructive border-destructive/40\",\n write: \"text-foreground/70 border-white/20\",\n idle: \"text-foreground/30 border-white/10\",\n },\n buttonBase:\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-sm font-mono transition-colors duration-200 disabled:pointer-events-none disabled:opacity-50 cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50\",\n buttonVariants: {\n ghost: \"border border-transparent text-foreground/70 hover:bg-white/5 hover:text-foreground\",\n outline: \"border border-primary/40 bg-background/40 text-foreground/85 hover:border-primary/70 hover:text-foreground\",\n primary: \"border border-primary bg-primary/90 text-primary-foreground hover:bg-primary\",\n },\n surface: \"border border-white/10 bg-background/85 backdrop-blur-md\",\n overlay: \"bg-black/70 backdrop-blur-sm\",\n codeBlock:\n \"rounded-sm border border-white/10 bg-black/40 px-2.5 py-2 font-mono text-[11px] leading-5 overflow-x-auto\",\n codeMuted: \"text-foreground/35\",\n kbd: \"font-mono text-[10px] px-1.5 py-0.5 border border-white/20 bg-white/5 rounded-sm text-foreground/80\",\n spotlight: \"rounded-sm ring-2 ring-primary/80 transition-all duration-300\",\n muted: \"text-foreground/40\",\n};\n","\"use client\";\r\n\r\nimport { useEffect, useState, type ButtonHTMLAttributes, type ReactNode } from \"react\";\r\nimport { createPortal } from \"react-dom\";\r\nimport { cn } from \"./cn\";\r\nimport { flattenChapters } from \"./flatten\";\r\nimport { defaultTheme, type StepwiseTheme } from \"./theme\";\r\nimport { useFocusTrap } from \"./use-focus-trap\";\r\nimport type { Chapter, ShortcutItem, StepTone, TourStepInput } from \"./types\";\n\n// Back-compat re-exports: the default theme maps, injectable per component.\nexport const TONE_SEGMENT_CLASS = defaultTheme.toneSegment;\nexport const TONE_CHIP_CLASS = defaultTheme.toneChip;\n\n// ─── Internal button (replaces external UI-kit imports) ─────────────────────\n\nconst BTN_BASE = defaultTheme.buttonBase;\nconst BTN_GHOST = defaultTheme.buttonVariants.ghost;\nconst BTN_OUTLINE = defaultTheme.buttonVariants.outline;\nconst BTN_PRIMARY = defaultTheme.buttonVariants.primary;\n\nfunction StepButton({\n variant = \"ghost\",\n className,\n ...props\n}: ButtonHTMLAttributes<HTMLButtonElement> & { variant?: \"ghost\" | \"outline\" | \"primary\" }) {\n const variantClass =\n variant === \"outline\" ? BTN_OUTLINE : variant === \"primary\" ? BTN_PRIMARY : BTN_GHOST;\n return <button type=\"button\" {...props} className={cn(BTN_BASE, variantClass, className)} />;\n}\n\n// ─── Code block ──────────────────────────────────────────────────────────────\r\n\r\nexport function CodeBlock({\r\n lines,\r\n theme = defaultTheme,\r\n className,\r\n}: {\r\n lines: string[];\r\n theme?: StepwiseTheme;\r\n className?: string;\r\n}) {\r\n return (\r\n <div className={cn(theme.codeBlock, className)}>\r\n {lines.map((line, i) => {\r\n const commentStart = line.indexOf(\"//\");\r\n if (commentStart === 0) {\r\n return (\r\n <div key={i} className={cn(\"whitespace-pre\", theme.codeMuted)}>\r\n {line}\r\n </div>\r\n );\r\n }\r\n if (commentStart > 0) {\r\n return (\r\n <div key={i} className=\"whitespace-pre\">\r\n <span className=\"text-foreground/85\">{line.slice(0, commentStart)}</span>\r\n <span className={theme.codeMuted}>{line.slice(commentStart)}</span>\r\n </div>\r\n );\r\n }\r\n return (\r\n <div key={i} className=\"whitespace-pre text-foreground/85\">\r\n {line}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n );\r\n}\n\n// ─── Scrubber + player bar ───────────────────────────────────────────────────\n\nexport interface ScrubberLabels {\n /** aria-label for the slider. */\n scrubber?: string;\n /** aria-valuetext for the current position. Receives the frame index. */\n frame?: (i: number) => string;\n}\n\nexport function StepScrubber({\r\n count,\r\n index,\r\n toneAt,\r\n titleAt,\r\n onSeek,\r\n emptyHint,\r\n className,\r\n theme = defaultTheme,\r\n labels,\r\n groupOf,\r\n}: {\r\n count: number;\r\n index: number;\r\n toneAt?: (i: number) => StepTone;\r\n titleAt?: (i: number) => string;\r\n onSeek: (i: number) => void;\r\n emptyHint?: string;\r\n className?: string;\r\n theme?: StepwiseTheme;\r\n labels?: ScrubberLabels;\r\n /**\r\n * Groups consecutive segments into one proportional wrapper — a chapter\r\n * with sub-chapters spans the width of its whole subtree and only the\r\n * active inner segment fills, so a chapter reads as \"halfway\" while its\r\n * children play. Segments must be group-contiguous (flattenChapters order).\r\n */\r\n groupOf?: (i: number) => number;\r\n}) {\n const onKey = (e: React.KeyboardEvent) => {\n if (count === 0) return;\n if (e.key === \"ArrowRight\" || e.key === \"ArrowUp\") {\n e.preventDefault();\n e.stopPropagation();\n onSeek(Math.min(count - 1, index + 1));\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n onSeek(Math.max(0, index - 1));\n } else if (e.key === \"Home\") {\n e.preventDefault();\n e.stopPropagation();\n onSeek(0);\n } else if (e.key === \"End\") {\n e.preventDefault();\n e.stopPropagation();\n onSeek(count - 1);\n }\n };\n\n if (count === 0) {\r\n return (\r\n <div className={cn(\"flex-1 flex items-center min-w-0\", className)}>\r\n {emptyHint && <span className={cn(\"text-xs font-mono px-2\", theme.muted)}>{emptyHint}</span>}\r\n </div>\r\n );\r\n }\n\n const valueText = labels?.frame ? labels.frame(index) : (titleAt?.(index) ?? `frame ${index + 1} of ${count}`);\r\n\r\n const segment = (i: number) => (\r\n <div\r\n key={i}\r\n aria-hidden=\"true\"\r\n title={titleAt ? titleAt(i) : `frame ${i + 1}`}\r\n onClick={() => onSeek(i)}\r\n className={cn(\r\n \"h-3.5 flex-1 min-w-[3px] rounded-[2px] transition-all cursor-pointer\",\r\n theme.toneSegment[toneAt?.(i) ?? \"neutral\"],\r\n i === index && \"ring-2 ring-primary scale-y-150\"\r\n )}\r\n />\r\n );\r\n\r\n // Grouped mode: consecutive segments sharing a groupOf value render inside\r\n // one wrapper whose flex-grow equals its unit count — subtrees occupy\r\n // proportional width and the group fills segment by segment.\r\n let rows: ReactNode;\r\n if (groupOf) {\r\n const groups: number[][] = [];\r\n for (let i = 0; i < count; i++) {\r\n const g = groupOf(i);\r\n const lastGroup = groups[groups.length - 1];\r\n if (lastGroup && groupOf(lastGroup[0]) === g) lastGroup.push(i);\r\n else groups.push([i]);\r\n }\r\n rows = groups.map((units, gi) => (\r\n <div\r\n key={gi}\r\n aria-hidden=\"true\"\r\n className=\"flex-1 min-w-[3px] flex gap-[2px] items-center\"\r\n style={{ flexGrow: units.length }}\r\n >\r\n {units.map(segment)}\r\n </div>\r\n ));\r\n } else {\r\n rows = Array.from({ length: count }, (_, i) => segment(i));\r\n }\r\n\r\n return (\r\n <div\r\n role=\"slider\"\r\n tabIndex={0}\r\n aria-label={labels?.scrubber ?? \"Frames\"}\r\n aria-valuemin={1}\r\n aria-valuemax={count}\r\n aria-valuenow={index + 1}\r\n aria-valuetext={valueText}\r\n aria-orientation=\"horizontal\"\r\n onKeyDown={onKey}\r\n className={cn(\r\n \"flex-1 flex items-center gap-[3px] min-w-0 cursor-pointer outline-none focus-visible:ring-2 focus-visible:ring-primary/60 rounded-sm\",\r\n className\r\n )}\r\n >\r\n {rows}\r\n </div>\r\n );\r\n}\n\nexport function PlayerBar({\n player,\n toneAt,\r\n titleAt,\r\n leading,\r\n onEmpty,\r\n emptyHint,\r\n className,\r\n theme = defaultTheme,\r\n groupOf,\r\n labels,\r\n}: {\r\n player: {\r\n total: number;\r\n index: number;\r\n playing: boolean;\r\n atEnd: boolean;\r\n next: (onEmpty?: () => void) => void;\r\n prev: () => void;\r\n toggle: (onEmpty?: () => void) => void;\r\n seek: (frame: number) => void;\n };\n toneAt?: (i: number) => StepTone;\r\n titleAt?: (i: number) => string;\r\n leading?: ReactNode;\r\n /** Fired when the user plays/steps with no timeline loaded. */\r\n onEmpty?: () => void;\r\n emptyHint?: string;\r\n className?: string;\r\n theme?: StepwiseTheme;\r\n /**\r\n * Forwarded to the scrubber — group consecutive segments into one\r\n * proportional wrapper (see StepScrubber).\r\n */\r\n groupOf?: (i: number) => number;\r\n labels?: {\r\n previous?: string;\r\n play?: string;\r\n pause?: string;\r\n replay?: string;\r\n next?: string;\r\n };\r\n}) {\n const L = {\n previous: labels?.previous ?? \"Previous step\",\n play: labels?.play ?? \"Play\",\n pause: labels?.pause ?? \"Pause\",\n replay: labels?.replay ?? \"Replay\",\n next: labels?.next ?? \"Next step\",\n };\n const playLabel = player.playing ? L.pause : player.total > 0 && player.atEnd ? L.replay : L.play;\n\n return (\n <div className={cn(\"flex items-center gap-2 p-2\", className)}>\n {leading}\n <StepButton variant=\"ghost\" onClick={() => player.prev()} className=\"h-7 px-2 text-xs\" aria-label={L.previous}>\n ←\n </StepButton>\n <StepButton variant=\"outline\" onClick={() => player.toggle(onEmpty)} className=\"h-7 px-3.5 text-[11px]\">\n {playLabel}\n </StepButton>\n <StepButton variant=\"ghost\" onClick={() => player.next(onEmpty)} className=\"h-7 px-2 text-xs\" aria-label={L.next}>\n →\n </StepButton>\n <StepScrubber\r\n count={player.total}\r\n index={player.index}\r\n toneAt={toneAt}\r\n titleAt={titleAt}\r\n onSeek={(i) => player.seek(i)}\r\n emptyHint={emptyHint}\r\n theme={theme}\r\n groupOf={groupOf}\r\n />\r\n <span className={cn(\"text-[10px] font-mono w-11 text-right shrink-0\", theme.muted)}>\r\n {player.total > 0 ? `${player.index + 1}/${player.total}` : \"—\"}\r\n </span>\n </div>\n );\n}\n\n// ─── Chapter navigation ──────────────────────────────────────────────────────\n\nexport function ChapterNav({\r\n chapters,\r\n active,\r\n onNavigate,\r\n hint,\r\n className,\r\n theme = defaultTheme,\r\n}: {\r\n chapters: Chapter[];\r\n active: number;\r\n onNavigate: (i: number) => void;\r\n hint?: string;\r\n className?: string;\r\n theme?: StepwiseTheme;\r\n}) {\n const flat = flattenChapters(chapters);\n\n const renderRow = (items: Chapter[], depth: number): ReactNode => {\n const indent = \"— \".repeat(depth);\n return items.map((chapter) => {\n const flatIndex = flat.findIndex((f) => f.chapter.id === chapter.id);\n const isActive = flatIndex === active;\n return (\n <div key={chapter.id} className={cn(\"flex items-center\", depth > 0 && \"gap-1\")}>\n <StepButton\n type=\"button\"\n onClick={() => onNavigate(flatIndex)}\n aria-current={isActive ? \"true\" : undefined}\n title={chapter.hint ?? chapter.label}\n className={cn(\n \"flex items-center gap-1.5 px-2.5 py-1 rounded-sm text-[11px] font-mono border transition-colors cursor-pointer whitespace-nowrap\",\n depth > 0 && \"px-2 text-[10px] border-transparent\",\n isActive\n ? depth === 0\n ? \"border-primary/50 text-primary bg-primary/10\"\n : \"text-primary bg-primary/5\"\n : depth === 0\n ? \"border-transparent text-foreground/50 hover:text-foreground hover:border-white/15\"\n : \"text-foreground/45 hover:text-foreground\"\n )}\n >\n {depth === 0 && chapter.numbered !== false && (\n <span className={cn(\"text-[9px]\", isActive ? \"text-primary/80\" : \"text-foreground/30\")}>\n {String(flatIndex + 1).padStart(2, \"0\")}\n </span>\n )}\n {depth > 0 && <span className=\"text-foreground/25\">{indent}</span>}\n {chapter.label}\r\n </StepButton>\n {chapter.children && chapter.children.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-1\">{renderRow(chapter.children, depth + 1)}</div>\n )}\n </div>\n );\n });\n };\n\n return (\r\n <nav\r\n aria-label=\"Chapters\"\r\n className={cn(\r\n \"sticky top-20 md:top-24 z-30 rounded-sm shadow-[0_8px_24px_rgba(0,0,0,0.35)]\",\r\n theme.surface,\r\n className\r\n )}\r\n >\r\n <div className=\"p-1.5\">\r\n <div className=\"flex items-center gap-1 overflow-x-auto\">\r\n <span className={cn(\"shrink-0 px-2 text-[9px] font-mono uppercase tracking-widest\", theme.muted)}>\r\n Chapters\r\n </span>\r\n {renderRow(chapters, 0)}\r\n </div>\r\n {hint && (\r\n <div className=\"flex justify-end px-2 pt-1.5\">\r\n <span className={cn(\"text-[10px] font-mono hidden md:inline\", theme.muted)}>{hint}</span>\r\n </div>\r\n )}\r\n </div>\r\n </nav>\r\n );\r\n}\n\n// ─── Lesson pager (cross-page chapter navigation) ────────────────────────────\n\nexport function LessonPager({\n prev,\n next,\n onNavigate,\n className,\n labels,\n}: {\n prev?: { label: string; hint?: string };\n next?: { label: string; hint?: string };\n onNavigate: (dir: \"prev\" | \"next\") => void;\n className?: string;\n labels?: { previous?: string; next?: string };\n}) {\n return (\n <div className={cn(\"flex items-center gap-2\", className)}>\n <StepButton\r\n variant=\"outline\"\r\n onClick={() => onNavigate(\"prev\")}\r\n disabled={!prev}\n title={prev?.hint ?? prev?.label}\n className=\"h-9 px-3 text-[11px]\"\n aria-label={prev ? `${labels?.previous ?? \"Previous lesson\"}: ${prev.label}` : \"No previous lesson\"}\n >\n ← {prev?.label ?? \"—\"}\n </StepButton>\n <StepButton\r\n variant=\"outline\"\r\n onClick={() => onNavigate(\"next\")}\r\n disabled={!next}\n title={next?.hint ?? next?.label}\n className=\"h-9 px-3 text-[11px] ml-auto\"\n aria-label={next ? `${labels?.next ?? \"Next lesson\"}: ${next.label}` : \"No next lesson\"}\n >\n {next?.label ?? \"—\"} →\n </StepButton>\n </div>\n );\n}\n\n// ─── Guided tour ─────────────────────────────────────────────────────────────\n\nexport function TourSpotlight({\r\n target,\r\n theme = defaultTheme,\r\n}: {\r\n target: string | null;\r\n theme?: StepwiseTheme;\r\n}) {\n const [rect, setRect] = useState<DOMRect | null>(null);\n\n useEffect(() => {\n if (!target) {\n setRect(null);\n return;\n }\n // The target may not exist yet (conditional rendering downstream) — poll\n // until it appears, then track it frame by frame.\n let el: Element | null = null;\n let scrolled = false;\n let raf = 0;\n let last = \"\";\n const tick = () => {\r\n if (!el) {\r\n // Resolve by DOM id first (most common), then by data-tour attribute.\r\n el = document.getElementById(target) ?? document.querySelector(`[data-tour=\"${target}\"]`);\r\n if (el && !scrolled) {\r\n scrolled = true;\r\n el.scrollIntoView({ block: \"center\", behavior: \"smooth\", inline: \"nearest\" });\r\n }\r\n }\n if (el) {\n const r = el.getBoundingClientRect();\n const key = [r.top, r.left, r.width, r.height].map((n) => Math.round(n)).join(\",\");\n if (key !== last) {\n last = key;\n setRect(r);\n }\n }\n raf = requestAnimationFrame(tick);\n };\n raf = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(raf);\n }, [target]);\n\n if (!rect) return null;\r\n const pad = 6;\r\n return (\r\n <div className=\"fixed inset-0 z-40 pointer-events-none\">\r\n <div\r\n className={cn(\"absolute\", theme.spotlight)}\r\n style={{\r\n top: rect.top - pad,\r\n left: rect.left - pad,\r\n width: rect.width + pad * 2,\r\n height: rect.height + pad * 2,\r\n boxShadow: \"0 0 0 9999px rgba(0,0,0,0.55)\",\r\n }}\r\n />\r\n </div>\r\n );\r\n}\n\nexport function TourCard({\r\n step,\r\n index,\r\n total,\r\n onNext,\r\n onBack,\r\n onEnd,\r\n labels,\r\n className,\r\n theme = defaultTheme,\r\n nextDisabled = false,\r\n}: {\r\n step: TourStepInput;\r\n index: number;\r\n total: number;\r\n onNext: () => void;\r\n onBack: () => void;\r\n onEnd: () => void;\r\n labels?: {\r\n title?: string;\r\n back?: string;\r\n next?: string;\r\n finish?: string;\r\n end?: string;\r\n };\r\n className?: string;\r\n theme?: StepwiseTheme;\r\n /** Disable the primary (Next/Finish) button — pair with tour.blocked. */\r\n nextDisabled?: boolean;\r\n}) {\r\n const L = {\r\n title: labels?.title ?? \"Guided tour\",\r\n back: labels?.back ?? \"Back\",\r\n next: labels?.next ?? \"Next\",\r\n finish: labels?.finish ?? \"Finish\",\r\n end: labels?.end ?? \"End tour\",\r\n };\r\n const trapRef = useFocusTrap(true);\r\n\r\n return (\r\n <div\r\n ref={trapRef}\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-label={`${L.title} · ${index + 1}/${total}`}\r\n tabIndex={-1}\r\n className={cn(\r\n \"fixed bottom-6 left-1/2 -translate-x-1/2 z-50 w-[min(92vw,26rem)] rounded-sm p-4 outline-none\",\r\n theme.surface,\r\n \"border-primary/30 bg-background/95 shadow-2xl\",\r\n className\r\n )}\r\n >\r\n <div className=\"flex items-center justify-between mb-2\">\r\n <span className=\"text-[10px] font-mono uppercase tracking-widest text-primary/70\">\r\n {L.title} · {index + 1}/{total}\r\n </span>\r\n <StepButton\r\n type=\"button\"\r\n onClick={onEnd}\r\n aria-label={L.end}\r\n className=\"text-foreground/40 hover:text-foreground cursor-pointer leading-none\"\r\n >\r\n ×\r\n </StepButton>\r\n </div>\r\n <p className=\"text-sm font-bold text-foreground/95 mb-1.5\">{step.title}</p>\r\n <div className=\"text-[12px] font-mono text-foreground/70 leading-relaxed\">{step.body}</div>\r\n {step.waitHint && <p className=\"text-[11px] font-mono text-accent mt-2 animate-pulse\">{step.waitHint}</p>}\r\n <div className=\"flex items-center gap-2 mt-3 pt-3 border-t border-white/10\">\r\n <StepButton variant=\"outline\" onClick={onBack} disabled={index === 0} className=\"h-7 px-3 text-[11px]\">\r\n {L.back}\r\n </StepButton>\r\n <StepButton\r\n variant=\"primary\"\r\n onClick={onNext}\r\n disabled={nextDisabled}\r\n className=\"h-7 px-4 text-[11px] ml-auto\"\r\n >\r\n {index === total - 1 ? L.finish : L.next}\r\n </StepButton>\r\n </div>\r\n </div>\r\n );\r\n}\n\n// ─── Shortcuts dialog ────────────────────────────────────────────────────────\r\n\r\nexport function ShortcutsDialog({\r\n open,\r\n onClose,\r\n items,\r\n title = \"Keyboard shortcuts\",\r\n className,\r\n theme = defaultTheme,\r\n}: {\r\n open: boolean;\r\n onClose: () => void;\r\n items: ShortcutItem[];\r\n title?: string;\r\n className?: string;\r\n theme?: StepwiseTheme;\r\n}) {\r\n // SSR-safe portal: render only after mount (invariant: no portals during\r\n // SSR), and hooks run unconditionally before the early return.\r\n const [mounted, setMounted] = useState(false);\r\n const trapRef = useFocusTrap(open);\r\n\r\n useEffect(() => setMounted(true), []);\r\n\r\n // Escape closes from anywhere; Tab containment comes from the focus trap.\r\n useEffect(() => {\r\n if (!open) return;\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\") onClose();\r\n };\r\n document.addEventListener(\"keydown\", onKey);\r\n return () => document.removeEventListener(\"keydown\", onKey);\r\n }, [open, onClose]);\r\n\r\n if (!open || !mounted) return null;\r\n\r\n return createPortal(\r\n <div\r\n className={cn(\"fixed inset-0 z-50 flex items-center justify-center p-4\", theme.overlay, className)}\r\n onClick={onClose}\r\n >\r\n <div\r\n ref={trapRef}\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-label={title}\r\n tabIndex={-1}\r\n onClick={(e) => e.stopPropagation()}\r\n className={cn(\r\n \"w-full max-w-md rounded-sm p-5 shadow-2xl outline-none\",\r\n theme.surface,\r\n \"border-white/15 bg-card\"\r\n )}\r\n >\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h3 className=\"text-lg text-primary\">{title}</h3>\r\n <StepButton\r\n type=\"button\"\r\n onClick={onClose}\r\n aria-label=\"Close shortcuts\"\r\n className=\"text-foreground/40 hover:text-foreground cursor-pointer leading-none text-lg\"\r\n >\r\n ×\r\n </StepButton>\r\n </div>\r\n <dl className=\"space-y-2\">\r\n {items.map((s) => (\r\n <div key={s.keys} className=\"flex items-center justify-between gap-4\">\r\n <dt>\r\n <kbd className={theme.kbd}>{s.keys}</kbd>\r\n </dt>\r\n <dd className=\"font-mono text-[11px] text-foreground/60 text-right\">{s.action}</dd>\r\n </div>\r\n ))}\r\n </dl>\r\n </div>\r\n </div>,\r\n document.body\r\n );\r\n}\n\r\n\r\n\r\n\r\n\r\n"],"mappings":"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","names":["useCallback","useEffect","useMemo","useRef","useState","useState","useRef","useCallback","useEffect","next","useMemo","useCallback","useEffect","useRef","useState","useState","useRef","useCallback","start","useEffect","useCallback","useEffect","useMemo","useRef","useState","depth","useState","useMemo","useRef","useEffect","flat","useCallback","useEffect","useRef","useCallback","useEffect","useMemo","useRef","useState","useEffect","useRef","useEffect","useState","useCallback","useEffect","useMemo","useRef","useState","useMemo","useState","useRef","useCallback","useEffect","useEffect","useState","createPortal","jsx","jsxs","useState","useEffect","createPortal"]}
1
+ {"version":3,"sources":["../src/use-steps.ts","../src/use-step-player.ts","../src/use-trace.ts","../src/create-trace.ts","../src/use-synced-tracks.ts","../src/use-lesson-stream.ts","../src/use-prefers-reduced-motion.ts","../src/use-guided-tour.ts","../src/use-chapters.ts","../src/flatten.ts","../src/use-global-keys.ts","../src/use-discoveries.ts","../src/use-focus-trap.ts","../src/glossary.tsx","../src/cn.ts","../src/theme.ts","../src/components.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nexport interface UseStepsOptions {\n /** Initial focus. Clamped. Defaults to 0. */\n initialIndex?: number;\n /** Fired whenever the focus index changes. */\n onChange?: (index: number) => void;\n}\n\nexport interface StepsCore {\n /** Number of steps in the sequence. */\n count: number;\n /** Clamped focus: 0..count-1, or -1 when the sequence is empty. */\n index: number;\n atStart: boolean;\n atEnd: boolean;\n canNext: boolean;\n canPrev: boolean;\n /** Clamped jump. No-op on an empty sequence. */\n go: (index: number) => void;\n /** Clamped forward step. */\n next: () => void;\n /** Clamped backward step. */\n prev: () => void;\n /** Jump to the first step. */\n first: () => void;\n}\n\n/**\n * The core primitive every stepwise machine composes: a clamped cursor over an\n * ordered sequence. Frames in a trace, chapters in a lesson, lessons in a\n * notebook, and tour steps are all the same thing at this layer — timers,\n * effects, and scroll-tracking are policies layered on top by consumers.\n *\n * All callbacks are referentially stable; `count` may change dynamically (a\n * new timeline, a mounted window) and the cursor re-clamps automatically.\n */\nexport function useSteps<T>(items: readonly T[] | number, opts?: UseStepsOptions): StepsCore {\n const count = typeof items === \"number\" ? items : items.length;\n const countRef = useRef(count);\n countRef.current = count;\n const onChangeRef = useRef(opts?.onChange);\n onChangeRef.current = opts?.onChange;\n\n const [cursor, setCursor] = useState(() => {\n const initial = opts?.initialIndex ?? 0;\n return count === 0 ? -1 : Math.max(0, Math.min(initial, count - 1));\n });\n\n const index = count === 0 ? -1 : Math.max(0, Math.min(cursor, count - 1));\n const indexRef = useRef(index);\n indexRef.current = index;\n\n // Re-clamp when the sequence shrinks.\n useEffect(() => {\n if (count === 0) {\n if (cursor !== -1) setCursor(-1);\n } else if (cursor < 0 || cursor > count - 1) {\n setCursor(Math.max(0, Math.min(cursor, count - 1)));\n }\n }, [count, cursor]);\n\n const go = useCallback((i: number) => {\n const c = countRef.current;\n if (c === 0) return;\n const clamped = Math.max(0, Math.min(i, c - 1));\n if (clamped === indexRef.current) return;\n indexRef.current = clamped;\n setCursor(clamped);\n onChangeRef.current?.(clamped);\n }, []);\n\n const next = useCallback(() => {\n go(indexRef.current + 1);\n }, [go]);\n\n const prev = useCallback(() => {\n go(indexRef.current - 1);\n }, [go]);\n\n const first = useCallback(() => {\n go(0);\n }, [go]);\n\n return useMemo(\n () => ({\n count,\n index,\n atStart: index <= 0,\n atEnd: count > 0 && index >= count - 1,\n canNext: count > 0 && index < count - 1,\n canPrev: count > 0 && index > 0,\n go,\n next,\n prev,\n first,\n }),\n [count, index, go, next, prev, first]\n );\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useSteps } from \"./use-steps\";\nimport type { PlayerEngine } from \"./types\";\n\nexport interface StepPlayerOptions {\n /** Number of frames in the current timeline (0 = no timeline loaded). */\n total: number;\n /** Delay per frame at 1× speed (built-in timer engine). */\n baseDelayMs?: number;\n /** Start playing immediately (used when a timeline exists on first render). */\n autoPlay?: boolean;\n /**\n * Alternate frame source (GSAP timeline, scroll progress, …). Replaces the\n * built-in timer. Memoize the engine per timeline — identity changes\n * reconnect it.\n */\n engine?: PlayerEngine;\n /**\n * Deep-link the current frame into the URL hash (`#<key>=<index>`), opt-in.\n * The initial hash is honored once on mount. Only this key is written —\n * other `&`-separated hash parts (anchors, other players' keys) are kept.\n */\n syncHash?: string;\n /**\n * Fired once when playback runs to the final frame on its own (built-in\n * timer or engine `onEnd`). Cleared by any cursor movement (seek/step/\n * reset/new timeline) — the next full playthrough fires it again.\n */\n onEnd?: () => void;\n /**\n * Honor `prefers-reduced-motion: reduce` by not auto-advancing: with\n * `autoPlay`, the player still lands on frame 0 but stays paused until the\n * user presses play. Default true.\n */\n respectReducedMotion?: boolean;\n}\n\nexport interface StepPlayer {\n /** Total frames in the current timeline. */\n total: number;\n /** Raw frame counter; -1 means \"no timeline / before first frame\". */\n frame: number;\n /** Frame clamped into [0, total-1]; -1 when there is nothing to show. */\n index: number;\n playing: boolean;\n speed: number;\n /** Position flag: the cursor is parked on the final frame (seek counts too). */\n atEnd: boolean;\n /**\n * Completion state: playback ran to the final frame on its own and nothing\n * has moved the cursor since. Unlike `atEnd`, a seek to the last frame does\n * not set it — `toggle()` at `ended` replays from frame 0.\n */\n ended: boolean;\n /** Jump to frame 0 and play. */\n start: () => void;\n /** Clear the player (frame = -1, paused). */\n reset: () => void;\n seek: (frame: number) => void;\n /** Step forward; pauses first. `onEmpty` fires when there is no timeline. */\n next: (onEmpty?: () => void) => void;\n /** Step backward; pauses first. */\n prev: () => void;\n /** Play/pause; replays from 0 at the end. `onEmpty` fires when there is no timeline. */\n toggle: (onEmpty?: () => void) => void;\n setPlaying: (playing: boolean) => void;\n setSpeed: (speed: number) => void;\n}\n\nexport function useStepPlayer({\n total,\n baseDelayMs = 900,\n autoPlay = false,\n engine,\n syncHash,\n onEnd,\n respectReducedMotion = true,\n}: StepPlayerOptions): StepPlayer {\n const core = useSteps(total);\n // useSteps' movement callbacks are referentially stable; depend on them\n // alone, never on `core` itself (its identity churns with the index).\n const { go, next: coreNext, prev: corePrev, first } = core;\n const [started, setStarted] = useState(autoPlay && total > 0);\n const [playing, setPlaying] = useState(autoPlay && total > 0);\n const [speed, setSpeed] = useState(1);\n const [ended, setEnded] = useState(false);\n const endedRef = useRef(false);\n const onEndRef = useRef(onEnd);\n onEndRef.current = onEnd;\n\n // Completion transitions are idempotent: adapters may repeat `onEnd`\n // (the port allows it); the option callback fires once per run.\n const markEnded = useCallback(() => {\n if (endedRef.current) return;\n endedRef.current = true;\n setEnded(true);\n onEndRef.current?.();\n }, []);\n\n const clearEnded = useCallback(() => {\n if (!endedRef.current) return;\n endedRef.current = false;\n setEnded(false);\n }, []);\n\n const index = started && core.index >= 0 ? core.index : -1;\n const atEnd = total > 0 && index >= 0 && index >= total - 1;\n\n // Live values for the public callbacks — read through refs so every\n // returned function keeps one identity for the player's lifetime.\n const totalRef = useRef(total);\n totalRef.current = total;\n const cursorRef = useRef(core.index);\n cursorRef.current = core.index;\n const playingRef = useRef(playing);\n playingRef.current = playing;\n const atEndRef = useRef(atEnd);\n atEndRef.current = atEnd;\n\n const engineRef = useRef(engine);\n engineRef.current = engine;\n const engineApiRef = useRef<{\n play?(): void;\n pause?(): void;\n seek?(frame: number): void;\n rate?(rate: number): void;\n }>({});\n\n // Engine lifecycle — reconnect only when the engine identity changes\n // (`go` and `markEnded` are stable).\n useEffect(() => {\n if (!engine) return;\n const handle = engine.connect({\n get total() {\n return totalRef.current;\n },\n onFrame: (f) => go(f),\n onEnd: () => {\n markEnded();\n setPlaying(false);\n },\n });\n engineApiRef.current = {\n play: () => handle.play(),\n pause: () => handle.pause(),\n seek: (f) => handle.seek(f),\n rate: (r) => handle.setRate(r),\n };\n return () => {\n engineApiRef.current = {};\n handle.disconnect();\n };\n }, [engine, go, markEnded]);\n\n // Reduced motion: an autoPlay player lands on frame 0, paused. Checked once\n // on mount (before the first timer tick), not tracked live — a preference\n // flip mid-playback shouldn't yank control from the user.\n useEffect(() => {\n if (!respectReducedMotion || !autoPlay) return;\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n if (!window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches) return;\n setPlaying(false);\n engineApiRef.current.pause?.();\n // Mount-only by design.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const start = useCallback(() => {\n setStarted(true);\n setPlaying(true);\n clearEnded();\n first();\n if (engineRef.current) {\n engineApiRef.current.seek?.(0);\n engineApiRef.current.play?.();\n }\n }, [first, clearEnded]);\n\n const reset = useCallback(() => {\n setStarted(false);\n setPlaying(false);\n clearEnded();\n if (engineRef.current) engineApiRef.current.pause?.();\n }, [clearEnded]);\n\n const seek = useCallback(\n (f: number) => {\n const t = totalRef.current;\n if (t === 0) return;\n setStarted(true);\n setPlaying(false);\n clearEnded();\n go(Math.max(0, Math.min(f, t - 1)));\n if (engineRef.current) {\n engineApiRef.current.pause?.();\n engineApiRef.current.seek?.(f);\n }\n },\n [go, clearEnded]\n );\n\n const next = useCallback(\n (onEmpty?: () => void) => {\n setPlaying(false);\n const t = totalRef.current;\n if (t === 0) {\n onEmpty?.();\n return;\n }\n setStarted(true);\n clearEnded();\n const target = Math.min(cursorRef.current + 1, t - 1);\n coreNext();\n if (engineRef.current) {\n engineApiRef.current.pause?.();\n engineApiRef.current.seek?.(target);\n }\n },\n [coreNext, clearEnded]\n );\n\n const prev = useCallback(() => {\n setPlaying(false);\n clearEnded();\n const target = Math.max(0, cursorRef.current - 1);\n corePrev();\n if (engineRef.current) {\n engineApiRef.current.pause?.();\n engineApiRef.current.seek?.(target);\n }\n }, [corePrev, clearEnded]);\n\n const toggle = useCallback(\n (onEmpty?: () => void) => {\n if (totalRef.current === 0) {\n onEmpty?.();\n return;\n }\n if (!playingRef.current && atEndRef.current) {\n start();\n return;\n }\n const nextPlaying = !playingRef.current;\n setPlaying(nextPlaying);\n setStarted(true);\n if (engineRef.current) {\n if (nextPlaying) engineApiRef.current.play?.();\n else engineApiRef.current.pause?.();\n }\n },\n [start]\n );\n\n const changeSpeed = useCallback((s: number) => {\n setSpeed(s);\n if (engineRef.current) engineApiRef.current.rate?.(s);\n }, []);\n\n // A new timeline wipes completion — the next playthrough ends it fresh.\n useEffect(() => {\n clearEnded();\n }, [total, clearEnded]);\n\n // Built-in timer loop — skipped entirely when a custom engine takes over.\n useEffect(() => {\n if (engineRef.current) return;\n if (!playing || !started || total === 0) return;\n if (core.index >= total - 1) {\n markEnded();\n setPlaying(false);\n return;\n }\n const id = setTimeout(() => coreNext(), baseDelayMs / speed);\n return () => clearTimeout(id);\n }, [playing, started, core.index, coreNext, total, speed, baseDelayMs, markEnded]);\n\n // Deep-linking: honor #<key>=<index> on mount and external hash edits only.\n // The hash values the player itself writes are ignored, and readHash never\n // re-runs on render churn (stable deps) — reading a lagging hash during\n // playback would ping-pong the cursor.\n const lastWrittenHash = useRef(\"\");\n const readHash = useCallback(() => {\n if (!syncHash || typeof window === \"undefined\" || total === 0) return;\n const hash = window.location.hash;\n if (hash === lastWrittenHash.current) return;\n const value = readHashParam(hash, syncHash);\n if (value === null || !/^\\d+$/.test(value)) return;\n const f = Number(value);\n if (f < total) {\n setStarted(true);\n go(f);\n }\n }, [syncHash, total, go]);\n\n useEffect(() => {\n readHash();\n const onHashChange = () => readHash();\n window.addEventListener(\"hashchange\", onHashChange);\n return () => window.removeEventListener(\"hashchange\", onHashChange);\n }, [readHash]);\n\n useEffect(() => {\n if (!syncHash || index < 0 || typeof window === \"undefined\") return;\n const next = writeHashParam(window.location.hash, syncHash, String(index));\n if (window.location.hash !== next) {\n lastWrittenHash.current = next;\n window.history.replaceState(null, \"\", next);\n }\n }, [syncHash, index]);\n\n return useMemo(\n () => ({\n total,\n frame: index,\n index,\n playing,\n speed,\n atEnd,\n ended,\n start,\n reset,\n seek,\n next,\n prev,\n toggle,\n setPlaying,\n setSpeed: changeSpeed,\n }),\n [total, index, playing, speed, atEnd, ended, start, reset, seek, next, prev, toggle, changeSpeed]\n );\n}\n\n// ── Hash params ──────────────────────────────────────────────────────────────\n// The fragment is read as `&`-separated parts: `key=value` parts are params,\n// anything else (a plain `#section` anchor) is kept verbatim. The player only\n// ever touches its own key, so it coexists with other hash users. Keys are\n// compared literally — no regex, so any key string is safe.\n\nfunction hashParts(hash: string): string[] {\n const body = hash.startsWith(\"#\") ? hash.slice(1) : hash;\n return body ? body.split(\"&\") : [];\n}\n\n/** Value of `key` in the hash, or null when absent. */\nexport function readHashParam(hash: string, key: string): string | null {\n for (const part of hashParts(hash)) {\n const eq = part.indexOf(\"=\");\n if (eq > 0 && part.slice(0, eq) === key) return part.slice(eq + 1);\n }\n return null;\n}\n\n/** The hash with `key` set to `value` — replaced in place, else appended. */\nexport function writeHashParam(hash: string, key: string, value: string): string {\n const parts = hashParts(hash);\n const pair = `${key}=${value}`;\n const i = parts.findIndex((p) => p.startsWith(`${key}=`));\n if (i >= 0) parts[i] = pair;\n else parts.push(pair);\n return `#${parts.join(\"&\")}`;\n}\n","\"use client\";\n\nimport { useCallback, useMemo, useRef } from \"react\";\nimport { useStepPlayer } from \"./use-step-player\";\nimport type { StepPlayer, StepPlayerOptions } from \"./use-step-player\";\nimport type { StepTone, StepwiseStep } from \"./types\";\n\nexport interface TracePlayer<S extends StepwiseStep> {\n /** The underlying player — pass it to PlayerBar. */\n player: StepPlayer;\n /**\n * The frame to render. Never undefined for a non-empty trace: before the\n * player starts (`player.index === -1`) this is frame 0, not the last one.\n */\n step: S | undefined;\n /** Index of `step` in the trace (0 before start; -1 for an empty trace). */\n frame: number;\n /** Stable `toneAt` for PlayerBar / StepScrubber. */\n toneAt: (i: number) => StepTone;\n /** Stable `titleAt` for PlayerBar / StepScrubber. */\n titleAt: (i: number) => string;\n}\n\n/**\n * A player bound to a concrete trace: the steps array is the timeline, and\n * the hook resolves the frame to render (frame 0 before start — invariant\n * \"index -1 means not started\"), plus scrubber accessors that read the\n * latest steps through a ref. Replaces the per-page\n * `player.index >= 0 ? … : 0` boilerplate.\n *\n * const trace = useTrace(STEPS, { autoPlay: true });\n * <Viz arr={trace.step.arr} />\n * <PlayerBar player={trace.player} toneAt={trace.toneAt} titleAt={trace.titleAt} />\n */\nexport function useTrace<S extends StepwiseStep>(\n steps: readonly S[],\n opts?: Omit<StepPlayerOptions, \"total\">\n): TracePlayer<S> {\n const player = useStepPlayer({ ...opts, total: steps.length });\n const stepsRef = useRef(steps);\n stepsRef.current = steps;\n\n const frame = steps.length === 0 ? -1 : Math.max(0, Math.min(player.index, steps.length - 1));\n const step = frame >= 0 ? steps[frame] : undefined;\n\n const toneAt = useCallback((i: number) => stepsRef.current[i]?.tone ?? \"neutral\", []);\n const titleAt = useCallback((i: number) => stepsRef.current[i]?.label ?? `step ${i + 1}`, []);\n\n return useMemo(() => ({ player, step, frame, toneAt, titleAt }), [player, step, frame, toneAt, titleAt]);\n}\n","import type { StepwiseStep } from \"./types\";\r\n\r\nexport interface TraceBuilder<Data extends object> {\r\n /** Append one frame. Returns the builder, so calls chain. */\r\n step(step: StepwiseStep<Data>): TraceBuilder<Data>;\r\n /** Frames appended so far. */\r\n readonly length: number;\r\n /** The most recently appended frame (handy for \"carry the state forward\"). */\r\n last(): StepwiseStep<Data> | undefined;\r\n /** Snapshot the trace. A fresh array each call — the builder stays usable. */\r\n build(): StepwiseStep<Data>[];\r\n}\r\n\r\n/**\r\n * Typed trace builder. Authors run their algorithm at module scope and record\r\n * frames as they go — no IIFE, no pre-declared `const STEPS = []` that a\r\n * component might read before it is filled (invariant 6):\r\n *\r\n * const t = createTrace<{ arr: number[] }>();\r\n * for (…) t.step({ tone: \"write\", label: \"swap\", arr: [...arr] });\r\n * export const STEPS = t.build();\r\n *\r\n * Pure data — no React, safe on the server.\r\n */\r\nexport function createTrace<Data extends object = Record<never, never>>(): TraceBuilder<Data> {\r\n const frames: StepwiseStep<Data>[] = [];\r\n const builder: TraceBuilder<Data> = {\r\n step(step) {\r\n frames.push(step);\r\n return builder;\r\n },\r\n get length() {\r\n return frames.length;\r\n },\r\n last() {\r\n return frames[frames.length - 1];\r\n },\r\n build() {\r\n return frames.slice();\r\n },\r\n };\r\n return builder;\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useMemo, useRef } from \"react\";\r\nimport { useStepPlayer } from \"./use-step-player\";\r\nimport type { StepPlayer, StepPlayerOptions } from \"./use-step-player\";\r\nimport type { StepTone, StepwiseStep } from \"./types\";\r\n\r\n/** Named traces to play side by side: `{ bubble: stepsA, insertion: stepsB }`. */\r\nexport type Tracks = Record<string, readonly StepwiseStep<object>[]>;\r\n\r\n/**\r\n * Sync-point key for a step. Steps with the same key in two or more tracks\r\n * land on the same aligned frame; `null`/`undefined` marks a free step. The\r\n * n-th occurrence of a key in one track pairs with the n-th in another.\r\n */\r\nexport type TrackKeyFn<T extends Tracks = Tracks> = (\r\n step: T[keyof T][number],\r\n index: number,\r\n track: keyof T & string\r\n) => string | null | undefined;\r\n\r\n/** One track's slot in one aligned frame. */\r\nexport interface AlignedCell {\r\n /** Index into the track's own steps; -1 only for an empty track. */\r\n index: number;\r\n /**\r\n * The track did not advance on this frame: it is holding its last frame\r\n * (finished, or waiting for a sync point), or waiting at frame 0 for its\r\n * first sync point.\r\n */\r\n held: boolean;\r\n}\r\n\r\nexport type AlignedRow<K extends string = string> = Record<K, AlignedCell>;\r\n\r\n/**\r\n * Align several traces into one timeline. Pure — use it directly for server\r\n * rendering or tests; `useSyncedTracks` memoizes it per track identity.\r\n *\r\n * - No `key` (hold): frame i shows step i of every track; a shorter track\r\n * holds its last frame once it runs out. Length = the longest track.\r\n * - With `key`: tracks advance together frame by frame, but a track whose\r\n * next step is a sync point holds until every other track that shares the\r\n * point has reached it, so matching steps share a frame. Keys must occur\r\n * in the same relative order across tracks; where they conflict, that\r\n * frame degrades to lockstep instead of deadlocking.\r\n */\r\nexport function alignTracks<T extends Tracks>(tracks: T, key?: TrackKeyFn<T>): AlignedRow<keyof T & string>[] {\r\n type K = keyof T & string;\r\n const names = Object.keys(tracks) as K[];\r\n const lens = names.map((n) => tracks[n].length);\r\n const rows: AlignedRow<K>[] = [];\r\n const holdCell = (len: number, at: number): AlignedCell => ({ index: len === 0 ? -1 : Math.min(at, len - 1), held: true });\r\n\r\n if (!key) {\r\n const length = Math.max(0, ...lens);\r\n for (let i = 0; i < length; i++) {\r\n const row = {} as AlignedRow<K>;\r\n names.forEach((n, t) => {\r\n row[n] = i < lens[t] ? { index: i, held: false } : holdCell(lens[t], i);\r\n });\r\n rows.push(row);\r\n }\r\n return rows;\r\n }\r\n\r\n // Occurrence-qualified keys: \"k\\0n\" is the n-th \"k\" in that track.\r\n const keyed = names.map((n) =>\r\n tracks[n].map((step, i) => {\r\n const k = key(step as T[keyof T][number], i, n);\r\n return k == null ? null : k;\r\n })\r\n );\r\n const qualified = keyed.map((ks) => {\r\n const seen = new Map<string, number>();\r\n return ks.map((k) => {\r\n if (k === null) return null;\r\n const n = seen.get(k) ?? 0;\r\n seen.set(k, n + 1);\r\n return `${k}\\u0000${n}`;\r\n });\r\n });\r\n // Sync point → position in each track that has it (only keys in ≥2 tracks).\r\n const where = new Map<string, Map<number, number>>();\r\n qualified.forEach((ks, t) =>\r\n ks.forEach((k, i) => {\r\n if (k === null) return;\r\n let m = where.get(k);\r\n if (!m) where.set(k, (m = new Map()));\r\n m.set(t, i);\r\n })\r\n );\r\n for (const [k, m] of where) if (m.size < 2) where.delete(k);\r\n\r\n const pos = names.map(() => 0);\r\n while (pos.some((p, t) => p < lens[t])) {\r\n const live = names.map((_, t) => pos[t] < lens[t]);\r\n const blocked = names.map((_, t) => {\r\n if (!live[t]) return false;\r\n const k = qualified[t][pos[t]];\r\n const m = k === null ? undefined : where.get(k);\r\n if (!m) return false;\r\n for (const [u, at] of m) if (u !== t && at > pos[u]) return true;\r\n return false;\r\n });\r\n const anyFree = live.some((l, t) => l && !blocked[t]);\r\n const row = {} as AlignedRow<K>;\r\n names.forEach((n, t) => {\r\n if (live[t] && (!blocked[t] || !anyFree)) {\r\n row[n] = { index: pos[t], held: false };\r\n pos[t]++;\r\n } else {\r\n row[n] = holdCell(lens[t], Math.max(0, pos[t] - 1));\r\n }\r\n });\r\n rows.push(row);\r\n }\r\n return rows;\r\n}\r\n\r\nexport interface TrackView<S> {\r\n /** The step to render for this track (undefined only for an empty track). */\r\n step: S | undefined;\r\n /** Index into the track's own steps; -1 for an empty track. */\r\n index: number;\r\n /** The track did not advance on this frame (see `AlignedCell.held`). */\r\n held: boolean;\r\n /** The track is on its final step. */\r\n done: boolean;\r\n /** Length of the track's own trace. */\r\n length: number;\r\n}\r\n\r\nexport interface SyncedTracksOptions<T extends Tracks = Tracks> extends Omit<StepPlayerOptions, \"total\"> {\r\n /**\r\n * Sync-point alignment (see `alignTracks`). Omit to hold shorter tracks on\r\n * their last frame. Read when the tracks change — pass the same tracks to\r\n * keep the alignment memoized; an inline function is fine.\r\n */\r\n key?: TrackKeyFn<T>;\r\n}\r\n\r\nexport interface SyncedTracks<T extends Tracks> {\r\n /** One player over the aligned timeline — pass it to PlayerBar. */\r\n player: StepPlayer;\r\n /** Aligned frame to render: 0 before the player starts, -1 when all tracks are empty. */\r\n frame: number;\r\n /** Number of aligned frames. */\r\n total: number;\r\n /** Per-track view of `frame`. */\r\n tracks: { [K in keyof T]: TrackView<T[K][number]> };\r\n /** The full alignment table (stable while the tracks are). */\r\n rows: readonly AlignedRow<keyof T & string>[];\r\n /** Stable scrubber accessors: the most severe tone among tracks that moved. */\r\n toneAt: (i: number) => StepTone;\r\n /** Stable scrubber accessor: `track: label` for every track that moved. */\r\n titleAt: (i: number) => string;\r\n}\r\n\r\nconst TONE_RANK: StepTone[] = [\"bad\", \"good\", \"write\", \"accent\", \"neutral\", \"idle\"];\r\n\r\n/**\r\n * Comparison mode: several traces of the same input (two engines, two\r\n * algorithms) under ONE player. The cursor walks the aligned timeline from\r\n * `alignTracks`; each track resolves its own step, so payload types stay\r\n * per-track. Like `useTrace`, frame 0 renders before playback starts.\r\n *\r\n * const cmp = useSyncedTracks({ bubble: BUBBLE, insertion: INSERTION }, { autoPlay: true });\r\n * <Lane step={cmp.tracks.bubble.step} held={cmp.tracks.bubble.held} />\r\n * <PlayerBar player={cmp.player} toneAt={cmp.toneAt} titleAt={cmp.titleAt} />\r\n */\r\nexport function useSyncedTracks<T extends Tracks>(tracks: T, opts?: SyncedTracksOptions<T>): SyncedTracks<T> {\r\n const { key, ...playerOpts } = opts ?? {};\r\n const keyRef = useRef(key);\r\n keyRef.current = key;\r\n\r\n // Shallow memo over the track arrays: `{ a, b }` is a fresh object every\r\n // render, but the arrays inside are what matter.\r\n const cache = useRef<{ names: string[]; arrays: unknown[]; keyed: boolean; rows: AlignedRow[] } | null>(null);\r\n const names = Object.keys(tracks);\r\n const arrays = names.map((n) => tracks[n]);\r\n const c = cache.current;\r\n if (\r\n !c ||\r\n c.keyed !== !!key ||\r\n c.names.length !== names.length ||\r\n names.some((n, i) => c.names[i] !== n || c.arrays[i] !== arrays[i])\r\n ) {\r\n cache.current = { names, arrays, keyed: !!key, rows: alignTracks(tracks, keyRef.current) };\r\n }\r\n const rows = cache.current!.rows as AlignedRow<keyof T & string>[];\r\n\r\n const player = useStepPlayer({ ...playerOpts, total: rows.length });\r\n\r\n const tracksRef = useRef(tracks);\r\n tracksRef.current = tracks;\r\n const rowsRef = useRef(rows);\r\n rowsRef.current = rows;\r\n\r\n const frame = rows.length === 0 ? -1 : Math.max(0, Math.min(player.index, rows.length - 1));\r\n const row = frame >= 0 ? rows[frame] : undefined;\r\n\r\n // Per-track view of the frame. `aligned` changes identity exactly when a\r\n // track array does, so consumers can depend on `tracks`.\r\n const aligned = cache.current!;\r\n const view = useMemo(() => {\r\n const out = {} as { [K in keyof T]: TrackView<T[K][number]> };\r\n aligned.names.forEach((n, t) => {\r\n const list = aligned.arrays[t] as readonly StepwiseStep<object>[];\r\n const cell = row?.[n as keyof T & string];\r\n const index = cell ? cell.index : list.length === 0 ? -1 : 0;\r\n out[n as keyof T] = {\r\n step: index >= 0 ? (list[index] as T[keyof T][number]) : undefined,\r\n index,\r\n held: cell?.held ?? false,\r\n done: list.length > 0 && index === list.length - 1,\r\n length: list.length,\r\n };\r\n });\r\n return out;\r\n }, [aligned, row]);\r\n\r\n const moved = useCallback((i: number) => {\r\n const r = rowsRef.current[i];\r\n if (!r) return [];\r\n return Object.keys(r)\r\n .filter((n) => !r[n as keyof typeof r].held)\r\n .map((n) => ({ name: n, step: tracksRef.current[n]?.[r[n as keyof typeof r].index] }))\r\n .filter((m): m is { name: string; step: StepwiseStep<object> } => !!m.step);\r\n }, []);\r\n\r\n const toneAt = useCallback(\r\n (i: number): StepTone => {\r\n const tones = moved(i).map((m) => m.step.tone);\r\n return TONE_RANK.find((t) => tones.includes(t)) ?? \"neutral\";\r\n },\r\n [moved]\r\n );\r\n const titleAt = useCallback(\r\n (i: number) => {\r\n const parts = moved(i).map((m) => `${m.name}: ${m.step.label}`);\r\n return parts.length ? parts.join(\" · \") : `frame ${i + 1}`;\r\n },\r\n [moved]\r\n );\r\n\r\n return useMemo(\r\n () => ({ player, frame, total: rows.length, tracks: view, rows, toneAt, titleAt }),\r\n [player, frame, rows, view, toneAt, titleAt]\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\r\nimport { useSteps } from \"./use-steps\";\r\nimport { usePrefersReducedMotion } from \"./use-prefers-reduced-motion\";\r\n\r\n// Layout effects run before paint and before rAF callbacks — what the prepend\r\n// compensation and the seed landing need. No-op'd on the server (SSR warning).\r\nconst useIsoLayoutEffect = typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\r\n\r\nexport interface LessonStreamOptions {\r\n /** Lesson to open on (deep link). Clamped. Default 0. */\r\n seed?: number;\r\n /** Lessons mounted on each side of the seed initially. Default 1. */\r\n radius?: number;\r\n /** Load the next lesson when the last mounted one's bottom is within this many px below the viewport. Default 600. */\r\n approachBelow?: number;\r\n /** Load the previous lesson when the first mounted one's top is below `-approachAbove`. Default 300. */\r\n approachAbove?: number;\r\n /** Scroll the seed lesson into view before first paint (seed > 0). Default true. */\r\n scrollToSeed?: boolean;\r\n /**\r\n * Fired when the scroll-tracked active lesson changes (not on mount) — sync\r\n * the URL / document title here. Read through a ref; inline is fine.\r\n */\r\n onActiveChange?: (index: number) => void;\r\n}\r\n\r\nexport interface LessonStream {\r\n /** Lesson containing the viewport center (the seed until the first measure). */\r\n active: number;\r\n /** The seed lesson — SSR'd visible; every other block should fade in. */\r\n seed: number;\r\n /** Indices to render, in order (the mounted window). */\r\n mounted: number[];\r\n /** The window reaches the last lesson — render an end-of-stream footer. */\r\n complete: boolean;\r\n /** Stable callback ref for lesson `i`'s block element (cached per index). */\r\n refFor: (index: number) => (el: HTMLElement | null) => void;\r\n /** Mount through lesson `i` (if needed) and scroll to it. */\r\n goTo: (index: number) => void;\r\n next: () => void;\r\n prev: () => void;\r\n reducedMotion: boolean;\r\n}\r\n\r\n/**\r\n * Continuous reader for a sequence of lessons (a notebook): renders a growing\r\n * window of lessons around the seed instead of all of them, and tracks the\r\n * active one by viewport-center containment (invariant 1).\r\n *\r\n * - The lesson after the window mounts as the reader approaches its place;\r\n * the one before mounts near the top, and a layout effect compensates the\r\n * scroll so prepended content never shoves the reader down.\r\n * - Navigation (`goTo`) expansions are NOT compensated — their scrollIntoView\r\n * is absolute, and compensating them displaced the landing.\r\n * - The cursor is a useSteps core, so it composes with ChapterNav\r\n * (`active` + `goTo`) and LessonPager (`prev`/`next`).\r\n *\r\n * Headless: the consumer renders `mounted.map(i => <Block ref={refFor(i)} />)`\r\n * and owns the content; pair blocks with `useFadeIn(i === seed)`.\r\n */\r\nexport function useLessonStream(count: number, opts: LessonStreamOptions = {}): LessonStream {\r\n const { radius = 1, approachBelow = 600, approachAbove = 300, scrollToSeed = true } = opts;\r\n const last = count - 1;\r\n const seed = count === 0 ? -1 : Math.max(0, Math.min(opts.seed ?? 0, last));\r\n const reducedMotion = usePrefersReducedMotion();\r\n\r\n const core = useSteps(count, { initialIndex: Math.max(0, seed) });\r\n const coreGoRef = useRef(core.go);\r\n coreGoRef.current = core.go;\r\n const activeRef = useRef(core.index);\r\n activeRef.current = core.index;\r\n\r\n const [range, setRange] = useState(() => ({\r\n first: Math.max(0, seed - radius),\r\n last: Math.min(last, seed + radius),\r\n }));\r\n // Clamp to the live count (lessons may be removed).\r\n const first = Math.max(0, Math.min(range.first, last));\r\n const lastMounted = Math.min(range.last, last);\r\n const rangeRef = useRef({ first, last: lastMounted });\r\n rangeRef.current = { first, last: lastMounted };\r\n const countRef = useRef(count);\r\n countRef.current = count;\r\n const reducedRef = useRef(reducedMotion);\r\n reducedRef.current = reducedMotion;\r\n const onActiveRef = useRef(opts.onActiveChange);\r\n onActiveRef.current = opts.onActiveChange;\r\n const optsRef = useRef({ approachBelow, approachAbove });\r\n optsRef.current = { approachBelow, approachAbove };\r\n\r\n const blocks = useRef(new Map<number, HTMLElement>());\r\n const refCache = useRef(new Map<number, (el: HTMLElement | null) => void>());\r\n const refFor = useCallback((i: number) => {\r\n let fn = refCache.current.get(i);\r\n if (!fn) {\r\n fn = (el) => {\r\n if (el) blocks.current.set(i, el);\r\n else blocks.current.delete(i);\r\n };\r\n refCache.current.set(i, fn);\r\n }\r\n return fn;\r\n }, []);\r\n\r\n // Why the window grew: \"scroll\" preloads are anchored (compensated), \"nav\"\r\n // expansions are not.\r\n const causeRef = useRef<\"scroll\" | \"nav\">(\"scroll\");\r\n const expandTo = useCallback((i: number, cause: \"scroll\" | \"nav\") => {\r\n const r = rangeRef.current;\r\n if (i >= r.first && i <= r.last) return;\r\n causeRef.current = cause;\r\n const grown = { first: Math.min(r.first, i), last: Math.max(r.last, i) };\r\n rangeRef.current = grown; // a second expansion in the same tick builds on this one\r\n setRange(grown);\r\n }, []);\r\n const scheduleRef = useRef<(() => void) | null>(null);\r\n\r\n // One rAF scroll loop: active tracking + approach loading.\r\n useEffect(() => {\r\n if (count === 0) return;\r\n let raf = 0;\r\n const update = () => {\r\n raf = 0;\r\n if (blocks.current.size === 0) return;\r\n const mid = window.innerHeight / 2;\r\n let best = -1;\r\n for (const [i, el] of blocks.current) {\r\n const rect = el.getBoundingClientRect();\r\n if (rect.top <= mid && rect.bottom >= mid) best = Math.max(best, i);\r\n }\r\n // No block straddles the center: fall back to the first mounted one.\r\n // NOT \"deepest top above center\" — right after a route change a stale\r\n // scroll position puts every block above center and that picks wrong.\r\n if (best === -1) best = Math.min(...blocks.current.keys());\r\n if (best !== activeRef.current) {\r\n activeRef.current = best;\r\n coreGoRef.current(best);\r\n onActiveRef.current?.(best);\r\n }\r\n\r\n const { first: f, last: l } = rangeRef.current;\r\n const { approachBelow: below, approachAbove: above } = optsRef.current;\r\n const lastEl = blocks.current.get(l);\r\n if (lastEl && l < countRef.current - 1 && lastEl.getBoundingClientRect().bottom - window.innerHeight < below) {\r\n expandTo(l + 1, \"scroll\");\r\n }\r\n const firstEl = blocks.current.get(f);\r\n if (firstEl && f > 0 && firstEl.getBoundingClientRect().top > -above) {\r\n expandTo(f - 1, \"scroll\");\r\n }\r\n };\r\n const onScroll = () => {\r\n if (!raf) raf = requestAnimationFrame(update);\r\n };\r\n scheduleRef.current = onScroll;\r\n update();\r\n window.addEventListener(\"scroll\", onScroll, { passive: true });\r\n window.addEventListener(\"resize\", onScroll);\r\n return () => {\r\n scheduleRef.current = null;\r\n window.removeEventListener(\"scroll\", onScroll);\r\n window.removeEventListener(\"resize\", onScroll);\r\n if (raf) cancelAnimationFrame(raf);\r\n };\r\n }, [count, expandTo]);\r\n\r\n // Re-run the loop after the window grows: freshly mounted blocks may\r\n // already satisfy an approach condition without any scroll event.\r\n useEffect(() => {\r\n scheduleRef.current?.();\r\n }, [first, lastMounted]);\r\n\r\n // Prepend anchor: a scroll-driven preload slides content in above the\r\n // reader; compensate by the prepended height before paint.\r\n const firstRef = useRef(first);\r\n useIsoLayoutEffect(() => {\r\n if (first < firstRef.current && causeRef.current === \"scroll\") {\r\n let height = 0;\r\n for (let i = first; i < firstRef.current; i++) {\r\n height += blocks.current.get(i)?.getBoundingClientRect().height ?? 0;\r\n }\r\n if (height) window.scrollBy({ top: height, behavior: \"auto\" });\r\n }\r\n causeRef.current = \"scroll\";\r\n firstRef.current = first;\r\n }, [first]);\r\n\r\n // Seed landing: exactly once, before first paint — no race with a router's\r\n // own scroll management.\r\n useIsoLayoutEffect(() => {\r\n if (!scrollToSeed || seed <= 0) return;\r\n blocks.current.get(seed)?.scrollIntoView({ block: \"start\", behavior: \"auto\" });\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n // Navigation scrolls after the expanded window has committed (an effect,\r\n // not a guessed number of rAFs), then waits one frame for layout to settle.\r\n const [nav, setNav] = useState<{ target: number } | null>(null);\r\n useEffect(() => {\r\n if (!nav) return;\r\n const raf = requestAnimationFrame(() =>\r\n blocks.current\r\n .get(nav.target)\r\n ?.scrollIntoView({ behavior: reducedRef.current ? \"auto\" : \"smooth\", block: \"start\" })\r\n );\r\n return () => cancelAnimationFrame(raf);\r\n }, [nav]);\r\n\r\n const goTo = useCallback(\r\n (i: number) => {\r\n const c = countRef.current;\r\n if (c === 0) return;\r\n const target = Math.max(0, Math.min(i, c - 1));\r\n expandTo(target, \"nav\");\r\n setNav({ target });\r\n },\r\n [expandTo]\r\n );\r\n const next = useCallback(() => goTo(activeRef.current + 1), [goTo]);\r\n const prev = useCallback(() => goTo(activeRef.current - 1), [goTo]);\r\n\r\n const mounted = useMemo(() => {\r\n const out: number[] = [];\r\n for (let i = first; i <= lastMounted; i++) out.push(i);\r\n return out;\r\n }, [first, lastMounted]);\r\n\r\n return useMemo(\r\n () => ({\r\n active: core.index,\r\n seed,\r\n mounted,\r\n complete: count > 0 && lastMounted === last,\r\n refFor,\r\n goTo,\r\n next,\r\n prev,\r\n reducedMotion,\r\n }),\r\n [core.index, seed, mounted, count, lastMounted, last, refFor, goTo, next, prev, reducedMotion]\r\n );\r\n}\r\n\r\n/**\r\n * Mount fade for streamed blocks: `false` on the first client render, `true`\r\n * a frame later (immediately with reduced motion). Pass `initiallyVisible`\r\n * for server-rendered blocks (the stream's seed) so they never flash.\r\n */\r\nexport function useFadeIn(initiallyVisible = false): boolean {\r\n const reduced = usePrefersReducedMotion();\r\n const [shown, setShown] = useState(initiallyVisible);\r\n useEffect(() => {\r\n if (shown) return;\r\n if (reduced) {\r\n setShown(true);\r\n return;\r\n }\r\n const raf = requestAnimationFrame(() => setShown(true));\r\n return () => cancelAnimationFrame(raf);\r\n }, [shown, reduced]);\r\n return shown;\r\n}\r\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\n/**\n * True when the user asks the OS to reduce motion. Consumers should disable\n * transitions, smooth scrolls, and entry animations when this is true.\n * SSR-safe: false on the server, corrected after mount.\n */\nexport function usePrefersReducedMotion(): boolean {\n const [reduced, setReduced] = useState(false);\n\n useEffect(() => {\n const mq = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n setReduced(mq.matches);\n const onChange = (e: MediaQueryListEvent) => setReduced(e.matches);\n mq.addEventListener(\"change\", onChange);\n return () => mq.removeEventListener(\"change\", onChange);\n }, []);\n\n return reduced;\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useSteps } from \"./use-steps\";\nimport type { TourDriver, TourStepInput } from \"./types\";\n\nexport interface GuidedTour {\n /** Active step index, or null when the tour is not running. */\n index: number | null;\n current: TourStepInput | null;\n active: boolean;\n /**\n * True while the active step's `gate` returns false: `next()` is a no-op\n * until the gate opens. Present the `blocked` state (disable Next, pulse\n * the waitHint) so the user knows what is being waited on.\n */\n blocked: boolean;\n start: () => void;\n end: () => void;\n next: () => void;\n back: () => void;\n goto: (index: number) => void;\n /** Jump to the step with this id. No-op when the id is unknown. */\n gotoId: (id: string) => void;\n}\n\nexport interface GuidedTourOptions {\n /**\n * Alternate presenter (driver.js, Shepherd, …). When set, the hook drives it\n * imperatively — show/hide per step, with transition controls wired — and\n * the app should not render the built-in TourSpotlight/TourCard. Without a\n * driver, the app renders the built-in presentation itself.\n */\n driver?: TourDriver;\n}\n\n/**\n * Tour state whose steps are effects over app state: `onEnter` fires whenever\n * the active step changes, reading the latest `steps` via ref so closures stay\n * fresh without re-triggering the effect on every render. Composed on\n * useSteps — a tour is a step sequence whose `next` past the end exits.\n *\n * On top of the linear cursor, steps may declare `when` (skip on arrival),\n * `gate` (block `next` until true), and `next` (edge override by step id) —\n * a small state machine where states are steps, edges are `next` functions,\n * and guards are gates. The cursor itself stays a cursor: skipped steps are\n * never landed on, and skipped/gated behavior is evaluated at transition\n * time, not on every render.\n */\nexport function useGuidedTour(steps: TourStepInput[], opts?: GuidedTourOptions): GuidedTour {\n const [running, setRunning] = useState(false);\n const runningRef = useRef(running);\n runningRef.current = running;\n const core = useSteps(steps.length);\n const stepsRef = useRef(steps);\n stepsRef.current = steps;\n const driverRef = useRef(opts?.driver);\n driverRef.current = opts?.driver;\n // core.go is referentially stable; reach it through a ref so the callbacks\n // below (and the driver effect) don't churn with the cursor.\n const coreGoRef = useRef(core.go);\n coreGoRef.current = core.go;\n const cursorRef = useRef(core.index);\n cursorRef.current = core.index;\n\n const isSkipped = useCallback(\n (i: number) => stepsRef.current[i]?.when?.() === false,\n []\n );\n\n /**\n * Land on `start` when eligible; otherwise walk in `dir` past skipped\n * steps. Forward exhaustion (or an all-skipped tour) returns null, which\n * ends the run; backward exhaustion restarts at the first eligible step.\n */\n const settle = useCallback(\n (start: number, dir: 1 | -1): number | null => {\n const len = stepsRef.current.length;\n let i = start;\n while (i >= 0 && i < len && isSkipped(i)) i += dir;\n if (i >= 0 && i < len) return i;\n if (dir === 1) return null;\n for (let j = 0; j < len; j++) if (!isSkipped(j)) return j;\n return null;\n },\n [isSkipped]\n );\n\n /** Enter the tour at (or, past skipped steps in direction `dir`) index `i`. */\n const arrive = useCallback(\n (i: number, dir: 1 | -1) => {\n const target = settle(i, dir);\n if (target === null) {\n setRunning(false);\n return;\n }\n setRunning(true);\n coreGoRef.current(target);\n },\n [settle]\n );\n\n const goTo = useCallback(\n (i: number) => {\n if (stepsRef.current.length === 0) return;\n arrive(Math.max(0, Math.min(i, stepsRef.current.length - 1)), 1);\n },\n [arrive]\n );\n\n const goToId = useCallback(\n (id: string) => {\n const i = stepsRef.current.findIndex((s) => s.id === id);\n if (i >= 0) goTo(i);\n },\n [goTo]\n );\n\n const index = running ? core.index : null;\n\n useEffect(() => {\n if (!running) return;\n stepsRef.current[core.index]?.onEnter?.();\n }, [running, core.index]);\n\n // Custom driver lifecycle — show the active step, hide on end/unmount.\n useEffect(() => {\n const driver = driverRef.current;\n if (!driver) return;\n if (!running) {\n driver.hide();\n return;\n }\n const step = stepsRef.current[core.index];\n if (!step) {\n driver.hide();\n return;\n }\n driver.show(step, {\n index: core.index,\n total: stepsRef.current.length,\n next: () => goTo(core.index + 1),\n back: () => goTo(core.index - 1),\n end: () => setRunning(false),\n });\n }, [running, core.index, goTo]);\n\n // Hide the driver if the tour unmounts mid-step.\n useEffect(() => () => driverRef.current?.hide(), []);\n\n const start = useCallback(() => {\n if (stepsRef.current.length === 0) return;\n arrive(0, 1);\n }, [arrive]);\n\n const end = useCallback(() => setRunning(false), []);\n\n /** Edge target of step i: explicit next() id resolved to an index, else i+1. */\n const resolveNext = useCallback((i: number): number => {\n const list = stepsRef.current;\n const edge = list[i]?.next?.();\n if (edge != null) {\n const t = list.findIndex((s) => s.id === edge);\n if (t >= 0) return t;\n }\n return i + 1;\n }, []);\n\n const next = useCallback(() => {\n if (!runningRef.current) return;\n const i = cursorRef.current;\n // A closed gate blocks the advance — the app surfaces `blocked`.\n if (stepsRef.current[i]?.gate?.() === false) return;\n const target = resolveNext(i);\n if (target > stepsRef.current.length - 1) {\n setRunning(false); // linear past the end — the tour exits\n return;\n }\n arrive(target, 1);\n }, [arrive, resolveNext]);\n\n const back = useCallback(() => {\n if (!runningRef.current) return;\n const i = cursorRef.current;\n if (i <= 0) return;\n arrive(i - 1, -1);\n }, [arrive]);\n\n const current = running ? (stepsRef.current[core.index] ?? null) : null;\n const blocked = current?.gate?.() === false;\n return useMemo(\n () => ({ index, current, active: running, blocked, start, end, next, back, goto: goTo, gotoId: goToId }),\n [index, current, running, blocked, start, end, next, back, goTo, goToId]\n );\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useSteps } from \"./use-steps\";\nimport { flattenChapters } from \"./flatten\";\nimport type { Chapter } from \"./types\";\n\nexport interface ChaptersApi {\n /** Index of the chapter currently in view (flattened order). */\n active: number;\n goTo: (index: number) => void;\n next: () => void;\n prev: () => void;\n}\n\nexport { flattenChapters };\n\n/**\n * Scroll-tracked chapter navigation for multi-section pages. Active = the\n * section containing the viewport center: a chapter becomes active when it\n * reaches the middle of the screen, not the moment its top scrolls past an\n * offset. Sections are resolved by DOM id; give each section CSS scroll-mt\n * so `goTo`'s scrollIntoView clears any sticky header. Composed on useSteps —\n * the scroll position is an external input driving the cursor.\n */\nexport function useChapters(chapters: Chapter[]): ChaptersApi {\n const [mounted, setMounted] = useState(false);\n const flat = useMemo(() => flattenChapters(chapters), [chapters]);\n const flatRef = useRef(flat);\n flatRef.current = flat;\n const [active, setActive] = useState(0);\n const activeRef = useRef(0);\n activeRef.current = active;\n\n const core = useSteps(flat.length, { initialIndex: 0 });\n // core.go is referentially stable; the tracker reaches it through a ref so\n // the effect below never depends on the core identity (which churns with\n // the index).\n const coreGoRef = useRef(core.go);\n coreGoRef.current = core.go;\n\n // Scroll → cursor (external input drives the sequence). Depending only on\n // `mounted` (+ the chapter count) matters: if this effect re-ran on every\n // cursor change, a programmatic goTo would be snapped back to the rect-\n // derived chapter before the smooth scroll has moved the viewport.\n useEffect(() => {\n if (!mounted) return;\n let raf = 0;\n const update = () => {\n raf = 0;\n const flat = flatRef.current;\n const mid = window.innerHeight / 2;\n let best = -1;\n for (let i = 0; i < flat.length; i++) {\n const el = document.getElementById(flat[i].chapter.id);\n if (!el) continue;\n const rect = el.getBoundingClientRect();\n if (rect.top <= mid && rect.bottom >= mid) best = i;\n }\n if (best === -1) {\n // No section contains the center (tall gap or beyond the ends): keep\n // the deepest section whose top is above center, else the first.\n for (let i = 0; i < flat.length; i++) {\n const el = document.getElementById(flat[i].chapter.id);\n if (el && el.getBoundingClientRect().top <= mid) best = i;\n }\n if (best === -1) best = 0;\n }\n if (best !== activeRef.current) {\n setActive(best);\n coreGoRef.current(best);\n }\n };\n const onScroll = () => {\n if (!raf) raf = requestAnimationFrame(update);\n };\n update();\n window.addEventListener(\"scroll\", onScroll, { passive: true });\n window.addEventListener(\"resize\", onScroll);\n return () => {\n window.removeEventListener(\"scroll\", onScroll);\n window.removeEventListener(\"resize\", onScroll);\n if (raf) cancelAnimationFrame(raf);\n };\n }, [mounted, flat.length]);\n\n useEffect(() => setMounted(true), []);\n\n const goTo = useCallback((i: number) => {\n const entry = flatRef.current[i];\n if (!entry) return;\n setActive(i);\n coreGoRef.current(i);\n const el = document.getElementById(entry.chapter.id);\n if (!el) return;\n el.scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n }, []);\n\n const next = useCallback(() => {\n if (activeRef.current < flatRef.current.length - 1) goTo(activeRef.current + 1);\n }, [goTo]);\n const prev = useCallback(() => {\n if (activeRef.current > 0) goTo(activeRef.current - 1);\n }, [goTo]);\n\n return useMemo(() => ({ active: core.index, goTo, next, prev }), [core.index, goTo, next, prev]);\n}\n","import type { Chapter } from \"./types\";\n\nexport interface FlatChapter {\n chapter: Chapter;\n depth: number;\n /** Index of this entry's top-level ancestor within the flat list (itself at depth 0). */\n rootIndex: number;\n /** Index of the immediate parent within the flat list; -1 at depth 0. */\n parentIndex: number;\n}\n\n/** Depth-first flattening — reading order for prev/next and scroll tracking. */\nexport function flattenChapters(chapters: Chapter[], depth = 0): FlatChapter[] {\n const out: FlatChapter[] = [];\n const walk = (list: Chapter[], depth: number, parentIndex: number, rootIndex: number) => {\n for (const chapter of list) {\n const index = out.length;\n const effectiveRoot = depth === 0 ? index : rootIndex;\n out.push({ chapter, depth, rootIndex: effectiveRoot, parentIndex });\n if (chapter.children?.length) walk(chapter.children, depth + 1, index, effectiveRoot);\n }\n };\n walk(chapters, depth, -1, -1);\n return out;\n}\n","\"use client\";\n\nimport { useEffect, useRef } from \"react\";\n\nexport type KeyMap = Record<string, (e: KeyboardEvent) => void>;\n\nconst DEFAULT_IGNORED_TAGS = [\"INPUT\", \"TEXTAREA\", \"SELECT\", \"BUTTON\"];\n\nexport interface GlobalKeysOptions {\n /** Element tags that swallow keys (except Escape). Defaults to form controls and buttons. */\n ignoreTags?: string[];\n /** Gate: bindings fire only while enabled. Boolean or function — checked per event. */\n enabled?: boolean | (() => boolean);\n}\n\n/**\n * Bind global keyboard shortcuts. Keys are matched against `event.key`\n * (exact first, then lowercase). Handlers fire with preventDefault applied;\n * Escape always fires, even from ignored targets, and is never prevented.\n */\nexport function useGlobalKeys(map: KeyMap, opts?: GlobalKeysOptions): void {\n const mapRef = useRef(map);\n mapRef.current = map;\n const ignoreRef = useRef<Set<string>>(new Set(opts?.ignoreTags ?? DEFAULT_IGNORED_TAGS));\n const enabledRef = useRef(opts?.enabled ?? true);\n enabledRef.current = opts?.enabled ?? true;\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n const gate = enabledRef.current;\n const enabled = typeof gate === \"function\" ? gate() : gate;\n if (!enabled && e.key !== \"Escape\") return;\n const tag = (e.target as HTMLElement | null)?.tagName;\n if (e.key !== \"Escape\" && tag && ignoreRef.current.has(tag)) return;\n const fn = mapRef.current[e.key] ?? mapRef.current[e.key.toLowerCase()];\n if (!fn) return;\n if (e.key !== \"Escape\") e.preventDefault();\n fn(e);\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, []);\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\n// Discovery ledger: which named things (features, tutorials, chapters) has\n// this user already seen? A set of opaque id strings plus a persistence seam.\n// The id scheme belongs to the consumer — encode versions in the id\n// (\"sort:v2\") to re-show improved tours.\n\nexport interface DiscoveryStore {\n /** All discovered ids (best-effort; corrupted/absent storage reads as empty). */\n read(): string[];\n /** Persist the full set (write-through, not a delta). */\n write(ids: string[]): void;\n}\n\n/** localStorage-backed store — the default. Survives reloads, per-browser. */\nexport function localStorageStore(key = \"stepwise.discoveries\"): DiscoveryStore {\n return {\n read() {\n if (typeof window === \"undefined\") return [];\n try {\n const parsed = JSON.parse(window.localStorage.getItem(key) ?? \"[]\");\n return Array.isArray(parsed) ? parsed.filter((x): x is string => typeof x === \"string\") : [];\n } catch {\n return [];\n }\n },\n write(ids) {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(key, JSON.stringify(ids));\n } catch {\n // private mode / quota exceeded — discovery state is best-effort\n }\n },\n };\n}\n\n/**\n * Cookie-backed store — only when the SERVER must know during SSR (e.g. to\n * render \"NEW\" badges without a hydration flash). Costs request bytes; prefer\n * localStorage otherwise. Values are JSON-encoded and URI-escaped.\n */\nexport function cookieStore(key = \"stepwise.discoveries\"): DiscoveryStore {\n const read = (): string[] => {\n if (typeof document === \"undefined\") return [];\n const match = document.cookie.match(new RegExp(`(?:^|;\\\\s*)${key}=([^;]*)`));\n if (!match) return [];\n try {\n const parsed = JSON.parse(decodeURIComponent(match[1]));\n return Array.isArray(parsed) ? parsed.filter((x): x is string => typeof x === \"string\") : [];\n } catch {\n return [];\n }\n };\n return {\n read,\n write(ids) {\n if (typeof document === \"undefined\") return;\n document.cookie = `${key}=${encodeURIComponent(JSON.stringify(ids))}; max-age=31536000; path=/; SameSite=Lax`;\n },\n };\n}\n\n/** In-memory store — tests, storybook, SSR fallbacks, \"always show\" previews. */\nexport function memoryStore(seed: string[] = []): DiscoveryStore {\n let ids = [...seed];\n return {\n read: () => [...ids],\n write(next) {\n ids = [...next];\n },\n };\n}\n\nexport interface DiscoveriesOptions {\n /**\n * Storage seam. Defaults to localStorage. Swap in cookieStore when SSR\n * markup must know, or your own store (backend sync for cross-device).\n */\n store?: DiscoveryStore;\n /** Storage key used by the built-in stores. */\n key?: string;\n}\n\nexport interface Discoveries {\n /** Discovered ids. Empty until hydration — gate triggers on `ready`. */\n discovered: Set<string>;\n /** False during SSR and before the first client hydration pass. */\n ready: boolean;\n /** Ref-backed check for event handlers; prefer `discovered.has` in render. */\n isDiscovered: (id: string) => boolean;\n /** Record ids as discovered and persist the merged set. */\n markDiscovered: (id: string | string[]) => void;\n /** Forget everything (debug / \"show me the tour again\"). */\n reset: () => void;\n}\n\n/**\n * A persisted set of discovered ids, hydrated after mount (SSR-safe: the\n * server renders the undiscovered state, the client corrects it in an\n * effect — same pattern as usePrefersReducedMotion). Compose with\n * useGuidedTour: `pending = features.filter(f => !discovered.has(f.id))`,\n * auto-start the first pending tour, `markDiscovered` on completion.\n */\nexport function useDiscoveries(opts?: DiscoveriesOptions): Discoveries {\n // The default store is built once (key captured at first call); an\n // explicitly passed store always wins and may change identity per render.\n const defaultStoreRef = useRef<DiscoveryStore | null>(null);\n const storeRef = useRef<DiscoveryStore | null>(null);\n if (opts?.store) {\n storeRef.current = opts.store;\n } else {\n if (!defaultStoreRef.current) defaultStoreRef.current = localStorageStore(opts?.key);\n storeRef.current = defaultStoreRef.current;\n }\n\n const [ids, setIds] = useState<Set<string>>(() => new Set());\n const [ready, setReady] = useState(false);\n const idsRef = useRef(ids);\n idsRef.current = ids;\n\n useEffect(() => {\n setIds(new Set(storeRef.current!.read()));\n setReady(true);\n }, []);\n\n const markDiscovered = useCallback((id: string | string[]) => {\n const additions = Array.isArray(id) ? id : [id];\n const merged = new Set(idsRef.current);\n let changed = false;\n for (const x of additions) {\n if (!merged.has(x)) {\n merged.add(x);\n changed = true;\n }\n }\n if (!changed) return;\n idsRef.current = merged;\n setIds(merged);\n storeRef.current!.write([...merged]);\n }, []);\n\n const reset = useCallback(() => {\n const empty = new Set<string>();\n idsRef.current = empty;\n setIds(empty);\n storeRef.current!.write([]);\n }, []);\n\n const isDiscovered = useCallback((id: string) => idsRef.current.has(id), []);\n\n return useMemo(\n () => ({ discovered: ids, ready, isDiscovered, markDiscovered, reset }),\n [ids, ready, isDiscovered, markDiscovered, reset]\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef } from \"react\";\n\n/**\n * Traps Tab focus inside `ref.current` while `active`, focuses the container\n * on activation, and restores the previously focused element on release.\n * Returns a ref to attach to the focusable container (tabIndex={-1}).\n */\nexport function useFocusTrap(active: boolean) {\n const ref = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (!active) return;\n const container = ref.current;\n if (!container) return;\n const previous = document.activeElement as HTMLElement | null;\n\n container.focus({ preventScroll: true });\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Tab\") return;\n const focusables = Array.from(\n container.querySelectorAll<HTMLElement>(\n 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex=\"-1\"])'\n )\n ).filter((el) => el.offsetParent !== null || el === container);\n if (focusables.length === 0) return;\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const current = document.activeElement as HTMLElement | null;\n if (e.shiftKey && (current === first || !container.contains(current))) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && (current === last || !container.contains(current))) {\n e.preventDefault();\n first.focus();\n }\n };\n\n document.addEventListener(\"keydown\", onKey, true);\n return () => {\n document.removeEventListener(\"keydown\", onKey, true);\n previous?.focus({ preventScroll: true });\n };\n }, [active]);\n\n return ref;\n}\n","\"use client\";\r\n\r\nimport {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useId,\r\n useLayoutEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { createPortal } from \"react-dom\";\r\nimport { cn } from \"./cn\";\r\nimport { defaultTheme, type StepwiseTheme } from \"./theme\";\r\n\r\n// Glossary + Paradox-style recursive tooltips. Define entries once, reference\r\n// them inline with <Term id=\"…\">; definitions are ReactNode, so they may\r\n// contain further <Term>s — chains stack outward and are depth-capped\r\n// (mutual references terminate at MAX_DEPTH).\r\n\r\nexport interface GlossaryEntry {\r\n id: string;\r\n /** Display name, shown as the tooltip's heading. */\r\n term: string;\r\n /** Body — may embed <Term> references for nested tooltips. */\r\n definition: ReactNode;\r\n}\r\n\r\nconst MAX_DEPTH = 4;\r\nconst CARD_WIDTH = 288; // w-72\r\nconst OPEN_DELAY_MS = 60;\r\nconst CLOSE_GRACE_MS = 120;\r\n\r\ninterface GlossaryContextValue {\r\n byId: Map<string, GlossaryEntry>;\r\n /** Original declaration order — the auto-appendix renders this. */\r\n entries: GlossaryEntry[];\r\n /** Theme for the tooltip card; injectable per provider. */\r\n theme: StepwiseTheme;\r\n}\r\n\r\nconst GlossaryContext = createContext<GlossaryContextValue | null>(null);\r\nconst DepthContext = createContext(0);\r\nconst AppendixContext = createContext(false);\r\n\r\nexport function GlossaryProvider({\r\n entries,\r\n theme = defaultTheme,\r\n children,\r\n}: {\r\n entries: GlossaryEntry[];\r\n /** Styling for tooltip cards (see StepwiseTheme). */\r\n theme?: StepwiseTheme;\r\n children: ReactNode;\r\n}) {\r\n const value = useMemo(\r\n () => ({ byId: new Map(entries.map((e) => [e.id, e])), entries, theme }),\r\n [entries, theme]\r\n );\r\n return <GlossaryContext.Provider value={value}>{children}</GlossaryContext.Provider>;\r\n}\r\n\r\nexport function Term({ id, children, className }: { id: string; children?: ReactNode; className?: string }) {\r\n const ctx = useContext(GlossaryContext);\r\n const depth = useContext(DepthContext);\r\n const entry = ctx?.byId.get(id);\r\n\r\n const [open, setOpen] = useState(false);\r\n const [pos, setPos] = useState<{ left: number; top: number } | null>(null);\r\n const openRef = useRef(false);\r\n const wrapperRef = useRef<HTMLSpanElement | null>(null);\r\n const triggerRef = useRef<HTMLSpanElement | null>(null);\r\n const cardRef = useRef<HTMLSpanElement | null>(null);\r\n const openTimer = useRef(0);\r\n const closeTimer = useRef(0);\r\n const tipId = useId();\r\n\r\n const display = children ?? entry?.term ?? id;\r\n\r\n const closeNow = useCallback(() => {\r\n window.clearTimeout(openTimer.current);\r\n window.clearTimeout(closeTimer.current);\r\n openRef.current = false;\r\n setOpen(false);\r\n }, []);\r\n\r\n const openNow = useCallback((focusCard = false) => {\r\n window.clearTimeout(closeTimer.current);\r\n window.clearTimeout(openTimer.current);\r\n openRef.current = true;\r\n setOpen(true);\r\n if (focusCard) {\r\n requestAnimationFrame(() => cardRef.current?.focus({ preventScroll: true }));\r\n }\r\n }, []);\r\n\r\n const scheduleOpen = useCallback(() => {\r\n window.clearTimeout(closeTimer.current);\r\n if (openRef.current) return;\r\n window.clearTimeout(openTimer.current);\r\n openTimer.current = window.setTimeout(() => openNow(), OPEN_DELAY_MS);\r\n }, [openNow]);\r\n\r\n const scheduleClose = useCallback(() => {\r\n window.clearTimeout(openTimer.current);\r\n window.clearTimeout(closeTimer.current);\r\n closeTimer.current = window.setTimeout(closeNow, CLOSE_GRACE_MS);\r\n }, [closeNow]);\r\n\r\n // Position: below the trigger by default, flipped above when there is no\r\n // room beneath, horizontally clamped inside the viewport. Runs as a layout\r\n // effect so the card is measured before paint (no flash), then tracked on\r\n // scroll + resize, rAF-throttled.\r\n useLayoutEffect(() => {\r\n if (!open) {\r\n setPos(null);\r\n return;\r\n }\r\n let raf = 0;\r\n const update = () => {\r\n raf = 0;\r\n const trigger = triggerRef.current;\r\n const card = cardRef.current;\r\n if (!trigger) return;\r\n const r = trigger.getBoundingClientRect();\r\n const margin = 8;\r\n const gap = 8;\r\n const cw = card?.offsetWidth ?? CARD_WIDTH;\r\n const ch = card?.offsetHeight ?? 160;\r\n let top = r.bottom + gap;\r\n if (top + ch > window.innerHeight - margin) {\r\n // Not enough room below — flip above the trigger.\r\n top = r.top - gap - ch;\r\n if (top < margin) top = margin; // no room either way: pin to the top\r\n }\r\n let left = r.left;\r\n left = Math.max(margin, Math.min(left, window.innerWidth - cw - margin));\r\n setPos({ left, top });\r\n };\r\n const onMove = () => {\r\n if (!raf) raf = requestAnimationFrame(update);\r\n };\r\n update();\r\n window.addEventListener(\"scroll\", onMove, { passive: true });\r\n window.addEventListener(\"resize\", onMove);\r\n return () => {\r\n window.removeEventListener(\"scroll\", onMove);\r\n window.removeEventListener(\"resize\", onMove);\r\n if (raf) cancelAnimationFrame(raf);\r\n };\r\n }, [open]);\r\n\r\n // Outside pointer closes (touch + click-away); Escape closes from anywhere\r\n // inside the tooltip subtree.\r\n useEffect(() => {\r\n if (!open) return;\r\n const onPointerDown = (e: PointerEvent) => {\r\n const target = e.target as Node;\r\n if (wrapperRef.current?.contains(target)) return;\r\n if (cardRef.current?.contains(target)) return;\r\n closeNow();\r\n };\r\n document.addEventListener(\"pointerdown\", onPointerDown);\r\n return () => document.removeEventListener(\"pointerdown\", onPointerDown);\r\n }, [open, closeNow]);\r\n\r\n // Timer cleanup.\r\n useEffect(() => () => {\r\n window.clearTimeout(openTimer.current);\r\n window.clearTimeout(closeTimer.current);\r\n }, []);\r\n\r\n const capped = depth >= MAX_DEPTH;\r\n const inAppendix = useContext(AppendixContext);\r\n const interactive = !capped && !inAppendix;\r\n const t = ctx?.theme ?? defaultTheme;\r\n\r\n // Inside a glossary appendix, references become anchor links to the entry's\r\n // row instead of nested tooltips.\r\n if (inAppendix) {\r\n const linked = ctx?.byId.get(id);\r\n if (!linked) return <span className={className}>{display}</span>;\r\n return (\r\n <a\r\n href={`#glossary-${linked.id}`}\r\n title={linked.term}\r\n className={cn(\"text-accent underline underline-offset-4 hover:text-primary\", className)}\r\n >\r\n {display}\r\n </a>\r\n );\r\n }\r\n\r\n const triggerProps = interactive\r\n ? {\r\n role: \"button\" as const,\r\n tabIndex: 0,\r\n \"aria-expanded\": open,\r\n \"aria-describedby\": open ? tipId : undefined,\r\n onMouseEnter: scheduleOpen,\r\n onMouseLeave: scheduleClose,\r\n onFocus: () => openNow(),\r\n onBlur: (e: React.FocusEvent) => {\r\n const next = e.relatedTarget as Node | null;\r\n if (next && (wrapperRef.current?.contains(next) || cardRef.current?.contains(next))) return;\r\n scheduleClose();\r\n },\r\n onClick: () => openNow(),\r\n onKeyDown: (e: React.KeyboardEvent) => {\r\n if (e.key === \"Escape\") {\r\n e.stopPropagation();\r\n closeNow();\r\n } else if ((e.key === \"Enter\" || e.key === \" \") && !open) {\r\n e.preventDefault();\r\n openNow(true);\r\n }\r\n },\r\n }\r\n : {};\r\n\r\n // Unknown id or no provider: render plain text. All hooks above ran\r\n // unconditionally — this branch only affects markup.\r\n if (!ctx || !entry) {\r\n return <span className={cn(\"text-foreground/85\", className)}>{display}</span>;\r\n }\r\n\r\n return (\r\n <span\r\n ref={wrapperRef}\r\n data-stepwise=\"\"\r\n className=\"relative inline\"\r\n onMouseEnter={interactive ? scheduleOpen : undefined}\r\n onMouseLeave={interactive ? scheduleClose : undefined}\r\n >\r\n <span\r\n ref={triggerRef}\r\n {...triggerProps}\r\n className={cn(\r\n \"border-b border-dotted\",\r\n interactive ? \"border-primary/50 text-foreground/85 hover:text-primary focus-visible:text-primary cursor-help\" : \"text-foreground/70\",\r\n className\r\n )}\r\n >\r\n {display}\r\n </span>\r\n {open &&\r\n createPortal(\r\n <DepthContext.Provider value={depth + 1}>\r\n <span\r\n ref={cardRef}\r\n data-stepwise=\"\"\r\n role=\"tooltip\"\r\n id={tipId}\r\n tabIndex={-1}\r\n onKeyDown={(e) => {\r\n if (e.key === \"Escape\") {\r\n e.stopPropagation();\r\n closeNow();\r\n triggerRef.current?.focus({ preventScroll: true });\r\n }\r\n }}\r\n onMouseEnter={interactive ? () => window.clearTimeout(closeTimer.current) : undefined}\r\n onMouseLeave={interactive ? scheduleClose : undefined}\r\n className={cn(\r\n \"fixed z-50 block w-72 max-w-[calc(100vw-1rem)] rounded-sm p-3 shadow-2xl outline-none motion-reduce:transition-none\",\r\n \"transition-opacity duration-150\",\r\n t.surface,\r\n \"border-white/15 bg-popover\",\r\n pos === null && \"invisible\"\r\n )}\r\n style={\r\n pos\r\n ? { left: pos.left, top: pos.top, maxHeight: \"min(60vh, 20rem)\", overflowY: \"auto\" }\r\n : { visibility: \"hidden\" }\r\n }\r\n >\r\n <span className=\"mb-1 block font-mono text-[11px] uppercase tracking-widest text-primary/90\">\r\n {entry.term}\r\n </span>\r\n <span className=\"block text-[11px] font-mono leading-relaxed text-foreground/70\">\r\n {entry.definition}\r\n </span>\r\n </span>\r\n </DepthContext.Provider>,\r\n document.body\r\n )}\r\n </span>\r\n );\r\n}\r\n\r\n/**\r\n * The glossary appendix: every entry rendered as an anchored row, placed\r\n * after the last chapter. Entries default to the provider's declarations —\r\n * define them once and the appendix follows automatically; pass `entries`\r\n * explicitly to override or to render without a provider. Inside it, <Term>\r\n * references resolve to in-page anchor links instead of tooltips.\r\n *\r\n * Customization hooks: `intro`/`footer` render arbitrary nodes around the\r\n * grid, `renderEntry` replaces the whole row renderer, `className` and\r\n * `entryClassName` style the section and each row. Opt out of the appendix\r\n * entirely by not rendering it.\r\n */\r\nexport function GlossaryAppendix({\r\n entries,\r\n title = \"Glossary\",\r\n intro,\r\n footer,\r\n columns = 2,\r\n bare = false,\r\n className,\r\n entryClassName,\r\n renderEntry,\r\n}: {\r\n /** Override the row list; defaults to the provider's entries. */\r\n entries?: GlossaryEntry[];\r\n title?: string;\r\n /** Rendered between the title and the grid — an introduction, usage notes, scope, … */\r\n intro?: ReactNode;\r\n /** Rendered after the grid. */\r\n footer?: ReactNode;\r\n columns?: 1 | 2;\r\n /** Omit the section chrome (title/border) — the host provides its own. */\r\n bare?: boolean;\r\n className?: string;\r\n entryClassName?: string;\r\n /** Replace the default row renderer entirely. */\r\n renderEntry?: (entry: GlossaryEntry) => ReactNode;\r\n}) {\r\n const ctxEntries = useContext(GlossaryContext)?.entries;\r\n const theme = useContext(GlossaryContext)?.theme ?? defaultTheme;\r\n const list = entries ?? ctxEntries;\r\n\r\n if (!list || list.length === 0) return null;\r\n\r\n const grid = (\r\n <div\r\n className={cn(\r\n \"grid grid-cols-1 gap-x-10 gap-y-8\",\r\n columns === 2 ? \"xl:grid-cols-2\" : \"grid-cols-1\"\r\n )}\r\n >\r\n {list.map((entry) =>\r\n renderEntry ? (\r\n <div key={entry.id} id={`glossary-${entry.id}`} className=\"scroll-mt-40\">\r\n {renderEntry(entry)}\r\n </div>\r\n ) : (\r\n <div key={entry.id} id={`glossary-${entry.id}`} className={cn(\"scroll-mt-40\", entryClassName)}>\r\n <h3 className=\"font-mono text-[11px] uppercase tracking-widest text-primary/90 mb-1.5\">\r\n {entry.term}\r\n </h3>\r\n <div className=\"text-[12px] font-mono text-foreground/60 leading-relaxed [&_strong]:text-foreground/80\">\r\n {entry.definition}\r\n </div>\r\n </div>\r\n )\r\n )}\r\n </div>\r\n );\r\n\r\n const body = (\r\n <>\r\n {intro && (\r\n <div className=\"mb-8 text-[12px] font-mono text-foreground/55 leading-relaxed max-w-3xl [&_a]:text-accent [&_a]:underline [&_a]:underline-offset-4\">\r\n {intro}\r\n </div>\r\n )}\r\n {grid}\r\n {footer && <div className=\"mt-8\">{footer}</div>}\r\n </>\r\n );\r\n\r\n if (bare) {\r\n return <AppendixContext.Provider value={true}>{body}</AppendixContext.Provider>;\r\n }\r\n return (\r\n <AppendixContext.Provider value={true}>\r\n <section data-stepwise=\"\" aria-label={title} className={cn(\"mt-16 border-t border-white/10 pt-10\", className)}>\r\n <p className={cn(\"text-[11px] font-mono uppercase tracking-widest mb-6\", theme.muted)}>{title}</p>\r\n {body}\r\n </section>\r\n </AppendixContext.Provider>\r\n );\r\n}\r\n\r\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import type { StepTone } from \"./types\";\n\n// Optional styled layer. The hooks are headless; these Tailwind classes are\n// the DEFAULTS the styled components ship with, overridable per component\n// via the `theme` prop — swap in any design system without touching the kit.\n//\n// The tokens cover every non-CSS-variable color the components hardcode\n// (white/black overlays, borders, code backgrounds), so a consumer theme can\n// flip the whole kit — not just the buttons — for light hosts.\n\nexport interface StepwiseTheme {\n /** Timeline-segment styling per tone. */\n toneSegment: Record<StepTone, string>;\n /** Step-kind chip styling per tone. */\n toneChip: Record<StepTone, string>;\n /** Shared structural classes for internal buttons. */\n buttonBase: string;\n /** Per-variant appearance for internal buttons. */\n buttonVariants: Record<\"ghost\" | \"outline\" | \"primary\", string>;\n /**\n * Panel chrome for nav bars, cards, dialogs, and tooltip popovers.\n * Components pass their own border/background overrides after this token,\n * so it stays a base, not a contract.\n */\n surface: string;\n /** Full-screen dimmed backdrop behind modal surfaces. */\n overlay: string;\n /** Code block frame — its own background, border, and type scale. */\n codeBlock: string;\n /** Comment / dimmed lines inside the code block. */\n codeMuted: string;\n /** Keyboard chip (ShortcutsDialog). */\n kbd: string;\n /** Ring + rounding around the tour spotlight target. */\n spotlight: string;\n /** Dimmed meta text — counters, hints, empty states. */\n muted: string;\n}\n\nexport const defaultTheme: StepwiseTheme = {\n toneSegment: {\n neutral: \"bg-white/10\",\n accent: \"bg-accent/70\",\n good: \"bg-primary\",\n bad: \"bg-destructive/70\",\n write: \"bg-foreground/30\",\n idle: \"bg-white/5\",\n },\n toneChip: {\n neutral: \"text-foreground/50 border-white/10\",\n accent: \"text-accent border-accent/40\",\n good: \"text-primary border-primary/40\",\n bad: \"text-destructive border-destructive/40\",\n write: \"text-foreground/70 border-white/20\",\n idle: \"text-foreground/30 border-white/10\",\n },\n buttonBase:\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-sm font-mono transition-colors duration-200 disabled:pointer-events-none disabled:opacity-50 cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50\",\n buttonVariants: {\n ghost: \"border border-transparent text-foreground/70 hover:bg-white/5 hover:text-foreground\",\n outline: \"border border-primary/40 bg-background/40 text-foreground/85 hover:border-primary/70 hover:text-foreground\",\n primary: \"border border-primary bg-primary/90 text-primary-foreground hover:bg-primary\",\n },\n surface: \"border border-white/10 bg-background/85 backdrop-blur-md\",\n overlay: \"bg-black/70 backdrop-blur-sm\",\n codeBlock:\n \"rounded-sm border border-white/10 bg-black/40 px-2.5 py-2 font-mono text-[11px] leading-5 overflow-x-auto\",\n codeMuted: \"text-foreground/35\",\n kbd: \"font-mono text-[10px] px-1.5 py-0.5 border border-white/20 bg-white/5 rounded-sm text-foreground/80\",\n spotlight: \"rounded-sm ring-2 ring-primary/80 transition-all duration-300\",\n muted: \"text-foreground/40\",\n};\n","\"use client\";\r\n\r\nimport { useEffect, useState, type ButtonHTMLAttributes, type ReactNode } from \"react\";\r\nimport { createPortal } from \"react-dom\";\r\nimport { cn } from \"./cn\";\r\nimport { flattenChapters } from \"./flatten\";\r\nimport { defaultTheme, type StepwiseTheme } from \"./theme\";\r\nimport { useFocusTrap } from \"./use-focus-trap\";\r\nimport type { Chapter, ShortcutItem, StepTone, TourStepInput } from \"./types\";\r\n\r\n// Back-compat re-exports: the default theme maps, injectable per component.\r\nexport const TONE_SEGMENT_CLASS = defaultTheme.toneSegment;\r\nexport const TONE_CHIP_CLASS = defaultTheme.toneChip;\r\n\r\n// Every component root carries `data-stepwise`: the precompiled stylesheet\r\n// (styles.css) scopes its preflight to those subtrees, so non-Tailwind hosts\r\n// get normalized buttons/margins without a global reset.\r\n\r\n// ─── Internal button (replaces external UI-kit imports) ─────────────────────\r\n\r\nconst BTN_BASE = defaultTheme.buttonBase;\r\nconst BTN_GHOST = defaultTheme.buttonVariants.ghost;\r\nconst BTN_OUTLINE = defaultTheme.buttonVariants.outline;\r\nconst BTN_PRIMARY = defaultTheme.buttonVariants.primary;\r\n\r\nfunction StepButton({\r\n variant = \"ghost\",\r\n className,\r\n ...props\r\n}: ButtonHTMLAttributes<HTMLButtonElement> & { variant?: \"ghost\" | \"outline\" | \"primary\" }) {\r\n const variantClass =\r\n variant === \"outline\" ? BTN_OUTLINE : variant === \"primary\" ? BTN_PRIMARY : BTN_GHOST;\r\n return <button type=\"button\" {...props} className={cn(BTN_BASE, variantClass, className)} />;\r\n}\r\n\r\n// ─── Code block ──────────────────────────────────────────────────────────────\r\n\r\nexport function CodeBlock({\r\n lines,\r\n theme = defaultTheme,\r\n className,\r\n}: {\r\n lines: string[];\r\n theme?: StepwiseTheme;\r\n className?: string;\r\n}) {\r\n return (\r\n <div data-stepwise=\"\" className={cn(theme.codeBlock, className)}>\r\n {lines.map((line, i) => {\r\n const commentStart = line.indexOf(\"//\");\r\n if (commentStart === 0) {\r\n return (\r\n <div key={i} className={cn(\"whitespace-pre\", theme.codeMuted)}>\r\n {line}\r\n </div>\r\n );\r\n }\r\n if (commentStart > 0) {\r\n return (\r\n <div key={i} className=\"whitespace-pre\">\r\n <span className=\"text-foreground/85\">{line.slice(0, commentStart)}</span>\r\n <span className={theme.codeMuted}>{line.slice(commentStart)}</span>\r\n </div>\r\n );\r\n }\r\n return (\r\n <div key={i} className=\"whitespace-pre text-foreground/85\">\r\n {line}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n );\r\n}\r\n\r\n// ─── Scrubber + player bar ───────────────────────────────────────────────────\r\n\r\nexport interface ScrubberLabels {\r\n /** aria-label for the slider. */\r\n scrubber?: string;\r\n /** aria-valuetext for the current position. Receives the frame index. */\r\n frame?: (i: number) => string;\r\n}\r\n\r\nexport function StepScrubber({\r\n count,\r\n index,\r\n toneAt,\r\n titleAt,\r\n onSeek,\r\n emptyHint,\r\n className,\r\n theme = defaultTheme,\r\n labels,\r\n groupOf,\r\n}: {\r\n count: number;\r\n index: number;\r\n toneAt?: (i: number) => StepTone;\r\n titleAt?: (i: number) => string;\r\n onSeek: (i: number) => void;\r\n emptyHint?: string;\r\n className?: string;\r\n theme?: StepwiseTheme;\r\n labels?: ScrubberLabels;\r\n /**\r\n * Groups consecutive segments into one proportional wrapper — a chapter\r\n * with sub-chapters spans the width of its whole subtree and only the\r\n * active inner segment fills, so a chapter reads as \"halfway\" while its\r\n * children play. Segments must be group-contiguous (flattenChapters order).\r\n */\r\n groupOf?: (i: number) => number;\r\n}) {\r\n const onKey = (e: React.KeyboardEvent) => {\r\n if (count === 0) return;\r\n if (e.key === \"ArrowRight\" || e.key === \"ArrowUp\") {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onSeek(Math.min(count - 1, index + 1));\r\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowDown\") {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onSeek(Math.max(0, index - 1));\r\n } else if (e.key === \"Home\") {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onSeek(0);\r\n } else if (e.key === \"End\") {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n onSeek(count - 1);\r\n }\r\n };\r\n\r\n if (count === 0) {\r\n return (\r\n <div data-stepwise=\"\" className={cn(\"flex-1 flex items-center min-w-0\", className)}>\r\n {emptyHint && <span className={cn(\"text-xs font-mono px-2\", theme.muted)}>{emptyHint}</span>}\r\n </div>\r\n );\r\n }\r\n\r\n const valueText = labels?.frame ? labels.frame(index) : (titleAt?.(index) ?? `frame ${index + 1} of ${count}`);\r\n\r\n const segment = (i: number) => (\r\n <div\r\n key={i}\r\n aria-hidden=\"true\"\r\n title={titleAt ? titleAt(i) : `frame ${i + 1}`}\r\n onClick={() => onSeek(i)}\r\n className={cn(\r\n \"h-3.5 flex-1 min-w-[3px] rounded-[2px] transition-all cursor-pointer\",\r\n theme.toneSegment[toneAt?.(i) ?? \"neutral\"],\r\n i === index && \"ring-2 ring-primary scale-y-150\"\r\n )}\r\n />\r\n );\r\n\r\n // Grouped mode: consecutive segments sharing a groupOf value render inside\r\n // one wrapper whose flex-grow equals its unit count — subtrees occupy\r\n // proportional width and the group fills segment by segment.\r\n let rows: ReactNode;\r\n if (groupOf) {\r\n const groups: number[][] = [];\r\n for (let i = 0; i < count; i++) {\r\n const g = groupOf(i);\r\n const lastGroup = groups[groups.length - 1];\r\n if (lastGroup && groupOf(lastGroup[0]) === g) lastGroup.push(i);\r\n else groups.push([i]);\r\n }\r\n rows = groups.map((units, gi) => (\r\n <div\r\n key={gi}\r\n aria-hidden=\"true\"\r\n className=\"flex-1 min-w-[3px] flex gap-[2px] items-center\"\r\n style={{ flexGrow: units.length }}\r\n >\r\n {units.map(segment)}\r\n </div>\r\n ));\r\n } else {\r\n rows = Array.from({ length: count }, (_, i) => segment(i));\r\n }\r\n\r\n return (\r\n <div\r\n data-stepwise=\"\"\r\n role=\"slider\"\r\n tabIndex={0}\r\n aria-label={labels?.scrubber ?? \"Frames\"}\r\n aria-valuemin={1}\r\n aria-valuemax={count}\r\n aria-valuenow={index + 1}\r\n aria-valuetext={valueText}\r\n aria-orientation=\"horizontal\"\r\n onKeyDown={onKey}\r\n className={cn(\r\n \"flex-1 flex items-center gap-[3px] min-w-0 cursor-pointer outline-none focus-visible:ring-2 focus-visible:ring-primary/60 rounded-sm\",\r\n className\r\n )}\r\n >\r\n {rows}\r\n </div>\r\n );\r\n}\r\n\r\nexport function PlayerBar({\r\n player,\r\n toneAt,\r\n titleAt,\r\n leading,\r\n onEmpty,\r\n emptyHint,\r\n className,\r\n theme = defaultTheme,\r\n groupOf,\r\n labels,\r\n}: {\r\n player: {\r\n total: number;\r\n index: number;\r\n playing: boolean;\r\n atEnd: boolean;\r\n next: (onEmpty?: () => void) => void;\r\n prev: () => void;\r\n toggle: (onEmpty?: () => void) => void;\r\n seek: (frame: number) => void;\r\n };\r\n toneAt?: (i: number) => StepTone;\r\n titleAt?: (i: number) => string;\r\n leading?: ReactNode;\r\n /** Fired when the user plays/steps with no timeline loaded. */\r\n onEmpty?: () => void;\r\n emptyHint?: string;\r\n className?: string;\r\n theme?: StepwiseTheme;\r\n /**\r\n * Forwarded to the scrubber — group consecutive segments into one\r\n * proportional wrapper (see StepScrubber).\r\n */\r\n groupOf?: (i: number) => number;\r\n labels?: {\r\n previous?: string;\r\n play?: string;\r\n pause?: string;\r\n replay?: string;\r\n next?: string;\r\n };\r\n}) {\r\n const L = {\r\n previous: labels?.previous ?? \"Previous step\",\r\n play: labels?.play ?? \"Play\",\r\n pause: labels?.pause ?? \"Pause\",\r\n replay: labels?.replay ?? \"Replay\",\r\n next: labels?.next ?? \"Next step\",\r\n };\r\n const playLabel = player.playing ? L.pause : player.total > 0 && player.atEnd ? L.replay : L.play;\r\n\r\n return (\r\n <div data-stepwise=\"\" className={cn(\"flex items-center gap-2 p-2\", className)}>\r\n {leading}\r\n <StepButton variant=\"ghost\" onClick={() => player.prev()} className=\"h-7 px-2 text-xs\" aria-label={L.previous}>\r\n ←\r\n </StepButton>\r\n <StepButton variant=\"outline\" onClick={() => player.toggle(onEmpty)} className=\"h-7 px-3.5 text-[11px]\">\r\n {playLabel}\r\n </StepButton>\r\n <StepButton variant=\"ghost\" onClick={() => player.next(onEmpty)} className=\"h-7 px-2 text-xs\" aria-label={L.next}>\r\n →\r\n </StepButton>\r\n <StepScrubber\r\n count={player.total}\r\n index={player.index}\r\n toneAt={toneAt}\r\n titleAt={titleAt}\r\n onSeek={(i) => player.seek(i)}\r\n emptyHint={emptyHint}\r\n theme={theme}\r\n groupOf={groupOf}\r\n />\r\n <span className={cn(\"text-[10px] font-mono w-11 text-right shrink-0\", theme.muted)}>\r\n {player.total > 0 ? `${player.index + 1}/${player.total}` : \"—\"}\r\n </span>\r\n </div>\r\n );\r\n}\r\n\r\n// ─── Chapter navigation ──────────────────────────────────────────────────────\r\n\r\nexport function ChapterNav({\r\n chapters,\r\n active,\r\n onNavigate,\r\n hint,\r\n className,\r\n theme = defaultTheme,\r\n}: {\r\n chapters: Chapter[];\r\n active: number;\r\n onNavigate: (i: number) => void;\r\n hint?: string;\r\n className?: string;\r\n theme?: StepwiseTheme;\r\n}) {\r\n const flat = flattenChapters(chapters);\r\n\r\n const renderRow = (items: Chapter[], depth: number): ReactNode => {\r\n const indent = \"— \".repeat(depth);\r\n return items.map((chapter) => {\r\n const flatIndex = flat.findIndex((f) => f.chapter.id === chapter.id);\r\n const isActive = flatIndex === active;\r\n return (\r\n <div key={chapter.id} className={cn(\"flex items-center\", depth > 0 && \"gap-1\")}>\r\n <StepButton\r\n type=\"button\"\r\n onClick={() => onNavigate(flatIndex)}\r\n aria-current={isActive ? \"true\" : undefined}\r\n title={chapter.hint ?? chapter.label}\r\n className={cn(\r\n \"flex items-center gap-1.5 px-2.5 py-1 rounded-sm text-[11px] font-mono border transition-colors cursor-pointer whitespace-nowrap\",\r\n depth > 0 && \"px-2 text-[10px] border-transparent\",\r\n isActive\r\n ? depth === 0\r\n ? \"border-primary/50 text-primary bg-primary/10\"\r\n : \"text-primary bg-primary/5\"\r\n : depth === 0\r\n ? \"border-transparent text-foreground/50 hover:text-foreground hover:border-white/15\"\r\n : \"text-foreground/45 hover:text-foreground\"\r\n )}\r\n >\r\n {depth === 0 && chapter.numbered !== false && (\r\n <span className={cn(\"text-[9px]\", isActive ? \"text-primary/80\" : \"text-foreground/30\")}>\r\n {String(flatIndex + 1).padStart(2, \"0\")}\r\n </span>\r\n )}\r\n {depth > 0 && <span className=\"text-foreground/25\">{indent}</span>}\r\n {chapter.label}\r\n </StepButton>\r\n {chapter.children && chapter.children.length > 0 && (\r\n <div className=\"flex flex-wrap items-center gap-1\">{renderRow(chapter.children, depth + 1)}</div>\r\n )}\r\n </div>\r\n );\r\n });\r\n };\r\n\r\n return (\r\n <nav\r\n data-stepwise=\"\"\r\n aria-label=\"Chapters\"\r\n className={cn(\r\n \"sticky top-20 md:top-24 z-30 rounded-sm shadow-[0_8px_24px_rgba(0,0,0,0.35)]\",\r\n theme.surface,\r\n className\r\n )}\r\n >\r\n <div className=\"p-1.5\">\r\n <div className=\"flex items-center gap-1 overflow-x-auto\">\r\n <span className={cn(\"shrink-0 px-2 text-[9px] font-mono uppercase tracking-widest\", theme.muted)}>\r\n Chapters\r\n </span>\r\n {renderRow(chapters, 0)}\r\n </div>\r\n {hint && (\r\n <div className=\"flex justify-end px-2 pt-1.5\">\r\n <span className={cn(\"text-[10px] font-mono hidden md:inline\", theme.muted)}>{hint}</span>\r\n </div>\r\n )}\r\n </div>\r\n </nav>\r\n );\r\n}\r\n\r\n// ─── Lesson pager (cross-page chapter navigation) ────────────────────────────\r\n\r\nexport function LessonPager({\r\n prev,\r\n next,\r\n onNavigate,\r\n className,\r\n labels,\r\n}: {\r\n prev?: { label: string; hint?: string };\r\n next?: { label: string; hint?: string };\r\n onNavigate: (dir: \"prev\" | \"next\") => void;\r\n className?: string;\r\n labels?: { previous?: string; next?: string };\r\n}) {\r\n return (\r\n <div data-stepwise=\"\" className={cn(\"flex items-center gap-2\", className)}>\r\n <StepButton\r\n variant=\"outline\"\r\n onClick={() => onNavigate(\"prev\")}\r\n disabled={!prev}\r\n title={prev?.hint ?? prev?.label}\r\n className=\"h-9 px-3 text-[11px]\"\r\n aria-label={prev ? `${labels?.previous ?? \"Previous lesson\"}: ${prev.label}` : \"No previous lesson\"}\r\n >\r\n ← {prev?.label ?? \"—\"}\r\n </StepButton>\r\n <StepButton\r\n variant=\"outline\"\r\n onClick={() => onNavigate(\"next\")}\r\n disabled={!next}\r\n title={next?.hint ?? next?.label}\r\n className=\"h-9 px-3 text-[11px] ml-auto\"\r\n aria-label={next ? `${labels?.next ?? \"Next lesson\"}: ${next.label}` : \"No next lesson\"}\r\n >\r\n {next?.label ?? \"—\"} →\r\n </StepButton>\r\n </div>\r\n );\r\n}\r\n\r\n// ─── Guided tour ─────────────────────────────────────────────────────────────\r\n\r\nexport function TourSpotlight({\r\n target,\r\n theme = defaultTheme,\r\n}: {\r\n target: string | null;\r\n theme?: StepwiseTheme;\r\n}) {\r\n const [rect, setRect] = useState<DOMRect | null>(null);\r\n\r\n useEffect(() => {\r\n if (!target) {\r\n setRect(null);\r\n return;\r\n }\r\n // The target may not exist yet (conditional rendering downstream) — poll\r\n // until it appears, then track it frame by frame.\r\n let el: Element | null = null;\r\n let scrolled = false;\r\n let raf = 0;\r\n let last = \"\";\r\n const tick = () => {\r\n if (!el) {\r\n // Resolve by DOM id first (most common), then by data-tour attribute.\r\n el = document.getElementById(target) ?? document.querySelector(`[data-tour=\"${target}\"]`);\r\n if (el && !scrolled) {\r\n scrolled = true;\r\n el.scrollIntoView({ block: \"center\", behavior: \"smooth\", inline: \"nearest\" });\r\n }\r\n }\r\n if (el) {\r\n const r = el.getBoundingClientRect();\r\n const key = [r.top, r.left, r.width, r.height].map((n) => Math.round(n)).join(\",\");\r\n if (key !== last) {\r\n last = key;\r\n setRect(r);\r\n }\r\n }\r\n raf = requestAnimationFrame(tick);\r\n };\r\n raf = requestAnimationFrame(tick);\r\n return () => cancelAnimationFrame(raf);\r\n }, [target]);\r\n\r\n if (!rect) return null;\r\n const pad = 6;\r\n return (\r\n <div data-stepwise=\"\" className=\"fixed inset-0 z-40 pointer-events-none\">\r\n <div\r\n className={cn(\"absolute\", theme.spotlight)}\r\n style={{\r\n top: rect.top - pad,\r\n left: rect.left - pad,\r\n width: rect.width + pad * 2,\r\n height: rect.height + pad * 2,\r\n boxShadow: \"0 0 0 9999px rgba(0,0,0,0.55)\",\r\n }}\r\n />\r\n </div>\r\n );\r\n}\r\n\r\nexport function TourCard({\r\n step,\r\n index,\r\n total,\r\n onNext,\r\n onBack,\r\n onEnd,\r\n labels,\r\n className,\r\n theme = defaultTheme,\r\n nextDisabled = false,\r\n}: {\r\n step: TourStepInput;\r\n index: number;\r\n total: number;\r\n onNext: () => void;\r\n onBack: () => void;\r\n onEnd: () => void;\r\n labels?: {\r\n title?: string;\r\n back?: string;\r\n next?: string;\r\n finish?: string;\r\n end?: string;\r\n };\r\n className?: string;\r\n theme?: StepwiseTheme;\r\n /** Disable the primary (Next/Finish) button — pair with tour.blocked. */\r\n nextDisabled?: boolean;\r\n}) {\r\n const L = {\r\n title: labels?.title ?? \"Guided tour\",\r\n back: labels?.back ?? \"Back\",\r\n next: labels?.next ?? \"Next\",\r\n finish: labels?.finish ?? \"Finish\",\r\n end: labels?.end ?? \"End tour\",\r\n };\r\n const trapRef = useFocusTrap(true);\r\n\r\n return (\r\n <div\r\n ref={trapRef}\r\n data-stepwise=\"\"\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-label={`${L.title} · ${index + 1}/${total}`}\r\n tabIndex={-1}\r\n className={cn(\r\n \"fixed bottom-6 left-1/2 -translate-x-1/2 z-50 w-[min(92vw,26rem)] rounded-sm p-4 outline-none\",\r\n theme.surface,\r\n \"border-primary/30 bg-background/95 shadow-2xl\",\r\n className\r\n )}\r\n >\r\n <div className=\"flex items-center justify-between mb-2\">\r\n <span className=\"text-[10px] font-mono uppercase tracking-widest text-primary/70\">\r\n {L.title} · {index + 1}/{total}\r\n </span>\r\n <StepButton\r\n type=\"button\"\r\n onClick={onEnd}\r\n aria-label={L.end}\r\n className=\"text-foreground/40 hover:text-foreground cursor-pointer leading-none\"\r\n >\r\n ×\r\n </StepButton>\r\n </div>\r\n <p className=\"text-sm font-bold text-foreground/95 mb-1.5\">{step.title}</p>\r\n <div className=\"text-[12px] font-mono text-foreground/70 leading-relaxed\">{step.body}</div>\r\n {step.waitHint && <p className=\"text-[11px] font-mono text-accent mt-2 animate-pulse\">{step.waitHint}</p>}\r\n <div className=\"flex items-center gap-2 mt-3 pt-3 border-t border-white/10\">\r\n <StepButton variant=\"outline\" onClick={onBack} disabled={index === 0} className=\"h-7 px-3 text-[11px]\">\r\n {L.back}\r\n </StepButton>\r\n <StepButton\r\n variant=\"primary\"\r\n onClick={onNext}\r\n disabled={nextDisabled}\r\n className=\"h-7 px-4 text-[11px] ml-auto\"\r\n >\r\n {index === total - 1 ? L.finish : L.next}\r\n </StepButton>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n// ─── Shortcuts dialog ────────────────────────────────────────────────────────\r\n\r\nexport function ShortcutsDialog({\r\n open,\r\n onClose,\r\n items,\r\n title = \"Keyboard shortcuts\",\r\n className,\r\n theme = defaultTheme,\r\n}: {\r\n open: boolean;\r\n onClose: () => void;\r\n items: ShortcutItem[];\r\n title?: string;\r\n className?: string;\r\n theme?: StepwiseTheme;\r\n}) {\r\n // SSR-safe portal: render only after mount (invariant: no portals during\r\n // SSR), and hooks run unconditionally before the early return.\r\n const [mounted, setMounted] = useState(false);\r\n const trapRef = useFocusTrap(open);\r\n\r\n useEffect(() => setMounted(true), []);\r\n\r\n // Escape closes from anywhere; Tab containment comes from the focus trap.\r\n useEffect(() => {\r\n if (!open) return;\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === \"Escape\") onClose();\r\n };\r\n document.addEventListener(\"keydown\", onKey);\r\n return () => document.removeEventListener(\"keydown\", onKey);\r\n }, [open, onClose]);\r\n\r\n if (!open || !mounted) return null;\r\n\r\n return createPortal(\r\n <div\r\n data-stepwise=\"\"\r\n className={cn(\"fixed inset-0 z-50 flex items-center justify-center p-4\", theme.overlay, className)}\r\n onClick={onClose}\r\n >\r\n <div\r\n ref={trapRef}\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-label={title}\r\n tabIndex={-1}\r\n onClick={(e) => e.stopPropagation()}\r\n className={cn(\r\n \"w-full max-w-md rounded-sm p-5 shadow-2xl outline-none\",\r\n theme.surface,\r\n \"border-white/15 bg-card\"\r\n )}\r\n >\r\n <div className=\"flex items-center justify-between mb-4\">\r\n <h3 className=\"text-lg text-primary\">{title}</h3>\r\n <StepButton\r\n type=\"button\"\r\n onClick={onClose}\r\n aria-label=\"Close shortcuts\"\r\n className=\"text-foreground/40 hover:text-foreground cursor-pointer leading-none text-lg\"\r\n >\r\n ×\r\n </StepButton>\r\n </div>\r\n <dl className=\"space-y-2\">\r\n {items.map((s) => (\r\n <div key={s.keys} className=\"flex items-center justify-between gap-4\">\r\n <dt>\r\n <kbd className={theme.kbd}>{s.keys}</kbd>\r\n </dt>\r\n <dd className=\"font-mono text-[11px] text-foreground/60 text-right\">{s.action}</dd>\r\n </div>\r\n ))}\r\n </dl>\r\n </div>\r\n </div>,\r\n document.body\r\n );\r\n}\r\n\r\n\r\n\r\n\r\n\r\n"],"mappings":"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","names":["useCallback","useEffect","useMemo","useRef","useState","useState","useRef","useCallback","useEffect","next","useMemo","useCallback","useMemo","useRef","useRef","useCallback","useMemo","useCallback","useMemo","useRef","useRef","useMemo","useCallback","useCallback","useEffect","useMemo","useRef","useState","useEffect","useState","useEffect","useRef","useState","useCallback","useMemo","useCallback","useEffect","useMemo","useRef","useState","useState","useRef","useCallback","start","useEffect","useMemo","useCallback","useEffect","useMemo","useRef","useState","depth","useState","useMemo","useRef","useEffect","flat","useCallback","useEffect","useRef","useCallback","useEffect","useMemo","useRef","useState","useEffect","useRef","useCallback","useEffect","useLayoutEffect","useMemo","useRef","useState","useMemo","useState","useRef","useCallback","useLayoutEffect","useEffect","useEffect","useState","createPortal","jsx","jsxs","useState","useEffect","createPortal"]}