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

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