Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add opened and closed events for dialog #4775

Merged
merged 1 commit into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions docs/src/components/common-ui/vben-modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,14 @@ const [Modal, modalApi] = useVbenModal({

以下事件,只有在 `useVbenModal({onCancel:()=>{}})` 中传入才会生效。

| 事件名 | 描述 | 类型 |
| --- | --- | --- |
| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` |
| onCancel | 点击取消按钮触发 | `()=>void` |
| onConfirm | 点击确认按钮触发 | `()=>void` |
| onOpenChange | 关闭或者打开弹窗时触发 | `(isOpen:boolean)=>void` |
| 事件名 | 描述 | 类型 | 版本号 |
| --- | --- | --- | --- |
| onBeforeClose | 关闭前触发,返回 `false`则禁止关闭 | `()=>boolean` | |
| onCancel | 点击取消按钮触发 | `()=>void` | |
| onClosed | 关闭动画播放完毕时触发 | `()=>void` | >5.4.3 |
| onConfirm | 点击确认按钮触发 | `()=>void` | |
| onOpenChange | 关闭或者打开弹窗时触发 | `(isOpen:boolean)=>void` | |
| onOpened | 打开动画播放完毕时触发 | `()=>void` | >5.4.3 |

### Slots

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,19 @@ describe('modalApi', () => {
expect(modalApi.store.state.title).toBe('Batch Title');
expect(modalApi.store.state.confirmText).toBe('Batch Confirm');
});

it('should call onClosed callback when provided', () => {
const onClosed = vi.fn();
const modalApiWithHook = new ModalApi({ onClosed });
modalApiWithHook.onClosed();
expect(onClosed).toHaveBeenCalled();
});
anncwb marked this conversation as resolved.
Show resolved Hide resolved

it('should call onOpened callback when provided', () => {
const onOpened = vi.fn();
const modalApiWithHook = new ModalApi({ onOpened });
modalApiWithHook.open();
modalApiWithHook.onOpened();
expect(onOpened).toHaveBeenCalled();
});
anncwb marked this conversation as resolved.
Show resolved Hide resolved
});
29 changes: 28 additions & 1 deletion packages/@core/ui-kit/popup-ui/src/modal/modal-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import { bindMethods, isFunction } from '@vben-core/shared/utils';
export class ModalApi {
private api: Pick<
ModalApiOptions,
'onBeforeClose' | 'onCancel' | 'onConfirm' | 'onOpenChange'
| 'onBeforeClose'
| 'onCancel'
| 'onClosed'
| 'onConfirm'
| 'onOpenChange'
| 'onOpened'
>;
// private prevState!: ModalState;
private state!: ModalState;
Expand All @@ -23,8 +28,10 @@ export class ModalApi {
connectedComponent: _,
onBeforeClose,
onCancel,
onClosed,
onConfirm,
onOpenChange,
onOpened,
...storeState
} = options;

Expand Down Expand Up @@ -77,8 +84,10 @@ export class ModalApi {
this.api = {
onBeforeClose,
onCancel,
onClosed,
onConfirm,
onOpenChange,
onOpened,
};
bindMethods(this);
}
Expand Down Expand Up @@ -115,13 +124,31 @@ export class ModalApi {
}
}

/**
* 弹窗关闭动画播放完毕后的回调
*/
onClosed() {
if (!this.state.isOpen) {
this.api.onClosed?.();
}
}

/**
* 确认操作
*/
onConfirm() {
this.api.onConfirm?.();
}

/**
* 弹窗打开动画播放完毕后的回调
*/
onOpened() {
if (this.state.isOpen) {
this.api.onOpened?.();
}
}

open() {
this.store.setState((prev) => ({ ...prev, isOpen: true }));
}
Expand Down
10 changes: 10 additions & 0 deletions packages/@core/ui-kit/popup-ui/src/modal/modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ export interface ModalApiOptions extends ModalState {
* 点击取消按钮的回调
*/
onCancel?: () => void;
/**
* 弹窗关闭动画结束的回调
* @returns
*/
onClosed?: () => void;
/**
* 点击确定按钮的回调
*/
Expand All @@ -149,4 +154,9 @@ export interface ModalApiOptions extends ModalState {
* @returns
*/
onOpenChange?: (isOpen: boolean) => void;
/**
* 弹窗打开动画结束的回调
* @returns
*/
onOpened?: () => void;
}
2 changes: 2 additions & 0 deletions packages/@core/ui-kit/popup-ui/src/modal/modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,12 @@ function handleFocusOutside(e: Event) {
:show-close="closable"
close-class="top-3"
@close-auto-focus="handleFocusOutside"
@closed="() => modalApi?.onClosed()"
@escape-key-down="escapeKeyDown"
@focus-outside="handleFocusOutside"
@interact-outside="interactOutside"
@open-auto-focus="handerOpenAutoFocus"
@opened="() => modalApi?.onOpened()"
@pointer-down-outside="pointerDownOutside"
>
<DialogHeader
Expand Down
13 changes: 11 additions & 2 deletions packages/@core/ui-kit/shadcn-ui/src/ui/dialog/DialogContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ const props = withDefaults(
>(),
{ showClose: true },
);
const emits = defineEmits<{ close: [] } & DialogContentEmits>();
const emits = defineEmits<
{ close: []; closed: []; opened: [] } & DialogContentEmits
>();

const delegatedProps = computed(() => {
const {
Expand All @@ -44,7 +46,13 @@ const delegatedProps = computed(() => {
const forwarded = useForwardPropsEmits(delegatedProps, emits);

const contentRef = ref<InstanceType<typeof DialogContent> | null>(null);

function onAnimationEnd() {
if (props.open) {
emits('opened');
} else {
emits('closed');
}
}
anncwb marked this conversation as resolved.
Show resolved Hide resolved
defineExpose({
getContentRef: () => contentRef.value,
});
Expand All @@ -57,6 +65,7 @@ defineExpose({
</Transition>
<DialogContent
ref="contentRef"
@animationend="onAnimationEnd"
v-bind="forwarded"
:class="
cn(
Expand Down
6 changes: 6 additions & 0 deletions playground/src/views/examples/modal/base-demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,16 @@ const [Modal, modalApi] = useVbenModal({
onCancel() {
modalApi.close();
},
onClosed() {
message.info('onClosed:关闭动画结束');
},
onConfirm() {
message.info('onConfirm');
// modalApi.close();
},
onOpened() {
message.info('onOpened:打开动画结束');
},
});
</script>
<template>
Expand Down