133 lines
3.1 KiB
Vue
133 lines
3.1 KiB
Vue
<template>
|
|
<div v-if="visible" class="modal is-active">
|
|
<div class="modal-background" @click="cancel" />
|
|
<div class="modal-card">
|
|
<header class="modal-card-head">
|
|
<p class="modal-card-title">{{ title }}</p>
|
|
<button class="delete" aria-label="close" @click="cancel" />
|
|
</header>
|
|
|
|
<section class="modal-card-body">
|
|
<p class="mb-3 title is-5" v-if="!html_message">{{ message }}</p>
|
|
<div
|
|
class="content"
|
|
v-if="html_message"
|
|
v-html="html_message"
|
|
style="max-height: 40vh; overflow: auto"
|
|
/>
|
|
|
|
<div v-if="options?.length">
|
|
<hr class="" />
|
|
<label
|
|
v-for="opt in options"
|
|
:key="opt.key"
|
|
class="checkbox is-block mb-2 is-unselectable"
|
|
>
|
|
<input type="checkbox" v-model="selected[opt.key]" class="mr-2" />
|
|
{{ opt.label }}
|
|
</label>
|
|
</div>
|
|
</section>
|
|
|
|
<footer class="modal-card-foot p-5">
|
|
<div class="field is-grouped" style="width: 100%">
|
|
<div class="control is-expanded">
|
|
<button
|
|
ref="confirmBtn"
|
|
class="button is-fullwidth"
|
|
:class="confirm_button_color"
|
|
@click="handleConfirm"
|
|
>
|
|
{{ confirm_button_label }}
|
|
</button>
|
|
</div>
|
|
<div class="control is-expanded">
|
|
<button
|
|
class="button is-success is-fullwidth"
|
|
:class="cancel_button_color"
|
|
@click="cancel"
|
|
>
|
|
{{ cancel_button_label }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { disableOpacity, enableOpacity } from '~/utils';
|
|
|
|
const props = defineProps({
|
|
visible: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
title: {
|
|
type: String,
|
|
default: 'Confirm',
|
|
},
|
|
message: {
|
|
type: String,
|
|
default: 'Are you sure?',
|
|
},
|
|
html_message: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
options: {
|
|
type: Array as () => Array<{ key: string; label: string; checked?: boolean }>,
|
|
default: () => [],
|
|
},
|
|
confirm_button_label: {
|
|
type: String,
|
|
default: 'Confirm',
|
|
},
|
|
cancel_button_label: {
|
|
type: String,
|
|
default: 'Cancel',
|
|
},
|
|
confirm_button_color: {
|
|
type: String,
|
|
default: 'is-danger',
|
|
},
|
|
cancel_button_color: {
|
|
type: String,
|
|
default: 'is-success',
|
|
},
|
|
});
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'confirm', options: Record<string, boolean>): void;
|
|
(e: 'cancel'): void;
|
|
}>();
|
|
|
|
const confirmBtn = ref<HTMLButtonElement | null>(null);
|
|
const selected = reactive<Record<string, boolean>>({});
|
|
|
|
watch(
|
|
() => props.visible,
|
|
async (visible) => {
|
|
if (!visible) {
|
|
return;
|
|
}
|
|
|
|
if (props.options) {
|
|
for (const opt of props.options) {
|
|
selected[opt.key] ??= false;
|
|
}
|
|
}
|
|
|
|
await nextTick();
|
|
confirmBtn.value?.focus();
|
|
},
|
|
{ immediate: true },
|
|
);
|
|
|
|
const handleConfirm = () => emit('confirm', { ...selected });
|
|
const cancel = () => emit('cancel');
|
|
|
|
onMounted(() => disableOpacity());
|
|
onBeforeUnmount(() => enableOpacity());
|
|
</script>
|