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.

109 lines 5.86 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DynamicNavigation = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const utils_1 = require("@/components/lib/utils"); const DynamicNavigation = ({ links, backgroundColor, textColor, highlightColor, glowIntensity = 5, className, showLabelsOnMobile = false, onLinkClick, activeLink, enableRipple = true, }) => { const navRef = (0, react_1.useRef)(null); const highlightRef = (0, react_1.useRef)(null); const [active, setActive] = (0, react_1.useState)(activeLink || (links.length > 0 ? links[0].id : null)); // Directly define the default black and white theme styles const defaultThemeStyles = { bg: backgroundColor || "bg-background", // Use provided or default black border: "border", text: textColor || "text-foreground", // Use provided or default white highlight: highlightColor || "bg-foreground/10", // Use provided or default white/10 glow: `shadow-[0_0_${glowIntensity}px_rgba(255,255,255,0.3)]`, }; // Update highlight position based on active link const updateHighlightPosition = (id) => { if (!navRef.current || !highlightRef.current) return; const linkElement = navRef.current.querySelector(`#nav-item-${id || active}`); if (!linkElement) return; const { left, width } = linkElement.getBoundingClientRect(); const navRect = navRef.current.getBoundingClientRect(); highlightRef.current.style.transform = `translateX(${left - navRect.left}px)`; highlightRef.current.style.width = `${width}px`; }; // Create ripple effect const createRipple = (event) => { if (!enableRipple) return; const button = event.currentTarget; const circle = document.createElement("span"); const diameter = Math.max(button.clientWidth, button.clientHeight); circle.style.width = circle.style.height = `${diameter}px`; circle.style.left = `${event.clientX - button.getBoundingClientRect().left - diameter / 2}px`; circle.style.top = `${event.clientY - button.getBoundingClientRect().top - diameter / 2}px`; circle.classList.add("absolute", "bg-white", "rounded-full", "pointer-events-none", "opacity-30", "animate-ripple"); const ripple = button.getElementsByClassName("ripple")[0]; if (ripple) { ripple.remove(); } button.appendChild(circle); setTimeout(() => circle.remove(), 600); }; // Handle link click const handleLinkClick = (id, event) => { if (enableRipple) { createRipple(event); } setActive(id); if (onLinkClick) { onLinkClick(id); } }; // Handle link hover const handleLinkHover = (id) => { if (!navRef.current || !highlightRef.current) return; updateHighlightPosition(id); }; // Set initial highlight position and update on window resize (0, react_1.useEffect)(() => { updateHighlightPosition(); const handleResize = () => { updateHighlightPosition(); }; window.addEventListener("resize", handleResize); return () => { window.removeEventListener("resize", handleResize); }; }, [active, links]); // Update when active link changes externally (0, react_1.useEffect)(() => { if (activeLink && activeLink !== active) { setActive(activeLink); } }, [activeLink]); return ((0, jsx_runtime_1.jsxs)("nav", { ref: navRef, className: (0, utils_1.cn)(`relative rounded-full backdrop-blur-md border shadow-lg transition-all duration-300`, defaultThemeStyles.bg, defaultThemeStyles.border, defaultThemeStyles.glow, className), style: { backgroundColor: backgroundColor, color: textColor, }, children: [(0, jsx_runtime_1.jsx)("div", { ref: highlightRef, className: (0, utils_1.cn)(`absolute top-0 left-0 h-full rounded-full transition-all duration-300 ease-[[cubic-bezier(0.25,1,0.5,1)]] z-0`, defaultThemeStyles.highlight), style: { backgroundColor: highlightColor, } }), (0, jsx_runtime_1.jsx)("ul", { className: "flex justify-between items-center gap-4 py-2 relative z-10", children: links.map((link) => ((0, jsx_runtime_1.jsx)("li", { className: "flex-1 rounded-full mx-1 lg:mx-2 px-4", id: `nav-item-${link.id}`, children: (0, jsx_runtime_1.jsxs)("a", { href: link.href, className: (0, utils_1.cn)(`flex gap-1 items-center justify-center h-8 md:h-8 text-xs md:text-sm rounded-full font-medium transition-all duration-300 hover:scale-105 relative overflow-hidden`, defaultThemeStyles.text, active === link.id && "font-semibold"), onClick: (e) => { e.preventDefault(); handleLinkClick(link.id, e); }, onMouseEnter: () => handleLinkHover(link.id), children: [link.icon && ((0, jsx_runtime_1.jsx)("span", { className: "text-current text-xs ", children: link.icon })), (0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)(showLabelsOnMobile ? "flex" : "hidden sm:flex"), children: link.label })] }) }, link.id))) }), (0, jsx_runtime_1.jsx)("style", { dangerouslySetInnerHTML: { __html: ` @keyframes ripple { to { transform: scale(4); opacity: 0; } } .animate-ripple { animation: ripple 0.6s linear; } `, } })] })); }; exports.DynamicNavigation = DynamicNavigation; exports.default = exports.DynamicNavigation; //# sourceMappingURL=dynamic-navigation.js.map