From 90ea1ea810573f730ebbc4c48272dd6181099933 Mon Sep 17 00:00:00 2001 From: zhouyun1 Date: Fri, 22 Sep 2023 17:58:44 +0800 Subject: [PATCH] feat(cascader): #2594 --- .changeset/late-bags-film.md | 5 + .changeset/yellow-humans-move.md | 5 + packages/ui/cascader/src/Cascader.tsx | 19 ++- packages/ui/cascader/src/CascaderMenuList.tsx | 16 ++- packages/ui/cascader/src/context.ts | 1 + .../dropdown-column-render.stories.tsx | 136 ++++++++++++++++++ .../ui/cascader/stories/footer.stories.tsx | 77 ++++++++++ .../ui/cascader/stories/index.stories.tsx | 2 + 8 files changed, 255 insertions(+), 6 deletions(-) create mode 100644 .changeset/late-bags-film.md create mode 100644 .changeset/yellow-humans-move.md create mode 100644 packages/ui/cascader/stories/dropdown-column-render.stories.tsx create mode 100644 packages/ui/cascader/stories/footer.stories.tsx diff --git a/.changeset/late-bags-film.md b/.changeset/late-bags-film.md new file mode 100644 index 000000000..d1a1574f7 --- /dev/null +++ b/.changeset/late-bags-film.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/hiui": patch +--- + +Cascader feat: 增加 renderExtraFooter 和 dropdownColumnRender api diff --git a/.changeset/yellow-humans-move.md b/.changeset/yellow-humans-move.md new file mode 100644 index 000000000..f94b0f90a --- /dev/null +++ b/.changeset/yellow-humans-move.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/cascader": minor +--- + +feat: 增加 renderExtraFooter 和 dropdownColumnRender api diff --git a/packages/ui/cascader/src/Cascader.tsx b/packages/ui/cascader/src/Cascader.tsx index 017d5c2ca..7577b2504 100644 --- a/packages/ui/cascader/src/Cascader.tsx +++ b/packages/ui/cascader/src/Cascader.tsx @@ -54,6 +54,8 @@ export const Cascader = forwardRef((props, visible, onOpen, onClose, + renderExtraFooter, + dropdownColumnRender, ...rest } = props const i18n = useLocaleContext() @@ -203,7 +205,13 @@ export const Cascader = forwardRef((props, return ( ((props, onClose={menuVisibleAction.off} searchable={searchable} scrollable={false} + footer={isFunction(renderExtraFooter) && renderExtraFooter()} onSearch={callAllFuncs(onSearchProp, onSearch)} trigger={ React.ReactNode + /** + * 自定义下拉菜单每列渲染 + */ + dropdownColumnRender?: (menu: React.ReactElement, level: number) => React.ReactNode } if (__DEV__) { diff --git a/packages/ui/cascader/src/CascaderMenuList.tsx b/packages/ui/cascader/src/CascaderMenuList.tsx index 4def2a00b..50761d9dd 100644 --- a/packages/ui/cascader/src/CascaderMenuList.tsx +++ b/packages/ui/cascader/src/CascaderMenuList.tsx @@ -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( ({ prefixCls = menuListPrefix, className, ...rest }, ref) => { - const { flatted, menuList } = useCascaderContext() + const { flatted, menuList, dropdownColumnRender } = useCascaderContext() const cls = cx(prefixCls, className, flatted && `${prefixCls}--flatted`) return (
{menuList.map((menu, menuIndex) => { - // @ts-ignore - return isArrayNonEmpty(menu) ? : null + return isArrayNonEmpty(menu) ? ( + isFunction(dropdownColumnRender) ? ( + dropdownColumnRender(, menuIndex) + ) : ( + + ) + ) : null })}
) @@ -40,6 +45,7 @@ export const CascaderMenu = ({ prefixCls = menuPrefix, role = 'menu', className, + style, data: menu, }: CascaderMenuProps) => { const { @@ -56,7 +62,7 @@ export const CascaderMenu = ({ const cls = cx(prefixCls, className) return ( -
    +
      {menu.map((option) => { const eventOption = getItemEventData(option, getItemRequiredProps(option)) diff --git a/packages/ui/cascader/src/context.ts b/packages/ui/cascader/src/context.ts index 3674bb3a1..b4c9ea707 100644 --- a/packages/ui/cascader/src/context.ts +++ b/packages/ui/cascader/src/context.ts @@ -7,6 +7,7 @@ const cascaderContext = createContext< | (Omit & { expandTrigger: CascaderExpandTriggerEnum titleRender: (item: CascaderItemEventData) => React.ReactNode + dropdownColumnRender?: (menu: React.ReactElement, level: number) => React.ReactNode }) | null >(null) diff --git a/packages/ui/cascader/stories/dropdown-column-render.stories.tsx b/packages/ui/cascader/stories/dropdown-column-render.stories.tsx new file mode 100644 index 000000000..5df155ff6 --- /dev/null +++ b/packages/ui/cascader/stories/dropdown-column-render.stories.tsx @@ -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 ( + <> +

      DropdownColumnRender

      +
      + { + console.log('onChange', ...args) + }} + // 如果有样式不满足需求,可以给弹出层设置独有的 className 来进行样式覆写 + overlay={{ className: 'my-overlay' }} + dropdownColumnRender={(menu, level) => { + return level < 5 ? ( +
      +
      + header +
      + {React.cloneElement(menu, { style: { height: 198 } })} +
      + footer(level {level}) +
      +
      + ) : ( + menu + ) + }} + >
      +
      + + ) +} diff --git a/packages/ui/cascader/stories/footer.stories.tsx b/packages/ui/cascader/stories/footer.stories.tsx new file mode 100644 index 000000000..4e1b72ced --- /dev/null +++ b/packages/ui/cascader/stories/footer.stories.tsx @@ -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 ( + <> +

      Footer

      +
      + { + console.log('onChange', ...args) + }} + renderExtraFooter={() =>
      custom footer
      } + >
      +
      + + ) +} diff --git a/packages/ui/cascader/stories/index.stories.tsx b/packages/ui/cascader/stories/index.stories.tsx index 3872342b0..94308dbc4 100644 --- a/packages/ui/cascader/stories/index.stories.tsx +++ b/packages/ui/cascader/stories/index.stories.tsx @@ -10,6 +10,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'