diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c5dcbe..78d51e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format ## [Unreleased] +## [1.6.0] - 13.06.2024 +### Added +- Added support for SFC custom elements + ## [1.5.1] - 12.06.2024 ### Fixed - Fixed issue with HMR in Vite.js diff --git a/README.md b/README.md index 50223a2..2d86039 100644 --- a/README.md +++ b/README.md @@ -276,7 +276,24 @@ import style from './style.css?raw' If you want to create a web component without shadow DOM, you can set the `disableShadowDOM` option to `true` in the `createWebComponent` function. This will create a web component without shadow DOM encapsulation. This feature uses a patch to the Vue source code, which could lead to some issues with future versions of Vue. If you encounter any issues, please report them in the issues section of this repository. ### Demo without Shadow DOM -[Demo](https://stackblitz.com/~/github.com/EranGrin/web-component-no-shadow-dom-demo) +[Demo Link](https://stackblitz.com/~/github.com/EranGrin/web-component-no-shadow-dom-demo) + + +## SFC as Custom Element +enhance the core functionality of SFC as Custom Element [defineCustomElement](https://vuejs.org/guide/extras/web-components#sfc-as-custom-element) with 2 new features: +1. **Nested Components**: You can use nested components with styles and for example share base components between multiple custom elements. +2. **Shadow DOM option**: You can disable shadow DOM for the SFC custom element. + +### Usage +```javascript +// main.js +import { defineCustomElementSFC } from 'vue-web-component-wrapper'; +const MyComponentElement = defineCustomElementSFC(MyComponent, {shadowRoot: false}) +customElements.define('my-component', MyComponentElement) +``` + +### Demo +[Demo Link](https://stackblitz.com/edit/vue-web-component-wrapper?file=README.md&startScript=sfc-demo) ## Tips diff --git a/demo-SFC-vite/src/main.ts b/demo-SFC-vite/src/main.ts index 6a9a4d6..e884e05 100644 --- a/demo-SFC-vite/src/main.ts +++ b/demo-SFC-vite/src/main.ts @@ -1,5 +1,4 @@ import { defineCustomElementSFC } from '../../package/index.js' -// import { defineCustomElement } from 'vue' import MyComponent from './MyComponent.ce.vue' const MyComponentElement = defineCustomElementSFC(MyComponent, {shadowRoot: false}) diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js index 4d4041a..7add2b2 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.js @@ -21,6 +21,7 @@ export default { { text: 'event-emitting', link: '/event-emitting' }, { text: 'disable-shadow-dom', link: '/disable-shadow-dom' }, { text: 'host-implementation', link: '/host-implementation' }, + { text: 'SFC as Custom Element', link: '/sfc-as-custom-element' }, ], }, { diff --git a/docs/sfc-as-custom-element.md b/docs/sfc-as-custom-element.md new file mode 100644 index 0000000..29e8cca --- /dev/null +++ b/docs/sfc-as-custom-element.md @@ -0,0 +1,34 @@ + + +## SFC as Custom Element + +This section explains how to enhance the core functionality of SFC (Single File Component) as a Custom Element using the `defineCustomElementSFC` method. It introduces two new features: **Nested Components** and **Shadow DOM option**. + +### Nested Components + +With the SFC as Custom Element approach, you can use nested components with styles and share base components between multiple custom elements. This allows for better code organization and reusability. + +### Shadow DOM option + +The SFC custom element supports the option to enable or disable the Shadow DOM. The Shadow DOM provides encapsulation for the component's styles and DOM structure, preventing them from affecting the rest of the page. By default, the Shadow DOM is enabled, but you can disable it if needed. + +### Usage + +To use SFC as a Custom Element, follow these steps: + +1. Import the `defineCustomElementSFC` function from the `vue-web-component-wrapper` package. +2. Call the `defineCustomElementSFC` function, passing in your SFC component and an options object. + - The options object can include the `shadowRoot` property, which determines whether the Shadow DOM should be enabled or disabled for the custom element. +3. Use the `customElements.define` method to define your custom element, providing a name for the element and the result of the `defineCustomElementSFC` function. + +### Example + +```javascript +// main.js +import { defineCustomElementSFC } from 'vue-web-component-wrapper'; +const MyComponentElement = defineCustomElementSFC(MyComponent, {shadowRoot: false}) +customElements.define('my-component', MyComponentElement) +``` + +### Demo +[Demo Link](https://stackblitz.com/edit/vue-web-component-wrapper?file=README.md&startScript=sfc-demo) \ No newline at end of file diff --git a/docs/usage.md b/docs/usage.md index b942bb8..24f7add 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -57,6 +57,7 @@ createWebComponent({ createApp, getCurrentInstance, disableStyleRemoval: false, + disableShadowDOM: false, }); ``` Each option in the `createWebComponent` function has a specific purpose: @@ -68,4 +69,5 @@ Each option in the `createWebComponent` function has a specific purpose: - `h`: The `h` function from Vue. - `createApp`: The `createApp` function from Vue. - `getCurrentInstance`: The `getCurrentInstance` function from Vue. -- `disableStyleRemoval`: A boolean value that determines whether or not to remove styles on unmount. This is useful for CSS transitions. \ No newline at end of file +- `disableStyleRemoval`: A boolean value that determines whether or not to remove styles on unmount. This is useful for CSS transitions. +- `disableShadowDOM`: A boolean value that determines whether or not to use Shadow DOM for the web component. \ No newline at end of file diff --git a/package.json b/package.json index 158306c..a50de4d 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "name": "vue-web-component-wrapper", - "version": "1.5.1", + "version": "1.6.0", "description": "A Vue 3 plugin that provides a web component wrapper with styles, seamlessly integrating with Vuex, Vue Router, Vue I18n, and supporting Tailwind CSS and Sass styles.", "repository": { "type": "git", "url": "https://github.com/EranGrin/vue3-web-component-wrapper/tree/main/plugin" }, + "homepage": "https://erangrin.github.io/vue-web-component-wrapper/", "main": "package/dist/vue-web-component-wrapper.umd.js", "module": "package/dist/vue-web-component-wrapper.es.js", "types": "package/types.d.ts", diff --git a/package/dist/vue-web-component-wrapper.es.js b/package/dist/vue-web-component-wrapper.es.js index 24be2ef..fa3bc05 100644 --- a/package/dist/vue-web-component-wrapper.es.js +++ b/package/dist/vue-web-component-wrapper.es.js @@ -1,7 +1,7 @@ var x = Object.defineProperty; -var T = (e, n, t) => n in e ? x(e, n, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[n] = t; -var d = (e, n, t) => (T(e, typeof n != "symbol" ? n + "" : n, t), t); -import { defineComponent as D, nextTick as H, render as O, createVNode as R, h as B } from "vue"; +var T = (e, i, t) => i in e ? x(e, i, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[i] = t; +var d = (e, i, t) => (T(e, typeof i != "symbol" ? i + "" : i, t), t); +import { defineComponent as D, nextTick as R, render as O, createVNode as H, h as B } from "vue"; /** * @vue/shared v3.4.27 * (c) 2018-present Yuxi (Evan) You and Vue contributors @@ -11,20 +11,20 @@ import { defineComponent as D, nextTick as H, render as O, createVNode as R, h a process.env.NODE_ENV !== "production" && Object.freeze({}); process.env.NODE_ENV !== "production" && Object.freeze([]); const $ = Object.assign, N = Array.isArray, K = (e) => typeof e == "string", P = (e) => { - const n = /* @__PURE__ */ Object.create(null); - return (t) => n[t] || (n[t] = e(t)); -}, U = /-(\w)/g, y = P((e) => e.replace(U, (n, t) => t ? t.toUpperCase() : "")), z = /\B([A-Z])/g, m = P( + const i = /* @__PURE__ */ Object.create(null); + return (t) => i[t] || (i[t] = e(t)); +}, U = /-(\w)/g, y = P((e) => e.replace(U, (i, t) => t ? t.toUpperCase() : "")), z = /\B([A-Z])/g, m = P( (e) => e.replace(z, "-$1").toLowerCase() ), g = (e) => { - const n = K(e) ? Number(e) : NaN; - return isNaN(n) ? e : n; + const i = K(e) ? Number(e) : NaN; + return isNaN(i) ? e : i; }; /*! #__NO_SIDE_EFFECTS__ */ -function M(e, n, t) { +function M(e, i, t) { const s = D(e); class o extends E { constructor(r) { - super(s, r, n, t); + super(s, r, i, t); } } return d(o, "def", s), o; @@ -32,7 +32,7 @@ function M(e, n, t) { const k = typeof HTMLElement < "u" ? HTMLElement : class { }; class E extends k { - constructor(t, s = {}, o = {}, i) { + constructor(t, s = {}, o = { shadowRoot: !0 }, n) { super(); /** * @internal @@ -44,7 +44,7 @@ class E extends k { d(this, "_styles"); d(this, "_slots", {}); d(this, "_ob", null); - this._def = t, this._props = s, this._config = o, this._root && i ? i(this._createVNode(), this._root) : (this._config.shadowRoot !== !1 && this.attachShadow({ mode: "open" }), this._def.__asyncLoader || this._resolveProps(this._def)); + this._def = t, this._props = s, this._config = o, this._root && n ? n(this._createVNode(), this._root) : (this._config.shadowRoot !== !1 && this.attachShadow({ mode: "open" }), this._def.__asyncLoader || this._resolveProps(this._def)); } get _root() { return this._config.shadowRoot ? this.shadowRoot : this; @@ -53,7 +53,7 @@ class E extends k { this._connected = !0, this._instance || (this._resolved ? this._update() : this._resolveDef()); } disconnectedCallback() { - this._connected = !1, H(() => { + this._connected = !1, R(() => { this._connected || (this._ob && (this._ob.disconnect(), this._ob = null), O(null, this._root), this._instance = null); }); } @@ -65,22 +65,22 @@ class E extends k { for (let o = 0; o < this.attributes.length; o++) this._setAttr(this.attributes[o].name); this._ob = new MutationObserver((o) => { - for (const i of o) - this._setAttr(i.attributeName); + for (const n of o) + this._setAttr(n.attributeName); }), this._ob.observe(this, { attributes: !0 }); - const t = (o, i = !1) => { + const t = (o, n = !1) => { const { props: r } = o, p = this._collectNestedStyles(o); let f; if (r && !N(r)) for (const a in r) { - const h = r[a]; - (h === Number || h && h.type === Number) && (a in this._props && (this._props[a] = g(this._props[a])), (f || (f = /* @__PURE__ */ Object.create(null)))[y(a)] = !0); + const _ = r[a]; + (_ === Number || _ && _.type === Number) && (a in this._props && (this._props[a] = g(this._props[a])), (f || (f = /* @__PURE__ */ Object.create(null)))[y(a)] = !0); } - if (this._numberProps = f, i && this._resolveProps(o), !this._config.shadowRoot) { + if (this._numberProps = f, n && this._resolveProps(o), !this._config.shadowRoot) { this._slots = {}; for (const a of Array.from(this.children)) { - const h = a.getAttribute("slot") || "default"; - this._slots[h] || (this._slots[h] = []), this._slots[h].push( + const _ = a.getAttribute("slot") || "default"; + this._slots[_] || (this._slots[_] = []), this._slots[_].push( B(a.tagName.toLowerCase(), {}, a.innerHTML) ); } @@ -92,15 +92,15 @@ class E extends k { } _resolveProps(t) { const { props: s } = t, o = N(s) ? s : Object.keys(s || {}); - for (const i of Object.keys(this)) - i[0] !== "_" && o.includes(i) && this._setProp(i, this[i], !0, !1); - for (const i of o.map(y)) - Object.defineProperty(this, i, { + for (const n of Object.keys(this)) + n[0] !== "_" && o.includes(n) && this._setProp(n, this[n], !0, !1); + for (const n of o.map(y)) + Object.defineProperty(this, n, { get() { - return this._getProp(i); + return this._getProp(n); }, set(r) { - this._setProp(i, r); + this._setProp(n, r); } }); } @@ -118,14 +118,14 @@ class E extends k { /** * @internal */ - _setProp(t, s, o = !0, i = !0) { - s !== this._props[t] && (this._props[t] = s, i && this._instance && this._update(), o && (s === !0 ? this.setAttribute(m(t), "") : typeof s == "string" || typeof s == "number" ? this.setAttribute(m(t), s + "") : s || this.removeAttribute(m(t)))); + _setProp(t, s, o = !0, n = !0) { + s !== this._props[t] && (this._props[t] = s, n && this._instance && this._update(), o && (s === !0 ? this.setAttribute(m(t), "") : typeof s == "string" || typeof s == "number" ? this.setAttribute(m(t), s + "") : s || this.removeAttribute(m(t)))); } _update() { O(this._createVNode(), this._root); } _createVNode() { - const t = R(this._def, $({}, this._props), this._slots); + const t = H(this._def, $({}, this._props), this._slots); return this._instance || (t.ce = (s) => { this._instance = s, s.isCE = !0; const o = (r, p) => { @@ -138,10 +138,10 @@ class E extends k { s.emit = (r, ...p) => { o(r, p), m(r) !== r && o(m(r), p); }; - let i = this; - for (; i = i && (i.parentNode || i.host); ) - if (i instanceof E) { - s.parent = i._instance, s.provides = i._instance.provides; + let n = this; + for (; n = n && (n.parentNode || n.host); ) + if (n instanceof E) { + s.parent = n._instance, s.provides = n._instance.provides; break; } }), t; @@ -159,7 +159,7 @@ class E extends k { }), s; } } -const G = (e) => { +const C = (e) => { for (; (e == null ? void 0 : e.nodeType) !== 1; ) { if (!e.parentElement) throw new Error( @@ -172,13 +172,13 @@ const G = (e) => { function F(e) { return "on" + e.charAt(0).toUpperCase() + e.slice(1); } -const q = ({ +const G = ({ rootComponent: e, - plugins: n, + plugins: i, cssFrameworkStyles: t, VueDefineCustomElement: s, h: o, - createApp: i, + createApp: n, getCurrentInstance: r, elementName: p, disableRemoveStylesOnUnmount: f, @@ -191,20 +191,20 @@ const q = ({ // v-model support }, emits: e == null ? void 0 : e.emits, - setup(A, { slots: S }) { + setup(S, { slots: A }) { var w; - const v = [...(e == null ? void 0 : e.emits) || [], "update:modelValue"], _ = i(); - if (_.component("app-root", e), e.provide) { + const v = [...(e == null ? void 0 : e.emits) || [], "update:modelValue"], h = n(); + if (h.component("app-root", e), e.provide) { const c = typeof e.provide == "function" ? e.provide() : e.provide; Object.keys(c).forEach((l) => { - _.provide(l, c[l]); + h.provide(l, c[l]); }); } - _.mixin({ + h.mixin({ mounted() { var l; const c = (u) => { - u != null && u.length && (this.__style = document.createElement("style"), this.__style.innerText = u.join().replace(/\n/g, ""), G(this.$el).prepend(this.__style)); + u != null && u.length && (this.__style = document.createElement("style"), this.__style.innerText = u.join().replace(/\n/g, ""), C(this.$el).prepend(this.__style)); }; if (c((l = this.$) == null ? void 0 : l.type.styles), this.$options.components) for (const u of Object.values(this.$options.components)) @@ -214,18 +214,18 @@ const q = ({ var c; f || (c = this.__style) == null || c.remove(); } - }), _.use(n); + }), h.use(i); const b = r(); - if (Object.assign(b.appContext, _._context), Object.assign(b.provides, _._context.provides), process.env.NODE_ENV === "development" && window.__VUE_DEVTOOLS_GLOBAL_HOOK__) { + if (Object.assign(b.appContext, h._context), Object.assign(b.provides, h._context.provides), process.env.NODE_ENV === "development" && window.__VUE_DEVTOOLS_GLOBAL_HOOK__) { const c = document.querySelector(p); - _._container = c, _._instance = b; + h._container = c, h._instance = b; const l = { Comment: Symbol("v-cmt"), Fragment: Symbol("v-fgt"), Static: Symbol("v-stc"), Text: Symbol("v-txt") }; - window.__VUE_DEVTOOLS_GLOBAL_HOOK__.emit("app:init", _, _.version, l), window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue = _; + window.__VUE_DEVTOOLS_GLOBAL_HOOK__.emit("app:init", h, h.version, l), window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue = h; } const L = v == null ? void 0 : v.reduce((c, l) => { const u = F(l); @@ -236,29 +236,29 @@ const q = ({ return () => o( e, { - ...A, + ...S, ...L }, { default: () => o("slot"), ...V, - ...S + ...A } ); } }, a && { shadowRoot: !1 }), W = ({ elementName: e, - rootComponent: n, + rootComponent: i, plugins: t, cssFrameworkStyles: s, VueDefineCustomElement: o, - h: i, + h: n, createApp: r, getCurrentInstance: p, disableRemoveStylesOnUnmount: f = !1, disableShadowDOM: a = !1 }) => { - if (!n) { + if (!i) { console.warn("No root component provided. Please provide a root component to create a web component."); return; } @@ -272,7 +272,7 @@ const q = ({ ); return; } - if (!i) { + if (!n) { console.warn("No h provided. Please provide an h to create a web component."); return; } @@ -284,12 +284,12 @@ const q = ({ console.warn("No getCurrentInstance provided. Please provide a getCurrentInstance to create a web component."); return; } - const h = q({ - rootComponent: n, + const _ = G({ + rootComponent: i, plugins: t, cssFrameworkStyles: s, VueDefineCustomElement: o, - h: i, + h: n, createApp: r, getCurrentInstance: p, elementName: e, @@ -298,10 +298,12 @@ const q = ({ }); customElements.define( e, - h + _ ); }; export { W as createWebComponent, - W as default + W as default, + G as defineCustomElement, + M as defineCustomElementSFC }; diff --git a/package/dist/vue-web-component-wrapper.umd.js b/package/dist/vue-web-component-wrapper.umd.js index 1a2cc8c..fb037eb 100644 --- a/package/dist/vue-web-component-wrapper.umd.js +++ b/package/dist/vue-web-component-wrapper.umd.js @@ -1,5 +1,5 @@ -(function(a,r){typeof exports=="object"&&typeof module<"u"?r(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],r):(a=typeof globalThis<"u"?globalThis:a||self,r(a.Vue3WebComponentWrapper={},a.Vue))})(this,function(a,r){"use strict";var W=Object.defineProperty;var k=(a,r,b)=>r in a?W(a,r,{enumerable:!0,configurable:!0,writable:!0,value:b}):a[r]=b;var f=(a,r,b)=>(k(a,typeof r!="symbol"?r+"":r,b),b);/** +(function(c,r){typeof exports=="object"&&typeof module<"u"?r(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],r):(c=typeof globalThis<"u"?globalThis:c||self,r(c.Vue3WebComponentWrapper={},c.Vue))})(this,function(c,r){"use strict";var z=Object.defineProperty;var W=(c,r,b)=>r in c?z(c,r,{enumerable:!0,configurable:!0,writable:!0,value:b}):c[r]=b;var f=(c,r,b)=>(W(c,typeof r!="symbol"?r+"":r,b),b);/** * @vue/shared v3.4.27 * (c) 2018-present Yuxi (Evan) You and Vue contributors * @license MIT -**//*! #__NO_SIDE_EFFECTS__ */process.env.NODE_ENV!=="production"&&Object.freeze({}),process.env.NODE_ENV!=="production"&&Object.freeze([]);const b=Object.assign,g=Array.isArray,j=e=>typeof e=="string",P=e=>{const l=Object.create(null);return t=>l[t]||(l[t]=e(t))},L=/-(\w)/g,O=P(e=>e.replace(L,(l,t)=>t?t.toUpperCase():"")),T=/\B([A-Z])/g,v=P(e=>e.replace(T,"-$1").toLowerCase()),S=e=>{const l=j(e)?Number(e):NaN;return isNaN(l)?e:l};/*! #__NO_SIDE_EFFECTS__ */function x(e,l,t){const s=r.defineComponent(e);class n extends w{constructor(i){super(s,i,l,t)}}return f(n,"def",s),n}const D=typeof HTMLElement<"u"?HTMLElement:class{};class w extends D{constructor(t,s={},n={},o){super();f(this,"_instance",null);f(this,"_connected",!1);f(this,"_resolved",!1);f(this,"_numberProps",null);f(this,"_styles");f(this,"_slots",{});f(this,"_ob",null);this._def=t,this._props=s,this._config=n,this._root&&o?o(this._createVNode(),this._root):(this._config.shadowRoot!==!1&&this.attachShadow({mode:"open"}),this._def.__asyncLoader||this._resolveProps(this._def))}get _root(){return this._config.shadowRoot?this.shadowRoot:this}connectedCallback(){this._connected=!0,this._instance||(this._resolved?this._update():this._resolveDef())}disconnectedCallback(){this._connected=!1,r.nextTick(()=>{this._connected||(this._ob&&(this._ob.disconnect(),this._ob=null),r.render(null,this._root),this._instance=null)})}_resolveDef(){this._resolved=!0;for(let n=0;n{for(const o of n)this._setAttr(o.attributeName)}),this._ob.observe(this,{attributes:!0});const t=(n,o=!1)=>{const{props:i}=n,h=this._collectNestedStyles(n);let y;if(i&&!g(i))for(const p in i){const u=i[p];(u===Number||u&&u.type===Number)&&(p in this._props&&(this._props[p]=S(this._props[p])),(y||(y=Object.create(null)))[O(p)]=!0)}if(this._numberProps=y,o&&this._resolveProps(n),!this._config.shadowRoot){this._slots={};for(const p of Array.from(this.children)){const u=p.getAttribute("slot")||"default";this._slots[u]||(this._slots[u]=[]),this._slots[u].push(r.h(p.tagName.toLowerCase(),{},p.innerHTML))}this.replaceChildren()}this._applyStyles(h),this._update()},s=this._def.__asyncLoader;s?s().then(n=>t(n,!0)):t(this._def)}_resolveProps(t){const{props:s}=t,n=g(s)?s:Object.keys(s||{});for(const o of Object.keys(this))o[0]!=="_"&&n.includes(o)&&this._setProp(o,this[o],!0,!1);for(const o of n.map(O))Object.defineProperty(this,o,{get(){return this._getProp(o)},set(i){this._setProp(o,i)}})}_setAttr(t){let s=this.hasAttribute(t)?this.getAttribute(t):void 0;const n=O(t);this._numberProps&&this._numberProps[n]&&(s=S(s)),this._setProp(n,s,!1)}_getProp(t){return this._props[t]}_setProp(t,s,n=!0,o=!0){s!==this._props[t]&&(this._props[t]=s,o&&this._instance&&this._update(),n&&(s===!0?this.setAttribute(v(t),""):typeof s=="string"||typeof s=="number"?this.setAttribute(v(t),s+""):s||this.removeAttribute(v(t))))}_update(){r.render(this._createVNode(),this._root)}_createVNode(){const t=r.createVNode(this._def,b({},this._props),this._slots);return this._instance||(t.ce=s=>{this._instance=s,s.isCE=!0;const n=(i,h)=>{this.dispatchEvent(new CustomEvent(i,{detail:h}))};s.emit=(i,...h)=>{n(i,h),v(i)!==i&&n(v(i),h)};let o=this;for(;o=o&&(o.parentNode||o.host);)if(o instanceof w){s.parent=o._instance,s.provides=o._instance.provides;break}}),t}_applyStyles(t){t&&t.forEach(s=>{const n=document.createElement("style");n.textContent=s,this._root.appendChild(n)})}_collectNestedStyles(t){let s=t.styles??[];return t.components&&Object.values(t.components).forEach(n=>{s=s.concat(this._collectNestedStyles(n))}),s}}const H=e=>{for(;(e==null?void 0:e.nodeType)!==1;){if(!e.parentElement)throw new Error("No parent element found, the rootComponent must be wrapped in a HTML element (e.g. )");e=e.parentElement}return e};function R(e){return"on"+e.charAt(0).toUpperCase()+e.slice(1)}const B=({rootComponent:e,plugins:l,cssFrameworkStyles:t,VueDefineCustomElement:s,h:n,createApp:o,getCurrentInstance:i,elementName:h,disableRemoveStylesOnUnmount:y,disableShadowDOM:p})=>(p?x:s)({styles:[t],props:{...e.props,modelValue:{type:[String,Number,Boolean,Array,Object]}},emits:e==null?void 0:e.emits,setup(M,{slots:$}){var V;const N=[...(e==null?void 0:e.emits)||[],"update:modelValue"],_=o();if(_.component("app-root",e),e.provide){const c=typeof e.provide=="function"?e.provide():e.provide;Object.keys(c).forEach(d=>{_.provide(d,c[d])})}_.mixin({mounted(){var d;const c=m=>{m!=null&&m.length&&(this.__style=document.createElement("style"),this.__style.innerText=m.join().replace(/\n/g,""),H(this.$el).prepend(this.__style))};if(c((d=this.$)==null?void 0:d.type.styles),this.$options.components)for(const m of Object.values(this.$options.components))c(m.styles)},unmounted(){var c;y||(c=this.__style)==null||c.remove()}}),_.use(l);const E=i();if(Object.assign(E.appContext,_._context),Object.assign(E.provides,_._context.provides),process.env.NODE_ENV==="development"&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__){const c=document.querySelector(h);_._container=c,_._instance=E;const d={Comment:Symbol("v-cmt"),Fragment:Symbol("v-fgt"),Static:Symbol("v-stc"),Text:Symbol("v-txt")};window.__VUE_DEVTOOLS_GLOBAL_HOOK__.emit("app:init",_,_.version,d),window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue=_}const K=N==null?void 0:N.reduce((c,d)=>{const m=R(d);return c[m]=z=>{E.emit(d,z)},c},{}),U=(V=e==null?void 0:e.namedSlots)==null?void 0:V.reduce((c,d)=>(c[d]=()=>n("slot",{name:d}),c),{});return()=>n(e,{...M,...K},{default:()=>n("slot"),...U,...$})}},p&&{shadowRoot:!1}),A=({elementName:e,rootComponent:l,plugins:t,cssFrameworkStyles:s,VueDefineCustomElement:n,h:o,createApp:i,getCurrentInstance:h,disableRemoveStylesOnUnmount:y=!1,disableShadowDOM:p=!1})=>{if(!l){console.warn("No root component provided. Please provide a root component to create a web component.");return}if(!e){console.warn("No element name provided. Please provide an element name to create a web component.");return}if(!n){console.warn("No VueDefineCustomElement provided. Please provide a VueDefineCustomElement to create a web component.");return}if(!o){console.warn("No h provided. Please provide an h to create a web component.");return}if(!i){console.warn("No createApp provided. Please provide a createApp to create a web component.");return}if(!h){console.warn("No getCurrentInstance provided. Please provide a getCurrentInstance to create a web component.");return}const u=B({rootComponent:l,plugins:t,cssFrameworkStyles:s,VueDefineCustomElement:n,h:o,createApp:i,getCurrentInstance:h,elementName:e,disableRemoveStylesOnUnmount:y,disableShadowDOM:p});customElements.define(e,u)};a.createWebComponent=A,a.default=A,Object.defineProperties(a,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); +**//*! #__NO_SIDE_EFFECTS__ */process.env.NODE_ENV!=="production"&&Object.freeze({}),process.env.NODE_ENV!=="production"&&Object.freeze([]);const b=Object.assign,g=Array.isArray,T=e=>typeof e=="string",P=e=>{const l=Object.create(null);return t=>l[t]||(l[t]=e(t))},x=/-(\w)/g,w=P(e=>e.replace(x,(l,t)=>t?t.toUpperCase():"")),D=/\B([A-Z])/g,v=P(e=>e.replace(D,"-$1").toLowerCase()),S=e=>{const l=T(e)?Number(e):NaN;return isNaN(l)?e:l};/*! #__NO_SIDE_EFFECTS__ */function A(e,l,t){const s=r.defineComponent(e);class n extends O{constructor(i){super(s,i,l,t)}}return f(n,"def",s),n}const R=typeof HTMLElement<"u"?HTMLElement:class{};class O extends R{constructor(t,s={},n={shadowRoot:!0},o){super();f(this,"_instance",null);f(this,"_connected",!1);f(this,"_resolved",!1);f(this,"_numberProps",null);f(this,"_styles");f(this,"_slots",{});f(this,"_ob",null);this._def=t,this._props=s,this._config=n,this._root&&o?o(this._createVNode(),this._root):(this._config.shadowRoot!==!1&&this.attachShadow({mode:"open"}),this._def.__asyncLoader||this._resolveProps(this._def))}get _root(){return this._config.shadowRoot?this.shadowRoot:this}connectedCallback(){this._connected=!0,this._instance||(this._resolved?this._update():this._resolveDef())}disconnectedCallback(){this._connected=!1,r.nextTick(()=>{this._connected||(this._ob&&(this._ob.disconnect(),this._ob=null),r.render(null,this._root),this._instance=null)})}_resolveDef(){this._resolved=!0;for(let n=0;n{for(const o of n)this._setAttr(o.attributeName)}),this._ob.observe(this,{attributes:!0});const t=(n,o=!1)=>{const{props:i}=n,u=this._collectNestedStyles(n);let y;if(i&&!g(i))for(const p in i){const _=i[p];(_===Number||_&&_.type===Number)&&(p in this._props&&(this._props[p]=S(this._props[p])),(y||(y=Object.create(null)))[w(p)]=!0)}if(this._numberProps=y,o&&this._resolveProps(n),!this._config.shadowRoot){this._slots={};for(const p of Array.from(this.children)){const _=p.getAttribute("slot")||"default";this._slots[_]||(this._slots[_]=[]),this._slots[_].push(r.h(p.tagName.toLowerCase(),{},p.innerHTML))}this.replaceChildren()}this._applyStyles(u),this._update()},s=this._def.__asyncLoader;s?s().then(n=>t(n,!0)):t(this._def)}_resolveProps(t){const{props:s}=t,n=g(s)?s:Object.keys(s||{});for(const o of Object.keys(this))o[0]!=="_"&&n.includes(o)&&this._setProp(o,this[o],!0,!1);for(const o of n.map(w))Object.defineProperty(this,o,{get(){return this._getProp(o)},set(i){this._setProp(o,i)}})}_setAttr(t){let s=this.hasAttribute(t)?this.getAttribute(t):void 0;const n=w(t);this._numberProps&&this._numberProps[n]&&(s=S(s)),this._setProp(n,s,!1)}_getProp(t){return this._props[t]}_setProp(t,s,n=!0,o=!0){s!==this._props[t]&&(this._props[t]=s,o&&this._instance&&this._update(),n&&(s===!0?this.setAttribute(v(t),""):typeof s=="string"||typeof s=="number"?this.setAttribute(v(t),s+""):s||this.removeAttribute(v(t))))}_update(){r.render(this._createVNode(),this._root)}_createVNode(){const t=r.createVNode(this._def,b({},this._props),this._slots);return this._instance||(t.ce=s=>{this._instance=s,s.isCE=!0;const n=(i,u)=>{this.dispatchEvent(new CustomEvent(i,{detail:u}))};s.emit=(i,...u)=>{n(i,u),v(i)!==i&&n(v(i),u)};let o=this;for(;o=o&&(o.parentNode||o.host);)if(o instanceof O){s.parent=o._instance,s.provides=o._instance.provides;break}}),t}_applyStyles(t){t&&t.forEach(s=>{const n=document.createElement("style");n.textContent=s,this._root.appendChild(n)})}_collectNestedStyles(t){let s=t.styles??[];return t.components&&Object.values(t.components).forEach(n=>{s=s.concat(this._collectNestedStyles(n))}),s}}const H=e=>{for(;(e==null?void 0:e.nodeType)!==1;){if(!e.parentElement)throw new Error("No parent element found, the rootComponent must be wrapped in a HTML element (e.g. )");e=e.parentElement}return e};function B(e){return"on"+e.charAt(0).toUpperCase()+e.slice(1)}const V=({rootComponent:e,plugins:l,cssFrameworkStyles:t,VueDefineCustomElement:s,h:n,createApp:o,getCurrentInstance:i,elementName:u,disableRemoveStylesOnUnmount:y,disableShadowDOM:p})=>(p?A:s)({styles:[t],props:{...e.props,modelValue:{type:[String,Number,Boolean,Array,Object]}},emits:e==null?void 0:e.emits,setup(C,{slots:M}){var L;const N=[...(e==null?void 0:e.emits)||[],"update:modelValue"],h=o();if(h.component("app-root",e),e.provide){const a=typeof e.provide=="function"?e.provide():e.provide;Object.keys(a).forEach(d=>{h.provide(d,a[d])})}h.mixin({mounted(){var d;const a=m=>{m!=null&&m.length&&(this.__style=document.createElement("style"),this.__style.innerText=m.join().replace(/\n/g,""),H(this.$el).prepend(this.__style))};if(a((d=this.$)==null?void 0:d.type.styles),this.$options.components)for(const m of Object.values(this.$options.components))a(m.styles)},unmounted(){var a;y||(a=this.__style)==null||a.remove()}}),h.use(l);const E=i();if(Object.assign(E.appContext,h._context),Object.assign(E.provides,h._context.provides),process.env.NODE_ENV==="development"&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__){const a=document.querySelector(u);h._container=a,h._instance=E;const d={Comment:Symbol("v-cmt"),Fragment:Symbol("v-fgt"),Static:Symbol("v-stc"),Text:Symbol("v-txt")};window.__VUE_DEVTOOLS_GLOBAL_HOOK__.emit("app:init",h,h.version,d),window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue=h}const $=N==null?void 0:N.reduce((a,d)=>{const m=B(d);return a[m]=U=>{E.emit(d,U)},a},{}),K=(L=e==null?void 0:e.namedSlots)==null?void 0:L.reduce((a,d)=>(a[d]=()=>n("slot",{name:d}),a),{});return()=>n(e,{...C,...$},{default:()=>n("slot"),...K,...M})}},p&&{shadowRoot:!1}),j=({elementName:e,rootComponent:l,plugins:t,cssFrameworkStyles:s,VueDefineCustomElement:n,h:o,createApp:i,getCurrentInstance:u,disableRemoveStylesOnUnmount:y=!1,disableShadowDOM:p=!1})=>{if(!l){console.warn("No root component provided. Please provide a root component to create a web component.");return}if(!e){console.warn("No element name provided. Please provide an element name to create a web component.");return}if(!n){console.warn("No VueDefineCustomElement provided. Please provide a VueDefineCustomElement to create a web component.");return}if(!o){console.warn("No h provided. Please provide an h to create a web component.");return}if(!i){console.warn("No createApp provided. Please provide a createApp to create a web component.");return}if(!u){console.warn("No getCurrentInstance provided. Please provide a getCurrentInstance to create a web component.");return}const _=V({rootComponent:l,plugins:t,cssFrameworkStyles:s,VueDefineCustomElement:n,h:o,createApp:i,getCurrentInstance:u,elementName:e,disableRemoveStylesOnUnmount:y,disableShadowDOM:p});customElements.define(e,_)};c.createWebComponent=j,c.default=j,c.defineCustomElement=V,c.defineCustomElementSFC=A,Object.defineProperties(c,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); diff --git a/package/package.json b/package/package.json index 29971d0..4f5df05 100644 --- a/package/package.json +++ b/package/package.json @@ -1,6 +1,6 @@ { "name": "vue-web-component-wrapper", - "version": "1.5.1", + "version": "1.6.0", "description": "A Vue 3 plugin that provides a web component wrapper with styles, seamlessly integrating with Vuex, Vue Router, Vue I18n, and supporting Tailwind CSS and Sass styles.", "types": "types.d.ts", "repository": {