{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "color",
  "title": "Color",
  "author": "Ballmac <https://ui.ballmac.com>",
  "description": "Resolves theme tokens for canvas and WebGL effects: CSS variables to color strings or RGBA numbers, plus a theme-change observer so effects repaint in dark mode.",
  "files": [
    {
      "path": "registry/ballmac/lib/color.ts",
      "content": "// Ballmac UI: Color. https://ui.ballmac.com/docs/theming\n\n/**\n * Resolves a theme color for canvas and WebGL effects, which can't use Tailwind classes.\n * Accepts a CSS variable name (\"--primary\"), a var() expression or any CSS color, read in\n * the context of `element` so light and dark themes both apply. Browser only.\n */\nfunction resolveCssColor(element: Element, color: string): string {\n  const style = getComputedStyle(element)\n  const name = color.startsWith(\"--\") ? color : /^var\\((--[^,)]+)/.exec(color)?.[1]\n  const value = name ? style.getPropertyValue(name).trim() : color\n  return value || style.color\n}\n\nlet probe: CanvasRenderingContext2D | null = null\n\n/** The same color as [r, g, b, a] in 0–1, for libraries such as WebGL that need numbers. */\nfunction cssColorToRgba(element: Element, color: string): [number, number, number, number] {\n  probe ??= document.createElement(\"canvas\").getContext(\"2d\", { willReadFrequently: true })\n  if (!probe) return [0, 0, 0, 1]\n  probe.clearRect(0, 0, 1, 1)\n  probe.fillStyle = resolveCssColor(element, color)\n  probe.fillRect(0, 0, 1, 1)\n  const [r, g, b, a] = probe.getImageData(0, 0, 1, 1).data\n  return [r / 255, g / 255, b / 255, a / 255]\n}\n\n/** Calls `onChange` when the theme switches (the `dark` class or a data-theme attribute on <html>). */\nfunction observeTheme(onChange: () => void): () => void {\n  const observer = new MutationObserver(onChange)\n  observer.observe(document.documentElement, { attributes: true, attributeFilter: [\"class\", \"data-theme\", \"style\"] })\n  const media = window.matchMedia(\"(prefers-color-scheme: dark)\")\n  media.addEventListener(\"change\", onChange)\n  return () => {\n    observer.disconnect()\n    media.removeEventListener(\"change\", onChange)\n  }\n}\n\nexport { resolveCssColor, cssColorToRgba, observeTheme }\n",
      "type": "registry:lib",
      "target": "@lib/ballmac/color.ts"
    }
  ],
  "meta": {
    "schema": 1,
    "tier": "free",
    "tags": [
      "color",
      "canvas",
      "webgl",
      "theme"
    ],
    "version": "1.0.0",
    "updated": "2026-09-29",
    "ai": {
      "summary": "Use resolveCssColor(el, '--primary') for canvas fillStyle and cssColorToRgba for WebGL, and observeTheme to repaint when the theme changes.",
      "whenToUse": [
        "Canvas or WebGL components that must follow the theme tokens"
      ],
      "whenNotToUse": [
        "DOM elements (use Tailwind token classes)"
      ],
      "composesWith": [],
      "a11y": [],
      "customization": [
        "Pass any CSS variable name, var() expression or CSS color"
      ]
    },
    "examples": [],
    "url": "https://ui.ballmac.com/components/color"
  },
  "categories": [
    "foundation"
  ],
  "type": "registry:lib"
}