mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-15 02:59:28 +00:00
194 lines
5.1 KiB
JavaScript
194 lines
5.1 KiB
JavaScript
//import Phrasen from '../../plugin/Phrasen.js';
|
|
|
|
export default {
|
|
name: 'BootstrapModal',
|
|
data: () => ({
|
|
modal: null,
|
|
fullscreen: false,
|
|
expandBtnHovered: false,
|
|
expandBtnFocused: false,
|
|
}),
|
|
props: {
|
|
backdrop: {
|
|
type: [Boolean,String],
|
|
default: true,
|
|
validator(value) {
|
|
return ['static', true, false].includes(value);
|
|
}
|
|
},
|
|
focus: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
keyboard: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
noCloseBtn: Boolean,
|
|
dialogClass: [String,Array,Object],
|
|
headerClass: {
|
|
type: [String,Array,Object],
|
|
default: ''
|
|
},
|
|
bodyClass: {
|
|
type: [String,Array,Object],
|
|
default: 'px-4 py-5'
|
|
},
|
|
footerClass: {
|
|
type: [String,Array,Object],
|
|
default: ''
|
|
},
|
|
allowFullscreenExpand: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
},
|
|
emits: [
|
|
"hideBsModal",
|
|
"hiddenBsModal",
|
|
"hidePreventedBsModal",
|
|
"showBsModal",
|
|
"shownBsModal",
|
|
"toggleFullscreen"
|
|
],
|
|
methods: {
|
|
dispose() {
|
|
return this.modal.dispose();
|
|
},
|
|
handleUpdate() {
|
|
return this.modal.handleUpdate();
|
|
},
|
|
hide() {
|
|
return this.modal.hide();
|
|
},
|
|
show(relatedTarget) {
|
|
return this.modal.show(relatedTarget);
|
|
},
|
|
toggle() {
|
|
return this.modal.toggle();
|
|
},
|
|
toggleFullscreen() {
|
|
this.fullscreen = !this.fullscreen
|
|
this.$emit('toggleFullscreen')
|
|
}
|
|
},
|
|
computed: {
|
|
getExpandButtonStyles() {
|
|
const hovered = this.expandBtnHovered;
|
|
const focused = this.expandBtnFocused;
|
|
return `display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 1em;
|
|
height: 1em;
|
|
padding: 0;
|
|
border: 0;
|
|
background: transparent;
|
|
font-size: 1em;
|
|
opacity: 0.5;
|
|
color: inherit;
|
|
cursor: pointer;
|
|
line-height: 1;
|
|
transition: opacity 0.15s ease;
|
|
opacity: ${focused ? '1' : hovered ? '0.75' : '0.5'};
|
|
outline: ${focused ? '1px solid currentColor' : 'none'};
|
|
outline-offset: 2px;`
|
|
}
|
|
},
|
|
mounted() {
|
|
if (this.$refs.modal)
|
|
this.modal = new bootstrap.Modal(this.$refs.modal, {
|
|
backdrop: this.backdrop,
|
|
focus: this.focus,
|
|
keyboard: this.keyboard
|
|
});
|
|
},
|
|
popup(body, options, title, footer) {
|
|
const BsModal = this,
|
|
slots = {};
|
|
if (body !== undefined)
|
|
slots.default = () => body;
|
|
if (title !== undefined)
|
|
slots.title = () => title;
|
|
if (footer !== undefined)
|
|
slots.footer = () => footer;
|
|
|
|
// little hack to check whether primevue is included in the app or not
|
|
let includedPrimevue = false;
|
|
if(typeof primevue !== 'undefined'){
|
|
includedPrimevue = true;
|
|
}
|
|
|
|
return new Promise((resolve,reject) => {
|
|
const instance = Vue.createApp({
|
|
name: 'ModalTmpApp',
|
|
setup() {
|
|
return () => Vue.h(BsModal, {...{
|
|
class: 'fade'
|
|
},...options, ...{
|
|
ref: 'modal',
|
|
'onHidden.bs.modal': instance.unmount
|
|
}}, slots);
|
|
},
|
|
mounted() {
|
|
this.$refs.modal.show();
|
|
|
|
},
|
|
beforeUnmount() {
|
|
if (this.$refs.modal)
|
|
this.$refs.modal.result !== false ? resolve(this.$refs.modal.result) : reject();
|
|
},
|
|
unmounted() {
|
|
wrapper.parentElement.removeChild(wrapper);
|
|
}
|
|
});
|
|
const wrapper = document.createElement("div");
|
|
|
|
// if(primevue) --> won't work because primevue is not defined in this scope and promise would be rejected
|
|
if (includedPrimevue){
|
|
instance.use(primevue.config.default, {zIndex: {overlay: 9999}})
|
|
}
|
|
|
|
//instance.use(Phrasen); // TODO(chris): find a more dynamic way
|
|
import('../../plugins/Phrasen.js').then((Phrasen) => {
|
|
instance.use(Phrasen.default);
|
|
instance.mount(wrapper);
|
|
document.body.appendChild(wrapper);
|
|
});
|
|
});
|
|
},
|
|
template: `<div ref="modal" class="bootstrap-modal modal" tabindex="-1" @[\`hide.bs.modal\`]="$emit('hideBsModal')" @[\`hidden.bs.modal\`]="$emit('hiddenBsModal')" @[\`hidePrevented.bs.modal\`]="$emit('hidePreventedBsModal')" @[\`show.bs.modal\`]="$emit('showBsModal')" @[\`shown.bs.modal\`]="$emit('shownBsModal')">
|
|
<div class="modal-dialog" :class="fullscreen ? 'modal-fullscreen' : dialogClass">
|
|
<div class="modal-content">
|
|
<div v-if="$slots.title" class="modal-header" :class="headerClass">
|
|
<h5 class="modal-title"><slot name="title"/></h5>
|
|
<div class="d-flex align-items-center ms-auto gap-2">
|
|
<button
|
|
type="button"
|
|
:style="getExpandButtonStyles"
|
|
v-if="allowFullscreenExpand"
|
|
@click="toggleFullscreen"
|
|
@mouseenter="expandBtnHovered = true"
|
|
@mouseleave="expandBtnHovered = false"
|
|
@focusin="expandBtnFocused = true"
|
|
@focusout="expandBtnFocused = false"
|
|
:aria-label="fullscreen ? 'Exit Fullscreen' : 'Enter Fullscreen'"
|
|
>
|
|
<i v-if="!fullscreen" class="fa-solid fa-expand"></i>
|
|
<i v-else class="fa-solid fa-compress"></i>
|
|
</button>
|
|
<button v-if="!noCloseBtn" type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<slot name="modal-header-content"></slot>
|
|
</div>
|
|
<div class="modal-body" :class="bodyClass">
|
|
<slot></slot>
|
|
</div>
|
|
<div v-if="$slots.footer" class="modal-footer" :class="footerClass">
|
|
<slot name="footer"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>`
|
|
}
|