{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "placeholder",
  "title": "Placeholder",
  "description": "deterministic abstract SVG art from a `seed` · the kit ships no raster imagery",
  "dependencies": [
    "cn@^0.4.0",
    "lucide-react@^1.52.0"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "components/kit/placeholder.tsx",
      "content": "import { cn } from 'cn';\nimport type { LucideIcon } from 'lucide-react';\n\ntype Palette = 'chart' | 'mono' | 'primary';\n\ntype Props = {\n  /** Any string: the same seed always draws the same art. */\n  seed: string;\n  /** Width / height. Default 1 (square). */\n  ratio?: number;\n  /** Which token family to draw in. Default `chart`. */\n  palette?: Palette;\n  /** Optional glyph centred over the art. */\n  icon?: LucideIcon;\n  className?: string;\n};\n\n/** 32-bit string hash: stable across platforms and reloads. The native kit uses the same one, so a seed draws the same art in both. */\nfunction hash(input: string) {\n  let h = 2166136261;\n  for (let i = 0; i < input.length; i++) {\n    h ^= input.charCodeAt(i);\n    h = Math.imul(h, 16777619);\n  }\n  return h >>> 0;\n}\n\n/** Small, fast, seedable PRNG. */\nfunction mulberry32(seed: number) {\n  let a = seed;\n  return () => {\n    a |= 0;\n    a = (a + 0x6d2b79f5) | 0;\n    let t = Math.imul(a ^ (a >>> 15), 1 | a);\n    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n  };\n}\n\ntype Shape =\n  | { kind: 'circle'; cx: number; cy: number; r: number; fill: number; opacity: number }\n  | { kind: 'rect'; x: number; y: number; w: number; h: number; rx: number; fill: number; opacity: number }\n  | { kind: 'arc'; d: string; fill: number; opacity: number };\n\nfunction shapesFor(seed: string): Shape[] {\n  const rand = mulberry32(hash(seed));\n  const count = 5 + Math.floor(rand() * 3);\n  const out: Shape[] = [];\n  for (let i = 0; i < count; i++) {\n    const fill = Math.floor(rand() * 5);\n    const opacity = 0.12 + rand() * 0.22;\n    const pick = rand();\n    if (pick < 0.45) {\n      out.push({ kind: 'circle', cx: rand() * 100, cy: rand() * 100, r: 14 + rand() * 30, fill, opacity });\n    } else if (pick < 0.8) {\n      const w = 22 + rand() * 46;\n      const h = 22 + rand() * 46;\n      out.push({ kind: 'rect', x: rand() * (100 - w), y: rand() * (100 - h), w, h, rx: 4 + rand() * 14, fill, opacity });\n    } else {\n      const cx = rand() * 100;\n      const cy = rand() * 100;\n      const r = 20 + rand() * 34;\n      out.push({ kind: 'arc', d: `M ${cx - r} ${cy} A ${r} ${r} 0 0 1 ${cx + r} ${cy} Z`, fill, opacity });\n    }\n  }\n  return out;\n}\n\nconst FILLS: Record<Palette, string[]> = {\n  chart: ['fill-chart-1', 'fill-chart-2', 'fill-chart-3', 'fill-chart-4', 'fill-chart-5'],\n  mono: ['fill-muted-foreground', 'fill-border', 'fill-muted-foreground', 'fill-border', 'fill-muted-foreground'],\n  primary: ['fill-primary', 'fill-primary', 'fill-ring', 'fill-primary', 'fill-ring'],\n};\n\n/**\n * Deterministic abstract SVG art from a seed: stand-in imagery that never 404s.\n *\n * Drawn from theme colours, so it follows light/dark and re-brands with the tokens. Use it wherever a prototype\n * needs a picture it does not have: product shots, covers, avatars, the art on a PromoCard.\n */\nexport function Placeholder({ seed, ratio = 1, palette = 'chart', icon: Icon, className }: Props) {\n  const fills = FILLS[palette];\n  return (\n    <div aria-hidden className={cn('bg-muted relative flex w-full items-center justify-center overflow-hidden rounded-lg', className)} style={{ aspectRatio: ratio }}>\n      <svg className=\"absolute inset-0 size-full\" viewBox=\"0 0 100 100\" preserveAspectRatio=\"xMidYMid slice\">\n        {shapesFor(seed).map((s, i) =>\n          s.kind === 'circle' ? (\n            <circle key={i} cx={s.cx} cy={s.cy} r={s.r} className={fills[s.fill]} opacity={s.opacity} />\n          ) : s.kind === 'rect' ? (\n            <rect key={i} x={s.x} y={s.y} width={s.w} height={s.h} rx={s.rx} className={fills[s.fill]} opacity={s.opacity} />\n          ) : (\n            <path key={i} d={s.d} className={fills[s.fill]} opacity={s.opacity} />\n          )\n        )}\n      </svg>\n      {Icon ? <Icon className=\"text-muted-foreground relative size-7\" /> : null}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/kit/placeholder.tsx"
    }
  ],
  "meta": {
    "exports": [
      "Placeholder"
    ],
    "api": "<Placeholder seed ratio? palette=\"chart|mono|primary\" icon? />"
  },
  "docs": "Needs the kit theme (`@kit/theme`) and a next-themes ThemeProvider (attribute=\"class\") at the root.",
  "categories": [
    "media"
  ],
  "type": "registry:component"
}