The bep new wizard was recently converted from @clack/prompts to Ink. The resulting App.tsx (~405 lines) is a monolith handling prompt definition, state management, keyboard input, navigation, and rendering. Two provider step components (ManualProviderStep, MixpanelProviderStep) are byte-identical. This refactor decomposes into focused units following container/presentation and single-responsibility principles.
R1: TheInkNewWizardshall expose the same public API: a singleInkNewWizardAppcomponent acceptingonComplete: (result: NewWizardResult) => void.R2: TheInkNewWizardshall preserve all existing keyboard behavior (arrow keys, vim j/k, Enter, Ctrl+C, Backspace, printable text input, Back option navigation) except that Escape shall navigate back (instead of cancelling).R3: TheInkNewWizardshall separate prompt configuration (titles, validation rules, options) into a pure module with no React dependency.R4: TheInkNewWizardshall separate wizard state management (draft, step index, UI state, navigation actions) into a dedicated React hook.R5: TheInkNewWizardshall separate keyboard input routing into a dedicated React hook.R6: TheInkNewWizardshall use a single two-branch dispatch (select vs text) for step rendering, eliminating duplicate provider wrapper components.R7: TheAppcontainer component shall contain only hook composition and presentation wiring — no business logic, no inline state management, no input handling.
S1: Createsrc/ui/ink/newWizard/promptFactory.tscontainingbuildPrompt(),buildUiState(),BACK_OPTION,MIXPANEL_URL_HINT,isProviderType(), and theWizardPrompt/WizardUiStatetype exports. All pure functions, no React. (R3)S2: UpdateApp.tsxto import frompromptFactory.tsand remove the extracted code. (R3)S3:npm run buildto confirm no compile errors. (R1)
S4: Deletecomponents/ManualProviderStep.tsxandcomponents/MixpanelProviderStep.tsx. Delete theisProviderStep()helper fromApp.tsx. Replace the four-branch body rendering with a two-branch select-or-text dispatch. (R6)S5:npm run build. (R1)
S6: Createsrc/ui/ink/newWizard/useWizardState.tscontaining alluseState/useMemo/useEffectcalls plusgoBack,submitSelect,submitText,completeIfDone, and acancelwrapper. Hook signature:useWizardState(onComplete) => { prompt, uiState, actions }whereactions = { goBack, submitSelect, submitText, cancel, setUiState }. (R4)S7: UpdateApp.tsxto use the hook, removing all inline state logic. (R4, R7)S8:npm run build. (R1)
S9: Createsrc/ui/ink/newWizard/useWizardInput.tscontaining theuseInputcallback that routes keys toactions.*methods. Signature:useWizardInput(prompt, uiState, actions) => void. (R5)S10: ReduceApp.tsxto ~25 lines: hook composition +WizardFramewithSelectStep/TextStep. (R7)S11: USER checkpoint: review final structure before committing.
V1 (R1, R2, R3, R4, R5, R6, R7):npm run buildafter each chunk.V2 (R1, R2):npm test— existingnewWizardFlow.test.tspasses.V3 (R2): Manual trace of keyboard handling paths throughuseWizardInputto confirm equivalence with originaluseInputcallback.