@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/).
263 lines (262 loc) • 9.52 kB
JavaScript
import '../mt-modal.css';
;
const vue = require("vue");
const useModalContext = require("../useModalContext-e62d6d51.js");
const mtIcon_vue_vue_type_style_index_0_lang = require("../mt-icon.vue_vue_type_style_index_0_lang-0a28c7b6.js");
const mtModalClose_vue_vue_type_script_setup_true_lang = require("../mt-modal-close.vue_vue_type_script_setup_true_lang-1e877a45.js");
const MtText = require("./MtText.js");
const id = require("../id-8e80f112.js");
const focusTrap_esm = require("../focus-trap.esm-8d514d11.js");
const _pluginVue_exportHelper = require("../_plugin-vue_export-helper-9c783a34.js");
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__ */ vue.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$1 = `mt-modal--${id.createId()}`;
const { isOpen, setIsOpen, closable } = useModalContext.useModalContext("mt-modal");
let closeOnEscapeEventListener = void 0;
vue.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 }
);
vue.onUnmounted(() => {
if (closeOnEscapeEventListener) {
document.removeEventListener("keydown", closeOnEscapeEventListener);
}
});
const modalRef = vue.ref(null);
let trap;
vue.watch(
isOpen,
async () => {
const isModalOpen = !!isOpen.value;
if (isModalOpen)
await vue.nextTick();
if (!modalRef.value)
return;
if (isModalOpen) {
trap = focusTrap_esm.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 }
);
vue.onUnmounted(() => {
if (trap)
trap.deactivate();
});
const modalContentRef = vue.ref(null);
const showShadows = vue.ref("none");
vue.onMounted(async () => {
const isModalClosed = !isOpen.value;
if (isModalClosed || !modalContentRef.value)
return;
await vue.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";
}
vue.watch(
isOpen,
async () => {
const isModalClosed = !isOpen.value;
if (isModalClosed) {
showShadows.value = "none";
if (!modalContentRef.value)
return;
modalContentRef.value.removeEventListener("scroll", handleScroll);
return;
}
await vue.nextTick();
if (!modalContentRef.value)
return;
modalContentRef.value.addEventListener("scroll", handleScroll);
},
{ immediate: true }
);
vue.onUnmounted(() => {
if (modalContentRef.value)
modalContentRef.value.removeEventListener("scroll", handleScroll);
});
return (_ctx, _cache) => {
return vue.openBlock(), vue.createBlock(vue.Transition, { name: "modal" }, {
default: vue.withCtx(() => [
(vue.openBlock(), vue.createBlock(vue.Teleport, { to: "body" }, [
vue.unref(isOpen) ? (vue.openBlock(), vue.createElementBlock("div", {
key: 0,
ref_key: "modalRef",
ref: modalRef,
class: vue.normalizeClass(["mt-modal", `mt-modal--width-${__props.width}`]),
role: "dialog",
"aria-modal": "true",
"aria-labelledby": id$1
}, [
!__props.hideHeader ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
vue.renderSlot(_ctx.$slots, "header-left", {}, void 0, true),
vue.createElementVNode("div", _hoisted_2, [
vue.createElementVNode("div", _hoisted_3, [
__props.title ? (vue.openBlock(), vue.createBlock(MtText, {
key: 0,
as: "h2",
class: "mt-modal__title",
size: "m",
weight: "semibold",
id: id$1
}, {
default: vue.withCtx(() => [
vue.createTextVNode(vue.toDisplayString(__props.title), 1)
]),
_: 1
})) : vue.createCommentVNode("", true),
vue.renderSlot(_ctx.$slots, "title-after", {}, void 0, true)
]),
__props.subtitle ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_4, vue.toDisplayString(__props.subtitle), 1)) : vue.createCommentVNode("", true)
]),
vue.renderSlot(_ctx.$slots, "header-right", {}, void 0, true),
vue.unref(closable) ? (vue.openBlock(), vue.createBlock(mtModalClose_vue_vue_type_script_setup_true_lang._sfc_main, {
key: 0,
class: "mt-modal__close-button",
"aria-label": "Close"
}, {
default: vue.withCtx(() => [
vue.createVNode(mtIcon_vue_vue_type_style_index_0_lang._sfc_main, {
"aria-hidden": "",
name: "regular-times-xs"
})
]),
_: 1
})) : vue.createCommentVNode("", true)
])) : vue.createCommentVNode("", true),
vue.createElementVNode("div", {
class: "mt-modal__content",
ref_key: "modalContentRef",
ref: modalContentRef
}, [
vue.createVNode(vue.Transition, { name: "shadow-fade" }, {
default: vue.withCtx(() => [
["bottom", "middle"].includes(showShadows.value) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5)) : vue.createCommentVNode("", true)
]),
_: 1
}),
vue.createElementVNode("div", {
class: vue.normalizeClass({
"mt-modal__content-inner": true,
"mt-modal__content-inner--no-padding": __props.inset
})
}, [
vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
], 2),
vue.createVNode(vue.Transition, { name: "shadow-fade" }, {
default: vue.withCtx(() => [
["top", "middle"].includes(showShadows.value) ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_6)) : vue.createCommentVNode("", true)
]),
_: 1
})
], 512),
vue.createElementVNode("div", _hoisted_7, [
vue.renderSlot(_ctx.$slots, "footer", {}, void 0, true)
])
], 2)) : vue.createCommentVNode("", true)
]))
]),
_: 3
});
};
}
});
const mtModal_vue_vue_type_style_index_0_scoped_16210e70_lang = "";
const MtModal = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["__scopeId", "data-v-16210e70"]]);
module.exports = MtModal;
//# sourceMappingURL=MtModal.js.map