ar-design
Version:
AR Design is a (react | nextjs) ui library.
90 lines (89 loc) • 4.76 kB
JavaScript
"use client";
import React, { useEffect, useState } from "react";
import "../../../assets/css/components/navigation/menu/styles.css";
import { DispatchEvent, SessionStorage } from "../../../libs/infrastructure/shared/Enums";
const Menu = ({ data, variant = "vertical", config, ...attributes }) => {
// states
const [openMenus, setOpenMenus] = useState([]);
const [selectedKey, setSelectedKey] = useState(null);
const [isMenuLocked, setIsMenuLocked] = useState(true);
// methods
const handleItemClick = (item) => {
if (!isMenuLocked && item.type === "group")
return;
if (item.type === "group") {
const parents = findPath(item.key, data) ?? [];
setOpenMenus((prev) => {
const isOpen = prev.includes(item.key);
if (isOpen)
return prev.filter((k) => k !== item.key);
return [...parents, item.key];
});
return;
}
if (item.type !== "divider") {
setSelectedKey(item.key);
sessionStorage.setItem(SessionStorage.SelectedMenuItem, String(item.key));
}
};
const findPath = (key, items, path = []) => {
for (const item of items) {
if (item.key === key)
return path;
if (item.submenu) {
const result = findPath(key, item.submenu, [...path, item.key]);
if (result)
return result;
}
}
return null;
};
// useEffects
useEffect(() => {
if (!data.length)
return;
const selectedMenuItem = sessionStorage.getItem(SessionStorage.SelectedMenuItem) ?? "";
setSelectedKey(selectedMenuItem);
const parents = findPath(selectedMenuItem, data);
if (parents)
setOpenMenus(parents);
}, [data]);
useEffect(() => {
const onStorageChangeSelectedMenuItem = () => {
setSelectedKey(JSON.parse(sessionStorage.getItem(SessionStorage.SelectedMenuItem) ?? ""));
};
const onStorageChangeMenuLock = () => {
setIsMenuLocked(JSON.parse(sessionStorage.getItem(SessionStorage.MenuIsLocked) ?? "true"));
};
window.addEventListener(DispatchEvent.SelectedMenuItem, onStorageChangeSelectedMenuItem);
window.addEventListener(DispatchEvent.MenuLock, onStorageChangeMenuLock);
const styles = document.createElement("style");
styles.innerHTML = `
:root {
--selected-icon-color: ${config?.icon?.selectedColor};
--selected-icon-bg-color: ${config?.icon?.selectedBackgroundColor};
--selected-icon-bg-color-rgb: ${config?.icon?.selectedBackgroundBorderColor};
}
`;
document.head.appendChild(styles);
return () => {
window.removeEventListener(DispatchEvent.SelectedMenuItem, onStorageChangeSelectedMenuItem);
window.removeEventListener(DispatchEvent.MenuLock, onStorageChangeMenuLock);
};
}, []);
return (React.createElement("nav", { className: "ar-menu", ...attributes },
React.createElement("ul", null, data.map((item) => (React.createElement(MenuItem, { key: item.key, item: item, openMenus: openMenus, selectedKey: selectedKey, isMenuLocked: isMenuLocked, onClick: handleItemClick }))))));
};
const MenuItem = ({ item, openMenus, selectedKey, isMenuLocked, onClick }) => {
const isOpen = openMenus.includes(item.key);
const isSelected = selectedKey === item.key && item.type !== "group";
return (React.createElement("li", { "data-menu-id": `ar-menu-${item.key}`, className: `${item.type === "divider" ? "divider" : ""} ${isSelected ? "selected" : ""}` },
React.createElement("div", { className: `item-render ${isMenuLocked ? "align-left" : "align-center"}`, onClick: () => onClick(item) },
item.type !== "divider" && React.createElement("span", { className: "icon" }, item.icon ?? React.createElement("span", { className: "no-icon" })),
isMenuLocked && (item.type === "divider" ? React.createElement("hr", null) : React.createElement("span", { className: "item" }, item.render)),
isMenuLocked && item.type === "group" && React.createElement("span", { className: `angel-down ${isOpen ? "opened" : ""}` })),
item.submenu && isMenuLocked && (React.createElement("ul", { className: `submenu ${isOpen ? "opened" : ""}` },
React.createElement("div", { className: "submenu-inner" }, item.submenu.map((sub) => (React.createElement(MenuItem, { key: sub.key, item: sub, openMenus: openMenus, selectedKey: selectedKey, isMenuLocked: isMenuLocked, onClick: onClick }))))))));
};
Menu.displayName = "Menu";
export default Menu;