Skip to content

Commit

Permalink
feat(transfer): #2477
Browse files Browse the repository at this point in the history
  • Loading branch information
zyprepare committed May 10, 2023
1 parent d4c0b21 commit 69e7d04
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 15 deletions.
3 changes: 3 additions & 0 deletions .changeset-pending/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 变更记录文件

暂时不发版的组件对应的 changeset 变更记录文件移入到此目录,需要发版时将对应的文件移入到 .changeset 目录中即可。
5 changes: 5 additions & 0 deletions .changeset-pending/itchy-drinks-teach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hi-ui/hiui": patch
---

Transfer feat: 增加树形穿梭框
5 changes: 5 additions & 0 deletions .changeset-pending/poor-meals-collect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hi-ui/transfer": minor
---

feat: 增加树形穿梭框
9 changes: 9 additions & 0 deletions packages/ui/transfer/src/Transfer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const Transfer = forwardRef<HTMLDivElement | null, TransferProps>(
emptyContent,
render: titleRender,
draggable = false,
leftListRender,
onChange,
onDragStart,
onDragLeave,
Expand Down Expand Up @@ -293,6 +294,7 @@ export const Transfer = forwardRef<HTMLDivElement | null, TransferProps>(
isCheckedIds={isSourceCheckedIds}
overflowed={isOverflowed}
draggable={false}
listRender={leftListRender}
onItemClick={(item) => {
onItemClick(item, 'right')
}}
Expand Down Expand Up @@ -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__) {
Expand Down
43 changes: 28 additions & 15 deletions packages/ui/transfer/src/TransferPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,16 @@ export const TransferPanel = forwardRef<HTMLDivElement | null, TransferPanelProp
targetSortType,
onItemClick,
draggable = false,
listRender,
...rest
},
ref
) => {
const i18n = useLocaleContext()
const limitContent = i18n.get('transfer.limit')

const customize = !!listRender

const { searchable, pageSize, showCheckAll } = useTransferContext()

const [searchValue, setSearchValue] = useState('')
Expand Down Expand Up @@ -111,6 +114,7 @@ export const TransferPanel = forwardRef<HTMLDivElement | null, TransferPanelProp
}, [current, cacheData, pageSize])

const showHeader = showCheckAll || title
const showPagination = !customize && pageSize

const cls = cx(prefixCls, className)

Expand Down Expand Up @@ -163,26 +167,31 @@ export const TransferPanel = forwardRef<HTMLDivElement | null, TransferPanelProp
</div>
) : null}
{showData.length > 0 ? (
<ul className={`${prefixCls}__list`}>
{showData.map((item) => {
return (
<TransferItem
key={item.id}
data={item}
onCheck={onCheck}
checked={isCheckedIds(item.id)}
draggable={draggable}
onClick={onItemClick}
/>
)
})}
</ul>
listRender?.({
checkedIds,
onCheck: setCheckedIds,
}) ?? (
<ul className={`${prefixCls}__list`}>
{showData.map((item) => {
return (
<TransferItem
key={item.id}
data={item}
onCheck={onCheck}
checked={isCheckedIds(item.id)}
draggable={draggable}
onClick={onItemClick}
/>
)
})}
</ul>
)
) : (
<div className={`${prefixCls}__empty`}>{emptyContent}</div>
)}
</div>
</div>
{pageSize ? (
{showPagination ? (
<div className={`${prefixCls}__footer`}>
<ShrinkPagination
size="sm"
Expand Down Expand Up @@ -273,6 +282,10 @@ export interface TransferPanelProps {
onCheck: (targetItem: TransferDataItem, shouldChecked: boolean) => void
isCheckedIds: (id: React.ReactText) => boolean
onItemClick: (item: TransferDataItem) => void
listRender?: (props: {
checkedIds: React.ReactText[]
onCheck: (checkedIds: React.ReactText[]) => void
}) => React.ReactNode
}

if (__DEV__) {
Expand Down
1 change: 1 addition & 0 deletions packages/ui/transfer/stories/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
105 changes: 105 additions & 0 deletions packages/ui/transfer/stories/tree.stories.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Transfer
{...restProps}
data={transferDataSource}
targetIds={targetIds}
type="multiple"
showCheckAll={false}
leftListRender={({ checkedIds, onCheck }) => {
const ids = [...checkedIds, ...targetIds]
return (
<Tree
checkable
defaultExpandAll
checkedIds={ids}
data={generateTree(data, targetIds)}
checkedMode="SEPARATE"
onCheck={(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<React.ReactText[]>([3, 5])

return (
<>
<h1>Tree</h1>
<div className="transfer-tree__wrap">
<TreeTransfer
data={data}
targetIds={targetIds}
onChange={(ids) => {
console.log('onChange', ids)
setTargetIds(ids)
}}
emptyContent={['暂无数据']}
/>
</div>
</>
)
}

0 comments on commit 69e7d04

Please sign in to comment.