@enquio/vue-popup 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,107 +1,78 @@
1
- # @enquio/vue
1
+ # @enquio/vue-popup
2
2
 
3
- Vue 3 wrapper component for the Enquio popup Web Component. Provides a Vue-idiomatic interface to integrate Enquio popups into your Vue applications.
3
+ See the [installation prerequisites](../../docs/installation.md), [support matrix](../../docs/support-matrix.md) and [troubleshooting](../../docs/troubleshooting.md). Registry commands assume a matching published release; local verification uses tarballs and does not establish npm/CDN availability.
4
4
 
5
- ## 📦 Installation
5
+ Vue 3 wrapper for the Enquio popup Web Component.
6
6
 
7
- ```bash
8
- npm install @enquio/vue
7
+ ```sh
8
+ npm install @enquio/vue-popup
9
9
  ```
10
10
 
11
- ## ✅ Requirements
11
+ This Options API example works from Vue 3.0 onward:
12
12
 
13
- - **Vue**: ^3.2.0
14
-
15
- ## 🚀 Quick Start
16
-
17
- ### Basic Usage
13
+ <!-- example:vue -->
18
14
 
19
15
  ```vue
20
- <script setup>
21
- import { EnquioPopup } from '@enquio/vue';
16
+ <script lang="ts">
17
+ import { defineComponent } from 'vue';
18
+ import { EnquioPopup } from '@enquio/vue-popup';
22
19
 
23
- const projectId = 'your-project-id';
20
+ export default defineComponent({ components: { EnquioPopup } });
24
21
  </script>
25
22
 
26
23
  <template>
27
- <div>
28
- <h1>My App</h1>
29
- <EnquioPopup :projectId="projectId" />
30
- </div>
24
+ <EnquioPopup project-id="YOUR_PROJECT_ID" />
31
25
  </template>
32
26
  ```
33
27
 
34
- ### With Composition API
28
+ `projectId` is a required string. Changes update the custom element's `project-id` attribute. The named component export and default plugin (`app.use(EnquioPlugin)`) remain available. The plugin registers `EnquioPopup` globally; locally importing the component provides template type checking without manual ambient declarations.
35
29
 
36
- ```vue
37
- <script setup>
38
- import { ref } from 'vue';
39
- import { EnquioPopup } from '@enquio/vue';
30
+ For consent, mount the component only after the host grants permission and unmount it on revocation. Place it outside transformed/clipped ancestors. Use one installation method per document; see the [compatibility contract](../../../EnquioClient/docs/integrations/embed-compatibility.md).
40
31
 
41
- const projectId = ref('your-project-id');
32
+ ## Distribution
42
33
 
43
- const handleSwitch = () => {
44
- projectId.value = 'different-project-id';
45
- };
46
- </script>
34
+ - ESM import: `import EnquioPlugin, { EnquioPopup } from '@enquio/vue-popup'`.
35
+ - CommonJS: `const { EnquioPopup, default: EnquioPlugin } = require('@enquio/vue-popup')`.
36
+ - UMD: load Vue's browser global first, then `dist/index.umd.js`; the exports are available on `window.EnquioVue`.
37
+ - Public declarations are generated from the component using `vue-tsc`, including required props and the plugin's `App` parameter.
47
38
 
48
- <template>
49
- <div>
50
- <button @click="handleSwitch">Switch Project</button>
51
- <EnquioPopup :projectId="projectId" />
52
- </div>
53
- </template>
54
- ```
39
+ The ESM entry is now `dist/index.es.mjs`. Consumers should import the package name and let the manifest select the format. The UMD filename remains unchanged. Vue stays external; the shared core loader is bundled as before and coordinates initialization through window state.
55
40
 
56
- ### With Options API
41
+ Mounting invokes the [shared loader](../core/README.md). Remounts reuse initialization. Loader failures produce a centralized diagnostic without error UI; remount after a transport failure can retry. Imports are safe without browser globals. This is not a Nuxt SSR/hydration guarantee.
57
42
 
58
- ```vue
59
- <script>
60
- import { EnquioPopup } from '@enquio/vue';
61
-
62
- export default {
63
- components: {
64
- EnquioPopup,
65
- },
66
- data() {
67
- return {
68
- projectId: 'your-project-id',
69
- };
70
- },
71
- };
72
- </script>
43
+ ## Supported versions and verification
73
44
 
