import { Navigate } from "@thorium/components/Navigate"; import Menubar from "@thorium/ui/Menubar"; import * as React from "react"; import "./docs.css"; import { NavLink, useLocation } from "react-router"; const ROUTES = import.meta.glob("./**/*.{md,mdx}", { eager: true, }); type RouteType = { route: string; section: string; path: string; frontmatter: { title: string; order: number; }; Doc: React.ComponentType; }; function isRoute(route: any): route is RouteType { if (!route) return false; return route.path; } function isRouteModule(route: unknown): route is { html: string; attributes: any; toc: any } { if (typeof route !== "object") return false; if (!route) return false; if (!("default" in route)) return false; return true; } export const routes = Object.keys(ROUTES) .map((route) => { const routeObj = ROUTES[route] as { frontmatter: { title: string; order: number }; default: React.ComponentType; }; if (!isRouteModule(routeObj)) return null; const path = route .replace(/\/src\/docs|index|\.(tsx|jsx|md|mdx)$/g, "") .replace(/^\/(.*)$/g, "$1") .replace(/\[\.{3}.+\]/, "*") .replace(/\[(.+)\]/, ":$1") .replace(/\+\//, "/") .replace(/^\.\//, ""); if (!routeObj.default) return null; const routeParts = path.split("/"); if (routeParts.length <= 1) return null; return { route, path: path, section: routeParts[0], frontmatter: routeObj.frontmatter, Doc: routeObj.default, }; }) .filter(isRoute); function generateTOC(element: HTMLElement) { function searchChildren(node: HTMLElement): HTMLElement[] { let output: HTMLElement[] = []; if (["H1", "H2", "H3", "H4", "H5", "H6"].includes(node.nodeName)) { output.push(node); } Array.from(node.children)?.forEach((node: any) => { output = output.concat(searchChildren(node as any)); }); return output; } const toc: { level: HeadingLevel; content: string }[] = searchChildren(element).map((index) => ({ level: index.tagName.replace("h", "") as HeadingLevel, content: index.innerText, })); return toc; } type HeadingLevel = "1" | "2" | "3" | "4" | "5" | "6"; type Heading = { title: string; id: string; level: "h1" | "h2" | "h3" | "h4" | "h5" | "h6"; }; const TOCItem = ({ title, id, level, scrollToHeading, }: Heading & { scrollToHeading: (id: string) => void }) => { if (level === "h1") return null; return (
  • { e.preventDefault(); scrollToHeading(id); }} > {title}
  • ); }; function TOC({ toc, scrollToHeading, }: { pathname: string; scrollToHeading: (id: string) => void; toc: { level: HeadingLevel; content: string }[]; }) { return (

    Table of Contents

    ); } export default function DocLayout() { const orderedRoutes = Object.entries( routes.reduce((acc: Record, route) => { const section = route?.section; if (!section) return acc; if (!acc[section]) { acc[section] = []; } acc[section].push(route); return acc; }, {}), ); const docRef = React.useRef(null); const scrollToHeading = React.useCallback((id: string) => { if (!docRef.current) return; docRef.current.querySelector(`#${id}`)?.scrollIntoView({ behavior: "smooth", block: "start", }); }, []); const location = useLocation(); const currentRoute = routes.find((r) => decodeURIComponent(location.pathname).endsWith(r.path)); const [toc, setToc] = React.useState<{ level: HeadingLevel; content: string }[]>([]); React.useEffect(() => { if (docRef.current) { setToc(generateTOC(docRef.current)); } }, [currentRoute]); return (
    {location.pathname === "/docs" ? ( ) : null}
    {currentRoute ? : null}
    ); }