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.

70 lines 4.28 kB
"use strict"; "use client"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AnimatedNumberStepper = AnimatedNumberStepper; 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 AnimatedNumberStepper({ defaultValue = 1, min = 0, max = 99, step = 1, onChange, size = "md", label = "Quantity", className, }) { const [value, setValue] = (0, react_1.useState)(defaultValue); const [direction, setDirection] = (0, react_1.useState)("up"); const sizes = { sm: { container: "h-9 gap-1", button: "h-9 w-9 text-sm", display: "w-12 h-9 text-sm", }, md: { container: "h-11 gap-1.5", button: "h-11 w-11", display: "w-16 h-11 text-base", }, lg: { container: "h-14 gap-2", button: "h-14 w-14 text-lg", display: "w-20 h-14 text-lg", }, }; const iconSizes = { sm: "h-3.5 w-3.5", md: "h-4 w-4", lg: "h-5 w-5", }; const s = sizes[size]; const handleDecrement = () => { if (value - step < min) return; setDirection("down"); const next = Math.max(min, value - step); setValue(next); onChange?.(next); }; const handleIncrement = () => { if (value + step > max) return; setDirection("up"); const next = Math.min(max, value + step); setValue(next); onChange?.(next); }; const isAtMin = value <= min; const isAtMax = value >= max; const variants = { enter: (dir) => ({ y: dir === "up" ? 16 : -16, opacity: 0, }), center: { y: 0, opacity: 1 }, exit: (dir) => ({ y: dir === "up" ? -16 : 16, opacity: 0, }), }; return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)("inline-flex items-center", s.container, className), "aria-label": label, children: [(0, jsx_runtime_1.jsx)(framer_motion_1.motion.button, { type: "button", onClick: handleDecrement, disabled: isAtMin, "aria-label": "Decrement", className: (0, utils_1.cn)("relative flex items-center justify-center rounded-xl border bg-background shadow-sm transition-colors", "hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "disabled:opacity-30 disabled:cursor-not-allowed", s.button), whileTap: { scale: isAtMin ? 1 : 0.88 }, whileHover: { scale: isAtMin ? 1 : 1.05 }, transition: { type: "spring", stiffness: 400, damping: 20 }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Minus, { className: iconSizes[size] }) }), (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("relative flex items-center justify-center overflow-hidden rounded-xl border bg-muted/30 font-semibold tabular-nums select-none", s.display), children: (0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { mode: "popLayout", custom: direction, initial: false, children: (0, jsx_runtime_1.jsx)(framer_motion_1.motion.span, { custom: direction, variants: variants, initial: "enter", animate: "center", exit: "exit", transition: { y: { type: "spring", stiffness: 500, damping: 35 }, opacity: { duration: 0.12 }, }, className: "absolute", children: value }, value) }) }), (0, jsx_runtime_1.jsx)(framer_motion_1.motion.button, { type: "button", onClick: handleIncrement, disabled: isAtMax, "aria-label": "Increment", className: (0, utils_1.cn)("relative flex items-center justify-center rounded-xl border bg-background shadow-sm transition-colors", "hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "disabled:opacity-30 disabled:cursor-not-allowed", s.button), whileTap: { scale: isAtMax ? 1 : 0.88 }, whileHover: { scale: isAtMax ? 1 : 1.05 }, transition: { type: "spring", stiffness: 400, damping: 20 }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { className: iconSizes[size] }) })] })); } //# sourceMappingURL=animated-number-stepper.js.map