74
- <template>
75
- <div>
76
- <h1>My App</h1>
77
- <EnquioPopup :projectId="projectId" />
78
- </div>
79
- </template>
80
- ```
45
+ Peer range: **Vue ^3.0.0** (Vue 3.0.0 and newer stable Vue 3 releases, below Vue 4). Vue 3.0 was released on [18 September 2020](https://news.vuejs.org/issues/186).
81
46
 
82
- ## 📖 API
47
+ Locally verified on 2026-09-25 with Node 24.21.0 and Chromium, Firefox and WebKit through Playwright 1.62.1:
83
48
 
84
- ### `EnquioPopup`
49
+ | Vue runtime | TypeScript | vue-tsc | Production consumer |
50
+ | ----------- | ---------- | ------- | ----------------------------------- |
51
+ | 3.0.0 | 4.7.4 | 1.8.27 | SFC compiler 3.0.0 + esbuild 0.27.3 |
52
+ | 3.2.0 | 4.7.4 | 1.8.27 | Vite 2.9.18 + Vue plugin 1.10.2 |
53
+ | 3.5.43 | 5.9.3 | 3.3.11 | Vite 8.0.5 + Vue plugin 6.0.9 |
85
54
 
86
- A Vue component that renders the Enquio popup Web Component.
55
+ The older Vue declarations are not compatible with TypeScript 5.9.3; the legacy rows deliberately use compatible TypeScript versions. All template checks use `skipLibCheck: false`. The matrix covers representative releases and the minimum boundary, not every patch or toolchain combination.
87
56
 
88
- #### Props
57
+ From the workspace root:
89
58
 
90
- | Prop | Type | Required | Description |
91
- |------|------|----------|-------------|
92
- | `projectId` | `string` | Yes | Your Enquio project ID |
59
+ ```sh
60
+ npm ci
61
+ npx playwright install chromium firefox webkit
62
+ npm run test:vue-package
63
+ ```
93
64
 
94
- #### Example
65
+ The runner builds and packs core and Vue, installs the tarballs outside the workspace and verifies:
95
66
 
96
- ```vue
97
- <EnquioPopup projectId="abc-123-def-456" />
98
- ```
67
+ - All declared distribution entries and native ESM/CommonJS imports without DOM globals.
68
+ - A real Vue template accepts the component with a string `projectId` and rejects missing or numeric values.
69
+ - Production consumer builds and direct browser UMD exports/plugin registration.
70
+ - ESM production bundles and UMD: mount, prop updates, unmount/remount before and after readiness, delayed initialization, and transport failure/retry without duplicate initialization or unhandled errors.
99
71
 
100
- ## 🔗 Dependencies
72
+ Registry access is required. Temporary consumers are removed on success and retained on failure. Browser tests simulate the remote runtime and do not verify a published package or live CDN. Vue 2 and Nuxt hydration are outside GC-004. See the [Nuxt example and Docker tests](../../docs/ssr-examples.md).
101
73
 
102
- - `@enquio/core`: Core script loader
103
- - `vue`: Peer dependency (must be installed separately)
74
+ MIT Copyright Enquio Team
104
75
 
105
- ## 📝 License
76
+ ## SSR framework example
106
77
 
107
- MIT © Enquio Team
78
+ In Nuxt SSR, place the existing component inside `<ClientOnly>` in a persistent layout outside changing page content. See the [runnable examples](../../docs/ssr-examples.md) and [support matrix](../../docs/support-matrix.md) for exact scope.
@@ -0,0 +1,9 @@
1
+ import type { DefineComponent } from 'vue';
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
4
+ declare const __VLS_export: DefineComponent<{
5
+ projectId: {
6
+ type: StringConstructor;
7
+ required: true;
8
+ };
9
+ }, {}, {}, {}, {}>;
@@ -0,0 +1,7 @@
1
+ import EnquioPopup from './EnquioPopup.vue';
2
+ import type { App } from 'vue';
3
+ export { EnquioPopup };
4
+ declare const _default: {
5
+ install(app: App): void;
6
+ };
7
+ export default _default;
@@ -0,0 +1,84 @@
1
+ import { defineComponent as e, h as t, onMounted as n } from "vue";
2
+ //#region ../core/dist/index.mjs
3
+ var r = "https://public.newapp.enquio.eu/popup.js", i = "enquio-popup-script", a = 3e4, o = class extends Error {
4
+ constructor(e, t = !1) {
5
+ super(e), this.retryable = t;
6
+ }
7
+ };
8
+ function s(e, t) {
9
+ e.context.reported || (e.context.reported = !0, console.warn("Enquio:", t instanceof Error ? t.message : String(t)));
10
+ }
11
+ function c(e) {
12
+ return window.__ENQUIO_POPUP_BOOTSTRAP__ ? Promise.resolve() : new Promise((t, n) => {
13
+ let a = document.getElementById(i), s, c = !1;
14
+ if (a && !(a instanceof HTMLScriptElement)) {
15
+ n(/* @__PURE__ */ Error("[script] enquio-popup-script is not a script element."));
16
+ return;
17
+ }
18
+ if (a && a !== e.failedScript) s = a;
19
+ else {
20
+ if (s = document.createElement("script"), a) for (let e of Array.from(a.attributes)) s.setAttribute(e.name, e.value);
21
+ s.nonce = a?.nonce || window.__ENQUIO_NONCE__ || "", s.src = r, s.id = i, s.async = !0, a?.remove(), e.failedScript = void 0, c = !0;
22
+ }
23
+ let l = () => {
24
+ s.removeEventListener("load", u), s.removeEventListener("error", d), window.removeEventListener("enquio:ready", f);
25
+ }, u = () => {
26
+ l(), t();
27
+ }, d = () => {
28
+ l(), e.failedScript = s, n(new o("[script] Could not load popup.js.", !0));
29
+ }, f = () => {
30
+ window.__ENQUIO_POPUP_BOOTSTRAP__ && u();
31
+ };
32
+ s.addEventListener("load", u), s.addEventListener("error", d), window.addEventListener("enquio:ready", f), window.__ENQUIO_LOAD_CONTEXT__ = e.context, c && (document.head ?? document.documentElement).appendChild(s);
33
+ });
34
+ }
35
+ function l(e = {}) {
36
+ if (typeof window > "u") return Promise.resolve();
37
+ window.__ENQUIO_NONCE__ ?? (window.__ENQUIO_NONCE__ = e.nonce ?? document.querySelector("script[nonce]")?.nonce);
38
+ let t = window.__ENQUIO_SCRIPT_LOAD__ ?? (window.__ENQUIO_SCRIPT_LOAD__ = { context: { reported: !1 } });
39
+ return t.task ||= (t.context = { reported: !1 }, Promise.resolve().then(async () => {
40
+ let e = window.__ENQUIO_POPUP_BOOTSTRAP__;
41
+ if (!e && customElements.get("enquio-popup")) {
42
+ await window.__ENQUIO_RENDERER_BOOTSTRAP__;
43
+ return;
44
+ }
45
+ await c(t);
46
+ let n = window.__ENQUIO_POPUP_BOOTSTRAP__;
47
+ if (!n) throw Error("[script] popup.js did not initialize its bootstrap controller.");
48
+ let r = e ? n.load(t.context) : n.current;
49
+ if (t.context = n.context, !r) throw Error("[script] popup.js did not start its bootstrap.");
50
+ await r;
51
+ }).catch((e) => {
52
+ throw e instanceof Error && "retryable" in e && e.retryable === !0 && (t.task = void 0), e;
53
+ })), t.wait ||= new Promise((e, n) => {
54
+ let r = window.setTimeout(() => {
55
+ let e = /* @__PURE__ */ Error("[timeout] Renderer was not ready within 30 seconds. Loading may still complete.");
56
+ s(t, e), n(e);
57
+ }, a);
58
+ t.task.then(() => {
59
+ window.clearTimeout(r), e();
60
+ }, (e) => {
61
+ window.clearTimeout(r), s(t, e), n(e);
62
+ });
63
+ }).finally(() => {
64
+ t.wait = void 0;
65
+ }), t.wait;
66
+ }
67
+ //#endregion
68
+ //#region src/EnquioPopup.vue
69
+ var u = e({
70
+ name: "EnquioPopup",
71
+ props: { projectId: {
72
+ type: String,
73
+ required: !0
74
+ } },
75
+ setup(e) {
76
+ return n(() => {
77
+ l().catch(() => {});
78
+ }), () => t("enquio-popup", { "project-id": e.projectId });
79
+ }
80
+ }), d = { install(e) {
81
+ e.component("EnquioPopup", u);
82
+ } };
83
+ //#endregion
84
+ export { u as EnquioPopup, d as default };
package/dist/index.umd.js CHANGED
@@ -1 +1 @@
1
- (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`vue`)):typeof define==`function`&&define.amd?define([`exports`,`vue`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.EnquioVue={},e.Vue))})(this,function(e,t){Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var n=`https://public.newapp.enquio.eu/popup.js`;function r(){return typeof window>`u`?Promise.resolve():(window.__ENQUIO_SCRIPT_PROMISE__||(window.__ENQUIO_SCRIPT_PROMISE__=new Promise((e,t)=>{if(document.getElementById(`enquio-popup-script`)){e();return}let r=document.createElement(`script`);r.src=n,r.async=!0,r.id=`enquio-popup-script`,r.onload=()=>e(),r.onerror=()=>t(Error(`Failed to load Enquio popup`)),document.body.appendChild(r)})),window.__ENQUIO_SCRIPT_PROMISE__)}var i=(0,t.defineComponent)({name:`EnquioPopup`,props:{projectId:{type:String,required:!0}},setup(e){return(0,t.onMounted)(()=>{r().then(()=>customElements.whenDefined(`enquio-popup`)).catch(e=>console.error(`Enquio: script failed to load`,e))}),()=>(0,t.h)(`enquio-popup`,{"project-id":e.projectId})}});e.EnquioPopup=i,e.default={install(e){e.component(`EnquioPopup`,i)}}});
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`vue`)):typeof define==`function`&&define.amd?define([`exports`,`vue`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.EnquioVue={},e.Vue))})(this,function(e,t){Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var n=`https://public.newapp.enquio.eu/popup.js`,r=`enquio-popup-script`,i=3e4,a=class extends Error{constructor(e,t=!1){super(e),this.retryable=t}};function o(e,t){e.context.reported||(e.context.reported=!0,console.warn(`Enquio:`,t instanceof Error?t.message:String(t)))}function s(e){return window.__ENQUIO_POPUP_BOOTSTRAP__?Promise.resolve():new Promise((t,i)=>{let o=document.getElementById(r),s,c=!1;if(o&&!(o instanceof HTMLScriptElement)){i(Error(`[script] enquio-popup-script is not a script element.`));return}if(o&&o!==e.failedScript)s=o;else{if(s=document.createElement(`script`),o)for(let e of Array.from(o.attributes))s.setAttribute(e.name,e.value);s.nonce=o?.nonce||window.__ENQUIO_NONCE__||``,s.src=n,s.id=r,s.async=!0,o?.remove(),e.failedScript=void 0,c=!0}let l=()=>{s.removeEventListener(`load`,u),s.removeEventListener(`error`,d),window.removeEventListener(`enquio:ready`,f)},u=()=>{l(),t()},d=()=>{l(),e.failedScript=s,i(new a(`[script] Could not load popup.js.`,!0))},f=()=>{window.__ENQUIO_POPUP_BOOTSTRAP__&&u()};s.addEventListener(`load`,u),s.addEventListener(`error`,d),window.addEventListener(`enquio:ready`,f),window.__ENQUIO_LOAD_CONTEXT__=e.context,c&&(document.head??document.documentElement).appendChild(s)})}function c(e={}){if(typeof window>`u`)return Promise.resolve();window.__ENQUIO_NONCE__??(window.__ENQUIO_NONCE__=e.nonce??document.querySelector(`script[nonce]`)?.nonce);let t=window.__ENQUIO_SCRIPT_LOAD__??(window.__ENQUIO_SCRIPT_LOAD__={context:{reported:!1}});return t.task||=(t.context={reported:!1},Promise.resolve().then(async()=>{let e=window.__ENQUIO_POPUP_BOOTSTRAP__;if(!e&&customElements.get(`enquio-popup`)){await window.__ENQUIO_RENDERER_BOOTSTRAP__;return}await s(t);let n=window.__ENQUIO_POPUP_BOOTSTRAP__;if(!n)throw Error(`[script] popup.js did not initialize its bootstrap controller.`);let r=e?n.load(t.context):n.current;if(t.context=n.context,!r)throw Error(`[script] popup.js did not start its bootstrap.`);await r}).catch(e=>{throw e instanceof Error&&`retryable`in e&&e.retryable===!0&&(t.task=void 0),e})),t.wait||=new Promise((e,n)=>{let r=window.setTimeout(()=>{let e=Error(`[timeout] Renderer was not ready within 30 seconds. Loading may still complete.`);o(t,e),n(e)},i);t.task.then(()=>{window.clearTimeout(r),e()},e=>{window.clearTimeout(r),o(t,e),n(e)})}).finally(()=>{t.wait=void 0}),t.wait}var l=(0,t.defineComponent)({name:`EnquioPopup`,props:{projectId:{type:String,required:!0}},setup(e){return(0,t.onMounted)(()=>{c().catch(()=>{})}),()=>(0,t.h)(`enquio-popup`,{"project-id":e.projectId})}});e.EnquioPopup=l,e.default={install(e){e.component(`EnquioPopup`,l)}}});
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@enquio/vue-popup",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Vue 3 popup component for Enquio Web Component",
5
5
  "main": "dist/index.umd.js",
