Skip to content
Open
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
21 changes: 13 additions & 8 deletions apps/www/public/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2338,6 +2338,7 @@ Description: A animated background grid pattern made with SVGs, fully customizab

import {
ComponentPropsWithoutRef,
useCallback,
useEffect,
useId,
useRef,
Expand Down Expand Up @@ -2375,6 +2376,18 @@ export function AnimatedGridPattern({
const id = useId()
const containerRef = useRef(null)
const [dimensions, setDimensions] = useState({ width: 0, height: 0 })

// Adjust the generateSquares function to return objects with an id, x, and y
const generateSquares = useCallback(
(count: number) => {
return Array.from({ length: count }, (_, i) => ({
id: i,
pos: getPos(),
}))
},
[dimensions.width, dimensions.height, width, height]
)

const [squares, setSquares] = useState(() => generateSquares(numSquares))

function getPos() {
Expand All @@ -2384,14 +2397,6 @@ export function AnimatedGridPattern({
]
}

// Adjust the generateSquares function to return objects with an id, x, and y
function generateSquares(count: number) {
return Array.from({ length: count }, (_, i) => ({
id: i,
pos: getPos(),
}))
}

// Function to update a single square's position
const updateSquarePosition = (id: number) => {
setSquares((currentSquares) =>
Expand Down
2 changes: 1 addition & 1 deletion apps/www/public/r/animated-grid-pattern.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"files": [
{
"path": "registry/magicui/animated-grid-pattern.tsx",
"content": "\"use client\"\n\nimport {\n ComponentPropsWithoutRef,\n useEffect,\n useId,\n useRef,\n useState,\n} from \"react\"\nimport { motion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface AnimatedGridPatternProps\n extends ComponentPropsWithoutRef<\"svg\"> {\n width?: number\n height?: number\n x?: number\n y?: number\n strokeDasharray?: number\n numSquares?: number\n maxOpacity?: number\n duration?: number\n repeatDelay?: number\n}\n\nexport function AnimatedGridPattern({\n width = 40,\n height = 40,\n x = -1,\n y = -1,\n strokeDasharray = 0,\n numSquares = 50,\n className,\n maxOpacity = 0.5,\n duration = 4,\n ...props\n}: AnimatedGridPatternProps) {\n const id = useId()\n const containerRef = useRef(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n const [squares, setSquares] = useState(() => generateSquares(numSquares))\n\n function getPos() {\n return [\n Math.floor((Math.random() * dimensions.width) / width),\n Math.floor((Math.random() * dimensions.height) / height),\n ]\n }\n\n // Adjust the generateSquares function to return objects with an id, x, and y\n function generateSquares(count: number) {\n return Array.from({ length: count }, (_, i) => ({\n id: i,\n pos: getPos(),\n }))\n }\n\n // Function to update a single square's position\n const updateSquarePosition = (id: number) => {\n setSquares((currentSquares) =>\n currentSquares.map((sq) =>\n sq.id === id\n ? {\n ...sq,\n pos: getPos(),\n }\n : sq\n )\n )\n }\n\n // Update squares to animate in\n useEffect(() => {\n if (dimensions.width && dimensions.height) {\n setSquares(generateSquares(numSquares))\n }\n }, [dimensions, numSquares, generateSquares])\n\n // Resize observer to update container dimensions\n useEffect(() => {\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n setDimensions({\n width: entry.contentRect.width,\n height: entry.contentRect.height,\n })\n }\n })\n\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current)\n }\n\n return () => {\n if (containerRef.current) {\n resizeObserver.unobserve(containerRef.current)\n }\n }\n }, [containerRef])\n\n return (\n <svg\n ref={containerRef}\n aria-hidden=\"true\"\n className={cn(\n \"pointer-events-none absolute inset-0 h-full w-full fill-gray-400/30 stroke-gray-400/30\",\n className\n )}\n {...props}\n >\n <defs>\n <pattern\n id={id}\n width={width}\n height={height}\n patternUnits=\"userSpaceOnUse\"\n x={x}\n y={y}\n >\n <path\n d={`M.5 ${height}V.5H${width}`}\n fill=\"none\"\n strokeDasharray={strokeDasharray}\n />\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill={`url(#${id})`} />\n <svg x={x} y={y} className=\"overflow-visible\">\n {squares.map(({ pos: [x, y], id }, index) => (\n <motion.rect\n initial={{ opacity: 0 }}\n animate={{ opacity: maxOpacity }}\n transition={{\n duration,\n repeat: 1,\n delay: index * 0.1,\n repeatType: \"reverse\",\n }}\n onAnimationComplete={() => updateSquarePosition(id)}\n key={`${x}-${y}-${index}`}\n width={width - 1}\n height={height - 1}\n x={x * width + 1}\n y={y * height + 1}\n fill=\"currentColor\"\n strokeWidth=\"0\"\n />\n ))}\n </svg>\n </svg>\n )\n}\n",
"content": "\"use client\"\n\nimport {\n ComponentPropsWithoutRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n} from \"react\"\nimport { motion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface AnimatedGridPatternProps\n extends ComponentPropsWithoutRef<\"svg\"> {\n width?: number\n height?: number\n x?: number\n y?: number\n strokeDasharray?: number\n numSquares?: number\n maxOpacity?: number\n duration?: number\n repeatDelay?: number\n}\n\nexport function AnimatedGridPattern({\n width = 40,\n height = 40,\n x = -1,\n y = -1,\n strokeDasharray = 0,\n numSquares = 50,\n className,\n maxOpacity = 0.5,\n duration = 4,\n ...props\n}: AnimatedGridPatternProps) {\n const id = useId()\n const containerRef = useRef(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n\n // Adjust the generateSquares function to return objects with an id, x, and y\n const generateSquares = useCallback(\n (count: number) => {\n return Array.from({ length: count }, (_, i) => ({\n id: i,\n pos: getPos(),\n }))\n },\n [dimensions.width, dimensions.height, width, height]\n )\n\n const [squares, setSquares] = useState(() => generateSquares(numSquares))\n\n function getPos() {\n return [\n Math.floor((Math.random() * dimensions.width) / width),\n Math.floor((Math.random() * dimensions.height) / height),\n ]\n }\n\n // Function to update a single square's position\n const updateSquarePosition = (id: number) => {\n setSquares((currentSquares) =>\n currentSquares.map((sq) =>\n sq.id === id\n ? {\n ...sq,\n pos: getPos(),\n }\n : sq\n )\n )\n }\n\n // Update squares to animate in\n useEffect(() => {\n if (dimensions.width && dimensions.height) {\n setSquares(generateSquares(numSquares))\n }\n }, [dimensions, numSquares, generateSquares])\n\n // Resize observer to update container dimensions\n useEffect(() => {\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n setDimensions({\n width: entry.contentRect.width,\n height: entry.contentRect.height,\n })\n }\n })\n\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current)\n }\n\n return () => {\n if (containerRef.current) {\n resizeObserver.unobserve(containerRef.current)\n }\n }\n }, [containerRef])\n\n return (\n <svg\n ref={containerRef}\n aria-hidden=\"true\"\n className={cn(\n \"pointer-events-none absolute inset-0 h-full w-full fill-gray-400/30 stroke-gray-400/30\",\n className\n )}\n {...props}\n >\n <defs>\n <pattern\n id={id}\n width={width}\n height={height}\n patternUnits=\"userSpaceOnUse\"\n x={x}\n y={y}\n >\n <path\n d={`M.5 ${height}V.5H${width}`}\n fill=\"none\"\n strokeDasharray={strokeDasharray}\n />\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill={`url(#${id})`} />\n <svg x={x} y={y} className=\"overflow-visible\">\n {squares.map(({ pos: [x, y], id }, index) => (\n <motion.rect\n initial={{ opacity: 0 }}\n animate={{ opacity: maxOpacity }}\n transition={{\n duration,\n repeat: 1,\n delay: index * 0.1,\n repeatType: \"reverse\",\n }}\n onAnimationComplete={() => updateSquarePosition(id)}\n key={`${x}-${y}-${index}`}\n width={width - 1}\n height={height - 1}\n x={x * width + 1}\n y={y * height + 1}\n fill=\"currentColor\"\n strokeWidth=\"0\"\n />\n ))}\n </svg>\n </svg>\n )\n}\n",
"type": "registry:ui"
}
]
Expand Down
21 changes: 13 additions & 8 deletions apps/www/registry/magicui/animated-grid-pattern.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import {
ComponentPropsWithoutRef,
useCallback,
useEffect,
useId,
useRef,
Expand Down Expand Up @@ -39,6 +40,18 @@ export function AnimatedGridPattern({
const id = useId()
const containerRef = useRef(null)
const [dimensions, setDimensions] = useState({ width: 0, height: 0 })

// Adjust the generateSquares function to return objects with an id, x, and y
const generateSquares = useCallback(
(count: number) => {
return Array.from({ length: count }, (_, i) => ({
id: i,
pos: getPos(),
}))
},
[dimensions.width, dimensions.height, width, height]
)

const [squares, setSquares] = useState(() => generateSquares(numSquares))

function getPos() {
Expand All @@ -48,14 +61,6 @@ export function AnimatedGridPattern({
]
}

// Adjust the generateSquares function to return objects with an id, x, and y
function generateSquares(count: number) {
return Array.from({ length: count }, (_, i) => ({
id: i,
pos: getPos(),
}))
}

// Function to update a single square's position
const updateSquarePosition = (id: number) => {
setSquares((currentSquares) =>
Expand Down