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
40 changes: 21 additions & 19 deletions apps/www/content/docs/components/animated-beam.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,25 +73,27 @@ import { AnimatedBeam } from "@/components/ui/animated-beam"

### Animated Beam

| Prop | Type | Default | Description |
| -------------------- | --------- | --------- | -------------------------------------------------------- |
| `className` | `string` | `-` | The class name for the component. |
| `containerRef` | `ref` | `-` | The container ref. |
| `fromRef` | `ref` | `-` | The ref of the element from which the beam should start. |
| `toRef` | `ref` | `-` | The ref of the element to which the beam should end. |
| `curvature` | `number` | `0` | The curvature of the beam. |
| `reverse` | `boolean` | `false` | Whether the beam should be reversed. |
| `duration` | `number` | `5` | The duration of the beam. |
| `delay` | `number` | `0` | The delay of the beam. |
| `pathColor` | `string` | `gray` | The color of the beam. |
| `pathWidth` | `number` | `2` | The width of the beam. |
| `pathOpacity` | `number` | `0.2` | The opacity of the beam. |
| `gradientStartColor` | `string` | `#ffaa40` | The start color of the gradient. |
| `gradientStopColor` | `string` | `#9c40ff` | The stop color of the gradient. |
| `startXOffset` | `number` | `0` | The start x offset of the beam. |
| `startYOffset` | `number` | `0` | The start y offset of the beam. |
| `endXOffset` | `number` | `0` | The end x offset of the beam. |
| `endYOffset` | `number` | `0` | The end y offset of the beam. |
| Prop | Type | Default | Description |
| -------------------- | --------- | ---------- | -------------------------------------------------------- |
| `className` | `string` | `-` | The class name for the component. |
| `containerRef` | `ref` | `-` | The container ref. |
| `fromRef` | `ref` | `-` | The ref of the element from which the beam should start. |
| `toRef` | `ref` | `-` | The ref of the element to which the beam should end. |
| `curvature` | `number` | `0` | The curvature of the beam. |
| `reverse` | `boolean` | `false` | Whether the beam should be reversed. |
| `duration` | `number` | `5` | The duration of the beam. |
| `delay` | `number` | `0` | The delay of the beam. |
| `repeat` | `number` | `Infinity` | The number of times the beam animation should repeat. |
| `repeatDelay` | `number` | `0` | The delay between repeated beam animation cycles. |
| `pathColor` | `string` | `gray` | The color of the beam. |
| `pathWidth` | `number` | `2` | The width of the beam. |
| `pathOpacity` | `number` | `0.2` | The opacity of the beam. |
| `gradientStartColor` | `string` | `#ffaa40` | The start color of the gradient. |
| `gradientStopColor` | `string` | `#9c40ff` | The stop color of the gradient. |
| `startXOffset` | `number` | `0` | The start x offset of the beam. |
| `startYOffset` | `number` | `0` | The start y offset of the beam. |
| `endXOffset` | `number` | `0` | The end x offset of the beam. |
| `endYOffset` | `number` | `0` | The end y offset of the beam. |

## Credits

Expand Down
12 changes: 8 additions & 4 deletions apps/www/public/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ Description: An animated beam of light which travels along a path. Useful for sh
--- file: magicui/animated-beam.tsx ---
"use client"

import { RefObject, useEffect, useId, useState } from "react"
import { useEffect, useId, useState, type RefObject } from "react"
import { motion } from "motion/react"