6
- "module": "dist/index.es.js",
6
+ "module": "dist/index.es.mjs",
7
7
  "types": "dist/index.d.ts",
8
8
  "files": [
9
9
  "dist"
@@ -29,20 +29,28 @@
29
29
  "license": "MIT",
30
30
  "author": "Enquio Team",
31
31
  "peerDependencies": {
32
- "vue": "^3.2.0"
32
+ "vue": "^3.0.0"
33
33
  },
34
34
  "devDependencies": {
35
- "vue": "^3.2.0",
35
+ "vue": "3.5.43",
36
36
  "vite": "8.0.5",
37
37
  "typescript": "^5.0.0",
38
- "@vitejs/plugin-vue": "^5.0.0"
38
+ "@vitejs/plugin-vue": "6.0.9",
39
+ "vue-tsc": "3.3.11"
39
40
  },
40
41
  "dependencies": {
41
- "@enquio/popup-core": "1.0.0"
42
+ "@enquio/popup-core": "1.1.0"
42
43
  },
43
44
  "scripts": {
44
- "build": "vite build",
45
+ "build": "vite build && vue-tsc -p tsconfig.build.json",
45
46
  "clean": "rm -rf dist",
46
47
  "prepublishOnly": "npm run build"
48
+ },
49
+ "exports": {
50
+ ".": {
51
+ "types": "./dist/index.d.ts",
52
+ "import": "./dist/index.es.mjs",
53
+ "require": "./dist/index.umd.js"
54
+ }
47
55
  }
48
56
  }
