{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "async-provisioning",
  "type": "registry:component",
  "title": "Async Provisioning",
  "description": "A deploy flow with an async guarded transition, pending UI, a failed first attempt, and a retry path.",
  "author": "Stepperize",
  "dependencies": [
    "@stepperize/react",
    "lucide-react"
  ],
  "registryDependencies": [
    "alert",
    "button",
    "label",
    "select"
  ],
  "categories": [
    "async"
  ],
  "meta": {
    "capabilities": [
      "async"
    ],
    "level": "advanced",
    "tags": [
      "async",
      "provisioning",
      "deploy",
      "retry",
      "pending"
    ]
  },
  "files": [
    {
      "path": "components/stepperize/async-provisioning.tsx",
      "type": "registry:component",
      "target": "components/stepperize/async-provisioning.tsx",
      "content": "\"use client\";\n\nimport { defineStepper } from \"@stepperize/react\";\nimport { AlertTriangle, Check, Cloud, Loader2, Server } from \"lucide-react\";\nimport { useRef, useState } from \"react\";\nimport { Alert, AlertDescription } from \"@/components/ui/alert\";\nimport { Button } from \"@/components/ui/button\";\nimport { Label } from \"@/components/ui/label\";\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from \"@/components/ui/select\";\n\nconst provisioning = defineStepper([\n\t{ id: \"configure\", title: \"Configure\" },\n\t{ id: \"deploy\", title: \"Deploy\" },\n\t{ id: \"live\", title: \"Live\" },\n] as const);\n\nconst { Stepper } = provisioning;\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Async transition with retry: leaving \"deploy\" runs an async\n * `beforeStepChange` that simulates provisioning. The first attempt fails, the\n * guard returns `false`, and the user stays on the deploy step. `isPending`\n * drives the loading state while the async guard is running.\n */\nexport function AsyncProvisioningBlock() {\n\tconst [error, setError] = useState<string | null>(null);\n\tconst attempts = useRef(0);\n\n\treturn (\n\t\t<Stepper.Root\n\t\t\tlinear\n\t\t\tclassName=\"w-full max-w-sm rounded-xl border bg-background p-6 shadow-sm\"\n\t\t\tbeforeStepChange={async ({ from, direction }) => {\n\t\t\t\tif (from.id !== \"deploy\" || direction !== \"next\") return true;\n\t\t\t\tsetError(null);\n\t\t\t\tawait sleep(1600); // ← the transition is async; isPending is true here\n\t\t\t\tattempts.current += 1;\n\t\t\t\tif (attempts.current === 1) {\n\t\t\t\t\tsetError(\"Region at capacity. Please retry.\");\n\t\t\t\t\treturn false; // ← failure cancels the move; the user stays on \"deploy\"\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}}\n\t\t>\n\t\t\t{({ stepper }) => (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"mb-4 flex items-center gap-2.5\">\n\t\t\t\t\t\t<span className=\"grid size-8 place-items-center rounded-lg bg-primary/10 text-primary\">\n\t\t\t\t\t\t\t<Server className=\"size-4\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<p className=\"text-sm font-semibold\">Provision a database</p>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div className=\"min-h-36\">\n\t\t\t\t\t\t<Stepper.Content step=\"configure\" className=\"space-y-3\">\n\t\t\t\t\t\t\t<div className=\"space-y-1.5\">\n\t\t\t\t\t\t\t\t<Label>Region</Label>\n\t\t\t\t\t\t\t\t<Select defaultValue=\"us-east-1\">\n\t\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full\">\n\t\t\t\t\t\t\t\t\t\t<SelectValue />\n\t\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"us-east-1\">us-east-1</SelectItem>\n\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"eu-west-1\">eu-west-1</SelectItem>\n\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"ap-south-1\">ap-south-1</SelectItem>\n\t\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"space-y-1.5\">\n\t\t\t\t\t\t\t\t<Label>Size</Label>\n\t\t\t\t\t\t\t\t<Select defaultValue=\"small\">\n\t\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-full\">\n\t\t\t\t\t\t\t\t\t\t<SelectValue />\n\t\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"small\">Small · 2 vCPU</SelectItem>\n\t\t\t\t\t\t\t\t\t\t<SelectItem value=\"medium\">Medium · 4 vCPU</SelectItem>\n\t\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<Button className=\"w-full\" onClick={() => stepper.next()}>\n\t\t\t\t\t\t\t\tContinue\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</Stepper.Content>\n\n\t\t\t\t\t\t<Stepper.Content step=\"deploy\" className=\"space-y-3\">\n\t\t\t\t\t\t\t<div className=\"grid place-items-center gap-2 py-2 text-center\">\n\t\t\t\t\t\t\t\t<span className=\"grid size-12 place-items-center rounded-full bg-muted text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t{stepper.isPending ? (\n\t\t\t\t\t\t\t\t\t\t<Loader2 className=\"size-6 animate-spin text-primary\" />\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<Cloud className=\"size-6\" />\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<p className=\"text-sm text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t{stepper.isPending\n\t\t\t\t\t\t\t\t\t\t? \"Provisioning your instance…\"\n\t\t\t\t\t\t\t\t\t\t: \"Ready to deploy to us-east-1.\"}\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{error && !stepper.isPending && (\n\t\t\t\t\t\t\t\t<Alert variant=\"destructive\">\n\t\t\t\t\t\t\t\t\t<AlertTriangle />\n\t\t\t\t\t\t\t\t\t<AlertDescription>{error}</AlertDescription>\n\t\t\t\t\t\t\t\t</Alert>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\tclassName=\"w-full\"\n\t\t\t\t\t\t\t\tdisabled={stepper.isPending}\n\t\t\t\t\t\t\t\tonClick={() => stepper.next()}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{stepper.isPending ? (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<Loader2 className=\"animate-spin\" /> Working…\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t) : error ? (\n\t\t\t\t\t\t\t\t\t\"Retry deploy\"\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\"Deploy now\"\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</Stepper.Content>\n\n\t\t\t\t\t\t<Stepper.Content\n\t\t\t\t\t\t\tstep=\"live\"\n\t\t\t\t\t\t\tclassName=\"grid place-items-center gap-2 py-6 text-center\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span className=\"grid size-12 place-items-center rounded-full bg-chart-2/15 text-chart-2\">\n\t\t\t\t\t\t\t\t<Check className=\"size-6\" />\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<p className=\"text-sm font-medium\">Database is live</p>\n\t\t\t\t\t\t\t<p className=\"font-mono text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\tdb.us-east-1.acme.cloud\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t</Stepper.Content>\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</Stepper.Root>\n\t);\n}\n\nexport default AsyncProvisioningBlock;\n"
    }
  ]
}
