import type { HTMLAttributes, ReactNode } from "react";
import { Children, createContext, isValidElement, useContext, useState } from "react";
import { cx } from "../../utils/cx.utils";
import { Icon } from "../icons/icon";
import "./tree.component.css";
interface TreeItemContextValue {
/** Whether this item is the last child among its siblings, so its connector line stops at the branch. */
isLast: boolean;
}
const TreeItemContext = createContext({ isLast: true });
/** Props accepted by {@link Tree.Item}. */
export interface TreeItemProps extends Omit, "onClick"> {
/** Label shown next to the branch/leaf icon. */
label: ReactNode;
/** Nested {@link Tree.Item} elements. When present, this item renders as an expandable branch. */
children?: ReactNode;
/** Whether the branch starts expanded. Defaults to `true`. Ignored on leaf items (no children). */
initialExpanded?: boolean;
}
/**
* Single node in a {@link Tree}, connected to its siblings and parent by
* guide lines. Renders as an expandable branch (folder) when it has nested
* `Tree.Item` children, or as a leaf (file) otherwise.
*
* @example
* ```tsx
*
*
*
* ```
*/
function TreeItem({ className, label, children, initialExpanded = true, ...rest }: TreeItemProps) {
const { isLast } = useContext(TreeItemContext);
const [expanded, setExpanded] = useState(initialExpanded);
const hasChildren = children != null && children !== false;
return (
);
}
/** Props accepted by {@link Tree}. */
export interface TreeProps extends Omit, "children"> {
/** {@link Tree.Item} elements forming the top level of the tree. */
children: ReactNode;
}
/**
* A hierarchical folder/file tree with guide lines connecting each node to
* its siblings and parent. Composes {@link Tree.Item}, which can itself
* nest further `Tree.Item`s to form branches; branches are expandable and
* collapsible.
*
* @example
* ```tsx
*
*
*
*
*
*
*
*
* ```
*/
export function Tree({ className, children, ...rest }: TreeProps) {
return (