Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 18 additions & 26 deletions apps/www/public/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8023,7 +8023,7 @@ Description: A text highlighter that mimics the effect of a human-drawn marker s
--- file: magicui/highlighter.tsx ---
"use client"

import { useEffect, useRef } from "react"
import { useLayoutEffect, useRef } from "react"
import type React from "react"
import { useInView } from "motion/react"
import { annotate } from "rough-notation"
Expand Down Expand Up @@ -8062,7 +8062,6 @@ export function Highlighter({
isView = false,
}: HighlighterProps) {
const elementRef = useRef<HTMLSpanElement>(null)
const annotationRef = useRef<RoughAnnotation | null>(null)

const isInView = useInView(elementRef, {
once: true,
Expand All @@ -8072,8 +8071,9 @@ export function Highlighter({
// If isView is false, always show. If isView is true, wait for inView
const shouldShow = !isView || isInView

useEffect(() => {
useLayoutEffect(() => {
const element = elementRef.current
let annotation: RoughAnnotation | null = null
let resizeObserver: ResizeObserver | null = null

if (shouldShow && element) {
Expand All @@ -8087,25 +8087,21 @@ export function Highlighter({
multiline,
}

const annotation = annotate(element, annotationConfig)

annotationRef.current = annotation
annotation.show()
const currentAnnotation = annotate(element, annotationConfig)
annotation = currentAnnotation
currentAnnotation.show()

resizeObserver = new ResizeObserver(() => {
annotation.hide()
annotation.show()
currentAnnotation.hide()
currentAnnotation.show()
})

resizeObserver.observe(element)
resizeObserver.observe(document.body)
}

return () => {
if (annotationRef.current) {
annotationRef.current.remove()
annotationRef.current = null
}
annotation?.remove()
if (resizeObserver) {
resizeObserver.disconnect()
}
Expand Down Expand Up @@ -8156,7 +8152,7 @@ export default function HighlighterDemo() {
--- file: magicui/highlighter.tsx ---
"use client"

import { useEffect, useRef } from "react"
import { useLayoutEffect, useRef } from "react"
import type React from "react"
import { useInView } from "motion/react"
import { annotate } from "rough-notation"
Expand Down Expand Up @@ -8195,7 +8191,6 @@ export function Highlighter({
isView = false,
}: HighlighterProps) {
const elementRef = useRef<HTMLSpanElement>(null)
const annotationRef = useRef<RoughAnnotation | null>(null)

const isInView = useInView(elementRef, {
once: true,
Expand All @@ -8205,8 +8200,9 @@ export function Highlighter({
// If isView is false, always show. If isView is true, wait for inView
const shouldShow = !isView || isInView

useEffect(() => {
useLayoutEffect(() => {
const element = elementRef.current
let annotation: RoughAnnotation | null = null
let resizeObserver: ResizeObserver | null = null

if (shouldShow && element) {
Expand All @@ -8220,25 +8216,21 @@ export function Highlighter({
multiline,
}

const annotation = annotate(element, annotationConfig)

annotationRef.current = annotation
annotation.show()
const currentAnnotation = annotate(element, annotationConfig)
annotation = currentAnnotation
currentAnnotation.show()

resizeObserver = new ResizeObserver(() => {
annotation.hide()
annotation.show()
currentAnnotation.hide()
currentAnnotation.show()
})

resizeObserver.observe(element)
resizeObserver.observe(document.body)
}

return () => {
if (annotationRef.current) {
annotationRef.current.remove()
annotationRef.current = null
}
annotation?.remove()
if (resizeObserver) {
resizeObserver.disconnect()
}
Expand Down
2 changes: 1 addition & 1 deletion apps/www/public/r/highlighter-demo.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
},
{
"path": "registry/magicui/highlighter.tsx",
"content": "\"use client\"\n\nimport { useEffect, useRef } from \"react\"\nimport type React from \"react\"\nimport { useInView } from \"motion/react\"\nimport { annotate } from \"rough-notation\"\nimport { type RoughAnnotation } from \"rough-notation/lib/model\"\n\ntype AnnotationAction =\n | \"highlight\"\n | \"underline\"\n | \"box\"\n | \"circle\"\n | \"strike-through\"\n | \"crossed-off\"\n | \"bracket\"\n\ninterface HighlighterProps {\n children: React.ReactNode\n action?: AnnotationAction\n color?: string\n strokeWidth?: number\n animationDuration?: number\n iterations?: number\n padding?: number\n multiline?: boolean\n isView?: boolean\n}\n\nexport function Highlighter({\n children,\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}: HighlighterProps) {\n const elementRef = useRef<HTMLSpanElement>(null)\n const annotationRef = useRef<RoughAnnotation | null>(null)\n\n const isInView = useInView(elementRef, {\n once: true,\n margin: \"-10%\",\n })\n\n // If isView is false, always show. If isView is true, wait for inView\n const shouldShow = !isView || isInView\n\n useEffect(() => {\n const element = elementRef.current\n let resizeObserver: ResizeObserver | null = null\n\n if (shouldShow && element) {\n const annotationConfig = {\n type: action,\n color,\n strokeWidth,\n animationDuration,\n iterations,\n padding,\n multiline,\n }\n\n const annotation = annotate(element, annotationConfig)\n\n annotationRef.current = annotation\n annotation.show()\n\n resizeObserver = new ResizeObserver(() => {\n annotation.hide()\n annotation.show()\n })\n\n resizeObserver.observe(element)\n resizeObserver.observe(document.body)\n }\n\n return () => {\n if (annotationRef.current) {\n annotationRef.current.remove()\n annotationRef.current = null\n }\n if (resizeObserver) {\n resizeObserver.disconnect()\n }\n }\n }, [\n shouldShow,\n action,\n color,\n strokeWidth,\n animationDuration,\n iterations,\n padding,\n multiline,\n ])\n\n return (\n <span ref={elementRef} className=\"relative inline-block bg-transparent\">\n {children}\n </span>\n )\n}\n",
"content": "\"use client\"\n\nimport { useLayoutEffect, useRef } from \"react\"\nimport type React from \"react\"\nimport { useInView } from \"motion/react\"\nimport { annotate } from \"rough-notation\"\nimport { type RoughAnnotation } from \"rough-notation/lib/model\"\n\ntype AnnotationAction =\n | \"highlight\"\n | \"underline\"\n | \"box\"\n | \"circle\"\n | \"strike-through\"\n | \"crossed-off\"\n | \"bracket\"\n\ninterface HighlighterProps {\n children: React.ReactNode\n action?: AnnotationAction\n color?: string\n strokeWidth?: number\n animationDuration?: number\n iterations?: number\n padding?: number\n multiline?: boolean\n isView?: boolean\n}\n\nexport function Highlighter({\n children,\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}: HighlighterProps) {\n const elementRef = useRef<HTMLSpanElement>(null)\n\n const isInView = useInView(elementRef, {\n once: true,\n margin: \"-10%\",\n })\n\n // If isView is false, always show. If isView is true, wait for inView\n const shouldShow = !isView || isInView\n\n 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 annotationConfig = {\n type: action,\n color,\n strokeWidth,\n animationDuration,\n iterations,\n padding,\n multiline,\n }\n\n const currentAnnotation = annotate(element, annotationConfig)\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 if (resizeObserver) {\n resizeObserver.disconnect()\n }\n }\n }, [\n shouldShow,\n action,\n color,\n strokeWidth,\n animationDuration,\n iterations,\n padding,\n multiline,\n ])\n\n return (\n <span ref={elementRef} className=\"relative inline-block bg-transparent\">\n {children}\n </span>\n )\n}\n",
"type": "registry:ui"
}
]
Expand Down
2 changes: 1 addition & 1 deletion apps/www/public/r/highlighter.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"files": [
{
"path": "registry/magicui/highlighter.tsx",
"content": "\"use client\"\n\nimport { useEffect, useRef } from \"react\"\nimport type React from \"react\"\nimport { useInView } from \"motion/react\"\nimport { annotate } from \"rough-notation\"\nimport { type RoughAnnotation } from \"rough-notation/lib/model\"\n\ntype AnnotationAction =\n | \"highlight\"\n | \"underline\"\n | \"box\"\n | \"circle\"\n | \"strike-through\"\n | \"crossed-off\"\n | \"bracket\"\n\ninterface HighlighterProps {\n children: React.ReactNode\n action?: AnnotationAction\n color?: string\n strokeWidth?: number\n animationDuration?: number\n iterations?: number\n padding?: number\n multiline?: boolean\n isView?: boolean\n}\n\nexport function Highlighter({\n children,\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}: HighlighterProps) {\n const elementRef = useRef<HTMLSpanElement>(null)\n const annotationRef = useRef<RoughAnnotation | null>(null)\n\n const isInView = useInView(elementRef, {\n once: true,\n margin: \"-10%\",\n })\n\n // If isView is false, always show. If isView is true, wait for inView\n const shouldShow = !isView || isInView\n\n useEffect(() => {\n const element = elementRef.current\n let resizeObserver: ResizeObserver | null = null\n\n if (shouldShow && element) {\n const annotationConfig = {\n type: action,\n color,\n strokeWidth,\n animationDuration,\n iterations,\n padding,\n multiline,\n }\n\n const annotation = annotate(element, annotationConfig)\n\n annotationRef.current = annotation\n annotation.show()\n\n resizeObserver = new ResizeObserver(() => {\n annotation.hide()\n annotation.show()\n })\n\n resizeObserver.observe(element)\n resizeObserver.observe(document.body)\n }\n\n return () => {\n if (annotationRef.current) {\n annotationRef.current.remove()\n annotationRef.current = null\n }\n if (resizeObserver) {\n resizeObserver.disconnect()\n }\n }\n }, [\n shouldShow,\n action,\n color,\n strokeWidth,\n animationDuration,\n iterations,\n padding,\n multiline,\n ])\n\n return (\n <span ref={elementRef} className=\"relative inline-block bg-transparent\">\n {children}\n </span>\n )\n}\n",
"content": "\"use client\"\n\nimport { useLayoutEffect, useRef } from \"react\"\nimport type React from \"react\"\nimport { useInView } from \"motion/react\"\nimport { annotate } from \"rough-notation\"\nimport { type RoughAnnotation } from \"rough-notation/lib/model\"\n\ntype AnnotationAction =\n | \"highlight\"\n | \"underline\"\n | \"box\"\n | \"circle\"\n | \"strike-through\"\n | \"crossed-off\"\n | \"bracket\"\n\ninterface HighlighterProps {\n children: React.ReactNode\n action?: AnnotationAction\n color?: string\n strokeWidth?: number\n animationDuration?: number\n iterations?: number\n padding?: number\n multiline?: boolean\n isView?: boolean\n}\n\nexport function Highlighter({\n children,\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}: HighlighterProps) {\n const elementRef = useRef<HTMLSpanElement>(null)\n\n const isInView = useInView(elementRef, {\n once: true,\n margin: \"-10%\",\n })\n\n // If isView is false, always show. If isView is true, wait for inView\n const shouldShow = !isView || isInView\n\n 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 annotationConfig = {\n type: action,\n color,\n strokeWidth,\n animationDuration,\n iterations,\n padding,\n multiline,\n }\n\n const currentAnnotation = annotate(element, annotationConfig)\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 if (resizeObserver) {\n resizeObserver.disconnect()\n }\n }\n }, [\n shouldShow,\n action,\n color,\n strokeWidth,\n animationDuration,\n iterations,\n padding,\n multiline,\n ])\n\n return (\n <span ref={elementRef} className=\"relative inline-block bg-transparent\">\n {children}\n </span>\n )\n}\n",
"type": "registry:ui"
}
]
Expand Down
22 changes: 9 additions & 13 deletions apps/www/registry/magicui/highlighter.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client"

import { useEffect, useRef } from "react"
import { useLayoutEffect, useRef } from "react"
import type React from "react"
import { useInView } from "motion/react"
import { annotate } from "rough-notation"
Expand Down Expand Up @@ -39,7 +39,6 @@ export function Highlighter({
isView = false,
}: HighlighterProps) {
const elementRef = useRef<HTMLSpanElement>(null)
const annotationRef = useRef<RoughAnnotation | null>(null)

const isInView = useInView(elementRef, {
once: true,
Expand All @@ -49,8 +48,9 @@ export function Highlighter({
// If isView is false, always show. If isView is true, wait for inView
const shouldShow = !isView || isInView

useEffect(() => {
useLayoutEffect(() => {
const element = elementRef.current
let annotation: RoughAnnotation | null = null
let resizeObserver: ResizeObserver | null = null

if (shouldShow && element) {
Expand All @@ -64,25 +64,21 @@ export function Highlighter({
multiline,
}

const annotation = annotate(element, annotationConfig)

annotationRef.current = annotation
annotation.show()
const currentAnnotation = annotate(element, annotationConfig)
annotation = currentAnnotation
currentAnnotation.show()

resizeObserver = new ResizeObserver(() => {
annotation.hide()
annotation.show()
currentAnnotation.hide()
currentAnnotation.show()
})

resizeObserver.observe(element)
resizeObserver.observe(document.body)
}

return () => {
if (annotationRef.current) {
annotationRef.current.remove()
annotationRef.current = null
}
annotation?.remove()
if (resizeObserver) {
resizeObserver.disconnect()
}
Expand Down
Loading