{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "watermark",
  "title": "Watermark",
  "description": "A faint tiled text mark over its content for confidential documents and drafts, drawn as an SVG overlay that cannot block clicks and restores itself if removed.",
  "files": [
    {
      "path": "registry/tealmac/watermark.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface WatermarkProps extends Omit<\n  React.HTMLAttributes<HTMLDivElement>,\n  \"content\"\n> {\n  /** One line, or several lines, drawn on every tile. */\n  content: string | string[]\n  /** Rotation in degrees. Default -22. */\n  rotate?: number\n  /** Horizontal and vertical gap between tiles in px. Default [80, 80]. */\n  gap?: [number, number]\n  fontSize?: number\n  /** Any CSS colour. The default is a translucent grey that reads in light and dark. */\n  color?: string\n  /** Keep the layer if someone removes it or hides it with devtools. Default true. */\n  tamperResistant?: boolean\n}\n\nfunction escapeXml(text: string) {\n  return text\n    .replace(/&/g, \"&amp;\")\n    .replace(/</g, \"&lt;\")\n    .replace(/>/g, \"&gt;\")\n    .replace(/\"/g, \"&quot;\")\n}\n\n/** Builds the tile as an SVG data URL. Pure, so it works on the server and in tests. */\nexport function watermarkImage(\n  lines: string[],\n  {\n    rotate,\n    gap,\n    fontSize,\n    color,\n  }: Required<Pick<WatermarkProps, \"rotate\" | \"gap\" | \"fontSize\" | \"color\">>\n) {\n  const width = Math.max(...lines.map((l) => l.length)) * fontSize * 0.62\n  const height = lines.length * fontSize * 1.4\n  const w = Math.ceil(width + gap[0])\n  const h = Math.ceil(height + gap[1])\n  const text = lines\n    .map(\n      (l, i) =>\n        `<text x=\"${w / 2}\" y=\"${h / 2 - height / 2 + (i + 0.8) * fontSize * 1.4}\" text-anchor=\"middle\">${escapeXml(l)}</text>`\n    )\n    .join(\"\")\n  const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${w}\" height=\"${h}\"><g transform=\"rotate(${rotate} ${w / 2} ${h / 2})\" font-family=\"system-ui,sans-serif\" font-size=\"${fontSize}\" fill=\"${escapeXml(color)}\">${text}</g></svg>`\n  return { url: `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`, w, h }\n}\n\n/**\n * Tiles a faint text mark over its children, for confidential documents,\n * drafts and screenshots of sensitive screens. The mark is a decorative\n * overlay (`aria-hidden`, no pointer events), so it never blocks clicks or\n * screen readers. With `tamperResistant` it puts itself back when removed or\n * restyled.\n */\nexport function Watermark({\n  content,\n  rotate = -22,\n  gap = [80, 80],\n  fontSize = 16,\n  color = \"rgba(128,128,128,0.28)\",\n  tamperResistant = true,\n  className,\n  children,\n  ...props\n}: WatermarkProps) {\n  const rootRef = React.useRef<HTMLDivElement>(null)\n  const markRef = React.useRef<HTMLDivElement | null>(null)\n  const lines = Array.isArray(content) ? content : [content]\n  const { url, w, h } = watermarkImage(lines, { rotate, gap, fontSize, color })\n  const style: React.CSSProperties = {\n    position: \"absolute\",\n    inset: 0,\n    zIndex: 9,\n    pointerEvents: \"none\",\n    backgroundImage: `url(\"${url}\")`,\n    backgroundSize: `${w}px ${h}px`,\n    backgroundRepeat: \"repeat\",\n  }\n\n  React.useEffect(() => {\n    const root = rootRef.current\n    if (!root || !tamperResistant || typeof MutationObserver === \"undefined\")\n      return\n    const force = (mark: HTMLElement, prop: string, want: string) => {\n      // Only write when it differs, so our own change cannot retrigger us.\n      if (\n        mark.style.getPropertyValue(prop) !== want ||\n        mark.style.getPropertyPriority(prop) !== \"important\"\n      )\n        mark.style.setProperty(prop, want, \"important\")\n    }\n    const restore = () => {\n      const mark = markRef.current\n      if (!mark) return\n      if (mark.parentElement !== root) root.appendChild(mark)\n      force(mark, \"display\", \"block\")\n      force(mark, \"opacity\", \"1\")\n      force(mark, \"visibility\", \"visible\")\n      force(mark, \"position\", \"absolute\")\n      force(mark, \"pointer-events\", \"none\")\n    }\n    const observer = new MutationObserver(restore)\n    observer.observe(root, { childList: true })\n    if (markRef.current)\n      observer.observe(markRef.current, {\n        attributes: true,\n        attributeFilter: [\"style\", \"class\", \"hidden\"],\n      })\n    return () => observer.disconnect()\n  })\n\n  return (\n    <div ref={rootRef} className={cn(\"relative\", className)} {...props}>\n      {children}\n      <div ref={markRef} aria-hidden data-watermark=\"\" style={style} />\n    </div>\n  )\n}\n\nexport default Watermark\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}