vue-final-modal
Version:
The most powerful yet most light-weight modal library for Vue 3.
1,104 lines (1,103 loc) • 33.3 kB
JavaScript
import { ref as C, computed as g, watch as I, nextTick as z, onBeforeUnmount as he, reactive as pe, onMounted as Pe, getCurrentInstance as Ae, inject as Qe, shallowReactive as _, markRaw as te, defineComponent as me, useAttrs as Ie, toRef as ae, openBlock as B, createBlock as U, Teleport as _e, unref as v, withDirectives as ue, createElementBlock as N, mergeProps as x, withKeys as eo, withModifiers as Ce, Transition as ke, toHandlers as Ve, withCtx as ye, normalizeClass as oo, normalizeStyle as to, vShow as ce, createCommentVNode as Y, createVNode as no, renderSlot as Ee, normalizeProps as Re, guardReactiveProps as lo, createElementVNode as ee, Fragment as so, renderList as Be, resolveDynamicComponent as de, createSlots as ro } from "vue";
import { useEventListener as F, tryOnUnmounted as io } from "@vueuse/core";
import { useFocusTrap as ao } from "@vueuse/integrations/useFocusTrap";
const uo = (e) => (...o) => {
e && (e == null || e(...o), e = null);
}, q = () => {
};
function oe(e, o, l) {
return e > l ? l : e < o ? o : e;
}
const we = (e) => typeof e == "string";
function fe(e, o) {
var s;
const l = ((s = $(e, o)) == null ? void 0 : s[0]) || o;
e.push(l);
}
function $(e, o) {
const l = e.indexOf(o);
if (l !== -1)
return e.splice(l, 1);
}
function Fe(e) {
return Object.entries(e);
}
const co = {
/**
* @description Set `null | false` to disable teleport.
* @default `'body'`
* @example
* ```js
* teleportTo: '#modals'
* ```
*/
teleportTo: {
type: [String, null, Boolean, Object],
default: "body"
},
/**
* @description An uniq name for the open/close a modal via vfm.open/vfm.close APIs.
* @default `undefined`
* @example Symbol: `Symbol('MyModal')`
* @example String: `'AUniqString'`
* @example Number: `300`
*/
modalId: {
type: [String, Number, Symbol],
default: void 0
},
/**
* @description Display the modal or not.
* @default `undefined`
* @example
* ```js
* const showModal = ref(false)
* v-model="showModal"
* ```
*/
modelValue: {
type: Boolean,
default: void 0
},
/**
* @description Render the modal via `if` or `show`.
* @default `'if'`
* @example
* ```js
* displayDirective: 'if'
* ```
* @example
* ```js
* displayDirective: 'show'
* ```
*/
displayDirective: {
type: String,
default: "if",
validator: (e) => ["if", "show", "visible"].includes(e)
},
/**
* @description Hide the overlay or not.
* @default `undefined`
* @example
* ```js
* hideOverlay="true"
* ```
*/
hideOverlay: {
type: Boolean,
default: void 0
},
/**
* @description Customize the overlay behavior.
*/
overlayBehavior: {
type: String,
default: "auto",
validator: (e) => ["auto", "persist"].includes(e)
},
/**
* @description Customize the overlay transition.
* @default `undefined`
*/
overlayTransition: {
type: [String, Object],
default: void 0
},
/**
* @description Customize the content transition.
* @default `undefined`
*/
contentTransition: {
type: [String, Object],
default: void 0
},
/**
* @description Bind class to vfm__overlay.
* @default `undefined`
*/
overlayClass: {
type: void 0,
default: void 0
},
/**
* @description Bind class to vfm__content.
* @default `undefined`
*/
contentClass: {
type: void 0,
default: void 0
},
/**
* @description Bind style to vfm__overlay.
* @default `undefined`
*/
overlayStyle: {
type: [String, Object, Array],
default: void 0
},
/**
* @description Bind style to vfm__content.
* @default `undefined`
*/
contentStyle: {
type: [String, Object, Array],
default: void 0
},
/**
* @description Is it allow to close the modal by clicking the overlay.
* @default `true`
*/
clickToClose: {
type: Boolean,
default: !0
},
/**
* @description Is it allow to close the modal by keypress `esc`.
* @default `true`
*/
escToClose: {
type: Boolean,
default: !0
},
/**
* @description Is it allow to click outside of the vfm__content when the modal is opened
* @default `'non-interactive'`
*/
background: {
type: String,
default: "non-interactive",
validator: (e) => ["interactive", "non-interactive"].includes(e)
},
/**
* @description
* * Use `{ disabled: true }` to disable the focusTrap.
* * Checkout the createOptions type here https://github.com/focus-trap/focus-trap for more.
* @default `{ allowOutsideClick: true }`
*/
focusTrap: {
type: [Boolean, Object],
default: () => ({
allowOutsideClick: !0
})
},
/**
* @description Lock body scroll or not when the modal is opened.
* @default `true`
*/
lockScroll: {
type: Boolean,
default: !0
},
/**
* @description Creates a padding-right when scroll is locked to prevent the page from jumping
* @default `true`
*/
reserveScrollBarGap: {
type: Boolean,
default: !0
},
/**
* @description Define how to increase the zIndex when there are nested modals
* @default `({ index }) => 1000 + 2 * index`
*/
zIndexFn: {
type: Function,
default: ({ index: e }) => 1e3 + 2 * e
},
/**
* @description The direction of swiping to close the modal
* @default `none`
* @example
* Set swipeToClose="none" to disable swiping to close
* ```js
* swipeToClose="none"
* ```
*/
swipeToClose: {
type: String,
default: "none",
validator: (e) => ["none", "up", "right", "down", "left"].includes(e)
},
/**
* @description Threshold for swipe to close
* @default `0`
*/
threshold: {
type: Number,
default: 0
},
/**
* @description If set `:showSwipeBanner="true"`, only allow clicking `swipe-banner` slot to swipe to close
* @default `undefined`
* @example
* ```js
* swipeToClose="right"
* :showSwipeBanner="true"
* ```
* ```html
* <VueFinalModal
* ...
* swipeToClose="right"
* :showSwipeBanner="true"
* >
* <template #swipe-banner>
* <div style="position: absolute; height: 100%; top: 0; left: 0; width: 10px;" />
* </template>
* ...modal content
* </VueFinalModal>
* ```
*/
showSwipeBanner: {
type: Boolean,
default: void 0
},
/**
* @description When set `:preventNavigationGestures="true"`, there will be two invisible bars for prevent navigation gestures including swiping back/forward on mobile webkit. For example: Safari mobile.
* @default `undefined`
* @example
* Set preventNavigationGestures="true" to prevent Safari navigation gestures including swiping back/forward.
* ```js
* :preventNavigationGestures="true"
* ```
*/
preventNavigationGestures: {
type: Boolean,
default: void 0
}
};
function Oe(e = !1) {
const o = C(e), l = C(o.value ? 0 : void 0);
return [o, l, {
beforeEnter() {
l.value = 1;
},
afterEnter() {
l.value = 0;
},
beforeLeave() {
l.value = 3;
},
afterLeave() {
l.value = 2;
}
}];
}
function fo(e, o) {
const { modelValueLocal: l, onEntering: s, onEnter: u, onLeaving: c, onLeave: a } = o, n = C(l.value), [t, r, m] = Oe(n.value), [f, M, S] = Oe(n.value), V = g(() => typeof e.contentTransition == "string" ? { name: e.contentTransition, appear: !0 } : { appear: !0, ...e.contentTransition }), O = g(() => typeof e.overlayTransition == "string" ? { name: e.overlayTransition, appear: !0 } : { appear: !0, ...e.overlayTransition }), E = g(
() => (e.hideOverlay || M.value === 2) && r.value === 2
/* Leave */
);
I(
E,
(k) => {
k && (n.value = !1);
}
), I(r, (k) => {
if (k === 1) {
if (!n.value)
return;
s == null || s();
} else if (k === 0) {
if (!n.value)
return;
u == null || u();
} else
k === 3 ? c == null || c() : k === 2 && (a == null || a());
});
async function w() {
n.value = !0, await z(), t.value = !0, f.value = !0;
}
function D() {
t.value = !1, f.value = !1;
}
return {
visible: n,
contentVisible: t,
contentListeners: m,
contentTransition: V,
overlayVisible: f,
overlayListeners: S,
overlayTransition: O,
enterTransition: w,
leaveTransition: D
};
}
function vo(e, o, l) {
const { vfmRootEl: s, vfmContentEl: u, visible: c, modelValueLocal: a } = l, n = C();
function t() {
c.value && e.escToClose && (a.value = !1);
}
function r(f) {
n.value = f == null ? void 0 : f.target;
}
function m() {
var f;
n.value === s.value && (e.clickToClose ? a.value = !1 : ((f = u.value) == null || f.focus(), o("clickOutside")));
}
return {
onEsc: t,
onMouseupRoot: m,
onMousedown: r
};
}
function po(e, o, l) {
let s = !1;
const { open: u, close: c } = l, a = C(!1), n = {
get value() {
return a.value;
},
set value(r) {
t(r);
}
};
function t(r) {
(r ? u() : c()) ? (a.value = r, r !== e.modelValue && o("update:modelValue", r)) : (s = !0, o("update:modelValue", !r), z(() => {
s = !1;
}));
}
return I(() => e.modelValue, (r) => {
s || (n.value = !!r);
}), {
modelValueLocal: n
};
}
function yo(e, o) {
if (e.focusTrap === !1)
return {
focus() {
},
blur() {
}
};
const { focusEl: l } = o, { hasFocus: s, activate: u, deactivate: c } = ao(l, e.focusTrap);
function a() {
requestAnimationFrame(() => {
u();
});
}
function n() {
s.value && c();
}
return { focus: a, blur: n };
}
let be = !1;
if (typeof window < "u") {
const e = {
get passive() {
be = !0;
}
};
window.addEventListener("testPassive", null, e), window.removeEventListener("testPassive", null, e);
}
const He = typeof window < "u" && window.navigator && window.navigator.platform && (/iP(ad|hone|od)/.test(window.navigator.platform) || window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 1);
let j = [], le = !1, ne = 0, je = -1, W, X;
const ho = (e) => {
if (!e || e.nodeType !== Node.ELEMENT_NODE)
return !1;
const o = window.getComputedStyle(e);
return ["auto", "scroll"].includes(o.overflowY) && e.scrollHeight > e.clientHeight;
}, mo = (e, o) => !(e.scrollTop === 0 && o < 0 || e.scrollTop + e.clientHeight + o >= e.scrollHeight && o > 0), wo = (e) => {
const o = [];
for (; e; ) {
if (o.push(e), e.classList.contains("vfm"))
return o;
e = e.parentElement;
}
return o;
}, bo = (e, o) => {
let l = !1;
return wo(e).forEach((u) => {
ho(u) && mo(u, o) && (l = !0);
}), l;
}, Ne = (e) => j.some(() => bo(e, -ne)), se = (e) => {
const o = e || window.event;
return Ne(o.target) || o.touches.length > 1 ? !0 : (o.preventDefault && o.preventDefault(), !1);
}, To = (e) => {
if (X === void 0) {
const o = !!e && e.reserveScrollBarGap === !0, l = window.innerWidth - document.documentElement.clientWidth;
if (o && l > 0) {
const s = parseInt(getComputedStyle(document.body).getPropertyValue("padding-right"), 10);
X = document.body.style.paddingRight, document.body.style.paddingRight = `${s + l}px`;
}
}
W === void 0 && (W = document.body.style.overflow, document.body.style.overflow = "hidden");
}, So = () => {
X !== void 0 && (document.body.style.paddingRight = X, X = void 0), W !== void 0 && (document.body.style.overflow = W, W = void 0);
}, Mo = (e) => e ? e.scrollHeight - e.scrollTop <= e.clientHeight : !1, go = (e, o) => (ne = e.targetTouches[0].clientY - je, Ne(e.target) ? !1 : o && o.scrollTop === 0 && ne > 0 || Mo(o) && ne < 0 ? se(e) : (e.stopPropagation(), !0)), Co = (e, o) => {
if (!e) {
console.error(
"disableBodyScroll unsuccessful - targetElement must be provided when calling disableBodyScroll on IOS devices."
);
return;
}
if (j.some((s) => s.targetElement === e))
return;
const l = {
targetElement: e,
options: o || {}
};
j = [...j, l], He ? (e.ontouchstart = (s) => {
s.targetTouches.length === 1 && (je = s.targetTouches[0].clientY);
}, e.ontouchmove = (s) => {
s.targetTouches.length === 1 && go(s, e);
}, le || (document.addEventListener("touchmove", se, be ? { passive: !1 } : void 0), le = !0)) : To(o);
}, ko = (e) => {
if (!e) {
console.error(
"enableBodyScroll unsuccessful - targetElement must be provided when calling enableBodyScroll on IOS devices."
);
return;
}
j = j.filter((o) => o.targetElement !== e), He ? (e.ontouchstart = null, e.ontouchmove = null, le && j.length === 0 && (document.removeEventListener("touchmove", se, be ? { passive: !1 } : void 0), le = !1)) : j.length || So();
};
function Vo(e, o) {
const { lockScrollEl: l, modelValueLocal: s } = o;
let u;
I(l, (n) => {
n && (u = n);
}, { immediate: !0 }), I(() => e.lockScroll, (n) => {
n ? a() : c();
}), he(() => {
c();
});
function c() {
u && ko(u);
}
function a() {
s.value && e.lockScroll && u && Co(u, {
reserveScrollBarGap: e.reserveScrollBarGap,
allowTouchMove: (n) => {
for (; n && n !== document.body; ) {
if (n.getAttribute("vfm-scroll-lock-ignore") !== null)
return !0;
n = n.parentElement;
}
return !1;
}
});
}
return {
enableBodyScroll: c,
disableBodyScroll: a
};
}
function Eo(e) {
const o = C();
function l(u) {
var c;
o.value = (c = e.zIndexFn) == null ? void 0 : c.call(e, { index: u <= -1 ? 0 : u });
}
function s() {
o.value = void 0;
}
return {
zIndex: o,
refreshZIndex: l,
resetZIndex: s
};
}
const ve = {
beforeMount(e, { value: o }, { transition: l }) {
e._vov = e.style.visibility === "hidden" ? "" : e.style.visibility, l && o ? l.beforeEnter(e) : G(e, o);
},
mounted(e, { value: o }, { transition: l }) {
l && o && l.enter(e);
},
updated(e, { value: o, oldValue: l }, { transition: s }) {
!o != !l && (s ? o ? (s.beforeEnter(e), G(e, !0), s.enter(e)) : s.leave(e, () => {
G(e, !1);
}) : G(e, o));
},
beforeUnmount(e, { value: o }) {
G(e, o);
}
};
function G(e, o) {
e.style.visibility = o ? e._vov : "hidden";
}
const De = (e) => {
if (e instanceof MouseEvent) {
const { clientX: o, clientY: l } = e;
return { x: o, y: l };
} else {
const { clientX: o, clientY: l } = e.targetTouches[0];
return { x: o, y: l };
}
};
function Bo(e) {
if (!e)
return !1;
let o = !1;
const l = {
get passive() {
return o = !0, !1;
}
};
return e.addEventListener("x", q, l), e.removeEventListener("x", q), o;
}
function Oo(e, {
threshold: o = 0,
onSwipeStart: l,
onSwipe: s,
onSwipeEnd: u,
passive: c = !0
}) {
const a = pe({ x: 0, y: 0 }), n = pe({ x: 0, y: 0 }), t = g(() => a.x - n.x), r = g(() => a.y - n.y), { max: m, abs: f } = Math, M = g(
() => m(f(t.value), f(r.value)) >= o
), S = C(!1), V = g(() => M.value ? f(t.value) > f(r.value) ? t.value > 0 ? "left" : "right" : r.value > 0 ? "up" : "down" : "none"), O = (p, h) => {
a.x = p, a.y = h;
}, E = (p, h) => {
n.x = p, n.y = h;
};
let w, D;
function k(p) {
w.capture && !w.passive && p.preventDefault();
const { x: h, y: R } = De(p);
O(h, R), E(h, R), l == null || l(p), D = [
F(e, "mousemove", P, w),
F(e, "touchmove", P, w),
F(e, "mouseup", i, w),
F(e, "touchend", i, w),
F(e, "touchcancel", i, w)
];
}
function P(p) {
const { x: h, y: R } = De(p);
E(h, R), !S.value && M.value && (S.value = !0), S.value && (s == null || s(p));
}
function i(p) {
S.value && (u == null || u(p, V.value)), S.value = !1, D.forEach((h) => h());
}
let b = [];
return Pe(() => {
const p = Bo(window == null ? void 0 : window.document);
c ? w = p ? { passive: !0 } : { capture: !1 } : w = p ? { passive: !1, capture: !0 } : { capture: !0 }, b = [
F(e, "mousedown", k, w),
F(e, "touchstart", k, w)
];
}), {
isSwiping: S,
direction: V,
coordsStart: a,
coordsEnd: n,
lengthX: t,
lengthY: r,
stop: () => {
b.forEach((p) => p()), D.forEach((p) => p());
}
};
}
function Do(e, o) {
const { vfmContentEl: l, modelValueLocal: s } = o, u = 0.1, c = 300, a = C(), n = g(() => {
if (!(e.swipeToClose === void 0 || e.swipeToClose === "none"))
return e.showSwipeBanner ? a.value : l.value;
}), t = C(0), r = C(!0);
let m = q, f = !0, M, S = !1;
const { lengthX: V, lengthY: O, direction: E, isSwiping: w } = Oo(n, {
threshold: e.threshold,
onSwipeStart(i) {
m = F(document, "selectionchange", () => {
var b;
r.value = (b = window.getSelection()) == null ? void 0 : b.isCollapsed;
}), M = (/* @__PURE__ */ new Date()).getTime(), S = P(i == null ? void 0 : i.target);
},
onSwipe() {
var i, b, L, p;
if (S && r.value && E.value === e.swipeToClose) {
if (E.value === "up") {
const h = oe(Math.abs(O.value || 0), 0, ((i = n.value) == null ? void 0 : i.offsetHeight) || 0) - (e.threshold || 0);
t.value = h;
} else if (E.value === "down") {
const h = oe(Math.abs(O.value || 0), 0, ((b = n.value) == null ? void 0 : b.offsetHeight) || 0) - (e.threshold || 0);
t.value = -h;
} else if (E.value === "right") {
const h = oe(Math.abs(V.value || 0), 0, ((L = n.value) == null ? void 0 : L.offsetWidth) || 0) - (e.threshold || 0);
t.value = -h;
} else if (E.value === "left") {
const h = oe(Math.abs(V.value || 0), 0, ((p = n.value) == null ? void 0 : p.offsetWidth) || 0) - (e.threshold || 0);
t.value = h;
}
}
},
onSwipeEnd(i, b) {
if (m(), !r.value) {
r.value = !0;
return;
}
const L = (/* @__PURE__ */ new Date()).getTime(), p = b === e.swipeToClose, h = (() => {
var J, Q;
if (b === "up" || b === "down")
return Math.abs((O == null ? void 0 : O.value) || 0) > u * (((J = n.value) == null ? void 0 : J.offsetHeight) || 0);
if (b === "left" || b === "right")
return Math.abs((V == null ? void 0 : V.value) || 0) > u * (((Q = n.value) == null ? void 0 : Q.offsetWidth) || 0);
})(), R = L - M <= c;
if (f && S && p && (h || R)) {
s.value = !1;
return;
}
t.value = 0;
}
}), D = g(() => {
if (e.swipeToClose === "none")
return;
const i = (() => {
switch (e.swipeToClose) {
case "up":
case "down":
return "translateY";
case "left":
case "right":
return "translateX";
}
})();
return {
class: { "vfm-bounce-back": !w.value },
style: { transform: `${i}(${-t.value}px)` }
};
});
I(
() => r.value,
(i) => {
i || (t.value = 0);
}
), I(
() => s.value,
(i) => {
i && (t.value = 0);
}
), I(
() => t.value,
(i, b) => {
switch (e.swipeToClose) {
case "down":
case "right":
f = i < b;
break;
case "up":
case "left":
f = i > b;
break;
}
}
);
function k(i) {
e.preventNavigationGestures && i.preventDefault();
}
function P(i) {
const b = i == null ? void 0 : i.tagName;
if (!b || ["INPUT", "TEXTAREA"].includes(b))
return !1;
const L = (() => {
switch (e.swipeToClose) {
case "up":
return (i == null ? void 0 : i.scrollTop) + (i == null ? void 0 : i.clientHeight) === (i == null ? void 0 : i.scrollHeight);
case "left":
return (i == null ? void 0 : i.scrollLeft) + (i == null ? void 0 : i.clientWidth) === (i == null ? void 0 : i.scrollWidth);
case "down":
return (i == null ? void 0 : i.scrollTop) === 0;
case "right":
return (i == null ? void 0 : i.scrollLeft) === 0;
default:
return !1;
}
})();
return i === n.value ? L : L && P(i == null ? void 0 : i.parentElement);
}
return {
vfmContentEl: l,
swipeBannerEl: a,
bindSwipe: D,
onTouchStartSwipeBanner: k
};
}
const Ye = Symbol("vfm");
let H;
const Lo = (e) => H = e, Po = {
install: q,
modals: [],
openedModals: [],
openedModalOverlays: [],
dynamicModals: [],
modalsContainers: C([]),
get: () => {
},
toggle: () => {
},
open: () => {
},
close: () => {
},
closeAll: () => Promise.allSettled([])
}, Ao = () => Ae() && Qe(Ye, Po) || H;
function zo() {
const e = _([]), o = _([]), l = _([]), s = _([]), u = C([]), c = te({
install(a) {
a.provide(Ye, c), a.config.globalProperties.$vfm = c;
},
modals: e,
openedModals: o,
openedModalOverlays: l,
dynamicModals: s,
modalsContainers: u,
get(a) {
return e.find((n) => {
var t, r;
return ((r = (t = Z(n)) == null ? void 0 : t.value.modalId) == null ? void 0 : r.value) === a;
});
},
toggle(a, n) {
var r;
const t = c.get(a);
return (r = Z(t)) == null ? void 0 : r.value.toggle(n);
},
open(a) {
return c.toggle(a, !0);
},
close(a) {
return c.toggle(a, !1);
},
closeAll() {
return Promise.allSettled(
o.reduce((a, n) => {
const t = Z(n), r = t == null ? void 0 : t.value.toggle(!1);
return r && a.push(r), a;
}, [])
);
}
});
return Lo(c), c;
}
function Z(e) {
var o;
return (o = e == null ? void 0 : e.exposed) == null ? void 0 : o.modalExposed;
}
const Io = me({ inheritAttrs: !1 }), Ro = /* @__PURE__ */ me({
...Io,
__name: "VueFinalModal",
props: co,
emits: ["update:modelValue", "beforeOpen", "opened", "beforeClose", "closed", "clickOutside"],
setup(e, { expose: o, emit: l }) {
const s = e, u = l, c = Ie(), a = Ae(), { modals: n, openedModals: t, openedModalOverlays: r } = K(), m = C(), f = C(), { focus: M, blur: S } = yo(s, { focusEl: m }), { zIndex: V, refreshZIndex: O, resetZIndex: E } = Eo(s), { modelValueLocal: w } = po(s, u, { open: We, close: Xe }), { enableBodyScroll: D, disableBodyScroll: k } = Vo(s, {
lockScrollEl: m,
modelValueLocal: w
});
let P = q;
const {
visible: i,
contentVisible: b,
contentListeners: L,
contentTransition: p,
overlayVisible: h,
overlayListeners: R,
overlayTransition: J,
enterTransition: Q,
leaveTransition: xe
} = fo(s, {
modelValueLocal: w,
onEntering() {
z(() => {
k(), M();
});
},
onEnter() {
u("opened"), P("opened");
},
onLeave() {
$(t, a), E(), D(), u("closed"), P("closed");
}
}), { onEsc: ze, onMouseupRoot: Ge, onMousedown: Te } = vo(s, u, { vfmRootEl: m, vfmContentEl: f, visible: i, modelValueLocal: w }), {
swipeBannerEl: $e,
bindSwipe: Ue,
onTouchStartSwipeBanner: Se
} = Do(s, { vfmContentEl: f, modelValueLocal: w }), Me = g(() => a ? t.indexOf(a) : -1);
I([() => s.zIndexFn, Me], () => {
i.value && O(Me.value);
}), Pe(() => {
fe(n, a);
}), s.modelValue && (w.value = !0);
function We() {
let d = !1;
return u("beforeOpen", { stop: () => d = !0 }), d ? !1 : (fe(t, a), fe(r, a), ie(), Q(), !0);
}
function Xe() {
let d = !1;
return u("beforeClose", { stop: () => d = !0 }), d ? !1 : ($(r, a), ie(), S(), xe(), !0);
}
function Ze() {
w.value = !1;
}
he(() => {
D(), $(n, a), $(t, a), S(), ie();
});
async function ie() {
await z();
const d = r.filter((y) => {
var A;
const T = Z(y);
return (T == null ? void 0 : T.value.overlayBehavior.value) === "auto" && !((A = T == null ? void 0 : T.value.hideOverlay) != null && A.value);
});
d.forEach((y, T) => {
const A = Z(y);
A != null && A.value && (A.value.overlayVisible.value = T === d.length - 1);
});
}
const Ke = ae(() => s.modalId), ge = ae(() => s.hideOverlay), qe = ae(() => s.overlayBehavior), Je = g(() => ({
modalId: Ke,
hideOverlay: ge,
overlayBehavior: qe,
overlayVisible: h,
toggle(d) {
return new Promise((y) => {
P = uo((A) => y(A));
const T = typeof d == "boolean" ? d : !w.value;
w.value = T;
});
}
}));
return o({
modalExposed: Je
}), (d, y) => (B(), U(_e, {
to: d.teleportTo ? d.teleportTo : void 0,
disabled: !d.teleportTo
}, [
d.displayDirective !== "if" || v(i) ? ue((B(), N("div", x({ key: 0 }, v(c), {
ref_key: "vfmRootEl",
ref: m,
class: ["vfm vfm--fixed vfm--inset", { "vfm--prevent-none": d.background === "interactive" }],
style: { zIndex: v(V) },
role: "dialog",
"aria-modal": "true",
onKeydown: y[7] || (y[7] = eo(() => v(ze)(), ["esc"])),
onMouseup: y[8] || (y[8] = Ce(() => v(Ge)(), ["self"])),
onMousedown: y[9] || (y[9] = Ce((T) => v(Te)(T), ["self"]))
}), [
ge.value ? Y("", !0) : (B(), U(ke, x({ key: 0 }, v(J), Ve(v(R))), {
default: ye(() => [
d.displayDirective !== "if" || v(h) ? ue((B(), N("div", {
key: 0,
class: oo(["vfm__overlay vfm--overlay vfm--absolute vfm--inset vfm--prevent-none", d.overlayClass]),
style: to(d.overlayStyle),
"aria-hidden": "true"
}, null, 6)), [
[ce, d.displayDirective !== "show" || v(h)],
[v(ve), d.displayDirective !== "visible" || v(h)]
]) : Y("", !0)
]),
_: 1
}, 16)),
no(ke, x(v(p), Ve(v(L))), {
default: ye(() => [
d.displayDirective !== "if" || v(b) ? ue((B(), N("div", x({
key: 0,
ref_key: "vfmContentEl",
ref: f,
class: ["vfm__content vfm--outline-none", [d.contentClass, { "vfm--prevent-auto": d.background === "interactive" }]],
style: d.contentStyle,
tabindex: "0"
}, v(Ue), {
onMousedown: y[6] || (y[6] = () => v(Te)())
}), [
Ee(d.$slots, "default", Re(lo({ close: Ze }))),
d.showSwipeBanner ? (B(), N("div", {
key: 0,
ref_key: "swipeBannerEl",
ref: $e,
class: "vfm-swipe-banner-container",
onTouchstart: y[2] || (y[2] = (T) => v(Se)(T))
}, [
Ee(d.$slots, "swipe-banner", {}, () => [
ee("div", {
class: "vfm-swipe-banner-back",
onTouchstart: y[0] || (y[0] = (T) => d.swipeToClose === "left" && T.preventDefault())
}, null, 32),
ee("div", {
class: "vfm-swipe-banner-forward",
onTouchstart: y[1] || (y[1] = (T) => d.swipeToClose === "right" && T.preventDefault())
}, null, 32)
])
], 544)) : !d.showSwipeBanner && d.preventNavigationGestures ? (B(), N("div", {
key: 1,
class: "vfm-swipe-banner-container",
onTouchstart: y[5] || (y[5] = (T) => v(Se)(T))
}, [
ee("div", {
class: "vfm-swipe-banner-back",
onTouchstart: y[3] || (y[3] = (T) => d.swipeToClose === "left" && T.preventDefault())
}, null, 32),
ee("div", {
class: "vfm-swipe-banner-forward",
onTouchstart: y[4] || (y[4] = (T) => d.swipeToClose === "right" && T.preventDefault())
}, null, 32)
], 32)) : Y("", !0)
], 16)), [
[ce, d.displayDirective !== "show" || v(b)],
[v(ve), d.displayDirective !== "visible" || v(b)]
]) : Y("", !0)
]),
_: 3
}, 16)
], 16)), [
[ce, d.displayDirective !== "show" || v(i)],
[v(ve), d.displayDirective !== "visible" || v(i)]
]) : Y("", !0)
], 8, ["to", "disabled"]));
}
});
function K() {
const e = Ao();
if (!e)
throw new Error(
`[Vue Final Modal]: getActiveVfm was called with no active Vfm. Did you forget to install vfm?
const vfm = createVfm()
app.use(vfm)
This will fail in production.`
);
return e;
}
function Le(e, o = Ro) {
const { component: l, slots: s, ...u } = e, c = typeof s > "u" ? {} : Object.fromEntries(Fe(s).map(([a, n]) => we(n) ? [a, n] : re(n) ? [a, {
...n,
component: te(n.component)
}] : [a, te(n)]));
return {
...u,
component: te(l || o),
slots: c
};
}
function Go(e) {
const o = pe({
id: Symbol("useModal"),
modelValue: !!(e != null && e.defaultModelValue),
resolveOpened: () => {
},
resolveClosed: () => {
},
attrs: {},
...Le(e)
});
io(() => {
o != null && o.keepAlive || n();
}), o.modelValue === !0 && (H ? H == null || H.dynamicModals.push(o) : z(() => {
const t = K();
t == null || t.dynamicModals.push(o);
}));
async function l() {
let t;
return H ? t = H : (await z(), t = K()), o.modelValue ? Promise.resolve("[Vue Final Modal] modal is already opened.") : (n(), o.modelValue = !0, t.dynamicModals.push(o), new Promise((r) => {
o.resolveOpened = () => r("opened");
}));
}
function s() {
return o.modelValue ? (o.modelValue = !1, new Promise((t) => {
o.resolveClosed = () => t("closed");
})) : Promise.resolve("[Vue Final Modal] modal is already closed.");
}
function u(t) {
const { slots: r, ...m } = Le(t, o.component);
t.defaultModelValue !== void 0 && (o.defaultModelValue = t.defaultModelValue), (t == null ? void 0 : t.keepAlive) !== void 0 && (o.keepAlive = t == null ? void 0 : t.keepAlive), c(o, m), r && Fe(r).forEach(([f, M]) => {
const S = o.slots[f];
we(S) ? o.slots[f] = M : re(S) && re(M) ? c(S, M) : o.slots[f] = M;
});
}
function c(t, r) {
r.component && (t.component = r.component), r.attrs && a(t.attrs, r.attrs);
}
function a(t, r) {
return Object.entries(r).forEach(([m, f]) => {
t[m] = f;
}), t;
}
function n() {
const t = K(), r = t.dynamicModals.indexOf(o);
r !== -1 && t.dynamicModals.splice(r, 1);
}
return {
options: o,
open: l,
close: s,
patchOptions: u,
destroy: n
};
}
function $o(e) {
return e;
}
function re(e) {
return typeof e == "object" && e !== null ? "component" in e : !1;
}
function Fo(e, o) {
return Object.keys(o).reduce((l, s) => (l[s] = e == null ? void 0 : e[s], l), {});
}
function Ho(e) {
return {
"onUpdate:modelValue": (o) => e == null ? void 0 : e("update:modelValue", o),
onBeforeClose: (o) => e == null ? void 0 : e("beforeClose", o),
onClosed: () => e == null ? void 0 : e("closed"),
onBeforeOpen: (o) => e == null ? void 0 : e("beforeOpen", o),
onOpened: () => e == null ? void 0 : e("opened"),
/** onClickOutside will only be emitted when clickToClose equal to `false` */
onClickOutside: () => e == null ? void 0 : e("clickOutside")
};
}
function Uo(e) {
const { props: o, modalProps: l, emit: s } = e, u = g(() => Fo(o, l)), c = Ho(s), a = Ie();
return g(() => ({
...u.value,
...c,
...a
}));
}
const jo = ["innerHTML"], Wo = /* @__PURE__ */ me({
__name: "ModalsContainer",
setup(e) {
const { modalsContainers: o, dynamicModals: l } = K(), s = Symbol("ModalsContainer"), u = g(() => {
var n;
return s === ((n = o.value) == null ? void 0 : n[0]);
});
o.value.push(s), he(() => {
o.value = o.value.filter((n) => n !== s);
});
function c(n) {
var t, r, m;
(r = (t = l[n]) == null ? void 0 : t.resolveClosed) == null || r.call(t), (m = l[n]) != null && m.keepAlive || l.splice(n, 1);
}
function a(n) {
var t, r;
(r = (t = l[n]) == null ? void 0 : t.resolveOpened) == null || r.call(t);
}
return (n, t) => u.value ? (B(!0), N(so, { key: 0 }, Be(v(l), (r, m) => (B(), U(de(r.component), x({
key: r.id
}, {
displayDirective: r != null && r.keepAlive ? "show" : void 0,
...typeof r.attrs == "object" ? r.attrs : {}
}, {
modelValue: r.modelValue,
"onUpdate:modelValue": (f) => r.modelValue = f,
onClosed: () => c(m),
onOpened: () => a(m)
}), ro({ _: 2 }, [
Be(r.slots, (f, M) => ({
name: M,
fn: ye(() => [
v(we)(f) ? (B(), N("div", {
key: 0,
innerHTML: f
}, null, 8, jo)) : v(re)(f) ? (B(), U(de(f.component), Re(x({ key: 1 }, f.attrs)), null, 16)) : (B(), U(de(f), { key: 2 }))
])
}))
]), 1040, ["modelValue", "onUpdate:modelValue", "onClosed", "onOpened"]))), 128)) : Y("", !0);
}
});
export {
Wo as ModalsContainer,
Ro as VueFinalModal,
zo as createVfm,
Z as getModalExposed,
Go as useModal,
$o as useModalSlot,
K as useVfm,
Uo as useVfmAttrs,
co as vueFinalModalProps
};