@saasquatch/squatch-js 2.8.2-2 → 2.8.2-21

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.
@@ -1108,393 +1108,32 @@ function delay(duration) {
1108
1108
  setTimeout(resolve, duration);
1109
1109
  });
1110
1110
  }
1111
- const getSkeleton = ({
1112
- height = "500px",
1113
- skeletonBackgroundColor = "#e0e0e0",
1114
- skeletonShimmerColor = "#f5f5f5",
1115
- borderColor = "#ccc"
1116
- }) => {
1117
- return `
1118
- <style>
1119
- * {
1120
- box-sizing: border-box;
1121
- padding: 0;
1122
- margin: 0;
1123
- }
1124
-
1125
- .widget-container {
1126
- background: white;
1127
- width: 100%;
1128
- max-width: 900px;
1129
- padding: 40px;
1130
- border-radius: 12px;
1131
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
1132
- box-sizing: border-box;
1133
- }
1134
-
1135
- @keyframes shimmer {
1136
- 0% {
1137
- background-position: -100% 0;
1138
- }
1139
- 100% {
1140
- background-position: 100% 0;
1141
- }
1142
- }
1143
-
1144
- .skeleton {
1145
- background: ${skeletonBackgroundColor};
1146
- background: linear-gradient(
1147
- 90deg,
1148
- ${skeletonBackgroundColor} 25%,
1149
- ${skeletonShimmerColor} 50%,
1150
- ${skeletonBackgroundColor} 75%
1151
- );
1152
- background-size: 200% 100%;
1153
- animation: shimmer 1.5s infinite linear;
1154
- border-radius: 6px;
1155
- margin-bottom: 12px;
1156
- }
1157
-
1158
- .sk-title-lg {
1159
- height: 36px;
1160
- width: 50%;
1161
- margin-bottom: 16px;
1162
- }
1163
- .sk-title-md {
1164
- height: 28px;
1165
- width: 30%;
1166
- margin-bottom: 20px;
1167
- margin-top: 40px;
1168
- }
1169
- .sk-text {
1170
- height: 16px;
1171
- width: 80%;
1172
- margin-bottom: 8px;
1173
- }
1174
- .sk-text-short {
1175
- width: 40%;
1176
- }
1177
- .sk-label {
1178
- height: 14px;
1179
- width: 25%;
1180
- margin-bottom: 10px;
1181
- }
1182
-
1183
- .hero-section {
1184
- display: flex;
1185
- gap: 40px;
1186
- margin-bottom: 40px;
1187
- border-bottom: 1px solid ${borderColor};
1188
- padding-bottom: 40px;
1189
- flex-direction: row;
1190
- }
1191
- .hero-content {
1192
- flex: 1;
1193
- display: flex;
1194
- flex-direction: column;
1195
- justify-content: center;
1196
- }
1197
- .hero-image {
1198
- flex: 1;
1199
- height: 300px;
1200
- border-radius: 12px;
1201
- }
1202
-
1203
- .share-section {
1204
- margin-bottom: 40px;
1205
- }
1206
- .sk-input {
1207
- height: 50px;
1208
- width: 100%;
1209
- border-radius: 8px;
1210
- margin-bottom: 16px;
1211
- }
1212
- .social-buttons {
1213
- display: flex;
1214
- gap: 12px;
1215
- }
1216
- .sk-btn-social {
1217
- flex: 1;
1218
- height: 50px;
1219
- border-radius: 8px;
1220
- }
1221
-
1222
- .stats-section {
1223
- display: flex;
1224
- gap: 24px;
1225
- margin-bottom: 40px;
1226
- padding: 30px 0;
1227
- border-top: 1px solid ${borderColor};
1228
- border-bottom: 1px solid ${borderColor};
1229
- }
1230
- .stat-card {
1231
- flex: 1;
1232
- display: flex;
1233
- flex-direction: column;
1234
- align-items: center;
1235
- }
1236
- .stat-divider {
1237
- padding-left: 24px;
1238
- }
1239
-
1240
- .sk-stat-num {
1241
- height: 48px;
1242
- width: 120px;
1243
- margin-bottom: 8px;
1244
- }
1245
- .sk-stat-label {
1246
- height: 18px;
1247
- width: 80px;
1248
- }
1249
-
1250
- .table-header {
1251
- display: flex;
1252
- gap: 16px;
1253
- margin-bottom: 16px;
1254
- }
1255
- .sk-th {
1256
- height: 16px;
1257
- }
1258
- .table-row {
1259
- display: flex;
1260
- align-items: center;
1261
- gap: 16px;
1262
- padding: 16px 0;
1263
- border-bottom: 1px solid ${borderColor};
1264
- }
1265
-
1266
- .col-user {
1267
- flex: 2;
1268
- }
1269
- .col-status {
1270
- flex: 1;
1271
- }
1272
- .col-reward {
1273
- flex: 2;
1274
- }
1275
- .col-date {
1276
- flex: 1;
1277
- }
1278
-
1279
- .sk-badge {
1280
- height: 28px;
1281
- width: 90px;
1282
- border-radius: 14px;
1283
- }
1284
- .sk-reward-block {
1285
- height: 36px;
1286
- width: 100%;
1287
- border-radius: 6px;
1288
- }
1289
-
1290
- .pagination {
1291
- display: flex;
1292
- justify-content: flex-end;
1293
- gap: 8px;
1294
- margin-top: 24px;
1295
- }
1296
- .sk-btn-page {
1297
- height: 36px;
1298
- width: 64px;
1299
- border-radius: 6px;
1300
- margin-bottom: 0;
1301
- }
1302
-
1303
- @media (max-width: 768px) {
1304
- body {
1305
- padding: 20px;
1306
- }
1307
- .widget-container {
1308
- padding: 24px;
1309
- }
1310
-
1311
- .hero-section {
1312
- flex-direction: column-reverse;
1313
- gap: 24px;
1314
- }
1315
- .hero-image {
1316
- height: 220px;
1317
- width: 100%;
1318
- }
1319
- .sk-title-lg {
1320
- width: 80%;
1321
- }
1322
-
1323
- .col-date {
1324
- display: none;
1325
- }
1326
- }
1327
-
1328
- @media (max-width: 480px) {
1329
- body {
1330
- padding: 10px;
1331
- }
1332
- .widget-container {
1333
- padding: 16px;
1334
- }
1335
-
1336
- .sk-stat-num {
1337
- width: 80px;
1338
- height: 40px;
1339
- }
1340
-
1341
- .col-reward {
1342
- display: none;
1343
- }
1344
-
1345
- .col-user {
1346
- flex: 3;
1347
- }
1348
- .col-status {
1349
- flex: 2;
1350
- display: flex;
1351
- justify-content: flex-end;
1352
- }
1353
- }
1354
- </style>
1355
-
1356
- <div class="widget-container">
1357
- <div class="hero-section">
1358
- <div class="hero-content">
1359
- <div class="skeleton sk-title-lg"></div>
1360
- <div class="skeleton sk-text"></div>
1361
- <div class="skeleton sk-text sk-text-short"></div>
1362
- </div>
1363
- <div class="skeleton hero-image"></div>
1364
- </div>
1365
-
1366
- <div class="share-section">
1367
- <div class="skeleton sk-label"></div>
1368
- <div class="skeleton sk-input"></div>
1369
- <div class="social-buttons">
1370
- <div class="skeleton sk-btn-social"></div>
1371
- <div class="skeleton sk-btn-social"></div>
1372
- <div class="skeleton sk-btn-social"></div>
1373
- <div class="skeleton sk-btn-social"></div>
1374
- </div>
1375
- </div>
1376
-
1377
- <div
1378
- class="skeleton sk-title-md"
1379
- style="margin-top: 0; width: 30%; margin-left: auto; margin-right: auto"
1380
- ></div>
1381
- <div
1382
- class="skeleton sk-text"
1383
- style="width: 60%; margin-left: auto; margin-right: auto"
1384
- ></div>
1385
-
1386
- <div class="stats-section">
1387
- <div class="stat-card">
1388
- <div class="skeleton sk-stat-num"></div>
1389
- <div class="skeleton sk-stat-label"></div>
1390
- </div>
1391
- <div class="stat-card stat-divider">
1392
- <div class="skeleton sk-stat-num"></div>
1393
- <div class="skeleton sk-stat-label"></div>
1394
- </div>
1395
- </div>
1396
-
1397
- <div class="skeleton sk-title-md"></div>
1398
-
1399
- <div class="table-header">
1400
- <div class="skeleton sk-th col-user"></div>
1401
- <div class="skeleton sk-th col-status"></div>
1402
- <div class="skeleton sk-th col-reward"></div>
1403
- <div class="skeleton sk-th col-date"></div>
1404
- </div>
1405
-
1406
- <div class="table-row">
1407
- <div class="col-user">
1408
- <div class="skeleton sk-text" style="width: 70%; margin: 0"></div>
1409
- </div>
1410
- <div class="col-status">
1411
- <div class="skeleton sk-badge" style="margin: 0"></div>
1412
- </div>
1413
- <div class="col-reward">
1414
- <div class="skeleton sk-reward-block" style="margin: 0"></div>
1415
- </div>
1416
- <div class="col-date">
1417
- <div class="skeleton sk-text" style="width: 80%; margin: 0"></div>
1418
- </div>
1419
- </div>
1420
- <div class="table-row">
1421
- <div class="col-user">
1422
- <div class="skeleton sk-text" style="width: 60%; margin: 0"></div>
1423
- </div>
1424
- <div class="col-status">
1425
- <div class="skeleton sk-badge" style="margin: 0"></div>
1426
- </div>
1427
- <div class="col-reward">
1428
- <div class="skeleton sk-reward-block" style="margin: 0"></div>
1429
- </div>
1430
- <div class="col-date">
1431
- <div class="skeleton sk-text" style="width: 80%; margin: 0"></div>
1432
- </div>
1433
- </div>
1434
- <div class="table-row">
1435
- <div class="col-user">
1436
- <div class="skeleton sk-text" style="width: 75%; margin: 0"></div>
1437
- </div>
1438
- <div class="col-status">
1439
- <div class="skeleton sk-badge" style="margin: 0"></div>
1440
- </div>
1441
- <div class="col-reward">
1442
- <div class="skeleton sk-reward-block" style="margin: 0"></div>
1443
- </div>
1444
- <div class="col-date">
1445
- <div class="skeleton sk-text" style="width: 80%; margin: 0"></div>
1446
- </div>
1447
- </div>
1448
-
1449
- <div class="pagination">
1450
- <div class="skeleton sk-btn-page"></div>
1451
- <div class="skeleton sk-btn-page"></div>
1452
- </div>
1453
- </div>
1454
- `;
1455
- };
1456
1111
  const _log$7 = browserExports.debug("squatch-js:EMBEDwidget");
