{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "slide-to-unlock", "title": "Slide to Unlock", "author": "siby369 ", "description": "Interactive slider inspired by the classic iPhone 'slide to unlock' gesture.", "dependencies": [ "motion" ], "registryDependencies": [ "https://siby369.github.io/r/shimmering-text.json" ], "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 type { ComponentProps, ComponentPropsWithoutRef, JSX } from \"react\"\nimport { createContext, useCallback, useContext, useRef, useState } 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 = ComponentProps<\"div\"> & {\n /**\n * Width of the drag handle in pixels.\n * @defaultValue 56\n * */\n handleWidth?: number\n /** Called when the handle is dragged fully to the end. */\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 = 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 /**\n * Accepts a render function as `children` to react to the dragging state.\n *\n * @example\n * ```tsx\n * \n * {({ isDragging }) => {isDragging ? \"Release...\" : \"Slide to unlock\"}}\n * \n * ```\n */\n children: JSX.Element | ((props: { isDragging: boolean }) => JSX.Element)\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://siby369.github.io/components/slide-to-unlock", "type": "registry:component" }