@saasquatch/squatch-js 2.6.0-4 → 2.6.0-6

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 (37) hide show
  1. package/coverage/clover.xml +849 -64
  2. package/coverage/coverage-final.json +19 -1
  3. package/coverage/lcov-report/DeclarativeWidget.ts.html +298 -118
  4. package/coverage/lcov-report/Widgets.ts.html +70 -22
  5. package/coverage/lcov-report/api/AnalyticsApi.ts.html +38 -38
  6. package/coverage/lcov-report/api/EventsApi.ts.html +352 -0
  7. package/coverage/lcov-report/api/WidgetApi.ts.html +57 -30
  8. package/coverage/lcov-report/api/graphql.ts.html +1 -1
  9. package/coverage/lcov-report/squatch.ts.html +721 -0
  10. package/coverage/lcov-report/utils/cookieUtils.ts.html +10 -10
  11. package/coverage/lcov-report/utils/decodeUserJwt.ts.html +19 -19
  12. package/coverage/lcov-report/utils/domready.ts.html +1 -1
  13. package/coverage/lcov-report/utils/io.ts.html +7 -7
  14. package/coverage/lcov-report/utils/utmUtils.ts.html +1 -1
  15. package/coverage/lcov-report/utils/validate.ts.html +37 -37
  16. package/coverage/lcov-report/validate.ts.html +1 -1
  17. package/coverage/lcov-report/widgets/EmbedWidget.ts.html +67 -19
  18. package/coverage/lcov-report/widgets/PopupWidget.ts.html +23 -8
  19. package/coverage/lcov-report/widgets/Widget.ts.html +7 -16
  20. package/coverage/lcov-report/widgets/Widgets.ts.html +61 -16
  21. package/coverage/lcov-report/widgets/declarative/DeclarativeWidget.ts.html +373 -82
  22. package/coverage/lcov-report/widgets/declarative/DeclarativeWidgets.ts.html +388 -0
  23. package/coverage/lcov.info +1559 -125
  24. package/dist/api/WidgetApi.d.ts +2 -2
  25. package/dist/squatch.d.ts +28 -1
  26. package/dist/squatch.esm.js +274 -121
  27. package/dist/squatch.esm.js.map +1 -1
  28. package/dist/squatch.js +274 -121
  29. package/dist/squatch.js.map +1 -1
  30. package/dist/squatch.min.js +1 -1
  31. package/dist/types.d.ts +8 -6
  32. package/dist/widgets/EmbedWidget.d.ts +6 -0
  33. package/dist/widgets/PopupWidget.d.ts +6 -1
  34. package/dist/widgets/Widgets.d.ts +15 -2
  35. package/dist/widgets/declarative/DeclarativeWidget.d.ts +57 -1
  36. package/dist/widgets/declarative/DeclarativeWidgets.d.ts +22 -0
  37. package/package.json +1 -1
@@ -211,7 +211,7 @@ class WidgetApi {
211
211
  this.npmCdn = clean.npmCdn;
212
212
  }
213
213
  /**
214
- * Creates/upserts user.
214
+ * Creates/upserts user, requests widget template.
215
215
  *
216
216
  * @param {Object} params Parameters for request
217
217
  * @param {Object?} params.user The user details
@@ -253,7 +253,7 @@ class WidgetApi {
253
253
  return doPut(url, JSON.stringify(user), jwt);
254
254
  }
255
255
  /**
256
- * Description here.
256
+ * Requests widget template
257
257
  *
258
258
  * @param {Object} params Parameters for request
259
259
  * @param {Object} params.user The user details
@@ -400,7 +400,7 @@ function _validateAnalyticsConfig(raw) {
400
400
  // @ts-check
401
401
  /** @hidden */
402
402
 
