{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "info-box",
  "type": "registry:component",
  "title": "Info Box",
  "description": "A simple info box component for displaying information, warnings, errors, loading states, and status messages.",
  "dependencies": [
    "iconsax-react",
    "class-variance-authority"
  ],
  "registryDependencies": [
    "@aevr/button",
    "@aevr/loader"
  ],
  "files": [
    {
      "path": "registry/lagos/ui/info-box.tsx",
      "content": "// ./registry/lagos/ui/info-box.tsx\n\"use client\";\n\nimport {\n  TickCircle,\n  CloseCircle,\n  Danger,\n  InfoCircle,\n  Warning2,\n  Information,\n} from \"iconsax-react\";\nimport Link from \"next/link\";\nimport React, { FC, ReactNode } from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/registry/lagos/ui/button\";\nimport Loader from \"@/registry/lagos/ui/loader\";\n\n// Types for InfoBox\nexport type InfoBoxType =\n  | \"warning\"\n  | \"error\"\n  | \"success\"\n  | \"info\"\n  | \"loading\"\n  | \"default\";\n\nexport type InfoBoxSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\";\n\ninterface ActionObject {\n  name: string;\n  path?: string;\n  onClick?: () => void;\n  disabled?: boolean;\n  type?: \"default\" | \"primary\" | \"secondary\" | \"danger\" | \"ghost\" | \"tertiary\";\n  icon?: ReactNode;\n  iconStart?: boolean;\n  custom?: boolean;\n}\n\n// CVA variants for the main container\nconst infoBoxVariants = cva(\n  \"relative flex grow flex-wrap items-start border transition-colors duration-200\",\n  {\n    variants: {\n      type: {\n        default: \"\",\n        warning: \"\",\n        error: \"\",\n        success: \"\",\n        info: \"\",\n        loading: \"\",\n      },\n      size: {\n        xs: \"gap-2 rounded-xl p-2\",\n        sm: \"gap-3 rounded-2xl p-3\",\n        md: \"gap-4 rounded-3xl p-5 max-md:flex-col max-md:gap-2 max-md:p-3\",\n        lg: \"gap-5 rounded-3xl p-6\",\n        xl: \"gap-6 rounded-3xl p-8\",\n        \"2xl\": \"gap-8 rounded-3xl p-10\",\n      },\n      colorScheme: {\n        default:\n          \"border-gray-200 bg-gray-50 text-gray-900 dark:border-gray-700 dark:bg-gray-950 dark:text-gray-100\",\n        full: \"\",\n      },\n    },\n    compoundVariants: [\n      // Full color scheme variants\n      {\n        type: \"warning\",\n        colorScheme: \"full\",\n        className:\n          \"bg-yellow-50 dark:bg-yellow-950 border-yellow-200 dark:border-yellow-800 text-yellow-900 dark:text-yellow-100\",\n      },\n      {\n        type: \"error\",\n        colorScheme: \"full\",\n        className:\n          \"bg-red-50 dark:bg-red-950 border-red-200 dark:border-red-800 text-red-900 dark:text-red-100\",\n      },\n      {\n        type: \"success\",\n        colorScheme: \"full\",\n        className:\n          \"bg-green-50 dark:bg-green-950 border-green-200 dark:border-green-800 text-green-900 dark:text-green-100\",\n      },\n      {\n        type: \"info\",\n        colorScheme: \"full\",\n        className:\n          \"bg-blue-50 dark:bg-blue-950 border-blue-200 dark:border-blue-800 text-blue-900 dark:text-blue-100\",\n      },\n      {\n        type: \"loading\",\n        colorScheme: \"full\",\n        className:\n          \"bg-gray-50 dark:bg-gray-950 border-gray-200 dark:border-gray-800 text-gray-900 dark:text-gray-100\",\n      },\n      {\n        type: \"default\",\n        colorScheme: \"full\",\n        className:\n          \"bg-gray-50 dark:bg-gray-950 border-gray-200 dark:border-gray-800 text-gray-900 dark:text-gray-100\",\n      },\n    ],\n    defaultVariants: {\n      type: \"default\",\n      size: \"md\",\n      colorScheme: \"full\",\n    },\n  }\n);\n\n// CVA variants for the icon container\nconst iconContainerVariants = cva(\"relative flex items-start justify-center\", {\n  variants: {\n    type: {\n      default: \"bg-gray-100 dark:bg-gray-800\",\n      warning: \"bg-yellow-100 dark:bg-yellow-900/20\",\n      error: \"bg-red-100 dark:bg-red-900/20\",\n      success: \"bg-green-100 dark:bg-green-900/20\",\n      info: \"bg-blue-100 dark:bg-blue-900/20\",\n      loading: \"bg-gray-100 dark:bg-gray-800\",\n    },\n    size: {\n      xs: \"rounded-lg p-2\",\n      sm: \"rounded-xl p-2\",\n      md: \"rounded-2xl p-3\",\n      lg: \"rounded-2xl p-4\",\n      xl: \"rounded-3xl p-5\",\n      \"2xl\": \"rounded-3xl p-6\",\n    },\n  },\n  defaultVariants: {\n    type: \"default\",\n    size: \"md\",\n  },\n});\n\n// CVA variants for icons\nconst iconVariants = cva(\"icon\", {\n  variants: {\n    type: {\n      default: \"text-gray-500\",\n      warning: \"text-yellow-500\",\n      error: \"text-red-500\",\n      success: \"text-green-500\",\n      info: \"text-blue-500\",\n      loading: \"text-gray-500\",\n    },\n    size: {\n      xs: \"w-3 h-3\",\n      sm: \"w-4 h-4\",\n      md: \"w-5 h-5\",\n      lg: \"w-6 h-6\",\n      xl: \"w-7 h-7\",\n      \"2xl\": \"w-8 h-8\",\n    },\n  },\n  defaultVariants: {\n    type: \"default\",\n    size: \"md\",\n  },\n});\n\n// CVA variants for title\nconst titleVariants = cva(\"font-medium\", {\n  variants: {\n    size: {\n      xs: \"text-sm\",\n      sm: \"text-base\",\n      md: \"text-lg font-semibold max-md:text-base\",\n      lg: \"text-xl font-semibold\",\n      xl: \"text-2xl font-semibold\",\n      \"2xl\": \"text-3xl font-bold\",\n    },\n  },\n  defaultVariants: {\n    size: \"md\",\n  },\n});\n\n// CVA variants for description\nconst descriptionVariants = cva(\"opacity-80\", {\n  variants: {\n    size: {\n      xs: \"text-xs\",\n      sm: \"text-sm\",\n      md: \"text-base max-md:text-sm\",\n      lg: \"text-lg\",\n      xl: \"text-xl\",\n      \"2xl\": \"text-2xl\",\n    },\n  },\n  defaultVariants: {\n    size: \"md\",\n  },\n});\n\n// CVA variants for actions container\nconst actionsVariants = cva(\"flex flex-wrap\", {\n  variants: {\n    size: {\n      xs: \"mt-1 gap-1\",\n      sm: \"mt-1.5 gap-1.5\",\n      md: \"mt-2 gap-2\",\n      lg: \"mt-3 gap-2.5\",\n      xl: \"mt-4 gap-3\",\n      \"2xl\": \"mt-5 gap-4\",\n    },\n  },\n  defaultVariants: {\n    size: \"md\",\n  },\n});\n\n// CVA variants for close button\nconst closeButtonVariants = cva(\"absolute\", {\n  variants: {\n    size: {\n      xs: \"right-1 top-1\",\n      sm: \"right-2 top-2\",\n      md: \"right-3 top-3\",\n      lg: \"right-4 top-4\",\n      xl: \"right-5 top-5\",\n      \"2xl\": \"right-6 top-6\",\n    },\n  },\n  defaultVariants: {\n    size: \"md\",\n  },\n});\n\ninterface InfoBoxProps\n  extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\">,\n    VariantProps<typeof infoBoxVariants> {\n  loading?: boolean;\n  icon?: ReactNode;\n  title?: string | ReactNode;\n  description?: string | ReactNode;\n  actions?: Array<ActionObject | ReactNode>;\n  children?: ReactNode;\n  onClose?: () => void;\n}\n\n// Safe type guard function\nconst isActionObject = (action: unknown): action is ActionObject => {\n  return (\n    typeof action === \"object\" &&\n    action !== null &&\n    !React.isValidElement(action) &&\n    \"name\" in (action as never)\n  );\n};\n\nconst InfoBox: FC<InfoBoxProps> = ({\n  loading,\n  icon,\n  title,\n  description,\n  actions,\n  children,\n  type = \"default\",\n  size = \"md\",\n  colorScheme = \"default\",\n  className,\n  onClose,\n  ...props\n}) => {\n  // Map type to appropriate icon\n  const getIconByType = () => {\n    const iconProps = {\n      className: iconVariants({ type, size }),\n      color: \"currentColor\" as const,\n      variant: \"Bulk\" as const,\n    };\n\n    if (loading) {\n      return <Loader loading className={iconVariants({ size })} />;\n    }\n\n    switch (type) {\n      case \"warning\":\n        return <Warning2 {...iconProps} />;\n      case \"error\":\n        return <Danger {...iconProps} />;\n      case \"success\":\n        return <TickCircle {...iconProps} />;\n      case \"info\":\n        return <InfoCircle {...iconProps} />;\n      case \"loading\":\n        return <Loader loading={true} className={iconVariants({ size })} />;\n      default:\n        return <Information {...iconProps} />;\n    }\n  };\n\n  const getActionVariant = (actionType: string) => {\n    switch (actionType) {\n      case \"default\":\n        return \"primary\";\n      case \"primary\":\n        return \"primary\";\n      case \"secondary\":\n        return \"secondary\";\n      case \"tertiary\":\n        return \"tertiary\";\n      case \"ghost\":\n        return \"ghost\";\n      case \"danger\":\n        return \"danger\";\n      default:\n        return \"primary\";\n    }\n  };\n\n  const getActionSize = () => {\n    switch (size) {\n      case \"xs\":\n      case \"sm\":\n        return \"sm\";\n      case \"lg\":\n      case \"xl\":\n      case \"2xl\":\n        return \"lg\";\n      default:\n        return \"md\";\n    }\n  };\n\n  const renderAction = (action: ActionObject, index: number) => {\n    const variant = getActionVariant(action.type || \"default\");\n    const buttonSize = getActionSize();\n\n    const content = (\n      <>\n        {action.icon && action.iconStart && (\n          <span className=\"icon\">{action.icon}</span>\n        )}\n        <span>{action.name}</span>\n        {action.icon && !action.iconStart && (\n          <span className=\"icon\">{action.icon}</span>\n        )}\n      </>\n    );\n\n    // If path exists, render Link with Button\n    if (action.path) {\n      return (\n        <Button key={index} asChild variant={variant} size={buttonSize}>\n          <Link href={action.path}>{content}</Link>\n        </Button>\n      );\n    }\n\n    // Otherwise render Button with onClick\n    return (\n      <Button\n        key={index}\n        variant={variant}\n        size={buttonSize}\n        onClick={action.onClick}\n        disabled={action.disabled}\n      >\n        {content}\n      </Button>\n    );\n  };\n\n  const renderActionItem = (\n    action: ActionObject | ReactNode,\n    index: number\n  ) => {\n    if (isActionObject(action)) {\n      return renderAction(action, index);\n    } else {\n      return <React.Fragment key={index}>{action}</React.Fragment>;\n    }\n  };\n\n  const displayIcon = icon || getIconByType();\n\n  return (\n    <div\n      className={cn(infoBoxVariants({ type, size, colorScheme }), className)}\n      {...props}\n    >\n      {displayIcon && (\n        <div className={iconContainerVariants({ type, size })}>\n          {displayIcon}\n        </div>\n      )}\n\n      <div className=\"flex-1\">\n        {title && <h3 className={titleVariants({ size })}>{title}</h3>}\n        {description && (\n          <div className={descriptionVariants({ size })}>{description}</div>\n        )}\n\n        {actions && actions.length > 0 && (\n          <div className={actionsVariants({ size })}>\n            {actions.map((action, index) => renderActionItem(action, index))}\n          </div>\n        )}\n\n        {children}\n      </div>\n\n      {onClose && (\n        <Button\n          onClick={onClose}\n          variant=\"ghost\"\n          size={getActionSize()}\n          className={closeButtonVariants({ size })}\n          aria-label=\"Close\"\n        >\n          <CloseCircle className=\"icon\" color=\"currentColor\" variant=\"Bulk\" />\n        </Button>\n      )}\n    </div>\n  );\n};\n\nexport { InfoBox, infoBoxVariants };\nexport type { InfoBoxProps };\n",
      "type": "registry:component",
      "target": "components/ui/aevr/info-box.tsx"
    }
  ]
}