PronounsPage/components/DialogueBox.vue

139 lines
4.9 KiB
Vue

<template>
<div :class="['modal', shown ? 'd-block-force' : '', shownFull ? 'modal-shown' : '']" @click="hideClick">
<div :class="['modal-dialog', 'modal-dialog-centered', 'modal-dialog-scrollable', size ? `modal-${size}` : '']" role="document">
<div class="modal-content shadow">
<div v-if="header" class="modal-header">
<p class="h5 modal-title">
<Icon v-if="icon" :v="icon" />
{{ header }}
</p>
</div>
<div v-if="message" class="modal-body">
<p :class="[margin ? 'py-5 text-center' : '']" v-html="message"></p>
</div>
<div v-if="value !== undefined" class="modal-body">
<ListInput v-if="Array.isArray(value)" v-slot="s" v-model="value">
<textarea v-model="s.val" class="form-control" rows="5" @keyup="s.update(s.val)" @update="s.update(s.val)"></textarea>
</ListInput>
<textarea v-else v-model="value" class="form-control" rows="5"></textarea>
</div>
<div v-if="choice" class="modal-footer">
<button class="btn btn-outline-dark" @click="cancel">
{{ $t('confirm.no') }}
</button>
<button :class="`btn btn-${color || 'primary'}`" @click="confirm">
{{ $t('confirm.yes') }}
</button>
</div>
<div v-else-if="value !== undefined" class="modal-footer">
<button class="btn btn-outline-dark" @click="cancel">
{{ $t('confirm.dismiss') }}
</button>
<button :class="`btn btn-${color || 'primary'}`" @click="confirm">
{{ $t('confirm.save') }}
</button>
</div>
<div v-else class="modal-footer">
<button :class="`btn btn-${color || 'primary'}`" @click="confirm">
{{ $t('confirm.ok') }}
</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
shown: false,
shownFull: false,
choice: false,
icon: undefined,
header: undefined,
message: undefined,
margin: true,
color: null,
value: undefined,
size: undefined,
resolve: undefined,
reject: undefined,
};
},
mounted() {
if (process.client) {
window.addEventListener('keydown', (e) => {
if (!this.shown) {
return;
}
if (e.keyCode === 27) {
e.stopPropagation();
e.preventDefault();
this.cancel();
} else if (e.keyCode === 13) {
e.stopPropagation();
e.preventDefault();
this.confirm();
}
});
}
},
methods: {
show(choice, message, color, value, size, resolve, reject) {
this.choice = choice;
if (typeof message === 'string') {
message = { message };
}
this.icon = message.icon || (choice ? 'map-marker-question' : null);
this.header = message.header;
this.message = message.message || (choice ? this.$t('confirm.header') : null);
this.margin = message.margin ?? true;
this.size = message.size ?? size;
this.color = color;
this.value = value;
this.shown = true;
this.resolve = resolve;
this.reject = reject;
requestAnimationFrame(() => this.shownFull = true);
},
confirm() {
const resolve = this.resolve;
this.hide();
if (resolve) {
resolve(this.value);
}
},
cancel() {
const reject = this.reject;
this.hide();
if (reject) {
reject();
}
},
hide() {
this.shownFull = false;
setTimeout(() => {
this.shown = false;
this.choice = false;
this.icon = undefined;
this.header = undefined;
this.message = undefined;
this.margin = true;
this.color = null;
this.value = undefined;
this.size = undefined;
this.resolve = undefined;
this.reject = undefined;
}, 500);
},
hideClick(event) {
if (event.target === this.$el) {
this.cancel();
}
},
},
};
</script>