@saasquatch/squatch-js 2.8.3-28 → 2.8.3-29
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/CHANGELOG.md +1 -1
- package/demo/perf-benchmark.ts +5 -2
- package/demo/perf-compare.html +20 -8
- package/demo/perf-deploy/vercel.json +17 -0
- package/demo/perf-frame.html +23 -6
- package/dist/{ErrorTemplate-B5s_98qz.cjs → ErrorTemplate-D6tB2pB6.cjs} +2 -2
- package/dist/{ErrorTemplate-B5s_98qz.cjs.map → ErrorTemplate-D6tB2pB6.cjs.map} +1 -1
- package/dist/{ErrorTemplate-qH6JPm8K.js → ErrorTemplate-md163BNI.js} +5 -5
- package/dist/{ErrorTemplate-qH6JPm8K.js.map → ErrorTemplate-md163BNI.js.map} +1 -1
- package/dist/squatch.cjs.js +10 -10
- package/dist/squatch.cjs.js.map +1 -1
- package/dist/squatch.esm.js +50 -52
- package/dist/squatch.esm.js.map +1 -1
- package/dist/squatch.js +11 -11
- package/dist/squatch.js.map +1 -1
- package/dist/squatch.min.js +2 -2
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
package/demo/perf-benchmark.ts
CHANGED
|
@@ -40,6 +40,7 @@ interface PerfMetrics {
|
|
|
40
40
|
stable: number;
|
|
41
41
|
timeUnstyled: number;
|
|
42
42
|
bundleSizeBytes: number;
|
|
43
|
+
networkTime: number;
|
|
43
44
|
totalLoad: number;
|
|
44
45
|
}
|
|
45
46
|
|
|
@@ -58,8 +59,8 @@ const METRICS: MetricDef[] = [
|
|
|
58
59
|
{ key: "frameCreated", label: "Frame Created", unit: "ms", format: (v) => v > 0 ? v.toFixed(0) : "—", lowerBetter: true },
|
|
59
60
|
{ key: "meaningfulPaint", label: "Meaningful Paint", unit: "ms", format: (v) => v > 0 ? v.toFixed(0) : "—", lowerBetter: true },
|
|
60
61
|
{ key: "timeUnstyled", label: "Time Unstyled", unit: "ms", format: (v) => v > 0 ? v.toFixed(0) : "—", lowerBetter: true },
|
|
61
|
-
{ key: "
|
|
62
|
-
{ key: "totalLoad", label: "Total Load", unit: "ms", format: (v) => v > 0 ? v.toFixed(0) : "—", lowerBetter: true },
|
|
62
|
+
{ key: "networkTime", label: "Network Request Time", unit: "ms", format: (v) => v > 0 ? v.toFixed(0) : "—", lowerBetter: true },
|
|
63
|
+
{ key: "totalLoad", label: "Total Load Time", unit: "ms", format: (v) => v > 0 ? v.toFixed(0) : "—", lowerBetter: true },
|
|
63
64
|
];
|
|
64
65
|
|
|
65
66
|
// ── CLI args ───────────────────────────────────────────────
|
|
@@ -159,6 +160,7 @@ async function collectMetrics(
|
|
|
159
160
|
stable: m.stable,
|
|
160
161
|
timeUnstyled: m.timeUnstyled || 0,
|
|
161
162
|
bundleSizeBytes: m.bundleSizeBytes || 0,
|
|
163
|
+
networkTime: m.networkTime || 0,
|
|
162
164
|
totalLoad: m.stable,
|
|
163
165
|
});
|
|
164
166
|
} else if (attempts >= maxAttempts) {
|
|
@@ -174,6 +176,7 @@ async function collectMetrics(
|
|
|
174
176
|
stable: m.stable || 0,
|
|
175
177
|
timeUnstyled: m.timeUnstyled || 0,
|
|
176
178
|
bundleSizeBytes: m.bundleSizeBytes || 0,
|
|
179
|
+
networkTime: m.networkTime || 0,
|
|
177
180
|
totalLoad: m.stable || 0,
|
|
178
181
|
});
|
|
179
182
|
} else {
|
package/demo/perf-compare.html
CHANGED
|
@@ -200,7 +200,6 @@
|
|
|
200
200
|
border-bottom: 1px solid var(--border);
|
|
201
201
|
}
|
|
202
202
|
th {
|
|
203
|
-
text-align: left;
|
|
204
203
|
font-weight: 500;
|
|
205
204
|
color: var(--text-dim);
|
|
206
205
|
font-size: 11px;
|
|
@@ -391,8 +390,8 @@
|
|
|
391
390
|
<div class="metric-card"><div class="label">Frame Created</div><div class="value pending" data-metric="frameCreated">—</div></div>
|
|
392
391
|
<div class="metric-card"><div class="label">Meaningful Paint</div><div class="value pending" data-metric="meaningfulPaint">—</div></div>
|
|
393
392
|
<div class="metric-card"><div class="label">Time Unstyled</div><div class="value pending" data-metric="timeUnstyled">—</div></div>
|
|
394
|
-
<div class="metric-card"><div class="label">
|
|
395
|
-
<div class="metric-card"><div class="label">Total Load</div><div class="value pending" data-metric="totalLoad">—</div></div>
|
|
393
|
+
<div class="metric-card"><div class="label">Network Request Time</div><div class="value pending" data-metric="networkTime">—</div></div>
|
|
394
|
+
<div class="metric-card"><div class="label">Total Load Time</div><div class="value pending" data-metric="totalLoad">—</div></div>
|
|
396
395
|
</div>
|
|
397
396
|
</div>
|
|
398
397
|
|
|
@@ -435,8 +434,8 @@
|
|
|
435
434
|
<div class="metric-card"><div class="label">Frame Created</div><div class="value pending" data-metric="frameCreated">—</div></div>
|
|
436
435
|
<div class="metric-card"><div class="label">Meaningful Paint</div><div class="value pending" data-metric="meaningfulPaint">—</div></div>
|
|
437
436
|
<div class="metric-card"><div class="label">Time Unstyled</div><div class="value pending" data-metric="timeUnstyled">—</div></div>
|
|
438
|
-
<div class="metric-card"><div class="label">
|
|
439
|
-
<div class="metric-card"><div class="label">Total Load</div><div class="value pending" data-metric="totalLoad">—</div></div>
|
|
437
|
+
<div class="metric-card"><div class="label">Network Request Time</div><div class="value pending" data-metric="networkTime">—</div></div>
|
|
438
|
+
<div class="metric-card"><div class="label">Total Load Time</div><div class="value pending" data-metric="totalLoad">—</div></div>
|
|
440
439
|
</div>
|
|
441
440
|
</div>
|
|
442
441
|
</div>
|
|
@@ -536,8 +535,8 @@
|
|
|
536
535
|
{ key: "frameCreated", label: "Frame Created", unit: "ms", format: formatMs, lowerBetter: true },
|
|
537
536
|
{ key: "meaningfulPaint", label: "Meaningful Paint", unit: "ms", format: formatMs, lowerBetter: true },
|
|
538
537
|
{ key: "timeUnstyled", label: "Time Unstyled", unit: "ms", format: formatMs, lowerBetter: true },
|
|
539
|
-
{ key: "
|
|
540
|
-
{ key: "totalLoad", label: "Total Load", unit: "ms", format: formatMs, lowerBetter: true }
|
|
538
|
+
{ key: "networkTime", label: "Network Request Time", unit: "ms", format: formatMs, lowerBetter: true },
|
|
539
|
+
{ key: "totalLoad", label: "Total Load Time", unit: "ms", format: formatMs, lowerBetter: true }
|
|
541
540
|
];
|
|
542
541
|
|
|
543
542
|
function formatMs(v) { return v > 0 ? v.toFixed(0) + " ms" : "—"; }
|
|
@@ -581,7 +580,19 @@
|
|
|
581
580
|
resolved = true;
|
|
582
581
|
window.removeEventListener("message", onMessage);
|
|
583
582
|
clearInterval(pollId);
|
|
584
|
-
|
|
583
|
+
// Wait for late resize events to settle — V2 often has
|
|
584
|
+
// multiple resize rounds after the first stable report.
|
|
585
|
+
// After waiting, read the final metrics from the iframe.
|
|
586
|
+
setTimeout(function () {
|
|
587
|
+
try {
|
|
588
|
+
var latest = iframe.contentWindow && iframe.contentWindow.__perfMetrics;
|
|
589
|
+
if (latest && latest.sdkUrl === sdkUrl && latest.stable > 0) {
|
|
590
|
+
resolve(latest);
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
} catch (e) {}
|
|
594
|
+
resolve(metrics);
|
|
595
|
+
}, 1500);
|
|
585
596
|
}
|
|
586
597
|
|
|
587
598
|
// Method 1: Listen for postMessage from child
|
|
@@ -624,6 +635,7 @@
|
|
|
624
635
|
function enrichMetrics(m) {
|
|
625
636
|
if (!m) return null;
|
|
626
637
|
m.totalLoad = m.stable || 0;
|
|
638
|
+
m.networkTime = m.networkTime || 0;
|
|
627
639
|
m.bundleSize = m.bundleSizeBytes || 0;
|
|
628
640
|
return m;
|
|
629
641
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"rewrites": [
|
|
3
|
+
{ "source": "/api/:path*", "destination": "https://staging.referralsaasquatch.com/api/:path*" },
|
|
4
|
+
{ "source": "/a/:path*", "destination": "https://staging.referralsaasquatch.com/a/:path*" }
|
|
5
|
+
],
|
|
6
|
+
"headers": [
|
|
7
|
+
{
|
|
8
|
+
"source": "/(.*)",
|
|
9
|
+
"headers": [
|
|
10
|
+
{ "key": "Access-Control-Allow-Origin", "value": "*" },
|
|
11
|
+
{ "key": "Access-Control-Allow-Methods", "value": "GET, POST, PUT, DELETE, OPTIONS" },
|
|
12
|
+
{ "key": "Access-Control-Allow-Headers", "value": "Content-Type, Authorization, X-SaaSquatch-Referrer" }
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"cleanUrls": true
|
|
17
|
+
}
|
package/demo/perf-frame.html
CHANGED
|
@@ -56,6 +56,17 @@
|
|
|
56
56
|
}
|
|
57
57
|
} catch (e) {}
|
|
58
58
|
|
|
59
|
+
var networkTime = 0;
|
|
60
|
+
try {
|
|
61
|
+
var resEntries = performance.getEntriesByType("resource");
|
|
62
|
+
for (var j = 0; j < resEntries.length; j++) {
|
|
63
|
+
var e = resEntries[j];
|
|
64
|
+
if (e.responseEnd > 0 && e.startTime >= 0) {
|
|
65
|
+
networkTime += e.responseEnd - e.startTime;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} catch (e) {}
|
|
69
|
+
|
|
59
70
|
var out = {
|
|
60
71
|
sdkUrl: sdkUrl,
|
|
61
72
|
sdkScriptLoad: delta("sdk-script-loaded"),
|
|
@@ -67,6 +78,7 @@
|
|
|
67
78
|
? delta("skeleton-start")
|
|
68
79
|
: delta("unstyled-end"),
|
|
69
80
|
bundleSizeBytes: bundleSize,
|
|
81
|
+
networkTime: networkTime,
|
|
70
82
|
raw: marks
|
|
71
83
|
};
|
|
72
84
|
window.__perfMetrics = out;
|
|
@@ -188,17 +200,21 @@
|
|
|
188
200
|
var frameDetected = false;
|
|
189
201
|
|
|
190
202
|
function observeWidgetIframe(iframe) {
|
|
203
|
+
// Track whether the iframe has been resized at least once
|
|
204
|
+
var hasResized = false;
|
|
205
|
+
|
|
191
206
|
// Watch height/style attribute changes for stable timer
|
|
192
207
|
var resizeObs = new MutationObserver(function (mutations) {
|
|
193
208
|
for (var i = 0; i < mutations.length; i++) {
|
|
194
209
|
var attr = mutations[i].attributeName;
|
|
195
210
|
if (attr === "height" || attr === "style") {
|
|
211
|
+
hasResized = true;
|
|
196
212
|
resetStableTimer();
|
|
197
213
|
}
|
|
198
214
|
}
|
|
199
215
|
});
|
|
200
216
|
resizeObs.observe(iframe, { attributes: true, attributeFilter: ["height", "style"] });
|
|
201
|
-
|
|
217
|
+
// Don't start stable timer here — wait for first actual mutation
|
|
202
218
|
|
|
203
219
|
// Helper: check if any real CSS rules have been applied in the iframe document
|
|
204
220
|
function hasStylesApplied(doc) {
|
|
@@ -313,12 +329,13 @@
|
|
|
313
329
|
var html = doc.documentElement;
|
|
314
330
|
if (html && doc.body && doc.body.children.length > 0) {
|
|
315
331
|
var vis = getComputedStyle(html).visibility;
|
|
316
|
-
//
|
|
317
|
-
// (
|
|
318
|
-
//
|
|
319
|
-
//
|
|
332
|
+
// Wait until styled and either the iframe has been resized
|
|
333
|
+
// (V2 starts at default small height) OR the iframe already
|
|
334
|
+
// has a reasonable height (>300px — @next sets a near-final
|
|
335
|
+
// default height so waiting for resize is unnecessary).
|
|
320
336
|
var ready = doc.readyState === "complete";
|
|
321
|
-
|
|
337
|
+
var tallEnough = iframe.offsetHeight > 300 || parseInt(iframe.style.height, 10) > 300;
|
|
338
|
+
if (vis === "visible" && ready && hasStylesApplied(doc) && (hasResized || tallEnough)) {
|
|
322
339
|
window.__perfMark("meaningful-paint");
|
|
323
340
|
return;
|
|
324
341
|
}
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
</head>
|
|
95
95
|
<body>
|
|
96
96
|
|
|
97
|
-
<div class="squatch-container ${l}" style="width:100
|
|
97
|
+
<div class="squatch-container ${l}" style="width:100%;background:#FFF;">
|
|
98
98
|
<div class="errorbody">
|
|
99
99
|
<div class="sadface"><img src="https://fast-staging.ssqt.io/assets/images/whoops-error-image.png"></div>
|
|
100
100
|
<h4>Our referral program is temporarily unavailable.</h4>
|
|
@@ -106,4 +106,4 @@
|
|
|
106
106
|
</div>
|
|
107
107
|
</body>
|
|
108
108
|
</html>`}exports.getErrorTemplate=c;
|
|
109
|
-
//# sourceMappingURL=ErrorTemplate-
|
|
109
|
+
//# sourceMappingURL=ErrorTemplate-D6tB2pB6.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorTemplate-
|
|
1
|
+
{"version":3,"file":"ErrorTemplate-D6tB2pB6.cjs","sources":["../src/widgets/ErrorTemplate.ts"],"sourcesContent":["export interface ErrorTemplateOptions {\n rsCode?: string;\n apiErrorCode?: string;\n statusCode?: number;\n message?: string;\n mode?: string;\n style?: string;\n}\n\nexport function getErrorTemplate(options: ErrorTemplateOptions = {}): string {\n const {\n rsCode,\n apiErrorCode,\n statusCode,\n message,\n mode = \"modal\",\n style = \"\",\n } = options;\n\n // Escape values using the browser's built-in HTML encoding\n const tmp = document.createElement(\"span\");\n const esc = (s: string) => ((tmp.textContent = s), tmp.innerHTML);\n\n // Build error details items\n const detailItems: string[] = [];\n\n if (statusCode !== undefined) {\n detailItems.push(`<dt>Status Code</dt><dd>${esc(String(statusCode))}</dd>`);\n }\n if (apiErrorCode) {\n detailItems.push(`<dt>API Error Code</dt><dd>${esc(apiErrorCode)}</dd>`);\n }\n if (rsCode) {\n detailItems.push(`<dt>RS Code</dt><dd>${esc(rsCode)}</dd>`);\n }\n if (message) {\n detailItems.push(`<dt>Message</dt><dd>${esc(message)}</dd>`);\n }\n\n // Build the error details section\n const errorDetailsHtml =\n detailItems.length > 0\n ? `<dl class=\"error-details\">${detailItems.join(\"\\n \")}</dl>`\n : \"\";\n\n return `<!DOCTYPE html>\n <!--[if IE 7]><html class=\"ie7 oldie\" lang=\"en\"><![endif]-->\n <!--[if IE 8]><html class=\"ie8 oldie\" lang=\"en\"><![endif]-->\n <!--[if gt IE 8]><!--><html lang=\"en\"><!--<![endif]-->\n <head>\n <style>\n ${style}\n body {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n line-height: 20px;\n }\n h3 {\n text-align: center;\n }\n .errortitle {\n margin: 0;\n font-size: 14px;\n }\n .errorbody p {\n text-align: center;\n font-size: 12px;\n margin: 0 0 10px;\n }\n h4 {\n font-size: 17.5px;\n text-align: center;\n margin: 10px 0;\n }\n .embed {\n width: 100%;\n max-width: 500px;\n margin-left: auto;\n margin-right: auto;\n }\n .errorbody {\n padding: 15px;\n position: relative;\n height: auto;\n }\n p {\n text-align: center;\n font-size: 12px;\n }\n .sadface {\n padding: 10px;\n }\n .sadface img {\n display: block;\n margin: auto;\n height: 100px;\n }\n .modal-disable-overlay {\n display: none;\n position: absolute;\n top: 50px;\n width: 100%;\n height: 85%;\n background: rgba(255, 255, 255, 0.4);\n }\n\n .right-align {\n text-align: right;\n }\n .errtxt {\n color: #CCC9C9;\n }\n .error-details {\n margin-top: 16px;\n padding: 12px;\n background: #f8f8f8;\n border-radius: 4px;\n text-align: left;\n font-size: 13px;\n color: #666;\n display: block;\n overflow: visible;\n }\n .error-details dt {\n display: block;\n font-weight: 600;\n color: #333;\n margin-top: 8px;\n }\n .error-details dt:first-child {\n margin-top: 0;\n }\n .error-details dd {\n display: block;\n margin: 4px 0 0 0;\n word-break: break-word;\n }\n </style>\n </head>\n <body>\n\n <div class=\"squatch-container ${mode}\" style=\"width:100%;background:#FFF;\">\n <div class=\"errorbody\">\n <div class=\"sadface\"><img src=\"https://fast-staging.ssqt.io/assets/images/whoops-error-image.png\"></div>\n <h4>Our referral program is temporarily unavailable.</h4>\n <p>Please reload the page or check back later.</p>\n <p>If the problem persists please contact our support team.</p>\n\n ${errorDetailsHtml}\n </div>\n </div>\n </body>\n </html>`;\n}\n"],"names":["getErrorTemplate","options","rsCode","apiErrorCode","statusCode","message","mode","style","tmp","esc","s","detailItems","errorDetailsHtml"],"mappings":"gFASgB,SAAAA,EAAiBC,EAAgC,GAAY,CACrE,KAAA,CACJ,OAAAC,EACA,aAAAC,EACA,WAAAC,EACA,QAAAC,EACA,KAAAC,EAAO,QACP,MAAAC,EAAQ,EAAA,EACNN,EAGEO,EAAM,SAAS,cAAc,MAAM,EACnCC,EAAOC,IAAgBF,EAAI,YAAcE,EAAIF,EAAI,WAGjDG,EAAwB,CAAC,EAE3BP,IAAe,QACjBO,EAAY,KAAK,2BAA2BF,EAAI,OAAOL,CAAU,CAAC,CAAC,OAAO,EAExED,GACFQ,EAAY,KAAK,8BAA8BF,EAAIN,CAAY,CAAC,OAAO,EAErED,GACFS,EAAY,KAAK,uBAAuBF,EAAIP,CAAM,CAAC,OAAO,EAExDG,GACFM,EAAY,KAAK,uBAAuBF,EAAIJ,CAAO,CAAC,OAAO,EAIvD,MAAAO,EACJD,EAAY,OAAS,EACjB,6BAA6BA,EAAY,KAAK;AAAA,aAAgB,CAAC,QAC/D,GAEC,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAMCJ,CAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sCAyFuBD,CAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAO9BM,CAAgB;AAAA;AAAA;AAAA;AAAA,YAK5B"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
function c(s = {}) {
|
|
2
2
|
const {
|
|
3
|
-
rsCode:
|
|
4
|
-
apiErrorCode:
|
|
3
|
+
rsCode: r,
|
|
4
|
+
apiErrorCode: i,
|
|
5
5
|
statusCode: a,
|
|
6
6
|
message: d,
|
|
7
7
|
mode: l = "modal",
|
|
8
8
|
style: n = ""
|
|
9
9
|
} = s, o = document.createElement("span"), t = (g) => (o.textContent = g, o.innerHTML), e = [];
|
|
10
|
-
a !== void 0 && e.push(`<dt>Status Code</dt><dd>${t(String(a))}</dd>`),
|
|
10
|
+
a !== void 0 && e.push(`<dt>Status Code</dt><dd>${t(String(a))}</dd>`), i && e.push(`<dt>API Error Code</dt><dd>${t(i)}</dd>`), r && e.push(`<dt>RS Code</dt><dd>${t(r)}</dd>`), d && e.push(`<dt>Message</dt><dd>${t(d)}</dd>`);
|
|
11
11
|
const p = e.length > 0 ? `<dl class="error-details">${e.join(`
|
|
12
12
|
`)}</dl>` : "";
|
|
13
13
|
return `<!DOCTYPE html>
|
|
@@ -105,7 +105,7 @@ function c(s = {}) {
|
|
|
105
105
|
</head>
|
|
106
106
|
<body>
|
|
107
107
|
|
|
108
|
-
<div class="squatch-container ${l}" style="width:100
|
|
108
|
+
<div class="squatch-container ${l}" style="width:100%;background:#FFF;">
|
|
109
109
|
<div class="errorbody">
|
|
110
110
|
<div class="sadface"><img src="https://fast-staging.ssqt.io/assets/images/whoops-error-image.png"></div>
|
|
111
111
|
<h4>Our referral program is temporarily unavailable.</h4>
|
|
@@ -121,4 +121,4 @@ function c(s = {}) {
|
|
|
121
121
|
export {
|
|
122
122
|
c as getErrorTemplate
|
|
123
123
|
};
|
|
124
|
-
//# sourceMappingURL=ErrorTemplate-
|
|
124
|
+
//# sourceMappingURL=ErrorTemplate-md163BNI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorTemplate-
|
|
1
|
+
{"version":3,"file":"ErrorTemplate-md163BNI.js","sources":["../src/widgets/ErrorTemplate.ts"],"sourcesContent":["export interface ErrorTemplateOptions {\n rsCode?: string;\n apiErrorCode?: string;\n statusCode?: number;\n message?: string;\n mode?: string;\n style?: string;\n}\n\nexport function getErrorTemplate(options: ErrorTemplateOptions = {}): string {\n const {\n rsCode,\n apiErrorCode,\n statusCode,\n message,\n mode = \"modal\",\n style = \"\",\n } = options;\n\n // Escape values using the browser's built-in HTML encoding\n const tmp = document.createElement(\"span\");\n const esc = (s: string) => ((tmp.textContent = s), tmp.innerHTML);\n\n // Build error details items\n const detailItems: string[] = [];\n\n if (statusCode !== undefined) {\n detailItems.push(`<dt>Status Code</dt><dd>${esc(String(statusCode))}</dd>`);\n }\n if (apiErrorCode) {\n detailItems.push(`<dt>API Error Code</dt><dd>${esc(apiErrorCode)}</dd>`);\n }\n if (rsCode) {\n detailItems.push(`<dt>RS Code</dt><dd>${esc(rsCode)}</dd>`);\n }\n if (message) {\n detailItems.push(`<dt>Message</dt><dd>${esc(message)}</dd>`);\n }\n\n // Build the error details section\n const errorDetailsHtml =\n detailItems.length > 0\n ? `<dl class=\"error-details\">${detailItems.join(\"\\n \")}</dl>`\n : \"\";\n\n return `<!DOCTYPE html>\n <!--[if IE 7]><html class=\"ie7 oldie\" lang=\"en\"><![endif]-->\n <!--[if IE 8]><html class=\"ie8 oldie\" lang=\"en\"><![endif]-->\n <!--[if gt IE 8]><!--><html lang=\"en\"><!--<![endif]-->\n <head>\n <style>\n ${style}\n body {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n line-height: 20px;\n }\n h3 {\n text-align: center;\n }\n .errortitle {\n margin: 0;\n font-size: 14px;\n }\n .errorbody p {\n text-align: center;\n font-size: 12px;\n margin: 0 0 10px;\n }\n h4 {\n font-size: 17.5px;\n text-align: center;\n margin: 10px 0;\n }\n .embed {\n width: 100%;\n max-width: 500px;\n margin-left: auto;\n margin-right: auto;\n }\n .errorbody {\n padding: 15px;\n position: relative;\n height: auto;\n }\n p {\n text-align: center;\n font-size: 12px;\n }\n .sadface {\n padding: 10px;\n }\n .sadface img {\n display: block;\n margin: auto;\n height: 100px;\n }\n .modal-disable-overlay {\n display: none;\n position: absolute;\n top: 50px;\n width: 100%;\n height: 85%;\n background: rgba(255, 255, 255, 0.4);\n }\n\n .right-align {\n text-align: right;\n }\n .errtxt {\n color: #CCC9C9;\n }\n .error-details {\n margin-top: 16px;\n padding: 12px;\n background: #f8f8f8;\n border-radius: 4px;\n text-align: left;\n font-size: 13px;\n color: #666;\n display: block;\n overflow: visible;\n }\n .error-details dt {\n display: block;\n font-weight: 600;\n color: #333;\n margin-top: 8px;\n }\n .error-details dt:first-child {\n margin-top: 0;\n }\n .error-details dd {\n display: block;\n margin: 4px 0 0 0;\n word-break: break-word;\n }\n </style>\n </head>\n <body>\n\n <div class=\"squatch-container ${mode}\" style=\"width:100%;background:#FFF;\">\n <div class=\"errorbody\">\n <div class=\"sadface\"><img src=\"https://fast-staging.ssqt.io/assets/images/whoops-error-image.png\"></div>\n <h4>Our referral program is temporarily unavailable.</h4>\n <p>Please reload the page or check back later.</p>\n <p>If the problem persists please contact our support team.</p>\n\n ${errorDetailsHtml}\n </div>\n </div>\n </body>\n </html>`;\n}\n"],"names":["getErrorTemplate","options","rsCode","apiErrorCode","statusCode","message","mode","style","tmp","esc","s","detailItems","errorDetailsHtml"],"mappings":"AASgB,SAAAA,EAAiBC,IAAgC,IAAY;AACrE,QAAA;AAAA,IACJ,QAAAC;AAAA,IACA,cAAAC;AAAA,IACA,YAAAC;AAAA,IACA,SAAAC;AAAA,IACA,MAAAC,IAAO;AAAA,IACP,OAAAC,IAAQ;AAAA,EAAA,IACNN,GAGEO,IAAM,SAAS,cAAc,MAAM,GACnCC,IAAM,CAACC,OAAgBF,EAAI,cAAcE,GAAIF,EAAI,YAGjDG,IAAwB,CAAC;AAE/B,EAAIP,MAAe,UACjBO,EAAY,KAAK,2BAA2BF,EAAI,OAAOL,CAAU,CAAC,CAAC,OAAO,GAExED,KACFQ,EAAY,KAAK,8BAA8BF,EAAIN,CAAY,CAAC,OAAO,GAErED,KACFS,EAAY,KAAK,uBAAuBF,EAAIP,CAAM,CAAC,OAAO,GAExDG,KACFM,EAAY,KAAK,uBAAuBF,EAAIJ,CAAO,CAAC,OAAO;AAIvD,QAAAO,IACJD,EAAY,SAAS,IACjB,6BAA6BA,EAAY,KAAK;AAAA,aAAgB,CAAC,UAC/D;AAEC,SAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAMCJ,CAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sCAyFuBD,CAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAO9BM,CAAgB;AAAA;AAAA;AAAA;AAAA;AAK5B;"}
|
package/dist/squatch.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var Ae=Object.defineProperty;var Ie=(o,t,e)=>t in o?Ae(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e;var l=(o,t,e)=>Ie(o,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let _=null;function _e(o){const e=o.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");_=new RegExp(`^${e}$`)}function ke(){_=null}function C(o){const t=(...e)=>{_&&_.test(o)&&console.log(`[${o}]`,...e)};return Object.defineProperty(t,"enabled",{get(){return!!(_&&_.test(o))}}),t}const v=C("squatch-js");function Q(o){const t=document.cookie.match(new RegExp("(?:^|; )"+o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"=([^;]*)"));return t?decodeURIComponent(t[1]):void 0}function
|
|
1
|
+
"use strict";var Ae=Object.defineProperty;var Ie=(o,t,e)=>t in o?Ae(o,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[t]=e;var l=(o,t,e)=>Ie(o,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let _=null;function _e(o){const e=o.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");_=new RegExp(`^${e}$`)}function ke(){_=null}function C(o){const t=(...e)=>{_&&_.test(o)&&console.log(`[${o}]`,...e)};return Object.defineProperty(t,"enabled",{get(){return!!(_&&_.test(o))}}),t}const v=C("squatch-js");function Q(o){const t=document.cookie.match(new RegExp("(?:^|; )"+o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"=([^;]*)"));return t?decodeURIComponent(t[1]):void 0}function Se(o,t,e){let n=`${encodeURIComponent(o)}=${encodeURIComponent(t)}`;{const i=new Date;i.setTime(i.getTime()+e.expires*864e5),n+=`; expires=${i.toUTCString()}`}e.path&&(n+=`; path=${e.path}`),e.domain&&(n+=`; domain=${e.domain}`),e.sameSite&&(n+=`; SameSite=${e.sameSite}`),document.cookie=n}const ae=o=>typeof o=="object"&&!Array.isArray(o),le=(o,t)=>{const e=i=>ae(t[i])&&o.hasOwnProperty(i)&&ae(o[i]),n=Object.getOwnPropertyNames(t).map(i=>({[i]:e(i)?le(o[i],t[i]):t[i]})).reduce((i,s)=>({...i,...s}),{});return{...o,...n}};function N(o){const t=atob(o.replace(/_/g,"/").replace(/-/g,"+")),e=new Uint8Array(t.length);for(let n=0;n<t.length;n++)e[n]=t.charCodeAt(n);return new TextDecoder("utf8").decode(e)}function ce(o){const t=new TextEncoder().encode(o),e=Array.from(t,n=>String.fromCodePoint(n)).join("");return btoa(e).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}function We(){var o,t,e="weird_get_top_level_domain=cookie",n=document.location.hostname.split(".");for(o=n.length-1;o>=0;o--)if(t=n.slice(o).join("."),document.cookie=e+";domain=."+t+";",document.cookie.indexOf(e)>-1)return document.cookie=e.split("=")[0]+"=;domain=."+t+";expires=Thu, 01 Jan 1970 00:00:01 GMT;",t}function Te(){const o=window.location.search,e=new URLSearchParams(o).get("_saasquatch")||"";if(e){let n="",i="",s="";try{n=JSON.parse(N(e))}catch(r){v("Unable to decode params",r);return}try{i=JSON.parse(N(Q("_saasquatch"))),v("existing cookie",i)}catch(r){v("Unable to retrieve cookie",r)}try{const r=We();if(v("domain retrieved:",r),i){const a=le(i,n);s=ce(JSON.stringify(a)),v("cookie to store:",a)}else s=ce(JSON.stringify(n)),v("cookie to store:",n);Se("_saasquatch",s,{expires:365,secure:!1,sameSite:"Lax",domain:r,path:"/"})}catch(r){v("Unable to set cookie",r)}}}const k="https://app.referralsaasquatch.com",Y="https://fast.ssqt.io/npm",L="squatch",X="impact";function P(o){if(typeof o!="object")throw new Error("config must be an object");const t=window.squatchTenant,e=K(),n={tenantAlias:(o==null?void 0:o.tenantAlias)||t,domain:(o==null?void 0:o.domain)||(e==null?void 0:e.domain),npmCdn:(o==null?void 0:o.npmCdn)||(e==null?void 0:e.npmCdn),debug:(o==null?void 0:o.debug)||(e==null?void 0:e.debug)};if(typeof n.tenantAlias!="string")throw new Error("tenantAlias not provided");const i=n.tenantAlias,s=typeof n.domain=="string"&&n.domain||k,r=typeof n.debug=="boolean"&&n.debug||!1,a=typeof n.npmCdn=="string"&&n.npmCdn||Y;return{tenantAlias:i,domain:s,debug:r,npmCdn:a}}function S(o){return typeof o=="object"&&!Array.isArray(o)&&o!==null}function $e(o){if(o&&/^[a-z]{2}_(?:[A-Z]{2}|[0-9]{3})$/.test(o))return o}function he(o){if(!S(o))throw new Error("Widget properties must be an object");if(!(o!=null&&o.user))throw new Error("Required properties missing.");return o}function ue(o){if(!S(o))throw new Error("Widget properties must be an object");return o}function U(){return window.impactToken||window.squatchToken}function K(){return window.impactConfig||window.squatchConfig}const me=C("squatch-js:io");function G(o){let t,e,n,i=o;try{const r=JSON.parse(o);r&&typeof r=="object"&&(t=r.apiErrorCode,e=r.rsCode,n=r.statusCode,i=r.message||o)}catch{}const s=new Error(i);return t&&(s.apiErrorCode=t),e&&(s.rsCode=e),n!==void 0&&(s.statusCode=n),s}async function qe(o,t,e,n){const i=n||U(),s={Accept:"application/json","Content-Type":"application/json",...i?{Authorization:`Bearer ${i}`}:{},"X-SaaSquatch-Referrer":window?window.location.href:""};try{const r=await fetch(o,{method:"POST",body:JSON.stringify({query:t,variables:e}),headers:s});if(!r.ok)throw G(await r.text());return await r.json()}catch(r){throw r}}async function xe(o,t=""){const e={Accept:"application/json","Content-Type":"application/json"},n=t||U();n?e["X-SaaSquatch-User-Token"]=n:me("[DEBUG] doGet - No token found, proceeding without authentication header.");try{const i=await fetch(o,{method:"GET",credentials:"include",headers:e}),s=await i.text();if(!i.ok)throw G(s);return s&&JSON.parse(s)}catch(i){throw i}}async function Z(o,t,e){const n={Accept:"application/json","Content-Type":"application/json"},i=e||U();i?n["X-SaaSquatch-User-Token"]=i:me("[DEBUG] doPost - No token found, proceeding without authentication header.");try{const s=await fetch(o,{method:"POST",body:t,headers:n}),r=await s.text();if(!s.ok)throw G(r);return r&&JSON.parse(r)}catch(s){throw s}}async function Me(o,t,e){const n={Accept:"application/json","Content-Type":"application/json","X-SaaSquatch-Referrer":window?window.location.href:""},i=e||U();i&&(n["X-SaaSquatch-User-Token"]=i);try{const s=await fetch(o,{headers:n,method:"PUT",credentials:"include",body:t}),r=await s.text();if(!s.ok)throw G(r);return r&&JSON.parse(r)}catch(s){throw s}}const Pe=`
|
|
2
2
|
query renderWidget ($user: UserIdInput, $engagementMedium: UserEngagementMedium, $widgetType: WidgetType, $locale: RSLocale) {
|
|
3
3
|
renderWidget(user: $user, engagementMedium: $engagementMedium, widgetType: $widgetType, locale: $locale) {
|
|
4
4
|
template
|
|
@@ -12,18 +12,18 @@
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
-
`;class z{constructor(t){l(this,"tenantAlias");l(this,"domain");l(this,"npmCdn");l(this,"referralCookie",this.squatchReferralCookie);const n=
|
|
15
|
+
`;class z{constructor(t){l(this,"tenantAlias");l(this,"domain");l(this,"npmCdn");l(this,"referralCookie",this.squatchReferralCookie);const n=P(t);this.tenantAlias=n.tenantAlias,this.domain=n.domain,this.npmCdn=n.npmCdn}upsertUser(t){const n=he(t),{widgetType:i,engagementMedium:s="POPUP",jwt:r,locale:a,user:c}=n,d=encodeURIComponent(this.tenantAlias),h=c.accountId?encodeURIComponent(c.accountId):null,u=c.id?encodeURIComponent(c.id):null,m=Ue({widgetType:i,engagementMedium:s,locale:a}),p=`/api/v1/${d}/widget/account/${h}/user/${u}/upsert${m}`,g=this.domain+p,f=Q("_saasquatch");return f&&(c.cookies=f),Me(g,JSON.stringify(c),r)}render(t){const n=ue(t),{widgetType:i,engagementMedium:s="POPUP",jwt:r,user:a}=n,c=encodeURIComponent(this.tenantAlias),d=a!=null&&a.accountId?encodeURIComponent(a.accountId):null,h=a!=null&&a.id?encodeURIComponent(a.id):null,u=n.locale??$e(navigator.language.replace(/\-/g,"_")),m=`/api/v1/${c}/graphql`,p=this.domain+m;return new Promise(async(g,f)=>{var b;try{const w=await qe(p,Pe,{user:h&&d?{id:h,accountId:d}:null,engagementMedium:s,widgetType:i,locale:u},r);g((b=w==null?void 0:w.data)==null?void 0:b.renderWidget)}catch(w){f(w)}})}async squatchReferralCookie(){const t=encodeURIComponent(this.tenantAlias),e=Q("_saasquatch")||"",n=e?`?cookies=${encodeURIComponent(e)}`:"",i=`${this.domain}/a/${t}/widgets/squatchcookiejson${n}`,s=await xe(i);return Promise.resolve({...s,encodedCookie:e})}}function Ue({widgetType:o,engagementMedium:t,locale:e}){const n=new URLSearchParams;return n.append("engagementMedium",t),o&&n.append("widgetType",o),e&&n.append("locale",e),`?${n.toString()}`}/*!
|
|
16
16
|
* domready (c) Dustin Diaz 2014 - License MIT
|
|
17
17
|
*
|
|
18
|
-
*/function
|
|
18
|
+
*/function $(o,t){let e=[],n,i=o,s=i.documentElement.doScroll,r="DOMContentLoaded",a=(s?/^loaded|^c/:/^loaded|^i|^c/).test(i.readyState);return a||i.addEventListener(r,n=()=>{for(i.removeEventListener(r,n),a=!0;n=e.shift();)n()}),a?setTimeout(t,0):e.push(t)}function F({value:o,unit:t}){switch(t){case"px":return`${o}px`;case"%":return`${o}%`;default:return`${o}px`}}class ge{constructor(t){l(this,"domain");var i;const n=Re(t);this.domain=(n==null?void 0:n.domain)||((i=K())==null?void 0:i.domain)||k}pushAnalyticsLoadEvent(t){if(!t.externalUserId||!t.externalAccountId)return;const e=window.location.search,n=new URLSearchParams(e),i=n==null?void 0:n.get("rsShareMedium"),s=encodeURIComponent(t.tenantAlias),r=encodeURIComponent(t.externalAccountId),a=encodeURIComponent(t.externalUserId),c=encodeURIComponent(t.engagementMedium),d=t.programId?`&programId=${encodeURIComponent(t.programId)}`:"",h=i?`&shareMedium=${encodeURIComponent(i)}`:"",u=`/a/${s}/widgets/analytics/loaded?externalAccountId=${r}&externalUserId=${a}&engagementMedium=${c}${h}${d}`,m=this.domain+u;return Z(m,JSON.stringify({}))}pushAnalyticsShareClickedEvent(t){const e=encodeURIComponent(t.tenantAlias),n=encodeURIComponent(t.externalAccountId),i=encodeURIComponent(t.externalUserId),s=encodeURIComponent(t.engagementMedium),r=encodeURIComponent(t.shareMedium),a=`/a/${e}/widgets/analytics/shared?externalAccountId=${n}&externalUserId=${i}&engagementMedium=${s}&shareMedium=${r}`,c=this.domain+a;return Z(c,JSON.stringify({}))}}function Re(o){if(!S(o))throw new Error("'options' should be an object");return o}const y=C("squatch-js:widget");class pe{constructor(t){l(this,"type");l(this,"content");l(this,"analyticsApi");l(this,"widgetApi");l(this,"context");l(this,"npmCdn");l(this,"container");l(this,"loadEventListener",null);l(this,"errorInfo");var e;y("widget initializing ..."),t.content==="error"?(this.content="error",this.errorInfo={rsCode:t.rsCode,apiErrorCode:t.apiErrorCode,statusCode:t.statusCode,message:t.errorMessage}):this.content=t.content,this.type=t.type,this.widgetApi=t.api,this.npmCdn=t.npmCdn,this.analyticsApi=new ge({domain:t.domain}),this.context=t.context,this.container=((e=t.context)==null?void 0:e.container)||t.container}async _getContent(){if(this.content==="error"&&this.errorInfo){const{getErrorTemplate:t}=await Promise.resolve().then(()=>require("./ErrorTemplate-D6tB2pB6.cjs"));return t({rsCode:this.errorInfo.rsCode,apiErrorCode:this.errorInfo.apiErrorCode,statusCode:this.errorInfo.statusCode,mode:this._getErrorMode(),style:this._getErrorStyle(),message:this.errorInfo.message})}return this.content}_getErrorMode(){return"modal"}_getErrorStyle(){return""}_findElement(){let t;if(typeof this.container=="string"?(t=document.querySelector(this.container),y("loading widget with selector",t)):this.container instanceof HTMLElement?(t=this.container,y("loading widget with container",t)):this.container?(t=null,y("container must be an HTMLElement or string",this.container)):(t=document.querySelector("#squatchembed")||document.querySelector(".squatchembed")||document.querySelector("#impactembed")||document.querySelector(".impactembed"),y("loading widget with default selector",t)),!(t instanceof HTMLElement))throw new Error(`element with selector '${this.container||"#squatchembed, .squatchembed, #impactembed, or .impactembed"}' not found.'`);return t}_createFrame(t){const e=document.createElement("iframe");return e.squatchJsApi=this,e.id="squatchFrame",e.width="100%",e.src="about:blank",e.scrolling="no",e.setAttribute("style","border: 0; background-color: none; width: 1px; min-width: 100%; display: block;"),t!=null&&t.minWidth&&(e.style.minWidth=t.minWidth),t!=null&&t.maxWidth&&(e.style.maxWidth=t.maxWidth),(t!=null&&t.maxWidth||t!=null&&t.minWidth)&&(e.style.width="100%"),t!=null&&t.initialHeight&&(e.height=String(t.initialHeight)),e}_findFrame(){const t=this.container?this._findElement():document.body;return(t.shadowRoot||t).querySelector("iframe#squatchFrame")}_detachLoadEventListener(t){this.loadEventListener&&(t.removeEventListener("sq:user-registration",this.loadEventListener),this.loadEventListener=null)}_attachLoadEventListener(t,e){this.loadEventListener===null&&(this.loadEventListener=n=>{this._loadEvent({...e,userId:n.detail.userId,accountId:n.detail.accountId})},t.addEventListener("sq:user-registration",this.loadEventListener))}_loadEvent(t){var n;if(!t)return;if(!S(t))throw new Error("Widget Load event identity property is not an object");let e;if("programId"in t){if(!t.tenantAlias||!t.accountId||!t.userId||!t.engagementMedium)throw new Error("Widget Load event missing required properties");e={tenantAlias:t.tenantAlias,externalAccountId:t.accountId,externalUserId:t.userId,engagementMedium:t.engagementMedium,programId:t.programId}}else{const{analytics:i,mode:s}=t;e={tenantAlias:i.attributes.tenant,externalAccountId:i.attributes.accountId,externalUserId:i.attributes.userId,engagementMedium:s.widgetMode}}(n=this.analyticsApi.pushAnalyticsLoadEvent(e))==null||n.then(i=>{y(`${e.engagementMedium} loaded event recorded.`)}).catch(i=>{y(`ERROR: pushAnalyticsLoadEvent() ${i}`)})}_shareEvent(t,e){t&&this.analyticsApi.pushAnalyticsShareClickedEvent({tenantAlias:t.analytics.attributes.tenant,externalAccountId:t.analytics.attributes.accountId,externalUserId:t.analytics.attributes.userId,engagementMedium:t.mode.widgetMode,shareMedium:e}).then(n=>{y(`${t.mode.widgetMode} share ${e} event recorded. ${n}`)}).catch(n=>{y(`ERROR: pushAnalyticsShareClickedEvent() ${n}`)})}async _findInnerContainer(t){const{contentWindow:e}=t;if(!e)throw new Error("Squatch.js frame inner frame is empty");const n=e.document;function i(){const r=n.getElementsByTagName("sqh-global-container"),a=n.getElementsByClassName("squatch-container");return r.length>0?r[0]:a.length>0?a[0]:null}let s=null;for(let r=0;r<5&&(s=i(),!s);r++)await Le(100);return s||n.body}async _getSkeletonPreloadHTML(t,e){if(!t)return"";const{getSkeleton:n}=await Promise.resolve().then(()=>require("./SkeletonTemplate-B3Bk4NFu.cjs")),i=this.context.type==="passwordless"?"instant-access":"verified-access",s=n({type:i}),r=new Set,a=/<([a-z][\w]*-[\w-]*)/gi;let c;for(;c=a.exec(this.content);)r.add(c[1].toLowerCase());const d=JSON.stringify([...r]);return`
|
|
19
19
|
<div id="sq-preload" style="visibility: visible; position: absolute; top: 0; left: 0; width: 100%; z-index: 9999; background: ${(e||"white").replace(/[^a-zA-Z0-9#(),.\s%-]/g,"")};">
|
|
20
20
|
${s}
|
|
21
21
|
</div>
|
|
22
22
|
<script>(${Oe.toString()})(${d})<\/script>
|
|
23
|
-
`}reload({email:t,firstName:e,lastName:n},i){const s=this._findFrame();if(!s)throw new Error("Could not find widget iframe");const r=s.contentWindow,a=this.context.engagementMedium||"POPUP";if(!r)throw new Error("Frame needs a content window");let c;if(this.context.type==="upsert"){if(!this.context.user)throw new Error("Can't reload without user ids");let d={email:t||null,firstName:e||null,lastName:n||null,id:this.context.user.id,accountId:this.context.user.accountId};c=this.widgetApi.upsertUser({user:d,engagementMedium:a,widgetType:this.type,jwt:i})}else if(this.context.type==="passwordless")c=this.widgetApi.render({user:void 0,engagementMedium:a,widgetType:this.type,jwt:void 0});else throw new Error("can't reload an error widget");c.then(({template:d})=>{d&&(this.content=d,this.__deprecated__register(s,{email:t,engagementMedium:a},()=>{this.load(),a==="POPUP"&&this.open()}))}).catch(({message:d})=>{y(`${d}`)})}__deprecated__register(t,e,n){const s=t.contentWindow.document,r=s.createElement("button"),a=s.getElementsByClassName("squatch-register")[0];if(a){r.className="btn btn-primary",r.id="show-stats-btn",r.textContent=this.type==="REFERRER_WIDGET"?"Show Stats":"Show Reward";const c=e.engagementMedium==="POPUP"?"margin-top: 10px; max-width: 130px; width: 100%;":"margin-top: 10px;";r.setAttribute("style",c),r.onclick=n,a.style.paddingTop="30px",a.innerHTML=`<p><strong>${e.email}</strong><br>Has been successfully registered</p>`,a.appendChild(r)}}}function Le(o){return new Promise(t=>{setTimeout(t,o)})}function Oe(o){var t=setTimeout(e,1e4);function e(){var i=document.getElementById("sq-preload");i&&i.remove(),clearTimeout(t)}function n(){if(!o||!o.length)return e();Promise.all(o.map(function(i){return customElements.whenDefined(i)})).then(function(){requestAnimationFrame(function(){requestAnimationFrame(e)})})}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",n):setTimeout(n,0)}const A=C("squatch-js:EMBEDwidget");class
|
|
23
|
+
`}reload({email:t,firstName:e,lastName:n},i){const s=this._findFrame();if(!s)throw new Error("Could not find widget iframe");const r=s.contentWindow,a=this.context.engagementMedium||"POPUP";if(!r)throw new Error("Frame needs a content window");let c;if(this.context.type==="upsert"){if(!this.context.user)throw new Error("Can't reload without user ids");let d={email:t||null,firstName:e||null,lastName:n||null,id:this.context.user.id,accountId:this.context.user.accountId};c=this.widgetApi.upsertUser({user:d,engagementMedium:a,widgetType:this.type,jwt:i})}else if(this.context.type==="passwordless")c=this.widgetApi.render({user:void 0,engagementMedium:a,widgetType:this.type,jwt:void 0});else throw new Error("can't reload an error widget");c.then(({template:d})=>{d&&(this.content=d,this.__deprecated__register(s,{email:t,engagementMedium:a},()=>{this.load(),a==="POPUP"&&this.open()}))}).catch(({message:d})=>{y(`${d}`)})}__deprecated__register(t,e,n){const s=t.contentWindow.document,r=s.createElement("button"),a=s.getElementsByClassName("squatch-register")[0];if(a){r.className="btn btn-primary",r.id="show-stats-btn",r.textContent=this.type==="REFERRER_WIDGET"?"Show Stats":"Show Reward";const c=e.engagementMedium==="POPUP"?"margin-top: 10px; max-width: 130px; width: 100%;":"margin-top: 10px;";r.setAttribute("style",c),r.onclick=n,a.style.paddingTop="30px",a.innerHTML=`<p><strong>${e.email}</strong><br>Has been successfully registered</p>`,a.appendChild(r)}}}function Le(o){return new Promise(t=>{setTimeout(t,o)})}function Oe(o){var t=setTimeout(e,1e4);function e(){var i=document.getElementById("sq-preload");i&&i.remove(),clearTimeout(t)}function n(){if(!o||!o.length)return e();Promise.all(o.map(function(i){return customElements.whenDefined(i)})).then(function(){requestAnimationFrame(function(){requestAnimationFrame(e)})})}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",n):setTimeout(n,0)}const A=C("squatch-js:EMBEDwidget");class q extends pe{constructor(e,n){super(e);l(this,"show",this.open);l(this,"hide",this.close);n&&(this.container=n)}async load(){var g,f,b,w,W,ne,ie,oe,se;const e=(f=(g=this.context.widgetConfig)==null?void 0:g.values)==null?void 0:f.brandingConfig,n=(b=this.content)==null?void 0:b.includes("mint-components"),i=(e==null?void 0:e.loadingHeight)||500,s=(w=e==null?void 0:e.widgetSize)==null?void 0:w.embeddedWidgets,r=s!=null&&s.maxWidth?F(s.maxWidth):"",a=s!=null&&s.minWidth?F(s.minWidth):"",c=this._createFrame({minWidth:a,maxWidth:r,initialHeight:i}),d=this._findElement();(W=this.context)!=null&&W.container&&(d.style.visibility="hidden",d.style.height="0",d.style["overflow-y"]="hidden"),this.container?d.shadowRoot?((ne=d.shadowRoot.lastChild)==null?void 0:ne.nodeName)==="IFRAME"?d.shadowRoot.replaceChild(c,d.shadowRoot.lastChild):d.shadowRoot.appendChild(c):d.firstChild?d.replaceChild(c,d.firstChild):d.appendChild(c):(!d.firstChild||d.firstChild.nodeName==="#text")&&d.appendChild(c);const{contentWindow:h}=c;if(!h)throw new Error("Frame needs a content window");const u=h.document;if(u.open(),this.content==="error"){u.write(await this._getContent()),u.close(),$(u,()=>{c.height=u.body.scrollHeight});return}const p=this.widgetApi.domain==="https://staging.referralsaasquatch.com"?"-staging":"";u.write(`
|
|
24
24
|
${(ie=e==null?void 0:e.main)!=null&&ie.brandFont?`
|
|
25
25
|
<link rel="preconnect" href="https://fast${p}.ssqt.io">
|
|
26
|
-
<link rel="preconnect" href="https://fonts.gstatic.com">
|
|
26
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
27
27
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
28
28
|
<link rel="preload" href="https://fonts.googleapis.com/css2?family=${encodeURIComponent((oe=e==null?void 0:e.main)==null?void 0:oe.brandFont)}" as="style">`:""}
|
|
29
29
|
<link rel="dns-prefetch" href="https://res.cloudinary.com">
|
|
@@ -34,19 +34,19 @@
|
|
|
34
34
|
</style>`:""}
|
|
35
35
|
${await this._getSkeletonPreloadHTML(n,(se=e==null?void 0:e.color)==null?void 0:se.backgroundColor)}
|
|
36
36
|
${await this._getContent()}
|
|
37
|
-
`),u.close()
|
|
37
|
+
`),u.close(),$(u,async()=>{const re=h.squatch||h.widgetIdent;c.height=i;const ye=new h.ResizeObserver(Ce=>{for(const be of Ce){const{height:ve}=be.contentRect;c.height=ve}}),Ee=await this._findInnerContainer(c);ye.observe(Ee),this._shouldFireLoadEvent()?(this._loadEvent(re),A("loaded")):u&&this._attachLoadEventListener(u,re)})}open(){const e=this._findFrame();if(!e)return A("no target element to open");if(!e.contentWindow)return A("Frame needs a content window");const n=this._findElement();n.style.visibility="unset",n.style.height="auto",n.style["overflow-y"]="auto",e.contentWindow.document.dispatchEvent(new CustomEvent("sq:refresh"));const i=e.contentWindow.squatch||e.contentWindow.widgetIdent;if(this.context.user)this._loadEvent(i),A("loaded");else{if(!e.contentDocument)return;this._attachLoadEventListener(e.contentDocument,i)}}close(){const e=this._findFrame();if(!e)return A("no target element to close");e.contentDocument&&this._detachLoadEventListener(e.contentDocument);const n=this._findElement();n.style.visibility="hidden",n.style.height="0",n.style["overflow-y"]="hidden",A("Embed widget closed")}_getErrorMode(){return"embed"}_shouldFireLoadEvent(){const e=!this.container,n=this.container instanceof HTMLElement&&(this.container.tagName.startsWith("SQUATCH-")||this.container.tagName.startsWith("IMPACT-"));return!!this.context.user&&(e||n)}}const I=C("squatch-js:POPUPwidget");let O=0;class x extends pe{constructor(e,n=".squatchpop"){super(e);l(this,"trigger");l(this,"id");l(this,"show",this.open);l(this,"hide",this.close);this.trigger=n,this.container?this.id="squatchModal":(this.id=O===0?"squatchModal":`squatchModal__${O}`,O=O+1),document.head.insertAdjacentHTML("beforeend",`<style>#${this.id}::-webkit-scrollbar { display: none; }</style>`)}_initialiseCTA(){if(!this.trigger)return;let e;try{e=document.querySelector(this.trigger)||document.querySelector(".impactpop"),this.trigger&&!e&&I("No element found with trigger selector",this.trigger)}catch{I("Not a valid selector",this.trigger)}e&&(e.onclick=()=>{this.open()})}_createPopupDialog(e){var c;const n=document.createElement("dialog"),i=(c=e==null?void 0:e.widgetSize)==null?void 0:c.popupWidgets,s=i!=null&&i.minWidth?F(i.minWidth):"auto",r=i!=null&&i.maxWidth?F(i.maxWidth):"500px";n.id=this.id,n.setAttribute("style",`width: 100%; min-width: ${s}; max-width: ${r}; border: none; padding: 0;`);const a=d=>{d.stopPropagation(),d.target===n&&n.close()};return n.addEventListener("click",a),n}async load(){var m,p,g,f,b,w,W;const e=(p=(m=this.context.widgetConfig)==null?void 0:m.values)==null?void 0:p.brandingConfig,n=(e==null?void 0:e.loadingHeight)||500,i=(g=this.content)==null?void 0:g.includes("mint-components"),s=this._createFrame();s.style.height=n+"px",this._initialiseCTA();const r=this.container?this._findElement():document.body,a=(r==null?void 0:r.shadowRoot)||r,c=this._createPopupDialog(e);c.appendChild(s),((f=a.lastChild)==null?void 0:f.nodeName)==="DIALOG"?a.replaceChild(c,a.lastChild):a.appendChild(c);const{contentWindow:d}=s;if(!d)throw new Error("Frame needs a content window");const h=d.document;if(h.open(),this.content==="error"){h.write(await this._getContent()),h.close(),$(h,()=>{s.height=h.body.scrollHeight}),I("Popup error template loaded into iframe");return}const u=this.widgetApi.domain;h.write(`
|
|
38
38
|
${(b=e==null?void 0:e.main)!=null&&b.brandFont?`
|
|
39
39
|
<link rel="preconnect" href="https://fast${u==="https://staging.referralsaasquatch.com"?"-staging":""}.ssqt.io">
|
|
40
|
-
<link rel="preconnect" href="https://fonts.gstatic.com">
|
|
40
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
41
41
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
42
|
-
<link rel="preload" href="https://fonts.googleapis.com/css2?family=${encodeURIComponent((
|
|
42
|
+
<link rel="preload" href="https://fonts.googleapis.com/css2?family=${encodeURIComponent((w=e==null?void 0:e.main)==null?void 0:w.brandFont)}" as="style">`:""}
|
|
43
43
|
<link rel="dns-prefetch" href="https://res.cloudinary.com">
|
|
44
44
|
<link rel="preconnect" href="https://res.cloudinary.com" crossorigin>
|
|
45
45
|
${i?`
|
|
46
46
|
<style data-styles>
|
|
47
47
|
html { visibility: hidden; }
|
|
48
48
|
</style>`:""}
|
|
49
|
-
${await this._getSkeletonPreloadHTML(i,(
|
|
49
|
+
${await this._getSkeletonPreloadHTML(i,(W=e==null?void 0:e.color)==null?void 0:W.backgroundColor)}
|
|
50
50
|
${await this._getContent()}
|
|
51
|
-
`),h.close(),I("Popup template loaded into iframe"),await this._setupResizeHandler(s)}async _setupResizeHandler(e){const{contentWindow:n}=e;if(!n)throw new Error("Frame needs a content window");const i=n.document;q(i,async()=>{i.body.style.overflowY="hidden";let s=!0;new n.ResizeObserver(a=>{for(const c of a){const{top:d,bottom:h}=c.contentRect,u=h+d;u<=0||(s?(s=!1,e.style.height="0",e.height=i.body.scrollHeight+"",e.style.height=""):e.height=u+"",c.target.style="")}}).observe(await this._findInnerContainer(e))})}open(){const e=this.container?this._findElement():document.body,i=(e.shadowRoot||e).querySelector(`#${this.id}`);if(!i)throw new Error("Could not determine container div");i.showModal();const s=this._findFrame();if(!s)throw new Error("Could not find iframe");const{contentWindow:r}=s;if(!r)throw new Error("Squatch.js has an empty iframe");const a=r.document;q(a,()=>{var d;const c=r.squatch||r.widgetIdent;(d=s.contentDocument)==null||d.dispatchEvent(new CustomEvent("sq:refresh")),this.context.user?(this._loadEvent(c),I("Popup opened")):this._attachLoadEventListener(a,c)})}close(){const e=this._findFrame();e!=null&&e.contentDocument&&this._detachLoadEventListener(e.contentDocument);const n=this.container?this._findElement():document.body,s=(n.shadowRoot||n).querySelector(`#${this.id}`);if(!s)throw new Error("Could not determine container div");s.close(),I("Popup closed")}_getErrorStyle(){return"body { margin: 0; } .modal { box-shadow: none; border: 0; }"}}const E=C("squatch-js:widgets");class P{constructor(t){l(this,"api");l(this,"tenantAlias");l(this,"domain");l(this,"npmCdn");const e=M(t);this.tenantAlias=e.tenantAlias,this.domain=e.domain,this.npmCdn=e.npmCdn,this.api=new z(e)}async upsertUser(t){const n=he(t);try{const i=await this.api.upsertUser(n);return{widget:this._renderWidget(i,n,{type:"upsert",user:n.user,engagementMedium:t.engagementMedium,container:t.container,trigger:t.trigger,widgetConfig:{values:{brandingConfig:i==null?void 0:i.brandingConfig}}}),user:i.user}}catch(i){throw E(i),i.apiErrorCode&&this._renderErrorWidget(i,t.engagementMedium),new Error(i)}}async render(t){const n=ue(t);try{const i=await this.api.render(n);return{widget:this._renderWidget(i,n,{type:"passwordless",engagementMedium:n.engagementMedium,container:n.container,trigger:n.trigger,widgetConfig:i==null?void 0:i.widgetConfig}),user:i.user}}catch(i){throw i.apiErrorCode&&this._renderErrorWidget(i,n.engagementMedium),new Error(i)}}async autofill(t){const e=t;if(typeof e=="function"){try{const s=await this.api.squatchReferralCookie();e(s)}catch(s){throw E("Autofill error",s),new Error(s)}return}if(typeof e!="string")throw new Error("Autofill accepts a string or function");let n=document.querySelectorAll(e),i;if(n.length>0)i=n[0];else throw E("Element id/class or function missing"),new Error("Element id/class or function missing");try{const s=await this.api.squatchReferralCookie();i.value=s.codes[0]}catch(s){throw new Error(s)}}_renderWidget(t,e,n){var c;if(E("Rendering Widget..."),!t)throw new Error("Unable to get a response");let i,s=!!e.displayOnLoad;const r=t.jsOptions||{},a={content:t.template,type:e.widgetType||((c=r.widget)==null?void 0:c.defaultWidgetType),api:this.api,domain:this.domain,npmCdn:this.npmCdn,context:n};return r.widgetUrlMappings&&r.widgetUrlMappings.forEach(d=>{var h,u;P._matchesUrl(d.url)&&(d.widgetType!=="CONVERSION_WIDGET"||(u=(h=t.user)==null?void 0:h.referredBy)!=null&&u.code?(s=d.displayOnLoad,E(`Display ${d.widgetType} on ${d.url}`)):E(`Don't display ${d.widgetType} when no referral on widget rule match ${d.url}`))}),r.fuelTankAutofillUrls&&(E("We found a fuel tank autofill!"),r.fuelTankAutofillUrls.forEach(({url:d,formSelector:h})=>{var u,m,p;if(P._matchesUrl(d)&&(E("Fuel Tank URL matches"),(m=(u=t.user)==null?void 0:u.referredBy)!=null&&m.code)){const g=document.querySelector(h);g?g.value=((p=t.user.referredBy.referredReward)==null?void 0:p.fuelTankCode)||"":E(new Error(`Element with id/class ${h} was not found.`))}})),e.engagementMedium==="EMBED"?i=this._renderEmbedWidget(a):(i=this._renderPopupWidget(a),s&&i.open()),i}_renderPopupWidget(t){const e=new x(t,t.context.trigger);return e.load(),e}_renderEmbedWidget(t){const e=new $(t,t.context.container);return e.load(),e}_renderErrorWidget(t,e="POPUP"){const{apiErrorCode:n,rsCode:i,statusCode:s,message:r}=t;E(new Error(`${n} (${i}) ${r}`));const a={content:"error",rsCode:i,apiErrorCode:n,statusCode:s,errorMessage:r,api:this.api,domain:this.domain,npmCdn:this.npmCdn,type:"ERROR_WIDGET",context:{type:"error"}};let c;e==="EMBED"?(c=new $(a),c.load()):e==="POPUP"&&(c=new x(a),c.load())}static _matchesUrl(t){return!!window.location.href.match(new RegExp(t))}}class De{constructor(t){l(this,"tenantAlias");l(this,"domain");const n=M(t);this.tenantAlias=n.tenantAlias,this.domain=n.domain}track(t,e){const n=t,i=e,s=je(n),{jwt:r}=Ne(i),a=encodeURIComponent(this.tenantAlias),c=encodeURIComponent(s.userId),d=encodeURIComponent(s.accountId),h=`/api/v1/${a}/open/account/${d}/user/${c}/events`,u=this.domain+h;return Z(u,JSON.stringify(s),r)}}function je(o){if(!W(o))throw new Error("tracking parameter must be an object");if(!(o!=null&&o.accountId))throw new Error("accountId field is required");if(!(o!=null&&o.events))throw new Error("events field is required");if(!(o!=null&&o.userId))throw new Error("userId field is required");const t=o;if(!Array.isArray(t.events))throw new Error("'events' should be an array");return t}function Ne(o){if(!W(o))throw new Error("'options' should be an object");return o}function Fe(){var i;const o=window[X]?X:L,t=((i=window["_"+o])==null?void 0:i.ready)||[],e=window.impactOnReady||window.squatchOnReady,n=[...t,e].filter(s=>!!s);setTimeout(()=>{window[L]&&(window[X]=window[L],n.forEach(s=>s()),window[L]._auto(),window["_"+o]=void 0,delete window["_"+o])},0)}const D=C("squatch-js");function He(){var u;const o=window.location.search,e=new URLSearchParams(o).get("_saasquatchExtra")||"";if(!e){D("No _saasquatchExtra param");return}const n=M({tenantAlias:"UNKNOWN"});if(!n.domain){D("domain must be provided in config to use _saasquatchExtra");return}let i;try{i=JSON.parse(N(e))}catch{D("Unable to decode _saasquatchExtra config");return}function s(m){return m.replace(/^https?:\/\//,"")}const r=s(n.domain),a=Object.keys((i==null?void 0:i[r])||{})[0],c=(u=i==null?void 0:i[r])==null?void 0:u[a];if(!c){D("_saasquatchExtra did not have an expected structure");return}const{autoPopupWidgetType:d,...h}=c;return{widgetConfig:{widgetType:d,displayOnLoad:!0,...h},squatchConfig:{...n,tenantAlias:a}}}const Je=C("squatch-js:decodeUserJwt");function Be(o){var t;try{const e=o.split(".")[1];if(e===void 0)return null;const n=N(e);return(t=JSON.parse(n))==null?void 0:t.user}catch(e){return Je(e),null}}const j=C("squatch-js:DeclarativeWidget");class fe extends HTMLElement{constructor(){super();l(this,"config");l(this,"token");l(this,"tenant");l(this,"widgetType");l(this,"locale");l(this,"widgetApi");l(this,"analyticsApi");l(this,"widgetInstance");l(this,"type");l(this,"container");l(this,"element");l(this,"loaded");l(this,"_setWidget",(e,n)=>{var s;const i={api:this.widgetApi,content:e.template,context:{type:n.type,user:n.user,container:this.container||void 0,engagementMedium:this.type,widgetConfig:e.widgetConfig},type:this.widgetType,domain:((s=this.config)==null?void 0:s.domain)||k,npmCdn:Y,container:this};if(this.type==="EMBED")return new $(i);{const r=this.firstChild?null:void 0;return new x(i,r)}});l(this,"setErrorWidget",e=>{var c;const n=e instanceof Error?e.message:e==null?void 0:e.message,i=e==null?void 0:e.apiErrorCode,s=e==null?void 0:e.rsCode,r=e==null?void 0:e.statusCode,a={api:this.widgetApi,content:"error",context:{type:"error",container:this.container||void 0},type:"ERROR_WIDGET",domain:((c=this.config)==null?void 0:c.domain)||k,npmCdn:Y,container:this,apiErrorCode:i,rsCode:s,statusCode:r,errorMessage:n};if(this.type==="EMBED")return new $(a);{const d=this.firstChild?null:void 0;return new x(a,d)}});l(this,"reload",this.renderWidget);l(this,"show",this.open);l(this,"hide",this.close);this.attachShadow({mode:"open"}).innerHTML="<style>:host { display: block; }</style><slot></slot>",this.config=K(),this.token=U(),this.tenant=window.squatchTenant,this.container=this}_setupApis(e){var n,i;if(!this.tenant)throw new Error("tenantAlias not provided");this.widgetApi=new z({tenantAlias:(e==null?void 0:e.tenantAlias)||this.tenant,domain:(e==null?void 0:e.domain)||((n=this.config)==null?void 0:n.domain)||k}),this.analyticsApi=new ge({domain:(e==null?void 0:e.domain)||((i=this.config)==null?void 0:i.domain)||k})}getWidgetType(e){return e&&e.includes("friendWidget")?"instant-access":"verified-access"}async renderPasswordlessVariant(){return this._setupApis(),j("Rendering as an Instant Access widget"),await this.widgetApi.render({engagementMedium:this.type,widgetType:this.widgetType,locale:this.locale}).then(e=>this._setWidget(e,{type:"passwordless"})).catch(this.setErrorWidget)}async renderUserUpsertVariant(){this._setupApis();const e=Be(this.token);if(!e)return this.setErrorWidget(Error("No user object in token."));!this.locale&&e.locale&&(this.locale=e.locale),j("Rendering as a Verified widget");try{await this.widgetApi.upsertUser({user:e,locale:this.locale,engagementMedium:this.type,widgetType:this.widgetType,jwt:this.token})}catch(i){return this.setErrorWidget(i)}return await this.widgetApi.render({locale:this.locale,engagementMedium:this.type,widgetType:this.widgetType}).then(i=>this._setWidget(i,{type:"upsert",user:e})).catch(this.setErrorWidget)}async getWidgetInstance(){let e;this.widgetType=this.getAttribute("widget")||void 0,this.locale=this.getAttribute("locale")||this.locale;const n=this.getWidgetType(this.widgetType);if(!this.widgetType)throw new Error("No widget has been specified");return!this.token&&n==="verified-access"&&(j("[SquatchJS] Authentication token is required for this widget type."),console.log("[SquatchJS] Authentication token is required for this widget type.")),this.token?e=await this.renderUserUpsertVariant():e=await this.renderPasswordlessVariant(),this.widgetInstance=e,this.widgetInstance&&this.dispatchEvent(new CustomEvent("sq:widget-loaded")),e}async renderWidget(){await this.getWidgetInstance(),await this.widgetInstance.load()}open(){if(!this.widgetInstance)throw new Error("Widget has not loaded yet");this.widgetInstance.open()}close(){if(!this.widgetInstance)throw new Error("Widget has not loaded yet");this.widgetInstance.close()}static get observedAttributes(){return["widget","locale"]}attributeChangedCallback(e,n,i){if(!(n===i||!this.loaded))switch(e){case"locale":case"widget":this.connectedCallback();break}}async connectedCallback(){this.loaded=!0,this.container=this.getAttribute("container"),this.widgetType=this.getAttribute("widget")||void 0;const e=this.getWidgetType(this.widgetType),{getSkeleton:n}=await Promise.resolve().then(()=>require("./SkeletonTemplate-B3Bk4NFu.cjs")),i=n({type:e}),s=document.createElement("div");s.id="loading-skeleton",s.innerHTML=i;const r=this.shadowRoot||this.attachShadow({mode:"open"});if(this.type==="POPUP"){const a=r.getElementById("squatchModal");a?(a.innerHTML="",a.appendChild(s)):r.appendChild(s)}else r.innerHTML="",r.appendChild(s);try{await this.renderWidget()}catch(a){j("Failed to render widget",a)}finally{const a=r.getElementById("loading-skeleton");a&&a.remove()}this.getAttribute("open")!==null&&this.open()}}class ee extends fe{constructor(){super(),this.type="EMBED",this.loaded=!1}}class te extends fe{constructor(){super(),this.type="POPUP",this.loaded=!1,this.addEventListener("click",t=>{t.stopPropagation(),this.open()})}}class Ge extends ee{}class ze extends te{}class Ve extends ee{}class Xe extends te{}window.customElements.get("squatch-embed")||window.customElements.define("squatch-embed",Ge);window.customElements.get("impact-embed")||window.customElements.define("impact-embed",Ve);window.customElements.get("squatch-popup")||window.customElements.define("squatch-popup",ze);window.customElements.get("impact-popup")||window.customElements.define("impact-popup",Xe);function Qe(){console.log("Having trouble using Squatch.js? Go to https://docs.referralsaasquatch.com/developer/ for tutorials, references and error codes.")}const T=C("squatch-js");let H=null,J=null,B=null;function Ye(){return H||R({}),H}function V(){return J||R({}),J}function Ze(){return B||R({}),B}function Ke(o){var t;return(t=V())==null?void 0:t.render(o)}function et(){var t;const o=He();if(o){const{squatchConfig:e,widgetConfig:n}=o;return R(e),(t=V())==null?void 0:t.render(n)}}function R(o){const e=M(o);e.tenantAlias.match("^test")||e.debug?_e("squatch-js*"):ke(),T("initializing ..."),H=new z(e),J=new P(e),B=new De(e),T("Widget API instance",H),T("Widgets instance",J),T("Events API instance",B)}function tt(o){o()}function nt(o){V().autofill(o)}function we(){Te()}typeof document<"u"&&!window.SaaSquatchDoNotAutoDrop&&we();var de;(de=window.squatch)!=null&&de.init&&T("Squatchjs is being loaded more than once. This may lead to multiple load events being sent, duplicated widgets, and inaccurate analytics.");typeof document<"u"&&Fe();exports.DeclarativeEmbedWidget=ee;exports.DeclarativePopupWidget=te;exports.EmbedWidget=$;exports.PopupWidget=x;exports.WidgetApi=z;exports.Widgets=P;exports._auto=et;exports.api=Ye;exports.autofill=nt;exports.events=Ze;exports.help=Qe;exports.init=R;exports.pushCookie=we;exports.ready=tt;exports.widget=Ke;exports.widgets=V;
|
|
51
|
+
`),h.close(),I("Popup template loaded into iframe"),await this._setupResizeHandler(s)}async _setupResizeHandler(e){const{contentWindow:n}=e;if(!n)throw new Error("Frame needs a content window");const i=n.document;$(i,async()=>{i.body.style.overflowY="hidden";let s=!0;new n.ResizeObserver(a=>{for(const c of a){const{top:d,bottom:h}=c.contentRect,u=h+d;u<=0||(s?(s=!1,e.style.height="0",e.height=i.body.scrollHeight+"",e.style.height=""):e.height=u+"",c.target.style="")}}).observe(await this._findInnerContainer(e))})}open(){const e=this.container?this._findElement():document.body,i=(e.shadowRoot||e).querySelector(`#${this.id}`);if(!i)throw new Error("Could not determine container div");i.showModal();const s=this._findFrame();if(!s)throw new Error("Could not find iframe");const{contentWindow:r}=s;if(!r)throw new Error("Squatch.js has an empty iframe");const a=r.document;$(a,()=>{var d;const c=r.squatch||r.widgetIdent;(d=s.contentDocument)==null||d.dispatchEvent(new CustomEvent("sq:refresh")),this.context.user?(this._loadEvent(c),I("Popup opened")):this._attachLoadEventListener(a,c)})}close(){const e=this._findFrame();e!=null&&e.contentDocument&&this._detachLoadEventListener(e.contentDocument);const n=this.container?this._findElement():document.body,s=(n.shadowRoot||n).querySelector(`#${this.id}`);if(!s)throw new Error("Could not determine container div");s.close(),I("Popup closed")}_getErrorStyle(){return"body { margin: 0; } .modal { box-shadow: none; border: 0; }"}}const E=C("squatch-js:widgets");class M{constructor(t){l(this,"api");l(this,"tenantAlias");l(this,"domain");l(this,"npmCdn");const e=P(t);this.tenantAlias=e.tenantAlias,this.domain=e.domain,this.npmCdn=e.npmCdn,this.api=new z(e)}async upsertUser(t){const n=he(t);try{const i=await this.api.upsertUser(n);return{widget:this._renderWidget(i,n,{type:"upsert",user:n.user,engagementMedium:t.engagementMedium,container:t.container,trigger:t.trigger,widgetConfig:{values:{brandingConfig:i==null?void 0:i.brandingConfig}}}),user:i.user}}catch(i){throw E(i),i.apiErrorCode&&this._renderErrorWidget(i,t.engagementMedium),new Error(i)}}async render(t){const n=ue(t);try{const i=await this.api.render(n);return{widget:this._renderWidget(i,n,{type:"passwordless",engagementMedium:n.engagementMedium,container:n.container,trigger:n.trigger,widgetConfig:i==null?void 0:i.widgetConfig}),user:i.user}}catch(i){throw i.apiErrorCode&&this._renderErrorWidget(i,n.engagementMedium),new Error(i)}}async autofill(t){const e=t;if(typeof e=="function"){try{const s=await this.api.squatchReferralCookie();e(s)}catch(s){throw E("Autofill error",s),new Error(s)}return}if(typeof e!="string")throw new Error("Autofill accepts a string or function");let n=document.querySelectorAll(e),i;if(n.length>0)i=n[0];else throw E("Element id/class or function missing"),new Error("Element id/class or function missing");try{const s=await this.api.squatchReferralCookie();i.value=s.codes[0]}catch(s){throw new Error(s)}}_renderWidget(t,e,n){var c;if(E("Rendering Widget..."),!t)throw new Error("Unable to get a response");let i,s=!!e.displayOnLoad;const r=t.jsOptions||{},a={content:t.template,type:e.widgetType||((c=r.widget)==null?void 0:c.defaultWidgetType),api:this.api,domain:this.domain,npmCdn:this.npmCdn,context:n};return r.widgetUrlMappings&&r.widgetUrlMappings.forEach(d=>{var h,u;M._matchesUrl(d.url)&&(d.widgetType!=="CONVERSION_WIDGET"||(u=(h=t.user)==null?void 0:h.referredBy)!=null&&u.code?(s=d.displayOnLoad,E(`Display ${d.widgetType} on ${d.url}`)):E(`Don't display ${d.widgetType} when no referral on widget rule match ${d.url}`))}),r.fuelTankAutofillUrls&&(E("We found a fuel tank autofill!"),r.fuelTankAutofillUrls.forEach(({url:d,formSelector:h})=>{var u,m,p;if(M._matchesUrl(d)&&(E("Fuel Tank URL matches"),(m=(u=t.user)==null?void 0:u.referredBy)!=null&&m.code)){const g=document.querySelector(h);g?g.value=((p=t.user.referredBy.referredReward)==null?void 0:p.fuelTankCode)||"":E(new Error(`Element with id/class ${h} was not found.`))}})),e.engagementMedium==="EMBED"?i=this._renderEmbedWidget(a):(i=this._renderPopupWidget(a),s&&i.open()),i}_renderPopupWidget(t){const e=new x(t,t.context.trigger);return e.load(),e}_renderEmbedWidget(t){const e=new q(t,t.context.container);return e.load(),e}_renderErrorWidget(t,e="POPUP"){const{apiErrorCode:n,rsCode:i,statusCode:s,message:r}=t;E(new Error(`${n} (${i}) ${r}`));const a={content:"error",rsCode:i,apiErrorCode:n,statusCode:s,errorMessage:r,api:this.api,domain:this.domain,npmCdn:this.npmCdn,type:"ERROR_WIDGET",context:{type:"error"}};let c;e==="EMBED"?(c=new q(a),c.load()):e==="POPUP"&&(c=new x(a),c.load())}static _matchesUrl(t){return!!window.location.href.match(new RegExp(t))}}class De{constructor(t){l(this,"tenantAlias");l(this,"domain");const n=P(t);this.tenantAlias=n.tenantAlias,this.domain=n.domain}track(t,e){const n=t,i=e,s=je(n),{jwt:r}=Ne(i),a=encodeURIComponent(this.tenantAlias),c=encodeURIComponent(s.userId),d=encodeURIComponent(s.accountId),h=`/api/v1/${a}/open/account/${d}/user/${c}/events`,u=this.domain+h;return Z(u,JSON.stringify(s),r)}}function je(o){if(!S(o))throw new Error("tracking parameter must be an object");if(!(o!=null&&o.accountId))throw new Error("accountId field is required");if(!(o!=null&&o.events))throw new Error("events field is required");if(!(o!=null&&o.userId))throw new Error("userId field is required");const t=o;if(!Array.isArray(t.events))throw new Error("'events' should be an array");return t}function Ne(o){if(!S(o))throw new Error("'options' should be an object");return o}function Fe(){var i;const o=window[X]?X:L,t=((i=window["_"+o])==null?void 0:i.ready)||[],e=window.impactOnReady||window.squatchOnReady,n=[...t,e].filter(s=>!!s);setTimeout(()=>{window[L]&&(window[X]=window[L],n.forEach(s=>s()),window[L]._auto(),window["_"+o]=void 0,delete window["_"+o])},0)}const D=C("squatch-js");function He(){var u;const o=window.location.search,e=new URLSearchParams(o).get("_saasquatchExtra")||"";if(!e){D("No _saasquatchExtra param");return}const n=P({tenantAlias:"UNKNOWN"});if(!n.domain){D("domain must be provided in config to use _saasquatchExtra");return}let i;try{i=JSON.parse(N(e))}catch{D("Unable to decode _saasquatchExtra config");return}function s(m){return m.replace(/^https?:\/\//,"")}const r=s(n.domain),a=Object.keys((i==null?void 0:i[r])||{})[0],c=(u=i==null?void 0:i[r])==null?void 0:u[a];if(!c){D("_saasquatchExtra did not have an expected structure");return}const{autoPopupWidgetType:d,...h}=c;return{widgetConfig:{widgetType:d,displayOnLoad:!0,...h},squatchConfig:{...n,tenantAlias:a}}}const Je=C("squatch-js:decodeUserJwt");function Be(o){var t;try{const e=o.split(".")[1];if(e===void 0)return null;const n=N(e);return(t=JSON.parse(n))==null?void 0:t.user}catch(e){return Je(e),null}}const j=C("squatch-js:DeclarativeWidget");class we extends HTMLElement{constructor(){super();l(this,"config");l(this,"token");l(this,"tenant");l(this,"widgetType");l(this,"locale");l(this,"widgetApi");l(this,"analyticsApi");l(this,"widgetInstance");l(this,"type");l(this,"container");l(this,"element");l(this,"loaded");l(this,"_setWidget",(e,n)=>{var s;const i={api:this.widgetApi,content:e.template,context:{type:n.type,user:n.user,container:this.container||void 0,engagementMedium:this.type,widgetConfig:e.widgetConfig},type:this.widgetType,domain:((s=this.config)==null?void 0:s.domain)||k,npmCdn:Y,container:this};if(this.type==="EMBED")return new q(i);{const r=this.firstChild?null:void 0;return new x(i,r)}});l(this,"setErrorWidget",e=>{var c;const n=e instanceof Error?e.message:e==null?void 0:e.message,i=e==null?void 0:e.apiErrorCode,s=e==null?void 0:e.rsCode,r=e==null?void 0:e.statusCode,a={api:this.widgetApi,content:"error",context:{type:"error",container:this.container||void 0},type:"ERROR_WIDGET",domain:((c=this.config)==null?void 0:c.domain)||k,npmCdn:Y,container:this,apiErrorCode:i,rsCode:s,statusCode:r,errorMessage:n};if(this.type==="EMBED")return new q(a);{const d=this.firstChild?null:void 0;return new x(a,d)}});l(this,"reload",this.renderWidget);l(this,"show",this.open);l(this,"hide",this.close);this.attachShadow({mode:"open"}).innerHTML="<style>:host { display: block; }</style><slot></slot>",this.config=K(),this.token=U(),this.tenant=window.squatchTenant,this.container=this}_setupApis(e){var n,i;if(!this.tenant)throw new Error("tenantAlias not provided");this.widgetApi=new z({tenantAlias:(e==null?void 0:e.tenantAlias)||this.tenant,domain:(e==null?void 0:e.domain)||((n=this.config)==null?void 0:n.domain)||k}),this.analyticsApi=new ge({domain:(e==null?void 0:e.domain)||((i=this.config)==null?void 0:i.domain)||k})}getWidgetType(e){return e&&e.includes("friendWidget")?"instant-access":"verified-access"}async renderPasswordlessVariant(){return this._setupApis(),j("Rendering as an Instant Access widget"),await this.widgetApi.render({engagementMedium:this.type,widgetType:this.widgetType,locale:this.locale}).then(e=>this._setWidget(e,{type:"passwordless"})).catch(this.setErrorWidget)}async renderUserUpsertVariant(){this._setupApis();const e=Be(this.token);if(!e)return this.setErrorWidget(Error("No user object in token."));!this.locale&&e.locale&&(this.locale=e.locale),j("Rendering as a Verified widget");try{await this.widgetApi.upsertUser({user:e,locale:this.locale,engagementMedium:this.type,widgetType:this.widgetType,jwt:this.token})}catch(i){return this.setErrorWidget(i)}return await this.widgetApi.render({locale:this.locale,engagementMedium:this.type,widgetType:this.widgetType}).then(i=>this._setWidget(i,{type:"upsert",user:e})).catch(this.setErrorWidget)}async getWidgetInstance(){let e;this.widgetType=this.getAttribute("widget")||void 0,this.locale=this.getAttribute("locale")||this.locale;const n=this.getWidgetType(this.widgetType);if(!this.widgetType)throw new Error("No widget has been specified");return!this.token&&n==="verified-access"&&j("[SquatchJS] Authentication token is required for this widget type."),this.token?e=await this.renderUserUpsertVariant():e=await this.renderPasswordlessVariant(),this.widgetInstance=e,this.widgetInstance&&this.dispatchEvent(new CustomEvent("sq:widget-loaded")),e}async renderWidget(){await this.getWidgetInstance(),await this.widgetInstance.load()}open(){if(!this.widgetInstance)throw new Error("Widget has not loaded yet");this.widgetInstance.open()}close(){if(!this.widgetInstance)throw new Error("Widget has not loaded yet");this.widgetInstance.close()}static get observedAttributes(){return["widget","locale"]}attributeChangedCallback(e,n,i){if(!(n===i||!this.loaded))switch(e){case"locale":case"widget":this.connectedCallback();break}}async connectedCallback(){this.loaded=!0,this.container=this.getAttribute("container"),this.widgetType=this.getAttribute("widget")||void 0;const e=this.getWidgetType(this.widgetType),{getSkeleton:n}=await Promise.resolve().then(()=>require("./SkeletonTemplate-B3Bk4NFu.cjs")),i=n({type:e}),s=document.createElement("div");s.id="loading-skeleton",s.innerHTML=i;const r=this.shadowRoot||this.attachShadow({mode:"open"});if(this.type==="POPUP"){const a=r.getElementById("squatchModal");a?(a.innerHTML="",a.appendChild(s)):r.appendChild(s)}else r.innerHTML="",r.appendChild(s);try{await this.renderWidget()}catch(a){j("Failed to render widget",a)}finally{const a=r.getElementById("loading-skeleton");a&&a.remove()}this.getAttribute("open")!==null&&this.open()}}class ee extends we{constructor(){super(),this.type="EMBED",this.loaded=!1}}class te extends we{constructor(){super(),this.type="POPUP",this.loaded=!1,this.addEventListener("click",t=>{t.stopPropagation(),this.open()})}}class Ge extends ee{}class ze extends te{}class Ve extends ee{}class Xe extends te{}window.customElements.get("squatch-embed")||window.customElements.define("squatch-embed",Ge);window.customElements.get("impact-embed")||window.customElements.define("impact-embed",Ve);window.customElements.get("squatch-popup")||window.customElements.define("squatch-popup",ze);window.customElements.get("impact-popup")||window.customElements.define("impact-popup",Xe);function Qe(){console.log("Having trouble using Squatch.js? Go to https://docs.referralsaasquatch.com/developer/ for tutorials, references and error codes.")}const T=C("squatch-js");let H=null,J=null,B=null;function Ye(){return H||R({}),H}function V(){return J||R({}),J}function Ze(){return B||R({}),B}function Ke(o){var t;return(t=V())==null?void 0:t.render(o)}function et(){var t;const o=He();if(o){const{squatchConfig:e,widgetConfig:n}=o;return R(e),(t=V())==null?void 0:t.render(n)}}function R(o){const e=P(o);e.tenantAlias.match("^test")||e.debug?_e("squatch-js*"):ke(),T("initializing ..."),H=new z(e),J=new M(e),B=new De(e),T("Widget API instance",H),T("Widgets instance",J),T("Events API instance",B)}function tt(o){o()}function nt(o){V().autofill(o)}function fe(){Te()}typeof document<"u"&&!window.SaaSquatchDoNotAutoDrop&&fe();var de;(de=window.squatch)!=null&&de.init&&T("Squatchjs is being loaded more than once. This may lead to multiple load events being sent, duplicated widgets, and inaccurate analytics.");typeof document<"u"&&Fe();exports.DeclarativeEmbedWidget=ee;exports.DeclarativePopupWidget=te;exports.EmbedWidget=q;exports.PopupWidget=x;exports.WidgetApi=z;exports.Widgets=M;exports._auto=et;exports.api=Ye;exports.autofill=nt;exports.events=Ze;exports.help=Qe;exports.init=R;exports.pushCookie=fe;exports.ready=tt;exports.widget=Ke;exports.widgets=V;
|
|
52
52
|
//# sourceMappingURL=squatch.cjs.js.map
|