refactor: dropdown

pull/4606/head
tangjinzhou 3 years ago
parent f71a72208b
commit 38258d33ba

@ -4,8 +4,6 @@ exports[`DropdownButton should support href like Button 1`] = `
<div class="ant-btn-group ant-dropdown-button"><a class="ant-btn ant-btn-default" href="https://ant.design">
<!---->
</a>
<!----><button class="ant-btn ant-btn-default ant-dropdown-trigger" type="button">
<!----><span role="img" aria-label="ellipsis" class="anticon anticon-ellipsis"><svg focusable="false" class="" data-icon="ellipsis" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"></path></svg></span>
</button>
<!----><button class="ant-btn ant-btn-default ant-dropdown-trigger ant-btn-icon-only" type="button"><span role="img" aria-label="ellipsis" class="anticon anticon-ellipsis"><svg focusable="false" class="" data-icon="ellipsis" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M176 511a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0zm280 0a56 56 0 10112 0 56 56 0 10-112 0z"></path></svg></span></button>
</div>
`;

@ -24,8 +24,8 @@ describe('DropdownButton', () => {
it("don't pass visible to Dropdown if it's not exits", () => {
const wrapper = mount(Dropdown.Button, {
props: {
overlay: (
slots: {
overlay: () => (
<Menu>
<Menu.Item>foo</Menu.Item>
</Menu>
@ -43,11 +43,13 @@ describe('DropdownButton', () => {
return (
<Dropdown.Button
href="https://ant.design"
overlay={
<Menu>
<Menu.Item>foo</Menu.Item>
</Menu>
}
v-slots={{
overlay: () => (
<Menu>
<Menu.Item>foo</Menu.Item>
</Menu>
),
}}
/>
);
},

@ -1,117 +1,92 @@
import type { VNode, ExtractPropTypes } from 'vue';
import { provide, inject, defineComponent } from 'vue';
import { ExtractPropTypes } from 'vue';
import { defineComponent } from 'vue';
import Button from '../button';
import classNames from '../_util/classNames';
import buttonTypes from '../button/buttonTypes';
import Dropdown from './dropdown';
import PropTypes from '../_util/vue-types';
import { hasProp, getComponent, getSlot } from '../_util/props-util';
import getDropdownProps from './getDropdownProps';
import { defaultConfigProvider } from '../config-provider';
import { initDefaultProps } from '../_util/props-util';
import { dropdownButtonProps } from './props';
import EllipsisOutlined from '@ant-design/icons-vue/EllipsisOutlined';
import { tuple } from '../_util/type';
const ButtonTypesProps = buttonTypes();
const DropdownProps = getDropdownProps();
import useConfigInject from '../_util/hooks/useConfigInject';
const ButtonGroup = Button.Group;
const dropdownButtonProps = {
...DropdownProps,
type: PropTypes.oneOf(tuple('primary', 'ghost', 'dashed', 'danger', 'default')).def('default'),
size: PropTypes.oneOf(tuple('small', 'large', 'default')).def('default'),
htmlType: ButtonTypesProps.htmlType,
href: PropTypes.string,
disabled: PropTypes.looseBool,
prefixCls: PropTypes.string,
placement: DropdownProps.placement.def('bottomRight'),
icon: PropTypes.any,
title: PropTypes.string,
onClick: PropTypes.func,
onVisibleChange: PropTypes.func,
'onUpdate:visible': PropTypes.func,
};
export type DropdownButtonProps = Partial<ExtractPropTypes<typeof dropdownButtonProps>>;
export type DropdownButtonProps = Partial<ExtractPropTypes<ReturnType<typeof dropdownButtonProps>>>;
export default defineComponent({
name: 'ADropdownButton',
inheritAttrs: false,
props: dropdownButtonProps,
__ANT_BUTTON: true,
props: initDefaultProps(dropdownButtonProps(), {
trigger: 'hover',
placement: 'bottomRight',
type: 'default',
}),
emits: ['click', 'visibleChange', 'update:visible'],
setup() {
return {
configProvider: inject('configProvider', defaultConfigProvider),
popupRef: null,
slots: ['icon', 'leftButton', 'rightButton', 'overlay'],
setup(props, { slots, attrs, emit }) {
const handleClick = (e: MouseEvent) => {
emit('click', e);
};
},
created() {
provide('savePopupRef', this.savePopupRef);
},
methods: {
savePopupRef(ref: VNode) {
this.popupRef = ref;
},
handleClick(e: Event) {
this.$emit('click', e);
},
handleVisibleChange(val: boolean) {
this.$emit('update:visible', val);
this.$emit('visibleChange', val);
},
},
render() {
const {
type,
disabled,
onClick,
htmlType,
class: className,
prefixCls: customizePrefixCls,
overlay,
trigger,
align,
visible,
onVisibleChange,
placement,
getPopupContainer,
href,
title,
...restProps
} = { ...this.$props, ...this.$attrs } as any;
const icon = getComponent(this, 'icon') || <EllipsisOutlined />;
const { getPopupContainer: getContextPopupContainer } = this.configProvider;
const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('dropdown-button', customizePrefixCls);
const dropdownProps: any = {
align,
disabled,
trigger: disabled ? [] : trigger,
placement,
getPopupContainer: getPopupContainer || getContextPopupContainer,
onVisibleChange: this.handleVisibleChange,
const handleVisibleChange = (val: boolean) => {
emit('update:visible', val);
emit('visibleChange', val);
};
if (hasProp(this, 'visible')) {
dropdownProps.visible = visible;
}
const buttonGroupProps = {
...restProps,
class: classNames(prefixCls, className),
};
const { prefixCls, direction, getPopupContainer } = useConfigInject('dropdown-button', props);
return () => {
const {
type,
disabled,
htmlType,
class: className = '',
overlay = slots.overlay?.(),
trigger,
align,
visible,
onVisibleChange,
placement = direction.value === 'rtl' ? 'bottomLeft' : 'bottomRight',
href,
title,
icon = slots.icon?.() || <EllipsisOutlined />,
mouseEnterDelay,
mouseLeaveDelay,
...restProps
} = { ...props, ...attrs };
const dropdownProps = {
align,
disabled,
trigger: disabled ? [] : trigger,
placement,
getPopupContainer: getPopupContainer.value,
onVisibleChange: handleVisibleChange,
mouseEnterDelay,
mouseLeaveDelay,
visible,
};
return (
<ButtonGroup {...buttonGroupProps}>
const leftButton = (
<Button
type={type}
disabled={disabled}
onClick={this.handleClick}
onClick={handleClick}
htmlType={htmlType}
href={href}
title={title}
>
{getSlot(this)}
</Button>
<Dropdown {...dropdownProps} overlay={getComponent(this, 'overlay')}>
<Button type={type}>{icon}</Button>
</Dropdown>
</ButtonGroup>
);
v-slots={{ default: slots.default }}
></Button>
);
const rightButton = <Button type={type} icon={icon} />;
return (
<ButtonGroup {...restProps} class={classNames(prefixCls.value, className)}>
{slots.leftButton ? slots.leftButton({ button: leftButton }) : leftButton}
<Dropdown {...dropdownProps} v-slots={{ overlay: slots.overlay }}>
{slots.rightButton ? slots.rightButton({ button: rightButton }) : rightButton}
</Dropdown>
</ButtonGroup>
);
};
},
});

@ -1,123 +1,148 @@
import type { VNode, ExtractPropTypes } from 'vue';
import { provide, inject, cloneVNode, defineComponent } from 'vue';
import RcDropdown from '../vc-dropdown/src/index';
import { ExtractPropTypes, computed } from 'vue';
import { defineComponent } from 'vue';
import RcDropdown from '../vc-dropdown';
import DropdownButton from './dropdown-button';
import PropTypes from '../_util/vue-types';
import { cloneElement } from '../_util/vnode';
import classNames from '../_util/classNames';
import {
getOptionProps,
getPropsData,
getComponent,
isValidElement,
getSlot,
} from '../_util/props-util';
import getDropdownProps from './getDropdownProps';
import { defaultConfigProvider } from '../config-provider';
import { isValidElement, initDefaultProps } from '../_util/props-util';
import { dropdownProps } from './props';
import RightOutlined from '@ant-design/icons-vue/RightOutlined';
import useConfigInject from '../_util/hooks/useConfigInject';
import devWarning from '../vc-util/devWarning';
import omit from '../_util/omit';
const dropdownProps = getDropdownProps();
export type DropdownProps = Partial<ExtractPropTypes<typeof dropdownProps>>;
export type DropdownProps = Partial<ExtractPropTypes<ReturnType<typeof dropdownProps>>>;
const Dropdown = defineComponent({
name: 'ADropdown',
inheritAttrs: false,
props: {
...dropdownProps,
prefixCls: PropTypes.string,
mouseEnterDelay: PropTypes.number.def(0.15),
mouseLeaveDelay: PropTypes.number.def(0.1),
placement: dropdownProps.placement.def('bottomLeft'),
onVisibleChange: PropTypes.func,
'onUpdate:visible': PropTypes.func,
},
props: initDefaultProps(dropdownProps(), {
mouseEnterDelay: 0.15,
mouseLeaveDelay: 0.1,
placement: 'bottomLeft',
trigger: 'hover',
}),
emits: ['visibleChange', 'update:visible'],
setup() {
return {
configProvider: inject('configProvider', defaultConfigProvider),
popupRef: null,
};
},
created() {
provide('savePopupRef', this.savePopupRef);
},
methods: {
savePopupRef(ref: VNode) {
this.popupRef = ref;
},
getTransitionName() {
const { placement = '', transitionName } = this.$props;
slots: ['overlay'],
setup(props, { slots, attrs, emit }) {
const { prefixCls, rootPrefixCls, direction, getPopupContainer } = useConfigInject(
'dropdown',
props,
);
const transitionName = computed(() => {
const { placement = '', transitionName } = props;
if (transitionName !== undefined) {
return transitionName;
}
if (placement.indexOf('top') >= 0) {
return 'slide-down';
return `${rootPrefixCls.value}-slide-down`;
}
return 'slide-up';
},
renderOverlay(prefixCls: string) {
const overlay = getComponent(this, 'overlay');
return `${rootPrefixCls.value}-slide-up`;
});
const renderOverlay = () => {
// rc-dropdown already can process the function of overlay, but we have check logic here.
// So we need render the element to check and pass back to rc-dropdown.
const overlay = props.overlay || slots.overlay?.();
const overlayNode = Array.isArray(overlay) ? overlay[0] : overlay;
// menu cannot be selectable in dropdown defaultly
// menu should be focusable in dropdown defaultly
const overlayProps = overlayNode && getPropsData(overlayNode);
const { selectable = false, focusable = true } = (overlayProps || {}) as any;
const expandIcon = () => (
<span class={`${prefixCls}-menu-submenu-arrow`}>
<RightOutlined class={`${prefixCls}-menu-submenu-arrow-icon`} />
</span>
if (!overlayNode) return null;
const overlayProps = overlayNode.props || {};
// Warning if use other mode
devWarning(
!overlayProps.mode || overlayProps.mode === 'vertical',
'Dropdown',
`mode="${overlayProps.mode}" is not supported for Dropdown's Menu.`,
);
// menu cannot be selectable in dropdown defaultly
const { selectable = false, expandIcon = (overlayNode.children as any)?.expandIcon?.() } =
overlayProps;
const overlayNodeExpandIcon =
typeof expandIcon !== 'undefined' && isValidElement(expandIcon) ? (
expandIcon
) : (
<span class={`${prefixCls.value}-menu-submenu-arrow`}>
<RightOutlined class={`${prefixCls.value}-menu-submenu-arrow-icon`} />
</span>
);
const fixedModeOverlay = isValidElement(overlayNode)
? cloneVNode(overlayNode, {
? cloneElement(overlayNode, {
mode: 'vertical',
selectable,
focusable,
expandIcon,
expandIcon: () => overlayNodeExpandIcon,
})
: overlay;
: overlayNode;
return fixedModeOverlay;
},
handleVisibleChange(val: boolean) {
this.$emit('update:visible', val);
this.$emit('visibleChange', val);
},
},
};
const placement = computed(() => {
if (props.placement !== undefined) {
return props.placement;
}
return direction.value === 'rtl' ? 'bottomRight' : 'bottomLeft';
});
const handleVisibleChange = (val: boolean) => {
emit('update:visible', val);
emit('visibleChange', val);
};
render() {
const props = getOptionProps(this);
const { prefixCls: customizePrefixCls, trigger, disabled, getPopupContainer } = props;
const { getPopupContainer: getContextPopupContainer } = this.configProvider;
const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('dropdown', customizePrefixCls);
const child = getSlot(this)[0];
const dropdownTrigger = cloneElement(
child,
Object.assign(
return () => {
const { arrow, trigger, disabled, overlayClassName } = props;
const child = slots.default?.()[0];
const dropdownTrigger = cloneElement(
child,
Object.assign(
{
class: classNames(
child?.props?.class,
{
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
},
`${prefixCls.value}-trigger`,
),
},
disabled ? { disabled } : {},
),
);
const overlayClassNameCustomized = classNames(overlayClassName, {
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
});
const triggerActions = disabled ? [] : trigger;
let alignPoint: boolean;
if (triggerActions && triggerActions.indexOf('contextmenu') !== -1) {
alignPoint = true;
}
const dropdownProps = omit(
{
class: classNames(child?.props?.class, `${prefixCls}-trigger`),
...props,
...attrs,
overlayClassName: overlayClassNameCustomized,
arrow,
alignPoint,
prefixCls: prefixCls.value,
getPopupContainer: getPopupContainer.value,
transitionName: transitionName.value,
trigger: triggerActions,
onVisibleChange: handleVisibleChange,
placement: placement.value,
},
disabled ? { disabled } : {},
),
);
const triggerActions = disabled ? [] : typeof trigger === 'string' ? [trigger] : trigger;
let alignPoint;
if (triggerActions && triggerActions.indexOf('contextmenu') !== -1) {
alignPoint = true;
}
const dropdownProps = {
alignPoint,
...props,
...this.$attrs,
prefixCls,
getPopupContainer: getPopupContainer || getContextPopupContainer,
transitionName: this.getTransitionName(),
trigger: triggerActions,
overlay: this.renderOverlay(prefixCls),
onVisibleChange: this.handleVisibleChange,
['overlay'],
);
return (
<RcDropdown {...dropdownProps} v-slots={{ overlay: renderOverlay }}>
{dropdownTrigger}
</RcDropdown>
);
};
return <RcDropdown {...dropdownProps}>{dropdownTrigger}</RcDropdown>;
},
});

@ -1,28 +0,0 @@
import { tuple } from '../_util/type';
import type { PropType } from 'vue';
import PropTypes from '../_util/vue-types';
export default () => ({
trigger: {
type: [Array, String] as PropType<
('click' | 'hover' | 'contextmenu')[] | 'click' | 'hover' | 'contextmenu'
>,
default: 'hover',
},
overlay: PropTypes.any,
visible: PropTypes.looseBool,
disabled: PropTypes.looseBool,
align: PropTypes.object,
getPopupContainer: PropTypes.func,
prefixCls: PropTypes.string,
transitionName: PropTypes.string,
placement: PropTypes.oneOf(
tuple('topLeft', 'topCenter', 'topRight', 'bottomLeft', 'bottomCenter', 'bottomRight'),
),
overlayClassName: PropTypes.string,
overlayStyle: PropTypes.style,
forceRender: PropTypes.looseBool,
mouseEnterDelay: PropTypes.number,
mouseLeaveDelay: PropTypes.number,
openClassName: PropTypes.string,
minOverlayWidthMatchTrigger: PropTypes.looseBool,
});

@ -1,7 +1,7 @@
import type { App, Plugin } from 'vue';
import Dropdown from './dropdown';
import DropdownButton from './dropdown-button';
import { dropdownProps, dropdownButtonProps } from './props';
export type { DropdownProps } from './dropdown';
export type { DropdownButtonProps } from './dropdown-button';
@ -14,7 +14,7 @@ Dropdown.install = function (app: App) {
return app;
};
export { DropdownButton };
export { DropdownButton, dropdownProps, dropdownButtonProps };
export default Dropdown as typeof Dropdown &
Plugin & {

@ -0,0 +1,60 @@
import { tuple } from '../_util/type';
import type { PropType } from 'vue';
import PropTypes from '../_util/vue-types';
import buttonTypes from '../button/buttonTypes';
type Align = {
points?: [string, string];
offset?: [number, number];
targetOffset?: [number, number];
overflow?: {
adjustX?: boolean;
adjustY?: boolean;
};
useCssRight?: boolean;
useCssBottom?: boolean;
useCssTransform?: boolean;
};
const dropdownProps = () => ({
arrow: PropTypes.looseBool,
trigger: {
type: [Array, String] as PropType<
('click' | 'hover' | 'contextmenu')[] | 'click' | 'hover' | 'contextmenu'
>,
},
overlay: PropTypes.any,
visible: PropTypes.looseBool,
disabled: PropTypes.looseBool,
align: { type: Object as PropType<Align> },
getPopupContainer: PropTypes.func,
prefixCls: PropTypes.string,
transitionName: PropTypes.string,
placement: PropTypes.oneOf(
tuple('topLeft', 'topCenter', 'topRight', 'bottomLeft', 'bottomCenter', 'bottomRight'),
),
overlayClassName: PropTypes.string,
overlayStyle: PropTypes.style,
forceRender: PropTypes.looseBool,
mouseEnterDelay: PropTypes.number,
mouseLeaveDelay: PropTypes.number,
openClassName: PropTypes.string,
minOverlayWidthMatchTrigger: PropTypes.looseBool,
});
const ButtonTypesProps = buttonTypes();
const dropdownButtonProps = () => ({
...dropdownProps(),
type: PropTypes.oneOf(tuple('primary', 'ghost', 'dashed', 'default')),
size: PropTypes.oneOf(tuple('small', 'large')),
htmlType: ButtonTypesProps.htmlType,
href: PropTypes.string,
disabled: PropTypes.looseBool,
prefixCls: PropTypes.string,
icon: PropTypes.any,
title: PropTypes.string,
});
export { dropdownProps, dropdownButtonProps };
export default dropdownProps;

@ -1,5 +1,6 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@import './status';
@dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
@ -27,11 +28,11 @@
position: relative;
.@{ant-prefix}-btn > .@{iconfont-css-prefix}-down {
.iconfont-size-under-12px(10px);
font-size: 10px;
}
.@{iconfont-css-prefix}-down::before {
transition: transform 0.2s;
transition: transform @animation-duration-base;
}
}
@ -42,10 +43,81 @@
}
&-hidden,
&-menu-hidden {
&-menu-hidden,
&-menu-submenu-hidden {
display: none;
}
// Offset the popover to account for the dropdown arrow
&-show-arrow&-placement-topCenter,
&-show-arrow&-placement-topLeft,
&-show-arrow&-placement-topRight {
padding-bottom: @popover-distance;
}
&-show-arrow&-placement-bottomCenter,
&-show-arrow&-placement-bottomLeft,
&-show-arrow&-placement-bottomRight {
padding-top: @popover-distance;
}
// Arrows
// .popover-arrow is outer, .popover-arrow:after is inner
&-arrow {
position: absolute;
z-index: 1; // lift it up so the menu wouldn't cask shadow on it
display: block;
width: sqrt(@popover-arrow-width * @popover-arrow-width * 2);
height: sqrt(@popover-arrow-width * @popover-arrow-width * 2);
background: transparent;
border-style: solid;
border-width: (sqrt(@popover-arrow-width * @popover-arrow-width * 2) / 2);
transform: rotate(45deg);
}
&-placement-topCenter > &-arrow,
&-placement-topLeft > &-arrow,
&-placement-topRight > &-arrow {
bottom: @popover-distance - @popover-arrow-width + 2.2px;
border-top-color: transparent;
border-right-color: @popover-bg;
border-bottom-color: @popover-bg;
border-left-color: transparent;
box-shadow: 3px 3px 7px fade(@black, 7%);
}
&-placement-topCenter > &-arrow {
left: 50%;
transform: translateX(-50%) rotate(45deg);
}
&-placement-topLeft > &-arrow {
left: 16px;
}
&-placement-topRight > &-arrow {
right: 16px;
}
&-placement-bottomCenter > &-arrow,
&-placement-bottomLeft > &-arrow,
&-placement-bottomRight > &-arrow {
top: @popover-distance - @popover-arrow-width + 2px;
border-top-color: @popover-bg;
border-right-color: transparent;
border-bottom-color: transparent;
border-left-color: @popover-bg;
box-shadow: -2px -2px 5px fade(@black, 6%);
}
&-placement-bottomCenter > &-arrow {
left: 50%;
transform: translateX(-50%) rotate(45deg);
}
&-placement-bottomLeft > &-arrow {
left: 16px;
}
&-placement-bottomRight > &-arrow {
right: 16px;
}
&-menu {
position: relative;
margin: 0;
@ -57,12 +129,11 @@
border-radius: @border-radius-base;
outline: none;
box-shadow: @box-shadow-base;
-webkit-transform: translate3d(0, 0, 0);
&-item-group-title {
padding: 5px @control-padding-horizontal;
color: @text-color-secondary;
transition: all 0.3s;
transition: all @animation-duration-slow;
}
&-submenu-popup {
@ -72,10 +143,6 @@
box-shadow: none;
transform-origin: 0 0;
> .@{dropdown-prefix-cls}-menu {
transform-origin: 0 0;
}
ul,
li {
list-style: none;
@ -87,6 +154,42 @@
}
}
// ======================= Item Content =======================
&-item {
position: relative;
display: flex;
align-items: center;
}
&-item-icon {
min-width: 12px;
margin-right: 8px;
font-size: @font-size-sm;
}
&-title-content {
flex: auto;
> a {
color: inherit;
transition: all @animation-duration-slow;
&:hover {
color: inherit;
}
&::after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
content: '';
}
}
}
// =========================== Item ===========================
&-item,
&-submenu-title {
clear: both;
@ -98,25 +201,7 @@
line-height: @dropdown-line-height;
white-space: nowrap;
cursor: pointer;
transition: all 0.3s;
> .anticon:first-child,
> span > .anticon:first-child {
min-width: 12px;
margin-right: 8px;
font-size: @font-size-sm;
}
> a {
display: block;
margin: -@dropdown-vertical-padding -@control-padding-horizontal;
padding: @dropdown-vertical-padding @control-padding-horizontal;
color: @text-color;
transition: all 0.3s;
&:hover {
color: @text-color;
}
}
transition: all @animation-duration-slow;
&:first-child {
& when (@dropdown-edge-child-vertical-padding = 0) {
@ -130,8 +215,7 @@
}
}
&-selected,
&-selected > a {
&-selected {
color: @dropdown-selected-color;
background-color: @item-active-bg;
}
@ -146,9 +230,13 @@
&:hover {
color: @disabled-color;
background-color: @component-background;
background-color: @dropdown-menu-submenu-disabled-bg;
cursor: not-allowed;
}
a {
pointer-events: none;
}
}
&-divider {
@ -159,13 +247,15 @@
background-color: @border-color-split;
}
.@{dropdown-prefix-cls}-menu-submenu-arrow {
.@{dropdown-prefix-cls}-menu-submenu-expand-icon {
position: absolute;
right: @padding-xs;
&-icon {
.@{dropdown-prefix-cls}-menu-submenu-arrow-icon {
margin-right: 0 !important;
color: @text-color-secondary;
font-size: 10px;
font-style: normal;
.iconfont-size-under-12px(10px);
}
}
}
@ -177,7 +267,7 @@
}
&-submenu-title {
padding-right: 26px;
padding-right: @control-padding-horizontal + @font-size-sm;
}
&-submenu-vertical {
@ -208,54 +298,54 @@
}
}
&.slide-down-enter.slide-down-enter-active&-placement-bottomLeft,
&.slide-down-appear.slide-down-appear-active&-placement-bottomLeft,
&.slide-down-enter.slide-down-enter-active&-placement-bottomCenter,
&.slide-down-appear.slide-down-appear-active&-placement-bottomCenter,
&.slide-down-enter.slide-down-enter-active&-placement-bottomRight,
&.slide-down-appear.slide-down-appear-active&-placement-bottomRight {
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomLeft,
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomLeft,
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomCenter,
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomCenter,
&.@{ant-prefix}-slide-down-enter.@{ant-prefix}-slide-down-enter-active&-placement-bottomRight,
&.@{ant-prefix}-slide-down-appear.@{ant-prefix}-slide-down-appear-active&-placement-bottomRight {
animation-name: antSlideUpIn;
}
&.slide-up-enter.slide-up-enter-active&-placement-topLeft,
&.slide-up-appear.slide-up-appear-active&-placement-topLeft,
&.slide-up-enter.slide-up-enter-active&-placement-topCenter,
&.slide-up-appear.slide-up-appear-active&-placement-topCenter,
&.slide-up-enter.slide-up-enter-active&-placement-topRight,
&.slide-up-appear.slide-up-appear-active&-placement-topRight {
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topLeft,
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topLeft,
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topCenter,
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topCenter,
&.@{ant-prefix}-slide-up-enter.@{ant-prefix}-slide-up-enter-active&-placement-topRight,
&.@{ant-prefix}-slide-up-appear.@{ant-prefix}-slide-up-appear-active&-placement-topRight {
animation-name: antSlideDownIn;
}
&.slide-down-leave.slide-down-leave-active&-placement-bottomLeft,
&.slide-down-leave.slide-down-leave-active&-placement-bottomCenter,
&.slide-down-leave.slide-down-leave-active&-placement-bottomRight {
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomLeft,
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomCenter,
&.@{ant-prefix}-slide-down-leave.@{ant-prefix}-slide-down-leave-active&-placement-bottomRight {
animation-name: antSlideUpOut;
}
&.slide-up-leave.slide-up-leave-active&-placement-topLeft,
&.slide-up-leave.slide-up-leave-active&-placement-topCenter,
&.slide-up-leave.slide-up-leave-active&-placement-topRight {
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topLeft,
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topCenter,
&.@{ant-prefix}-slide-up-leave.@{ant-prefix}-slide-up-leave-active&-placement-topRight {
animation-name: antSlideDownOut;
}
}
.@{dropdown-prefix-cls}-trigger,
.@{dropdown-prefix-cls}-link {
.@{dropdown-prefix-cls}-link,
.@{dropdown-prefix-cls}-button {
> .@{iconfont-css-prefix}.@{iconfont-css-prefix}-down {
.iconfont-size-under-12px(10px);
font-size: 10px;
vertical-align: baseline;
}
}
.@{dropdown-prefix-cls}-button {
white-space: nowrap;
&.@{ant-prefix}-btn-group > .@{ant-prefix}-btn:last-child:not(:first-child) {
&.@{ant-prefix}-btn-group
> .@{ant-prefix}-btn:last-child:not(:first-child):not(.@{ant-prefix}-btn-icon-only) {
padding-right: @padding-xs;
padding-left: @padding-xs;
}
.@{iconfont-css-prefix}.@{iconfont-css-prefix}-down {
.iconfont-size-under-12px(10px);
}
}
// https://github.com/ant-design/ant-design/issues/4903
@ -266,7 +356,8 @@
}
.@{dropdown-prefix-cls}-menu-item,
.@{dropdown-prefix-cls}-menu-submenu-title,
.@{dropdown-prefix-cls}-menu-item > a {
.@{dropdown-prefix-cls}-menu-item > a,
.@{dropdown-prefix-cls}-menu-item > .@{iconfont-css-prefix} + span > a {
color: @text-color-secondary-dark;
.@{dropdown-prefix-cls}-menu-submenu-arrow::after {
color: @text-color-secondary-dark;
@ -285,3 +376,5 @@
}
}
}
@import './rtl';

@ -0,0 +1,89 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
.@{dropdown-prefix-cls} {
&-rtl {
direction: rtl;
}
&::before {
.@{dropdown-prefix-cls}-rtl& {
right: -7px;
left: 0;
}
}
&-menu {
&&-rtl {
direction: rtl;
text-align: right;
}
&-item-group-title {
.@{dropdown-prefix-cls}-rtl & {
direction: rtl;
text-align: right;
}
}
&-submenu-popup {
&.@{dropdown-prefix-cls}-menu-submenu-rtl {
transform-origin: 100% 0;
}
ul,
li {
.@{dropdown-prefix-cls}-rtl & {
text-align: right;
}
}
}
&-item,
&-submenu-title {
.@{dropdown-prefix-cls}-rtl & {
text-align: right;
}
> .@{iconfont-css-prefix}:first-child,
> span > .@{iconfont-css-prefix}:first-child {
.@{dropdown-prefix-cls}-rtl & {
margin-right: 0;
margin-left: 8px;
}
}
.@{dropdown-prefix-cls}-menu-submenu-arrow {
.@{dropdown-prefix-cls}-rtl & {
right: auto;
left: @padding-xs;
}
&-icon {
.@{dropdown-prefix-cls}-rtl & {
margin-left: 0 !important;
transform: scaleX(-1);
}
}
}
}
&-submenu-title {
.@{dropdown-prefix-cls}-rtl & {
padding-right: @control-padding-horizontal;
padding-left: @control-padding-horizontal + @font-size-sm;
}
}
&-submenu-vertical > & {
.@{dropdown-prefix-cls}-rtl & {
right: 100%;
left: 0;
margin-right: 4px;
margin-left: 0;
}
}
}
}

@ -0,0 +1,12 @@
@import './index';
.@{dropdown-prefix-cls}-menu-item {
&&-danger {
color: @error-color;
&:hover {
color: @text-color-inverse;
background-color: @error-color;
}
}
}

@ -23,6 +23,7 @@ import Overflow from '../../vc-overflow';
import MenuItem from './MenuItem';
import SubMenu from './SubMenu';
import EllipsisOutlined from '@ant-design/icons-vue/EllipsisOutlined';
import { cloneElement } from '../../_util/vnode';
export const menuProps = {
prefixCls: String,
@ -345,7 +346,17 @@ export default defineComponent({
};
const lastVisibleIndex = ref(0);
const expandIcon: MenuProps['expandIcon'] = opt => {
let icon = props.expandIcon || slots.expandIcon;
icon = typeof icon === 'function' ? icon(opt) : icon;
return cloneElement(
icon,
{
class: `${prefixCls.value}-submenu-expand-icon`,
},
false,
);
};
useProvideMenu({
store,
prefixCls,
@ -374,7 +385,7 @@ export default defineComponent({
unRegisterMenuInfo,
selectedSubMenuEventKeys,
isRootMenu: ref(true),
expandIcon: props.expandIcon || slots.expandIcon,
expandIcon,
});
return () => {
const childList = flattenChildren(slots.default?.());

@ -5,7 +5,6 @@ import Tooltip from '../tooltip';
import abstractTooltipProps from '../tooltip/abstractTooltipProps';
import PropTypes from '../_util/vue-types';
import { initDefaultProps } from '../_util/props-util';
import BaseMixin from '../_util/BaseMixin';
import type { ButtonProps, LegacyButtonType } from '../button/buttonTypes';
import { convertLegacyProps } from '../button/buttonTypes';
import ExclamationCircleFilled from '@ant-design/icons-vue/ExclamationCircleFilled';
@ -47,7 +46,6 @@ export interface PopconfirmLocale {
const Popconfirm = defineComponent({
name: 'APopconfirm',
mixins: [BaseMixin],
props: initDefaultProps(popconfirmProps(), {
trigger: 'click',
transitionName: 'zoom-big',

@ -7,7 +7,7 @@ import raf from '../_util/raf';
export default defineComponent({
name: 'SliderTooltip',
inheritAttrs: false,
props: tooltipProps,
props: tooltipProps(),
setup(props, { attrs, slots }) {
const innerRef = ref<any>(null);

@ -0,0 +1,144 @@
import { computed, defineComponent, ref, watch } from 'vue';
import PropTypes from '../_util/vue-types';
import Trigger from '../vc-trigger';
import placements from './placements';
import { cloneElement } from '../_util/vnode';
import classNames from '../_util/classNames';
export default defineComponent({
props: {
minOverlayWidthMatchTrigger: PropTypes.looseBool,
arrow: PropTypes.looseBool.def(false),
prefixCls: PropTypes.string.def('rc-dropdown'),
transitionName: PropTypes.string,
overlayClassName: PropTypes.string.def(''),
openClassName: PropTypes.string,
animation: PropTypes.any,
align: PropTypes.object,
overlayStyle: PropTypes.style,
placement: PropTypes.string.def('bottomLeft'),
overlay: PropTypes.any,
trigger: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]).def(
'hover',
),
alignPoint: PropTypes.looseBool,
showAction: PropTypes.array,
hideAction: PropTypes.array,
getPopupContainer: PropTypes.func,
visible: PropTypes.looseBool,
defaultVisible: PropTypes.looseBool.def(false),
mouseEnterDelay: PropTypes.number.def(0.15),
mouseLeaveDelay: PropTypes.number.def(0.1),
},
emits: ['visibleChange', 'overlayClick'],
slots: ['overlay'],
setup(props, { slots, emit, expose }) {
const triggerVisible = ref(!!props.visible);
watch(
() => props.visible,
val => {
if (val !== undefined) {
triggerVisible.value = val;
}
},
);
const triggerRef = ref();
expose({
triggerRef,
});
const onClick = (e: MouseEvent) => {
if (props.visible === undefined) {
triggerVisible.value = false;
}
emit('overlayClick', e);
};
const onVisibleChange = (visible: boolean) => {
if (props.visible === undefined) {
triggerVisible.value = visible;
}
emit('visibleChange', visible);
};
const getMenuElement = () => {
const overlayElement = slots.overlay?.();
const extraOverlayProps = {
prefixCls: `${props.prefixCls}-menu`,
onClick,
getPopupContainer: () => triggerRef.value.getPopupDomNode(),
};
return (
<>
{props.arrow && <div class={`${props.prefixCls}-arrow`} />}
{cloneElement(overlayElement, extraOverlayProps, false)}
</>
);
};
const minOverlayWidthMatchTrigger = computed(() => {
const { minOverlayWidthMatchTrigger: matchTrigger = !props.alignPoint } = props;
return matchTrigger;
});
const renderChildren = () => {
const children = slots.default?.();
return triggerVisible.value && children
? cloneElement(
children[0],
{ class: props.openClassName || `${props.prefixCls}-open` },
false,
)
: children;
};
const triggerHideAction = computed(() => {
if (!props.hideAction && props.trigger.indexOf('contextmenu') !== -1) {
return ['click'];
}
return props.hideAction;
});
return () => {
const {
prefixCls,
arrow,
showAction,
overlayStyle,
trigger,
placement,
align,
getPopupContainer,
transitionName,
animation,
overlayClassName,
...otherProps
} = props;
return (
<Trigger
{...otherProps}
prefixCls={prefixCls}
ref={triggerRef}
popupClassName={classNames(overlayClassName, {
[`${prefixCls}-show-arrow`]: arrow,
})}
popupStyle={overlayStyle}
builtinPlacements={placements}
action={trigger}
showAction={showAction}
hideAction={triggerHideAction.value || []}
popupPlacement={placement}
popupAlign={align}
popupTransitionName={transitionName}
popupAnimation={animation}
popupVisible={triggerVisible.value}
stretch={minOverlayWidthMatchTrigger.value ? 'minWidth' : ''}
onPopupVisibleChange={onVisibleChange}
getPopupContainer={getPopupContainer}
v-slots={{ popup: getMenuElement, default: renderChildren }}
></Trigger>
);
};
},
});

@ -1,225 +0,0 @@
@dropdownPrefixCls: rc-dropdown;
@font-face {
font-family: 'anticon';
src: url('//at.alicdn.com/t/font_1434092639_4910953.eot');
/* IE9*/
src: url('//at.alicdn.com/t/font_1434092639_4910953.eot?#iefix') format('embedded-opentype'),
/* IE6-IE8 */ url('//at.alicdn.com/t/font_1434092639_4910953.woff') format('woff'),
/* chrome、firefox */ url('//at.alicdn.com/t/font_1434092639_4910953.ttf') format('truetype'),
/* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
url('//at.alicdn.com/t/font_1434092639_4910953.svg#iconfont') format('svg');
/* iOS 4.1- */
}
.@{dropdownPrefixCls} {
position: absolute;
left: -9999px;
top: -9999px;
z-index: 1070;
display: block;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12px;
font-weight: normal;
line-height: 1.5;
&-hidden {
display: none;
}
&-menu {
outline: none;
position: relative;
list-style-type: none;
padding: 0;
margin: 2px 0 0 0;
text-align: left;
background-color: #fff;
border-radius: 3px;
box-shadow: 0 1px 5px #ccc;
background-clip: padding-box;
border: 1px solid #ccc;
> li {
margin: 0;
padding: 0;
}
&:before {
content: '';
position: absolute;
top: -4px;
left: 0;
width: 100%;
height: 4px;
background: rgb(255, 255, 255);
background: rgba(255, 255, 255, 0.01);
}
& > &-item {
position: relative;
display: block;
padding: 7px 10px;
clear: both;
font-size: 12px;
font-weight: normal;
color: #666666;
white-space: nowrap;
&:hover,
&-active,
&-selected {
background-color: #ebfaff;
}
&-selected {
position: relative;
&:after {
content: '\e613';
font-family: 'anticon';
font-weight: bold;
position: absolute;
top: 6px;
right: 16px;
color: #3cb8f0;
}
}
&-disabled {
color: #ccc;
cursor: not-allowed;
pointer-events: none;
&:hover {
color: #ccc;
background-color: #fff;
cursor: not-allowed;
}
}
&:last-child {
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
}
&:first-child {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
&-divider {
height: 1px;
margin: 1px 0;
overflow: hidden;
background-color: #e5e5e5;
line-height: 0;
}
}
}
.effect() {
animation-duration: 0.3s;
animation-fill-mode: both;
transform-origin: 0 0;
display: block !important;
}
&-slide-up-enter,
&-slide-up-appear {
.effect();
opacity: 0;
animation-timing-function: cubic-bezier(0.08, 0.82, 0.17, 1);
animation-play-state: paused;
}
&-slide-up-leave {
.effect();
opacity: 1;
animation-timing-function: cubic-bezier(0.6, 0.04, 0.98, 0.34);
animation-play-state: paused;
}
&-slide-up-enter&-slide-up-enter-active&-placement-bottomLeft,
&-slide-up-appear&-slide-up-appear-active&-placement-bottomLeft,
&-slide-up-enter&-slide-up-enter-active&-placement-bottomCenter,
&-slide-up-appear&-slide-up-appear-active&-placement-bottomCenter,
&-slide-up-enter&-slide-up-enter-active&-placement-bottomRight,
&-slide-up-appear&-slide-up-appear-active&-placement-bottomRight {
animation-name: rcDropdownSlideUpIn;
animation-play-state: running;
}
&-slide-up-enter&-slide-up-enter-active&-placement-topLeft,
&-slide-up-appear&-slide-up-appear-active&-placement-topLeft,
&-slide-up-enter&-slide-up-enter-active&-placement-topCenter,
&-slide-up-appear&-slide-up-appear-active&-placement-topCenter,
&-slide-up-enter&-slide-up-enter-active&-placement-topRight,
&-slide-up-appear&-slide-up-appear-active&-placement-topRight {
animation-name: rcDropdownSlideDownIn;
animation-play-state: running;
}
&-slide-up-leave&-slide-up-leave-active&-placement-bottomLeft,
&-slide-up-leave&-slide-up-leave-active&-placement-bottomCenter,
&-slide-up-leave&-slide-up-leave-active&-placement-bottomRight {
animation-name: rcDropdownSlideUpOut;
animation-play-state: running;
}
&-slide-up-leave&-slide-up-leave-active&-placement-topLeft,
&-slide-up-leave&-slide-up-leave-active&-placement-topCenter,
&-slide-up-leave&-slide-up-leave-active&-placement-topRight {
animation-name: rcDropdownSlideDownOut;
animation-play-state: running;
}
@keyframes rcDropdownSlideUpIn {
0% {
opacity: 0;
transform-origin: 0% 0%;
transform: scaleY(0);
}
100% {
opacity: 1;
transform-origin: 0% 0%;
transform: scaleY(1);
}
}
@keyframes rcDropdownSlideUpOut {
0% {
opacity: 1;
transform-origin: 0% 0%;
transform: scaleY(1);
}
100% {
opacity: 0;
transform-origin: 0% 0%;
transform: scaleY(0);
}
}
@keyframes rcDropdownSlideDownIn {
0% {
opacity: 0;
transform-origin: 0% 100%;
transform: scaleY(0);
}
100% {
opacity: 1;
transform-origin: 0% 100%;
transform: scaleY(1);
}
}
@keyframes rcDropdownSlideDownOut {
0% {
opacity: 1;
transform-origin: 0% 100%;
transform: scaleY(1);
}
100% {
opacity: 0;
transform-origin: 0% 100%;
transform: scaleY(0);
}
}
}

@ -1,3 +1,3 @@
// base in 2.4.1
// base in 3.2.0
import Dropdown from './Dropdown';
export default Dropdown;

@ -5,7 +5,7 @@ const autoAdjustOverflow = {
const targetOffset = [0, 0];
export const placements = {
const placements = {
topLeft: {
points: ['bl', 'tl'],
overflow: autoAdjustOverflow,

@ -1,202 +0,0 @@
import { defineComponent, Text } from 'vue';
import PropTypes from '../../_util/vue-types';
import Trigger from '../../vc-trigger';
import placements from './placements';
import {
hasProp,
getComponent,
getOptionProps,
getSlot,
findDOMNode,
} from '../../_util/props-util';
import BaseMixin from '../../_util/BaseMixin';
import { cloneElement } from '../../_util/vnode';
export default defineComponent({
mixins: [BaseMixin],
props: {
minOverlayWidthMatchTrigger: PropTypes.looseBool,
prefixCls: PropTypes.string.def('rc-dropdown'),
transitionName: PropTypes.string,
overlayClassName: PropTypes.string.def(''),
openClassName: PropTypes.string,
animation: PropTypes.any,
align: PropTypes.object,
overlayStyle: PropTypes.style,
placement: PropTypes.string.def('bottomLeft'),
overlay: PropTypes.any,
trigger: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]).def(
'hover',
),
alignPoint: PropTypes.looseBool,
showAction: PropTypes.array,
hideAction: PropTypes.array,
getPopupContainer: PropTypes.func,
visible: PropTypes.looseBool,
defaultVisible: PropTypes.looseBool.def(false),
mouseEnterDelay: PropTypes.number.def(0.15),
mouseLeaveDelay: PropTypes.number.def(0.1),
},
data() {
let sVisible = this.defaultVisible;
if (hasProp(this, 'visible')) {
sVisible = this.visible;
}
return {
sVisible,
};
},
watch: {
visible(val) {
if (val !== undefined) {
this.setState({
sVisible: val,
});
}
},
},
methods: {
onClick(e) {
const overlayProps = this.getOverlayElement().props;
// do no call onVisibleChange, if you need click to hide, use onClick and control visible
if (!hasProp(this, 'visible')) {
this.setState({
sVisible: false,
});
}
this.__emit('overlayClick', e);
if (overlayProps.onClick) {
overlayProps.onClick(e);
}
},
onVisibleChange(visible) {
if (!hasProp(this, 'visible')) {
this.setState({
sVisible: visible,
});
}
this.__emit('update:visible', visible);
this.__emit('visibleChange', visible);
},
getMinOverlayWidthMatchTrigger() {
const props = getOptionProps(this);
const { minOverlayWidthMatchTrigger, alignPoint } = props;
if ('minOverlayWidthMatchTrigger' in props) {
return minOverlayWidthMatchTrigger;
}
return !alignPoint;
},
getOverlayElement() {
const overlay = getComponent(this, 'overlay');
return Array.isArray(overlay) ? overlay[0] : overlay;
},
getMenuElement() {
const { onClick, prefixCls } = this;
const overlayElement = this.getOverlayElement();
const extraOverlayProps = {
prefixCls: `${prefixCls}-menu`,
getPopupContainer: () => this.getPopupDomNode(),
onClick,
};
if (overlayElement && overlayElement.type === Text) {
delete extraOverlayProps.prefixCls;
}
return cloneElement(overlayElement, extraOverlayProps);
},
getMenuElementOrLambda() {
const overlay = this.overlay || this.$slots.overlay;
if (typeof overlay === 'function') {
return this.getMenuElement;
}
return this.getMenuElement();
},
getPopupDomNode() {
return this.triggerRef.getPopupDomNode();
},
getOpenClassName() {
const { openClassName, prefixCls } = this.$props;
if (openClassName !== undefined) {
return openClassName;
}
return `${prefixCls}-open`;
},
afterVisibleChange(visible) {
if (visible && this.getMinOverlayWidthMatchTrigger()) {
const overlayNode = this.getPopupDomNode();
const rootNode = findDOMNode(this);
if (rootNode && overlayNode && rootNode.offsetWidth > overlayNode.offsetWidth) {
overlayNode.style.minWidth = `${rootNode.offsetWidth}px`;
if (
this.triggerRef &&
this.triggerRef._component &&
this.triggerRef._component.alignInstance
) {
this.triggerRef._component.alignInstance.forceAlign();
}
}
}
},
renderChildren() {
const children = getSlot(this);
const { sVisible } = this;
return sVisible && children
? cloneElement(children[0], { class: this.getOpenClassName() }, false)
: children;
},
saveTrigger(node) {
this.triggerRef = node;
},
},
render() {
const {
prefixCls,
transitionName,
animation,
align,
placement,
getPopupContainer,
showAction,
hideAction,
overlayClassName,
overlayStyle,
trigger,
...otherProps
} = this.$props;
let triggerHideAction = hideAction;
if (!triggerHideAction && trigger.indexOf('contextmenu') !== -1) {
triggerHideAction = ['click'];
}
const triggerProps = {
...otherProps,
prefixCls,
popupClassName: overlayClassName,
popupStyle: overlayStyle,
builtinPlacements: placements,
action: trigger,
showAction,
hideAction: triggerHideAction || [],
popupPlacement: placement,
popupAlign: align,
popupTransitionName: transitionName,
popupAnimation: animation,
popupVisible: this.sVisible,
afterPopupVisibleChange: this.afterVisibleChange,
getPopupContainer,
onPopupVisibleChange: this.onVisibleChange,
popup: this.getMenuElementOrLambda(),
ref: this.saveTrigger,
};
return <Trigger {...triggerProps}>{this.renderChildren()}</Trigger>;
},
});

@ -21,13 +21,11 @@ export default function Mask(props: MaskProps) {
let motion = {};
if (maskTransitionName || maskAnimation) {
motion = {
...getMotion({
prefixCls,
transitionName: maskTransitionName,
animation: maskAnimation,
}),
};
motion = getMotion({
prefixCls,
transitionName: maskTransitionName,
animation: maskAnimation,
});
}
return (

@ -83,7 +83,7 @@ export default defineComponent({
// ======================== Motion ========================
const motion = computed(() => {
const m = { ...getMotion(props) };
const m = getMotion(props);
['onAfterEnter', 'onAfterLeave'].forEach(eventName => {
m[eventName] = () => {
goNextStatus();

@ -18,6 +18,5 @@ export function getMotion({ prefixCls, animation, transitionName }: GetMotionPro
name: transitionName,
};
}
return null;
return {};
}

Loading…
Cancel
Save