1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
<script setup lang="ts">
import { useTheme } from './c-modal.theme';
defineOptions({
inheritAttrs: false,
});
const props = withDefaults(defineProps<{ open?: boolean; centered?: boolean }>(), {
open: false,
centered: true,
});
const emit = defineEmits(['update:open']);
const isOpen = useVModel(props, 'open', emit, { passive: true });
const { centered } = toRefs(props);
function close() {
isOpen.value = false;
}
function open() {
isOpen.value = true;
}
function toggle() {
isOpen.value = !isOpen.value;
}
defineExpose({
close,
open,
toggle,
isOpen,
});
const theme = useTheme();
const modal = ref();
onClickOutside(modal, () => {
if (isOpen.value) {
close();
}
});
</script>
<template>
<transition>
<div v-if="isOpen" class="c-modal--overlay" fixed left-0 top-0 z-10 h-full w-full flex justify-center px-2 :class="{ 'items-center': centered }">
<div ref="modal" class="c-modal--container" v-bind="$attrs" max-w-xl w-full flex-grow rounded-md pa-24px>
<slot />
</div>
</div>
</transition>
</template>
<style scoped lang="less">
.c-modal--overlay {
background-color: rgba(0, 0, 0, 0.5);
}
.c-modal--container {
background-color: v-bind('theme.background');
}
.v-enter-active,
.v-leave-active {
transition: opacity 0.3s ease-in-out;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
</style>
|