1457
1112
  class EmbedWidget extends Widget {
1458
1113
  constructor(params, container) {
1459
1114
  super(params);
1460
1115
  __publicField(this, "show", this.open);
1461
1116
  __publicField(this, "hide", this.close);
1462
- if (container) this.container = container;
1117
+ if (container) {
1118
+ this.container = container;
1119
+ }
1463
1120
  }
1464
1121
  async load() {
1465
1122
  var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
1466
- const brandingConfig = (_b = (_a2 = this.context.widgetConfig) == null ? void 0 : _a2.values) == null ? void 0 : _b.brandingConfig;
1467
- const initialHeight = brandingConfig == null ? void 0 : brandingConfig.loadingHeight;
1468
- const skeletonBackgroundColor = (_d = (_c = brandingConfig == null ? void 0 : brandingConfig.color) == null ? void 0 : _c.loadingSkeleton) == null ? void 0 : _d.background;
1469
- const skeletonShimmerColor = (_f = (_e = brandingConfig == null ? void 0 : brandingConfig.color) == null ? void 0 : _e.loadingSkeleton) == null ? void 0 : _f.animationBackground;
1470
- const borderColor = (_g = brandingConfig == null ? void 0 : brandingConfig.border) == null ? void 0 : _g.borderColor;
1471
- const sizes = (_h = brandingConfig == null ? void 0 : brandingConfig.widgetSize) == null ? void 0 : _h.embeddedWidgets;
1123
+ const brandingConfig2 = (_b = (_a2 = this.context.widgetConfig) == null ? void 0 : _a2.values) == null ? void 0 : _b.brandingConfig;
1124
+ const initialHeight = brandingConfig2 == null ? void 0 : brandingConfig2.loadingHeight;
1125
+ (_d = (_c = brandingConfig2 == null ? void 0 : brandingConfig2.color) == null ? void 0 : _c.loadingSkeleton) == null ? void 0 : _d.background;
1126
+ (_f = (_e = brandingConfig2 == null ? void 0 : brandingConfig2.color) == null ? void 0 : _e.loadingSkeleton) == null ? void 0 : _f.animationBackground;
1127
+ (_g = brandingConfig2 == null ? void 0 : brandingConfig2.border) == null ? void 0 : _g.borderColor;
1128
+ const sizes = (_h = brandingConfig2 == null ? void 0 : brandingConfig2.widgetSize) == null ? void 0 : _h.embeddedWidgets;
1472
1129
  const maxWidth = (sizes == null ? void 0 : sizes.maxWidth) ? formatWidth(sizes.maxWidth) : "";
1473
1130
  const minWidth = (sizes == null ? void 0 : sizes.minWidth) ? formatWidth(sizes.minWidth) : "";
1474
- console.log({
1475
- brandingConfig,
1476
- initialHeight,
1477
- widgetConfig: this.context.widgetConfig
1478
- });
1479
- const skeletonHTML = getSkeleton({
1480
- height: initialHeight,
1481
- skeletonBackgroundColor,
1482
- skeletonShimmerColor,
1483
- borderColor
1484
- });
1485
- const skeletonContainer = document.createElement("div");
1486
- skeletonContainer.innerHTML = skeletonHTML;
1487
1131
  const frame = this._createFrame({
1488
1132
  minWidth,
1489
1133
  maxWidth,
1490
1134
  initialHeight
1491
1135
  });
1492
1136
  const element = this._findElement();
1493
- frame.style.display = "none";
1494
- const injectContents = (target) => {
1495
- target.appendChild(skeletonContainer);
1496
- target.appendChild(frame);
1497
- };
1498
1137
  if ((_i = this.context) == null ? void 0 : _i.container) {
1499
1138
  element.style.visibility = "hidden";
1500
1139
  element.style.height = "0";
@@ -1505,16 +1144,15 @@ class EmbedWidget extends Widget {
1505
1144
  if (((_j = element.shadowRoot.lastChild) == null ? void 0 : _j.nodeName) === "IFRAME") {
1506
1145
  element.shadowRoot.replaceChild(frame, element.shadowRoot.lastChild);
1507
1146
  } else {
1508
- injectContents(element.shadowRoot);
1147
+ element.shadowRoot.appendChild(frame);
1509
1148
  }
1510
1149
  } else if (element.firstChild) {
1511
- element.innerHTML = "";
1512
- injectContents(element);
1150
+ element.replaceChild(frame, element.firstChild);
1513
1151
  } else {
1514
- injectContents(element);
1152
+ element.appendChild(frame);
1515
1153
  }
1516
1154
  } else if (!element.firstChild || element.firstChild.nodeName === "#text") {
1517
- injectContents(element);
1155
+ element.appendChild(frame);
1518
1156
  }
1519
1157
  const { contentWindow } = frame;
1520
1158
  if (!contentWindow) {
@@ -1522,16 +1160,15 @@ class EmbedWidget extends Widget {
1522
1160
  }
1523
1161
  const frameDoc = contentWindow.document;
1524
1162
  frameDoc.open();
1525
- console.log({ content: this.content, context: this.context, this: this });
1526
1163
  const domain = this.widgetApi.domain;
1527
1164
  frameDoc.write(`
1528
- ${((_k = brandingConfig == null ? void 0 : brandingConfig.main) == null ? void 0 : _k.brandFont) && `
1165
+ ${((_k = brandingConfig2 == null ? void 0 : brandingConfig2.main) == null ? void 0 : _k.brandFont) ? `
1529
1166
  <link rel="preconnect" href="https://fast${domain === "https://staging.referralsaasquatch.com" && "-staging"}.ssqt.io">
1530
1167
  <link rel="preconnect" href="https://fonts.gstatic.com">
1531
1168
  <link rel="preconnect" href="https://fonts.googleapis.com">
1532
1169
  <link rel="preload" href="https://fonts.googleapis.com/css2?family=${encodeURIComponent(
1533
- (_l = brandingConfig == null ? void 0 : brandingConfig.main) == null ? void 0 : _l.brandFont
1534
- )}">`}
1170
+ (_l = brandingConfig2 == null ? void 0 : brandingConfig2.main) == null ? void 0 : _l.brandFont
1171
+ )}" as="style">` : ""}
1535
1172
  <script src="${this.npmCdn}/resize-observer-polyfill@1.5.x"><\/script>
1536
1173
  <style data-styles>
1537
1174
  html { visibility:hidden;}
@@ -1541,10 +1178,6 @@ class EmbedWidget extends Widget {
1541
1178
  `);
1542
1179
  frameDoc.close();
1543
1180
  domready(frameDoc, async () => {
1544
- if (skeletonContainer && skeletonContainer.parentNode) {
1545
- skeletonContainer.parentNode.removeChild(skeletonContainer);
1546
- }
1547
- frame.style.display = "block";
1548
1181
  const _sqh = contentWindow.squatch || contentWindow.widgetIdent;
1549
1182
  frame.height = initialHeight || frameDoc.body.scrollHeight;
1550
1183
  console.log({ height: frameDoc.body.scrollHeight });
@@ -1646,8 +1279,8 @@ class PopupWidget extends Widget {
1646
1279
  _createPopupDialog() {
1647
1280
  var _a2, _b, _c;
1648
1281
  const dialog = document.createElement("dialog");
1649
- const brandingConfig = (_b = (_a2 = this.context.widgetConfig) == null ? void 0 : _a2.values) == null ? void 0 : _b.brandingConfig;
1650
- const sizes = (_c = brandingConfig == null ? void 0 : brandingConfig.widgetSize) == null ? void 0 : _c.popupWidgets;
1282
+ const brandingConfig2 = (_b = (_a2 = this.context.widgetConfig) == null ? void 0 : _a2.values) == null ? void 0 : _b.brandingConfig;
1283
+ const sizes = (_c = brandingConfig2 == null ? void 0 : brandingConfig2.widgetSize) == null ? void 0 : _c.popupWidgets;
1651
1284
  const minWidth = (sizes == null ? void 0 : sizes.minWidth) ? formatWidth(sizes.minWidth) : "auto";
1652
1285
  const maxWidth = (sizes == null ? void 0 : sizes.maxWidth) ? formatWidth(sizes.maxWidth) : "500px";
1653
1286
  dialog.id = this.id;
@@ -2110,125 +1743,470 @@ const deepMerge = (target, source) => {
2110
1743
  [prop]: isDeep(prop) ? deepMerge(target[prop], source[prop]) : source[prop]
2111
1744
  })).reduce((a, b) => ({ ...a, ...b }), {});
2112
1745
  return {
2113
- ...target,
2114
- ...replaced
1746
+ ...target,
1747
+ ...replaced
1748
+ };
1749
+ };
1750
+ function b64decode(input) {
1751
+ const binary = atob(input.replace(/_/g, "/").replace(/-/g, "+"));
1752
+ const bytes = new Uint8Array(binary.length);
1753
+ for (let i = 0; i < binary.length; i++) {
1754
+ bytes[i] = binary.charCodeAt(i);
1755
+ }
1756
+ return new TextDecoder("utf8").decode(bytes);
1757
+ }
1758
+ function b64encode(input) {
1759
+ const encodedInput = new TextEncoder().encode(input);
1760
+ const binary = Array.from(
1761
+ encodedInput,
1762
+ (byte) => String.fromCodePoint(byte)
1763
+ ).join("");
1764
+ return btoa(binary).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
1765
+ }
1766
+ function getTopDomain() {
1767
+ var i, h, weird_cookie = "weird_get_top_level_domain=cookie", hostname = document.location.hostname.split(".");
1768
+ for (i = hostname.length - 1; i >= 0; i--) {
1769
+ h = hostname.slice(i).join(".");
1770
+ document.cookie = weird_cookie + ";domain=." + h + ";";
1771
+ if (document.cookie.indexOf(weird_cookie) > -1) {
1772
+ document.cookie = weird_cookie.split("=")[0] + "=;domain=." + h + ";expires=Thu, 01 Jan 1970 00:00:01 GMT;";
1773
+ return h;
1774
+ }
1775
+ }
1776
+ }
1777
+ function _pushCookie() {
1778
+ const queryString = window.location.search;
1779
+ const urlParams = new URLSearchParams(queryString);
1780
+ const refParam = urlParams.get("_saasquatch") || "";
1781
+ if (refParam) {
1782
+ let paramsJSON = "", existingCookie = "", reEncodedCookie = "";
1783
+ try {
1784
+ paramsJSON = JSON.parse(b64decode(refParam));
1785
+ } catch (error) {
1786
+ _log$4("Unable to decode params", error);
1787
+ return;
1788
+ }
1789
+ try {
1790
+ existingCookie = JSON.parse(b64decode(api$1.get("_saasquatch")));
1791
+ _log$4("existing cookie", existingCookie);
1792
+ } catch (error) {
1793
+ _log$4("Unable to retrieve cookie", error);
1794
+ }
1795
+ try {
1796
+ const domain = getTopDomain();
1797
+ _log$4("domain retrieved:", domain);
1798
+ if (existingCookie) {
1799
+ const newCookie = deepMerge(existingCookie, paramsJSON);
1800
+ reEncodedCookie = b64encode(JSON.stringify(newCookie));
1801
+ _log$4("cookie to store:", newCookie);
1802
+ } else {
1803
+ reEncodedCookie = b64encode(JSON.stringify(paramsJSON));
1804
+ _log$4("cookie to store:", paramsJSON);
1805
+ }
1806
+ api$1.set("_saasquatch", reEncodedCookie, {
1807
+ expires: 365,
1808
+ secure: false,
1809
+ sameSite: "Lax",
1810
+ domain,
1811
+ path: "/"
1812
+ });
1813
+ } catch (error) {
1814
+ _log$4("Unable to set cookie", error);
1815
+ }
1816
+ }
1817
+ }
1818
+ const _log$3 = browserExports.debug("squatch-js");
1819
+ function _getAutoConfig() {
1820
+ var _a2;
1821
+ const queryString = window.location.search;
1822
+ const urlParams = new URLSearchParams(queryString);
1823
+ const refParam = urlParams.get("_saasquatchExtra") || "";
1824
+ if (!refParam) {
1825
+ _log$3("No _saasquatchExtra param");
1826
+ return;
1827
+ }
1828
+ const config = validateConfig({
1829
+ tenantAlias: "UNKNOWN"
1830
+ });
1831
+ if (!config.domain) {
1832
+ _log$3("domain must be provided in config to use _saasquatchExtra");
1833
+ return;
1834
+ }
1835
+ let raw;
1836
+ try {
1837
+ raw = JSON.parse(b64decode(refParam));
1838
+ } catch (e) {
1839
+ _log$3("Unable to decode _saasquatchExtra config");
1840
+ return;
1841
+ }
1842
+ function normalizeDomain(domain) {
1843
+ return domain.replace(/^https?:\/\//, "");
1844
+ }
1845
+ const normalizedDomain = normalizeDomain(config.domain);
1846
+ const tenantAlias = Object.keys((raw == null ? void 0 : raw[normalizedDomain]) || {})[0];
1847
+ const widgetConfig = (_a2 = raw == null ? void 0 : raw[normalizedDomain]) == null ? void 0 : _a2[tenantAlias];
1848
+ if (!widgetConfig) {
1849
+ _log$3("_saasquatchExtra did not have an expected structure");
1850
+ return void 0;
1851
+ }
1852
+ const { autoPopupWidgetType, ...rest } = widgetConfig;
1853
+ return {
1854
+ widgetConfig: {
1855
+ widgetType: autoPopupWidgetType,
1856
+ displayOnLoad: true,
1857
+ ...rest
1858
+ },
1859
+ squatchConfig: {
1860
+ ...config,
1861
+ tenantAlias
1862
+ }
2115
1863
  };
1864
+ }
1865
+ const getSkeleton = ({
1866
+ height = "500px",
1867
+ skeletonBackgroundColor = "#e0e0e0",
1868
+ skeletonShimmerColor = "#f5f5f5",
1869
+ borderColor = "#ccc"
1870
+ }) => {
1871
+ return `
1872
+ <style>
1873
+ * {
1874
+ box-sizing: border-box;
1875
+ padding: 0;
1876
+ margin: 0;
1877
+ }
1878
+
1879
+ .widget-container {
1880
+ background: white;
1881
+ width: 100%;
1882
+ max-width: 900px;
1883
+ padding: 40px;
1884
+ border-radius: 12px;
1885
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
1886
+ box-sizing: border-box;
1887
+ }
1888
+
1889
+ @keyframes shimmer {
1890
+ 0% {
1891
+ background-position: -100% 0;
1892
+ }
1893
+ 100% {
1894
+ background-position: 100% 0;
1895
+ }
1896
+ }
1897
+
1898
+ .skeleton {
1899
+ background: ${skeletonBackgroundColor};
1900
+ background: linear-gradient(
1901
+ 90deg,
1902
+ ${skeletonBackgroundColor} 25%,
1903
+ ${skeletonShimmerColor} 50%,
1904
+ ${skeletonBackgroundColor} 75%
1905
+ );
1906
+ background-size: 200% 100%;
1907
+ animation: shimmer 1.5s infinite linear;
1908
+ border-radius: 6px;
1909
+ margin-bottom: 12px;
1910
+ }
1911
+
1912
+ .sk-title-lg {
1913
+ height: 36px;
1914
+ width: 50%;
1915
+ margin-bottom: 16px;
1916
+ }
1917
+ .sk-title-md {
1918
+ height: 28px;
1919
+ width: 30%;
1920
+ margin-bottom: 20px;
1921
+ margin-top: 40px;
1922
+ }
1923
+ .sk-text {
1924
+ height: 16px;
1925
+ width: 80%;
1926
+ margin-bottom: 8px;
1927
+ }
1928
+ .sk-text-short {
1929
+ width: 40%;
1930
+ }
1931
+ .sk-label {
1932
+ height: 14px;
1933
+ width: 25%;
1934
+ margin-bottom: 10px;
1935
+ }
1936
+
1937
+ .hero-section {
1938
+ display: flex;
1939
+ gap: 40px;
1940
+ margin-bottom: 40px;
1941
+ border-bottom: 1px solid ${borderColor};
1942
+ padding-bottom: 40px;
1943
+ flex-direction: row;
1944
+ }
1945
+ .hero-content {
1946
+ flex: 1;
1947
+ display: flex;
1948
+ flex-direction: column;
1949
+ justify-content: center;
1950
+ }
1951
+ .hero-image {
1952
+ flex: 1;
1953
+ height: 300px;
1954
+ border-radius: 12px;
1955
+ }
1956
+
1957
+ .share-section {
1958
+ margin-bottom: 40px;
1959
+ }
1960
+ .sk-input {
1961
+ height: 50px;
1962
+ width: 100%;
1963
+ border-radius: 8px;
1964
+ margin-bottom: 16px;
1965
+ }
1966
+ .social-buttons {
1967
+ display: flex;
1968
+ gap: 12px;
1969
+ }
1970
+ .sk-btn-social {
1971
+ flex: 1;
1972
+ height: 50px;
1973
+ border-radius: 8px;
1974
+ }
1975
+
1976
+ .stats-section {
1977
+ display: flex;
1978
+ gap: 24px;
1979
+ margin-bottom: 40px;
1980
+ padding: 30px 0;
1981
+ border-top: 1px solid ${borderColor};
1982
+ border-bottom: 1px solid ${borderColor};
1983
+ }
1984
+ .stat-card {
1985
+ flex: 1;
1986
+ display: flex;
1987
+ flex-direction: column;
1988
+ align-items: center;
1989
+ }
1990
+ .stat-divider {
1991
+ padding-left: 24px;
1992
+ }
1993
+
1994
+ .sk-stat-num {
1995
+ height: 48px;
1996
+ width: 120px;
1997
+ margin-bottom: 8px;
1998
+ }
1999
+ .sk-stat-label {
2000
+ height: 18px;
2001
+ width: 80px;
2002
+ }
2003
+
2004
+ .table-header {
2005
+ display: flex;
2006
+ gap: 16px;
2007
+ margin-bottom: 16px;
2008
+ }
2009
+ .sk-th {
2010
+ height: 16px;
2011
+ }
2012
+ .table-row {
2013
+ display: flex;
2014
+ align-items: center;
2015
+ gap: 16px;
2016
+ padding: 16px 0;
2017
+ border-bottom: 1px solid ${borderColor};
2018
+ }
2019
+
2020
+ .col-user {
2021
+ flex: 2;
2022
+ }
2023
+ .col-status {
2024
+ flex: 1;
2025
+ }
2026
+ .col-reward {
2027
+ flex: 2;
2028
+ }
2029
+ .col-date {
2030
+ flex: 1;
2031
+ }
2032
+
2033
+ .sk-badge {
2034
+ height: 28px;
2035
+ width: 90px;
2036
+ border-radius: 14px;
2037
+ }
2038
+ .sk-reward-block {
2039
+ height: 36px;
2040
+ width: 100%;
2041
+ border-radius: 6px;
2042
+ }
2043
+
2044
+ .pagination {
2045
+ display: flex;
2046
+ justify-content: flex-end;
2047
+ gap: 8px;
2048
+ margin-top: 24px;
2049
+ }
2050
+ .sk-btn-page {
2051
+ height: 36px;
2052
+ width: 64px;
2053
+ border-radius: 6px;
2054
+ margin-bottom: 0;
2055
+ }
2056
+
2057
+ @media (max-width: 768px) {
2058
+ body {
2059
+ padding: 20px;
2060
+ }
2061
+ .widget-container {
2062
+ padding: 24px;
2063
+ }
2064
+
2065
+ .hero-section {
2066
+ flex-direction: column-reverse;
2067
+ gap: 24px;
2068
+ }
2069
+ .hero-image {
2070
+ height: 220px;
2071
+ width: 100%;
2072
+ }
2073
+ .sk-title-lg {
2074
+ width: 80%;
2075
+ }
2076
+
2077
+ .col-date {
2078
+ display: none;
2079
+ }
2080
+ }
2081
+
2082
+ @media (max-width: 480px) {
2083
+ body {
2084
+ padding: 10px;
2085
+ }
2086
+ .widget-container {
2087
+ padding: 16px;
2088
+ }
2089
+
2090
+ .sk-stat-num {
2091
+ width: 80px;
2092
+ height: 40px;
2093
+ }
2094
+
2095
+ .col-reward {
2096
+ display: none;
2097
+ }
2098
+
2099
+ .col-user {
2100
+ flex: 3;
2101
+ }
2102
+ .col-status {
2103
+ flex: 2;
2104
+ display: flex;
2105
+ justify-content: flex-end;
2106
+ }
2107
+ }
2108
+ </style>
2109
+
2110
+ <div class="widget-container">
2111
+ <div class="hero-section">
2112
+ <div class="hero-content">
2113
+ <div class="skeleton sk-title-lg"></div>
2114
+ <div class="skeleton sk-text"></div>
2115
+ <div class="skeleton sk-text sk-text-short"></div>
2116
+ </div>
2117
+ <div class="skeleton hero-image"></div>
2118
+ </div>
2119
+
2120
+ <div class="share-section">
2121
+ <div class="skeleton sk-label"></div>
2122
+ <div class="skeleton sk-input"></div>
2123
+ <div class="social-buttons">
2124
+ <div class="skeleton sk-btn-social"></div>
2125
+ <div class="skeleton sk-btn-social"></div>
2126
+ <div class="skeleton sk-btn-social"></div>
2127
+ <div class="skeleton sk-btn-social"></div>
2128
+ </div>
2129
+ </div>
2130
+
2131
+ <div
2132
+ class="skeleton sk-title-md"
2133
+ style="margin-top: 0; width: 30%; margin-left: auto; margin-right: auto"
2134
+ ></div>
2135
+ <div
2136
+ class="skeleton sk-text"
2137
+ style="width: 60%; margin-left: auto; margin-right: auto"
2138
+ ></div>
2139
+
2140
+ <div class="stats-section">
2141
+ <div class="stat-card">
2142
+ <div class="skeleton sk-stat-num"></div>
2143
+ <div class="skeleton sk-stat-label"></div>
2144
+ </div>
2145
+ <div class="stat-card stat-divider">
2146
+ <div class="skeleton sk-stat-num"></div>
2147
+ <div class="skeleton sk-stat-label"></div>
2148
+ </div>
2149
+ </div>
2150
+
2151
+ <div class="skeleton sk-title-md"></div>
2152
+
2153
+ <div class="table-header">
2154
+ <div class="skeleton sk-th col-user"></div>
2155
+ <div class="skeleton sk-th col-status"></div>
2156
+ <div class="skeleton sk-th col-reward"></div>
2157
+ <div class="skeleton sk-th col-date"></div>
2158
+ </div>
2159
+
2160
+ <div class="table-row">
2161
+ <div class="col-user">
2162
+ <div class="skeleton sk-text" style="width: 70%; margin: 0"></div>
2163
+ </div>
2164
+ <div class="col-status">
2165
+ <div class="skeleton sk-badge" style="margin: 0"></div>
2166
+ </div>
2167
+ <div class="col-reward">
2168
+ <div class="skeleton sk-reward-block" style="margin: 0"></div>
2169
+ </div>
2170
+ <div class="col-date">
2171
+ <div class="skeleton sk-text" style="width: 80%; margin: 0"></div>
2172
+ </div>
2173
+ </div>
2174
+ <div class="table-row">
2175
+ <div class="col-user">
2176
+ <div class="skeleton sk-text" style="width: 60%; margin: 0"></div>
2177
+ </div>
2178
+ <div class="col-status">
2179
+ <div class="skeleton sk-badge" style="margin: 0"></div>
2180
+ </div>
2181
+ <div class="col-reward">
2182
+ <div class="skeleton sk-reward-block" style="margin: 0"></div>
2183
+ </div>
2184
+ <div class="col-date">
2185
+ <div class="skeleton sk-text" style="width: 80%; margin: 0"></div>
2186
+ </div>
2187
+ </div>
2188
+ <div class="table-row">
2189
+ <div class="col-user">
2190
+ <div class="skeleton sk-text" style="width: 75%; margin: 0"></div>
2191
+ </div>
2192
+ <div class="col-status">
2193
+ <div class="skeleton sk-badge" style="margin: 0"></div>
2194
+ </div>
2195
+ <div class="col-reward">
2196
+ <div class="skeleton sk-reward-block" style="margin: 0"></div>
2197
+ </div>
2198
+ <div class="col-date">
2199
+ <div class="skeleton sk-text" style="width: 80%; margin: 0"></div>
2200
+ </div>
2201
+ </div>
2202
+
2203
+ <div class="pagination">
2204
+ <div class="skeleton sk-btn-page"></div>
2205
+ <div class="skeleton sk-btn-page"></div>
2206
+ </div>
2207
+ </div>
2208
+ `;
2116
2209
  };
2117
- function b64decode(input) {
2118
- const binary = atob(input.replace(/_/g, "/").replace(/-/g, "+"));
2119
- const bytes = new Uint8Array(binary.length);
2120
- for (let i = 0; i < binary.length; i++) {
2121
- bytes[i] = binary.charCodeAt(i);
2122
- }
2123
- return new TextDecoder("utf8").decode(bytes);
2124
- }
2125
- function b64encode(input) {
2126
- const encodedInput = new TextEncoder().encode(input);
2127
- const binary = Array.from(
2128
- encodedInput,
2129
- (byte) => String.fromCodePoint(byte)
2130
- ).join("");
2131
- return btoa(binary).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
2132
- }
2133
- function getTopDomain() {
2134
- var i, h, weird_cookie = "weird_get_top_level_domain=cookie", hostname = document.location.hostname.split(".");
2135
- for (i = hostname.length - 1; i >= 0; i--) {
2136
- h = hostname.slice(i).join(".");
2137
- document.cookie = weird_cookie + ";domain=." + h + ";";
2138
- if (document.cookie.indexOf(weird_cookie) > -1) {
2139
- document.cookie = weird_cookie.split("=")[0] + "=;domain=." + h + ";expires=Thu, 01 Jan 1970 00:00:01 GMT;";
2140
- return h;
2141
- }
2142
- }
2143
- }
2144
- function _pushCookie() {
2145
- const queryString = window.location.search;
2146
- const urlParams = new URLSearchParams(queryString);
2147
- const refParam = urlParams.get("_saasquatch") || "";
2148
- if (refParam) {
2149
- let paramsJSON = "", existingCookie = "", reEncodedCookie = "";
2150
- try {
2151
- paramsJSON = JSON.parse(b64decode(refParam));
2152
- } catch (error) {
2153
- _log$4("Unable to decode params", error);
2154
- return;
2155
- }
2156
- try {
2157
- existingCookie = JSON.parse(b64decode(api$1.get("_saasquatch")));
2158
- _log$4("existing cookie", existingCookie);
2159
- } catch (error) {
2160
- _log$4("Unable to retrieve cookie", error);
2161
- }
2162
- try {
2163
- const domain = getTopDomain();
2164
- _log$4("domain retrieved:", domain);
2165
- if (existingCookie) {
2166
- const newCookie = deepMerge(existingCookie, paramsJSON);
2167
- reEncodedCookie = b64encode(JSON.stringify(newCookie));
2168
- _log$4("cookie to store:", newCookie);
2169
- } else {
2170
- reEncodedCookie = b64encode(JSON.stringify(paramsJSON));
2171
- _log$4("cookie to store:", paramsJSON);
2172
- }
2173
- api$1.set("_saasquatch", reEncodedCookie, {
2174
- expires: 365,
2175
- secure: false,
2176
- sameSite: "Lax",
2177
- domain,
2178
- path: "/"
2179
- });
2180
- } catch (error) {
2181
- _log$4("Unable to set cookie", error);
2182
- }
2183
- }
2184
- }
2185
- const _log$3 = browserExports.debug("squatch-js");
2186
- function _getAutoConfig() {
2187
- var _a2;
2188
- const queryString = window.location.search;
2189
- const urlParams = new URLSearchParams(queryString);
2190
- const refParam = urlParams.get("_saasquatchExtra") || "";
2191
- if (!refParam) {
2192
- _log$3("No _saasquatchExtra param");
2193
- return;
2194
- }
2195
- const config = validateConfig({
2196
- tenantAlias: "UNKNOWN"
2197
- });
2198
- if (!config.domain) {
2199
- _log$3("domain must be provided in config to use _saasquatchExtra");
2200
- return;
2201
- }
2202
- let raw;
2203
- try {
2204
- raw = JSON.parse(b64decode(refParam));
2205
- } catch (e) {
2206
- _log$3("Unable to decode _saasquatchExtra config");
2207
- return;
2208
- }
2209
- function normalizeDomain(domain) {
2210
- return domain.replace(/^https?:\/\//, "");
2211
- }
2212
- const normalizedDomain = normalizeDomain(config.domain);
2213
- const tenantAlias = Object.keys((raw == null ? void 0 : raw[normalizedDomain]) || {})[0];
2214
- const widgetConfig = (_a2 = raw == null ? void 0 : raw[normalizedDomain]) == null ? void 0 : _a2[tenantAlias];
2215
- if (!widgetConfig) {
2216
- _log$3("_saasquatchExtra did not have an expected structure");
2217
- return void 0;
2218
- }
2219
- const { autoPopupWidgetType, ...rest } = widgetConfig;
2220
- return {
2221
- widgetConfig: {
2222
- widgetType: autoPopupWidgetType,
2223
- displayOnLoad: true,
2224
- ...rest
2225
- },
2226
- squatchConfig: {
2227
- ...config,
2228
- tenantAlias
2229
- }
2230
- };
2231
- }
2232
2210
  const _log$2 = browserExports.debug("squatch-js:decodeUserJwt");
2233
2211
  function decodeUserJwt(tokenStr) {
2234
2212
  var _a2;
@@ -2462,12 +2440,21 @@ class DeclarativeEmbedWidget extends DeclarativeWidget {
2462
2440
  }
2463
2441
  }
2464
2442
  async connectedCallback() {
2465
- var _a2, _b;
2466
2443
  this.loaded = true;
2467
2444
  this.container = this.getAttribute("container");
2445
+ brandingConfig == null ? void 0 : brandingConfig.loadingHeight;
2446
+ const skeletonHTML = getSkeleton({});
2447
+ const skeletonContainer = document.createElement("div");
2448
+ skeletonContainer.id = "loading-skeleton";
2449
+ skeletonContainer.innerHTML = skeletonHTML;
2450
+ const root = this.shadowRoot || this.attachShadow({ mode: "open" });
2451
+ root.innerHTML = "";
2452
+ root.appendChild(skeletonContainer);
2468
2453
  await this.renderWidget();
2469
- const slot = (_a2 = this.shadowRoot && Array.from(this.shadowRoot.children)) == null ? void 0 : _a2.find((c) => c.tagName === "SLOT");
2470
- if (slot) (_b = this.shadowRoot) == null ? void 0 : _b.removeChild(slot);
2454
+ const loadingElement = root.getElementById("loading-skeleton");
2455
+ if (loadingElement) {
2456
+ loadingElement.remove();
2457
+ }
2471
2458
  if (this.getAttribute("open") !== null) this.open();
2472
2459
  }
2473
2460
  }
@@ -2494,9 +2481,29 @@ class DeclarativePopupWidget extends DeclarativeWidget {
2494
2481
  }
2495
2482
  }
2496
2483
  async connectedCallback() {
2484
+ var _a2;
2497
2485
  this.loaded = true;
2498
2486
  this.container = this.getAttribute("container");
2487
+ const skeletonHTML = `
2488
+ <div>
2489
+ <h1>Dynamic Content</h1>
2490
+ <p>This content was dynamically added to the widget before it loaded.</p>
2491
+ </div>
2492
+ `;
2493
+ const skeletonContainer = document.createElement("div");
2494
+ skeletonContainer.id = "loading-skeleton";
2495
+ skeletonContainer.innerHTML = skeletonHTML;
2496
+ if (!this.shadowRoot) {
2497
+ this.attachShadow({ mode: "open" });
2498
+ }
2499
+ if (this.shadowRoot) {
2500
+ this.shadowRoot.innerHTML = skeletonHTML;
2501
+ }
2499
2502
  await this.renderWidget();
2503
+ const loadingElement = (_a2 = this.shadowRoot) == null ? void 0 : _a2.getElementById("loading-skeleton");
2504
+ if (loadingElement) {
2505
+ loadingElement.remove();
2506
+ }
2500
2507
  if (this.getAttribute("open") !== null) this.open();
2501
2508
  }
2502
2509
  }