@ant-design/x
Version:
Craft AI-driven interfaces effortlessly
108 lines (105 loc) • 3.61 kB
JavaScript
import { FileOutlined, FolderOutlined } from '@ant-design/icons';
import { Tree } from 'antd';
import clsx from 'clsx';
import React, { useCallback } from 'react';
import { useXProviderContext } from "../x-provider";
// File tree node type
const {
DirectoryTree: AntDirectoryTree
} = Tree;
const DirectoryTree = ({
treeData,
selectedKeys,
expandedKeys,
onSelect,
onExpand,
showLine = false,
defaultExpandAll = true,
className,
classNames,
directoryIcons,
styles,
style,
directoryTitle,
prefixCls: customizePrefixCls
}) => {
// ============================ Tree Config ============================
const isFolder = node => {
return !!node.children && node.children.length > 0;
};
const getIcon = useCallback(node => {
// If directoryIcons is false or null, do not display icons
if (directoryIcons === false || directoryIcons === null) {
return null;
}
if (isFolder(node)) {
const icon = directoryIcons?.directory;
if (typeof icon === 'function') {
return icon();
}
return icon || /*#__PURE__*/React.createElement(FolderOutlined, null);
}
// Return corresponding icon based on file extension
const filePath = node.path.toLowerCase();
const extension = filePath.split('.').pop();
if (extension) {
// Check if custom icon configuration exists
const icon = directoryIcons?.[extension];
if (icon) {
return typeof icon === 'function' ? icon() : icon;
}
}
return /*#__PURE__*/React.createElement(FileOutlined, null);
}, [directoryIcons]);
const buildPathSegments = useCallback((node, parentSegments = []) => {
if (node.path === '/' && parentSegments.length === 0) {
return ['/'];
}
return [...parentSegments, node.path].filter(segment => segment !== '');
}, []);
const convertToTreeData = useCallback((nodes, parentSegments = []) => {
return nodes.map(node => {
const pathSegments = buildPathSegments(node, parentSegments);
const fullPath = pathSegments.join('/').replace(/^\/+/, '');
return {
...node,
key: fullPath,
path: fullPath,
pathSegments,
title: node.title,
icon: getIcon(node),
isLeaf: !isFolder(node),
children: node.children ? convertToTreeData(node.children, pathSegments) : undefined
};
});
}, [buildPathSegments, getIcon]);
const treeDataConverted = convertToTreeData(treeData);
const titleNode = directoryTitle === false || directoryTitle === null ? null : typeof directoryTitle === 'function' ? directoryTitle() : directoryTitle;
// ============================ Prefix ============================
const {
getPrefixCls
} = useXProviderContext();
const prefixCls = getPrefixCls('folder', customizePrefixCls);
return /*#__PURE__*/React.createElement(React.Fragment, null, titleNode ? /*#__PURE__*/React.createElement("div", {
style: {
...styles?.directoryTitle,
...style
},
className: clsx(`${prefixCls}-directory-tree-title`, className, classNames?.directoryTitle)
}, titleNode) : null, /*#__PURE__*/React.createElement(AntDirectoryTree, {
treeData: treeDataConverted,
selectedKeys: selectedKeys,
expandedKeys: expandedKeys,
onSelect: onSelect,
onExpand: onExpand,
multiple: false,
blockNode: true,
classNames: {
itemTitle: `${prefixCls}-directory-tree-item-title`
},
showLine: showLine,
defaultExpandAll: defaultExpandAll,
className: clsx(`${prefixCls}-directory-tree-content`)
}));
};
export default DirectoryTree;