kenobi-js 0.1.42 → 0.1.43
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/README.md +3 -3
- package/browser/dist.js +710 -71
- package/browser/dist.js.map +3 -3
- package/browser/dist.min.js +156 -8
- package/package.json +1 -1
package/browser/dist.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Kenobi SDK v0.1.
|
|
2
|
+
* Kenobi SDK v0.1.42
|
|
3
3
|
* (c) 2026 Kenobi.ai
|
|
4
4
|
*/
|
|
5
5
|
"use strict";
|
|
@@ -1129,6 +1129,200 @@ var KenobiLib = (() => {
|
|
|
1129
1129
|
)
|
|
1130
1130
|
}
|
|
1131
1131
|
), "ArrowPathIcon");
|
|
1132
|
+
var IDENTITY_RESOLVED_EVENT = "kenobi:identity-resolved";
|
|
1133
|
+
var KENOBI_SNITCHER_SCRIPT_ID = "kenobi-snitcher";
|
|
1134
|
+
var DEFAULT_DEANON_TIMEOUT_MS = 1600;
|
|
1135
|
+
var dispatchCueCardEvent = /* @__PURE__ */ __name((eventName, detail) => {
|
|
1136
|
+
if (typeof window === "undefined") return;
|
|
1137
|
+
window.dispatchEvent(
|
|
1138
|
+
new CustomEvent(`kenobi:${eventName}`, {
|
|
1139
|
+
detail,
|
|
1140
|
+
bubbles: true
|
|
1141
|
+
})
|
|
1142
|
+
);
|
|
1143
|
+
}, "dispatchCueCardEvent");
|
|
1144
|
+
var resolveDeanonymizedCompany = /* @__PURE__ */ __name((detail) => {
|
|
1145
|
+
if (!detail || detail.type !== "business") return null;
|
|
1146
|
+
const company = detail.company;
|
|
1147
|
+
const name = company?.name || detail.domain || void 0;
|
|
1148
|
+
const domain = company?.domain || detail.domain || void 0;
|
|
1149
|
+
if (!name) return null;
|
|
1150
|
+
return {
|
|
1151
|
+
name,
|
|
1152
|
+
domain,
|
|
1153
|
+
logoUrl: company?.logoUrl || (domain ? `https://logo.clearbit.com/${domain}` : void 0)
|
|
1154
|
+
};
|
|
1155
|
+
}, "resolveDeanonymizedCompany");
|
|
1156
|
+
var normalizeDomain = /* @__PURE__ */ __name((value) => {
|
|
1157
|
+
if (!value) return "";
|
|
1158
|
+
return value.replace(/^https?:\/\//i, "").replace(/\/.*$/, "").replace(/:\d+$/, "").replace(/^www\./i, "").trim().toLowerCase();
|
|
1159
|
+
}, "normalizeDomain");
|
|
1160
|
+
var ensureKenobiSnitcherLoaded = /* @__PURE__ */ __name((config) => {
|
|
1161
|
+
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
1162
|
+
if (window.__kenobiSnitcherLoaded || window.__kenobiSnitcherLoading) return;
|
|
1163
|
+
if (window.Snitcher || window.SpotterSettings) {
|
|
1164
|
+
window.__kenobiSnitcherLoaded = true;
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
if (document.getElementById(KENOBI_SNITCHER_SCRIPT_ID)) {
|
|
1168
|
+
window.__kenobiSnitcherLoaded = true;
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
const snitcher = config?.snitcher;
|
|
1172
|
+
if (!snitcher?.spotterToken || !snitcher.profileId) {
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
window.__kenobiSnitcherLoading = true;
|
|
1176
|
+
const resolvedLogoTemplate = config?.logoUrlTemplate || "https://logo.clearbit.com/{domain}";
|
|
1177
|
+
const apiEndpoint = snitcher.apiEndpoint || `${window.location.origin}/api/snitcher-proxy/radar`;
|
|
1178
|
+
const cdn = snitcher.cdn || `${window.location.origin}/api/snitcher-proxy/cdn`;
|
|
1179
|
+
const namespace = snitcher.namespace || "Snitcher";
|
|
1180
|
+
const snitcherScript = `
|
|
1181
|
+
(function () {
|
|
1182
|
+
function spotterCb(response) {
|
|
1183
|
+
var rawDomain = (response.company && response.company.domain) || response.domain || "";
|
|
1184
|
+
var normalizedDomain = rawDomain
|
|
1185
|
+
.replace(/^https?:\\/\\//i, "")
|
|
1186
|
+
.replace(/\\/.*$/, "")
|
|
1187
|
+
.replace(/:\\d+$/, "")
|
|
1188
|
+
.replace(/^www\\./i, "");
|
|
1189
|
+
var identity = {
|
|
1190
|
+
provider: "snitcher",
|
|
1191
|
+
type: response.type === "business" ? "business" : "unknown",
|
|
1192
|
+
domain: response.domain || null,
|
|
1193
|
+
ip: response.ip,
|
|
1194
|
+
company: response.company
|
|
1195
|
+
? {
|
|
1196
|
+
id: response.company.id,
|
|
1197
|
+
name: response.company.name || response.domain,
|
|
1198
|
+
domain: response.company.domain || response.domain,
|
|
1199
|
+
logoUrl: "${resolvedLogoTemplate}".replace("{domain}", normalizedDomain),
|
|
1200
|
+
industry: response.company.industry,
|
|
1201
|
+
location: response.company.location,
|
|
1202
|
+
employeeRange: response.company.employee_range,
|
|
1203
|
+
foundedYear: response.company.founded_year,
|
|
1204
|
+
description: response.company.description,
|
|
1205
|
+
geo: response.company.geo
|
|
1206
|
+
? {
|
|
1207
|
+
city: response.company.geo.city,
|
|
1208
|
+
country: response.company.geo.country,
|
|
1209
|
+
countryCode: response.company.geo.country_code,
|
|
1210
|
+
region: response.company.geo.region,
|
|
1211
|
+
postalCode: response.company.geo.postal_code,
|
|
1212
|
+
address:
|
|
1213
|
+
response.company.geo.full_address ||
|
|
1214
|
+
response.company.geo.address,
|
|
1215
|
+
}
|
|
1216
|
+
: undefined,
|
|
1217
|
+
profiles: response.company.profiles
|
|
1218
|
+
? {
|
|
1219
|
+
linkedin: response.company.profiles.linkedin?.url,
|
|
1220
|
+
twitter: response.company.profiles.twitter?.url,
|
|
1221
|
+
facebook: response.company.profiles.facebook?.url,
|
|
1222
|
+
crunchbase: response.company.profiles.crunchbase?.url,
|
|
1223
|
+
}
|
|
1224
|
+
: undefined,
|
|
1225
|
+
}
|
|
1226
|
+
: undefined,
|
|
1227
|
+
raw: response,
|
|
1228
|
+
};
|
|
1229
|
+
|
|
1230
|
+
window.__kenobiIdentityResolution = identity;
|
|
1231
|
+
window.dispatchEvent(
|
|
1232
|
+
new CustomEvent("${IDENTITY_RESOLVED_EVENT}", {
|
|
1233
|
+
detail: identity,
|
|
1234
|
+
bubbles: true,
|
|
1235
|
+
})
|
|
1236
|
+
);
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
window.SpotterSettings = {
|
|
1240
|
+
token: "${snitcher.spotterToken}",
|
|
1241
|
+
callback: spotterCb,
|
|
1242
|
+
};
|
|
1243
|
+
|
|
1244
|
+
!(function (e) {
|
|
1245
|
+
"use strict";
|
|
1246
|
+
var t = e && e.namespace;
|
|
1247
|
+
if (t && e.profileId && e.cdn) {
|
|
1248
|
+
var i = window[t];
|
|
1249
|
+
if (((i && Array.isArray(i)) || (i = window[t] = []), !i.initialized && !i._loaded))
|
|
1250
|
+
if (i._loaded) console && console.warn("[Radar] Duplicate initialization attempted");
|
|
1251
|
+
else {
|
|
1252
|
+
i._loaded = !0;
|
|
1253
|
+
[
|
|
1254
|
+
"track",
|
|
1255
|
+
"page",
|
|
1256
|
+
"identify",
|
|
1257
|
+
"group",
|
|
1258
|
+
"alias",
|
|
1259
|
+
"ready",
|
|
1260
|
+
"debug",
|
|
1261
|
+
"on",
|
|
1262
|
+
"off",
|
|
1263
|
+
"once",
|
|
1264
|
+
"trackClick",
|
|
1265
|
+
"trackSubmit",
|
|
1266
|
+
"trackLink",
|
|
1267
|
+
"trackForm",
|
|
1268
|
+
"pageview",
|
|
1269
|
+
"screen",
|
|
1270
|
+
"reset",
|
|
1271
|
+
"register",
|
|
1272
|
+
"setAnonymousId",
|
|
1273
|
+
"addSourceMiddleware",
|
|
1274
|
+
"addIntegrationMiddleware",
|
|
1275
|
+
"addDestinationMiddleware",
|
|
1276
|
+
"giveCookieConsent",
|
|
1277
|
+
].forEach(function (e) {
|
|
1278
|
+
var a;
|
|
1279
|
+
i[e] =
|
|
1280
|
+
((a = e),
|
|
1281
|
+
function () {
|
|
1282
|
+
var e = window[t];
|
|
1283
|
+
if (e.initialized) return e[a].apply(e, arguments);
|
|
1284
|
+
var i = [].slice.call(arguments);
|
|
1285
|
+
return i.unshift(a), e.push(i), e;
|
|
1286
|
+
});
|
|
1287
|
+
}),
|
|
1288
|
+
-1 === e.apiEndpoint.indexOf("http") &&
|
|
1289
|
+
(e.apiEndpoint = "https://" + e.apiEndpoint),
|
|
1290
|
+
(i.bootstrap = function () {
|
|
1291
|
+
var t,
|
|
1292
|
+
i = document.createElement("script");
|
|
1293
|
+
(i.async = !0),
|
|
1294
|
+
(i.type = "text/javascript"),
|
|
1295
|
+
(i.id = "__radar__"),
|
|
1296
|
+
i.setAttribute("data-settings", JSON.stringify(e)),
|
|
1297
|
+
(i.src = [
|
|
1298
|
+
-1 !== (t = e.cdn).indexOf("http") ? "" : "https://",
|
|
1299
|
+
t,
|
|
1300
|
+
"/releases/latest/radar.min.js",
|
|
1301
|
+
].join(""));
|
|
1302
|
+
var a = document.scripts[0];
|
|
1303
|
+
a.parentNode.insertBefore(i, a);
|
|
1304
|
+
}),
|
|
1305
|
+
i.bootstrap();
|
|
1306
|
+
}
|
|
1307
|
+
} else
|
|
1308
|
+
"undefined" != typeof console &&
|
|
1309
|
+
console.error("[Radar] Configuration incomplete");
|
|
1310
|
+
})({
|
|
1311
|
+
apiEndpoint: "${apiEndpoint}",
|
|
1312
|
+
cdn: "${cdn}",
|
|
1313
|
+
namespace: "${namespace}",
|
|
1314
|
+
profileId: "${snitcher.profileId}",
|
|
1315
|
+
});
|
|
1316
|
+
})();
|
|
1317
|
+
`;
|
|
1318
|
+
const script = document.createElement("script");
|
|
1319
|
+
script.id = KENOBI_SNITCHER_SCRIPT_ID;
|
|
1320
|
+
script.type = "text/javascript";
|
|
1321
|
+
script.text = snitcherScript;
|
|
1322
|
+
document.head?.appendChild(script);
|
|
1323
|
+
window.__kenobiSnitcherLoaded = true;
|
|
1324
|
+
window.__kenobiSnitcherLoading = false;
|
|
1325
|
+
}, "ensureKenobiSnitcherLoaded");
|
|
1132
1326
|
var STYLES = `
|
|
1133
1327
|
:host { --kb-font-family: system-ui, -apple-system, sans-serif; --kb-bg-container: rgba(255, 255, 255, 0.05); --kb-border-container: rgba(255, 255, 255, 0.2); --kb-shadow-container: 0 25px 50px -12px rgba(0, 0, 0, 0.25); --kb-backdrop-blur: 16px; --kb-text-title: #ffffff; --kb-text-subtitle: rgba(255, 255, 255, 0.7); --kb-btn-dismiss-bg: rgba(0, 0, 0, 0.7); --kb-btn-dismiss-border: rgba(255, 255, 255, 0.2); --kb-btn-dismiss-text: rgba(255, 255, 255, 0.8); --kb-btn-dismiss-hover-bg: rgba(0, 0, 0, 0.9); --kb-btn-dismiss-hover-text: #ffffff; --kb-btn-trigger-bg: #ffffff; --kb-btn-trigger-text: #000000; --kb-btn-trigger-hover-bg: rgba(255, 255, 255, 0.9); --kb-progress-track: rgba(255, 255, 255, 0.2); --kb-progress-indicator: #ffffff; --kb-popover-bg: rgba(255, 255, 255, 0.05); --kb-popover-border: rgba(255, 255, 255, 0.2); --kb-popover-text: #ffffff; --kb-input-bg: transparent; --kb-input-border: rgba(255, 255, 255, 0.3); --kb-input-text: #ffffff; --kb-input-placeholder: rgba(255, 255, 255, 0.6); --kb-form-label: #ffffff; --kb-success-color: #6ee7b7; --kb-error-text: #ef4444; --kb-focus-blur: 10px; --kb-kbd-bg: rgba(255, 255, 255, 0.15); --kb-kbd-border: rgba(255, 255, 255, 0.4); --kb-kbd-text: #ffffff; --kb-watermark-text: rgba(255, 255, 255, 0.4); font-family: var(--kb-font-family); }
|
|
1134
1328
|
.theme-light { --kb-bg-container: #ffffff; --kb-border-container: #e2e8f0; --kb-shadow-container: 0 20px 25px -5px rgba(0, 0, 0, 0.1); --kb-backdrop-blur: 0px; --kb-text-title: #0f172a; --kb-text-subtitle: #475569; --kb-btn-dismiss-bg: #ffffff; --kb-btn-dismiss-border: #e2e8f0; --kb-btn-dismiss-text: #64748b; --kb-btn-dismiss-hover-bg: #f1f5f9; --kb-btn-dismiss-hover-text: #0f172a; --kb-btn-trigger-bg: #0f172a; --kb-btn-trigger-text: #ffffff; --kb-btn-trigger-hover-bg: #1e293b; --kb-progress-track: #e2e8f0; --kb-progress-indicator: #0f172a; --kb-popover-bg: #ffffff; --kb-popover-border: #e2e8f0; --kb-popover-text: #0f172a; --kb-input-bg: #ffffff; --kb-input-border: #cbd5e1; --kb-input-text: #0f172a; --kb-input-placeholder: #94a3b8; --kb-form-label: #334155; --kb-success-color: #059669; --kb-error-text: #ef4444; --kb-kbd-bg: #f1f5f9; --kb-kbd-border: #e2e8f0; --kb-kbd-text: #64748b; --kb-watermark-text: #94a3b8; }
|
|
@@ -1142,6 +1336,17 @@ var KenobiLib = (() => {
|
|
|
1142
1336
|
.launcher .kbd-hint .kbd { background: var(--kb-kbd-bg); border: 1px solid var(--kb-kbd-border); color: var(--kb-kbd-text); }
|
|
1143
1337
|
.launcher .kbd-hint .kbd-text { color: var(--kb-kbd-text); }
|
|
1144
1338
|
.launcher:hover { transform: scale(1.02); background-color: var(--kb-bg-container); }
|
|
1339
|
+
.kb-chip-row { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; }
|
|
1340
|
+
.kb-chip { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.35rem 0.8rem; border-radius: 9999px; border: 1px solid rgba(255,255,255,0.85); background: linear-gradient(135deg, rgba(255,255,255,0.28), rgba(255,255,255,0.08)); color: var(--kb-text-title); font-size: 0.8rem; font-weight: 600; backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); box-shadow: 0 8px 18px rgba(0,0,0,0.4), inset 0 0 0 1px rgba(255,255,255,0.45); }
|
|
1341
|
+
.kb-chip-logo { width: 18px; height: 18px; border-radius: 9999px; overflow: hidden; background: rgba(255,255,255,0.2); display: flex; align-items: center; justify-content: center; }
|
|
1342
|
+
.kb-chip-logo img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
1343
|
+
.kb-chip-fallback { width: 18px; height: 18px; border-radius: 9999px; display: flex; align-items: center; justify-content: center; font-size: 0.7rem; font-weight: 700; color: var(--kb-text-title); background: rgba(255,255,255,0.25); }
|
|
1344
|
+
.kb-chip-action { margin-left: 0.35rem; font-size: 0.7rem; color: var(--kb-text-subtitle); text-decoration: underline; background: none; border: none; padding: 0; cursor: pointer; }
|
|
1345
|
+
.kb-chip-action:hover { color: var(--kb-text-title); }
|
|
1346
|
+
.kb-chip--launcher { padding: 0.25rem 0.65rem; font-size: 0.7rem; }
|
|
1347
|
+
.kb-chip-row.launcher-row { margin-bottom: 0; }
|
|
1348
|
+
.launcher-label { display: inline-flex; align-items: center; gap: 0.5rem; }
|
|
1349
|
+
.subtitle-chip { margin-top: 0.35rem; }
|
|
1145
1350
|
.pos-top-center { left: 50%; translate: -50% 0; top: 1rem; }
|
|
1146
1351
|
.pos-top-right { right: 1rem; top: 1rem; left: auto; }
|
|
1147
1352
|
@media (max-width: 768px) { .pos-top-center, .pos-top-right { left: 0.5rem; right: 0.5rem; top: 0.5rem; translate: none; width: auto; max-width: none; } }
|
|
@@ -1156,7 +1361,7 @@ var KenobiLib = (() => {
|
|
|
1156
1361
|
.text-content { flex: 1; user-select: none; }
|
|
1157
1362
|
.text-row { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; }
|
|
1158
1363
|
.title { color: var(--kb-text-title); font-size: 1rem; font-weight: 600; line-height: 1.5; }
|
|
1159
|
-
.subtitle { color: var(--kb-text-title); font-size: 0.875rem; line-height: 1.25; opacity: 0.8; }
|
|
1364
|
+
.subtitle-text { color: var(--kb-text-title); font-size: 0.875rem; line-height: 1.25; opacity: 0.8; }
|
|
1160
1365
|
.btn { display: inline-flex; align-items: center; justify-content: center; border-radius: 0.375rem; font-weight: 500; font-size: 0.875rem; line-height: 1.25rem; padding: 0.5rem 1rem; transition: all 0.2s; cursor: pointer; border: none; outline: none; }
|
|
1161
1366
|
.btn-trigger { background-color: var(--kb-btn-trigger-bg); color: var(--kb-btn-trigger-text); min-width: 8rem; gap: 0.5rem; transition: opacity 0.2s ease-out, background-color 0.2s ease-out; }
|
|
1162
1367
|
.btn-trigger.hidden { opacity: 0; pointer-events: none; }
|
|
@@ -1321,7 +1526,14 @@ var KenobiLib = (() => {
|
|
|
1321
1526
|
}
|
|
1322
1527
|
return styles;
|
|
1323
1528
|
}, "getThemeStyles");
|
|
1324
|
-
var CueCardContent = /* @__PURE__ */ __name(({
|
|
1529
|
+
var CueCardContent = /* @__PURE__ */ __name(({
|
|
1530
|
+
config,
|
|
1531
|
+
isOpen,
|
|
1532
|
+
skipFocus,
|
|
1533
|
+
setIsOpen,
|
|
1534
|
+
deanonymizedCompany,
|
|
1535
|
+
onClearDeanonymizedCompany
|
|
1536
|
+
}) => {
|
|
1325
1537
|
const isInline = config.mountMode === "inline";
|
|
1326
1538
|
const containerRef = A2(null);
|
|
1327
1539
|
const launcherRef = A2(null);
|
|
@@ -1348,6 +1560,14 @@ var KenobiLib = (() => {
|
|
|
1348
1560
|
const timerProgressRef = A2(0);
|
|
1349
1561
|
const timerEnabled = config.enableTimer !== false;
|
|
1350
1562
|
const timerDuration = Math.max(500, config.timerDurationMs ?? 2e4);
|
|
1563
|
+
const isPending = config.status === "starting";
|
|
1564
|
+
const isSuccess = config.status === "success";
|
|
1565
|
+
const isError = config.status === "error";
|
|
1566
|
+
const isDeanonymized = !!deanonymizedCompany;
|
|
1567
|
+
const isPopoverEnabled = !isDeanonymized;
|
|
1568
|
+
const isPopoverOpen = isPopoverEnabled ? isOpen : false;
|
|
1569
|
+
const deanonymizedLabel = deanonymizedCompany?.name || deanonymizedCompany?.domain || "";
|
|
1570
|
+
const deanonymizedDomain = deanonymizedCompany?.domain;
|
|
1351
1571
|
const setTimerProgress = q2((value) => {
|
|
1352
1572
|
timerProgressRef.current = value;
|
|
1353
1573
|
setTimerProgressState(value);
|
|
@@ -1415,7 +1635,7 @@ var KenobiLib = (() => {
|
|
|
1415
1635
|
skipFocusRef.current = true;
|
|
1416
1636
|
}
|
|
1417
1637
|
y2(() => {
|
|
1418
|
-
if (
|
|
1638
|
+
if (isPopoverOpen) {
|
|
1419
1639
|
if (hasHadSuccess && formRef.current) {
|
|
1420
1640
|
formRef.current.reset();
|
|
1421
1641
|
}
|
|
@@ -1430,15 +1650,15 @@ var KenobiLib = (() => {
|
|
|
1430
1650
|
return () => clearTimeout(focusTimer);
|
|
1431
1651
|
}
|
|
1432
1652
|
}
|
|
1433
|
-
}, [
|
|
1434
|
-
const prevIsOpenForExpandRef = A2(
|
|
1653
|
+
}, [isPopoverOpen]);
|
|
1654
|
+
const prevIsOpenForExpandRef = A2(isPopoverOpen);
|
|
1435
1655
|
y2(() => {
|
|
1436
1656
|
const wasOpen = prevIsOpenForExpandRef.current;
|
|
1437
|
-
prevIsOpenForExpandRef.current =
|
|
1438
|
-
if (!wasOpen &&
|
|
1657
|
+
prevIsOpenForExpandRef.current = isPopoverOpen;
|
|
1658
|
+
if (!wasOpen && isPopoverOpen && mode === "launcher") {
|
|
1439
1659
|
setMode("card");
|
|
1440
1660
|
}
|
|
1441
|
-
}, [
|
|
1661
|
+
}, [isPopoverOpen, mode]);
|
|
1442
1662
|
const isFirstAppearance = !hasEnteredRef.current;
|
|
1443
1663
|
const wasLauncherPreviously = previousModeRef.current === "launcher";
|
|
1444
1664
|
const cardEntranceDelay = isFirstAppearance ? config.entranceDelayMs || 0 : wasLauncherPreviously && mode === "card" ? 400 : 0;
|
|
@@ -1528,7 +1748,7 @@ var KenobiLib = (() => {
|
|
|
1528
1748
|
e3.preventDefault();
|
|
1529
1749
|
if (mode === "launcher") {
|
|
1530
1750
|
setMode("card");
|
|
1531
|
-
setIsOpen(
|
|
1751
|
+
setIsOpen(isPopoverEnabled);
|
|
1532
1752
|
} else if (mode === "card") {
|
|
1533
1753
|
if (config.enableLauncher) {
|
|
1534
1754
|
setMode("launcher");
|
|
@@ -1542,11 +1762,12 @@ var KenobiLib = (() => {
|
|
|
1542
1762
|
return () => window.removeEventListener("keydown", handleKey);
|
|
1543
1763
|
}, [
|
|
1544
1764
|
config.isVisible,
|
|
1545
|
-
|
|
1765
|
+
isPopoverOpen,
|
|
1546
1766
|
mode,
|
|
1547
1767
|
config.enableLauncher,
|
|
1548
1768
|
setIsOpen,
|
|
1549
|
-
config.onDismiss
|
|
1769
|
+
config.onDismiss,
|
|
1770
|
+
isPopoverEnabled
|
|
1550
1771
|
]);
|
|
1551
1772
|
const isMac = typeof navigator !== "undefined" && /Mac/.test(navigator.userAgent);
|
|
1552
1773
|
const shortcutDisplay = (() => {
|
|
@@ -1562,9 +1783,24 @@ var KenobiLib = (() => {
|
|
|
1562
1783
|
}
|
|
1563
1784
|
return [isMac ? "\u2318" : "Ctrl", "P"];
|
|
1564
1785
|
})();
|
|
1565
|
-
const
|
|
1566
|
-
const
|
|
1567
|
-
|
|
1786
|
+
const [logoFailed, setLogoFailed] = d2(false);
|
|
1787
|
+
const [logoAttempt, setLogoAttempt] = d2(
|
|
1788
|
+
"primary"
|
|
1789
|
+
);
|
|
1790
|
+
y2(() => {
|
|
1791
|
+
setLogoFailed(false);
|
|
1792
|
+
setLogoAttempt("primary");
|
|
1793
|
+
}, [deanonymizedCompany?.logoUrl, deanonymizedLabel, deanonymizedDomain]);
|
|
1794
|
+
y2(() => {
|
|
1795
|
+
if (!isPopoverEnabled && isOpen) {
|
|
1796
|
+
setIsOpen(false);
|
|
1797
|
+
}
|
|
1798
|
+
}, [isPopoverEnabled, isOpen, setIsOpen]);
|
|
1799
|
+
const logoUrlTemplate = config.deanonymization?.logoUrlTemplate;
|
|
1800
|
+
const normalizedLogoDomain = normalizeDomain(deanonymizedDomain);
|
|
1801
|
+
const fallbackLogoUrl = normalizedLogoDomain ? `https://logo.clearbit.com/${normalizedLogoDomain}` : void 0;
|
|
1802
|
+
const primaryLogoUrl = normalizedLogoDomain && logoUrlTemplate ? logoUrlTemplate.replace("{domain}", normalizedLogoDomain) : deanonymizedCompany?.logoUrl || fallbackLogoUrl;
|
|
1803
|
+
const resolvedLogoUrl = logoAttempt === "fallback" && fallbackLogoUrl && fallbackLogoUrl !== primaryLogoUrl ? fallbackLogoUrl : primaryLogoUrl;
|
|
1568
1804
|
const showAsSuccess = isSuccess && isShowingInitialSuccessRef.current;
|
|
1569
1805
|
const txt = config.textOverrides || {};
|
|
1570
1806
|
const titleText = (() => {
|
|
@@ -1591,6 +1827,94 @@ var KenobiLib = (() => {
|
|
|
1591
1827
|
}
|
|
1592
1828
|
return txt.btnResting || "Show me";
|
|
1593
1829
|
})();
|
|
1830
|
+
const launcherLabelText = (() => {
|
|
1831
|
+
if (isDeanonymized) {
|
|
1832
|
+
if (hasHadSuccess) {
|
|
1833
|
+
return txt.launcherLabelDeanonymizedSuccess || txt.launcherLabelDeanonymized || "See it again for";
|
|
1834
|
+
}
|
|
1835
|
+
return txt.launcherLabelDeanonymized || "See it in action for";
|
|
1836
|
+
}
|
|
1837
|
+
if (hasHadSuccess) {
|
|
1838
|
+
return txt.launcherLabelSuccess || txt.launcherLabel || "Personalize again";
|
|
1839
|
+
}
|
|
1840
|
+
return txt.launcherLabel || "Personalize";
|
|
1841
|
+
})();
|
|
1842
|
+
const renderDeanonymizedChip = /* @__PURE__ */ __name((variant) => {
|
|
1843
|
+
if (!deanonymizedCompany || !deanonymizedLabel) return null;
|
|
1844
|
+
const isLauncher = variant === "launcher";
|
|
1845
|
+
const fallbackLetter = deanonymizedLabel.trim().slice(0, 1).toUpperCase();
|
|
1846
|
+
const showLogo = !!resolvedLogoUrl && !logoFailed;
|
|
1847
|
+
return /* @__PURE__ */ u3("div", { class: `kb-chip ${isLauncher ? "kb-chip--launcher" : ""}`, children: [
|
|
1848
|
+
showLogo ? /* @__PURE__ */ u3("span", { class: "kb-chip-logo", children: /* @__PURE__ */ u3(
|
|
1849
|
+
"img",
|
|
1850
|
+
{
|
|
1851
|
+
src: resolvedLogoUrl,
|
|
1852
|
+
alt: "",
|
|
1853
|
+
referrerPolicy: "no-referrer",
|
|
1854
|
+
onError: () => {
|
|
1855
|
+
if (logoAttempt === "primary" && fallbackLogoUrl && fallbackLogoUrl !== primaryLogoUrl) {
|
|
1856
|
+
setLogoAttempt("fallback");
|
|
1857
|
+
return;
|
|
1858
|
+
}
|
|
1859
|
+
setLogoFailed(true);
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
) }) : /* @__PURE__ */ u3("span", { class: "kb-chip-fallback", children: fallbackLetter }),
|
|
1863
|
+
/* @__PURE__ */ u3("span", { children: deanonymizedLabel }),
|
|
1864
|
+
onClearDeanonymizedCompany && /* @__PURE__ */ u3(
|
|
1865
|
+
"button",
|
|
1866
|
+
{
|
|
1867
|
+
class: "kb-chip-action",
|
|
1868
|
+
type: "button",
|
|
1869
|
+
onClick: (e3) => {
|
|
1870
|
+
e3.stopPropagation();
|
|
1871
|
+
onClearDeanonymizedCompany();
|
|
1872
|
+
setIsOpen(true);
|
|
1873
|
+
},
|
|
1874
|
+
children: "Not you?"
|
|
1875
|
+
}
|
|
1876
|
+
)
|
|
1877
|
+
] });
|
|
1878
|
+
}, "renderDeanonymizedChip");
|
|
1879
|
+
const buildDeanonymizedValues = /* @__PURE__ */ __name(() => {
|
|
1880
|
+
const normalizedInputDomain = normalizeDomain(deanonymizedDomain);
|
|
1881
|
+
const fallbackValue = (normalizedInputDomain || deanonymizedDomain || deanonymizedLabel || "").toString();
|
|
1882
|
+
const values = {};
|
|
1883
|
+
config.fields.forEach((field) => {
|
|
1884
|
+
const key = field.name;
|
|
1885
|
+
const lowerKey = key.toLowerCase();
|
|
1886
|
+
if (lowerKey.includes("domain")) {
|
|
1887
|
+
values[key] = normalizedInputDomain || fallbackValue;
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
if (lowerKey.includes("company")) {
|
|
1891
|
+
values[key] = deanonymizedLabel;
|
|
1892
|
+
return;
|
|
1893
|
+
}
|
|
1894
|
+
values[key] = fallbackValue;
|
|
1895
|
+
});
|
|
1896
|
+
return values;
|
|
1897
|
+
}, "buildDeanonymizedValues");
|
|
1898
|
+
const submitValues = /* @__PURE__ */ __name((values) => {
|
|
1899
|
+
const newErrors = {};
|
|
1900
|
+
let hasErrors = false;
|
|
1901
|
+
config.fields.forEach((field) => {
|
|
1902
|
+
const rawValue = values[field.name] ?? "";
|
|
1903
|
+
const value = typeof rawValue === "string" ? rawValue : String(rawValue);
|
|
1904
|
+
const error = validateField(field.name, value, field);
|
|
1905
|
+
if (error) {
|
|
1906
|
+
newErrors[field.name] = error;
|
|
1907
|
+
hasErrors = true;
|
|
1908
|
+
}
|
|
1909
|
+
});
|
|
1910
|
+
if (hasErrors) {
|
|
1911
|
+
setErrors(newErrors);
|
|
1912
|
+
return;
|
|
1913
|
+
}
|
|
1914
|
+
setErrors({});
|
|
1915
|
+
setIsOpen(false);
|
|
1916
|
+
config.onSubmitPersonalization?.(values);
|
|
1917
|
+
}, "submitValues");
|
|
1594
1918
|
const validateField = /* @__PURE__ */ __name((name, value, fieldConfig) => {
|
|
1595
1919
|
if (!fieldConfig) return null;
|
|
1596
1920
|
if (fieldConfig.required && !value.trim()) {
|
|
@@ -1629,25 +1953,11 @@ var KenobiLib = (() => {
|
|
|
1629
1953
|
if (isPending) return;
|
|
1630
1954
|
const formData = new FormData(e3.target);
|
|
1631
1955
|
const values = {};
|
|
1632
|
-
const newErrors = {};
|
|
1633
|
-
let hasErrors = false;
|
|
1634
1956
|
formData.forEach((value, key) => {
|
|
1635
1957
|
const strValue = value.toString();
|
|
1636
1958
|
values[key] = strValue;
|
|
1637
|
-
const fieldConfig = config.fields.find((f4) => f4.name === key);
|
|
1638
|
-
const error = validateField(key, strValue, fieldConfig);
|
|
1639
|
-
if (error) {
|
|
1640
|
-
newErrors[key] = error;
|
|
1641
|
-
hasErrors = true;
|
|
1642
|
-
}
|
|
1643
1959
|
});
|
|
1644
|
-
|
|
1645
|
-
setErrors(newErrors);
|
|
1646
|
-
return;
|
|
1647
|
-
}
|
|
1648
|
-
setErrors({});
|
|
1649
|
-
setIsOpen(false);
|
|
1650
|
-
config.onSubmitPersonalization?.(values);
|
|
1960
|
+
submitValues(values);
|
|
1651
1961
|
}, "handleSubmit");
|
|
1652
1962
|
const handleInput = /* @__PURE__ */ __name((e3) => {
|
|
1653
1963
|
const target = e3.target;
|
|
@@ -1666,10 +1976,15 @@ var KenobiLib = (() => {
|
|
|
1666
1976
|
});
|
|
1667
1977
|
}
|
|
1668
1978
|
}, "handleInput");
|
|
1979
|
+
const handleDeanonymizedSubmit = /* @__PURE__ */ __name(() => {
|
|
1980
|
+
if (isPending || !isDeanonymized) return;
|
|
1981
|
+
submitValues(buildDeanonymizedValues());
|
|
1982
|
+
}, "handleDeanonymizedSubmit");
|
|
1669
1983
|
const togglePopover = /* @__PURE__ */ __name((e3) => {
|
|
1670
1984
|
e3.stopPropagation();
|
|
1985
|
+
if (isDeanonymized) return;
|
|
1671
1986
|
if (isPending || isSuccess) return;
|
|
1672
|
-
const opening = !
|
|
1987
|
+
const opening = !isPopoverOpen;
|
|
1673
1988
|
setIsOpen(opening);
|
|
1674
1989
|
if (opening && config.enableClickSheen) {
|
|
1675
1990
|
setSheenActive(true);
|
|
@@ -1679,7 +1994,7 @@ var KenobiLib = (() => {
|
|
|
1679
1994
|
y2(() => {
|
|
1680
1995
|
if (!timerEnabled) return;
|
|
1681
1996
|
if (hasTimerCompletedRef.current) return;
|
|
1682
|
-
const shouldRun = config.isVisible && mode === "card" && config.status === "resting" && !
|
|
1997
|
+
const shouldRun = config.isVisible && mode === "card" && config.status === "resting" && !isPopoverOpen && !isHovering;
|
|
1683
1998
|
if (!shouldRun) {
|
|
1684
1999
|
if (timerRafRef.current !== null) {
|
|
1685
2000
|
cancelAnimationFrame(timerRafRef.current);
|
|
@@ -1723,7 +2038,7 @@ var KenobiLib = (() => {
|
|
|
1723
2038
|
config.onDismiss,
|
|
1724
2039
|
config.status,
|
|
1725
2040
|
isHovering,
|
|
1726
|
-
|
|
2041
|
+
isPopoverOpen,
|
|
1727
2042
|
mode,
|
|
1728
2043
|
setIsOpen,
|
|
1729
2044
|
timerDuration,
|
|
@@ -1755,12 +2070,12 @@ var KenobiLib = (() => {
|
|
|
1755
2070
|
"div",
|
|
1756
2071
|
{
|
|
1757
2072
|
ref: containerRef,
|
|
1758
|
-
class: `container theme-${config.theme || "glass"} pos-${config.position || "top-center"}${
|
|
2073
|
+
class: `container theme-${config.theme || "glass"} pos-${config.position || "top-center"}${isPopoverOpen ? " popover-open" : ""}`,
|
|
1759
2074
|
style: {
|
|
1760
2075
|
...getThemeStyles(config.customTheme),
|
|
1761
2076
|
pointerEvents: isContainerVisible ? "auto" : "none"
|
|
1762
2077
|
},
|
|
1763
|
-
onClick: () => !
|
|
2078
|
+
onClick: () => !isPopoverOpen && !isPending && !isSuccess && isPopoverEnabled && setIsOpen(true),
|
|
1764
2079
|
onMouseEnter: () => setIsHovering(true),
|
|
1765
2080
|
onMouseLeave: () => setIsHovering(false),
|
|
1766
2081
|
children: [
|
|
@@ -1785,7 +2100,7 @@ var KenobiLib = (() => {
|
|
|
1785
2100
|
/* @__PURE__ */ u3("div", { class: "content-wrapper", children: /* @__PURE__ */ u3("div", { class: "text-content", children: /* @__PURE__ */ u3("div", { class: "text-row", children: [
|
|
1786
2101
|
/* @__PURE__ */ u3("div", { children: [
|
|
1787
2102
|
/* @__PURE__ */ u3("div", { class: "title", children: titleText }),
|
|
1788
|
-
/* @__PURE__ */ u3("div", { class: "subtitle", children: subtitleText })
|
|
2103
|
+
isDeanonymized ? /* @__PURE__ */ u3("div", { class: "subtitle-chip", children: renderDeanonymizedChip("card") }) : /* @__PURE__ */ u3("div", { class: "subtitle-text", children: subtitleText })
|
|
1789
2104
|
] }),
|
|
1790
2105
|
isPending ? /* @__PURE__ */ u3("span", { class: "status-text", children: [
|
|
1791
2106
|
/* @__PURE__ */ u3(LoaderIcon, {}),
|
|
@@ -1794,9 +2109,9 @@ var KenobiLib = (() => {
|
|
|
1794
2109
|
] }) : /* @__PURE__ */ u3(
|
|
1795
2110
|
"button",
|
|
1796
2111
|
{
|
|
1797
|
-
class: `btn btn-trigger ${showAsSuccess ? "success" : ""}${
|
|
2112
|
+
class: `btn btn-trigger ${showAsSuccess ? "success" : ""}${isPopoverOpen || isExitingToLauncher ? " hidden" : ""}`,
|
|
1798
2113
|
disabled: showAsSuccess,
|
|
1799
|
-
onClick: togglePopover,
|
|
2114
|
+
onClick: isDeanonymized ? handleDeanonymizedSubmit : togglePopover,
|
|
1800
2115
|
children: showAsSuccess ? /* @__PURE__ */ u3(k, { children: [
|
|
1801
2116
|
/* @__PURE__ */ u3(CheckIcon, {}),
|
|
1802
2117
|
" ",
|
|
@@ -1814,10 +2129,10 @@ var KenobiLib = (() => {
|
|
|
1814
2129
|
}
|
|
1815
2130
|
}
|
|
1816
2131
|
) }) }),
|
|
1817
|
-
/* @__PURE__ */ u3(
|
|
2132
|
+
!isDeanonymized && /* @__PURE__ */ u3(
|
|
1818
2133
|
"div",
|
|
1819
2134
|
{
|
|
1820
|
-
class: `popover ${
|
|
2135
|
+
class: `popover ${isPopoverOpen ? "open" : ""}`,
|
|
1821
2136
|
onClick: (e3) => e3.stopPropagation(),
|
|
1822
2137
|
children: [
|
|
1823
2138
|
/* @__PURE__ */ u3("form", { onSubmit: handleSubmit, ref: formRef, children: [
|
|
@@ -1884,7 +2199,7 @@ var KenobiLib = (() => {
|
|
|
1884
2199
|
config.showKeyboardHints && config.enableFocusMode && /* @__PURE__ */ u3(
|
|
1885
2200
|
"div",
|
|
1886
2201
|
{
|
|
1887
|
-
class: `kbd-hint ${!
|
|
2202
|
+
class: `kbd-hint ${!isPopoverOpen && !isPending && !isSuccess ? "visible" : ""}`,
|
|
1888
2203
|
children: [
|
|
1889
2204
|
/* @__PURE__ */ u3("div", { class: "kbd-group", children: /* @__PURE__ */ u3("div", { class: "kbd", children: "Esc" }) }),
|
|
1890
2205
|
/* @__PURE__ */ u3("span", { class: "kbd-text", children: "to dismiss" })
|
|
@@ -1908,7 +2223,7 @@ var KenobiLib = (() => {
|
|
|
1908
2223
|
e3.stopPropagation();
|
|
1909
2224
|
setIsDismissed(false);
|
|
1910
2225
|
setMode("card");
|
|
1911
|
-
setIsOpen(
|
|
2226
|
+
setIsOpen(isPopoverEnabled);
|
|
1912
2227
|
},
|
|
1913
2228
|
role: "button",
|
|
1914
2229
|
tabIndex: 0,
|
|
@@ -1938,7 +2253,10 @@ var KenobiLib = (() => {
|
|
|
1938
2253
|
}
|
|
1939
2254
|
),
|
|
1940
2255
|
config.showLauncherLogo !== false && /* @__PURE__ */ u3("div", { class: "launcher-logo", children: /* @__PURE__ */ u3(LogoIcon, {}) }),
|
|
1941
|
-
|
|
2256
|
+
/* @__PURE__ */ u3("div", { class: "launcher-label", children: [
|
|
2257
|
+
/* @__PURE__ */ u3("span", { children: launcherLabelText }),
|
|
2258
|
+
isDeanonymized && renderDeanonymizedChip("launcher")
|
|
2259
|
+
] }),
|
|
1942
2260
|
config.enableUndoToggle && hasHadSuccess && /* @__PURE__ */ u3(
|
|
1943
2261
|
"button",
|
|
1944
2262
|
{
|
|
@@ -1968,6 +2286,33 @@ var KenobiLib = (() => {
|
|
|
1968
2286
|
__publicField(this, "isOpen", false);
|
|
1969
2287
|
__publicField(this, "skipFocus", false);
|
|
1970
2288
|
__publicField(this, "mountTarget", null);
|
|
2289
|
+
__publicField(this, "deanonymizedCompany", null);
|
|
2290
|
+
__publicField(this, "deanonymizationStatus", "idle");
|
|
2291
|
+
__publicField(this, "deanonymizationCleanup", null);
|
|
2292
|
+
__publicField(this, "hasStartedDeanonymization", false);
|
|
2293
|
+
__publicField(this, "clearDeanonymizedCompany", /* @__PURE__ */ __name(() => {
|
|
2294
|
+
const previousCompany = this.deanonymizedCompany;
|
|
2295
|
+
const shouldResetStatus = this.config.status === "success" || this.config.isPersonalized;
|
|
2296
|
+
if (this.config.isPersonalized) {
|
|
2297
|
+
this.config.onTogglePersonalization?.();
|
|
2298
|
+
}
|
|
2299
|
+
this.deanonymizedCompany = null;
|
|
2300
|
+
this.deanonymizationStatus = "failed";
|
|
2301
|
+
if (previousCompany) {
|
|
2302
|
+
dispatchCueCardEvent("deanonymization:not-you", {
|
|
2303
|
+
company: previousCompany
|
|
2304
|
+
});
|
|
2305
|
+
}
|
|
2306
|
+
if (shouldResetStatus) {
|
|
2307
|
+
this.config = {
|
|
2308
|
+
...this.config,
|
|
2309
|
+
status: "resting",
|
|
2310
|
+
progressPct: 0,
|
|
2311
|
+
isPersonalized: false
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2314
|
+
this.render();
|
|
2315
|
+
}, "clearDeanonymizedCompany"));
|
|
1971
2316
|
this.config = {
|
|
1972
2317
|
position: "top-center",
|
|
1973
2318
|
direction: "top-to-bottom",
|
|
@@ -1990,6 +2335,9 @@ var KenobiLib = (() => {
|
|
|
1990
2335
|
...config
|
|
1991
2336
|
};
|
|
1992
2337
|
this.mountTarget = config.mountNode ?? null;
|
|
2338
|
+
if (this.isDeanonymizationEnabled()) {
|
|
2339
|
+
this.deanonymizationStatus = "pending";
|
|
2340
|
+
}
|
|
1993
2341
|
this.host = document.createElement("div");
|
|
1994
2342
|
this.host.id = "kenobi-cue-card-root";
|
|
1995
2343
|
this.applyHostStyles();
|
|
@@ -2038,20 +2386,95 @@ var KenobiLib = (() => {
|
|
|
2038
2386
|
resolvedTarget.appendChild(this.host);
|
|
2039
2387
|
}
|
|
2040
2388
|
this.applyHostStyles();
|
|
2389
|
+
this.startDeanonymization();
|
|
2041
2390
|
this.render();
|
|
2042
2391
|
}
|
|
2043
2392
|
unmount() {
|
|
2044
2393
|
G(null, this.shadow.lastElementChild);
|
|
2045
2394
|
this.host.remove();
|
|
2395
|
+
this.deanonymizationCleanup?.();
|
|
2396
|
+
this.deanonymizationCleanup = null;
|
|
2046
2397
|
}
|
|
2047
2398
|
update(newState) {
|
|
2048
2399
|
if (newState.status === "starting" && this.config.status !== "starting") {
|
|
2049
2400
|
this.isOpen = false;
|
|
2050
2401
|
}
|
|
2402
|
+
const wasDeanonymizationEnabled = this.isDeanonymizationEnabled();
|
|
2051
2403
|
this.config = { ...this.config, ...newState };
|
|
2404
|
+
const isDeanonymizationEnabled = this.isDeanonymizationEnabled();
|
|
2405
|
+
if (isDeanonymizationEnabled && !wasDeanonymizationEnabled) {
|
|
2406
|
+
this.deanonymizationStatus = "pending";
|
|
2407
|
+
this.startDeanonymization();
|
|
2408
|
+
}
|
|
2409
|
+
if (!isDeanonymizationEnabled && wasDeanonymizationEnabled) {
|
|
2410
|
+
this.deanonymizedCompany = null;
|
|
2411
|
+
this.deanonymizationStatus = "idle";
|
|
2412
|
+
this.deanonymizationCleanup?.();
|
|
2413
|
+
this.deanonymizationCleanup = null;
|
|
2414
|
+
this.hasStartedDeanonymization = false;
|
|
2415
|
+
}
|
|
2052
2416
|
this.applyHostStyles();
|
|
2053
2417
|
this.render();
|
|
2054
2418
|
}
|
|
2419
|
+
isDeanonymizationEnabled() {
|
|
2420
|
+
return this.config.deanonymization?.provider === "Kenobi";
|
|
2421
|
+
}
|
|
2422
|
+
startDeanonymization() {
|
|
2423
|
+
if (!this.isDeanonymizationEnabled()) return;
|
|
2424
|
+
if (this.hasStartedDeanonymization) return;
|
|
2425
|
+
if (this.deanonymizationStatus !== "pending") return;
|
|
2426
|
+
this.hasStartedDeanonymization = true;
|
|
2427
|
+
if (typeof window === "undefined") {
|
|
2428
|
+
this.deanonymizationStatus = "failed";
|
|
2429
|
+
this.render();
|
|
2430
|
+
return;
|
|
2431
|
+
}
|
|
2432
|
+
const cachedIdentity = window.__kenobiIdentityResolution;
|
|
2433
|
+
if (cachedIdentity) {
|
|
2434
|
+
this.handleDeanonymizationResult(cachedIdentity);
|
|
2435
|
+
return;
|
|
2436
|
+
}
|
|
2437
|
+
const handleEvent = /* @__PURE__ */ __name((event) => {
|
|
2438
|
+
const detail = event.detail;
|
|
2439
|
+
this.handleDeanonymizationResult(detail);
|
|
2440
|
+
}, "handleEvent");
|
|
2441
|
+
window.addEventListener(IDENTITY_RESOLVED_EVENT, handleEvent);
|
|
2442
|
+
ensureKenobiSnitcherLoaded(this.config.deanonymization);
|
|
2443
|
+
const timeoutMs = this.config.deanonymization?.timeoutMs ?? DEFAULT_DEANON_TIMEOUT_MS;
|
|
2444
|
+
const timeoutId = window.setTimeout(() => {
|
|
2445
|
+
window.removeEventListener(IDENTITY_RESOLVED_EVENT, handleEvent);
|
|
2446
|
+
this.handleDeanonymizationResult(null);
|
|
2447
|
+
}, timeoutMs);
|
|
2448
|
+
this.deanonymizationCleanup = () => {
|
|
2449
|
+
window.removeEventListener(IDENTITY_RESOLVED_EVENT, handleEvent);
|
|
2450
|
+
window.clearTimeout(timeoutId);
|
|
2451
|
+
};
|
|
2452
|
+
}
|
|
2453
|
+
handleDeanonymizationResult(detail) {
|
|
2454
|
+
if (this.deanonymizationStatus !== "pending") return;
|
|
2455
|
+
this.deanonymizationCleanup?.();
|
|
2456
|
+
this.deanonymizationCleanup = null;
|
|
2457
|
+
const company = resolveDeanonymizedCompany(detail);
|
|
2458
|
+
this.deanonymizedCompany = company;
|
|
2459
|
+
this.deanonymizationStatus = company ? "resolved" : "failed";
|
|
2460
|
+
if (company) {
|
|
2461
|
+
dispatchCueCardEvent("deanonymization:success", {
|
|
2462
|
+
company,
|
|
2463
|
+
detail
|
|
2464
|
+
});
|
|
2465
|
+
} else {
|
|
2466
|
+
dispatchCueCardEvent("deanonymization:fail", {
|
|
2467
|
+
detail
|
|
2468
|
+
});
|
|
2469
|
+
}
|
|
2470
|
+
this.render();
|
|
2471
|
+
}
|
|
2472
|
+
getRenderConfig() {
|
|
2473
|
+
if (this.deanonymizationStatus === "pending") {
|
|
2474
|
+
return { ...this.config, isVisible: false };
|
|
2475
|
+
}
|
|
2476
|
+
return this.config;
|
|
2477
|
+
}
|
|
2055
2478
|
setTheme(theme) {
|
|
2056
2479
|
this.update({ theme });
|
|
2057
2480
|
}
|
|
@@ -2068,9 +2491,11 @@ var KenobiLib = (() => {
|
|
|
2068
2491
|
/* @__PURE__ */ u3(
|
|
2069
2492
|
CueCardContent,
|
|
2070
2493
|
{
|
|
2071
|
-
config: this.
|
|
2494
|
+
config: this.getRenderConfig(),
|
|
2072
2495
|
isOpen: this.isOpen,
|
|
2073
2496
|
skipFocus: skipFocusOnce,
|
|
2497
|
+
deanonymizedCompany: this.deanonymizedCompany,
|
|
2498
|
+
onClearDeanonymizedCompany: this.clearDeanonymizedCompany,
|
|
2074
2499
|
setIsOpen: (val) => {
|
|
2075
2500
|
this.isOpen = val;
|
|
2076
2501
|
this.config.onOpenChange?.(val);
|
|
@@ -2492,6 +2917,8 @@ var KenobiLib = (() => {
|
|
|
2492
2917
|
};
|
|
2493
2918
|
__name(_TransitionOrchestrator, "TransitionOrchestrator");
|
|
2494
2919
|
var TransitionOrchestrator = _TransitionOrchestrator;
|
|
2920
|
+
var IDENTITY_RESOLVED_EVENT2 = "kenobi:identity-resolved";
|
|
2921
|
+
var DEFAULT_DEANON_TIMEOUT_MS2 = 1600;
|
|
2495
2922
|
var isCueCardConfigResponse = /* @__PURE__ */ __name((value) => {
|
|
2496
2923
|
if (typeof value !== "object" || value === null) return false;
|
|
2497
2924
|
const candidate = value;
|
|
@@ -2528,6 +2955,10 @@ var KenobiLib = (() => {
|
|
|
2528
2955
|
__publicField(this, "visitorKey", null);
|
|
2529
2956
|
__publicField(this, "orchestrator");
|
|
2530
2957
|
__publicField(this, "cueCardInstance", null);
|
|
2958
|
+
__publicField(this, "preparedPersonalization", null);
|
|
2959
|
+
__publicField(this, "isPreparingPersonalization", false);
|
|
2960
|
+
__publicField(this, "preparePersonalizationPromise", null);
|
|
2961
|
+
__publicField(this, "deanonymizationPrefetchCleanup", null);
|
|
2531
2962
|
//
|
|
2532
2963
|
__publicField(this, "currentPath");
|
|
2533
2964
|
__publicField(this, "currentUrl");
|
|
@@ -3227,6 +3658,8 @@ var KenobiLib = (() => {
|
|
|
3227
3658
|
}
|
|
3228
3659
|
this.log("debug", "Active template found, mounting CueCard...");
|
|
3229
3660
|
const serverConfig = configResponse.config;
|
|
3661
|
+
const deanonymizationConfig = serverConfig?.deanonymization;
|
|
3662
|
+
const shouldWaitForDeanonymization = !!deanonymizationConfig?.provider;
|
|
3230
3663
|
this.cueCardInstance = new CueCard({
|
|
3231
3664
|
theme: serverConfig?.theme ?? "light",
|
|
3232
3665
|
position: serverConfig?.position ?? "top-center",
|
|
@@ -3241,7 +3674,7 @@ var KenobiLib = (() => {
|
|
|
3241
3674
|
errorMessage: "Company name or domain is required"
|
|
3242
3675
|
}
|
|
3243
3676
|
],
|
|
3244
|
-
isVisible:
|
|
3677
|
+
isVisible: !shouldWaitForDeanonymization,
|
|
3245
3678
|
enableFocusMode: serverConfig?.enableFocusMode ?? false,
|
|
3246
3679
|
showWatermark: serverConfig?.showWatermark ?? false,
|
|
3247
3680
|
showKeyboardHints: serverConfig?.showKeyboardHints ?? true,
|
|
@@ -3249,6 +3682,7 @@ var KenobiLib = (() => {
|
|
|
3249
3682
|
customTheme: serverConfig?.customTheme,
|
|
3250
3683
|
textOverrides: serverConfig?.textOverrides,
|
|
3251
3684
|
enableUndoToggle: serverConfig?.enableUndoToggle ?? false,
|
|
3685
|
+
deanonymization: deanonymizationConfig,
|
|
3252
3686
|
isPersonalized: this.isPersonalized,
|
|
3253
3687
|
onDismiss: /* @__PURE__ */ __name(() => {
|
|
3254
3688
|
this.log("debug", "CueCard dismissed by user");
|
|
@@ -3277,8 +3711,220 @@ var KenobiLib = (() => {
|
|
|
3277
3711
|
}, "onTogglePersonalization")
|
|
3278
3712
|
});
|
|
3279
3713
|
this.cueCardInstance.mount();
|
|
3714
|
+
if (shouldWaitForDeanonymization) {
|
|
3715
|
+
this.setupDeanonymizationPrefetch(
|
|
3716
|
+
deanonymizationConfig,
|
|
3717
|
+
serverConfig?.fields
|
|
3718
|
+
);
|
|
3719
|
+
}
|
|
3280
3720
|
this.log("debug", "CueCard mounted successfully");
|
|
3281
3721
|
}, "initCueCard"));
|
|
3722
|
+
__publicField(this, "isSameInput", /* @__PURE__ */ __name((a3, b) => {
|
|
3723
|
+
const aKeys = Object.keys(a3).sort();
|
|
3724
|
+
const bKeys = Object.keys(b).sort();
|
|
3725
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
3726
|
+
for (let i3 = 0; i3 < aKeys.length; i3 += 1) {
|
|
3727
|
+
const key = aKeys[i3];
|
|
3728
|
+
if (key !== bKeys[i3]) return false;
|
|
3729
|
+
if ((a3[key] ?? "") !== (b[key] ?? "")) return false;
|
|
3730
|
+
}
|
|
3731
|
+
return true;
|
|
3732
|
+
}, "isSameInput"));
|
|
3733
|
+
__publicField(this, "buildInputFromFields", /* @__PURE__ */ __name((fields, companyName, companyDomain) => {
|
|
3734
|
+
const fallback = companyDomain || companyName;
|
|
3735
|
+
if (!fallback) return null;
|
|
3736
|
+
const input = {};
|
|
3737
|
+
fields.forEach((field) => {
|
|
3738
|
+
const key = field.name;
|
|
3739
|
+
const lowerKey = key.toLowerCase();
|
|
3740
|
+
if (lowerKey.includes("domain")) {
|
|
3741
|
+
input[key] = companyDomain || fallback;
|
|
3742
|
+
return;
|
|
3743
|
+
}
|
|
3744
|
+
if (lowerKey.includes("company")) {
|
|
3745
|
+
input[key] = companyName || fallback;
|
|
3746
|
+
return;
|
|
3747
|
+
}
|
|
3748
|
+
input[key] = fallback;
|
|
3749
|
+
});
|
|
3750
|
+
return input;
|
|
3751
|
+
}, "buildInputFromFields"));
|
|
3752
|
+
__publicField(this, "buildDeanonymizedInput", /* @__PURE__ */ __name((detail, fields) => {
|
|
3753
|
+
const name = detail.company?.name || detail.domain || "";
|
|
3754
|
+
const domain = detail.company?.domain || detail.domain || "";
|
|
3755
|
+
if (!fields || fields.length === 0) {
|
|
3756
|
+
if (!name && !domain) return null;
|
|
3757
|
+
return {
|
|
3758
|
+
companyName: name || domain,
|
|
3759
|
+
companyDomain: domain || name
|
|
3760
|
+
};
|
|
3761
|
+
}
|
|
3762
|
+
return this.buildInputFromFields(fields, name, domain);
|
|
3763
|
+
}, "buildDeanonymizedInput"));
|
|
3764
|
+
__publicField(this, "requestPersonalization", /* @__PURE__ */ __name(async (input, options) => {
|
|
3765
|
+
const payload = {
|
|
3766
|
+
publicKey: this.config.publicKey,
|
|
3767
|
+
input,
|
|
3768
|
+
pagePath: this.currentPath
|
|
3769
|
+
};
|
|
3770
|
+
if (options?.notifySlack === false) {
|
|
3771
|
+
payload.notifySlack = false;
|
|
3772
|
+
}
|
|
3773
|
+
if (options?.notifyOnly) {
|
|
3774
|
+
payload.notifyOnly = true;
|
|
3775
|
+
}
|
|
3776
|
+
if (options?.predictionSource) {
|
|
3777
|
+
payload.predictionSource = options.predictionSource;
|
|
3778
|
+
}
|
|
3779
|
+
if (options?.prefetchedTransformations) {
|
|
3780
|
+
payload.prefetchedTransformations = options.prefetchedTransformations;
|
|
3781
|
+
}
|
|
3782
|
+
if (options?.prefetchedMetadata) {
|
|
3783
|
+
payload.prefetchedMetadata = options.prefetchedMetadata;
|
|
3784
|
+
}
|
|
3785
|
+
const response = await fetch(`${this.config.apiHost}/v1/personalize`, {
|
|
3786
|
+
method: "POST",
|
|
3787
|
+
headers: {
|
|
3788
|
+
"Content-Type": "application/json"
|
|
3789
|
+
},
|
|
3790
|
+
body: JSON.stringify(payload)
|
|
3791
|
+
});
|
|
3792
|
+
if (!response.ok) {
|
|
3793
|
+
const errorBody = await response.json().catch(() => ({}));
|
|
3794
|
+
throw new Error(errorBody.error || `API error: ${response.status}`);
|
|
3795
|
+
}
|
|
3796
|
+
const result = await response.json();
|
|
3797
|
+
this.log("debug", "Personalization API response:", result);
|
|
3798
|
+
return result;
|
|
3799
|
+
}, "requestPersonalization"));
|
|
3800
|
+
__publicField(this, "preparePersonalization", /* @__PURE__ */ __name(async (input, options) => {
|
|
3801
|
+
if (!this.config.publicKey) {
|
|
3802
|
+
this.log("error", "Cannot prepare personalization: publicKey not configured");
|
|
3803
|
+
return null;
|
|
3804
|
+
}
|
|
3805
|
+
if (this.preparedPersonalization?.input && this.isSameInput(this.preparedPersonalization.input, input)) {
|
|
3806
|
+
if (options?.source && !this.preparedPersonalization.source) {
|
|
3807
|
+
this.preparedPersonalization = {
|
|
3808
|
+
...this.preparedPersonalization,
|
|
3809
|
+
source: options.source
|
|
3810
|
+
};
|
|
3811
|
+
}
|
|
3812
|
+
return this.preparedPersonalization.result;
|
|
3813
|
+
}
|
|
3814
|
+
if (this.preparePersonalizationPromise) {
|
|
3815
|
+
return this.preparePersonalizationPromise;
|
|
3816
|
+
}
|
|
3817
|
+
this.isPreparingPersonalization = true;
|
|
3818
|
+
this.preparePersonalizationPromise = (async () => {
|
|
3819
|
+
try {
|
|
3820
|
+
const result = await this.requestPersonalization(input, {
|
|
3821
|
+
notifySlack: false,
|
|
3822
|
+
predictionSource: options?.source
|
|
3823
|
+
});
|
|
3824
|
+
this.preparedPersonalization = { input, result, source: options?.source };
|
|
3825
|
+
this.dispatchKenobiEvent("personalization:ready", {
|
|
3826
|
+
input,
|
|
3827
|
+
pagePath: this.currentPath,
|
|
3828
|
+
transformationsCount: result.transformations?.length ?? 0,
|
|
3829
|
+
metadata: result.metadata,
|
|
3830
|
+
source: options?.source
|
|
3831
|
+
});
|
|
3832
|
+
return result;
|
|
3833
|
+
} catch (error) {
|
|
3834
|
+
this.log("error", "Personalization prefetch failed:", error);
|
|
3835
|
+
return null;
|
|
3836
|
+
} finally {
|
|
3837
|
+
this.isPreparingPersonalization = false;
|
|
3838
|
+
this.preparePersonalizationPromise = null;
|
|
3839
|
+
}
|
|
3840
|
+
})();
|
|
3841
|
+
return this.preparePersonalizationPromise;
|
|
3842
|
+
}, "preparePersonalization"));
|
|
3843
|
+
__publicField(this, "notifyPreparedPersonalization", /* @__PURE__ */ __name(async (prepared) => {
|
|
3844
|
+
if (!prepared.result.transformations || !prepared.result.metadata) {
|
|
3845
|
+
this.log(
|
|
3846
|
+
"warn",
|
|
3847
|
+
"Prepared personalization missing transformations or metadata for notify"
|
|
3848
|
+
);
|
|
3849
|
+
return;
|
|
3850
|
+
}
|
|
3851
|
+
try {
|
|
3852
|
+
await this.requestPersonalization(prepared.input, {
|
|
3853
|
+
notifySlack: true,
|
|
3854
|
+
notifyOnly: true,
|
|
3855
|
+
predictionSource: prepared.source,
|
|
3856
|
+
prefetchedTransformations: prepared.result.transformations,
|
|
3857
|
+
prefetchedMetadata: prepared.result.metadata
|
|
3858
|
+
});
|
|
3859
|
+
} catch (error) {
|
|
3860
|
+
this.log(
|
|
3861
|
+
"warn",
|
|
3862
|
+
"Failed to send Slack notification for prepared personalization:",
|
|
3863
|
+
error
|
|
3864
|
+
);
|
|
3865
|
+
}
|
|
3866
|
+
}, "notifyPreparedPersonalization"));
|
|
3867
|
+
__publicField(this, "setupDeanonymizationPrefetch", /* @__PURE__ */ __name((config, fields) => {
|
|
3868
|
+
if (!this.cueCardInstance) return;
|
|
3869
|
+
if (typeof window === "undefined") {
|
|
3870
|
+
this.cueCardInstance.update({ isVisible: true });
|
|
3871
|
+
return;
|
|
3872
|
+
}
|
|
3873
|
+
if (this.deanonymizationPrefetchCleanup) return;
|
|
3874
|
+
let resolved = false;
|
|
3875
|
+
let hasIdentity = false;
|
|
3876
|
+
let shouldDisableDeanonymization = false;
|
|
3877
|
+
const finish = /* @__PURE__ */ __name(() => {
|
|
3878
|
+
if (resolved) return;
|
|
3879
|
+
resolved = true;
|
|
3880
|
+
if (shouldDisableDeanonymization) {
|
|
3881
|
+
this.cueCardInstance?.update({
|
|
3882
|
+
deanonymization: void 0,
|
|
3883
|
+
isVisible: true
|
|
3884
|
+
});
|
|
3885
|
+
} else {
|
|
3886
|
+
this.cueCardInstance?.update({ isVisible: true });
|
|
3887
|
+
}
|
|
3888
|
+
this.deanonymizationPrefetchCleanup?.();
|
|
3889
|
+
this.deanonymizationPrefetchCleanup = null;
|
|
3890
|
+
}, "finish");
|
|
3891
|
+
const handleIdentity = /* @__PURE__ */ __name(async (event) => {
|
|
3892
|
+
if (resolved) return;
|
|
3893
|
+
const detail = event.detail;
|
|
3894
|
+
hasIdentity = true;
|
|
3895
|
+
if (detail?.type !== "business") {
|
|
3896
|
+
finish();
|
|
3897
|
+
return;
|
|
3898
|
+
}
|
|
3899
|
+
const input = this.buildDeanonymizedInput(detail, fields);
|
|
3900
|
+
if (!input) {
|
|
3901
|
+
finish();
|
|
3902
|
+
return;
|
|
3903
|
+
}
|
|
3904
|
+
const prepared = await this.preparePersonalization(input, {
|
|
3905
|
+
source: "deanonymized"
|
|
3906
|
+
});
|
|
3907
|
+
if (!prepared) {
|
|
3908
|
+
shouldDisableDeanonymization = true;
|
|
3909
|
+
}
|
|
3910
|
+
finish();
|
|
3911
|
+
}, "handleIdentity");
|
|
3912
|
+
const cachedIdentity = window.__kenobiIdentityResolution;
|
|
3913
|
+
if (cachedIdentity) {
|
|
3914
|
+
void handleIdentity({ detail: cachedIdentity });
|
|
3915
|
+
}
|
|
3916
|
+
window.addEventListener(IDENTITY_RESOLVED_EVENT2, handleIdentity);
|
|
3917
|
+
const timeoutMs = config?.timeoutMs ?? DEFAULT_DEANON_TIMEOUT_MS2;
|
|
3918
|
+
const timeoutId = window.setTimeout(() => {
|
|
3919
|
+
if (!hasIdentity) {
|
|
3920
|
+
finish();
|
|
3921
|
+
}
|
|
3922
|
+
}, timeoutMs + 50);
|
|
3923
|
+
this.deanonymizationPrefetchCleanup = () => {
|
|
3924
|
+
window.removeEventListener(IDENTITY_RESOLVED_EVENT2, handleIdentity);
|
|
3925
|
+
window.clearTimeout(timeoutId);
|
|
3926
|
+
};
|
|
3927
|
+
}, "setupDeanonymizationPrefetch"));
|
|
3282
3928
|
/**
|
|
3283
3929
|
* Syncs CueCard visibility based on the current path.
|
|
3284
3930
|
* Checks with the server if an active template exists for the new path.
|
|
@@ -3323,42 +3969,32 @@ var KenobiLib = (() => {
|
|
|
3323
3969
|
}
|
|
3324
3970
|
const startTime = /* @__PURE__ */ new Date();
|
|
3325
3971
|
this.log("debug", "Starting personalization with input:", input);
|
|
3972
|
+
const prepared = this.preparedPersonalization?.input && this.isSameInput(this.preparedPersonalization.input, input) ? this.preparedPersonalization : null;
|
|
3973
|
+
const isDeanonymizedInput = prepared?.source === "deanonymized";
|
|
3326
3974
|
this.dispatchKenobiEvent("personalization:start", {
|
|
3327
3975
|
input,
|
|
3328
|
-
pagePath: this.currentPath
|
|
3976
|
+
pagePath: this.currentPath,
|
|
3977
|
+
deanonymized: isDeanonymizedInput
|
|
3329
3978
|
});
|
|
3330
|
-
if (this.cueCardInstance) {
|
|
3331
|
-
this.cueCardInstance.update({ status: "starting", progressPct: 10 });
|
|
3332
|
-
}
|
|
3333
3979
|
try {
|
|
3334
|
-
const response = await fetch(`${this.config.apiHost}/v1/personalize`, {
|
|
3335
|
-
method: "POST",
|
|
3336
|
-
headers: {
|
|
3337
|
-
"Content-Type": "application/json"
|
|
3338
|
-
},
|
|
3339
|
-
body: JSON.stringify({
|
|
3340
|
-
publicKey: this.config.publicKey,
|
|
3341
|
-
input,
|
|
3342
|
-
pagePath: this.currentPath
|
|
3343
|
-
})
|
|
3344
|
-
});
|
|
3345
3980
|
if (this.cueCardInstance) {
|
|
3346
|
-
this.cueCardInstance.update({
|
|
3981
|
+
this.cueCardInstance.update({
|
|
3982
|
+
status: "starting",
|
|
3983
|
+
progressPct: prepared ? 80 : 10
|
|
3984
|
+
});
|
|
3347
3985
|
}
|
|
3348
|
-
if (
|
|
3349
|
-
|
|
3350
|
-
throw new Error(errorBody.error || `API error: ${response.status}`);
|
|
3351
|
-
}
|
|
3352
|
-
const result = await response.json();
|
|
3353
|
-
this.log("debug", "Personalization API response:", result);
|
|
3354
|
-
if (this.cueCardInstance) {
|
|
3355
|
-
this.cueCardInstance.update({ progressPct: 80 });
|
|
3986
|
+
if (prepared) {
|
|
3987
|
+
void this.notifyPreparedPersonalization(prepared);
|
|
3356
3988
|
}
|
|
3989
|
+
const result = prepared ? prepared.result : await this.requestPersonalization(input);
|
|
3357
3990
|
if (result.transformations && Array.isArray(result.transformations)) {
|
|
3358
3991
|
await this.applyTransformations(result.transformations, {
|
|
3359
3992
|
shouldConsolidate: true
|
|
3360
3993
|
});
|
|
3361
3994
|
}
|
|
3995
|
+
if (prepared) {
|
|
3996
|
+
this.preparedPersonalization = null;
|
|
3997
|
+
}
|
|
3362
3998
|
if (this.cueCardInstance) {
|
|
3363
3999
|
this.cueCardInstance.update({ status: "success", progressPct: 100 });
|
|
3364
4000
|
}
|
|
@@ -3373,7 +4009,9 @@ var KenobiLib = (() => {
|
|
|
3373
4009
|
pagePath: this.currentPath,
|
|
3374
4010
|
durationMs: duration,
|
|
3375
4011
|
transformationsCount: result.transformations?.length ?? 0,
|
|
3376
|
-
metadata: result.metadata
|
|
4012
|
+
metadata: result.metadata,
|
|
4013
|
+
source: prepared ? "prefetch" : "api",
|
|
4014
|
+
deanonymized: isDeanonymizedInput
|
|
3377
4015
|
});
|
|
3378
4016
|
} catch (error) {
|
|
3379
4017
|
this.log("error", "Personalization failed:", error);
|
|
@@ -3383,7 +4021,8 @@ var KenobiLib = (() => {
|
|
|
3383
4021
|
this.dispatchKenobiEvent("personalization:error", {
|
|
3384
4022
|
input,
|
|
3385
4023
|
pagePath: this.currentPath,
|
|
3386
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4024
|
+
error: error instanceof Error ? error.message : String(error),
|
|
4025
|
+
deanonymized: isDeanonymizedInput
|
|
3387
4026
|
});
|
|
3388
4027
|
}
|
|
3389
4028
|
}, "personalize"));
|