{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "raised-button",
  "type": "registry:ui",
  "title": "Raised Button",
  "description": "A beautiful 3D raised button with customizable colors and dynamic text contrast.",
  "dependencies": [
    "class-variance-authority"
  ],
  "files": [
    {
      "path": "registry/new-york/ui/raised-button.tsx",
      "content": "\"use client\";\n\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n\tgetContrastColor,\n\tgetLuminance,\n\tparseColor,\n} from \"@/lib/utils/colorUtils\";\n\nconst buttonVariants = cva(\n\t\"inline-flex items-center justify-center dark:bg-zinc-500 dark:text-white whitespace-nowrap text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 relative bg-primary text-primary-foreground hover:bg-primary/90 border border-primary/50 shadow-md before:absolute before:inset-0 before:border-t before:border-white/40 before:bg-gradient-to-b before:from-white/20 before:to-transparent cursor-pointer transition-transform duration-200 active:scale-[0.96] subpixel-antialiased gap-2\",\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: \"\",\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: \"h-10 px-4 py-2 rounded-xl before:rounded-xl\",\n\t\t\t\tsm: \"h-9 rounded-lg px-3 before:rounded-xl\",\n\t\t\t\tlg: \"h-11 rounded-lg px-8 before:rounded-lg\",\n\t\t\t\ticon: \"h-10 w-10\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: \"default\",\n\t\t\tsize: \"default\",\n\t\t},\n\t},\n);\n\nexport interface ButtonProps\n\textends React.ButtonHTMLAttributes<HTMLButtonElement>,\n\t\tVariantProps<typeof buttonVariants> {\n\tcolor?: string;\n}\n\nconst RaisedButton = React.forwardRef<HTMLButtonElement, ButtonProps>(\n\t({ className, variant, size, color, style = {}, ...props }, ref) => {\n\t\tconst Comp = \"button\";\n\n\t\tconst dynamicStyles = React.useMemo(() => {\n\t\t\tif (!color) return {};\n\n\t\t\ttry {\n\t\t\t\tconst rgb = parseColor(color);\n\t\t\t\tif (!rgb) return {};\n\n\t\t\t\tconst luminance = getLuminance(rgb);\n\t\t\t\tconst textColor = getContrastColor(luminance);\n\t\t\t\tconst borderOpacity = 0.5;\n\t\t\t\tconst hoverOpacity = 0.9;\n\t\t\t\tconst whiteBorderOpacity = 0.6;\n\t\t\t\tconst whiteGradientOpacity = 0.3;\n\t\t\t\tconst shadowOpacity = 0.2;\n\t\t\t\tconst shadowSpread = \"0px\";\n\t\t\t\tconst shadowBlur = \"5px\";\n\n\t\t\t\treturn {\n\t\t\t\t\tbackgroundColor: color,\n\t\t\t\t\tcolor: textColor,\n\t\t\t\t\tborderColor: `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${borderOpacity})`,\n\t\t\t\t\t\"--hover-bg\": `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${hoverOpacity})`,\n\t\t\t\t\t\"--border\": `rgba(255, 255, 255, ${whiteBorderOpacity})`,\n\t\t\t\t\t\"--gradient\": `rgba(255, 255, 255, ${whiteGradientOpacity})`,\n\t\t\t\t\t\"--shadow-color\": `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${shadowOpacity})`,\n\t\t\t\t\tboxShadow: `0 4px ${shadowBlur} ${shadowSpread} var(--shadow-color)`,\n\t\t\t\t\ttransition: \"all 0.2s ease-in-out\",\n\t\t\t\t};\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error(\"Error processing color:\", e);\n\t\t\t\treturn {};\n\t\t\t}\n\t\t}, [color]);\n\n\t\tconst computedClassName = cn(\n\t\t\tbuttonVariants({ variant, size, className }),\n\t\t\tcolor &&\n\t\t\t\t\"hover:bg-[color:var(--hover-bg)] before:border-[color:var(--border)] before:from-[color:var(--gradient)] hover:opacity-80 overflow-hidden\",\n\t\t);\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tclassName={computedClassName}\n\t\t\t\tref={ref}\n\t\t\t\tstyle={{\n\t\t\t\t\t...style,\n\t\t\t\t\t...dynamicStyles,\n\t\t\t\t}}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nRaisedButton.displayName = \"RaisedButton\";\n\nexport { buttonVariants, RaisedButton };\n",
      "type": "registry:ui"
    },
    {
      "path": "lib/utils/colorUtils.ts",
      "content": "const CSS_COLOR_NAMES: Record<string, [number, number, number]> = {\n\tblack: [0, 0, 0],\n\twhite: [255, 255, 255],\n\tred: [255, 0, 0],\n\tgreen: [0, 128, 0],\n\tblue: [0, 0, 255],\n\tyellow: [255, 255, 0],\n\tcyan: [0, 255, 255],\n\tmagenta: [255, 0, 255],\n\tgray: [128, 128, 128],\n\tgrey: [128, 128, 128],\n\torange: [255, 165, 0],\n\tpurple: [128, 0, 128],\n\tpink: [255, 192, 203],\n\tbrown: [165, 42, 42],\n\tnavy: [0, 0, 128],\n\tteal: [0, 128, 128],\n\tolive: [128, 128, 0],\n\tmaroon: [128, 0, 0],\n\tsilver: [192, 192, 192],\n\tlime: [0, 255, 0],\n\taqua: [0, 255, 255],\n\tfuchsia: [255, 0, 255],\n};\n\nexport function hexToRgb(\n\thex: string,\n): { r: number; g: number; b: number } | null {\n\tconst normalizedHex = hex.charAt(0) === \"#\" ? hex.substring(1) : hex;\n\n\tif (normalizedHex.length === 3) {\n\t\tconst r = parseInt(normalizedHex.charAt(0) + normalizedHex.charAt(0), 16);\n\t\tconst g = parseInt(normalizedHex.charAt(1) + normalizedHex.charAt(1), 16);\n\t\tconst b = parseInt(normalizedHex.charAt(2) + normalizedHex.charAt(2), 16);\n\t\treturn { r, g, b };\n\t}\n\n\tif (normalizedHex.length === 6) {\n\t\tconst r = parseInt(normalizedHex.substring(0, 2), 16);\n\t\tconst g = parseInt(normalizedHex.substring(2, 4), 16);\n\t\tconst b = parseInt(normalizedHex.substring(4, 6), 16);\n\t\treturn { r, g, b };\n\t}\n\n\tif (normalizedHex !== hex) {\n\t\ttry {\n\t\t\tconst tempElement = document.createElement(\"div\");\n\t\t\ttempElement.style.color = hex;\n\t\t\tdocument.body.appendChild(tempElement);\n\n\t\t\tconst computedColor = window.getComputedStyle(tempElement).color;\n\t\t\tdocument.body.removeChild(tempElement);\n\n\t\t\tconst rgbMatch = computedColor.match(\n\t\t\t\t/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*[\\d.]+)?\\)/,\n\t\t\t);\n\t\t\tif (rgbMatch) {\n\t\t\t\treturn {\n\t\t\t\t\tr: parseInt(rgbMatch[1], 10),\n\t\t\t\t\tg: parseInt(rgbMatch[2], 10),\n\t\t\t\t\tb: parseInt(rgbMatch[3], 10),\n\t\t\t\t};\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.error(\"Error processing color name:\", e);\n\t\t}\n\t}\n\n\treturn null;\n}\n\nexport function getLuminance(rgb: { r: number; g: number; b: number }): number {\n\tconst { r, g, b } = rgb;\n\n\tconst sR = r / 255;\n\tconst sG = g / 255;\n\tconst sB = b / 255;\n\n\tconst R = sR <= 0.03928 ? sR / 12.92 : ((sR + 0.055) / 1.055) ** 2.4;\n\tconst G = sG <= 0.03928 ? sG / 12.92 : ((sG + 0.055) / 1.055) ** 2.4;\n\tconst B = sB <= 0.03928 ? sB / 12.92 : ((sB + 0.055) / 1.055) ** 2.4;\n\n\treturn 0.2126 * R + 0.7152 * G + 0.0722 * B;\n}\n\nexport function getContrastColor(luminance: number): string {\n\treturn luminance > 0.5 ? \"#000000\" : \"#ffffff\";\n}\n\nexport function parseColor(\n\tcolor: string,\n): { r: number; g: number; b: number } | null {\n\tconst hexResult = hexToRgb(color);\n\tif (hexResult) return hexResult;\n\n\ttry {\n\t\tif (typeof document !== \"undefined\") {\n\t\t\tconst tempElement = document.createElement(\"div\");\n\t\t\ttempElement.style.color = color;\n\t\t\tdocument.body.appendChild(tempElement);\n\n\t\t\tconst computedColor = window.getComputedStyle(tempElement).color;\n\t\t\tdocument.body.removeChild(tempElement);\n\n\t\t\tconst rgbMatch = computedColor.match(\n\t\t\t\t/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*[\\d.]+)?\\)/,\n\t\t\t);\n\t\t\tif (rgbMatch) {\n\t\t\t\treturn {\n\t\t\t\t\tr: parseInt(rgbMatch[1], 10),\n\t\t\t\t\tg: parseInt(rgbMatch[2], 10),\n\t\t\t\t\tb: parseInt(rgbMatch[3], 10),\n\t\t\t\t};\n\t\t\t}\n\t\t} else {\n\t\t\tconst colorMap: Record<string, { r: number; g: number; b: number }> = {};\n\t\t\tfor (const [name, rgb] of Object.entries(CSS_COLOR_NAMES)) {\n\t\t\t\tconst [r, g, b] = rgb;\n\t\t\t\tcolorMap[name.toLowerCase()] = { r, g, b };\n\t\t\t}\n\n\t\t\tconst normalizedColorName = color.toLowerCase().trim();\n\t\t\tif (colorMap[normalizedColorName]) {\n\t\t\t\treturn colorMap[normalizedColorName];\n\t\t\t}\n\t\t}\n\n\t\tconst rgbDirectMatch = color.match(\n\t\t\t/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*[\\d.]+)?\\)/,\n\t\t);\n\t\tif (rgbDirectMatch) {\n\t\t\treturn {\n\t\t\t\tr: parseInt(rgbDirectMatch[1], 10),\n\t\t\t\tg: parseInt(rgbDirectMatch[2], 10),\n\t\t\t\tb: parseInt(rgbDirectMatch[3], 10),\n\t\t\t};\n\t\t}\n\n\t\tconst hslMatch = color.match(\n\t\t\t/hsla?\\((\\d+),\\s*(\\d+)%,\\s*(\\d+)%(?:,\\s*[\\d.]+)?\\)/,\n\t\t);\n\t\tif (hslMatch) {\n\t\t\tconst h = parseInt(hslMatch[1], 10) / 360;\n\t\t\tconst s = parseInt(hslMatch[2], 10) / 100;\n\t\t\tconst l = parseInt(hslMatch[3], 10) / 100;\n\n\t\t\treturn hslToRgb(h, s, l);\n\t\t}\n\t} catch (e) {\n\t\tconsole.error(\"Error processing color:\", e);\n\t}\n\n\treturn null;\n}\n\nexport function hslToRgb(\n\th: number,\n\ts: number,\n\tl: number,\n): { r: number; g: number; b: number } {\n\tlet r: number, g: number, b: number;\n\n\tif (s === 0) {\n\t\tr = g = b = l * 255;\n\t} else {\n\t\tconst hue2rgb = (p: number, q: number, t: number): number => {\n\t\t\tif (t < 0) t += 1;\n\t\t\tif (t > 1) t -= 1;\n\t\t\tif (t < 1 / 6) return p + (q - p) * 6 * t;\n\t\t\tif (t < 1 / 2) return q;\n\t\t\tif (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n\t\t\treturn p;\n\t\t};\n\n\t\tconst q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n\t\tconst p = 2 * l - q;\n\n\t\tr = hue2rgb(p, q, h + 1 / 3) * 255;\n\t\tg = hue2rgb(p, q, h) * 255;\n\t\tb = hue2rgb(p, q, h - 1 / 3) * 255;\n\t}\n\n\treturn {\n\t\tr: Math.round(r),\n\t\tg: Math.round(g),\n\t\tb: Math.round(b),\n\t};\n}\n",
      "type": "registry:lib"
    }
  ]
}