@saasquatch/squatch-js 2.5.1-9 → 2.6.0-0

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 (70) hide show
  1. package/.github/workflows/size-limit.yml +15 -0
  2. package/CHANGELOG.md +326 -334
  3. package/LICENSE +20 -20
  4. package/README.md +180 -145
  5. package/babel.config.js +8 -0
  6. package/coverage/clover.xml +888 -0
  7. package/coverage/coverage-final.json +23 -0
  8. package/coverage/lcov-report/api/AnalyticsApi.ts.html +304 -0
  9. package/coverage/lcov-report/api/WidgetApi.ts.html +628 -0
  10. package/coverage/lcov-report/api/graphql.ts.html +130 -0
  11. package/coverage/lcov-report/base.css +224 -0
  12. package/coverage/lcov-report/block-navigation.js +87 -0
  13. package/coverage/lcov-report/favicon.png +0 -0
  14. package/coverage/lcov-report/prettify.css +1 -0
  15. package/coverage/lcov-report/prettify.js +2 -0
  16. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  17. package/coverage/lcov-report/sorter.js +196 -0
  18. package/coverage/lcov-report/utils/cookieUtils.ts.html +415 -0
  19. package/coverage/lcov-report/utils/decodeUserJwt.ts.html +133 -0
  20. package/coverage/lcov-report/utils/domready.ts.html +160 -0
  21. package/coverage/lcov-report/utils/io.ts.html +385 -0
  22. package/coverage/lcov-report/utils/utmUtils.ts.html +277 -0
  23. package/coverage/lcov-report/utils/validate.ts.html +268 -0
  24. package/coverage/lcov-report/validate.ts.html +268 -0
  25. package/coverage/lcov-report/widgets/EmbedWidget.ts.html +436 -0
  26. package/coverage/lcov-report/widgets/PopupWidget.ts.html +625 -0
  27. package/coverage/lcov-report/widgets/Widget.ts.html +1108 -0
  28. package/coverage/lcov-report/widgets/declarative/DeclarativeWidget.ts.html +499 -0
  29. package/coverage/lcov.info +1628 -0
  30. package/demo/sandbox.ts +124 -124
  31. package/demo/toolbar.tsx +526 -526
  32. package/dist/api/AnalyticsApi.d.ts +32 -32
  33. package/dist/api/EventsApi.d.ts +52 -52
  34. package/dist/api/WidgetApi.d.ts +63 -80
  35. package/dist/api/graphql.d.ts +1 -1
  36. package/dist/async.d.ts +15 -11
  37. package/dist/docs.d.ts +1 -1
  38. package/dist/squatch.d.ts +108 -108
  39. package/dist/squatch.esm.js +1105 -1417
  40. package/dist/squatch.esm.js.map +1 -1
  41. package/dist/squatch.js +1105 -1438
  42. package/dist/squatch.js.map +1 -1
  43. package/dist/squatch.min.js +2 -13
  44. package/dist/squatch.min.js.LICENSE.txt +6 -0
  45. package/dist/squatch.min.js.map +1 -1
  46. package/dist/squatch.modern.js +1 -1
  47. package/dist/squatch.modern.js.map +1 -1
  48. package/dist/stats.html +1 -1
  49. package/dist/types.d.ts +107 -106
  50. package/dist/utils/cookieUtils.d.ts +2 -2
  51. package/dist/utils/decodeUserJwt.d.ts +2 -0
  52. package/dist/utils/domUtils.d.ts +1 -0
  53. package/dist/utils/domready.d.ts +6 -6
  54. package/dist/utils/io.d.ts +5 -13
  55. package/dist/utils/loadEvent.d.ts +2 -0
  56. package/dist/utils/utmUtils.d.ts +14 -14
  57. package/dist/utils/validate.d.ts +12 -16
  58. package/dist/widgets/EmbedWidget.d.ts +16 -15
  59. package/dist/widgets/IREmbedWidget.d.ts +29 -0
  60. package/dist/widgets/IRPopupWidget.d.ts +32 -0
  61. package/dist/widgets/PopupWidget.d.ts +25 -23
  62. package/dist/widgets/Widget.d.ts +53 -33
  63. package/dist/widgets/Widgets.d.ts +108 -116
  64. package/dist/widgets/declarative/DeclarativeEmbedWidget.d.ts +12 -0
  65. package/dist/widgets/declarative/DeclarativeWidget.d.ts +32 -0
  66. package/dist/widgets/declarative/DeclarativeWidgets.d.ts +13 -0
  67. package/jest.config.ts +202 -0
  68. package/package.json +123 -105
  69. package/stats.json +1 -0
  70. package/tsconfig.json +2 -2
@@ -1,8 +1,5 @@
1
- import * as debug from 'debug';
2
- import debug__default from 'debug';
3
- import * as EventBus from 'eventbusjs';
1
+ import debug$1, { debug } from 'debug';
4
2
  import Cookies from 'js-cookie';
5
- import * as superagent from 'superagent';
6
3
 
