@shopware-ag/meteor-component-library
Version:
The meteor component library is a Vue component library developed by Shopware. It is based on the [Meteor Design System](https://shopware.design/).
264 lines (263 loc) • 9.3 kB
JavaScript
import '../mt-modal.css';
import { defineComponent, watch, onUnmounted, ref, nextTick, onMounted, openBlock, createBlock, Transition, withCtx, Teleport, unref, createElementBlock, normalizeClass, renderSlot, createElementVNode, createTextVNode, toDisplayString, createCommentVNode, createVNode } from "vue";
import { u as useModalContext } from "../useModalContext-3b7570bc.mjs";
import { _ as _sfc_main$2 } from "../mt-icon.vue_vue_type_style_index_0_lang-2cc5f73e.mjs";
import { _ as _sfc_main$1 } from "../mt-modal-close.vue_vue_type_script_setup_true_lang-15d65d8b.mjs";
import MtText from "./MtText.js";
import { c as createId } from "../id-1e5b8276.mjs";
import { c as createFocusTrap } from "../focus-trap.esm-3b050c4a.mjs";
import { _ as _export_sfc } from "../_plugin-vue_export-helper-cc2b3d55.mjs";
const _hoisted_1 = {
key: 0,
class: "mt-modal__header"
};
const _hoisted_2 = { class: "mt-modal__header-content" };
const _hoisted_3 = { class: "mt-modal__header-content-title" };
const _hoisted_4 = {
key: 0,
class: "mt-modal__subtitle"
};
const _hoisted_5 = {
key: 0,
class: "mt-modal__scroll-shadow mt-modal__scroll-shadow--top"
};
const _hoisted_6 = {
key: 0,
class: "mt-modal__scroll-shadow mt-modal__scroll-shadow--bottom"
};
const _hoisted_7 = { class: "mt-modal__footer" };
const thresholdInPx = 24;
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "mt-modal",
props: {
title: {
type: String,
required: false,
default: void 0
},
subtitle: {
type: String,
required: false,
default: void 0
},
width: {
type: String,
required: false,
default: "m"
},
inset: {
type: Boolean,
required: false,
default: false
},
hideHeader: {
type: Boolean,
required: false,
default: false
}
},
setup(__props) {
const id = `mt-modal--${createId()}`;
const { isOpen, setIsOpen, closable } = useModalContext("mt-modal");
let closeOnEscapeEventListener = void 0;
watch(
isOpen,
(value) => {
if (value) {
closeOnEscapeEventListener = (event) => {
if (event.key === "Escape" && closable.value)
setIsOpen(false);
};
document.addEventListener("keydown", closeOnEscapeEventListener);
} else {
if (closeOnEscapeEventListener) {
document.removeEventListener("keydown", closeOnEscapeEventListener);
}
}
},
{ immediate: true }
);
onUnmounted(() => {
if (closeOnEscapeEventListener) {
document.removeEventListener("keydown", closeOnEscapeEventListener);
}
});
const modalRef = ref(null);
let trap;
watch(
isOpen,
async () => {
const isModalOpen = !!isOpen.value;
if (isModalOpen)
await nextTick();
if (!modalRef.value)
return;
if (isModalOpen) {
trap = createFocusTrap(modalRef.value, {
tabbableOptions: { displayCheck: "none" },
allowOutsideClick: true,
onPause: () => {
console.warn(
"[MtModal] It is not recommended to stack multiple modals on top of each other."
);
},
onUnpause: () => {
}
});
trap.activate();
return;
}
if (trap)
trap.deactivate();
},
{ immediate: true }
);
onUnmounted(() => {
if (trap)
trap.deactivate();
});
const modalContentRef = ref(null);
const showShadows = ref("none");
onMounted(async () => {
const isModalClosed = !isOpen.value;
if (isModalClosed || !modalContentRef.value)
return;
await nextTick();
const hasScrollableContent = modalContentRef.value.scrollHeight > modalContentRef.value.clientHeight;
if (hasScrollableContent)
showShadows.value = "top";
});
function handleScroll(event) {
if (!(event.target instanceof Element))
return;
const hasScrollableContent = event.target.scrollHeight > event.target.clientHeight;
if (!hasScrollableContent) {
showShadows.value = "none";
return;
}
const reachedTop = event.target.scrollTop < thresholdInPx;
if (reachedTop) {
showShadows.value = "top";
return;
}
const reachedBottom = Math.abs(event.target.scrollHeight - event.target.scrollTop - event.target.clientHeight) < 1;
if (reachedBottom) {
showShadows.value = "bottom";
return;
}
showShadows.value = "middle";
}
watch(
isOpen,
async () => {
const isModalClosed = !isOpen.value;
if (isModalClosed) {
showShadows.value = "none";
if (!modalContentRef.value)
return;
modalContentRef.value.removeEventListener("scroll", handleScroll);
return;
}
await nextTick();
if (!modalContentRef.value)
return;
modalContentRef.value.addEventListener("scroll", handleScroll);
},
{ immediate: true }
);
onUnmounted(() => {
if (modalContentRef.value)
modalContentRef.value.removeEventListener("scroll", handleScroll);
});
return (_ctx, _cache) => {
return openBlock(), createBlock(Transition, { name: "modal" }, {
default: withCtx(() => [
(openBlock(), createBlock(Teleport, { to: "body" }, [
unref(isOpen) ? (openBlock(), createElementBlock("div", {
key: 0,
ref_key: "modalRef",
ref: modalRef,
class: normalizeClass(["mt-modal", `mt-modal--width-${__props.width}`]),
role: "dialog",
"aria-modal": "true",
"aria-labelledby": id
}, [
!__props.hideHeader ? (openBlock(), createElementBlock("div", _hoisted_1, [
renderSlot(_ctx.$slots, "header-left", {}, void 0, true),
createElementVNode("div", _hoisted_2, [
createElementVNode("div", _hoisted_3, [
__props.title ? (openBlock(), createBlock(MtText, {
key: 0,
as: "h2",
class: "mt-modal__title",
size: "m",
weight: "semibold",
id
}, {
default: withCtx(() => [
createTextVNode(toDisplayString(__props.title), 1)
]),
_: 1
})) : createCommentVNode("", true),
renderSlot(_ctx.$slots, "title-after", {}, void 0, true)
]),
__props.subtitle ? (openBlock(), createElementBlock("span", _hoisted_4, toDisplayString(__props.subtitle), 1)) : createCommentVNode("", true)
]),
renderSlot(_ctx.$slots, "header-right", {}, void 0, true),
unref(closable) ? (openBlock(), createBlock(_sfc_main$1, {
key: 0,
class: "mt-modal__close-button",
"aria-label": "Close"
}, {
default: withCtx(() => [
createVNode(_sfc_main$2, {
"aria-hidden": "",
name: "regular-times-xs"
})
]),
_: 1
})) : createCommentVNode("", true)
])) : createCommentVNode("", true),
createElementVNode("div", {
class: "mt-modal__content",
ref_key: "modalContentRef",
ref: modalContentRef
}, [
createVNode(Transition, { name: "shadow-fade" }, {
default: withCtx(() => [
["bottom", "middle"].includes(showShadows.value) ? (openBlock(), createElementBlock("div", _hoisted_5)) : createCommentVNode("", true)
]),
_: 1
}),
createElementVNode("div", {
class: normalizeClass({
"mt-modal__content-inner": true,
"mt-modal__content-inner--no-padding": __props.inset
})
}, [
renderSlot(_ctx.$slots, "default", {}, void 0, true)
], 2),
createVNode(Transition, { name: "shadow-fade" }, {
default: withCtx(() => [
["top", "middle"].includes(showShadows.value) ? (openBlock(), createElementBlock("div", _hoisted_6)) : createCommentVNode("", true)
]),
_: 1
})
], 512),
createElementVNode("div", _hoisted_7, [
renderSlot(_ctx.$slots, "footer", {}, void 0, true)
])
], 2)) : createCommentVNode("", true)
]))
]),
_: 3
});
};
}
});
const mtModal_vue_vue_type_style_index_0_scoped_16210e70_lang = "";
const MtModal = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-16210e70"]]);
export {
MtModal as default
};
//# sourceMappingURL=MtModal.js.map