{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "slide-to-unlock", "title": "Slide to Unlock", "author": "ncdai ", "description": "A sleek, interactive slider inspired by the classic iPhone OS 'slide to unlock' gesture.", "dependencies": [ "motion" ], "registryDependencies": [ "@ncdai/shimmering-text" ], "files": [ { "path": "src/registry/components/slide-to-unlock/slide-to-unlock.tsx", "content": "\"use client\"\n\nimport {\n animate,\n motion,\n type MotionValue,\n useMotionValue,\n useTransform,\n} from \"motion/react\"\nimport {\n type ComponentPropsWithoutRef,\n createContext,\n useCallback,\n useContext,\n useRef,\n useState,\n} from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype SlideToUnlockContextValue = {\n x: MotionValue\n trackRef: React.RefObject\n isDragging: boolean\n handleWidth: number\n textOpacity: MotionValue\n onDragStart: () => void\n onDragEnd: () => void\n}\n\nconst SlideToUnlockContext = createContext(\n null\n)\n\nfunction useSlideToUnlock() {\n const context = useContext(SlideToUnlockContext)\n if (!context) {\n throw new Error(\n `SlideToUnlock components must be used within SlideToUnlock`\n )\n }\n return context\n}\n\nexport type SlideToUnlockRootProps = React.ComponentProps<\"div\"> & {\n handleWidth?: number\n onUnlock?: () => void\n}\n\nexport function SlideToUnlock({\n className,\n handleWidth = 56,\n children,\n onUnlock,\n ...props\n}: SlideToUnlockRootProps) {\n const trackRef = useRef(null)\n const [isDragging, setIsDragging] = useState(false)\n const x = useMotionValue(0)\n\n const fadeDistance = handleWidth\n const textOpacity = useTransform(x, [0, fadeDistance], [1, 0])\n\n const handleDragStart = useCallback(() => {\n setIsDragging(true)\n }, [])\n\n const handleDragEnd = useCallback(() => {\n setIsDragging(false)\n\n const trackWidth = trackRef.current?.offsetWidth || 0\n const maxX = trackWidth - handleWidth\n\n if (x.get() >= maxX) {\n onUnlock?.()\n } else {\n animate(x, 0, { type: \"spring\", bounce: 0, duration: 0.25 })\n }\n }, [x, onUnlock, handleWidth])\n\n return (\n \n \n {children}\n \n \n )\n}\n\nexport type SlideToUnlockTrackProps = React.ComponentProps<\"div\">\n\nexport function SlideToUnlockTrack({\n className,\n children,\n ...props\n}: SlideToUnlockTrackProps) {\n const { trackRef } = useSlideToUnlock()\n\n return (\n \n {children}\n \n )\n}\n\nexport type SlideToUnlockTextProps = Omit<\n ComponentPropsWithoutRef,\n \"children\"\n> & {\n children:\n | React.ReactNode\n | ((props: { isDragging: boolean }) => React.ReactNode)\n}\n\nexport function SlideToUnlockText({\n className,\n children,\n style,\n ...props\n}: SlideToUnlockTextProps) {\n const { handleWidth, textOpacity, isDragging } = useSlideToUnlock()\n\n return (\n \n {typeof children === \"function\" ? children({ isDragging }) : children}\n \n )\n}\n\nexport type SlideToUnlockHandleProps = ComponentPropsWithoutRef<\n typeof motion.div\n>\n\nexport function SlideToUnlockHandle({\n className,\n children,\n style,\n ...props\n}: SlideToUnlockHandleProps) {\n const {\n x,\n trackRef,\n onDragStart,\n onDragEnd,\n handleWidth: width,\n } = useSlideToUnlock()\n\n return (\n \n {children ?? (\n \n \n \n )}\n \n )\n}\n", "type": "registry:component" } ], "docs": "https://chanhdai.com/components/slide-to-unlock", "type": "registry:component" }