diff --git a/.changeset/afraid-impalas-remain.md b/.changeset/afraid-impalas-remain.md new file mode 100644 index 000000000..6bb1e6928 --- /dev/null +++ b/.changeset/afraid-impalas-remain.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/menu": minor +--- + +feat: 新增支持配置字段别名 diff --git a/.changeset/fifty-teachers-admire.md b/.changeset/fifty-teachers-admire.md new file mode 100644 index 000000000..fc6cab7af --- /dev/null +++ b/.changeset/fifty-teachers-admire.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/hiui": patch +--- + +feat(menu): 新增支持配置字段别名 diff --git a/packages/ui/menu/src/Menu.tsx b/packages/ui/menu/src/Menu.tsx index 586790d15..c091e273e 100644 --- a/packages/ui/menu/src/Menu.tsx +++ b/packages/ui/menu/src/Menu.tsx @@ -10,7 +10,7 @@ import { cx, getPrefixCls } from '@hi-ui/classname' import { MenuFoldOutlined, MenuUnfoldOutlined } from '@hi-ui/icons' import { __DEV__ } from '@hi-ui/env' import { useUncontrolledState } from '@hi-ui/use-uncontrolled-state' -import { HiBaseHTMLProps, HiBaseSizeEnum } from '@hi-ui/core' +import { HiBaseFieldNames, HiBaseHTMLProps, HiBaseSizeEnum } from '@hi-ui/core' import Tooltip from '@hi-ui/tooltip' import { useUncontrolledToggle } from '@hi-ui/use-toggle' import { getTreeNodesWithChildren } from '@hi-ui/tree-utils' @@ -21,7 +21,7 @@ import { uuid } from '@hi-ui/use-id' import { MenuDataItem, MenuFooterRenderProps } from './types' import { MenuItem } from './MenuItem' import MenuContext from './context' -import { getAncestorIds } from './util' +import { getAncestorIds, transformTreeData } from './util' const MENU_PREFIX = getPrefixCls('menu') @@ -41,6 +41,7 @@ export const Menu = forwardRef( role = 'menu', className, data = NOOP_ARRAY, + fieldNames, placement = 'vertical', showCollapse = false, // 仅对垂直模式有效 @@ -70,14 +71,18 @@ export const Menu = forwardRef( const [activeParents, updateActiveParents] = useState(() => getAncestorIds(activeId, data)) + const transformedData = useMemo(() => { + return transformTreeData(data, fieldNames) + }, [data, fieldNames]) + useEffect(() => { - updateActiveParents(getAncestorIds(activeId, data)) - }, [activeId, data]) + updateActiveParents(getAncestorIds(activeId, transformedData)) + }, [activeId, transformedData]) const [expandedIds, updateExpandedIds] = useUncontrolledState( () => { return defaultExpandAll - ? getTreeNodesWithChildren(data).map((node) => node.id) + ? getTreeNodesWithChildren(transformedData).map((node) => node.id) : defaultExpandedIds }, expandedIdsProp, @@ -143,15 +148,15 @@ export const Menu = forwardRef( const [tagMaxCount, setTagMaxCount] = useState(0) const mergedTagList = useMemo(() => { - if (showVertical) return data - if (containerWidth < MIN_WIDTH) return data - return data.slice(0, Math.min(data.length, containerWidth / MIN_WIDTH)) - }, [showVertical, data, containerWidth]) + if (showVertical) return transformedData + if (containerWidth < MIN_WIDTH) return transformedData + return transformedData.slice(0, Math.min(transformedData.length, containerWidth / MIN_WIDTH)) + }, [showVertical, transformedData, containerWidth]) const restTagList = useMemo(() => { - if (tagMaxCount > 0) return data.slice(tagMaxCount) + if (tagMaxCount > 0) return transformedData.slice(tagMaxCount) return [] - }, [data, tagMaxCount]) + }, [transformedData, tagMaxCount]) const getTagWidth = useCallback( (index: number) => { @@ -303,6 +308,10 @@ export interface MenuProps extends Omit, 'onClick'> { * 菜单项数据列表 */ data: MenuDataItem[] + /** + * 设置 data 中 id, title, disabled, children 对应的 key + */ + fieldNames?: HiBaseFieldNames /** * 默认激活的菜单项 id */ diff --git a/packages/ui/menu/src/util.ts b/packages/ui/menu/src/util.ts index 03907e7e8..6ae78efef 100644 --- a/packages/ui/menu/src/util.ts +++ b/packages/ui/menu/src/util.ts @@ -1,5 +1,7 @@ import { filterTree, cloneTree, getTreeNodesWithChildren } from '@hi-ui/tree-utils' import { MenuDataItem } from './types' +import { HiBaseFieldNameKeys, HiBaseFieldNames } from '@hi-ui/core' +import React from 'react' // 寻找某一节点的父节点 export const getParentId = (id: string | number, data: Record[]): string | number => { @@ -55,3 +57,33 @@ export const filterTreeData = ( }) ?? [] ) } + +export const transformTreeData = (data: MenuDataItem[], fieldNames?: HiBaseFieldNames) => { + /** + * 转换对象 + */ + const getKeyFields = (node: MenuDataItem, key: HiBaseFieldNameKeys) => { + if (fieldNames) { + return node[(fieldNames[key] || key) as keyof MenuDataItem] + } + return node[key] + } + + /** + * 递归处理树形数组 + */ + const traverseTreeNode = (node: MenuDataItem): MenuDataItem => { + const newNode: MenuDataItem = { ...node } + newNode.id = getKeyFields(newNode, 'id') as React.ReactText + newNode.title = getKeyFields(newNode, 'title') + newNode.icon = getKeyFields(newNode, 'icon' as HiBaseFieldNameKeys) + newNode.disabled = (getKeyFields(newNode, 'disabled') ?? false) as boolean + newNode.children = getKeyFields(newNode, 'children') as MenuDataItem[] + if (newNode.children) { + newNode.children = newNode.children.map(traverseTreeNode) + } + return newNode + } + + return data.map(traverseTreeNode) +}