@saasquatch/squatch-js 2.6.0-1 → 2.6.0-11

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.
Files changed (52) hide show
  1. package/.github/workflows/size-limit.yml +14 -14
  2. package/.github/workflows/static.yml +89 -0
  3. package/CHANGELOG.md +329 -326
  4. package/LICENSE +20 -20
  5. package/README.md +208 -199
  6. package/babel.config.js +7 -7
  7. package/coverage/clover.xml +2 -2
  8. package/cucumber.js +45 -45
  9. package/demo/sandbox.ts +124 -124
  10. package/demo/toolbar.tsx +526 -526
  11. package/dist/api/WidgetApi.d.ts +3 -2
  12. package/dist/async.d.ts +5 -0
  13. package/dist/globals.d.ts +4 -0
  14. package/dist/squatch.d.ts +28 -16
  15. package/dist/squatch.esm.js +464 -249
  16. package/dist/squatch.esm.js.map +1 -1
  17. package/dist/squatch.js +463 -249
  18. package/dist/squatch.js.map +1 -1
  19. package/dist/squatch.min.js +1 -1
  20. package/dist/squatch.min.js.br +0 -0
  21. package/dist/squatch.min.js.map +1 -1
  22. package/dist/squatch.modern.js +1 -1
  23. package/dist/squatch.modern.js.map +1 -1
  24. package/dist/stats.html +1 -1
  25. package/dist/types.d.ts +8 -6
  26. package/dist/utils/decodeJwt.d.ts +1 -0
  27. package/dist/utils/validate.d.ts +2 -2
  28. package/dist/widgets/EmbedWidget.d.ts +9 -0
  29. package/dist/widgets/PopupWidget.d.ts +8 -3
  30. package/dist/widgets/Widgets.d.ts +21 -8
  31. package/dist/widgets/declarative/DeclarativeWidget.d.ts +72 -2
  32. package/dist/widgets/declarative/DeclarativeWidgets.d.ts +22 -0
  33. package/jest.config.ts +200 -202
  34. package/package.json +123 -123
  35. package/tsconfig.json +23 -23
  36. package/coverage/lcov-report/WidgetApi.ts.html +0 -631
  37. package/coverage/lcov-report/api/AnalyticsApi.ts.html +0 -304
  38. package/coverage/lcov-report/api/WidgetApi.ts.html +0 -631
  39. package/coverage/lcov-report/api/graphql.ts.html +0 -130
  40. package/coverage/lcov-report/utils/cookieUtils.ts.html +0 -415
  41. package/coverage/lcov-report/utils/decodeUserJwt.ts.html +0 -133
  42. package/coverage/lcov-report/utils/domready.ts.html +0 -160
  43. package/coverage/lcov-report/utils/io.ts.html +0 -400
  44. package/coverage/lcov-report/utils/utmUtils.ts.html +0 -277
  45. package/coverage/lcov-report/utils/validate.ts.html +0 -268
  46. package/coverage/lcov-report/validate.ts.html +0 -268
  47. package/coverage/lcov-report/widgets/EmbedWidget.ts.html +0 -433
  48. package/coverage/lcov-report/widgets/PopupWidget.ts.html +0 -670
  49. package/coverage/lcov-report/widgets/Widget.ts.html +0 -1165
  50. package/coverage/lcov-report/widgets/Widgets.ts.html +0 -1060
  51. package/coverage/lcov-report/widgets/declarative/DeclarativeWidget.ts.html +0 -499
  52. package/stats.json +0 -1
package/dist/squatch.js CHANGED
@@ -39,10 +39,61 @@ function _objectWithoutPropertiesLoose(source, excluded) {
39
39
  return target;
40
40
  }
41
41
 
42
+ var DEFAULT_DOMAIN = "https://app.referralsaasquatch.com";
43
+ var DEFAULT_NPM_CDN = "https://fast.ssqt.io/npm";
44
+ var DEFAULT_NAMESPACE = "squatch";
45
+ var IMPACT_NAMESPACE = "impact";
46
+
47
+ function validateConfig(_raw) {
48
+ if (typeof _raw !== "object") throw new Error("config must be an object");
49
+ var tenant = window.squatchTenant;
50
+ var config = getConfig();
51
+ var raw = {
52
+ tenantAlias: (_raw == null ? void 0 : _raw["tenantAlias"]) || tenant,
53
+ domain: (_raw == null ? void 0 : _raw["domain"]) || (config == null ? void 0 : config.domain),
54
+ npmCdn: (_raw == null ? void 0 : _raw["npmCdn"]) || (config == null ? void 0 : config.npmCdn),
55
+ debug: (_raw == null ? void 0 : _raw["debug"]) || (config == null ? void 0 : config.debug)
56
+ };
57
+ if (typeof raw.tenantAlias !== "string") throw new Error("tenantAlias not provided");
58
+ var tenantAlias = raw.tenantAlias;
59
+ var domain = typeof raw.domain === "string" && raw.domain || DEFAULT_DOMAIN;
60
+ var debug = typeof raw.debug === "boolean" && raw.debug || false;
61
+ var npmCdn = typeof raw.npmCdn === "string" && raw.npmCdn || DEFAULT_NPM_CDN;
62
+ return {
63
+ tenantAlias,
64
+ domain,
65
+ debug,
66
+ npmCdn
67
+ };
68
+ }
69
+ function isObject$1(obj) {
70
+ return typeof obj === "object" && !Array.isArray(obj) && obj !== null;
71
+ }
72
+ function validateLocale(locale) {
73
+ if (locale && /^[a-z]{2}_(?:[A-Z]{2}|[0-9]{3})$/.test(locale)) {
74
+ return locale;
75
+ }
76
+ }
77
+ function validateWidgetConfig(raw) {
78
+ if (!isObject$1(raw)) throw new Error("Widget properties must be an object");
79
+ if (!(raw != null && raw["user"])) throw new Error("Required properties missing.");
80
+ return raw;
81
+ }
82
+ function validatePasswordlessConfig(raw) {
83
+ if (!isObject$1(raw)) throw new Error("Widget properties must be an object");
84
+ return raw;
85
+ }
86
+ function getToken() {
87
+ return window.impactToken || window.squatchToken;
88
+ }
89
+ function getConfig() {
90
+ return window.impactConfig || window.squatchConfig;
91
+ }
92
+
42
93
  debug.debug("squatch-js:io");
43
94
 
