{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "admonition",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "components/ui/admonition.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { useEffect, useState } from \"react\"\nimport {\n  ChevronDown,\n  CircleAlert,\n  CircleCheck,\n  CircleX,\n  Info,\n  Lightbulb,\n  ShieldAlert,\n  TriangleAlert,\n  X,\n} from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\n// --- Types ---\nexport interface AdmonitionAction {\n  label: string\n  onClick: () => void\n  variant?: \"primary\" | \"secondary\"\n}\n\n// --- Configuration ---\nconst admonitionConfig = {\n  note: {\n    bgColor: \"bg-blue-50 dark:bg-blue-950/30\",\n    borderColor: \"border-blue-200 dark:border-blue-800\",\n    textColor: \"text-blue-900 dark:text-blue-200\",\n    iconColor: \"text-blue-600 dark:text-blue-400\",\n    icon: Info,\n    selectionColor:\n      \"selection:bg-blue-200 selection:text-blue-900 dark:selection:bg-blue-800 dark:selection:text-blue-100\",\n    primaryButton:\n      \"bg-blue-600 text-white hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-400\",\n    secondaryButton:\n      \"bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/50 dark:text-blue-300 dark:hover:bg-blue-900\",\n  },\n  tip: {\n    bgColor: \"bg-emerald-50 dark:bg-emerald-950/30\",\n    borderColor: \"border-emerald-200 dark:border-emerald-800\",\n    textColor: \"text-emerald-900 dark:text-emerald-200\",\n    iconColor: \"text-emerald-600 dark:text-emerald-400\",\n    icon: Lightbulb,\n    selectionColor:\n      \"selection:bg-emerald-200 selection:text-emerald-900 dark:selection:bg-emerald-800 dark:selection:text-emerald-100\",\n    primaryButton:\n      \"bg-emerald-600 text-white hover:bg-emerald-700 dark:bg-emerald-500 dark:hover:bg-emerald-400\",\n    secondaryButton:\n      \"bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/50 dark:text-emerald-300 dark:hover:bg-emerald-900\",\n  },\n  info: {\n    bgColor: \"bg-slate-50 dark:bg-slate-950/30\",\n    borderColor: \"border-slate-200 dark:border-slate-800\",\n    textColor: \"text-slate-700 dark:text-slate-300\",\n    iconColor: \"text-slate-500 dark:text-slate-400\",\n    icon: CircleAlert,\n    selectionColor:\n      \"selection:bg-slate-200 selection:text-slate-900 dark:selection:bg-slate-800 dark:selection:text-slate-100\",\n    primaryButton:\n      \"bg-slate-900 text-white hover:bg-slate-800 dark:bg-slate-100 dark:text-slate-900 dark:hover:bg-slate-200\",\n    secondaryButton:\n      \"bg-slate-100 text-slate-700 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-700\",\n  },\n  warning: {\n    bgColor: \"bg-yellow-50 dark:bg-yellow-950/30\",\n    borderColor: \"border-yellow-300 dark:border-yellow-700\",\n    textColor: \"text-yellow-900 dark:text-yellow-200\",\n    iconColor: \"text-yellow-600 dark:text-yellow-400\",\n    icon: TriangleAlert,\n    selectionColor:\n      \"selection:bg-yellow-200 selection:text-yellow-900 dark:selection:bg-yellow-800 dark:selection:text-yellow-100\",\n    primaryButton:\n      \"bg-yellow-600 text-white hover:bg-yellow-700 dark:bg-yellow-500 dark:hover:bg-yellow-400\",\n    secondaryButton:\n      \"bg-yellow-100 text-yellow-700 hover:bg-yellow-200 dark:bg-yellow-900/50 dark:text-yellow-300 dark:hover:bg-yellow-900\",\n  },\n  danger: {\n    bgColor: \"bg-red-50 dark:bg-red-950/30\",\n    borderColor: \"border-red-200 dark:border-red-800\",\n    textColor: \"text-red-900 dark:text-red-200\",\n    iconColor: \"text-red-600 dark:text-red-400\",\n    icon: CircleX,\n    selectionColor:\n      \"selection:bg-red-200 selection:text-red-900 dark:selection:bg-red-800 dark:selection:text-red-100\",\n    primaryButton:\n      \"bg-red-600 text-white hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-400\",\n    secondaryButton:\n      \"bg-red-100 text-red-700 hover:bg-red-200 dark:bg-red-900/50 dark:text-red-300 dark:hover:bg-red-900\",\n  },\n  success: {\n    bgColor: \"bg-green-50 dark:bg-green-950/30\",\n    borderColor: \"border-green-200 dark:border-green-800\",\n    textColor: \"text-green-900 dark:text-green-200\",\n    iconColor: \"text-green-600 dark:text-green-400\",\n    icon: CircleCheck,\n    selectionColor:\n      \"selection:bg-green-200 selection:text-green-900 dark:selection:bg-green-800 dark:selection:text-green-100\",\n    primaryButton:\n      \"bg-green-600 text-white hover:bg-green-700 dark:bg-green-500 dark:hover:bg-green-400\",\n    secondaryButton:\n      \"bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/50 dark:text-green-300 dark:hover:bg-green-900\",\n  },\n  caution: {\n    bgColor: \"bg-orange-50 dark:bg-orange-950/30\",\n    borderColor: \"border-orange-200 dark:border-orange-700\",\n    textColor: \"text-orange-900 dark:text-orange-200\",\n    iconColor: \"text-orange-600 dark:text-orange-400\",\n    icon: ShieldAlert,\n    selectionColor:\n      \"selection:bg-orange-200 selection:text-orange-900 dark:selection:bg-orange-800 dark:selection:text-orange-100\",\n    primaryButton:\n      \"bg-orange-600 text-white hover:bg-orange-700 dark:bg-orange-500 dark:hover:bg-orange-400\",\n    secondaryButton:\n      \"bg-orange-100 text-orange-700 hover:bg-orange-200 dark:bg-orange-900/50 dark:text-orange-300 dark:hover:bg-orange-900\",\n  },\n}\n\nconst sizeVariants = {\n  sm: {\n    container: \"p-3\",\n    title: \"text-sm\",\n    content: \"text-sm mt-1\",\n    icon: \"h-4 w-4\",\n    button: \"text-xs px-2.5 py-1.5\",\n  },\n  small: {\n    container: \"p-3\",\n    title: \"text-sm\",\n    content: \"text-sm mt-1\",\n    icon: \"h-4 w-4\",\n    button: \"text-xs px-2.5 py-1.5\",\n  },\n  default: {\n    container: \"p-4\",\n    title: \"text-base\",\n    content: \"text-base mt-2\",\n    icon: \"h-5 w-5\",\n    button: \"text-sm px-3 py-2\",\n  },\n  lg: {\n    container: \"p-5\",\n    title: \"text-lg\",\n    content: \"text-lg mt-3\",\n    icon: \"h-6 w-6\",\n    button: \"text-base px-4 py-2.5\",\n  },\n  large: {\n    container: \"p-5\",\n    title: \"text-lg\",\n    content: \"text-lg mt-3\",\n    icon: \"h-6 w-6\",\n    button: \"text-base px-4 py-2.5\",\n  },\n}\n\ninterface AdmonitionProps {\n  type?: keyof typeof admonitionConfig\n  title?: string\n  children?: React.ReactNode\n  icon?: React.ComponentType<{ className?: string }>\n  dismissible?: boolean\n  dismissKey?: string\n  expandable?: boolean\n  defaultCollapsed?: boolean\n  actions?: AdmonitionAction[]\n  size?: keyof typeof sizeVariants\n  className?: string\n}\n\nexport function Admonition({\n  type = \"note\",\n  title,\n  children,\n  icon: CustomIcon,\n  dismissible = false,\n  dismissKey,\n  expandable = false,\n  defaultCollapsed = false,\n  actions,\n  size = \"default\",\n  className,\n}: AdmonitionProps) {\n  const config = admonitionConfig[type]\n  const sizeConfig = sizeVariants[size]\n  const Icon = CustomIcon || config.icon\n\n  // State\n  const [isDismissed, setIsDismissed] = useState(false)\n  // If expandable, default to collapsed state, otherwise always expanded.\n  const [isCollapsed, setIsCollapsed] = useState(\n    expandable ? defaultCollapsed : false\n  )\n\n  useEffect(() => {\n    if (dismissible && dismissKey) {\n      if (\n        localStorage.getItem(`admonition-dismissed-${dismissKey}`) === \"true\"\n      ) {\n        setIsDismissed(true)\n      }\n    }\n  }, [dismissible, dismissKey])\n\n  if (isDismissed) return null\n\n  const hasControls = expandable || dismissible\n\n  const handleToggleExpand = () => {\n    if (expandable) {\n      setIsCollapsed(!isCollapsed)\n    }\n  }\n\n  return (\n    <div\n      className={cn(\n        \"rounded-xl border\",\n        sizeConfig.container,\n        config.bgColor,\n        config.borderColor,\n        config.selectionColor,\n        expandable && \"cursor-pointer\",\n        className\n      )}\n      onClick={expandable ? handleToggleExpand : undefined}\n    >\n      <div className=\"flex items-start gap-3\">\n        {/* Icon */}\n        <div\n          className={cn(\n            config.iconColor,\n            \"flex h-[1lh] shrink-0 items-center leading-[1.5]\"\n          )}\n        >\n          <Icon className=\"size-[1.25em]\" />\n        </div>\n\n        {/* Content Container */}\n        <div className=\"min-w-0 flex-1 leading-[1.5]\">\n          {/* Header (Title + Controls) */}\n          <div className=\"flex items-start justify-between gap-2\">\n            {title && (\n              <div\n                className={cn(\n                  config.textColor,\n                  sizeConfig.title,\n                  \"font-normal [text-box-trim:trim-start]\"\n                )}\n              >\n                {title}\n              </div>\n            )}\n\n            {/* Controls (Top Right) */}\n            {hasControls && (\n              <div\n                className={cn(\n                  \"flex shrink-0 items-center gap-1\",\n                  // Adjust control alignment based on presence of title\n                  title ? \"-mt-0.5\" : \"\"\n                )}\n              >\n                {expandable && (\n                  <button\n                    onClick={(e) => {\n                      e.stopPropagation()\n                      handleToggleExpand()\n                    }}\n                    aria-label={isCollapsed ? \"Expand\" : \"Collapse\"}\n                    className={cn(\n                      config.iconColor,\n                      \"rounded p-1 transition-transform hover:bg-black/5 dark:hover:bg-white/5\",\n                      isCollapsed && \"rotate-180\"\n                    )}\n                  >\n                    <ChevronDown className={sizeConfig.icon} />\n                  </button>\n                )}\n                {dismissible && (\n                  <button\n                    onClick={(e) => {\n                      e.stopPropagation()\n                      setIsDismissed(true)\n                      dismissKey &&\n                        localStorage.setItem(\n                          `admonition-dismissed-${dismissKey}`,\n                          \"true\"\n                        )\n                    }}\n                    aria-label=\"Dismiss\"\n                    className={cn(\n                      config.iconColor,\n                      \"rounded p-1 hover:bg-black/5 dark:hover:bg-white/5\"\n                    )}\n                  >\n                    <X className={sizeConfig.icon} />\n                  </button>\n                )}\n              </div>\n            )}\n          </div>\n\n          {/* Body Content */}\n          {children && (\n            <div\n              className={cn(\n                config.textColor,\n                sizeConfig.content,\n                // Only apply margin-top if there's a title\n                !title && \"!mt-0\",\n                \"[text-box-trim:trim-start] [&_*]:!text-inherit\",\n                // CSS Line Clamp for collapsing behavior\n                expandable && isCollapsed ? \"line-clamp-2\" : \"\"\n              )}\n            >\n              {children}\n            </div>\n          )}\n\n          {/* Actions Footer */}\n          {actions && actions.length > 0 && !isCollapsed && (\n            <div\n              className={cn(\n                \"flex flex-wrap items-center gap-2\",\n                sizeConfig.content\n              )}\n            >\n              {actions.map((action, index) => (\n                <button\n                  key={index}\n                  onClick={(e) => {\n                    e.stopPropagation()\n                    action.onClick()\n                  }}\n                  className={cn(\n                    \"focus-visible:ring-ring inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50\",\n                    sizeConfig.button,\n                    action.variant === \"secondary\"\n                      ? config.secondaryButton\n                      : config.primaryButton\n                  )}\n                >\n                  {action.label}\n                </button>\n              ))}\n            </div>\n          )}\n        </div>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}