fix: add missing emits event

This commit is contained in:
zernonia 2023-08-23 18:43:51 +08:00
parent 81197d1e02
commit fd0eb2f5e8
4 changed files with 42 additions and 11 deletions

View File

@ -20,7 +20,7 @@ import { Label } from '@/registry/default/ui/label'
Edit Profile
</Button>
</DialogTrigger>
<DialogContent class="sm:max-w-[425px]">
<DialogContent class="sm:max-w-[425px]" @escape-key-down.prevent>
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>

View File

@ -2,14 +2,16 @@ import { defineComponent, h } from 'vue'
import {
AlertDialogAction as AlertDialogActionPrimitive, type AlertDialogActionProps,
AlertDialogCancel as AlertDialogCancelPrimitive, type AlertDialogCancelProps,
AlertDialogContent as AlertDialogContentPrimitive, type AlertDialogContentProps,
type AlertDialogContentEmits, AlertDialogContent as AlertDialogContentPrimitive, type AlertDialogContentProps,
AlertDialogDescription as AlertDialogDescriptionPrimitive, type AlertDialogDescriptionProps,
AlertDialogOverlay as AlertDialogOverlayPrimitive, type AlertDialogOverlayProps,
AlertDialogPortal as AlertDialogPortalPrimitive,
AlertDialogRoot, AlertDialogTitle as AlertDialogTitlePrimitive,
type AlertDialogTitleProps, AlertDialogTrigger as AlertDialogTriggerPrimitive,
} from 'radix-vue'
import { cn } from '@/utils'
import type { ParseEmits } from '@/utils'
import { cn, useEmitAsProps } from '@/utils'
import { buttonVariants } from '@/registry/default/ui/button'
export const AlertDialog = AlertDialogRoot
@ -25,16 +27,19 @@ export const AlertDialogOverlay = defineComponent<AlertDialogOverlayProps>(
}, { name: 'AlertDialogOverlay' },
)
export const AlertDialogContent = defineComponent<AlertDialogContentProps>(
(props, { attrs, slots }) => {
export const AlertDialogContent = defineComponent<AlertDialogContentProps, ParseEmits<AlertDialogContentEmits>>(
(props, { emit, attrs, slots }) => {
const emitsAsProps = useEmitAsProps(emit)
return () => h(AlertDialogPortal, () => [
h(AlertDialogOverlay),
h(AlertDialogContentPrimitive, {
class: cn('fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full', attrs.class ?? ''),
...props,
...emitsAsProps,
}, slots),
])
}, { name: 'AlertDialogContent' },
}, { name: 'AlertDialogContent', emits: AlertDialogContentPrimitive.emits },
)
export const AlertDialogHeader = defineComponent(

View File

@ -1,6 +1,6 @@
import { defineComponent, h } from 'vue'
import {
DialogClose, DialogContent as DialogContentPrimitive, type DialogContentProps,
DialogClose, type DialogContentEmits, DialogContent as DialogContentPrimitive, type DialogContentProps,
DialogDescription as DialogDescriptionPrimitive, type DialogDescriptionProps,
DialogOverlay as DialogOverlayPrimitive, type DialogOverlayProps,
DialogPortal as DialogPortalPrimitive, DialogRoot,
@ -8,7 +8,8 @@ import {
DialogTrigger as DialogTriggerPrimitive,
} from 'radix-vue'
import { X } from 'lucide-vue-next'
import { cn } from '@/utils'
import type { ParseEmits } from '@/utils'
import { cn, useEmitAsProps } from '@/utils'
export const Dialog = DialogRoot
export const DialogTrigger = DialogTriggerPrimitive
@ -23,13 +24,16 @@ export const DialogOverlay = defineComponent<DialogOverlayProps>(
}, { name: 'DialogOverlay' },
)
export const DialogContent = defineComponent<DialogContentProps>(
(props, { attrs, slots }) => {
export const DialogContent = defineComponent<DialogContentProps, ParseEmits<DialogContentEmits>>(
(props, { emit, attrs, slots }) => {
const emitsAsProps = useEmitAsProps(emit)
return () => h(DialogPortal, () => [
h(DialogOverlay),
h(DialogContentPrimitive, {
class: cn('fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full', attrs.class ?? ''),
...props,
...emitsAsProps,
}, () => [
slots.default(),
h(DialogClose,
@ -38,7 +42,7 @@ export const DialogContent = defineComponent<DialogContentProps>(
),
]),
])
}, { name: 'DialogContent' },
}, { name: 'DialogContent', emits: DialogContentPrimitive.emits },
)
export const DialogHeader = defineComponent(

View File

@ -1,6 +1,7 @@
import type { ClassValue } from 'clsx'
import { clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
import { camelize, getCurrentInstance, toHandlerKey } from 'vue'
export type ParseEmits<T extends Record<string, any>> = {
[K in keyof T]: (...args: T[K]) => void;
@ -9,3 +10,24 @@ export type ParseEmits<T extends Record<string, any>> = {
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
// Vue doesn't have emits forwarding, in order to bind the emits we have to convert events into `onXXX` handlers
// issue: https://github.com/vuejs/core/issues/5917
export function useEmitAsProps<Name extends string>(
emit: (name: Name, ...args: any[]) => void,
) {
const vm = getCurrentInstance()
const events = vm?.type.emits as Name[]
const result: Record<string, any> = {}
if (!events?.length) {
console.warn(
`No emitted event found. Please check component: ${vm?.type.__name}`,
)
}
events?.forEach((ev) => {
result[toHandlerKey(camelize(ev))] = (...arg: any) => emit(ev, ...arg)
})
return result
}