{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "image-comparison-motion",
  "type": "registry:component",
  "description": "A component for comparing two images with a slider.",
  "dependencies": [
    "motion/react"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "src/app/components/animatedComponents/cards/image-comparison/ImageComparisonMotion.tsx",
      "content": "'use client';\r\nimport { cn } from '@/lib/utils';\r\nimport { useState, createContext, useContext } from 'react';\r\nimport {\r\n  motion,\r\n  MotionValue,\r\n  SpringOptions,\r\n  useMotionValue,\r\n  useSpring,\r\n  useTransform,\r\n} from 'motion/react';\r\n\r\n\r\nconst ImageComparisonContext = createContext<\r\n  | {\r\n    sliderPosition: number;\r\n    setSliderPosition: (pos: number) => void;\r\n    motionSliderPosition: MotionValue<number>;\r\n  }\r\n  | undefined\r\n>(undefined);\r\n\r\nexport type ImageComparisonProps = {\r\n  children: React.ReactNode;\r\n  className?: string;\r\n  enableHover?: boolean;\r\n  springOptions?: SpringOptions;\r\n};\r\n\r\nconst DEFAULT_SPRING_OPTIONS = {\r\n  bounce: 0,\r\n  duration: 0,\r\n};\r\n\r\nfunction ImageComparison({\r\n  children,\r\n  className,\r\n  enableHover,\r\n  springOptions,\r\n}: ImageComparisonProps) {\r\n  const [isDragging, setIsDragging] = useState(false);\r\n  const motionValue = useMotionValue(50);\r\n  const motionSliderPosition = useSpring(\r\n    motionValue,\r\n    springOptions ?? DEFAULT_SPRING_OPTIONS\r\n  );\r\n  const [sliderPosition, setSliderPosition] = useState(50);\r\n\r\n  const handleDrag = (event: React.MouseEvent | React.TouchEvent) => {\r\n    if (!isDragging && !enableHover) return;\r\n\r\n    const containerRect = (\r\n      event.currentTarget as HTMLElement\r\n    ).getBoundingClientRect();\r\n    const x =\r\n      'touches' in event\r\n        ? event.touches[0].clientX - containerRect.left\r\n        : (event as React.MouseEvent).clientX - containerRect.left;\r\n\r\n    const percentage = Math.min(\r\n      Math.max((x / containerRect.width) * 100, 0),\r\n      100\r\n    );\r\n    motionValue.set(percentage);\r\n    setSliderPosition(percentage);\r\n  };\r\n\r\n  return (\r\n    <ImageComparisonContext.Provider\r\n      value={{ sliderPosition, setSliderPosition, motionSliderPosition }}\r\n    >\r\n      <div\r\n        className={cn(\r\n          'relative select-none overflow-hidden',\r\n          enableHover && 'cursor-ew-resize',\r\n          className\r\n        )}\r\n        onMouseMove={handleDrag}\r\n        onMouseDown={() => !enableHover && setIsDragging(true)}\r\n        onMouseUp={() => !enableHover && setIsDragging(false)}\r\n        onMouseLeave={() => !enableHover && setIsDragging(false)}\r\n        onTouchMove={handleDrag}\r\n        onTouchStart={() => !enableHover && setIsDragging(true)}\r\n        onTouchEnd={() => !enableHover && setIsDragging(false)}\r\n      >\r\n        {children}\r\n      </div>\r\n    </ImageComparisonContext.Provider>\r\n  );\r\n}\r\n\r\nconst ImageComparisonImage = ({\r\n  className,\r\n  alt,\r\n  src,\r\n  position,\r\n}: {\r\n  className?: string;\r\n  alt: string;\r\n  src: string;\r\n  position: 'left' | 'right';\r\n}) => {\r\n  const { motionSliderPosition } = useContext(ImageComparisonContext)!;\r\n  const leftClipPath = useTransform(\r\n    motionSliderPosition,\r\n    (value) => `inset(0 0 0 ${value}%)`\r\n  );\r\n  const rightClipPath = useTransform(\r\n    motionSliderPosition,\r\n    (value) => `inset(0 ${100 - value}% 0 0)`\r\n  );\r\n\r\n  return (\r\n    <motion.img\r\n      src={src}\r\n      alt={alt}\r\n      className={cn('absolute inset-0 h-full w-full object-cover', className)}\r\n      style={{\r\n        clipPath: position === 'left' ? leftClipPath : rightClipPath,\r\n      }}\r\n    />\r\n  );\r\n};\r\n\r\nconst ImageComparisonSlider = ({\r\n  className,\r\n  children,\r\n}: {\r\n  className: string;\r\n  children?: React.ReactNode;\r\n}) => {\r\n  const { motionSliderPosition } = useContext(ImageComparisonContext)!;\r\n\r\n  const left = useTransform(motionSliderPosition, (value) => `${value}%`);\r\n\r\n  return (\r\n    <motion.div\r\n      className={cn('absolute bottom-0 top-0 w-1 cursor-ew-resize', className)}\r\n      style={{\r\n        left,\r\n      }}\r\n    >\r\n      {children}\r\n    </motion.div>\r\n  );\r\n};\r\n\r\nexport default function ImageComparisonMotion() {\r\n  return (\r\n    <ImageComparison className='aspect-16/10 w-full lg:max-w-md max-w-full rounded-lg border border-zinc-200 dark:border-zinc-800'>\r\n      <ImageComparisonImage\r\n        src='/images/demo/tailwind-admin-main-light-version.webp'\r\n        alt='Motion Primitives Dark'\r\n        position='left'\r\n      />\r\n      <ImageComparisonImage\r\n        src='/images/demo/tailwind-admin-main-dark-version.webp'\r\n        alt='Motion Primitives Light'\r\n        position='right'\r\n      />\r\n      <ImageComparisonSlider className='bg-white' />\r\n    </ImageComparison>\r\n  );\r\n}\r\n\r\n",
      "type": "registry:component",
      "target": "components/animated/cards/image-comparison/ImageComparisonMotion.tsx"
    }
  ]
}