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.
47 lines • 4.36 kB
JavaScript
;
"use client";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = Dock;
const jsx_runtime_1 = require("react/jsx-runtime");
const framer_motion_1 = require("framer-motion");
const react_1 = require("react");
function useDockItemSize(mouseX, baseItemSize, magnification, distance, ref, spring) {
const mouseDistance = (0, framer_motion_1.useTransform)(mouseX, (val) => {
if (typeof val !== "number" || isNaN(val))
return 0;
const rect = ref.current?.getBoundingClientRect() ?? {
x: 0,
width: baseItemSize,
};
return val - rect.x - baseItemSize / 2;
});
const targetSize = (0, framer_motion_1.useTransform)(mouseDistance, [-distance, 0, distance], [baseItemSize, magnification, baseItemSize]);
return (0, framer_motion_1.useSpring)(targetSize, spring);
}
function DockItem({ icon, label, onClick, mouseX, baseItemSize, magnification, distance, spring, badgeCount, }) {
const ref = (0, react_1.useRef)(null);
const isHovered = (0, framer_motion_1.useMotionValue)(0);
const size = useDockItemSize(mouseX, baseItemSize, magnification, distance, ref, spring);
const [showLabel, setShowLabel] = (0, react_1.useState)(false);
(0, react_1.useEffect)(() => {
const unsubscribe = isHovered.on("change", (value) => setShowLabel(value === 1));
return () => unsubscribe();
}, [isHovered]);
return ((0, jsx_runtime_1.jsxs)(framer_motion_1.motion.div, { ref: ref, style: { width: size, height: size }, onHoverStart: () => isHovered.set(1), onHoverEnd: () => isHovered.set(0), onFocus: () => isHovered.set(1), onBlur: () => isHovered.set(0), onClick: onClick, className: "relative inline-flex items-center justify-center rounded-full bg-background shadow-md", tabIndex: 0, role: "button", "aria-haspopup": "true", "aria-label": label, children: [(0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center", children: icon }), badgeCount !== undefined && badgeCount > 0 && ((0, jsx_runtime_1.jsx)("span", { className: "absolute -top-2 -right-2 flex items-center justify-center w-5 h-5 text-xs font-bold text-white bg-red-500 rounded-full", children: badgeCount > 99 ? "99+" : badgeCount })), (0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { children: showLabel && ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { initial: { opacity: 0, y: 0 }, animate: { opacity: 1, y: -10 }, exit: { opacity: 0, y: 0 }, transition: { duration: 0.2 }, className: "absolute -top-6 left-1/2 w-fit whitespace-pre rounded-md \r\n border border bg-[#060606] px-2 py-0.5 text-xs text-white", style: { x: "-50%" }, role: "tooltip", children: label })) })] }));
}
function Dock({ items, className = "", spring = { mass: 0.1, stiffness: 150, damping: 12 }, magnification = 70, distance = 200, panelHeight = 64, dockHeight = 256, baseItemSize = 50, }) {
const mouseX = (0, framer_motion_1.useMotionValue)(Infinity);
const isHovered = (0, framer_motion_1.useMotionValue)(0);
const maxHeight = (0, react_1.useMemo)(() => Math.max(dockHeight, magnification + magnification / 2 + 4), [magnification, dockHeight]);
const animatedHeight = (0, framer_motion_1.useSpring)((0, framer_motion_1.useTransform)(isHovered, [0, 1], [panelHeight, maxHeight]), spring);
return ((0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { style: { height: animatedHeight }, className: "mx-2 flex max-w-full items-center", children: (0, jsx_runtime_1.jsx)(framer_motion_1.motion.div, { onMouseMove: ({ pageX }) => {
isHovered.set(1);
mouseX.set(pageX);
}, onMouseLeave: () => {
isHovered.set(0);
mouseX.set(Infinity);
}, className: `absolute bottom-2 left-1/2 -translate-x-1/2 transform
flex items-end gap-4 w-fit rounded-2xl
border-2 border px-4 pb-2 ${className}`, style: { height: panelHeight }, role: "toolbar", "aria-label": "Application dock", children: items.map((item, index) => ((0, jsx_runtime_1.jsx)(DockItem, { icon: item.icon, label: item.label, onClick: item.onClick, mouseX: mouseX, baseItemSize: baseItemSize, magnification: magnification, distance: distance, spring: spring, badgeCount: item.badgeCount }, index))) }) }));
}
//# sourceMappingURL=Dock.js.map