From 43fedf38724bf1678ea40fd5a13ceb0324e0fae1 Mon Sep 17 00:00:00 2001 From: qiusen Date: Tue, 10 Oct 2023 15:02:49 +0800 Subject: [PATCH 1/9] fix(menu): #2618 --- packages/ui/menu/src/MenuItem.tsx | 28 ++++++++++----------- packages/ui/menu/src/styles/menu.scss | 35 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/packages/ui/menu/src/MenuItem.tsx b/packages/ui/menu/src/MenuItem.tsx index ba92c9580..c8ba54ae7 100644 --- a/packages/ui/menu/src/MenuItem.tsx +++ b/packages/ui/menu/src/MenuItem.tsx @@ -90,11 +90,11 @@ export const MenuItem = forwardRef( })} onClick={() => { if (isArrayNonEmpty(children)) { - if (clickSubMenu) { + if (!disabled && clickSubMenu) { clickSubMenu(id) } } else { - if (clickMenu) { + if (!disabled && clickMenu) { // @ts-ignore clickMenu(id, raw) } @@ -121,7 +121,7 @@ export const MenuItem = forwardRef( placement === 'vertical' && expandedType === 'collapse' && !showAllSubMenus && - (expandedIds?.includes(id) ? ( + (!disabled && expandedIds?.includes(id) ? ( ) : ( @@ -144,7 +144,7 @@ export const MenuItem = forwardRef( {hasChildren && placement === 'horizontal' && level === 1 && - (expandedIds?.includes(id) ? ( + (!disabled && expandedIds?.includes(id) ? ( ) : ( @@ -156,7 +156,7 @@ export const MenuItem = forwardRef( !mini && !showAllSubMenus && expandedType === 'collapse' ? ( - +
    {children!.map((child) => ( ( {child.children.map((item) => (
    { - if (clickMenu) { - clickMenu(item.id, item) - } - if (closePopper) { - closePopper(id) + if(!item.disabled) { + clickMenu && clickMenu(item.id, item) + closePopper && closePopper(id) } }} className={cx(`${prefixCls}-item`, { [`${prefixCls}-item--active`]: activeId === item.id, + [`${prefixCls}-item--disabled`]: item.disabled })} key={item.id} > @@ -431,13 +430,12 @@ export const MenuItem = forwardRef(
    { - if (clickMenu) { - clickMenu(item.id, item) - } - if (closePopper) { - closePopper(id) + if(!item.disabled) { + clickMenu && clickMenu(item.id, item) + closePopper && closePopper(id) } }} key={item.id} diff --git a/packages/ui/menu/src/styles/menu.scss b/packages/ui/menu/src/styles/menu.scss index c4ec80c6b..256adb926 100644 --- a/packages/ui/menu/src/styles/menu.scss +++ b/packages/ui/menu/src/styles/menu.scss @@ -1,6 +1,12 @@ @import '~@hi-ui/core-css/lib/index.scss'; $prefix: '#{$component-prefix}-menu' !default; +$disabled-color: var(--hi-v4-color-gray-400, #c9ced6) !default; + +@mixin menu-item-disabled() { + color: $disabled-color; + cursor: not-allowed; +} .#{$prefix}-fat-menu { background-color: use-color-static('white'); @@ -41,6 +47,10 @@ $prefix: '#{$component-prefix}-menu' !default; &:not(.#{$prefix}-item--active):hover { background-color: use-color('gray', 100); } + + &--disabled { + @include menu-item-disabled; + } } ul { @@ -92,6 +102,10 @@ $prefix: '#{$component-prefix}-menu' !default; &:not(.#{$prefix}-item__inner--active):hover { background-color: use-color('gray', 100); } + + &--disabled { + @include menu-item-disabled; + } } &__content { @@ -143,6 +157,10 @@ $prefix: '#{$component-prefix}-menu' !default; height: 100%; flex-shrink: 0; } + + &--disabled { + @include menu-item-disabled; + } } &__wrapper { @@ -220,6 +238,18 @@ $prefix: '#{$component-prefix}-menu' !default; white-space: nowrap; max-width: none; } + + &--disabled { + @include menu-item-disabled; + + .#{$prefix}-item__inner.#{$prefix}-item__inner { + border-bottom: 0; + + .#{$prefix}-item__content { + color: $disabled-color; + } + } + } } } @@ -309,6 +339,11 @@ $prefix: '#{$component-prefix}-menu' !default; white-space: nowrap; text-indent: 0.5px; } + + &--disabled { + color: var(--hi-v4-color-gray-400, #c9ced6); + cursor: not-allowed; + } } } From e7907733bf2bae882a8ac1107b6a3c49f9d2eee7 Mon Sep 17 00:00:00 2001 From: qiusen Date: Tue, 10 Oct 2023 15:39:08 +0800 Subject: [PATCH 2/9] fix(menu): #2618 --- packages/ui/menu/src/styles/menu.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ui/menu/src/styles/menu.scss b/packages/ui/menu/src/styles/menu.scss index 256adb926..73cf0ecca 100644 --- a/packages/ui/menu/src/styles/menu.scss +++ b/packages/ui/menu/src/styles/menu.scss @@ -341,8 +341,7 @@ $disabled-color: var(--hi-v4-color-gray-400, #c9ced6) !default; } &--disabled { - color: var(--hi-v4-color-gray-400, #c9ced6); - cursor: not-allowed; + @include menu-item-disabled; } } } From 6a15028b3fdb7b29805021d0f35eb5f2c992a35e Mon Sep 17 00:00:00 2001 From: qiusen Date: Mon, 16 Oct 2023 09:33:27 +0800 Subject: [PATCH 3/9] =?UTF-8?q?fix(menu):=20#2618=20=E4=BF=AE=E6=94=B9if?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E4=B8=BA=E5=8F=AF=E9=80=89=E9=93=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/menu/src/MenuItem.tsx | 51 ++++++++----------------------- 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/packages/ui/menu/src/MenuItem.tsx b/packages/ui/menu/src/MenuItem.tsx index c8ba54ae7..47d425ab0 100644 --- a/packages/ui/menu/src/MenuItem.tsx +++ b/packages/ui/menu/src/MenuItem.tsx @@ -90,14 +90,9 @@ export const MenuItem = forwardRef( })} onClick={() => { if (isArrayNonEmpty(children)) { - if (!disabled && clickSubMenu) { - clickSubMenu(id) - } + !disabled && clickSubMenu?.(id) } else { - if (!disabled && clickMenu) { - // @ts-ignore - clickMenu(id, raw) - } + !disabled && clickMenu?.(id, raw as MenuDataItem) if ( closeAllPopper && !(placement === 'vertical' && expandedType === 'collapse' && mini === false) @@ -188,9 +183,7 @@ export const MenuItem = forwardRef( gutterGap={16} className={overlayClassName} onClose={() => { - if (closePopper) { - closePopper(id) - } + closePopper?.(id) }} >
      @@ -218,9 +211,7 @@ export const MenuItem = forwardRef( disabledPortal className={overlayClassName} onClose={() => { - if (closePopper) { - closePopper(id) - } + closePopper?.(id) }} >
        @@ -251,9 +242,7 @@ export const MenuItem = forwardRef( gutterGap={16} className={overlayClassName} onClose={() => { - if (closePopper) { - closePopper(id) - } + closePopper?.(id) }} >
          @@ -279,9 +268,7 @@ export const MenuItem = forwardRef( gutterGap={16} className={overlayClassName} onClose={() => { - if (closePopper) { - closePopper(id) - } + closePopper?.(id) }} >
            @@ -308,9 +295,7 @@ export const MenuItem = forwardRef( gutterGap={16} className={overlayClassName} onClose={() => { - if (closePopper) { - closePopper(id) - } + closePopper?.(id) }} >
            @@ -323,10 +308,7 @@ export const MenuItem = forwardRef( {child.children.map((item) => (
            { - if(!item.disabled) { - clickMenu && clickMenu(item.id, item) - closePopper && closePopper(id) - } + !item.disabled && (clickMenu?.(item.id, item), closePopper?.(id)) }} className={cx(`${prefixCls}-item`, { [`${prefixCls}-item--active`]: activeId === item.id, @@ -357,9 +339,7 @@ export const MenuItem = forwardRef( gutterGap={level === 1 ? 8 : 16} className={overlayClassName} onClose={() => { - if (closePopper) { - closePopper(id) - } + closePopper?.(id) }} >
              @@ -385,9 +365,7 @@ export const MenuItem = forwardRef( gutterGap={level === 1 ? 8 : 16} className={overlayClassName} onClose={() => { - if (closePopper) { - closePopper(id) - } + closePopper?.(id) }} >
                @@ -414,9 +392,7 @@ export const MenuItem = forwardRef( gutterGap={8} className={overlayClassName} onClose={() => { - if (closePopper) { - closePopper(id) - } + closePopper?.(id) }} >
                @@ -433,10 +409,7 @@ export const MenuItem = forwardRef( [`${prefixCls}-item--disabled`]: item.disabled })} onClick={() => { - if(!item.disabled) { - clickMenu && clickMenu(item.id, item) - closePopper && closePopper(id) - } + !item.disabled && (clickMenu?.(item.id, item),closePopper?.(id)) }} key={item.id} > From 1f82d7075fb6f445c8c3330950dfb1fd352313ed Mon Sep 17 00:00:00 2001 From: qiusen Date: Tue, 17 Oct 2023 09:52:12 +0800 Subject: [PATCH 4/9] =?UTF-8?q?fix(menu):=20#2618=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=EF=BC=8C=E8=A7=A3=E5=86=B3hover=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E8=8F=9C=E5=8D=95=E5=90=91=E4=B8=8B=E8=B7=B3=E5=8A=A8?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/menu/src/styles/menu.scss | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/ui/menu/src/styles/menu.scss b/packages/ui/menu/src/styles/menu.scss index 73cf0ecca..bdbb2defc 100644 --- a/packages/ui/menu/src/styles/menu.scss +++ b/packages/ui/menu/src/styles/menu.scss @@ -241,14 +241,14 @@ $disabled-color: var(--hi-v4-color-gray-400, #c9ced6) !default; &--disabled { @include menu-item-disabled; - - .#{$prefix}-item__inner.#{$prefix}-item__inner { - border-bottom: 0; - - .#{$prefix}-item__content { - color: $disabled-color; + &:hover{ + .#{$prefix}-item__inner { + border-color:var(--hi-v4-color-static-white, #fff) ; } } + .#{$prefix}-item__content { + color: $disabled-color; + } } } } From 863bcde0033f8bb4c9866e6f975e52726e4a5825 Mon Sep 17 00:00:00 2001 From: qiusen Date: Wed, 18 Oct 2023 18:59:43 +0800 Subject: [PATCH 5/9] =?UTF-8?q?fix(menu):=20#2618=20=E5=A2=9E=E5=8A=A0chan?= =?UTF-8?q?gset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/pink-jokes-flow.md | 6 ++++++ .changeset/shiny-rivers-jam.md | 6 ++++++ .changeset/stupid-meals-repair.md | 5 +++++ packages/ui/menu/src/MenuItem.tsx | 12 +++++++++--- packages/ui/menu/src/styles/menu.scss | 4 ++-- 5 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 .changeset/pink-jokes-flow.md create mode 100644 .changeset/shiny-rivers-jam.md create mode 100644 .changeset/stupid-meals-repair.md diff --git a/.changeset/pink-jokes-flow.md b/.changeset/pink-jokes-flow.md new file mode 100644 index 000000000..c6e47de27 --- /dev/null +++ b/.changeset/pink-jokes-flow.md @@ -0,0 +1,6 @@ +--- +"@hi-ui/hiui": patch +--- + +Menu fix: 修复 disabled 不生效问题 +Badge 支持字符串和数字 hover 显示完全 diff --git a/.changeset/shiny-rivers-jam.md b/.changeset/shiny-rivers-jam.md new file mode 100644 index 000000000..7ac9e5ce2 --- /dev/null +++ b/.changeset/shiny-rivers-jam.md @@ -0,0 +1,6 @@ +--- +"@hi-ui/badge": patch +--- + +Badge 支持字符串和数字 hover 显示完全 + diff --git a/.changeset/stupid-meals-repair.md b/.changeset/stupid-meals-repair.md new file mode 100644 index 000000000..d59da3962 --- /dev/null +++ b/.changeset/stupid-meals-repair.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/menu": patch +--- + +fix: 修复 disabled 不生效问题 diff --git a/packages/ui/menu/src/MenuItem.tsx b/packages/ui/menu/src/MenuItem.tsx index 47d425ab0..bb3b24ab7 100644 --- a/packages/ui/menu/src/MenuItem.tsx +++ b/packages/ui/menu/src/MenuItem.tsx @@ -308,7 +308,10 @@ export const MenuItem = forwardRef( {child.children.map((item) => (
                { - !item.disabled && (clickMenu?.(item.id, item), closePopper?.(id)) + if (!item.disabled) { + clickMenu?.(item.id, item) + closePopper?.(id) + } }} className={cx(`${prefixCls}-item`, { [`${prefixCls}-item--active`]: activeId === item.id, @@ -409,7 +412,10 @@ export const MenuItem = forwardRef( [`${prefixCls}-item--disabled`]: item.disabled })} onClick={() => { - !item.disabled && (clickMenu?.(item.id, item),closePopper?.(id)) + if (!item.disabled) { + clickMenu?.(item.id, item) + closePopper?.(id) + } }} key={item.id} > @@ -447,7 +453,7 @@ if (__DEV__) { } const Arrow = ({ prefixCls, direction }: any) => { - let icon = null + let icon switch (direction) { case 'up': icon = diff --git a/packages/ui/menu/src/styles/menu.scss b/packages/ui/menu/src/styles/menu.scss index bdbb2defc..003bd1064 100644 --- a/packages/ui/menu/src/styles/menu.scss +++ b/packages/ui/menu/src/styles/menu.scss @@ -1,7 +1,7 @@ @import '~@hi-ui/core-css/lib/index.scss'; $prefix: '#{$component-prefix}-menu' !default; -$disabled-color: var(--hi-v4-color-gray-400, #c9ced6) !default; +$disabled-color: use-color('gray', 400) !default; @mixin menu-item-disabled() { color: $disabled-color; @@ -243,7 +243,7 @@ $disabled-color: var(--hi-v4-color-gray-400, #c9ced6) !default; @include menu-item-disabled; &:hover{ .#{$prefix}-item__inner { - border-color:var(--hi-v4-color-static-white, #fff) ; + border-color:use-color-static('white') ; } } .#{$prefix}-item__content { From dca232939f68c56e0b6b51a3515767051358a271 Mon Sep 17 00:00:00 2001 From: qiusen Date: Thu, 19 Oct 2023 10:35:26 +0800 Subject: [PATCH 6/9] =?UTF-8?q?fix(menu):=20#2618=20=E4=BF=AE=E6=94=B9chan?= =?UTF-8?q?gset=E6=8F=8F=E8=BF=B0=E6=96=87=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/pink-jokes-flow.md | 2 +- .changeset/shiny-rivers-jam.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/pink-jokes-flow.md b/.changeset/pink-jokes-flow.md index c6e47de27..864a926bf 100644 --- a/.changeset/pink-jokes-flow.md +++ b/.changeset/pink-jokes-flow.md @@ -3,4 +3,4 @@ --- Menu fix: 修复 disabled 不生效问题 -Badge 支持字符串和数字 hover 显示完全 +Badge 支持字符串和数字 hover 时显示完整内容 diff --git a/.changeset/shiny-rivers-jam.md b/.changeset/shiny-rivers-jam.md index 7ac9e5ce2..ede800762 100644 --- a/.changeset/shiny-rivers-jam.md +++ b/.changeset/shiny-rivers-jam.md @@ -2,5 +2,5 @@ "@hi-ui/badge": patch --- -Badge 支持字符串和数字 hover 显示完全 +Badge 支持字符串和数字 hover 时显示完整内容 From 3757feda7561484df61c7ce37730f3d1215441a2 Mon Sep 17 00:00:00 2001 From: qiusen Date: Thu, 19 Oct 2023 10:47:54 +0800 Subject: [PATCH 7/9] =?UTF-8?q?fix(badge):=20#2618=20=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/menu/src/styles/menu.scss | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/ui/menu/src/styles/menu.scss b/packages/ui/menu/src/styles/menu.scss index 003bd1064..b3005a50d 100644 --- a/packages/ui/menu/src/styles/menu.scss +++ b/packages/ui/menu/src/styles/menu.scss @@ -241,11 +241,13 @@ $disabled-color: use-color('gray', 400) !default; &--disabled { @include menu-item-disabled; - &:hover{ + + &:hover { .#{$prefix}-item__inner { - border-color:use-color-static('white') ; + border-color: use-color-static('white'); } } + .#{$prefix}-item__content { color: $disabled-color; } From b9aef7fe63ef3c8bee50145c565d9892a8554127 Mon Sep 17 00:00:00 2001 From: zhouyun1 Date: Fri, 20 Oct 2023 11:04:16 +0800 Subject: [PATCH 8/9] feat(drawer): add onOutsideClick api (#2629) --- .changeset/kind-beers-check.md | 5 ++ .changeset/shy-crabs-clean.md | 5 ++ packages/ui/drawer/src/Drawer.tsx | 17 +++- packages/ui/drawer/stories/index.stories.tsx | 1 + .../drawer/stories/outside-click.stories.tsx | 90 +++++++++++++++++++ 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 .changeset/kind-beers-check.md create mode 100644 .changeset/shy-crabs-clean.md create mode 100644 packages/ui/drawer/stories/outside-click.stories.tsx diff --git a/.changeset/kind-beers-check.md b/.changeset/kind-beers-check.md new file mode 100644 index 000000000..78f4b8fe3 --- /dev/null +++ b/.changeset/kind-beers-check.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/hiui": patch +--- + +Drawer feat: add onOutsideClick api diff --git a/.changeset/shy-crabs-clean.md b/.changeset/shy-crabs-clean.md new file mode 100644 index 000000000..cfecfaa86 --- /dev/null +++ b/.changeset/shy-crabs-clean.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/drawer": minor +--- + +feat: add onOutsideClick api diff --git a/packages/ui/drawer/src/Drawer.tsx b/packages/ui/drawer/src/Drawer.tsx index f7f8c5d3a..3ccc25767 100644 --- a/packages/ui/drawer/src/Drawer.tsx +++ b/packages/ui/drawer/src/Drawer.tsx @@ -10,6 +10,8 @@ import { useToggle } from '@hi-ui/use-toggle' import { isNumeric } from '@hi-ui/type-assertion' import { CloseOutlined } from '@hi-ui/icons' import { IconButton } from '@hi-ui/icon-button' +import { mergeRefs } from '@hi-ui/react-utils' +import { useOutsideClick } from '@hi-ui/use-outside-click' import { DrawerPlacementEnum } from './types' const DRAWER_PREFIX = getPrefixCls('drawer') @@ -42,6 +44,7 @@ export const Drawer = forwardRef( showMask = true, placement = 'right', drawerConfig, + onOutsideClick, ...rest }, ref @@ -70,6 +73,11 @@ export const Drawer = forwardRef( } }, [visible, transitionVisibleAction, transitionExitedAction]) + const modalProps = getModalProps(rootProps, ref) + const innerRef = React.useRef(null) + + useOutsideClick(innerRef, onOutsideClick) + const onExitedLatest = useLatestCallback(onExitedProp) const onExited = useCallback(() => { transitionExitedAction.on() @@ -95,7 +103,10 @@ export const Drawer = forwardRef( >
                , 'title'>, UseM * 是否展示右上角关闭按钮 */ closeable?: boolean + /** + * 外界元素点击数触发 + */ + onOutsideClick?: (evt: Event) => void /** * 自定义关闭时 icon。暂不对外暴露 * @private diff --git a/packages/ui/drawer/stories/index.stories.tsx b/packages/ui/drawer/stories/index.stories.tsx index 5d8e66884..c321b8f94 100644 --- a/packages/ui/drawer/stories/index.stories.tsx +++ b/packages/ui/drawer/stories/index.stories.tsx @@ -4,6 +4,7 @@ import Drawer from '../src' export * from './basic.stories' export * from './header.stories' export * from './mask.stories' +export * from './outside-click.stories' export * from './container.stories' export * from './nested.stories' export * from './extra.stories' diff --git a/packages/ui/drawer/stories/outside-click.stories.tsx b/packages/ui/drawer/stories/outside-click.stories.tsx new file mode 100644 index 000000000..2d7b4bd85 --- /dev/null +++ b/packages/ui/drawer/stories/outside-click.stories.tsx @@ -0,0 +1,90 @@ +import React from 'react' +import Drawer from '../src' +import Button from '@hi-ui/button' +import Tree, { TreeDataItem } from '@hi-ui/tree' + +/** + * @title 点击外部事件处理 + * @desc 常用于无蒙层模式下,切换列表项详情内容 + */ +export const OutsideClick = () => { + const [visible, setVisible] = React.useState(false) + const [data] = React.useState([ + { + id: 1, + title: '小米', + children: [ + { + id: 2, + title: '研发', + disabled: true, + children: [ + { id: 3, title: '后端', disabled: true }, + { id: 4, title: '运维' }, + { id: 5, title: '前端' }, + ], + }, + { id: 6, title: '产品' }, + ], + }, + { + id: 11, + title: '大米', + children: [ + { id: 22, title: '可视化' }, + { id: 66, title: 'HiUI' }, + ], + }, + ]) + const [currentData, setCurrentData] = React.useState() + const wrapperRef = React.useRef(null) + + return ( + <> +

                OutsideClick

                +
                +
                + { + // console.log('node', node) + + if (id) { + setVisible(true) + setCurrentData(node?.raw) + } else { + setVisible(false) + } + }} + /> +
                + setVisible(false)} + // 点击列表外部内容时关闭抽屉 + onOutsideClick={(e) => { + // console.log('target', e.target) + + if (!wrapperRef.current?.contains(e.target as Element)) { + setVisible(false) + } + }} + footer={ +
                + + +
                + } + > + {currentData?.title} +
                +
                + + ) +} From 48a16f4bbff22ba966608a6e3d040043b82e17cb Mon Sep 17 00:00:00 2001 From: zhouyun1 Date: Thu, 12 Oct 2023 21:00:07 +0800 Subject: [PATCH 9/9] feat(date-picker): #2621 --- .changeset/eighty-terms-agree.md | 5 ++ .changeset/funny-peaches-carry.md | 5 ++ packages/ui/date-picker/src/DatePicker.tsx | 8 +-- .../date-picker/src/components/calendar.tsx | 11 ++-- .../ui/date-picker/src/components/input.tsx | 20 ++++++-- .../ui/date-picker/src/components/panel.tsx | 2 + .../src/components/range-panel.tsx | 37 +++++++++++++- .../ui/date-picker/src/components/root.tsx | 17 ++++++- .../date-picker/src/hooks/useCalenderData.tsx | 1 + packages/ui/date-picker/src/hooks/useData.ts | 28 +++++++++-- packages/ui/date-picker/src/types.ts | 10 +++- packages/ui/date-picker/src/utils/index.tsx | 14 +++++- .../stories/cell-render.stories.tsx | 50 ++++++++++++++++++- 13 files changed, 183 insertions(+), 25 deletions(-) create mode 100644 .changeset/eighty-terms-agree.md create mode 100644 .changeset/funny-peaches-carry.md diff --git a/.changeset/eighty-terms-agree.md b/.changeset/eighty-terms-agree.md new file mode 100644 index 000000000..f25fdd48e --- /dev/null +++ b/.changeset/eighty-terms-agree.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/hiui": patch +--- + +DatePicker feat: 增加 strideSelectMode API & format 支持函数 diff --git a/.changeset/funny-peaches-carry.md b/.changeset/funny-peaches-carry.md new file mode 100644 index 000000000..cf7840497 --- /dev/null +++ b/.changeset/funny-peaches-carry.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/date-picker": minor +--- + +feat: 增加 strideSelectMode API & format 支持函数 diff --git a/packages/ui/date-picker/src/DatePicker.tsx b/packages/ui/date-picker/src/DatePicker.tsx index 4a9a61045..3d7ca6851 100644 --- a/packages/ui/date-picker/src/DatePicker.tsx +++ b/packages/ui/date-picker/src/DatePicker.tsx @@ -74,6 +74,7 @@ export const DatePicker = forwardRef( invalid = false, onClose, cellRender, + strideSelectMode = 'auto', ...otherProps }, ref @@ -169,20 +170,20 @@ export const DatePicker = forwardRef( valueAdapter, uncontrolledValue, ]) - const [outDate, changeOutDate] = useDate({ value, type, defaultValue, cacheDate, - format, + format: typeof format === 'function' ? undefined : format, weekOffset: safeWeekOffset, locale, + strideSelectMode, }) const realFormat = useFormat({ type, showTime, - format, + format: typeof format === 'function' ? undefined : format, locale, }) @@ -416,6 +417,7 @@ export const DatePicker = forwardRef( isInDateRangeTimeMode, size, cellRender, + strideSelectMode, }} >
                diff --git a/packages/ui/date-picker/src/components/calendar.tsx b/packages/ui/date-picker/src/components/calendar.tsx index 5fea02ae0..729afca3c 100644 --- a/packages/ui/date-picker/src/components/calendar.tsx +++ b/packages/ui/date-picker/src/components/calendar.tsx @@ -84,7 +84,7 @@ const Calendar = ({ _class.push(`${prefixCls}__cell--out`) break default: - _class.push(`${prefixCls}__cell--${td.type}`) + !td.weekNum && _class.push(`${prefixCls}__cell--${td.type}`) break } @@ -120,24 +120,21 @@ const Calendar = ({ if (!['SPAN', 'DIV'].includes(td.nodeName) || td.getAttribute('type') === 'disabled') { return false } + const clickVal = parseInt(value) const _date = moment(renderDate) as any const cellType = td.getAttribute('type') const cellWeekType = td.getAttribute('weektype') - // 如果点击的是周数,则直接拿到该周的周一日期返回 - if (cellType === 'week') { - onPick(moment().isoWeek(clickVal)) - return false - } - if (type !== 'weekrange' || isBelongFullOurOfRange) { if (cellType === 'prev' || cellWeekType === 'prev') { _date.subtract(1, 'months') } + if (cellType === 'next' || cellWeekType === 'next') { _date.add(1, 'months') } + _date[view](clickVal) } else { // 点击的上个月的部分,鼠标还在本月的panel上,则视作,鼠标正在本月第一天 diff --git a/packages/ui/date-picker/src/components/input.tsx b/packages/ui/date-picker/src/components/input.tsx index 0ca41a577..35418ab35 100644 --- a/packages/ui/date-picker/src/components/input.tsx +++ b/packages/ui/date-picker/src/components/input.tsx @@ -36,8 +36,10 @@ const Input = ({ const cacheValues = useRef(null) const [value, setValue] = useState('') + useEffect(() => { let vals = date && moment(date).format(realFormat) + if (type.includes('week') && date) { // const _date = moment(date).year(y) // vals = moment(_date).format(realFormat) @@ -51,19 +53,30 @@ const Input = ({ week: getBelongWeek(date, weekOffset), }) } else { - const y = moment(date).weekYear() - const _date = moment(date).year(y) - vals = moment(_date).format(realFormat) + if (typeof format === 'function') { + vals = format(date) + } else { + const y = moment(date).weekYear() + const _date = moment(date).year(y) + + vals = moment(_date).format(realFormat) + } } } + setValue(vals) + cacheValues.current = vals }, [date, weekOffset, i18n, type, format, realFormat, locale]) + const inputChangeEvent = (e: React.ChangeEvent) => { const val = e.target.value + setValue(val) + if (val && val.trim().length === realFormat.length) { const nVal = moment(val) + if (nVal.isValid()) { onChange(nVal, dir) } else { @@ -71,6 +84,7 @@ const Input = ({ } } } + return (
                { } setView(_view) const _innerDates = genNewDates(calRenderDates, date) + if (view === 'date') { onPick(_innerDates, showTime) return } + setCalRenderDates(_innerDates) }, [calRenderDates, onPick, onSelect, showTime, type, view, weekOffset] diff --git a/packages/ui/date-picker/src/components/range-panel.tsx b/packages/ui/date-picker/src/components/range-panel.tsx index 10b8784ec..417217bb8 100644 --- a/packages/ui/date-picker/src/components/range-panel.tsx +++ b/packages/ui/date-picker/src/components/range-panel.tsx @@ -36,6 +36,7 @@ const RangePanel = () => { showPanel, prefixCls, disabledDate, + strideSelectMode, } = useContext(DPContext) const calendarClickIsEnd = useRef(false) const [showRangeMask, setShowRangeMask] = useState(false) @@ -51,6 +52,7 @@ const RangePanel = () => { useEffect(() => { const _outDate = cloneDeep(outDate) + setRange({ start: _outDate[0], end: _outDate[1], @@ -95,11 +97,44 @@ const RangePanel = () => { newRange.end = newRange.start newRange.start = date } + // 此处是明显的语法错误,故而注释修改 // onSelect(date, calendarClickIsEnd) onSelect(date as any, !calendarClickIsEnd.current) + if (type === 'weekrange') { - onPick([newRange.start!.startOf('week'), newRange.end!.endOf('week')], showTime) + // 固定模式下,即使跨月选择了日期,仍然显示当前月的日期选择面板 + if (strideSelectMode === 'fixed') { + const { start, end } = newRange + // 开始周周一日期 + const startOfWeek = start.clone()!.startOf('week') + // 结束周周日日期 + const endOfWeek = end!.clone()!.endOf('week') + // 当月最后一天 + const endOfMonth = end!.clone().endOf('month') + // 重新计算出的开始日期,逻辑:(开始周日期不能是上个月的日期) + // 如果当前日期是当月第一天,则返回当前日期,否则 + // 如果当前日期小于当前周周一,则返回当月第一天,否则返回当前周周一 + const rangeStart = + start.date() === 1 + ? start + : startOfWeek.date() > start.date() + ? start.clone().startOf('month') + : startOfWeek + // 重新计算出的结束日期,逻辑:(结束周日期不能是下个月的日期) + // 如果当前日期是当月最后一天,则返回当前日期,否则 + // 如果当前日期大于当前周周日,则返回当月最后一天,否则返回当前周周日 + const rangeEnd = + end?.date() === endOfMonth.date() + ? end + : end!.date() > endOfWeek.date() + ? endOfMonth + : endOfWeek + + onPick([rangeStart, rangeEnd], showTime) + } else { + onPick([newRange.start!.startOf('week'), newRange.end!.endOf('week')], showTime) + } } else { onPick([newRange.start, newRange.end], showTime) } diff --git a/packages/ui/date-picker/src/components/root.tsx b/packages/ui/date-picker/src/components/root.tsx index 25de2fa74..249aaefd8 100644 --- a/packages/ui/date-picker/src/components/root.tsx +++ b/packages/ui/date-picker/src/components/root.tsx @@ -43,6 +43,7 @@ const Root = ({ min, max, size, + strideSelectMode, } = useContext(DPContext) const [inputData, setInputData] = useState(outDate) @@ -52,9 +53,21 @@ const Root = ({ placeholder, i18n, }) + useEffect(() => { - setInputData(value ? parseValue(value, type, weekOffset, format) : outDate) - }, [value, format, type, outDate, weekOffset]) + setInputData( + value + ? parseValue( + value, + type, + weekOffset, + typeof format === 'string' ? format : undefined, + strideSelectMode + ) + : outDate + ) + }, [value, format, type, outDate, weekOffset, strideSelectMode]) + const onPickerClickEvent = (index: number) => { if (disabled) return onTrigger(index) diff --git a/packages/ui/date-picker/src/hooks/useCalenderData.tsx b/packages/ui/date-picker/src/hooks/useCalenderData.tsx index 75a3e4b90..a74f12dee 100644 --- a/packages/ui/date-picker/src/hooks/useCalenderData.tsx +++ b/packages/ui/date-picker/src/hooks/useCalenderData.tsx @@ -339,6 +339,7 @@ const getDateRows = ({ } } + // 新增功能:周选择显示周数 // 如果是周类型,则计算出每一行的周数并放入每行数组第一个 if (type === 'week' || type === 'weekrange') { const year = _date.year() diff --git a/packages/ui/date-picker/src/hooks/useData.ts b/packages/ui/date-picker/src/hooks/useData.ts index de3fbcd2e..b81ca7638 100644 --- a/packages/ui/date-picker/src/hooks/useData.ts +++ b/packages/ui/date-picker/src/hooks/useData.ts @@ -11,12 +11,27 @@ interface IUseDateConfig { cacheDate: React.MutableRefObject<(moment.Moment | null)[]> type: DatePickerTypeEnum weekOffset: number + strideSelectMode?: 'auto' | 'fixed' } + export const useDate = (config: IUseDateConfig) => { - const { value, defaultValue, cacheDate, type, format, locale, weekOffset } = config + const { + value, + defaultValue, + cacheDate, + type, + format, + locale, + weekOffset, + strideSelectMode, + } = config + const [outDate, setOutDate] = useState<(moment.Moment | null)[]>(() => { - const d = parseValue(value || defaultValue, type, weekOffset, format as any) as any + const _value = value || defaultValue + const d = parseValue(_value, type, weekOffset, format as any, strideSelectMode) as any + cacheDate.current = d + return d }) @@ -25,14 +40,19 @@ export const useDate = (config: IUseDateConfig) => { dates[0] && moment(dates[0]).isValid() ? dates[0] : null, dates[1] && moment(dates[1]).isValid() ? dates[1] : null, ] + setOutDate(_datas as any) } + useEffect(() => { if (value === undefined) return - const d = parseValue(value, type, weekOffset, format as any) as any + + const d = parseValue(value, type, weekOffset, format as any, strideSelectMode) as any + setOutDate(d) + cacheDate.current = d - }, [value, type, weekOffset, format, locale, setOutDate, cacheDate]) + }, [value, type, weekOffset, format, locale, setOutDate, cacheDate, strideSelectMode]) return [outDate, changeOutDate] as const } diff --git a/packages/ui/date-picker/src/types.ts b/packages/ui/date-picker/src/types.ts index c71e040e7..e7fcd3864 100644 --- a/packages/ui/date-picker/src/types.ts +++ b/packages/ui/date-picker/src/types.ts @@ -3,6 +3,7 @@ import { HiBaseHTMLProps } from '@hi-ui/core' import { PopperOverlayProps } from '@hi-ui/popper' import { TimePickerPanelType } from '@hi-ui/time-picker' import { CalendarColInfo } from './hooks/useCalenderData' +import { Moment } from 'moment' export type CalendarViewEnum = 'date' | 'year' | 'month' @@ -157,7 +158,7 @@ export interface DatePickerProps extends Omit, 'placehold /** * 展示的日期格式,配置参考 [moment.js](http://momentjs.cn/docs/#/displaying/format/) */ - format?: string + format?: string | ((date: Moment) => string) /** * 快捷面板 */ @@ -261,4 +262,11 @@ export interface DatePickerProps extends Omit, 'placehold * 自定义单元格内容 */ cellRender?: (colInfo: CalendarColInfo) => React.ReactNode + /** + * 跨月选择模式 + * 'auto' 自动切换模式,跨月选择时自动切换到跨月的日期选择面板; + * 'fixed' 固定模式,不自动切换(仅周范围选择下生效) + * @default 'auto' + */ + strideSelectMode?: 'auto' | 'fixed' } diff --git a/packages/ui/date-picker/src/utils/index.tsx b/packages/ui/date-picker/src/utils/index.tsx index 28ef8302d..6f498e798 100644 --- a/packages/ui/date-picker/src/utils/index.tsx +++ b/packages/ui/date-picker/src/utils/index.tsx @@ -294,22 +294,31 @@ export const parseValue = ( value: DatePickerValueV3, type: DatePickerTypeEnum, weekOffset: number, - format?: string + format?: string, + strideSelectMode?: 'auto' | 'fixed' ) => { if (!value) return [null] + // 暂时无法理解为何此处自行获取了 type // const _format = getLocaleTypeFormatMap(locale)[type] // const _value = moment(value as any, _format) - const _value = moment(value as any, format) + const _value = moment(value as any, typeof format === 'string' ? format : undefined) const isValid = moment(_value).isValid() + if (value && typeof value === 'object' && (type.includes('range') || type === 'timeperiod')) { const rangeValue = value as DateRange + if (type === 'weekrange') { + if (strideSelectMode === 'fixed') { + return [moment(rangeValue.start), moment(rangeValue.end)] + } + return [ rangeValue.start ? getBelongWeekBoundary(moment(rangeValue.start), weekOffset) : null, rangeValue.end ? getBelongWeekBoundary(moment(rangeValue.end), weekOffset, false) : null, ] } + return [ rangeValue.start && moment(rangeValue.start).isValid() ? moment(rangeValue.start, format) @@ -317,5 +326,6 @@ export const parseValue = ( rangeValue.end && moment(rangeValue.end).isValid() ? moment(rangeValue.end, format) : null, ] } + return [isValid ? _value : null] } diff --git a/packages/ui/date-picker/stories/cell-render.stories.tsx b/packages/ui/date-picker/stories/cell-render.stories.tsx index 4a846374d..e95720d53 100644 --- a/packages/ui/date-picker/stories/cell-render.stories.tsx +++ b/packages/ui/date-picker/stories/cell-render.stories.tsx @@ -1,4 +1,5 @@ import React from 'react' +import moment from 'moment' import DatePicker from '../src' /** @@ -53,8 +54,38 @@ export const CellRender = () => { { + // console.log('format', value) + + const lastDay = value.clone().endOf('month').date() + const startOfWeek = value.clone().startOf('week') + const endOfWeek = value.clone().endOf('week') + const week = value.clone().week() + const weekYear = value.clone().weekYear() + + // 如果当前日期是当月第一天或者或者小于周一,并且周一不是当月第一天,则该周视为 B 周 + if ( + (value.date() === 1 || startOfWeek.date() > value.date()) && + startOfWeek.date() !== 1 + ) { + return `${weekYear}-${week}B` + } + + // 如果当前日期是当月最后一天或者大于周日,并且周日不是最后一天,则该周视为 A 周 + if ( + (value.date() === lastDay || value.date() > endOfWeek.date()) && + endOfWeek.date() !== lastDay + ) { + return `${weekYear}-${week}A` + } + + return `${weekYear}-${week}` + }} + // 自定义渲染出 AB 周,逻辑: + // 在当前月周选择面板下,如果当月第一天位于第一行并且不是周一,则该周视为B周 + // 如果当前月最后一天位于最后一行并且不是周日,则该周视为A周 cellRender={(cellInfo) => { // console.log('cellInfo', cellInfo) @@ -94,6 +125,21 @@ export const CellRender = () => { }} onChange={(date, dateStr) => { console.log('onChange', date, dateStr) + + const _date = date as Date[] + const start = moment(_date?.[0]) + const end = moment(_date?.[1]) + const lastDay = end.clone().endOf('month').date() + + // 如果开始日期是当月第一天并且不是周一,则该周视为 B 周 + if (start.date() === 1 && start.clone().startOf('week').date() !== 1) { + console.log('start week', dateStr?.[0] + 'B') + } + + // 如果当前日期是当月最后一天并且不是周末,则该周视为 A 周 + if (end.date() === lastDay && end.clone().endOf('week').date() !== lastDay) { + console.log('end week', dateStr?.[1] + 'A') + } }} />