import { cn } from "@/lib/utils"
Expand All @@ -185,6 +185,8 @@ export interface AnimatedBeamProps {
gradientStopColor?: string
delay?: number
duration?: number
repeat?: number
repeatDelay?: number
startXOffset?: number
startYOffset?: number
endXOffset?: number
Expand All @@ -198,13 +200,15 @@ export const AnimatedBeam: React.FC<AnimatedBeamProps> = ({
toRef,
curvature = 0,
reverse = false, // Include the reverse prop
duration = Math.random() * 3 + 4,
duration = 5,
delay = 0,
pathColor = "gray",
pathWidth = 2,
pathOpacity = 0.2,
gradientStartColor = "#ffaa40",
gradientStopColor = "#9c40ff",
repeat = Infinity,
repeatDelay = 0,
startXOffset = 0,
startYOffset = 0,
endXOffset = 0,
Expand Down Expand Up @@ -332,8 +336,8 @@ export const AnimatedBeam: React.FC<AnimatedBeamProps> = ({
delay,
duration,
ease: [0.16, 1, 0.3, 1], // https://easings.net/#easeOutExpo
repeat: Infinity,
repeatDelay: 0,
repeat,
repeatDelay,
}}
>
<stop stopColor={gradientStartColor} stopOpacity="0"></stop>
Expand Down
2 changes: 1 addition & 1 deletion apps/www/public/r/animated-beam.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"files": [
{
"path": "registry/magicui/animated-beam.tsx",
"content": "\"use client\"\n\nimport { RefObject, useEffect, useId, useState } from \"react\"\nimport { motion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface AnimatedBeamProps {\n className?: string\n containerRef: RefObject<HTMLElement | null> // Container ref\n fromRef: RefObject<HTMLElement | null>\n toRef: RefObject<HTMLElement | null>\n curvature?: number\n reverse?: boolean\n pathColor?: string\n pathWidth?: number\n pathOpacity?: number\n gradientStartColor?: string\n gradientStopColor?: string\n delay?: number\n duration?: number\n startXOffset?: number\n startYOffset?: number\n endXOffset?: number\n endYOffset?: number\n}\n\nexport const AnimatedBeam: React.FC<AnimatedBeamProps> = ({\n className,\n containerRef,\n fromRef,\n toRef,\n curvature = 0,\n reverse = false, // Include the reverse prop\n duration = Math.random() * 3 + 4,\n delay = 0,\n pathColor = \"gray\",\n pathWidth = 2,\n pathOpacity = 0.2,\n gradientStartColor = \"#ffaa40\",\n gradientStopColor = \"#9c40ff\",\n startXOffset = 0,\n startYOffset = 0,\n endXOffset = 0,\n endYOffset = 0,\n}) => {\n const id = useId()\n const [pathD, setPathD] = useState(\"\")\n const [svgDimensions, setSvgDimensions] = useState({ width: 0, height: 0 })\n\n // Calculate the gradient coordinates based on the reverse prop\n const gradientCoordinates = reverse\n ? {\n x1: [\"90%\", \"-10%\"],\n x2: [\"100%\", \"0%\"],\n y1: [\"0%\", \"0%\"],\n y2: [\"0%\", \"0%\"],\n }\n : {\n x1: [\"10%\", \"110%\"],\n x2: [\"0%\", \"100%\"],\n y1: [\"0%\", \"0%\"],\n y2: [\"0%\", \"0%\"],\n }\n\n useEffect(() => {\n const updatePath = () => {\n if (containerRef.current && fromRef.current && toRef.current) {\n const containerRect = containerRef.current.getBoundingClientRect()\n const rectA = fromRef.current.getBoundingClientRect()\n const rectB = toRef.current.getBoundingClientRect()\n\n const svgWidth = containerRect.width\n const svgHeight = containerRect.height\n setSvgDimensions({ width: svgWidth, height: svgHeight })\n\n const startX =\n rectA.left - containerRect.left + rectA.width / 2 + startXOffset\n const startY =\n rectA.top - containerRect.top + rectA.height / 2 + startYOffset\n const endX =\n rectB.left - containerRect.left + rectB.width / 2 + endXOffset\n const endY =\n rectB.top - containerRect.top + rectB.height / 2 + endYOffset\n\n const controlY = startY - curvature\n const d = `M ${startX},${startY} Q ${\n (startX + endX) / 2\n },${controlY} ${endX},${endY}`\n setPathD(d)\n }\n }\n\n // Initialize ResizeObserver\n const resizeObserver = new ResizeObserver(() => {\n updatePath()\n })\n\n // Observe the container element\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current)\n }\n\n // Call the updatePath initially to set the initial path\n updatePath()\n\n // Clean up the observer on component unmount\n return () => {\n resizeObserver.disconnect()\n }\n }, [\n containerRef,\n fromRef,\n toRef,\n curvature,\n startXOffset,\n startYOffset,\n endXOffset,\n endYOffset,\n ])\n\n return (\n <svg\n fill=\"none\"\n width={svgDimensions.width}\n height={svgDimensions.height}\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cn(\n \"pointer-events-none absolute top-0 left-0 transform-gpu stroke-2\",\n className\n )}\n viewBox={`0 0 ${svgDimensions.width} ${svgDimensions.height}`}\n >\n <path\n d={pathD}\n stroke={pathColor}\n strokeWidth={pathWidth}\n strokeOpacity={pathOpacity}\n strokeLinecap=\"round\"\n />\n <path\n d={pathD}\n strokeWidth={pathWidth}\n stroke={`url(#${id})`}\n strokeOpacity=\"1\"\n strokeLinecap=\"round\"\n />\n <defs>\n <motion.linearGradient\n className=\"transform-gpu\"\n id={id}\n gradientUnits={\"userSpaceOnUse\"}\n initial={{\n x1: \"0%\",\n x2: \"0%\",\n y1: \"0%\",\n y2: \"0%\",\n }}\n animate={{\n x1: gradientCoordinates.x1,\n x2: gradientCoordinates.x2,\n y1: gradientCoordinates.y1,\n y2: gradientCoordinates.y2,\n }}\n transition={{\n delay,\n duration,\n ease: [0.16, 1, 0.3, 1], // https://easings.net/#easeOutExpo\n repeat: Infinity,\n repeatDelay: 0,\n }}\n >\n <stop stopColor={gradientStartColor} stopOpacity=\"0\"></stop>\n <stop stopColor={gradientStartColor}></stop>\n <stop offset=\"32.5%\" stopColor={gradientStopColor}></stop>\n <stop\n offset=\"100%\"\n stopColor={gradientStopColor}\n stopOpacity=\"0\"\n ></stop>\n </motion.linearGradient>\n </defs>\n </svg>\n )\n}\n",
"content": "\"use client\"\n\nimport { useEffect, useId, useState, type RefObject } from \"react\"\nimport { motion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface AnimatedBeamProps {\n className?: string\n containerRef: RefObject<HTMLElement | null> // Container ref\n fromRef: RefObject<HTMLElement | null>\n toRef: RefObject<HTMLElement | null>\n curvature?: number\n reverse?: boolean\n pathColor?: string\n pathWidth?: number\n pathOpacity?: number\n gradientStartColor?: string\n gradientStopColor?: string\n delay?: number\n duration?: number\n repeat?: number\n repeatDelay?: number\n startXOffset?: number\n startYOffset?: number\n endXOffset?: number\n endYOffset?: number\n}\n\nexport const AnimatedBeam: React.FC<AnimatedBeamProps> = ({\n className,\n containerRef,\n fromRef,\n toRef,\n curvature = 0,\n reverse = false, // Include the reverse prop\n duration = 5,\n delay = 0,\n pathColor = \"gray\",\n pathWidth = 2,\n pathOpacity = 0.2,\n gradientStartColor = \"#ffaa40\",\n gradientStopColor = \"#9c40ff\",\n repeat = Infinity,\n repeatDelay = 0,\n startXOffset = 0,\n startYOffset = 0,\n endXOffset = 0,\n endYOffset = 0,\n}) => {\n const id = useId()\n const [pathD, setPathD] = useState(\"\")\n const [svgDimensions, setSvgDimensions] = useState({ width: 0, height: 0 })\n\n // Calculate the gradient coordinates based on the reverse prop\n const gradientCoordinates = reverse\n ? {\n x1: [\"90%\", \"-10%\"],\n x2: [\"100%\", \"0%\"],\n y1: [\"0%\", \"0%\"],\n y2: [\"0%\", \"0%\"],\n }\n : {\n x1: [\"10%\", \"110%\"],\n x2: [\"0%\", \"100%\"],\n y1: [\"0%\", \"0%\"],\n y2: [\"0%\", \"0%\"],\n }\n\n useEffect(() => {\n const updatePath = () => {\n if (containerRef.current && fromRef.current && toRef.current) {\n const containerRect = containerRef.current.getBoundingClientRect()\n const rectA = fromRef.current.getBoundingClientRect()\n const rectB = toRef.current.getBoundingClientRect()\n\n const svgWidth = containerRect.width\n const svgHeight = containerRect.height\n setSvgDimensions({ width: svgWidth, height: svgHeight })\n\n const startX =\n rectA.left - containerRect.left + rectA.width / 2 + startXOffset\n const startY =\n rectA.top - containerRect.top + rectA.height / 2 + startYOffset\n const endX =\n rectB.left - containerRect.left + rectB.width / 2 + endXOffset\n const endY =\n rectB.top - containerRect.top + rectB.height / 2 + endYOffset\n\n const controlY = startY - curvature\n const d = `M ${startX},${startY} Q ${\n (startX + endX) / 2\n },${controlY} ${endX},${endY}`\n setPathD(d)\n }\n }\n\n // Initialize ResizeObserver\n const resizeObserver = new ResizeObserver(() => {\n updatePath()\n })\n\n // Observe the container element\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current)\n }\n\n // Call the updatePath initially to set the initial path\n updatePath()\n\n // Clean up the observer on component unmount\n return () => {\n resizeObserver.disconnect()\n }\n }, [\n containerRef,\n fromRef,\n toRef,\n curvature,\n startXOffset,\n startYOffset,\n endXOffset,\n endYOffset,\n ])\n\n return (\n <svg\n fill=\"none\"\n width={svgDimensions.width}\n height={svgDimensions.height}\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cn(\n \"pointer-events-none absolute top-0 left-0 transform-gpu stroke-2\",\n className\n )}\n viewBox={`0 0 ${svgDimensions.width} ${svgDimensions.height}`}\n >\n <path\n d={pathD}\n stroke={pathColor}\n strokeWidth={pathWidth}\n strokeOpacity={pathOpacity}\n strokeLinecap=\"round\"\n />\n <path\n d={pathD}\n strokeWidth={pathWidth}\n stroke={`url(#${id})`}\n strokeOpacity=\"1\"\n strokeLinecap=\"round\"\n />\n <defs>\n <motion.linearGradient\n className=\"transform-gpu\"\n id={id}\n gradientUnits={\"userSpaceOnUse\"}\n initial={{\n x1: \"0%\",\n x2: \"0%\",\n y1: \"0%\",\n y2: \"0%\",\n }}\n animate={{\n x1: gradientCoordinates.x1,\n x2: gradientCoordinates.x2,\n y1: gradientCoordinates.y1,\n y2: gradientCoordinates.y2,\n }}\n transition={{\n delay,\n duration,\n ease: [0.16, 1, 0.3, 1], // https://easings.net/#easeOutExpo\n repeat,\n repeatDelay,\n }}\n >\n <stop stopColor={gradientStartColor} stopOpacity=\"0\"></stop>\n <stop stopColor={gradientStartColor}></stop>\n <stop offset=\"32.5%\" stopColor={gradientStopColor}></stop>\n <stop\n offset=\"100%\"\n stopColor={gradientStopColor}\n stopOpacity=\"0\"\n ></stop>\n </motion.linearGradient>\n </defs>\n </svg>\n )\n}\n",
"type": "registry:ui"
}
]
Expand Down
12 changes: 8 additions & 4 deletions apps/www/registry/magicui/animated-beam.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client"

import { RefObject, useEffect, useId, useState } from "react"
import { useEffect, useId, useState, type RefObject } from "react"
import { motion } from "motion/react"

import { cn } from "@/lib/utils"
Expand All @@ -19,6 +19,8 @@ export interface AnimatedBeamProps {
gradientStopColor?: string
delay?: number
duration?: number
repeat?: number
repeatDelay?: number
startXOffset?: number
startYOffset?: number
endXOffset?: number
Expand All @@ -32,13 +34,15 @@ export const AnimatedBeam: React.FC<AnimatedBeamProps> = ({
toRef,
curvature = 0,
reverse = false, // Include the reverse prop
duration = Math.random() * 3 + 4,
duration = 5,
delay = 0,
pathColor = "gray",
pathWidth = 2,
pathOpacity = 0.2,
gradientStartColor = "#ffaa40",
gradientStopColor = "#9c40ff",
repeat = Infinity,
repeatDelay = 0,
startXOffset = 0,
startYOffset = 0,
endXOffset = 0,
Expand Down Expand Up @@ -166,8 +170,8 @@ export const AnimatedBeam: React.FC<AnimatedBeamProps> = ({
delay,
duration,
ease: [0.16, 1, 0.3, 1], // https://easings.net/#easeOutExpo
repeat: Infinity,
repeatDelay: 0,
repeat,
repeatDelay,
}}
>
<stop stopColor={gradientStartColor} stopOpacity="0"></stop>
Expand Down
Loading