{ "name": "image-comparison", "type": "registry:ui", "registryDependencies": [], "dependencies": [ "motion" ], "devDependencies": [], "tailwind": {}, "cssVars": { "light": {}, "dark": {} }, "files": [ { "path": "image-comparison.tsx", "content": "'use client';\nimport { cn } from '@/lib/utils';\nimport { useState, createContext, useContext } from 'react';\nimport {\n motion,\n MotionValue,\n SpringOptions,\n useMotionValue,\n useSpring,\n useTransform,\n} from 'motion/react';\n\nconst ImageComparisonContext = createContext<\n | {\n sliderPosition: number;\n setSliderPosition: (pos: number) => void;\n motionSliderPosition: MotionValue;\n }\n | undefined\n>(undefined);\n\nexport type ImageComparisonProps = {\n children: React.ReactNode;\n className?: string;\n enableHover?: boolean;\n springOptions?: SpringOptions;\n};\n\nconst DEFAULT_SPRING_OPTIONS = {\n bounce: 0,\n duration: 0,\n};\n\nfunction ImageComparison({\n children,\n className,\n enableHover,\n springOptions,\n}: ImageComparisonProps) {\n const [isDragging, setIsDragging] = useState(false);\n const motionValue = useMotionValue(50);\n const motionSliderPosition = useSpring(\n motionValue,\n springOptions ?? DEFAULT_SPRING_OPTIONS\n );\n const [sliderPosition, setSliderPosition] = useState(50);\n\n const handleDrag = (event: React.MouseEvent | React.TouchEvent) => {\n if (!isDragging && !enableHover) return;\n\n const containerRect = (\n event.currentTarget as HTMLElement\n ).getBoundingClientRect();\n const x =\n 'touches' in event\n ? event.touches[0].clientX - containerRect.left\n : (event as React.MouseEvent).clientX - containerRect.left;\n\n const percentage = Math.min(\n Math.max((x / containerRect.width) * 100, 0),\n 100\n );\n motionValue.set(percentage);\n setSliderPosition(percentage);\n };\n\n return (\n \n !enableHover && setIsDragging(true)}\n onMouseUp={() => !enableHover && setIsDragging(false)}\n onMouseLeave={() => !enableHover && setIsDragging(false)}\n onTouchMove={handleDrag}\n onTouchStart={() => !enableHover && setIsDragging(true)}\n onTouchEnd={() => !enableHover && setIsDragging(false)}\n >\n {children}\n \n \n );\n}\n\nconst ImageComparisonImage = ({\n className,\n alt,\n src,\n position,\n}: {\n className?: string;\n alt: string;\n src: string;\n position: 'left' | 'right';\n}) => {\n const { motionSliderPosition } = useContext(ImageComparisonContext)!;\n const leftClipPath = useTransform(\n motionSliderPosition,\n (value) => `inset(0 0 0 ${value}%)`\n );\n const rightClipPath = useTransform(\n motionSliderPosition,\n (value) => `inset(0 ${100 - value}% 0 0)`\n );\n\n return (\n \n );\n};\n\nconst ImageComparisonSlider = ({\n className,\n children,\n}: {\n className: string;\n children?: React.ReactNode;\n}) => {\n const { motionSliderPosition } = useContext(ImageComparisonContext)!;\n\n const left = useTransform(motionSliderPosition, (value) => `${value}%`);\n\n return (\n \n {children}\n \n );\n};\n\nexport { ImageComparison, ImageComparisonImage, ImageComparisonSlider };\n", "type": "registry:ui" } ] }