{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "loader",
  "title": "Loader",
  "author": "AlgorizeTech",
  "description": "Ask the user to pick one of 5 loader variants: https://avaraui.com/view/loader. This item holds 5 of them as looks of one component (spinner, orbit, dots, pulse, bar). Skip the question if the user already named one. A loading indicator in six shapes — spinner, orbit, dots, pulse, ring and bar — with an optional caption. Use it for inline and full-panel pending states.",
  "dependencies": [],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "src/components/custom/blocks/LoaderBlock.tsx",
      "content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { getThemeColor } from \"./loader-theme\";\n\n// ==========================================\n// DYNAMIC THEME ENGINE\n// ==========================================\nexport type LoaderColor =\n  | \"indigo\"\n  | \"rose\"\n  | \"emerald\"\n  | \"zinc\"\n  | \"blue\"\n  | \"amber\"\n  | string;\nexport type LoaderVariant =\n  | \"spinner\"\n  | \"dots\"\n  | \"pulse\"\n  | \"ring\"\n  | \"bar\"\n  | \"orbit\";\nexport type LoaderSize = \"sm\" | \"md\" | \"lg\" | \"xl\";\nexport type LoaderDirection = \"single\" | \"dual\";\n\n// ==========================================\n// PROPS & MAIN COMPONENT\n// ==========================================\nexport interface LoaderBlockProps {\n  variant?: LoaderVariant;\n  size?: LoaderSize;\n  color?: LoaderColor;\n  secondaryColor?: LoaderColor;\n  direction?: LoaderDirection;\n  text?: string;\n  /** Vertical padding for top and bottom (default: \"py-5\" / 20px). Accepts Tailwind class (e.g. \"py-2\", \"py-8\") or numeric/pixel value. */\n  py?: string | number;\n  className?: string;\n  style?: React.CSSProperties;\n}\n\nexport function LoaderBlock({\n  variant = \"spinner\",\n  size = \"md\",\n  color = \"primary\",\n  secondaryColor,\n  direction = \"single\",\n  text,\n  py,\n  className,\n  style,\n}: LoaderBlockProps) {\n  const themeColor = getThemeColor(color);\n  const secondaryThemeColor = secondaryColor\n    ? getThemeColor(secondaryColor)\n    : color === \"emerald\"\n    ? \"#6366f1\"\n    : \"#10b981\";\n\n  const pyClass =\n    typeof py === \"string\" && !py.endsWith(\"px\") && !py.endsWith(\"rem\") && !py.endsWith(\"em\")\n      ? py\n      : undefined;\n\n  const pyInlineStyle =\n    typeof py === \"number\"\n      ? { paddingTop: `${py}px`, paddingBottom: `${py}px` }\n      : typeof py === \"string\" && (py.endsWith(\"px\") || py.endsWith(\"rem\") || py.endsWith(\"em\"))\n      ? { paddingTop: py, paddingBottom: py }\n      : undefined;\n\n  const sizeClasses = {\n    sm: \"w-4 h-4\",\n    md: \"w-8 h-8\",\n    lg: \"w-12 h-12\",\n    xl: \"w-16 h-16\",\n  };\n\n  const orbitSizeClasses = {\n    sm: \"w-5 h-5\",\n    md: \"w-10 h-10\",\n    lg: \"w-14 h-14\",\n    xl: \"w-20 h-20\",\n  };\n\n  const barSizeClasses = {\n    sm: \"w-16 h-1\",\n    md: \"w-32 h-1.5\",\n    lg: \"w-48 h-2\",\n    xl: \"w-64 h-3\",\n  };\n\n  const textClasses = {\n    sm: \"text-xs\",\n    md: \"text-sm\",\n    lg: \"text-base\",\n    xl: \"text-lg\",\n  };\n\n  const currentSize =\n    variant === \"bar\"\n      ? barSizeClasses[size]\n      : variant === \"orbit\" || variant === \"ring\"\n      ? orbitSizeClasses[size]\n      : sizeClasses[size];\n\n  return (\n    <div\n      style={{ ...pyInlineStyle, ...style }}\n      className={cn(\n        \"flex flex-col items-center justify-center gap-3 py-5\",\n        pyClass,\n        className,\n      )}\n    >\n      {/* Premium Custom Keyframes */}\n      <style>{`\n        @keyframes wave {\n          0%, 60%, 100% { transform: translateY(0) scale(1); opacity: 0.6; }\n          30% { transform: translateY(-4px) scale(1.2); opacity: 1; }\n        }\n        @keyframes indeterminate {\n          0% { transform: translateX(-100%); }\n          100% { transform: translateX(200%); }\n        }\n        @keyframes spin-slow {\n          0% { transform: rotate(0deg); }\n          100% { transform: rotate(360deg); }\n        }\n        @keyframes spin-reverse {\n          0% { transform: rotate(360deg); }\n          100% { transform: rotate(0deg); }\n        }\n        @keyframes spin-fast {\n          0% { transform: rotate(0deg); }\n          100% { transform: rotate(360deg); }\n        }\n        .animate-wave { animation: wave 1.2s ease-in-out infinite; }\n        .animate-indet { animation: indeterminate 1.5s infinite linear; }\n        .animate-spin-slow { animation: spin-slow 3s linear infinite; }\n        .animate-spin-reverse { animation: spin-reverse 0.85s linear infinite; }\n        .animate-spin-fast { animation: spin-fast 0.85s linear infinite; }\n      `}</style>\n\n      <div\n        className={cn(\n          \"relative flex items-center justify-center\",\n          (variant === \"orbit\" || variant === \"ring\") &&\n            \"aspect-square rounded-full shrink-0\",\n          currentSize,\n        )}\n      >\n        {variant === \"spinner\" && <Spinner color={themeColor} />}\n        {variant === \"dots\" && <Dots color={themeColor} />}\n        {variant === \"pulse\" && <Pulse color={themeColor} />}\n        {(variant === \"orbit\" || variant === \"ring\") && (\n          <OrbitRing\n            color={themeColor}\n            secondaryColor={secondaryThemeColor}\n            direction={direction}\n          />\n        )}\n        {variant === \"bar\" && <Bar color={themeColor} />}\n      </div>\n\n      {text && (\n        <span\n          className={cn(\n            \"font-medium text-muted-foreground animate-pulse\",\n            textClasses[size],\n          )}\n        >\n          {text}\n        </span>\n      )}\n    </div>\n  );\n}\n\n// ==========================================\n// VARIANTS\n// ==========================================\nfunction Spinner({ color }: { color: string }) {\n  return (\n    <svg\n      className=\"animate-spin w-full h-full\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <circle\n        className=\"opacity-25\"\n        cx=\"12\"\n        cy=\"12\"\n        r=\"10\"\n        stroke={color}\n        strokeWidth=\"4\"\n        strokeLinecap=\"round\"\n      />\n      <path\n        className=\"opacity-100\"\n        fill={color}\n        d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n      />\n    </svg>\n  );\n}\n\nfunction Dots({ color }: { color: string }) {\n  return (\n    <div className=\"flex items-center justify-center gap-1.5 w-full h-full\">\n      <div\n        className=\"w-[25%] h-[25%] rounded-full animate-wave\"\n        style={{ backgroundColor: color, animationDelay: \"0s\" }}\n      />\n      <div\n        className=\"w-[25%] h-[25%] rounded-full animate-wave\"\n        style={{ backgroundColor: color, animationDelay: \"0.15s\" }}\n      />\n      <div\n        className=\"w-[25%] h-[25%] rounded-full animate-wave\"\n        style={{ backgroundColor: color, animationDelay: \"0.3s\" }}\n      />\n    </div>\n  );\n}\n\nfunction Pulse({ color }: { color: string }) {\n  return (\n    <div className=\"relative w-full h-full flex items-center justify-center\">\n      <div\n        className=\"absolute w-full h-full rounded-full animate-ping opacity-75\"\n        style={{ backgroundColor: color }}\n      />\n      <div\n        className=\"relative w-[50%] h-[50%] rounded-full\"\n        style={{ backgroundColor: color }}\n      />\n    </div>\n  );\n}\n\nfunction OrbitRing({\n  color,\n  secondaryColor,\n  direction = \"single\",\n}: {\n  color: string;\n  secondaryColor: string;\n  direction?: LoaderDirection;\n}) {\n  const isDual = direction === \"dual\";\n\n  return (\n    <div className=\"relative w-full h-full aspect-square rounded-full flex items-center justify-center shrink-0\">\n      {/* Outer Orbit: Full Faint Track & Rounded Active Arc */}\n      <svg\n        className=\"animate-spin absolute inset-0 w-full h-full aspect-square overflow-visible\"\n        viewBox=\"0 0 48 48\"\n        fill=\"none\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n      >\n        <circle\n          cx=\"24\"\n          cy=\"24\"\n          r=\"21\"\n          stroke={color}\n          strokeWidth=\"3.2\"\n          className=\"opacity-25\"\n        />\n        <circle\n          cx=\"24\"\n          cy=\"24\"\n          r=\"21\"\n          stroke={color}\n          strokeWidth=\"3.2\"\n          strokeDasharray=\"34 98\"\n          strokeLinecap=\"round\"\n        />\n      </svg>\n\n      {/* Inner Orbit: Full Faint Track & Rounded Arc (Single: same direction, Dual: counter-spin) */}\n      <svg\n        className={cn(\n          \"absolute inset-0 w-full h-full aspect-square overflow-visible\",\n          isDual ? \"animate-spin-reverse\" : \"animate-spin-fast\",\n        )}\n        viewBox=\"0 0 48 48\"\n        fill=\"none\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n      >\n        <circle\n          cx=\"24\"\n          cy=\"24\"\n          r=\"13\"\n          stroke={secondaryColor}\n          strokeWidth=\"2.6\"\n          className=\"opacity-35\"\n        />\n        <circle\n          cx=\"24\"\n          cy=\"24\"\n          r=\"13\"\n          stroke={secondaryColor}\n          strokeWidth=\"2.6\"\n          strokeDasharray=\"25 57\"\n          strokeLinecap=\"round\"\n        />\n      </svg>\n\n      {/* Core Center: Mathematically Perfect Pulsing Rounded Circle Dot */}\n      <svg\n        className=\"absolute inset-0 w-full h-full aspect-square pointer-events-none\"\n        viewBox=\"0 0 48 48\"\n        fill=\"none\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n      >\n        <circle\n          cx=\"24\"\n          cy=\"24\"\n          r=\"3.6\"\n          fill={color}\n          className=\"animate-pulse\"\n        />\n      </svg>\n    </div>\n  );\n}\n\nfunction Bar({ color }: { color: string }) {\n  return (\n    <div className=\"w-full h-full overflow-hidden rounded-full bg-muted\">\n      <div\n        className=\"h-full w-[50%] rounded-full animate-indet\"\n        style={{ backgroundColor: color }}\n      />\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/custom/blocks/LoaderBlock.tsx"
    },
    {
      "path": "src/components/custom/blocks/loader-theme.ts",
      "content": "\"use client\";\n\nconst colorMap: Record<string, string> = {\n  primary: \"var(--primary)\",\n  lavender: \"#9b8afb\",\n  indigo: \"#4f46e5\",\n  rose: \"#e11d48\",\n  emerald: \"#10b981\",\n  zinc: \"#71717a\",\n  blue: \"#3b82f6\",\n  amber: \"#f59e0b\",\n  violet: \"#8b5cf6\",\n  purple: \"#a855f7\",\n  cyan: \"#06b6d4\",\n  teal: \"#14b8a6\",\n  orange: \"#f97316\",\n  red: \"#ef4444\",\n  pink: \"#ec4899\",\n  yellow: \"#eab308\",\n  green: \"#22c55e\",\n};\n\nexport const getThemeColor = (color: string) => {\n  return color.startsWith(\"#\") ? color : colorMap[color] || colorMap.primary;\n};\n",
      "type": "registry:component",
      "target": "components/custom/blocks/loader-theme.ts"
    }
  ],
  "docs": "Named exports: LoaderBlock, getThemeColor. `variant` picks the shape, `size` is sm | md | lg | xl, and `text` renders a caption beneath. Pure CSS animation with no runtime dependencies. For content-shaped placeholders, use `skeleton`.",
  "categories": [
    "feedback"
  ],
  "type": "registry:component"
}
