{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "confirmation",
  "title": "Confirmation",
  "description": "An agent asking permission, with press-and-hold for risky actions.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils",
    "https://ui.cuelark.com/r/theme.json",
    "https://ui.cuelark.com/r/button.json",
    "https://ui.cuelark.com/r/hold-to-confirm.json",
    "https://ui.cuelark.com/r/motion.json"
  ],
  "files": [
    {
      "path": "src/registry/cuelark/ui/confirmation.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { CheckIcon, ShieldAlertIcon, ShieldQuestionIcon, XIcon } from \"lucide-react\";\n\nimport { enterOnce, pop } from \"@/lib/motion\";\nimport { Button } from \"@/registry/cuelark/ui/button\";\nimport { HoldToConfirm } from \"@/registry/cuelark/ui/hold-to-confirm\";\nimport { cn } from \"@/lib/utils\";\n\ntype ConfirmationProps = Omit<React.ComponentProps<\"div\">, \"title\"> & {\n  title: React.ReactNode;\n  description?: React.ReactNode;\n  /** The exact command or action, shown verbatim. */\n  command?: string;\n  /** High-risk actions must be held to approve, so they cannot be clicked through by reflex. */\n  risk?: \"low\" | \"high\";\n  onApprove?: () => void;\n  onDeny?: () => void;\n  /** Start as a receipt, e.g. when rendering a past turn from history. */\n  defaultDecision?: \"approved\" | \"denied\";\n};\n\n/**\n * An agent asking permission before it acts (running a command, sending an email, spending money). The exact\n * action is shown verbatim; risky ones require press-and-hold; the decision then collapses to a one-line receipt.\n */\nfunction Confirmation({ title, description, command, risk = \"low\", onApprove, onDeny, defaultDecision, className, ...props }: ConfirmationProps) {\n  const [decision, setDecision] = React.useState<\"approved\" | \"denied\" | null>(defaultDecision ?? null);\n  const enter = React.useCallback((node: HTMLDivElement | null) => enterOnce(node, (s) => ({ opacity: 0, y: 8 * s, scale: 0.98 }), { duration: 0.35 }), []);\n\n  if (decision) {\n    return (\n      <div ref={(n) => pop(n?.firstElementChild ?? null)} data-slot=\"confirmation\" data-decision={decision} className={cn(\"flex items-center gap-2 text-sm text-muted-foreground\", className)}>\n        <span className={cn(\"grid size-4 place-items-center rounded-full\", decision === \"approved\" ? \"bg-signal text-signal-foreground\" : \"bg-muted\")}>\n          {decision === \"approved\" ? <CheckIcon className=\"size-2.5\" strokeWidth={3.5} /> : <XIcon className=\"size-2.5\" strokeWidth={3} />}\n        </span>\n        <span className=\"text-foreground\">{decision === \"approved\" ? \"Approved\" : \"Denied\"}</span>\n        {command && <code className=\"truncate font-mono text-xs\">{command}</code>}\n      </div>\n    );\n  }\n\n  const Icon = risk === \"high\" ? ShieldAlertIcon : ShieldQuestionIcon;\n  return (\n    <div\n      ref={enter}\n      role=\"group\"\n      aria-label=\"Permission request\"\n      data-slot=\"confirmation\"\n      data-risk={risk}\n      className={cn(\"grid gap-3 rounded-2xl border border-border bg-card p-4 shadow-raised data-[risk=high]:border-destructive/30\", className)}\n      {...props}\n    >\n      <div className=\"flex gap-3\">\n        <span className={cn(\"grid size-8 shrink-0 place-items-center rounded-lg\", risk === \"high\" ? \"bg-destructive/10 text-destructive\" : \"bg-muted\")}>\n          <Icon className=\"size-4\" />\n        </span>\n        <div className=\"grid gap-0.5\">\n          <p className=\"text-sm font-medium\">{title}</p>\n          {description && <p className=\"text-sm text-muted-foreground\">{description}</p>}\n        </div>\n      </div>\n      {command && <pre className=\"overflow-x-auto rounded-lg bg-muted/60 px-3 py-2 font-mono text-xs ring-1 ring-border\">{command}</pre>}\n      <div className=\"flex justify-end gap-2\">\n        <Button\n          variant=\"ghost\"\n          size=\"sm\"\n          onClick={() => {\n            setDecision(\"denied\");\n            onDeny?.();\n          }}\n        >\n          Deny\n        </Button>\n        {risk === \"high\" ? (\n          <HoldToConfirm\n            className=\"h-ctl-sm\"\n            duration={1000}\n            onConfirm={() => {\n              setDecision(\"approved\");\n              onApprove?.();\n            }}\n          >\n            Hold to allow\n          </HoldToConfirm>\n        ) : (\n          <Button\n            size=\"sm\"\n            onClick={() => {\n              setDecision(\"approved\");\n              onApprove?.();\n            }}\n          >\n            Allow\n          </Button>\n        )}\n      </div>\n    </div>\n  );\n}\n\nexport { Confirmation };\nexport type { ConfirmationProps };\n",
      "type": "registry:ui"
    }
  ],
  "docs": "Docs and examples: https://ui.cuelark.com/components/confirmation",
  "categories": [
    "agents"
  ],
  "type": "registry:ui"
}