import Router from 'next/router' import Image, { ImageProps } from 'next/image' import React from 'react' import { ChevronDown, Menu as LucideMenu } from 'lucide-react' import Text from '../Text' import Menu from '../Menu' import Sidebar from '../Sidebar' import Col from '../Col' import Row from '../Row' import Link from '../Link' import { buildClassName } from '../Util' import css from './Navbar.module.styl' import { Icon } from '../interfaces' import Button from '../Button' interface MenuItem { path?: string icon?: Icon name: string subMenu?: Array } interface Props { /** * Logo to display */ logo?: ImageProps & {height: number, width: number} /** * Login URL */ loginUrl?: string /** * Login URL */ registerUrl?: string /** * User Informations if loggedin */ user?: { /** * Username */ name: string /** * User Menu */ menu?: Array } /** * Links to display */ menu: Array children?: React.ReactNode } interface State { path?: string short: boolean isMobile: boolean menuActive: boolean subMenu?: { x: number menu: Menu['props']['items'] } } /** * Navbar Component * @version 1.0.4 */ export default class Navbar extends React.Component { public state: State = { short: false, isMobile: false, menuActive: false } public componentDidMount() { this.setState({ path: Router.asPath, menuActive: false }) Router.events.on('routeChangeComplete', () => { this.setState({path: Router.asPath, menuActive: false}) }) Router.events.on('routeChangeError', () => { this.setState({path: Router.asPath, menuActive: false}) }) document.body.classList.add(css['body-navbar']) document.body.addEventListener('click', this.onBodyClick) window.addEventListener('resize', this.onResize) this.onResize() } public onResize = () => { const isMobile = window.innerWidth <= 768 if (this.state.isMobile !== isMobile) { this.setState({isMobile}) } } public componentWillUnmount() { document.body.classList.remove(css['body-sidebar']) document.body.removeEventListener('click', this.onBodyClick) window.removeEventListener('resize', this.onResize) } public menuCloseCallback = () => { this.setState({menuActive: false}) return true } public render = () => ( <> {this.state.isMobile && (
)} {this.state.subMenu && (
)} ) private onBodyClick = (ev: MouseEvent) => { let target = ev.target as HTMLElement | null do { if (target && target.classList.contains(css.menu)) { return } target = target?.parentElement as HTMLElement | null } while (target) this.setState({subMenu: undefined}) } private onClick = (subMenu?: Array) => (ev: React.MouseEvent) => { ev.stopPropagation() const x = window.innerWidth - (ev.currentTarget.offsetLeft + ev.currentTarget.offsetWidth) if (subMenu && (!this.state.subMenu || x !== this.state.subMenu?.x)) { this.setState({ subMenu: { x, menu: subMenu.map((v) => ({ display: v.name, value: v.path, href: v.path })) } }) } else { this.setState({subMenu: undefined}) } } }