403
- var _log$7 = debug("squatch-js:widget");
403
+ var _log$8 = debug("squatch-js:widget");
404
404
  /*
405
405
  * The Widget class is the base class for the different widget types available
406
406
  *
@@ -421,7 +421,7 @@ class Widget {
421
421
  this.npmCdn = void 0;
422
422
  this.container = void 0;
423
423
 
424
- _log$7("widget initializing ...");
424
+ _log$8("widget initializing ...");
425
425
 
426
426
  this.content = params.content === "error" ? this._error(params.rsCode) : params.content;
427
427
  this.type = params.type;
@@ -431,7 +431,7 @@ class Widget {
431
431
  domain: params.domain
432
432
  });
433
433
  this.context = params.context;
434
- this.container = params.container;
434
+ this.container = params.context.container;
435
435
  }
436
436
 
437
437
  _findElement() {
@@ -441,22 +441,22 @@ class Widget {
441
441
  // selector is a string
442
442
  element = document.querySelector(this.container);
443
443
 
444
- _log$7("loading widget with selector", element); // selector is an HTML element
444
+ _log$8("loading widget with selector", element); // selector is an HTML element
445
445
 
446
446
  } else if (this.container instanceof HTMLElement) {
447
447
  element = this.container;
448
448
 
449
- _log$7("loading widget with container", element); // garbage container found
449
+ _log$8("loading widget with container", element); // garbage container found
450
450
 
451
451
  } else if (this.container) {
452
452
  element = null;
453
453
 
454
- _log$7("container must be an HTMLElement or string", this.container); // find element on page
454
+ _log$8("container must be an HTMLElement or string", this.container); // find element on page
455
455
 
456
456
  } else {
457
457
  element = document.querySelector("#squatchembed") || document.querySelector(".squatchembed");
458
458
 
459
- _log$7("loading widget with default selector", element);
459
+ _log$8("loading widget with default selector", element);
460
460
  }
461
461
 
462
462
  if (!(element instanceof HTMLElement)) throw new Error("element with selector '" + (this.container || "#squatchembed or .squatchembed") + "' not found.'");
@@ -475,8 +475,7 @@ class Widget {
475
475
  }
476
476
 
477
477
  _findFrame() {
478
- var element = this._findElement();
479
-
478
+ var element = this.container ? this._findElement() : document.body;
480
479
  var parent = element.shadowRoot || element;
481
480
  return parent.querySelector("iframe#squatchFrame");
482
481
  }
@@ -515,9 +514,9 @@ class Widget {
515
514
  }
516
515
 
517
516
  (_this$analyticsApi$pu = this.analyticsApi.pushAnalyticsLoadEvent(params)) == null ? void 0 : _this$analyticsApi$pu.then(response => {
518
- _log$7(params.engagementMedium + " loaded event recorded.");
517
+ _log$8(params.engagementMedium + " loaded event recorded.");
519
518
  }).catch(ex => {
520
- _log$7("ERROR: pushAnalyticsLoadEvent() " + ex);
519
+ _log$8("ERROR: pushAnalyticsLoadEvent() " + ex);
521
520
  });
522
521
  }
523
522
 
@@ -530,9 +529,9 @@ class Widget {
530
529
  engagementMedium: sqh.mode.widgetMode,
531
530
  shareMedium: medium
532
531
  }).then(response => {
533
- _log$7(sqh.mode.widgetMode + " share " + medium + " event recorded. " + response);
532
+ _log$8(sqh.mode.widgetMode + " share " + medium + " event recorded. " + response);
534
533
  }).catch(ex => {
535
- _log$7("ERROR: pushAnalyticsShareClickedEvent() " + ex);
534
+ _log$8("ERROR: pushAnalyticsShareClickedEvent() " + ex);
536
535
  });
537
536
  }
538
537
  } // TODO: CA: Refactor how error templates are shown
@@ -654,7 +653,7 @@ class Widget {
654
653
  message
655
654
  } = _ref3;
656
655
 
657
- _log$7("" + message);
656
+ _log$8("" + message);
658
657
  });
659
658
  }
660
659
 
@@ -682,10 +681,7 @@ class Widget {
682
681
 
683
682
  function delay(duration) {
684
683
  return new Promise(function (resolve, reject) {
685
- setTimeout(function () {
686
- /* istanbul ignore next */
687
- resolve(() => {});
688
- }, duration);
684
+ setTimeout(resolve, duration);
689
685
  });
690
686
  }
691
687
 
