"use client"; import React, { useState, useRef, useEffect } from "react"; import { motion, useAnimation, useMotionValue, useTransform } from "framer-motion"; import { ArrowRight, Check, Loader2 } from "lucide-react"; import { cn } from "../lib/utils"; interface SlideToConfirmProps { /** Text to show before sliding */ text?: string; /** Text to show after confirming */ successText?: string; /** Async callback fired when slide completes */ onConfirm: () => Promise | void; /** Width of the component */ width?: number; /** Height of the component */ height?: number; /** Additional classes for the container */ className?: string; } export function SlideToConfirm({ text = "Slide to confirm", successText = "Confirmed", onConfirm, width = 320, height = 56, className, }: SlideToConfirmProps) { const [state, setState] = useState<"idle" | "loading" | "success">("idle"); const containerRef = useRef(null); const trackWidth = width - height; // Total drag distance const thumbSize = height - 8; // Margin inside const x = useMotionValue(0); const controls = useAnimation(); // Opacity of the text fades out as you drag const textOpacity = useTransform(x, [0, trackWidth * 0.5], [1, 0]); // Background gradient progresses as you drag const bgWidth = useTransform(x, [0, trackWidth], [height, width]); const handleDragEnd = async () => { if (state !== "idle") return; if (x.get() >= trackWidth * 0.9) { // Completed drag controls.start({ x: trackWidth, transition: { type: "spring", stiffness: 400, damping: 30 } }); setState("loading"); try { await onConfirm(); setState("success"); } catch (error) { // If error, reset setState("idle"); controls.start({ x: 0, transition: { type: "spring", stiffness: 400, damping: 30 } }); } } else { // Reset if not fully dragged controls.start({ x: 0, transition: { type: "spring", stiffness: 400, damping: 30 } }); } }; const handleReset = () => { if (state === "success") { setState("idle"); x.set(0); controls.start({ x: 0 }); } }; return (
{/* Background fill transitioning to green on success */} {/* Main Text */} {text} {/* Success Text */} {successText} {/* Draggable Thumb */} {/* Refined macOS Style Spinner (12 Spokes) */}
{[...Array(12)].map((_, i) => ( ))}
); }