advent22/ui/src/components/MultiModal.vue

79 lines
1.9 KiB
Vue

<template>
<div v-if="state.show !== 'none'" class="modal is-active" @click="dismiss()">
<div class="modal-background" />
<div class="modal-content" style="max-height: 100vh; max-width: 95vw">
<template v-if="state.show === 'loading'">
<progress class="progress is-primary" max="100" />
</template>
<template v-else-if="state.show === 'image'">
<figure>
<figcaption class="tag is-primary">
{{ state.caption }}
</figcaption>
<div class="image is-square">
<img :src="state.src" alt="Kalender-Bild" />
</div>
</figure>
</template>
</div>
<button
v-if="state.show !== 'loading'"
class="modal-close is-large has-background-primary"
/>
</div>
</template>
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from "vue";
type ModalState =
| { show: "none" }
| { show: "loading" }
| { show: "image"; src: string; caption: string };
const state = ref<ModalState>({ show: "none" });
export type HMultiModal = {
show_image(src: string, caption: string): void;
show_loading(): void;
hide(): void;
};
const emit = defineEmits<{
(event: "handle", handle: HMultiModal): void;
}>();
function hide(): void {
state.value = { show: "none" };
}
function dismiss(): void {
if (state.value.show !== "loading") {
hide();
}
}
onMounted(() => {
emit("handle", {
show_image(src: string, caption: string = ""): void {
state.value = { show: "image", src: src, caption: caption };
},
show_loading(): void {
state.value = { show: "loading" };
},
hide,
});
const on_keydown = (e: KeyboardEvent) => {
if (e.key === "Escape") dismiss();
};
window.addEventListener("keydown", on_keydown);
onBeforeUnmount(() => {
window.removeEventListener("keydown", on_keydown);
});
});
</script>