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
JavaScript
"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