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

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