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/).

264 lines (263 loc) 9.3 kB
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