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.
87 lines • 4.98 kB
JavaScript
;
"use client";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExpandableSpeedDial = ExpandableSpeedDial;
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 ExpandableSpeedDial({ actions, direction = "up", className, size = "md", }) {
const [isOpen, setIsOpen] = (0, react_1.useState)(false);
const toggleOpen = () => setIsOpen(!isOpen);
const sizes = {
sm: "h-10 w-10",
md: "h-12 w-12",
lg: "h-14 w-14",
};
const actionSizes = {
sm: "h-8 w-8",
md: "h-10 w-10",
lg: "h-12 w-12",
};
const getDirectionClasses = () => {
switch (direction) {
case "up":
return "bottom-full mb-3 flex-col-reverse left-1/2 -translate-x-1/2";
case "down":
return "top-full mt-3 flex-col left-1/2 -translate-x-1/2";
case "left":
return "right-full mr-3 flex-row-reverse top-1/2 -translate-y-1/2";
case "right":
return "left-full ml-3 flex-row top-1/2 -translate-y-1/2";
default:
return "bottom-full mb-3 flex-col-reverse left-1/2 -translate-x-1/2";
}
};
const getMotionVariants = (index) => {
const delay = index * 0.05;
const distance = 15;
let x = 0;
let y = 0;
switch (direction) {
case "up":
y = distance;
break;
case "down":
y = -distance;
break;
case "left":
x = distance;
break;
case "right":
x = -distance;
break;
}
return {
hidden: { opacity: 0, scale: 0.5, x, y },
visible: {
opacity: 1,
scale: 1,
x: 0,
y: 0,
transition: {
type: "spring",
stiffness: 300,
damping: 20,
delay
}
},
exit: {
opacity: 0,
scale: 0.5,
x,
y,
transition: {
duration: 0.2,
delay: (actions.length - 1 - index) * 0.05
}
}
};
};
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)("relative z-50", className), children: [(0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { children: isOpen && ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("absolute flex gap-3", getDirectionClasses()), children: actions.map((action, index) => ((0, jsx_runtime_1.jsxs)(framer_motion_1.motion.button, { variants: getMotionVariants(index), initial: "hidden", animate: "visible", exit: "exit", onClick: () => {
action.onClick();
setIsOpen(false);
}, className: (0, utils_1.cn)("relative flex items-center justify-center rounded-full bg-background shadow-md border hover:bg-muted transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", actionSizes[size]), title: action.label, "aria-label": action.label, whileHover: { scale: 1.1 }, whileTap: { scale: 0.95 }, children: [action.icon, (direction === "up" || direction === "down") && ((0, jsx_runtime_1.jsx)("span", { className: "absolute right-full mr-3 whitespace-nowrap rounded-md bg-foreground px-2 py-1 text-xs text-background opacity-0 transition-opacity group-hover:opacity-100 hidden sm:block", children: action.label })), (direction === "left" || direction === "right") && ((0, jsx_runtime_1.jsx)("span", { className: "absolute bottom-full mb-3 whitespace-nowrap rounded-md bg-foreground px-2 py-1 text-xs text-background opacity-0 transition-opacity group-hover:opacity-100 hidden sm:block", children: action.label }))] }, action.label))) })) }), (0, jsx_runtime_1.jsx)(framer_motion_1.motion.button, { onClick: toggleOpen, className: (0, utils_1.cn)("flex items-center justify-center rounded-full bg-primary text-primary-foreground shadow-lg hover:shadow-xl focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", sizes[size]), "aria-label": "Toggle Speed Dial", whileTap: { scale: 0.9 }, children: (0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { animate: { rotate: isOpen ? 135 : 0 }, transition: { type: "spring", stiffness: 300, damping: 20 }, className: "flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { className: size === "sm" ? "h-5 w-5" : size === "lg" ? "h-8 w-8" : "h-6 w-6" }) }) })] }));
}
//# sourceMappingURL=expandable-speed-dial.js.map