{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "primitives-animate-motion-grid",
  "title": "Motion Grid",
  "description": "A grid that displays animations in a grid.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "@animate-ui/primitives-animate-slot",
    "@animate-ui/lib-get-strict-context"
  ],
  "files": [
    {
      "path": "registry/primitives/animate/motion-grid/index.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { motion, type HTMLMotionProps } from 'motion/react';\n\nimport { cn } from '@/lib/utils';\nimport { getStrictContext } from '@/lib/get-strict-context';\nimport { Slot, type WithAsChild } from '@/components/animate-ui/primitives/animate/slot';\n\ntype FrameDot = [number, number];\ntype Frame = FrameDot[];\ntype Frames = Frame[];\n\ntype MotionGridContextType = {\n  index: number;\n  cols: number;\n  rows: number;\n  frames: Frames;\n  duration: number;\n  animate: boolean;\n};\n\nconst [MotionGridProvider, useMotionGrid] =\n  getStrictContext<MotionGridContextType>('MotionGridContext');\n\ntype MotionGridProps = WithAsChild<\n  {\n    gridSize: [number, number];\n    frames: Frames;\n    duration?: number;\n    animate?: boolean;\n  } & HTMLMotionProps<'div'>\n>;\n\nconst MotionGrid = ({\n  gridSize,\n  frames,\n  duration = 200,\n  animate = true,\n  asChild = false,\n  style,\n  ...props\n}: MotionGridProps) => {\n  const [index, setIndex] = React.useState(0);\n  const intervalRef = React.useRef<NodeJS.Timeout | null>(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 Component = asChild ? Slot : motion.div;\n\n  return (\n    <MotionGridProvider\n      value={{ animate, index, cols, rows, frames, duration }}\n    >\n      <Component\n        data-animate={animate}\n        style={{\n          display: 'grid',\n          gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))`,\n          gridAutoRows: '1fr',\n          ...style,\n        }}\n        {...props}\n      />\n    </MotionGridProvider>\n  );\n};\n\ntype MotionGridCellsProps = HTMLMotionProps<'div'> & {\n  activeProps?: HTMLMotionProps<'div'>;\n  inactiveProps?: HTMLMotionProps<'div'>;\n};\n\nfunction MotionGridCells({\n  activeProps,\n  inactiveProps,\n  ...props\n}: MotionGridCellsProps) {\n  const { animate, index, cols, rows, frames, duration } = useMotionGrid();\n\n  const active = new Set<number>(\n    frames[index]?.map(([x, y]) => y * cols + x) ?? [],\n  );\n\n  return Array.from({ length: cols * rows }).map((_, i) => {\n    const isActive = active.has(i);\n    const componentProps: HTMLMotionProps<'div'> = {\n      ...(isActive ? activeProps : inactiveProps),\n    };\n    componentProps.className = cn(\n      props?.className,\n      isActive ? activeProps?.className : inactiveProps?.className,\n    );\n    componentProps.style = {\n      ...props?.style,\n      ...(isActive ? activeProps?.style : inactiveProps?.style),\n    };\n\n    return (\n      <motion.div\n        key={i}\n        data-active={isActive}\n        data-animate={animate}\n        transition={{ duration, ease: 'easeInOut' }}\n        {...props}\n        {...componentProps}\n      />\n    );\n  });\n}\n\nexport {\n  MotionGrid,\n  MotionGridCells,\n  type MotionGridProps,\n  type MotionGridCellsProps,\n  type FrameDot,\n  type Frame,\n  type Frames,\n};\n",
      "type": "registry:ui",
      "target": "components/animate-ui/primitives/animate/motion-grid.tsx"
    }
  ],
  "type": "registry:ui"
}