import React, { useCallback, type CSSProperties } from "react"; import { CanAccess, useIsExistAuthentication, useLink, useLogout, useMenu, useActiveAuthProvider, useRefineContext, useTranslate, useWarnAboutChange, } from "@refinedev/core"; import { Box, Drawer, Navbar, NavLink, type NavLinkStylesNames, type NavLinkStylesParams, ScrollArea, MediaQuery, Tooltip, type TooltipProps, type Styles, useMantineTheme, Flex, } from "@mantine/core"; import { IconList, IconPower, IconDashboard } from "@tabler/icons-react"; import { ThemedTitle as DefaultTitle } from "@components"; import { useThemedLayoutContext } from "@hooks"; import type { RefineThemedLayoutSiderProps } from "../types"; const defaultNavIcon = ; export const ThemedSider: React.FC = ({ render, meta, Title: TitleFromProps, activeItemDisabled = false, siderItemsAreCollapsed = true, }) => { const theme = useMantineTheme(); const { siderCollapsed, mobileSiderOpen, setMobileSiderOpen } = useThemedLayoutContext(); const Link = useLink(); const { defaultOpenKeys, menuItems, selectedKey } = useMenu({ meta }); const isExistAuthentication = useIsExistAuthentication(); const t = useTranslate(); const authProvider = useActiveAuthProvider(); const { warnWhen, setWarnWhen } = useWarnAboutChange(); const { mutate: mutateLogout } = useLogout(); const RenderToTitle = TitleFromProps ?? DefaultTitle; const drawerWidth = () => { if (siderCollapsed) return 80; return 200; }; const borderColor = theme.colorScheme === "dark" ? theme.colors.dark[6] : theme.colors.gray[2]; const commonNavLinkStyles: Styles = { root: { display: "flex", marginTop: "12px", justifyContent: siderCollapsed && !mobileSiderOpen ? "center" : "flex-start", }, icon: { marginRight: siderCollapsed && !mobileSiderOpen ? 0 : 12, }, body: { display: siderCollapsed && !mobileSiderOpen ? "none" : "flex", }, }; const commonTooltipProps: Partial = { disabled: !siderCollapsed || mobileSiderOpen, position: "right", withinPortal: true, withArrow: true, arrowSize: 8, arrowOffset: 12, offset: 4, }; const getDefaultExpandMenuItemsCB = (key?: string) => { const defaultOpened = defaultOpenKeys.includes(key || ""); if (siderItemsAreCollapsed) return defaultOpened; return true; }; const getDefaultExpandMenuItems = useCallback( getDefaultExpandMenuItemsCB, [], ); const renderTreeView = (tree: any[], selectedKey?: string) => { return tree.map((item) => { const { icon, label, route, name, children } = item; const isSelected = item.key === selectedKey; const isParent = children.length > 0; const additionalLinkProps = isParent ? {} : { component: Link as any, to: route }; const disablePointerStyle: CSSProperties = activeItemDisabled && isSelected ? { pointerEvents: "none" } : {}; const defaultExpandMenuItems = getDefaultExpandMenuItems(item.key); return ( {isParent && renderTreeView(children, selectedKey)} ); }); }; const items = renderTreeView(menuItems, selectedKey); const handleLogout = () => { if (warnWhen) { const confirm = window.confirm( t( "warnWhenUnsavedChanges", "Are you sure you want to leave? You have unsaved changes.", ), ); if (confirm) { setWarnWhen(false); mutateLogout(); } } else { mutateLogout(); } }; const logout = isExistAuthentication && ( } pl={siderCollapsed || mobileSiderOpen ? "12px" : "18px"} onClick={handleLogout} styles={commonNavLinkStyles} /> ); const renderSider = () => { if (render) { return render({ logout, items, collapsed: siderCollapsed, }); } return ( <> {items} {logout} ); }; return ( <> setMobileSiderOpen(false)} size={200} zIndex={1200} withCloseButton={false} styles={{ drawer: { overflow: "hidden", }, }} > {renderSider()} {renderSider()} ); };