{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "noise-background",
  "title": "Noise Background",
  "description": "Film grain drawn from an inline SVG with no image files: fine grain, warm paper, grain over a soft accent wash, or sparse flecks.",
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/miseui/ui/noise-background.tsx",
      "content": "import type * as React from \"react\"\nimport { cn } from \"@/registry/miseui/lib/utils\"\n\ntype NoiseBackgroundVariant = \"grain\" | \"paper\" | \"tint\" | \"speckle\"\n\ninterface NoiseTile {\n  /** feTurbulence baseFrequency: higher is finer. Two numbers stretch the grain along one axis. */\n  frequency: string\n  octaves: number\n  /** Alpha out = slope * alpha in + intercept. A steep slope with a low intercept leaves only the rare peaks: flecks. */\n  slope: number\n  intercept: number\n  size: number\n  seed: number\n}\n\ninterface NoiseLayer {\n  tile?: NoiseTile\n  /** A token colour: the tile is a mask over it, because a data URI cannot read a theme. */\n  className: string\n}\n\n/** The noise goes into the alpha channel, so one image serves both themes through the colour behind the mask. stitchTiles hides the seam. */\nfunction noiseTile({ frequency, octaves, slope, intercept, size, seed }: NoiseTile) {\n  const matrix = `0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ${slope} ${intercept}`\n  const svg =\n    `<svg xmlns='http://www.w3.org/2000/svg' width='${size}' height='${size}'>` +\n    `<filter id='n' x='0' y='0' width='100%' height='100%'>` +\n    `<feTurbulence type='fractalNoise' baseFrequency='${frequency}' numOctaves='${octaves}' seed='${seed}' stitchTiles='stitch'/>` +\n    `<feColorMatrix values='${matrix}'/>` +\n    `</filter><rect width='100%' height='100%' filter='url(#n)'/></svg>`\n  return `url(\"data:image/svg+xml,${encodeURIComponent(svg)}\")`\n}\n\nconst FINE_GRAIN: NoiseTile = { frequency: \"0.8\", octaves: 2, slope: 3.5, intercept: -1.25, size: 220, seed: 3 }\n\n/**\n * Grain stays near single-pixel. A big soft cloud at this strength has only about ten colour levels to work with and draws\n * contour lines, and anything coarser than a couple of pixels reads as blotches, so paper stays fine too and differs by its stretched fibre.\n * Warm paper is a low chroma cast on the page colour, not a yellow: yellow on a dark page turns to mud.\n */\nconst LAYERS: Record<NoiseBackgroundVariant, readonly NoiseLayer[]> = {\n  grain: [{ tile: FINE_GRAIN, className: \"bg-foreground opacity-[0.05]\" }],\n  paper: [\n    {\n      className:\n        \"supports-[color:oklch(from_red_l_c_h)]:bg-[color:oklch(from_var(--background)_calc(l_-_0.012)_0.012_75)] dark:supports-[color:oklch(from_red_l_c_h)]:bg-[color:oklch(from_var(--background)_calc(l_+_0.012)_0.012_65)]\",\n    },\n    {\n      tile: { frequency: \"0.65 0.95\", octaves: 3, slope: 3, intercept: -1.1, size: 320, seed: 11 },\n      className: \"bg-foreground opacity-[0.06] supports-[color:oklch(from_red_l_c_h)]:bg-[color:oklch(from_var(--foreground)_l_0.05_65)]\",\n    },\n  ],\n  tint: [\n    { className: \"bg-[linear-gradient(160deg,var(--mise-soft),transparent_90%)]\" },\n    { tile: FINE_GRAIN, className: \"bg-foreground opacity-[0.045]\" },\n  ],\n  speckle: [\n    { tile: { frequency: \"0.14\", octaves: 1, slope: 14, intercept: -10.2, size: 256, seed: 7 }, className: \"bg-foreground opacity-[0.16] dark:opacity-[0.18]\" },\n    // A second colour is what makes flecks read as stationery. One grey alone reads as dirt.\n    { tile: { frequency: \"0.09\", octaves: 1, slope: 14, intercept: -10.6, size: 256, seed: 21 }, className: \"bg-mise opacity-50\" },\n  ],\n}\n\nfunction layerStyle(tile: NoiseTile | undefined): React.CSSProperties | undefined {\n  if (!tile) return undefined\n  const image = noiseTile(tile)\n  const size = `${tile.size}px ${tile.size}px`\n  return { maskImage: image, WebkitMaskImage: image, maskSize: size, WebkitMaskSize: size }\n}\n\ntype NoiseBackgroundProps = React.ComponentProps<\"div\"> & {\n  /** `grain` fine and even, `paper` coarse and warm, `tint` grain over a soft accent wash, `speckle` sparse larger flecks. */\n  variant?: NoiseBackgroundVariant\n}\n\n/** Grain that moves is distracting, so there is no effect. */\nfunction NoiseBackground({ variant = \"grain\", className, children, ...props }: NoiseBackgroundProps) {\n  return (\n    <div {...props} data-slot=\"noise-background\" data-variant={variant} className={cn(\"relative isolate overflow-clip\", className)}>\n      <div aria-hidden=\"true\" data-slot=\"noise-background-layer\" className=\"pointer-events-none absolute inset-0 rounded-[inherit] contrast-more:hidden forced-colors:hidden\">\n        {LAYERS[variant].map((layer) => (\n          <div key={layer.className} data-slot=\"noise-background-film\" className={cn(\"absolute inset-0\", layer.className)} style={layerStyle(layer.tile)} />\n        ))}\n      </div>\n      <div data-slot=\"noise-background-content\" className=\"relative h-full min-h-[inherit]\">\n        {children}\n      </div>\n    </div>\n  )\n}\n\nexport { NoiseBackground, noiseTile, type NoiseBackgroundProps, type NoiseBackgroundVariant, type NoiseTile }\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "backgrounds"
  ],
  "type": "registry:ui"
}