@@ -714,12 +710,17 @@ function domready(targetDoc, fn) {
714
710
 
715
711
  // @ts-check
716
712
 
717
- var _log$6 = debug("squatch-js:EMBEDwidget");
713
+ var _log$7 = debug("squatch-js:EMBEDwidget");
718
714
  /**
719
715
  * An EmbedWidget is displayed inline in part of your page.
720
716
  *
721
717
  * To create an EmbedWidget use {@link Widgets}
722
718
  *
719
+ * @example
720
+ * const widget = new EmbedWidget({ ... })
721
+ * widget.load() // Loads widget into the DOM
722
+ * widget.open() // Makes the iframe container visible
723
+ * widget.close() // Hides the iframe container
723
724
  */
724
725
 
725
726
 
@@ -728,6 +729,7 @@ class EmbedWidget extends Widget {
728
729
  super(params);
729
730
  this.show = this.open;
730
731
  this.hide = this.close;
732
+ if (container) this.container = container;
731
733
  }
732
734
 
733
735
  async load() {
@@ -771,6 +773,8 @@ class EmbedWidget extends Widget {
771
773
 
772
774
  frame.height = frameDoc.body.scrollHeight; // Adjust frame height when size of body changes
773
775
 
776
+ /* istanbul ignore next: hard to test */
777
+
774
778
  var ro = new contentWindow["ResizeObserver"](entries => {
775
779
  for (var entry of entries) {
776
780
  var {
@@ -780,12 +784,13 @@ class EmbedWidget extends Widget {
780
784
  frame.height = height;
781
785
  }
782
786
  });
783
- ro.observe(await this._findInnerContainer(frame)); // Regular load - trigger event
787
+ var container = await this._findInnerContainer(frame);
788
+ ro.observe(container);
784
789
 
785
- if (!this.container) {
790
+ if (this._shouldFireLoadEvent()) {
786
791
  this._loadEvent(_sqh);
787
792
 
788
- _log$6("loaded");
793
+ _log$7("loaded");
789
794
  }
790
795
  });
791
796
  }
@@ -799,7 +804,7 @@ class EmbedWidget extends Widget {
799
804
 
800
805
  var frame = this._findFrame();
801
806
 
802
- if (!frame) return _log$6("no target element to open");
807
+ if (!frame) return _log$7("no target element to open");
803
808
 
804
809
  var element = this._findElement();
805
810
 
@@ -810,15 +815,17 @@ class EmbedWidget extends Widget {
810
815
 
811
816
  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);
812
817
 
813
- this._loadEvent(_sqh);
818
+ if (this.context.user) {
819
+ this._loadEvent(_sqh);
814
820
 
815
- _log$6("loaded");
821
+ _log$7("loaded");
822
+ }
816
823
  }
817
824
 
818
825
  close() {
819
826
  var frame = this._findFrame();
820
827
 
821
- if (!frame) return _log$6("no target element to close");
828
+ if (!frame) return _log$7("no target element to close");
822
829
 
823
830
  var element = this._findElement();
824
831
 
@@ -826,7 +833,7 @@ class EmbedWidget extends Widget {
826
833
  element.style.height = "0";
827
834
  element.style["overflow-y"] = "hidden";
828
835
 
829
- _log$6("Embed widget closed");
836
+ _log$7("Embed widget closed");
830
837
  }
831
838
 
832
839
  _error(rs, mode, style) {
@@ -841,11 +848,18 @@ class EmbedWidget extends Widget {
841
848
  return super._error(rs, mode, style);
842
849
  }
843
850
 
851
+ _shouldFireLoadEvent() {
852
+ var noContainer = !this.container;
853
+ var isComponent = this.container instanceof HTMLElement && this.container.tagName.startsWith("SQUATCH-");
854
+ var isVerified = !!this.context.user;
855
+ return isVerified && (noContainer || isComponent);
856
+ }
857
+
844
858
  }
845
859
 
846
860
  // @ts-check
847
861
 
848
- var _log$5 = debug("squatch-js:POPUPwidget");
862
+ var _log$6 = debug("squatch-js:POPUPwidget");
849
863
 
850
864
  var popupId = 0;
851
865
  /**
@@ -854,6 +868,11 @@ var popupId = 0;
854
868
  *
855
869
  * To create a PopupWidget use {@link Widgets}
856
870
  *
871
+ * @example
872
+ * const widget = new PopupWidget({ ... })
873
+ * widget.load() // Loads the widget into a dialog element
874
+ * widget.open() // Opens the dialog element
875
+ * widget.close() // Hides the dialog element
857
876
  */
858
877
 
859
878
  class PopupWidget extends Widget {
@@ -879,7 +898,7 @@ class PopupWidget extends Widget {
879
898
  document.head.insertAdjacentHTML("beforeend", "<style>#" + this.id + "::-webkit-scrollbar { display: none; }</style>");
880
899
  }
881
900
 
882
- _initialiseCTA(frame) {
901
+ _initialiseCTA() {
883
902
  if (!this.trigger) return;
884
903
  var triggerElement;
885
904
 
@@ -887,9 +906,9 @@ class PopupWidget extends Widget {
887
906
  triggerElement
888
907
  /* HTMLButton */
889
908
  = document.querySelector(this.trigger);
890
- if (this.trigger && !triggerElement) _log$5("No element found with trigger selector", this.trigger);
909
+ if (this.trigger && !triggerElement) _log$6("No element found with trigger selector", this.trigger);
891
910
  } catch (_unused) {
892
- _log$5("Not a valid selector", this.trigger);
911
+ _log$6("Not a valid selector", this.trigger);
893
912
  } // Trigger is optional
894
913
 
895
914
 
@@ -897,16 +916,7 @@ class PopupWidget extends Widget {
897
916
  triggerElement.onclick = () => {
898
917
  this.open();
899
918
  };
900
- } // const element = this._findElement();
901
- // If widget is loaded with CTA, look for a 'squatchpop' element to use
902
- // that element as a trigger as well.
903
- // const triggerWhenCTA = element.querySelector(".squatchpop") as HTMLElement;
904
- // if (this.trigger === "#cta" && triggerWhenCTA) {
905
- // triggerWhenCTA.onclick = () => {
906
- // this.open(frame);
907
- // };
908
- // }
909
-
919
+ }
910
920
  }
911
921
 
912
922
  _createPopupDialog() {
@@ -915,6 +925,7 @@ class PopupWidget extends Widget {
915
925
  dialog.setAttribute("style", "width: 100%; max-width: 500px; border: none; padding: 0;");
916
926
 
917
927
  var onClick = e => {
928
+ e.stopPropagation();
918
929
  if (e.target === dialog) dialog.close();
919
930
  };
920
931
 
@@ -927,10 +938,9 @@ class PopupWidget extends Widget {
927
938
 
928
939
  var frame = this._createFrame();
929
940
 
930
- this._initialiseCTA(frame);
931
-
932
- var element = this._findElement();
941
+ this._initialiseCTA();
933
942
 
943
+ var element = this.container ? this._findElement() : document.body;
934
944
  var dialogParent = element.shadowRoot || element;
935
945
 
936
946
  var dialog = this._createPopupDialog();
@@ -959,7 +969,7 @@ class PopupWidget extends Widget {
959
969
  frameDoc.write("<script src=\"" + this.npmCdn + "/resize-observer-polyfill@1.5.x\"></script>");
960
970
  frameDoc.close();
961
971
 
962
- _log$5("Popup template loaded into iframe");
972
+ _log$6("Popup template loaded into iframe");
963
973
 
964
974
  this._setupResizeHandler(frame);
965
975
  }
@@ -996,8 +1006,7 @@ class PopupWidget extends Widget {
996
1006
  }
997
1007
 
998
1008
  open() {
999
- var element = this._findElement();
1000
-
1009
+ var element = this.container ? this._findElement() : document.body;
1001
1010
  var parent = element.shadowRoot || element;
1002
1011
  var dialog = parent.querySelector("#" + this.id);
1003
1012
  if (!dialog) throw new Error("Could not determine container div");
@@ -1019,21 +1028,22 @@ class PopupWidget extends Widget {
1019
1028
 
1020
1029
  (_frame$contentDocumen = frame.contentDocument) == null ? void 0 : _frame$contentDocumen.dispatchEvent(new CustomEvent("sq:refresh"));
1021
1030
 
1022
- this._loadEvent(_sqh);
1031
+ if (this.context.user) {
1032
+ this._loadEvent(_sqh);
1023
1033
 
1024
- _log$5("Popup opened");
1034
+ _log$6("Popup opened");
1035
+ }
1025
1036
  });
1026
1037
  }
1027
1038
 
1028
1039
  close() {
1029
- var element = this._findElement();
1030
-
1040
+ var element = this.container ? this._findElement() : document.body;
1031
1041
  var parent = element.shadowRoot || element;
1032
1042
  var dialog = parent.querySelector("#" + this.id);
1033
1043
  if (!dialog) throw new Error("Could not determine container div");
1034
1044
  dialog.close();
1035
1045
 
1036
- _log$5("Popup closed");
1046
+ _log$6("Popup closed");
1037
1047
  }
1038
1048
 
1039
1049
  _clickedOutside(_ref) {
@@ -1054,16 +1064,33 @@ class PopupWidget extends Widget {
1054
1064
 
1055
1065
  }
1056
1066
 
1057
- var _log$4 = debug("squatch-js:widgets");
1067
+ var _log$5 = debug("squatch-js:widgets");
1058
1068
  /**
1059
- *
1060
1069
  * `Widgets` is a factory for creating widgets. It's possible to build your own widgets using the
1061
1070
  * {@link WidgetApi} but most people will prefer to use these easy methods.
1062
- *
1071
+ * @class
1063
1072
  */
1064
1073
 
1065
1074
 
1066
1075
  class Widgets {
1076
+ /**
1077
+ * Instance of {@link WidgetApi}
1078
+ */
1079
+
1080
+ /**
1081
+ * Tenant alias of SaaSquatch tenant.
1082
+ */
1083
+
1084
+ /**
1085
+ * SaaSquatch domain for API requests.
1086
+ * @default "https://app.referralsaasquatch.com"
1087
+ */
1088
+
1089
+ /**
1090
+ * Hosted CDN for npm packages
1091
+ * @default "https://fast.ssqt.io/npm"
1092
+ */
1093
+
1067
1094
  /**
1068
1095
  * Initialize a new {@link Widgets} instance.
1069
1096
  *
@@ -1089,7 +1116,7 @@ class Widgets {
1089
1116
  this.tenantAlias = config.tenantAlias;
1090
1117
  this.domain = config.domain;
1091
1118
  this.npmCdn = config.npmCdn;
1092
- this.api = new WidgetApi(config); // listens to a 'submit_email' event in the theme.
1119
+ this.api = new WidgetApi(config);
1093
1120
  }
1094
1121
  /**
1095
1122
  * This function calls the {@link WidgetApi.upsertUser} method, and it renders
@@ -1126,7 +1153,7 @@ class Widgets {
1126
1153
  user: response.user
1127
1154
  };
1128
1155
  } catch (err) {
1129
- _log$4(err);
1156
+ _log$5(err);
1130
1157
 
1131
1158
  if (err.apiErrorCode) {
1132
1159
  this._renderErrorWidget(err, config.engagementMedium);
@@ -1161,7 +1188,9 @@ class Widgets {
1161
1188
  return {
1162
1189
  widget: this._renderWidget(response, clean, {
1163
1190
  type: "passwordless",
1164
- engagementMedium: clean.engagementMedium
1191
+ engagementMedium: clean.engagementMedium,
1192
+ container: clean.container,
1193
+ trigger: clean.trigger
1165
1194
  }),
1166
1195
  user: response.user
1167
1196
  };
@@ -1190,7 +1219,7 @@ class Widgets {
1190
1219
  var response = await this.api.squatchReferralCookie();
1191
1220
  input(response);
1192
1221
  } catch (e) {
1193
- _log$4("Autofill error", e);
1222
+ _log$5("Autofill error", e);
1194
1223
 
1195
1224
  throw new Error(e);
1196
1225
  }
@@ -1206,7 +1235,7 @@ class Widgets {
1206
1235
  // Only use the first element found
1207
1236
  elem = elems[0];
1208
1237
  } else {
1209
- _log$4("Element id/class or function missing");
1238
+ _log$5("Element id/class or function missing");
1210
1239
 
1211
1240
  throw new Error("Element id/class or function missing");
1212
1241
  }
@@ -1232,7 +1261,7 @@ class Widgets {
1232
1261
  _renderWidget(response, config, context) {
1233
1262
  var _opts$widget;
1234
1263
 
1235
- _log$4("Rendering Widget...");
1264
+ _log$5("Rendering Widget...");
1236
1265
 
1237
1266
  if (!response) throw new Error("Unable to get a response");
1238
1267
  var widget;
@@ -1255,16 +1284,16 @@ class Widgets {
1255
1284
  if (rule.widgetType !== "CONVERSION_WIDGET" || (_response$user = response.user) != null && (_response$user$referr = _response$user.referredBy) != null && _response$user$referr.code) {
1256
1285
  displayOnLoad = rule.displayOnLoad;
1257
1286
 
1258
- _log$4("Display " + rule.widgetType + " on " + rule.url);
1287
+ _log$5("Display " + rule.widgetType + " on " + rule.url);
1259
1288
  } else {
1260
- _log$4("Don't display " + rule.widgetType + " when no referral on widget rule match " + rule.url);
1289
+ _log$5("Don't display " + rule.widgetType + " when no referral on widget rule match " + rule.url);
1261
1290
  }
1262
1291
  }
1263
1292
  });
1264
1293
  }
1265
1294
 
1266
1295
  if (opts.fuelTankAutofillUrls) {
1267
- _log$4("We found a fuel tank autofill!");
1296
+ _log$5("We found a fuel tank autofill!");
1268
1297
 
1269
1298
  opts.fuelTankAutofillUrls.forEach(_ref => {
1270
1299
  var {
@@ -1275,7 +1304,7 @@ class Widgets {
1275
1304
  if (Widgets._matchesUrl(url)) {
1276
1305
  var _response$user2, _response$user2$refer;
1277
1306
 
1278
- _log$4("Fuel Tank URL matches");
1307
+ _log$5("Fuel Tank URL matches");
1279
1308
 
1280
1309
  if ((_response$user2 = response.user) != null && (_response$user2$refer = _response$user2.referredBy) != null && _response$user2$refer.code) {
1281
1310
  var formAutofill = document.querySelector(formSelector);
@@ -1285,7 +1314,7 @@ class Widgets {
1285
1314
 
1286
1315
  formAutofill.value = ((_response$user$referr2 = response.user.referredBy.referredReward) == null ? void 0 : _response$user$referr2.fuelTankCode) || "";
1287
1316
  } else {
1288
- _log$4(new Error("Element with id/class " + formSelector + " was not found."));
1317
+ _log$5(new Error("Element with id/class " + formSelector + " was not found."));
1289
1318
  }
1290
1319
  }
1291
1320
  }
@@ -1293,15 +1322,9 @@ class Widgets {
1293
1322
  }
1294
1323
 
1295
1324
  if (config.engagementMedium === "EMBED") {
1296
- widget = this._renderEmbedWidget(params, params.context.container);
1297
- } else if (config.engagementMedium === "POPUP") {
1298
- widget = this._renderPopupWidget(params);
1299
- if (displayOnLoad) widget.open();
1325
+ widget = this._renderEmbedWidget(params);
1300
1326
  } else {
1301
- _log$4("display popup on load");
1302
-
1303
- widget = new PopupWidget(params);
1304
- widget.load();
1327
+ widget = this._renderPopupWidget(params);
1305
1328
  if (displayOnLoad) widget.open();
1306
1329
  }
1307
1330
 
@@ -1314,8 +1337,8 @@ class Widgets {
1314
1337
  return widget;
1315
1338
  }
1316
1339
 
1317
- _renderEmbedWidget(params, container) {
1318
- var widget = new EmbedWidget(params, container);
1340
+ _renderEmbedWidget(params) {
1341
+ var widget = new EmbedWidget(params, params.context.container);
1319
1342
  widget.load();
1320
1343
  return widget;
1321
1344
  }
@@ -1338,7 +1361,7 @@ class Widgets {
1338
1361
  message
1339
1362
  } = props;
1340
1363
 
1341
- _log$4(new Error(apiErrorCode + " (" + rsCode + ") " + message));
1364
+ _log$5(new Error(apiErrorCode + " (" + rsCode + ") " + message));
1342
1365
 
1343
1366
  var params = {
1344
1367
  content: "error",
@@ -1370,9 +1393,6 @@ class Widgets {
1370
1393
 
1371
1394
  static _matchesUrl(rule) {
1372
1395
  // If there were no matches, null is returned.
1373
- console.log({
1374
- href: window.location.href
1375
- });
1376
1396
  return window.location.href.match(new RegExp(rule)) ? true : false;
1377
1397
  }
1378
1398
 
@@ -1477,7 +1497,7 @@ function asyncLoad() {
1477
1497
 
1478
1498
  /** @hidden */
1479
1499
 
1480
- var _log$3 = debug("squatch-js");
1500
+ var _log$4 = debug("squatch-js");
1481
1501
 
1482
1502
  var isObject = item => typeof item === "object" && !Array.isArray(item);
1483
1503
 
@@ -1530,7 +1550,7 @@ function _pushCookie() {
1530
1550
  try {
1531
1551
  paramsJSON = JSON.parse(b64decode(refParam));
1532
1552
  } catch (error) {
1533
- _log$3("Unable to decode params", error); // don't merge invalid params
1553
+ _log$4("Unable to decode params", error); // don't merge invalid params
1534
1554
 
1535
1555
 
1536
1556
  return;
@@ -1539,26 +1559,26 @@ function _pushCookie() {
1539
1559
  try {
1540
1560
  existingCookie = JSON.parse(b64decode(Cookies.get("_saasquatch")));
1541
1561
 
1542
- _log$3("existing cookie", existingCookie);
1562
+ _log$4("existing cookie", existingCookie);
1543
1563
  } catch (error) {
1544
- _log$3("Unable to retrieve cookie", error);
1564
+ _log$4("Unable to retrieve cookie", error);
1545
1565
  } // don't merge if there's no existing object
1546
1566
 
1547
1567
 
1548
1568
  try {
1549
1569
  var domain = getTopDomain();
1550
1570
 
1551
- _log$3("domain retrieved:", domain);
1571
+ _log$4("domain retrieved:", domain);
1552
1572
 
1553
1573
  if (existingCookie) {
1554
1574
  var newCookie = deepMerge(existingCookie, paramsJSON);
1555
1575
  reEncodedCookie = b64encode(JSON.stringify(newCookie));
1556
1576
 
1557
- _log$3("cookie to store:", newCookie);
1577
+ _log$4("cookie to store:", newCookie);
1558
1578
  } else {
1559
1579
  reEncodedCookie = b64encode(JSON.stringify(paramsJSON));
1560
1580
 
1561
- _log$3("cookie to store:", paramsJSON);
1581
+ _log$4("cookie to store:", paramsJSON);
1562
1582
  }
1563
1583
 
1564
1584
  Cookies.set("_saasquatch", reEncodedCookie, {
@@ -1569,14 +1589,14 @@ function _pushCookie() {
1569
1589
  path: "/"
1570
1590
  });
1571
1591
  } catch (error) {
1572
- _log$3("Unable to set cookie", error);
1592
+ _log$4("Unable to set cookie", error);
1573
1593
  }
1574
1594
  }
1575
1595
  }
1576
1596
 
1577
1597
  /** @hidden */
1578
1598
 
1579
- var _log$2 = debug("squatch-js");
1599
+ var _log$3 = debug("squatch-js");
1580
1600
 
1581
1601
  function _getAutoConfig(configIn) {
1582
1602
  var queryString = window.location.search;
@@ -1584,7 +1604,7 @@ function _getAutoConfig(configIn) {
1584
1604
  var refParam = urlParams.get("_saasquatchExtra") || "";
1585
1605
 
1586
1606
  if (!refParam) {
1587
- _log$2("No _saasquatchExtra param");
1607
+ _log$3("No _saasquatchExtra param");
1588
1608
 
1589
1609
  return;
1590
1610
  }
@@ -1594,7 +1614,7 @@ function _getAutoConfig(configIn) {
1594
1614
  try {
1595
1615
  raw = JSON.parse(b64decode(refParam));
1596
1616
  } catch (e) {
1597
- _log$2("Unable to decode _saasquatchExtra config");
1617
+ _log$3("Unable to decode _saasquatchExtra config");
1598
1618
 
1599
1619
  return;
1600
1620
  }
@@ -1606,7 +1626,7 @@ function _getAutoConfig(configIn) {
1606
1626
  } = convertExtraToConfig(raw);
1607
1627
 
1608
1628
  if (!domain || !tenantAlias || !widgetConfig) {
1609
- _log$2("_saasquatchExtra did not have an expected structure");
1629
+ _log$3("_saasquatchExtra did not have an expected structure");
1610
1630
 
1611
1631
  return undefined;
1612
1632
  }
@@ -1649,7 +1669,7 @@ function convertExtraToConfig(obj) {
1649
1669
  };
1650
1670
  }
1651
1671
 
1652
- var _log$1 = debug("squatch-js:decodeJwt");
1672
+ var _log$2 = debug("squatch-js:decodeJwt");
1653
1673
 
1654
1674
  function decodeUserJwt(tokenStr) {
1655
1675
  try {
@@ -1660,15 +1680,69 @@ function decodeUserJwt(tokenStr) {
1660
1680
  var jsonStr = b64decode(base64Url);
1661
1681
  return (_JSON$parse = JSON.parse(jsonStr)) == null ? void 0 : _JSON$parse.user;
1662
1682
  } catch (e) {
1663
- _log$1(e);
1683
+ _log$2(e);
1664
1684
 
1665
1685
  return null;
1666
1686
  }
1667
1687
  }
1668
1688
 
1669
- debug$1("sqh:DeclarativeWidget");
1689
+ var _log$1 = debug$1("squatch-js:DeclarativeWidget");
1690
+ /**
1691
+ * Abstract class for building web-components that render SaaSquatch widgets to the DOM.
1692
+ * @abstract
1693
+ * @example
1694
+ * class TestWidgetElement extends DeclarativeWidget {}
1695
+ * const testWidget = new TestWidgetElement()
1696
+ * testWidget.widgetType = 'w/widget-type'
1697
+ * testWidget.type = 'EMBED'
1698
+ * testWidget.renderWidget()
1699
+ */
1700
+
1670
1701
 
1671
1702
  class DeclarativeWidget extends HTMLElement {
1703
+ /**
1704
+ * Configuration overrides
1705
+ * @default window.squatchConfig
1706
+ */
1707
+
1708
+ /**
1709
+ * Signed JWT containing user information
1710
+ * @default window.squatchToken
1711
+ */
1712
+
1713
+ /**
1714
+ * Tenant alias of SaaSquatch tenant
1715
+ * @default window.squatchTenant
1716
+ */
1717
+
1718
+ /**
1719
+ * widgetType of widget to load
1720
+ */
1721
+
1722
+ /**
1723
+ * Locale to render the widget in
1724
+ */
1725
+
1726
+ /**
1727
+ * Instance of {@link WidgetApi}
1728
+ */
1729
+
1730
+ /**
1731
+ * Instance of {@link AnalyticsApi}
1732
+ */
1733
+
1734
+ /**
1735
+ * Instance of {@link EmbedWidget} or {@link PopupWidget}
1736
+ */
1737
+
1738
+ /**
1739
+ * Determines whether to render the widget as an embedding widget or popup widget.
1740
+ */
1741
+
1742
+ /**
1743
+ * Container element to contain the widget iframe
1744
+ * @default this
1745
+ */
1672
1746
  constructor() {
1673
1747
  super();
1674
1748
  this.config = void 0;
@@ -1678,8 +1752,8 @@ class DeclarativeWidget extends HTMLElement {
1678
1752
  this.locale = void 0;
1679
1753
  this.widgetApi = void 0;
1680
1754
  this.analyticsApi = void 0;
1681
- this.type = void 0;
1682
1755
  this.widgetInstance = void 0;
1756
+ this.type = void 0;
1683
1757
  this.container = void 0;
1684
1758
  this.element = void 0;
1685
1759
 
@@ -1691,16 +1765,17 @@ class DeclarativeWidget extends HTMLElement {
1691
1765
  content: template,
1692
1766
  context: {
1693
1767
  type: config.type,
1768
+ user: config.user,
1769
+ container: this.container || this,
1694
1770
  engagementMedium: this.type
1695
1771
  },
1696
1772
  type: this.widgetType,
1697
1773
  domain: ((_this$config = this.config) == null ? void 0 : _this$config.domain) || DEFAULT_DOMAIN,
1698
- npmCdn: DEFAULT_NPM_CDN,
1699
- container: this.container || this
1774
+ npmCdn: DEFAULT_NPM_CDN
1700
1775
  };
1701
1776
 
1702
1777
  if (this.type === "EMBED") {
1703
- return new EmbedWidget(params);
1778
+ return new EmbedWidget(params, params.context.container);
1704
1779
  } else {
1705
1780
  return new PopupWidget(params, this.firstChild ? null : undefined);
1706
1781
  }
@@ -1713,16 +1788,16 @@ class DeclarativeWidget extends HTMLElement {
1713
1788
  api: this.widgetApi,
1714
1789
  content: "error",
1715
1790
  context: {
1716
- type: "error"
1791
+ type: "error",
1792
+ container: this.container || this
1717
1793
  },
1718
1794
  type: "ERROR_WIDGET",
1719
1795
  domain: ((_this$config2 = this.config) == null ? void 0 : _this$config2.domain) || DEFAULT_DOMAIN,
1720
- npmCdn: DEFAULT_NPM_CDN,
1721
- container: this.container || this
1796
+ npmCdn: DEFAULT_NPM_CDN
1722
1797
  };
1723
1798
 
1724
1799
  if (this.type === "EMBED") {
1725
- return new EmbedWidget(params);
1800
+ return new EmbedWidget(params, params.context.container);
1726
1801
  } else {
1727
1802
  return new PopupWidget(params, this.firstChild ? null : undefined);
1728
1803
  }
@@ -1738,13 +1813,12 @@ class DeclarativeWidget extends HTMLElement {
1738
1813
  this.token = window.squatchToken;
1739
1814
  this.tenant = window.squatchTenant;
1740
1815
  this.container = this;
1741
- this.locale = validateLocale(navigator.language.replace(/\-/g, "_"));
1742
1816
  }
1743
1817
 
1744
1818
  _setupApis(config) {
1745
1819
  var _this$config3, _this$config4;
1746
1820
 
1747
- if (!this.tenant) throw new Error("Requires tenantAlias");
1821
+ if (!this.tenant) throw new Error("tenantAlias not provided");
1748
1822
  this.widgetApi = new WidgetApi({
1749
1823
  tenantAlias: (config == null ? void 0 : config.tenantAlias) || this.tenant,
1750
1824
  domain: (config == null ? void 0 : config.domain) || ((_this$config3 = this.config) == null ? void 0 : _this$config3.domain) || DEFAULT_DOMAIN
@@ -1755,16 +1829,14 @@ class DeclarativeWidget extends HTMLElement {
1755
1829
  }
1756
1830
 
1757
1831
  async renderPasswordlessVariant() {
1758
- var _configs$widgetConfig, _configs$widgetConfig2, _configs$widgetConfig3;
1759
-
1760
- var configs = _getAutoConfig();
1832
+ this._setupApis();
1761
1833
 
1762
- this._setupApis(configs == null ? void 0 : configs.squatchConfig);
1834
+ _log$1("Rendering as an Instant Access widget");
1763
1835
 
1764
1836
  return await this.widgetApi.render({
1765
- engagementMedium: (configs == null ? void 0 : (_configs$widgetConfig = configs.widgetConfig) == null ? void 0 : _configs$widgetConfig.engagementMedium) || this.type,
1766
- widgetType: (configs == null ? void 0 : (_configs$widgetConfig2 = configs.widgetConfig) == null ? void 0 : _configs$widgetConfig2.widgetType) || this.widgetType,
1767
- locale: (configs == null ? void 0 : (_configs$widgetConfig3 = configs.widgetConfig) == null ? void 0 : _configs$widgetConfig3.locale) || this.locale
1837
+ engagementMedium: this.type,
1838
+ widgetType: this.widgetType,
1839
+ locale: this.locale
1768
1840
  }).then(res => this._setWidget(res.template, {
1769
1841
  type: "passwordless"
1770
1842
  })).catch(this.setErrorWidget);
@@ -1774,7 +1846,13 @@ class DeclarativeWidget extends HTMLElement {
1774
1846
  this._setupApis();
1775
1847
 
1776
1848
  var userObj = decodeUserJwt(this.token);
1777
- if (!userObj) throw new Error("Could not load user information from jwt");
1849
+
1850
+ if (!userObj) {
1851
+ return this.setErrorWidget(Error("No user object in token."));
1852
+ }
1853
+
1854
+ _log$1("Rendering as a Verified widget");
1855
+
1778
1856
  var widgetInstance = await this.widgetApi.upsertUser({
1779
1857
  user: userObj,
1780
1858
  locale: this.locale,
@@ -1782,11 +1860,17 @@ class DeclarativeWidget extends HTMLElement {
1782
1860
  widgetType: this.widgetType,
1783
1861
  jwt: this.token
1784
1862
  }).then(res => this._setWidget(res.template, {
1785
- type: "upsert"
1863
+ type: "upsert",
1864
+ user: userObj
1786
1865
  })).catch(this.setErrorWidget);
1787
1866
  return widgetInstance;
1788
1867
  }
1789
1868
 
1869
+ /**
1870
+ * Fetches widget content from SaaSquatch and builds a Widget instance to support rendering the widget in the DOM.
1871
+ * @returns Instance of either {@link EmbedWidget} or {@link PopupWidget} depending on `this.type`
1872
+ * @throws Throws an Error if `widgetType` is undefined
1873
+ */
1790
1874
  async getWidgetInstance() {
1791
1875
  var widgetInstance;
1792
1876
  this.widgetType = this.getAttribute("widget") || undefined;
@@ -1799,15 +1883,23 @@ class DeclarativeWidget extends HTMLElement {
1799
1883
  widgetInstance = await this.renderUserUpsertVariant();
1800
1884
  }
1801
1885
 
1802
- if (!widgetInstance) throw new Error("Could not create widget.");
1803
1886
  this.widgetInstance = widgetInstance;
1804
1887
  return widgetInstance;
1805
1888
  }
1889
+ /**
1890
+ * Calls {@link getWidgetInstance} to build the Widget instance and loads the widget iframe into the DOM.
1891
+ */
1892
+
1806
1893
 
1807
1894
  async renderWidget() {
1808
1895
  await this.getWidgetInstance();
1809
1896
  await this.widgetInstance.load();
1810
1897
  }
1898
+ /**
1899
+ * Builds a Widget instance for the default error widget.
1900
+ * @returns Instance of either {@link EmbedWidget} or {@link PopupWidget} depending on `this.type`
1901
+ */
1902
+
1811
1903
 
1812
1904
  /**
1813
1905
  * Calls `open` method of `widgetInstance`
@@ -1830,9 +1922,25 @@ class DeclarativeWidget extends HTMLElement {
1830
1922
 
1831
1923
  }
1832
1924
 
1925
+ /**
1926
+ * Base class for `squatch-embed` web-component
1927
+ * @extends {DeclarativeWidget}
1928
+ * @class
1929
+ * @example
1930
+ * window.createCustomElement('squatch-embed', DeclarativeEmbedWidget)
1931
+ * const widget = document.querySelector('squatch-embed') as DeclarativeEmbedWidget
1932
+ * widget.open()
1933
+ * widget.close()
1934
+ * widget.reload()
1935
+ */
1936
+
1833
1937
  class DeclarativeEmbedWidget extends DeclarativeWidget {
1834
1938
  constructor() {
1835
1939
  super();
1940
+ /**
1941
+ * @static
1942
+ */
1943
+
1836
1944
  this.type = "EMBED";
1837
1945
  }
1838
1946
 
@@ -1861,14 +1969,29 @@ class DeclarativeEmbedWidget extends DeclarativeWidget {
1861
1969
  }
1862
1970
 
1863
1971
  }
1972
+ /**
1973
+ * Base class for `squatch-popup` web-component
1974
+ * @extends {DeclarativeWidget}
1975
+ * @class
1976
+ * @example
1977
+ * window.createCustomElement('squatch-popup', DeclarativePopupWidget)
1978
+ * const widget = document.querySelector('squatch-popup') as DeclarativePopupWidget
1979
+ * widget.open()
1980
+ * widget.close()
1981
+ * widget.reload()
1982
+ */
1983
+
1864
1984
  class DeclarativePopupWidget extends DeclarativeWidget {
1865
1985
  constructor() {
1866
1986
  super();
1987
+ /**
1988
+ * @static
1989
+ */
1990
+
1867
1991
  this.type = "POPUP";
1868
1992
  this.addEventListener("click", e => {
1869
- e.stopPropagation(); // SQUATCH-POPUP target means something in the shadowDOM was clicked (i.e. the dialog element)
1870
-
1871
- if (e.target.tagName !== "SQUATCH-POPUP") this.open();
1993
+ e.stopPropagation();
1994
+ this.open();
1872
1995
  });
1873
1996
  }
1874
1997
 
@@ -1888,6 +2011,7 @@ class DeclarativePopupWidget extends DeclarativeWidget {
1888
2011
  }
1889
2012
 
1890
2013
  async connectedCallback() {
2014
+ this.container = this.getAttribute("container") || this;
1891
2015
  await this.renderWidget();
1892
2016
  if (this.getAttribute("open") !== null) this.open();
1893
2017
  }
@@ -1922,6 +2046,10 @@ var _events = null;
1922
2046
  * Read the {@link WidgetApi} docs.
1923
2047
  *
1924
2048
  * @returns WidgetApi static instance
2049
+ * @example
2050
+ * squatch.api().render({ ... })
2051
+ * squatch.api().upsertUser({ ... })
2052
+ * squatch.api().squatchReferralCookie()
1925
2053
  */
1926
2054
 
1927
2055
  function api() {
@@ -1934,6 +2062,10 @@ function api() {
1934
2062
  * Read the {@link Widgets} docs.
1935
2063
  *
1936
2064
  * @returns static instance
2065
+ * @example
2066
+ * squatch.widgets().render({ widgetType: "w/widget-type" })
2067
+ * squatch.widgets().upsertUser({ user: { ... }, widgetType: "w/widget-type" })
2068
+ * squatch.widgets().autofill(".referral-code")
1937
2069
  */
1938
2070
 
1939
2071
  function widgets() {
@@ -1946,6 +2078,9 @@ function widgets() {
1946
2078
  * Read the {@link EventsApi} docs.
1947
2079
  *
1948
2080
  * @returns EventsApi static instance
2081
+ *
2082
+ * @example
2083
+ * squatch.events().track({ ... })
1949
2084
  */
1950
2085
 
1951
2086
  function events() {
@@ -1954,6 +2089,13 @@ function events() {
1954
2089
  }
1955
2090
  /**
1956
2091
  * Entry-point for high level API to render a widget using the instance of {@link Widgets} created when you call {@link #init init}.
2092
+ *
2093
+ * Read the {@link Widgets.render} docs.
2094
+ *
2095
+ * @example
2096
+ * squatch.widget().then(res => {
2097
+ * const widget = res.widget
2098
+ * }).catch(e => console.error("Did not render widget:", e))
1957
2099
  */
1958
2100
 
1959
2101
  function widget(widgetConfig) {
@@ -1963,6 +2105,9 @@ function widget(widgetConfig) {
1963
2105
  }
1964
2106
  /**
1965
2107
  * Extracts widget configuration from `_saasquatchExtra` UTM parameter. Initialises `squatch` and renders the widget as a {@link PopupWidget} via static instanct of {@link Widgets}.
2108
+ *
2109
+ * Called by default on startup via the loader script.
2110
+ * @private
1966
2111
  */
1967
2112
 
1968
2113
  function _auto(configIn) {
@@ -1989,7 +2134,9 @@ function _auto(configIn) {
1989
2134
  * @param config Configuration details
1990
2135
  *
1991
2136
  * @example
1992
- * squatch.init({tenantAlias:'test_basbtabstq51v'});
2137
+ * squatch.init({
2138
+ * tenantAlias:'test_basbtabstq51v',
2139
+ * });
1993
2140
  */
1994
2141
 
1995
2142
  function init(configIn) {
@@ -1998,6 +2145,8 @@ function init(configIn) {
1998
2145
 
1999
2146
  if (config.tenantAlias.match("^test") || config.debug) {
2000
2147
  debug.enable("squatch-js*");
2148
+ } else {
2149
+ debug.disable();
2001
2150
  }
2002
2151
 
2003
2152
  _log("initializing ...");
@@ -2034,6 +2183,10 @@ function ready(fn) {
2034
2183
  *
2035
2184
  * @param {string} selector Element class/id
2036
2185
  * @returns {void}
2186
+ *
2187
+ * @example
2188
+ * squatch.autofill("input.referral-code")
2189
+ * squatch.autofill("input#referral-code")
2037
2190
  */
2038
2191
 
2039
2192
  function autofill(selector) {