UNPKG

@pagamio/frontend-commons-lib

Version:

Pagamio library for Frontend reusable components like the form engine and table container

88 lines (87 loc) 7 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { Sidebar, TextInput } from 'flowbite-react'; import { HiSearch } from 'react-icons/hi'; import { twMerge } from 'tailwind-merge'; import React, { useEffect, useState } from 'react'; import { useAppSidebarContext } from '../../context'; import { useLibTranslations, useTranslation } from '../../translations'; const AppSidebarMenu = () => { const { pages } = useAppSidebarContext(); return (_jsx(Sidebar.Items, { children: _jsx(Sidebar.ItemGroup, { className: "mt-0 border-t-0 pb-1 pt-0", children: pages.map((item) => (_jsx(AppSidebarItem, { ...item }, item.label))) }) })); }; const AppSidebarItem = ({ href, target, icon, label, items, badge, forceDropdown }) => { const { pathname, linkComponent: Link } = useAppSidebarContext(); const { t } = useTranslation(); // Check if current path matches this item or any of its descendants const isParentActive = href ? pathname === href || pathname.startsWith(`${href}/`) : false; // Recursive function to check if any nested child is active const hasActiveChild = (children = []) => { return children.some((child) => { if (child.href && pathname.startsWith(child.href)) return true; if (child.items) return hasActiveChild(child.items); return false; }); }; // If there's exactly one item, render it as a direct link instead of a dropdown if (items?.length === 1 && !forceDropdown) { const singleItem = items[0]; return (_jsx(Sidebar.Item, { as: Link, href: singleItem.href, target: target, icon: icon, label: badge && t(badge), className: twMerge('text-gray-600 hover:text-primary-700 hover:bg-primary-50/70', 'dark:text-gray-400 dark:hover:text-primary-300 dark:hover:bg-primary-900/30', pathname === singleItem.href && 'text-primary-700 bg-primary-100/80 hover:bg-primary-100/80 dark:text-primary-300 dark:bg-primary-900/40 dark:hover:bg-primary-900/40'), children: t(label) })); } if (items?.length) { const isOpen = isParentActive || hasActiveChild(items); return (_jsx(Sidebar.Collapse, { icon: icon, label: t(label), open: isOpen, className: twMerge('text-gray-600 hover:text-primary-700 hover:bg-primary-50/70', 'dark:text-gray-400 dark:hover:text-primary-300 dark:hover:bg-primary-900/30', // Parent styling when its child is active hasActiveChild(items) && 'text-primary-700 dark:text-primary-300', // Parent styling when it's directly active isParentActive && !hasActiveChild(items) && 'text-primary-700 bg-primary-100/80 hover:bg-primary-100/80 dark:text-primary-300 dark:bg-primary-900/40 dark:hover:bg-primary-900/40'), theme: { list: 'space-y-2 py-2 [&>li>div]:w-full' }, children: items.map((child) => (_jsx(React.Fragment, { children: child.items?.length ? ( // Recursively render nested items _jsx("div", { className: "pl-3", children: _jsx(AppSidebarItem, { ...child }) })) : ( // Render leaf item _jsx(Sidebar.Item, { as: Link, href: child.href, target: child.target, icon: child.icon, className: twMerge('justify-center [&>*]:font-normal', 'text-gray-600 hover:text-primary-700 hover:bg-primary-50/70', 'dark:text-gray-400 dark:hover:text-primary-300 dark:hover:bg-primary-900/30', pathname === child.href && 'text-primary-700 bg-primary-100/80 hover:bg-primary-100/80 dark:text-primary-300 dark:bg-primary-900/40 dark:hover:bg-primary-900/40'), children: t(child.label) })) }, child.label))) })); } // Render leaf item return (_jsx(Sidebar.Item, { as: Link, href: href, target: target, icon: icon, label: badge && t(badge), className: twMerge('text-gray-600 hover:text-primary-700 hover:bg-primary-50/70', 'dark:text-gray-400 dark:hover:text-primary-300 dark:hover:bg-primary-900/30', isParentActive && 'text-primary-700 bg-primary-100/80 hover:bg-primary-100/80 dark:text-primary-300 dark:bg-primary-900/40 dark:hover:bg-primary-900/40'), children: t(label) })); }; const AppMobileSidebar = () => { const { mobile: { isOpen, close }, sidebarHeader, } = useAppSidebarContext(); const { t } = useTranslation(); const { tLib } = useLibTranslations(); if (!isOpen) return null; return (_jsxs(_Fragment, { children: [_jsx(Sidebar, { "aria-label": t('sidebar.mobileAriaLabel', 'Sidebar with multi-level dropdown example'), className: twMerge('fixed inset-y-0 left-0 z-20 hidden h-full shrink-0 flex-col border-r border-gray-200 pt-16 dark:border-gray-700 md:flex', isOpen && 'flex'), id: "sidebar", children: _jsx("div", { className: "flex h-full flex-col justify-between", children: _jsxs("div", { className: "py-2", children: [sidebarHeader && _jsx("div", { className: "mb-4 px-3", children: sidebarHeader }), _jsx("form", { className: "pb-3", children: _jsx(TextInput, { icon: HiSearch, type: "search", placeholder: tLib('sidebar.searchPlaceholder', 'Search'), required: true, size: 32 }) }), _jsx(AppSidebarMenu, {})] }) }) }), _jsx("div", { onClick: close, "aria-hidden": "true", className: "fixed inset-0 z-10 h-full w-full bg-gray-900/50 pt-16 dark:bg-gray-900/90" })] })); }; const AppDesktopSidebar = () => { const { desktop: { isCollapsed, setCollapsed }, sidebarHeader, } = useAppSidebarContext(); const [isPreview, setIsPreview] = useState(isCollapsed); const { tLib } = useLibTranslations(); useEffect(() => { if (isCollapsed) setIsPreview(false); }, [isCollapsed]); const preview = { enable() { if (!isCollapsed) return; setIsPreview(true); setCollapsed(false); }, disable() { if (!isPreview) return; setCollapsed(true); }, }; return (_jsx(Sidebar, { onMouseEnter: preview.enable, onMouseLeave: preview.disable, "aria-label": tLib('sidebar.desktopAriaLabel', 'Sidebar with multi-level dropdown example'), collapsed: isCollapsed, className: twMerge('fixed inset-y-0 left-0 z-20 flex h-full shrink-0 flex-col border-r border-gray-200 pt-16 duration-75 dark:border-gray-700', isCollapsed && 'hidden w-16'), id: "sidebar", children: _jsx("div", { className: "flex h-full flex-col justify-between", children: _jsxs("div", { className: "py-2", children: [sidebarHeader && _jsx("div", { className: "mb-4 px-3", children: sidebarHeader }), _jsx(AppSidebarMenu, {})] }) }) })); }; const AppDashboardSidebar = () => { return (_jsxs(_Fragment, { children: [_jsx("div", { className: "md:hidden", children: _jsx(AppMobileSidebar, {}) }), _jsx("div", { className: "hidden md:block", children: _jsx(AppDesktopSidebar, {}) })] })); }; export default AppDashboardSidebar; export { AppSidebarMenu, AppMobileSidebar, AppDesktopSidebar, AppDashboardSidebar };