package/dist/index.es.js DELETED
@@ -1,31 +0,0 @@
1
- import { defineComponent as e, h as t, onMounted as n } from "vue";
2
- //#region ../core/dist/loader.js
3
- var r = "https://public.newapp.enquio.eu/popup.js";
4
- function i() {
5
- return typeof window > "u" ? Promise.resolve() : (window.__ENQUIO_SCRIPT_PROMISE__ || (window.__ENQUIO_SCRIPT_PROMISE__ = new Promise((e, t) => {
6
- if (document.getElementById("enquio-popup-script")) {
7
- e();
8
- return;
9
- }
10
- let n = document.createElement("script");
11
- n.src = r, n.async = !0, n.id = "enquio-popup-script", n.onload = () => e(), n.onerror = () => t(/* @__PURE__ */ Error("Failed to load Enquio popup")), document.body.appendChild(n);
12
- })), window.__ENQUIO_SCRIPT_PROMISE__);
13
- }
14
- //#endregion
15
- //#region src/EnquioPopup.vue
16
- var a = e({
17
- name: "EnquioPopup",
18
- props: { projectId: {
19
- type: String,
20
- required: !0
21
- } },
22
- setup(e) {
23
- return n(() => {
24
- i().then(() => customElements.whenDefined("enquio-popup")).catch((e) => console.error("Enquio: script failed to load", e));
25
- }), () => t("enquio-popup", { "project-id": e.projectId });
26
- }
27
- }), o = { install(e) {
28
- e.component("EnquioPopup", a);
29
- } };
30
- //#endregion
31
- export { a as EnquioPopup, o as default };