{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "agent-plan",
  "title": "Agent Plan",
  "description": "An editable plan checklist the agent proposes before running.",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "components/spectrumui/blocks/ai-assistants/agent-plan.tsx",
      "content": "'use client';\n\nimport { useState } from 'react';\nimport { ArrowRight, Check, GripVertical } from 'lucide-react';\nimport { cn } from '@/lib/utils';\n\nexport interface PlanStep {\n  id: string;\n  title: string;\n  detail?: string;\n}\n\nexport type AgentPlanVariant = 'Default' | 'Compact';\n\nexport interface AgentPlanProps {\n  title?: string;\n  steps: PlanStep[];\n  runLabel?: string;\n  onRun?: (enabledStepIds: string[]) => void;\n  variant?: AgentPlanVariant;\n  className?: string;\n}\n\nexport function AgentPlan({\n  title = 'Proposed plan',\n  steps,\n  runLabel = 'Run plan',\n  onRun,\n  variant = 'Default',\n  className,\n}: AgentPlanProps) {\n  const [disabled, setDisabled] = useState<Set<string>>(new Set());\n  const compact = variant === 'Compact';\n  const enabledCount = steps.length - disabled.size;\n\n  function toggle(id: string) {\n    setDisabled((previous) => {\n      const next = new Set(previous);\n      if (next.has(id)) next.delete(id);\n      else next.add(id);\n      return next;\n    });\n  }\n\n  return (\n    <div\n      className={cn(\n        'w-full max-w-[440px] rounded-2xl border border-black/[0.08] bg-white shadow-xs dark:border-white/[0.09] dark:bg-[#0B0B0D]',\n        className,\n      )}\n    >\n      <div className=\"flex items-center justify-between gap-3 border-b border-black/[0.06] px-4 py-2.5 dark:border-white/[0.07]\">\n        <h3 className=\"text-[13px] font-semibold tracking-[-0.1px] text-neutral-900 dark:text-neutral-50\">\n          {title}\n        </h3>\n        <span className=\"font-mono text-[10.5px] tabular-nums text-neutral-400 dark:text-neutral-600\">\n          {enabledCount}/{steps.length} steps\n        </span>\n      </div>\n\n      <ol className={cn('px-2 py-1.5', compact ? 'space-y-0' : 'space-y-0.5')}>\n        {steps.map((step, index) => {\n          const off = disabled.has(step.id);\n          return (\n            <li key={step.id}>\n              <button\n                type=\"button\"\n                role=\"checkbox\"\n                aria-checked={!off}\n                onClick={() => toggle(step.id)}\n                className={cn(\n                  'group flex w-full items-start gap-2.5 rounded-lg px-2 text-left transition-[background-color,opacity] duration-150',\n                  compact ? 'py-1.5' : 'py-2',\n                  'hover:bg-black/[0.03] focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-neutral-400 dark:hover:bg-white/[0.04]',\n                  off && 'opacity-45',\n                )}\n              >\n                <GripVertical className=\"mt-0.5 size-3 shrink-0 text-neutral-200 opacity-0 transition-opacity duration-150 [@media(hover:hover)]:group-hover:opacity-100 dark:text-neutral-700\" />\n                <span\n                  aria-hidden\n                  className={cn(\n                    'mt-px grid size-4 shrink-0 place-items-center rounded-[5px] border transition-colors duration-150',\n                    off\n                      ? 'border-neutral-300 dark:border-neutral-600'\n                      : 'border-neutral-900 bg-neutral-900 text-white dark:border-neutral-100 dark:bg-neutral-100 dark:text-neutral-900',\n                  )}\n                >\n                  <Check\n                    className={cn(\n                      'size-2.5 transition-transform duration-200 ease-[cubic-bezier(0.23,1,0.32,1)]',\n                      off ? 'scale-0' : 'scale-100',\n                    )}\n                    strokeWidth={3}\n                  />\n                </span>\n                <span className=\"min-w-0\">\n                  <span\n                    className={cn(\n                      'block font-medium text-neutral-800 dark:text-neutral-200',\n                      compact ? 'text-[12.5px]' : 'text-[13px]',\n                      off && 'line-through decoration-neutral-300 dark:decoration-neutral-600',\n                    )}\n                  >\n                    <span className=\"mr-1.5 font-mono text-[10.5px] font-normal tabular-nums text-neutral-400 dark:text-neutral-600\">\n                      {String(index + 1).padStart(2, '0')}\n                    </span>\n                    {step.title}\n                  </span>\n                  {!compact && step.detail && (\n                    <span className=\"mt-0.5 block text-[11.5px] leading-[1.5] text-neutral-500 dark:text-neutral-500\">\n                      {step.detail}\n                    </span>\n                  )}\n                </span>\n              </button>\n            </li>\n          );\n        })}\n      </ol>\n\n      <div className=\"border-t border-black/[0.06] px-3 py-2.5 dark:border-white/[0.07]\">\n        <button\n          type=\"button\"\n          disabled={enabledCount === 0}\n          onClick={() => onRun?.(steps.filter((step) => !disabled.has(step.id)).map((step) => step.id))}\n          className=\"group flex w-full items-center justify-center gap-1.5 rounded-lg bg-neutral-900 py-2 text-[12.5px] font-medium text-white transition-[transform,opacity] duration-[160ms] ease-[cubic-bezier(0.23,1,0.32,1)] active:scale-[0.98] disabled:opacity-30 dark:bg-neutral-100 dark:text-neutral-900\"\n        >\n          {runLabel}\n          <ArrowRight className=\"size-3.5 transition-transform duration-[180ms] ease-[cubic-bezier(0.23,1,0.32,1)] group-hover:translate-x-0.5\" />\n        </button>\n      </div>\n    </div>\n  );\n}\n\nexport default AgentPlan;\n",
      "type": "registry:block",
      "target": "components/spectrumui/blocks/ai-assistants/agent-plan.tsx"
    }
  ],
  "type": "registry:block"
}
