'use client'; import styles from '@components/TreeView.module.css'; import * as React from 'react'; interface TreeViewProps { children?: React.ReactNode; defaultValue?: boolean; depth?: number; isFile?: boolean; isLastChild?: boolean; isRoot?: boolean; parentLines?: boolean[]; style?: any; title: string; } const TreeView: React.FC = ({ defaultValue = false, title, children, depth = 0, isFile = false, isRoot = false, isLastChild = false, style, parentLines = [] }) => { const [show, setShow] = React.useState(defaultValue); const onToggleShow = (): void => { if (!isFile) setShow((prevShow) => !prevShow); }; const hasChildren = React.Children.count(children) > 0; const isEmptyFolder = !isFile && !hasChildren; const spacing = parentLines.map((line) => (line ? '│ . ' : '. . ')).join(''); const endPrefix = isLastChild ? '└───' : '├───'; const prefix = `${spacing}${endPrefix}`; const icon = isFile ? ' ' : show ? '╦ ' : '╤ '; const updatedParentLines = [...parentLines, !isLastChild]; return (
{ if (e.key === 'Enter' || e.key === ' ') { if (e.key === ' ') e.preventDefault(); onToggleShow(); } }} className={styles.item} aria-expanded={show}> {prefix} {icon} {title}
{show && hasChildren && (
{React.Children.map(children, (child, index) => React.isValidElement(child) ? React.cloneElement( child as React.ReactElement, { depth: depth + 1, isLastChild: index === React.Children.count(children) - 1, parentLines: updatedParentLines, } as any ) : child )}
)}
); }; export default TreeView;