From 69e7d042c18a2d27fb5c708c7306aeeeea2565b0 Mon Sep 17 00:00:00 2001 From: zhouyun1 Date: Wed, 10 May 2023 17:04:05 +0800 Subject: [PATCH 1/2] feat(transfer): #2477 --- .changeset-pending/README.md | 3 + .changeset-pending/itchy-drinks-teach.md | 5 + .changeset-pending/poor-meals-collect.md | 5 + packages/ui/transfer/src/Transfer.tsx | 9 ++ packages/ui/transfer/src/TransferPanel.tsx | 43 ++++--- .../ui/transfer/stories/index.stories.tsx | 1 + packages/ui/transfer/stories/tree.stories.tsx | 105 ++++++++++++++++++ 7 files changed, 156 insertions(+), 15 deletions(-) create mode 100644 .changeset-pending/README.md create mode 100644 .changeset-pending/itchy-drinks-teach.md create mode 100644 .changeset-pending/poor-meals-collect.md create mode 100644 packages/ui/transfer/stories/tree.stories.tsx 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/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..97bb84a08 100644 --- a/packages/ui/transfer/src/TransferPanel.tsx +++ b/packages/ui/transfer/src/TransferPanel.tsx @@ -39,6 +39,7 @@ export const TransferPanel = forwardRef ) : null} {showData.length > 0 ? ( -
    - {showData.map((item) => { - return ( - - ) - })} -
+ 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..c12d0d5ac --- /dev/null +++ b/packages/ui/transfer/stories/tree.stories.tsx @@ -0,0 +1,105 @@ +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 ( + { + 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={['暂无数据']} + /> +
+ + ) +} From 2cb27d5fd178a3caa05c020cba8e74eb4cb29166 Mon Sep 17 00:00:00 2001 From: zhouyun1 Date: Thu, 11 May 2023 09:43:49 +0800 Subject: [PATCH 2/2] =?UTF-8?q?chore(transfer):=20=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/check-select/src/utils/index.ts | 2 +- packages/ui/transfer/src/TransferPanel.tsx | 2 +- packages/ui/transfer/stories/tree.stories.tsx | 25 +++++++++++-------- 3 files changed, 16 insertions(+), 13 deletions(-) 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/TransferPanel.tsx b/packages/ui/transfer/src/TransferPanel.tsx index 97bb84a08..ec523a82a 100644 --- a/packages/ui/transfer/src/TransferPanel.tsx +++ b/packages/ui/transfer/src/TransferPanel.tsx @@ -166,7 +166,7 @@ export const TransferPanel = forwardRef{limitContent}
) : null} - {showData.length > 0 ? ( + {showData.length > 0 || customize ? ( listRender?.({ checkedIds, onCheck: setCheckedIds, diff --git a/packages/ui/transfer/stories/tree.stories.tsx b/packages/ui/transfer/stories/tree.stories.tsx index c12d0d5ac..922a9f29a 100644 --- a/packages/ui/transfer/stories/tree.stories.tsx +++ b/packages/ui/transfer/stories/tree.stories.tsx @@ -35,20 +35,23 @@ export const TreeTransfer = () => { data={transferDataSource} targetIds={targetIds} type="multiple" - showCheckAll={false} + showCheckAll={true} leftListRender={({ checkedIds, onCheck }) => { const ids = [...checkedIds, ...targetIds] return ( - { - onCheck(checkedIds.filter((item) => !targetIds.includes(item))) - }} - /> +
+ { + console.log(checkedIds) + onCheck(checkedIds.filter((item) => !targetIds.includes(item))) + }} + /> +
) }} />