{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "watermark",
  "title": "Watermark",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-react/components/watermark/Watermark.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface WatermarkProps extends React.HTMLAttributes<HTMLDivElement> {\n  /** Text content for the watermark. Ignored when `image` is set. */\n  content?: string\n  /** Image URL. When set, repeats the image instead of text. */\n  image?: string\n  /** Rotation angle in degrees. */\n  rotate?: number\n  /** Gap between repeats in pixels (both x and y). */\n  gap?: number\n  /** Opacity 0-1. */\n  opacity?: number\n  /** Font size in pixels (text only). */\n  fontSize?: number\n  /** Font color (text only). */\n  color?: string\n  /** Font family (text only). */\n  fontFamily?: string\n  /** Font weight (text only). */\n  fontWeight?: number | string\n  /** z-index of the overlay. */\n  zIndex?: number\n  /** When true, the overlay captures pointer events (blocks interaction). Default false (pointer-events-none). */\n  interactive?: boolean\n}\n\nconst Watermark = React.forwardRef<HTMLDivElement, WatermarkProps>(\n  (\n    {\n      className,\n      children,\n      content = '',\n      image,\n      rotate = -22,\n      gap = 100,\n      opacity = 0.08,\n      fontSize = 16,\n      color = 'currentColor',\n      fontFamily = 'sans-serif',\n      fontWeight = 'normal',\n      zIndex = 9,\n      interactive = false,\n      ...props\n    },\n    ref,\n  ) => {\n    const containerRef = React.useRef<HTMLDivElement | null>(null)\n    const [size, setSize] = React.useState({ width: 0, height: 0 })\n\n    React.useImperativeHandle(ref, () => containerRef.current as HTMLDivElement)\n\n    React.useEffect(() => {\n      const el = containerRef.current\n      if (!el) return\n      const measure = () => {\n        const rect = el.getBoundingClientRect()\n        setSize({ width: rect.width, height: rect.height })\n      }\n      measure()\n      let ro: ResizeObserver | null = null\n      if (typeof ResizeObserver !== 'undefined') {\n        ro = new ResizeObserver(() => measure())\n        ro.observe(el)\n      }\n      return () => {\n        ro?.disconnect()\n      }\n    }, [])\n\n    // Build a tiled SVG data URL that repeats the text/image across a tile of\n    // size (gap + contentSize). The SVG is then used as a background-image on\n    // the overlay div, rotated to the requested angle.\n    const watermarkUrl = React.useMemo(() => {\n      if (!size.width || !size.height) return ''\n      const text = content || ''\n\n      if (image) {\n        // For images we tile the image at its natural size within the gap.\n        const tile = gap + 100\n        const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${tile}\" height=\"${tile}\" viewBox=\"0 0 ${tile} ${tile}\">\n  <image href=\"${image}\" x=\"${gap / 2}\" y=\"${gap / 2}\" width=\"100\" height=\"100\" opacity=\"${opacity}\" transform=\"rotate(${rotate} ${tile / 2} ${tile / 2})\"/>\n</svg>`\n        return `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svg)))}`\n      }\n\n      if (!text) return ''\n\n      // Estimate text width — rough heuristic, good enough for tiling.\n      const textWidth = text.length * fontSize * 0.6\n      const tileW = gap + textWidth\n      const tileH = gap + fontSize * 1.5\n\n      const escapedText = text\n        .replace(/&/g, '&amp;')\n        .replace(/</g, '&lt;')\n        .replace(/>/g, '&gt;')\n        .replace(/\"/g, '&quot;')\n        .replace(/'/g, '&#39;')\n\n      const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${tileW}\" height=\"${tileH}\" viewBox=\"0 0 ${tileW} ${tileH}\">\n  <text x=\"${gap / 2}\" y=\"${gap / 2 + fontSize}\" font-size=\"${fontSize}\" font-family=\"${fontFamily}\" font-weight=\"${fontWeight}\" fill=\"${color}\" opacity=\"${opacity}\" transform=\"rotate(${rotate} ${gap / 2} ${gap / 2 + fontSize / 2})\">${escapedText}</text>\n</svg>`\n      return `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svg)))}`\n    }, [size.width, size.height, image, content, gap, fontSize, rotate, opacity, color, fontFamily, fontWeight])\n\n    const overlayStyle: React.CSSProperties = {\n      backgroundImage: watermarkUrl ? `url(\"${watermarkUrl}\")` : undefined,\n      backgroundRepeat: 'repeat',\n      zIndex,\n      pointerEvents: interactive ? 'auto' : 'none',\n    }\n\n    return (\n      <div ref={containerRef} data-uipkge=\"\" data-slot=\"watermark\" className={cn('relative', className)} {...props}>\n        {children}\n        <div\n          data-uipkge=\"\"\n          data-slot=\"watermark-overlay\"\n          className=\"absolute inset-0 overflow-hidden\"\n          style={overlayStyle}\n          aria-hidden=\"true\"\n        />\n      </div>\n    )\n  },\n)\nWatermark.displayName = 'Watermark'\n\nexport { Watermark }\n",
      "type": "registry:ui",
      "target": "~/components/ui/watermark/Watermark.tsx"
    },
    {
      "path": "packages/registry-react/components/watermark/index.ts",
      "content": "export { Watermark, type WatermarkProps } from './Watermark'\n",
      "type": "registry:ui",
      "target": "~/components/ui/watermark/index.ts"
    }
  ],
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "description": "Overlay watermark that repeats text or an image across the content area at a configurable angle. Supports rotate angle, gap between repeats, opacity, font size/color/weight, z-index, and pointer-event control. Wrap any content via children.",
  "categories": [
    "display",
    "utility"
  ]
}