shelving
Version:
Toolkit for using data in JavaScript.
45 lines (44 loc) • 2.33 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { filterElements } from "../../util/element.js";
import { joinPath } from "../../util/path.js";
import { Menu } from "../menu/Menu.js";
import { MenuItem } from "../menu/MenuItem.js";
import { createMapper } from "../misc/Mapper.js";
/**
* Match an element that should appear in the sidebar menu.
* - Directories and plain files always qualify.
* - For documentation elements, only `kind: "module"` qualifies — functions, classes, methods, properties, etc. are kept off the navigation.
*/
export function matchMenuElement(element) {
const { type, props } = element;
if (type === "tree-directory" || type === "tree-file")
return true;
if (type === "tree-documentation")
return props.kind === "module";
return false;
}
/**
* Default menu item renderer for any `tree-*` element.
* - Computes its own URL path by appending its `name` to the parent's `path`.
* - Passes both the label and the nested `<TreeMenuMapper>` to `<MenuItem>`; `<MenuItem>` itself decides whether to reveal the nested submenu based on the current URL.
*/
export function TreeMenuItem({ path = "/", name, title, children }) {
const href = joinPath(path, name);
const submenu = Array.from(filterElements(children, matchMenuElement));
return (_jsxs(MenuItem, { href: href, children: [title ?? name, submenu.length ? (_jsx(Menu, { children: _jsx(TreeMenuMapper, { path: href, children: submenu }) })) : null] }));
}
/** Mapping + Mapper pair for the menu — wrap children in `<TreeMenuMapping>` to override. */
export const [TreeMenuMapping, TreeMenuMapper] = createMapper({
"tree-directory": TreeMenuItem,
"tree-file": TreeMenuItem,
"tree-documentation": TreeMenuItem,
});
/**
* Sidebar navigation menu built from the children of a root tree element.
* - Renders each child via `<TreeMenuItem>` (the default mapping for `tree-directory` / `tree-file`).
* - To customise renderers for specific types, wrap in `<TreeMenuMapping mapping={…}>`.
* - Only directories and files appear — code symbols are kept off the navigation.
*/
export function TreeMenu({ path = "/", tree }) {
return (_jsx(Menu, { children: _jsx(TreeMenuMapper, { path: path, children: filterElements(tree.props.children, matchMenuElement) }) }));
}