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