7
4
  function _extends() {
8
5
  _extends = Object.assign || function (target) {
@@ -37,159 +34,117 @@ function _objectWithoutPropertiesLoose(source, excluded) {
37
34
  return target;
38
35
  }
39
36
 
40
- function doQuery(url, query, variables, token) {
41
- const headers = _extends({
42
- Accept: "application/json"
37
+ debug("squatch-js:io");
38
+
39
+ async function doQuery(url, query, variables, token) {
40
+ var headers = _extends({
41
+ Accept: "application/json",
42
+ "Content-Type": "application/json"
43
43
  }, token ? {
44
- Authorization: `Bearer ${token}`
44
+ Authorization: "Bearer " + token
45
45
  } : {}, {
46
46
  "X-SaaSquatch-Referrer": window ? window.location.href : ""
47
47
  });
48
48
 
49
- const request = superagent.post(url).send({
50
- query,
51
- variables
52
- }).set(headers);
53
- return thenableSuperagent(request).then(response => response, error => {
54
- let json;
55
-
56
- try {
57
- json = JSON.parse(error.response.text);
58
- } catch (e) {
59
- }
60
-
61
- throw json;
62
- });
49
+ try {
50
+ var res = await fetch(url, {
51
+ method: "POST",
52
+ body: JSON.stringify({
53
+ query,
54
+ variables
55
+ }),
56
+ headers
57
+ });
58
+ if (!res.ok) throw new Error(await res.text());
59
+ return await res.json();
60
+ } catch (e) {
61
+ throw e;
62
+ }
63
63
  }
64
- function doGet(url, jwt = "") {
65
- const headers = {
64
+ async function doGet(url, jwt) {
65
+ if (jwt === void 0) {
66
+ jwt = "";
67
+ }
68
+
69
+ var headers = {
66
70
  Accept: "application/json",
67
71
  "Content-Type": "application/json"
68
72
  };
69
73
  if (jwt) headers["X-SaaSquatch-User-Token"] = jwt;
70
- const request = superagent.get(url).withCredentials().set(headers);
71
- return thenableSuperagent(request).then(response => {
72
- if ( //@ts-ignore -- superagent types might just be outdated?
73
- response.headers["content-type"] && //@ts-ignore -- superagent types might just be outdated?
74
- includes(response.headers["content-type"].toLowerCase(), "application/json")) {
75
- return JSON.parse(response.text);
76
- }
77
74
 
78
- return response.text;
79
- }, ({
80
- response
81
- }) => {
82
- const json = JSON.parse(response.text);
83
- throw json;
84
- });
75
+ try {
76
+ var res = await fetch(url, {
77
+ method: "GET",
78
+ credentials: "include",
79
+ headers
80
+ });
81
+ var reply = await res.text();
82
+ if (!res.ok) throw new Error(reply);
83
+ return reply ? JSON.parse(reply) : reply;
84
+ } catch (e) {
85
+ throw e;
86
+ }
85
87
  }
86
- /**
87
- * @hidden
88
- *
89
- * @param url The requested url
90
- * @param data Stringified json object
91
- *
92
- * @returns {Promise} superagent promise
93
- */
94
-
95
- function doPost(url, data, jwt) {
96
- const headers = {
88
+ async function doPost(url, data, jwt) {
89
+ var headers = {
97
90
  Accept: "application/json",
98
91
  "Content-Type": "application/json"
99
92
  };
100
93
  if (jwt) headers["X-SaaSquatch-User-Token"] = jwt;
101
- const request = superagent.post(url).send(data).set(headers);
102
- return thenableSuperagent(request).then(({
103
- text
104
- }) => text ? JSON.parse(text) : text, error => {
105
- let json;
106
94
 
107
- try {
108
- json = JSON.parse(error.response.text);
109
- } catch (e) {
110
- const out = error || e;
111
- throw out;
112
- }
113
-
114
- throw json;
115
- });
95
+ try {
96
+ var res = await fetch(url, {
97
+ method: "POST",
98
+ body: data,
99
+ headers
100
+ });
101
+ var reply = await res.text();
102
+ if (!res.ok) throw new Error(reply);
103
+ return reply ? JSON.parse(reply) : reply;
104
+ } catch (e) {
105
+ throw e;
106
+ }
116
107
  }
117
- function doPut(url, data, jwt) {
118
- const headers = {
108
+ async function doPut(url, data, jwt) {
109
+ var headers = {
119
110
  Accept: "application/json",
120
111
  "Content-Type": "application/json",
121
112
  "X-SaaSquatch-Referrer": window ? window.location.href : ""
122
113
  };
123
114
  if (jwt) headers["X-SaaSquatch-User-Token"] = jwt;
124
- const request = superagent.put(url).withCredentials().send(data).set(headers);
125
- return thenableSuperagent(request).then(({
126
- text
127
- }) => text ? JSON.parse(text) : text, error => {
128
- let json;
129
115
 
130
- try {
131
- json = JSON.parse(error.response.text);
132
- } catch (e) {
133
- const out = error || e;
134
- throw out;
135
- }
136
-
137
- throw json;
138
- });
139
- }
140
- /**
141
- * Avoids using superagent's built in `then` method because that relies on a global promise object being valid.
142
- *
143
- * Instead, thanks to babel the promise used in this function should be our custom sandboxed polyfill
144
- */
145
-
146
- function thenableSuperagent(request) {
147
- return new Promise((innerResolve, innerReject) => {
148
- request.on("error", innerReject);
149
- request.end((err, res) => {
150
- if (err) innerReject(err);else innerResolve(res);
116
+ try {
117
+ var res = await fetch(url, {
118
+ headers,
119
+ method: "PUT",
120
+ credentials: "include",
121
+ body: data
151
122
  });
152
- });
153
- }
154
-
155
- function includes(string, search, start) {
156
-
157
- if (typeof start !== "number") {
158
- start = 0;
159
- }
160
-
161
- if (start + search.length > string.length) {
162
- return false;
163
- } else {
164
- return string.indexOf(search, start) !== -1;
123
+ var reply = await res.text();
124
+ if (!res.ok) throw new Error(reply);
125
+ return reply ? JSON.parse(reply) : reply;
126
+ } catch (e) {
127
+ throw e;
165
128
  }
166
129
  }
167
130
 
168
- function hasProps(object, props) {
169
- if (!isObject$1(object)) return false;
170
- const keys = Object.keys(object);
171
- if (!Array.isArray(props)) return object.hasOwnProperty(props);
172
- const hasKeys = props.reduce((acc, cur) => {
173
- return acc && keys.indexOf(cur) >= 0;
174
- }, true);
175
- return hasKeys;
176
- }
177
- function isObject$1(x) {
178
- return typeof x === "object";
179
- }
180
- function assertProp(object, ...props) {
181
- props.forEach(p => {
182
- if (!hasProps(object, props)) throw new Error(p + " is required");
183
- });
184
- return true;
185
- }
186
- function validateConfig(raw) {
187
- if (!isObject$1(raw)) throw new Error("config must be an object");
188
- if (!hasProps(raw, "tenantAlias") || typeof raw.tenantAlias !== "string") throw new Error("tenantAlias not provided");
189
- const tenantAlias = raw.tenantAlias;
190
- const domain = hasProps(raw, "domain") && typeof raw.domain === "string" && raw.domain || "https://app.referralsaasquatch.com";
191
- const debug = hasProps(raw, "debug") && typeof raw.debug === "boolean" && raw.debug || false;
192
- const npmCdn = hasProps(raw, "npmCdn") && typeof raw.npmCdn === "string" && raw.npmCdn || "https://fast.ssqt.io/npm";
131
+ var DEFAULT_DOMAIN = "https://app.referralsaasquatch.com";
132
+ var DEFAULT_NPM_CDN = "https://fast.ssqt.io/npm";
133
+ function validateConfig(_raw) {
134
+ var _window$squatchConfig, _window$squatchConfig2, _window$squatchConfig3;
135
+
136
+ if (typeof _raw !== "object") throw new Error("config must be an object");
137
+ var raw = {
138
+ tenantAlias: (_raw == null ? void 0 : _raw["tenantAlias"]) || window.squatchTenant,
139
+ domain: (_raw == null ? void 0 : _raw["domain"]) || ((_window$squatchConfig = window.squatchConfig) == null ? void 0 : _window$squatchConfig.domain),
140
+ npmCdn: (_raw == null ? void 0 : _raw["npmCdn"]) || ((_window$squatchConfig2 = window.squatchConfig) == null ? void 0 : _window$squatchConfig2.npmCdn),
141
+ debug: (_raw == null ? void 0 : _raw["debug"]) || ((_window$squatchConfig3 = window.squatchConfig) == null ? void 0 : _window$squatchConfig3.debug)
142
+ };
143
+ if (typeof raw.tenantAlias !== "string") throw new Error("tenantAlias not provided");
144
+ var tenantAlias = raw.tenantAlias;
145
+ var domain = typeof raw.domain === "string" && raw.domain || DEFAULT_DOMAIN;
146
+ var debug = typeof raw.debug === "boolean" && raw.debug || false;
147
+ var npmCdn = typeof raw.npmCdn === "string" && raw.npmCdn || DEFAULT_NPM_CDN;
193
148
  return {
194
149
  tenantAlias,
195
150
  domain,
@@ -197,6 +152,9 @@ function validateConfig(raw) {
197
152
  npmCdn
198
153
  };
199
154
  }
155
+ function isObject$1(obj) {
156
+ return typeof obj === "object" && !Array.isArray(obj) && obj !== null;
157
+ }
200
158
  function validateLocale(locale) {
201
159
  if (locale && /^[a-z]{2}_(?:[A-Z]{2}|[0-9]{3})$/.test(locale)) {
202
160
  return locale;
@@ -204,8 +162,7 @@ function validateLocale(locale) {
204
162
  }
205
163
  function validateWidgetConfig(raw) {
206
164
  if (!isObject$1(raw)) throw new Error("Widget properties must be an object");
207
- if (!assertProp(raw, "user")) ; // TODO: This should be better type checked
208
-
165
+ if (!(raw != null && raw["user"])) throw new Error("Required properties missing.");
209
166
  return raw;
210
167
  }
211
168
  function validatePasswordlessConfig(raw) {
@@ -213,130 +170,120 @@ function validatePasswordlessConfig(raw) {
213
170
  return raw;
214
171
  }
215
172
 
216
- const RENDER_WIDGET_QUERY = `
217
- query renderWidget ($user: UserIdInput, $engagementMedium: UserEngagementMedium, $widgetType: WidgetType, $locale: RSLocale) {
218
- renderWidget(user: $user, engagementMedium: $engagementMedium, widgetType: $widgetType, locale: $locale) {
219
- template
220
- user {
221
- id
222
- accountId
223
- }
224
- jsOptions
225
- widgetConfig {
226
- values
227
- }
228
- }
229
- }
230
- `;
173
+ 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";
231
174
 
232
- /**
233
- *
234
- * The WidgetApi class is a wrapper around the Widget Endpoints of the SaaSquatch REST API.
235
- *
175
+ /**
176
+ *
177
+ * The WidgetApi class is a wrapper around the Widget Endpoints of the SaaSquatch REST API.
178
+ *
236
179
  */
237
180
 
238
181
  class WidgetApi {
239
- /**
240
- * Initialize a new {@link WidgetApi} instance.
241
- *
242
- * @param {ConfigOptions} config Config details
243
- *
244
- * @example <caption>Browser example</caption>
245
- * var squatchApi = new squatch.WidgetApi({tenantAlias:'test_12b5bo1b25125'});
246
- *
247
- * @example <caption>Browserify/Webpack example</caption>
248
- * var WidgetApi = require('@saasquatch/squatch-js').WidgetApi;
249
- * var squatchApi = new WidgetApi({tenantAlias:'test_12b5bo1b25125'});
250
- *
251
- * @example <caption>Babel+Browserify/Webpack example</caption>
252
- * import {WidgetApi} from '@saasquatch/squatch-js';
253
- * let squatchApi = new WidgetApi({tenantAlias:'test_12b5bo1b25125'});
182
+ // TODO: Support using new window variables for initialisation
183
+
184
+ /**
185
+ * Initialize a new {@link WidgetApi} instance.
186
+ *
187
+ * @param {ConfigOptions} config Config details
188
+ *
189
+ * @example <caption>Browser example</caption>
190
+ * var squatchApi = new squatch.WidgetApi({tenantAlias:'test_12b5bo1b25125'});
191
+ *
192
+ * @example <caption>Browserify/Webpack example</caption>
193
+ * var WidgetApi = require('@saasquatch/squatch-js').WidgetApi;
194
+ * var squatchApi = new WidgetApi({tenantAlias:'test_12b5bo1b25125'});
195
+ *
196
+ * @example <caption>Babel+Browserify/Webpack example</caption>
197
+ * import {WidgetApi} from '@saasquatch/squatch-js';
198
+ * let squatchApi = new WidgetApi({tenantAlias:'test_12b5bo1b25125'});
254
199
  */
255
200
  constructor(config) {
256
- const raw = config; // Flags that we need to validate anything we use from this type
257
-
258
- const clean = validateConfig(raw);
201
+ this.tenantAlias = void 0;
202
+ this.domain = void 0;
203
+ this.npmCdn = void 0;
204
+ var raw = config;
205
+ var clean = validateConfig(raw);
259
206
  this.tenantAlias = clean.tenantAlias;
260
207
  this.domain = clean.domain;
261
208
  this.npmCdn = clean.npmCdn;
262
209
  }
263
- /**
264
- * Creates/upserts user.
265
- *
266
- * @param {Object} params Parameters for request
267
- * @param {Object?} params.user The user details
268
- * @param {string} params.user.id The user id
269
- * @param {string} params.user.accountId The user account id
270
- * @param {WidgetType} params.widgetType The content of the widget.
271
- * @param {EngagementMedium?} params.engagementMedium How to display the widget.
272
- * @param {string?} params.jwt the JSON Web Token (JWT) that is used
273
- * to validate the data (can be disabled)
274
- *
275
- * @return {Promise} string if true, with the widget template, jsOptions and user details.
210
+ /**
211
+ * Creates/upserts user.
212
+ *
213
+ * @param {Object} params Parameters for request
214
+ * @param {Object?} params.user The user details
215
+ * @param {string} params.user.id The user id
216
+ * @param {string} params.user.accountId The user account id
217
+ * @param {WidgetType} params.widgetType The content of the widget.
218
+ * @param {EngagementMedium?} params.engagementMedium How to display the widget.
219
+ * @param {string?} params.jwt the JSON Web Token (JWT) that is used
220
+ * to validate the data (can be disabled)
221
+ *
222
+ * @return {Promise} string if true, with the widget template, jsOptions and user details.
276
223
  */
277
224
 
278
225
 
279
226
  upsertUser(params) {
280
- const raw = params;
281
- const clean = validateWidgetConfig(raw);
282
- const {
227
+ var raw = params;
228
+ var clean = validateWidgetConfig(raw);
229
+ var {
283
230
  widgetType,
284
231
  engagementMedium = "POPUP",
285
232
  jwt,
286
233
  user
287
234
  } = clean;
288
- const tenantAlias = encodeURIComponent(this.tenantAlias);
289
- const accountId = encodeURIComponent(user.accountId);
290
- const userId = encodeURIComponent(user.id);
235
+ var tenantAlias = encodeURIComponent(this.tenantAlias);
236
+ var accountId = encodeURIComponent(user.accountId);
237
+ var userId = encodeURIComponent(user.id);
291
238
 
292
- const optionalParams = _buildParams({
239
+ var optionalParams = _buildParams({
293
240
  widgetType,
294
241
  engagementMedium
295
242
  });
296
243
 
297
- const path = `/api/v1/${tenantAlias}/widget/account/${accountId}/user/${userId}/upsert${optionalParams}`;
298
- const url = this.domain + path;
299
- const cookies = Cookies.get("_saasquatch");
244
+ var path = "/api/v1/" + tenantAlias + "/widget/account/" + accountId + "/user/" + userId + "/upsert" + optionalParams;
245
+ var url = this.domain + path;
246
+ var cookies = (Cookies || window.Cookies).get("_saasquatch");
300
247
  if (cookies) user["cookies"] = cookies;
301
248
  return doPut(url, JSON.stringify(user), jwt);
302
249
  }
303
- /**
304
- * Description here.
305
- *
306
- * @param {Object} params Parameters for request
307
- * @param {Object} params.user The user details
308
- * @param {string} params.user.id The user id
309
- * @param {string} params.user.accountId The user account id
310
- * @param {WidgetType} params.widgetType The content of the widget.
311
- * @param {EngagementMedium} params.engagementMedium How to display the widget.
312
- * @param {string} params.jwt the JSON Web Token (JWT) that is used
313
- * to validate the data (can be disabled)
314
- * @return {Promise} template html if true.
250
+ /**
251
+ * Description here.
252
+ *
253
+ * @param {Object} params Parameters for request
254
+ * @param {Object} params.user The user details
255
+ * @param {string} params.user.id The user id
256
+ * @param {string} params.user.accountId The user account id
257
+ * @param {WidgetType} params.widgetType The content of the widget.
258
+ * @param {EngagementMedium} params.engagementMedium How to display the widget.
259
+ * @param {string} params.jwt the JSON Web Token (JWT) that is used
260
+ * to validate the data (can be disabled)
261
+ * @return {Promise} template html if true.
315
262
  */
316
263
 
317
264
 
318
265
  render(params) {
319
266
  var _clean$locale;
320
267
 
321
- const raw = params;
322
- const clean = validatePasswordlessConfig(raw);
323
- const {
268
+ var raw = params;
269
+ var clean = validatePasswordlessConfig(raw);
270
+ var {
324
271
  widgetType,
325
272
  engagementMedium = "POPUP",
326
273
  jwt,
327
274
  user
328
275
  } = clean;
329
- const tenantAlias = encodeURIComponent(this.tenantAlias);
330
- const accountId = user ? encodeURIComponent(user.accountId) : null;
331
- const userId = user ? encodeURIComponent(user.id) : null;
332
- const locale = (_clean$locale = clean.locale) != null ? _clean$locale : validateLocale(navigator.language.replace(/\-/g, "_"));
333
- const path = `/api/v1/${tenantAlias}/graphql`;
334
- const url = this.domain + path;
276
+ var tenantAlias = encodeURIComponent(this.tenantAlias);
277
+ var accountId = user ? encodeURIComponent(user.accountId) : null;
278
+ var userId = user ? encodeURIComponent(user.id) : null;
279
+ var locale = (_clean$locale = clean.locale) != null ? _clean$locale : validateLocale(navigator.language.replace(/\-/g, "_"));
280
+ var path = "/api/v1/" + tenantAlias + "/graphql";
281
+ var url = this.domain + path;
335
282
  return new Promise(async (resolve, reject) => {
336
283
  try {
337
- var _res$body, _res$body$data;
284
+ var _res$data;
338
285
 
339
- const res = await doQuery(url, RENDER_WIDGET_QUERY, {
286
+ var res = await doQuery(url, RENDER_WIDGET_QUERY, {
340
287
  user: userId && accountId ? {
341
288
  id: userId,
342
289
  accountId
@@ -345,56 +292,27 @@ class WidgetApi {
345
292
  widgetType,
346
293
  locale
347
294
  }, jwt);
348
- resolve(res == null ? void 0 : (_res$body = res.body) == null ? void 0 : (_res$body$data = _res$body.data) == null ? void 0 : _res$body$data.renderWidget);
295
+ resolve(res == null ? void 0 : (_res$data = res.data) == null ? void 0 : _res$data.renderWidget);
349
296
  } catch (e) {
350
297
  reject(e);
351
298
  }
352
299
  });
353
300
  }
354
- /**
355
- * An API call to send out referral invites to contacts
356
- *
357
- * @param {Object} params Parameters for request
358
- * @param {Array} params.emailList The list of recipients to send to
359
- * @param {string} params.userId The user id
360
- * @param {string} params.accountId The user account id
361
- * @param {string} params.tenantAlias The tenant alias
362
- *
363
- * @return {Promise} an object containing total accepted / rejected emails send or error
364
- */
365
-
366
-
367
- invite({
368
- emailList = [],
369
- userId,
370
- accountId,
371
- tenantAlias
372
- }) {
373
- const tenantAliasP = encodeURIComponent(tenantAlias);
374
- const path = `/api/v1/${tenantAliasP}/mail/referralinvite`;
375
- const url = this.domain + path;
376
- const request = {
377
- sendingAccountId: accountId,
378
- sendingUserId: userId,
379
- recipients: emailList
380
- };
381
- return doPost(url, JSON.stringify(request));
382
- }
383
- /**
384
- * Looks up the referral code of the current user, if there is any.
385
- *
386
- * @return {Promise<ReferralCookie>} code referral code if true.
301
+ /**
302
+ * Looks up the referral code of the current user, if there is any.
303
+ *
304
+ * @return {Promise<ReferralCookie>} code referral code if true.
387
305
  */
388
306
 
389
307
 
390
308
  async squatchReferralCookie() {
391
- const tenantAlias = encodeURIComponent(this.tenantAlias);
309
+ var tenantAlias = encodeURIComponent(this.tenantAlias);
392
310
 
393
- const _saasquatch = Cookies.get("_saasquatch") || "";
311
+ var _saasquatch = (Cookies || window.Cookies).get("_saasquatch") || "";
394
312
 
395
- const cookie = _saasquatch ? `?cookies=${encodeURIComponent(_saasquatch)}` : ``;
396
- const url = `${this.domain}/a/${tenantAlias}/widgets/squatchcookiejson${cookie}`;
397
- const response = await doGet(url);
313
+ var cookie = _saasquatch ? "?cookies=" + encodeURIComponent(_saasquatch) : "";
314
+ var url = this.domain + "/a/" + tenantAlias + "/widgets/squatchcookiejson" + cookie;
315
+ var response = await doGet(url);
398
316
  return Promise.resolve(_extends({}, response, {
399
317
  encodedCookie: _saasquatch
400
318
  }));
@@ -402,84 +320,99 @@ class WidgetApi {
402
320
 
403
321
  } // builds a param string for widgets
404
322
 
405
- function _buildParams({
406
- widgetType,
407
- engagementMedium
408
- }) {
409
- const widgetTypeP = widgetType ? `?widgetType=${encodeURIComponent(widgetType)}` : ``;
410
- const engagementMediumP = `${widgetType ? "&" : "?"}engagementMedium=${encodeURIComponent(engagementMedium)}`;
411
- const optionalParams = widgetTypeP + engagementMediumP;
323
+ function _buildParams(_ref) {
324
+ var {
325
+ widgetType,
326
+ engagementMedium
327
+ } = _ref;
328
+ var widgetTypeP = widgetType ? "?widgetType=" + encodeURIComponent(widgetType) : "";
329
+ var engagementMediumP = (widgetType ? "&" : "?") + "engagementMedium=" + encodeURIComponent(engagementMedium);
330
+ var optionalParams = widgetTypeP + engagementMediumP;
412
331
  return optionalParams;
413
332
  }
414
333
 
415
334
  // @ts-check
416
- /**
417
- *
418
- * The AnalyticsApi class is a wrapper around the Analytics Endpoints of
419
- * the SaaSquatch REST API. Used to record Widget events.
420
- *
421
- * @hidden
335
+ /**
336
+ *
337
+ * The AnalyticsApi class is a wrapper around the Analytics Endpoints of
338
+ * the SaaSquatch REST API. Used to record Widget events.
339
+ *
340
+ * @hidden
422
341
  */
423
342
 
424
343
  class AnalyticsApi {
425
- /**
426
- * Initialize a new {@link AnalyticsApi} instance.
427
- *
428
- * @param {Object} config Config details
429
- * @param {string} [config.domain='https://app.referralsaasquatch.com'] The server domain.
430
- *
344
+ /**
345
+ * Initialize a new {@link AnalyticsApi} instance.
346
+ *
347
+ * @param {Object} config Config details
348
+ * @param {string} [config.domain='https://app.referralsaasquatch.com'] The server domain.
349
+ *
431
350
  */
432
351
  constructor(config) {
433
- const raw = config;
352
+ var _window$squatchConfig;
434
353
 
435
- if (hasProps(raw, "domain") && typeof raw.domain === "string") {
436
- this.domain = raw.domain;
437
- } else {
438
- this.domain = "https://app.referralsaasquatch.com";
439
- }
354
+ this.domain = void 0;
355
+ var raw = config;
356
+
357
+ var clean = _validateAnalyticsConfig(raw);
358
+
359
+ this.domain = (clean == null ? void 0 : clean["domain"]) || ((_window$squatchConfig = window.squatchConfig) == null ? void 0 : _window$squatchConfig.domain) || DEFAULT_DOMAIN;
440
360
  }
441
361
 
442
362
  pushAnalyticsLoadEvent(params) {
443
363
  if (!params.externalUserId || !params.externalAccountId) return;
444
- const tenantAlias = encodeURIComponent(params.tenantAlias);
445
- const accountId = encodeURIComponent(params.externalAccountId);
446
- const userId = encodeURIComponent(params.externalUserId);
447
- const engagementMedium = encodeURIComponent(params.engagementMedium);
448
- const programId = params.programId ? `&programId=${encodeURIComponent(params.programId)}` : ``;
449
- const path = `/a/${tenantAlias}/widgets/analytics/loaded?externalAccountId=${accountId}&externalUserId=${userId}&engagementMedium=${engagementMedium}${programId}`;
450
- const url = this.domain + path;
364
+ var tenantAlias = encodeURIComponent(params.tenantAlias);
365
+ var accountId = encodeURIComponent(params.externalAccountId);
366
+ var userId = encodeURIComponent(params.externalUserId);
367
+ var engagementMedium = encodeURIComponent(params.engagementMedium);
368
+ var programId = params.programId ? "&programId=" + encodeURIComponent(params.programId) : "";
369
+ var path = "/a/" + tenantAlias + "/widgets/analytics/loaded?externalAccountId=" + accountId + "&externalUserId=" + userId + "&engagementMedium=" + engagementMedium + programId;
370
+ var url = this.domain + path;
451
371
  return doPost(url, JSON.stringify({}));
452
372
  }
453
373
 
454
374
  pushAnalyticsShareClickedEvent(params) {
455
- const tenantAlias = encodeURIComponent(params.tenantAlias);
456
- const accountId = encodeURIComponent(params.externalAccountId);
457
- const userId = encodeURIComponent(params.externalUserId);
458
- const engagementMedium = encodeURIComponent(params.engagementMedium);
459
- const shareMedium = encodeURIComponent(params.shareMedium);
460
- const path = `/a/${tenantAlias}/widgets/analytics/shared?externalAccountId=${accountId}&externalUserId=${userId}&engagementMedium=${engagementMedium}&shareMedium=${shareMedium}`;
461
- const url = this.domain + path;
375
+ var tenantAlias = encodeURIComponent(params.tenantAlias);
376
+ var accountId = encodeURIComponent(params.externalAccountId);
377
+ var userId = encodeURIComponent(params.externalUserId);
378
+ var engagementMedium = encodeURIComponent(params.engagementMedium);
379
+ var shareMedium = encodeURIComponent(params.shareMedium);
380
+ var path = "/a/" + tenantAlias + "/widgets/analytics/shared?externalAccountId=" + accountId + "&externalUserId=" + userId + "&engagementMedium=" + engagementMedium + "&shareMedium=" + shareMedium;
381
+ var url = this.domain + path;
462
382
  return doPost(url, JSON.stringify({}));
463
383
  }
464
384
 
465
385
  }
466
386
 
387
+ function _validateAnalyticsConfig(raw) {
388
+ if (!isObject$1(raw)) throw new Error("'options' should be an object");
389
+ return raw;
390
+ }
391
+
467
392
  // @ts-check
468
393
  /** @hidden */
469
394
 
470
- const _log$7 = debug__default("squatch-js:widget");
471
- /*
472
- * The Widget class is the base class for the different widget types available
473
- *
474
- * Creates an `iframe` in which the html content of the widget gets embedded.
475
- * Uses element-resize-detector (https://github.com/wnr/element-resize-detector)
476
- * for listening to the height of the widget content and make the iframe responsive.
477
- *
395
+ var _log$7 = debug("squatch-js:widget");
396
+ /*
397
+ * The Widget class is the base class for the different widget types available
398
+ *
399
+ * Creates an `iframe` in which the html content of the widget gets embedded.
400
+ * Uses element-resize-detector (https://github.com/wnr/element-resize-detector)
401
+ * for listening to the height of the widget content and make the iframe responsive.
402
+ *
478
403
  */
479
404
 
480
405
 
481
406
  class Widget {
482
407
  constructor(params) {
408
+ this.type = void 0;
409
+ this.content = void 0;
410
+ this.analyticsApi = void 0;
411
+ this.widgetApi = void 0;
412
+ this.context = void 0;
413
+ this.npmCdn = void 0;
414
+ this.container = void 0;
415
+
483
416
  _log$7("widget initializing ...");
484
417
 
485
418
  this.content = params.content === "error" ? this._error(params.rsCode) : params.content;
@@ -489,12 +422,47 @@ class Widget {
489
422
  this.analyticsApi = new AnalyticsApi({
490
423
  domain: params.domain
491
424
  });
492
- this.frame = document.createElement("iframe");
493
- this.frame["squatchJsApi"] = this;
494
- this.frame.width = "100%";
495
- this.frame.scrolling = "no";
496
- this.frame.setAttribute("style", "border: 0; background-color: none; width: 1px; min-width: 100%;");
497
425
  this.context = params.context;
426
+ this.container = params.container;
427
+ }
428
+
429
+ _findElement() {
430
+ var element;
431
+
432
+ if (typeof this.container === "string") {
433
+ // selector is a string
434
+ element = document.querySelector(this.container);
435
+
436
+ _log$7("loading widget with selector", element); // selector is an HTML element
437
+
438
+ } else if (this.container instanceof HTMLElement) {
439
+ element = this.container;
440
+
441
+ _log$7("loading widget with container", element); // garbage container found
442
+
443
+ } else if (this.container) {
444
+ element = null;
445
+
446
+ _log$7("container must be an HTMLElement or string", this.container); // find element on page
447
+
448
+ } else {
449
+ element = document.querySelector("#squatchembed") || document.querySelector(".squatchembed");
450
+
451
+ _log$7("loading widget with default selector", element);
452
+ }
453
+
454
+ if (!(element instanceof HTMLElement)) throw new Error("element with selector '" + (this.container || "#squatchembed or .squatchembed") + "' not found.'");
455
+ return element;
456
+ }
457
+
458
+ _createFrame() {
459
+ var frame = document.createElement("iframe");
460
+ frame["squatchJsApi"] = this;
461
+ frame.width = "100%";
462
+ frame.src = "about:blank";
463
+ frame.scrolling = "no";
464
+ frame.setAttribute("style", "border: 0; background-color: none; width: 1px; min-width: 100%;");
465
+ return frame;
498
466
  }
499
467
 
500
468
  _loadEvent(sqh) {
@@ -506,13 +474,10 @@ class Widget {
506
474
  throw new Error("Widget Load event identity property is not an object");
507
475
  }
508
476
 
509
- let params;
510
-
511
- if (hasProps(sqh, "programId")) {
512
- if (!hasProps(sqh, ["tenantAlias", "accountId", "userId", "engagementMedium"])) {
513
- throw new Error("Widget Load event missing required properties");
514
- }
477
+ var params;
515
478
 
479
+ if ("programId" in sqh) {
480
+ if (!sqh.tenantAlias || !sqh.accountId || !sqh.userId || !sqh.engagementMedium) throw new Error("Widget Load event missing required properties");
516
481
  params = {
517
482
  tenantAlias: sqh.tenantAlias,
518
483
  externalAccountId: sqh.accountId,
@@ -521,7 +486,7 @@ class Widget {
521
486
  programId: sqh.programId
522
487
  };
523
488
  } else {
524
- const {
489
+ var {
525
490
  analytics,
526
491
  mode
527
492
  } = sqh;
@@ -534,9 +499,9 @@ class Widget {
534
499
  }
535
500
 
536
501
  (_this$analyticsApi$pu = this.analyticsApi.pushAnalyticsLoadEvent(params)) == null ? void 0 : _this$analyticsApi$pu.then(response => {
537
- _log$7(`${params.engagementMedium} loaded event recorded.`);
502
+ _log$7(params.engagementMedium + " loaded event recorded.");
538
503
  }).catch(ex => {
539
- _log$7(new Error(`pushAnalyticsLoadEvent() ${ex}`));
504
+ _log$7(new Error("pushAnalyticsLoadEvent() " + ex));
540
505
  });
541
506
  }
542
507
 
@@ -549,80 +514,44 @@ class Widget {
549
514
  engagementMedium: sqh.mode.widgetMode,
550
515
  shareMedium: medium
551
516
  }).then(response => {
552
- _log$7(`${sqh.mode.widgetMode} share ${medium} event recorded. ${response}`);
517
+ _log$7(sqh.mode.widgetMode + " share " + medium + " event recorded. " + response);
553
518
  }).catch(ex => {
554
- _log$7(new Error(`pushAnalyticsLoadEvent() ${ex}`));
519
+ _log$7(new Error("pushAnalyticsLoadEvent() " + ex));
555
520
  });
556
521
  }
557
- }
522
+ } // TODO: CA: Refactor how error templates are shown
558
523
 
559
- _inviteContacts(sqh, emailList) {
560
- if (sqh) {
561
- this.widgetApi.invite({
562
- tenantAlias: sqh.analytics.attributes.tenant,
563
- accountId: sqh.analytics.attributes.accountId,
564
- userId: sqh.analytics.attributes.userId,
565
- emailList
566
- }).then(response => {
567
- _log$7(`Sent email invites to share ${emailList}. ${response}`);
568
- }).catch(ex => {
569
- _log$7(new Error(`invite() ${ex}`));
570
- });
524
+
525
+ _error(rs, mode, style) {
526
+ if (mode === void 0) {
527
+ mode = "modal";
528
+ }
529
+
530
+ if (style === void 0) {
531
+ style = "";
571
532
  }
572
- }
573
533
 
574
- _error(rs, mode = "modal", style = "") {
575
- const errorTemplate = `<!DOCTYPE html>
576
- <!--[if IE 7]><html class="ie7 oldie" lang="en"><![endif]-->
577
- <!--[if IE 8]><html class="ie8 oldie" lang="en"><![endif]-->
578
- <!--[if gt IE 8]><!--><html lang="en"><!--<![endif]-->
579
- <head>
580
- <link rel="stylesheet" media="all" href="https://fast.ssqt.io/assets/css/widget/errorpage.css">
581
- <style>
582
- ${style}
583
- </style>
584
- </head>
585
- <body>
586
-
587
- <div class="squatch-container ${mode}" style="width:100%">
588
- <div class="errorheader">
589
- <button type="button" class="close" onclick="window.frameElement.squatchJsApi.close();">&times;</button>
590
- <p class="errortitle">Error</p>
591
- </div>
592
- <div class="errorbody">
593
- <div class="sadface"><img src="https://fast.ssqt.io/assets/images/face.png"></div>
594
- <h4>Our referral program is temporarily unavailable.</h4><br>
595
- <p>Please reload the page or check back later.</p>
596
- <p>If the persists please contact our support team.</p>
597
- <br>
598
- <br>
599
- <div class="right-align errtxt">
600
- Error Code: ${rs}
601
- </div>
602
- </div>
603
- </div>
604
- </body>
605
- </html>`;
534
+ var errorTemplate = "<!DOCTYPE html>\n <!--[if IE 7]><html class=\"ie7 oldie\" lang=\"en\"><![endif]-->\n <!--[if IE 8]><html class=\"ie8 oldie\" lang=\"en\"><![endif]-->\n <!--[if gt IE 8]><!--><html lang=\"en\"><!--<![endif]-->\n <head>\n <link rel=\"stylesheet\" media=\"all\" href=\"https://fast.ssqt.io/assets/css/widget/errorpage.css\">\n <style>\n " + style + "\n </style>\n </head>\n <body>\n\n <div class=\"squatch-container " + mode + "\" style=\"width:100%\">\n <div class=\"errorheader\">\n <button type=\"button\" class=\"close\" onclick=\"window.frameElement.squatchJsApi.close();\">&times;</button>\n <p class=\"errortitle\">Error</p>\n </div>\n <div class=\"errorbody\">\n <div class=\"sadface\"><img src=\"https://fast.ssqt.io/assets/images/face.png\"></div>\n <h4>Our referral program is temporarily unavailable.</h4><br>\n <p>Please reload the page or check back later.</p>\n <p>If the persists please contact our support team.</p>\n <br>\n <br>\n <div class=\"right-align errtxt\">\n Error Code: " + rs + "\n </div>\n </div>\n </div>\n </body>\n </html>";
606
535
  return errorTemplate;
607
536
  }
608
537
 
609
- async _findInnerContainer() {
610
- const {
538
+ async _findInnerContainer(frame) {
539
+ var {
611
540
  contentWindow
612
- } = this.frame;
541
+ } = frame;
613
542
  if (!contentWindow) throw new Error("Squatch.js frame inner frame is empty");
614
- const frameDoc = contentWindow.document;
543
+ var frameDoc = contentWindow.document;
615
544
 
616
545
  function search() {
617
- const containers = frameDoc.getElementsByTagName("sqh-global-container");
618
- const legacyContainers = frameDoc.getElementsByClassName("squatch-container");
619
- const fallback = containers.length > 0 ? containers[0] : legacyContainers.length > 0 ? legacyContainers[0] : null;
546
+ var containers = frameDoc.getElementsByTagName("sqh-global-container");
547
+ var legacyContainers = frameDoc.getElementsByClassName("squatch-container");
548
+ var fallback = containers.length > 0 ? containers[0] : legacyContainers.length > 0 ? legacyContainers[0] : null;
620
549
  return fallback;
621
550
  }
622
551
 
623
- let found = null;
552
+ var found = null;
624
553
 
625
- for (let i = 0; i < 5; i++) {
554
+ for (var i = 0; i < 5; i++) {
626
555
  found = search();
627
556
  if (found) break;
628
557
  await delay(100);
@@ -634,28 +563,34 @@ class Widget {
634
563
 
635
564
  return found;
636
565
  }
566
+ /**
567
+ * Reloads the current widget, makes updated request to API and renders result.
568
+ * Primarily for Classic widgets with registration
569
+ * @param param0 Form field values
570
+ * @param jwt JWT for API authentication
571
+ */
572
+
637
573
 
638
- reload({
639
- email,
640
- firstName,
641
- lastName
642
- }, jwt) {
643
- const frameWindow = this.frame.contentWindow;
644
- const engagementMedium = this.context.engagementMedium || "POPUP";
574
+ reload(frame, _ref, jwt) {
575
+ var {
576
+ email,
577
+ firstName,
578
+ lastName
579
+ } = _ref;
580
+ var frameWindow = frame.contentWindow;
581
+ var engagementMedium = this.context.engagementMedium || "POPUP";
645
582
 
646
583
  if (!frameWindow) {
647
584
  throw new Error("Frame needs a content window");
648
585
  }
649
586
 
650
- const frameDoc = frameWindow.document;
651
- let response;
587
+ var response;
652
588
 
653
589
  if (this.context.type === "upsert") {
654
- let userObj = {
590
+ var userObj = {
655
591
  email: email || null,
656
592
  firstName: firstName || null,
657
593
  lastName: lastName || null,
658
- // FIXME: Double check this
659
594
  id: this.context.user.id,
660
595
  accountId: this.context.user.accountId
661
596
  };
@@ -676,66 +611,80 @@ class Widget {
676
611
  throw new Error("can't reload an error widget");
677
612
  }
678
613
 
679
- response.then(({
680
- template
681
- }) => {
682
- if (template) {
683
- this.content = template;
684
- const showStatsBtn = frameDoc.createElement("button");
685
- const registerForm = frameDoc.getElementsByClassName("squatch-register")[0];
614
+ response.then(_ref2 => {
615
+ var {
616
+ template
617
+ } = _ref2;
686
618
 
687
- if (registerForm) {
688
- showStatsBtn.className = "btn btn-primary";
689
- showStatsBtn.id = "show-stats-btn";
690
- showStatsBtn.textContent = this.type === "REFERRER_WIDGET" ? "Show Stats" : "Show Reward";
691
- const widgetStyle = engagementMedium === "POPUP" ? "margin-top: 10px; max-width: 130px; width: 100%;" : "margin-top: 10px;";
692
- showStatsBtn.setAttribute("style", widgetStyle);
693
-
694
- showStatsBtn.onclick = () => {
695
- this.load(); // @ts-ignore -- open exists in the PopupWidget, so this call will always exist when it's called.
696
-
697
- engagementMedium === "POPUP" && this.open();
698
- }; // @ts-ignore -- expect register form to be a stylable element
619
+ if (template) {
620
+ this.content = template; // Support for classic widget registration forms
699
621
 
622
+ this.__deprecated__register(frame, {
623
+ email,
624
+ engagementMedium
625
+ }, () => {
626
+ this.load(frame); // @ts-ignore -- open exists in the PopupWidget, so this call will always exist when it's called.
700
627
 
701
- registerForm.style.paddingTop = "30px";
702
- registerForm.innerHTML = `<p><strong>${email}</strong><br>Has been successfully registered</p>`;
703
- registerForm.appendChild(showStatsBtn);
704
- }
628
+ engagementMedium === "POPUP" && this.open(frame);
629
+ });
705
630
  }
706
- }).catch(({
707
- message
708
- }) => {
709
- _log$7(`${message}`);
631
+ }).catch(_ref3 => {
632
+ var {
633
+ message
634
+ } = _ref3;
635
+
636
+ _log$7("" + message);
710
637
  });
711
638
  }
712
639
 
640
+ __deprecated__register(frame, params, onClick) {
641
+ var frameWindow = frame.contentWindow;
642
+ var frameDoc = frameWindow.document;
643
+ var showStatsBtn = frameDoc.createElement("button");
644
+ var registerForm = frameDoc.getElementsByClassName("squatch-register")[0];
645
+
646
+ if (registerForm) {
647
+ showStatsBtn.className = "btn btn-primary";
648
+ showStatsBtn.id = "show-stats-btn";
649
+ showStatsBtn.textContent = this.type === "REFERRER_WIDGET" ? "Show Stats" : "Show Reward";
650
+ var widgetStyle = params.engagementMedium === "POPUP" ? "margin-top: 10px; max-width: 130px; width: 100%;" : "margin-top: 10px;";
651
+ showStatsBtn.setAttribute("style", widgetStyle);
652
+ showStatsBtn.onclick = onClick; // @ts-ignore -- expect register form to be a stylable element
653
+
654
+ registerForm.style.paddingTop = "30px";
655
+ registerForm.innerHTML = "<p><strong>" + params.email + "</strong><br>Has been successfully registered</p>";
656
+ registerForm.appendChild(showStatsBtn);
657
+ }
658
+ }
659
+
713
660
  }
714
661
 
715
662
  function delay(duration) {
716
663
  return new Promise(function (resolve, reject) {
717
664
  setTimeout(function () {
718
- resolve();
665
+ resolve(() => {});
719
666
  }, duration);
720
667
  });
721
668
  }
722
669
 
723
- /*!
724
- * domready (c) Dustin Diaz 2014 - License MIT
725
- *
670
+ /*!
671
+ * domready (c) Dustin Diaz 2014 - License MIT
672
+ *
726
673
  */
727
674
  function domready(targetDoc, fn) {
728
- let fns = [];
729
- let listener;
730
- let doc = targetDoc;
731
- let hack = doc.documentElement.doScroll;
732
- let domContentLoaded = "DOMContentLoaded";
733
- let loaded = (hack ? /^loaded|^c/ : /^loaded|^i|^c/).test(doc.readyState);
675
+ var fns = [];
676
+ var listener;
677
+ var doc = targetDoc;
678
+ var hack = doc.documentElement.doScroll;
679
+ var domContentLoaded = "DOMContentLoaded";
680
+ var loaded = (hack ? /^loaded|^c/ : /^loaded|^i|^c/).test(doc.readyState);
734
681
  if (!loaded) doc.addEventListener(domContentLoaded, listener = () => {
735
682
  doc.removeEventListener(domContentLoaded, listener);
736
683
  loaded = true;
737
684
 
738
- while (listener = fns.shift()) listener();
685
+ while (listener = fns.shift()) {
686
+ listener();
687
+ }
739
688
  }); // @ts-ignore
740
689
 
741
690
  return loaded ? setTimeout(fn, 0) : fns.push(fn);
@@ -743,78 +692,55 @@ function domready(targetDoc, fn) {
743
692
 
744
693
  // @ts-check
745
694
 
746
- const _log$6 = debug__default("squatch-js:EMBEDwidget");
747
- /**
748
- * An EmbedWidget is displayed inline in part of your page.
749
- *
750
- * To create an EmbedWidget use {@link Widgets}
751
- *
695
+ var _log$6 = debug("squatch-js:EMBEDwidget");
696
+ /**
697
+ * An EmbedWidget is displayed inline in part of your page.
698
+ *
699
+ * To create an EmbedWidget use {@link Widgets}
700
+ *
752
701
  */
753
702
 
754
703
 
755
704
  class EmbedWidget extends Widget {
756
705
  constructor(params, container) {
757
706
  super(params);
758
- let element;
759
-
760
- if (typeof container === "string") {
761
- // selector is a string
762
- element = document.querySelector(container);
763
-
764
- _log$6("loading widget with selector", element); // selector is an HTML element
765
-
766
- } else if (container instanceof HTMLElement) {
767
- element = container;
768
-
769
- _log$6("loading widget with container", element); // garbage container found
770
-
771
- } else if (container) {
772
- element = null;
773
-
774
- _log$6("container must be an HTMLElement or string", container); // find element on page
775
-
776
- } else {
777
- element = document.querySelector("#squatchembed") || document.querySelector(".squatchembed");
778
-
779
- _log$6("loading widget with default selector", element);
780
- }
781
-
782
- if (!(element instanceof HTMLElement)) throw new Error(`element with selector '${container}' not found.'`);
783
- this.element = element;
707
+ this.show = this.open;
708
+ this.hide = this.close;
784
709
  }
785
710
 
786
- async load() {
787
- if (this.context.container) {
788
- this.element.style.visibility = "hidden";
789
- this.element.style.height = "0";
790
- this.element.style["overflow-y"] = "hidden"; // Widget reloaded - replace existing element
711
+ async load(frame) {
712
+ var element = this._findElement();
791
713
 
792
- if (this.element.firstChild) {
793
- this.element.replaceChild(this.frame, this.element.firstChild); // Add iframe for the first time
714
+ if (this.container) {
715
+ if (element.shadowRoot) {
716
+ element.shadowRoot.appendChild(frame);
717
+ } // Widget reloaded - replace existing element
718
+ else if (element.firstChild) {
719
+ element.replaceChild(frame, element.firstChild); // Add iframe for the first time
794
720
  } else {
795
- this.element.appendChild(this.frame);
721
+ element.appendChild(frame);
796
722
  }
797
- } else if (!this.element.firstChild || this.element.firstChild.nodeName === "#text") {
798
- this.element.appendChild(this.frame);
723
+ } else if (!element.firstChild || element.firstChild.nodeName === "#text") {
724
+ element.appendChild(frame);
799
725
  }
800
726
 
801
- const {
727
+ var {
802
728
  contentWindow
803
- } = this.frame;
729
+ } = frame;
804
730
 
805
731
  if (!contentWindow) {
806
732
  throw new Error("Frame needs a content window");
807
733
  }
808
734
 
809
- const frameDoc = contentWindow.document;
735
+ var frameDoc = contentWindow.document;
810
736
  frameDoc.open();
811
737
  frameDoc.write(this.content);
812
- frameDoc.write(`<script src="${this.npmCdn}/resize-observer-polyfill@1.5.x"></script>`);
738
+ frameDoc.write("<script src=\"" + this.npmCdn + "/resize-observer-polyfill@1.5.x\"></script>");
813
739
  frameDoc.close();
814
740
  domready(frameDoc, async () => {
815
- const _sqh = contentWindow.squatch || contentWindow.widgetIdent;
741
+ var _sqh = contentWindow.squatch || contentWindow.widgetIdent;
816
742
 
817
- const ctaElement = frameDoc.getElementById("cta");
743
+ var ctaElement = frameDoc.getElementById("cta");
818
744
 
819
745
  if (ctaElement) {
820
746
  if (!ctaElement.parentNode) {
@@ -825,21 +751,20 @@ class EmbedWidget extends Widget {
825
751
  } // @ts-ignore -- number will be cast to string by browsers
826
752
 
827
753
 
828
- this.frame.height = frameDoc.body.scrollHeight; // Adjust frame height when size of body changes
829
- // @ts-ignore
754
+ frame.height = frameDoc.body.scrollHeight; // Adjust frame height when size of body changes
830
755
 
831
- const ro = new contentWindow["ResizeObserver"](entries => {
832
- for (const entry of entries) {
833
- const {
756
+ var ro = new contentWindow["ResizeObserver"](entries => {
757
+ for (var entry of entries) {
758
+ var {
834
759
  height
835
760
  } = entry.contentRect; // @ts-ignore -- number will be cast to string by browsers
836
761
 
837
- this.frame.height = height;
762
+ frame.height = height;
838
763
  }
839
764
  });
840
- ro.observe(await this._findInnerContainer()); // Regular load - trigger event
765
+ ro.observe(await this._findInnerContainer(frame)); // Regular load - trigger event
841
766
 
842
- if (!this.context.container) {
767
+ if (!this.container) {
843
768
  this._loadEvent(_sqh);
844
769
 
845
770
  _log$6("loaded");
@@ -848,32 +773,46 @@ class EmbedWidget extends Widget {
848
773
  } // Un-hide if element is available and refresh data
849
774
 
850
775
 
851
- open() {
852
- var _this$frame, _this$frame$contentDo, _this$frame2, _this$frame2$contentW, _this$frame3, _this$frame3$contentW;
776
+ open(frame) {
777
+ var _frame$contentDocumen, _frame$contentWindow, _frame$contentWindow2;
778
+
779
+ if (!frame) return _log$6("no target element to open");
780
+
781
+ var element = this._findElement();
853
782
 
854
- if (!this.frame) return _log$6("no target element to open");
855
- this.element.style.visibility = "unset";
856
- this.element.style.height = "auto";
857
- this.element.style["overflow-y"] = "auto";
858
- (_this$frame = this.frame) == null ? void 0 : (_this$frame$contentDo = _this$frame.contentDocument) == null ? void 0 : _this$frame$contentDo.dispatchEvent(new CustomEvent("sq:refresh"));
783
+ element.style.visibility = "unset";
784
+ element.style.height = "auto";
785
+ element.style["overflow-y"] = "auto";
786
+ frame == null ? void 0 : (_frame$contentDocumen = frame.contentDocument) == null ? void 0 : _frame$contentDocumen.dispatchEvent(new CustomEvent("sq:refresh"));
859
787
 
860
- const _sqh = ((_this$frame2 = this.frame) == null ? void 0 : (_this$frame2$contentW = _this$frame2.contentWindow) == null ? void 0 : _this$frame2$contentW.squatch) || ((_this$frame3 = this.frame) == null ? void 0 : (_this$frame3$contentW = _this$frame3.contentWindow) == null ? void 0 : _this$frame3$contentW.widgetIdent);
788
+ 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);
861
789
 
862
790
  this._loadEvent(_sqh);
863
791
 
864
792
  _log$6("loaded");
865
793
  }
866
794
 
867
- close() {
868
- if (!this.frame) return _log$6("no target element to close");
869
- this.element.style.visibility = "hidden";
870
- this.element.style.height = "0";
871
- this.element.style["overflow-y"] = "hidden";
795
+ close(frame) {
796
+ if (!frame) return _log$6("no target element to close");
797
+
798
+ var element = this._findElement();
799
+
800
+ element.style.visibility = "hidden";
801
+ element.style.height = "0";
802
+ element.style["overflow-y"] = "hidden";
872
803
 
873
804
  _log$6("Embed widget closed");
874
805
  }
875
806
 
876
- _error(rs, mode = "embed", style = "") {
807
+ _error(rs, mode, style) {
808
+ if (mode === void 0) {
809
+ mode = "embed";
810
+ }
811
+
812
+ if (style === void 0) {
813
+ style = "";
814
+ }
815
+
877
816
  return super._error(rs, mode, style);
878
817
  }
879
818
 
@@ -881,78 +820,117 @@ class EmbedWidget extends Widget {
881
820
 
882
821
  // @ts-check
883
822
 
884
- const _log$5 = debug__default("squatch-js:POPUPwidget");
885
- /**
886
- * The PopupWidget is used to display popups (also known as "Modals").
887
- * Popups widgets are rendered on top of other elements in a page.
888
- *
889
- * To create a PopupWidget use {@link Widgets}
890
- *
891
- */
823
+ var _log$5 = debug("squatch-js:POPUPwidget");
892
824
 
825
+ var popupId = 0;
826
+ /**
827
+ * The PopupWidget is used to display popups (also known as "Modals").
828
+ * Popups widgets are rendered on top of other elements in a page.
829
+ *
830
+ * To create a PopupWidget use {@link Widgets}
831
+ *
832
+ */
893
833
 
894
834
  class PopupWidget extends Widget {
895
- constructor(params, trigger = ".squatchpop") {
835
+ constructor(params, trigger) {
836
+ if (trigger === void 0) {
837
+ trigger = ".squatchpop";
838
+ }
839
+
896
840
  super(params);
841
+ this.trigger = void 0;
842
+ this.id = void 0;
843
+ this.show = this.open;
844
+ this.hide = this.close;
845
+ this.trigger = trigger;
846
+
847
+ if (this.container) {
848
+ this.id = "squatchModal";
849
+ } else {
850
+ this.id = popupId === 0 ? "squatchModal" : "squatchModal__" + popupId;
851
+ popupId = popupId + 1;
852
+ }
853
+
854
+ document.head.insertAdjacentHTML("beforeend", "<style>#" + this.id + "::-webkit-scrollbar { display: none; }</style>");
855
+ }
856
+
857
+ _initialiseCTA(frame) {
858
+ var triggerElement;
897
859
 
898
860
  try {
899
- this.triggerElement
861
+ triggerElement
900
862
  /* HTMLButton */
901
- = document.querySelector(trigger);
902
- if (trigger && !this.triggerElement) _log$5("No element found with trigger selector", trigger);
863
+ = document.querySelector(this.trigger);
864
+ if (this.trigger && !triggerElement) _log$5("No element found with trigger selector", this.trigger);
903
865
  } catch (_unused) {
904
- _log$5("Not a valid selector", trigger);
866
+ _log$5("Not a valid selector", this.trigger);
905
867
  } // Trigger is optional
906
868
 
907
869
 
908
- if (this.triggerElement) {
909
- this.triggerElement.onclick = () => {
910
- this.open();
870
+ if (triggerElement) {
871
+ triggerElement.onclick = () => {
872
+ this.open(frame);
911
873
  };
912
- } // If widget is loaded with CTA, look for a 'squatchpop' element to use
874
+ }
875
+
876
+ var element = this._findElement(); // If widget is loaded with CTA, look for a 'squatchpop' element to use
913
877
  // that element as a trigger as well.
914
878
 
915
879
 
916
- this.triggerWhenCTA = document.querySelector(".squatchpop");
880
+ var triggerWhenCTA = element.querySelector(".squatchpop");
917
881
 
918
- if (trigger === "#cta" && this.triggerWhenCTA) {
919
- this.triggerWhenCTA.onclick = () => {
920
- this.open();
882
+ if (this.trigger === "#cta" && triggerWhenCTA) {
883
+ triggerWhenCTA.onclick = () => {
884
+ this.open(frame);
921
885
  };
922
886
  }
887
+ }
923
888
 
924
- this.popupdiv = document.createElement("div");
925
- this.popupdiv.id = "squatchModal";
926
- this.popupdiv.setAttribute("style", "display: none; position: fixed; z-index: 1; padding-top: 5%; left: 0; top: -2000px; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4);");
927
- document.head.insertAdjacentHTML("beforeend", `<style>#squatchModal::-webkit-scrollbar { display: none; }</style>`);
928
- this.popupcontent = document.createElement("div");
929
- this.popupcontent.setAttribute("style", "margin: auto; width: 80%; max-width: 500px; position: relative;");
889
+ _createPopupDialog() {
890
+ var dialog = document.createElement("dialog");
891
+ dialog.id = this.id;
892
+ dialog.setAttribute("style", "width: 100%; max-width: 500px; border: none; padding: 0;");
930
893
 
931
- this.popupdiv.onclick = event => {
932
- this._clickedOutside(event);
894
+ var onClick = e => {
895
+ if (e.target === dialog) dialog.close();
933
896
  };
897
+
898
+ dialog.addEventListener("click", onClick);
899
+ return dialog;
934
900
  }
935
901
 
936
- load() {
937
- this.popupdiv.appendChild(this.popupcontent);
938
- document.body.appendChild(this.popupdiv);
939
- this.popupcontent.appendChild(this.frame); //@ts-ignore -- will occasionally throw a null pointer exception at runtime
902
+ load(frame) {
903
+ this._initialiseCTA(frame);
904
+
905
+ var element = this._findElement();
906
+
907
+ var dialogParent = element.shadowRoot || element;
940
908
 
941
- const frameDoc = this.frame.contentWindow.document;
909
+ var dialog = this._createPopupDialog();
910
+
911
+ dialog.appendChild(frame);
912
+ dialogParent.appendChild(dialog);
913
+ var {
914
+ contentWindow
915
+ } = frame;
916
+
917
+ if (!contentWindow) {
918
+ throw new Error("Frame needs a content window");
919
+ }
920
+
921
+ var frameDoc = contentWindow.document;
942
922
  frameDoc.open();
943
923
  frameDoc.write(this.content);
944
- frameDoc.write(`<script src="${this.npmCdn}/resize-observer-polyfill@1.5.x"></script>`);
924
+ frameDoc.write("<script src=\"" + this.npmCdn + "/resize-observer-polyfill@1.5.x\"></script>");
945
925
  frameDoc.close();
946
926
 
947
927
  _log$5("Popup template loaded into iframe");
948
928
 
949
- this._setupResizeHandler();
929
+ this._setupResizeHandler(frame);
950
930
  }
951
931
 
952
- _setupResizeHandler() {
953
- const popupdiv = this.popupdiv;
954
- const frame = this.frame;
955
- const {
932
+ _setupResizeHandler(frame) {
933
+ var {
956
934
  contentWindow
957
935
  } = frame;
958
936
 
@@ -960,59 +938,46 @@ class PopupWidget extends Widget {
960
938
  throw new Error("Frame needs a content window");
961
939
  }
962
940
 
963
- const frameDoc = contentWindow.document; // Adjust frame height when size of body changes
941
+ var frameDoc = contentWindow.document; // Adjust frame height when size of body changes
964
942
 
965
943
  domready(frameDoc, async () => {
966
944
  frameDoc.body.style.overflowY = "hidden";
967
- popupdiv.style.visibility = "hidden";
968
- popupdiv.style.display = "block";
969
- frame.height = `${frameDoc.body.offsetHeight}px`; // Adjust frame height when size of body changes
945
+ frame.height = frameDoc.body.offsetHeight + "px"; // Adjust frame height when size of body changes
970
946
 
971
- const ro = new contentWindow["ResizeObserver"](entries => {
972
- for (const entry of entries) {
973
- const {
947
+ var ro = new contentWindow["ResizeObserver"](entries => {
948
+ for (var entry of entries) {
949
+ var {
974
950
  top,
975
951
  bottom
976
952
  } = entry.contentRect;
977
- const computedHeight = bottom + top;
953
+ var computedHeight = bottom + top;
978
954
  frame.height = computedHeight + ""; // Don't let anything else set the height of this element
979
955
 
980
- entry.target.style = ``;
981
-
982
- if (window.innerHeight > Number(frame.height)) {
983
- popupdiv.style.paddingTop = `${(window.innerHeight - Number(frame.height)) / 2}px`;
984
- } else {
985
- popupdiv.style.paddingTop = "5px";
986
- }
956
+ entry.target.style = "";
987
957
  }
988
958
  });
989
- ro.observe(await this._findInnerContainer());
959
+ ro.observe(await this._findInnerContainer(frame));
990
960
  });
991
961
  }
992
962
 
993
- open() {
994
- const popupdiv = this.popupdiv;
995
- const frame = this.frame;
996
- const {
963
+ open(frame) {
964
+ var element = this._findElement();
965
+
966
+ var parent = element.shadowRoot || element;
967
+ var dialog = parent.querySelector("#" + this.id);
968
+ if (!dialog) throw new Error("Could not determine container div");
969
+ dialog.showModal();
970
+ var {
997
971
  contentWindow
998
972
  } = frame;
999
973
  if (!contentWindow) throw new Error("Squatch.js has an empty iframe");
1000
- const frameDoc = contentWindow.document; // Adjust frame height when size of body changes
974
+ var frameDoc = contentWindow.document; // Adjust frame height when size of body changes
1001
975
 
1002
976
  domready(frameDoc, () => {
1003
977
  var _frame$contentDocumen;
1004
978
 
1005
- const _sqh = contentWindow.squatch || contentWindow.widgetIdent;
1006
-
1007
- const ctaElement = frameDoc.getElementById("cta");
1008
-
1009
- if (ctaElement) {
1010
- //@ts-ignore -- will occasionally throw a null pointer exception at runtime
1011
- ctaElement.parentNode.removeChild(ctaElement);
1012
- }
979
+ var _sqh = contentWindow.squatch || contentWindow.widgetIdent;
1013
980
 
1014
- popupdiv.style.visibility = "visible";
1015
- popupdiv.style.top = "0px";
1016
981
  (_frame$contentDocumen = frame.contentDocument) == null ? void 0 : _frame$contentDocumen.dispatchEvent(new CustomEvent("sq:refresh"));
1017
982
 
1018
983
  this._loadEvent(_sqh);
@@ -1022,218 +987,92 @@ class PopupWidget extends Widget {
1022
987
  }
1023
988
 
1024
989
  close() {
1025
- this.popupdiv.style.visibility = "hidden";
1026
- this.popupdiv.style.top = "-2000px";
990
+ var dialog = document.getElementById(this.id);
991
+ if (!dialog) throw new Error("Could not determine container div");
992
+ dialog.close();
1027
993
 
1028
994
  _log$5("Popup closed");
1029
995
  }
1030
996
 
1031
- _clickedOutside({
1032
- target
1033
- }) {
1034
- if (target === this.popupdiv) {
1035
- this.close();
1036
- }
1037
- }
1038
-
1039
- _error(rs, mode = "modal", style = "") {
1040
- const _style = "body { margin: 0; } .modal { box-shadow: none; border: 0; }";
1041
- return super._error(rs, mode, style || _style);
997
+ _clickedOutside(_ref) {
1042
998
  }
1043
999
 
1044
- }
1045
-
1046
- const _log$4 = debug("squatch-js:CTAwidget");
1047
- /**
1048
- * A CtaWidget is displayed on top of your page
1049
- *
1050
- * To create a CtaWidget use {@link Widgets}
1051
- *
1052
- */
1053
-
1054
-
1055
- class CtaWidget extends PopupWidget {
1056
- constructor(params, opts) {
1057
- _log$4("CTA constructor");
1058
-
1059
- const ctaElement = document.createElement("div");
1060
- ctaElement.id = "cta";
1061
- document.body.appendChild(ctaElement);
1062
- super(params, "#cta");
1063
-
1064
- if (!opts.side && !opts.position) {
1065
- opts.position = "bottom";
1066
- opts.side = "right";
1000
+ _error(rs, mode, style) {
1001
+ if (mode === void 0) {
1002
+ mode = "modal";
1067
1003
  }
1068
1004
 
1069
- if (opts.position === "middle") {
1070
- this.position = "top: 45%;";
1071
- this.side = opts.side === "center" ? "right: 45%;" : `${opts.side}: -10px;`;
1072
- } else {
1073
- this.position = `${opts.position}: -10px;`;
1074
- this.side = opts.side === "center" ? "right: 45%;" : `${opts.side}: 20px;`;
1005
+ if (style === void 0) {
1006
+ style = "";
1075
1007
  }
1076
1008
 
1077
- this.positionClass = opts.position;
1078
- this.ctaFrame = document.createElement("iframe"); // @ts-ignore - we are creating this pass-through
1079
-
1080
- this.ctaFrame.squatchJsApi = this;
1081
- this.ctaFrame.scrolling = "no";
1082
- this.ctaFrame.setAttribute("style", `border:0; background-color:transparent; position:fixed; display:none;${this.side}${this.position}`);
1083
- document.body.appendChild(this.ctaFrame);
1084
-
1085
- _log$4("ctaframe appended to body");
1086
- }
1087
-
1088
- load() {
1089
- super.load();
1090
-
1091
- if (!this.frame.contentWindow) {
1092
- throw new Error("frame requires a contentWindow");
1093
- }
1094
-
1095
- const widgetFrameDoc = this.frame.contentWindow.document;
1096
- const ctaFrame = this.ctaFrame;
1097
- const positionClass = this.positionClass; // Wait for widget doc to be ready to grab the cta HTML
1098
-
1099
- domready(widgetFrameDoc, () => {
1100
- const ctaElement = widgetFrameDoc.getElementById("cta");
1101
-
1102
- if (ctaElement) {
1103
- if (!ctaElement.parentNode) {
1104
- throw new Error("ctaElement requires a parentNode");
1105
- }
1106
-
1107
- ctaElement.parentNode.removeChild(ctaElement);
1108
- const ctaFrameWindow = ctaFrame.contentWindow;
1109
-
1110
- if (!ctaFrameWindow) {
1111
- throw new Error("ctaFrame requires a contentWindow");
1112
- }
1113
-
1114
- const ctaFrameDoc = ctaFrameWindow.document;
1115
- ctaFrameDoc.open();
1116
- ctaFrameDoc.write(ctaElement.innerHTML);
1117
- ctaFrameDoc.write(`<script src="${this.npmCdn}/resize-observer-polyfill@1.5.x"></script>`);
1118
- ctaFrameDoc.close(); // Figure out size of CTA as well
1119
-
1120
- domready(ctaFrameDoc, () => {
1121
- const ctaContainer = ctaFrameDoc.getElementsByClassName("cta-container")[0]; // @ts-ignore - Assume it's a stylable element, die otherwise
1122
-
1123
- ctaContainer.style.position = "fixed"; // @ts-ignore - Assume it's an element with offsetHeight
1124
-
1125
- ctaFrame.height = ctaContainer.offsetHeight; // @ts-ignore - Browser will cast from number to string (we hope)
1126
-
1127
- ctaFrame.width = ctaContainer.scrollWidth;
1128
- ctaFrame.style.display = "block";
1129
-
1130
- if (!ctaContainer.classList.contains(positionClass)) {
1131
- ctaContainer.className += ` ${positionClass}`;
1132
- } // Adjust frame height when size of body changes
1133
-
1134
-
1135
- const ro = new ctaFrameWindow["ResizeObserver"](entries => {
1136
- for (const entry of entries) {
1137
- const {
1138
- height,
1139
- width
1140
- } = entry.contentRect; // @ts-ignore - Browser will cast from number to string (we hope)
1141
-
1142
- ctaFrame.height = height; // @ts-ignore - Browser will cast from number to string (we hope)
1143
-
1144
- ctaFrame.width = width;
1145
- }
1146
- });
1147
- ro.observe(ctaContainer);
1148
-
1149
- _log$4("CTA template loaded into iframe");
1150
- });
1151
- } else {
1152
- _log$4(new Error("CTA element not found in theme"));
1153
- }
1154
- });
1155
- }
1156
- /**
1157
- * @inheritdoc
1158
- */
1159
-
1160
-
1161
- open() {
1162
- super.open();
1163
- }
1164
- /**
1165
- * @inheritdoc
1166
- */
1167
-
1168
-
1169
- close() {
1170
- super.close();
1009
+ var _style = "body { margin: 0; } .modal { box-shadow: none; border: 0; }";
1010
+ return super._error(rs, mode, style || _style);
1171
1011
  }
1172
1012
 
1173
1013
  }
1174
1014
 
1175
- const _log$3 = debug__default("squatch-js:widgets");
1176
- /**
1177
- *
1178
- * `Widgets` is a factory for creating widgets. It's possible to build your own widgets using the
1179
- * {@link WidgetApi} but most people will prefer to use these easy methods.
1180
- *
1015
+ var _log$4 = debug("squatch-js:widgets");
1016
+ /**
1017
+ *
1018
+ * `Widgets` is a factory for creating widgets. It's possible to build your own widgets using the
1019
+ * {@link WidgetApi} but most people will prefer to use these easy methods.
1020
+ *
1181
1021
  */
1182
1022
 
1183
1023
 
1184
1024
  class Widgets {
1185
- /**
1186
- * Initialize a new {@link Widgets} instance.
1187
- *
1188
- * @param {ConfigOptions} config Config details
1189
- *
1190
- * @example <caption>Browser example</caption>
1191
- * var widgets = new squatch.Widgets({tenantAlias:'test_12b5bo1b25125'});
1192
- *
1193
- * @example <caption>Browserify/Webpack example</caption>
1194
- * var Widgets = require('@saasquatch/squatch-js').Widgets;
1195
- * var widgets = new Widgets({tenantAlias:'test_12b5bo1b25125'});
1196
- *
1197
- * @example <caption>Babel+Browserify/Webpack example</caption>
1198
- * import {Widgets} from '@saasquatch/squatch-js';
1199
- * let widgets = new Widgets({tenantAlias:'test_12b5bo1b25125'});
1025
+ /**
1026
+ * Initialize a new {@link Widgets} instance.
1027
+ *
1028
+ * @param {ConfigOptions} config Config details
1029
+ *
1030
+ * @example <caption>Browser example</caption>
1031
+ * var widgets = new squatch.Widgets({tenantAlias:'test_12b5bo1b25125'});
1032
+ *
1033
+ * @example <caption>Browserify/Webpack example</caption>
1034
+ * var Widgets = require('@saasquatch/squatch-js').Widgets;
1035
+ * var widgets = new Widgets({tenantAlias:'test_12b5bo1b25125'});
1036
+ *
1037
+ * @example <caption>Babel+Browserify/Webpack example</caption>
1038
+ * import {Widgets} from '@saasquatch/squatch-js';
1039
+ * let widgets = new Widgets({tenantAlias:'test_12b5bo1b25125'});
1200
1040
  */
1201
1041
  constructor(configin) {
1202
- const raw = configin;
1203
- const config = validateConfig(raw);
1042
+ this.api = void 0;
1043
+ this.tenantAlias = void 0;
1044
+ this.domain = void 0;
1045
+ this.npmCdn = void 0;
1046
+ var config = validateConfig(configin);
1204
1047
  this.tenantAlias = config.tenantAlias;
1205
1048
  this.domain = config.domain;
1206
- this.npmCdn = config.npmCdn; // for with locals custom theme, can be removed once with locals isnt' using eventBus anymore.
1207
-
1208
- this.eventBus = EventBus;
1049
+ this.npmCdn = config.npmCdn;
1209
1050
  this.api = new WidgetApi(config); // listens to a 'submit_email' event in the theme.
1210
-
1211
- EventBus.addEventListener("submit_email", Widgets._cb);
1212
- }
1213
- /**
1214
- * This function calls the {@link WidgetApi.upsertUser} method, and it renders
1215
- * the widget if it is successful. Otherwise it shows the "error" widget.
1216
- *
1217
- * @param {Object} config Config details
1218
- * @param {Object} config.user The user details
1219
- * @param {string} config.user.id The user id
1220
- * @param {string} config.user.accountId The user account id
1221
- * @param {WidgetType} config.widgetType The content of the widget.
1222
- * @param {EngagementMedium} config.engagementMedium How to display the widget.
1223
- * @param {string} config.jwt the JSON Web Token (JWT) that is used to validate the data (can be disabled)
1224
- * @param {HTMLElement | string | undefined} config.container Element to load the widget into
1225
- * @param {string | undefined} config.trigger Trigger element for opening the popup widget
1226
- *
1227
- * @return {Promise<WidgetResult>} json object if true, with a Widget and user details.
1051
+ }
1052
+ /**
1053
+ * This function calls the {@link WidgetApi.upsertUser} method, and it renders
1054
+ * the widget if it is successful. Otherwise it shows the "error" widget.
1055
+ *
1056
+ * @param {Object} config Config details
1057
+ * @param {Object} config.user The user details
1058
+ * @param {string} config.user.id The user id
1059
+ * @param {string} config.user.accountId The user account id
1060
+ * @param {WidgetType} config.widgetType The content of the widget.
1061
+ * @param {EngagementMedium} config.engagementMedium How to display the widget.
1062
+ * @param {string} config.jwt the JSON Web Token (JWT) that is used to validate the data (can be disabled)
1063
+ * @param {HTMLElement | string | undefined} config.container Element to load the widget into
1064
+ * @param {string | undefined} config.trigger Trigger element for opening the popup widget
1065
+ *
1066
+ * @return {Promise<WidgetResult>} json object if true, with a Widget and user details.
1228
1067
  */
1229
1068
 
1230
1069
 
1231
1070
  async upsertUser(config) {
1232
- const raw = config;
1233
- const clean = validateWidgetConfig(raw);
1071
+ var raw = config;
1072
+ var clean = validateWidgetConfig(raw);
1234
1073
 
1235
1074
  try {
1236
- const response = await this.api.upsertUser(clean);
1075
+ var response = await this.api.upsertUser(clean);
1237
1076
  return {
1238
1077
  widget: this._renderWidget(response, clean, {
1239
1078
  type: "upsert",
@@ -1245,7 +1084,7 @@ class Widgets {
1245
1084
  user: response.user
1246
1085
  };
1247
1086
  } catch (err) {
1248
- _log$3(err);
1087
+ _log$4(err);
1249
1088
 
1250
1089
  if (err.apiErrorCode) {
1251
1090
  this._renderErrorWidget(err, config.engagementMedium);
@@ -1254,29 +1093,29 @@ class Widgets {
1254
1093
  throw err;
1255
1094
  }
1256
1095
  }
1257
- /**
1258
- * This function calls the {@link WidgetApi.render} method, and it renders
1259
- * the widget if it is successful. Otherwise it shows the "error" widget.
1260
- *
1261
- * @param {Object} config Config details
1262
- * @param {Object} config.user The user details
1263
- * @param {string} config.user.id The user id
1264
- * @param {string} config.user.accountId The user account id
1265
- * @param {WidgetType} config.widgetType The content of the widget.
1266
- * @param {EngagementMedium} config.engagementMedium How to display the widget.
1267
- * @param {string} config.jwt the JSON Web Token (JWT) that is used
1268
- * to validate the data (can be disabled)
1269
- *
1270
- * @return {Promise<WidgetResult>} json object if true, with a Widget and user details.
1096
+ /**
1097
+ * This function calls the {@link WidgetApi.render} method, and it renders
1098
+ * the widget if it is successful. Otherwise it shows the "error" widget.
1099
+ *
1100
+ * @param {Object} config Config details
1101
+ * @param {Object} config.user The user details
1102
+ * @param {string} config.user.id The user id
1103
+ * @param {string} config.user.accountId The user account id
1104
+ * @param {WidgetType} config.widgetType The content of the widget.
1105
+ * @param {EngagementMedium} config.engagementMedium How to display the widget.
1106
+ * @param {string} config.jwt the JSON Web Token (JWT) that is used
1107
+ * to validate the data (can be disabled)
1108
+ *
1109
+ * @return {Promise<WidgetResult>} json object if true, with a Widget and user details.
1271
1110
  */
1272
1111
 
1273
1112
 
1274
1113
  async render(config) {
1275
- const raw = config;
1276
- const clean = validatePasswordlessConfig(raw);
1114
+ var raw = config;
1115
+ var clean = validatePasswordlessConfig(raw);
1277
1116
 
1278
1117
  try {
1279
- const response = await this.api.render(clean);
1118
+ var response = await this.api.render(clean);
1280
1119
  return {
1281
1120
  widget: this._renderWidget(response, clean, {
1282
1121
  type: "passwordless",
@@ -1292,21 +1131,23 @@ class Widgets {
1292
1131
  throw err;
1293
1132
  }
1294
1133
  }
1295
- /**
1296
- * Autofills a referral code into an element when someone has been referred.
1297
- * Uses {@link WidgetApi.squatchReferralCookie} behind the scenes.
1298
- *
1299
- * @param selector Element class/id selector, or a callback function
1300
- * @returns
1134
+ /**
1135
+ * Autofills a referral code into an element when someone has been referred.
1136
+ * Uses {@link WidgetApi.squatchReferralCookie} behind the scenes.
1137
+ *
1138
+ * @param selector Element class/id selector, or a callback function
1139
+ * @returns
1301
1140
  */
1302
1141
 
1303
1142
 
1304
1143
  autofill(selector) {
1305
- const input = selector;
1144
+ var input = selector;
1306
1145
 
1307
1146
  if (typeof input === "function") {
1308
- this.api.squatchReferralCookie().then((...args) => input(...args)).catch(ex => {
1309
- _log$3("Autofill error", ex);
1147
+ this.api.squatchReferralCookie().then(function () {
1148
+ return input(...arguments);
1149
+ }).catch(ex => {
1150
+ _log$4("Autofill error", ex);
1310
1151
 
1311
1152
  throw ex;
1312
1153
  });
@@ -1314,59 +1155,45 @@ class Widgets {
1314
1155
  }
1315
1156
 
1316
1157
  if (typeof input !== "string") throw new Error("Autofill accepts a string or function");
1317
- let elems = document.querySelectorAll(input);
1318
- let elem;
1158
+ var elems = document.querySelectorAll(input);
1159
+ var elem;
1319
1160
 
1320
1161
  if (elems.length > 0) {
1321
1162
  // Only use the first element found
1322
1163
  elem = elems[0];
1323
1164
  } else {
1324
- _log$3("Element id/class or function missing");
1165
+ _log$4("Element id/class or function missing");
1325
1166
 
1326
1167
  throw new Error("Element id/class or function missing");
1327
1168
  }
1328
1169
 
1329
- this.api.squatchReferralCookie() //@ts-ignore
1330
- .then(({
1331
- code
1332
- }) => {
1333
- elem.value = code;
1170
+ this.api.squatchReferralCookie().then(_ref => {
1171
+ var {
1172
+ codes
1173
+ } = _ref;
1174
+ elem.value = codes[0];
1334
1175
  }).catch(ex => {
1335
1176
  throw ex;
1336
1177
  });
1337
1178
  }
1338
- /**
1339
- * Overrides the default function that submits the user email. If you have
1340
- * Security enabled, the email needs to be signed before it's submitted.
1341
- *
1342
- * @param {function} fn Callback function for the 'submit_email' event.
1343
- * @returns {void}
1344
- */
1345
-
1346
-
1347
- submitEmail(fn) {
1348
- EventBus.removeEventListener("submit_email", Widgets._cb);
1349
- EventBus.addEventListener("submit_email", fn);
1350
- }
1351
- /**
1352
- * @hidden
1353
- * @param {Object} response The json object return from the WidgetApi
1354
- * @param {Object} config Config details
1355
- * @param {string} config.widgetType The widget type (REFERRER_WIDGET, CONVERSION_WIDGET)
1356
- * @param {string} config.engagementMedium (POPUP, EMBED)
1357
- * @returns {Widget} widget (PopupWidget, EmbedWidget, or CtaWidget)
1179
+ /**
1180
+ * @hidden
1181
+ * @param {Object} response The json object return from the WidgetApi
1182
+ * @param {Object} config Config details
1183
+ * @param {string} config.widgetType The widget type (REFERRER_WIDGET, CONVERSION_WIDGET)
1184
+ * @param {string} config.engagementMedium (POPUP, EMBED)
1185
+ * @returns {Widget} widget (PopupWidget or EmbedWidget)
1358
1186
  */
1359
1187
 
1360
1188
 
1361
1189
  _renderWidget(response, config, context) {
1362
- _log$3("Rendering Widget...");
1190
+ _log$4("Rendering Widget...");
1363
1191
 
1364
1192
  if (!response) throw new Error("Unable to get a response");
1365
- let widget;
1366
- let displayOnLoad = !!config.displayOnLoad;
1367
- let displayCTA = false;
1368
- const opts = response.jsOptions || "";
1369
- const params = {
1193
+ var widget;
1194
+ var displayOnLoad = !!config.displayOnLoad;
1195
+ var opts = response.jsOptions || "";
1196
+ var params = {
1370
1197
  content: response.template,
1371
1198
  type: config.widgetType || opts.widget.defaultWidgetType,
1372
1199
  api: this.api,
@@ -1380,67 +1207,47 @@ class Widgets {
1380
1207
  if (Widgets._matchesUrl(rule.url)) {
1381
1208
  if (rule.widgetType !== "CONVERSION_WIDGET" || response.user.referredBy && response.user.referredBy.code) {
1382
1209
  displayOnLoad = rule.displayOnLoad;
1383
- displayCTA = rule.showAsCTA;
1384
1210
 
1385
- _log$3(`Display ${rule.widgetType} on ${rule.url}`);
1211
+ _log$4("Display " + rule.widgetType + " on " + rule.url);
1386
1212
  } else {
1387
- _log$3(`Don't display ${rule.widgetType} when no referral on widget rule match ${rule.url}`);
1213
+ _log$4("Don't display " + rule.widgetType + " when no referral on widget rule match " + rule.url);
1388
1214
  }
1389
1215
  }
1390
1216
  });
1391
1217
  }
1392
1218
 
1393
- if (opts.conversionUrls) {
1394
- opts.conversionUrls.forEach(rule => {
1395
- if (response.user.referredBy && Widgets._matchesUrl(rule)) {
1396
- _log$3("This is a conversion URL", rule);
1397
- }
1398
- });
1399
- }
1400
-
1401
1219
  if (opts.fuelTankAutofillUrls) {
1402
- _log$3("We found a fuel tank autofill!");
1220
+ _log$4("We found a fuel tank autofill!");
1221
+
1222
+ opts.fuelTankAutofillUrls.forEach(_ref2 => {
1223
+ var {
1224
+ url,
1225
+ formSelector
1226
+ } = _ref2;
1403
1227
 
1404
- opts.fuelTankAutofillUrls.forEach(({
1405
- url,
1406
- formSelector
1407
- }) => {
1408
1228
  if (Widgets._matchesUrl(url)) {
1409
- _log$3("Fuel Tank URL matches");
1229
+ _log$4("Fuel Tank URL matches");
1410
1230
 
1411
1231
  if (response.user.referredBy && response.user.referredBy.code) {
1412
- const formAutofill = document.querySelector(formSelector);
1232
+ var formAutofill = document.querySelector(formSelector);
1413
1233
 
1414
1234
  if (formAutofill) {
1415
1235
  formAutofill.value = response.user.referredBy.referredReward.fuelTankCode || "";
1416
1236
  } else {
1417
- _log$3(new Error(`Element with id/class ${formSelector} was not found.`));
1237
+ _log$4(new Error("Element with id/class " + formSelector + " was not found."));
1418
1238
  }
1419
1239
  }
1420
1240
  }
1421
1241
  });
1422
1242
  }
1423
1243
 
1424
- if (!displayCTA && config.engagementMedium === "EMBED") {
1425
- widget = new EmbedWidget(params, params.context.container);
1426
- widget.load();
1427
- } else if (!displayCTA && config.engagementMedium === "POPUP") {
1428
- widget = new PopupWidget(params, params.context.trigger);
1429
- widget.load();
1430
- if (displayOnLoad) widget.open();
1431
- } else if (displayCTA) {
1432
- _log$3("display CTA");
1433
-
1434
- const side = opts.cta.content.buttonSide;
1435
- const position = opts.cta.content.buttonPosition;
1436
- widget = new CtaWidget(params, {
1437
- side,
1438
- position
1439
- });
1440
- widget.load();
1244
+ if (config.engagementMedium === "EMBED") {
1245
+ this._renderEmbedWidget(params, params.context.container);
1246
+ } else if (config.engagementMedium === "POPUP") {
1247
+ widget = this._renderPopupWidget(params);
1441
1248
  if (displayOnLoad) widget.open();
1442
1249
  } else {
1443
- _log$3("display popup on load");
1250
+ _log$4("display popup on load");
1444
1251
 
1445
1252
  widget = new PopupWidget(params);
1446
1253
  widget.load();
@@ -1449,24 +1256,45 @@ class Widgets {
1449
1256
 
1450
1257
  return widget;
1451
1258
  }
1452
- /**
1453
- * @hidden
1454
- * @param {Object} error The json object containing the error details
1455
- * @param {string} em The engagementMedium
1456
- * @returns {void}
1259
+
1260
+ _renderPopupWidget(params) {
1261
+ var widget = new PopupWidget(params, params.context.trigger);
1262
+
1263
+ var frame = widget._createFrame();
1264
+
1265
+ widget.load(frame);
1266
+ return widget;
1267
+ }
1268
+
1269
+ _renderEmbedWidget(params, container) {
1270
+ var widget = new EmbedWidget(params);
1271
+
1272
+ var frame = widget._createFrame();
1273
+
1274
+ widget.load(frame);
1275
+ }
1276
+ /**
1277
+ * @hidden
1278
+ * @param {Object} error The json object containing the error details
1279
+ * @param {string} em The engagementMedium
1280
+ * @returns {void}
1457
1281
  */
1458
1282
 
1459
1283
 
1460
- _renderErrorWidget(props, em = "POPUP") {
1461
- const {
1284
+ _renderErrorWidget(props, em) {
1285
+ if (em === void 0) {
1286
+ em = "POPUP";
1287
+ }
1288
+
1289
+ var {
1462
1290
  apiErrorCode,
1463
1291
  rsCode,
1464
1292
  message
1465
1293
  } = props;
1466
1294
 
1467
- _log$3(new Error(`${apiErrorCode} (${rsCode}) ${message}`));
1295
+ _log$4(new Error(apiErrorCode + " (" + rsCode + ") " + message));
1468
1296
 
1469
- const params = {
1297
+ var params = {
1470
1298
  content: "error",
1471
1299
  rsCode,
1472
1300
  api: this.api,
@@ -1477,20 +1305,26 @@ class Widgets {
1477
1305
  type: "error"
1478
1306
  }
1479
1307
  };
1480
- let widget;
1308
+ var widget;
1481
1309
 
1482
1310
  if (em === "EMBED") {
1483
1311
  widget = new EmbedWidget(params);
1484
- widget.load();
1312
+
1313
+ var frame = widget._createFrame();
1314
+
1315
+ widget.load(frame);
1485
1316
  } else if (em === "POPUP") {
1486
1317
  widget = new PopupWidget(params);
1487
- widget.load();
1318
+
1319
+ var _frame = widget._createFrame();
1320
+
1321
+ widget.load(_frame);
1488
1322
  }
1489
1323
  }
1490
- /**
1491
- * @hidden
1492
- * @param {string} rule A regular expression
1493
- * @returns {boolean} true if rule matches Url, false otherwise
1324
+ /**
1325
+ * @hidden
1326
+ * @param {string} rule A regular expression
1327
+ * @returns {boolean} true if rule matches Url, false otherwise
1494
1328
  */
1495
1329
 
1496
1330
 
@@ -1498,18 +1332,18 @@ class Widgets {
1498
1332
  // If there were no matches, null is returned.
1499
1333
  return window.location.href.match(new RegExp(rule)) ? true : false;
1500
1334
  }
1501
- /**
1502
- * @hidden
1503
- * @param {Object} target Object containing the target DOM element
1504
- * @param {Widget} widget A widget (EmbedWidget, PopupWidget, CtaWidget)
1505
- * @param {Object} params An object with valid parameters
1506
- * (e.g) {email:'email', firstName:'firstName'}
1507
- * @returns {void}
1335
+ /**
1336
+ * @hidden
1337
+ * @param {Object} target Object containing the target DOM element
1338
+ * @param {Widget} widget A widget (EmbedWidget, PopupWidget)
1339
+ * @param {Object} params An object with valid parameters
1340
+ * (e.g) {email:'email', firstName:'firstName'}
1341
+ * @returns {void}
1508
1342
  */
1509
1343
 
1510
1344
 
1511
1345
  static _cb(target, widget, params) {
1512
- let paramsObj; // If params is a string, then it should be an email
1346
+ var paramsObj; // If params is a string, then it should be an email
1513
1347
 
1514
1348
  if (typeof params === "string" || params instanceof String) {
1515
1349
  paramsObj = {
@@ -1525,71 +1359,76 @@ class Widgets {
1525
1359
 
1526
1360
  }
1527
1361
 
1528
- /**
1529
- *
1530
- * The EventsApi class is a wrapper around the open endpoints of the SaaSquatch REST API.
1531
- *
1362
+ /**
1363
+ *
1364
+ * The EventsApi class is a wrapper around the open endpoints of the SaaSquatch REST API.
1365
+ *
1532
1366
  */
1533
1367
 
1534
1368
  class EventsApi {
1535
- /**
1536
- * Initialize a new {@link EventsApi} instance.
1537
- *
1538
- * @param {ConfigOptions} config Config details
1539
- *
1540
- * @example <caption>Browser example</caption>
1541
- * var squatchApi = new squatch.EventsApi({tenantAlias:'test_12b5bo1b25125'});
1542
- *
1543
- * @example <caption>Browserify/Webpack example</caption>
1544
- * var EventsApi = require('@saasquatch/squatch-js').EventsApi;
1545
- * var squatchApi = new EventsApi({tenantAlias:'test_12b5bo1b25125'});
1546
- *
1547
- * @example <caption>Babel+Browserify/Webpack example</caption>
1548
- * import {EventsApi} from '@saasquatch/squatch-js';
1549
- * let squatchApi = new EventsApi({tenantAlias:'test_12b5bo1b25125'});
1369
+ /**
1370
+ * Initialize a new {@link EventsApi} instance.
1371
+ *
1372
+ * @param {ConfigOptions} config Config details
1373
+ *
1374
+ * @example <caption>Browser example</caption>
1375
+ * var squatchApi = new squatch.EventsApi({tenantAlias:'test_12b5bo1b25125'});
1376
+ *
1377
+ * @example <caption>Browserify/Webpack example</caption>
1378
+ * var EventsApi = require('@saasquatch/squatch-js').EventsApi;
1379
+ * var squatchApi = new EventsApi({tenantAlias:'test_12b5bo1b25125'});
1380
+ *
1381
+ * @example <caption>Babel+Browserify/Webpack example</caption>
1382
+ * import {EventsApi} from '@saasquatch/squatch-js';
1383
+ * let squatchApi = new EventsApi({tenantAlias:'test_12b5bo1b25125'});
1550
1384
  */
1551
1385
  constructor(config) {
1552
- const raw = config; // Flags that we need to validate anything we use from this type
1386
+ this.tenantAlias = void 0;
1387
+ this.domain = void 0;
1388
+ var raw = config; // Flags that we need to validate anything we use from this type
1553
1389
 
1554
- const clean = validateConfig(raw);
1390
+ var clean = validateConfig(raw);
1555
1391
  this.tenantAlias = clean.tenantAlias;
1556
1392
  this.domain = clean.domain;
1557
1393
  }
1558
- /**
1559
- * Track an event for a user
1560
- *
1561
- * @param params Parameters for request
1562
- * @param options.jwt the JSON Web Token (JWT) that is used to authenticate the user
1563
- *
1564
- * @return An ID to confirm the event has been accepted for asynchronous processing
1394
+ /**
1395
+ * Track an event for a user
1396
+ *
1397
+ * @param params Parameters for request
1398
+ * @param options.jwt the JSON Web Token (JWT) that is used to authenticate the user
1399
+ *
1400
+ * @return An ID to confirm the event has been accepted for asynchronous processing
1565
1401
  */
1566
1402
 
1567
1403
 
1568
1404
  track(params, options) {
1569
- const raw = params;
1570
- const rawOpts = options;
1405
+ var raw = params;
1406
+ var rawOpts = options;
1571
1407
 
1572
- const body = _validateEvent(raw);
1408
+ var body = _validateEvent(raw);
1573
1409
 
1574
- const {
1410
+ var {
1575
1411
  jwt
1576
1412
  } = _validateTrackOptions(rawOpts);
1577
1413
 
1578
- const ta = encodeURIComponent(this.tenantAlias);
1579
- const userId = encodeURIComponent(body.userId);
1580
- const accountId = encodeURIComponent(body.accountId);
1581
- const path = `/api/v1/${ta}/open/account/${accountId}/user/${userId}/events`;
1582
- const url = this.domain + path;
1414
+ var ta = encodeURIComponent(this.tenantAlias);
1415
+ var userId = encodeURIComponent(body.userId);
1416
+ var accountId = encodeURIComponent(body.accountId);
1417
+ var path = "/api/v1/" + ta + "/open/account/" + accountId + "/user/" + userId + "/events";
1418
+ var url = this.domain + path;
1583
1419
  return doPost(url, JSON.stringify(body), jwt);
1584
1420
  }
1585
1421
 
1586
1422
  }
1587
1423
 
1588
1424
  function _validateEvent(raw) {
1589
- if (!assertProp(raw, "accountId", "events", "userId")) ;
1590
- if (!Array.isArray(raw.events)) throw new Error("'events' should be an array"); // TODO: Better type checking
1591
-
1592
- return raw;
1425
+ if (!isObject$1(raw)) throw new Error("tracking parameter must be an object");
1426
+ if (!(raw != null && raw["accountId"])) throw new Error("accountId field is required");
1427
+ if (!(raw != null && raw["events"])) throw new Error("events field is required");
1428
+ if (!(raw != null && raw["userId"])) throw new Error("userId field is required");
1429
+ var clean = raw;
1430
+ if (!Array.isArray(clean.events)) throw new Error("'events' should be an array");
1431
+ return clean;
1593
1432
  }
1594
1433
 
1595
1434
  function _validateTrackOptions(raw) {
@@ -1599,12 +1438,13 @@ function _validateTrackOptions(raw) {
1599
1438
 
1600
1439
  /** @hidden */
1601
1440
  function asyncLoad() {
1602
- const loaded = window.squatch || null;
1603
- const cached = window._squatch || null;
1441
+ var loaded = window.squatch || null;
1442
+ var cached = window._squatch || null;
1604
1443
 
1605
1444
  if (loaded && cached) {
1606
- const ready = cached.ready || [];
1607
- ready.forEach(cb => setTimeout(() => cb(), 0)); // @ts-ignore -- intetionally deletes `_squatch` to cleanup initialization
1445
+ var ready = cached.ready || [];
1446
+ ready.forEach(cb => setTimeout(() => cb(), 0));
1447
+ setTimeout(() => window.squatch._auto(), 0); // @ts-ignore -- intetionally deletes `_squatch` to cleanup initialization
1608
1448
 
1609
1449
  window._squatch = undefined;
1610
1450
 
@@ -1616,392 +1456,16 @@ function asyncLoad() {
1616
1456
  }
1617
1457
  }
1618
1458
 
1619
- /*! (c) Andrea Giammarchi - ISC */
1620
- var self = undefined || /* istanbul ignore next */ {};
1621
- try {
1622
- (function (URLSearchParams, plus) {
1623
- if (
1624
- new URLSearchParams('q=%2B').get('q') !== plus ||
1625
- new URLSearchParams({q: plus}).get('q') !== plus ||
1626
- new URLSearchParams([['q', plus]]).get('q') !== plus ||
1627
- new URLSearchParams('q=\n').toString() !== 'q=%0A' ||
1628
- new URLSearchParams({q: ' &'}).toString() !== 'q=+%26' ||
1629
- new URLSearchParams({q: '%zx'}).toString() !== 'q=%25zx'
1630
- )
1631
- throw URLSearchParams;
1632
- self.URLSearchParams = URLSearchParams;
1633
- }(URLSearchParams, '+'));
1634
- } catch(URLSearchParams) {
1635
- (function (Object, String, isArray) { var create = Object.create;
1636
- var defineProperty = Object.defineProperty;
1637
- var find = /[!'\(\)~]|%20|%00/g;
1638
- var findPercentSign = /%(?![0-9a-fA-F]{2})/g;
1639
- var plus = /\+/g;
1640
- var replace = {
1641
- '!': '%21',
1642
- "'": '%27',
1643
- '(': '%28',
1644
- ')': '%29',
1645
- '~': '%7E',
1646
- '%20': '+',
1647
- '%00': '\x00'
1648
- };
1649
- var proto = {
1650
- append: function (key, value) {
1651
- appendTo(this._ungap, key, value);
1652
- },
1653
- delete: function (key) {
1654
- delete this._ungap[key];
1655
- },
1656
- get: function (key) {
1657
- return this.has(key) ? this._ungap[key][0] : null;
1658
- },
1659
- getAll: function (key) {
1660
- return this.has(key) ? this._ungap[key].slice(0) : [];
1661
- },
1662
- has: function (key) {
1663
- return key in this._ungap;
1664
- },
1665
- set: function (key, value) {
1666
- this._ungap[key] = [String(value)];
1667
- },
1668
- forEach: function (callback, thisArg) {
1669
- var self = this;
1670
- for (var key in self._ungap)
1671
- self._ungap[key].forEach(invoke, key);
1672
- function invoke(value) {
1673
- callback.call(thisArg, value, String(key), self);
1674
- }
1675
- },
1676
- toJSON: function () {
1677
- return {};
1678
- },
1679
- toString: function () {
1680
- var query = [];
1681
- for (var key in this._ungap) {
1682
- var encoded = encode(key);
1683
- for (var
1684
- i = 0,
1685
- value = this._ungap[key];
1686
- i < value.length; i++
1687
- ) {
1688
- query.push(encoded + '=' + encode(value[i]));
1689
- }
1690
- }
1691
- return query.join('&');
1692
- }
1693
- };
1694
- for (var key in proto)
1695
- defineProperty(URLSearchParams.prototype, key, {
1696
- configurable: true,
1697
- writable: true,
1698
- value: proto[key]
1699
- });
1700
- self.URLSearchParams = URLSearchParams;
1701
- function URLSearchParams(query) {
1702
- var dict = create(null);
1703
- defineProperty(this, '_ungap', {value: dict});
1704
- switch (true) {
1705
- case !query:
1706
- break;
1707
- case typeof query === 'string':
1708
- if (query.charAt(0) === '?') {
1709
- query = query.slice(1);
1710
- }
1711
- for (var
1712
- pairs = query.split('&'),
1713
- i = 0,
1714
- length = pairs.length; i < length; i++
1715
- ) {
1716
- var value = pairs[i];
1717
- var index = value.indexOf('=');
1718
- if (-1 < index) {
1719
- appendTo(
1720
- dict,
1721
- decode(value.slice(0, index)),
1722
- decode(value.slice(index + 1))
1723
- );
1724
- } else if (value.length){
1725
- appendTo(
1726
- dict,
1727
- decode(value),
1728
- ''
1729
- );
1730
- }
1731
- }
1732
- break;
1733
- case isArray(query):
1734
- for (var
1735
- i = 0,
1736
- length = query.length; i < length; i++
1737
- ) {
1738
- var value = query[i];
1739
- appendTo(dict, value[0], value[1]);
1740
- }
1741
- break;
1742
- case 'forEach' in query:
1743
- query.forEach(addEach, dict);
1744
- break;
1745
- default:
1746
- for (var key in query)
1747
- appendTo(dict, key, query[key]);
1748
- }
1749
- }
1750
-
1751
- function addEach(value, key) {
1752
- appendTo(this, key, value);
1753
- }
1754
-
1755
- function appendTo(dict, key, value) {
1756
- var res = isArray(value) ? value.join(',') : value;
1757
- if (key in dict)
1758
- dict[key].push(res);
1759
- else
1760
- dict[key] = [res];
1761
- }
1762
-
1763
- function decode(str) {
1764
- return decodeURIComponent(str.replace(findPercentSign, '%25').replace(plus, ' '));
1765
- }
1766
-
1767
- function encode(str) {
1768
- return encodeURIComponent(str).replace(find, replacer);
1769
- }
1770
-
1771
- function replacer(match) {
1772
- return replace[match];
1773
- }
1774
-
1775
- }(Object, String, Array.isArray));
1776
- }
1777
-
1778
- (function (URLSearchParamsProto) {
1779
-
1780
- var iterable = false;
1781
- try { iterable = !!Symbol.iterator; } catch (o_O) {}
1782
-
1783
- /* istanbul ignore else */
1784
- if (!('forEach' in URLSearchParamsProto)) {
1785
- URLSearchParamsProto.forEach = function forEach(callback, thisArg) {
1786
- var self = this;
1787
- var names = Object.create(null);
1788
- this.toString()
1789
- .replace(/=[\s\S]*?(?:&|$)/g, '=')
1790
- .split('=')
1791
- .forEach(function (name) {
1792
- if (!name.length || name in names)
1793
- return;
1794
- (names[name] = self.getAll(name)).forEach(function(value) {
1795
- callback.call(thisArg, value, name, self);
1796
- });
1797
- });
1798
- };
1799
- }
1800
-
1801
- /* istanbul ignore else */
1802
- if (!('keys' in URLSearchParamsProto)) {
1803
- URLSearchParamsProto.keys = function keys() {
1804
- return iterator(this, function(value, key) { this.push(key); });
1805
- };
1806
- }
1807
-
1808
- /* istanbul ignore else */
1809
- if (!('values' in URLSearchParamsProto)) {
1810
- URLSearchParamsProto.values = function values() {
1811
- return iterator(this, function(value, key) { this.push(value); });
1812
- };
1813
- }
1814
-
1815
- /* istanbul ignore else */
1816
- if (!('entries' in URLSearchParamsProto)) {
1817
- URLSearchParamsProto.entries = function entries() {
1818
- return iterator(this, function(value, key) { this.push([key, value]); });
1819
- };
1820
- }
1821
-
1822
- /* istanbul ignore else */
1823
- if (iterable && !(Symbol.iterator in URLSearchParamsProto)) {
1824
- URLSearchParamsProto[Symbol.iterator] = URLSearchParamsProto.entries;
1825
- }
1826
-
1827
- /* istanbul ignore else */
1828
- if (!('sort' in URLSearchParamsProto)) {
1829
- URLSearchParamsProto.sort = function sort() {
1830
- var
1831
- entries = this.entries(),
1832
- entry = entries.next(),
1833
- done = entry.done,
1834
- keys = [],
1835
- values = Object.create(null),
1836
- i, key, value
1837
- ;
1838
- while (!done) {
1839
- value = entry.value;
1840
- key = value[0];
1841
- keys.push(key);
1842
- if (!(key in values)) {
1843
- values[key] = [];
1844
- }
1845
- values[key].push(value[1]);
1846
- entry = entries.next();
1847
- done = entry.done;
1848
- }
1849
- // not the champion in efficiency
1850
- // but these two bits just do the job
1851
- keys.sort();
1852
- for (i = 0; i < keys.length; i++) {
1853
- this.delete(keys[i]);
1854
- }
1855
- for (i = 0; i < keys.length; i++) {
1856
- key = keys[i];
1857
- this.append(key, values[key].shift());
1858
- }
1859
- };
1860
- }
1861
-
1862
- function iterator(self, callback) {
1863
- var items = [];
1864
- self.forEach(callback, items);
1865
- /* istanbul ignore next */
1866
- return iterable ?
1867
- items[Symbol.iterator]() :
1868
- {
1869
- next: function() {
1870
- var value = items.shift();
1871
- return {done: value === void 0, value: value};
1872
- }
1873
- };
1874
- }
1875
-
1876
- /* istanbul ignore next */
1877
- (function (Object) {
1878
- var
1879
- dP = Object.defineProperty,
1880
- gOPD = Object.getOwnPropertyDescriptor,
1881
- createSearchParamsPollute = function (search) {
1882
- function append(name, value) {
1883
- URLSearchParamsProto.append.call(this, name, value);
1884
- name = this.toString();
1885
- search.set.call(this._usp, name ? ('?' + name) : '');
1886
- }
1887
- function del(name) {
1888
- URLSearchParamsProto.delete.call(this, name);
1889
- name = this.toString();
1890
- search.set.call(this._usp, name ? ('?' + name) : '');
1891
- }
1892
- function set(name, value) {
1893
- URLSearchParamsProto.set.call(this, name, value);
1894
- name = this.toString();
1895
- search.set.call(this._usp, name ? ('?' + name) : '');
1896
- }
1897
- return function (sp, value) {
1898
- sp.append = append;
1899
- sp.delete = del;
1900
- sp.set = set;
1901
- return dP(sp, '_usp', {
1902
- configurable: true,
1903
- writable: true,
1904
- value: value
1905
- });
1906
- };
1907
- },
1908
- createSearchParamsCreate = function (polluteSearchParams) {
1909
- return function (obj, sp) {
1910
- dP(
1911
- obj, '_searchParams', {
1912
- configurable: true,
1913
- writable: true,
1914
- value: polluteSearchParams(sp, obj)
1915
- }
1916
- );
1917
- return sp;
1918
- };
1919
- },
1920
- updateSearchParams = function (sp) {
1921
- var append = sp.append;
1922
- sp.append = URLSearchParamsProto.append;
1923
- URLSearchParams.call(sp, sp._usp.search.slice(1));
1924
- sp.append = append;
1925
- },
1926
- verifySearchParams = function (obj, Class) {
1927
- if (!(obj instanceof Class)) throw new TypeError(
1928
- "'searchParams' accessed on an object that " +
1929
- "does not implement interface " + Class.name
1930
- );
1931
- },
1932
- upgradeClass = function (Class) {
1933
- var
1934
- ClassProto = Class.prototype,
1935
- searchParams = gOPD(ClassProto, 'searchParams'),
1936
- href = gOPD(ClassProto, 'href'),
1937
- search = gOPD(ClassProto, 'search'),
1938
- createSearchParams
1939
- ;
1940
- if (!searchParams && search && search.set) {
1941
- createSearchParams = createSearchParamsCreate(
1942
- createSearchParamsPollute(search)
1943
- );
1944
- Object.defineProperties(
1945
- ClassProto,
1946
- {
1947
- href: {
1948
- get: function () {
1949
- return href.get.call(this);
1950
- },
1951
- set: function (value) {
1952
- var sp = this._searchParams;
1953
- href.set.call(this, value);
1954
- if (sp) updateSearchParams(sp);
1955
- }
1956
- },
1957
- search: {
1958
- get: function () {
1959
- return search.get.call(this);
1960
- },
1961
- set: function (value) {
1962
- var sp = this._searchParams;
1963
- search.set.call(this, value);
1964
- if (sp) updateSearchParams(sp);
1965
- }
1966
- },
1967
- searchParams: {
1968
- get: function () {
1969
- verifySearchParams(this, Class);
1970
- return this._searchParams || createSearchParams(
1971
- this,
1972
- new URLSearchParams(this.search.slice(1))
1973
- );
1974
- },
1975
- set: function (sp) {
1976
- verifySearchParams(this, Class);
1977
- createSearchParams(this, sp);
1978
- }
1979
- }
1980
- }
1981
- );
1982
- }
1983
- }
1984
- ;
1985
- try {
1986
- upgradeClass(HTMLAnchorElement);
1987
- if (/^function|object$/.test(typeof URL) && URL.prototype)
1988
- upgradeClass(URL);
1989
- } catch (meh) {}
1990
- }(Object));
1991
-
1992
- }(self.URLSearchParams.prototype));
1993
- var URLSearchParams$1 = self.URLSearchParams;
1994
-
1995
1459
  /** @hidden */
1996
1460
 
1997
- const _log$2 = debug__default("squatch-js");
1461
+ var _log$3 = debug("squatch-js");
1998
1462
 
1999
- const isObject = item => typeof item === "object" && !Array.isArray(item);
1463
+ var isObject = item => typeof item === "object" && !Array.isArray(item);
2000
1464
 
2001
- const deepMerge = (target, source) => {
2002
- const isDeep = prop => isObject(source[prop]) && target.hasOwnProperty(prop) && isObject(target[prop]);
1465
+ var deepMerge = (target, source) => {
1466
+ var isDeep = prop => isObject(source[prop]) && target.hasOwnProperty(prop) && isObject(target[prop]);
2003
1467
 
2004
- const replaced = Object.getOwnPropertyNames(source).map(prop => ({
1468
+ var replaced = Object.getOwnPropertyNames(source).map(prop => ({
2005
1469
  [prop]: isDeep(prop) ? deepMerge(target[prop], source[prop]) : source[prop]
2006
1470
  })).reduce((a, b) => _extends({}, a, b), {});
2007
1471
  return _extends({}, target, replaced);
@@ -2035,19 +1499,19 @@ function getTopDomain() {
2035
1499
  }
2036
1500
 
2037
1501
  function _pushCookie() {
2038
- const queryString = window.location.search;
2039
- const urlParams = new URLSearchParams$1(queryString);
2040
- const refParam = urlParams.get("_saasquatch") || ""; // do nothing if no params
1502
+ var queryString = window.location.search;
1503
+ var urlParams = new URLSearchParams(queryString);
1504
+ var refParam = urlParams.get("_saasquatch") || ""; // do nothing if no params
2041
1505
 
2042
1506
  if (refParam) {
2043
- let paramsJSON = "",
1507
+ var paramsJSON = "",
2044
1508
  existingCookie = "",
2045
1509
  reEncodedCookie = "";
2046
1510
 
2047
1511
  try {
2048
1512
  paramsJSON = JSON.parse(b64decode(refParam));
2049
1513
  } catch (error) {
2050
- _log$2("Unable to decode params", error); // don't merge invalid params
1514
+ _log$3("Unable to decode params", error); // don't merge invalid params
2051
1515
 
2052
1516
 
2053
1517
  return;
@@ -2056,26 +1520,26 @@ function _pushCookie() {
2056
1520
  try {
2057
1521
  existingCookie = JSON.parse(b64decode(Cookies.get("_saasquatch")));
2058
1522
 
2059
- _log$2("existing cookie", existingCookie);
1523
+ _log$3("existing cookie", existingCookie);
2060
1524
  } catch (error) {
2061
- _log$2("Unable to retrieve cookie", error);
1525
+ _log$3("Unable to retrieve cookie", error);
2062
1526
  } // don't merge if there's no existing object
2063
1527
 
2064
1528
 
2065
1529
  try {
2066
- const domain = getTopDomain();
1530
+ var domain = getTopDomain();
2067
1531
 
2068
- _log$2("domain retrieved:", domain);
1532
+ _log$3("domain retrieved:", domain);
2069
1533
 
2070
1534
  if (existingCookie) {
2071
- const newCookie = deepMerge(existingCookie, paramsJSON);
1535
+ var newCookie = deepMerge(existingCookie, paramsJSON);
2072
1536
  reEncodedCookie = b64encode(JSON.stringify(newCookie));
2073
1537
 
2074
- _log$2("cookie to store:", newCookie);
1538
+ _log$3("cookie to store:", newCookie);
2075
1539
  } else {
2076
1540
  reEncodedCookie = b64encode(JSON.stringify(paramsJSON));
2077
1541
 
2078
- _log$2("cookie to store:", paramsJSON);
1542
+ _log$3("cookie to store:", paramsJSON);
2079
1543
  }
2080
1544
 
2081
1545
  Cookies.set("_saasquatch", reEncodedCookie, {
@@ -2086,52 +1550,52 @@ function _pushCookie() {
2086
1550
  path: "/"
2087
1551
  });
2088
1552
  } catch (error) {
2089
- _log$2("Unable to set cookie", error);
1553
+ _log$3("Unable to set cookie", error);
2090
1554
  }
2091
1555
  }
2092
1556
  }
2093
1557
 
2094
1558
  /** @hidden */
2095
1559
 
2096
- const _log$1 = debug__default("squatch-js");
1560
+ var _log$2 = debug("squatch-js");
2097
1561
 
2098
1562
  function _getAutoConfig(configIn) {
2099
- const queryString = window.location.search;
2100
- const urlParams = new URLSearchParams(queryString);
2101
- const refParam = urlParams.get("_saasquatchExtra") || "";
1563
+ var queryString = window.location.search;
1564
+ var urlParams = new URLSearchParams(queryString);
1565
+ var refParam = urlParams.get("_saasquatchExtra") || "";
2102
1566
 
2103
1567
  if (!refParam) {
2104
- _log$1("No _saasquatchExtra param");
1568
+ _log$2("No _saasquatchExtra param");
2105
1569
 
2106
1570
  return;
2107
1571
  }
2108
1572
 
2109
- let raw;
1573
+ var raw;
2110
1574
 
2111
1575
  try {
2112
1576
  raw = JSON.parse(b64decode(refParam));
2113
1577
  } catch (e) {
2114
- _log$1("Unable to decode _saasquatchExtra config");
1578
+ _log$2("Unable to decode _saasquatchExtra config");
2115
1579
 
2116
1580
  return;
2117
1581
  }
2118
1582
 
2119
- const {
1583
+ var {
2120
1584
  domain,
2121
1585
  tenantAlias,
2122
1586
  widgetConfig
2123
1587
  } = convertExtraToConfig(raw);
2124
1588
 
2125
1589
  if (!domain || !tenantAlias || !widgetConfig) {
2126
- _log$1("_saasquatchExtra did not have an expected structure");
1590
+ _log$2("_saasquatchExtra did not have an expected structure");
2127
1591
 
2128
1592
  return undefined;
2129
1593
  }
2130
1594
 
2131
- const {
1595
+ var {
2132
1596
  autoPopupWidgetType
2133
1597
  } = widgetConfig,
2134
- rest = _objectWithoutPropertiesLoose(widgetConfig, ["autoPopupWidgetType"]);
1598
+ rest = _objectWithoutPropertiesLoose(widgetConfig, ["autoPopupWidgetType"]);
2135
1599
 
2136
1600
  return {
2137
1601
  widgetConfig: _extends({
@@ -2146,19 +1610,19 @@ function _getAutoConfig(configIn) {
2146
1610
  })
2147
1611
  };
2148
1612
  }
2149
- /**
2150
- * Deconstructs _saasquatchExtra into domain, tenantAlias, and widgetConfig
2151
- * @param obj {Record<string, any>} Expected to be of the form `{ [appDomain]: { [tenantAlias]: { autoPopupWidgetType: [widgetType], [rest]?: ... } } }`
1613
+ /**
1614
+ * Deconstructs _saasquatchExtra into domain, tenantAlias, and widgetConfig
1615
+ * @param obj {Record<string, any>} Expected to be of the form `{ [appDomain]: { [tenantAlias]: { autoPopupWidgetType: [widgetType], [rest]?: ... } } }`
2152
1616
  */
2153
1617
 
2154
1618
  function convertExtraToConfig(obj) {
2155
1619
  var _obj$_domain;
2156
1620
 
2157
- const _domain = Object.keys(obj || {})[0];
2158
- const tenantAlias = Object.keys((obj == null ? void 0 : obj[_domain]) || {})[0];
2159
- const widgetConfig = obj == null ? void 0 : (_obj$_domain = obj[_domain]) == null ? void 0 : _obj$_domain[tenantAlias]; // domain in _saasquatchExtra doesn't contain "https://"
1621
+ var _domain = Object.keys(obj || {})[0];
1622
+ var tenantAlias = Object.keys((obj == null ? void 0 : obj[_domain]) || {})[0];
1623
+ var widgetConfig = obj == null ? void 0 : (_obj$_domain = obj[_domain]) == null ? void 0 : _obj$_domain[tenantAlias]; // domain in _saasquatchExtra doesn't contain "https://"
2160
1624
 
2161
- const domain = _domain ? `https://${_domain}` : undefined;
1625
+ var domain = _domain ? "https://" + _domain : undefined;
2162
1626
  return {
2163
1627
  domain,
2164
1628
  tenantAlias,
@@ -2166,9 +1630,240 @@ function convertExtraToConfig(obj) {
2166
1630
  };
2167
1631
  }
2168
1632
 
1633
+ var _log$1 = debug("squatch-js:decodeJwt");
1634
+
1635
+ function decodeUserJwt(tokenStr) {
1636
+ try {
1637
+ var _JSON$parse;
1638
+
1639
+ var base64Url = tokenStr.split(".")[1];
1640
+ if (base64Url === undefined) return null;
1641
+ var jsonStr = b64decode(base64Url);
1642
+ return (_JSON$parse = JSON.parse(jsonStr)) == null ? void 0 : _JSON$parse.user;
1643
+ } catch (e) {
1644
+ _log$1(e);
1645
+
1646
+ return null;
1647
+ }
1648
+ }
1649
+
1650
+ debug$1("sqh:DeclarativeWidget");
1651
+
1652
+ class DeclarativeWidget extends HTMLElement {
1653
+ constructor() {
1654
+ super();
1655
+ this.config = void 0;
1656
+ this.token = void 0;
1657
+ this.tenant = void 0;
1658
+ this.widgetType = void 0;
1659
+ this.widgetApi = void 0;
1660
+ this.analyticsApi = void 0;
1661
+ this.type = void 0;
1662
+ this.widgetInstance = void 0;
1663
+ this.frame = void 0;
1664
+ this.container = void 0;
1665
+ this.element = void 0;
1666
+
1667
+ this._setWidget = (template, config) => {
1668
+ var _this$config;
1669
+
1670
+ if (!this.widgetType) throw new Error("Widget was no specified");
1671
+ var Widget = this.type === "EMBED" ? EmbedWidget : PopupWidget;
1672
+ return new Widget({
1673
+ api: this.widgetApi,
1674
+ content: template,
1675
+ context: {
1676
+ type: config.type,
1677
+ engagementMedium: this.type
1678
+ },
1679
+ type: this.widgetType,
1680
+ domain: ((_this$config = this.config) == null ? void 0 : _this$config.domain) || DEFAULT_DOMAIN,
1681
+ npmCdn: DEFAULT_NPM_CDN,
1682
+ container: this.container || this
1683
+ });
1684
+ };
1685
+
1686
+ this.setErrorWidget = e => {
1687
+ var _this$config2;
1688
+
1689
+ var Widget = this.type === "EMBED" ? EmbedWidget : PopupWidget;
1690
+ return new Widget({
1691
+ api: this.widgetApi,
1692
+ content: "error",
1693
+ context: {
1694
+ type: "error"
1695
+ },
1696
+ type: "ERROR_WIDGET",
1697
+ domain: ((_this$config2 = this.config) == null ? void 0 : _this$config2.domain) || DEFAULT_DOMAIN,
1698
+ npmCdn: DEFAULT_NPM_CDN,
1699
+ container: this.container || this
1700
+ });
1701
+ };
1702
+
1703
+ this.show = this.open;
1704
+ this.hide = this.close;
1705
+ this.attachShadow({
1706
+ mode: "open"
1707
+ }).innerHTML = "<style>:host { display: contents; }</style><slot></slot>";
1708
+ this.config = window.squatchConfig;
1709
+ this.token = window.squatchToken;
1710
+ this.tenant = window.squatchTenant;
1711
+ this.container = this;
1712
+ }
1713
+
1714
+ _setupApis(config) {
1715
+ var _this$config3, _this$config4;
1716
+
1717
+ if (!this.tenant) throw new Error("Requires tenantAlias");
1718
+ this.widgetApi = new WidgetApi({
1719
+ tenantAlias: (config == null ? void 0 : config.tenantAlias) || this.tenant,
1720
+ domain: (config == null ? void 0 : config.domain) || ((_this$config3 = this.config) == null ? void 0 : _this$config3.domain) || DEFAULT_DOMAIN
1721
+ });
1722
+ this.analyticsApi = new AnalyticsApi({
1723
+ domain: (config == null ? void 0 : config.domain) || ((_this$config4 = this.config) == null ? void 0 : _this$config4.domain) || DEFAULT_DOMAIN
1724
+ });
1725
+ }
1726
+
1727
+ renderPasswordlessVariant() {
1728
+ var _configs$widgetConfig, _configs$widgetConfig2;
1729
+
1730
+ var configs = _getAutoConfig();
1731
+
1732
+ this._setupApis(configs == null ? void 0 : configs.squatchConfig);
1733
+
1734
+ return this.widgetApi.render({
1735
+ engagementMedium: (configs == null ? void 0 : (_configs$widgetConfig = configs.widgetConfig) == null ? void 0 : _configs$widgetConfig.engagementMedium) || this.type,
1736
+ widgetType: (configs == null ? void 0 : (_configs$widgetConfig2 = configs.widgetConfig) == null ? void 0 : _configs$widgetConfig2.widgetType) || this.widgetType
1737
+ }).then(res => this._setWidget(res.template, {
1738
+ type: "passwordless"
1739
+ })).catch(this.setErrorWidget);
1740
+ }
1741
+
1742
+ async renderUserUpsertVariant() {
1743
+ if (!this.widgetType) throw new Error("Widget must be specified");
1744
+
1745
+ this._setupApis();
1746
+
1747
+ var userObj = decodeUserJwt(this.token);
1748
+ if (!userObj) throw new Error("Could not load user information from jwt");
1749
+ var widgetInstance = await this.widgetApi.upsertUser({
1750
+ user: userObj,
1751
+ engagementMedium: this.type,
1752
+ widgetType: this.widgetType,
1753
+ jwt: this.token
1754
+ }).then(res => this._setWidget(res.template, {
1755
+ type: "upsert"
1756
+ })).catch(this.setErrorWidget);
1757
+ return widgetInstance;
1758
+ }
1759
+
1760
+ async getWidgetInstance() {
1761
+ var widgetInstance;
1762
+ this.widgetType = this.getAttribute("widget") || undefined;
1763
+ if (!this.widgetType) throw new Error("No widget has been specified");
1764
+
1765
+ if (!this.token) {
1766
+ widgetInstance = await this.renderPasswordlessVariant();
1767
+ } else {
1768
+ widgetInstance = await this.renderUserUpsertVariant();
1769
+ }
1770
+
1771
+ if (!widgetInstance) throw new Error("Could not create widget.");
1772
+ this.widgetInstance = widgetInstance;
1773
+ return widgetInstance;
1774
+ }
1775
+
1776
+ async renderWidget() {
1777
+ await this.getWidgetInstance();
1778
+ this.element = this.widgetInstance._findElement();
1779
+ this.frame = this.widgetInstance._createFrame();
1780
+ await this.widgetInstance.load(this.frame);
1781
+ }
1782
+
1783
+ open() {
1784
+ this.widgetInstance.open(this.frame);
1785
+ }
1786
+
1787
+ close() {
1788
+ this.widgetInstance.close(this.frame);
1789
+ }
1790
+
1791
+ }
1792
+
1793
+ class DeclarativeEmbedWidget extends DeclarativeWidget {
1794
+ constructor() {
1795
+ super();
1796
+ this.type = "EMBED";
1797
+ this.container = this.getAttribute("container") || this;
1798
+ }
1799
+
1800
+ static get observedAttributes() {
1801
+ return ["widget", "container"];
1802
+ }
1803
+
1804
+ attributeChangedCallback(attr, oldVal, newVal) {
1805
+ if (oldVal === newVal || !oldVal) return; // nothing to do
1806
+
1807
+ switch (attr) {
1808
+ case "widget":
1809
+ this.connectedCallback();
1810
+ break;
1811
+ // Specific to embed widgets
1812
+
1813
+ case "container":
1814
+ if (this.element) this.close();
1815
+ this.connectedCallback();
1816
+ break;
1817
+ }
1818
+ }
1819
+
1820
+ async connectedCallback() {
1821
+ var _ref, _this$shadowRoot;
1822
+
1823
+ await this.renderWidget();
1824
+ var slot = (_ref = this.shadowRoot && Array.from(this.shadowRoot.children)) == null ? void 0 : _ref.find(c => c.tagName === "SLOT");
1825
+ (_this$shadowRoot = this.shadowRoot) == null ? void 0 : _this$shadowRoot.removeChild(slot);
1826
+ }
1827
+
1828
+ }
1829
+ class DeclarativePopupWidget extends DeclarativeWidget {
1830
+ constructor() {
1831
+ super();
1832
+ this.type = "POPUP";
1833
+ this.addEventListener("click", e => {
1834
+ e.stopPropagation(); // SQUATCH-POPUP target means something in the shadowDOM was clicked (i.e. the dialog element)
1835
+
1836
+ if (e.target.tagName !== "SQUATCH-POPUP") this.open();
1837
+ });
1838
+ }
1839
+
1840
+ static get observedAttributes() {
1841
+ return ["widget", "id", "open"];
1842
+ }
1843
+
1844
+ attributeChangedCallback(attr, oldVal, newVal) {
1845
+ if (oldVal === newVal || !oldVal) return; // nothing to do
1846
+
1847
+ switch (attr) {
1848
+ case "open":
1849
+ case "widget":
1850
+ this.connectedCallback();
1851
+ break;
1852
+ }
1853
+ }
1854
+
1855
+ async connectedCallback() {
1856
+ await this.renderWidget();
1857
+ if (this.getAttribute("open") !== null) this.open();
1858
+ }
1859
+
1860
+ }
1861
+ window.customElements.define("squatch-embed", DeclarativeEmbedWidget);
1862
+ window.customElements.define("squatch-popup", DeclarativePopupWidget);
1863
+
2169
1864
  // @ts-check
2170
1865
  function help() {
2171
- console.log(`Having trouble using Squatch.js? Go to https://docs.referralsaasquatch.com/developer/ for tutorials, references and error codes.`);
1866
+ console.log("Having trouble using Squatch.js? Go to https://docs.referralsaasquatch.com/developer/ for tutorials, references and error codes.");
2172
1867
  }
2173
1868
 
2174
1869
  // @ts-check
@@ -2176,51 +1871,54 @@ function help() {
2176
1871
 
2177
1872
  /** @hidden */
2178
1873
 
2179
- const _log = debug__default("squatch-js");
1874
+ var _log = debug("squatch-js");
2180
1875
  /** @hidden */
2181
1876
 
2182
- let _api = null;
1877
+ var _api = null;
2183
1878
  /** @hidden */
2184
1879
 
2185
- let _widgets = null;
1880
+ var _widgets = null;
2186
1881
  /** @hidden */
2187
1882
 
2188
- let _events = null;
2189
- /**
2190
- * A static instance of the {@link WidgetApi} created when you call {@link #init init}.
2191
- *
2192
- * Read the {@link WidgetApi} docs.
2193
- *
2194
- * @returns WidgetApi static instance
1883
+ var _events = null;
1884
+ /**
1885
+ * A static instance of the {@link WidgetApi} created when you call {@link #init init}.
1886
+ *
1887
+ * Read the {@link WidgetApi} docs.
1888
+ *
1889
+ * @returns WidgetApi static instance
2195
1890
  */
2196
1891
 
2197
1892
  function api() {
1893
+ if (!_api) this.init({});
2198
1894
  return _api;
2199
1895
  }
2200
- /**
2201
- * A static instance of the {@link Widgets} created when you call {@link #init init}.
2202
- *
2203
- * Read the {@link Widgets} docs.
2204
- *
2205
- * @returns static instance
1896
+ /**
1897
+ * A static instance of the {@link Widgets} created when you call {@link #init init}.
1898
+ *
1899
+ * Read the {@link Widgets} docs.
1900
+ *
1901
+ * @returns static instance
2206
1902
  */
2207
1903
 
2208
1904
  function widgets() {
1905
+ if (!_widgets) this.init({});
2209
1906
  return _widgets;
2210
1907
  }
2211
- /**
2212
- * A static instance of the {@link EventsApi} created when you call {@link #init init}.
2213
- *
2214
- * Read the {@link EventsApi} docs.
2215
- *
2216
- * @returns EventsApi static instance
1908
+ /**
1909
+ * A static instance of the {@link EventsApi} created when you call {@link #init init}.
1910
+ *
1911
+ * Read the {@link EventsApi} docs.
1912
+ *
1913
+ * @returns EventsApi static instance
2217
1914
  */
2218
1915
 
2219
1916
  function events() {
1917
+ if (!_events) this.init({});
2220
1918
  return _events;
2221
1919
  }
2222
- /**
2223
- * Entry-point for high level API to render a widget using the instance of {@link Widgets} created when you call {@link #init init}.
1920
+ /**
1921
+ * Entry-point for high level API to render a widget using the instance of {@link Widgets} created when you call {@link #init init}.
2224
1922
  */
2225
1923
 
2226
1924
  function widget(widgetConfig) {
@@ -2228,21 +1926,17 @@ function widget(widgetConfig) {
2228
1926
 
2229
1927
  return (_widgets2 = widgets()) == null ? void 0 : _widgets2.render(widgetConfig);
2230
1928
  }
2231
- /**
2232
- * Extracts widget configuration from `_saasquatchExtra` UTM parameter. Initialises `squatch` and renders the widget as a {@link PopupWidget} via static instanct of {@link Widgets}.
1929
+ /**
1930
+ * Extracts widget configuration from `_saasquatchExtra` UTM parameter. Initialises `squatch` and renders the widget as a {@link PopupWidget} via static instanct of {@link Widgets}.
2233
1931
  */
2234
1932
 
2235
1933
  function _auto(configIn) {
2236
- console.log({
2237
- configIn
2238
- });
2239
-
2240
- const configs = _getAutoConfig(configIn);
1934
+ var configs = _getAutoConfig(configIn);
2241
1935
 
2242
1936
  if (configs) {
2243
1937
  var _widgets3;
2244
1938
 
2245
- const {
1939
+ var {
2246
1940
  squatchConfig,
2247
1941
  widgetConfig
2248
1942
  } = configs;
@@ -2250,25 +1944,25 @@ function _auto(configIn) {
2250
1944
  return (_widgets3 = widgets()) == null ? void 0 : _widgets3.render(widgetConfig);
2251
1945
  }
2252
1946
  }
2253
- /**
2254
- * Initializes the static `squatch` global. This sets up:
2255
- *
2256
- * - `squatch.api()` a static instance of the {@link WidgetApi}
2257
- * - `squatch.widgets()` a static instance of {@link Widgets}
2258
- * - `squatch.events()` a static instance of {@link EventsApi}
2259
- *
2260
- * @param config Configuration details
2261
- *
2262
- * @example
2263
- * squatch.init({tenantAlias:'test_basbtabstq51v'});
1947
+ /**
1948
+ * Initializes the static `squatch` global. This sets up:
1949
+ *
1950
+ * - `squatch.api()` a static instance of the {@link WidgetApi}
1951
+ * - `squatch.widgets()` a static instance of {@link Widgets}
1952
+ * - `squatch.events()` a static instance of {@link EventsApi}
1953
+ *
1954
+ * @param config Configuration details
1955
+ *
1956
+ * @example
1957
+ * squatch.init({tenantAlias:'test_basbtabstq51v'});
2264
1958
  */
2265
1959
 
2266
1960
  function init(configIn) {
2267
- const raw = configIn;
2268
- const config = validateConfig(raw);
1961
+ var raw = configIn;
1962
+ var config = validateConfig(raw);
2269
1963
 
2270
1964
  if (config.tenantAlias.match("^test") || config.debug) {
2271
- debug__default.enable("squatch-js*");
1965
+ debug.enable("squatch-js*");
2272
1966
  }
2273
1967
 
2274
1968
  _log("initializing ...");
@@ -2283,71 +1977,65 @@ function init(configIn) {
2283
1977
 
2284
1978
  _log("Events API instance", _events);
2285
1979
  }
2286
- /**
2287
- * Squatch.js can't start safely making operations until it's "ready". This
2288
- * function detects that state.
2289
- *
2290
- * @param fn A callback once Squatch.js is ready.
2291
- *
2292
- * @example
2293
- * squatch.ready(function() {
2294
- * console.log("ready!");
2295
- * squatch.api().upsertUser();
2296
- * });
1980
+ /**
1981
+ * Squatch.js can't start safely making operations until it's "ready". This
1982
+ * function detects that state.
1983
+ *
1984
+ * @param fn A callback once Squatch.js is ready.
1985
+ *
1986
+ * @example
1987
+ * squatch.ready(function() {
1988
+ * console.log("ready!");
1989
+ * squatch.api().upsertUser();
1990
+ * });
2297
1991
  */
2298
1992
 
2299
1993
  function ready(fn) {
2300
- console.log({
2301
- _auto: window.squatch._auto()
2302
- });
2303
-
2304
- window.squatch._auto();
2305
-
2306
1994
  fn();
2307
1995
  }
2308
- /**
2309
- * Autofills a referral code into an element when someone has been referred.
2310
- * Uses {@link WidgetApi.squatchReferralCookie} behind the scenes.
2311
- *
2312
- * @param {string} selector Element class/id
2313
- * @returns {void}
1996
+ /**
1997
+ * Autofills a referral code into an element when someone has been referred.
1998
+ * Uses {@link WidgetApi.squatchReferralCookie} behind the scenes.
1999
+ *
2000
+ * @param {string} selector Element class/id
2001
+ * @returns {void}
2314
2002
  */
2315
2003
 
2316
2004
  function autofill(selector) {
2317
2005
  // @ts-ignore -- will throw occasionally throw a null pointer exception at runtime
2318
2006
  widgets().autofill(selector);
2319
2007
  }
2320
- /**
2321
- * Overrides the default function that submits the user email. If you have
2322
- * Security enabled, the email needs to be signed before it's submitted.
2323
- *
2324
- * @param {function} fn Callback function for the 'submit_email' event.
2325
- * @returns {void}
2326
- *
2327
- * @example
2328
- * squatch.submitEmail(function(target, widget, email) {
2329
- * // Sign email and generate jwt token
2330
- * var jwt = 'token';
2331
- * widget.reload(email, jwt);
2332
- * });
2008
+ /**
2009
+ * Overrides the default function that submits the user email. If you have
2010
+ * Security enabled, the email needs to be signed before it's submitted.
2011
+ *
2012
+ * @param {function} fn Callback function for the 'submit_email' event.
2013
+ * @returns {void}
2014
+ *
2015
+ * @example
2016
+ * squatch.submitEmail(function(target, widget, email) {
2017
+ * // Sign email and generate jwt token
2018
+ * var jwt = 'token';
2019
+ * widget.reload(email, jwt);
2020
+ * });
2333
2021
  */
2334
2022
 
2335
2023
  function submitEmail(fn) {
2336
2024
  // @ts-ignore -- will throw occasionally throw a null pointer exception at runtime
2337
2025
  widgets().submitEmail(fn);
2338
2026
  }
2339
- /**
2340
- * Manually set the _saasquatch cookie as a 1st party cookie if available as a URL parameter on the current page.
2341
- * This runs automatically immediately when squatch-js is loaded, except when window.SaaSquatchDoNotAutoDrop is true.
2342
- * Use this function manually if you have a single page application or custom routing that causes the `_saasquatch` URL parameter to not be set when Squatch.js loads.
2027
+ /**
2028
+ * Manually set the _saasquatch cookie as a 1st party cookie if available as a URL parameter on the current page.
2029
+ * This runs automatically immediately when squatch-js is loaded, except when window.SaaSquatchDoNotAutoDrop is true.
2030
+ * Use this function manually if you have a single page application or custom routing that causes the `_saasquatch` URL parameter to not be set when Squatch.js loads.
2343
2031
 
2344
- * It is safe to run this function multiple times. If the `_saasquatch` URL parameter is invalid or missing it will not clear the 1st party cookie.
2032
+ * It is safe to run this function multiple times. If the `_saasquatch` URL parameter is invalid or missing it will not clear the 1st party cookie.
2345
2033
 
2346
- *
2347
- * @returns {void}
2348
- *
2349
- * @example
2350
- * squatch.pushCookie();
2034
+ *
2035
+ * @returns {void}
2036
+ *
2037
+ * @example
2038
+ * squatch.pushCookie();
2351
2039
  */
2352
2040
 
2353
2041
  function pushCookie() {
@@ -2360,5 +2048,5 @@ if (typeof document !== "undefined" && !window.SaaSquatchDoNotAutoDrop) {
2360
2048
 
2361
2049
  if (typeof document !== "undefined") asyncLoad();
2362
2050
 
2363
- export { CtaWidget, EmbedWidget, PopupWidget, WidgetApi, Widgets, _auto, api, autofill, events, help, init, pushCookie, ready, submitEmail, widget, widgets };
2051
+ export { DeclarativeEmbedWidget, DeclarativePopupWidget, EmbedWidget, PopupWidget, WidgetApi, Widgets, _auto, api, autofill, events, help, init, pushCookie, ready, submitEmail, widget, widgets };
2364
2052
  //# sourceMappingURL=squatch.esm.js.map