{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "highlighter",
  "title": "Highlighter",
  "description": "Hand-drawn rough-notation annotations (highlight, underline, box, circle) over text.",
  "dependencies": ["framer-motion", "rough-notation"],
  "registryDependencies": ["@godui/godui-theme"],
  "files": [
    {
      "path": "packages/components/src/highlighter/highlighter.tsx",
      "content": "\"use client\";\n\nimport { useInView } from \"framer-motion\";\nimport * as React from \"react\";\nimport { annotate } from \"rough-notation\";\nimport type { RoughAnnotation } from \"rough-notation/lib/model\";\n\nexport type HighlighterAction =\n  | \"highlight\"\n  | \"underline\"\n  | \"box\"\n  | \"circle\"\n  | \"strike-through\"\n  | \"crossed-off\"\n  | \"bracket\";\n\nexport type HighlighterProps = React.HTMLAttributes<HTMLSpanElement> & {\n  children: React.ReactNode;\n  /** Annotation style drawn over the text */\n  action?: HighlighterAction;\n  /** Annotation color (any CSS color string) */\n  color?: string;\n  /** Stroke width of the sketch annotation */\n  strokeWidth?: number;\n  /** Duration of the draw-in animation in milliseconds */\n  animationDuration?: number;\n  /** Number of sketch passes (higher looks more hand-drawn) */\n  iterations?: number;\n  /** Padding between the text and the annotation */\n  padding?: number;\n  /** Allow the annotation to wrap across multiple lines */\n  multiline?: boolean;\n  /** Only draw the annotation once the element scrolls into view */\n  isView?: boolean;\n};\n\nconst Highlighter = React.forwardRef<HTMLSpanElement, HighlighterProps>(\n  (\n    {\n      children,\n      className,\n      action = \"highlight\",\n      color = \"#ffd1dc\",\n      strokeWidth = 1.5,\n      animationDuration = 600,\n      iterations = 2,\n      padding = 2,\n      multiline = true,\n      isView = false,\n      ...props\n    },\n    ref,\n  ) => {\n    const elementRef = React.useRef<HTMLSpanElement>(null);\n    const mergedRef = React.useCallback(\n      (node: HTMLSpanElement | null) => {\n        elementRef.current = node;\n        if (typeof ref === \"function\") {\n          ref(node);\n        } else if (ref) {\n          ref.current = node;\n        }\n      },\n      [ref],\n    );\n\n    const isInView = useInView(elementRef, {\n      once: true,\n      margin: \"-10%\",\n    });\n\n    const shouldShow = !isView || isInView;\n\n    React.useLayoutEffect(() => {\n      const element = elementRef.current;\n      let annotation: RoughAnnotation | null = null;\n      let resizeObserver: ResizeObserver | null = null;\n\n      if (shouldShow && element) {\n        const currentAnnotation = annotate(element, {\n          type: action,\n          color,\n          strokeWidth,\n          animationDuration,\n          iterations,\n          padding,\n          multiline,\n        });\n        annotation = currentAnnotation;\n        currentAnnotation.show();\n\n        resizeObserver = new ResizeObserver(() => {\n          currentAnnotation.hide();\n          currentAnnotation.show();\n        });\n\n        resizeObserver.observe(element);\n        resizeObserver.observe(document.body);\n      }\n\n      return () => {\n        annotation?.remove();\n        resizeObserver?.disconnect();\n      };\n    }, [\n      shouldShow,\n      action,\n      color,\n      strokeWidth,\n      animationDuration,\n      iterations,\n      padding,\n      multiline,\n    ]);\n\n    // The highlight marker paints a pale fill *behind* the text, so it needs\n    // dark text to stay legible on any theme (like a real highlighter pen).\n    // Other actions draw around the text, which keeps the inherited color.\n    const actionTextClass = action === \"highlight\" ? \"text-neutral-950\" : \"\";\n\n    return (\n      <span\n        ref={mergedRef}\n        className={`relative inline-block bg-transparent ${actionTextClass} ${className ?? \"\"}`}\n        {...props}\n      >\n        {children}\n      </span>\n    );\n  },\n);\nHighlighter.displayName = \"Highlighter\";\n\nexport { Highlighter };\n",
      "type": "registry:ui",
      "target": "components/godui/highlighter.tsx"
    }
  ],
  "type": "registry:ui"
}
