UNPKG

vue-create-shadow-app

Version:
92 lines (91 loc) 3.01 kB
import { defineComponent, createApp, ref, getCurrentInstance, onMounted, h } from "vue"; import { isPlainObject, extend, hyphenate } from "@vue/shared"; function createShadowApp(rootComponent, rootProps, extraOptions) { const Comp = defineComponent(rootComponent, extraOptions); if (isPlainObject(Comp)) extend(Comp, extraOptions); let shadowRoot = null; let fakeCE = null; const rawApp = createApp({ setup() { const rootInstance = ref(null); const instance = getCurrentInstance(); if (!instance) { throw new Error("no instance"); } fakeCE._instance = instance; instance.ce = fakeCE; instance.isCE = true; const dispatch = (event, args) => { fakeCE.dispatchEvent( new CustomEvent( event, isPlainObject(args[0]) ? extend({ detail: args }, args[0]) : { detail: args } ) ); }; instance.emit = (event, ...args) => { dispatch(event, args); if (hyphenate(event) !== event) { dispatch(hyphenate(event), args); } }; onMounted(() => { instance.exposed = {}; instance.exposeProxy = rootInstance.value; }); return () => { const vnode = h(rootComponent, { ...rootProps, ref: rootInstance }); vnode.ce = (instance2) => { instance2.ce = instance2.root.ce; }; return vnode; }; } }); const converted = Object.create(rawApp); converted.mount = (rootContainer, isHydrate, isSVG) => { const rootElm = typeof rootContainer === "string" ? document.querySelector(rootContainer) : rootContainer; if (!rootElm) { throw new Error(`dom ${rootContainer} is not found`); } fakeCE = rootElm; fakeCE._nonce = extraOptions == null ? void 0 : extraOptions.nonce; fakeCE._instance = null; fakeCE._injectChildStyle = function(comp) { this._applyStyles(comp.styles, comp); }; fakeCE._removeChildStyle = () => { }; fakeCE._styleChildren = /* @__PURE__ */ new WeakSet(); fakeCE._applyStyles = function(styles2, owner) { if (!styles2) return; if (owner) { if (owner === rootComponent || this._styleChildren.has(owner)) { return; } this._styleChildren.add(owner); } const nonce = this._nonce; for (let i = styles2.length - 1; i >= 0; i--) { const s = document.createElement("style"); if (nonce) s.setAttribute("nonce", nonce); s.textContent = styles2[i]; this.shadowRoot.prepend(s); } }; shadowRoot = rootElm.attachShadow({ mode: "open" }); const { styles } = Comp; fakeCE._applyStyles(styles); const appRoot = document.createElement("div"); shadowRoot.appendChild(appRoot); return rawApp.mount(appRoot, isHydrate, isSVG); }; converted.use = (plugin, ...args) => { rawApp.use(plugin, ...args); return converted; }; return converted; } export { createShadowApp };