2023-01-25 20:03:22 +00:00
|
|
|
<template>
|
|
|
|
<TransitionRoot appear :show="isOpen" as="template">
|
|
|
|
<Dialog as="div" @close="closeModal" class="relative z-10">
|
|
|
|
<TransitionChild
|
|
|
|
as="template"
|
|
|
|
enter="duration-300 ease-out"
|
|
|
|
enter-from="opacity-0"
|
|
|
|
enter-to="opacity-100"
|
|
|
|
leave="duration-200 ease-in"
|
|
|
|
leave-from="opacity-100"
|
|
|
|
leave-to="opacity-0"
|
|
|
|
>
|
|
|
|
<div class="fixed inset-0 bg-black bg-opacity-25" />
|
|
|
|
</TransitionChild>
|
|
|
|
|
|
|
|
<div class="fixed inset-0 overflow-y-auto">
|
|
|
|
<div
|
|
|
|
class="flex min-h-full items-center justify-center p-4 text-center"
|
|
|
|
>
|
|
|
|
<TransitionChild
|
|
|
|
as="template"
|
|
|
|
enter="duration-300 ease-out"
|
|
|
|
enter-from="opacity-0 scale-95"
|
|
|
|
enter-to="opacity-100 scale-100"
|
|
|
|
leave="duration-200 ease-in"
|
|
|
|
leave-from="opacity-100 scale-100"
|
|
|
|
leave-to="opacity-0 scale-95"
|
|
|
|
>
|
|
|
|
<DialogPanel
|
|
|
|
:class="`w-full ${maxWidth} transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all`"
|
|
|
|
>
|
|
|
|
<DialogTitle
|
|
|
|
as="h3"
|
|
|
|
class="text-lg font-bold leading-6 text-gray-900"
|
|
|
|
>
|
2023-01-27 16:27:14 +00:00
|
|
|
<div class="mb-4 flex items-center justify-between">
|
2023-01-25 20:03:22 +00:00
|
|
|
<slot name="title" />
|
|
|
|
<button v-if="closeButton" @click="closeModal">
|
|
|
|
<XMarkIcon class="h-6 w-6" />
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</DialogTitle>
|
|
|
|
<slot :closeModal="closeModal" />
|
|
|
|
</DialogPanel>
|
|
|
|
</TransitionChild>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Dialog>
|
|
|
|
</TransitionRoot>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
import { computed, ref } from 'vue';
|
|
|
|
import {
|
|
|
|
TransitionRoot,
|
|
|
|
TransitionChild,
|
|
|
|
Dialog,
|
|
|
|
DialogPanel,
|
|
|
|
DialogTitle,
|
|
|
|
} from '@headlessui/vue';
|
|
|
|
import { XMarkIcon } from '@heroicons/vue/24/outline';
|
|
|
|
|
|
|
|
const isOpen = ref(false);
|
|
|
|
|
|
|
|
const props = withDefaults(
|
|
|
|
defineProps<{
|
|
|
|
closeButton?: boolean;
|
|
|
|
size?: 'sm' | 'md' | 'lg' | 'xl';
|
|
|
|
}>(),
|
|
|
|
{
|
|
|
|
closeButton: true,
|
|
|
|
size: 'sm',
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
function closeModal() {
|
|
|
|
isOpen.value = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function openModal() {
|
|
|
|
isOpen.value = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const maxWidth = computed(() => {
|
|
|
|
if (props.size === 'sm') return 'max-w-md';
|
|
|
|
if (props.size === 'md') return 'max-w-xl';
|
|
|
|
if (props.size === 'lg') return 'max-w-2xl';
|
|
|
|
return 'max-w-4xl';
|
|
|
|
});
|
|
|
|
|
|
|
|
defineExpose({
|
|
|
|
openModal,
|
|
|
|
closeModal,
|
|
|
|
isOpen,
|
|
|
|
});
|
|
|
|
</script>
|