diff --git a/components/modal/ActionButton.tsx b/components/_util/ActionButton.tsx similarity index 92% rename from components/modal/ActionButton.tsx rename to components/_util/ActionButton.tsx index cc3766368..fe1eb83de 100644 --- a/components/modal/ActionButton.tsx +++ b/components/_util/ActionButton.tsx @@ -4,6 +4,7 @@ import Button from '../button'; import type { ButtonProps } from '../button'; import type { LegacyButtonType } from '../button/buttonTypes'; import { convertLegacyProps } from '../button/buttonTypes'; +import useDestroyed from './hooks/useDestroyed'; const actionButtonProps = { type: { @@ -32,6 +33,7 @@ export default defineComponent({ const buttonRef = ref(); const loading = ref(false); let timeoutId: any; + const isDestroyed = useDestroyed(); onMounted(() => { if (props.autofocus) { timeoutId = setTimeout(() => buttonRef.value.$el?.focus()); @@ -49,7 +51,9 @@ export default defineComponent({ loading.value = true; returnValueOfOnOk!.then( (...args: any[]) => { - loading.value = false; + if (!isDestroyed.value) { + loading.value = false; + } close(...args); clickedRef.value = false; }, @@ -58,7 +62,9 @@ export default defineComponent({ // eslint-disable-next-line no-console console.error(e); // See: https://github.com/ant-design/ant-design/issues/6183 - loading.value = false; + if (!isDestroyed.value) { + loading.value = false; + } clickedRef.value = false; }, ); diff --git a/components/modal/ConfirmDialog.tsx b/components/modal/ConfirmDialog.tsx index 7a889a208..aa77dd5be 100644 --- a/components/modal/ConfirmDialog.tsx +++ b/components/modal/ConfirmDialog.tsx @@ -1,7 +1,7 @@ import classNames from '../_util/classNames'; import type { ModalFuncProps } from './Modal'; import Dialog from './Modal'; -import ActionButton from './ActionButton'; +import ActionButton from '../_util/ActionButton'; import { defineComponent } from 'vue'; import { useLocaleReceiver } from '../locale-provider/LocaleReceiver'; import { getTransitionName } from '../_util/transition'; diff --git a/components/popconfirm/__tests__/__snapshots__/demo.test.js.snap b/components/popconfirm/__tests__/__snapshots__/demo.test.js.snap index ef00ec92e..6756abf7f 100644 --- a/components/popconfirm/__tests__/__snapshots__/demo.test.js.snap +++ b/components/popconfirm/__tests__/__snapshots__/demo.test.js.snap @@ -62,3 +62,9 @@ exports[`renders ./components/popconfirm/demo/placement.vue correctly 1`] = ` `; + +exports[`renders ./components/popconfirm/demo/promise.vue correctly 1`] = ` + +`; diff --git a/components/popconfirm/demo/index.vue b/components/popconfirm/demo/index.vue index dd2a1fc65..55a10f904 100644 --- a/components/popconfirm/demo/index.vue +++ b/components/popconfirm/demo/index.vue @@ -5,6 +5,7 @@ + diff --git a/components/popconfirm/index.en-US.md b/components/popconfirm/index.en-US.md index 331c0206d..1760946b1 100644 --- a/components/popconfirm/index.en-US.md +++ b/components/popconfirm/index.en-US.md @@ -24,6 +24,7 @@ The difference with the 'confirm' modal dialog is that it's more lightweight tha | okText | text of the Confirm button | string\|slot | `Confirm` | | | okButton | custom render confirm button | slot | - | 3.0 | | okType | Button `type` of the Confirm button | string | `primary` | | +| showCancel | Show cancel button | boolean | true | 3.0 | | title | title of the confirmation box | string\|slot | - | | | visible (v-model) | hide or show | boolean | - | | | icon | customize icon of confirmation | vNode\|slot | <Icon type="exclamation-circle" /> | | diff --git a/components/popconfirm/index.tsx b/components/popconfirm/index.tsx index 1abd400bd..afa942ceb 100644 --- a/components/popconfirm/index.tsx +++ b/components/popconfirm/index.tsx @@ -20,6 +20,7 @@ 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(), @@ -36,6 +37,9 @@ export const popconfirmProps = () => ({ icon: PropTypes.any, okButtonProps: PropTypes.object, cancelButtonProps: PropTypes.object, + showCancel: { type: Boolean, default: true }, + onConfirm: Function as PropType<(e: MouseEvent) => void>, + onCancel: Function as PropType<(e: MouseEvent) => void>, }); export type PopconfirmProps = Partial>>; @@ -61,7 +65,7 @@ const Popconfirm = defineComponent({ disabled: false, }), slots: ['title', 'content', 'okText', 'icon', 'cancelText', 'cancelButton', 'okButton'], - emits: ['update:visible', 'confirm', 'cancel', 'visibleChange'], + emits: ['update:visible', 'visibleChange'], setup(props: PopconfirmProps, { slots, emit, expose }) { onMounted(() => { devWarning( @@ -71,7 +75,6 @@ const Popconfirm = defineComponent({ ); }); const tooltipRef = ref(); - expose({ getPopupDomNode: () => { return tooltipRef.value?.getPopupDomNode?.(); @@ -91,14 +94,17 @@ const Popconfirm = defineComponent({ emit('visibleChange', value, e); }; - const onConfirm = (e: MouseEvent) => { + const close = (e: MouseEvent) => { settingVisible(false, e); - emit('confirm', e); + }; + + const onConfirm = (e: MouseEvent) => { + return props.onConfirm?.(e); }; const onCancel = (e: MouseEvent) => { settingVisible(false, e); - emit('cancel', e); + props.onCancel?.(e); }; const onKeyDown = (e: KeyboardEvent) => { @@ -114,9 +120,10 @@ const Popconfirm = defineComponent({ } settingVisible(value); }; - const { prefixCls: prefixClsConfirm, configProvider } = useConfigInject('popconfirm', props); - const rootPrefixCls = computed(() => configProvider.getPrefixCls()); - const popoverPrefixCls = computed(() => configProvider.getPrefixCls('popover')); + 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 { @@ -127,6 +134,7 @@ const Popconfirm = defineComponent({ okText = slots.okText?.(), okType, icon = slots.icon?.(), + showCancel = true, } = props; const { cancelButton, okButton } = slots; const cancelProps: ButtonProps = { @@ -147,15 +155,26 @@ const Popconfirm = defineComponent({
{title}
- {cancelButton ? ( - cancelButton(cancelProps) - ) : ( - - )} + {showCancel ? ( + cancelButton ? ( + cancelButton(cancelProps) + ) : ( + + ) + ) : null} {okButton ? ( okButton(okProps) ) : ( - + + {okText || popconfirmLocale.value.okText} + )}
@@ -170,6 +189,8 @@ const Popconfirm = defineComponent({ 'cancelText', 'okText', 'onUpdate:visible', + 'onConfirm', + 'onCancel', ]); const overlayClassNames = classNames(prefixClsConfirm.value, overlayClassName); return ( diff --git a/components/popconfirm/index.zh-CN.md b/components/popconfirm/index.zh-CN.md index c70cd67e1..4802b440d 100644 --- a/components/popconfirm/index.zh-CN.md +++ b/components/popconfirm/index.zh-CN.md @@ -23,6 +23,7 @@ cover: https://gw.alipayobjects.com/zos/alicdn/fjMCD9xRq/Popconfirm.svg | okText | 确认按钮文字 | string\|slot | 确定 | | | okButton | 完全自定义确认按钮 | slot | - | 3.0 | | okType | 确认按钮类型 | string | primary | | +| showCancel | 是否显示取消按钮 | boolean | true | 3.0 | | title | 确认框的描述 | string\|slot | 无 | | | visible (v-model) | 是否显示 | boolean | - | | | icon | 自定义弹出气泡 Icon 图标 | vNode | <Icon type="exclamation-circle" /> | |