ant-design-vue/components/popconfirm/index.tsx
Garret MH a2f7d6d062
feat: Vue 3 Migration Build support (#5973), close #5765
closes vueComponent/ant-design-vue#5765

Add `compatConfig: { MODE: 3 }` to all component definitions to signal to `@vue/compat` not to use any Vue 2 compatibility features.
2022-09-26 21:33:41 +08:00

229 lines
7.3 KiB
Vue

import type { ExtractPropTypes, HTMLAttributes, PropType } from 'vue';
import { computed, onMounted, ref, toRef, defineComponent } from 'vue';
import Tooltip from '../tooltip';
import abstractTooltipProps from '../tooltip/abstractTooltipProps';
import PropTypes from '../_util/vue-types';
import { initDefaultProps } from '../_util/props-util';
import type { ButtonProps, LegacyButtonType } from '../button/buttonTypes';
import { convertLegacyProps } from '../button/buttonTypes';
import ExclamationCircleFilled from '@ant-design/icons-vue/ExclamationCircleFilled';
import Button from '../button';
import { useLocaleReceiver } from '../locale-provider/LocaleReceiver';
import defaultLocale from '../locale-provider/default';
import { withInstall } from '../_util/type';
import useMergedState from '../_util/hooks/useMergedState';
import devWarning from '../vc-util/devWarning';
import KeyCode from '../_util/KeyCode';
import useConfigInject from '../_util/hooks/useConfigInject';
import classNames from '../_util/classNames';
import { getTransitionName } from '../_util/transition';
import { cloneVNodes } from '../_util/vnode';
import omit from '../_util/omit';
import { tooltipDefaultProps } from '../tooltip/Tooltip';
import ActionButton from '../_util/ActionButton';
export const popconfirmProps = () => ({
...abstractTooltipProps(),
prefixCls: String,
content: PropTypes.any,
title: PropTypes.any,
okType: {
type: String as PropType<LegacyButtonType>,
default: 'primary',
},
disabled: { type: Boolean, default: false },
okText: PropTypes.any,
cancelText: PropTypes.any,
icon: PropTypes.any,
okButtonProps: {
type: Object as PropType<ButtonProps & HTMLAttributes>,
default: undefined as ButtonProps & HTMLAttributes,
},
cancelButtonProps: {
type: Object as PropType<ButtonProps & HTMLAttributes>,
default: undefined as ButtonProps & HTMLAttributes,
},
showCancel: { type: Boolean, default: true },
onConfirm: Function as PropType<(e: MouseEvent) => void>,
onCancel: Function as PropType<(e: MouseEvent) => void>,
});
export type PopconfirmProps = Partial<ExtractPropTypes<ReturnType<typeof popconfirmProps>>>;
export interface PopconfirmLocale {
okText: string;
cancelText: string;
}
const Popconfirm = defineComponent({
compatConfig: { MODE: 3 },
name: 'APopconfirm',
props: initDefaultProps(popconfirmProps(), {
...tooltipDefaultProps(),
trigger: 'click',
transitionName: 'zoom-big',
placement: 'top',
mouseEnterDelay: 0.1,
mouseLeaveDelay: 0.1,
arrowPointAtCenter: false,
autoAdjustOverflow: true,
okType: 'primary',
disabled: false,
}),
slots: ['title', 'content', 'okText', 'icon', 'cancelText', 'cancelButton', 'okButton'],
emits: ['update:visible', 'visibleChange'],
setup(props: PopconfirmProps, { slots, emit, expose }) {
onMounted(() => {
devWarning(
props.defaultVisible === undefined,
'Popconfirm',
`'defaultVisible' is deprecated, please use 'v-model:visible'`,
);
});
const tooltipRef = ref();
expose({
getPopupDomNode: () => {
return tooltipRef.value?.getPopupDomNode?.();
},
});
const [visible, setVisible] = useMergedState(false, {
value: toRef(props, 'visible'),
defaultValue: props.defaultVisible,
});
const settingVisible = (value: boolean, e?: MouseEvent | KeyboardEvent) => {
if (props.visible === undefined) {
setVisible(value);
}
emit('update:visible', value);
emit('visibleChange', value, e);
};
const close = (e: MouseEvent) => {
settingVisible(false, e);
};
const onConfirm = (e: MouseEvent) => {
return props.onConfirm?.(e);
};
const onCancel = (e: MouseEvent) => {
settingVisible(false, e);
props.onCancel?.(e);
};
const onKeyDown = (e: KeyboardEvent) => {
if (e.keyCode === KeyCode.ESC && visible) {
settingVisible(false, e);
}
};
const onVisibleChange = (value: boolean) => {
const { disabled } = props;
if (disabled) {
return;
}
settingVisible(value);
};
const { prefixCls: prefixClsConfirm, getPrefixCls } = useConfigInject('popconfirm', props);
const rootPrefixCls = computed(() => getPrefixCls());
const popoverPrefixCls = computed(() => getPrefixCls('popover'));
const btnPrefixCls = computed(() => getPrefixCls('btn'));
const [popconfirmLocale] = useLocaleReceiver('Popconfirm', defaultLocale.Popconfirm);
const renderOverlay = () => {
const {
okButtonProps,
cancelButtonProps,
title = slots.title?.(),
cancelText = slots.cancel?.(),
okText = slots.okText?.(),
okType,
icon = slots.icon?.(),
showCancel = true,
} = props;
const { cancelButton, okButton } = slots;
const cancelProps: ButtonProps = {
onClick: onCancel,
size: 'small',
...cancelButtonProps,
};
const okProps: ButtonProps = {
onClick: onConfirm,
...convertLegacyProps(okType),
size: 'small',
...okButtonProps,
};
return (
<div class={`${popoverPrefixCls.value}-inner-content`}>
<div class={`${popoverPrefixCls.value}-message`}>
{icon || <ExclamationCircleFilled />}
<div class={`${popoverPrefixCls.value}-message-title`}>{title}</div>
</div>
<div class={`${popoverPrefixCls.value}-buttons`}>
{showCancel ? (
cancelButton ? (
cancelButton(cancelProps)
) : (
<Button {...cancelProps}>{cancelText || popconfirmLocale.value.cancelText}</Button>
)
) : null}
{okButton ? (
okButton(okProps)
) : (
<ActionButton
buttonProps={{ size: 'small', ...convertLegacyProps(okType), ...okButtonProps }}
actionFn={onConfirm}
close={close}
prefixCls={btnPrefixCls.value}
quitOnNullishReturnValue
emitEvent
>
{okText || popconfirmLocale.value.okText}
</ActionButton>
)}
</div>
</div>
);
};
return () => {
const { placement, overlayClassName, ...restProps } = props;
const otherProps = omit(restProps, [
'title',
'content',
'cancelText',
'okText',
'onUpdate:visible',
'onConfirm',
'onCancel',
]);
const overlayClassNames = classNames(prefixClsConfirm.value, overlayClassName);
return (
<Tooltip
{...otherProps}
prefixCls={popoverPrefixCls.value}
placement={placement}
onVisibleChange={onVisibleChange}
visible={visible.value}
overlayClassName={overlayClassNames}
transitionName={getTransitionName(rootPrefixCls.value, 'zoom-big', props.transitionName)}
v-slots={{ title: renderOverlay }}
ref={tooltipRef}
>
{cloneVNodes(
slots.default?.() || [],
{
onKeydown: (e: KeyboardEvent) => {
onKeyDown(e);
},
},
false,
)}
</Tooltip>
);
};
},
});
export default withInstall(Popconfirm);