62 lines
2.0 KiB
TypeScript
62 lines
2.0 KiB
TypeScript
import { observer } from 'mobx-react-lite';
|
|
import { useEffect, useRef } from 'react';
|
|
import { state } from '../state';
|
|
import './MenuView.scss';
|
|
import type { MenuNode } from '../state/menuState';
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
|
export const MenuNodeView = observer(function ({ node }: { node: MenuNode }) {
|
|
const forceOpen = state.menu.nodeContainsSelected(node);
|
|
const navigate = useNavigate();
|
|
|
|
const ref = useRef<HTMLDetailsElement>(null);
|
|
|
|
useEffect(() => {
|
|
if (forceOpen && ref.current)
|
|
ref.current.open = true;
|
|
}, [forceOpen]);
|
|
|
|
const classNames = [];
|
|
if (node.selected?.())
|
|
classNames.push('selected');
|
|
if (node.className !== undefined)
|
|
classNames.push(node.className);
|
|
|
|
return (
|
|
<details ref={ref}>
|
|
<summary
|
|
className={classNames.join(' ')}
|
|
onClick={() => node.onClick?.()}
|
|
>
|
|
<div className="title">{node.title}</div>
|
|
{node.actions && <div className="actions">
|
|
{node.actions.map((action) =>
|
|
<div
|
|
key={action.id}
|
|
title={action.tooltip}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
action.onClick?.();
|
|
if (action.link)
|
|
navigate(action.link);
|
|
}}
|
|
>
|
|
{action.content}
|
|
</div>
|
|
)}
|
|
</div>}
|
|
</summary>
|
|
{node.children?.map((child) => <MenuNodeView key={child.id} node={child} />)}
|
|
</details>
|
|
);
|
|
});
|
|
|
|
export const MenuView = observer(function () {
|
|
return (
|
|
<nav className="menu">
|
|
{state.menu.nodes.map((node) => <MenuNodeView key={node.id} node={node} />)}
|
|
</nav>
|
|
);
|
|
});
|