diff --git a/components/tree/tree-context.ts b/components/tree/tree-context.ts index a36969f64..e0348b0fc 100644 --- a/components/tree/tree-context.ts +++ b/components/tree/tree-context.ts @@ -4,11 +4,13 @@ export interface TreeConfig { onFileClick?: (path: string) => void initialExpand: boolean isImperative: boolean + noSort: boolean } const defaultContext = { initialExpand: false, isImperative: false, + noSort: false, } export const TreeContext = React.createContext<TreeConfig>(defaultContext) diff --git a/components/tree/tree-folder.tsx b/components/tree/tree-folder.tsx index 2f68842c1..567976acc 100644 --- a/components/tree/tree-folder.tsx +++ b/components/tree/tree-folder.tsx @@ -37,7 +37,7 @@ const TreeFolder: React.FC<React.PropsWithChildren<TreeFolderProps>> = ({ ...props }: React.PropsWithChildren<TreeFolderProps> & typeof defaultProps) => { const theme = useTheme() - const { initialExpand, isImperative } = useTreeContext() + const { initialExpand, isImperative, noSort } = useTreeContext() const [expanded, setExpanded] = useState<boolean>(initialExpand) useEffect(() => setExpanded(initialExpand), []) @@ -55,7 +55,7 @@ const TreeFolder: React.FC<React.PropsWithChildren<TreeFolderProps>> = ({ const sortedChildren = isImperative ? nextChildren - : sortChildren(nextChildren, TreeFolder) + : sortChildren(nextChildren, TreeFolder, noSort) return ( <div className={useClasses('folder', className)} onClick={clickHandler} {...props}> diff --git a/components/tree/tree-help.ts b/components/tree/tree-help.ts index 7ddba86a7..a8482c72d 100644 --- a/components/tree/tree-help.ts +++ b/components/tree/tree-help.ts @@ -3,12 +3,18 @@ import React, { ReactNode } from 'react' export const sortChildren = ( children: ReactNode | undefined, folderComponentType: React.ElementType, + noSort: boolean ) => { - return React.Children.toArray(children).sort((a, b) => { - if (!React.isValidElement(a) || !React.isValidElement(b)) return 0 - if (a.type !== b.type) return a.type !== folderComponentType ? 1 : -1 - return `${a.props.name}`.charCodeAt(0) - `${b.props.name}`.charCodeAt(0) - }) + if (!noSort) { + // Sort + return React.Children.toArray(children).sort((a, b) => { + if (!React.isValidElement(a) || !React.isValidElement(b)) return 0 + if (a.type !== b.type) return a.type !== folderComponentType ? 1 : -1 + return `${a.props.name}`.charCodeAt(0) - `${b.props.name}`.charCodeAt(0) + }) + } else { + return React.Children.toArray(children); + } } export const makeChildPath = (name: string, parentPath?: string) => { diff --git a/components/tree/tree.tsx b/components/tree/tree.tsx index f0530f391..ac1c7da50 100644 --- a/components/tree/tree.tsx +++ b/components/tree/tree.tsx @@ -22,32 +22,36 @@ interface Props { initialExpand?: boolean onClick?: (path: string) => void className?: string + noSort?: boolean } const defaultProps = { initialExpand: false, className: '', + noSort: false, } type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props> export type TreeProps = Props & NativeAttrs -const makeChildren = (value: Array<TreeFile> = []) => { +const makeChildren = (value: Array<TreeFile> = [], noSort: boolean) => { if (!value || !value.length) return null - return value - .sort((a, b) => { + if (!noSort) { + // Sort + value = value.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) => { + } + return value.map((item, index) => { if (item.type === directoryType) return ( <TreeFolder name={item.name} extra={item.extra} key={`folder-${item.name}-${index}`}> - {makeChildren(item.files)} + {makeChildren(item.files, noSort)} </TreeFolder> ) return ( @@ -66,6 +70,7 @@ const Tree: React.FC<React.PropsWithChildren<TreeProps>> = ({ initialExpand, value, className, + noSort, ...props }: React.PropsWithChildren<TreeProps> & typeof defaultProps) => { const isImperative = Boolean(value && value.length > 0) @@ -78,13 +83,14 @@ const Tree: React.FC<React.PropsWithChildren<TreeProps>> = ({ onFileClick, initialExpand, isImperative, + noSort, }), [initialExpand], ) const customChildren = isImperative - ? makeChildren(value) - : sortChildren(children, TreeFolder) + ? makeChildren(value, noSort) + : sortChildren(children, TreeFolder, noSort) return ( <TreeContext.Provider value={initialValue}> diff --git a/pages/en-us/components/file-tree.mdx b/pages/en-us/components/file-tree.mdx index cde18201a..b549a95ac 100644 --- a/pages/en-us/components/file-tree.mdx +++ b/pages/en-us/components/file-tree.mdx @@ -68,7 +68,7 @@ Display a list of files and folders in a hierarchical tree structure. <Playground title="Extra Message" - desc="Use props `value` to show more complex file tree." + desc="Use props `value` to show more complex file tree. Also ask for NO sorting" scope={{ Tree }} code={` () => { @@ -102,8 +102,17 @@ Display a list of files and folders in a hierarchical tree structure. type: 'file', name: 'views.md', extra: '8.1kb', + }, { + type: 'file', + name: 'abc.md', + extra: '9kb', + }, { + type: 'directory', + name: 'empty', + extra: '0 files', + files: [], }] - return <Tree value={files} /> + return <Tree value={files} noSort="true" /> } `} /> @@ -142,6 +151,7 @@ Display a list of files and folders in a hierarchical tree structure. | ----------------- | ----------------- | ------------------------ | --------------------------------- | ------- | | **value** | value of files | `Array<FileTreeValue>` | - | - | | **initialExpand** | expand by default | `boolean` | - | `false` | +| **noSort** | no sort elements | `boolean` | - | `false` | | **onClick** | click file event | `(path: string) => void` | - | - | | ... | native props | `HTMLAttributes` | `'id', 'title', 'className', ...` | - |