UNPKG

lightswind

Version:

A collection of beautifully crafted React Components, Blocks & Templates for Modern Developers. Create stunning web applications effortlessly by using our 160+ professional and animated react components.

86 lines 6.31 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SlideToConfirm = SlideToConfirm; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const framer_motion_1 = require("framer-motion"); const lucide_react_1 = require("lucide-react"); const utils_1 = require("@/components/lib/utils"); function SlideToConfirm({ text = "Slide to confirm", successText = "Confirmed", onConfirm, width = 320, height = 56, className, }) { const [state, setState] = (0, react_1.useState)("idle"); const containerRef = (0, react_1.useRef)(null); const trackWidth = width - height; // Total drag distance const thumbSize = height - 8; // Margin inside const x = (0, framer_motion_1.useMotionValue)(0); const controls = (0, framer_motion_1.useAnimation)(); // Opacity of the text fades out as you drag const textOpacity = (0, framer_motion_1.useTransform)(x, [0, trackWidth * 0.5], [1, 0]); // Background gradient progresses as you drag const bgWidth = (0, framer_motion_1.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 ((0, jsx_runtime_1.jsxs)("div", { ref: containerRef, className: (0, utils_1.cn)("relative flex items-center justify-center overflow-hidden rounded-full border bg-muted select-none", state === "success" ? "cursor-pointer border-green-500/50" : "", className), style: { width, height, }, onClick: handleReset, children: [(0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { className: "absolute left-0 top-0 h-full rounded-full", style: { width: state === "success" ? width : bgWidth, backgroundColor: state === "success" ? "#22c55e" : "var(--primary)", opacity: state === "success" ? 0.1 : 0.05, }, animate: { width: state === "success" ? width : undefined }, transition: { duration: 0.3 } }), (0, jsx_runtime_1.jsx)(framer_motion_1.motion.span, { className: (0, utils_1.cn)("absolute font-medium text-sm z-0", state === "success" ? "text-green-600 dark:text-green-400" : "text-muted-foreground"), style: { opacity: state === "idle" ? textOpacity : 0 }, children: text }), (0, jsx_runtime_1.jsx)(framer_motion_1.motion.span, { className: "absolute font-medium text-sm z-0 text-green-600 dark:text-green-400", initial: { opacity: 0, y: 10 }, animate: { opacity: state === "success" ? 1 : 0, y: state === "success" ? 0 : 10 }, transition: { duration: 0.3, delay: 0.1 }, children: successText }), (0, jsx_runtime_1.jsxs)(framer_motion_1.motion.div, { drag: state === "idle" ? "x" : false, dragConstraints: { left: 0, right: trackWidth }, dragElastic: 0.05, dragMomentum: false, onDragEnd: handleDragEnd, className: (0, utils_1.cn)("absolute left-1 z-10 flex cursor-grab items-center justify-center rounded-full bg-background shadow-md active:cursor-grabbing", state !== "idle" && "cursor-default"), initial: false, whileTap: { scale: state === "idle" ? 0.95 : 1 }, animate: state === "success" ? { x: trackWidth, backgroundColor: "#22c55e", color: "white" } : controls, style: { width: thumbSize, height: thumbSize, x, }, children: [(0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { animate: { rotate: state === "loading" ? 360 : 0, scale: state === "idle" ? 1 : 0, opacity: state === "idle" ? 1 : 0, }, transition: { duration: 0.2 }, className: "absolute", children: (0, jsx_runtime_1.jsx)(lucide_react_1.ArrowRight, { className: "h-5 w-5 opacity-70" }) }), (0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { animate: { scale: state === "loading" ? 1 : 0, opacity: state === "loading" ? 1 : 0, }, transition: { duration: 0.2 }, className: "absolute flex h-full w-full items-center justify-center", children: (0, jsx_runtime_1.jsx)("div", { className: "relative h-[20px] w-[20px]", children: [...Array(12)].map((_, i) => ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.span, { className: "absolute left-[9px] top-0 h-[5.5px] w-[1.8px] rounded-full bg-foreground", style: { rotate: i * 30, transformOrigin: "center 10px", }, animate: { opacity: [0.15, 1, 0.15], }, transition: { duration: 1.1, repeat: Infinity, delay: i * 0.091, ease: "linear", } }, i))) }) }), (0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { animate: { scale: state === "success" ? 1 : 0, opacity: state === "success" ? 1 : 0, }, transition: { type: "spring", stiffness: 300, damping: 20 }, className: "absolute text-white", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "h-5 w-5" }) })] })] })); } //# sourceMappingURL=slide-to-confirm.js.map