Skip to content

Commit

Permalink
Merge pull request #2605 from XiaoMi/feature/cascader(#2594)
Browse files Browse the repository at this point in the history
feat(cascader): #2594
  • Loading branch information
solarjoker authored Sep 25, 2023
2 parents fbe2939 + 41056f0 commit 4db95ac
Show file tree
Hide file tree
Showing 8 changed files with 255 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/late-bags-film.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hi-ui/hiui": patch
---

Cascader feat: 增加 renderExtraFooter 和 dropdownColumnRender api
5 changes: 5 additions & 0 deletions .changeset/yellow-humans-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hi-ui/cascader": minor
---

feat: 增加 renderExtraFooter 和 dropdownColumnRender api
19 changes: 18 additions & 1 deletion packages/ui/cascader/src/Cascader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ export const Cascader = forwardRef<HTMLDivElement | null, CascaderProps>((props,
size = 'md',
onOpen,
onClose,
renderExtraFooter,
dropdownColumnRender,
...rest
} = props
const i18n = useLocaleContext()
Expand Down Expand Up @@ -204,7 +206,13 @@ export const Cascader = forwardRef<HTMLDivElement | null, CascaderProps>((props,

return (
<CascaderProvider
value={{ ...context, expandTrigger, titleRender: proxyTitleRender, menuList: showData }}
value={{
...context,
expandTrigger,
titleRender: proxyTitleRender,
menuList: showData,
dropdownColumnRender,
}}
>
<Picker
ref={ref}
Expand All @@ -219,6 +227,7 @@ export const Cascader = forwardRef<HTMLDivElement | null, CascaderProps>((props,
onClose={menuVisibleAction.off}
searchable={searchable}
scrollable={false}
footer={isFunction(renderExtraFooter) && renderExtraFooter()}
onSearch={callAllFuncs(onSearchProp, onSearch)}
trigger={
<MockInput
Expand Down Expand Up @@ -305,6 +314,14 @@ export interface CascaderProps
* 搜索结果拍平展示
*/
flattedSearchResult?: boolean
/**
* 自定义下拉菜单底部渲染
*/
renderExtraFooter?: () => React.ReactNode
/**
* 自定义下拉菜单每列渲染
*/
dropdownColumnRender?: (menu: React.ReactElement, level: number) => React.ReactNode
/**
* 设置尺寸
*/
Expand Down
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
1 change: 1 addition & 0 deletions packages/ui/cascader/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const cascaderContext = createContext<
| (Omit<UseCascaderReturn, 'rootProps'> & {
expandTrigger: CascaderExpandTriggerEnum
titleRender: (item: CascaderItemEventData) => React.ReactNode
dropdownColumnRender?: (menu: React.ReactElement, level: number) => React.ReactNode
})
| null
>(null)
Expand Down
136 changes: 136 additions & 0 deletions packages/ui/cascader/stories/dropdown-column-render.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import React from 'react'
import Cascader from '../src'

/**
* @title 自定义下拉菜单内容
*/
export const DropdownColumnRender = () => {
const [data] = React.useState([
{
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',
},
])

return (
<>
<h1>DropdownColumnRender</h1>
<div className="cascader-dropdown-column-render__wrap">
<Cascader
style={{ width: 240 }}
clearable
placeholder="请选择品类"
defaultValue={['手机', '红米', '红米4']}
data={data}
onChange={(...args) => {
console.log('onChange', ...args)
}}
// 如果有样式不满足需求,可以给弹出层设置独有的 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
)
}}
></Cascader>
</div>
</>
)
}
77 changes: 77 additions & 0 deletions packages/ui/cascader/stories/footer.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React from 'react'
import Cascader from '../src'

/**
* @title 吸底内容条
*/
export const Footer = () => {
const [data] = React.useState([
{
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',
},
],
},
])

return (
<>
<h1>Footer</h1>
<div className="cascader-footer__wrap">
<Cascader
style={{ width: 240 }}
clearable
placeholder="请选择品类"
defaultValue={['手机', '红米', '红米4']}
data={data}
onChange={(...args) => {
console.log('onChange', ...args)
}}
renderExtraFooter={() => <div>custom footer</div>}
></Cascader>
</div>
</>
)
}
2 changes: 2 additions & 0 deletions packages/ui/cascader/stories/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export * from './hover-expand.stories'
export * from './dynamic.stories'
export * from './display-render.stories'
export * from './title-render.stories'
export * from './footer.stories'
export * from './dropdown-column-render.stories'
export * from './field-names.stories'
export * from './visible.stories'

Expand Down

0 comments on commit 4db95ac

Please sign in to comment.