2020-05-23 13:32:14 +02:00
|
|
|
<template>
|
2022-04-25 22:51:24 +02:00
|
|
|
<div class="dummy-wrapper">
|
|
|
|
<Teleport to="#window-content">
|
|
|
|
<div class="modal active" :class="modalSizeClass">
|
|
|
|
<a class="modal-overlay" @click="hideModal" />
|
2022-06-26 15:07:37 +02:00
|
|
|
<div ref="trapRef" class="modal-container">
|
2022-04-25 22:51:24 +02:00
|
|
|
<div v-if="hasHeader" class="modal-header pl-2">
|
|
|
|
<div class="modal-title h6">
|
|
|
|
<slot name="header" />
|
|
|
|
</div>
|
|
|
|
<a class="btn btn-clear float-right" @click="hideModal" />
|
2022-04-25 13:45:07 +02:00
|
|
|
</div>
|
2022-04-25 22:51:24 +02:00
|
|
|
<div v-if="hasDefault" class="modal-header">
|
|
|
|
<div class="modal-title h6">
|
|
|
|
<slot />
|
|
|
|
</div>
|
|
|
|
<a class="btn btn-clear float-right" @click="hideModal" />
|
2022-04-25 13:45:07 +02:00
|
|
|
</div>
|
2022-04-26 13:01:21 +02:00
|
|
|
<div v-if="hasBody" class="modal-body pb-0">
|
2022-04-25 22:51:24 +02:00
|
|
|
<a
|
|
|
|
v-if="!hasHeader && !hasDefault"
|
|
|
|
class="btn btn-clear float-right"
|
|
|
|
@click="hideModal"
|
|
|
|
/>
|
|
|
|
<div class="content">
|
|
|
|
<slot name="body" />
|
|
|
|
</div>
|
|
|
|
</div>
|
2022-04-26 13:01:21 +02:00
|
|
|
<div v-if="!hideFooter" class="modal-footer">
|
2022-04-25 22:51:24 +02:00
|
|
|
<button
|
|
|
|
class="btn btn-primary mr-2"
|
|
|
|
@click.stop="confirmModal"
|
|
|
|
>
|
|
|
|
{{ confirmText || $t('word.confirm') }}
|
|
|
|
</button>
|
|
|
|
<button
|
|
|
|
class="btn btn-link"
|
|
|
|
@click="hideModal"
|
|
|
|
>
|
|
|
|
{{ cancelText || $t('word.cancel') }}
|
|
|
|
</button>
|
2022-04-25 13:45:07 +02:00
|
|
|
</div>
|
2020-05-23 13:32:14 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
2022-04-25 22:51:24 +02:00
|
|
|
</Teleport>
|
|
|
|
</div>
|
2020-05-23 13:32:14 +02:00
|
|
|
</template>
|
|
|
|
|
2022-05-10 13:02:01 +02:00
|
|
|
<script setup lang="ts">
|
2022-06-26 15:07:37 +02:00
|
|
|
import { useFocusTrap } from '@/composables/useFocusTrap';
|
2022-05-10 13:02:01 +02:00
|
|
|
import { computed, onBeforeUnmount, PropType, useSlots } from 'vue';
|
2022-05-09 11:48:30 +02:00
|
|
|
|
2022-05-10 13:02:01 +02:00
|
|
|
const props = defineProps({
|
|
|
|
size: {
|
|
|
|
type: String as PropType<'small' | 'medium' | '400' | 'large'>,
|
|
|
|
validator: (prop: string) => ['small', 'medium', '400', 'large'].includes(prop),
|
|
|
|
default: 'small'
|
2020-07-30 19:12:29 +02:00
|
|
|
},
|
2022-05-10 13:02:01 +02:00
|
|
|
hideFooter: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
},
|
|
|
|
confirmText: String,
|
|
|
|
cancelText: String
|
|
|
|
});
|
|
|
|
const emit = defineEmits(['confirm', 'hide']);
|
|
|
|
const slots = useSlots();
|
2020-05-23 13:32:14 +02:00
|
|
|
|
2022-06-26 15:07:37 +02:00
|
|
|
const { trapRef } = useFocusTrap();
|
|
|
|
|
2022-05-10 13:02:01 +02:00
|
|
|
const hasHeader = computed(() => !!slots.header);
|
|
|
|
const hasBody = computed(() => !!slots.body);
|
|
|
|
const hasDefault = computed(() => !!slots.default);
|
|
|
|
const modalSizeClass = computed(() => {
|
|
|
|
if (props.size === 'small')
|
|
|
|
return 'modal-sm';
|
|
|
|
if (props.size === '400')
|
|
|
|
return 'modal-400';
|
|
|
|
else if (props.size === 'large')
|
|
|
|
return 'modal-lg';
|
|
|
|
else return '';
|
|
|
|
});
|
2022-05-09 11:48:30 +02:00
|
|
|
|
2022-05-10 13:02:01 +02:00
|
|
|
const confirmModal = () => {
|
|
|
|
emit('confirm');
|
|
|
|
hideModal();
|
|
|
|
};
|
2022-05-09 11:48:30 +02:00
|
|
|
|
2022-05-10 13:02:01 +02:00
|
|
|
const hideModal = () => {
|
|
|
|
emit('hide');
|
|
|
|
};
|
2022-05-09 11:48:30 +02:00
|
|
|
|
2022-05-10 13:02:01 +02:00
|
|
|
const onKey = (e: KeyboardEvent) => {
|
|
|
|
e.stopPropagation();
|
|
|
|
if (e.key === 'Escape')
|
|
|
|
hideModal();
|
|
|
|
};
|
2022-05-09 11:48:30 +02:00
|
|
|
|
2022-05-10 13:02:01 +02:00
|
|
|
window.addEventListener('keydown', onKey);
|
2022-05-09 11:48:30 +02:00
|
|
|
|
2022-05-10 13:02:01 +02:00
|
|
|
onBeforeUnmount(() => {
|
|
|
|
window.removeEventListener('keydown', onKey);
|
2022-05-09 11:48:30 +02:00
|
|
|
});
|
2020-05-23 13:32:14 +02:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
2020-11-13 12:39:40 +01:00
|
|
|
.modal-400 .modal-container {
|
|
|
|
max-width: 400px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.modal.modal-sm .modal-container {
|
|
|
|
padding: 0;
|
|
|
|
}
|
2020-05-23 13:32:14 +02:00
|
|
|
</style>
|