44
95
  async function doQuery(url, query, variables, jwt) {
45
- var token = jwt || window.squatchToken;
96
+ var token = jwt || getToken();
46
97
 
47
98
  var headers = _extends({
48
99
  Accept: "application/json",
@@ -77,7 +128,7 @@ async function doGet(url, jwt) {
77
128
  Accept: "application/json",
78
129
  "Content-Type": "application/json"
79
130
  };
80
- var token = jwt || window.squatchToken;
131
+ var token = jwt || getToken();
81
132
  if (token) headers["X-SaaSquatch-User-Token"] = token;
82
133
 
83
134
  try {
@@ -98,7 +149,7 @@ async function doPost(url, data, jwt) {
98
149
  Accept: "application/json",
99
150
  "Content-Type": "application/json"
100
151
  };
101
- var token = jwt || window.squatchToken;
152
+ var token = jwt || getToken();
102
153
  if (token) headers["X-SaaSquatch-User-Token"] = token;
103
154
 
104
155
  try {
@@ -120,7 +171,7 @@ async function doPut(url, data, jwt) {
120
171
  "Content-Type": "application/json",
121
172
  "X-SaaSquatch-Referrer": window ? window.location.href : ""
122
173
  };
123
- var token = jwt || window.squatchToken;
174
+ var token = jwt || getToken();
124
175
  if (token) headers["X-SaaSquatch-User-Token"] = token;
125
176
 
126
177
  try {
@@ -138,48 +189,6 @@ async function doPut(url, data, jwt) {
138
189
  }
139
190
  }
140
191
 
141
- var DEFAULT_DOMAIN = "https://app.referralsaasquatch.com";
142
- var DEFAULT_NPM_CDN = "https://fast.ssqt.io/npm";
143
- function validateConfig(_raw) {
144
- var _window$squatchConfig, _window$squatchConfig2, _window$squatchConfig3;
145
-
146
- if (typeof _raw !== "object") throw new Error("config must be an object");
147
- var raw = {
148
- tenantAlias: (_raw == null ? void 0 : _raw["tenantAlias"]) || window.squatchTenant,
149
- domain: (_raw == null ? void 0 : _raw["domain"]) || ((_window$squatchConfig = window.squatchConfig) == null ? void 0 : _window$squatchConfig.domain),
150
- npmCdn: (_raw == null ? void 0 : _raw["npmCdn"]) || ((_window$squatchConfig2 = window.squatchConfig) == null ? void 0 : _window$squatchConfig2.npmCdn),
151
- debug: (_raw == null ? void 0 : _raw["debug"]) || ((_window$squatchConfig3 = window.squatchConfig) == null ? void 0 : _window$squatchConfig3.debug)
152
- };
153
- if (typeof raw.tenantAlias !== "string") throw new Error("tenantAlias not provided");
154
- var tenantAlias = raw.tenantAlias;
155
- var domain = typeof raw.domain === "string" && raw.domain || DEFAULT_DOMAIN;
156
- var debug = typeof raw.debug === "boolean" && raw.debug || false;
157
- var npmCdn = typeof raw.npmCdn === "string" && raw.npmCdn || DEFAULT_NPM_CDN;
158
- return {
159
- tenantAlias,
160
- domain,
161
- debug,
162
- npmCdn
163
- };
164
- }
165
- function isObject$1(obj) {
166
- return typeof obj === "object" && !Array.isArray(obj) && obj !== null;
167
- }
168
- function validateLocale(locale) {
169
- if (locale && /^[a-z]{2}_(?:[A-Z]{2}|[0-9]{3})$/.test(locale)) {
170
- return locale;
171
- }
172
- }
173
- function validateWidgetConfig(raw) {
174
- if (!isObject$1(raw)) throw new Error("Widget properties must be an object");
175
- if (!(raw != null && raw["user"])) throw new Error("Required properties missing.");
176
- return raw;
177
- }
178
- function validatePasswordlessConfig(raw) {
179
- if (!isObject$1(raw)) throw new Error("Widget properties must be an object");
180
- return raw;
181
- }
182
-
183
192
  var RENDER_WIDGET_QUERY = "\n query renderWidget ($user: UserIdInput, $engagementMedium: UserEngagementMedium, $widgetType: WidgetType, $locale: RSLocale) {\n renderWidget(user: $user, engagementMedium: $engagementMedium, widgetType: $widgetType, locale: $locale) {\n template\n user {\n id\n accountId\n }\n jsOptions\n widgetConfig {\n values\n }\n }\n }\n";
184
193
 
185
194
  /**
@@ -209,6 +218,7 @@ class WidgetApi {
209
218
  this.tenantAlias = void 0;
210
219
  this.domain = void 0;
211
220
  this.npmCdn = void 0;
221
+ this.referralCookie = this.squatchReferralCookie;
212
222
  var raw = config;
213
223
  var clean = validateConfig(raw);
214
224
  this.tenantAlias = clean.tenantAlias;
@@ -216,7 +226,7 @@ class WidgetApi {
216
226
  this.npmCdn = clean.npmCdn;
217
227
  }
218
228
  /**
219
- * Creates/upserts user.
229
+ * Creates/upserts user, requests widget template.
220
230
  *
221
231
  * @param {Object} params Parameters for request
222
232
  * @param {Object?} params.user The user details
@@ -238,6 +248,7 @@ class WidgetApi {
238
248
  widgetType,
239
249
  engagementMedium = "POPUP",
240
250
  jwt,
251
+ locale,
241
252
  user
242
253
  } = clean;
243
254
  var tenantAlias = encodeURIComponent(this.tenantAlias);
@@ -246,7 +257,8 @@ class WidgetApi {
246
257
 
247
258
  var optionalParams = _buildParams({
248
259
  widgetType,
249
- engagementMedium
260
+ engagementMedium,
261
+ locale
250
262
  });
251
263
 
252
264
  var path = "/api/v1/" + tenantAlias + "/widget/account/" + accountId + "/user/" + userId + "/upsert" + optionalParams;
@@ -256,7 +268,7 @@ class WidgetApi {
256
268
  return doPut(url, JSON.stringify(user), jwt);
257
269
  }
258
270
  /**
259
- * Description here.
271
+ * Requests widget template
260
272
  *
261
273
  * @param {Object} params Parameters for request
262
274
  * @param {Object} params.user The user details
@@ -331,12 +343,14 @@ class WidgetApi {
331
343
  function _buildParams(_ref) {
332
344
  var {
333
345
  widgetType,
334
- engagementMedium
346
+ engagementMedium,
347
+ locale
335
348
  } = _ref;
336
- var widgetTypeP = widgetType ? "?widgetType=" + encodeURIComponent(widgetType) : "";
337
- var engagementMediumP = (widgetType ? "&" : "?") + "engagementMedium=" + encodeURIComponent(engagementMedium);
338
- var optionalParams = widgetTypeP + engagementMediumP;
339
- return optionalParams;
349
+ var queryParams = new URLSearchParams();
350
+ queryParams.append("engagementMedium", engagementMedium);
351
+ if (widgetType) queryParams.append("widgetType", widgetType);
352
+ if (locale) queryParams.append("locale", locale);
353
+ return "?" + queryParams.toString();
340
354
  }
341
355
 
342
356
  // @ts-check
@@ -357,14 +371,14 @@ class AnalyticsApi {
357
371
  *
358
372
  */
359
373
  constructor(config) {
360
- var _window$squatchConfig;
374
+ var _getConfig;
361
375
 
362
376
  this.domain = void 0;
363
377
  var raw = config;
364
378
 
365
379
  var clean = _validateAnalyticsConfig(raw);
366
380
 
367
- this.domain = (clean == null ? void 0 : clean["domain"]) || ((_window$squatchConfig = window.squatchConfig) == null ? void 0 : _window$squatchConfig.domain) || DEFAULT_DOMAIN;
381
+ this.domain = (clean == null ? void 0 : clean["domain"]) || ((_getConfig = getConfig()) == null ? void 0 : _getConfig.domain) || DEFAULT_DOMAIN;
368
382
  }
369
383
 
370
384
  pushAnalyticsLoadEvent(params) {
@@ -400,7 +414,7 @@ function _validateAnalyticsConfig(raw) {
400
414
  // @ts-check
401
415
  /** @hidden */
402
416
 
403
- var _log$7 = debug.debug("squatch-js:widget");
417
+ var _log$8 = debug.debug("squatch-js:widget");
404
418
  /*
405
419
  * The Widget class is the base class for the different widget types available
406
420
  *
@@ -413,6 +427,8 @@ var _log$7 = debug.debug("squatch-js:widget");
413
427
 
414
428
  class Widget {
415
429
  constructor(params) {
430
+ var _params$context;
431
+
416
432
  this.type = void 0;
417
433
  this.content = void 0;
418
434
  this.analyticsApi = void 0;
@@ -421,7 +437,7 @@ class Widget {
421
437
  this.npmCdn = void 0;
422
438
  this.container = void 0;
423
439
 
424
- _log$7("widget initializing ...");
440
+ _log$8("widget initializing ...");
425
441
 
426
442
  this.content = params.content === "error" ? this._error(params.rsCode) : params.content;
427
443
  this.type = params.type;
@@ -431,7 +447,7 @@ class Widget {
431
447
  domain: params.domain
432
448
  });
433
449
  this.context = params.context;
434
- this.container = params.container;
450
+ this.container = ((_params$context = params.context) == null ? void 0 : _params$context.container) || params.container;
435
451
  }
436
452
 
437
453
  _findElement() {
@@ -441,25 +457,25 @@ class Widget {
441
457
  // selector is a string
442
458
  element = document.querySelector(this.container);
443
459
 
444
- _log$7("loading widget with selector", element); // selector is an HTML element
460
+ _log$8("loading widget with selector", element); // selector is an HTML element
445
461
 
446
462
  } else if (this.container instanceof HTMLElement) {
447
463
  element = this.container;
448
464
 
449
- _log$7("loading widget with container", element); // garbage container found
465
+ _log$8("loading widget with container", element); // garbage container found
450
466
 
451
467
  } else if (this.container) {
452
468
  element = null;
453
469
 
454
- _log$7("container must be an HTMLElement or string", this.container); // find element on page
470
+ _log$8("container must be an HTMLElement or string", this.container); // find element on page
455
471
 
456
472
  } else {
457
- element = document.querySelector("#squatchembed") || document.querySelector(".squatchembed");
473
+ element = document.querySelector("#squatchembed") || document.querySelector(".squatchembed") || document.querySelector("#impactembed") || document.querySelector(".impactembed");
458
474
 
459
- _log$7("loading widget with default selector", element);
475
+ _log$8("loading widget with default selector", element);
460
476
  }
461
477
 
462
- if (!(element instanceof HTMLElement)) throw new Error("element with selector '" + (this.container || "#squatchembed or .squatchembed") + "' not found.'");
478
+ if (!(element instanceof HTMLElement)) throw new Error("element with selector '" + (this.container || "#squatchembed, .squatchembed, #impactembed, or .impactembed") + "' not found.'");
463
479
  return element;
464
480
  }
465
481
 
@@ -475,8 +491,7 @@ class Widget {
475
491
  }
476
492
 
477
493
  _findFrame() {
478
- var element = this._findElement();
479
-
494
+ var element = this.container ? this._findElement() : document.body;
480
495
  var parent = element.shadowRoot || element;
481
496
  return parent.querySelector("iframe#squatchFrame");
482
497
  }
@@ -515,9 +530,9 @@ class Widget {
515
530
  }
516
531
 
517
532
  (_this$analyticsApi$pu = this.analyticsApi.pushAnalyticsLoadEvent(params)) == null ? void 0 : _this$analyticsApi$pu.then(response => {
518
- _log$7(params.engagementMedium + " loaded event recorded.");
533
+ _log$8(params.engagementMedium + " loaded event recorded.");
519
534
  }).catch(ex => {
520
- _log$7("ERROR: pushAnalyticsLoadEvent() " + ex);
535
+ _log$8("ERROR: pushAnalyticsLoadEvent() " + ex);
521
536
  });
522
537
  }
523
538
 
@@ -530,13 +545,12 @@ class Widget {
530
545
  engagementMedium: sqh.mode.widgetMode,
531
546
  shareMedium: medium
532
547
  }).then(response => {
533
- _log$7(sqh.mode.widgetMode + " share " + medium + " event recorded. " + response);
548
+ _log$8(sqh.mode.widgetMode + " share " + medium + " event recorded. " + response);
534
549
  }).catch(ex => {
535
- _log$7("ERROR: pushAnalyticsShareClickedEvent() " + ex);
550
+ _log$8("ERROR: pushAnalyticsShareClickedEvent() " + ex);
536
551
  });
537
552
  }
538
- } // TODO: CA: Refactor how error templates are shown
539
-
553
+ }
540
554
 
541
555
  _error(rs, mode, style) {
542
556
  if (mode === void 0) {
@@ -654,7 +668,7 @@ class Widget {
654
668
  message
655
669
  } = _ref3;
656
670
 
657
- _log$7("" + message);
671
+ _log$8("" + message);
658
672
  });
659
673
  }
660
674
 
@@ -681,10 +695,8 @@ class Widget {
681
695
  }
682
696
 
683
697
  function delay(duration) {
684
- return new Promise(function (resolve, reject) {
685
- setTimeout(function () {
686
- resolve(() => {});
687
- }, duration);
698
+ return new Promise(resolve => {
699
+ setTimeout(resolve, duration);
688
700
  });
689
701
  }
690
702
 
@@ -713,12 +725,17 @@ function domready(targetDoc, fn) {
713
725
 
714
726
  // @ts-check
715
727
 
716
- var _log$6 = debug.debug("squatch-js:EMBEDwidget");
728
+ var _log$7 = debug.debug("squatch-js:EMBEDwidget");
717
729
  /**
718
730
  * An EmbedWidget is displayed inline in part of your page.
719
731
  *
720
732
  * To create an EmbedWidget use {@link Widgets}
721
733
  *
734
+ * @example
735
+ * const widget = new EmbedWidget({ ... })
736
+ * widget.load() // Loads widget into the DOM
737
+ * widget.open() // Makes the iframe container visible
738
+ * widget.close() // Hides the iframe container
722
739
  */
723
740
 
724
741
 
@@ -727,18 +744,30 @@ class EmbedWidget extends Widget {
727
744
  super(params);
728
745
  this.show = this.open;
729
746
  this.hide = this.close;
747
+ if (container) this.container = container;
730
748
  }
731
749
 
732
750
  async load() {
751
+ var _this$context;
752
+
733
753
  var frame = this._createFrame();
734
754
 
735
755
  var element = this._findElement();
736
756
 
757
+ if ((_this$context = this.context) != null && _this$context.container) {
758
+ // Custom container is used
759
+ element.style.visibility = "hidden";
760
+ element.style.height = "0";
761
+ element.style["overflow-y"] = "hidden";
762
+ }
763
+
737
764
  if (this.container) {
738
765
  if (element.shadowRoot) {
739
766
  var _element$shadowRoot$l;
740
767
 
741
- if (((_element$shadowRoot$l = element.shadowRoot.lastChild) == null ? void 0 : _element$shadowRoot$l.nodeName) === "IFRAME") element.shadowRoot.replaceChild(frame, element.shadowRoot.lastChild);else {
768
+ if (((_element$shadowRoot$l = element.shadowRoot.lastChild) == null ? void 0 : _element$shadowRoot$l.nodeName) === "IFRAME") {
769
+ element.shadowRoot.replaceChild(frame, element.shadowRoot.lastChild);
770
+ } else {
742
771
  element.shadowRoot.appendChild(frame);
743
772
  }
744
773
  } // Widget reloaded - replace existing element
@@ -770,6 +799,8 @@ class EmbedWidget extends Widget {
770
799
 
771
800
  frame.height = frameDoc.body.scrollHeight; // Adjust frame height when size of body changes
772
801
 
802
+ /* istanbul ignore next: hard to test */
803
+
773
804
  var ro = new contentWindow["ResizeObserver"](entries => {
774
805
  for (var entry of entries) {
775
806
  var {
@@ -777,44 +808,50 @@ class EmbedWidget extends Widget {
777
808
  } = entry.contentRect; // @ts-ignore -- number will be cast to string by browsers
778
809
 
779
810
  frame.height = height;
811
+ console.log("RESIZE");
780
812
  }
781
813
  });
782
- ro.observe(await this._findInnerContainer(frame)); // Regular load - trigger event
814
+ var container = await this._findInnerContainer(frame);
815
+ ro.observe(container);
783
816
 
784
- if (!this.container) {
817
+ if (this._shouldFireLoadEvent()) {
785
818
  this._loadEvent(_sqh);
786
819
 
787
- _log$6("loaded");
820
+ _log$7("loaded");
788
821
  }
789
822
  });
790
- } // Un-hide if element is available and refresh data
823
+ }
824
+ /**
825
+ * Un-hide if element is available and refresh data
826
+ */
791
827
 
792
828
 
793
829
  open() {
794
- var _frame$contentDocumen, _frame$contentWindow, _frame$contentWindow2;
795
-
796
830
  var frame = this._findFrame();
797
831
 
798
- if (!frame) return _log$6("no target element to open");
832
+ if (!frame) return _log$7("no target element to open");
833
+ if (!frame.contentWindow) return _log$7("Frame needs a content window");
799
834
 
800
835
  var element = this._findElement();
801
836
 
802
837
  element.style.visibility = "unset";
803
838
  element.style.height = "auto";
804
839
  element.style["overflow-y"] = "auto";
805
- frame == null ? void 0 : (_frame$contentDocumen = frame.contentDocument) == null ? void 0 : _frame$contentDocumen.dispatchEvent(new CustomEvent("sq:refresh"));
840
+ frame.contentWindow.document.dispatchEvent(new CustomEvent("sq:refresh"));
806
841
 
807
- var _sqh = (frame == null ? void 0 : (_frame$contentWindow = frame.contentWindow) == null ? void 0 : _frame$contentWindow.squatch) || (frame == null ? void 0 : (_frame$contentWindow2 = frame.contentWindow) == null ? void 0 : _frame$contentWindow2.widgetIdent);
842
+ var _sqh = frame.contentWindow.squatch || frame.contentWindow.widgetIdent;
808
843
 
809
- this._loadEvent(_sqh);
844
+ if (this.context.user) {
845
+ this._loadEvent(_sqh);
810
846
 
811
- _log$6("loaded");
847
+ _log$7("loaded");
848
+ }
812
849
  }
813
850
 
814
851
  close() {
815
852
  var frame = this._findFrame();
816
853
 
817
- if (!frame) return _log$6("no target element to close");
854
+ if (!frame) return _log$7("no target element to close");
818
855
 
819
856
  var element = this._findElement();
820
857
 
@@ -822,7 +859,7 @@ class EmbedWidget extends Widget {
822
859
  element.style.height = "0";
823
860
  element.style["overflow-y"] = "hidden";
824
861
 
825
- _log$6("Embed widget closed");
862
+ _log$7("Embed widget closed");
826
863
  }
827
864
 
828
865
  _error(rs, mode, style) {
@@ -837,11 +874,18 @@ class EmbedWidget extends Widget {
837
874
  return super._error(rs, mode, style);
838
875
  }
839
876
 
877
+ _shouldFireLoadEvent() {
878
+ var noContainer = !this.container;
879
+ var isComponent = this.container instanceof HTMLElement && (this.container.tagName.startsWith("SQUATCH-") || this.container.tagName.startsWith("IMPACT-"));
880
+ var isVerified = !!this.context.user;
881
+ return isVerified && (noContainer || isComponent);
882
+ }
883
+
840
884
  }
841
885
 
842
886
  // @ts-check
843
887
 
844
- var _log$5 = debug.debug("squatch-js:POPUPwidget");
888
+ var _log$6 = debug.debug("squatch-js:POPUPwidget");
845
889
 
846
890
  var popupId = 0;
847
891
  /**
@@ -850,6 +894,11 @@ var popupId = 0;
850
894
  *
851
895
  * To create a PopupWidget use {@link Widgets}
852
896
  *
897
+ * @example
898
+ * const widget = new PopupWidget({ ... })
899
+ * widget.load() // Loads the widget into a dialog element
900
+ * widget.open() // Opens the dialog element
901
+ * widget.close() // Hides the dialog element
853
902
  */
854
903
 
855
904
  class PopupWidget extends Widget {
@@ -875,17 +924,17 @@ class PopupWidget extends Widget {
875
924
  document.head.insertAdjacentHTML("beforeend", "<style>#" + this.id + "::-webkit-scrollbar { display: none; }</style>");
876
925
  }
877
926
 
878
- _initialiseCTA(frame) {
927
+ _initialiseCTA() {
879
928
  if (!this.trigger) return;
880
929
  var triggerElement;
881
930
 
882
931
  try {
883
932
  triggerElement
884
933
  /* HTMLButton */
885
- = document.querySelector(this.trigger);
886
- if (this.trigger && !triggerElement) _log$5("No element found with trigger selector", this.trigger);
934
+ = document.querySelector(this.trigger) || document.querySelector(".impactpop");
935
+ if (this.trigger && !triggerElement) _log$6("No element found with trigger selector", this.trigger);
887
936
  } catch (_unused) {
888
- _log$5("Not a valid selector", this.trigger);
937
+ _log$6("Not a valid selector", this.trigger);
889
938
  } // Trigger is optional
890
939
 
891
940
 
@@ -893,16 +942,7 @@ class PopupWidget extends Widget {
893
942
  triggerElement.onclick = () => {
894
943
  this.open();
895
944
  };
896
- } // const element = this._findElement();
897
- // If widget is loaded with CTA, look for a 'squatchpop' element to use
898
- // that element as a trigger as well.
899
- // const triggerWhenCTA = element.querySelector(".squatchpop") as HTMLElement;
900
- // if (this.trigger === "#cta" && triggerWhenCTA) {
901
- // triggerWhenCTA.onclick = () => {
902
- // this.open(frame);
903
- // };
904
- // }
905
-
945
+ }
906
946
  }
907
947
 
908
948
  _createPopupDialog() {
@@ -911,6 +951,7 @@ class PopupWidget extends Widget {
911
951
  dialog.setAttribute("style", "width: 100%; max-width: 500px; border: none; padding: 0;");
912
952
 
913
953
  var onClick = e => {
954
+ e.stopPropagation();
914
955
  if (e.target === dialog) dialog.close();
915
956
  };
916
957
 
@@ -918,15 +959,14 @@ class PopupWidget extends Widget {
918
959
  return dialog;
919
960
  }
920
961
 
921
- load() {
962
+ async load() {
922
963
  var _dialogParent$lastChi;
923
964
 
924
965
  var frame = this._createFrame();
925
966
 
926
- this._initialiseCTA(frame);
927
-
928
- var element = this._findElement();
967
+ this._initialiseCTA();
929
968
 
969
+ var element = this.container ? this._findElement() : document.body;
930
970
  var dialogParent = element.shadowRoot || element;
931
971
 
932
972
  var dialog = this._createPopupDialog();
@@ -955,12 +995,12 @@ class PopupWidget extends Widget {
955
995
  frameDoc.write("<script src=\"" + this.npmCdn + "/resize-observer-polyfill@1.5.x\"></script>");
956
996
  frameDoc.close();
957
997
 
958
- _log$5("Popup template loaded into iframe");
998
+ _log$6("Popup template loaded into iframe");
959
999
 
960
- this._setupResizeHandler(frame);
1000
+ await this._setupResizeHandler(frame);
961
1001
  }
962
1002
 
963
- _setupResizeHandler(frame) {
1003
+ async _setupResizeHandler(frame) {
964
1004
  var {
965
1005
  contentWindow
966
1006
  } = frame;
@@ -992,8 +1032,7 @@ class PopupWidget extends Widget {
992
1032
  }
993
1033
 
994
1034
  open() {
995
- var element = this._findElement();
996
-
1035
+ var element = this.container ? this._findElement() : document.body;
997
1036
  var parent = element.shadowRoot || element;
998
1037
  var dialog = parent.querySelector("#" + this.id);
999
1038
  if (!dialog) throw new Error("Could not determine container div");
@@ -1015,21 +1054,22 @@ class PopupWidget extends Widget {
1015
1054
 
1016
1055
  (_frame$contentDocumen = frame.contentDocument) == null ? void 0 : _frame$contentDocumen.dispatchEvent(new CustomEvent("sq:refresh"));
1017
1056
 
1018
- this._loadEvent(_sqh);
1057
+ if (this.context.user) {
1058
+ this._loadEvent(_sqh);
1019
1059
 
1020
- _log$5("Popup opened");
1060
+ _log$6("Popup opened");
1061
+ }
1021
1062
  });
1022
1063
  }
1023
1064
 
1024
1065
  close() {
1025
- var element = this._findElement();
1026
-
1066
+ var element = this.container ? this._findElement() : document.body;
1027
1067
  var parent = element.shadowRoot || element;
1028
1068
  var dialog = parent.querySelector("#" + this.id);
1029
1069
  if (!dialog) throw new Error("Could not determine container div");
1030
1070
  dialog.close();
1031
1071
 
1032
- _log$5("Popup closed");
1072
+ _log$6("Popup closed");
1033
1073
  }
1034
1074
 
1035
1075
  _clickedOutside(_ref) {
@@ -1050,16 +1090,33 @@ class PopupWidget extends Widget {
1050
1090
 
1051
1091
  }
1052
1092
 
1053
- var _log$4 = debug.debug("squatch-js:widgets");
1093
+ var _log$5 = debug.debug("squatch-js:widgets");
1054
1094
  /**
1055
- *
1056
1095
  * `Widgets` is a factory for creating widgets. It's possible to build your own widgets using the
1057
1096
  * {@link WidgetApi} but most people will prefer to use these easy methods.
1058
- *
1097
+ * @class
1059
1098
  */
1060
1099
 
1061
1100
 
1062
1101
  class Widgets {
1102
+ /**
1103
+ * Instance of {@link WidgetApi}
1104
+ */
1105
+
1106
+ /**
1107
+ * Tenant alias of SaaSquatch tenant
1108
+ */
1109
+
1110
+ /**
1111
+ * SaaSquatch domain for API requests
1112
+ * @default "https://app.referralsaasquatch.com"
1113
+ */
1114
+
1115
+ /**
1116
+ * Hosted CDN for npm packages
1117
+ * @default "https://fast.ssqt.io/npm"
1118
+ */
1119
+
1063
1120
  /**
1064
1121
  * Initialize a new {@link Widgets} instance.
1065
1122
  *
@@ -1085,7 +1142,7 @@ class Widgets {
1085
1142
  this.tenantAlias = config.tenantAlias;
1086
1143
  this.domain = config.domain;
1087
1144
  this.npmCdn = config.npmCdn;
1088
- this.api = new WidgetApi(config); // listens to a 'submit_email' event in the theme.
1145
+ this.api = new WidgetApi(config);
1089
1146
  }
1090
1147
  /**
1091
1148
  * This function calls the {@link WidgetApi.upsertUser} method, and it renders
@@ -1095,13 +1152,13 @@ class Widgets {
1095
1152
  * @param {Object} config.user The user details
1096
1153
  * @param {string} config.user.id The user id
1097
1154
  * @param {string} config.user.accountId The user account id
1098
- * @param {WidgetType} config.widgetType The content of the widget.
1099
- * @param {EngagementMedium} config.engagementMedium How to display the widget.
1155
+ * @param {WidgetType} config.widgetType The content of the widget
1156
+ * @param {EngagementMedium} config.engagementMedium How to display the widget
1100
1157
  * @param {string} config.jwt the JSON Web Token (JWT) that is used to validate the data (can be disabled)
1101
1158
  * @param {HTMLElement | string | undefined} config.container Element to load the widget into
1102
1159
  * @param {string | undefined} config.trigger Trigger element for opening the popup widget
1103
1160
  *
1104
- * @return {Promise<WidgetResult>} json object if true, with a Widget and user details.
1161
+ * @return {Promise<WidgetResult>} json object if true, with a Widget and user details
1105
1162
  */
1106
1163
 
1107
1164
 
@@ -1114,7 +1171,7 @@ class Widgets {
1114
1171
  return {
1115
1172
  widget: this._renderWidget(response, clean, {
1116
1173
  type: "upsert",
1117
- user: clean.user || null,
1174
+ user: clean.user,
1118
1175
  engagementMedium: config.engagementMedium,
1119
1176
  container: config.container,
1120
1177
  trigger: config.trigger
@@ -1122,7 +1179,7 @@ class Widgets {
1122
1179
  user: response.user
1123
1180
  };
1124
1181
  } catch (err) {
1125
- _log$4(err);
1182
+ _log$5(err);
1126
1183
 
1127
1184
  if (err.apiErrorCode) {
1128
1185
  this._renderErrorWidget(err, config.engagementMedium);
@@ -1139,12 +1196,12 @@ class Widgets {
1139
1196
  * @param {Object} config.user The user details
1140
1197
  * @param {string} config.user.id The user id
1141
1198
  * @param {string} config.user.accountId The user account id
1142
- * @param {WidgetType} config.widgetType The content of the widget.
1143
- * @param {EngagementMedium} config.engagementMedium How to display the widget.
1199
+ * @param {WidgetType} config.widgetType The content of the widget
1200
+ * @param {EngagementMedium} config.engagementMedium How to display the widget
1144
1201
  * @param {string} config.jwt the JSON Web Token (JWT) that is used
1145
1202
  * to validate the data (can be disabled)
1146
1203
  *
1147
- * @return {Promise<WidgetResult>} json object if true, with a Widget and user details.
1204
+ * @return {Promise<WidgetResult>} json object if true, with a Widget and user details
1148
1205
  */
1149
1206
 
1150
1207
 
@@ -1157,7 +1214,9 @@ class Widgets {
1157
1214
  return {
1158
1215
  widget: this._renderWidget(response, clean, {
1159
1216
  type: "passwordless",
1160
- engagementMedium: clean.engagementMedium
1217
+ engagementMedium: clean.engagementMedium,
1218
+ container: clean.container,
1219
+ trigger: clean.trigger
1161
1220
  }),
1162
1221
  user: response.user
1163
1222
  };
@@ -1186,7 +1245,7 @@ class Widgets {
1186
1245
  var response = await this.api.squatchReferralCookie();
1187
1246
  input(response);
1188
1247
  } catch (e) {
1189
- _log$4("Autofill error", e);
1248
+ _log$5("Autofill error", e);
1190
1249
 
1191
1250
  throw new Error(e);
1192
1251
  }
@@ -1202,7 +1261,7 @@ class Widgets {
1202
1261
  // Only use the first element found
1203
1262
  elem = elems[0];
1204
1263
  } else {
1205
- _log$4("Element id/class or function missing");
1264
+ _log$5("Element id/class or function missing");
1206
1265
 
1207
1266
  throw new Error("Element id/class or function missing");
1208
1267
  }
@@ -1226,15 +1285,17 @@ class Widgets {
1226
1285
 
1227
1286
 
1228
1287
  _renderWidget(response, config, context) {
1229
- _log$4("Rendering Widget...");
1288
+ var _opts$widget;
1289
+
1290
+ _log$5("Rendering Widget...");
1230
1291
 
1231
1292
  if (!response) throw new Error("Unable to get a response");
1232
1293
  var widget;
1233
1294
  var displayOnLoad = !!config.displayOnLoad;
1234
- var opts = response.jsOptions || "";
1295
+ var opts = response.jsOptions || {};
1235
1296
  var params = {
1236
1297
  content: response.template,
1237
- type: config.widgetType || opts.widget.defaultWidgetType,
1298
+ type: config.widgetType || ((_opts$widget = opts.widget) == null ? void 0 : _opts$widget.defaultWidgetType),
1238
1299
  api: this.api,
1239
1300
  domain: this.domain,
1240
1301
  npmCdn: this.npmCdn,
@@ -1244,19 +1305,21 @@ class Widgets {
1244
1305
  if (opts.widgetUrlMappings) {
1245
1306
  opts.widgetUrlMappings.forEach(rule => {
1246
1307
  if (Widgets._matchesUrl(rule.url)) {
1247
- if (rule.widgetType !== "CONVERSION_WIDGET" || response.user.referredBy && response.user.referredBy.code) {
1308
+ var _response$user, _response$user$referr;
1309
+
1310
+ if (rule.widgetType !== "CONVERSION_WIDGET" || (_response$user = response.user) != null && (_response$user$referr = _response$user.referredBy) != null && _response$user$referr.code) {
1248
1311
  displayOnLoad = rule.displayOnLoad;
1249
1312
 
1250
- _log$4("Display " + rule.widgetType + " on " + rule.url);
1313
+ _log$5("Display " + rule.widgetType + " on " + rule.url);
1251
1314
  } else {
1252
- _log$4("Don't display " + rule.widgetType + " when no referral on widget rule match " + rule.url);
1315
+ _log$5("Don't display " + rule.widgetType + " when no referral on widget rule match " + rule.url);
1253
1316
  }
1254
1317
  }
1255
1318
  });
1256
1319
  }
1257
1320
 
1258
1321
  if (opts.fuelTankAutofillUrls) {
1259
- _log$4("We found a fuel tank autofill!");
1322
+ _log$5("We found a fuel tank autofill!");
1260
1323
 
1261
1324
  opts.fuelTankAutofillUrls.forEach(_ref => {
1262
1325
  var {
@@ -1265,15 +1328,19 @@ class Widgets {
1265
1328
  } = _ref;
1266
1329
 
1267
1330
  if (Widgets._matchesUrl(url)) {
1268
- _log$4("Fuel Tank URL matches");
1331
+ var _response$user2, _response$user2$refer;
1269
1332
 
1270
- if (response.user.referredBy && response.user.referredBy.code) {
1333
+ _log$5("Fuel Tank URL matches");
1334
+
1335
+ if ((_response$user2 = response.user) != null && (_response$user2$refer = _response$user2.referredBy) != null && _response$user2$refer.code) {
1271
1336
  var formAutofill = document.querySelector(formSelector);
1272
1337
 
1273
1338
  if (formAutofill) {
1274
- formAutofill.value = response.user.referredBy.referredReward.fuelTankCode || "";
1339
+ var _response$user$referr2;
1340
+
1341
+ formAutofill.value = ((_response$user$referr2 = response.user.referredBy.referredReward) == null ? void 0 : _response$user$referr2.fuelTankCode) || "";
1275
1342
  } else {
1276
- _log$4(new Error("Element with id/class " + formSelector + " was not found."));
1343
+ _log$5(new Error("Element with id/class " + formSelector + " was not found."));
1277
1344
  }
1278
1345
  }
1279
1346
  }
@@ -1281,15 +1348,9 @@ class Widgets {
1281
1348
  }
1282
1349
 
1283
1350
  if (config.engagementMedium === "EMBED") {
1284
- this._renderEmbedWidget(params, params.context.container);
1285
- } else if (config.engagementMedium === "POPUP") {
1286
- widget = this._renderPopupWidget(params);
1287
- if (displayOnLoad) widget.open();
1351
+ widget = this._renderEmbedWidget(params);
1288
1352
  } else {
1289
- _log$4("display popup on load");
1290
-
1291
- widget = new PopupWidget(params);
1292
- widget.load();
1353
+ widget = this._renderPopupWidget(params);
1293
1354
  if (displayOnLoad) widget.open();
1294
1355
  }
1295
1356
 
@@ -1302,8 +1363,8 @@ class Widgets {
1302
1363
  return widget;
1303
1364
  }
1304
1365
 
1305
- _renderEmbedWidget(params, container) {
1306
- var widget = new EmbedWidget(params);
1366
+ _renderEmbedWidget(params) {
1367
+ var widget = new EmbedWidget(params, params.context.container);
1307
1368
  widget.load();
1308
1369
  return widget;
1309
1370
  }
@@ -1326,7 +1387,7 @@ class Widgets {
1326
1387
  message
1327
1388
  } = props;
1328
1389
 
1329
- _log$4(new Error(apiErrorCode + " (" + rsCode + ") " + message));
1390
+ _log$5(new Error(apiErrorCode + " (" + rsCode + ") " + message));
1330
1391
 
1331
1392
  var params = {
1332
1393
  content: "error",
@@ -1441,28 +1502,32 @@ function _validateTrackOptions(raw) {
1441
1502
  }
1442
1503
 
1443
1504
  /** @hidden */
1505
+
1444
1506
  function asyncLoad() {
1445
- var loaded = window.squatch || null;
1446
- var cached = window._squatch || null;
1507
+ var _window;
1447
1508
 
1448
- if (loaded && cached) {
1449
- var ready = cached.ready || [];
1450
- ready.forEach(cb => setTimeout(() => cb(), 0));
1451
- setTimeout(() => window.squatch._auto(), 0); // @ts-ignore -- intetionally deletes `_squatch` to cleanup initialization
1509
+ var namespace = window[IMPACT_NAMESPACE] ? IMPACT_NAMESPACE : DEFAULT_NAMESPACE;
1510
+ var cached = ((_window = window["_" + namespace]) == null ? void 0 : _window.ready) || [];
1511
+ var declarativeCache = window.impactOnReady || window.squatchOnReady;
1512
+ var readyFns = [...cached, declarativeCache].filter(a => !!a); // Run all of this in a setTimeout because we need to wait for the squatch module to finish loading
1452
1513
 
1453
- window._squatch = undefined;
1514
+ setTimeout(() => {
1515
+ // Set window.impact as an alias for window.squatch.
1516
+ window[IMPACT_NAMESPACE] = window[DEFAULT_NAMESPACE]; // Run all the ready functions in a set timeout to they happen after namespace aliasing.
1454
1517
 
1455
- try {
1456
- delete window._squatch;
1457
- } catch (e) {
1458
- throw e;
1459
- }
1460
- }
1518
+ readyFns.forEach(cb => cb()); // Perform auto popup
1519
+
1520
+ window[DEFAULT_NAMESPACE]._auto(); // @ts-ignore -- intentionally deletes `_squatch` to cleanup initialization
1521
+
1522
+
1523
+ window["_" + namespace] = undefined;
1524
+ delete window["_" + namespace];
1525
+ }, 0);
1461
1526
  }
1462
1527
 
1463
1528
  /** @hidden */
1464
1529
 
1465
- var _log$3 = debug.debug("squatch-js");
1530
+ var _log$4 = debug.debug("squatch-js");
1466
1531
 
1467
1532
  var isObject = item => typeof item === "object" && !Array.isArray(item);
1468
1533
 
@@ -1515,7 +1580,7 @@ function _pushCookie() {
1515
1580
  try {
1516
1581
  paramsJSON = JSON.parse(b64decode(refParam));
1517
1582
  } catch (error) {
1518
- _log$3("Unable to decode params", error); // don't merge invalid params
1583
+ _log$4("Unable to decode params", error); // don't merge invalid params
1519
1584
 
1520
1585
 
1521
1586
  return;
@@ -1524,26 +1589,26 @@ function _pushCookie() {
1524
1589
  try {
1525
1590
  existingCookie = JSON.parse(b64decode(Cookies__default['default'].get("_saasquatch")));
1526
1591
 
1527
- _log$3("existing cookie", existingCookie);
1592
+ _log$4("existing cookie", existingCookie);
1528
1593
  } catch (error) {
1529
- _log$3("Unable to retrieve cookie", error);
1594
+ _log$4("Unable to retrieve cookie", error);
1530
1595
  } // don't merge if there's no existing object
1531
1596
 
1532
1597
 
1533
1598
  try {
1534
1599
  var domain = getTopDomain();
1535
1600
 
1536
- _log$3("domain retrieved:", domain);
1601
+ _log$4("domain retrieved:", domain);
1537
1602
 
1538
1603
  if (existingCookie) {
1539
1604
  var newCookie = deepMerge(existingCookie, paramsJSON);
1540
1605
  reEncodedCookie = b64encode(JSON.stringify(newCookie));
1541
1606
 
1542
- _log$3("cookie to store:", newCookie);
1607
+ _log$4("cookie to store:", newCookie);
1543
1608
  } else {
1544
1609
  reEncodedCookie = b64encode(JSON.stringify(paramsJSON));
1545
1610
 
1546
- _log$3("cookie to store:", paramsJSON);
1611
+ _log$4("cookie to store:", paramsJSON);
1547
1612
  }
1548
1613
 
1549
1614
  Cookies__default['default'].set("_saasquatch", reEncodedCookie, {
@@ -1554,14 +1619,14 @@ function _pushCookie() {
1554
1619
  path: "/"
1555
1620
  });
1556
1621
  } catch (error) {
1557
- _log$3("Unable to set cookie", error);
1622
+ _log$4("Unable to set cookie", error);
1558
1623
  }
1559
1624
  }
1560
1625
  }
1561
1626
 
1562
1627
  /** @hidden */
1563
1628
 
1564
- var _log$2 = debug.debug("squatch-js");
1629
+ var _log$3 = debug.debug("squatch-js");
1565
1630
 
1566
1631
  function _getAutoConfig(configIn) {
1567
1632
  var queryString = window.location.search;
@@ -1569,7 +1634,7 @@ function _getAutoConfig(configIn) {
1569
1634
  var refParam = urlParams.get("_saasquatchExtra") || "";
1570
1635
 
1571
1636
  if (!refParam) {
1572
- _log$2("No _saasquatchExtra param");
1637
+ _log$3("No _saasquatchExtra param");
1573
1638
 
1574
1639
  return;
1575
1640
  }
@@ -1579,7 +1644,7 @@ function _getAutoConfig(configIn) {
1579
1644
  try {
1580
1645
  raw = JSON.parse(b64decode(refParam));
1581
1646
  } catch (e) {
1582
- _log$2("Unable to decode _saasquatchExtra config");
1647
+ _log$3("Unable to decode _saasquatchExtra config");
1583
1648
 
1584
1649
  return;
1585
1650
  }
@@ -1591,7 +1656,7 @@ function _getAutoConfig(configIn) {
1591
1656
  } = convertExtraToConfig(raw);
1592
1657
 
1593
1658
  if (!domain || !tenantAlias || !widgetConfig) {
1594
- _log$2("_saasquatchExtra did not have an expected structure");
1659
+ _log$3("_saasquatchExtra did not have an expected structure");
1595
1660
 
1596
1661
  return undefined;
1597
1662
  }
@@ -1634,7 +1699,7 @@ function convertExtraToConfig(obj) {
1634
1699
  };
1635
1700
  }
1636
1701
 
1637
- var _log$1 = debug.debug("squatch-js:decodeJwt");
1702
+ var _log$2 = debug.debug("squatch-js:decodeUserJwt");
1638
1703
 
1639
1704
  function decodeUserJwt(tokenStr) {
1640
1705
  try {
@@ -1645,28 +1710,88 @@ function decodeUserJwt(tokenStr) {
1645
1710
  var jsonStr = b64decode(base64Url);
1646
1711
  return (_JSON$parse = JSON.parse(jsonStr)) == null ? void 0 : _JSON$parse.user;
1647
1712
  } catch (e) {
1648
- _log$1(e);
1713
+ _log$2(e);
1649
1714
 
1650
1715
  return null;
1651
1716
  }
1652
1717
  }
1653
1718
 
1654
- debug__default['default']("sqh:DeclarativeWidget");
1719
+ var _log$1 = debug__default['default']("squatch-js:DeclarativeWidget");
1720
+ /**
1721
+ * Abstract class for building web-components that render SaaSquatch widgets to the DOM
1722
+ * @abstract
1723
+ * @example
1724
+ * class TestWidgetElement extends DeclarativeWidget {}
1725
+ * const testWidget = new TestWidgetElement()
1726
+ * testWidget.widgetType = 'w/widget-type'
1727
+ * testWidget.type = 'EMBED'
1728
+ * testWidget.renderWidget()
1729
+ */
1730
+
1655
1731
 
1656
1732
  class DeclarativeWidget extends HTMLElement {
1733
+ /**
1734
+ * Configuration overrides
1735
+ * @default window.squatchConfig
1736
+ */
1737
+
1738
+ /**
1739
+ * Signed JWT containing user information
1740
+ * @default window.squatchToken
1741
+ */
1742
+
1743
+ /**
1744
+ * Tenant alias of SaaSquatch tenant
1745
+ * @default window.squatchTenant
1746
+ */
1747
+
1748
+ /**
1749
+ * widgetType of widget to load
1750
+ */
1751
+
1752
+ /**
1753
+ * Locale to render the widget in
1754
+ */
1755
+
1756
+ /**
1757
+ * Instance of {@link WidgetApi}
1758
+ */
1759
+
1760
+ /**
1761
+ * Instance of {@link AnalyticsApi}
1762
+ */
1763
+
1764
+ /**
1765
+ * Instance of {@link EmbedWidget} or {@link PopupWidget}
1766
+ */
1767
+
1768
+ /**
1769
+ * Determines whether to render the widget as an embedding widget or popup widget
1770
+ */
1771
+
1772
+ /**
1773
+ * Container element to contain the widget iframe
1774
+ * @default this
1775
+ */
1776
+
1777
+ /**
1778
+ * Flag for if the component has been loaded or not
1779
+ * @hidden
1780
+ */
1657
1781
  constructor() {
1658
1782
  super();
1659
1783
  this.config = void 0;
1660
1784
  this.token = void 0;
1661
1785
  this.tenant = void 0;
1662
1786
  this.widgetType = void 0;
1787
+ this.locale = void 0;
1663
1788
  this.widgetApi = void 0;
1664
1789
  this.analyticsApi = void 0;
1665
- this.type = void 0;
1666
1790
  this.widgetInstance = void 0;
1791
+ this.type = void 0;
1667
1792
  this.container = void 0;
1668
1793
  this.element = void 0;
1669
- this._hasChildren = void 0;
1794
+ this.loaded = void 0;
1670
1795
 
1671
1796
  this._setWidget = (template, config) => {
1672
1797
  var _this$config;
@@ -1676,18 +1801,21 @@ class DeclarativeWidget extends HTMLElement {
1676
1801
  content: template,
1677
1802
  context: {
1678
1803
  type: config.type,
1804
+ user: config.user,
1805
+ container: this.container || undefined,
1679
1806
  engagementMedium: this.type
1680
1807
  },
1681
1808
  type: this.widgetType,
1682
1809
  domain: ((_this$config = this.config) == null ? void 0 : _this$config.domain) || DEFAULT_DOMAIN,
1683
1810
  npmCdn: DEFAULT_NPM_CDN,
1684
- container: this.container || this
1811
+ container: this
1685
1812
  };
1686
1813
 
1687
1814
  if (this.type === "EMBED") {
1688
1815
  return new EmbedWidget(params);
1689
1816
  } else {
1690
- return new PopupWidget(params, this.firstChild ? null : undefined);
1817
+ var useFirstChildTrigger = this.firstChild ? null : undefined;
1818
+ return new PopupWidget(params, useFirstChildTrigger);
1691
1819
  }
1692
1820
  };
1693
1821
 
@@ -1698,28 +1826,31 @@ class DeclarativeWidget extends HTMLElement {
1698
1826
  api: this.widgetApi,
1699
1827
  content: "error",
1700
1828
  context: {
1701
- type: "error"
1829
+ type: "error",
1830
+ container: this.container || undefined
1702
1831
  },
1703
1832
  type: "ERROR_WIDGET",
1704
1833
  domain: ((_this$config2 = this.config) == null ? void 0 : _this$config2.domain) || DEFAULT_DOMAIN,
1705
1834
  npmCdn: DEFAULT_NPM_CDN,
1706
- container: this.container || this
1835
+ container: this
1707
1836
  };
1708
1837
 
1709
1838
  if (this.type === "EMBED") {
1710
1839
  return new EmbedWidget(params);
1711
1840
  } else {
1712
- return new PopupWidget(params, this.firstChild ? null : undefined);
1841
+ var useFirstChildTrigger = this.firstChild ? null : undefined;
1842
+ return new PopupWidget(params, useFirstChildTrigger);
1713
1843
  }
1714
1844
  };
1715
1845
 
1846
+ this.reload = this.renderWidget;
1716
1847
  this.show = this.open;
1717
1848
  this.hide = this.close;
1718
1849
  this.attachShadow({
1719
1850
  mode: "open"
1720
- }).innerHTML = "<style>:host { display: contents; }</style><slot></slot>";
1721
- this.config = window.squatchConfig;
1722
- this.token = window.squatchToken;
1851
+ }).innerHTML = "<style>:host { display: block; }</style><slot></slot>";
1852
+ this.config = getConfig();
1853
+ this.token = getToken();
1723
1854
  this.tenant = window.squatchTenant;
1724
1855
  this.container = this;
1725
1856
  }
@@ -1727,7 +1858,7 @@ class DeclarativeWidget extends HTMLElement {
1727
1858
  _setupApis(config) {
1728
1859
  var _this$config3, _this$config4;
1729
1860
 
1730
- if (!this.tenant) throw new Error("Requires tenantAlias");
1861
+ if (!this.tenant) throw new Error("tenantAlias not provided");
1731
1862
  this.widgetApi = new WidgetApi({
1732
1863
  tenantAlias: (config == null ? void 0 : config.tenantAlias) || this.tenant,
1733
1864
  domain: (config == null ? void 0 : config.domain) || ((_this$config3 = this.config) == null ? void 0 : _this$config3.domain) || DEFAULT_DOMAIN
@@ -1738,15 +1869,14 @@ class DeclarativeWidget extends HTMLElement {
1738
1869
  }
1739
1870
 
1740
1871
  async renderPasswordlessVariant() {
1741
- var _configs$widgetConfig, _configs$widgetConfig2;
1742
-
1743
- var configs = _getAutoConfig();
1872
+ this._setupApis();
1744
1873
 
1745
- this._setupApis(configs == null ? void 0 : configs.squatchConfig);
1874
+ _log$1("Rendering as an Instant Access widget");
1746
1875
 
1747
1876
  return await this.widgetApi.render({
1748
- engagementMedium: (configs == null ? void 0 : (_configs$widgetConfig = configs.widgetConfig) == null ? void 0 : _configs$widgetConfig.engagementMedium) || this.type,
1749
- widgetType: (configs == null ? void 0 : (_configs$widgetConfig2 = configs.widgetConfig) == null ? void 0 : _configs$widgetConfig2.widgetType) || this.widgetType
1877
+ engagementMedium: this.type,
1878
+ widgetType: this.widgetType,
1879
+ locale: this.locale
1750
1880
  }).then(res => this._setWidget(res.template, {
1751
1881
  type: "passwordless"
1752
1882
  })).catch(this.setErrorWidget);
@@ -1756,21 +1886,35 @@ class DeclarativeWidget extends HTMLElement {
1756
1886
  this._setupApis();
1757
1887
 
1758
1888
  var userObj = decodeUserJwt(this.token);
1759
- if (!userObj) throw new Error("Could not load user information from jwt");
1889
+
1890
+ if (!userObj) {
1891
+ return this.setErrorWidget(Error("No user object in token."));
1892
+ }
1893
+
1894
+ _log$1("Rendering as a Verified widget");
1895
+
1760
1896
  var widgetInstance = await this.widgetApi.upsertUser({
1761
1897
  user: userObj,
1898
+ locale: this.locale,
1762
1899
  engagementMedium: this.type,
1763
1900
  widgetType: this.widgetType,
1764
1901
  jwt: this.token
1765
1902
  }).then(res => this._setWidget(res.template, {
1766
- type: "upsert"
1903
+ type: "upsert",
1904
+ user: userObj
1767
1905
  })).catch(this.setErrorWidget);
1768
1906
  return widgetInstance;
1769
1907
  }
1770
1908
 
1909
+ /**
1910
+ * Fetches widget content from SaaSquatch and builds a Widget instance to support rendering the widget in the DOM
1911
+ * @returns Instance of either {@link EmbedWidget} or {@link PopupWidget} depending on `this.type`
1912
+ * @throws Throws an Error if `widgetType` is undefined
1913
+ */
1771
1914
  async getWidgetInstance() {
1772
1915
  var widgetInstance;
1773
1916
  this.widgetType = this.getAttribute("widget") || undefined;
1917
+ this.locale = this.getAttribute("locale") || this.locale;
1774
1918
  if (!this.widgetType) throw new Error("No widget has been specified");
1775
1919
 
1776
1920
  if (!this.token) {
@@ -1779,82 +1923,130 @@ class DeclarativeWidget extends HTMLElement {
1779
1923
  widgetInstance = await this.renderUserUpsertVariant();
1780
1924
  }
1781
1925
 
1782
- if (!widgetInstance) throw new Error("Could not create widget.");
1783
1926
  this.widgetInstance = widgetInstance;
1784
1927
  return widgetInstance;
1785
1928
  }
1929
+ /**
1930
+ * Calls {@link getWidgetInstance} to build the Widget instance and loads the widget iframe into the DOM
1931
+ */
1932
+
1786
1933
 
1787
1934
  async renderWidget() {
1788
1935
  await this.getWidgetInstance();
1789
1936
  await this.widgetInstance.load();
1790
1937
  }
1938
+ /**
1939
+ * Builds a Widget instance for the default error widget
1940
+ * @returns Instance of either {@link EmbedWidget} or {@link PopupWidget} depending on `this.type`
1941
+ */
1942
+
1791
1943
 
1944
+ /**
1945
+ * Calls `open` method of `widgetInstance`
1946
+ * @throws Throws an Error if called before the widget has loaded
1947
+ */
1792
1948
  open() {
1949
+ if (!this.widgetInstance) throw new Error("Widget has not loaded yet");
1793
1950
  this.widgetInstance.open();
1794
1951
  }
1952
+ /**
1953
+ * Calls `close` method of `widgetInstance`
1954
+ * @throws Throws an Error if called before the widget has loaded
1955
+ */
1956
+
1795
1957
 
1796
1958
  close() {
1959
+ if (!this.widgetInstance) throw new Error("Widget has not loaded yet");
1797
1960
  this.widgetInstance.close();
1798
1961
  }
1799
1962
 
1800
1963
  }
1801
1964
 
1965
+ /**
1966
+ * Base class for `squatch-embed` web-component
1967
+ * @extends {DeclarativeWidget}
1968
+ * @class
1969
+ * @example
1970
+ * window.createCustomElement('squatch-embed', DeclarativeEmbedWidget)
1971
+ * const widget = document.querySelector('squatch-embed') as DeclarativeEmbedWidget
1972
+ * widget.open()
1973
+ * widget.close()
1974
+ * widget.reload()
1975
+ */
1976
+
1802
1977
  class DeclarativeEmbedWidget extends DeclarativeWidget {
1803
1978
  constructor() {
1804
1979
  super();
1980
+ /**
1981
+ * @static
1982
+ */
1983
+
1805
1984
  this.type = "EMBED";
1985
+ this.loaded = false;
1806
1986
  }
1807
1987
 
1808
1988
  static get observedAttributes() {
1809
- return ["widget", "container"];
1989
+ return ["widget", "locale"];
1810
1990
  }
1811
1991
 
1812
1992
  attributeChangedCallback(attr, oldVal, newVal) {
1813
- if (oldVal === newVal || !oldVal) return; // nothing to do
1993
+ if (oldVal === newVal || !this.loaded) return; // nothing to do
1814
1994
 
1815
1995
  switch (attr) {
1996
+ case "locale":
1816
1997
  case "widget":
1817
1998
  this.connectedCallback();
1818
1999
  break;
1819
- // Specific to embed widgets
1820
-
1821
- case "container":
1822
- if (this.widgetInstance._findElement()) this.close();
1823
- this.connectedCallback();
1824
- break;
1825
2000
  }
1826
2001
  }
1827
2002
 
1828
2003
  async connectedCallback() {
1829
2004
  var _ref, _this$shadowRoot;
1830
2005
 
1831
- this.container = this.getAttribute("container") || this;
2006
+ this.loaded = true;
2007
+ this.container = this.getAttribute("container");
1832
2008
  await this.renderWidget();
1833
2009
  var slot = (_ref = this.shadowRoot && Array.from(this.shadowRoot.children)) == null ? void 0 : _ref.find(c => c.tagName === "SLOT");
1834
2010
  if (slot) (_this$shadowRoot = this.shadowRoot) == null ? void 0 : _this$shadowRoot.removeChild(slot);
1835
2011
  }
1836
2012
 
1837
2013
  }
2014
+ /**
2015
+ * Base class for `squatch-popup` web-component
2016
+ * @extends {DeclarativeWidget}
2017
+ * @class
2018
+ * @example
2019
+ * window.createCustomElement('squatch-popup', DeclarativePopupWidget)
2020
+ * const widget = document.querySelector('squatch-popup') as DeclarativePopupWidget
2021
+ * widget.open()
2022
+ * widget.close()
2023
+ * widget.reload()
2024
+ */
2025
+
1838
2026
  class DeclarativePopupWidget extends DeclarativeWidget {
1839
2027
  constructor() {
1840
2028
  super();
2029
+ /**
2030
+ * @static
2031
+ */
2032
+
1841
2033
  this.type = "POPUP";
2034
+ this.loaded = false;
1842
2035
  this.addEventListener("click", e => {
1843
- e.stopPropagation(); // SQUATCH-POPUP target means something in the shadowDOM was clicked (i.e. the dialog element)
1844
-
1845
- if (e.target.tagName !== "SQUATCH-POPUP") this.open();
2036
+ e.stopPropagation();
2037
+ this.open();
1846
2038
  });
1847
2039
  }
1848
2040
 
1849
2041
  static get observedAttributes() {
1850
- return ["widget", "id", "open"];
2042
+ return ["widget", "locale"];
1851
2043
  }
1852
2044
 
1853
2045
  attributeChangedCallback(attr, oldVal, newVal) {
1854
- if (oldVal === newVal || !oldVal) return; // nothing to do
2046
+ if (oldVal === newVal || !this.loaded) return; // nothing to do
1855
2047
 
1856
2048
  switch (attr) {
1857
- case "open":
2049
+ case "locale":
1858
2050
  case "widget":
1859
2051
  this.connectedCallback();
1860
2052
  break;
@@ -1862,13 +2054,26 @@ class DeclarativePopupWidget extends DeclarativeWidget {
1862
2054
  }
1863
2055
 
1864
2056
  async connectedCallback() {
2057
+ this.loaded = true;
2058
+ this.container = this.getAttribute("container");
1865
2059
  await this.renderWidget();
1866
2060
  if (this.getAttribute("open") !== null) this.open();
1867
2061
  }
1868
2062
 
1869
2063
  }
1870
- window.customElements.define("squatch-embed", DeclarativeEmbedWidget);
1871
- window.customElements.define("squatch-popup", DeclarativePopupWidget);
2064
+
2065
+ class SquatchEmbed extends DeclarativeEmbedWidget {}
2066
+
2067
+ class SquatchPopup extends DeclarativePopupWidget {}
2068
+
2069
+ class ImpactEmbed extends DeclarativeEmbedWidget {}
2070
+
2071
+ class ImpactPopup extends DeclarativePopupWidget {}
2072
+
2073
+ window.customElements.define("squatch-embed", SquatchEmbed);
2074
+ window.customElements.define("impact-embed", ImpactEmbed);
2075
+ window.customElements.define("squatch-popup", SquatchPopup);
2076
+ window.customElements.define("impact-popup", ImpactPopup);
1872
2077
 
1873
2078
  // @ts-check
1874
2079
  function help() {
@@ -1896,10 +2101,14 @@ var _events = null;
1896
2101
  * Read the {@link WidgetApi} docs.
1897
2102
  *
1898
2103
  * @returns WidgetApi static instance
2104
+ * @example
2105
+ * squatch.api().render({ ... })
2106
+ * squatch.api().upsertUser({ ... })
2107
+ * squatch.api().squatchReferralCookie()
1899
2108
  */
1900
2109
 
1901
2110
  function api() {
1902
- if (!_api) exports.init({});
2111
+ if (!_api) init({});
1903
2112
  return _api;
1904
2113
  }
1905
2114
  /**
@@ -1908,10 +2117,14 @@ function api() {
1908
2117
  * Read the {@link Widgets} docs.
1909
2118
  *
1910
2119
  * @returns static instance
2120
+ * @example
2121
+ * squatch.widgets().render({ widgetType: "w/widget-type" })
2122
+ * squatch.widgets().upsertUser({ user: { ... }, widgetType: "w/widget-type" })
2123
+ * squatch.widgets().autofill(".referral-code")
1911
2124
  */
1912
2125
 
1913
2126
  function widgets() {
1914
- if (!_widgets) exports.init({});
2127
+ if (!_widgets) init({});
1915
2128
  return _widgets;
1916
2129
  }
1917
2130
  /**
@@ -1920,14 +2133,24 @@ function widgets() {
1920
2133
  * Read the {@link EventsApi} docs.
1921
2134
  *
1922
2135
  * @returns EventsApi static instance
2136
+ *
2137
+ * @example
2138
+ * squatch.events().track({ ... })
1923
2139
  */
1924
2140
 
1925
2141
  function events() {
1926
- if (!_events) exports.init({});
2142
+ if (!_events) init({});
1927
2143
  return _events;
1928
2144
  }
1929
2145
  /**
1930
2146
  * Entry-point for high level API to render a widget using the instance of {@link Widgets} created when you call {@link #init init}.
2147
+ *
2148
+ * Read the {@link Widgets.render} docs.
2149
+ *
2150
+ * @example
2151
+ * squatch.widget().then(res => {
2152
+ * const widget = res.widget
2153
+ * }).catch(e => console.error("Did not render widget:", e))
1931
2154
  */
1932
2155
 
1933
2156
  function widget(widgetConfig) {
@@ -1937,6 +2160,9 @@ function widget(widgetConfig) {
1937
2160
  }
1938
2161
  /**
1939
2162
  * Extracts widget configuration from `_saasquatchExtra` UTM parameter. Initialises `squatch` and renders the widget as a {@link PopupWidget} via static instanct of {@link Widgets}.
2163
+ *
2164
+ * Called by default on startup via the loader script.
2165
+ * @private
1940
2166
  */
1941
2167
 
1942
2168
  function _auto(configIn) {
@@ -1963,7 +2189,9 @@ function _auto(configIn) {
1963
2189
  * @param config Configuration details
1964
2190
  *
1965
2191
  * @example
1966
- * squatch.init({tenantAlias:'test_basbtabstq51v'});
2192
+ * squatch.init({
2193
+ * tenantAlias:'test_basbtabstq51v',
2194
+ * });
1967
2195
  */
1968
2196
 
1969
2197
  function init(configIn) {
@@ -1972,6 +2200,8 @@ function init(configIn) {
1972
2200
 
1973
2201
  if (config.tenantAlias.match("^test") || config.debug) {
1974
2202
  debug.debug.enable("squatch-js*");
2203
+ } else {
2204
+ debug.debug.disable();
1975
2205
  }
1976
2206
 
1977
2207
  _log("initializing ...");
@@ -1995,7 +2225,7 @@ function init(configIn) {
1995
2225
  * @example
1996
2226
  * squatch.ready(function() {
1997
2227
  * console.log("ready!");
1998
- * squatch.api().upsertUser();
2228
+ * squatch.api().upsertUser({ ... });
1999
2229
  * });
2000
2230
  */
2001
2231
 
@@ -2008,30 +2238,15 @@ function ready(fn) {
2008
2238
  *
2009
2239
  * @param {string} selector Element class/id
2010
2240
  * @returns {void}
2011
- */
2012
-
2013
- function autofill(selector) {
2014
- // @ts-ignore -- will throw occasionally throw a null pointer exception at runtime
2015
- widgets().autofill(selector);
2016
- }
2017
- /**
2018
- * Overrides the default function that submits the user email. If you have
2019
- * Security enabled, the email needs to be signed before it's submitted.
2020
- *
2021
- * @param {function} fn Callback function for the 'submit_email' event.
2022
- * @returns {void}
2023
2241
  *
2024
2242
  * @example
2025
- * squatch.submitEmail(function(target, widget, email) {
2026
- * // Sign email and generate jwt token
2027
- * var jwt = 'token';
2028
- * widget.reload(email, jwt);
2029
- * });
2243
+ * squatch.autofill("input.referral-code")
2244
+ * squatch.autofill("input#referral-code")
2030
2245
  */
2031
2246
 
2032
- function submitEmail(fn) {
2247
+ function autofill(selector) {
2033
2248
  // @ts-ignore -- will throw occasionally throw a null pointer exception at runtime
2034
- widgets().submitEmail(fn);
2249
+ widgets().autofill(selector);
2035
2250
  }
2036
2251
  /**
2037
2252
  * Manually set the _saasquatch cookie as a 1st party cookie if available as a URL parameter on the current page.
@@ -2071,7 +2286,6 @@ exports.help = help;
2071
2286
  exports.init = init;
2072
2287
  exports.pushCookie = pushCookie;
2073
2288
  exports.ready = ready;
2074
- exports.submitEmail = submitEmail;
2075
2289
  exports.widget = widget;
2076
2290
  exports.widgets = widgets;
2077
2291
  //# sourceMappingURL=squatch.js.map