UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

124 lines (123 loc) • 4.72 kB
"use client"; import Icon from "../../Icon/Icon.mjs"; import { controlHeight } from "../controlSize.mjs"; import Checkbox_default from "../Checkbox/Checkbox.mjs"; import { styles } from "./style.mjs"; import { useTreeContext } from "./context.mjs"; import { hasChildren } from "./utils.mjs"; import { memo } from "react"; import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime"; import { cx } from "antd-style"; import { ChevronRight, File, Folder } from "lucide-react"; import { Collapsible } from "@base-ui/react/collapsible"; //#region src/base-ui/Tree/TreeNode.tsx const ARC = 6; const SWITCHER_CENTER = 11.5; const guidePath = (depth, isLast, trail, indent, height) => { const cx = (i) => i * indent + SWITCHER_CENTER; let d = ""; trail.forEach((more, i) => { if (more && i > 0) d += `M${cx(i)} 0V${height}`; }); const x = cx(depth - 1); const y = height / 2; const elbow = `M${x} ${y - ARC}A${ARC} ${ARC} 0 0 0 ${x + ARC} ${y}H${x + indent - 2}`; d += isLast ? `M${x} 0V${y - ARC}${elbow.slice(elbow.indexOf("A"))}` : `M${x} 0V${height}${elbow}`; return d; }; const TreeNode = memo(({ node, depth, isLast, trail }) => { const ctx = useTreeContext(); const expandable = hasChildren(node); const expanded = expandable && ctx.expanded.has(node.key); const disabled = ctx.disabled || !!node.disabled; const checkable = ctx.checkable && node.checkable !== false; const checkState = ctx.checked.has(node.key) ? "checked" : ctx.halfChecked.has(node.key) ? "mixed" : "unchecked"; const rowHeight = typeof ctx.styles.node?.height === "number" ? ctx.styles.node.height : controlHeight[ctx.size]; const switcherIcon = typeof ctx.switcherIcon === "function" ? ctx.switcherIcon({ expanded, node }) : ctx.switcherIcon ?? /* @__PURE__ */ jsx(Icon, { icon: ChevronRight, size: 14 }); const rowStyle = { height: rowHeight, paddingInlineStart: depth * ctx.indent, ...ctx.styles.node }; const select = (event) => ctx.toggleSelect(node, event); return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", { "data-scope-item": true, "aria-disabled": disabled || void 0, "aria-expanded": expandable ? expanded : void 0, "aria-level": depth + 1, "aria-selected": ctx.selected.has(node.key), "data-id": node.key, role: "treeitem", style: rowStyle, tabIndex: ctx.activeKey === node.key ? 0 : -1, "aria-checked": checkable ? checkState === "mixed" ? "mixed" : checkState === "checked" : void 0, className: cx(styles.node, ctx.blockNode && styles.nodeBlock, disabled && styles.nodeDisabled, ctx.classNames.node), onClick: ctx.blockNode ? select : void 0, onContextMenu: (event) => ctx.onRightClick(event, node), onFocus: () => ctx.setActiveKey(node.key), children: [ ctx.showLine && depth > 0 && /* @__PURE__ */ jsx("svg", { "aria-hidden": true, className: cx(styles.guide, ctx.classNames.guide), height: rowHeight, style: ctx.styles.guide, width: depth * ctx.indent, children: /* @__PURE__ */ jsx("path", { d: guidePath(depth, isLast, trail, ctx.indent, rowHeight) }) }), /* @__PURE__ */ jsx("button", { "aria-hidden": true, style: ctx.styles.switcher, tabIndex: -1, type: "button", className: cx(styles.switcher, !expandable && styles.switcherLeaf, ctx.classNames.switcher), onClick: (event) => { event.stopPropagation(); ctx.toggleExpand(node); }, children: switcherIcon }), checkable && /* @__PURE__ */ jsx(Checkbox_default, { checked: checkState === "checked", className: styles.checkbox, disabled, indeterminate: checkState === "mixed", onChange: () => ctx.toggleCheck(node), onClick: (event) => event.stopPropagation() }), ctx.showIcon && /* @__PURE__ */ jsx("span", { className: styles.icon, children: node.icon ?? /* @__PURE__ */ jsx(Icon, { icon: expandable ? Folder : File, size: 16 }) }), /* @__PURE__ */ jsx("span", { style: ctx.styles.title, className: cx(styles.title, ctx.blockNode ? styles.titleBlock : styles.titleInline, ctx.classNames.title), onClick: ctx.blockNode ? void 0 : select, children: ctx.titleRender ? ctx.titleRender(node) : node.title }) ] }), expandable && /* @__PURE__ */ jsx(Collapsible.Root, { open: expanded, children: /* @__PURE__ */ jsx(Collapsible.Panel, { className: styles.panel, children: node.children.map((child, i) => /* @__PURE__ */ jsx(TreeNode, { depth: depth + 1, isLast: i === node.children.length - 1, node: child, trail: [...trail, !isLast] }, child.key)) }) })] }); }); TreeNode.displayName = "TreeNode"; //#endregion export { TreeNode as default }; //# sourceMappingURL=TreeNode.mjs.map