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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,63 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
10
10
  - Added custom web-components `squatch-embed` and `squatch-popup` for easier widget rendering.
11
11
  - Support for additional namespacing of squatchjs
12
12
 
13
+ ## [2.6.0] - 2023-08-23
14
+
15
+ ### Added
16
+
17
+ - SquatchJS now supports declarative widget initialization
18
+
19
+ - For rendering widgets and API calls, squatchjs respects configurations set on the following:
20
+
21
+ - `window.squatchToken`: Signed JWT for calls to the SaaSquatch API -- [How to generate valid JWT Tokens](https://docs.saasquatch.com/topics/json-web-tokens#example-building-the-jwt)
22
+ - `window.squatchTenant`: SaaSquatch tenant alias
23
+ - `window.squatchConfig`: Additional configuration overrides (Optional)
24
+ - debug: Turn on console debugging (Default: false)
25
+ - `window.squatchOnReady`: Declarative on ready function to be run when the squatch-js module has finished loading
26
+
27
+ - Note: If window.squatchToken is undefined, widgets will be rendered as [Instant Access widgets.](https://docs.saasquatch.com/topics/widget-types#instant-access-widgets)
28
+
29
+ - Widget components added:
30
+
31
+ - `<squatch-embed></squatch-embed>`
32
+
33
+ - widget: Specifies the SaaSquatch widgetType identifier of the desired widget
34
+ - Required
35
+ - Changing this attribute's value causes the widget to reload
36
+ - container: A CSS selector for a container element to use as the parent of the widget's iframe
37
+ - Default: null
38
+ - Note, if no container is specified, the widget iframe will attach to the shadow DOM of squatch-embed
39
+ - locale: Locale that determines the widget translation displayed. Should be of the form "xx_XX"
40
+ - Default: Browser's current locale
41
+ - Changing this attribute's value causes the widget to reload
42
+
43
+ - `<squatch-popup></squatch-popup>`
44
+ - widget: string: Specifies the SaaSquatch widgetType identifier of the desired widget
45
+ - Required
46
+ - open: boolean: Whether to the popup is open when loaded into the page
47
+ - Default: false
48
+ - container: A CSS selector for a container element to use as the parent of the widget's iframe.
49
+ - Default: null
50
+ - Note, if no container is specified, the widget iframe will attach to the shadow DOM of squatch-embed.
51
+ - locale: Locale that determines the widget translation displayed. Should be of the form "xx_XX".
52
+ - Default: Browser's current locale
53
+ - Changing this attribute's value causes the widget to reload.
54
+
55
+ ### Removed
56
+
57
+ - Deprecated api functions have been removed
58
+ - Removed functions:
59
+ - `squatch.api().invite()`
60
+ - `squatch.submitEmail()`
61
+ - Removed widgets:
62
+ - `CtaWidget`
63
+
64
+ ### Changed
65
+
66
+ - Bundle size reduced significantly thanks to the removal of deprecated features and other optimizations
67
+ - Before: 19.75 kB
68
+ - After: 12.06 kB
69
+
13
70
  ## [2.5.0] - 2023-05-16
14
71
 
15
72
  ### Removed
@@ -33,7 +90,7 @@ var initObj = {
33
90
  squatch
34
91
  .widget(initObj)
35
92
  .then(function (response) {
36
- const widget = response.widget
93
+ const widget = response.widget;
37
94
  })
38
95
  .catch(function (error) {
39
96
  console.log(error);
@@ -47,6 +104,7 @@ squatch
47
104
  ## [2.4.3] - 2023-04-20
48
105
 
49
106
  ### Changed
107
+
50
108
  - Updated license copyright to be in line with SaaSquatch open-source policy.
51
109
 
52
110
  ## [2.4.2] - 2023-04-10
@@ -290,7 +348,8 @@ No release notes.
290
348
 
291
349
  No release notes.
292
350
 
293
- [unreleased]: https://github.com/saasquatch/squatch-js/compare/@saasquatch%2Fsquatch-js@2.5.0...HEAD
351
+ [unreleased]: https://github.com/saasquatch/squatch-js/compare/@saasquatch%2Fsquatch-js@2.6.0...HEAD
352
+ [2.6.0]: https://github.com/saasquatch/squatch-js/compare/@saasquatch%2Fsquatch-js@2.5.0...@saasquatch%2Fsquatch-js@2.6.0
294
353
  [2.5.0]: https://github.com/saasquatch/squatch-js/compare/@saasquatch%2Fsquatch-js@2.4.1...@saasquatch%2Fsquatch-js@2.5.0
295
354
  [2.4.3]: https://github.com/saasquatch/squatch-js/compare/@saasquatch%2Fsquatch-js@2.4.2...@saasquatch%2Fsquatch-js@2.4.3
296
355
  [2.4.2]: https://github.com/saasquatch/squatch-js/compare/@saasquatch%2Fsquatch-js@2.4.1...@saasquatch%2Fsquatch-js@2.4.2
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  - [Install the library](#install-the-library)
5
5
  - [Getting Started](#getting-started)
6
6
  - [Data Only Operations](#data-only-operations)
7
- - [Create/upsert users without loading a widget.](#createupsert-users-without-loading-a-widget)
7
+ - [Create/upsert users without loading a widget.](#createupsert-users-without-loading-a-widget)
8
8
  - [Get Referral Cookie Code](#get-referral-cookie-code)
9
9
  - [Install via NPM and Webpack (advanced)](#install-via-npm-and-webpack-advanced)
10
10
  - [Component API:](#component-api)
@@ -15,14 +15,28 @@
15
15
  - [Contributing](#contributing)
16
16
  - [Support](#support)
17
17
 
18
-
19
18
  ## Install the library
20
19
 
21
20
  To integrate any SaaSquatch program to your website or web app, copy/paste this snippet of JavaScript above the `</head>` tag of your page:
22
21
 
23
22
  ```html
24
23
  <script type="text/javascript">
25
- !function(a,b){a("squatch","https://fast.ssqt.io/squatch-js@2",b)}(function(a,b,c){var d,e,f;c["_"+a]={},c[a]={},c[a].ready=function(b){c["_" + a].ready = c["_" + a].ready || [];c["_" + a].ready.push(b);},e=document.createElement("script"),e.async=1,e.src=b,f=document.getElementsByTagName("script")[0],f.parentNode.insertBefore(e,f)},this);
24
+ !(function (a, b) {
25
+ a("squatch", "https://fast.ssqt.io/squatch-js@2", b);
26
+ })(function (a, b, c) {
27
+ var d, e, f;
28
+ (c["_" + a] = {}),
29
+ (c[a] = {}),
30
+ (c[a].ready = function (b) {
31
+ c["_" + a].ready = c["_" + a].ready || [];
32
+ c["_" + a].ready.push(b);
33
+ }),
34
+ (e = document.createElement("script")),
35
+ (e.async = 1),
36
+ (e.src = b),
37
+ (f = document.getElementsByTagName("script")[0]),
38
+ f.parentNode.insertBefore(e, f);
39
+ }, this);
26
40
  </script>
27
41
  ```
28
42
 
@@ -32,32 +46,54 @@ Or load the library synchronously from our CDN:
32
46
  <script src="https://fast.ssqt.io/squatch-js@2" type="text/javascript"></script>
33
47
  ```
34
48
 
35
-
36
49
  ## Getting Started
37
50
 
38
51
  Include either of the squatchjs generated web-components in your page's HTML to render your desired widget:
52
+
39
53
  ```html
40
54
  <!-- EMBED WIDGET -->
41
- <squatch-embed widget="WIDGET_TYPE"><!-- Widget is rendered here --></squatch-embed>
55
+ <squatch-embed widget="WIDGET_TYPE"
56
+ ><!-- Widget is rendered here --></squatch-embed
57
+ >
42
58
 
43
59
  <!-- POPUP WIDGET -->
44
- <squatch-popup widget="WIDGET_TYPE"><!-- Widget is rendered here --></squatch-popup>
60
+ <squatch-popup widget="WIDGET_TYPE"
61
+ ><!-- Widget is rendered here --></squatch-popup
62
+ >
45
63
  ```
46
- For rendering widgets and API calls, squatchjs respects configurations set on the following:
47
- - `window.squatchToken`: Signed JWT for calls to the SaaSquatch API -- [How to generate valid JWT Tokens](https://docs.saasquatch.com/topics/json-web-tokens#example-building-the-jwt)
48
- - `window.squatchTenant`: SaaSquatch tenant alias
49
- - `window.squatchConfig`: Additional configuration overrides (Optional)
50
- - `debug`: Turn on console debugging (Default: `false`)
51
-
52
- **Note**: If `window.squatchToken` is undefined, widgets will be rendered as [Instant Access widgets](https://docs.saasquatch.com/topics/widget-types#instant-access-widgets).
53
-
54
64
 
65
+ For rendering widgets and API calls, squatchjs respects configurations set on the following:
55
66
 
67
+ - `window.squatchToken`: Signed JWT for calls to the SaaSquatch API -- [How to generate valid JWT Tokens](https://docs.saasquatch.com/topics/json-web-tokens#example-building-the-jwt)
68
+ - `window.squatchTenant`: SaaSquatch tenant alias
69
+ - `window.squatchConfig`: Additional configuration overrides (Optional)
70
+ - `debug`: Turn on console debugging (Default: `false`)
71
+ - `window.squatchOnReady`: Declarative on ready function to be run when the squatch-js module has finished loading
72
+
73
+ ```html
74
+ <script type="text/javascript">
75
+ window.squatchOnReady = () => {
76
+ squatch.widgets().upsertUser({
77
+ user: { // Object (required)
78
+ id: 'USER_ID', // String (required)
79
+ accountId: 'USER_ACCOUNT_ID', // String (required)
80
+ email: 'USER_EMAIL', // String (optional)
81
+ firstName: 'USER_FIRST_NAME', // String (optional)
82
+ lastName: 'USER_LAST_NAME', // String (optional)
83
+
84
+ ...
85
+ },
86
+ engagementMedium: 'EMBED', // String (optional: POPUP, EMBED)
87
+ widgetType: 'p/PROGRAM-ID/w/referrerWidget', // Update PROGRAM-ID
88
+ });
89
+ }
90
+ </script>
91
+ ```
56
92
 
93
+ **Note**: If `window.squatchToken` is undefined, widgets will be rendered as [Instant Access widgets](https://docs.saasquatch.com/topics/widget-types#instant-access-widgets).
57
94
 
58
95
  ## Data Only Operations
59
96
 
60
-
61
97
  #### Create/upsert users without loading a widget.
62
98
 
63
99
  ```html
@@ -93,27 +129,28 @@ For rendering widgets and API calls, squatchjs respects configurations set on th
93
129
  ```
94
130
 
95
131
  ## Get Referral Cookie Code
132
+
96
133
  You can also use the `api()` function to call the WidgetApi methods directly.
97
134
 
98
135
  ```html
99
136
  <script type="text/javascript">
100
- squatch.ready(function(){
137
+ squatch.ready(function () {
138
+ var element = document.getElementById("my_coupon");
101
139
 
102
- var element = document.getElementById('my_coupon');
103
-
104
- squatch.api().squatchReferralCookie().then(function(response) {
105
- /* `response.codes` looks like `{"program_id":"NEWCO", "friend_program":"BOB"}` */
106
-
107
- element.value = response.codes["program-id"];
108
- });
140
+ squatch
141
+ .api()
142
+ .squatchReferralCookie()
143
+ .then(function (response) {
144
+ /* `response.codes` looks like `{"program_id":"NEWCO", "friend_program":"BOB"}` */
109
145
 
146
+ element.value = response.codes["program-id"];
147
+ });
110
148
  });
111
149
  </script>
112
150
  ```
113
151
 
114
152
  Want more control? Visit our [guide](https://github.com/saasquatch/squatch-js/blob/master/docs/docs.md).
115
153
 
116
-
117
154
  ## Install via NPM and Webpack (advanced)
118
155
 
119
156
  Squatch.js can also be installed via NPM and bundled into your application with Webpack.
@@ -139,6 +176,7 @@ squatch.api().upsertUser({...});
139
176
  ## Component API:
140
177
 
141
178
  ### `squatch-embed`
179
+
142
180
  ```html
143
181
  <squatch-embed widget="WIDGET_TYPE" [ container="#selector" | locale="en_US" ]>
144
182
  <!-- Children of squatch-embed act as a loading state -->
@@ -149,7 +187,7 @@ squatch.api().upsertUser({...});
149
187
  - `widget`: Specifies the SaaSquatch `widgetType` identifier of the desired widget
150
188
  - Required
151
189
  - Changing this attribute's value causes the widget to reload.
152
- - `container`: A CSS selector for a container element to use as the parent of the widget's iframe.
190
+ - `container`: A CSS selector for a container element to use as the parent of the widget's iframe.
153
191
  - Default: `null`
154
192
  - Note, if no container is specified, the widget iframe will attach to the shadow DOM of `squatch-embed`.
155
193
  - `locale`: Locale that determines the widget translation displayed. Should be of the form "xx_XX".
@@ -157,10 +195,20 @@ squatch.api().upsertUser({...});
157
195
  - Changing this attribute's value causes the widget to reload.
158
196
 
159
197
  ### `squatch-popup`
198
+
160
199
  ```html
161
- <squatch-embed widget="WIDGET_TYPE" [ open | container="#selector" | locale="en_US" ]>
200
+ <squatch-embed
201
+ widget="WIDGET_TYPE"
202
+ [
203
+ open
204
+ |
205
+ container="#selector"
206
+ |
207
+ locale="en_US"
208
+ ]
209
+ >
162
210
  <!-- Clicking a child of squatch-popup opens the popup -->
163
- <button>Click me to open</button>
211
+ <button>Click me to open</button>
164
212
  </squatch-embed>
165
213
  ```
166
214
 
@@ -168,7 +216,7 @@ squatch.api().upsertUser({...});
168
216
  - Required
169
217
  - `open: boolean`: Whether to the popup is open when loaded into the page
170
218
  - Default: `false`
171
- - `container`: A CSS selector for a container element to use as the parent of the widget's iframe.
219
+ - `container`: A CSS selector for a container element to use as the parent of the widget's iframe.
172
220
  - Default: `null`
173
221
  - Note, if no container is specified, the widget iframe will attach to the shadow DOM of `squatch-embed`.
174
222
  - `locale`: Locale that determines the widget translation displayed. Should be of the form "xx_XX".
@@ -178,6 +226,7 @@ squatch.api().upsertUser({...});
178
226
  ## Legacy
179
227
 
180
228
  ### Rendering a widget via Widgets API
229
+
181
230
  Note: `engagementMedium` is required in the `squatch.widgets()` functions if you want to load the widget. Otherwise, squatch.js will look for your portal settings and render the widget that's mapped to the URL where this snippet is included.
182
231
 
183
232
  ```html
@@ -191,7 +240,7 @@ Note: `engagementMedium` is required in the `squatch.widgets()` functions if you
191
240
  email: 'USER_EMAIL', // String (optional)
192
241
  firstName: 'USER_FIRST_NAME', // String (optional)
193
242
  lastName: 'USER_LAST_NAME', // String (optional)
194
-
243
+
195
244
  ...
196
245
  },
197
246
  engagementMedium: 'EMBED', // String (optional: POPUP, EMBED)
@@ -202,7 +251,9 @@ Note: `engagementMedium` is required in the `squatch.widgets()` functions if you
202
251
  ```
203
252
 
204
253
  ## Contributing
254
+
205
255
  This is an open source project! If you are interested in contributing please look at [contributing guidelines](CONTRIBUTING.md) first.
206
256
 
207
257
  ## Support
258
+
208
259
  Shoot us an email at [support@saasqt.ch](mailto:support@saasqt.ch) if you need help!
@@ -60,4 +60,5 @@ export default class WidgetApi {
60
60
  * @return {Promise<ReferralCookie>} code referral code if true.
61
61
  */
62
62
  squatchReferralCookie(): Promise<ReferralCookie>;
63
+ referralCookie: () => Promise<ReferralCookie>;
63
64
  }
@@ -213,6 +213,7 @@ class WidgetApi {
213
213
  this.tenantAlias = void 0;
214
214
  this.domain = void 0;
215
215
  this.npmCdn = void 0;
216
+ this.referralCookie = this.squatchReferralCookie;
216
217
  var raw = config;
217
218
  var clean = validateConfig(raw);
218
219
  this.tenantAlias = clean.tenantAlias;
@@ -421,6 +422,8 @@ var _log$8 = debug("squatch-js:widget");
421
422
 
422
423
  class Widget {
423
424
  constructor(params) {
425
+ var _params$context;
426
+
424
427
  this.type = void 0;
425
428
  this.content = void 0;
426
429
  this.analyticsApi = void 0;
@@ -439,7 +442,7 @@ class Widget {
439
442
  domain: params.domain
440
443
  });
441
444
  this.context = params.context;
442
- this.container = params.container || params.context.container;
445
+ this.container = ((_params$context = params.context) == null ? void 0 : _params$context.container) || params.container;
443
446
  }
444
447
 
445
448
  _findElement() {
@@ -740,10 +743,19 @@ class EmbedWidget extends Widget {
740
743
  }
741
744
 
742
745
  async load() {
746
+ var _this$context;
747
+
743
748
  var frame = this._createFrame();
744
749
 
745
750
  var element = this._findElement();
746
751
 
752
+ if ((_this$context = this.context) != null && _this$context.container) {
753
+ // Custom container is used
754
+ element.style.visibility = "hidden";
755
+ element.style.height = "0";
756
+ element.style["overflow-y"] = "hidden";
757
+ }
758
+
747
759
  if (this.container) {
748
760
  if (element.shadowRoot) {
749
761
  var _element$shadowRoot$l;
@@ -791,6 +803,7 @@ class EmbedWidget extends Widget {
791
803
  } = entry.contentRect; // @ts-ignore -- number will be cast to string by browsers
792
804
 
793
805
  frame.height = height;
806
+ console.log("RESIZE");
794
807
  }
795
808
  });
796
809
  var container = await this._findInnerContainer(frame);
@@ -1486,27 +1499,27 @@ function _validateTrackOptions(raw) {
1486
1499
  /** @hidden */
1487
1500
 
1488
1501
  function asyncLoad() {
1502
+ var _window;
1503
+
1489
1504
  var namespace = window[IMPACT_NAMESPACE] ? IMPACT_NAMESPACE : DEFAULT_NAMESPACE;
1490
- var loaded = window[namespace] || null;
1491
- var cached = window["_" + namespace] || null;
1505
+ var cached = ((_window = window["_" + namespace]) == null ? void 0 : _window.ready) || [];
1492
1506
  var declarativeCache = window.impactOnReady || window.squatchOnReady;
1493
- setTimeout(() => window[IMPACT_NAMESPACE] = window[DEFAULT_NAMESPACE], 0);
1494
- if (declarativeCache) setTimeout(() => declarativeCache(), 0);
1507
+ var readyFns = [...cached, declarativeCache].filter(a => !!a); // Run all of this in a setTimeout because we need to wait for the squatch module to finish loading
1495
1508
 
1496
- if (loaded) {
1497
- if (cached) (cached.ready || []).forEach(cb => setTimeout(() => cb(), 0));
1498
- setTimeout(() => {
1499
- window.squatch._auto();
1500
- }, 0); // @ts-ignore -- intentionally deletes `_squatch` to cleanup initialization
1509
+ setTimeout(() => {
1510
+ // Exit early if module wasn't loaded onto window
1511
+ if (!window[DEFAULT_NAMESPACE]) return; // Set window.impact as an alias for window.squatch.
1501
1512
 
1502
- window["_" + namespace] = undefined;
1513
+ window[IMPACT_NAMESPACE] = window[DEFAULT_NAMESPACE]; // Run all the ready functions in a set timeout to they happen after namespace aliasing.
1503
1514
 
1504
- try {
1505
- delete window["_" + namespace];
1506
- } catch (e) {
1507
- throw e;
1508
- }
1509
- }
1515
+ readyFns.forEach(cb => cb()); // Perform auto popup
1516
+
1517
+ window[DEFAULT_NAMESPACE]._auto(); // @ts-ignore -- intentionally deletes `_squatch` to cleanup initialization
1518
+
1519
+
1520
+ window["_" + namespace] = undefined;
1521
+ delete window["_" + namespace];
1522
+ }, 0);
1510
1523
  }
1511
1524
 
1512
1525
  /** @hidden */
@@ -1786,16 +1799,17 @@ class DeclarativeWidget extends HTMLElement {
1786
1799
  context: {
1787
1800
  type: config.type,
1788
1801
  user: config.user,
1789
- container: this.container || this,
1802
+ container: this.container || undefined,
1790
1803
  engagementMedium: this.type
1791
1804
  },
1792
1805
  type: this.widgetType,
1793
1806
  domain: ((_this$config = this.config) == null ? void 0 : _this$config.domain) || DEFAULT_DOMAIN,
1794
- npmCdn: DEFAULT_NPM_CDN
1807
+ npmCdn: DEFAULT_NPM_CDN,
1808
+ container: this
1795
1809
  };
1796
1810
 
1797
1811
  if (this.type === "EMBED") {
1798
- return new EmbedWidget(params, params.context.container);
1812
+ return new EmbedWidget(params);
1799
1813
  } else {
1800
1814
  var useFirstChildTrigger = this.firstChild ? null : undefined;
1801
1815
  return new PopupWidget(params, useFirstChildTrigger);
@@ -1810,15 +1824,16 @@ class DeclarativeWidget extends HTMLElement {
1810
1824
  content: "error",
1811
1825
  context: {
1812
1826
  type: "error",
1813
- container: this.container || this
1827
+ container: this.container || undefined
1814
1828
  },
1815
1829
  type: "ERROR_WIDGET",
1816
1830
  domain: ((_this$config2 = this.config) == null ? void 0 : _this$config2.domain) || DEFAULT_DOMAIN,
1817
- npmCdn: DEFAULT_NPM_CDN
1831
+ npmCdn: DEFAULT_NPM_CDN,
1832
+ container: this
1818
1833
  };
1819
1834
 
1820
1835
  if (this.type === "EMBED") {
1821
- return new EmbedWidget(params, params.context.container);
1836
+ return new EmbedWidget(params);
1822
1837
  } else {
1823
1838
  var useFirstChildTrigger = this.firstChild ? null : undefined;
1824
1839
  return new PopupWidget(params, useFirstChildTrigger);
@@ -1830,7 +1845,7 @@ class DeclarativeWidget extends HTMLElement {
1830
1845
  this.hide = this.close;
1831
1846
  this.attachShadow({
1832
1847
  mode: "open"
1833
- }).innerHTML = "<style>:host { display: contents; }</style><slot></slot>";
1848
+ }).innerHTML = "<style>:host { display: block; }</style><slot></slot>";
1834
1849
  this.config = getConfig();
1835
1850
  this.token = getToken();
1836
1851
  this.tenant = window.squatchTenant;
@@ -1906,6 +1921,7 @@ class DeclarativeWidget extends HTMLElement {
1906
1921
  }
1907
1922
 
1908
1923
  this.widgetInstance = widgetInstance;
1924
+ if (this.widgetInstance) this.dispatchEvent(new CustomEvent("sq:widget-loaded"));
1909
1925
  return widgetInstance;
1910
1926
  }
1911
1927
  /**
@@ -1985,11 +2001,12 @@ class DeclarativeEmbedWidget extends DeclarativeWidget {
1985
2001
  async connectedCallback() {
1986
2002
  var _ref, _this$shadowRoot;
1987
2003
 
1988
- this.container = this.getAttribute("container") || this;
2004
+ this.loaded = true;
2005
+ this.container = this.getAttribute("container");
1989
2006
  await this.renderWidget();
1990
2007
  var slot = (_ref = this.shadowRoot && Array.from(this.shadowRoot.children)) == null ? void 0 : _ref.find(c => c.tagName === "SLOT");
1991
2008
  if (slot) (_this$shadowRoot = this.shadowRoot) == null ? void 0 : _this$shadowRoot.removeChild(slot);
1992
- this.loaded = true;
2009
+ if (this.getAttribute("open") !== null) this.open();
1993
2010
  }
1994
2011
 
1995
2012
  }
@@ -2036,10 +2053,10 @@ class DeclarativePopupWidget extends DeclarativeWidget {
2036
2053
  }
2037
2054
 
2038
2055
  async connectedCallback() {
2039
- this.container = this.getAttribute("container") || this;
2056
+ this.loaded = true;
2057
+ this.container = this.getAttribute("container");
2040
2058
  await this.renderWidget();
2041
2059
  if (this.getAttribute("open") !== null) this.open();
2042
- this.loaded = true;
2043
2060
  }
2044
2061
 
2045
2062
  }
@@ -2052,10 +2069,10 @@ class ImpactEmbed extends DeclarativeEmbedWidget {}
2052
2069
 
2053
2070
  class ImpactPopup extends DeclarativePopupWidget {}
2054
2071
 
2055
- window.customElements.define("squatch-embed", SquatchEmbed);
2056
- window.customElements.define("impact-embed", ImpactEmbed);
2057
- window.customElements.define("squatch-popup", SquatchPopup);
2058
- window.customElements.define("impact-popup", ImpactPopup);
2072
+ if (!window.customElements.get("squatch-embed")) window.customElements.define("squatch-embed", SquatchEmbed);
2073
+ if (!window.customElements.get("impact-embed")) window.customElements.define("impact-embed", ImpactEmbed);
2074
+ if (!window.customElements.get("squatch-popup")) window.customElements.define("squatch-popup", SquatchPopup);
2075
+ if (!window.customElements.get("impact-popup")) window.customElements.define("impact-popup", ImpactPopup);
2059
2076
 
2060
2077
  // @ts-check
2061
2078
  function help() {