import React, { useMemo } from 'react' import TreeLeaf from './tree-leaf' import TreeFolder from './tree-folder' import { TreeContext } from './tree-context' import { tuple } from '../utils/prop-types' import { sortChildren } from './/tree-help' const TreeValueType = tuple('directory', 'leaf') const directoryType = TreeValueType[0] export type TreeValue = { type?: (typeof TreeValueType)[number] | string name: string extra?: string children?: Array } interface Props { value?: Array initialExpand?: boolean onClick?: (path: string) => void selectableNodes?: boolean className?: string } const defaultProps = { initialExpand: false, type: TreeValueType[1], className: '' } type NativeAttrs = Omit, keyof Props> export type TreeProps = Props & typeof defaultProps & NativeAttrs const makeLeafs = (value: Array = []) => { if (!value || !value.length) return null return value .slice() .sort((a, b) => { if (a.type !== b.type) return a.type !== directoryType ? 1 : -1 return `${a.name}`.charCodeAt(0) - `${b.name}`.charCodeAt(0) }) .map((item, index) => { if (item.type === directoryType) return ( {makeLeafs(item.children)} ) return }) } const Tree: React.FC> = ({ children, onClick, selectableNodes, initialExpand, value, className, ...props }) => { const isImperative = Boolean(value && value.length > 0) const onLeafClick = (path: string) => { onClick && onClick(path) } const onNodeClick = selectableNodes ? (path: string) => { onClick && onClick(path) } : undefined const initialValue = useMemo( () => ({ onLeafClick, onNodeClick, initialExpand, isImperative }), [initialExpand, isImperative, onLeafClick, onNodeClick] ) const customChildren = isImperative ? makeLeafs(value) : sortChildren(children, TreeFolder) return (
{customChildren}
) } type TreeComponent

= React.FC

& { Leaf: typeof TreeLeaf File: typeof TreeLeaf Folder: typeof TreeFolder } type ComponentProps = Partial & Omit & NativeAttrs Tree.defaultProps = defaultProps export default Tree as TreeComponent