Skip to content

Commit

Permalink
feat(check-cascader): #2595
Browse files Browse the repository at this point in the history
  • Loading branch information
zyprepare committed Sep 22, 2023
1 parent cde6e3b commit 9be456e
Show file tree
Hide file tree
Showing 9 changed files with 299 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/afraid-guests-smoke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hi-ui/check-cascader": minor
---

feat: 增加 renderExtraFooter 和 dropdownColumnRender api
5 changes: 5 additions & 0 deletions .changeset/red-plants-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hi-ui/hiui": patch
---

feat: 增加 renderExtraFooter 和 dropdownColumnRender api
16 changes: 11 additions & 5 deletions packages/ui/cascader/src/CascaderMenuList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,26 @@ import { checkCanLoadChildren, getItemEventData } from './utils'
import { useCascaderContext } from './context'
import { CascaderDataItem, FlattedCascaderDataItem, CascaderItemEventData } from './types'
import { getTopDownAncestors } from '@hi-ui/tree-utils'
import { isArrayNonEmpty } from '@hi-ui/type-assertion'
import { isArrayNonEmpty, isFunction } from '@hi-ui/type-assertion'

const menuListPrefix = getPrefixCls('cascader-menu-list')

export const CascaderMenuList = forwardRef<HTMLDivElement | null, CascaderMenuListProps>(
({ prefixCls = menuListPrefix, className, ...rest }, ref) => {
const { flatted, menuList } = useCascaderContext()
const { flatted, menuList, dropdownColumnRender } = useCascaderContext()

const cls = cx(prefixCls, className, flatted && `${prefixCls}--flatted`)

return (
<div ref={ref} className={cls} {...rest}>
{menuList.map((menu, menuIndex) => {
// @ts-ignore
return isArrayNonEmpty(menu) ? <CascaderMenu key={menuIndex} data={menu} /> : null
return isArrayNonEmpty(menu) ? (
isFunction(dropdownColumnRender) ? (
dropdownColumnRender(<CascaderMenu key={menuIndex} data={menu} />, menuIndex)
) : (
<CascaderMenu key={menuIndex} data={menu} />
)
) : null
})}
</div>
)
Expand All @@ -40,6 +45,7 @@ export const CascaderMenu = ({
prefixCls = menuPrefix,
role = 'menu',
className,
style,
data: menu,
}: CascaderMenuProps) => {
const {
Expand All @@ -56,7 +62,7 @@ export const CascaderMenu = ({
const cls = cx(prefixCls, className)

return (
<ul className={cls} role={role}>
<ul className={cls} style={style} role={role}>
{menu.map((option) => {
const eventOption = getItemEventData(option, getItemRequiredProps(option))

Expand Down
14 changes: 13 additions & 1 deletion packages/ui/check-cascader/src/CheckCascader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
import { flattenTreeData } from './utils'
import { getNodeAncestorsWithMe, getTopDownAncestors } from '@hi-ui/tree-utils'
import { useLatestCallback } from '@hi-ui/use-latest'
import { isArrayNonEmpty, isUndef } from '@hi-ui/type-assertion'
import { isArrayNonEmpty, isFunction, isUndef } from '@hi-ui/type-assertion'
import { HiBaseAppearanceEnum, HiBaseSizeEnum, useLocaleContext } from '@hi-ui/core'

import { callAllFuncs } from '@hi-ui/func-utils'
Expand Down Expand Up @@ -70,6 +70,8 @@ export const CheckCascader = forwardRef<HTMLDivElement | null, CheckCascaderProp
onClose,
tagInputProps,
size = 'md',
renderExtraFooter,
dropdownColumnRender,
...rest
},
ref
Expand Down Expand Up @@ -222,6 +224,7 @@ export const CheckCascader = forwardRef<HTMLDivElement | null, CheckCascaderProp
onClose={menuVisibleAction.off}
searchable={searchable}
scrollable={false}
footer={isFunction(renderExtraFooter) && renderExtraFooter()}
onSearch={callAllFuncs(onSearchProp, onSearch)}
trigger={
<TagInputMock
Expand Down Expand Up @@ -264,6 +267,7 @@ export const CheckCascader = forwardRef<HTMLDivElement | null, CheckCascaderProp
data={cascaderData}
onChangeData={setCascaderData}
checkedMode={checkedMode}
dropdownColumnRender={dropdownColumnRender}
/>
) : null}
</Picker>
Expand Down Expand Up @@ -375,6 +379,14 @@ export interface CheckCascaderProps extends Omit<PickerProps, 'trigger' | 'scrol
* 设置尺寸
*/
size?: HiBaseSizeEnum
/**
* 自定义下拉菜单底部渲染
*/
renderExtraFooter?: () => React.ReactNode
/**
* 自定义下拉菜单每列渲染
*/
dropdownColumnRender?: (menu: React.ReactElement, level: number) => React.ReactNode
}

if (__DEV__) {
Expand Down
3 changes: 2 additions & 1 deletion packages/ui/check-cascader/src/CheckCascaderMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const CheckCascaderMenu = ({
prefixCls = _prefix,
role = _role,
className,
style,
data: menu,
getCascaderItemRequiredProps,
}: CheckCascaderMenuProps) => {
Expand Down Expand Up @@ -65,7 +66,7 @@ export const CheckCascaderMenu = ({
const cls = cx(prefixCls, className, isCheckableMenu && `${prefixCls}--checkable`)

return (
<ul className={cls} role={role}>
<ul className={cls} style={style} role={role}>
{menu.map((option) => {
const eventOption = getCascaderItemEventData(option, getCascaderItemRequiredProps(option))
const { selected, checked, loading, semiChecked } = eventOption
Expand Down
18 changes: 14 additions & 4 deletions packages/ui/check-cascader/src/CheckCascaderMenuList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { CheckCascaderMenu } from './CheckCascaderMenu'
import { CheckCascaderProvider } from './context'
import { getActiveMenus, getFlattedMenus, getActiveMenuIds } from './utils'
import { useCheck, useSelect, useAsyncSwitch } from './hooks'
// import { fFindNodesByIds } from '@hi-ui/tree-utils'
import { isFunction } from '@hi-ui/type-assertion'

const _role = 'check-cascader-menus'
const _prefix = getPrefixCls(_role)
Expand All @@ -40,6 +40,7 @@ export const CheckCascaderMenuList = forwardRef<HTMLDivElement | null, CascaderM
onChange,
onSelect,
titleRender,
dropdownColumnRender,
flatted,
checkedMode = 'ALL',
...rest
Expand Down Expand Up @@ -91,11 +92,11 @@ export const CheckCascaderMenuList = forwardRef<HTMLDivElement | null, CascaderM
disabled,
}),
[
changeOnSelect,
expandTrigger,
onOptionCheck,
onItemExpand,
flatted,
changeOnSelect,
titleRender,
onLoadChildren,
disabled,
Expand All @@ -115,13 +116,18 @@ export const CheckCascaderMenuList = forwardRef<HTMLDivElement | null, CascaderM
<CheckCascaderProvider value={providedValue}>
<div ref={ref} role={role} className={cls} {...rest}>
{menus.map((menu, menuIndex) => {
return menu.length > 0 ? (
const menuContent = (
<CheckCascaderMenu
key={menuIndex}
data={menu}
getCascaderItemRequiredProps={getCascaderItemRequiredProps}
/>
) : null
)
return menu.length > 0
? isFunction(dropdownColumnRender)
? dropdownColumnRender(menuContent, menuIndex)
: menuContent
: null
})}
</div>
</CheckCascaderProvider>
Expand Down Expand Up @@ -190,6 +196,10 @@ export interface CascaderMenusProps {
* 自定义渲染节点的 title 内容
*/
titleRender?: (item: CheckCascaderItemEventData) => React.ReactNode
/**
* 自定义下拉菜单每列渲染
*/
dropdownColumnRender?: (menu: React.ReactElement, level: number) => React.ReactNode
/**
* 多选数据交互时回填、回显模式
* PARENT: 当所有子节点被选中时将只保留父节点
Expand Down
153 changes: 153 additions & 0 deletions packages/ui/check-cascader/stories/dropdown-column-render.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import React from 'react'
import CheckCascader from '../src'

/**
* @title 自定义下拉菜单内容
*/
export const DropdownColumnRender = () => {
const [dataOnlyLeafCheckable] = React.useState(() => {
const data = [
{
id: '手机',
title: '手机t',
children: [
{
id: '小米',
title: '小米t',
children: [
{
id: '小米3',
title: '小米3t',
},
{
id: '小米4',
title: '小米4t',
},
],
},
{
id: '红米',
title: '红米t',
children: [
{
id: '红米3',
title: '红米3t',
},
{
id: '红米4',
title: '红米4t',
},
],
},
],
},
{
id: '电视',
title: '电视t',
children: [
{
id: '小米电视4A',
title: '小米电视4At',
},
{
id: '小米电视4C',
title: '小米电视4Ct',
},
],
},
{
id: '1',
title: '小米1',
},
{
id: '2',
title: '小米2',
},
{
id: '3',
title: '小米3',
},
{
id: '4',
title: '小米4',
},
{
id: '5',
title: '小米5',
},
{
id: '6',
title: '小米6',
},
{
id: '7',
title: '小米7',
},
]

const getDataOnlyLeafCheckable = (data: any) => {
return data.map((item: any) => {
if (item.children) {
item.checkable = item.checkable ?? false
item.children = getDataOnlyLeafCheckable(item.children)
}

return item
})
}

const dataOnlyLeafCheckable = getDataOnlyLeafCheckable(data)

return dataOnlyLeafCheckable
})

return (
<>
<h1>DropdownColumnRender</h1>
<div className="cascader-dropdown-column-render__wrap">
<CheckCascader
style={{ width: 240 }}
searchable={false}
// clearable
placeholder="请选择品类"
defaultValue={[['手机', '红米', '红米4']]}
changeOnSelect
data={dataOnlyLeafCheckable}
onChange={console.log}
// 如果有样式不满足需求,可以给弹出层设置独有的 className 来进行样式覆写
overlay={{ className: 'my-overlay' }}
dropdownColumnRender={(menu, level) => {
return level < 5 ? (
<div
className="custom-menu"
style={{ overflow: 'hidden', borderRight: '1px solid #ebedf0' }}
>
<header
style={{
lineHeight: '20px',
padding: '0px 8px 8px',
borderBottom: '1px solid #ebedf0',
}}
>
header
</header>
{React.cloneElement(menu, { style: { height: 198 } })}
<footer
style={{
lineHeight: '20px',
padding: '8px 8px 0',
borderTop: '1px solid #ebedf0',
}}
>
footer(level {level})
</footer>
</div>
) : (
menu
)
}}
></CheckCascader>
</div>
</>
)
}
Loading

0 comments on commit 9be456e

Please sign in to comment.