@flanksource/clicky-ui
Version:
Flanksource Clicky UI — React component library built on shadcn/ui with light/dark and density theming.
101 lines (100 loc) • 3.43 kB
JavaScript
import { jsxs, jsx } from "react/jsx-runtime";
import { useState, useRef, useEffect } from "react";
import { cn } from "../lib/utils.js";
import { Icon } from "./Icon.js";
function TreeNode({
node,
depth = 0,
expandAll = null,
forcedOpenKeys = null,
selected = null,
defaultOpen,
getChildren,
getKey,
onSelect,
renderRow,
rowClass,
indentPx = 16,
basePaddingPx = 8,
isSecondary
}) {
const children = getChildren(node);
const hasChildren = ((children == null ? void 0 : children.length) ?? 0) > 0;
const initialOpen = defaultOpen ? defaultOpen(node, depth) : depth < 1;
const [open, setOpen] = useState(initialOpen);
const prevExpandAll = useRef(expandAll);
const isSelected = selected === node;
const key = getKey(node);
const isForcedOpen = (forcedOpenKeys == null ? void 0 : forcedOpenKeys.has(key)) ?? false;
const isOpen = isForcedOpen || open;
const secondaryNode = (isSecondary == null ? void 0 : isSecondary(node)) ?? false;
const childrenAllSecondary = hasChildren && isSecondary != null && children.every((c) => isSecondary(c));
const skipExpandAll = secondaryNode || childrenAllSecondary;
useEffect(() => {
if (expandAll !== null && expandAll !== prevExpandAll.current && !skipExpandAll) {
setOpen(expandAll);
}
prevExpandAll.current = expandAll;
}, [expandAll, skipExpandAll]);
function toggle() {
if (hasChildren) setOpen((o) => !o);
}
const defaultRowBg = isSelected ? "bg-primary/10 border-l-2 border-primary" : "hover:bg-accent";
const rowClassName = rowClass ? rowClass(node, isSelected) : defaultRowBg;
return /* @__PURE__ */ jsxs(
"div",
{
role: "treeitem",
"aria-expanded": hasChildren ? isOpen : void 0,
"aria-selected": isSelected,
children: [
/* @__PURE__ */ jsxs(
"div",
{
className: cn("flex items-center gap-1.5 py-1 px-2 cursor-pointer text-sm", rowClassName),
style: { paddingLeft: `${depth * indentPx + basePaddingPx}px` },
onClick: (e) => {
e.stopPropagation();
onSelect == null ? void 0 : onSelect(node);
toggle();
},
children: [
hasChildren ? /* @__PURE__ */ jsx(
Icon,
{
name: isOpen ? "codicon:chevron-down" : "codicon:chevron-right",
className: "text-muted-foreground text-xs w-3"
}
) : /* @__PURE__ */ jsx("span", { className: "w-3 shrink-0", "aria-hidden": true }),
renderRow({ node, depth, open: isOpen, selected: isSelected, hasChildren, toggle })
]
}
),
isOpen && hasChildren && /* @__PURE__ */ jsx("div", { role: "group", children: children.map((child) => /* @__PURE__ */ jsx(
TreeNode,
{
node: child,
depth: depth + 1,
expandAll,
forcedOpenKeys,
selected,
getChildren,
getKey,
renderRow,
indentPx,
basePaddingPx,
...defaultOpen ? { defaultOpen } : {},
...onSelect ? { onSelect } : {},
...rowClass ? { rowClass } : {},
...isSecondary ? { isSecondary } : {}
},
getKey(child)
)) })
]
}
);
}
export {
TreeNode
};
//# sourceMappingURL=TreeNode.js.map