@queuezero/embed 0.1.8 → 0.1.9
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 +23 -0
- package/dist/index.global.js +34 -34
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,6 +41,29 @@ Mounts a complete waitlist widget (form + status + referral share) to the specif
|
|
|
41
41
|
| `elementId` | `string` | ID of the container element |
|
|
42
42
|
| `campaignSlug` | `string` | Your campaign identifier |
|
|
43
43
|
| `options.apiUrl` | `string` | API endpoint URL |
|
|
44
|
+
| `options.displayMode` | `'inline' \| 'modal'` | Display as inline form or modal (default: `'inline'`) |
|
|
45
|
+
| `options.modalOptions` | `object` | Modal configuration (only when `displayMode: 'modal'`) |
|
|
46
|
+
| `options.modalOptions.triggerText` | `string` | Button text (default: `'Join Waitlist'`) |
|
|
47
|
+
| `options.modalOptions.size` | `'sm' \| 'md' \| 'lg'` | Modal width (default: `'md'`) |
|
|
48
|
+
|
|
49
|
+
### Modal Mode Example
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<div id="queuezero-waitlist"></div>
|
|
53
|
+
<script src="https://cdn.jsdelivr.net/npm/@queuezero/embed@latest/dist/index.global.js"></script>
|
|
54
|
+
<script>
|
|
55
|
+
QueueZero.init('queuezero-waitlist', 'your-campaign-slug', {
|
|
56
|
+
apiUrl: 'https://api.queuezero.io',
|
|
57
|
+
displayMode: 'modal',
|
|
58
|
+
modalOptions: {
|
|
59
|
+
triggerText: 'Join Our Waitlist',
|
|
60
|
+
size: 'md'
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
</script>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The modal automatically uses your campaign's branding (logo, cover image, theme color) from the API.
|
|
44
67
|
|
|
45
68
|
## Styling
|
|
46
69
|
|
package/dist/index.global.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var QueueZero=(()=>{var h=Object.defineProperty;var
|
|
1
|
+
var QueueZero=(()=>{var h=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var v=Object.prototype.hasOwnProperty;var z=(a,e,t)=>e in a?h(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var q=(a,e)=>{for(var t in e)h(a,t,{get:e[t],enumerable:!0})},x=(a,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of b(e))!v.call(a,o)&&o!==t&&h(a,o,{get:()=>e[o],enumerable:!(r=y(e,o))||r.enumerable});return a};var $=a=>x(h({},"__esModule",{value:!0}),a);var d=(a,e,t)=>z(a,typeof e!="symbol"?e+"":e,t);var C={};q(C,{init:()=>k});var w=`
|
|
2
2
|
/* Base Form Styles */
|
|
3
3
|
.qz-form {
|
|
4
4
|
font-family: var(--qz-font-family, system-ui, -apple-system, sans-serif);
|
|
@@ -217,90 +217,90 @@ var QueueZero=(()=>{var h=Object.defineProperty;var b=Object.getOwnPropertyDescr
|
|
|
217
217
|
margin: 0 0 20px 0;
|
|
218
218
|
text-align: center;
|
|
219
219
|
}
|
|
220
|
-
`,u=class{constructor(e,t,
|
|
221
|
-
<button class="qz-trigger ${
|
|
220
|
+
`,u=class{constructor(e,t,r){d(this,"container");d(this,"campaign","");d(this,"options",{apiUrl:""});d(this,"configData",null);d(this,"submitted",!1);d(this,"submittedData",null);d(this,"modalElement",null);d(this,"modalOverlay",null);let o=document.getElementById(e);if(!o){console.error(`QueueZero: Element with ID "${e}" not found.`),this.container=document.createElement("div");return}this.container=o,this.campaign=t,this.options=r,this.injectStyles(),this.render(),this.loadCampaign()}injectStyles(){if(document.getElementById("qz-styles"))return;let e=document.createElement("style");e.id="qz-styles",e.textContent=w,document.head.appendChild(e)}render(){this.container.innerHTML='<div class="qz-loading">Loading waitlist...</div>'}async loadCampaign(){try{let e=await fetch(`${this.options.apiUrl}/v1/config/${this.campaign}`);if(!e.ok)throw new Error(`Waitlist not found (${e.status})`);this.configData=await e.json(),this.applyBranding(),this.options.displayMode==="modal"?this.renderTrigger():this.renderInlineForm()}catch(e){this.container.innerHTML=`<div class="qz-error">Failed to load waitlist: ${e.message}</div>`}}applyBranding(){if(!this.configData)return;let e=this.configData.branding||{},t=document.documentElement;e.themeColor&&(t.style.setProperty("--qz-theme-color",e.themeColor),this.container.style.setProperty("--qz-theme-color",e.themeColor)),e.backgroundColor&&t.style.setProperty("--qz-bg-color",e.backgroundColor),e.fontFamily&&t.style.setProperty("--qz-font-family",e.fontFamily)}renderTrigger(){if(!this.configData)return;let e=this.options.modalOptions||{},t=e.triggerText||"Join Waitlist",r=e.triggerClass||"";this.container.innerHTML=`
|
|
221
|
+
<button class="qz-trigger ${r}" id="qz-trigger-${this.campaign}">
|
|
222
222
|
${t}
|
|
223
223
|
</button>
|
|
224
|
-
`,this.container.querySelector(".qz-trigger")?.addEventListener("click",()=>this.openModal()),this.createModalDOM()}createModalDOM(){if(!this.configData)return;let e=this.configData.branding||{},
|
|
224
|
+
`,this.container.querySelector(".qz-trigger")?.addEventListener("click",()=>this.openModal()),this.createModalDOM()}createModalDOM(){if(!this.configData)return;let e=this.configData.branding||{},r=`qz-modal-${(this.options.modalOptions||{}).size||"md"}`;this.modalOverlay=document.createElement("div"),this.modalOverlay.className="qz-modal-overlay",this.modalOverlay.id=`qz-modal-overlay-${this.campaign}`;let o="";e.logoUrl?o+=`<img src="${e.logoUrl}" alt="Logo" class="qz-modal-logo" />`:o+="<span></span>",o+=`
|
|
225
225
|
<button class="qz-modal-close" aria-label="Close">
|
|
226
226
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
227
227
|
<path d="M18 6L6 18M6 6l12 12" />
|
|
228
228
|
</svg>
|
|
229
229
|
</button>
|
|
230
|
-
`;let
|
|
231
|
-
<div class="qz-modal ${
|
|
230
|
+
`;let s="";e.coverImageUrl&&(s=`<img src="${e.coverImageUrl}" alt="" class="qz-modal-cover" />`),this.modalOverlay.innerHTML=`
|
|
231
|
+
<div class="qz-modal ${r}">
|
|
232
232
|
<div class="qz-modal-header">
|
|
233
|
-
${
|
|
233
|
+
${o}
|
|
234
234
|
</div>
|
|
235
|
-
${
|
|
235
|
+
${s}
|
|
236
236
|
<div class="qz-modal-body">
|
|
237
237
|
<h2 class="qz-modal-title">${this.configData.name}</h2>
|
|
238
238
|
<div id="qz-modal-form-container-${this.campaign}"></div>
|
|
239
239
|
</div>
|
|
240
240
|
</div>
|
|
241
|
-
`,document.body.appendChild(this.modalOverlay),this.modalOverlay.querySelector(".qz-modal-close")?.addEventListener("click",()=>this.closeModal()),this.modalOverlay.addEventListener("click",
|
|
241
|
+
`,document.body.appendChild(this.modalOverlay),this.modalOverlay.querySelector(".qz-modal-close")?.addEventListener("click",()=>this.closeModal()),this.modalOverlay.addEventListener("click",i=>{i.target===this.modalOverlay&&this.closeModal()}),document.addEventListener("keydown",i=>{i.key==="Escape"&&this.modalOverlay?.classList.contains("qz-modal-open")&&this.closeModal()})}openModal(){if(!this.modalOverlay)return;let e=document.getElementById(`qz-modal-form-container-${this.campaign}`);e&&!e.hasChildNodes()&&this.renderFormInto(e),this.modalOverlay.classList.add("qz-modal-open"),document.body.style.overflow="hidden"}closeModal(){this.modalOverlay?.classList.remove("qz-modal-open"),document.body.style.overflow=""}renderInlineForm(){this.renderFormInto(this.container)}renderFormInto(e){if(!this.configData)return;let t=this.configData.branding?.themeColor||"#10B981";e.style.setProperty("--qz-theme-color",t);let r=(this.configData.formFields||[]).filter(i=>i.enabled);r.length===0&&r.push({key:"email",label:"Email Address",type:"email",enabled:!0,required:!0});let o=i=>{let m=`qz-${i.key}`,g=`<label class="qz-label" for="${m}">${i.label}${i.required?" *":""}</label>`,n=i.required?"required":"",l=i.placeholder||"";switch(i.type){case"select":let p=(i.options||[]).map(f=>`<option value="${f}">${f}</option>`).join("");return`
|
|
242
242
|
<div class="qz-form-group">
|
|
243
|
-
${
|
|
244
|
-
<select class="qz-input qz-select" id="${
|
|
245
|
-
|
|
246
|
-
${
|
|
243
|
+
${g}
|
|
244
|
+
<select class="qz-input qz-select" id="${m}" name="${i.key}" ${n}>
|
|
245
|
+
<option value="">Select an option</option>
|
|
246
|
+
${p}
|
|
247
247
|
</select>
|
|
248
248
|
</div>
|
|
249
249
|
`;case"checkbox":return`
|
|
250
250
|
<div class="qz-form-group qz-checkbox-group">
|
|
251
251
|
<label class="qz-checkbox-label">
|
|
252
|
-
<input type="checkbox" class="qz-checkbox" id="${
|
|
253
|
-
<span>${
|
|
252
|
+
<input type="checkbox" class="qz-checkbox" id="${m}" name="${i.key}" ${n} />
|
|
253
|
+
<span>${i.label}${i.required?" *":""}</span>
|
|
254
254
|
</label>
|
|
255
255
|
</div>
|
|
256
256
|
`;case"textarea":return`
|
|
257
257
|
<div class="qz-form-group">
|
|
258
|
-
${
|
|
258
|
+
${g}
|
|
259
259
|
<textarea
|
|
260
260
|
class="qz-input qz-textarea"
|
|
261
|
-
id="${
|
|
262
|
-
name="${
|
|
263
|
-
placeholder="${
|
|
261
|
+
id="${m}"
|
|
262
|
+
name="${i.key}"
|
|
263
|
+
placeholder="${l}"
|
|
264
264
|
rows="3"
|
|
265
265
|
${n}
|
|
266
266
|
></textarea>
|
|
267
267
|
</div>
|
|
268
268
|
`;case"number":return`
|
|
269
269
|
<div class="qz-form-group">
|
|
270
|
-
${
|
|
270
|
+
${g}
|
|
271
271
|
<input
|
|
272
272
|
class="qz-input"
|
|
273
|
-
id="${
|
|
274
|
-
name="${
|
|
273
|
+
id="${m}"
|
|
274
|
+
name="${i.key}"
|
|
275
275
|
type="number"
|
|
276
|
-
placeholder="${
|
|
276
|
+
placeholder="${l}"
|
|
277
277
|
${n}
|
|
278
278
|
/>
|
|
279
279
|
</div>
|
|
280
280
|
`;default:return`
|
|
281
281
|
<div class="qz-form-group">
|
|
282
|
-
${
|
|
282
|
+
${g}
|
|
283
283
|
<input
|
|
284
284
|
class="qz-input"
|
|
285
|
-
id="${
|
|
286
|
-
name="${
|
|
287
|
-
type="${
|
|
288
|
-
placeholder="${
|
|
285
|
+
id="${m}"
|
|
286
|
+
name="${i.key}"
|
|
287
|
+
type="${i.type==="email"?"email":"text"}"
|
|
288
|
+
placeholder="${l}"
|
|
289
289
|
${n}
|
|
290
290
|
/>
|
|
291
291
|
</div>
|
|
292
|
-
`}},
|
|
292
|
+
`}},s=r.map(o).join("");e.innerHTML=`
|
|
293
293
|
<form class="qz-form" id="qz-form-${this.campaign}">
|
|
294
|
-
${
|
|
294
|
+
${s}
|
|
295
295
|
<button type="submit" class="qz-button">Join Waitlist</button>
|
|
296
296
|
</form>
|
|
297
|
-
`,e.querySelector("form")?.addEventListener("submit",
|
|
297
|
+
`,e.querySelector("form")?.addEventListener("submit",i=>this.handleSubmit(i))}async handleSubmit(e){e.preventDefault();let t=e.target,r=t.querySelector("button"),o=new FormData(t),s={},c="";if(o.forEach((n,l)=>{let p=n.toString();l==="email"&&(c=p),s[l]=p}),!c){this.showError(t,"Email is required");return}let m=new URLSearchParams(window.location.search).get("ref"),g={campaign:this.campaign,email:c,metadata:s,referrer_code:m||null};r&&(r.disabled=!0,r.textContent="Joining...");try{let n=await fetch(`${this.options.apiUrl}/v1/submit`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(g)});if(!n.ok){let p=await n.json();throw new Error(p.message||p.error||"Failed to join")}let l=await n.json();this.submitted=!0,this.submittedData=l,this.renderSuccess(),this.options.onSuccess?.(l)}catch(n){this.showError(t,n.message||"Something went wrong"),r&&(r.disabled=!1,r.textContent="Join Waitlist"),this.options.onError?.(n)}}showError(e,t){let r=e.querySelector(".qz-error");r&&r.remove();let o=document.createElement("div");o.className="qz-error",o.textContent=t,e.insertBefore(o,e.firstChild)}renderSuccess(){let e=this.submittedData?.position||"?",t=this.submittedData?.referralCode,r=window.location.origin+window.location.pathname,o=t?`${r}?ref=${t}`:null,s=`
|
|
298
298
|
<div class="qz-success">
|
|
299
299
|
<h3>You're on the list!</h3>
|
|
300
300
|
<p>You're #${e} in line.</p>
|
|
301
|
-
`;
|
|
301
|
+
`;if(o&&(s+=`
|
|
302
302
|
<div style="margin-top: 20px;">
|
|
303
303
|
<p style="margin-bottom: 8px; color: #a6e3a1;">Refer friends to move up:</p>
|
|
304
|
-
<input class="qz-input" readonly value="${
|
|
304
|
+
<input class="qz-input" readonly value="${o}" onclick="this.select()" style="text-align: center; cursor: pointer;">
|
|
305
305
|
</div>
|
|
306
|
-
`),
|
|
306
|
+
`),s+="</div>",this.options.displayMode==="modal"){let c=document.getElementById(`qz-modal-form-container-${this.campaign}`);if(c){c.innerHTML=s;return}}this.container.innerHTML=s}};function k(a,e,t){return new u(a,e,t)}return $(C);})();
|