'use client' import { useState, useCallback } from 'react' import { motion, AnimatePresence } from 'framer-motion' import { ArrowRight, ArrowLeft, Check, FileText, Edit3, Eye, Download, ListTodo, Wrench, Terminal } from 'lucide-react' import type { InstallMdGeneratorData, InstallMdTodoItem, InstallMdStep } from '@/types' import { createDefaultGeneratorData, createEmptyTodoItem, createEmptyStep, generateInstallMd, validateGeneratorData, INSTALL_MD_TEMPLATES, type InstallMdTemplateKey } from '@/lib/install-md-generator' import TodoEditor from './TodoEditor' import StepEditor from './StepEditor' import Preview from './Preview' interface InstallMdWizardProps { onComplete?: (content: string) => void } type Step = 'basic' | 'todos' | 'steps' | 'preview' const STEPS: { id: Step; label: string; icon: React.ElementType }[] = [ { id: 'basic', label: 'Basic Info', icon: FileText }, { id: 'todos', label: 'TODO List', icon: ListTodo }, { id: 'steps', label: 'Steps', icon: Wrench }, { id: 'preview', label: 'Preview', icon: Eye }, ] export default function InstallMdWizard({ onComplete }: InstallMdWizardProps) { const [step, setStep] = useState('basic') const [data, setData] = useState(createDefaultGeneratorData()) const [selectedTemplate, setSelectedTemplate] = useState('empty') const [validationErrors, setValidationErrors] = useState([]) const handleTemplateSelect = useCallback((templateKey: string) => { setSelectedTemplate(templateKey) if (templateKey === 'empty') { setData(createDefaultGeneratorData()) } else { const template = INSTALL_MD_TEMPLATES[templateKey as InstallMdTemplateKey] if (template) { // Deep copy to avoid readonly type issues setData({ ...createDefaultGeneratorData(), objective: template.data.objective, doneWhen: template.data.doneWhen, todoItems: template.data.todoItems.map(t => ({ id: t.id, text: t.text, completed: t.completed })), steps: template.data.steps.map(s => ({ id: s.id, title: s.title, description: s.description, codeBlocks: s.codeBlocks.map(cb => ({ ...cb })), })), productName: data.productName || '', description: data.description || '', }) } } }, [data.productName, data.description]) const handleBasicSubmit = useCallback((e: React.FormEvent) => { e.preventDefault() setStep('todos') }, []) const handleTodosChange = useCallback((todoItems: InstallMdTodoItem[]) => { setData(prev => ({ ...prev, todoItems })) }, []) const handleStepsChange = useCallback((steps: InstallMdStep[]) => { setData(prev => ({ ...prev, steps })) }, []) const handleComplete = useCallback(() => { const { isValid, errors } = validateGeneratorData(data) if (!isValid) { setValidationErrors(errors) return } const content = generateInstallMd(data) onComplete?.(content) }, [data, onComplete]) const canProceedToTodos = data.productName.trim().length > 0 && data.objective.trim().length > 0 const canProceedToSteps = data.todoItems.some(t => t.text.trim()) const canProceedToPreview = data.steps.some(s => s.title.trim()) const currentStepIndex = STEPS.findIndex(s => s.id === step) return (
{/* Progress Steps */}
{STEPS.map((s, index) => { const Icon = s.icon const isActive = s.id === step const isPast = index < currentStepIndex const isFuture = index > currentStepIndex return (
{index < STEPS.length - 1 && ( )}
) })}
{/* Validation Errors */} {validationErrors.length > 0 && (
    {validationErrors.map((error, i) => (
  • {error}
  • ))}
)}
{/* Step Content */} {step === 'basic' && (
{/* Template Selection */}
{Object.entries(INSTALL_MD_TEMPLATES).map(([key, template]) => ( ))}
{/* Product Name */}
setData(prev => ({ ...prev, productName: e.target.value }))} placeholder="e.g., Mintlify CLI" className="w-full px-4 py-3 bg-white/5 border border-neutral-700 rounded-lg focus:outline-none focus:border-white text-white placeholder-neutral-500" />

Will be converted to lowercase-hyphenated format (e.g., mintlify-cli)

{/* Description */}
setData(prev => ({ ...prev, description: e.target.value }))} placeholder="e.g., Documentation and setup instructions for Mintlify CLI" className="w-full px-4 py-3 bg-white/5 border border-neutral-700 rounded-lg focus:outline-none focus:border-white text-white placeholder-neutral-500" />
{/* Objective */}
setData(prev => ({ ...prev, objective: e.target.value }))} placeholder="e.g., Install the CLI and set up a local preview environment" className="w-full px-4 py-3 bg-white/5 border border-neutral-700 rounded-lg focus:outline-none focus:border-white text-white placeholder-neutral-500" />

What should the installation achieve?

{/* Done When */}
setData(prev => ({ ...prev, doneWhen: e.target.value }))} placeholder="e.g., Local server is running at http://localhost:3000" className="w-full px-4 py-3 bg-white/5 border border-neutral-700 rounded-lg focus:outline-none focus:border-white text-white placeholder-neutral-500" />

Specific verification criteria for success

{/* Next Button */}
)} {step === 'todos' && (

TODO Checklist

Define the steps the LLM should complete. These appear as checkboxes.

{/* Navigation */}
)} {step === 'steps' && (

Installation Steps

Define detailed instructions with code blocks for each step.

{/* Navigation */}
)} {step === 'preview' && (

Preview & Download

Review your install.md file and download when ready.

{/* Navigation */}
)}
) }