UNPKG

@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
import '../mt-modal.css'; "use strict"; 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