-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: new component Catalogue in v5 (#389)
* feat(Catalogue): new component, catalogue initial * chore(Catalogue): lint * docs: update demo docs * feat: clear searchStr when close search * docs: update demo docs * feat: add defaultStatus & onStatusChange props in Catalogue.DtTree * chore: rename dtTree、dtTreeSelect to Tree、TreeSelect * chore: update demos and docs * chore: treeTit prop exchange to treeTitle --------- Co-authored-by: dilu <dilu@dtstack.com>
- Loading branch information
Showing
22 changed files
with
2,156 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { default as Tree } from './tree'; | ||
export { type ITabsStatus, type ITreeDataItem } from './tree'; | ||
export { default as TreeSelect } from './treeSelect'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import * as React from 'react'; | ||
import { MenuFoldOutlined, MenuUnfoldOutlined, ProfileFilled } from '@ant-design/icons'; | ||
|
||
import { ITreeProps } from '../../'; | ||
import './style.scss'; | ||
|
||
export const prefixCls = 'dtTreeHeaderWrapper'; | ||
|
||
export const btnSlotProp = 'btnSlot'; | ||
|
||
export interface ITreeHeaderProps { | ||
/** 目录标题 */ | ||
title?: React.ReactNode; | ||
/** 是否收起 */ | ||
collapsed?: boolean; | ||
/** 展开、收起的回调 */ | ||
onCollapsed?: (collapsed: boolean) => void; | ||
/** Header 右侧按扭组插槽【建议 icon 不超过3个,超出使用更多icon,下拉显示】,showHeader 为 true 时生效 */ | ||
btnSlot?: React.ReactElement; | ||
size?: ITreeProps['size']; | ||
} | ||
|
||
export default (props: ITreeHeaderProps) => { | ||
const { onCollapsed, btnSlot } = props; | ||
const handleCollapsed = (flag: boolean) => (_: any) => { | ||
onCollapsed?.(flag); | ||
}; | ||
return ( | ||
<div className={prefixCls}> | ||
<div className={`${prefixCls}-left`}> | ||
<ProfileFilled className={`${prefixCls}-left__catalogueIcon`} /> | ||
<span className={`${prefixCls}-left__title`}>{props?.title ?? ''}</span> | ||
</div> | ||
<div className={`${prefixCls}-right`}> | ||
{btnSlot} | ||
{props.collapsed ? ( | ||
<MenuUnfoldOutlined | ||
className={`${prefixCls}-menuFold`} | ||
onClick={handleCollapsed(false)} | ||
/> | ||
) : ( | ||
<MenuFoldOutlined | ||
className={`${prefixCls}-menuFold`} | ||
onClick={handleCollapsed(true)} | ||
/> | ||
)} | ||
</div> | ||
</div> | ||
); | ||
}; |
27 changes: 27 additions & 0 deletions
27
src/catalogue/components/tree/components/header/style.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
.dtTreeHeaderWrapper { | ||
display: flex; | ||
align-items: center; | ||
justify-content: space-between; | ||
padding: 12px 12px 0; | ||
margin-bottom: 8px; | ||
&-left { | ||
display: flex; | ||
align-items: center; | ||
&__catalogueIcon { | ||
font-size: 20px; | ||
margin-right: 4px; | ||
color: #1D78FF; | ||
} | ||
&__title { | ||
font-size: 14px; | ||
} | ||
} | ||
&-right { | ||
display: flex; | ||
align-items: center; | ||
} | ||
&-menuFold { | ||
font-size: 20px; | ||
color: #AAA; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default as Header } from './header'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import * as React from 'react'; | ||
import { FolderFilled, FolderOpenFilled } from '@ant-design/icons'; | ||
import type { TreeProps } from 'antd'; | ||
import type { DataNode } from 'antd/es/tree'; | ||
import { ContextMenu } from 'dt-react-component'; | ||
|
||
import type { ITreeDataItem } from '..'; | ||
|
||
/** | ||
* @description 根据 query 计算应该展开的 expendKeys | ||
*/ | ||
export const getExpendKeysByQuery = ({ | ||
tree, | ||
searchStr, | ||
}: { | ||
/** 树数据 */ | ||
tree: DataNode[]; | ||
/** 搜索字符串 */ | ||
searchStr: string; | ||
}): React.Key[] => { | ||
const keys: React.Key[] = []; | ||
if (!searchStr) return []; | ||
tree?.forEach?.((item) => { | ||
if (item?.title?.toString()?.includes?.(searchStr)) { | ||
keys.push(item.key); | ||
} | ||
if (item?.children && item?.children?.length) { | ||
keys.push(...getExpendKeysByQuery({ tree: item?.children, searchStr })); | ||
} | ||
}); | ||
return keys; | ||
}; | ||
|
||
/** | ||
* @description 文件 展开/收起样式 | ||
*/ | ||
export const getIcon: DataNode['icon'] = ({ expanded, data }) => { | ||
if (!data) return null; | ||
if (!data?.hasOwnProperty('children')) return null; | ||
const styles: React.CSSProperties = { | ||
fontSize: 14, | ||
color: '#1D78FF', | ||
}; | ||
if (expanded) return <FolderOpenFilled style={styles} />; | ||
return <FolderFilled style={styles} />; | ||
}; | ||
|
||
/** | ||
* @description 轮询 Tree 数据,赋值 搜索标识和leafIcon | ||
*/ | ||
export const loopTree = ( | ||
data: ITreeDataItem[] | undefined, | ||
searchValue: string | ||
): TreeProps['treeData'] => { | ||
return data?.map((item: ITreeDataItem) => { | ||
const strTitle = item?.title as string; | ||
const index = strTitle?.indexOf?.(searchValue); | ||
const beforeStr = strTitle?.substring?.(0, index); | ||
const afterStr = strTitle?.slice?.(index + searchValue?.length); | ||
const contextMenuData = | ||
item?.contextMenuConfig?.data?.map?.((e: any) => ({ | ||
...e, | ||
cb: () => { | ||
item?.contextMenuConfig?.onClick(e, item); | ||
}, | ||
})) || []; | ||
const title = | ||
index > -1 ? ( | ||
<ContextMenu data={contextMenuData}> | ||
{beforeStr} | ||
<span style={{ color: '#f50' }}>{searchValue}</span> | ||
{afterStr} | ||
</ContextMenu> | ||
) : ( | ||
<ContextMenu data={contextMenuData}>{strTitle}</ContextMenu> | ||
); | ||
if (item.children) { | ||
return { | ||
icon: getIcon, | ||
...item, | ||
title, | ||
key: item.key, | ||
children: loopTree(item.children, searchValue), | ||
}; | ||
} | ||
return { ...item, title, key: item.key, children: undefined }; | ||
}); | ||
}; |
Oops, something went wrong.