diff --git a/.changeset-pending/README.md b/.changeset-pending/README.md new file mode 100644 index 000000000..589d9bb72 --- /dev/null +++ b/.changeset-pending/README.md @@ -0,0 +1,3 @@ +# 变更记录文件 + +暂时不发版的组件对应的 changeset 变更记录文件移入到此目录,需要发版时将对应的文件移入到 .changeset 目录中即可。 diff --git a/.changeset-pending/itchy-drinks-teach.md b/.changeset-pending/itchy-drinks-teach.md new file mode 100644 index 000000000..cc25d17e5 --- /dev/null +++ b/.changeset-pending/itchy-drinks-teach.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/hiui": patch +--- + +Transfer feat: 增加树形穿梭框 diff --git a/.changeset-pending/poor-meals-collect.md b/.changeset-pending/poor-meals-collect.md new file mode 100644 index 000000000..1c8e0b6fb --- /dev/null +++ b/.changeset-pending/poor-meals-collect.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/transfer": minor +--- + +feat: 增加树形穿梭框 diff --git a/packages/ui/check-select/src/utils/index.ts b/packages/ui/check-select/src/utils/index.ts index 50ee67d83..f4f2f7002 100644 --- a/packages/ui/check-select/src/utils/index.ts +++ b/packages/ui/check-select/src/utils/index.ts @@ -19,7 +19,7 @@ export const isOption = (item: any) => { export const getAllCheckedStatus = ( dropdownItems: any[], - values: React.ReactText[], + values: React.ReactText[] = [], filterFunc: (item: any) => boolean ) => { const dropdownIds = dropdownItems.filter(filterFunc).map(({ id }: any) => id) diff --git a/packages/ui/transfer/src/Transfer.tsx b/packages/ui/transfer/src/Transfer.tsx index a367850b7..e906cfa92 100644 --- a/packages/ui/transfer/src/Transfer.tsx +++ b/packages/ui/transfer/src/Transfer.tsx @@ -43,6 +43,7 @@ export const Transfer = forwardRef( emptyContent, render: titleRender, draggable = false, + leftListRender, onChange, onDragStart, onDragLeave, @@ -293,6 +294,7 @@ export const Transfer = forwardRef( isCheckedIds={isSourceCheckedIds} overflowed={isOverflowed} draggable={false} + listRender={leftListRender} onItemClick={(item) => { onItemClick(item, 'right') }} @@ -439,6 +441,13 @@ export interface TransferProps * 开启分页 */ pagination?: boolean | { pageSize?: number } + /** + * 左边列表自定义渲染 + */ + leftListRender?: (props: { + checkedIds: React.ReactText[] + onCheck: (checkedIds: React.ReactText[]) => void + }) => React.ReactNode } if (__DEV__) { diff --git a/packages/ui/transfer/src/TransferPanel.tsx b/packages/ui/transfer/src/TransferPanel.tsx index cf2550971..ec523a82a 100644 --- a/packages/ui/transfer/src/TransferPanel.tsx +++ b/packages/ui/transfer/src/TransferPanel.tsx @@ -39,6 +39,7 @@ export const TransferPanel = forwardRef{limitContent} ) : null} - {showData.length > 0 ? ( -
    - {showData.map((item) => { - return ( - - ) - })} -
+ {showData.length > 0 || customize ? ( + listRender?.({ + checkedIds, + onCheck: setCheckedIds, + }) ?? ( +
    + {showData.map((item) => { + return ( + + ) + })} +
+ ) ) : (
{emptyContent}
)} - {pageSize ? ( + {showPagination ? (
void isCheckedIds: (id: React.ReactText) => boolean onItemClick: (item: TransferDataItem) => void + listRender?: (props: { + checkedIds: React.ReactText[] + onCheck: (checkedIds: React.ReactText[]) => void + }) => React.ReactNode } if (__DEV__) { diff --git a/packages/ui/transfer/stories/index.stories.tsx b/packages/ui/transfer/stories/index.stories.tsx index c14c69290..811925dc4 100644 --- a/packages/ui/transfer/stories/index.stories.tsx +++ b/packages/ui/transfer/stories/index.stories.tsx @@ -11,6 +11,7 @@ export * from './searchable.stories' export * from './pagination.stories' export * from './draggable.stories' export * from './render.stories' +export * from './tree.stories' export default { title: 'Data Input/Transfer', diff --git a/packages/ui/transfer/stories/tree.stories.tsx b/packages/ui/transfer/stories/tree.stories.tsx new file mode 100644 index 000000000..922a9f29a --- /dev/null +++ b/packages/ui/transfer/stories/tree.stories.tsx @@ -0,0 +1,108 @@ +import React from 'react' +import Tree, { TreeDataItem } from '@hi-ui/tree' +import Transfer, { TransferProps, TransferDataItem } from '../src' + +/** + * @title 树形穿梭框 + * @desc 自定义穿梭框的渲染 + */ +export const TreeTransfer = () => { + interface TreeTransferProps extends TransferProps { + data: TreeDataItem[] + } + + // 树形穿梭框组件 + const TreeTransfer = ({ data, targetIds, ...restProps }: TreeTransferProps) => { + const transferDataSource: TransferDataItem[] = [] + function flatten(list: TreeDataItem[] = []) { + list.forEach((item) => { + transferDataSource.push(item) + flatten(item.children) + }) + } + flatten(data) + + const generateTree = (treeNodes: TreeDataItem[] = [], checkedIds: React.ReactText[] = []) => + treeNodes.map(({ children, ...props }) => ({ + ...props, + disabled: checkedIds.includes(props.id as string), + children: generateTree(children, checkedIds), + })) + + return ( + { + const ids = [...checkedIds, ...targetIds] + return ( +
+ { + console.log(checkedIds) + onCheck(checkedIds.filter((item) => !targetIds.includes(item))) + }} + /> +
+ ) + }} + /> + ) + } + + const [data] = React.useState(() => { + return [ + { + id: 1, + title: '小米', + children: [ + { + id: 2, + title: '研发', + children: [ + { id: 3, title: '后端' }, + { id: 4, title: '运维' }, + { id: 5, title: '前端' }, + ], + }, + { id: 6, title: '产品' }, + ], + }, + { + id: 11, + title: '大米', + children: [ + { id: 22, title: '可视化' }, + { id: 66, title: 'HiUI' }, + ], + }, + ] + }) + + const [targetIds, setTargetIds] = React.useState([3, 5]) + + return ( + <> +

Tree

+
+ { + console.log('onChange', ids) + setTargetIds(ids) + }} + emptyContent={['暂无数据']} + /> +
+ + ) +}