UNPKG

portal-vue

Version:

> A Portal Component for Vue 3, to render DOM outside of a component, anywhere in the document.

189 lines (188 loc) 4.51 kB
import { inject as S, provide as M, defineComponent as p, onMounted as h, onUpdated as T, onBeforeUnmount as g, watch as y, computed as N, h as d, reactive as _, readonly as j, createApp as F, getCurrentInstance as O } from "vue"; const m = Symbol("wormhole"); function w() { const e = S(m); if (!e) throw new Error(` [portal-vue]: Necessary Injection not found. Make sur you installed the plugin properly.`); return e; } function x(e) { M(m, e); } const v = typeof window < "u"; function k(e, t) { return e.map((n, l) => [l, n]).sort(function(n, l) { return t(n[1], l[1]) || n[0] - l[0]; }).map((n) => n[1]); } function B(e, t) { const n = w(); function l() { if (!v) return; const { to: c, name: o, order: r } = e; t.default ? n.open({ to: c, from: o, order: r, content: t.default }) : s(); } function s(c) { n.close({ to: c ?? e.to, from: e.name }); } h(() => { e.disabled || l(); }), T(() => { e.disabled ? s() : l(); }), g(() => { s(); }), y( () => e.to, (c, o) => { e.disabled || (o && o !== c && s(o), l()); } ); } const W = p({ compatConfig: { MODE: 3 }, name: "portal", props: { disabled: { type: Boolean }, name: { type: [String, Symbol], default: () => Symbol() }, order: { type: Number }, slotProps: { type: Object, default: () => ({}) }, to: { type: String, default: () => String(Math.round(Math.random() * 1e7)) } }, setup(e, { slots: t }) { return B(e, t), () => e.disabled && t.default ? t.default(e.slotProps) : null; } }), E = (e, { slots: t }) => { var n; return (n = t.default) == null ? void 0 : n.call(t); }, b = p({ compatConfig: { MODE: 3 }, name: "portalTarget", props: { multiple: { type: Boolean, default: !1 }, name: { type: String, required: !0 }, slotProps: { type: Object, default: () => ({}) } }, emits: ["change"], setup(e, { emit: t, slots: n }) { const l = w(), s = N( () => { const c = l.getContentForTarget( e.name, e.multiple ), o = n.wrapper, r = c.map((u) => u.content(e.slotProps)), a = o ? r.flatMap( (u) => u.length ? o(u) : [] ) : r.flat(1); return { vnodes: a, vnodesFn: () => a }; } ); return y( s, ({ vnodes: c }) => { const o = c.length > 0, r = l.transports.get(e.name), a = r ? [...r.keys()] : []; t("change", { hasContent: o, sources: a }); }, { flush: "post" } ), () => { var o; return s.value.vnodes.length ? [ d("div", { style: "display: none", key: "__portal-vue-hacky-scoped-slot-repair__" }), d(E, s.value.vnodesFn) ] : (o = n.default) == null ? void 0 : o.call(n); }; } }); function I(e = !0) { const t = _(/* @__PURE__ */ new Map()); function n(o) { if (!v) return; const { to: r, from: a, content: u, order: i = 1 / 0 } = o; if (!r || !a || !u) return; t.has(r) || t.set(r, /* @__PURE__ */ new Map()); const f = t.get(r), P = { to: r, from: a, content: u, order: i }; f.set(a, P); } function l(o) { const { to: r, from: a } = o; if (!r || !a) return; const u = t.get(r); !u || (u.delete(a), u.size || t.delete(r)); } function s(o, r) { const a = t.get(o); if (!a) return []; const u = Array.from((a == null ? void 0 : a.values()) || []); return r ? k( u, (i, f) => i.order - f.order ) : [u.pop()]; } const c = { open: n, close: l, transports: t, getContentForTarget: s }; return e ? j(c) : c; } const C = I(); function A(e, t) { const n = F({ render: () => d(b, e) }); if (!e.multiple) { const l = O().provides ?? {}; n._context.provides = Object.create(l); } h(() => { n.mount(t); }), g(() => { n.unmount(); }); } function D(e, t = {}) { t.portalName !== !1 && e.component(t.portalName || "Portal", W), t.portalTargetName !== !1 && e.component(t.portalTargetName || "PortalTarget", b); const n = t.wormhole ?? C; e.provide(m, n); } const q = C, z = "3.0.0"; export { W as Portal, b as PortalTarget, q as Wormhole, I as createWormhole, D as default, D as install, A as mountPortalTarget, x as provideWormhole, w as useWormhole, z as version }; //# sourceMappingURL=portal-vue.mjs.map