|
| 1 | +<script setup lang="ts"> |
| 2 | +import type { DialogContentEmits, DialogContentProps } from 'reka-ui'; |
| 3 | +import type { HTMLAttributes } from 'vue'; |
| 4 | +import { reactiveOmit } from '@vueuse/core'; |
| 5 | +import { DialogClose, DialogContent, DialogPortal, useForwardPropsEmits } from 'reka-ui'; |
| 6 | +import { cn } from '@/utils'; |
| 7 | +import DialogOverlay from './DialogOverlay.vue'; |
| 8 | +import Button from '@/components/ui/Button.vue'; |
| 9 | +
|
| 10 | +const props = defineProps< |
| 11 | + DialogContentProps & { class?: HTMLAttributes['class']; headerClass?: HTMLAttributes['class'] } |
| 12 | +>(); |
| 13 | +const emits = defineEmits<DialogContentEmits>(); |
| 14 | +
|
| 15 | +const delegatedProps = reactiveOmit(props, 'class', 'headerClass'); |
| 16 | +
|
| 17 | +const forwarded = useForwardPropsEmits(delegatedProps, emits); |
| 18 | +</script> |
| 19 | + |
| 20 | +<template> |
| 21 | + <DialogPortal> |
| 22 | + <DialogOverlay /> |
| 23 | + <DialogContent |
| 24 | + data-slot="dialog-content" |
| 25 | + v-bind="forwarded" |
| 26 | + :class=" |
| 27 | + cn( |
| 28 | + 'bg-background 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 fixed top-[50%] left-[50%] z-50 flex h-full w-full translate-x-[-50%] translate-y-[-50%] flex-col border shadow-lg duration-200 sm:h-160 sm:max-w-xl sm:rounded-2xl', |
| 29 | + props.class, |
| 30 | + ) |
| 31 | + " |
| 32 | + > |
| 33 | + <div class="relative flex flex-row items-center justify-start gap-2 p-2"> |
| 34 | + <DialogClose data-slot="dialog-close" as-child> |
| 35 | + <Button variant="ghost-default" size="icon-xs" class="absolute inset-2"> |
| 36 | + <Icon name="lucide:x" class="size-5" /> |
| 37 | + <span class="sr-only">{{ $t('ui.close') }}</span> |
| 38 | + </Button> |
| 39 | + </DialogClose> |
| 40 | + <div |
| 41 | + v-if="$slots.header" |
| 42 | + :class="cn('flex h-8 w-full items-center ps-10 text-lg font-medium', props.headerClass)" |
| 43 | + > |
| 44 | + <slot name="header" /> |
| 45 | + </div> |
| 46 | + </div> |
| 47 | + |
| 48 | + <div class="flex h-full w-full flex-col gap-4 px-6 pb-6"> |
| 49 | + <slot /> |
| 50 | + </div> |
| 51 | + </DialogContent> |
| 52 | + </DialogPortal> |
| 53 | +</template> |
0 commit comments