@posthog/wizard 2.13.0 → 2.13.1
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/{AuditChecksViewer-B0J7zcY2.js → AuditChecksViewer-CjBCZjxG.js} +4 -4
- package/dist/{AuditChecksViewer-B0J7zcY2.js.map → AuditChecksViewer-CjBCZjxG.js.map} +1 -1
- package/dist/{add-mcp-server-to-clients-CUNR00bB.js → add-mcp-server-to-clients-D1IyBa9u.js} +4 -4
- package/dist/{add-mcp-server-to-clients-CUNR00bB.js.map → add-mcp-server-to-clients-D1IyBa9u.js.map} +1 -1
- package/dist/{agent-interface-CV0-vtxj.js → agent-interface-D9DeIikl.js} +6 -6
- package/dist/{agent-interface-CV0-vtxj.js.map → agent-interface-D9DeIikl.js.map} +1 -1
- package/dist/{agent-runner-LvVQH31D.js → agent-runner-B41-Iig3.js} +7 -7
- package/dist/{agent-runner-LvVQH31D.js.map → agent-runner-B41-Iig3.js.map} +1 -1
- package/dist/{analytics-VM7laaFx.js → analytics-Cek5hIwm.js} +2 -2
- package/dist/{analytics-VM7laaFx.js.map → analytics-Cek5hIwm.js.map} +1 -1
- package/dist/analytics-CpbY05Lf.js +2 -0
- package/dist/bin.js +25 -25
- package/dist/{debug-Cqi6nVfX.js → debug-B2BH87dh.js} +2 -2
- package/dist/{debug-Cqi6nVfX.js.map → debug-B2BH87dh.js.map} +1 -1
- package/dist/{debug-BdcTB7EF.js → debug-BNWsxaDm.js} +1 -1
- package/dist/{detection-CSjmal-X.js → detection-BFl2AYV6.js} +3 -3
- package/dist/{detection-CSjmal-X.js.map → detection-BFl2AYV6.js.map} +1 -1
- package/dist/{package-manager-CD8RQW-e.js → package-manager-BBTvHn9i.js} +2 -2
- package/dist/{package-manager-CD8RQW-e.js.map → package-manager-BBTvHn9i.js.map} +1 -1
- package/dist/{posthog-integration-BL21S3T6.js → posthog-integration-vFBuSN5U.js} +9 -9
- package/dist/{posthog-integration-BL21S3T6.js.map → posthog-integration-vFBuSN5U.js.map} +1 -1
- package/dist/provisioning--RCv39tI.js +2 -0
- package/dist/{provisioning-g9aoVIEd.js → provisioning-DRwH4skH.js} +3 -3
- package/dist/{provisioning-g9aoVIEd.js.map → provisioning-DRwH4skH.js.map} +1 -1
- package/dist/{registry-BaMEaAKd.js → registry-CZjMhhsK.js} +4 -4
- package/dist/{registry-BaMEaAKd.js.map → registry-CZjMhhsK.js.map} +1 -1
- package/dist/{setup-utils-CNV7FSlY.js → setup-utils-DGUR4Djo.js} +6 -6
- package/dist/{setup-utils-CNV7FSlY.js.map → setup-utils-DGUR4Djo.js.map} +1 -1
- package/dist/setup-utils-eh1450iu.js +2 -0
- package/dist/{start-playground-C9GWnVdM.js → start-playground-DPYl5WR-.js} +3 -3
- package/dist/{start-playground-C9GWnVdM.js.map → start-playground-DPYl5WR-.js.map} +1 -1
- package/dist/{start-tui-B_zwutLe.js → start-tui-Cj_4BhK8.js} +10 -10
- package/dist/{start-tui-B_zwutLe.js.map → start-tui-Cj_4BhK8.js.map} +1 -1
- package/dist/{steps-Dawz7k3T.js → steps-BFD76-MP.js} +6 -6
- package/dist/{steps-Dawz7k3T.js.map → steps-BFD76-MP.js.map} +1 -1
- package/dist/{telemetry-D6bjWA-A.js → telemetry-DCyjsXhw.js} +2 -2
- package/dist/{telemetry-D6bjWA-A.js.map → telemetry-DCyjsXhw.js.map} +1 -1
- package/dist/{wizard-abort-CJkNkSjT.js → wizard-abort-54DpTnUi.js} +3 -3
- package/dist/{wizard-abort-CJkNkSjT.js.map → wizard-abort-54DpTnUi.js.map} +1 -1
- package/dist/{wizard-abort-Dl0BkqhT.js → wizard-abort-CZH03nD0.js} +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/analytics-BH7bEHQR.js +0 -2
- package/dist/provisioning-BdQ1ONIg.js +0 -2
- package/dist/setup-utils-CU4FIqjB.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuditChecksViewer-B0J7zcY2.js","names":["CHROME_ROWS","fs"],"sources":["../src/ui/tui/store.ts","../src/ui/tui/styles.ts","../src/ui/tui/primitives/CardLayout.tsx","../src/ui/tui/primitives/SplitView.tsx","../src/ui/tui/primitives/LoadingBox.tsx","../src/ui/tui/primitives/ProgressList.tsx","../src/ui/tui/primitives/PromptLabel.tsx","../src/ui/tui/hooks/keyboard-hints-utils.ts","../src/ui/tui/hooks/useKeyboardHints.tsx","../src/ui/tui/hooks/useKeyBindings.ts","../src/ui/tui/primitives/PickerMenu.tsx","../src/ui/tui/hooks/useStdoutDimensions.ts","../src/ui/tui/primitives/GroupedPickerMenu.tsx","../src/ui/tui/primitives/ConfirmationInput.tsx","../src/ui/tui/primitives/Divider.tsx","../src/ui/tui/primitives/ModalOverlay.tsx","../src/ui/tui/primitives/LogViewer.tsx","../src/ui/tui/primitives/EventPlanViewer.tsx","../src/ui/tui/components/TitleBar.tsx","../src/ui/tui/primitives/DissolveTransition.tsx","../src/ui/tui/primitives/KeyboardHintsBar.tsx","../src/ui/tui/primitives/ScreenErrorBoundary.tsx","../src/ui/tui/primitives/ScreenContainer.tsx","../src/ui/tui/primitives/TabContainer.tsx","../src/ui/tui/primitives/HNViewer.tsx","../src/ui/tui/primitives/text-helpers.ts","../src/ui/tui/primitives/content-types.ts","../src/ui/tui/primitives/layout-helpers.ts","../src/ui/tui/primitives/TextBlock.tsx","../src/ui/tui/primitives/LinesBlock.tsx","../src/ui/tui/primitives/NodeBlock.tsx","../src/ui/tui/primitives/ContentSequencer.tsx","../src/ui/tui/components/LearnCard.tsx","../src/ui/tui/components/TipsCard.tsx","../src/ui/tui/components/ServiceHealthList.tsx","../src/ui/tui/screens/doctor/IssueTable.tsx","../src/ui/tui/screens/McpScreen.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/AreaHeaderRow.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/layout.ts","../src/ui/tui/screens/audit/AuditChecksViewer/CheckRow.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/DetailRow.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/Legend.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/Header.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/Footer.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/sort.ts","../src/ui/tui/screens/audit/AuditChecksViewer/AuditChecksViewer.tsx"],"sourcesContent":["/**\n * WizardStore — Nanostore-backed reactive store for the TUI.\n * React components subscribe via useSyncExternalStore.\n *\n * The active screen is derived from session state — WizardRouter walks\n * the flow and shows the first step whose `isComplete` is still false.\n *\n * Define a step `gate` if your screen needs to await user interactions.\n * bin.ts calls `await store.getGate(stepId)` to pause until the gate\n * predicate becomes true.\n *\n * All session mutations that affect screen resolution go through\n * explicit setters so emitChange() is always called.\n */\n\nimport { atom, map } from 'nanostores';\nimport { TaskStatus, isTaskStatus } from '../wizard-ui.js';\nimport {\n type WizardSession,\n type OutroData,\n type DiscoveredFeature,\n AdditionalFeature,\n McpOutcome,\n RunPhase,\n buildSession,\n} from '../../lib/wizard-session.js';\nimport type { SettingsConflict } from '../../lib/agent/agent-interface.js';\nimport type { WizardReadinessResult } from '../../lib/health-checks/readiness.js';\nimport {\n WizardRouter,\n type ScreenName,\n Screen,\n Overlay,\n Flow,\n} from './router.js';\nimport { analytics, sessionProperties } from '../../utils/analytics.js';\nimport type {\n StoreInitContext,\n WorkflowReadyContext,\n} from '../../lib/workflows/workflow-step.js';\nimport { WORKFLOW_STEPS } from './flows.js';\n\nexport { TaskStatus, Screen, Overlay, Flow, RunPhase, McpOutcome };\nexport type { ScreenName, OutroData, WizardSession };\n\nexport interface TaskItem {\n label: string;\n activeForm?: string;\n status: TaskStatus;\n /** Legacy compat */\n done: boolean;\n}\n\nexport interface PlannedEvent {\n name: string;\n description: string;\n}\n\ninterface GateEntry {\n predicate: (session: WizardSession) => boolean;\n promise: Promise<void>;\n resolve: () => void;\n resolved: boolean;\n}\n\nexport class WizardStore {\n // ── Internal nanostore atoms ─────────────────────────────────────\n private $session = map<WizardSession>(buildSession({}));\n private $statusMessages = atom<string[]>([]);\n private $statusExpanded = atom(false);\n private $tasks = atom<TaskItem[]>([]);\n private $eventPlan = atom<PlannedEvent[]>([]);\n private $learnCardBlockIdx = atom(0);\n private $learnCardComplete = atom(false);\n private $version = atom(0);\n\n private _onTasksChanged: (() => void) | null = null;\n /** Last screen seen — used to detect screen transitions for analytics. */\n private _lastScreen: ScreenName | null = null;\n\n /** Hooks run when transitioning onto a screen. */\n private _enterScreenHooks = new Map<ScreenName, (() => void)[]>();\n\n /** Gate promises derived from workflow step definitions. */\n private _gates = new Map<string, GateEntry>();\n\n version = '';\n\n /** Navigation router — resolves active screen from session state. */\n readonly router: WizardRouter;\n\n /** Blocks agent execution until the settings-override overlay is dismissed. */\n private _resolveSettingsOverride: (() => void) | null = null;\n private _backupAndFixSettings: (() => boolean) | null = null;\n\n /** Blocks OAuth flow until the port-conflict overlay is dismissed. */\n private _resolvePortConflict: (() => void) | null = null;\n\n constructor(flow: Flow = Flow.PostHogIntegration) {\n this.router = new WizardRouter(flow);\n this._initFromWorkflow(flow);\n }\n\n /**\n * Scan workflow steps for gate predicates and onInit callbacks.\n * Creates gate promises and fires init work.\n */\n private _initFromWorkflow(flow: Flow): void {\n const steps = WORKFLOW_STEPS[flow];\n if (!steps) return;\n\n // Create gate promises from steps that define them\n for (const step of steps) {\n if (step.gate) {\n let resolve!: () => void;\n const promise = new Promise<void>((r) => {\n resolve = r;\n });\n this._gates.set(step.id, {\n predicate: step.gate,\n promise,\n resolve,\n resolved: false,\n });\n }\n }\n\n // Run onInit callbacks with a minimal context interface.\n // Arrow functions capture `this` from _initFromWorkflow so we don't\n // need to alias it.\n const getSession = (): WizardSession => this.session;\n const ctx: StoreInitContext = {\n get session() {\n return getSession();\n },\n setReadinessResult: (r) => this.setReadinessResult(r),\n setFrameworkContext: (k, v) => this.setFrameworkContext(k, v),\n emitChange: () => this.emitChange(),\n };\n for (const step of steps) {\n step.onInit?.(ctx);\n }\n }\n\n /**\n * Run all `onReady` hooks declared by the current flow's steps, in\n * order. Must be called after `store.session = session` so hooks see\n * the real installDir. bin.ts calls this generically — it doesn't\n * need to know which workflow has which pre-flow work.\n */\n async runReadyHooks(): Promise<void> {\n const steps = WORKFLOW_STEPS[this.router.activeFlow];\n if (!steps) return;\n const ctx: WorkflowReadyContext = {\n session: this.session,\n setFrameworkContext: (k, v) => this.setFrameworkContext(k, v),\n setFrameworkConfig: (i, c) => this.setFrameworkConfig(i, c),\n setDetectedFramework: (l) => this.setDetectedFramework(l),\n setUnsupportedVersion: (info) => this.setUnsupportedVersion(info),\n addDiscoveredFeature: (f) => this.addDiscoveredFeature(f),\n setDetectionComplete: () => this.setDetectionComplete(),\n };\n for (const step of steps) {\n if (step.onReady) {\n await step.onReady(ctx);\n }\n }\n }\n\n // ── Gate API ────────────────────────────────────────────────────\n\n /**\n * Get a gate promise by step ID — the primary blocking checkpoint API\n * for bin.ts. `await store.getGate('...')` parks the caller until the\n * corresponding workflow step's gate predicate flips to true (if the\n * predicate stays false, the caller stays parked indefinitely — the\n * TUI keeps rendering so the user can resolve whatever is blocking).\n *\n * If the workflow doesn't define a step with this ID, or the step\n * has no `gate` predicate, this returns an already-resolved promise\n * so bin.ts flows straight through. This lets workflows opt in to\n * gates on a per-step basis without bin.ts needing to know which\n * gates exist in which flow.\n */\n getGate(stepId: string): Promise<void> {\n return this._gates.get(stepId)?.promise ?? Promise.resolve();\n }\n\n /**\n * Re-evaluate every gate predicate against the current session and\n * resolve any whose predicate now returns true. Called after every\n * emitChange(), so gates unblock as soon as the session mutation\n * that satisfies them lands. Gates only resolve once — a predicate\n * that goes true → false → true will NOT re-block a caller that\n * already awaited through.\n */\n private _checkGates(): void {\n for (const [, gate] of this._gates) {\n if (!gate.resolved && gate.predicate(this.session)) {\n gate.resolved = true;\n gate.resolve();\n }\n }\n }\n\n // ── State accessors (read from atoms) ────────────────────────────\n\n get session(): WizardSession {\n return this.$session.get();\n }\n\n set session(value: WizardSession) {\n this.$session.set(value);\n this.emitChange();\n }\n\n get statusMessages(): string[] {\n return this.$statusMessages.get();\n }\n\n get tasks(): TaskItem[] {\n return this.$tasks.get();\n }\n\n get eventPlan(): PlannedEvent[] {\n return this.$eventPlan.get();\n }\n\n get statusExpanded(): boolean {\n return this.$statusExpanded.get();\n }\n\n toggleStatusExpanded(): void {\n this.$statusExpanded.set(!this.$statusExpanded.get());\n this.emitChange();\n }\n\n setStatusExpanded(expanded: boolean): void {\n if (this.$statusExpanded.get() !== expanded) {\n this.$statusExpanded.set(expanded);\n this.emitChange();\n }\n }\n\n // ── Session setters ─────────────────────────────────────────────\n // Every setter that affects screen resolution calls emitChange().\n // Business logic calls these instead of mutating session directly.\n\n /** Sets setupConfirmed. Gate resolves via _checkGates(). */\n completeSetup(): void {\n this.$session.setKey('setupConfirmed', true);\n analytics.wizardCapture('setup confirmed', sessionProperties(this.session));\n this.emitChange();\n }\n\n setRunPhase(phase: RunPhase): void {\n this.$session.setKey('runPhase', phase);\n this.emitChange();\n }\n\n setCredentials(credentials: WizardSession['credentials']): void {\n this.$session.setKey('credentials', credentials);\n analytics.wizardCapture('auth complete', {\n project_id: credentials?.projectId,\n });\n this.emitChange();\n }\n\n setFrameworkConfig(\n integration: WizardSession['integration'],\n config: WizardSession['frameworkConfig'],\n ): void {\n this.$session.setKey('integration', integration);\n this.$session.setKey('frameworkConfig', config);\n this.$session.setKey('unsupportedVersion', null);\n this.emitChange();\n }\n\n setDetectionComplete(): void {\n this.$session.setKey('detectionComplete', true);\n this.emitChange();\n }\n\n setDetectedFramework(label: string): void {\n this.$session.setKey('detectedFrameworkLabel', label);\n this.emitChange();\n }\n\n setUnsupportedVersion(info: {\n current: string;\n minimum: string;\n docsUrl: string;\n }): void {\n this.$session.setKey('unsupportedVersion', info);\n this.emitChange();\n }\n\n setLoginUrl(url: string | null): void {\n this.$session.setKey('loginUrl', url);\n this.emitChange();\n }\n\n setReadinessResult(result: WizardReadinessResult | null): void {\n this.$session.setKey('readinessResult', result);\n this.emitChange();\n }\n\n /** User dismissed the blocking outage screen. Gate resolves via _checkGates(). */\n dismissOutage(): void {\n this.$session.setKey('outageDismissed', true);\n this.emitChange();\n }\n\n /**\n * Push the settings-override overlay and return a promise that blocks\n * until the user dismisses it via backupAndFixSettingsOverride().\n */\n showSettingsOverride(\n conflicts: SettingsConflict[],\n backupAndFix: () => boolean,\n ): Promise<void> {\n const allKeys = conflicts.flatMap((c) => c.keys);\n this.$session.setKey('settingsOverrideKeys', allKeys);\n this.$session.setKey('settingsConflicts', conflicts);\n this._backupAndFixSettings = backupAndFix;\n\n const hasReadOnly = conflicts.some((c) => !c.writable);\n if (hasReadOnly) {\n this.pushOverlay(Overlay.ManagedSettings);\n } else {\n this.pushOverlay(Overlay.SettingsOverride);\n }\n\n return new Promise((resolve) => {\n this._resolveSettingsOverride = resolve;\n });\n }\n\n /**\n * Push the port-conflict overlay and return a promise that blocks\n * until the user frees the ports and retries, or exits.\n */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n port: number;\n user: string;\n }): Promise<void> {\n this.$session.setKey('portConflictProcess', processInfo);\n this.pushOverlay(Overlay.PortConflict);\n return new Promise((resolve) => {\n this._resolvePortConflict = resolve;\n });\n }\n\n /** Dismiss the port-conflict overlay and retry the OAuth port loop. */\n resolvePortConflict(): void {\n this.$session.setKey('portConflictProcess', null);\n this.popOverlay();\n this._resolvePortConflict?.();\n this._resolvePortConflict = null;\n }\n\n /**\n * Back up .claude/settings.json. Dismisses the overlay on success.\n */\n backupAndFixSettingsOverride(): boolean {\n const ok = this._backupAndFixSettings?.() ?? false;\n if (ok) {\n this.$session.setKey('settingsOverrideKeys', null);\n this.$session.setKey('settingsConflicts', null);\n this.popOverlay();\n this._resolveSettingsOverride?.();\n this._resolveSettingsOverride = null;\n this._backupAndFixSettings = null;\n }\n return ok;\n }\n\n /** Push the auth-error overlay (no dismiss — user must exit). */\n showAuthError(): void {\n this.pushOverlay(Overlay.AuthError);\n }\n\n addDiscoveredFeature(feature: DiscoveredFeature): void {\n if (!this.session.discoveredFeatures.includes(feature)) {\n this.session.discoveredFeatures.push(feature);\n this.emitChange();\n }\n }\n\n /**\n * Enable an additional feature: enqueue it for the stop hook\n * and set any feature-specific session flags.\n */\n enableFeature(feature: AdditionalFeature): void {\n if (!this.session.additionalFeatureQueue.includes(feature)) {\n this.session.additionalFeatureQueue.push(feature);\n }\n // Feature-specific flags\n if (feature === AdditionalFeature.LLM) {\n this.session.llmOptIn = true;\n }\n analytics.wizardCapture('feature enabled', { feature });\n this.emitChange();\n }\n\n setMcpComplete(\n outcome: McpOutcome = McpOutcome.Skipped,\n installedClients: string[] = [],\n ): void {\n this.$session.setKey('mcpComplete', true);\n this.$session.setKey('mcpOutcome', outcome);\n this.$session.setKey('mcpInstalledClients', installedClients);\n analytics.wizardCapture('mcp complete', {\n mcp_outcome: outcome,\n mcp_installed_clients: installedClients,\n ...sessionProperties(this.session),\n });\n this.emitChange();\n }\n\n setSkillsComplete(kept: boolean): void {\n this.$session.setKey('skillsComplete', true);\n analytics.wizardCapture('skills complete', {\n skills_kept: kept,\n ...sessionProperties(this.session),\n });\n this.emitChange();\n }\n\n setOutroDismissed(): void {\n this.$session.setKey('outroDismissed', true);\n this.emitChange();\n }\n\n setOutroData(data: OutroData): void {\n this.$session.setKey('outroData', data);\n this.emitChange();\n }\n\n setFrameworkContext(key: string, value: unknown): void {\n const ctx = { ...this.$session.get().frameworkContext, [key]: value };\n this.$session.setKey('frameworkContext', ctx);\n this.emitChange();\n }\n\n // ── Derived state ───────────────────────────────────────────────\n\n /**\n * The screen that should be rendered right now.\n * Derived from session state via the router.\n */\n get currentScreen(): ScreenName {\n return this.router.resolve(this.session);\n }\n\n /** Direction hint for screen transitions. */\n get lastNavDirection(): 'push' | 'pop' | null {\n return this.router.lastNavDirection;\n }\n\n // ── Change notification ─────────────────────────────────────────\n\n getVersion(): number {\n return this.$version.get();\n }\n\n /**\n * Notify React that state has changed.\n * The router re-resolves the active screen on next render.\n * Gate predicates are checked and resolved if ready.\n */\n emitChange(): void {\n this.router._setDirection('push');\n this.$version.set(this.$version.get() + 1);\n this._checkGates();\n this._detectTransition();\n }\n\n // ── Overlay navigation ──────────────────────────────────────────\n\n pushOverlay(overlay: Overlay): void {\n this.router._setDirection('push');\n this.router.pushOverlay(overlay);\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n popOverlay(): void {\n this.router._setDirection('pop');\n this.router.popOverlay();\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n // ── Screen transition analytics ─────────────────────────────────\n\n /**\n * Register a callback to run when transitioning onto the given screen.\n * Fires after every transition that lands on this screen.\n */\n onEnterScreen(screen: ScreenName, fn: () => void): void {\n const list = this._enterScreenHooks.get(screen) ?? [];\n list.push(fn);\n this._enterScreenHooks.set(screen, list);\n }\n\n /**\n * Detect screen transitions, run enter-screen hooks, and fire analytics.\n * Called at the end of emitChange/pushOverlay/popOverlay.\n */\n private _detectTransition(): void {\n const next = this.router.resolve(this.session);\n const prev = this._lastScreen;\n if (prev !== null && next !== prev) {\n const hooks = this._enterScreenHooks.get(next);\n if (hooks) {\n for (const fn of hooks) fn();\n }\n analytics.wizardCapture(`screen ${next}`, {\n from_screen: prev,\n workflow: this.router.activeFlow,\n ...sessionProperties(this.session),\n });\n }\n this._lastScreen = next;\n }\n\n // ── Agent observation state ─────────────────────────────────────\n\n pushStatus(message: string): void {\n const msgs = this.$statusMessages.get();\n // Skip consecutive duplicate messages\n if (msgs.length > 0 && msgs[msgs.length - 1] === message) return;\n this.$statusMessages.set([...msgs, message]);\n this.emitChange();\n }\n\n setTasks(tasks: TaskItem[]): void {\n this.$tasks.set(tasks);\n this.emitChange();\n }\n\n updateTask(index: number, done: boolean): void {\n const tasks = this.$tasks.get();\n if (tasks[index]) {\n const updated = [...tasks];\n updated[index] = {\n ...updated[index],\n done,\n status: done ? TaskStatus.Completed : TaskStatus.Pending,\n };\n this.$tasks.set(updated);\n this.emitChange();\n }\n }\n\n setEventPlan(events: PlannedEvent[]): void {\n this.$eventPlan.set(events);\n this.emitChange();\n }\n\n get learnCardBlockIdx(): number {\n return this.$learnCardBlockIdx.get();\n }\n\n setLearnCardBlockIdx(idx: number): void {\n this.$learnCardBlockIdx.set(idx);\n }\n\n get learnCardComplete(): boolean {\n return this.$learnCardComplete.get();\n }\n\n setLearnCardComplete(): void {\n this.$learnCardComplete.set(true);\n this.emitChange();\n }\n\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void {\n const incoming = todos.map((t) => {\n const status = isTaskStatus(t.status) ? t.status : TaskStatus.Pending;\n return {\n label: t.content,\n activeForm: t.activeForm,\n status,\n done: status === TaskStatus.Completed,\n };\n });\n\n const incomingLabels = new Set(incoming.map((t) => t.label));\n\n const retained = this.$tasks\n .get()\n .filter((t) => t.done && !incomingLabels.has(t.label));\n\n this.$tasks.set([...retained, ...incoming]);\n this.emitChange();\n this._onTasksChanged?.();\n }\n\n /** Register a listener for task state changes (e.g. task stream push). */\n set onTasksChanged(fn: () => void) {\n this._onTasksChanged = fn;\n }\n\n // ── React integration ───────────────────────────────────────────\n\n subscribe(callback: () => void): () => void {\n return this.$version.listen(() => callback());\n }\n\n getSnapshot(): number {\n return this.$version.get();\n }\n}\n","/**\n * Shared style constants for TUI layout primitives.\n */\n\nexport enum HAlign {\n Left = 'flex-start',\n Center = 'center',\n Right = 'flex-end',\n}\n\nexport enum VAlign {\n Top = 'flex-start',\n Center = 'center',\n Bottom = 'flex-end',\n}\n\nexport const Colors = {\n primary: 'cyan',\n accent: '#DC9300',\n titleColor: '#3D2800',\n success: 'green',\n error: 'red',\n muted: 'gray',\n} as const;\n\nexport const Icons = {\n diamond: '\\u25C6',\n diamondOpen: '\\u25C7',\n check: '\\u2714',\n warning: '\\u26A0',\n squareFilled: '\\u25FC',\n squareOpen: '\\u25FB',\n triangleRight: '\\u25B6',\n triangleSmallRight: '\\u25B8',\n bullet: '\\u2022',\n} as const;\n","/**\n * CardLayout — Aligns a single child within available space.\n */\n\nimport { Box } from 'ink';\nimport type { ReactNode } from 'react';\nimport { HAlign, VAlign } from '../styles.js';\n\ninterface CardLayoutProps {\n hAlign?: HAlign;\n vAlign?: VAlign;\n children: ReactNode;\n}\n\nexport const CardLayout = ({\n hAlign = HAlign.Left,\n vAlign = VAlign.Top,\n children,\n}: CardLayoutProps) => {\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n justifyContent={vAlign}\n alignItems={hAlign}\n >\n {children}\n </Box>\n );\n};\n","/**\n * SplitView — Two-pane horizontal layout: 50/50.\n */\n\nimport { Box } from 'ink';\nimport type { ReactNode } from 'react';\n\ninterface SplitViewProps {\n left: ReactNode;\n right: ReactNode;\n gap?: number;\n}\n\nexport const SplitView = ({ left, right, gap = 2 }: SplitViewProps) => {\n return (\n <Box flexDirection=\"row\" flexGrow={1} flexShrink={1} gap={gap}>\n <Box width=\"50%\" flexDirection=\"column\" overflow=\"hidden\">\n {left}\n </Box>\n <Box width=\"50%\" flexDirection=\"column\" overflow=\"hidden\">\n {right}\n </Box>\n </Box>\n );\n};\n","/**\n * LoadingBox — Spinner with message.\n */\n\nimport { Box, Text } from 'ink';\nimport { Spinner } from '@inkjs/ui';\n\ninterface LoadingBoxProps {\n message: string;\n}\n\nexport const LoadingBox = ({ message }: LoadingBoxProps) => {\n return (\n <Box gap={1}>\n <Spinner />\n <Text>{message}</Text>\n </Box>\n );\n};\n","/**\n * ProgressList — Reusable task checklist with status icons.\n * Extracted from StatusTab logic.\n */\n\nimport { Box, Text } from 'ink';\nimport { Spinner } from '@inkjs/ui';\nimport { Colors, Icons } from '../styles.js';\nimport { LoadingBox } from './LoadingBox.js';\n\nexport interface ProgressItem {\n label: string;\n activeForm?: string;\n status: 'pending' | 'in_progress' | 'completed';\n}\n\ninterface ProgressListProps {\n items: ProgressItem[];\n title?: string;\n}\n\nexport const ProgressList = ({ items, title }: ProgressListProps) => {\n const completed = items.filter((t) => t.status === 'completed').length;\n const total = items.length;\n\n return (\n <Box flexDirection=\"column\">\n {title && (\n <>\n <Text bold>{title}</Text>\n <Text> </Text>\n </>\n )}\n {items.length === 0 && <LoadingBox message=\"Analyzing project...\" />}\n {items.map((item, i) => {\n const icon =\n item.status === 'completed'\n ? Icons.squareFilled\n : item.status === 'in_progress'\n ? Icons.triangleRight\n : Icons.squareOpen;\n const color =\n item.status === 'completed'\n ? Colors.success\n : item.status === 'in_progress'\n ? Colors.primary\n : Colors.muted;\n const label =\n item.status === 'in_progress' && item.activeForm\n ? item.activeForm\n : item.label;\n\n return (\n <Text key={i}>\n <Text color={color}>{icon}</Text>\n <Text dimColor={item.status === 'pending'}> {label}</Text>\n </Text>\n );\n })}\n {total > 0 && (\n <Box marginTop={1} gap={1}>\n <Spinner />\n <Text dimColor>\n {completed < total\n ? `Progress: ${completed}/${total} completed`\n : 'Cleaning up...'}\n </Text>\n </Box>\n )}\n </Box>\n );\n};\n","/**\n * PromptLabel — Compact inline label for input prompts.\n *\n * Renders: [!] message\n * where [!] is black text on accent background.\n */\n\nimport { Box, Text } from 'ink';\nimport { Colors } from '../styles.js';\n\ninterface PromptLabelProps {\n message?: string;\n}\n\nexport const PromptLabel = ({ message }: PromptLabelProps) => {\n return (\n <Box>\n <Text bold color={Colors.accent}>\n {' '}\n {message}\n </Text>\n </Box>\n );\n};\n","/**\n * Pure utility functions for keyboard hints — no React or Ink dependencies.\n * Extracted for testability in a node Jest environment.\n */\n\nexport interface KeyboardHint {\n label: string;\n action: string;\n priority: number;\n}\n\n/** Well-known key matches corresponding to Ink's key.* properties. */\nexport enum KeyMatch {\n UpArrow = 'upArrow',\n DownArrow = 'downArrow',\n LeftArrow = 'leftArrow',\n RightArrow = 'rightArrow',\n Return = 'return',\n Escape = 'escape',\n Space = 'space',\n}\n\n/** A key match: either a KeyMatch enum value or a literal character string (e.g. 'a', 's'). */\nexport type KeyMatchOrChar = KeyMatch | (string & NonNullable<unknown>);\n\n/** Default priorities by key type. */\nconst DEFAULT_PRIORITY: Record<string, number> = {\n [KeyMatch.UpArrow]: 0,\n [KeyMatch.DownArrow]: 0,\n [KeyMatch.LeftArrow]: 1,\n [KeyMatch.RightArrow]: 1,\n [KeyMatch.Space]: 10,\n [KeyMatch.Escape]: 20,\n [KeyMatch.Return]: 21,\n};\n\n/** Get the default display priority for a key match. */\nexport function getDefaultPriority(\n match: KeyMatchOrChar | KeyMatchOrChar[],\n): number {\n const first = Array.isArray(match) ? match[0] : match;\n return DEFAULT_PRIORITY[first] ?? 15;\n}\n\n/** Check if a KeyMatchOrChar matches the given input string and key flags. */\nexport function matchesKey(\n m: KeyMatchOrChar,\n input: string,\n key: { [k: string]: unknown },\n): boolean {\n switch (m) {\n case KeyMatch.UpArrow:\n return !!key.upArrow;\n case KeyMatch.DownArrow:\n return !!key.downArrow;\n case KeyMatch.LeftArrow:\n return !!key.leftArrow;\n case KeyMatch.RightArrow:\n return !!key.rightArrow;\n case KeyMatch.Return:\n return !!key.return;\n case KeyMatch.Escape:\n return !!key.escape;\n case KeyMatch.Space:\n return input === ' ';\n default:\n return input === m;\n }\n}\n\n/** Serialize hints for comparison. */\nexport function hintsKey(hints: KeyboardHint[]): string {\n return hints.map((h) => `${h.label}:${h.action}`).join('|');\n}\n\n/** Deduplicate hints by label+action and sort by priority. */\nexport function deduplicateAndSort(hints: KeyboardHint[]): KeyboardHint[] {\n const seen = new Set<string>();\n const deduped: KeyboardHint[] = [];\n for (const hint of hints) {\n const k = `${hint.label}:${hint.action}`;\n if (!seen.has(k)) {\n seen.add(k);\n deduped.push(hint);\n }\n }\n deduped.sort((a, b) => a.priority - b.priority);\n return deduped;\n}\n","/**\n * KeyboardHintsProvider — Context for collecting and displaying keyboard hints.\n *\n * Input components register their hints via useKeyBindings. The provider\n * flattens, deduplicates, and sorts them. It auto-dismisses 3s after the\n * first keypress and resets when the hint set changes (screen navigation).\n */\n\nimport { useInput } from 'ink';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport {\n hintsKey,\n deduplicateAndSort,\n type KeyboardHint,\n} from './keyboard-hints-utils.js';\n\nexport type { KeyboardHint } from './keyboard-hints-utils.js';\n\ninterface KeyboardHintsContextValue {\n register(id: string, hints: KeyboardHint[]): void;\n unregister(id: string): void;\n hints: KeyboardHint[];\n visible: boolean;\n}\n\nconst KeyboardHintsContext = createContext<KeyboardHintsContextValue>({\n register: () => undefined,\n unregister: () => undefined,\n hints: [],\n visible: false,\n});\n\nexport const useKeyboardHintsContext = () => useContext(KeyboardHintsContext);\n\nconst DISMISS_DELAY = 3000;\n\nexport const KeyboardHintsProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => {\n const registrationsRef = useRef(new Map<string, KeyboardHint[]>());\n const [hints, setHints] = useState<KeyboardHint[]>([]);\n const [visible, setVisible] = useState(true);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const prevHintsKeyRef = useRef('');\n\n const recompute = useCallback(() => {\n const all: KeyboardHint[] = [];\n for (const h of registrationsRef.current.values()) {\n all.push(...h);\n }\n const deduped = deduplicateAndSort(all);\n\n const newKey = hintsKey(deduped);\n if (newKey !== prevHintsKeyRef.current) {\n prevHintsKeyRef.current = newKey;\n setHints(deduped);\n // Reset visibility when hints change (new screen)\n if (newKey.length > 0) {\n setVisible(true);\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n }\n }\n }, []);\n\n const register = useCallback(\n (id: string, h: KeyboardHint[]) => {\n registrationsRef.current.set(id, h);\n recompute();\n },\n [recompute],\n );\n\n const unregister = useCallback(\n (id: string) => {\n registrationsRef.current.delete(id);\n recompute();\n },\n [recompute],\n );\n\n // Dismiss on first keypress after 3s\n useInput(() => {\n if (!visible) return;\n if (timerRef.current) return; // already counting down\n timerRef.current = setTimeout(() => {\n setVisible(false);\n timerRef.current = null;\n }, DISMISS_DELAY);\n });\n\n // Cleanup timer on unmount\n useEffect(() => {\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n };\n }, []);\n\n return (\n <KeyboardHintsContext.Provider\n value={{ register, unregister, hints, visible }}\n >\n {children}\n </KeyboardHintsContext.Provider>\n );\n};\n","/**\n * useKeyBindings — Declarative keyboard input + automatic hint registration.\n *\n * Replaces raw `useInput` in input components. Define bindings as data;\n * the hook wires up the Ink input handler AND registers hints in the\n * KeyboardHintsProvider. One source of truth for keys and their labels.\n */\n\nimport { useInput, type Key } from 'ink';\nimport { useEffect, useRef } from 'react';\nimport { useKeyboardHintsContext } from './useKeyboardHints.js';\nimport {\n matchesKey,\n getDefaultPriority,\n KeyMatch,\n type KeyboardHint,\n type KeyMatchOrChar,\n} from './keyboard-hints-utils.js';\n\nexport { KeyMatch };\nexport type { KeyMatchOrChar } from './keyboard-hints-utils.js';\n\nexport interface KeyBinding {\n /** Which key(s) trigger this binding. Array = multiple keys, one hint. */\n match: KeyMatchOrChar | KeyMatchOrChar[];\n /** Display label in hints bar (e.g. \"↑↓\", \"space\", \"enter\") */\n label: string;\n /** Description in hints bar (e.g. \"navigate\", \"toggle\") */\n action: string;\n /** Ordering priority (lower = further left). Defaults based on key type. */\n priority?: number;\n /** Handler called when the key matches. */\n handler: (input: string, key: Key) => void;\n}\n\n/**\n * Declarative key bindings hook. Replaces `useInput` in input components.\n * Registers hints automatically with the KeyboardHintsProvider.\n *\n * @param id Unique identifier for this component's hints registration\n * @param bindings Array of key binding definitions\n */\nexport function useKeyBindings(id: string, bindings: KeyBinding[]): void {\n const ctx = useKeyboardHintsContext();\n\n // Extract hints and register. Use a serialized key to avoid unnecessary updates.\n const hintsRef = useRef<string>('');\n const hints: KeyboardHint[] = bindings.map((b) => ({\n label: b.label,\n action: b.action,\n priority: b.priority ?? getDefaultPriority(b.match),\n }));\n const serialized = hints\n .map((h) => `${h.label}:${h.action}:${h.priority}`)\n .join('|');\n\n useEffect(() => {\n if (serialized !== hintsRef.current) {\n hintsRef.current = serialized;\n ctx.register(id, hints);\n }\n return () => ctx.unregister(id);\n // eslint-disable-next-line\n }, [id, serialized]);\n\n // Wire up input handling\n useInput((input, key) => {\n for (const binding of bindings) {\n const matches = Array.isArray(binding.match)\n ? binding.match\n : [binding.match];\n if (matches.some((m) => matchesKey(m, input, key))) {\n binding.handler(input, key);\n return;\n }\n }\n });\n}\n","/**\n * PickerMenu — Single and multi select.\n * Single mode: custom renderer with small triangle indicator.\n * Multi mode: checkbox glyphs with space to toggle.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState } from 'react';\nimport { Icons, Colors } from '../styles.js';\nimport { PromptLabel } from './PromptLabel.js';\nimport {\n useKeyBindings,\n KeyMatch,\n type KeyBinding,\n} from '../hooks/useKeyBindings.js';\n\ninterface PickerOption<T> {\n label: string;\n value: T;\n hint?: string;\n}\n\ninterface PickerMenuProps<T> {\n message?: string;\n options: PickerOption<T>[];\n mode?: 'single' | 'multi';\n centered?: boolean;\n columns?: 1 | 2 | 3 | 4;\n onSelect: (value: T | T[]) => void;\n}\n\nexport const PickerMenu = <T,>({\n message,\n options,\n mode = 'single',\n centered = false,\n columns = 1,\n onSelect,\n}: PickerMenuProps<T>) => {\n if (mode === 'multi') {\n return (\n <MultiPickerMenu\n message={message}\n options={options}\n centered={centered}\n columns={columns}\n onSelect={onSelect}\n />\n );\n }\n\n return (\n <SinglePickerMenu\n message={message}\n options={options}\n centered={centered}\n columns={columns}\n onSelect={onSelect}\n />\n );\n};\n\n/** Custom single-select with triangle indicator and accent highlight. */\nconst SinglePickerMenu = <T,>({\n message,\n options,\n centered = false,\n columns = 1,\n onSelect,\n}: {\n message?: string;\n options: PickerOption<T>[];\n centered?: boolean;\n columns?: number;\n onSelect: (value: T | T[]) => void;\n}) => {\n const [focused, setFocused] = useState(0);\n const rows = Math.ceil(options.length / columns);\n\n const bindings: KeyBinding[] = [\n {\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '\\u2191\\u2193',\n action: 'navigate',\n handler: (_input, key) => {\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n\n if (key.upArrow) {\n if (row > 0) {\n setFocused(col * rows + row - 1);\n } else {\n setFocused(Math.min(col * rows + rows - 1, options.length - 1));\n }\n }\n if (key.downArrow) {\n const next = col * rows + row + 1;\n if (next < options.length && row + 1 < rows) {\n setFocused(next);\n } else {\n setFocused(col * rows);\n }\n }\n },\n },\n {\n match: KeyMatch.Return,\n label: 'enter',\n action: 'select',\n handler: () => {\n const selected = options[focused];\n if (selected) {\n onSelect(selected.value);\n }\n },\n },\n ];\n\n if (columns > 1) {\n bindings.splice(1, 0, {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'navigate',\n handler: (_input, key) => {\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n\n if (key.leftArrow) {\n const prevCol = col > 0 ? col - 1 : columns - 1;\n setFocused(Math.min(prevCol * rows + row, options.length - 1));\n }\n if (key.rightArrow) {\n const nextCol = col < columns - 1 ? col + 1 : 0;\n setFocused(Math.min(nextCol * rows + row, options.length - 1));\n }\n },\n });\n }\n\n useKeyBindings('single-picker', bindings);\n\n // Chunk options into columns (column-first ordering)\n const columnArrays: PickerOption<T>[][] = [];\n for (let c = 0; c < columns; c++) {\n columnArrays.push(options.slice(c * rows, c * rows + rows));\n }\n\n const align = centered ? 'center' : undefined;\n\n return (\n <Box flexDirection=\"column\" alignItems={align}>\n <PromptLabel message={message} />\n <Box flexDirection=\"row\" gap={4}>\n {columnArrays.map((colOpts, colIdx) => (\n <Box key={colIdx} flexDirection=\"column\">\n {colOpts.map((opt, rowIdx) => {\n const flatIdx = colIdx * rows + rowIdx;\n const isFocused = flatIdx === focused;\n const label = opt.hint ? `${opt.label} (${opt.hint})` : opt.label;\n return (\n <Box key={flatIdx} gap={1}>\n <Text\n color={isFocused ? Colors.accent : undefined}\n dimColor={!isFocused}\n >\n {isFocused ? Icons.triangleSmallRight : ' '}\n </Text>\n <Text\n color={isFocused ? Colors.accent : undefined}\n bold={isFocused}\n dimColor={!isFocused}\n >\n {label}\n </Text>\n </Box>\n );\n })}\n </Box>\n ))}\n </Box>\n </Box>\n );\n};\n\n/** Custom multi-select with checkbox glyphs and accent highlight. */\nconst MultiPickerMenu = <T,>({\n message,\n options,\n centered = false,\n columns = 1,\n onSelect,\n}: {\n message?: string;\n options: PickerOption<T>[];\n centered?: boolean;\n columns?: number;\n onSelect: (value: T | T[]) => void;\n}) => {\n const [focused, setFocused] = useState(0);\n const [selected, setSelected] = useState<Set<number>>(new Set());\n const rows = Math.ceil(options.length / columns);\n\n const bindings: KeyBinding[] = [\n {\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '\\u2191\\u2193',\n action: 'navigate',\n handler: (_input, key) => {\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n\n if (key.upArrow) {\n if (row > 0) {\n setFocused(col * rows + row - 1);\n } else {\n setFocused(Math.min(col * rows + rows - 1, options.length - 1));\n }\n }\n if (key.downArrow) {\n const next = col * rows + row + 1;\n if (next < options.length && row + 1 < rows) {\n setFocused(next);\n } else {\n setFocused(col * rows);\n }\n }\n },\n },\n {\n match: KeyMatch.Space,\n label: 'space',\n action: 'toggle',\n handler: () => {\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(focused)) {\n next.delete(focused);\n } else {\n next.add(focused);\n }\n return next;\n });\n },\n },\n {\n match: KeyMatch.Return,\n label: 'enter',\n action: 'confirm',\n handler: () => {\n if (selected.size === 0) {\n const hovered = options[focused];\n if (hovered) {\n onSelect(hovered.value);\n }\n } else {\n const values = [...selected].sort().map((i) => options[i].value);\n onSelect(values);\n }\n },\n },\n ];\n\n if (columns > 1) {\n bindings.splice(1, 0, {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'navigate',\n handler: (_input, key) => {\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n\n if (key.leftArrow) {\n const prevCol = col > 0 ? col - 1 : columns - 1;\n setFocused(Math.min(prevCol * rows + row, options.length - 1));\n }\n if (key.rightArrow) {\n const nextCol = col < columns - 1 ? col + 1 : 0;\n setFocused(Math.min(nextCol * rows + row, options.length - 1));\n }\n },\n });\n }\n\n useKeyBindings('multi-picker', bindings);\n\n const columnArrays: PickerOption<T>[][] = [];\n for (let c = 0; c < columns; c++) {\n columnArrays.push(options.slice(c * rows, c * rows + rows));\n }\n\n return (\n <Box flexDirection=\"column\" alignItems={centered ? 'center' : undefined}>\n <PromptLabel message={message} />\n <Box\n flexDirection=\"row\"\n gap={4}\n marginLeft={centered ? 0 : 2}\n marginTop={1}\n >\n {columnArrays.map((colOpts, colIdx) => (\n <Box key={colIdx} flexDirection=\"column\">\n {colOpts.map((opt, rowIdx) => {\n const flatIdx = colIdx * rows + rowIdx;\n const isFocused = flatIdx === focused;\n const isSelected = selected.has(flatIdx);\n const label = opt.hint ? `${opt.label} (${opt.hint})` : opt.label;\n const checkbox = isSelected\n ? Icons.squareFilled\n : Icons.squareOpen;\n return (\n <Box key={flatIdx} gap={1}>\n <Text\n color={isSelected ? 'white' : Colors.muted}\n dimColor={!isFocused && !isSelected}\n >\n {checkbox}\n </Text>\n <Text\n color={isFocused ? Colors.accent : undefined}\n bold={isFocused}\n dimColor={!isFocused}\n >\n {label}\n </Text>\n </Box>\n );\n })}\n </Box>\n ))}\n </Box>\n </Box>\n );\n};\n","/**\n * useStdoutDimensions — Returns [columns, rows] and re-renders on terminal resize.\n *\n * Ink's useStdout() does not subscribe to resize events, so layout only updates\n * when something else causes a re-render. This hook listens to the stream's\n * 'resize' event (Node TTY) and updates state so the component re-renders\n * with the new dimensions.\n */\n\nimport { useStdout } from 'ink';\nimport { useState, useEffect } from 'react';\n\nexport function useStdoutDimensions(): [number, number] {\n const { stdout } = useStdout();\n const [size, setSize] = useState<[number, number]>(() => [\n stdout.columns || 80,\n stdout.rows || 24,\n ]);\n\n useEffect(() => {\n const cols = stdout.columns || 80;\n const rows = stdout.rows || 24;\n setSize([cols, rows]);\n\n const stream = stdout as NodeJS.WriteStream & {\n on?(event: string, fn: () => void): void;\n };\n if (typeof stream.on !== 'function') return;\n\n const onResize = () => {\n const c = stdout.columns || 80;\n const r = stdout.rows || 24;\n if (c > 0 && r > 0) setSize([c, r]);\n };\n stream.on('resize', onResize);\n return () => {\n stream.off?.('resize', onResize);\n };\n }, [stdout]);\n\n return size;\n}\n","/**\n * GroupedPickerMenu — Multi-select with category headers.\n *\n * Renders groups of options with bold category labels.\n * Arrow keys navigate selectable items (headers are skipped),\n * space toggles, \"a\" toggles all, enter submits.\n *\n * When content exceeds available terminal height, the list scrolls\n * to keep the focused item visible with up/down indicators.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useMemo } from 'react';\nimport { Icons, Colors } from '../styles.js';\nimport { PromptLabel } from './PromptLabel.js';\nimport { useStdoutDimensions } from '../hooks/useStdoutDimensions.js';\nimport { useKeyBindings, KeyMatch } from '../hooks/useKeyBindings.js';\n\ninterface GroupOption {\n value: string;\n label: string;\n hint?: string;\n}\n\ninterface GroupedPickerMenuProps {\n message?: string;\n groups: Record<string, GroupOption[]>;\n initialSelected?: string[];\n onSelect: (values: string[]) => void;\n}\n\ntype Row =\n | { kind: 'header'; label: string }\n | { kind: 'option'; value: string; label: string; hint?: string };\n\n/** Truncate text with \"\\u2026\" if it exceeds maxWidth. */\nfunction truncateWithEllipsis(text: string, maxWidth: number): string {\n if (text.length <= maxWidth) return text;\n return text.slice(0, maxWidth - 1) + '\\u2026';\n}\n\n/** Rows consumed by chrome outside this component (title bar, screen padding, etc.) */\nconst CHROME_OVERHEAD = 10;\n/** Rows used by the prompt label + marginTop before content (hint text moved to KeyboardHintsBar). */\nconst MENU_CHROME = 2;\n\n/** Count the visual rows occupied by rows[start..end), accounting for header margins. */\nfunction countVisualRows(rows: Row[], start: number, end: number): number {\n let count = 0;\n for (let i = start; i < end && i < rows.length; i++) {\n if (rows[i].kind === 'header' && i > start) count += 1; // marginTop gap\n count += 1;\n }\n return count;\n}\n\n/** From scrollOffset, find how many flat rows fit in the visual budget. */\nfunction computeVisibleEnd(\n rows: Row[],\n scrollOffset: number,\n budget: number,\n): number {\n let visualCount = 0;\n let i = scrollOffset;\n while (i < rows.length) {\n const cost = rows[i].kind === 'header' && i > scrollOffset ? 2 : 1;\n if (visualCount + cost > budget) break;\n visualCount += cost;\n i++;\n }\n return i;\n}\n\n/** Adjust scroll offset to keep focusedRowIdx visible within the viewport. */\nfunction adjustScrollOffset(\n currentOffset: number,\n focusedRowIdx: number,\n rows: Row[],\n viewportBudget: number,\n): number {\n const visibleEnd = computeVisibleEnd(rows, currentOffset, viewportBudget);\n\n // Already visible\n if (focusedRowIdx >= currentOffset && focusedRowIdx < visibleEnd) {\n return currentOffset;\n }\n\n // Focus moved above viewport — scroll up, including group header if adjacent\n if (focusedRowIdx < currentOffset) {\n let newOffset = focusedRowIdx;\n if (newOffset > 0 && rows[newOffset - 1]?.kind === 'header') {\n newOffset--;\n }\n return Math.max(0, newOffset);\n }\n\n // Focus moved below viewport — scroll down minimally\n let newOffset = currentOffset + 1;\n while (newOffset < rows.length) {\n const end = computeVisibleEnd(rows, newOffset, viewportBudget);\n if (focusedRowIdx < end) break;\n newOffset++;\n }\n return Math.min(newOffset, Math.max(0, rows.length - 1));\n}\n\nexport const GroupedPickerMenu = ({\n message,\n groups,\n initialSelected,\n onSelect,\n}: GroupedPickerMenuProps) => {\n const [termCols, termRows] = useStdoutDimensions();\n\n // Available width for option labels, after subtracting layout chrome:\n // paddingX(2) + marginLeft(2) + option marginLeft(1) + gap(1) + checkbox(2) = 8\n const labelWidth = Math.max(10, Math.min(termCols, 120) - 8);\n\n // Build a flat row list with headers interleaved\n const rows = useMemo<Row[]>(() => {\n const result: Row[] = [];\n for (const [groupName, options] of Object.entries(groups)) {\n result.push({ kind: 'header', label: groupName });\n for (const opt of options) {\n result.push({ kind: 'option', ...opt });\n }\n }\n return result;\n }, [groups]);\n\n // Indices of selectable (non-header) rows\n const selectableIndices = useMemo(\n () =>\n rows.map((r, i) => (r.kind === 'option' ? i : -1)).filter((i) => i >= 0),\n [rows],\n );\n\n // All option values for toggle-all\n const allValues = useMemo(\n () =>\n rows\n .filter((r): r is Row & { kind: 'option' } => r.kind === 'option')\n .map((r) => r.value),\n [rows],\n );\n\n const [focusedSelectable, setFocusedSelectable] = useState(0);\n const [selected, setSelected] = useState<Set<string>>(\n () => new Set(initialSelected ?? allValues),\n );\n const [scrollOffset, setScrollOffset] = useState(0);\n\n const focusedRowIdx = selectableIndices[focusedSelectable] ?? 0;\n\n // Viewport budget: how many visual rows can be shown\n const viewportBudget = Math.max(5, termRows - CHROME_OVERHEAD - MENU_CHROME);\n const totalVisual = countVisualRows(rows, 0, rows.length);\n const needsScroll = totalVisual > viewportBudget;\n const effectiveBudget = needsScroll ? viewportBudget - 2 : viewportBudget;\n\n useKeyBindings('grouped-picker', [\n {\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '\\u2191\\u2193',\n action: 'navigate',\n handler: (_input, key) => {\n let newFocused = focusedSelectable;\n\n if (key.upArrow) {\n newFocused =\n focusedSelectable > 0\n ? focusedSelectable - 1\n : selectableIndices.length - 1;\n }\n if (key.downArrow) {\n newFocused =\n focusedSelectable < selectableIndices.length - 1\n ? focusedSelectable + 1\n : 0;\n }\n\n if (newFocused !== focusedSelectable) {\n setFocusedSelectable(newFocused);\n if (needsScroll) {\n const newFocusedRowIdx = selectableIndices[newFocused] ?? 0;\n setScrollOffset((prev) =>\n adjustScrollOffset(prev, newFocusedRowIdx, rows, effectiveBudget),\n );\n }\n }\n },\n },\n {\n match: KeyMatch.Space,\n label: 'space',\n action: 'toggle',\n handler: () => {\n const targetRowIdx = selectableIndices[focusedSelectable] ?? 0;\n const row = rows[targetRowIdx];\n if (row?.kind === 'option') {\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(row.value)) {\n next.delete(row.value);\n } else {\n next.add(row.value);\n }\n return next;\n });\n }\n },\n },\n {\n match: 'a',\n label: 'a',\n action: 'toggle all',\n priority: 11,\n handler: () => {\n setSelected((prev) => {\n if (prev.size === allValues.length) {\n return new Set();\n }\n return new Set(allValues);\n });\n },\n },\n {\n match: KeyMatch.Return,\n label: 'enter',\n action: 'confirm',\n handler: () => {\n onSelect([...selected]);\n },\n },\n ]);\n\n // Determine visible slice\n const visibleStart = needsScroll ? scrollOffset : 0;\n const visibleEnd = needsScroll\n ? computeVisibleEnd(rows, visibleStart, effectiveBudget)\n : rows.length;\n const visibleRows = rows.slice(visibleStart, visibleEnd);\n const hiddenAbove = needsScroll\n ? selectableIndices.filter((s) => s < visibleStart).length\n : 0;\n const hiddenBelow = needsScroll\n ? selectableIndices.filter((s) => s >= visibleEnd).length\n : 0;\n\n return (\n <Box flexDirection=\"column\">\n <PromptLabel message={message} />\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n {needsScroll && (\n <Text dimColor>\n {hiddenAbove > 0 ? `\\u2191 ${hiddenAbove} more` : ' '}\n </Text>\n )}\n {visibleRows.map((row, relIdx) => {\n const absIdx = visibleStart + relIdx;\n\n if (row.kind === 'header') {\n return (\n <Box\n key={`h-${absIdx}`}\n marginTop={relIdx > 0 && absIdx > 0 ? 1 : 0}\n >\n <Text bold dimColor>\n {row.label}\n </Text>\n </Box>\n );\n }\n\n const isFocused = focusedRowIdx === absIdx;\n const isSelected = selected.has(row.value);\n const checkbox = isSelected ? Icons.squareFilled : Icons.squareOpen;\n const fullLabel = row.hint ? `${row.label} (${row.hint})` : row.label;\n const label = truncateWithEllipsis(fullLabel, labelWidth);\n\n return (\n <Box key={row.value} gap={1} marginLeft={1}>\n <Text\n color={isSelected ? 'white' : Colors.muted}\n dimColor={!isFocused && !isSelected}\n >\n {checkbox}\n </Text>\n <Box flexGrow={1} flexShrink={1} overflow=\"hidden\">\n <Text\n color={isFocused ? Colors.accent : undefined}\n bold={isFocused}\n dimColor={!isFocused}\n wrap=\"truncate\"\n >\n {label}\n </Text>\n </Box>\n </Box>\n );\n })}\n {needsScroll && (\n <Text dimColor>\n {hiddenBelow > 0 ? `\\u2193 ${hiddenBelow} more` : ' '}\n </Text>\n )}\n </Box>\n </Box>\n );\n};\n","/**\n * ConfirmationInput — Continue/cancel prompt.\n * Enter confirms, escape cancels. Arrow keys toggle focus.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState } from 'react';\nimport { Icons, Colors } from '../styles.js';\nimport { PromptLabel } from './PromptLabel.js';\nimport { useKeyBindings, KeyMatch } from '../hooks/useKeyBindings.js';\n\ninterface ConfirmationInputProps {\n message: string;\n onConfirm: () => void;\n onCancel: () => void;\n confirmLabel?: string;\n cancelLabel?: string;\n}\n\nenum FocusTarget {\n Continue = 'continue',\n Cancel = 'cancel',\n}\n\nexport const ConfirmationInput = ({\n message,\n onConfirm,\n onCancel,\n confirmLabel = 'Continue',\n cancelLabel = 'Cancel',\n}: ConfirmationInputProps) => {\n const [focused, setFocused] = useState<FocusTarget>(FocusTarget.Continue);\n\n useKeyBindings('confirmation', [\n {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'switch',\n handler: () => {\n setFocused((f) =>\n f === FocusTarget.Continue\n ? FocusTarget.Cancel\n : FocusTarget.Continue,\n );\n },\n },\n {\n match: KeyMatch.Return,\n label: 'enter',\n action: 'confirm',\n handler: () => {\n if (focused === FocusTarget.Continue) {\n onConfirm();\n } else {\n onCancel();\n }\n },\n },\n {\n match: KeyMatch.Escape,\n label: 'esc',\n action: 'cancel',\n handler: () => {\n onCancel();\n },\n },\n ]);\n\n return (\n <Box flexDirection=\"column\">\n <PromptLabel message={message} />\n <Box gap={2} marginTop={1} marginLeft={2}>\n <Text\n bold={focused === FocusTarget.Continue}\n color={\n focused === FocusTarget.Continue ? Colors.accent : Colors.muted\n }\n >\n {focused === FocusTarget.Continue ? Icons.triangleSmallRight : ' '}{' '}\n {confirmLabel}\n </Text>\n <Text\n bold={focused === FocusTarget.Cancel}\n color={focused === FocusTarget.Cancel ? Colors.accent : Colors.muted}\n >\n {focused === FocusTarget.Cancel ? Icons.triangleSmallRight : ' '}{' '}\n {cancelLabel}\n </Text>\n </Box>\n </Box>\n );\n};\n","import { Box, Text, measureElement } from 'ink';\nimport { useRef, useState, useEffect } from 'react';\n\ninterface DividerProps {\n dimColor?: boolean;\n char?: string;\n}\n\nexport const Divider = ({ dimColor = true, char = '─' }: DividerProps) => {\n const ref = useRef(null);\n const [width, setWidth] = useState(0);\n\n useEffect(() => {\n if (ref.current) {\n const { width: measured } = measureElement(ref.current);\n setWidth(measured);\n }\n }, []);\n\n return (\n <Box ref={ref} width=\"100%\">\n <Text dimColor={dimColor}>{width > 0 ? char.repeat(width) : ''}</Text>\n </Box>\n );\n};\n","/**\n * ModalOverlay — Reusable centered card for overlay screens.\n *\n * Shared layout for HealthCheckScreen, SettingsOverrideScreen, PortConflictScreen, etc.\n * Provides: centered card with border, title, body, optional feedback, divider, and actions.\n */\n\nimport type { ReactNode } from 'react';\nimport { Box, Text } from 'ink';\nimport { Divider } from './Divider.js';\n\ninterface ModalOverlayProps {\n /** Card border color */\n borderColor: string;\n /** Title text */\n title: string;\n /** Title text color (defaults to borderColor) */\n titleColor?: string;\n /** Card width (default 68) */\n width?: number;\n /** Body content */\n children: ReactNode;\n /** Optional feedback message (shown in yellow above the divider) */\n feedback?: string | null;\n /** Footer content below the divider (typically ConfirmationInput) */\n footer?: ReactNode;\n}\n\nexport const ModalOverlay = ({\n borderColor,\n title,\n titleColor,\n width = 68,\n children,\n feedback,\n footer,\n}: ModalOverlayProps) => {\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={borderColor}\n paddingX={3}\n paddingY={1}\n width={width}\n >\n <Box justifyContent=\"center\" marginBottom={1}>\n <Text color={titleColor ?? borderColor} bold>\n {title}\n </Text>\n </Box>\n\n {children}\n\n {feedback && (\n <Box marginTop={1}>\n <Text color=\"yellow\">{feedback}</Text>\n </Box>\n )}\n\n {footer && (\n <>\n <Box marginY={1}>\n <Divider />\n </Box>\n {footer}\n </>\n )}\n </Box>\n </Box>\n );\n};\n","/**\n * LogViewer — Real-time log tail, pinned to available terminal height.\n * Only renders the last N lines that fit on screen.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useEffect } from 'react';\nimport * as fs from 'fs';\nimport { useStdoutDimensions } from '../hooks/useStdoutDimensions.js';\n\n/** Rows consumed by TitleBar + spacer + ScreenContainer padding + status bar + tab bar */\nconst CHROME_ROWS = 8;\n\ninterface LogViewerProps {\n filePath: string;\n /** Fixed visible height. Defaults to terminal rows minus chrome. */\n height?: number;\n}\n\nexport const LogViewer = ({ filePath, height }: LogViewerProps) => {\n const [, rows] = useStdoutDimensions();\n const visibleLines = height ?? Math.max(5, rows - CHROME_ROWS);\n\n const [lines, setLines] = useState<string[]>([]);\n\n useEffect(() => {\n const readTail = () => {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const allLines = content.split('\\n');\n setLines(allLines.slice(-visibleLines));\n } catch {\n setLines(['(No log file found)']);\n }\n };\n\n readTail();\n\n let watcher: fs.FSWatcher | undefined;\n try {\n watcher = fs.watch(filePath, () => {\n readTail();\n });\n } catch {\n // File might not exist yet — retry when it appears\n const interval = setInterval(() => {\n try {\n fs.accessSync(filePath);\n readTail();\n clearInterval(interval);\n watcher = fs.watch(filePath, () => readTail());\n } catch {\n // Still waiting\n }\n }, 1000);\n\n return () => clearInterval(interval);\n }\n\n return () => {\n watcher?.close();\n };\n }, [filePath, visibleLines]);\n\n return (\n <Box flexDirection=\"column\" height={visibleLines}>\n {lines.map((line, i) => (\n <Text key={i} dimColor wrap=\"truncate\">\n {line}\n </Text>\n ))}\n </Box>\n );\n};\n","/**\n * EventPlanViewer — Renders a table of planned analytics events.\n */\n\nimport { Box, Text } from 'ink';\nimport type { PlannedEvent } from '../store.js';\n\ninterface EventPlanViewerProps {\n events: PlannedEvent[];\n}\n\nexport const EventPlanViewer = ({ events }: EventPlanViewerProps) => {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text bold>Event plan</Text>\n <Box height={1} />\n {events.map((event) => (\n <Box key={event.name}>\n <Text bold>{event.name}</Text>\n <Text dimColor> {event.description}</Text>\n </Box>\n ))}\n </Box>\n );\n};\n","import { Box, Text } from 'ink';\nimport { Colors } from '../styles.js';\n\nconst FEEDBACK = 'Feedback: wizard@posthog.com ';\nconst FEEDBACK_SHORT = ' wizard@posthog.com ';\n\ninterface TitleBarProps {\n version: string;\n width: number;\n}\n\nexport const TitleBar = ({ version, width }: TitleBarProps) => {\n const fullTitle = ` PostHog Wizard v${version}`;\n const needShort = width < fullTitle.length + FEEDBACK.length;\n const feedback = needShort ? FEEDBACK_SHORT : FEEDBACK;\n const title =\n needShort && fullTitle.length + feedback.length > width\n ? ` Wizard v${version}`\n : fullTitle;\n const gap = Math.max(0, width - title.length - feedback.length);\n const padding = ' '.repeat(gap);\n\n return (\n <Box width={width} overflow=\"hidden\">\n <Text backgroundColor={Colors.accent} color={Colors.titleColor}>\n {title}\n {padding}\n {feedback}\n </Text>\n </Box>\n );\n};\n","/**\n * DissolveTransition — Column-sweep inspired by TTE's Sweep effect.\n *\n * Uses a SequenceEaser (in_out_circ) to activate columns with eased pacing.\n * Each activated column cycles through shade characters (░▒▓█) independently.\n *\n * Out phase: columns sweep, building up shade chars until solid █ (covers old content).\n * In phase: columns sweep in reverse, dissolving █ back through shades to empty (reveals new content).\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useEffect, useRef, type ReactNode } from 'react';\n\n/** Shade characters in build-up order (light → solid). */\nconst SHADES = ['░', '▒', '▓', '█'] as const;\n/** How many ticks each shade character displays before advancing. */\nconst TICKS_PER_SHADE = 2;\n/** Total ticks a column needs to complete its shade cycle. */\nconst SHADE_CYCLE_TICKS = SHADES.length * TICKS_PER_SHADE;\n\nexport type WipeDirection = 'left' | 'right';\n\ninterface DissolveTransitionProps {\n transitionKey: string;\n width: number;\n height: number;\n children: ReactNode;\n direction?: WipeDirection;\n duration?: number;\n}\n\nfunction easeInOutCirc(t: number): number {\n if (t < 0.5) {\n return (1 - Math.sqrt(1 - 4 * t * t)) / 2;\n }\n return (Math.sqrt(1 - (2 * t - 2) ** 2) + 1) / 2;\n}\n\nenum TransitionPhase {\n Idle = 'idle',\n Out = 'out',\n In = 'in',\n}\n\nexport const DissolveTransition = ({\n transitionKey,\n width,\n height,\n children,\n direction = 'left',\n duration = 2,\n}: DissolveTransitionProps) => {\n const [phase, setPhase] = useState<TransitionPhase>(TransitionPhase.Idle);\n const [tick, setTick] = useState(0);\n const [activeDir, setActiveDir] = useState<WipeDirection>(direction);\n const prevKey = useRef(transitionKey);\n const pendingChildren = useRef<ReactNode>(children);\n const [displayChildren, setDisplayChildren] = useState<ReactNode>(children);\n\n // Track when each column was activated (tick number), -1 means not yet.\n const columnActivationTick = useRef<number[]>([]);\n\n useEffect(() => {\n if (transitionKey !== prevKey.current) {\n prevKey.current = transitionKey;\n pendingChildren.current = children;\n setActiveDir(direction);\n setPhase(TransitionPhase.Out);\n setTick(0);\n columnActivationTick.current = new Array(width).fill(-1);\n } else if (phase !== TransitionPhase.Idle) {\n // Terminal resized mid-transition — abort and show new content immediately\n setPhase(TransitionPhase.Idle);\n setDisplayChildren(children);\n } else {\n setDisplayChildren(children);\n }\n }, [transitionKey, children, width, height, phase, direction]);\n\n useEffect(() => {\n if (phase === TransitionPhase.Idle) return;\n\n const timer = setInterval(() => {\n setTick((prev) => prev + 1);\n }, duration);\n\n return () => clearInterval(timer);\n }, [phase, duration]);\n\n // Easer steps = width: roughly one column activates per tick.\n // This keeps the sweep front tight (only a few columns in-flight at once).\n const easerSteps = width;\n\n // A phase ends when the easer has completed AND all columns have finished their shade cycle.\n const maxTicks = easerSteps + SHADE_CYCLE_TICKS;\n\n useEffect(() => {\n if (phase === TransitionPhase.Idle) return;\n if (tick >= maxTicks) {\n if (phase === TransitionPhase.Out) {\n setDisplayChildren(pendingChildren.current);\n setPhase(TransitionPhase.In);\n setTick(0);\n columnActivationTick.current = new Array(width).fill(-1);\n } else {\n setPhase(TransitionPhase.Idle);\n }\n }\n }, [tick, phase, maxTicks, width]);\n\n if (phase === TransitionPhase.Idle) {\n return <>{displayChildren}</>;\n }\n\n // --- SequenceEaser logic ---\n // Map current tick to easer progress (0..1), apply easing,\n // then determine how many columns should be activated.\n const easerProgress = Math.min(tick / easerSteps, 1);\n const easedValue = easeInOutCirc(easerProgress);\n const activatedCount = Math.floor(easedValue * width);\n\n // Build column order based on direction.\n // \"left\" means sweep moves left-to-right; \"right\" means right-to-left.\n // TTE's COLUMN_RIGHT_TO_LEFT activates rightmost first.\n const columnOrder: number[] = [];\n if (activeDir === 'left') {\n for (let c = width - 1; c >= 0; c--) columnOrder.push(c);\n } else {\n for (let c = 0; c < width; c++) columnOrder.push(c);\n }\n\n // Activate columns that should be active but aren't yet.\n for (let i = 0; i < activatedCount && i < columnOrder.length; i++) {\n const col = columnOrder[i];\n if (columnActivationTick.current[col] === -1) {\n columnActivationTick.current[col] = tick;\n }\n }\n\n // --- Render frame ---\n const rows: string[] = [];\n for (let r = 0; r < height; r++) {\n let row = '';\n for (let c = 0; c < width; c++) {\n const activatedAt = columnActivationTick.current[c];\n\n let char: string;\n if (activatedAt === -1) {\n // Not yet activated\n char = phase === TransitionPhase.Out ? ' ' : '█';\n } else {\n // Column is activated — determine shade based on ticks since activation\n const age = tick - activatedAt;\n const shadeIndex = Math.min(\n Math.floor(age / TICKS_PER_SHADE),\n SHADES.length - 1,\n );\n\n if (phase === TransitionPhase.Out) {\n // Building up: ░ → ▒ → ▓ → █\n char = SHADES[shadeIndex];\n } else {\n // Dissolving: █ → ▓ → ▒ → ░ → space\n if (shadeIndex >= SHADES.length - 1 && age >= SHADE_CYCLE_TICKS) {\n char = ' ';\n } else {\n char = SHADES[SHADES.length - 1 - shadeIndex];\n }\n }\n }\n\n row += char;\n }\n rows.push(row);\n }\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n {rows.map((row, i) => (\n <Text key={i} dimColor>\n {row}\n </Text>\n ))}\n </Box>\n );\n};\n","/**\n * KeyboardHintsBar — Row showing active keyboard shortcuts.\n *\n * Always reserves its row to prevent layout shift. When hints are\n * visible, renders them in dimmed grey text. When dismissed, renders\n * an empty reserved row.\n */\n\nimport { Box, Text } from 'ink';\nimport { useKeyboardHintsContext } from '../hooks/useKeyboardHints.js';\nimport { Colors } from '../styles.js';\n\nexport const KeyboardHintsBar = () => {\n const { hints, visible } = useKeyboardHintsContext();\n\n const showHints = visible && hints.length > 0;\n\n return (\n <Box height={1} paddingX={1}>\n {showHints &&\n hints.map((hint, i) => (\n <Box\n key={`${hint.label}-${hint.action}`}\n marginRight={i < hints.length - 1 ? 2 : 0}\n >\n <Text bold color={Colors.muted}>\n {hint.label}\n </Text>\n <Text dimColor> {hint.action}</Text>\n </Box>\n ))}\n </Box>\n );\n};\n","/**\n * ScreenErrorBoundary — catches React render errors in screens\n * and routes to the outro screen with an error message.\n *\n * Without this, a screen crash silently hangs the TUI.\n */\n\nimport { Box, Text } from 'ink';\nimport { Component, type ReactNode } from 'react';\nimport type { WizardStore } from '../store.js';\nimport { OutroKind, RunPhase } from '../../../lib/wizard-session.js';\n\ninterface Props {\n store: WizardStore;\n children: ReactNode;\n}\n\ninterface State {\n error: Error | null;\n}\n\nexport class ScreenErrorBoundary extends Component<Props, State> {\n state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n componentDidCatch(error: Error): void {\n const { store } = this.props;\n\n // eslint-disable-next-line no-console\n console.error('[ScreenErrorBoundary]', error.message, error.stack);\n\n // Set error state — the router will resolve to outro\n store.setOutroData({\n kind: OutroKind.Error,\n message: `A screen crashed: ${error.message}`,\n });\n store.setRunPhase(RunPhase.Error);\n }\n\n render(): ReactNode {\n if (this.state.error) {\n // Fallback while the store transition fires\n return (\n <Box flexDirection=\"column\">\n <Text color=\"red\" bold>\n Something went wrong.\n </Text>\n <Text dimColor>{this.state.error.message}</Text>\n </Box>\n );\n }\n\n return this.props.children;\n }\n}\n","/**\n * ScreenContainer — Renders TitleBar + routes between screens with transitions.\n * Takes a screens map and renders the one matching store.currentScreen.\n * Horizontal wipe plays on push (left) or pop (right).\n *\n * Each screen is wrapped in a ScreenErrorBoundary so that render crashes\n * route to the outro screen with an error message instead of hanging.\n *\n * Provides KeyboardHintsProvider context. The hints bar is rendered below\n * screen content (inside the transition area) so all screens get it.\n */\n\nimport { Box } from 'ink';\nimport { useSyncExternalStore, type ReactNode } from 'react';\nimport { TitleBar } from '../components/TitleBar.js';\nimport { useStdoutDimensions } from '../hooks/useStdoutDimensions.js';\nimport { KeyboardHintsProvider } from '../hooks/useKeyboardHints.js';\nimport { DissolveTransition } from './DissolveTransition.js';\nimport { KeyboardHintsBar } from './KeyboardHintsBar.js';\nimport { ScreenErrorBoundary } from './ScreenErrorBoundary.js';\nimport type { WizardStore } from '../store.js';\n\nconst MIN_WIDTH = 80;\nexport const MAX_WIDTH = 120;\n\n/** Use terminal width when small so we don't overflow; otherwise clamp to [MIN_WIDTH, MAX_WIDTH]. */\nfunction getContentWidth(terminalColumns: number): number {\n if (terminalColumns < MIN_WIDTH) return terminalColumns;\n return Math.min(MAX_WIDTH, terminalColumns);\n}\n\ninterface ScreenContainerProps {\n store: WizardStore;\n screens: Record<string, ReactNode>;\n}\n\nexport const ScreenContainer = ({ store, screens }: ScreenContainerProps) => {\n const [columns, rows] = useStdoutDimensions();\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const terminalWidth = columns;\n const width = getContentWidth(terminalWidth);\n const contentHeight = Math.max(5, rows - 3);\n const contentAreaWidth = Math.max(10, width - 2);\n const direction = store.lastNavDirection === 'pop' ? 'right' : 'left';\n const activeScreen = screens[store.currentScreen] ?? null;\n\n const inner = (\n <Box flexDirection=\"column\" height={rows} width={width}>\n <TitleBar version={store.version} width={width} />\n <Box height={1} />\n <Box flexDirection=\"column\" flexGrow={1} paddingX={1}>\n <DissolveTransition\n transitionKey={store.currentScreen}\n width={contentAreaWidth}\n height={contentHeight}\n direction={direction}\n >\n <ScreenErrorBoundary store={store}>\n <Box flexDirection=\"column\" height={contentHeight}>\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n flexShrink={1}\n overflow=\"hidden\"\n >\n {activeScreen}\n </Box>\n <Box height={1} />\n <KeyboardHintsBar />\n </Box>\n </ScreenErrorBoundary>\n </DissolveTransition>\n </Box>\n </Box>\n );\n\n return (\n <Box\n flexDirection=\"column\"\n height={rows}\n width={terminalWidth}\n alignItems=\"center\"\n justifyContent=\"flex-start\"\n >\n <KeyboardHintsProvider>{inner}</KeyboardHintsProvider>\n </Box>\n );\n};\n","/**\n * TabContainer — Self-contained tabbed interface.\n * Absorbs BottomTabBar + StatusPanel functionality.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar (rendered by ScreenContainer).\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useMemo, type ReactNode } from 'react';\nimport { Colors, Icons } from '../styles.js';\nimport {\n useKeyBindings,\n KeyMatch,\n type KeyBinding,\n} from '../hooks/useKeyBindings.js';\nimport type { WizardStore } from '../store.js';\n\nexport interface TabDefinition {\n id: string;\n label: string;\n component: ReactNode;\n}\n\nexport const COLLAPSED_COUNT = 2;\nexport const EXPANDED_COUNT = 10;\n\ninterface TabContainerProps {\n tabs: TabDefinition[];\n statusMessage?: string | string[];\n /** Enable expand/collapse on the status box via 's' key */\n expandableStatus?: boolean;\n /** Store reference — required when expandableStatus is true so status state is shared. */\n store?: WizardStore;\n}\n\nexport const TabContainer = ({\n tabs,\n statusMessage,\n expandableStatus = false,\n store,\n}: TabContainerProps) => {\n const [activeTab, setActiveTab] = useState(0);\n // Fallback to local state when no store is provided\n const [localExpanded, setLocalExpanded] = useState(false);\n\n const statusExpanded = store ? store.statusExpanded : localExpanded;\n\n const bindings = useMemo<KeyBinding[]>(() => {\n const b: KeyBinding[] = [\n {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'switch tab',\n handler: (_input, key) => {\n if (key.leftArrow) {\n setActiveTab((prev) => Math.max(0, prev - 1));\n }\n if (key.rightArrow) {\n setActiveTab((prev) => Math.min(tabs.length - 1, prev + 1));\n }\n },\n },\n ];\n if (expandableStatus) {\n b.push({\n match: 's',\n label: 's',\n action: 'toggle status',\n priority: 12,\n handler: () => {\n if (store) {\n store.toggleStatusExpanded();\n } else {\n setLocalExpanded((prev) => !prev);\n }\n },\n });\n }\n return b;\n }, [tabs.length, expandableStatus, store]);\n\n useKeyBindings('tab-container', bindings);\n\n const current = tabs[activeTab];\n\n const allMessages = statusMessage\n ? Array.isArray(statusMessage)\n ? statusMessage\n : [statusMessage]\n : [];\n const visibleCount =\n expandableStatus && statusExpanded ? EXPANDED_COUNT : COLLAPSED_COUNT;\n const visibleMessages = allMessages.slice(-visibleCount);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n {/* Active tab content — overflow hidden so expanded status eats into this area */}\n <Box flexDirection=\"column\" flexGrow={1} flexShrink={1} overflow=\"hidden\">\n {current?.component}\n </Box>\n\n {/* Status bar */}\n {visibleMessages.length > 0 && (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderTop\n borderBottom={false}\n borderLeft={false}\n borderRight={false}\n borderColor={Colors.muted}\n paddingX={1}\n overflow=\"hidden\"\n >\n {visibleMessages.map((msg, i, arr) => {\n const isCurrent = i === arr.length - 1;\n return (\n <Text key={i} color={Colors.muted} dimColor={!isCurrent}>\n {isCurrent ? Icons.diamond : '\\u250A'} {msg}\n </Text>\n );\n })}\n </Box>\n )}\n\n {/* Tab bar */}\n <Box height={1} />\n <Box gap={1} paddingX={1}>\n {tabs.map((tab, i) => (\n <Text\n key={tab.id}\n inverse={i === activeTab}\n color={i === activeTab ? Colors.accent : Colors.muted}\n bold={i === activeTab}\n >\n {` ${tab.label} `}\n </Text>\n ))}\n </Box>\n </Box>\n );\n};\n","/**\n * HNViewer — Top 10 Hacker News stories.\n *\n * Fetches from the HN Firebase API on mount.\n * Each story has a [1]–[0] numeral; typing it opens the HN comments page.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useEffect } from 'react';\nimport { Colors } from '../styles.js';\nimport { useKeyBindings } from '../hooks/useKeyBindings.js';\n\nconst HN_API = 'https://hacker-news.firebaseio.com/v0';\n\ninterface HNStory {\n id: number;\n title: string;\n by: string;\n time: number;\n score: number;\n}\n\nexport const HNViewer = () => {\n const [stories, setStories] = useState<HNStory[]>([]);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n void (async () => {\n try {\n const res = await fetch(`${HN_API}/topstories.json`);\n const ids = (await res.json()) as number[];\n const top10 = ids.slice(0, 10);\n\n const items = await Promise.all(\n top10.map(async (id) => {\n const r = await fetch(`${HN_API}/item/${id}.json`);\n return r.json() as Promise<HNStory>;\n }),\n );\n\n setStories(items);\n } catch {\n // Silently fail — tab just stays empty\n }\n setLoading(false);\n })();\n }, []);\n\n useKeyBindings('hn-viewer', [\n {\n match: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],\n label: 'number keys',\n action: 'open story',\n priority: 5,\n handler: (input) => openStory(input, stories),\n },\n ]);\n\n if (loading) {\n return (\n <Box paddingX={1}>\n <Text dimColor>Loading Hacker News...</Text>\n </Box>\n );\n }\n\n if (stories.length === 0) {\n return (\n <Box paddingX={1}>\n <Text dimColor>Could not load Hacker News.</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text bold color={Colors.accent}>\n Hacker News — Top 10\n </Text>\n <Box height={1} />\n {stories.map((story, i) => {\n const key = i === 9 ? '0' : String(i + 1);\n const date = new Date(story.time * 1000);\n const dateStr = date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n });\n\n return (\n <Box key={story.id} flexDirection=\"column\">\n <Box>\n <Text color={Colors.accent} bold>\n [{key}]\n </Text>\n <Text bold> {story.title}</Text>\n </Box>\n <Box marginLeft={4}>\n <Text dimColor>\n {story.score}pts • {story.by}, {dateStr}\n </Text>\n </Box>\n </Box>\n );\n })}\n </Box>\n );\n};\n\nfunction openStory(input: string, stories: HNStory[]): void {\n const num = parseInt(input, 10);\n if (isNaN(num)) return;\n const index = num === 0 ? 9 : num - 1;\n const story = stories[index];\n if (!story) return;\n\n const url = `https://news.ycombinator.com/item?id=${story.id}`;\n void import('child_process').then(({ exec }) => {\n exec(`open \"${url}\" 2>/dev/null || xdg-open \"${url}\" 2>/dev/null`);\n });\n}\n","/**\n * Text-splitting helpers for sentence boundary detection.\n * Used by TextBlock for animation pauses at punctuation.\n */\n\n/** Split text into sentences (keeps the delimiter attached) */\nexport function splitSentences(text: string): string[] {\n const parts: string[] = [];\n const re = /[^.!?]*[.!?]+\\s*/g;\n let match: RegExpExecArray | null;\n let lastIndex = 0;\n while ((match = re.exec(text)) !== null) {\n parts.push(match[0]);\n lastIndex = re.lastIndex;\n }\n if (lastIndex < text.length) {\n parts.push(text.slice(lastIndex));\n }\n return parts;\n}\n\n/** Build a set of character indices where sentences end (for typewriter pause) */\nexport function sentenceEndChars(text: string): Set<number> {\n const ends = new Set<number>();\n const sentences = splitSentences(text);\n let pos = 0;\n for (const s of sentences) {\n pos += s.length;\n ends.add(pos - 1);\n }\n return ends;\n}\n\n/** Build a set of word indices where sentences end (for word-by-word pause) */\nexport function sentenceEndWords(text: string): Set<number> {\n const ends = new Set<number>();\n const sentences = splitSentences(text);\n let wordCount = 0;\n for (const s of sentences) {\n const words = s.trim().split(/\\s+/).filter(Boolean);\n wordCount += words.length;\n ends.add(wordCount - 1);\n }\n return ends;\n}\n","/**\n * Content block types and type guards.\n *\n * Extracted from ContentSequencer so that pure-logic modules (like\n * layout-helpers) can import them without pulling in Ink/React.\n */\n\nimport type { ReactNode } from 'react';\nimport type { TextRevealMode } from './TextBlock.js';\n\n/** Object form — string or ReactNode content with per-block overrides. */\nexport interface ContentObjectBlock {\n content: string | ReactNode;\n mode?: TextRevealMode;\n animationInterval?: number;\n sentenceInterval?: number;\n pause?: number;\n persist?: boolean;\n}\n\n/** Lines block — reveals ReactNode lines one at a time. */\nexport interface ContentLinesBlock {\n type: 'lines';\n lines: ReactNode[];\n interval?: number;\n pause?: number;\n}\n\n/** Clear block — page break that hides all prior blocks. */\nexport interface ContentClearBlock {\n type: 'clear';\n pause?: number;\n}\n\n/** A content block in the sequence. Bare strings are sugar for { content: '...' }. */\nexport type ContentBlock =\n | string\n | ContentObjectBlock\n | ContentLinesBlock\n | ContentClearBlock;\n\n/** Type guard for lines blocks. */\nexport function isLinesBlock(block: ContentBlock): block is ContentLinesBlock {\n return typeof block !== 'string' && 'type' in block && block.type === 'lines';\n}\n\n/** Type guard for clear blocks. */\nexport function isClearBlock(block: ContentBlock): block is ContentClearBlock {\n return typeof block !== 'string' && 'type' in block && block.type === 'clear';\n}\n\n/** Type guard for object blocks (text or node content). */\nexport function isObjectBlock(\n block: ContentBlock,\n): block is ContentObjectBlock {\n return typeof block !== 'string' && !('type' in block);\n}\n","/**\n * Layout helpers — pure functions for height estimation and viewport eviction.\n *\n * These are the core of the responsive content system. They estimate how many\n * terminal rows a content block will occupy and determine which blocks fit\n * within a given height budget.\n */\n\nimport type { ContentBlock } from './content-types.js';\nimport { isLinesBlock, isClearBlock, isObjectBlock } from './content-types.js';\n\n/**\n * Estimate the number of terminal rows a content block will occupy,\n * including 1 row of marginBottom.\n */\nexport function estimateBlockHeight(\n block: ContentBlock,\n availableWidth: number,\n): number {\n if (typeof block === 'string') {\n return wordWrap(block, availableWidth).length + 1; // +1 for marginBottom\n }\n\n if (isClearBlock(block)) return 0;\n\n if (isLinesBlock(block)) {\n return block.lines.length + 1;\n }\n\n if (isObjectBlock(block)) {\n if (typeof block.content === 'string') {\n return wordWrap(block.content, availableWidth).length + 1;\n }\n return 4; // conservative fixed estimate for ReactNode\n }\n\n return 1;\n}\n\n/**\n * Given all blocks, the active index, available width, and a row budget,\n * return [startIdx, endIdx] — the range of blocks to render.\n *\n * Always includes activeIdx. Walks backward to include as many completed\n * blocks as fit within maxHeight.\n */\nexport function computeVisibleRange(\n blocks: ContentBlock[],\n activeIdx: number,\n availableWidth: number,\n maxHeight: number,\n): [number, number] {\n // Reserve a 2-row buffer so resize-induced estimate drift doesn't\n // cause overflow=\"hidden\" to clip the margin between blocks.\n const budget = Math.max(4, maxHeight - 2);\n\n let totalHeight = estimateBlockHeight(blocks[activeIdx], availableWidth);\n let start = activeIdx;\n\n for (let i = activeIdx - 1; i >= 0; i--) {\n // Clear blocks act as a hard boundary — don't show anything before them\n if (isClearBlock(blocks[i])) break;\n const h = estimateBlockHeight(blocks[i], availableWidth);\n if (totalHeight + h > budget) break;\n totalHeight += h;\n start = i;\n }\n\n return [start, activeIdx];\n}\n\n/**\n * Word-wrap text at clean word boundaries. Always returns pre-wrapped text\n * joined with \\n — this avoids Ink's native wrap which can leave leading\n * spaces on continuation lines.\n *\n * Uses a 1-char safety margin so slight width estimate mismatches don't\n * cause Ink to re-wrap our already-wrapped lines.\n */\nexport function wordWrap(text: string, availableWidth: number): string[] {\n const safeWidth = Math.max(10, availableWidth - 1);\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let currentLine = '';\n\n for (const word of words) {\n if (\n currentLine.length + word.length + 1 > safeWidth &&\n currentLine.length > 0\n ) {\n lines.push(currentLine);\n currentLine = word;\n } else {\n currentLine += (currentLine.length > 0 ? ' ' : '') + word;\n }\n }\n if (currentLine.length > 0) {\n lines.push(currentLine);\n }\n\n return lines;\n}\n\n/**\n * Word-wrap text and return only the last `maxRows` lines.\n * Used for intra-block truncation when a single text block exceeds the viewport.\n * Also used for normal rendering to avoid Ink's leading-space wrap artifacts.\n */\nexport function wrapAndTruncate(\n text: string,\n availableWidth: number,\n maxRows: number,\n): string {\n const lines = wordWrap(text, availableWidth);\n\n if (lines.length <= maxRows) {\n return lines.join('\\n');\n }\n\n return lines.slice(-maxRows).join('\\n');\n}\n","/**\n * TextBlock — Animates a single string paragraph.\n *\n * Self-contained: owns its own animIdx and timer.\n * Calls onComplete() when the animation finishes.\n *\n * Five animation modes:\n * 1. Typewriter — character-by-character reveal\n * 2. Word by word — each word appears in order\n * 3. Sentence by sentence — sentences appear one at a time\n * 4. Paragraph fade — paragraph appears at full opacity immediately\n * 5. Sentence fade — paragraph dim, sentences light up in order\n */\n\nimport { Text } from 'ink';\nimport { useState, useEffect, useRef, useMemo, type ReactNode } from 'react';\nimport { Colors } from '../styles.js';\nimport {\n splitSentences,\n sentenceEndChars,\n sentenceEndWords,\n} from './text-helpers.js';\nimport { wrapAndTruncate } from './layout-helpers.js';\n\nexport enum TextRevealMode {\n Typewriter = 0,\n WordByWord = 1,\n SentenceBySentence = 2,\n ParagraphFade = 3,\n SentenceFade = 4,\n}\n\nexport const TEXT_REVEAL_MODE_LABELS = [\n 'Typewriter',\n 'Word by word',\n 'Sentence by sentence',\n 'Paragraph fade',\n 'Sentence fade',\n];\n\nexport const TEXT_REVEAL_MODE_COUNT = 5;\n\n/** Default interval per mode (ms) */\nexport const TEXT_REVEAL_MODE_DEFAULTS: Record<TextRevealMode, number> = {\n [TextRevealMode.WordByWord]: 240,\n [TextRevealMode.Typewriter]: 32,\n [TextRevealMode.SentenceBySentence]: 1800,\n [TextRevealMode.ParagraphFade]: 4800,\n [TextRevealMode.SentenceFade]: 2400,\n};\n\ninterface TextBlockProps {\n text: string;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n mode: TextRevealMode;\n bullet?: ReactNode;\n animationInterval?: number;\n sentenceInterval?: number;\n /** Max rows this block may occupy. When exceeded, top lines are truncated. */\n maxHeight?: number;\n /** Available text width in columns (for truncation wrapping). */\n availableWidth?: number;\n}\n\nexport const TextBlock = ({\n text,\n active,\n completed,\n onComplete,\n mode,\n bullet,\n animationInterval,\n sentenceInterval = 1600,\n maxHeight,\n availableWidth,\n}: TextBlockProps) => {\n const speed = animationInterval ?? TEXT_REVEAL_MODE_DEFAULTS[mode];\n\n const [animIdx, setAnimIdx] = useState(\n mode === TextRevealMode.SentenceFade ? 1 : 0,\n );\n\n // Reset synchronously during render to avoid a one-frame flash\n const resetRef = useRef(0);\n const prevMode = useRef(mode);\n if (prevMode.current !== mode) {\n prevMode.current = mode;\n resetRef.current += 1;\n setAnimIdx(mode === TextRevealMode.SentenceFade ? 1 : 0);\n }\n\n const words = text.split(/\\s+/);\n const sentences = splitSentences(text);\n\n const sentenceCharEnds = useMemo(() => sentenceEndChars(text), [text]);\n const sentenceWordEnds = useMemo(() => sentenceEndWords(text), [text]);\n\n const isDone =\n mode === TextRevealMode.Typewriter\n ? animIdx >= text.length\n : mode === TextRevealMode.ParagraphFade\n ? true\n : mode === TextRevealMode.WordByWord\n ? animIdx >= words.length\n : mode === TextRevealMode.SentenceFade ||\n mode === TextRevealMode.SentenceBySentence\n ? animIdx >= sentences.length\n : true;\n\n // Fire onComplete when done\n useEffect(() => {\n if (isDone && active) onComplete();\n }, [isDone, active, onComplete]);\n\n // Animate: single effect for all tick-based modes\n useEffect(() => {\n if (!active || mode === TextRevealMode.ParagraphFade || isDone) return;\n const token = resetRef.current;\n\n const isFirstTick = animIdx === 0;\n\n let delay = isFirstTick ? 0 : speed;\n if (\n !isFirstTick &&\n mode === TextRevealMode.Typewriter &&\n animIdx > 0 &&\n sentenceCharEnds.has(animIdx - 1)\n ) {\n delay = sentenceInterval;\n } else if (\n !isFirstTick &&\n mode === TextRevealMode.WordByWord &&\n animIdx > 0 &&\n sentenceWordEnds.has(animIdx - 1)\n ) {\n delay = sentenceInterval;\n }\n\n const timer = setTimeout(() => {\n if (token !== resetRef.current) return;\n setAnimIdx((c) => c + 1);\n }, delay);\n return () => clearTimeout(timer);\n }, [\n active,\n mode,\n animIdx,\n isDone,\n speed,\n sentenceInterval,\n sentenceCharEnds,\n sentenceWordEnds,\n ]);\n\n // Pre-wrap text ourselves to avoid Ink's native wrap leaving leading spaces\n // on continuation lines. When maxHeight is set, also truncates to last N rows.\n const wrap = (visibleText: string): string => {\n if (availableWidth == null) return visibleText;\n if (maxHeight == null) {\n return wrapAndTruncate(visibleText, availableWidth, Infinity);\n }\n return wrapAndTruncate(visibleText, availableWidth, maxHeight);\n };\n\n // Completed: dimmed text\n if (completed) {\n return (\n <Text dimColor>\n {bullet}\n {wrap(text)}\n </Text>\n );\n }\n\n // Active: mode-specific rendering\n if (mode === TextRevealMode.Typewriter) {\n const revealed = text.slice(0, animIdx);\n const atSentenceEnd = /[.!?]\\s*$/.test(revealed);\n const display = atSentenceEnd ? revealed.trimEnd() : revealed;\n return (\n <Text>\n {bullet}\n {wrap(display)}\n <Text color={Colors.muted}>{'\\u258C'}</Text>\n </Text>\n );\n }\n\n if (mode === TextRevealMode.WordByWord) {\n const visible = words.slice(0, animIdx).join(' ');\n return (\n <Text>\n {bullet}\n {wrap(visible)}\n </Text>\n );\n }\n\n if (mode === TextRevealMode.ParagraphFade) {\n return (\n <Text>\n {bullet}\n {wrap(text)}\n </Text>\n );\n }\n\n if (mode === TextRevealMode.SentenceBySentence) {\n const visible = sentences.slice(0, animIdx).join('');\n return (\n <Text>\n {bullet}\n {wrap(visible)}\n </Text>\n );\n }\n\n // SentenceFade\n return (\n <Text>\n {bullet}\n {sentences.map((s, si) => (\n <Text key={si} dimColor={si >= animIdx}>\n {s}\n </Text>\n ))}\n </Text>\n );\n};\n","/**\n * LinesBlock — Reveals ReactNode lines one at a time.\n * Each line can contain colors, bold, ASCII art — any JSX.\n */\n\nimport { Box } from 'ink';\nimport { useState, useEffect, type ReactNode } from 'react';\n\ninterface LinesBlockProps {\n lines: ReactNode[];\n interval: number;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n /** Max rows this block may occupy. When exceeded, top lines are truncated. */\n maxHeight?: number;\n}\n\nexport const LinesBlock = ({\n lines,\n interval,\n active,\n completed,\n onComplete,\n maxHeight,\n}: LinesBlockProps) => {\n const [revealedCount, setRevealedCount] = useState(0);\n\n // Reveal lines one at a time\n useEffect(() => {\n if (!active || revealedCount >= lines.length) return;\n const timer = setTimeout(\n () => setRevealedCount((c) => c + 1),\n revealedCount === 0 ? 0 : interval,\n );\n return () => clearTimeout(timer);\n }, [active, revealedCount, lines.length, interval]);\n\n // Fire onComplete when all lines revealed\n useEffect(() => {\n if (active && revealedCount >= lines.length) onComplete();\n }, [active, revealedCount, lines.length, onComplete]);\n\n // When maxHeight is set, only show the last maxHeight lines\n const visibleStart =\n maxHeight != null\n ? Math.max(0, (completed ? lines.length : revealedCount) - maxHeight)\n : 0;\n\n return (\n <Box flexDirection=\"column\">\n {lines.map((line, li) => {\n if (completed) {\n if (li < visibleStart) return null;\n return <Box key={li}>{line}</Box>;\n }\n if (li >= revealedCount || li < visibleStart) return null;\n return <Box key={li}>{line}</Box>;\n })}\n </Box>\n );\n};\n","/**\n * NodeBlock — Renders static JSX, fires onComplete immediately.\n * The sequencer's blockInterval handles dwell time.\n */\n\nimport { Text } from 'ink';\nimport { useEffect, type ReactNode } from 'react';\n\ninterface NodeBlockProps {\n content: ReactNode;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n}\n\nexport const NodeBlock = ({\n content,\n active,\n completed,\n onComplete,\n}: NodeBlockProps) => {\n useEffect(() => {\n if (active) onComplete();\n }, [active, onComplete]);\n\n if (completed) return <Text dimColor>{content}</Text>;\n return <>{content}</>;\n};\n","/**\n * ContentSequencer — Plays content blocks in order.\n *\n * Each block is a self-animating component that fires onComplete() when done.\n * The sequencer waits blockInterval ms between blocks, then advances.\n *\n * Block types:\n * - string → TextBlock (animated text, sugar for { content: '...' })\n * - { content: str } → TextBlock (animated text with per-block overrides)\n * - { content: JSX } → NodeBlock (static JSX)\n * - { type: 'lines' } → LinesBlock (line-by-line reveal)\n * - { type: 'clear' } → ClearBlock (page break — hides all prior blocks)\n */\n\nimport { Box } from 'ink';\nimport {\n useState,\n useCallback,\n useEffect,\n useRef,\n useMemo,\n type ReactNode,\n} from 'react';\nimport { TextBlock, type TextRevealMode } from './TextBlock.js';\nimport { LinesBlock } from './LinesBlock.js';\nimport { NodeBlock } from './NodeBlock.js';\nimport { computeVisibleRange } from './layout-helpers.js';\nimport { isLinesBlock, isClearBlock, isObjectBlock } from './content-types.js';\nexport type {\n ContentBlock,\n ContentObjectBlock,\n ContentLinesBlock,\n ContentClearBlock,\n} from './content-types.js';\nexport { isLinesBlock, isClearBlock, isObjectBlock } from './content-types.js';\n\nimport type { ContentBlock } from './content-types.js';\n\n/** Resolve the pause after a block completes. */\nexport function getBlockPause(\n block: ContentBlock,\n blockInterval: number,\n): number {\n if (typeof block === 'string') return blockInterval;\n return block.pause ?? blockInterval;\n}\n\ninterface ContentSequencerProps {\n blocks: ContentBlock[];\n mode: TextRevealMode;\n /** Row budget for visible content. When set, older blocks are evicted. */\n maxHeight?: number;\n /** Available text width in columns (for height estimation). */\n availableWidth?: number;\n bullet?: ReactNode;\n animationInterval?: number;\n sentenceInterval?: number;\n lineInterval?: number;\n blockInterval?: number;\n /** Delay in ms before the first block appears. */\n startDelay?: number;\n /** Resume from a previously persisted block index. */\n initialBlockIdx?: number;\n /** Called whenever the active block index advances. */\n onBlockChange?: (idx: number) => void;\n /** Called once when the last block completes (after its pause). */\n onSequenceComplete?: () => void;\n}\n\nexport const ContentSequencer = ({\n blocks,\n mode,\n maxHeight,\n availableWidth,\n bullet,\n animationInterval,\n sentenceInterval,\n lineInterval = 200,\n blockInterval = 3200,\n startDelay = 0,\n initialBlockIdx = 0,\n onBlockChange,\n onSequenceComplete,\n}: ContentSequencerProps) => {\n const resuming = initialBlockIdx > 0;\n const [activeIdx, setActiveIdx] = useState(\n resuming ? initialBlockIdx : startDelay > 0 ? -1 : 0,\n );\n const transitionTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Initial delay before first block (skip when resuming)\n useEffect(() => {\n if (resuming || startDelay <= 0 || activeIdx !== -1) return;\n const timer = setTimeout(() => setActiveIdx(0), startDelay);\n return () => clearTimeout(timer);\n }, [startDelay, activeIdx]);\n\n // Compute visible range reactively (re-evaluates on resize, block advance, etc.)\n const [visibleStart, visibleEnd] = useMemo(() => {\n if (activeIdx < 0) return [0, -1] as [number, number];\n if (maxHeight == null || availableWidth == null) {\n return [0, activeIdx] as [number, number];\n }\n return computeVisibleRange(blocks, activeIdx, availableWidth, maxHeight);\n }, [blocks, activeIdx, maxHeight, availableWidth]);\n\n const handleComplete = useCallback(\n (blockIndex: number) => {\n // Only the active block can trigger advancement\n if (blockIndex !== activeIdx) return;\n // Last block — fire sequence-complete after its pause, don't advance\n if (activeIdx >= blocks.length - 1) {\n if (onSequenceComplete && !transitionTimer.current) {\n const pause = getBlockPause(blocks[blockIndex], blockInterval);\n transitionTimer.current = setTimeout(() => {\n transitionTimer.current = null;\n onSequenceComplete();\n }, pause);\n }\n return;\n }\n // Don't double-trigger\n if (transitionTimer.current) return;\n\n const pause = getBlockPause(blocks[blockIndex], blockInterval);\n transitionTimer.current = setTimeout(() => {\n transitionTimer.current = null;\n setActiveIdx((i) => {\n const next = i + 1;\n onBlockChange?.(next);\n return next;\n });\n }, pause);\n },\n [activeIdx, blocks, blockInterval, onBlockChange, onSequenceComplete],\n );\n\n // Find the most recent clear block — nothing before it renders.\n // When the active block IS a clear block, immediately hide all prior content\n // so the pause shows a blank screen (not dim prior text).\n const clearFloor = useMemo(() => {\n if (activeIdx >= 0 && isClearBlock(blocks[activeIdx])) return activeIdx;\n for (let i = activeIdx - 1; i >= 0; i--) {\n if (isClearBlock(blocks[i])) return i + 1;\n }\n return 0;\n }, [blocks, activeIdx]);\n\n return (\n <Box flexDirection=\"column\">\n {blocks.map((block, i) => {\n // Not yet reached\n if (i > activeIdx) return null;\n // Hidden by clear block\n if (i < clearFloor) return null;\n // Completed clear blocks don't render (active ones must mount to fire onComplete)\n if (isClearBlock(block) && i < activeIdx) return null;\n // Evicted by viewport\n if (i < visibleStart || i > visibleEnd) return null;\n\n const active = i === activeIdx;\n const completed = i < activeIdx;\n\n // Completed non-text blocks don't persist by default\n if (completed && isObjectBlock(block)) {\n const isText = typeof block.content === 'string';\n const shouldPersist = block.persist ?? isText;\n if (!shouldPersist) return null;\n }\n\n return (\n <Box key={i} flexDirection=\"column\" marginBottom={1}>\n <BlockRenderer\n block={block}\n active={active}\n completed={completed}\n onComplete={() => handleComplete(i)}\n mode={mode}\n bullet={bullet}\n animationInterval={animationInterval}\n sentenceInterval={sentenceInterval}\n lineInterval={lineInterval}\n maxHeight={maxHeight}\n availableWidth={availableWidth}\n />\n </Box>\n );\n })}\n </Box>\n );\n};\n\ninterface BlockRendererProps {\n block: ContentBlock;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n mode: TextRevealMode;\n bullet?: ReactNode;\n animationInterval?: number;\n sentenceInterval?: number;\n lineInterval: number;\n maxHeight?: number;\n availableWidth?: number;\n}\n\nconst BlockRenderer = ({\n block,\n active,\n completed,\n onComplete,\n mode,\n bullet,\n animationInterval,\n sentenceInterval,\n lineInterval,\n maxHeight,\n availableWidth,\n}: BlockRendererProps) => {\n // Clear block — completes immediately, renders nothing\n if (isClearBlock(block)) {\n useEffect(() => {\n if (active) onComplete();\n }, [active, onComplete]);\n return null;\n }\n\n // Bare string sugar → TextBlock with sequencer defaults\n if (typeof block === 'string') {\n return (\n <TextBlock\n text={block}\n active={active}\n completed={completed}\n onComplete={onComplete}\n mode={mode}\n bullet={bullet}\n animationInterval={animationInterval}\n sentenceInterval={sentenceInterval}\n maxHeight={maxHeight}\n availableWidth={availableWidth}\n />\n );\n }\n\n // Lines block\n if (isLinesBlock(block)) {\n return (\n <LinesBlock\n lines={block.lines}\n interval={block.interval ?? lineInterval}\n active={active}\n completed={completed}\n onComplete={onComplete}\n maxHeight={maxHeight}\n />\n );\n }\n\n // Object block — dispatch on content type\n if (typeof block.content === 'string') {\n return (\n <TextBlock\n text={block.content}\n active={active}\n completed={completed}\n onComplete={onComplete}\n mode={block.mode ?? mode}\n bullet={bullet}\n animationInterval={block.animationInterval ?? animationInterval}\n sentenceInterval={block.sentenceInterval ?? sentenceInterval}\n maxHeight={maxHeight}\n availableWidth={availableWidth}\n />\n );\n }\n\n return (\n <NodeBlock\n content={block.content}\n active={active}\n completed={completed}\n onComplete={onComplete}\n />\n );\n};\n","/**\n * LearnCard — PostHog educational content with animated text reveal.\n */\n\nimport { Box, Text } from 'ink';\nimport { useEffect, useMemo, useRef } from 'react';\nimport { Colors } from '../styles.js';\nimport type { WizardStore } from '../store.js';\nimport { ContentSequencer, TextRevealMode } from '../primitives/index.js';\nimport type { ContentBlock } from '../primitives/index.js';\nimport { useStdoutDimensions } from '../hooks/useStdoutDimensions.js';\nimport { COLLAPSED_COUNT, EXPANDED_COUNT } from '../primitives/TabContainer.js';\n\n/**\n * StatusPeekTrigger — Fires the status bar expansion once, renders nothing.\n * The peek is guarded by peekedRef so re-mounts are safe.\n */\nconst StatusPeekTrigger = ({\n store,\n duration = 10000,\n peekedRef,\n}: {\n store?: WizardStore;\n duration?: number;\n peekedRef: ReturnType<typeof useRef<boolean>>;\n}) => {\n useEffect(() => {\n if (peekedRef.current) return;\n peekedRef.current = true;\n store?.setStatusExpanded(true);\n // No cleanup — the store call is safe after unmount and the component\n // may be evicted before the timer fires (non-persist NodeBlock).\n setTimeout(() => {\n store?.setStatusExpanded(false);\n }, duration);\n }, [store, duration, peekedRef]);\n\n return <Text>You can view the Wizard's status below.</Text>;\n};\n\nconst POSTHOG_DATA_FLOW: ContentBlock = {\n type: 'lines',\n interval: 500,\n pause: 8000,\n // Box is 30 chars wide between │ borders.\n // Labels: 1-char indent. Arrows: \" ↓ \" (5). Sub-items: \" │ \" (7).\n lines: [\n <Text color=\"gray\">{' ┌──────────────────────────────┐'}</Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color=\"cyan\">\n Your App\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text>posthog.capture()</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>custom events</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>custom properties</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>person profiles</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text dimColor>groups</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color={Colors.accent}>\n PostHog SDK\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text>HTTP</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color={Colors.accent}>\n PostHog Cloud\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text>query + visualize</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color=\"green\">\n Dashboards & Insights\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text color=\"gray\">{' └──────────────────────────────┘'}</Text>,\n ],\n};\n\nconst PRODUCT_SUITE_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 1000,\n pause: 15000,\n lines: [\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Product Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Error Tracking'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Web Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Session Replay'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Feature Flags '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Data Pipelines'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Experiments '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Data Warehouse'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'LLM Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Surveys'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Workflows '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Logs'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Product Tours '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Support'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Revenue Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Endpoints'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Customer Analytics'}\n </Text>,\n ],\n};\n\nconst LINE_CHART_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 300,\n pause: 6000,\n lines: [\n <Text bold>{' Trends · user signups (monthly)'}</Text>,\n <Text> </Text>,\n // 10k\n <Text>\n <Text color=\"gray\">{' 10k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──'}</Text>\n <Text dimColor>{' 9,575'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭╯'}</Text>\n </Text>,\n // 7.5k\n <Text>\n <Text color=\"gray\">{' 7.5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭─╯'}</Text>\n </Text>,\n // 5k\n <Text>\n <Text color=\"gray\">{' 5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭─╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──╯'}</Text>\n </Text>,\n // 2.5k\n <Text>\n <Text color=\"gray\">{' 2.5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭───╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──────╯'}</Text>\n </Text>,\n // 0\n <Text>\n <Text color=\"gray\">{' 0 ┤'}</Text>\n <Text color=\"cyan\">{'──────╯'}</Text>\n </Text>,\n // X-axis\n <Text color=\"gray\">{' └┬─────┬─────┬─────┬─────┬──'}</Text>,\n <Text dimColor>{' May Aug Nov Feb May'}</Text>,\n ],\n};\n\nconst FUNNEL_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 200,\n pause: 8000,\n lines: [\n <Text bold>{' Funnel · ride conversion'}</Text>,\n <Text> </Text>,\n // Step 1\n <Text>\n {' '}\n <Text bold>1</Text>\n {' app_launched'}\n {' '}\n <Text bold color=\"green\">\n 100.00%\n </Text>\n </Text>,\n <Text color=\"cyan\">{' ██████████████████████████████'}</Text>,\n <Text dimColor>{' → 1,200 users'}</Text>,\n <Text> </Text>,\n // Step 2\n <Text>\n {' '}\n <Text bold>2</Text>\n {' ride_requested'}\n {' '}\n <Text dimColor>{'avg 2m 30s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 72.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'██████████████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 864 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 336 (28%)'}</Text>\n </Text>,\n <Text> </Text>,\n // Step 3\n <Text>\n {' '}\n <Text bold>3</Text>\n {' ride_accepted'}\n {' '}\n <Text dimColor>{'avg 5m 12s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 51.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'██████████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 612 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 252 (29%)'}</Text>\n </Text>,\n <Text> </Text>,\n // Step 4\n <Text>\n {' '}\n <Text bold>4</Text>\n {' ride_started'}\n {' '}\n <Text dimColor>{'avg 1m 45s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 38.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'█████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 456 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 156 (25%)'}</Text>\n </Text>,\n ],\n};\n\n/** Fixed chrome: ScreenContainer (3) + TabContainer tab bar (2) */\nconst FIXED_CHROME = 5;\nconst HEADER_ROWS = 2; // title + spacer\nconst MIN_CONTENT_ROWS = 6;\n\ninterface LearnCardProps {\n store?: WizardStore;\n onComplete?: () => void;\n}\n\nexport const LearnCard = ({ store, onComplete }: LearnCardProps) => {\n const peekedRef = useRef(false);\n const [columns, rows] = useStdoutDimensions();\n\n const blocks = useMemo<ContentBlock[]>(\n () => [\n {\n content: 'Welcome.',\n pause: 3000,\n mode: TextRevealMode.Typewriter,\n animationInterval: 160,\n },\n\n { content: 'The Wizard is an agent.', pause: 4000 },\n\n {\n content: 'It handles the entire PostHog setup process on your behalf.',\n pause: 5000,\n },\n\n {\n content:\n \"As we speak, it's building a plan to set up PostHog in your project.\",\n pause: 6000,\n },\n\n { type: 'clear', pause: 2000 },\n\n {\n pause: 5000,\n persist: true,\n content: <StatusPeekTrigger store={store} peekedRef={peekedRef} />,\n },\n\n {\n pause: 6000,\n content: (\n <Text>\n Press{' '}\n <Text color={Colors.accent} bold>\n S\n </Text>{' '}\n to expand or collapse the status.\n </Text>\n ),\n },\n\n { type: 'clear', pause: 2000 },\n\n {\n content: 'It takes about eight minutes.',\n pause: 2000,\n },\n\n {\n content: 'So grab some coffee ☕️.',\n pause: 2000,\n },\n\n {\n content: 'Or stick around and learn about PostHog.',\n pause: 5000,\n },\n\n { type: 'clear', pause: 3000 },\n\n {\n content: 'Events are the foundation of the PostHog platform.',\n pause: 4000,\n },\n\n {\n content:\n 'Every time an action is performed in your codebase — like button clicks, function calls, or thrown errors — we can capture an event.',\n pause: 6000,\n },\n\n {\n content:\n 'Events are sent to PostHog and joined with other product data.',\n pause: 6000,\n },\n\n { type: 'clear', pause: 1000 },\n\n { content: \"Here's the flow.\", pause: 1000 },\n\n POSTHOG_DATA_FLOW,\n\n { type: 'clear', pause: 2000 },\n\n {\n content:\n 'With enough event data, you can answer powerful questions about your product.',\n pause: 4000,\n },\n\n { content: 'And create insights.', pause: 4000 },\n\n { type: 'clear', pause: 500 },\n\n { content: 'Like trends to measure growth.', pause: 2500 },\n\n LINE_CHART_BLOCK,\n\n { type: 'clear', pause: 500 },\n\n { content: 'Or funnels to reveal bottlenecks.', pause: 2500 },\n\n FUNNEL_BLOCK,\n\n { type: 'clear', pause: 1000 },\n\n {\n content: 'Use those signals to decide what to build next.',\n pause: 4000,\n },\n\n { content: 'PostHog has all the dev tools you need.', pause: 3000 },\n\n PRODUCT_SUITE_BLOCK,\n ],\n [store],\n );\n\n // Dynamic status bar height: messages + border when present\n const hasStatus = store ? store.statusMessages.length > 0 : false;\n const statusBarRows = hasStatus\n ? (store?.statusExpanded ? EXPANDED_COUNT : COLLAPSED_COUNT) + 1\n : 0;\n\n const contentHeight = rows - FIXED_CHROME - statusBarRows;\n const tooSmall = contentHeight < MIN_CONTENT_ROWS;\n\n const maxHeight = Math.max(1, contentHeight - HEADER_ROWS);\n // Half of clamped content width, minus paddingX on both sides\n const paneWidth = Math.floor((Math.min(120, columns) - 2) / 2) - 2;\n\n // Always render so ContentSequencer stays mounted (preserves activeIdx).\n // When too small, hide visually via display=\"none\".\n return (\n <Box\n flexDirection=\"column\"\n paddingX={1}\n display={tooSmall ? 'none' : 'flex'}\n >\n <Text bold color={Colors.accent}>\n Learn\n </Text>\n <Box height={1} />\n <ContentSequencer\n blocks={blocks}\n mode={TextRevealMode.SentenceBySentence}\n maxHeight={maxHeight}\n availableWidth={paneWidth}\n startDelay={2000}\n initialBlockIdx={store?.learnCardBlockIdx ?? 0}\n onBlockChange={(idx) => store?.setLearnCardBlockIdx(idx)}\n onSequenceComplete={onComplete}\n />\n </Box>\n );\n};\n","/**\n * TipsCard — Shows PostHog tips during the agent run.\n * Reactively shows/hides tips based on discovered features.\n * Supports toggling additional features via key bindings.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport type { WizardStore } from '../store.js';\nimport { Colors, Icons } from '../styles.js';\nimport {\n DiscoveredFeature,\n AdditionalFeature,\n} from '../../../lib/wizard-session.js';\n\n/** A discrete tip shown in the TipsCard during the agent run. */\ninterface Tip {\n /** Unique identifier */\n id: string;\n /** Title line */\n title: string;\n /** Description shown below the title */\n description: string;\n /** Optional URL shown after the description */\n url?: string;\n /** When provided, the tip is only shown if this returns true */\n visible?: (store: WizardStore) => boolean;\n /** Optional key binding that toggles an AdditionalFeature */\n toggle?: {\n /** The key the user presses (lowercase) */\n key: string;\n /** The additional feature to enqueue */\n feature: AdditionalFeature;\n /** Label shown when toggled on */\n enabledLabel: string;\n /** Prompt shown when not yet toggled */\n prompt: string;\n /** Returns true if already toggled */\n isEnabled: (store: WizardStore) => boolean;\n };\n}\n\nconst TIPS: Tip[] = [\n {\n id: 'persons',\n title: 'You can also track people and groups with PostHog',\n description:\n \"Events can be associated with the humans who generate them, letting you understand a specific user or customer's situation.\",\n },\n {\n id: 'properties',\n title: 'Get way more detail using properties',\n description:\n 'Events and person records can have any properties you want. Track things like how they found your website, what subscription tier they choose, and much more.',\n },\n {\n id: 'stripe',\n title: 'You can track Stripe revenue with PostHog',\n description: 'Add Stripe as a data source while you wait:',\n url: 'https://app.posthog.com/project/data-warehouse/new-source?kind=Stripe',\n visible: (store) =>\n store.session.discoveredFeatures.includes(DiscoveredFeature.Stripe),\n },\n {\n id: 'llm',\n title: 'PostHog can also help you track your LLM costs',\n description: '',\n visible: (store) =>\n store.session.discoveredFeatures.includes(DiscoveredFeature.LLM),\n toggle: {\n key: 'l',\n feature: AdditionalFeature.LLM,\n enabledLabel: 'LLM analytics setup queued next',\n prompt: 'We detected LLM dependencies in your project.',\n isEnabled: (store) => store.session.llmOptIn,\n },\n },\n];\n\nexport const TipsCard = ({ store }: { store: WizardStore }) => {\n useInput((input) => {\n for (const tip of TIPS) {\n if (\n tip.toggle &&\n input.toLowerCase() === tip.toggle.key &&\n (!tip.visible || tip.visible(store)) &&\n !tip.toggle.isEnabled(store)\n ) {\n store.enableFeature(tip.toggle.feature);\n }\n }\n });\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text bold color={Colors.accent}>\n Tips\n </Text>\n <Box height={1} />\n\n {TIPS.filter((tip) => !tip.visible || tip.visible(store)).map((tip) => (\n <Box key={tip.id} flexDirection=\"column\" marginBottom={1}>\n <Text>\n <Text color={Colors.accent}>{Icons.diamond} </Text>\n <Text bold>{tip.title}</Text>\n </Text>\n\n {tip.toggle ? (\n tip.toggle.isEnabled(store) ? (\n <Text color={Colors.success}>\n {Icons.check} {tip.toggle.enabledLabel}\n </Text>\n ) : (\n <Text dimColor>\n {tip.toggle.prompt} Press{' '}\n <Text bold color={Colors.accent}>\n {tip.toggle.key.toUpperCase()}\n </Text>{' '}\n to enable.\n </Text>\n )\n ) : (\n <Text dimColor>\n {tip.description}\n {tip.url && (\n <>\n {' '}\n <Text color=\"cyan\">{tip.url}</Text>\n </>\n )}\n </Text>\n )}\n </Box>\n ))}\n </Box>\n );\n};\n","/**\n * ServiceHealthList — Shared component for displaying service health status.\n *\n * Used by HealthCheckScreen (blocking services only) and HealthWarningsTab (all services).\n */\n\nimport { Box, Text } from 'ink';\nimport {\n ServiceHealthStatus,\n type AllServicesHealth,\n type ComponentHealthResult,\n type ComponentStatus,\n type HealthCheckKey,\n} from '../../../lib/health-checks/types.js';\nimport { SERVICE_LABELS } from '../../../lib/health-checks/readiness.js';\nimport { Icons } from '../styles.js';\n\n/** Keys that are component-level detail — shown inline under their parent. */\nconst COMPONENT_KEYS: HealthCheckKey[] = [\n 'posthogComponents',\n 'npmComponents',\n 'cloudflareComponents',\n];\n\n/** Map component key → its parent \"overall\" key */\nconst COMPONENT_PARENT: Partial<Record<HealthCheckKey, HealthCheckKey>> = {\n posthogComponents: 'posthogOverall',\n npmComponents: 'npmOverall',\n cloudflareComponents: 'cloudflareOverall',\n};\n\nfunction statusIcon(status: ServiceHealthStatus): {\n icon: string;\n color: string;\n} {\n switch (status) {\n case ServiceHealthStatus.Down:\n return { icon: Icons.squareFilled, color: 'red' };\n case ServiceHealthStatus.Degraded:\n return { icon: Icons.squareFilled, color: '#DC9300' };\n case ServiceHealthStatus.Healthy:\n return { icon: Icons.check, color: 'green' };\n }\n}\n\ninterface ServiceHealthListProps {\n health: AllServicesHealth;\n /** If set, only show services with these keys */\n filterKeys?: HealthCheckKey[];\n /** Show healthy services (default true) */\n showHealthy?: boolean;\n}\n\nexport const ServiceHealthList = ({\n health,\n filterKeys,\n showHealthy = true,\n}: ServiceHealthListProps) => {\n const topLevelKeys = (Object.keys(health) as HealthCheckKey[]).filter(\n (k) => !COMPONENT_KEYS.includes(k),\n );\n\n const keysToShow = filterKeys\n ? topLevelKeys.filter((k) => filterKeys.includes(k))\n : topLevelKeys;\n\n return (\n <Box flexDirection=\"column\" paddingLeft={1}>\n {keysToShow.map((key) => {\n const result = health[key];\n if (!showHealthy && result.status === ServiceHealthStatus.Healthy) {\n return null;\n }\n\n const { icon, color } = statusIcon(result.status);\n const label = SERVICE_LABELS[key];\n\n // Find component-level details if this is a parent key\n const componentKey = (\n Object.entries(COMPONENT_PARENT) as [HealthCheckKey, HealthCheckKey][]\n ).find(([, parent]) => parent === key)?.[0];\n const componentResult = componentKey\n ? (health[componentKey] as ComponentHealthResult)\n : undefined;\n const affectedComponents: ComponentStatus[] =\n componentResult?.degradedOrDownComponents ?? [];\n\n return (\n <Box key={key} flexDirection=\"column\">\n <Text>\n <Text color={color}>{icon}</Text>{' '}\n <Text bold={result.status !== ServiceHealthStatus.Healthy}>\n {label}\n </Text>\n </Text>\n {affectedComponents.length > 0 && (\n <Box flexDirection=\"column\" paddingLeft={3}>\n {affectedComponents.slice(0, 5).map((c) => {\n const ci = statusIcon(c.status);\n return (\n <Text key={c.name} dimColor>\n <Text color={ci.color}>{ci.icon}</Text> {c.name}\n </Text>\n );\n })}\n {affectedComponents.length > 5 && (\n <Text dimColor>+{affectedComponents.length - 5} more</Text>\n )}\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n};\n","import { Box, Text } from 'ink';\nimport { useStdoutDimensions } from '../../hooks/useStdoutDimensions.js';\nimport { Colors, Icons } from '../../styles.js';\nimport {\n getKindMeta,\n type HealthIssue,\n type HealthIssueSeverity,\n} from '../../../../lib/workflows/posthog-doctor/index.js';\n\nexport const SEVERITY_ORDER: HealthIssueSeverity[] = [\n 'critical',\n 'warning',\n 'info',\n];\n\nconst SEVERITY_COLOR: Record<HealthIssueSeverity, string> = {\n critical: Colors.error,\n warning: Colors.accent,\n info: Colors.primary,\n};\n\nexport const SEVERITY_LABEL: Record<HealthIssueSeverity, string> = {\n critical: 'Critical',\n warning: 'Warning',\n info: 'Info',\n};\n\nconst ICON_COL = 2;\nconst ROW_GAP = 2;\nconst NARROW_TERM_THRESHOLD = 90;\nconst MAX_DOCS_WIDTH = 50;\nconst MIN_DOCS_WIDTH = 20;\n\nfunction computeDocsWidth(termCols: number): number {\n if (termCols < NARROW_TERM_THRESHOLD) return 0;\n const inner = termCols - 12;\n return Math.min(\n MAX_DOCS_WIDTH,\n Math.max(MIN_DOCS_WIDTH, Math.floor(inner * 0.45)),\n );\n}\n\ninterface IssueTableProps {\n issues: HealthIssue[];\n}\n\nexport const IssueTable = ({ issues }: IssueTableProps) => {\n const [termCols] = useStdoutDimensions();\n const docsWidth = computeDocsWidth(termCols);\n\n const grouped: Partial<Record<HealthIssueSeverity, HealthIssue[]>> = {};\n for (const issue of issues) {\n (grouped[issue.severity] ??= []).push(issue);\n }\n\n return (\n <Box flexDirection=\"column\">\n {SEVERITY_ORDER.map((sev) => {\n const list = grouped[sev];\n if (!list || list.length === 0) return null;\n return (\n <Box key={sev} flexDirection=\"column\" marginTop={1}>\n <Text bold color={SEVERITY_COLOR[sev]}>\n {SEVERITY_LABEL[sev]} ({list.length})\n </Text>\n {list.map((issue) => (\n <IssueRow key={issue.id} issue={issue} docsWidth={docsWidth} />\n ))}\n </Box>\n );\n })}\n </Box>\n );\n};\n\nconst IssueRow = ({\n issue,\n docsWidth,\n}: {\n issue: HealthIssue;\n docsWidth: number;\n}) => {\n const meta = getKindMeta(issue.kind);\n const sevColor = SEVERITY_COLOR[issue.severity];\n\n if (docsWidth === 0) {\n return (\n <Box flexDirection=\"column\">\n <Box>\n <Box width={ICON_COL}>\n <Text color={sevColor}>{Icons.squareFilled}</Text>\n </Box>\n <Box flexGrow={1} flexShrink={1} overflow=\"hidden\">\n <Text wrap=\"truncate\">{meta.title}</Text>\n </Box>\n </Box>\n <Box paddingLeft={ICON_COL}>\n <Text color={Colors.primary} wrap=\"truncate\">\n {meta.docsUrl}\n </Text>\n </Box>\n </Box>\n );\n }\n\n return (\n <Box>\n <Box width={ICON_COL}>\n <Text color={sevColor}>{Icons.squareFilled}</Text>\n </Box>\n <Box flexGrow={1} flexShrink={1} overflow=\"hidden\" marginRight={ROW_GAP}>\n <Text wrap=\"truncate\">{meta.title}</Text>\n </Box>\n <Box width={docsWidth} flexShrink={0}>\n <Text color={Colors.primary} wrap=\"truncate\">\n {meta.docsUrl}\n </Text>\n </Box>\n </Box>\n );\n};\n","/**\n * McpScreen — MCP server install/remove flow.\n *\n * Uses an McpInstaller service (passed via props) instead of\n * importing business logic directly. Testable, no dynamic imports.\n *\n * Supports two modes via the `mode` prop:\n * - 'install': detect clients → confirm → [pick clients] → pick features → install\n * - 'remove': detect installed clients → confirm → remove\n *\n * When done, calls store.setMcpComplete(). The router resolves to outro.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { useState, useEffect } from 'react';\nimport { useSyncExternalStore } from 'react';\nimport { type WizardStore, McpOutcome } from '../store.js';\nimport {\n ConfirmationInput,\n PickerMenu,\n GroupedPickerMenu,\n} from '../primitives/index.js';\nimport { Colors } from '../styles.js';\nimport type { McpInstaller, McpClientInfo } from '../services/mcp-installer.js';\nimport {\n AVAILABLE_FEATURES,\n ALL_FEATURE_VALUES,\n} from '../../../steps/add-mcp-server-to-clients/defaults.js';\n\nexport type McpMode = 'install' | 'remove';\n\ninterface McpScreenProps {\n store: WizardStore;\n installer: McpInstaller;\n mode?: McpMode;\n}\n\nenum Phase {\n Detecting = 'detecting',\n Ask = 'ask',\n Pick = 'pick',\n FeatureSelect = 'feature-select',\n Working = 'working',\n Done = 'done',\n None = 'none',\n}\n\nconst markDone = (\n store: WizardStore,\n outcome: McpOutcome,\n clients: string[] = [],\n) => {\n store.setMcpComplete(outcome, clients);\n};\n\nexport const McpScreen = ({\n store,\n installer,\n mode = 'install',\n}: McpScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n // Keep stdin active from mount so Windows cmd.exe doesn't drop\n // the first keypress when ConfirmationInput appears after detection.\n useInput(() => undefined);\n\n const isRemove = mode === 'remove';\n\n const [phase, setPhase] = useState<Phase>(Phase.Detecting);\n const [clients, setClients] = useState<McpClientInfo[]>([]);\n const [selectedClientNames, setSelectedClientNames] = useState<string[]>([]);\n const [resultClients, setResultClients] = useState<string[]>([]);\n const [pluginClients, setPluginClients] = useState<string[]>([]);\n\n useEffect(() => {\n void (async () => {\n try {\n const detected = await installer.detectClients();\n if (detected.length === 0) {\n setPhase(Phase.None);\n setTimeout(() => markDone(store, McpOutcome.NoClients), 1500);\n } else {\n setClients(detected);\n setPhase(Phase.Ask);\n }\n } catch {\n setPhase(Phase.None);\n setTimeout(() => markDone(store, McpOutcome.Failed), 1500);\n }\n })();\n }, [installer]); // eslint-disable-line\n\n const proceedToFeatureSelectOrInstall = (clientNames: string[]) => {\n setSelectedClientNames(clientNames);\n // Skip feature picker if CLI already specified features\n if (store.session.mcpFeatures) {\n void doInstall(clientNames, store.session.mcpFeatures);\n } else {\n setPhase(Phase.FeatureSelect);\n }\n };\n\n const handleConfirm = () => {\n if (isRemove) {\n void doRemove();\n } else if (clients.length === 1) {\n proceedToFeatureSelectOrInstall(clients.map((c) => c.name));\n } else {\n setPhase(Phase.Pick);\n }\n };\n\n const handleSkip = () => {\n markDone(store, McpOutcome.Skipped);\n };\n\n const doInstall = async (names: string[], features?: string[]) => {\n setPhase(Phase.Working);\n let mcpResult: string[] = [];\n let pluginResult: string[] = [];\n try {\n mcpResult = await installer.install(\n names,\n features,\n store.session.apiKey,\n );\n } catch {\n // mcpResult stays []\n }\n try {\n pluginResult = await installer.installPlugins(names);\n } catch {\n // best-effort — plugin failure does not affect MCP outcome\n }\n setResultClients(mcpResult);\n setPluginClients(pluginResult);\n setPhase(Phase.Done);\n const outcome =\n mcpResult.length > 0 ? McpOutcome.Installed : McpOutcome.Failed;\n setTimeout(() => markDone(store, outcome, mcpResult), 2000);\n };\n\n const doRemove = async () => {\n setPhase(Phase.Working);\n let result: string[] = [];\n try {\n result = await installer.remove();\n setResultClients(result);\n } catch {\n setResultClients([]);\n }\n setPhase(Phase.Done);\n const outcome =\n result.length > 0 ? McpOutcome.Installed : McpOutcome.Failed;\n setTimeout(() => markDone(store, outcome, result), 2000);\n };\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n MCP Server {isRemove ? 'Removal' : 'Setup'}\n </Text>\n\n <Box marginTop={1} flexDirection=\"column\">\n {phase === Phase.Detecting && (\n <Text dimColor>Detecting supported editors...</Text>\n )}\n\n {phase === Phase.None && (\n <Text dimColor>\n No {isRemove ? 'installed' : 'supported'} MCP clients detected.\n Skipping...\n </Text>\n )}\n\n {phase === Phase.Ask && (\n <>\n <Text dimColor>\n Detected: {clients.map((c) => c.name).join(', ')}\n </Text>\n <Box marginTop={1}>\n <ConfirmationInput\n message={`${\n isRemove ? 'Remove' : 'Install'\n } the PostHog MCP server${\n clients.some((c) => c.supportsPlugin) ? ' and plugin' : ''\n }?`}\n confirmLabel={isRemove ? 'Remove' : 'Install'}\n cancelLabel=\"No thanks\"\n onConfirm={handleConfirm}\n onCancel={handleSkip}\n />\n </Box>\n </>\n )}\n\n {phase === Phase.Pick && (\n <PickerMenu\n message=\"Select editor to install MCP server\"\n options={clients.map((c) => ({\n label: c.name,\n value: c.name,\n }))}\n mode=\"multi\"\n onSelect={(selected) => {\n const names = Array.isArray(selected) ? selected : [selected];\n proceedToFeatureSelectOrInstall(names);\n }}\n />\n )}\n\n {phase === Phase.FeatureSelect && (\n <GroupedPickerMenu\n message=\"Select features to enable\"\n groups={AVAILABLE_FEATURES}\n initialSelected={[...ALL_FEATURE_VALUES]}\n onSelect={(features) => {\n void doInstall(selectedClientNames, features);\n }}\n />\n )}\n\n {phase === Phase.Working && (\n <Text dimColor>\n {isRemove ? 'Removing' : 'Installing'} MCP server...\n </Text>\n )}\n\n {phase === Phase.Done && (\n <Box flexDirection=\"column\">\n {resultClients.length > 0 ? (\n <>\n <Text color=\"green\" bold>\n {'\\u2714'} MCP server\n {!isRemove && pluginClients.length > 0 ? ' and plugin' : ''}{' '}\n {isRemove ? 'removed from' : 'installed for'}:\n </Text>\n {resultClients.map((name, i) => (\n <Text key={i}>\n {' '}\n {'\\u2022'} {name}\n </Text>\n ))}\n </>\n ) : (\n <Text dimColor>\n {isRemove ? 'Removal' : 'Installation'} skipped.\n </Text>\n )}\n </Box>\n )}\n </Box>\n </Box>\n );\n};\n","import { Box, Text } from 'ink';\n\ninterface AreaHeaderRowProps {\n area: string;\n resolved: number;\n total: number;\n}\n\n/** Sub-header row inside the scrollable body — one per area group. */\nexport const AreaHeaderRow = ({\n area,\n resolved,\n total,\n}: AreaHeaderRowProps) => (\n <Box flexShrink={0} marginTop={1}>\n <Text bold color=\"cyan\">\n {area}{' '}\n </Text>\n <Text dimColor>\n ({resolved}/{total})\n </Text>\n </Box>\n);\n","import { MAX_WIDTH } from '../../../primitives/ScreenContainer.js';\n\n/** Terminal rows used by chrome outside the viewer\n * (TitleBar, spacer, screen padding, status bar, tab bar). */\nexport const CHROME_ROWS = 10;\n\n/** Rows used by the viewer's own header / footer\n * (title, subtitle, top summary, spacer, column headers, divider,\n * scroll-up marker, scroll-down marker, legend, footer summary). */\nexport const VIEWER_CHROME_BASE = 10;\n\nexport const COL_AREA_WIDTH = 18;\nexport const COL_LABEL_MIN = 28;\nexport const COL_GAP = 2;\n\nexport interface ViewerLayout {\n cols: number;\n visibleHeight: number;\n viewerChrome: number;\n padding: number;\n statusWidth: number;\n areaWidth: number;\n labelWidth: number;\n colGap: number;\n dividerWidth: number;\n detailIndent: number;\n detailWidth: number;\n}\n\n/** ScreenContainer wraps content in paddingX={1} inside a width capped at\n * MAX_WIDTH, so the actual width available to the viewer is\n * min(cols, MAX_WIDTH) - 2. */\nfunction getViewerWidth(rawCols: number): number {\n return Math.min(MAX_WIDTH, rawCols) - 2;\n}\n\nexport function computeLayout(rawCols: number, termRows: number): ViewerLayout {\n const cols = getViewerWidth(rawCols);\n const padding = 2;\n const statusWidth = 2;\n\n // CHECK flexes to consume the rest of the row so long labels stay readable\n // instead of getting truncated.\n const fixedExceptLabel =\n padding + statusWidth + COL_GAP + COL_AREA_WIDTH + COL_GAP + COL_GAP;\n const labelWidth = Math.max(COL_LABEL_MIN, cols - fixedExceptLabel);\n\n const detailIndent = statusWidth + COL_GAP + COL_AREA_WIDTH + COL_GAP;\n\n const viewerChrome = VIEWER_CHROME_BASE;\n const visibleHeight = Math.max(5, termRows - CHROME_ROWS - viewerChrome);\n\n return {\n cols,\n visibleHeight,\n viewerChrome,\n padding,\n statusWidth,\n areaWidth: COL_AREA_WIDTH,\n labelWidth,\n colGap: COL_GAP,\n dividerWidth: Math.max(20, cols - padding),\n detailIndent,\n detailWidth: Math.max(20, cols - detailIndent - padding),\n };\n}\n\nexport function truncate(text: string, max: number): string {\n if (max <= 0) return '';\n if (text.length <= max) return text;\n return text.slice(0, Math.max(1, max - 1)) + '…';\n}\n","import { Box, Text } from 'ink';\nimport {\n AUDIT_SEVERITY_STYLE,\n type AuditCheck,\n} from '../../../../../lib/workflows/audit/types.js';\nimport { truncate, type ViewerLayout } from './layout.js';\n\ninterface CheckRowProps {\n item: AuditCheck;\n layout: ViewerLayout;\n}\n\nexport const CheckRow = ({ item, layout }: CheckRowProps) => {\n const style = AUDIT_SEVERITY_STYLE[item.status];\n return (\n <Box flexShrink={0}>\n <Box width={layout.statusWidth + layout.colGap}>\n <Text color={style.color}>{style.glyph}</Text>\n </Box>\n <Box width={layout.areaWidth + layout.colGap}>\n <Text dimColor>{truncate(item.area, layout.areaWidth)}</Text>\n </Box>\n <Box width={layout.labelWidth + layout.colGap}>\n <Text\n bold={item.status !== 'pending'}\n dimColor={item.status === 'pending'}\n >\n {truncate(item.label, layout.labelWidth)}\n </Text>\n </Box>\n </Box>\n );\n};\n","import { Box, Text } from 'ink';\nimport type { AuditCheck } from '../../../../../lib/workflows/audit/types.js';\nimport type { ViewerLayout } from './layout.js';\n\ninterface DetailRowProps {\n item: AuditCheck;\n layout: ViewerLayout;\n}\n\n/** Format a `details` string. If it parses as a JSON object, render it as\n * indented key: value lines (skipping huge nested arrays/objects which we\n * truncate). Otherwise return the original text. v3000 emits structured\n * JSON for several event-quality checks — a raw dump is unreadable. */\nfunction formatDetails(raw: string): string[] {\n const trimmed = raw.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return [raw];\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n return [raw];\n }\n if (parsed === null || typeof parsed !== 'object') return [raw];\n const lines: string[] = [];\n const renderValue = (v: unknown): string => {\n if (v === null) return 'null';\n if (typeof v === 'string') return v;\n if (typeof v === 'number' || typeof v === 'boolean') return String(v);\n if (Array.isArray(v)) {\n if (v.length === 0) return '[]';\n const allPrimitive = v.every((e) => e === null || typeof e !== 'object');\n if (allPrimitive) return v.map(renderValue).join(', ');\n return `[${v.length} item${v.length === 1 ? '' : 's'}]`;\n }\n if (typeof v === 'object') {\n const keys = Object.keys(v);\n return `{${keys.length} field${keys.length === 1 ? '' : 's'}}`;\n }\n return String(v);\n };\n for (const [key, value] of Object.entries(parsed)) {\n lines.push(`${key}: ${renderValue(value)}`);\n }\n return lines.length > 0 ? lines : [raw];\n}\n\n/** Indented under the CHECK column; wrap continuation aligns with the prefix. */\nexport const DetailRow = ({ item, layout }: DetailRowProps) => {\n const detailLines = item.details ? formatDetails(item.details) : [];\n return (\n <Box flexShrink={0}>\n <Box width={layout.detailIndent} />\n <Box flexDirection=\"column\" width={layout.detailWidth}>\n {item.file && (\n <Text dimColor wrap=\"wrap\">\n {`↳ File: ${item.file}`}\n </Text>\n )}\n {detailLines.map((line, i) => (\n <Text key={i} dimColor italic wrap=\"wrap\">\n {i === 0 ? `${item.file ? ' ' : '↳ '}${line}` : ` ${line}`}\n </Text>\n ))}\n </Box>\n </Box>\n );\n};\n","import { Text } from 'ink';\n\nexport const Legend = () => (\n <Text>\n <Text color=\"green\">✔ pass</Text>\n <Text dimColor>{' · '}</Text>\n <Text color=\"red\">✘ error</Text>\n <Text dimColor>{' · '}</Text>\n <Text color=\"yellow\">⚠ warning</Text>\n <Text dimColor>{' · '}</Text>\n <Text color=\"cyan\">• suggestion</Text>\n </Text>\n);\n","import { Box, Text } from 'ink';\nimport type {\n AuditCheck,\n AuditStatus,\n} from '../../../../../lib/workflows/audit/types.js';\nimport type { ViewerLayout } from './layout.js';\n\ninterface HeaderProps {\n layout: ViewerLayout;\n}\n\ninterface SummaryProps {\n total: number;\n counts: Record<AuditStatus, number>;\n}\n\nfunction statusCounts(checks: AuditCheck[]): Record<AuditStatus, number> {\n const out: Record<AuditStatus, number> = {\n pending: 0,\n pass: 0,\n error: 0,\n warning: 0,\n suggestion: 0,\n };\n for (const c of checks) out[c.status] += 1;\n return out;\n}\n\nexport { statusCounts };\n\nexport const Header = ({ layout }: HeaderProps) => (\n <Box>\n <Box width={layout.statusWidth + layout.colGap}>\n <Text dimColor bold>\n {' '}\n </Text>\n </Box>\n <Box width={layout.areaWidth + layout.colGap}>\n <Text dimColor bold>\n AREA\n </Text>\n </Box>\n <Box width={layout.labelWidth + layout.colGap}>\n <Text dimColor bold>\n CHECK\n </Text>\n </Box>\n </Box>\n);\n\nexport const Summary = ({ total, counts }: SummaryProps) => (\n <Text dimColor>\n {total} total · {counts.pending} pending · {counts.error} errors ·{' '}\n {counts.warning} warnings · {counts.suggestion} suggestions · {counts.pass}{' '}\n passes\n </Text>\n);\n","import { Legend } from './Legend.js';\nimport { Summary } from './Header.js';\nimport type { AuditStatus } from '../../../../../lib/workflows/audit/types.js';\n\ninterface FooterProps {\n total: number;\n counts: Record<AuditStatus, number>;\n}\n\nexport const Footer = ({ total, counts }: FooterProps) => (\n <>\n <Legend />\n <Summary total={total} counts={counts} />\n </>\n);\n","import type {\n AuditCheck,\n AuditStatus,\n} from '../../../../../lib/workflows/audit/types.js';\n\nconst STATUS_ORDER: Record<AuditStatus, number> = {\n error: 0,\n warning: 1,\n suggestion: 2,\n pass: 3,\n pending: 4,\n};\n\n/** Audit areas in the order they should be displayed. Areas not listed\n * here fall through to alphabetical order at the end. Mirrors the\n * Full audit section grouping in the generated report. */\nconst AREA_ORDER: string[] = [\n 'Installation',\n 'Identification',\n 'Event Capture',\n 'Event Quality',\n 'Feature Flags',\n 'Session Replay',\n 'Session Replay — Optimize',\n 'Use Case: Expansion',\n 'Additional Sections',\n];\n\nfunction areaRank(area: string): number {\n const idx = AREA_ORDER.indexOf(area);\n return idx === -1 ? AREA_ORDER.length : idx;\n}\n\n/** Issues at the top (error → warning → suggestion), then passes, then pending todos. */\nexport function sortChecks(checks: ReadonlyArray<AuditCheck>): AuditCheck[] {\n return [...checks].sort((a, b) => {\n const da = STATUS_ORDER[a.status] - STATUS_ORDER[b.status];\n if (da !== 0) return da;\n return a.area.localeCompare(b.area);\n });\n}\n\nexport interface AreaGroup {\n area: string;\n checks: AuditCheck[];\n counts: { total: number; resolved: number };\n}\n\n/** Group checks by area, in AREA_ORDER. Within each area, sort by status. */\nexport function groupChecksByArea(\n checks: ReadonlyArray<AuditCheck>,\n): AreaGroup[] {\n const byArea = new Map<string, AuditCheck[]>();\n for (const c of checks) {\n const list = byArea.get(c.area);\n if (list) list.push(c);\n else byArea.set(c.area, [c]);\n }\n const groups: AreaGroup[] = [];\n for (const [area, areaChecks] of byArea) {\n const sorted = [...areaChecks].sort(\n (a, b) => STATUS_ORDER[a.status] - STATUS_ORDER[b.status],\n );\n const resolved = sorted.filter((c) => c.status !== 'pending').length;\n groups.push({\n area,\n checks: sorted,\n counts: { total: sorted.length, resolved },\n });\n }\n groups.sort((a, b) => {\n const dr = areaRank(a.area) - areaRank(b.area);\n if (dr !== 0) return dr;\n return a.area.localeCompare(b.area);\n });\n return groups;\n}\n","/**\n * AuditChecksViewer — \"Audit plan\" tab.\n *\n * Renders the full audit ledger as a scrollable, area-grouped list that\n * mirrors the structure of the final report. Each area gets a sub-header\n * with a resolved/total count; checks within an area are sorted by\n * severity (error → warning → suggestion → pass → pending).\n *\n * Two interactions, both registered via `useKeyBindings`:\n * - `e` — toggle detail rows (file:line + agent's `details` text)\n * - `↑` / `↓` — scroll one row at a time, clamped to content bounds\n *\n * Auto-expands on first mount when the ledger contains any issue, since\n * the AuditAreaPane's `[→] View issues` hint sends users here precisely\n * to read those details.\n */\n\nimport { Box, Text } from 'ink';\nimport { Fragment, useMemo, useState, type ReactNode } from 'react';\nimport { useStdoutDimensions } from '../../../hooks/useStdoutDimensions.js';\nimport {\n KeyMatch,\n useKeyBindings,\n type KeyBinding,\n} from '../../../hooks/useKeyBindings.js';\nimport type { AuditCheck } from '../../../../../lib/workflows/audit/types.js';\nimport { AreaHeaderRow } from './AreaHeaderRow.js';\nimport { CheckRow } from './CheckRow.js';\nimport { DetailRow } from './DetailRow.js';\nimport { Footer } from './Footer.js';\nimport { Header, Summary, statusCounts } from './Header.js';\nimport { computeLayout } from './layout.js';\nimport { groupChecksByArea } from './sort.js';\n\ninterface AuditChecksViewerProps {\n checks: AuditCheck[];\n}\n\nexport const AuditChecksViewer = ({ checks }: AuditChecksViewerProps) => {\n // ── Layout ─────────────────────────────────────────────────────────\n const [rawCols, termRows] = useStdoutDimensions();\n const layout = computeLayout(rawCols, termRows);\n const totalHeight = layout.visibleHeight + layout.viewerChrome;\n\n // ── Group by area ──────────────────────────────────────────────────\n const groups = useMemo(() => groupChecksByArea(checks), [checks]);\n const counts = useMemo(() => statusCounts(checks), [checks]);\n\n // ── Expand state ───────────────────────────────────────────────────\n const hasExpandable = checks.some((c) => Boolean(c.details || c.file));\n const hasIssues = checks.some(\n (c) =>\n c.status === 'error' ||\n c.status === 'warning' ||\n c.status === 'suggestion',\n );\n const [expanded, setExpanded] = useState(hasIssues && hasExpandable);\n\n // ── Flat row list ──────────────────────────────────────────────────\n // One ReactNode per visible terminal row so scroll math stays simple.\n // Sub-header + check rows + (optional) detail rows interleave here.\n const allRows = useMemo<ReactNode[]>(() => {\n const rows: ReactNode[] = [];\n for (const group of groups) {\n rows.push(\n <AreaHeaderRow\n key={`header-${group.area}`}\n area={group.area}\n resolved={group.counts.resolved}\n total={group.counts.total}\n />,\n );\n for (const item of group.checks) {\n rows.push(<CheckRow key={item.id} item={item} layout={layout} />);\n if (expanded && (item.details || item.file)) {\n rows.push(\n <DetailRow key={`${item.id}-detail`} item={item} layout={layout} />,\n );\n }\n }\n }\n return rows;\n }, [groups, expanded, layout]);\n\n // ── Scroll viewport ────────────────────────────────────────────────\n const [offset, setOffset] = useState(0);\n const maxOffset = Math.max(0, allRows.length - layout.visibleHeight);\n const clampedOffset = Math.min(offset, maxOffset);\n const hiddenAbove = clampedOffset;\n const hiddenBelow = Math.max(\n 0,\n allRows.length - clampedOffset - layout.visibleHeight,\n );\n\n // ── Key bindings ───────────────────────────────────────────────────\n const bindings: KeyBinding[] = [];\n if (hasExpandable) {\n bindings.push({\n match: 'e',\n label: 'e',\n action: expanded ? 'collapse details' : 'expand details',\n handler: () => setExpanded((prev) => !prev),\n });\n }\n bindings.push({\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '↑↓',\n action: 'scroll',\n handler: (_input, key) => {\n if (key.upArrow) setOffset((o) => Math.max(0, o - 1));\n else if (key.downArrow) setOffset((o) => Math.min(maxOffset, o + 1));\n },\n });\n useKeyBindings('audit-checks-viewer', bindings);\n\n // ── Render ─────────────────────────────────────────────────────────\n const visibleRows = allRows.slice(\n clampedOffset,\n clampedOffset + layout.visibleHeight,\n );\n\n // Dynamic subtitle — lists the actual areas in the ledger.\n const subtitle =\n groups.length === 0\n ? 'No checks yet.'\n : `Review across ${groups.length} ${\n groups.length === 1 ? 'area' : 'areas'\n } — mirrors the final report.`;\n\n return (\n <Box flexDirection=\"column\" paddingX={1} height={totalHeight}>\n {/* Title + dynamic subtitle */}\n <Text bold>Audit plan</Text>\n <Text dimColor>{subtitle}</Text>\n\n {/* Top summary — same as Footer summary, promoted here for at-a-glance */}\n <Summary total={checks.length} counts={counts} />\n <Box height={1} />\n\n {/* Column headers + divider */}\n <Header layout={layout} />\n <Text dimColor>{'─'.repeat(layout.dividerWidth)}</Text>\n\n {/* Scroll-up marker */}\n <Text dimColor>{hiddenAbove > 0 ? `↑ ${hiddenAbove} more` : ' '}</Text>\n\n {/* Scrollable body */}\n <Box\n flexDirection=\"column\"\n height={layout.visibleHeight}\n overflow=\"hidden\"\n >\n {visibleRows.map((node, i) => (\n <Fragment key={`row-${clampedOffset + i}`}>{node}</Fragment>\n ))}\n </Box>\n\n {/* Scroll-down marker */}\n <Text dimColor>{hiddenBelow > 0 ? `↓ ${hiddenBelow} more` : ' '}</Text>\n\n {/* Legend (counts already shown at the top) */}\n <Footer total={checks.length} counts={counts} />\n </Box>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AuditChecksViewer-CjBCZjxG.js","names":["CHROME_ROWS","fs"],"sources":["../src/ui/tui/store.ts","../src/ui/tui/styles.ts","../src/ui/tui/primitives/CardLayout.tsx","../src/ui/tui/primitives/SplitView.tsx","../src/ui/tui/primitives/LoadingBox.tsx","../src/ui/tui/primitives/ProgressList.tsx","../src/ui/tui/primitives/PromptLabel.tsx","../src/ui/tui/hooks/keyboard-hints-utils.ts","../src/ui/tui/hooks/useKeyboardHints.tsx","../src/ui/tui/hooks/useKeyBindings.ts","../src/ui/tui/primitives/PickerMenu.tsx","../src/ui/tui/hooks/useStdoutDimensions.ts","../src/ui/tui/primitives/GroupedPickerMenu.tsx","../src/ui/tui/primitives/ConfirmationInput.tsx","../src/ui/tui/primitives/Divider.tsx","../src/ui/tui/primitives/ModalOverlay.tsx","../src/ui/tui/primitives/LogViewer.tsx","../src/ui/tui/primitives/EventPlanViewer.tsx","../src/ui/tui/components/TitleBar.tsx","../src/ui/tui/primitives/DissolveTransition.tsx","../src/ui/tui/primitives/KeyboardHintsBar.tsx","../src/ui/tui/primitives/ScreenErrorBoundary.tsx","../src/ui/tui/primitives/ScreenContainer.tsx","../src/ui/tui/primitives/TabContainer.tsx","../src/ui/tui/primitives/HNViewer.tsx","../src/ui/tui/primitives/text-helpers.ts","../src/ui/tui/primitives/content-types.ts","../src/ui/tui/primitives/layout-helpers.ts","../src/ui/tui/primitives/TextBlock.tsx","../src/ui/tui/primitives/LinesBlock.tsx","../src/ui/tui/primitives/NodeBlock.tsx","../src/ui/tui/primitives/ContentSequencer.tsx","../src/ui/tui/components/LearnCard.tsx","../src/ui/tui/components/TipsCard.tsx","../src/ui/tui/components/ServiceHealthList.tsx","../src/ui/tui/screens/doctor/IssueTable.tsx","../src/ui/tui/screens/McpScreen.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/AreaHeaderRow.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/layout.ts","../src/ui/tui/screens/audit/AuditChecksViewer/CheckRow.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/DetailRow.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/Legend.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/Header.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/Footer.tsx","../src/ui/tui/screens/audit/AuditChecksViewer/sort.ts","../src/ui/tui/screens/audit/AuditChecksViewer/AuditChecksViewer.tsx"],"sourcesContent":["/**\n * WizardStore — Nanostore-backed reactive store for the TUI.\n * React components subscribe via useSyncExternalStore.\n *\n * The active screen is derived from session state — WizardRouter walks\n * the flow and shows the first step whose `isComplete` is still false.\n *\n * Define a step `gate` if your screen needs to await user interactions.\n * bin.ts calls `await store.getGate(stepId)` to pause until the gate\n * predicate becomes true.\n *\n * All session mutations that affect screen resolution go through\n * explicit setters so emitChange() is always called.\n */\n\nimport { atom, map } from 'nanostores';\nimport { TaskStatus, isTaskStatus } from '../wizard-ui.js';\nimport {\n type WizardSession,\n type OutroData,\n type DiscoveredFeature,\n AdditionalFeature,\n McpOutcome,\n RunPhase,\n buildSession,\n} from '../../lib/wizard-session.js';\nimport type { SettingsConflict } from '../../lib/agent/agent-interface.js';\nimport type { WizardReadinessResult } from '../../lib/health-checks/readiness.js';\nimport {\n WizardRouter,\n type ScreenName,\n Screen,\n Overlay,\n Flow,\n} from './router.js';\nimport { analytics, sessionProperties } from '../../utils/analytics.js';\nimport type {\n StoreInitContext,\n WorkflowReadyContext,\n} from '../../lib/workflows/workflow-step.js';\nimport { WORKFLOW_STEPS } from './flows.js';\n\nexport { TaskStatus, Screen, Overlay, Flow, RunPhase, McpOutcome };\nexport type { ScreenName, OutroData, WizardSession };\n\nexport interface TaskItem {\n label: string;\n activeForm?: string;\n status: TaskStatus;\n /** Legacy compat */\n done: boolean;\n}\n\nexport interface PlannedEvent {\n name: string;\n description: string;\n}\n\ninterface GateEntry {\n predicate: (session: WizardSession) => boolean;\n promise: Promise<void>;\n resolve: () => void;\n resolved: boolean;\n}\n\nexport class WizardStore {\n // ── Internal nanostore atoms ─────────────────────────────────────\n private $session = map<WizardSession>(buildSession({}));\n private $statusMessages = atom<string[]>([]);\n private $statusExpanded = atom(false);\n private $tasks = atom<TaskItem[]>([]);\n private $eventPlan = atom<PlannedEvent[]>([]);\n private $learnCardBlockIdx = atom(0);\n private $learnCardComplete = atom(false);\n private $version = atom(0);\n\n private _onTasksChanged: (() => void) | null = null;\n /** Last screen seen — used to detect screen transitions for analytics. */\n private _lastScreen: ScreenName | null = null;\n\n /** Hooks run when transitioning onto a screen. */\n private _enterScreenHooks = new Map<ScreenName, (() => void)[]>();\n\n /** Gate promises derived from workflow step definitions. */\n private _gates = new Map<string, GateEntry>();\n\n version = '';\n\n /** Navigation router — resolves active screen from session state. */\n readonly router: WizardRouter;\n\n /** Blocks agent execution until the settings-override overlay is dismissed. */\n private _resolveSettingsOverride: (() => void) | null = null;\n private _backupAndFixSettings: (() => boolean) | null = null;\n\n /** Blocks OAuth flow until the port-conflict overlay is dismissed. */\n private _resolvePortConflict: (() => void) | null = null;\n\n constructor(flow: Flow = Flow.PostHogIntegration) {\n this.router = new WizardRouter(flow);\n this._initFromWorkflow(flow);\n }\n\n /**\n * Scan workflow steps for gate predicates and onInit callbacks.\n * Creates gate promises and fires init work.\n */\n private _initFromWorkflow(flow: Flow): void {\n const steps = WORKFLOW_STEPS[flow];\n if (!steps) return;\n\n // Create gate promises from steps that define them\n for (const step of steps) {\n if (step.gate) {\n let resolve!: () => void;\n const promise = new Promise<void>((r) => {\n resolve = r;\n });\n this._gates.set(step.id, {\n predicate: step.gate,\n promise,\n resolve,\n resolved: false,\n });\n }\n }\n\n // Run onInit callbacks with a minimal context interface.\n // Arrow functions capture `this` from _initFromWorkflow so we don't\n // need to alias it.\n const getSession = (): WizardSession => this.session;\n const ctx: StoreInitContext = {\n get session() {\n return getSession();\n },\n setReadinessResult: (r) => this.setReadinessResult(r),\n setFrameworkContext: (k, v) => this.setFrameworkContext(k, v),\n emitChange: () => this.emitChange(),\n };\n for (const step of steps) {\n step.onInit?.(ctx);\n }\n }\n\n /**\n * Run all `onReady` hooks declared by the current flow's steps, in\n * order. Must be called after `store.session = session` so hooks see\n * the real installDir. bin.ts calls this generically — it doesn't\n * need to know which workflow has which pre-flow work.\n */\n async runReadyHooks(): Promise<void> {\n const steps = WORKFLOW_STEPS[this.router.activeFlow];\n if (!steps) return;\n const ctx: WorkflowReadyContext = {\n session: this.session,\n setFrameworkContext: (k, v) => this.setFrameworkContext(k, v),\n setFrameworkConfig: (i, c) => this.setFrameworkConfig(i, c),\n setDetectedFramework: (l) => this.setDetectedFramework(l),\n setUnsupportedVersion: (info) => this.setUnsupportedVersion(info),\n addDiscoveredFeature: (f) => this.addDiscoveredFeature(f),\n setDetectionComplete: () => this.setDetectionComplete(),\n };\n for (const step of steps) {\n if (step.onReady) {\n await step.onReady(ctx);\n }\n }\n }\n\n // ── Gate API ────────────────────────────────────────────────────\n\n /**\n * Get a gate promise by step ID — the primary blocking checkpoint API\n * for bin.ts. `await store.getGate('...')` parks the caller until the\n * corresponding workflow step's gate predicate flips to true (if the\n * predicate stays false, the caller stays parked indefinitely — the\n * TUI keeps rendering so the user can resolve whatever is blocking).\n *\n * If the workflow doesn't define a step with this ID, or the step\n * has no `gate` predicate, this returns an already-resolved promise\n * so bin.ts flows straight through. This lets workflows opt in to\n * gates on a per-step basis without bin.ts needing to know which\n * gates exist in which flow.\n */\n getGate(stepId: string): Promise<void> {\n return this._gates.get(stepId)?.promise ?? Promise.resolve();\n }\n\n /**\n * Re-evaluate every gate predicate against the current session and\n * resolve any whose predicate now returns true. Called after every\n * emitChange(), so gates unblock as soon as the session mutation\n * that satisfies them lands. Gates only resolve once — a predicate\n * that goes true → false → true will NOT re-block a caller that\n * already awaited through.\n */\n private _checkGates(): void {\n for (const [, gate] of this._gates) {\n if (!gate.resolved && gate.predicate(this.session)) {\n gate.resolved = true;\n gate.resolve();\n }\n }\n }\n\n // ── State accessors (read from atoms) ────────────────────────────\n\n get session(): WizardSession {\n return this.$session.get();\n }\n\n set session(value: WizardSession) {\n this.$session.set(value);\n this.emitChange();\n }\n\n get statusMessages(): string[] {\n return this.$statusMessages.get();\n }\n\n get tasks(): TaskItem[] {\n return this.$tasks.get();\n }\n\n get eventPlan(): PlannedEvent[] {\n return this.$eventPlan.get();\n }\n\n get statusExpanded(): boolean {\n return this.$statusExpanded.get();\n }\n\n toggleStatusExpanded(): void {\n this.$statusExpanded.set(!this.$statusExpanded.get());\n this.emitChange();\n }\n\n setStatusExpanded(expanded: boolean): void {\n if (this.$statusExpanded.get() !== expanded) {\n this.$statusExpanded.set(expanded);\n this.emitChange();\n }\n }\n\n // ── Session setters ─────────────────────────────────────────────\n // Every setter that affects screen resolution calls emitChange().\n // Business logic calls these instead of mutating session directly.\n\n /** Sets setupConfirmed. Gate resolves via _checkGates(). */\n completeSetup(): void {\n this.$session.setKey('setupConfirmed', true);\n analytics.wizardCapture('setup confirmed', sessionProperties(this.session));\n this.emitChange();\n }\n\n setRunPhase(phase: RunPhase): void {\n this.$session.setKey('runPhase', phase);\n this.emitChange();\n }\n\n setCredentials(credentials: WizardSession['credentials']): void {\n this.$session.setKey('credentials', credentials);\n analytics.wizardCapture('auth complete', {\n project_id: credentials?.projectId,\n });\n this.emitChange();\n }\n\n setFrameworkConfig(\n integration: WizardSession['integration'],\n config: WizardSession['frameworkConfig'],\n ): void {\n this.$session.setKey('integration', integration);\n this.$session.setKey('frameworkConfig', config);\n this.$session.setKey('unsupportedVersion', null);\n this.emitChange();\n }\n\n setDetectionComplete(): void {\n this.$session.setKey('detectionComplete', true);\n this.emitChange();\n }\n\n setDetectedFramework(label: string): void {\n this.$session.setKey('detectedFrameworkLabel', label);\n this.emitChange();\n }\n\n setUnsupportedVersion(info: {\n current: string;\n minimum: string;\n docsUrl: string;\n }): void {\n this.$session.setKey('unsupportedVersion', info);\n this.emitChange();\n }\n\n setLoginUrl(url: string | null): void {\n this.$session.setKey('loginUrl', url);\n this.emitChange();\n }\n\n setReadinessResult(result: WizardReadinessResult | null): void {\n this.$session.setKey('readinessResult', result);\n this.emitChange();\n }\n\n /** User dismissed the blocking outage screen. Gate resolves via _checkGates(). */\n dismissOutage(): void {\n this.$session.setKey('outageDismissed', true);\n this.emitChange();\n }\n\n /**\n * Push the settings-override overlay and return a promise that blocks\n * until the user dismisses it via backupAndFixSettingsOverride().\n */\n showSettingsOverride(\n conflicts: SettingsConflict[],\n backupAndFix: () => boolean,\n ): Promise<void> {\n const allKeys = conflicts.flatMap((c) => c.keys);\n this.$session.setKey('settingsOverrideKeys', allKeys);\n this.$session.setKey('settingsConflicts', conflicts);\n this._backupAndFixSettings = backupAndFix;\n\n const hasReadOnly = conflicts.some((c) => !c.writable);\n if (hasReadOnly) {\n this.pushOverlay(Overlay.ManagedSettings);\n } else {\n this.pushOverlay(Overlay.SettingsOverride);\n }\n\n return new Promise((resolve) => {\n this._resolveSettingsOverride = resolve;\n });\n }\n\n /**\n * Push the port-conflict overlay and return a promise that blocks\n * until the user frees the ports and retries, or exits.\n */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n port: number;\n user: string;\n }): Promise<void> {\n this.$session.setKey('portConflictProcess', processInfo);\n this.pushOverlay(Overlay.PortConflict);\n return new Promise((resolve) => {\n this._resolvePortConflict = resolve;\n });\n }\n\n /** Dismiss the port-conflict overlay and retry the OAuth port loop. */\n resolvePortConflict(): void {\n this.$session.setKey('portConflictProcess', null);\n this.popOverlay();\n this._resolvePortConflict?.();\n this._resolvePortConflict = null;\n }\n\n /**\n * Back up .claude/settings.json. Dismisses the overlay on success.\n */\n backupAndFixSettingsOverride(): boolean {\n const ok = this._backupAndFixSettings?.() ?? false;\n if (ok) {\n this.$session.setKey('settingsOverrideKeys', null);\n this.$session.setKey('settingsConflicts', null);\n this.popOverlay();\n this._resolveSettingsOverride?.();\n this._resolveSettingsOverride = null;\n this._backupAndFixSettings = null;\n }\n return ok;\n }\n\n /** Push the auth-error overlay (no dismiss — user must exit). */\n showAuthError(): void {\n this.pushOverlay(Overlay.AuthError);\n }\n\n addDiscoveredFeature(feature: DiscoveredFeature): void {\n if (!this.session.discoveredFeatures.includes(feature)) {\n this.session.discoveredFeatures.push(feature);\n this.emitChange();\n }\n }\n\n /**\n * Enable an additional feature: enqueue it for the stop hook\n * and set any feature-specific session flags.\n */\n enableFeature(feature: AdditionalFeature): void {\n if (!this.session.additionalFeatureQueue.includes(feature)) {\n this.session.additionalFeatureQueue.push(feature);\n }\n // Feature-specific flags\n if (feature === AdditionalFeature.LLM) {\n this.session.llmOptIn = true;\n }\n analytics.wizardCapture('feature enabled', { feature });\n this.emitChange();\n }\n\n setMcpComplete(\n outcome: McpOutcome = McpOutcome.Skipped,\n installedClients: string[] = [],\n ): void {\n this.$session.setKey('mcpComplete', true);\n this.$session.setKey('mcpOutcome', outcome);\n this.$session.setKey('mcpInstalledClients', installedClients);\n analytics.wizardCapture('mcp complete', {\n mcp_outcome: outcome,\n mcp_installed_clients: installedClients,\n ...sessionProperties(this.session),\n });\n this.emitChange();\n }\n\n setSkillsComplete(kept: boolean): void {\n this.$session.setKey('skillsComplete', true);\n analytics.wizardCapture('skills complete', {\n skills_kept: kept,\n ...sessionProperties(this.session),\n });\n this.emitChange();\n }\n\n setOutroDismissed(): void {\n this.$session.setKey('outroDismissed', true);\n this.emitChange();\n }\n\n setOutroData(data: OutroData): void {\n this.$session.setKey('outroData', data);\n this.emitChange();\n }\n\n setFrameworkContext(key: string, value: unknown): void {\n const ctx = { ...this.$session.get().frameworkContext, [key]: value };\n this.$session.setKey('frameworkContext', ctx);\n this.emitChange();\n }\n\n // ── Derived state ───────────────────────────────────────────────\n\n /**\n * The screen that should be rendered right now.\n * Derived from session state via the router.\n */\n get currentScreen(): ScreenName {\n return this.router.resolve(this.session);\n }\n\n /** Direction hint for screen transitions. */\n get lastNavDirection(): 'push' | 'pop' | null {\n return this.router.lastNavDirection;\n }\n\n // ── Change notification ─────────────────────────────────────────\n\n getVersion(): number {\n return this.$version.get();\n }\n\n /**\n * Notify React that state has changed.\n * The router re-resolves the active screen on next render.\n * Gate predicates are checked and resolved if ready.\n */\n emitChange(): void {\n this.router._setDirection('push');\n this.$version.set(this.$version.get() + 1);\n this._checkGates();\n this._detectTransition();\n }\n\n // ── Overlay navigation ──────────────────────────────────────────\n\n pushOverlay(overlay: Overlay): void {\n this.router._setDirection('push');\n this.router.pushOverlay(overlay);\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n popOverlay(): void {\n this.router._setDirection('pop');\n this.router.popOverlay();\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n // ── Screen transition analytics ─────────────────────────────────\n\n /**\n * Register a callback to run when transitioning onto the given screen.\n * Fires after every transition that lands on this screen.\n */\n onEnterScreen(screen: ScreenName, fn: () => void): void {\n const list = this._enterScreenHooks.get(screen) ?? [];\n list.push(fn);\n this._enterScreenHooks.set(screen, list);\n }\n\n /**\n * Detect screen transitions, run enter-screen hooks, and fire analytics.\n * Called at the end of emitChange/pushOverlay/popOverlay.\n */\n private _detectTransition(): void {\n const next = this.router.resolve(this.session);\n const prev = this._lastScreen;\n if (prev !== null && next !== prev) {\n const hooks = this._enterScreenHooks.get(next);\n if (hooks) {\n for (const fn of hooks) fn();\n }\n analytics.wizardCapture(`screen ${next}`, {\n from_screen: prev,\n workflow: this.router.activeFlow,\n ...sessionProperties(this.session),\n });\n }\n this._lastScreen = next;\n }\n\n // ── Agent observation state ─────────────────────────────────────\n\n pushStatus(message: string): void {\n const msgs = this.$statusMessages.get();\n // Skip consecutive duplicate messages\n if (msgs.length > 0 && msgs[msgs.length - 1] === message) return;\n this.$statusMessages.set([...msgs, message]);\n this.emitChange();\n }\n\n setTasks(tasks: TaskItem[]): void {\n this.$tasks.set(tasks);\n this.emitChange();\n }\n\n updateTask(index: number, done: boolean): void {\n const tasks = this.$tasks.get();\n if (tasks[index]) {\n const updated = [...tasks];\n updated[index] = {\n ...updated[index],\n done,\n status: done ? TaskStatus.Completed : TaskStatus.Pending,\n };\n this.$tasks.set(updated);\n this.emitChange();\n }\n }\n\n setEventPlan(events: PlannedEvent[]): void {\n this.$eventPlan.set(events);\n this.emitChange();\n }\n\n get learnCardBlockIdx(): number {\n return this.$learnCardBlockIdx.get();\n }\n\n setLearnCardBlockIdx(idx: number): void {\n this.$learnCardBlockIdx.set(idx);\n }\n\n get learnCardComplete(): boolean {\n return this.$learnCardComplete.get();\n }\n\n setLearnCardComplete(): void {\n this.$learnCardComplete.set(true);\n this.emitChange();\n }\n\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void {\n const incoming = todos.map((t) => {\n const status = isTaskStatus(t.status) ? t.status : TaskStatus.Pending;\n return {\n label: t.content,\n activeForm: t.activeForm,\n status,\n done: status === TaskStatus.Completed,\n };\n });\n\n const incomingLabels = new Set(incoming.map((t) => t.label));\n\n const retained = this.$tasks\n .get()\n .filter((t) => t.done && !incomingLabels.has(t.label));\n\n this.$tasks.set([...retained, ...incoming]);\n this.emitChange();\n this._onTasksChanged?.();\n }\n\n /** Register a listener for task state changes (e.g. task stream push). */\n set onTasksChanged(fn: () => void) {\n this._onTasksChanged = fn;\n }\n\n // ── React integration ───────────────────────────────────────────\n\n subscribe(callback: () => void): () => void {\n return this.$version.listen(() => callback());\n }\n\n getSnapshot(): number {\n return this.$version.get();\n }\n}\n","/**\n * Shared style constants for TUI layout primitives.\n */\n\nexport enum HAlign {\n Left = 'flex-start',\n Center = 'center',\n Right = 'flex-end',\n}\n\nexport enum VAlign {\n Top = 'flex-start',\n Center = 'center',\n Bottom = 'flex-end',\n}\n\nexport const Colors = {\n primary: 'cyan',\n accent: '#DC9300',\n titleColor: '#3D2800',\n success: 'green',\n error: 'red',\n muted: 'gray',\n} as const;\n\nexport const Icons = {\n diamond: '\\u25C6',\n diamondOpen: '\\u25C7',\n check: '\\u2714',\n warning: '\\u26A0',\n squareFilled: '\\u25FC',\n squareOpen: '\\u25FB',\n triangleRight: '\\u25B6',\n triangleSmallRight: '\\u25B8',\n bullet: '\\u2022',\n} as const;\n","/**\n * CardLayout — Aligns a single child within available space.\n */\n\nimport { Box } from 'ink';\nimport type { ReactNode } from 'react';\nimport { HAlign, VAlign } from '../styles.js';\n\ninterface CardLayoutProps {\n hAlign?: HAlign;\n vAlign?: VAlign;\n children: ReactNode;\n}\n\nexport const CardLayout = ({\n hAlign = HAlign.Left,\n vAlign = VAlign.Top,\n children,\n}: CardLayoutProps) => {\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n justifyContent={vAlign}\n alignItems={hAlign}\n >\n {children}\n </Box>\n );\n};\n","/**\n * SplitView — Two-pane horizontal layout: 50/50.\n */\n\nimport { Box } from 'ink';\nimport type { ReactNode } from 'react';\n\ninterface SplitViewProps {\n left: ReactNode;\n right: ReactNode;\n gap?: number;\n}\n\nexport const SplitView = ({ left, right, gap = 2 }: SplitViewProps) => {\n return (\n <Box flexDirection=\"row\" flexGrow={1} flexShrink={1} gap={gap}>\n <Box width=\"50%\" flexDirection=\"column\" overflow=\"hidden\">\n {left}\n </Box>\n <Box width=\"50%\" flexDirection=\"column\" overflow=\"hidden\">\n {right}\n </Box>\n </Box>\n );\n};\n","/**\n * LoadingBox — Spinner with message.\n */\n\nimport { Box, Text } from 'ink';\nimport { Spinner } from '@inkjs/ui';\n\ninterface LoadingBoxProps {\n message: string;\n}\n\nexport const LoadingBox = ({ message }: LoadingBoxProps) => {\n return (\n <Box gap={1}>\n <Spinner />\n <Text>{message}</Text>\n </Box>\n );\n};\n","/**\n * ProgressList — Reusable task checklist with status icons.\n * Extracted from StatusTab logic.\n */\n\nimport { Box, Text } from 'ink';\nimport { Spinner } from '@inkjs/ui';\nimport { Colors, Icons } from '../styles.js';\nimport { LoadingBox } from './LoadingBox.js';\n\nexport interface ProgressItem {\n label: string;\n activeForm?: string;\n status: 'pending' | 'in_progress' | 'completed';\n}\n\ninterface ProgressListProps {\n items: ProgressItem[];\n title?: string;\n}\n\nexport const ProgressList = ({ items, title }: ProgressListProps) => {\n const completed = items.filter((t) => t.status === 'completed').length;\n const total = items.length;\n\n return (\n <Box flexDirection=\"column\">\n {title && (\n <>\n <Text bold>{title}</Text>\n <Text> </Text>\n </>\n )}\n {items.length === 0 && <LoadingBox message=\"Analyzing project...\" />}\n {items.map((item, i) => {\n const icon =\n item.status === 'completed'\n ? Icons.squareFilled\n : item.status === 'in_progress'\n ? Icons.triangleRight\n : Icons.squareOpen;\n const color =\n item.status === 'completed'\n ? Colors.success\n : item.status === 'in_progress'\n ? Colors.primary\n : Colors.muted;\n const label =\n item.status === 'in_progress' && item.activeForm\n ? item.activeForm\n : item.label;\n\n return (\n <Text key={i}>\n <Text color={color}>{icon}</Text>\n <Text dimColor={item.status === 'pending'}> {label}</Text>\n </Text>\n );\n })}\n {total > 0 && (\n <Box marginTop={1} gap={1}>\n <Spinner />\n <Text dimColor>\n {completed < total\n ? `Progress: ${completed}/${total} completed`\n : 'Cleaning up...'}\n </Text>\n </Box>\n )}\n </Box>\n );\n};\n","/**\n * PromptLabel — Compact inline label for input prompts.\n *\n * Renders: [!] message\n * where [!] is black text on accent background.\n */\n\nimport { Box, Text } from 'ink';\nimport { Colors } from '../styles.js';\n\ninterface PromptLabelProps {\n message?: string;\n}\n\nexport const PromptLabel = ({ message }: PromptLabelProps) => {\n return (\n <Box>\n <Text bold color={Colors.accent}>\n {' '}\n {message}\n </Text>\n </Box>\n );\n};\n","/**\n * Pure utility functions for keyboard hints — no React or Ink dependencies.\n * Extracted for testability in a node Jest environment.\n */\n\nexport interface KeyboardHint {\n label: string;\n action: string;\n priority: number;\n}\n\n/** Well-known key matches corresponding to Ink's key.* properties. */\nexport enum KeyMatch {\n UpArrow = 'upArrow',\n DownArrow = 'downArrow',\n LeftArrow = 'leftArrow',\n RightArrow = 'rightArrow',\n Return = 'return',\n Escape = 'escape',\n Space = 'space',\n}\n\n/** A key match: either a KeyMatch enum value or a literal character string (e.g. 'a', 's'). */\nexport type KeyMatchOrChar = KeyMatch | (string & NonNullable<unknown>);\n\n/** Default priorities by key type. */\nconst DEFAULT_PRIORITY: Record<string, number> = {\n [KeyMatch.UpArrow]: 0,\n [KeyMatch.DownArrow]: 0,\n [KeyMatch.LeftArrow]: 1,\n [KeyMatch.RightArrow]: 1,\n [KeyMatch.Space]: 10,\n [KeyMatch.Escape]: 20,\n [KeyMatch.Return]: 21,\n};\n\n/** Get the default display priority for a key match. */\nexport function getDefaultPriority(\n match: KeyMatchOrChar | KeyMatchOrChar[],\n): number {\n const first = Array.isArray(match) ? match[0] : match;\n return DEFAULT_PRIORITY[first] ?? 15;\n}\n\n/** Check if a KeyMatchOrChar matches the given input string and key flags. */\nexport function matchesKey(\n m: KeyMatchOrChar,\n input: string,\n key: { [k: string]: unknown },\n): boolean {\n switch (m) {\n case KeyMatch.UpArrow:\n return !!key.upArrow;\n case KeyMatch.DownArrow:\n return !!key.downArrow;\n case KeyMatch.LeftArrow:\n return !!key.leftArrow;\n case KeyMatch.RightArrow:\n return !!key.rightArrow;\n case KeyMatch.Return:\n return !!key.return;\n case KeyMatch.Escape:\n return !!key.escape;\n case KeyMatch.Space:\n return input === ' ';\n default:\n return input === m;\n }\n}\n\n/** Serialize hints for comparison. */\nexport function hintsKey(hints: KeyboardHint[]): string {\n return hints.map((h) => `${h.label}:${h.action}`).join('|');\n}\n\n/** Deduplicate hints by label+action and sort by priority. */\nexport function deduplicateAndSort(hints: KeyboardHint[]): KeyboardHint[] {\n const seen = new Set<string>();\n const deduped: KeyboardHint[] = [];\n for (const hint of hints) {\n const k = `${hint.label}:${hint.action}`;\n if (!seen.has(k)) {\n seen.add(k);\n deduped.push(hint);\n }\n }\n deduped.sort((a, b) => a.priority - b.priority);\n return deduped;\n}\n","/**\n * KeyboardHintsProvider — Context for collecting and displaying keyboard hints.\n *\n * Input components register their hints via useKeyBindings. The provider\n * flattens, deduplicates, and sorts them. It auto-dismisses 3s after the\n * first keypress and resets when the hint set changes (screen navigation).\n */\n\nimport { useInput } from 'ink';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport {\n hintsKey,\n deduplicateAndSort,\n type KeyboardHint,\n} from './keyboard-hints-utils.js';\n\nexport type { KeyboardHint } from './keyboard-hints-utils.js';\n\ninterface KeyboardHintsContextValue {\n register(id: string, hints: KeyboardHint[]): void;\n unregister(id: string): void;\n hints: KeyboardHint[];\n visible: boolean;\n}\n\nconst KeyboardHintsContext = createContext<KeyboardHintsContextValue>({\n register: () => undefined,\n unregister: () => undefined,\n hints: [],\n visible: false,\n});\n\nexport const useKeyboardHintsContext = () => useContext(KeyboardHintsContext);\n\nconst DISMISS_DELAY = 3000;\n\nexport const KeyboardHintsProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => {\n const registrationsRef = useRef(new Map<string, KeyboardHint[]>());\n const [hints, setHints] = useState<KeyboardHint[]>([]);\n const [visible, setVisible] = useState(true);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const prevHintsKeyRef = useRef('');\n\n const recompute = useCallback(() => {\n const all: KeyboardHint[] = [];\n for (const h of registrationsRef.current.values()) {\n all.push(...h);\n }\n const deduped = deduplicateAndSort(all);\n\n const newKey = hintsKey(deduped);\n if (newKey !== prevHintsKeyRef.current) {\n prevHintsKeyRef.current = newKey;\n setHints(deduped);\n // Reset visibility when hints change (new screen)\n if (newKey.length > 0) {\n setVisible(true);\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n }\n }\n }, []);\n\n const register = useCallback(\n (id: string, h: KeyboardHint[]) => {\n registrationsRef.current.set(id, h);\n recompute();\n },\n [recompute],\n );\n\n const unregister = useCallback(\n (id: string) => {\n registrationsRef.current.delete(id);\n recompute();\n },\n [recompute],\n );\n\n // Dismiss on first keypress after 3s\n useInput(() => {\n if (!visible) return;\n if (timerRef.current) return; // already counting down\n timerRef.current = setTimeout(() => {\n setVisible(false);\n timerRef.current = null;\n }, DISMISS_DELAY);\n });\n\n // Cleanup timer on unmount\n useEffect(() => {\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n };\n }, []);\n\n return (\n <KeyboardHintsContext.Provider\n value={{ register, unregister, hints, visible }}\n >\n {children}\n </KeyboardHintsContext.Provider>\n );\n};\n","/**\n * useKeyBindings — Declarative keyboard input + automatic hint registration.\n *\n * Replaces raw `useInput` in input components. Define bindings as data;\n * the hook wires up the Ink input handler AND registers hints in the\n * KeyboardHintsProvider. One source of truth for keys and their labels.\n */\n\nimport { useInput, type Key } from 'ink';\nimport { useEffect, useRef } from 'react';\nimport { useKeyboardHintsContext } from './useKeyboardHints.js';\nimport {\n matchesKey,\n getDefaultPriority,\n KeyMatch,\n type KeyboardHint,\n type KeyMatchOrChar,\n} from './keyboard-hints-utils.js';\n\nexport { KeyMatch };\nexport type { KeyMatchOrChar } from './keyboard-hints-utils.js';\n\nexport interface KeyBinding {\n /** Which key(s) trigger this binding. Array = multiple keys, one hint. */\n match: KeyMatchOrChar | KeyMatchOrChar[];\n /** Display label in hints bar (e.g. \"↑↓\", \"space\", \"enter\") */\n label: string;\n /** Description in hints bar (e.g. \"navigate\", \"toggle\") */\n action: string;\n /** Ordering priority (lower = further left). Defaults based on key type. */\n priority?: number;\n /** Handler called when the key matches. */\n handler: (input: string, key: Key) => void;\n}\n\n/**\n * Declarative key bindings hook. Replaces `useInput` in input components.\n * Registers hints automatically with the KeyboardHintsProvider.\n *\n * @param id Unique identifier for this component's hints registration\n * @param bindings Array of key binding definitions\n */\nexport function useKeyBindings(id: string, bindings: KeyBinding[]): void {\n const ctx = useKeyboardHintsContext();\n\n // Extract hints and register. Use a serialized key to avoid unnecessary updates.\n const hintsRef = useRef<string>('');\n const hints: KeyboardHint[] = bindings.map((b) => ({\n label: b.label,\n action: b.action,\n priority: b.priority ?? getDefaultPriority(b.match),\n }));\n const serialized = hints\n .map((h) => `${h.label}:${h.action}:${h.priority}`)\n .join('|');\n\n useEffect(() => {\n if (serialized !== hintsRef.current) {\n hintsRef.current = serialized;\n ctx.register(id, hints);\n }\n return () => ctx.unregister(id);\n // eslint-disable-next-line\n }, [id, serialized]);\n\n // Wire up input handling\n useInput((input, key) => {\n for (const binding of bindings) {\n const matches = Array.isArray(binding.match)\n ? binding.match\n : [binding.match];\n if (matches.some((m) => matchesKey(m, input, key))) {\n binding.handler(input, key);\n return;\n }\n }\n });\n}\n","/**\n * PickerMenu — Single and multi select.\n * Single mode: custom renderer with small triangle indicator.\n * Multi mode: checkbox glyphs with space to toggle.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState } from 'react';\nimport { Icons, Colors } from '../styles.js';\nimport { PromptLabel } from './PromptLabel.js';\nimport {\n useKeyBindings,\n KeyMatch,\n type KeyBinding,\n} from '../hooks/useKeyBindings.js';\n\ninterface PickerOption<T> {\n label: string;\n value: T;\n hint?: string;\n}\n\ninterface PickerMenuProps<T> {\n message?: string;\n options: PickerOption<T>[];\n mode?: 'single' | 'multi';\n centered?: boolean;\n columns?: 1 | 2 | 3 | 4;\n onSelect: (value: T | T[]) => void;\n}\n\nexport const PickerMenu = <T,>({\n message,\n options,\n mode = 'single',\n centered = false,\n columns = 1,\n onSelect,\n}: PickerMenuProps<T>) => {\n if (mode === 'multi') {\n return (\n <MultiPickerMenu\n message={message}\n options={options}\n centered={centered}\n columns={columns}\n onSelect={onSelect}\n />\n );\n }\n\n return (\n <SinglePickerMenu\n message={message}\n options={options}\n centered={centered}\n columns={columns}\n onSelect={onSelect}\n />\n );\n};\n\n/** Custom single-select with triangle indicator and accent highlight. */\nconst SinglePickerMenu = <T,>({\n message,\n options,\n centered = false,\n columns = 1,\n onSelect,\n}: {\n message?: string;\n options: PickerOption<T>[];\n centered?: boolean;\n columns?: number;\n onSelect: (value: T | T[]) => void;\n}) => {\n const [focused, setFocused] = useState(0);\n const rows = Math.ceil(options.length / columns);\n\n const bindings: KeyBinding[] = [\n {\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '\\u2191\\u2193',\n action: 'navigate',\n handler: (_input, key) => {\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n\n if (key.upArrow) {\n if (row > 0) {\n setFocused(col * rows + row - 1);\n } else {\n setFocused(Math.min(col * rows + rows - 1, options.length - 1));\n }\n }\n if (key.downArrow) {\n const next = col * rows + row + 1;\n if (next < options.length && row + 1 < rows) {\n setFocused(next);\n } else {\n setFocused(col * rows);\n }\n }\n },\n },\n {\n match: KeyMatch.Return,\n label: 'enter',\n action: 'select',\n handler: () => {\n const selected = options[focused];\n if (selected) {\n onSelect(selected.value);\n }\n },\n },\n ];\n\n if (columns > 1) {\n bindings.splice(1, 0, {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'navigate',\n handler: (_input, key) => {\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n\n if (key.leftArrow) {\n const prevCol = col > 0 ? col - 1 : columns - 1;\n setFocused(Math.min(prevCol * rows + row, options.length - 1));\n }\n if (key.rightArrow) {\n const nextCol = col < columns - 1 ? col + 1 : 0;\n setFocused(Math.min(nextCol * rows + row, options.length - 1));\n }\n },\n });\n }\n\n useKeyBindings('single-picker', bindings);\n\n // Chunk options into columns (column-first ordering)\n const columnArrays: PickerOption<T>[][] = [];\n for (let c = 0; c < columns; c++) {\n columnArrays.push(options.slice(c * rows, c * rows + rows));\n }\n\n const align = centered ? 'center' : undefined;\n\n return (\n <Box flexDirection=\"column\" alignItems={align}>\n <PromptLabel message={message} />\n <Box flexDirection=\"row\" gap={4}>\n {columnArrays.map((colOpts, colIdx) => (\n <Box key={colIdx} flexDirection=\"column\">\n {colOpts.map((opt, rowIdx) => {\n const flatIdx = colIdx * rows + rowIdx;\n const isFocused = flatIdx === focused;\n const label = opt.hint ? `${opt.label} (${opt.hint})` : opt.label;\n return (\n <Box key={flatIdx} gap={1}>\n <Text\n color={isFocused ? Colors.accent : undefined}\n dimColor={!isFocused}\n >\n {isFocused ? Icons.triangleSmallRight : ' '}\n </Text>\n <Text\n color={isFocused ? Colors.accent : undefined}\n bold={isFocused}\n dimColor={!isFocused}\n >\n {label}\n </Text>\n </Box>\n );\n })}\n </Box>\n ))}\n </Box>\n </Box>\n );\n};\n\n/** Custom multi-select with checkbox glyphs and accent highlight. */\nconst MultiPickerMenu = <T,>({\n message,\n options,\n centered = false,\n columns = 1,\n onSelect,\n}: {\n message?: string;\n options: PickerOption<T>[];\n centered?: boolean;\n columns?: number;\n onSelect: (value: T | T[]) => void;\n}) => {\n const [focused, setFocused] = useState(0);\n const [selected, setSelected] = useState<Set<number>>(new Set());\n const rows = Math.ceil(options.length / columns);\n\n const bindings: KeyBinding[] = [\n {\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '\\u2191\\u2193',\n action: 'navigate',\n handler: (_input, key) => {\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n\n if (key.upArrow) {\n if (row > 0) {\n setFocused(col * rows + row - 1);\n } else {\n setFocused(Math.min(col * rows + rows - 1, options.length - 1));\n }\n }\n if (key.downArrow) {\n const next = col * rows + row + 1;\n if (next < options.length && row + 1 < rows) {\n setFocused(next);\n } else {\n setFocused(col * rows);\n }\n }\n },\n },\n {\n match: KeyMatch.Space,\n label: 'space',\n action: 'toggle',\n handler: () => {\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(focused)) {\n next.delete(focused);\n } else {\n next.add(focused);\n }\n return next;\n });\n },\n },\n {\n match: KeyMatch.Return,\n label: 'enter',\n action: 'confirm',\n handler: () => {\n if (selected.size === 0) {\n const hovered = options[focused];\n if (hovered) {\n onSelect(hovered.value);\n }\n } else {\n const values = [...selected].sort().map((i) => options[i].value);\n onSelect(values);\n }\n },\n },\n ];\n\n if (columns > 1) {\n bindings.splice(1, 0, {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'navigate',\n handler: (_input, key) => {\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n\n if (key.leftArrow) {\n const prevCol = col > 0 ? col - 1 : columns - 1;\n setFocused(Math.min(prevCol * rows + row, options.length - 1));\n }\n if (key.rightArrow) {\n const nextCol = col < columns - 1 ? col + 1 : 0;\n setFocused(Math.min(nextCol * rows + row, options.length - 1));\n }\n },\n });\n }\n\n useKeyBindings('multi-picker', bindings);\n\n const columnArrays: PickerOption<T>[][] = [];\n for (let c = 0; c < columns; c++) {\n columnArrays.push(options.slice(c * rows, c * rows + rows));\n }\n\n return (\n <Box flexDirection=\"column\" alignItems={centered ? 'center' : undefined}>\n <PromptLabel message={message} />\n <Box\n flexDirection=\"row\"\n gap={4}\n marginLeft={centered ? 0 : 2}\n marginTop={1}\n >\n {columnArrays.map((colOpts, colIdx) => (\n <Box key={colIdx} flexDirection=\"column\">\n {colOpts.map((opt, rowIdx) => {\n const flatIdx = colIdx * rows + rowIdx;\n const isFocused = flatIdx === focused;\n const isSelected = selected.has(flatIdx);\n const label = opt.hint ? `${opt.label} (${opt.hint})` : opt.label;\n const checkbox = isSelected\n ? Icons.squareFilled\n : Icons.squareOpen;\n return (\n <Box key={flatIdx} gap={1}>\n <Text\n color={isSelected ? 'white' : Colors.muted}\n dimColor={!isFocused && !isSelected}\n >\n {checkbox}\n </Text>\n <Text\n color={isFocused ? Colors.accent : undefined}\n bold={isFocused}\n dimColor={!isFocused}\n >\n {label}\n </Text>\n </Box>\n );\n })}\n </Box>\n ))}\n </Box>\n </Box>\n );\n};\n","/**\n * useStdoutDimensions — Returns [columns, rows] and re-renders on terminal resize.\n *\n * Ink's useStdout() does not subscribe to resize events, so layout only updates\n * when something else causes a re-render. This hook listens to the stream's\n * 'resize' event (Node TTY) and updates state so the component re-renders\n * with the new dimensions.\n */\n\nimport { useStdout } from 'ink';\nimport { useState, useEffect } from 'react';\n\nexport function useStdoutDimensions(): [number, number] {\n const { stdout } = useStdout();\n const [size, setSize] = useState<[number, number]>(() => [\n stdout.columns || 80,\n stdout.rows || 24,\n ]);\n\n useEffect(() => {\n const cols = stdout.columns || 80;\n const rows = stdout.rows || 24;\n setSize([cols, rows]);\n\n const stream = stdout as NodeJS.WriteStream & {\n on?(event: string, fn: () => void): void;\n };\n if (typeof stream.on !== 'function') return;\n\n const onResize = () => {\n const c = stdout.columns || 80;\n const r = stdout.rows || 24;\n if (c > 0 && r > 0) setSize([c, r]);\n };\n stream.on('resize', onResize);\n return () => {\n stream.off?.('resize', onResize);\n };\n }, [stdout]);\n\n return size;\n}\n","/**\n * GroupedPickerMenu — Multi-select with category headers.\n *\n * Renders groups of options with bold category labels.\n * Arrow keys navigate selectable items (headers are skipped),\n * space toggles, \"a\" toggles all, enter submits.\n *\n * When content exceeds available terminal height, the list scrolls\n * to keep the focused item visible with up/down indicators.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useMemo } from 'react';\nimport { Icons, Colors } from '../styles.js';\nimport { PromptLabel } from './PromptLabel.js';\nimport { useStdoutDimensions } from '../hooks/useStdoutDimensions.js';\nimport { useKeyBindings, KeyMatch } from '../hooks/useKeyBindings.js';\n\ninterface GroupOption {\n value: string;\n label: string;\n hint?: string;\n}\n\ninterface GroupedPickerMenuProps {\n message?: string;\n groups: Record<string, GroupOption[]>;\n initialSelected?: string[];\n onSelect: (values: string[]) => void;\n}\n\ntype Row =\n | { kind: 'header'; label: string }\n | { kind: 'option'; value: string; label: string; hint?: string };\n\n/** Truncate text with \"\\u2026\" if it exceeds maxWidth. */\nfunction truncateWithEllipsis(text: string, maxWidth: number): string {\n if (text.length <= maxWidth) return text;\n return text.slice(0, maxWidth - 1) + '\\u2026';\n}\n\n/** Rows consumed by chrome outside this component (title bar, screen padding, etc.) */\nconst CHROME_OVERHEAD = 10;\n/** Rows used by the prompt label + marginTop before content (hint text moved to KeyboardHintsBar). */\nconst MENU_CHROME = 2;\n\n/** Count the visual rows occupied by rows[start..end), accounting for header margins. */\nfunction countVisualRows(rows: Row[], start: number, end: number): number {\n let count = 0;\n for (let i = start; i < end && i < rows.length; i++) {\n if (rows[i].kind === 'header' && i > start) count += 1; // marginTop gap\n count += 1;\n }\n return count;\n}\n\n/** From scrollOffset, find how many flat rows fit in the visual budget. */\nfunction computeVisibleEnd(\n rows: Row[],\n scrollOffset: number,\n budget: number,\n): number {\n let visualCount = 0;\n let i = scrollOffset;\n while (i < rows.length) {\n const cost = rows[i].kind === 'header' && i > scrollOffset ? 2 : 1;\n if (visualCount + cost > budget) break;\n visualCount += cost;\n i++;\n }\n return i;\n}\n\n/** Adjust scroll offset to keep focusedRowIdx visible within the viewport. */\nfunction adjustScrollOffset(\n currentOffset: number,\n focusedRowIdx: number,\n rows: Row[],\n viewportBudget: number,\n): number {\n const visibleEnd = computeVisibleEnd(rows, currentOffset, viewportBudget);\n\n // Already visible\n if (focusedRowIdx >= currentOffset && focusedRowIdx < visibleEnd) {\n return currentOffset;\n }\n\n // Focus moved above viewport — scroll up, including group header if adjacent\n if (focusedRowIdx < currentOffset) {\n let newOffset = focusedRowIdx;\n if (newOffset > 0 && rows[newOffset - 1]?.kind === 'header') {\n newOffset--;\n }\n return Math.max(0, newOffset);\n }\n\n // Focus moved below viewport — scroll down minimally\n let newOffset = currentOffset + 1;\n while (newOffset < rows.length) {\n const end = computeVisibleEnd(rows, newOffset, viewportBudget);\n if (focusedRowIdx < end) break;\n newOffset++;\n }\n return Math.min(newOffset, Math.max(0, rows.length - 1));\n}\n\nexport const GroupedPickerMenu = ({\n message,\n groups,\n initialSelected,\n onSelect,\n}: GroupedPickerMenuProps) => {\n const [termCols, termRows] = useStdoutDimensions();\n\n // Available width for option labels, after subtracting layout chrome:\n // paddingX(2) + marginLeft(2) + option marginLeft(1) + gap(1) + checkbox(2) = 8\n const labelWidth = Math.max(10, Math.min(termCols, 120) - 8);\n\n // Build a flat row list with headers interleaved\n const rows = useMemo<Row[]>(() => {\n const result: Row[] = [];\n for (const [groupName, options] of Object.entries(groups)) {\n result.push({ kind: 'header', label: groupName });\n for (const opt of options) {\n result.push({ kind: 'option', ...opt });\n }\n }\n return result;\n }, [groups]);\n\n // Indices of selectable (non-header) rows\n const selectableIndices = useMemo(\n () =>\n rows.map((r, i) => (r.kind === 'option' ? i : -1)).filter((i) => i >= 0),\n [rows],\n );\n\n // All option values for toggle-all\n const allValues = useMemo(\n () =>\n rows\n .filter((r): r is Row & { kind: 'option' } => r.kind === 'option')\n .map((r) => r.value),\n [rows],\n );\n\n const [focusedSelectable, setFocusedSelectable] = useState(0);\n const [selected, setSelected] = useState<Set<string>>(\n () => new Set(initialSelected ?? allValues),\n );\n const [scrollOffset, setScrollOffset] = useState(0);\n\n const focusedRowIdx = selectableIndices[focusedSelectable] ?? 0;\n\n // Viewport budget: how many visual rows can be shown\n const viewportBudget = Math.max(5, termRows - CHROME_OVERHEAD - MENU_CHROME);\n const totalVisual = countVisualRows(rows, 0, rows.length);\n const needsScroll = totalVisual > viewportBudget;\n const effectiveBudget = needsScroll ? viewportBudget - 2 : viewportBudget;\n\n useKeyBindings('grouped-picker', [\n {\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '\\u2191\\u2193',\n action: 'navigate',\n handler: (_input, key) => {\n let newFocused = focusedSelectable;\n\n if (key.upArrow) {\n newFocused =\n focusedSelectable > 0\n ? focusedSelectable - 1\n : selectableIndices.length - 1;\n }\n if (key.downArrow) {\n newFocused =\n focusedSelectable < selectableIndices.length - 1\n ? focusedSelectable + 1\n : 0;\n }\n\n if (newFocused !== focusedSelectable) {\n setFocusedSelectable(newFocused);\n if (needsScroll) {\n const newFocusedRowIdx = selectableIndices[newFocused] ?? 0;\n setScrollOffset((prev) =>\n adjustScrollOffset(prev, newFocusedRowIdx, rows, effectiveBudget),\n );\n }\n }\n },\n },\n {\n match: KeyMatch.Space,\n label: 'space',\n action: 'toggle',\n handler: () => {\n const targetRowIdx = selectableIndices[focusedSelectable] ?? 0;\n const row = rows[targetRowIdx];\n if (row?.kind === 'option') {\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(row.value)) {\n next.delete(row.value);\n } else {\n next.add(row.value);\n }\n return next;\n });\n }\n },\n },\n {\n match: 'a',\n label: 'a',\n action: 'toggle all',\n priority: 11,\n handler: () => {\n setSelected((prev) => {\n if (prev.size === allValues.length) {\n return new Set();\n }\n return new Set(allValues);\n });\n },\n },\n {\n match: KeyMatch.Return,\n label: 'enter',\n action: 'confirm',\n handler: () => {\n onSelect([...selected]);\n },\n },\n ]);\n\n // Determine visible slice\n const visibleStart = needsScroll ? scrollOffset : 0;\n const visibleEnd = needsScroll\n ? computeVisibleEnd(rows, visibleStart, effectiveBudget)\n : rows.length;\n const visibleRows = rows.slice(visibleStart, visibleEnd);\n const hiddenAbove = needsScroll\n ? selectableIndices.filter((s) => s < visibleStart).length\n : 0;\n const hiddenBelow = needsScroll\n ? selectableIndices.filter((s) => s >= visibleEnd).length\n : 0;\n\n return (\n <Box flexDirection=\"column\">\n <PromptLabel message={message} />\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n {needsScroll && (\n <Text dimColor>\n {hiddenAbove > 0 ? `\\u2191 ${hiddenAbove} more` : ' '}\n </Text>\n )}\n {visibleRows.map((row, relIdx) => {\n const absIdx = visibleStart + relIdx;\n\n if (row.kind === 'header') {\n return (\n <Box\n key={`h-${absIdx}`}\n marginTop={relIdx > 0 && absIdx > 0 ? 1 : 0}\n >\n <Text bold dimColor>\n {row.label}\n </Text>\n </Box>\n );\n }\n\n const isFocused = focusedRowIdx === absIdx;\n const isSelected = selected.has(row.value);\n const checkbox = isSelected ? Icons.squareFilled : Icons.squareOpen;\n const fullLabel = row.hint ? `${row.label} (${row.hint})` : row.label;\n const label = truncateWithEllipsis(fullLabel, labelWidth);\n\n return (\n <Box key={row.value} gap={1} marginLeft={1}>\n <Text\n color={isSelected ? 'white' : Colors.muted}\n dimColor={!isFocused && !isSelected}\n >\n {checkbox}\n </Text>\n <Box flexGrow={1} flexShrink={1} overflow=\"hidden\">\n <Text\n color={isFocused ? Colors.accent : undefined}\n bold={isFocused}\n dimColor={!isFocused}\n wrap=\"truncate\"\n >\n {label}\n </Text>\n </Box>\n </Box>\n );\n })}\n {needsScroll && (\n <Text dimColor>\n {hiddenBelow > 0 ? `\\u2193 ${hiddenBelow} more` : ' '}\n </Text>\n )}\n </Box>\n </Box>\n );\n};\n","/**\n * ConfirmationInput — Continue/cancel prompt.\n * Enter confirms, escape cancels. Arrow keys toggle focus.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState } from 'react';\nimport { Icons, Colors } from '../styles.js';\nimport { PromptLabel } from './PromptLabel.js';\nimport { useKeyBindings, KeyMatch } from '../hooks/useKeyBindings.js';\n\ninterface ConfirmationInputProps {\n message: string;\n onConfirm: () => void;\n onCancel: () => void;\n confirmLabel?: string;\n cancelLabel?: string;\n}\n\nenum FocusTarget {\n Continue = 'continue',\n Cancel = 'cancel',\n}\n\nexport const ConfirmationInput = ({\n message,\n onConfirm,\n onCancel,\n confirmLabel = 'Continue',\n cancelLabel = 'Cancel',\n}: ConfirmationInputProps) => {\n const [focused, setFocused] = useState<FocusTarget>(FocusTarget.Continue);\n\n useKeyBindings('confirmation', [\n {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'switch',\n handler: () => {\n setFocused((f) =>\n f === FocusTarget.Continue\n ? FocusTarget.Cancel\n : FocusTarget.Continue,\n );\n },\n },\n {\n match: KeyMatch.Return,\n label: 'enter',\n action: 'confirm',\n handler: () => {\n if (focused === FocusTarget.Continue) {\n onConfirm();\n } else {\n onCancel();\n }\n },\n },\n {\n match: KeyMatch.Escape,\n label: 'esc',\n action: 'cancel',\n handler: () => {\n onCancel();\n },\n },\n ]);\n\n return (\n <Box flexDirection=\"column\">\n <PromptLabel message={message} />\n <Box gap={2} marginTop={1} marginLeft={2}>\n <Text\n bold={focused === FocusTarget.Continue}\n color={\n focused === FocusTarget.Continue ? Colors.accent : Colors.muted\n }\n >\n {focused === FocusTarget.Continue ? Icons.triangleSmallRight : ' '}{' '}\n {confirmLabel}\n </Text>\n <Text\n bold={focused === FocusTarget.Cancel}\n color={focused === FocusTarget.Cancel ? Colors.accent : Colors.muted}\n >\n {focused === FocusTarget.Cancel ? Icons.triangleSmallRight : ' '}{' '}\n {cancelLabel}\n </Text>\n </Box>\n </Box>\n );\n};\n","import { Box, Text, measureElement } from 'ink';\nimport { useRef, useState, useEffect } from 'react';\n\ninterface DividerProps {\n dimColor?: boolean;\n char?: string;\n}\n\nexport const Divider = ({ dimColor = true, char = '─' }: DividerProps) => {\n const ref = useRef(null);\n const [width, setWidth] = useState(0);\n\n useEffect(() => {\n if (ref.current) {\n const { width: measured } = measureElement(ref.current);\n setWidth(measured);\n }\n }, []);\n\n return (\n <Box ref={ref} width=\"100%\">\n <Text dimColor={dimColor}>{width > 0 ? char.repeat(width) : ''}</Text>\n </Box>\n );\n};\n","/**\n * ModalOverlay — Reusable centered card for overlay screens.\n *\n * Shared layout for HealthCheckScreen, SettingsOverrideScreen, PortConflictScreen, etc.\n * Provides: centered card with border, title, body, optional feedback, divider, and actions.\n */\n\nimport type { ReactNode } from 'react';\nimport { Box, Text } from 'ink';\nimport { Divider } from './Divider.js';\n\ninterface ModalOverlayProps {\n /** Card border color */\n borderColor: string;\n /** Title text */\n title: string;\n /** Title text color (defaults to borderColor) */\n titleColor?: string;\n /** Card width (default 68) */\n width?: number;\n /** Body content */\n children: ReactNode;\n /** Optional feedback message (shown in yellow above the divider) */\n feedback?: string | null;\n /** Footer content below the divider (typically ConfirmationInput) */\n footer?: ReactNode;\n}\n\nexport const ModalOverlay = ({\n borderColor,\n title,\n titleColor,\n width = 68,\n children,\n feedback,\n footer,\n}: ModalOverlayProps) => {\n return (\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n alignItems=\"center\"\n justifyContent=\"center\"\n >\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={borderColor}\n paddingX={3}\n paddingY={1}\n width={width}\n >\n <Box justifyContent=\"center\" marginBottom={1}>\n <Text color={titleColor ?? borderColor} bold>\n {title}\n </Text>\n </Box>\n\n {children}\n\n {feedback && (\n <Box marginTop={1}>\n <Text color=\"yellow\">{feedback}</Text>\n </Box>\n )}\n\n {footer && (\n <>\n <Box marginY={1}>\n <Divider />\n </Box>\n {footer}\n </>\n )}\n </Box>\n </Box>\n );\n};\n","/**\n * LogViewer — Real-time log tail, pinned to available terminal height.\n * Only renders the last N lines that fit on screen.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useEffect } from 'react';\nimport * as fs from 'fs';\nimport { useStdoutDimensions } from '../hooks/useStdoutDimensions.js';\n\n/** Rows consumed by TitleBar + spacer + ScreenContainer padding + status bar + tab bar */\nconst CHROME_ROWS = 8;\n\ninterface LogViewerProps {\n filePath: string;\n /** Fixed visible height. Defaults to terminal rows minus chrome. */\n height?: number;\n}\n\nexport const LogViewer = ({ filePath, height }: LogViewerProps) => {\n const [, rows] = useStdoutDimensions();\n const visibleLines = height ?? Math.max(5, rows - CHROME_ROWS);\n\n const [lines, setLines] = useState<string[]>([]);\n\n useEffect(() => {\n const readTail = () => {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const allLines = content.split('\\n');\n setLines(allLines.slice(-visibleLines));\n } catch {\n setLines(['(No log file found)']);\n }\n };\n\n readTail();\n\n let watcher: fs.FSWatcher | undefined;\n try {\n watcher = fs.watch(filePath, () => {\n readTail();\n });\n } catch {\n // File might not exist yet — retry when it appears\n const interval = setInterval(() => {\n try {\n fs.accessSync(filePath);\n readTail();\n clearInterval(interval);\n watcher = fs.watch(filePath, () => readTail());\n } catch {\n // Still waiting\n }\n }, 1000);\n\n return () => clearInterval(interval);\n }\n\n return () => {\n watcher?.close();\n };\n }, [filePath, visibleLines]);\n\n return (\n <Box flexDirection=\"column\" height={visibleLines}>\n {lines.map((line, i) => (\n <Text key={i} dimColor wrap=\"truncate\">\n {line}\n </Text>\n ))}\n </Box>\n );\n};\n","/**\n * EventPlanViewer — Renders a table of planned analytics events.\n */\n\nimport { Box, Text } from 'ink';\nimport type { PlannedEvent } from '../store.js';\n\ninterface EventPlanViewerProps {\n events: PlannedEvent[];\n}\n\nexport const EventPlanViewer = ({ events }: EventPlanViewerProps) => {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text bold>Event plan</Text>\n <Box height={1} />\n {events.map((event) => (\n <Box key={event.name}>\n <Text bold>{event.name}</Text>\n <Text dimColor> {event.description}</Text>\n </Box>\n ))}\n </Box>\n );\n};\n","import { Box, Text } from 'ink';\nimport { Colors } from '../styles.js';\n\nconst FEEDBACK = 'Feedback: wizard@posthog.com ';\nconst FEEDBACK_SHORT = ' wizard@posthog.com ';\n\ninterface TitleBarProps {\n version: string;\n width: number;\n}\n\nexport const TitleBar = ({ version, width }: TitleBarProps) => {\n const fullTitle = ` PostHog Wizard v${version}`;\n const needShort = width < fullTitle.length + FEEDBACK.length;\n const feedback = needShort ? FEEDBACK_SHORT : FEEDBACK;\n const title =\n needShort && fullTitle.length + feedback.length > width\n ? ` Wizard v${version}`\n : fullTitle;\n const gap = Math.max(0, width - title.length - feedback.length);\n const padding = ' '.repeat(gap);\n\n return (\n <Box width={width} overflow=\"hidden\">\n <Text backgroundColor={Colors.accent} color={Colors.titleColor}>\n {title}\n {padding}\n {feedback}\n </Text>\n </Box>\n );\n};\n","/**\n * DissolveTransition — Column-sweep inspired by TTE's Sweep effect.\n *\n * Uses a SequenceEaser (in_out_circ) to activate columns with eased pacing.\n * Each activated column cycles through shade characters (░▒▓█) independently.\n *\n * Out phase: columns sweep, building up shade chars until solid █ (covers old content).\n * In phase: columns sweep in reverse, dissolving █ back through shades to empty (reveals new content).\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useEffect, useRef, type ReactNode } from 'react';\n\n/** Shade characters in build-up order (light → solid). */\nconst SHADES = ['░', '▒', '▓', '█'] as const;\n/** How many ticks each shade character displays before advancing. */\nconst TICKS_PER_SHADE = 2;\n/** Total ticks a column needs to complete its shade cycle. */\nconst SHADE_CYCLE_TICKS = SHADES.length * TICKS_PER_SHADE;\n\nexport type WipeDirection = 'left' | 'right';\n\ninterface DissolveTransitionProps {\n transitionKey: string;\n width: number;\n height: number;\n children: ReactNode;\n direction?: WipeDirection;\n duration?: number;\n}\n\nfunction easeInOutCirc(t: number): number {\n if (t < 0.5) {\n return (1 - Math.sqrt(1 - 4 * t * t)) / 2;\n }\n return (Math.sqrt(1 - (2 * t - 2) ** 2) + 1) / 2;\n}\n\nenum TransitionPhase {\n Idle = 'idle',\n Out = 'out',\n In = 'in',\n}\n\nexport const DissolveTransition = ({\n transitionKey,\n width,\n height,\n children,\n direction = 'left',\n duration = 2,\n}: DissolveTransitionProps) => {\n const [phase, setPhase] = useState<TransitionPhase>(TransitionPhase.Idle);\n const [tick, setTick] = useState(0);\n const [activeDir, setActiveDir] = useState<WipeDirection>(direction);\n const prevKey = useRef(transitionKey);\n const pendingChildren = useRef<ReactNode>(children);\n const [displayChildren, setDisplayChildren] = useState<ReactNode>(children);\n\n // Track when each column was activated (tick number), -1 means not yet.\n const columnActivationTick = useRef<number[]>([]);\n\n useEffect(() => {\n if (transitionKey !== prevKey.current) {\n prevKey.current = transitionKey;\n pendingChildren.current = children;\n setActiveDir(direction);\n setPhase(TransitionPhase.Out);\n setTick(0);\n columnActivationTick.current = new Array(width).fill(-1);\n } else if (phase !== TransitionPhase.Idle) {\n // Terminal resized mid-transition — abort and show new content immediately\n setPhase(TransitionPhase.Idle);\n setDisplayChildren(children);\n } else {\n setDisplayChildren(children);\n }\n }, [transitionKey, children, width, height, phase, direction]);\n\n useEffect(() => {\n if (phase === TransitionPhase.Idle) return;\n\n const timer = setInterval(() => {\n setTick((prev) => prev + 1);\n }, duration);\n\n return () => clearInterval(timer);\n }, [phase, duration]);\n\n // Easer steps = width: roughly one column activates per tick.\n // This keeps the sweep front tight (only a few columns in-flight at once).\n const easerSteps = width;\n\n // A phase ends when the easer has completed AND all columns have finished their shade cycle.\n const maxTicks = easerSteps + SHADE_CYCLE_TICKS;\n\n useEffect(() => {\n if (phase === TransitionPhase.Idle) return;\n if (tick >= maxTicks) {\n if (phase === TransitionPhase.Out) {\n setDisplayChildren(pendingChildren.current);\n setPhase(TransitionPhase.In);\n setTick(0);\n columnActivationTick.current = new Array(width).fill(-1);\n } else {\n setPhase(TransitionPhase.Idle);\n }\n }\n }, [tick, phase, maxTicks, width]);\n\n if (phase === TransitionPhase.Idle) {\n return <>{displayChildren}</>;\n }\n\n // --- SequenceEaser logic ---\n // Map current tick to easer progress (0..1), apply easing,\n // then determine how many columns should be activated.\n const easerProgress = Math.min(tick / easerSteps, 1);\n const easedValue = easeInOutCirc(easerProgress);\n const activatedCount = Math.floor(easedValue * width);\n\n // Build column order based on direction.\n // \"left\" means sweep moves left-to-right; \"right\" means right-to-left.\n // TTE's COLUMN_RIGHT_TO_LEFT activates rightmost first.\n const columnOrder: number[] = [];\n if (activeDir === 'left') {\n for (let c = width - 1; c >= 0; c--) columnOrder.push(c);\n } else {\n for (let c = 0; c < width; c++) columnOrder.push(c);\n }\n\n // Activate columns that should be active but aren't yet.\n for (let i = 0; i < activatedCount && i < columnOrder.length; i++) {\n const col = columnOrder[i];\n if (columnActivationTick.current[col] === -1) {\n columnActivationTick.current[col] = tick;\n }\n }\n\n // --- Render frame ---\n const rows: string[] = [];\n for (let r = 0; r < height; r++) {\n let row = '';\n for (let c = 0; c < width; c++) {\n const activatedAt = columnActivationTick.current[c];\n\n let char: string;\n if (activatedAt === -1) {\n // Not yet activated\n char = phase === TransitionPhase.Out ? ' ' : '█';\n } else {\n // Column is activated — determine shade based on ticks since activation\n const age = tick - activatedAt;\n const shadeIndex = Math.min(\n Math.floor(age / TICKS_PER_SHADE),\n SHADES.length - 1,\n );\n\n if (phase === TransitionPhase.Out) {\n // Building up: ░ → ▒ → ▓ → █\n char = SHADES[shadeIndex];\n } else {\n // Dissolving: █ → ▓ → ▒ → ░ → space\n if (shadeIndex >= SHADES.length - 1 && age >= SHADE_CYCLE_TICKS) {\n char = ' ';\n } else {\n char = SHADES[SHADES.length - 1 - shadeIndex];\n }\n }\n }\n\n row += char;\n }\n rows.push(row);\n }\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n {rows.map((row, i) => (\n <Text key={i} dimColor>\n {row}\n </Text>\n ))}\n </Box>\n );\n};\n","/**\n * KeyboardHintsBar — Row showing active keyboard shortcuts.\n *\n * Always reserves its row to prevent layout shift. When hints are\n * visible, renders them in dimmed grey text. When dismissed, renders\n * an empty reserved row.\n */\n\nimport { Box, Text } from 'ink';\nimport { useKeyboardHintsContext } from '../hooks/useKeyboardHints.js';\nimport { Colors } from '../styles.js';\n\nexport const KeyboardHintsBar = () => {\n const { hints, visible } = useKeyboardHintsContext();\n\n const showHints = visible && hints.length > 0;\n\n return (\n <Box height={1} paddingX={1}>\n {showHints &&\n hints.map((hint, i) => (\n <Box\n key={`${hint.label}-${hint.action}`}\n marginRight={i < hints.length - 1 ? 2 : 0}\n >\n <Text bold color={Colors.muted}>\n {hint.label}\n </Text>\n <Text dimColor> {hint.action}</Text>\n </Box>\n ))}\n </Box>\n );\n};\n","/**\n * ScreenErrorBoundary — catches React render errors in screens\n * and routes to the outro screen with an error message.\n *\n * Without this, a screen crash silently hangs the TUI.\n */\n\nimport { Box, Text } from 'ink';\nimport { Component, type ReactNode } from 'react';\nimport type { WizardStore } from '../store.js';\nimport { OutroKind, RunPhase } from '../../../lib/wizard-session.js';\n\ninterface Props {\n store: WizardStore;\n children: ReactNode;\n}\n\ninterface State {\n error: Error | null;\n}\n\nexport class ScreenErrorBoundary extends Component<Props, State> {\n state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n componentDidCatch(error: Error): void {\n const { store } = this.props;\n\n // eslint-disable-next-line no-console\n console.error('[ScreenErrorBoundary]', error.message, error.stack);\n\n // Set error state — the router will resolve to outro\n store.setOutroData({\n kind: OutroKind.Error,\n message: `A screen crashed: ${error.message}`,\n });\n store.setRunPhase(RunPhase.Error);\n }\n\n render(): ReactNode {\n if (this.state.error) {\n // Fallback while the store transition fires\n return (\n <Box flexDirection=\"column\">\n <Text color=\"red\" bold>\n Something went wrong.\n </Text>\n <Text dimColor>{this.state.error.message}</Text>\n </Box>\n );\n }\n\n return this.props.children;\n }\n}\n","/**\n * ScreenContainer — Renders TitleBar + routes between screens with transitions.\n * Takes a screens map and renders the one matching store.currentScreen.\n * Horizontal wipe plays on push (left) or pop (right).\n *\n * Each screen is wrapped in a ScreenErrorBoundary so that render crashes\n * route to the outro screen with an error message instead of hanging.\n *\n * Provides KeyboardHintsProvider context. The hints bar is rendered below\n * screen content (inside the transition area) so all screens get it.\n */\n\nimport { Box } from 'ink';\nimport { useSyncExternalStore, type ReactNode } from 'react';\nimport { TitleBar } from '../components/TitleBar.js';\nimport { useStdoutDimensions } from '../hooks/useStdoutDimensions.js';\nimport { KeyboardHintsProvider } from '../hooks/useKeyboardHints.js';\nimport { DissolveTransition } from './DissolveTransition.js';\nimport { KeyboardHintsBar } from './KeyboardHintsBar.js';\nimport { ScreenErrorBoundary } from './ScreenErrorBoundary.js';\nimport type { WizardStore } from '../store.js';\n\nconst MIN_WIDTH = 80;\nexport const MAX_WIDTH = 120;\n\n/** Use terminal width when small so we don't overflow; otherwise clamp to [MIN_WIDTH, MAX_WIDTH]. */\nfunction getContentWidth(terminalColumns: number): number {\n if (terminalColumns < MIN_WIDTH) return terminalColumns;\n return Math.min(MAX_WIDTH, terminalColumns);\n}\n\ninterface ScreenContainerProps {\n store: WizardStore;\n screens: Record<string, ReactNode>;\n}\n\nexport const ScreenContainer = ({ store, screens }: ScreenContainerProps) => {\n const [columns, rows] = useStdoutDimensions();\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n const terminalWidth = columns;\n const width = getContentWidth(terminalWidth);\n const contentHeight = Math.max(5, rows - 3);\n const contentAreaWidth = Math.max(10, width - 2);\n const direction = store.lastNavDirection === 'pop' ? 'right' : 'left';\n const activeScreen = screens[store.currentScreen] ?? null;\n\n const inner = (\n <Box flexDirection=\"column\" height={rows} width={width}>\n <TitleBar version={store.version} width={width} />\n <Box height={1} />\n <Box flexDirection=\"column\" flexGrow={1} paddingX={1}>\n <DissolveTransition\n transitionKey={store.currentScreen}\n width={contentAreaWidth}\n height={contentHeight}\n direction={direction}\n >\n <ScreenErrorBoundary store={store}>\n <Box flexDirection=\"column\" height={contentHeight}>\n <Box\n flexDirection=\"column\"\n flexGrow={1}\n flexShrink={1}\n overflow=\"hidden\"\n >\n {activeScreen}\n </Box>\n <Box height={1} />\n <KeyboardHintsBar />\n </Box>\n </ScreenErrorBoundary>\n </DissolveTransition>\n </Box>\n </Box>\n );\n\n return (\n <Box\n flexDirection=\"column\"\n height={rows}\n width={terminalWidth}\n alignItems=\"center\"\n justifyContent=\"flex-start\"\n >\n <KeyboardHintsProvider>{inner}</KeyboardHintsProvider>\n </Box>\n );\n};\n","/**\n * TabContainer — Self-contained tabbed interface.\n * Absorbs BottomTabBar + StatusPanel functionality.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar (rendered by ScreenContainer).\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useMemo, type ReactNode } from 'react';\nimport { Colors, Icons } from '../styles.js';\nimport {\n useKeyBindings,\n KeyMatch,\n type KeyBinding,\n} from '../hooks/useKeyBindings.js';\nimport type { WizardStore } from '../store.js';\n\nexport interface TabDefinition {\n id: string;\n label: string;\n component: ReactNode;\n}\n\nexport const COLLAPSED_COUNT = 2;\nexport const EXPANDED_COUNT = 10;\n\ninterface TabContainerProps {\n tabs: TabDefinition[];\n statusMessage?: string | string[];\n /** Enable expand/collapse on the status box via 's' key */\n expandableStatus?: boolean;\n /** Store reference — required when expandableStatus is true so status state is shared. */\n store?: WizardStore;\n}\n\nexport const TabContainer = ({\n tabs,\n statusMessage,\n expandableStatus = false,\n store,\n}: TabContainerProps) => {\n const [activeTab, setActiveTab] = useState(0);\n // Fallback to local state when no store is provided\n const [localExpanded, setLocalExpanded] = useState(false);\n\n const statusExpanded = store ? store.statusExpanded : localExpanded;\n\n const bindings = useMemo<KeyBinding[]>(() => {\n const b: KeyBinding[] = [\n {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'switch tab',\n handler: (_input, key) => {\n if (key.leftArrow) {\n setActiveTab((prev) => Math.max(0, prev - 1));\n }\n if (key.rightArrow) {\n setActiveTab((prev) => Math.min(tabs.length - 1, prev + 1));\n }\n },\n },\n ];\n if (expandableStatus) {\n b.push({\n match: 's',\n label: 's',\n action: 'toggle status',\n priority: 12,\n handler: () => {\n if (store) {\n store.toggleStatusExpanded();\n } else {\n setLocalExpanded((prev) => !prev);\n }\n },\n });\n }\n return b;\n }, [tabs.length, expandableStatus, store]);\n\n useKeyBindings('tab-container', bindings);\n\n const current = tabs[activeTab];\n\n const allMessages = statusMessage\n ? Array.isArray(statusMessage)\n ? statusMessage\n : [statusMessage]\n : [];\n const visibleCount =\n expandableStatus && statusExpanded ? EXPANDED_COUNT : COLLAPSED_COUNT;\n const visibleMessages = allMessages.slice(-visibleCount);\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n {/* Active tab content — overflow hidden so expanded status eats into this area */}\n <Box flexDirection=\"column\" flexGrow={1} flexShrink={1} overflow=\"hidden\">\n {current?.component}\n </Box>\n\n {/* Status bar */}\n {visibleMessages.length > 0 && (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderTop\n borderBottom={false}\n borderLeft={false}\n borderRight={false}\n borderColor={Colors.muted}\n paddingX={1}\n overflow=\"hidden\"\n >\n {visibleMessages.map((msg, i, arr) => {\n const isCurrent = i === arr.length - 1;\n return (\n <Text key={i} color={Colors.muted} dimColor={!isCurrent}>\n {isCurrent ? Icons.diamond : '\\u250A'} {msg}\n </Text>\n );\n })}\n </Box>\n )}\n\n {/* Tab bar */}\n <Box height={1} />\n <Box gap={1} paddingX={1}>\n {tabs.map((tab, i) => (\n <Text\n key={tab.id}\n inverse={i === activeTab}\n color={i === activeTab ? Colors.accent : Colors.muted}\n bold={i === activeTab}\n >\n {` ${tab.label} `}\n </Text>\n ))}\n </Box>\n </Box>\n );\n};\n","/**\n * HNViewer — Top 10 Hacker News stories.\n *\n * Fetches from the HN Firebase API on mount.\n * Each story has a [1]–[0] numeral; typing it opens the HN comments page.\n */\n\nimport { Box, Text } from 'ink';\nimport { useState, useEffect } from 'react';\nimport { Colors } from '../styles.js';\nimport { useKeyBindings } from '../hooks/useKeyBindings.js';\n\nconst HN_API = 'https://hacker-news.firebaseio.com/v0';\n\ninterface HNStory {\n id: number;\n title: string;\n by: string;\n time: number;\n score: number;\n}\n\nexport const HNViewer = () => {\n const [stories, setStories] = useState<HNStory[]>([]);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n void (async () => {\n try {\n const res = await fetch(`${HN_API}/topstories.json`);\n const ids = (await res.json()) as number[];\n const top10 = ids.slice(0, 10);\n\n const items = await Promise.all(\n top10.map(async (id) => {\n const r = await fetch(`${HN_API}/item/${id}.json`);\n return r.json() as Promise<HNStory>;\n }),\n );\n\n setStories(items);\n } catch {\n // Silently fail — tab just stays empty\n }\n setLoading(false);\n })();\n }, []);\n\n useKeyBindings('hn-viewer', [\n {\n match: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],\n label: 'number keys',\n action: 'open story',\n priority: 5,\n handler: (input) => openStory(input, stories),\n },\n ]);\n\n if (loading) {\n return (\n <Box paddingX={1}>\n <Text dimColor>Loading Hacker News...</Text>\n </Box>\n );\n }\n\n if (stories.length === 0) {\n return (\n <Box paddingX={1}>\n <Text dimColor>Could not load Hacker News.</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text bold color={Colors.accent}>\n Hacker News — Top 10\n </Text>\n <Box height={1} />\n {stories.map((story, i) => {\n const key = i === 9 ? '0' : String(i + 1);\n const date = new Date(story.time * 1000);\n const dateStr = date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n });\n\n return (\n <Box key={story.id} flexDirection=\"column\">\n <Box>\n <Text color={Colors.accent} bold>\n [{key}]\n </Text>\n <Text bold> {story.title}</Text>\n </Box>\n <Box marginLeft={4}>\n <Text dimColor>\n {story.score}pts • {story.by}, {dateStr}\n </Text>\n </Box>\n </Box>\n );\n })}\n </Box>\n );\n};\n\nfunction openStory(input: string, stories: HNStory[]): void {\n const num = parseInt(input, 10);\n if (isNaN(num)) return;\n const index = num === 0 ? 9 : num - 1;\n const story = stories[index];\n if (!story) return;\n\n const url = `https://news.ycombinator.com/item?id=${story.id}`;\n void import('child_process').then(({ exec }) => {\n exec(`open \"${url}\" 2>/dev/null || xdg-open \"${url}\" 2>/dev/null`);\n });\n}\n","/**\n * Text-splitting helpers for sentence boundary detection.\n * Used by TextBlock for animation pauses at punctuation.\n */\n\n/** Split text into sentences (keeps the delimiter attached) */\nexport function splitSentences(text: string): string[] {\n const parts: string[] = [];\n const re = /[^.!?]*[.!?]+\\s*/g;\n let match: RegExpExecArray | null;\n let lastIndex = 0;\n while ((match = re.exec(text)) !== null) {\n parts.push(match[0]);\n lastIndex = re.lastIndex;\n }\n if (lastIndex < text.length) {\n parts.push(text.slice(lastIndex));\n }\n return parts;\n}\n\n/** Build a set of character indices where sentences end (for typewriter pause) */\nexport function sentenceEndChars(text: string): Set<number> {\n const ends = new Set<number>();\n const sentences = splitSentences(text);\n let pos = 0;\n for (const s of sentences) {\n pos += s.length;\n ends.add(pos - 1);\n }\n return ends;\n}\n\n/** Build a set of word indices where sentences end (for word-by-word pause) */\nexport function sentenceEndWords(text: string): Set<number> {\n const ends = new Set<number>();\n const sentences = splitSentences(text);\n let wordCount = 0;\n for (const s of sentences) {\n const words = s.trim().split(/\\s+/).filter(Boolean);\n wordCount += words.length;\n ends.add(wordCount - 1);\n }\n return ends;\n}\n","/**\n * Content block types and type guards.\n *\n * Extracted from ContentSequencer so that pure-logic modules (like\n * layout-helpers) can import them without pulling in Ink/React.\n */\n\nimport type { ReactNode } from 'react';\nimport type { TextRevealMode } from './TextBlock.js';\n\n/** Object form — string or ReactNode content with per-block overrides. */\nexport interface ContentObjectBlock {\n content: string | ReactNode;\n mode?: TextRevealMode;\n animationInterval?: number;\n sentenceInterval?: number;\n pause?: number;\n persist?: boolean;\n}\n\n/** Lines block — reveals ReactNode lines one at a time. */\nexport interface ContentLinesBlock {\n type: 'lines';\n lines: ReactNode[];\n interval?: number;\n pause?: number;\n}\n\n/** Clear block — page break that hides all prior blocks. */\nexport interface ContentClearBlock {\n type: 'clear';\n pause?: number;\n}\n\n/** A content block in the sequence. Bare strings are sugar for { content: '...' }. */\nexport type ContentBlock =\n | string\n | ContentObjectBlock\n | ContentLinesBlock\n | ContentClearBlock;\n\n/** Type guard for lines blocks. */\nexport function isLinesBlock(block: ContentBlock): block is ContentLinesBlock {\n return typeof block !== 'string' && 'type' in block && block.type === 'lines';\n}\n\n/** Type guard for clear blocks. */\nexport function isClearBlock(block: ContentBlock): block is ContentClearBlock {\n return typeof block !== 'string' && 'type' in block && block.type === 'clear';\n}\n\n/** Type guard for object blocks (text or node content). */\nexport function isObjectBlock(\n block: ContentBlock,\n): block is ContentObjectBlock {\n return typeof block !== 'string' && !('type' in block);\n}\n","/**\n * Layout helpers — pure functions for height estimation and viewport eviction.\n *\n * These are the core of the responsive content system. They estimate how many\n * terminal rows a content block will occupy and determine which blocks fit\n * within a given height budget.\n */\n\nimport type { ContentBlock } from './content-types.js';\nimport { isLinesBlock, isClearBlock, isObjectBlock } from './content-types.js';\n\n/**\n * Estimate the number of terminal rows a content block will occupy,\n * including 1 row of marginBottom.\n */\nexport function estimateBlockHeight(\n block: ContentBlock,\n availableWidth: number,\n): number {\n if (typeof block === 'string') {\n return wordWrap(block, availableWidth).length + 1; // +1 for marginBottom\n }\n\n if (isClearBlock(block)) return 0;\n\n if (isLinesBlock(block)) {\n return block.lines.length + 1;\n }\n\n if (isObjectBlock(block)) {\n if (typeof block.content === 'string') {\n return wordWrap(block.content, availableWidth).length + 1;\n }\n return 4; // conservative fixed estimate for ReactNode\n }\n\n return 1;\n}\n\n/**\n * Given all blocks, the active index, available width, and a row budget,\n * return [startIdx, endIdx] — the range of blocks to render.\n *\n * Always includes activeIdx. Walks backward to include as many completed\n * blocks as fit within maxHeight.\n */\nexport function computeVisibleRange(\n blocks: ContentBlock[],\n activeIdx: number,\n availableWidth: number,\n maxHeight: number,\n): [number, number] {\n // Reserve a 2-row buffer so resize-induced estimate drift doesn't\n // cause overflow=\"hidden\" to clip the margin between blocks.\n const budget = Math.max(4, maxHeight - 2);\n\n let totalHeight = estimateBlockHeight(blocks[activeIdx], availableWidth);\n let start = activeIdx;\n\n for (let i = activeIdx - 1; i >= 0; i--) {\n // Clear blocks act as a hard boundary — don't show anything before them\n if (isClearBlock(blocks[i])) break;\n const h = estimateBlockHeight(blocks[i], availableWidth);\n if (totalHeight + h > budget) break;\n totalHeight += h;\n start = i;\n }\n\n return [start, activeIdx];\n}\n\n/**\n * Word-wrap text at clean word boundaries. Always returns pre-wrapped text\n * joined with \\n — this avoids Ink's native wrap which can leave leading\n * spaces on continuation lines.\n *\n * Uses a 1-char safety margin so slight width estimate mismatches don't\n * cause Ink to re-wrap our already-wrapped lines.\n */\nexport function wordWrap(text: string, availableWidth: number): string[] {\n const safeWidth = Math.max(10, availableWidth - 1);\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let currentLine = '';\n\n for (const word of words) {\n if (\n currentLine.length + word.length + 1 > safeWidth &&\n currentLine.length > 0\n ) {\n lines.push(currentLine);\n currentLine = word;\n } else {\n currentLine += (currentLine.length > 0 ? ' ' : '') + word;\n }\n }\n if (currentLine.length > 0) {\n lines.push(currentLine);\n }\n\n return lines;\n}\n\n/**\n * Word-wrap text and return only the last `maxRows` lines.\n * Used for intra-block truncation when a single text block exceeds the viewport.\n * Also used for normal rendering to avoid Ink's leading-space wrap artifacts.\n */\nexport function wrapAndTruncate(\n text: string,\n availableWidth: number,\n maxRows: number,\n): string {\n const lines = wordWrap(text, availableWidth);\n\n if (lines.length <= maxRows) {\n return lines.join('\\n');\n }\n\n return lines.slice(-maxRows).join('\\n');\n}\n","/**\n * TextBlock — Animates a single string paragraph.\n *\n * Self-contained: owns its own animIdx and timer.\n * Calls onComplete() when the animation finishes.\n *\n * Five animation modes:\n * 1. Typewriter — character-by-character reveal\n * 2. Word by word — each word appears in order\n * 3. Sentence by sentence — sentences appear one at a time\n * 4. Paragraph fade — paragraph appears at full opacity immediately\n * 5. Sentence fade — paragraph dim, sentences light up in order\n */\n\nimport { Text } from 'ink';\nimport { useState, useEffect, useRef, useMemo, type ReactNode } from 'react';\nimport { Colors } from '../styles.js';\nimport {\n splitSentences,\n sentenceEndChars,\n sentenceEndWords,\n} from './text-helpers.js';\nimport { wrapAndTruncate } from './layout-helpers.js';\n\nexport enum TextRevealMode {\n Typewriter = 0,\n WordByWord = 1,\n SentenceBySentence = 2,\n ParagraphFade = 3,\n SentenceFade = 4,\n}\n\nexport const TEXT_REVEAL_MODE_LABELS = [\n 'Typewriter',\n 'Word by word',\n 'Sentence by sentence',\n 'Paragraph fade',\n 'Sentence fade',\n];\n\nexport const TEXT_REVEAL_MODE_COUNT = 5;\n\n/** Default interval per mode (ms) */\nexport const TEXT_REVEAL_MODE_DEFAULTS: Record<TextRevealMode, number> = {\n [TextRevealMode.WordByWord]: 240,\n [TextRevealMode.Typewriter]: 32,\n [TextRevealMode.SentenceBySentence]: 1800,\n [TextRevealMode.ParagraphFade]: 4800,\n [TextRevealMode.SentenceFade]: 2400,\n};\n\ninterface TextBlockProps {\n text: string;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n mode: TextRevealMode;\n bullet?: ReactNode;\n animationInterval?: number;\n sentenceInterval?: number;\n /** Max rows this block may occupy. When exceeded, top lines are truncated. */\n maxHeight?: number;\n /** Available text width in columns (for truncation wrapping). */\n availableWidth?: number;\n}\n\nexport const TextBlock = ({\n text,\n active,\n completed,\n onComplete,\n mode,\n bullet,\n animationInterval,\n sentenceInterval = 1600,\n maxHeight,\n availableWidth,\n}: TextBlockProps) => {\n const speed = animationInterval ?? TEXT_REVEAL_MODE_DEFAULTS[mode];\n\n const [animIdx, setAnimIdx] = useState(\n mode === TextRevealMode.SentenceFade ? 1 : 0,\n );\n\n // Reset synchronously during render to avoid a one-frame flash\n const resetRef = useRef(0);\n const prevMode = useRef(mode);\n if (prevMode.current !== mode) {\n prevMode.current = mode;\n resetRef.current += 1;\n setAnimIdx(mode === TextRevealMode.SentenceFade ? 1 : 0);\n }\n\n const words = text.split(/\\s+/);\n const sentences = splitSentences(text);\n\n const sentenceCharEnds = useMemo(() => sentenceEndChars(text), [text]);\n const sentenceWordEnds = useMemo(() => sentenceEndWords(text), [text]);\n\n const isDone =\n mode === TextRevealMode.Typewriter\n ? animIdx >= text.length\n : mode === TextRevealMode.ParagraphFade\n ? true\n : mode === TextRevealMode.WordByWord\n ? animIdx >= words.length\n : mode === TextRevealMode.SentenceFade ||\n mode === TextRevealMode.SentenceBySentence\n ? animIdx >= sentences.length\n : true;\n\n // Fire onComplete when done\n useEffect(() => {\n if (isDone && active) onComplete();\n }, [isDone, active, onComplete]);\n\n // Animate: single effect for all tick-based modes\n useEffect(() => {\n if (!active || mode === TextRevealMode.ParagraphFade || isDone) return;\n const token = resetRef.current;\n\n const isFirstTick = animIdx === 0;\n\n let delay = isFirstTick ? 0 : speed;\n if (\n !isFirstTick &&\n mode === TextRevealMode.Typewriter &&\n animIdx > 0 &&\n sentenceCharEnds.has(animIdx - 1)\n ) {\n delay = sentenceInterval;\n } else if (\n !isFirstTick &&\n mode === TextRevealMode.WordByWord &&\n animIdx > 0 &&\n sentenceWordEnds.has(animIdx - 1)\n ) {\n delay = sentenceInterval;\n }\n\n const timer = setTimeout(() => {\n if (token !== resetRef.current) return;\n setAnimIdx((c) => c + 1);\n }, delay);\n return () => clearTimeout(timer);\n }, [\n active,\n mode,\n animIdx,\n isDone,\n speed,\n sentenceInterval,\n sentenceCharEnds,\n sentenceWordEnds,\n ]);\n\n // Pre-wrap text ourselves to avoid Ink's native wrap leaving leading spaces\n // on continuation lines. When maxHeight is set, also truncates to last N rows.\n const wrap = (visibleText: string): string => {\n if (availableWidth == null) return visibleText;\n if (maxHeight == null) {\n return wrapAndTruncate(visibleText, availableWidth, Infinity);\n }\n return wrapAndTruncate(visibleText, availableWidth, maxHeight);\n };\n\n // Completed: dimmed text\n if (completed) {\n return (\n <Text dimColor>\n {bullet}\n {wrap(text)}\n </Text>\n );\n }\n\n // Active: mode-specific rendering\n if (mode === TextRevealMode.Typewriter) {\n const revealed = text.slice(0, animIdx);\n const atSentenceEnd = /[.!?]\\s*$/.test(revealed);\n const display = atSentenceEnd ? revealed.trimEnd() : revealed;\n return (\n <Text>\n {bullet}\n {wrap(display)}\n <Text color={Colors.muted}>{'\\u258C'}</Text>\n </Text>\n );\n }\n\n if (mode === TextRevealMode.WordByWord) {\n const visible = words.slice(0, animIdx).join(' ');\n return (\n <Text>\n {bullet}\n {wrap(visible)}\n </Text>\n );\n }\n\n if (mode === TextRevealMode.ParagraphFade) {\n return (\n <Text>\n {bullet}\n {wrap(text)}\n </Text>\n );\n }\n\n if (mode === TextRevealMode.SentenceBySentence) {\n const visible = sentences.slice(0, animIdx).join('');\n return (\n <Text>\n {bullet}\n {wrap(visible)}\n </Text>\n );\n }\n\n // SentenceFade\n return (\n <Text>\n {bullet}\n {sentences.map((s, si) => (\n <Text key={si} dimColor={si >= animIdx}>\n {s}\n </Text>\n ))}\n </Text>\n );\n};\n","/**\n * LinesBlock — Reveals ReactNode lines one at a time.\n * Each line can contain colors, bold, ASCII art — any JSX.\n */\n\nimport { Box } from 'ink';\nimport { useState, useEffect, type ReactNode } from 'react';\n\ninterface LinesBlockProps {\n lines: ReactNode[];\n interval: number;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n /** Max rows this block may occupy. When exceeded, top lines are truncated. */\n maxHeight?: number;\n}\n\nexport const LinesBlock = ({\n lines,\n interval,\n active,\n completed,\n onComplete,\n maxHeight,\n}: LinesBlockProps) => {\n const [revealedCount, setRevealedCount] = useState(0);\n\n // Reveal lines one at a time\n useEffect(() => {\n if (!active || revealedCount >= lines.length) return;\n const timer = setTimeout(\n () => setRevealedCount((c) => c + 1),\n revealedCount === 0 ? 0 : interval,\n );\n return () => clearTimeout(timer);\n }, [active, revealedCount, lines.length, interval]);\n\n // Fire onComplete when all lines revealed\n useEffect(() => {\n if (active && revealedCount >= lines.length) onComplete();\n }, [active, revealedCount, lines.length, onComplete]);\n\n // When maxHeight is set, only show the last maxHeight lines\n const visibleStart =\n maxHeight != null\n ? Math.max(0, (completed ? lines.length : revealedCount) - maxHeight)\n : 0;\n\n return (\n <Box flexDirection=\"column\">\n {lines.map((line, li) => {\n if (completed) {\n if (li < visibleStart) return null;\n return <Box key={li}>{line}</Box>;\n }\n if (li >= revealedCount || li < visibleStart) return null;\n return <Box key={li}>{line}</Box>;\n })}\n </Box>\n );\n};\n","/**\n * NodeBlock — Renders static JSX, fires onComplete immediately.\n * The sequencer's blockInterval handles dwell time.\n */\n\nimport { Text } from 'ink';\nimport { useEffect, type ReactNode } from 'react';\n\ninterface NodeBlockProps {\n content: ReactNode;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n}\n\nexport const NodeBlock = ({\n content,\n active,\n completed,\n onComplete,\n}: NodeBlockProps) => {\n useEffect(() => {\n if (active) onComplete();\n }, [active, onComplete]);\n\n if (completed) return <Text dimColor>{content}</Text>;\n return <>{content}</>;\n};\n","/**\n * ContentSequencer — Plays content blocks in order.\n *\n * Each block is a self-animating component that fires onComplete() when done.\n * The sequencer waits blockInterval ms between blocks, then advances.\n *\n * Block types:\n * - string → TextBlock (animated text, sugar for { content: '...' })\n * - { content: str } → TextBlock (animated text with per-block overrides)\n * - { content: JSX } → NodeBlock (static JSX)\n * - { type: 'lines' } → LinesBlock (line-by-line reveal)\n * - { type: 'clear' } → ClearBlock (page break — hides all prior blocks)\n */\n\nimport { Box } from 'ink';\nimport {\n useState,\n useCallback,\n useEffect,\n useRef,\n useMemo,\n type ReactNode,\n} from 'react';\nimport { TextBlock, type TextRevealMode } from './TextBlock.js';\nimport { LinesBlock } from './LinesBlock.js';\nimport { NodeBlock } from './NodeBlock.js';\nimport { computeVisibleRange } from './layout-helpers.js';\nimport { isLinesBlock, isClearBlock, isObjectBlock } from './content-types.js';\nexport type {\n ContentBlock,\n ContentObjectBlock,\n ContentLinesBlock,\n ContentClearBlock,\n} from './content-types.js';\nexport { isLinesBlock, isClearBlock, isObjectBlock } from './content-types.js';\n\nimport type { ContentBlock } from './content-types.js';\n\n/** Resolve the pause after a block completes. */\nexport function getBlockPause(\n block: ContentBlock,\n blockInterval: number,\n): number {\n if (typeof block === 'string') return blockInterval;\n return block.pause ?? blockInterval;\n}\n\ninterface ContentSequencerProps {\n blocks: ContentBlock[];\n mode: TextRevealMode;\n /** Row budget for visible content. When set, older blocks are evicted. */\n maxHeight?: number;\n /** Available text width in columns (for height estimation). */\n availableWidth?: number;\n bullet?: ReactNode;\n animationInterval?: number;\n sentenceInterval?: number;\n lineInterval?: number;\n blockInterval?: number;\n /** Delay in ms before the first block appears. */\n startDelay?: number;\n /** Resume from a previously persisted block index. */\n initialBlockIdx?: number;\n /** Called whenever the active block index advances. */\n onBlockChange?: (idx: number) => void;\n /** Called once when the last block completes (after its pause). */\n onSequenceComplete?: () => void;\n}\n\nexport const ContentSequencer = ({\n blocks,\n mode,\n maxHeight,\n availableWidth,\n bullet,\n animationInterval,\n sentenceInterval,\n lineInterval = 200,\n blockInterval = 3200,\n startDelay = 0,\n initialBlockIdx = 0,\n onBlockChange,\n onSequenceComplete,\n}: ContentSequencerProps) => {\n const resuming = initialBlockIdx > 0;\n const [activeIdx, setActiveIdx] = useState(\n resuming ? initialBlockIdx : startDelay > 0 ? -1 : 0,\n );\n const transitionTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Initial delay before first block (skip when resuming)\n useEffect(() => {\n if (resuming || startDelay <= 0 || activeIdx !== -1) return;\n const timer = setTimeout(() => setActiveIdx(0), startDelay);\n return () => clearTimeout(timer);\n }, [startDelay, activeIdx]);\n\n // Compute visible range reactively (re-evaluates on resize, block advance, etc.)\n const [visibleStart, visibleEnd] = useMemo(() => {\n if (activeIdx < 0) return [0, -1] as [number, number];\n if (maxHeight == null || availableWidth == null) {\n return [0, activeIdx] as [number, number];\n }\n return computeVisibleRange(blocks, activeIdx, availableWidth, maxHeight);\n }, [blocks, activeIdx, maxHeight, availableWidth]);\n\n const handleComplete = useCallback(\n (blockIndex: number) => {\n // Only the active block can trigger advancement\n if (blockIndex !== activeIdx) return;\n // Last block — fire sequence-complete after its pause, don't advance\n if (activeIdx >= blocks.length - 1) {\n if (onSequenceComplete && !transitionTimer.current) {\n const pause = getBlockPause(blocks[blockIndex], blockInterval);\n transitionTimer.current = setTimeout(() => {\n transitionTimer.current = null;\n onSequenceComplete();\n }, pause);\n }\n return;\n }\n // Don't double-trigger\n if (transitionTimer.current) return;\n\n const pause = getBlockPause(blocks[blockIndex], blockInterval);\n transitionTimer.current = setTimeout(() => {\n transitionTimer.current = null;\n setActiveIdx((i) => {\n const next = i + 1;\n onBlockChange?.(next);\n return next;\n });\n }, pause);\n },\n [activeIdx, blocks, blockInterval, onBlockChange, onSequenceComplete],\n );\n\n // Find the most recent clear block — nothing before it renders.\n // When the active block IS a clear block, immediately hide all prior content\n // so the pause shows a blank screen (not dim prior text).\n const clearFloor = useMemo(() => {\n if (activeIdx >= 0 && isClearBlock(blocks[activeIdx])) return activeIdx;\n for (let i = activeIdx - 1; i >= 0; i--) {\n if (isClearBlock(blocks[i])) return i + 1;\n }\n return 0;\n }, [blocks, activeIdx]);\n\n return (\n <Box flexDirection=\"column\">\n {blocks.map((block, i) => {\n // Not yet reached\n if (i > activeIdx) return null;\n // Hidden by clear block\n if (i < clearFloor) return null;\n // Completed clear blocks don't render (active ones must mount to fire onComplete)\n if (isClearBlock(block) && i < activeIdx) return null;\n // Evicted by viewport\n if (i < visibleStart || i > visibleEnd) return null;\n\n const active = i === activeIdx;\n const completed = i < activeIdx;\n\n // Completed non-text blocks don't persist by default\n if (completed && isObjectBlock(block)) {\n const isText = typeof block.content === 'string';\n const shouldPersist = block.persist ?? isText;\n if (!shouldPersist) return null;\n }\n\n return (\n <Box key={i} flexDirection=\"column\" marginBottom={1}>\n <BlockRenderer\n block={block}\n active={active}\n completed={completed}\n onComplete={() => handleComplete(i)}\n mode={mode}\n bullet={bullet}\n animationInterval={animationInterval}\n sentenceInterval={sentenceInterval}\n lineInterval={lineInterval}\n maxHeight={maxHeight}\n availableWidth={availableWidth}\n />\n </Box>\n );\n })}\n </Box>\n );\n};\n\ninterface BlockRendererProps {\n block: ContentBlock;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n mode: TextRevealMode;\n bullet?: ReactNode;\n animationInterval?: number;\n sentenceInterval?: number;\n lineInterval: number;\n maxHeight?: number;\n availableWidth?: number;\n}\n\nconst BlockRenderer = ({\n block,\n active,\n completed,\n onComplete,\n mode,\n bullet,\n animationInterval,\n sentenceInterval,\n lineInterval,\n maxHeight,\n availableWidth,\n}: BlockRendererProps) => {\n // Clear block — completes immediately, renders nothing\n if (isClearBlock(block)) {\n useEffect(() => {\n if (active) onComplete();\n }, [active, onComplete]);\n return null;\n }\n\n // Bare string sugar → TextBlock with sequencer defaults\n if (typeof block === 'string') {\n return (\n <TextBlock\n text={block}\n active={active}\n completed={completed}\n onComplete={onComplete}\n mode={mode}\n bullet={bullet}\n animationInterval={animationInterval}\n sentenceInterval={sentenceInterval}\n maxHeight={maxHeight}\n availableWidth={availableWidth}\n />\n );\n }\n\n // Lines block\n if (isLinesBlock(block)) {\n return (\n <LinesBlock\n lines={block.lines}\n interval={block.interval ?? lineInterval}\n active={active}\n completed={completed}\n onComplete={onComplete}\n maxHeight={maxHeight}\n />\n );\n }\n\n // Object block — dispatch on content type\n if (typeof block.content === 'string') {\n return (\n <TextBlock\n text={block.content}\n active={active}\n completed={completed}\n onComplete={onComplete}\n mode={block.mode ?? mode}\n bullet={bullet}\n animationInterval={block.animationInterval ?? animationInterval}\n sentenceInterval={block.sentenceInterval ?? sentenceInterval}\n maxHeight={maxHeight}\n availableWidth={availableWidth}\n />\n );\n }\n\n return (\n <NodeBlock\n content={block.content}\n active={active}\n completed={completed}\n onComplete={onComplete}\n />\n );\n};\n","/**\n * LearnCard — PostHog educational content with animated text reveal.\n */\n\nimport { Box, Text } from 'ink';\nimport { useEffect, useMemo, useRef } from 'react';\nimport { Colors } from '../styles.js';\nimport type { WizardStore } from '../store.js';\nimport { ContentSequencer, TextRevealMode } from '../primitives/index.js';\nimport type { ContentBlock } from '../primitives/index.js';\nimport { useStdoutDimensions } from '../hooks/useStdoutDimensions.js';\nimport { COLLAPSED_COUNT, EXPANDED_COUNT } from '../primitives/TabContainer.js';\n\n/**\n * StatusPeekTrigger — Fires the status bar expansion once, renders nothing.\n * The peek is guarded by peekedRef so re-mounts are safe.\n */\nconst StatusPeekTrigger = ({\n store,\n duration = 10000,\n peekedRef,\n}: {\n store?: WizardStore;\n duration?: number;\n peekedRef: ReturnType<typeof useRef<boolean>>;\n}) => {\n useEffect(() => {\n if (peekedRef.current) return;\n peekedRef.current = true;\n store?.setStatusExpanded(true);\n // No cleanup — the store call is safe after unmount and the component\n // may be evicted before the timer fires (non-persist NodeBlock).\n setTimeout(() => {\n store?.setStatusExpanded(false);\n }, duration);\n }, [store, duration, peekedRef]);\n\n return <Text>You can view the Wizard's status below.</Text>;\n};\n\nconst POSTHOG_DATA_FLOW: ContentBlock = {\n type: 'lines',\n interval: 500,\n pause: 8000,\n // Box is 30 chars wide between │ borders.\n // Labels: 1-char indent. Arrows: \" ↓ \" (5). Sub-items: \" │ \" (7).\n lines: [\n <Text color=\"gray\">{' ┌──────────────────────────────┐'}</Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color=\"cyan\">\n Your App\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text>posthog.capture()</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>custom events</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>custom properties</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>person profiles</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text dimColor>groups</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color={Colors.accent}>\n PostHog SDK\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text>HTTP</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color={Colors.accent}>\n PostHog Cloud\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text>query + visualize</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color=\"green\">\n Dashboards & Insights\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text color=\"gray\">{' └──────────────────────────────┘'}</Text>,\n ],\n};\n\nconst PRODUCT_SUITE_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 1000,\n pause: 15000,\n lines: [\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Product Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Error Tracking'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Web Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Session Replay'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Feature Flags '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Data Pipelines'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Experiments '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Data Warehouse'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'LLM Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Surveys'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Workflows '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Logs'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Product Tours '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Support'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Revenue Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Endpoints'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Customer Analytics'}\n </Text>,\n ],\n};\n\nconst LINE_CHART_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 300,\n pause: 6000,\n lines: [\n <Text bold>{' Trends · user signups (monthly)'}</Text>,\n <Text> </Text>,\n // 10k\n <Text>\n <Text color=\"gray\">{' 10k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──'}</Text>\n <Text dimColor>{' 9,575'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭╯'}</Text>\n </Text>,\n // 7.5k\n <Text>\n <Text color=\"gray\">{' 7.5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭─╯'}</Text>\n </Text>,\n // 5k\n <Text>\n <Text color=\"gray\">{' 5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭─╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──╯'}</Text>\n </Text>,\n // 2.5k\n <Text>\n <Text color=\"gray\">{' 2.5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭───╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──────╯'}</Text>\n </Text>,\n // 0\n <Text>\n <Text color=\"gray\">{' 0 ┤'}</Text>\n <Text color=\"cyan\">{'──────╯'}</Text>\n </Text>,\n // X-axis\n <Text color=\"gray\">{' └┬─────┬─────┬─────┬─────┬──'}</Text>,\n <Text dimColor>{' May Aug Nov Feb May'}</Text>,\n ],\n};\n\nconst FUNNEL_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 200,\n pause: 8000,\n lines: [\n <Text bold>{' Funnel · ride conversion'}</Text>,\n <Text> </Text>,\n // Step 1\n <Text>\n {' '}\n <Text bold>1</Text>\n {' app_launched'}\n {' '}\n <Text bold color=\"green\">\n 100.00%\n </Text>\n </Text>,\n <Text color=\"cyan\">{' ██████████████████████████████'}</Text>,\n <Text dimColor>{' → 1,200 users'}</Text>,\n <Text> </Text>,\n // Step 2\n <Text>\n {' '}\n <Text bold>2</Text>\n {' ride_requested'}\n {' '}\n <Text dimColor>{'avg 2m 30s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 72.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'██████████████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 864 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 336 (28%)'}</Text>\n </Text>,\n <Text> </Text>,\n // Step 3\n <Text>\n {' '}\n <Text bold>3</Text>\n {' ride_accepted'}\n {' '}\n <Text dimColor>{'avg 5m 12s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 51.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'██████████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 612 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 252 (29%)'}</Text>\n </Text>,\n <Text> </Text>,\n // Step 4\n <Text>\n {' '}\n <Text bold>4</Text>\n {' ride_started'}\n {' '}\n <Text dimColor>{'avg 1m 45s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 38.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'█████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 456 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 156 (25%)'}</Text>\n </Text>,\n ],\n};\n\n/** Fixed chrome: ScreenContainer (3) + TabContainer tab bar (2) */\nconst FIXED_CHROME = 5;\nconst HEADER_ROWS = 2; // title + spacer\nconst MIN_CONTENT_ROWS = 6;\n\ninterface LearnCardProps {\n store?: WizardStore;\n onComplete?: () => void;\n}\n\nexport const LearnCard = ({ store, onComplete }: LearnCardProps) => {\n const peekedRef = useRef(false);\n const [columns, rows] = useStdoutDimensions();\n\n const blocks = useMemo<ContentBlock[]>(\n () => [\n {\n content: 'Welcome.',\n pause: 3000,\n mode: TextRevealMode.Typewriter,\n animationInterval: 160,\n },\n\n { content: 'The Wizard is an agent.', pause: 4000 },\n\n {\n content: 'It handles the entire PostHog setup process on your behalf.',\n pause: 5000,\n },\n\n {\n content:\n \"As we speak, it's building a plan to set up PostHog in your project.\",\n pause: 6000,\n },\n\n { type: 'clear', pause: 2000 },\n\n {\n pause: 5000,\n persist: true,\n content: <StatusPeekTrigger store={store} peekedRef={peekedRef} />,\n },\n\n {\n pause: 6000,\n content: (\n <Text>\n Press{' '}\n <Text color={Colors.accent} bold>\n S\n </Text>{' '}\n to expand or collapse the status.\n </Text>\n ),\n },\n\n { type: 'clear', pause: 2000 },\n\n {\n content: 'It takes about eight minutes.',\n pause: 2000,\n },\n\n {\n content: 'So grab some coffee ☕️.',\n pause: 2000,\n },\n\n {\n content: 'Or stick around and learn about PostHog.',\n pause: 5000,\n },\n\n { type: 'clear', pause: 3000 },\n\n {\n content: 'Events are the foundation of the PostHog platform.',\n pause: 4000,\n },\n\n {\n content:\n 'Every time an action is performed in your codebase — like button clicks, function calls, or thrown errors — we can capture an event.',\n pause: 6000,\n },\n\n {\n content:\n 'Events are sent to PostHog and joined with other product data.',\n pause: 6000,\n },\n\n { type: 'clear', pause: 1000 },\n\n { content: \"Here's the flow.\", pause: 1000 },\n\n POSTHOG_DATA_FLOW,\n\n { type: 'clear', pause: 2000 },\n\n {\n content:\n 'With enough event data, you can answer powerful questions about your product.',\n pause: 4000,\n },\n\n { content: 'And create insights.', pause: 4000 },\n\n { type: 'clear', pause: 500 },\n\n { content: 'Like trends to measure growth.', pause: 2500 },\n\n LINE_CHART_BLOCK,\n\n { type: 'clear', pause: 500 },\n\n { content: 'Or funnels to reveal bottlenecks.', pause: 2500 },\n\n FUNNEL_BLOCK,\n\n { type: 'clear', pause: 1000 },\n\n {\n content: 'Use those signals to decide what to build next.',\n pause: 4000,\n },\n\n { content: 'PostHog has all the dev tools you need.', pause: 3000 },\n\n PRODUCT_SUITE_BLOCK,\n ],\n [store],\n );\n\n // Dynamic status bar height: messages + border when present\n const hasStatus = store ? store.statusMessages.length > 0 : false;\n const statusBarRows = hasStatus\n ? (store?.statusExpanded ? EXPANDED_COUNT : COLLAPSED_COUNT) + 1\n : 0;\n\n const contentHeight = rows - FIXED_CHROME - statusBarRows;\n const tooSmall = contentHeight < MIN_CONTENT_ROWS;\n\n const maxHeight = Math.max(1, contentHeight - HEADER_ROWS);\n // Half of clamped content width, minus paddingX on both sides\n const paneWidth = Math.floor((Math.min(120, columns) - 2) / 2) - 2;\n\n // Always render so ContentSequencer stays mounted (preserves activeIdx).\n // When too small, hide visually via display=\"none\".\n return (\n <Box\n flexDirection=\"column\"\n paddingX={1}\n display={tooSmall ? 'none' : 'flex'}\n >\n <Text bold color={Colors.accent}>\n Learn\n </Text>\n <Box height={1} />\n <ContentSequencer\n blocks={blocks}\n mode={TextRevealMode.SentenceBySentence}\n maxHeight={maxHeight}\n availableWidth={paneWidth}\n startDelay={2000}\n initialBlockIdx={store?.learnCardBlockIdx ?? 0}\n onBlockChange={(idx) => store?.setLearnCardBlockIdx(idx)}\n onSequenceComplete={onComplete}\n />\n </Box>\n );\n};\n","/**\n * TipsCard — Shows PostHog tips during the agent run.\n * Reactively shows/hides tips based on discovered features.\n * Supports toggling additional features via key bindings.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport type { WizardStore } from '../store.js';\nimport { Colors, Icons } from '../styles.js';\nimport {\n DiscoveredFeature,\n AdditionalFeature,\n} from '../../../lib/wizard-session.js';\n\n/** A discrete tip shown in the TipsCard during the agent run. */\ninterface Tip {\n /** Unique identifier */\n id: string;\n /** Title line */\n title: string;\n /** Description shown below the title */\n description: string;\n /** Optional URL shown after the description */\n url?: string;\n /** When provided, the tip is only shown if this returns true */\n visible?: (store: WizardStore) => boolean;\n /** Optional key binding that toggles an AdditionalFeature */\n toggle?: {\n /** The key the user presses (lowercase) */\n key: string;\n /** The additional feature to enqueue */\n feature: AdditionalFeature;\n /** Label shown when toggled on */\n enabledLabel: string;\n /** Prompt shown when not yet toggled */\n prompt: string;\n /** Returns true if already toggled */\n isEnabled: (store: WizardStore) => boolean;\n };\n}\n\nconst TIPS: Tip[] = [\n {\n id: 'persons',\n title: 'You can also track people and groups with PostHog',\n description:\n \"Events can be associated with the humans who generate them, letting you understand a specific user or customer's situation.\",\n },\n {\n id: 'properties',\n title: 'Get way more detail using properties',\n description:\n 'Events and person records can have any properties you want. Track things like how they found your website, what subscription tier they choose, and much more.',\n },\n {\n id: 'stripe',\n title: 'You can track Stripe revenue with PostHog',\n description: 'Add Stripe as a data source while you wait:',\n url: 'https://app.posthog.com/project/data-warehouse/new-source?kind=Stripe',\n visible: (store) =>\n store.session.discoveredFeatures.includes(DiscoveredFeature.Stripe),\n },\n {\n id: 'llm',\n title: 'PostHog can also help you track your LLM costs',\n description: '',\n visible: (store) =>\n store.session.discoveredFeatures.includes(DiscoveredFeature.LLM),\n toggle: {\n key: 'l',\n feature: AdditionalFeature.LLM,\n enabledLabel: 'LLM analytics setup queued next',\n prompt: 'We detected LLM dependencies in your project.',\n isEnabled: (store) => store.session.llmOptIn,\n },\n },\n];\n\nexport const TipsCard = ({ store }: { store: WizardStore }) => {\n useInput((input) => {\n for (const tip of TIPS) {\n if (\n tip.toggle &&\n input.toLowerCase() === tip.toggle.key &&\n (!tip.visible || tip.visible(store)) &&\n !tip.toggle.isEnabled(store)\n ) {\n store.enableFeature(tip.toggle.feature);\n }\n }\n });\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text bold color={Colors.accent}>\n Tips\n </Text>\n <Box height={1} />\n\n {TIPS.filter((tip) => !tip.visible || tip.visible(store)).map((tip) => (\n <Box key={tip.id} flexDirection=\"column\" marginBottom={1}>\n <Text>\n <Text color={Colors.accent}>{Icons.diamond} </Text>\n <Text bold>{tip.title}</Text>\n </Text>\n\n {tip.toggle ? (\n tip.toggle.isEnabled(store) ? (\n <Text color={Colors.success}>\n {Icons.check} {tip.toggle.enabledLabel}\n </Text>\n ) : (\n <Text dimColor>\n {tip.toggle.prompt} Press{' '}\n <Text bold color={Colors.accent}>\n {tip.toggle.key.toUpperCase()}\n </Text>{' '}\n to enable.\n </Text>\n )\n ) : (\n <Text dimColor>\n {tip.description}\n {tip.url && (\n <>\n {' '}\n <Text color=\"cyan\">{tip.url}</Text>\n </>\n )}\n </Text>\n )}\n </Box>\n ))}\n </Box>\n );\n};\n","/**\n * ServiceHealthList — Shared component for displaying service health status.\n *\n * Used by HealthCheckScreen (blocking services only) and HealthWarningsTab (all services).\n */\n\nimport { Box, Text } from 'ink';\nimport {\n ServiceHealthStatus,\n type AllServicesHealth,\n type ComponentHealthResult,\n type ComponentStatus,\n type HealthCheckKey,\n} from '../../../lib/health-checks/types.js';\nimport { SERVICE_LABELS } from '../../../lib/health-checks/readiness.js';\nimport { Icons } from '../styles.js';\n\n/** Keys that are component-level detail — shown inline under their parent. */\nconst COMPONENT_KEYS: HealthCheckKey[] = [\n 'posthogComponents',\n 'npmComponents',\n 'cloudflareComponents',\n];\n\n/** Map component key → its parent \"overall\" key */\nconst COMPONENT_PARENT: Partial<Record<HealthCheckKey, HealthCheckKey>> = {\n posthogComponents: 'posthogOverall',\n npmComponents: 'npmOverall',\n cloudflareComponents: 'cloudflareOverall',\n};\n\nfunction statusIcon(status: ServiceHealthStatus): {\n icon: string;\n color: string;\n} {\n switch (status) {\n case ServiceHealthStatus.Down:\n return { icon: Icons.squareFilled, color: 'red' };\n case ServiceHealthStatus.Degraded:\n return { icon: Icons.squareFilled, color: '#DC9300' };\n case ServiceHealthStatus.Healthy:\n return { icon: Icons.check, color: 'green' };\n }\n}\n\ninterface ServiceHealthListProps {\n health: AllServicesHealth;\n /** If set, only show services with these keys */\n filterKeys?: HealthCheckKey[];\n /** Show healthy services (default true) */\n showHealthy?: boolean;\n}\n\nexport const ServiceHealthList = ({\n health,\n filterKeys,\n showHealthy = true,\n}: ServiceHealthListProps) => {\n const topLevelKeys = (Object.keys(health) as HealthCheckKey[]).filter(\n (k) => !COMPONENT_KEYS.includes(k),\n );\n\n const keysToShow = filterKeys\n ? topLevelKeys.filter((k) => filterKeys.includes(k))\n : topLevelKeys;\n\n return (\n <Box flexDirection=\"column\" paddingLeft={1}>\n {keysToShow.map((key) => {\n const result = health[key];\n if (!showHealthy && result.status === ServiceHealthStatus.Healthy) {\n return null;\n }\n\n const { icon, color } = statusIcon(result.status);\n const label = SERVICE_LABELS[key];\n\n // Find component-level details if this is a parent key\n const componentKey = (\n Object.entries(COMPONENT_PARENT) as [HealthCheckKey, HealthCheckKey][]\n ).find(([, parent]) => parent === key)?.[0];\n const componentResult = componentKey\n ? (health[componentKey] as ComponentHealthResult)\n : undefined;\n const affectedComponents: ComponentStatus[] =\n componentResult?.degradedOrDownComponents ?? [];\n\n return (\n <Box key={key} flexDirection=\"column\">\n <Text>\n <Text color={color}>{icon}</Text>{' '}\n <Text bold={result.status !== ServiceHealthStatus.Healthy}>\n {label}\n </Text>\n </Text>\n {affectedComponents.length > 0 && (\n <Box flexDirection=\"column\" paddingLeft={3}>\n {affectedComponents.slice(0, 5).map((c) => {\n const ci = statusIcon(c.status);\n return (\n <Text key={c.name} dimColor>\n <Text color={ci.color}>{ci.icon}</Text> {c.name}\n </Text>\n );\n })}\n {affectedComponents.length > 5 && (\n <Text dimColor>+{affectedComponents.length - 5} more</Text>\n )}\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n};\n","import { Box, Text } from 'ink';\nimport { useStdoutDimensions } from '../../hooks/useStdoutDimensions.js';\nimport { Colors, Icons } from '../../styles.js';\nimport {\n getKindMeta,\n type HealthIssue,\n type HealthIssueSeverity,\n} from '../../../../lib/workflows/posthog-doctor/index.js';\n\nexport const SEVERITY_ORDER: HealthIssueSeverity[] = [\n 'critical',\n 'warning',\n 'info',\n];\n\nconst SEVERITY_COLOR: Record<HealthIssueSeverity, string> = {\n critical: Colors.error,\n warning: Colors.accent,\n info: Colors.primary,\n};\n\nexport const SEVERITY_LABEL: Record<HealthIssueSeverity, string> = {\n critical: 'Critical',\n warning: 'Warning',\n info: 'Info',\n};\n\nconst ICON_COL = 2;\nconst ROW_GAP = 2;\nconst NARROW_TERM_THRESHOLD = 90;\nconst MAX_DOCS_WIDTH = 50;\nconst MIN_DOCS_WIDTH = 20;\n\nfunction computeDocsWidth(termCols: number): number {\n if (termCols < NARROW_TERM_THRESHOLD) return 0;\n const inner = termCols - 12;\n return Math.min(\n MAX_DOCS_WIDTH,\n Math.max(MIN_DOCS_WIDTH, Math.floor(inner * 0.45)),\n );\n}\n\ninterface IssueTableProps {\n issues: HealthIssue[];\n}\n\nexport const IssueTable = ({ issues }: IssueTableProps) => {\n const [termCols] = useStdoutDimensions();\n const docsWidth = computeDocsWidth(termCols);\n\n const grouped: Partial<Record<HealthIssueSeverity, HealthIssue[]>> = {};\n for (const issue of issues) {\n (grouped[issue.severity] ??= []).push(issue);\n }\n\n return (\n <Box flexDirection=\"column\">\n {SEVERITY_ORDER.map((sev) => {\n const list = grouped[sev];\n if (!list || list.length === 0) return null;\n return (\n <Box key={sev} flexDirection=\"column\" marginTop={1}>\n <Text bold color={SEVERITY_COLOR[sev]}>\n {SEVERITY_LABEL[sev]} ({list.length})\n </Text>\n {list.map((issue) => (\n <IssueRow key={issue.id} issue={issue} docsWidth={docsWidth} />\n ))}\n </Box>\n );\n })}\n </Box>\n );\n};\n\nconst IssueRow = ({\n issue,\n docsWidth,\n}: {\n issue: HealthIssue;\n docsWidth: number;\n}) => {\n const meta = getKindMeta(issue.kind);\n const sevColor = SEVERITY_COLOR[issue.severity];\n\n if (docsWidth === 0) {\n return (\n <Box flexDirection=\"column\">\n <Box>\n <Box width={ICON_COL}>\n <Text color={sevColor}>{Icons.squareFilled}</Text>\n </Box>\n <Box flexGrow={1} flexShrink={1} overflow=\"hidden\">\n <Text wrap=\"truncate\">{meta.title}</Text>\n </Box>\n </Box>\n <Box paddingLeft={ICON_COL}>\n <Text color={Colors.primary} wrap=\"truncate\">\n {meta.docsUrl}\n </Text>\n </Box>\n </Box>\n );\n }\n\n return (\n <Box>\n <Box width={ICON_COL}>\n <Text color={sevColor}>{Icons.squareFilled}</Text>\n </Box>\n <Box flexGrow={1} flexShrink={1} overflow=\"hidden\" marginRight={ROW_GAP}>\n <Text wrap=\"truncate\">{meta.title}</Text>\n </Box>\n <Box width={docsWidth} flexShrink={0}>\n <Text color={Colors.primary} wrap=\"truncate\">\n {meta.docsUrl}\n </Text>\n </Box>\n </Box>\n );\n};\n","/**\n * McpScreen — MCP server install/remove flow.\n *\n * Uses an McpInstaller service (passed via props) instead of\n * importing business logic directly. Testable, no dynamic imports.\n *\n * Supports two modes via the `mode` prop:\n * - 'install': detect clients → confirm → [pick clients] → pick features → install\n * - 'remove': detect installed clients → confirm → remove\n *\n * When done, calls store.setMcpComplete(). The router resolves to outro.\n */\n\nimport { Box, Text, useInput } from 'ink';\nimport { useState, useEffect } from 'react';\nimport { useSyncExternalStore } from 'react';\nimport { type WizardStore, McpOutcome } from '../store.js';\nimport {\n ConfirmationInput,\n PickerMenu,\n GroupedPickerMenu,\n} from '../primitives/index.js';\nimport { Colors } from '../styles.js';\nimport type { McpInstaller, McpClientInfo } from '../services/mcp-installer.js';\nimport {\n AVAILABLE_FEATURES,\n ALL_FEATURE_VALUES,\n} from '../../../steps/add-mcp-server-to-clients/defaults.js';\n\nexport type McpMode = 'install' | 'remove';\n\ninterface McpScreenProps {\n store: WizardStore;\n installer: McpInstaller;\n mode?: McpMode;\n}\n\nenum Phase {\n Detecting = 'detecting',\n Ask = 'ask',\n Pick = 'pick',\n FeatureSelect = 'feature-select',\n Working = 'working',\n Done = 'done',\n None = 'none',\n}\n\nconst markDone = (\n store: WizardStore,\n outcome: McpOutcome,\n clients: string[] = [],\n) => {\n store.setMcpComplete(outcome, clients);\n};\n\nexport const McpScreen = ({\n store,\n installer,\n mode = 'install',\n}: McpScreenProps) => {\n useSyncExternalStore(\n (cb) => store.subscribe(cb),\n () => store.getSnapshot(),\n );\n\n // Keep stdin active from mount so Windows cmd.exe doesn't drop\n // the first keypress when ConfirmationInput appears after detection.\n useInput(() => undefined);\n\n const isRemove = mode === 'remove';\n\n const [phase, setPhase] = useState<Phase>(Phase.Detecting);\n const [clients, setClients] = useState<McpClientInfo[]>([]);\n const [selectedClientNames, setSelectedClientNames] = useState<string[]>([]);\n const [resultClients, setResultClients] = useState<string[]>([]);\n const [pluginClients, setPluginClients] = useState<string[]>([]);\n\n useEffect(() => {\n void (async () => {\n try {\n const detected = await installer.detectClients();\n if (detected.length === 0) {\n setPhase(Phase.None);\n setTimeout(() => markDone(store, McpOutcome.NoClients), 1500);\n } else {\n setClients(detected);\n setPhase(Phase.Ask);\n }\n } catch {\n setPhase(Phase.None);\n setTimeout(() => markDone(store, McpOutcome.Failed), 1500);\n }\n })();\n }, [installer]); // eslint-disable-line\n\n const proceedToFeatureSelectOrInstall = (clientNames: string[]) => {\n setSelectedClientNames(clientNames);\n // Skip feature picker if CLI already specified features\n if (store.session.mcpFeatures) {\n void doInstall(clientNames, store.session.mcpFeatures);\n } else {\n setPhase(Phase.FeatureSelect);\n }\n };\n\n const handleConfirm = () => {\n if (isRemove) {\n void doRemove();\n } else if (clients.length === 1) {\n proceedToFeatureSelectOrInstall(clients.map((c) => c.name));\n } else {\n setPhase(Phase.Pick);\n }\n };\n\n const handleSkip = () => {\n markDone(store, McpOutcome.Skipped);\n };\n\n const doInstall = async (names: string[], features?: string[]) => {\n setPhase(Phase.Working);\n let mcpResult: string[] = [];\n let pluginResult: string[] = [];\n try {\n mcpResult = await installer.install(\n names,\n features,\n store.session.apiKey,\n );\n } catch {\n // mcpResult stays []\n }\n try {\n pluginResult = await installer.installPlugins(names);\n } catch {\n // best-effort — plugin failure does not affect MCP outcome\n }\n setResultClients(mcpResult);\n setPluginClients(pluginResult);\n setPhase(Phase.Done);\n const outcome =\n mcpResult.length > 0 ? McpOutcome.Installed : McpOutcome.Failed;\n setTimeout(() => markDone(store, outcome, mcpResult), 2000);\n };\n\n const doRemove = async () => {\n setPhase(Phase.Working);\n let result: string[] = [];\n try {\n result = await installer.remove();\n setResultClients(result);\n } catch {\n setResultClients([]);\n }\n setPhase(Phase.Done);\n const outcome =\n result.length > 0 ? McpOutcome.Installed : McpOutcome.Failed;\n setTimeout(() => markDone(store, outcome, result), 2000);\n };\n\n return (\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text bold color={Colors.accent}>\n MCP Server {isRemove ? 'Removal' : 'Setup'}\n </Text>\n\n <Box marginTop={1} flexDirection=\"column\">\n {phase === Phase.Detecting && (\n <Text dimColor>Detecting supported editors...</Text>\n )}\n\n {phase === Phase.None && (\n <Text dimColor>\n No {isRemove ? 'installed' : 'supported'} MCP clients detected.\n Skipping...\n </Text>\n )}\n\n {phase === Phase.Ask && (\n <>\n <Text dimColor>\n Detected: {clients.map((c) => c.name).join(', ')}\n </Text>\n <Box marginTop={1}>\n <ConfirmationInput\n message={`${\n isRemove ? 'Remove' : 'Install'\n } the PostHog MCP server${\n clients.some((c) => c.supportsPlugin) ? ' and plugin' : ''\n }?`}\n confirmLabel={isRemove ? 'Remove' : 'Install'}\n cancelLabel=\"No thanks\"\n onConfirm={handleConfirm}\n onCancel={handleSkip}\n />\n </Box>\n </>\n )}\n\n {phase === Phase.Pick && (\n <PickerMenu\n message=\"Select editor to install MCP server\"\n options={clients.map((c) => ({\n label: c.name,\n value: c.name,\n }))}\n mode=\"multi\"\n onSelect={(selected) => {\n const names = Array.isArray(selected) ? selected : [selected];\n proceedToFeatureSelectOrInstall(names);\n }}\n />\n )}\n\n {phase === Phase.FeatureSelect && (\n <GroupedPickerMenu\n message=\"Select features to enable\"\n groups={AVAILABLE_FEATURES}\n initialSelected={[...ALL_FEATURE_VALUES]}\n onSelect={(features) => {\n void doInstall(selectedClientNames, features);\n }}\n />\n )}\n\n {phase === Phase.Working && (\n <Text dimColor>\n {isRemove ? 'Removing' : 'Installing'} MCP server...\n </Text>\n )}\n\n {phase === Phase.Done && (\n <Box flexDirection=\"column\">\n {resultClients.length > 0 ? (\n <>\n <Text color=\"green\" bold>\n {'\\u2714'} MCP server\n {!isRemove && pluginClients.length > 0 ? ' and plugin' : ''}{' '}\n {isRemove ? 'removed from' : 'installed for'}:\n </Text>\n {resultClients.map((name, i) => (\n <Text key={i}>\n {' '}\n {'\\u2022'} {name}\n </Text>\n ))}\n </>\n ) : (\n <Text dimColor>\n {isRemove ? 'Removal' : 'Installation'} skipped.\n </Text>\n )}\n </Box>\n )}\n </Box>\n </Box>\n );\n};\n","import { Box, Text } from 'ink';\n\ninterface AreaHeaderRowProps {\n area: string;\n resolved: number;\n total: number;\n}\n\n/** Sub-header row inside the scrollable body — one per area group. */\nexport const AreaHeaderRow = ({\n area,\n resolved,\n total,\n}: AreaHeaderRowProps) => (\n <Box flexShrink={0} marginTop={1}>\n <Text bold color=\"cyan\">\n {area}{' '}\n </Text>\n <Text dimColor>\n ({resolved}/{total})\n </Text>\n </Box>\n);\n","import { MAX_WIDTH } from '../../../primitives/ScreenContainer.js';\n\n/** Terminal rows used by chrome outside the viewer\n * (TitleBar, spacer, screen padding, status bar, tab bar). */\nexport const CHROME_ROWS = 10;\n\n/** Rows used by the viewer's own header / footer\n * (title, subtitle, top summary, spacer, column headers, divider,\n * scroll-up marker, scroll-down marker, legend, footer summary). */\nexport const VIEWER_CHROME_BASE = 10;\n\nexport const COL_AREA_WIDTH = 18;\nexport const COL_LABEL_MIN = 28;\nexport const COL_GAP = 2;\n\nexport interface ViewerLayout {\n cols: number;\n visibleHeight: number;\n viewerChrome: number;\n padding: number;\n statusWidth: number;\n areaWidth: number;\n labelWidth: number;\n colGap: number;\n dividerWidth: number;\n detailIndent: number;\n detailWidth: number;\n}\n\n/** ScreenContainer wraps content in paddingX={1} inside a width capped at\n * MAX_WIDTH, so the actual width available to the viewer is\n * min(cols, MAX_WIDTH) - 2. */\nfunction getViewerWidth(rawCols: number): number {\n return Math.min(MAX_WIDTH, rawCols) - 2;\n}\n\nexport function computeLayout(rawCols: number, termRows: number): ViewerLayout {\n const cols = getViewerWidth(rawCols);\n const padding = 2;\n const statusWidth = 2;\n\n // CHECK flexes to consume the rest of the row so long labels stay readable\n // instead of getting truncated.\n const fixedExceptLabel =\n padding + statusWidth + COL_GAP + COL_AREA_WIDTH + COL_GAP + COL_GAP;\n const labelWidth = Math.max(COL_LABEL_MIN, cols - fixedExceptLabel);\n\n const detailIndent = statusWidth + COL_GAP + COL_AREA_WIDTH + COL_GAP;\n\n const viewerChrome = VIEWER_CHROME_BASE;\n const visibleHeight = Math.max(5, termRows - CHROME_ROWS - viewerChrome);\n\n return {\n cols,\n visibleHeight,\n viewerChrome,\n padding,\n statusWidth,\n areaWidth: COL_AREA_WIDTH,\n labelWidth,\n colGap: COL_GAP,\n dividerWidth: Math.max(20, cols - padding),\n detailIndent,\n detailWidth: Math.max(20, cols - detailIndent - padding),\n };\n}\n\nexport function truncate(text: string, max: number): string {\n if (max <= 0) return '';\n if (text.length <= max) return text;\n return text.slice(0, Math.max(1, max - 1)) + '…';\n}\n","import { Box, Text } from 'ink';\nimport {\n AUDIT_SEVERITY_STYLE,\n type AuditCheck,\n} from '../../../../../lib/workflows/audit/types.js';\nimport { truncate, type ViewerLayout } from './layout.js';\n\ninterface CheckRowProps {\n item: AuditCheck;\n layout: ViewerLayout;\n}\n\nexport const CheckRow = ({ item, layout }: CheckRowProps) => {\n const style = AUDIT_SEVERITY_STYLE[item.status];\n return (\n <Box flexShrink={0}>\n <Box width={layout.statusWidth + layout.colGap}>\n <Text color={style.color}>{style.glyph}</Text>\n </Box>\n <Box width={layout.areaWidth + layout.colGap}>\n <Text dimColor>{truncate(item.area, layout.areaWidth)}</Text>\n </Box>\n <Box width={layout.labelWidth + layout.colGap}>\n <Text\n bold={item.status !== 'pending'}\n dimColor={item.status === 'pending'}\n >\n {truncate(item.label, layout.labelWidth)}\n </Text>\n </Box>\n </Box>\n );\n};\n","import { Box, Text } from 'ink';\nimport type { AuditCheck } from '../../../../../lib/workflows/audit/types.js';\nimport type { ViewerLayout } from './layout.js';\n\ninterface DetailRowProps {\n item: AuditCheck;\n layout: ViewerLayout;\n}\n\n/** Format a `details` string. If it parses as a JSON object, render it as\n * indented key: value lines (skipping huge nested arrays/objects which we\n * truncate). Otherwise return the original text. v3000 emits structured\n * JSON for several event-quality checks — a raw dump is unreadable. */\nfunction formatDetails(raw: string): string[] {\n const trimmed = raw.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return [raw];\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n return [raw];\n }\n if (parsed === null || typeof parsed !== 'object') return [raw];\n const lines: string[] = [];\n const renderValue = (v: unknown): string => {\n if (v === null) return 'null';\n if (typeof v === 'string') return v;\n if (typeof v === 'number' || typeof v === 'boolean') return String(v);\n if (Array.isArray(v)) {\n if (v.length === 0) return '[]';\n const allPrimitive = v.every((e) => e === null || typeof e !== 'object');\n if (allPrimitive) return v.map(renderValue).join(', ');\n return `[${v.length} item${v.length === 1 ? '' : 's'}]`;\n }\n if (typeof v === 'object') {\n const keys = Object.keys(v);\n return `{${keys.length} field${keys.length === 1 ? '' : 's'}}`;\n }\n return String(v);\n };\n for (const [key, value] of Object.entries(parsed)) {\n lines.push(`${key}: ${renderValue(value)}`);\n }\n return lines.length > 0 ? lines : [raw];\n}\n\n/** Indented under the CHECK column; wrap continuation aligns with the prefix. */\nexport const DetailRow = ({ item, layout }: DetailRowProps) => {\n const detailLines = item.details ? formatDetails(item.details) : [];\n return (\n <Box flexShrink={0}>\n <Box width={layout.detailIndent} />\n <Box flexDirection=\"column\" width={layout.detailWidth}>\n {item.file && (\n <Text dimColor wrap=\"wrap\">\n {`↳ File: ${item.file}`}\n </Text>\n )}\n {detailLines.map((line, i) => (\n <Text key={i} dimColor italic wrap=\"wrap\">\n {i === 0 ? `${item.file ? ' ' : '↳ '}${line}` : ` ${line}`}\n </Text>\n ))}\n </Box>\n </Box>\n );\n};\n","import { Text } from 'ink';\n\nexport const Legend = () => (\n <Text>\n <Text color=\"green\">✔ pass</Text>\n <Text dimColor>{' · '}</Text>\n <Text color=\"red\">✘ error</Text>\n <Text dimColor>{' · '}</Text>\n <Text color=\"yellow\">⚠ warning</Text>\n <Text dimColor>{' · '}</Text>\n <Text color=\"cyan\">• suggestion</Text>\n </Text>\n);\n","import { Box, Text } from 'ink';\nimport type {\n AuditCheck,\n AuditStatus,\n} from '../../../../../lib/workflows/audit/types.js';\nimport type { ViewerLayout } from './layout.js';\n\ninterface HeaderProps {\n layout: ViewerLayout;\n}\n\ninterface SummaryProps {\n total: number;\n counts: Record<AuditStatus, number>;\n}\n\nfunction statusCounts(checks: AuditCheck[]): Record<AuditStatus, number> {\n const out: Record<AuditStatus, number> = {\n pending: 0,\n pass: 0,\n error: 0,\n warning: 0,\n suggestion: 0,\n };\n for (const c of checks) out[c.status] += 1;\n return out;\n}\n\nexport { statusCounts };\n\nexport const Header = ({ layout }: HeaderProps) => (\n <Box>\n <Box width={layout.statusWidth + layout.colGap}>\n <Text dimColor bold>\n {' '}\n </Text>\n </Box>\n <Box width={layout.areaWidth + layout.colGap}>\n <Text dimColor bold>\n AREA\n </Text>\n </Box>\n <Box width={layout.labelWidth + layout.colGap}>\n <Text dimColor bold>\n CHECK\n </Text>\n </Box>\n </Box>\n);\n\nexport const Summary = ({ total, counts }: SummaryProps) => (\n <Text dimColor>\n {total} total · {counts.pending} pending · {counts.error} errors ·{' '}\n {counts.warning} warnings · {counts.suggestion} suggestions · {counts.pass}{' '}\n passes\n </Text>\n);\n","import { Legend } from './Legend.js';\nimport { Summary } from './Header.js';\nimport type { AuditStatus } from '../../../../../lib/workflows/audit/types.js';\n\ninterface FooterProps {\n total: number;\n counts: Record<AuditStatus, number>;\n}\n\nexport const Footer = ({ total, counts }: FooterProps) => (\n <>\n <Legend />\n <Summary total={total} counts={counts} />\n </>\n);\n","import type {\n AuditCheck,\n AuditStatus,\n} from '../../../../../lib/workflows/audit/types.js';\n\nconst STATUS_ORDER: Record<AuditStatus, number> = {\n error: 0,\n warning: 1,\n suggestion: 2,\n pass: 3,\n pending: 4,\n};\n\n/** Audit areas in the order they should be displayed. Areas not listed\n * here fall through to alphabetical order at the end. Mirrors the\n * Full audit section grouping in the generated report. */\nconst AREA_ORDER: string[] = [\n 'Installation',\n 'Identification',\n 'Event Capture',\n 'Event Quality',\n 'Feature Flags',\n 'Session Replay',\n 'Session Replay — Optimize',\n 'Use Case: Expansion',\n 'Additional Sections',\n];\n\nfunction areaRank(area: string): number {\n const idx = AREA_ORDER.indexOf(area);\n return idx === -1 ? AREA_ORDER.length : idx;\n}\n\n/** Issues at the top (error → warning → suggestion), then passes, then pending todos. */\nexport function sortChecks(checks: ReadonlyArray<AuditCheck>): AuditCheck[] {\n return [...checks].sort((a, b) => {\n const da = STATUS_ORDER[a.status] - STATUS_ORDER[b.status];\n if (da !== 0) return da;\n return a.area.localeCompare(b.area);\n });\n}\n\nexport interface AreaGroup {\n area: string;\n checks: AuditCheck[];\n counts: { total: number; resolved: number };\n}\n\n/** Group checks by area, in AREA_ORDER. Within each area, sort by status. */\nexport function groupChecksByArea(\n checks: ReadonlyArray<AuditCheck>,\n): AreaGroup[] {\n const byArea = new Map<string, AuditCheck[]>();\n for (const c of checks) {\n const list = byArea.get(c.area);\n if (list) list.push(c);\n else byArea.set(c.area, [c]);\n }\n const groups: AreaGroup[] = [];\n for (const [area, areaChecks] of byArea) {\n const sorted = [...areaChecks].sort(\n (a, b) => STATUS_ORDER[a.status] - STATUS_ORDER[b.status],\n );\n const resolved = sorted.filter((c) => c.status !== 'pending').length;\n groups.push({\n area,\n checks: sorted,\n counts: { total: sorted.length, resolved },\n });\n }\n groups.sort((a, b) => {\n const dr = areaRank(a.area) - areaRank(b.area);\n if (dr !== 0) return dr;\n return a.area.localeCompare(b.area);\n });\n return groups;\n}\n","/**\n * AuditChecksViewer — \"Audit plan\" tab.\n *\n * Renders the full audit ledger as a scrollable, area-grouped list that\n * mirrors the structure of the final report. Each area gets a sub-header\n * with a resolved/total count; checks within an area are sorted by\n * severity (error → warning → suggestion → pass → pending).\n *\n * Two interactions, both registered via `useKeyBindings`:\n * - `e` — toggle detail rows (file:line + agent's `details` text)\n * - `↑` / `↓` — scroll one row at a time, clamped to content bounds\n *\n * Auto-expands on first mount when the ledger contains any issue, since\n * the AuditAreaPane's `[→] View issues` hint sends users here precisely\n * to read those details.\n */\n\nimport { Box, Text } from 'ink';\nimport { Fragment, useMemo, useState, type ReactNode } from 'react';\nimport { useStdoutDimensions } from '../../../hooks/useStdoutDimensions.js';\nimport {\n KeyMatch,\n useKeyBindings,\n type KeyBinding,\n} from '../../../hooks/useKeyBindings.js';\nimport type { AuditCheck } from '../../../../../lib/workflows/audit/types.js';\nimport { AreaHeaderRow } from './AreaHeaderRow.js';\nimport { CheckRow } from './CheckRow.js';\nimport { DetailRow } from './DetailRow.js';\nimport { Footer } from './Footer.js';\nimport { Header, Summary, statusCounts } from './Header.js';\nimport { computeLayout } from './layout.js';\nimport { groupChecksByArea } from './sort.js';\n\ninterface AuditChecksViewerProps {\n checks: AuditCheck[];\n}\n\nexport const AuditChecksViewer = ({ checks }: AuditChecksViewerProps) => {\n // ── Layout ─────────────────────────────────────────────────────────\n const [rawCols, termRows] = useStdoutDimensions();\n const layout = computeLayout(rawCols, termRows);\n const totalHeight = layout.visibleHeight + layout.viewerChrome;\n\n // ── Group by area ──────────────────────────────────────────────────\n const groups = useMemo(() => groupChecksByArea(checks), [checks]);\n const counts = useMemo(() => statusCounts(checks), [checks]);\n\n // ── Expand state ───────────────────────────────────────────────────\n const hasExpandable = checks.some((c) => Boolean(c.details || c.file));\n const hasIssues = checks.some(\n (c) =>\n c.status === 'error' ||\n c.status === 'warning' ||\n c.status === 'suggestion',\n );\n const [expanded, setExpanded] = useState(hasIssues && hasExpandable);\n\n // ── Flat row list ──────────────────────────────────────────────────\n // One ReactNode per visible terminal row so scroll math stays simple.\n // Sub-header + check rows + (optional) detail rows interleave here.\n const allRows = useMemo<ReactNode[]>(() => {\n const rows: ReactNode[] = [];\n for (const group of groups) {\n rows.push(\n <AreaHeaderRow\n key={`header-${group.area}`}\n area={group.area}\n resolved={group.counts.resolved}\n total={group.counts.total}\n />,\n );\n for (const item of group.checks) {\n rows.push(<CheckRow key={item.id} item={item} layout={layout} />);\n if (expanded && (item.details || item.file)) {\n rows.push(\n <DetailRow key={`${item.id}-detail`} item={item} layout={layout} />,\n );\n }\n }\n }\n return rows;\n }, [groups, expanded, layout]);\n\n // ── Scroll viewport ────────────────────────────────────────────────\n const [offset, setOffset] = useState(0);\n const maxOffset = Math.max(0, allRows.length - layout.visibleHeight);\n const clampedOffset = Math.min(offset, maxOffset);\n const hiddenAbove = clampedOffset;\n const hiddenBelow = Math.max(\n 0,\n allRows.length - clampedOffset - layout.visibleHeight,\n );\n\n // ── Key bindings ───────────────────────────────────────────────────\n const bindings: KeyBinding[] = [];\n if (hasExpandable) {\n bindings.push({\n match: 'e',\n label: 'e',\n action: expanded ? 'collapse details' : 'expand details',\n handler: () => setExpanded((prev) => !prev),\n });\n }\n bindings.push({\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '↑↓',\n action: 'scroll',\n handler: (_input, key) => {\n if (key.upArrow) setOffset((o) => Math.max(0, o - 1));\n else if (key.downArrow) setOffset((o) => Math.min(maxOffset, o + 1));\n },\n });\n useKeyBindings('audit-checks-viewer', bindings);\n\n // ── Render ─────────────────────────────────────────────────────────\n const visibleRows = allRows.slice(\n clampedOffset,\n clampedOffset + layout.visibleHeight,\n );\n\n // Dynamic subtitle — lists the actual areas in the ledger.\n const subtitle =\n groups.length === 0\n ? 'No checks yet.'\n : `Review across ${groups.length} ${\n groups.length === 1 ? 'area' : 'areas'\n } — mirrors the final report.`;\n\n return (\n <Box flexDirection=\"column\" paddingX={1} height={totalHeight}>\n {/* Title + dynamic subtitle */}\n <Text bold>Audit plan</Text>\n <Text dimColor>{subtitle}</Text>\n\n {/* Top summary — same as Footer summary, promoted here for at-a-glance */}\n <Summary total={checks.length} counts={counts} />\n <Box height={1} />\n\n {/* Column headers + divider */}\n <Header layout={layout} />\n <Text dimColor>{'─'.repeat(layout.dividerWidth)}</Text>\n\n {/* Scroll-up marker */}\n <Text dimColor>{hiddenAbove > 0 ? `↑ ${hiddenAbove} more` : ' '}</Text>\n\n {/* Scrollable body */}\n <Box\n flexDirection=\"column\"\n height={layout.visibleHeight}\n overflow=\"hidden\"\n >\n {visibleRows.map((node, i) => (\n <Fragment key={`row-${clampedOffset + i}`}>{node}</Fragment>\n ))}\n </Box>\n\n {/* Scroll-down marker */}\n <Text dimColor>{hiddenBelow > 0 ? `↓ ${hiddenBelow} more` : ' '}</Text>\n\n {/* Legend (counts already shown at the top) */}\n <Footer total={checks.length} counts={counts} />\n </Box>\n );\n};\n"],"mappings":"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"}
|