{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "motion-grid", "type": "registry:ui", "title": "Motion Grid", "description": "A grid that displays animations in a grid.", "dependencies": [ "motion" ], "files": [ { "path": "registry/components/motion-grid/index.tsx", "content": "'use client';\n\nimport * as React from 'react';\nimport { type HTMLMotionProps, motion } from 'motion/react';\n\nimport { cn } from '@/lib/utils';\n\ntype FrameDot = [number, number];\ntype Frame = FrameDot[];\ntype Frames = Frame[];\n\ntype MotionGridProps = {\n gridSize: [number, number];\n frames: Frames;\n duration?: number;\n animate?: boolean;\n cellClassName?: string;\n cellProps?: HTMLMotionProps<'div'>;\n cellActiveClassName?: string;\n cellInactiveClassName?: string;\n} & React.ComponentProps<'div'>;\n\nconst MotionGrid = ({\n gridSize,\n frames,\n duration = 200,\n animate = true,\n cellClassName,\n cellProps,\n cellActiveClassName,\n cellInactiveClassName,\n className,\n style,\n ...props\n}: MotionGridProps) => {\n const [index, setIndex] = React.useState(0);\n const intervalRef = React.useRef(null);\n\n React.useEffect(() => {\n if (!animate || frames.length === 0) return;\n intervalRef.current = setInterval(\n () => setIndex((i) => (i + 1) % frames.length),\n duration,\n );\n return () => clearInterval(intervalRef.current!);\n }, [frames.length, duration, animate]);\n\n const [cols, rows] = gridSize;\n\n const active = new Set(\n frames[index]?.map(([x, y]) => y * cols + x) ?? [],\n );\n\n return (\n \n {Array.from({ length: cols * rows }).map((_, i) => (\n \n ))}\n \n );\n};\n\nexport {\n MotionGrid,\n type MotionGridProps,\n type FrameDot,\n type Frame,\n type Frames,\n};\n", "type": "registry:ui", "target": "components/animate-ui/components/motion-grid.tsx" } ] }