{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "watermark",
  "title": "Watermark",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-svelte/components/watermark/Watermark.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Snippet } from 'svelte'\n  import type { HTMLAttributes } from 'svelte/elements'\n\n  export interface WatermarkProps extends HTMLAttributes<HTMLDivElement> {\n    children?: Snippet\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</script>\n\n<script lang=\"ts\">\n  import { cn } from '$lib/utils'\n\n  let {\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    class: className,\n    ...restProps\n  }: WatermarkProps = $props()\n\n  let containerRef: HTMLDivElement | null = $state(null)\n  let width = $state(0)\n  let height = $state(0)\n\n  $effect(() => {\n    const el = containerRef\n    if (!el) return\n    const measure = () => {\n      const rect = el.getBoundingClientRect()\n      width = rect.width\n      height = rect.height\n    }\n    measure()\n    if (typeof ResizeObserver === 'undefined') return\n    const ro = new ResizeObserver(() => measure())\n    ro.observe(el)\n    return () => ro.disconnect()\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 = $derived.by(() => {\n    if (!width || !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  })\n</script>\n\n<div bind:this={containerRef} data-uipkge data-slot=\"watermark\" class={cn('relative', className)} {...restProps}>\n  {@render children?.()}\n  <div\n    data-uipkge\n    data-slot=\"watermark-overlay\"\n    class=\"absolute inset-0 overflow-hidden\"\n    style:background-image={watermarkUrl ? `url(\"${watermarkUrl}\")` : undefined}\n    style:background-repeat=\"repeat\"\n    style:z-index={zIndex}\n    style:pointer-events={interactive ? 'auto' : 'none'}\n    aria-hidden=\"true\"\n  ></div>\n</div>\n",
      "type": "registry:ui",
      "target": "~/src/lib/components/ui/watermark/Watermark.svelte"
    },
    {
      "path": "packages/registry-svelte/components/watermark/index.ts",
      "content": "export { default as Watermark, type WatermarkProps } from './Watermark.svelte'\n",
      "type": "registry:ui",
      "target": "~/src/lib/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"
  ]
}