FrezManager/src/components/NavigationTree.tsx

62 lines
2.2 KiB
TypeScript

import { CustomRouteObject } from "../configure";
import { Link, useLocation } from "react-router-dom";
import { clearMultiplePathSlashes, trimPathOfParameters } from "../utils/StringTransformationUtils";
/**
* @returns Navigation tree elements, require to be used like in example below
* @example
* ```tsx
* <ul className="menu bg-base-200 w-56 h-full">
* <NavigationTree routes={navigation} />
* </ul>
* ```
*/
function NavigationTree(props: { routes: CustomRouteObject[] }): React.JSX.Element {
const locationHook = useLocation(); // Used to highlight active link in navigation tree
const GenerateNavigationEntries = (routes: CustomRouteObject[], parentPath?: string): React.ReactNode => {
return (
routes.map((route) => {
// Prepare path for links
let combinedPath = undefined;
if (parentPath !== undefined && route.path !== undefined)
combinedPath = trimPathOfParameters(clearMultiplePathSlashes(`/${parentPath}/${route.path}`));
else combinedPath = route.path;
// Does it have children and enabled? Make entry with `/{parent.path}/{route.path}`
if (route.children && !route.additionalProps.disableInNavbar) {
return (
<ul key={route.path}>
<li key={route.path}>
<Link to={combinedPath || "/"} className={locationHook.pathname === combinedPath ? "active" : ""}>
{route.additionalProps.name}
</Link>
{route.children ? <ul>{GenerateNavigationEntries(route.children, combinedPath)}</ul> : null}
</li>
</ul>
);
}
// Does it have children and not visible? Skip this entry and call this function for children passing path.
else if (route.children && route.additionalProps.disableInNavbar) {
return GenerateNavigationEntries(route.children, combinedPath);
} else if (route.additionalProps.disableInNavbar) {
return null;
}
// Make entry with `/{route.path}`
else {
return (
<li key={route.path}>
<Link to={combinedPath || "/"} className={locationHook.pathname === combinedPath ? "active" : ""}>
{route.additionalProps.name}
</Link>
</li>
);
}
}) || <>empty navigation tree</>
);
};
return <div className="h-fit">{GenerateNavigationEntries(props.routes)}</div>;
}
export default NavigationTree;