{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "wizard-expandable-demo",
  "type": "registry:component",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "wizard-expandable",
    "button",
    "input",
    "label",
    "textarea"
  ],
  "files": [
    {
      "path": "registry/default/example/wizard-expandable-demo.tsx",
      "content": "\"use client\"\n\nimport { useCallback, useMemo, useRef, useState } from \"react\"\nimport { Building2, CheckCircle2, Layers, User, UserCircle } from \"lucide-react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { Input } from \"@/components/ui/input\"\nimport { Label } from \"@/components/ui/label\"\nimport { Textarea } from \"@/components/ui/textarea\"\nimport WizardExpandable, {\n  type WizardNavigateContext,\n} from \"@/registry/default/ui/wizard-expandable\"\n\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\nconst WHITESPACE_SPLIT = /\\s+/\n\nexport default function WizardExpandableDemo() {\n  const [submitted, setSubmitted] = useState(false)\n  const [controlledExpanded, setControlledExpanded] = useState(false)\n  const [controlledActiveStep, setControlledActiveStep] = useState<\n    string | null\n  >(null)\n\n  const [accountName, setAccountName] = useState(\"\")\n  const [accountEmail, setAccountEmail] = useState(\"\")\n  const [headline, setHeadline] = useState(\"\")\n  const [bio, setBio] = useState(\"\")\n  const [organization, setOrganization] = useState(\"\")\n  const [planTier, setPlanTier] = useState(\"\")\n\n  const accountNameRef = useRef<HTMLInputElement>(null)\n  const accountEmailRef = useRef<HTMLInputElement>(null)\n  const headlineRef = useRef<HTMLInputElement>(null)\n  const bioRef = useRef<HTMLTextAreaElement>(null)\n  const organizationRef = useRef<HTMLInputElement>(null)\n  const planSelectRef = useRef<HTMLSelectElement>(null)\n\n  const canNavigateToStep = useCallback(\n    (ctx: WizardNavigateContext) => {\n      if (ctx.fromStepId === \"account\") {\n        const nameOk = accountName.trim().length > 0\n        const emailOk = EMAIL_PATTERN.test(accountEmail.trim())\n        return nameOk && emailOk\n      }\n      if (ctx.fromStepId === \"profile\") {\n        return (\n          headline.trim().length > 0 &&\n          bio.trim().split(WHITESPACE_SPLIT).filter(Boolean).length >= 3\n        )\n      }\n      if (ctx.fromStepId === \"organization\") {\n        return organization.trim().length > 0\n      }\n      if (ctx.fromStepId === \"plan\") {\n        return planTier.length > 0\n      }\n      return true\n    },\n    [accountEmail, accountName, bio, headline, organization, planTier]\n  )\n\n  const onNavigateBlocked = useCallback(\n    (ctx: WizardNavigateContext) => {\n      if (ctx.fromStepId === \"account\") {\n        if (!accountName.trim()) {\n          accountNameRef.current?.focus()\n          return\n        }\n        if (!EMAIL_PATTERN.test(accountEmail.trim())) {\n          accountEmailRef.current?.focus()\n        }\n        return\n      }\n      if (ctx.fromStepId === \"profile\") {\n        if (!headline.trim()) {\n          headlineRef.current?.focus()\n          return\n        }\n        bioRef.current?.focus()\n        return\n      }\n      if (ctx.fromStepId === \"organization\") {\n        organizationRef.current?.focus()\n        return\n      }\n      if (ctx.fromStepId === \"plan\") {\n        planSelectRef.current?.focus()\n      }\n    },\n    [accountEmail, accountName, headline]\n  )\n\n  const validatedSteps = useMemo(\n    () => [\n      {\n        id: \"account\",\n        title: \"Account\",\n        description:\n          \"Your sign-in details. Forward navigation requires a name and valid email.\",\n        icon: User,\n        content: (\n          <div className=\"space-y-4\">\n            <p className=\"text-muted-foreground text-xs\">\n              Try advancing without filling fields — focus returns to the first\n              invalid input.\n            </p>\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"wizard-account-name\">Full name</Label>\n              <Input\n                autoComplete=\"name\"\n                id=\"wizard-account-name\"\n                onChange={(e) => setAccountName(e.target.value)}\n                placeholder=\"Jordan Gilliam\"\n                ref={accountNameRef}\n                value={accountName}\n              />\n            </div>\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"wizard-account-email\">Email</Label>\n              <Input\n                autoComplete=\"email\"\n                id=\"wizard-account-email\"\n                onChange={(e) => setAccountEmail(e.target.value)}\n                placeholder=\"you@example.com\"\n                ref={accountEmailRef}\n                type=\"email\"\n                value={accountEmail}\n              />\n            </div>\n          </div>\n        ),\n      },\n      {\n        id: \"profile\",\n        title: \"Profile\",\n        description:\n          \"A short public profile. Requires a headline and at least three words in the bio.\",\n        icon: UserCircle,\n        content: (\n          <div className=\"space-y-4\">\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"wizard-headline\">Headline</Label>\n              <Input\n                id=\"wizard-headline\"\n                onChange={(e) => setHeadline(e.target.value)}\n                placeholder=\"Design engineer\"\n                ref={headlineRef}\n                value={headline}\n              />\n            </div>\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"wizard-bio\">Bio</Label>\n              <Textarea\n                className=\"min-h-[100px] resize-y\"\n                id=\"wizard-bio\"\n                onChange={(e) => setBio(e.target.value)}\n                placeholder=\"Write at least three words about what you do.\"\n                ref={bioRef}\n                rows={4}\n                value={bio}\n              />\n            </div>\n          </div>\n        ),\n      },\n      {\n        id: \"organization\",\n        title: \"Organization\",\n        description:\n          \"Where you work. Pick a name your team will recognize on invoices and invites.\",\n        icon: Building2,\n        content: (\n          <div className=\"space-y-4\">\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"wizard-org-name\">Company or team name</Label>\n              <Input\n                id=\"wizard-org-name\"\n                onChange={(e) => setOrganization(e.target.value)}\n                placeholder=\"Acme Design Co.\"\n                ref={organizationRef}\n                value={organization}\n              />\n            </div>\n            <p className=\"text-muted-foreground text-xs\">\n              Required before Plan and Review — try Next with an empty field to\n              see validation.\n            </p>\n          </div>\n        ),\n      },\n      {\n        id: \"plan\",\n        title: \"Plan\",\n        description:\n          \"Choose a starting tier. You can change this anytime after signup.\",\n        icon: Layers,\n        content: (\n          <div className=\"space-y-4\">\n            <div className=\"space-y-2\">\n              <Label htmlFor=\"wizard-plan\">Product tier</Label>\n              <select\n                className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n                id=\"wizard-plan\"\n                onChange={(e) => setPlanTier(e.target.value)}\n                ref={planSelectRef}\n                value={planTier}\n              >\n                <option value=\"\">Select a plan…</option>\n                <option value=\"starter\">Starter — individuals</option>\n                <option value=\"pro\">Pro — small teams</option>\n                <option value=\"business\">Business — orgs & SSO</option>\n              </select>\n            </div>\n          </div>\n        ),\n      },\n      {\n        id: \"review\",\n        title: \"Review\",\n        description: \"Confirm your answers before finishing.\",\n        icon: CheckCircle2,\n        content: (\n          <div className=\"space-y-3 text-sm\">\n            <div className=\"rounded-lg border bg-background/60 p-3\">\n              <div className=\"text-muted-foreground text-xs\">Name</div>\n              <div className=\"font-medium text-foreground\">\n                {accountName.trim() || \"—\"}\n              </div>\n            </div>\n            <div className=\"rounded-lg border bg-background/60 p-3\">\n              <div className=\"text-muted-foreground text-xs\">Email</div>\n              <div className=\"font-medium text-foreground\">\n                {accountEmail.trim() || \"—\"}\n              </div>\n            </div>\n            <div className=\"rounded-lg border bg-background/60 p-3\">\n              <div className=\"text-muted-foreground text-xs\">Headline</div>\n              <div className=\"font-medium text-foreground\">\n                {headline.trim() || \"—\"}\n              </div>\n            </div>\n            <div className=\"rounded-lg border bg-background/60 p-3\">\n              <div className=\"text-muted-foreground text-xs\">Bio</div>\n              <div className=\"text-pretty text-foreground leading-relaxed\">\n                {bio.trim() || \"—\"}\n              </div>\n            </div>\n            <div className=\"rounded-lg border bg-background/60 p-3\">\n              <div className=\"text-muted-foreground text-xs\">Organization</div>\n              <div className=\"font-medium text-foreground\">\n                {organization.trim() || \"—\"}\n              </div>\n            </div>\n            <div className=\"rounded-lg border bg-background/60 p-3\">\n              <div className=\"text-muted-foreground text-xs\">Plan</div>\n              <div className=\"font-medium text-foreground\">\n                {planTier === \"starter\" && \"Starter\"}\n                {planTier === \"pro\" && \"Pro\"}\n                {planTier === \"business\" && \"Business\"}\n                {!planTier && \"—\"}\n              </div>\n            </div>\n            {submitted ? (\n              <p className=\"text-center text-emerald-600 text-sm dark:text-emerald-400\">\n                <code className=\"text-foreground\">onComplete</code> ran. Reset\n                the controlled demo to clear this message.\n              </p>\n            ) : (\n              <p className=\"text-center text-muted-foreground text-xs\">\n                Use <strong>Finish</strong> in the bottom bar to run{\" \"}\n                <code className=\"text-foreground\">onComplete</code>.\n              </p>\n            )}\n          </div>\n        ),\n      },\n    ],\n    [\n      accountEmail,\n      accountName,\n      bio,\n      headline,\n      organization,\n      planTier,\n      submitted,\n    ]\n  )\n\n  return (\n    <div className=\"\">\n      <div className=\"mx-auto max-w-sm sm:max-w-6xl\">\n        <div className=\"mx-auto max-w-3xl space-y-12 px-4 sm:space-y-16 sm:px-0\">\n          <section className=\"rounded-xl p-4 pb-6 sm:border sm:bg-muted/50 sm:p-6 sm:pb-8\">\n            <div className=\"mb-8\">\n              <h2 className=\"mb-2 font-medium text-foreground text-lg\">\n                Validated wizard\n              </h2>\n              <p className=\"text-muted-foreground text-sm\">\n                Five steps with footer navigation,{\" \"}\n                <code className=\"text-foreground\">canNavigateToStep</code>, and{\" \"}\n                <code className=\"text-foreground\">onNavigateBlocked</code>{\" \"}\n                focusing the first invalid field. Profile step includes a hook\n                demo button.\n              </p>\n            </div>\n\n            <WizardExpandable\n              badgeText=\"SIGN UP\"\n              canNavigateToStep={canNavigateToStep}\n              onComplete={() => setSubmitted(true)}\n              onNavigateBlocked={onNavigateBlocked}\n              steps={validatedSteps}\n            />\n          </section>\n        </div>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:component"
    }
  ]
}