kenobi-js 0.1.42 → 0.1.44
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 +789 -100
- package/browser/dist.js.map +3 -3
- package/browser/dist.min.js +165 -16
- package/package.json +9 -9
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; }
|
|
@@ -1139,9 +1333,18 @@ var KenobiLib = (() => {
|
|
|
1139
1333
|
.backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0); backdrop-filter: blur(0); -webkit-backdrop-filter: blur(0); transition: all 0.5s ease; z-index: 0; pointer-events: none; }
|
|
1140
1334
|
.backdrop.active { background: rgba(0,0,0,0.1); backdrop-filter: blur(var(--kb-focus-blur)); -webkit-backdrop-filter: blur(var(--kb-focus-blur)); }
|
|
1141
1335
|
.launcher { position: absolute; pointer-events: auto; background-color: var(--kb-bg-container); border: 1px solid var(--kb-border-container); box-shadow: var(--kb-shadow-container); backdrop-filter: blur(var(--kb-backdrop-blur)); -webkit-backdrop-filter: blur(var(--kb-backdrop-blur)); border-radius: 9999px; padding: 0.5rem 1rem; display: flex; align-items: center; gap: 0.75rem; cursor: pointer; transition: transform 0.2s, opacity 0.3s; opacity: 0; z-index: 1; color: var(--kb-text-title); font-weight: 500; font-size: 0.875rem; font-family: var(--kb-font-family); }
|
|
1142
|
-
.launcher .kbd-hint .kbd { background: var(--kb-kbd-bg); border: 1px solid var(--kb-kbd-border); color: var(--kb-kbd-text); }
|
|
1143
|
-
.launcher .kbd-hint .kbd-text { color: var(--kb-kbd-text); }
|
|
1144
1336
|
.launcher:hover { transform: scale(1.02); background-color: var(--kb-bg-container); }
|
|
1337
|
+
.kb-chip-row { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; }
|
|
1338
|
+
.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); }
|
|
1339
|
+
.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; }
|
|
1340
|
+
.kb-chip-logo img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
1341
|
+
.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); }
|
|
1342
|
+
.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; }
|
|
1343
|
+
.kb-chip-action:hover { color: var(--kb-text-title); }
|
|
1344
|
+
.kb-chip--launcher { padding: 0.25rem 0.65rem; font-size: 0.7rem; }
|
|
1345
|
+
.kb-chip-row.launcher-row { margin-bottom: 0; }
|
|
1346
|
+
.launcher-label { display: inline-flex; align-items: center; gap: 0.5rem; }
|
|
1347
|
+
.subtitle-chip { margin-top: 0.35rem; }
|
|
1145
1348
|
.pos-top-center { left: 50%; translate: -50% 0; top: 1rem; }
|
|
1146
1349
|
.pos-top-right { right: 1rem; top: 1rem; left: auto; }
|
|
1147
1350
|
@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 +1359,7 @@ var KenobiLib = (() => {
|
|
|
1156
1359
|
.text-content { flex: 1; user-select: none; }
|
|
1157
1360
|
.text-row { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; }
|
|
1158
1361
|
.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; }
|
|
1362
|
+
.subtitle-text { color: var(--kb-text-title); font-size: 0.875rem; line-height: 1.25; opacity: 0.8; }
|
|
1160
1363
|
.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
1364
|
.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
1365
|
.btn-trigger.hidden { opacity: 0; pointer-events: none; }
|
|
@@ -1204,19 +1407,17 @@ var KenobiLib = (() => {
|
|
|
1204
1407
|
.popover-watermark { position: absolute; top: 100%; left: 0; right: 0; text-align: center; font-size: 0.625rem; color: var(--kb-watermark-text); opacity: 0.6; font-weight: 500; letter-spacing: 0.025em; padding-top: 0.5rem; }
|
|
1205
1408
|
.popover-watermark a { color: inherit; text-decoration: none; cursor: pointer; }
|
|
1206
1409
|
.popover-watermark a:hover { text-decoration: underline; opacity: 1; }
|
|
1207
|
-
/* Launcher hint
|
|
1208
|
-
.launcher
|
|
1209
|
-
.launcher
|
|
1210
|
-
.pos-top-right.launcher .kbd-hint { left: auto; right: auto; }
|
|
1410
|
+
/* Launcher helper hint (below launcher) */
|
|
1411
|
+
.launcher-hint { position: absolute; top: calc(100% + 0.4rem); left: 50%; transform: translateX(-50%); pointer-events: none; white-space: nowrap; }
|
|
1412
|
+
.launcher-hint.visible { opacity: 0.65; }
|
|
1211
1413
|
/* Launcher dismiss button */
|
|
1212
1414
|
.launcher .btn-dismiss.launcher-dismiss { top: -0.375rem; left: -0.375rem; width: 1.25rem; height: 1.25rem; opacity: 0; transition: opacity 0.2s ease-out, background-color 0.3s ease-out, color 0.3s ease-out; }
|
|
1213
1415
|
.launcher:hover .btn-dismiss.launcher-dismiss { opacity: 1; }
|
|
1214
1416
|
/* Launcher logo */
|
|
1215
1417
|
.launcher-logo { width: 20px; height: 20px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
|
|
1216
1418
|
.launcher-logo svg { width: 20px; height: 20px; }
|
|
1217
|
-
/* Mobile:
|
|
1419
|
+
/* Mobile: show dismiss button */
|
|
1218
1420
|
@media (max-width: 768px) {
|
|
1219
|
-
.launcher .kbd-hint { display: none; }
|
|
1220
1421
|
.launcher .btn-dismiss.launcher-dismiss { opacity: 1; }
|
|
1221
1422
|
}
|
|
1222
1423
|
/* Toggle personalization button */
|
|
@@ -1226,6 +1427,11 @@ var KenobiLib = (() => {
|
|
|
1226
1427
|
/* Custom tooltip for toggle button */
|
|
1227
1428
|
.btn-toggle-personalization .toggle-tooltip { position: absolute; top: calc(100% + 6px); left: 50%; transform: translateX(-50%); white-space: nowrap; background-color: var(--kb-bg-container); border: 1px solid var(--kb-border-container); color: var(--kb-text-title); font-size: 0.7rem; font-weight: 500; padding: 0.25rem 0.5rem; border-radius: 4px; opacity: 0; visibility: hidden; transition: opacity 0.15s ease-out, visibility 0.15s ease-out; pointer-events: none; z-index: 100; box-shadow: 0 2px 8px rgba(0,0,0,0.15); }
|
|
1228
1429
|
.btn-toggle-personalization:hover .toggle-tooltip { opacity: 1; visibility: visible; }
|
|
1430
|
+
.btn-toggle-personalization.loading { cursor: default; opacity: 0.7; }
|
|
1431
|
+
.btn-toggle-personalization.loading:hover { transform: none; }
|
|
1432
|
+
.btn-toggle-personalization:disabled { cursor: default; }
|
|
1433
|
+
.launcher-domain { text-decoration: underline; text-underline-offset: 2px; }
|
|
1434
|
+
.launcher-actions { display: flex; align-items: center; gap: 0.25rem; }
|
|
1229
1435
|
`;
|
|
1230
1436
|
var useEnterExitAnimation = /* @__PURE__ */ __name((ref, isVisible, config) => {
|
|
1231
1437
|
const hasEnteredRef = A2(false);
|
|
@@ -1321,7 +1527,14 @@ var KenobiLib = (() => {
|
|
|
1321
1527
|
}
|
|
1322
1528
|
return styles;
|
|
1323
1529
|
}, "getThemeStyles");
|
|
1324
|
-
var CueCardContent = /* @__PURE__ */ __name(({
|
|
1530
|
+
var CueCardContent = /* @__PURE__ */ __name(({
|
|
1531
|
+
config,
|
|
1532
|
+
isOpen,
|
|
1533
|
+
skipFocus,
|
|
1534
|
+
setIsOpen,
|
|
1535
|
+
deanonymizedCompany,
|
|
1536
|
+
onClearDeanonymizedCompany
|
|
1537
|
+
}) => {
|
|
1325
1538
|
const isInline = config.mountMode === "inline";
|
|
1326
1539
|
const containerRef = A2(null);
|
|
1327
1540
|
const launcherRef = A2(null);
|
|
@@ -1348,6 +1561,14 @@ var KenobiLib = (() => {
|
|
|
1348
1561
|
const timerProgressRef = A2(0);
|
|
1349
1562
|
const timerEnabled = config.enableTimer !== false;
|
|
1350
1563
|
const timerDuration = Math.max(500, config.timerDurationMs ?? 2e4);
|
|
1564
|
+
const isPending = config.status === "starting";
|
|
1565
|
+
const isSuccess = config.status === "success";
|
|
1566
|
+
const isError = config.status === "error";
|
|
1567
|
+
const isDeanonymized = !!deanonymizedCompany;
|
|
1568
|
+
const isPopoverEnabled = !isDeanonymized;
|
|
1569
|
+
const isPopoverOpen = isPopoverEnabled ? isOpen : false;
|
|
1570
|
+
const deanonymizedLabel = deanonymizedCompany?.name || deanonymizedCompany?.domain || "";
|
|
1571
|
+
const deanonymizedDomain = deanonymizedCompany?.domain;
|
|
1351
1572
|
const setTimerProgress = q2((value) => {
|
|
1352
1573
|
timerProgressRef.current = value;
|
|
1353
1574
|
setTimerProgressState(value);
|
|
@@ -1415,7 +1636,7 @@ var KenobiLib = (() => {
|
|
|
1415
1636
|
skipFocusRef.current = true;
|
|
1416
1637
|
}
|
|
1417
1638
|
y2(() => {
|
|
1418
|
-
if (
|
|
1639
|
+
if (isPopoverOpen) {
|
|
1419
1640
|
if (hasHadSuccess && formRef.current) {
|
|
1420
1641
|
formRef.current.reset();
|
|
1421
1642
|
}
|
|
@@ -1430,15 +1651,15 @@ var KenobiLib = (() => {
|
|
|
1430
1651
|
return () => clearTimeout(focusTimer);
|
|
1431
1652
|
}
|
|
1432
1653
|
}
|
|
1433
|
-
}, [
|
|
1434
|
-
const prevIsOpenForExpandRef = A2(
|
|
1654
|
+
}, [isPopoverOpen]);
|
|
1655
|
+
const prevIsOpenForExpandRef = A2(isPopoverOpen);
|
|
1435
1656
|
y2(() => {
|
|
1436
1657
|
const wasOpen = prevIsOpenForExpandRef.current;
|
|
1437
|
-
prevIsOpenForExpandRef.current =
|
|
1438
|
-
if (!wasOpen &&
|
|
1658
|
+
prevIsOpenForExpandRef.current = isPopoverOpen;
|
|
1659
|
+
if (!wasOpen && isPopoverOpen && mode === "launcher") {
|
|
1439
1660
|
setMode("card");
|
|
1440
1661
|
}
|
|
1441
|
-
}, [
|
|
1662
|
+
}, [isPopoverOpen, mode]);
|
|
1442
1663
|
const isFirstAppearance = !hasEnteredRef.current;
|
|
1443
1664
|
const wasLauncherPreviously = previousModeRef.current === "launcher";
|
|
1444
1665
|
const cardEntranceDelay = isFirstAppearance ? config.entranceDelayMs || 0 : wasLauncherPreviously && mode === "card" ? 400 : 0;
|
|
@@ -1528,7 +1749,7 @@ var KenobiLib = (() => {
|
|
|
1528
1749
|
e3.preventDefault();
|
|
1529
1750
|
if (mode === "launcher") {
|
|
1530
1751
|
setMode("card");
|
|
1531
|
-
setIsOpen(
|
|
1752
|
+
setIsOpen(isPopoverEnabled);
|
|
1532
1753
|
} else if (mode === "card") {
|
|
1533
1754
|
if (config.enableLauncher) {
|
|
1534
1755
|
setMode("launcher");
|
|
@@ -1542,29 +1763,61 @@ var KenobiLib = (() => {
|
|
|
1542
1763
|
return () => window.removeEventListener("keydown", handleKey);
|
|
1543
1764
|
}, [
|
|
1544
1765
|
config.isVisible,
|
|
1545
|
-
|
|
1766
|
+
isPopoverOpen,
|
|
1546
1767
|
mode,
|
|
1547
1768
|
config.enableLauncher,
|
|
1548
1769
|
setIsOpen,
|
|
1549
|
-
config.onDismiss
|
|
1770
|
+
config.onDismiss,
|
|
1771
|
+
isPopoverEnabled
|
|
1550
1772
|
]);
|
|
1773
|
+
const [isMobile, setIsMobile] = d2(false);
|
|
1551
1774
|
const isMac = typeof navigator !== "undefined" && /Mac/.test(navigator.userAgent);
|
|
1552
|
-
|
|
1775
|
+
y2(() => {
|
|
1776
|
+
if (typeof window === "undefined") return;
|
|
1777
|
+
const media = window.matchMedia("(max-width: 768px)");
|
|
1778
|
+
const update = /* @__PURE__ */ __name(() => setIsMobile(media.matches), "update");
|
|
1779
|
+
update();
|
|
1780
|
+
if ("addEventListener" in media) {
|
|
1781
|
+
media.addEventListener("change", update);
|
|
1782
|
+
return () => media.removeEventListener("change", update);
|
|
1783
|
+
}
|
|
1784
|
+
window.addEventListener("resize", update);
|
|
1785
|
+
return () => window.removeEventListener("resize", update);
|
|
1786
|
+
}, []);
|
|
1787
|
+
const launcherHint = (() => {
|
|
1788
|
+
if (isMobile) {
|
|
1789
|
+
return { keys: [], label: "tap to launch" };
|
|
1790
|
+
}
|
|
1553
1791
|
if (config.keyboardShortcut) {
|
|
1554
1792
|
const mods = config.keyboardShortcut.modifiers || [];
|
|
1555
1793
|
const keys = [];
|
|
1556
|
-
if (mods.includes("meta")) keys.push(isMac ? "\u2318" : "
|
|
1794
|
+
if (mods.includes("meta")) keys.push(isMac ? "\u2318" : "Ctrl");
|
|
1557
1795
|
if (mods.includes("ctrl")) keys.push("Ctrl");
|
|
1558
1796
|
if (mods.includes("alt")) keys.push(isMac ? "Opt" : "Alt");
|
|
1559
1797
|
if (mods.includes("shift")) keys.push("Shift");
|
|
1560
1798
|
keys.push(config.keyboardShortcut.key.toUpperCase());
|
|
1561
|
-
return keys;
|
|
1799
|
+
return { keys, label: "to launch" };
|
|
1562
1800
|
}
|
|
1563
|
-
return [isMac ? "\u2318" : "Ctrl", "P"];
|
|
1801
|
+
return { keys: [isMac ? "\u2318" : "Ctrl", "P"], label: "to launch" };
|
|
1564
1802
|
})();
|
|
1565
|
-
const
|
|
1566
|
-
const
|
|
1567
|
-
|
|
1803
|
+
const [logoFailed, setLogoFailed] = d2(false);
|
|
1804
|
+
const [logoAttempt, setLogoAttempt] = d2(
|
|
1805
|
+
"primary"
|
|
1806
|
+
);
|
|
1807
|
+
y2(() => {
|
|
1808
|
+
setLogoFailed(false);
|
|
1809
|
+
setLogoAttempt("primary");
|
|
1810
|
+
}, [deanonymizedCompany?.logoUrl, deanonymizedLabel, deanonymizedDomain]);
|
|
1811
|
+
y2(() => {
|
|
1812
|
+
if (!isPopoverEnabled && isOpen) {
|
|
1813
|
+
setIsOpen(false);
|
|
1814
|
+
}
|
|
1815
|
+
}, [isPopoverEnabled, isOpen, setIsOpen]);
|
|
1816
|
+
const logoUrlTemplate = config.deanonymization?.logoUrlTemplate;
|
|
1817
|
+
const normalizedLogoDomain = normalizeDomain(deanonymizedDomain);
|
|
1818
|
+
const fallbackLogoUrl = normalizedLogoDomain ? `https://logo.clearbit.com/${normalizedLogoDomain}` : void 0;
|
|
1819
|
+
const primaryLogoUrl = normalizedLogoDomain && logoUrlTemplate ? logoUrlTemplate.replace("{domain}", normalizedLogoDomain) : deanonymizedCompany?.logoUrl || fallbackLogoUrl;
|
|
1820
|
+
const resolvedLogoUrl = logoAttempt === "fallback" && fallbackLogoUrl && fallbackLogoUrl !== primaryLogoUrl ? fallbackLogoUrl : primaryLogoUrl;
|
|
1568
1821
|
const showAsSuccess = isSuccess && isShowingInitialSuccessRef.current;
|
|
1569
1822
|
const txt = config.textOverrides || {};
|
|
1570
1823
|
const titleText = (() => {
|
|
@@ -1591,6 +1844,94 @@ var KenobiLib = (() => {
|
|
|
1591
1844
|
}
|
|
1592
1845
|
return txt.btnResting || "Show me";
|
|
1593
1846
|
})();
|
|
1847
|
+
const launcherLabelText = (() => {
|
|
1848
|
+
if (isDeanonymized) {
|
|
1849
|
+
if (hasHadSuccess) {
|
|
1850
|
+
return txt.launcherLabelDeanonymizedSuccess || txt.launcherLabelDeanonymized || "See it again for";
|
|
1851
|
+
}
|
|
1852
|
+
return txt.launcherLabelDeanonymized || "See it in action for";
|
|
1853
|
+
}
|
|
1854
|
+
if (hasHadSuccess) {
|
|
1855
|
+
return txt.launcherLabelSuccess || txt.launcherLabel || "Personalize again";
|
|
1856
|
+
}
|
|
1857
|
+
return txt.launcherLabel || "Personalize";
|
|
1858
|
+
})();
|
|
1859
|
+
const renderDeanonymizedChip = /* @__PURE__ */ __name((variant) => {
|
|
1860
|
+
if (!deanonymizedCompany || !deanonymizedLabel) return null;
|
|
1861
|
+
const isLauncher = variant === "launcher";
|
|
1862
|
+
const fallbackLetter = deanonymizedLabel.trim().slice(0, 1).toUpperCase();
|
|
1863
|
+
const showLogo = !!resolvedLogoUrl && !logoFailed;
|
|
1864
|
+
return /* @__PURE__ */ u3("div", { class: `kb-chip ${isLauncher ? "kb-chip--launcher" : ""}`, children: [
|
|
1865
|
+
showLogo ? /* @__PURE__ */ u3("span", { class: "kb-chip-logo", children: /* @__PURE__ */ u3(
|
|
1866
|
+
"img",
|
|
1867
|
+
{
|
|
1868
|
+
src: resolvedLogoUrl,
|
|
1869
|
+
alt: "",
|
|
1870
|
+
referrerPolicy: "no-referrer",
|
|
1871
|
+
onError: () => {
|
|
1872
|
+
if (logoAttempt === "primary" && fallbackLogoUrl && fallbackLogoUrl !== primaryLogoUrl) {
|
|
1873
|
+
setLogoAttempt("fallback");
|
|
1874
|
+
return;
|
|
1875
|
+
}
|
|
1876
|
+
setLogoFailed(true);
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
) }) : /* @__PURE__ */ u3("span", { class: "kb-chip-fallback", children: fallbackLetter }),
|
|
1880
|
+
/* @__PURE__ */ u3("span", { children: deanonymizedLabel }),
|
|
1881
|
+
onClearDeanonymizedCompany && /* @__PURE__ */ u3(
|
|
1882
|
+
"button",
|
|
1883
|
+
{
|
|
1884
|
+
class: "kb-chip-action",
|
|
1885
|
+
type: "button",
|
|
1886
|
+
onClick: (e3) => {
|
|
1887
|
+
e3.stopPropagation();
|
|
1888
|
+
onClearDeanonymizedCompany();
|
|
1889
|
+
setIsOpen(true);
|
|
1890
|
+
},
|
|
1891
|
+
children: "Not you?"
|
|
1892
|
+
}
|
|
1893
|
+
)
|
|
1894
|
+
] });
|
|
1895
|
+
}, "renderDeanonymizedChip");
|
|
1896
|
+
const buildDeanonymizedValues = /* @__PURE__ */ __name(() => {
|
|
1897
|
+
const normalizedInputDomain = normalizeDomain(deanonymizedDomain);
|
|
1898
|
+
const fallbackValue = (normalizedInputDomain || deanonymizedDomain || deanonymizedLabel || "").toString();
|
|
1899
|
+
const values = {};
|
|
1900
|
+
config.fields.forEach((field) => {
|
|
1901
|
+
const key = field.name;
|
|
1902
|
+
const lowerKey = key.toLowerCase();
|
|
1903
|
+
if (lowerKey.includes("domain")) {
|
|
1904
|
+
values[key] = normalizedInputDomain || fallbackValue;
|
|
1905
|
+
return;
|
|
1906
|
+
}
|
|
1907
|
+
if (lowerKey.includes("company")) {
|
|
1908
|
+
values[key] = deanonymizedLabel;
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1911
|
+
values[key] = fallbackValue;
|
|
1912
|
+
});
|
|
1913
|
+
return values;
|
|
1914
|
+
}, "buildDeanonymizedValues");
|
|
1915
|
+
const submitValues = /* @__PURE__ */ __name((values) => {
|
|
1916
|
+
const newErrors = {};
|
|
1917
|
+
let hasErrors = false;
|
|
1918
|
+
config.fields.forEach((field) => {
|
|
1919
|
+
const rawValue = values[field.name] ?? "";
|
|
1920
|
+
const value = typeof rawValue === "string" ? rawValue : String(rawValue);
|
|
1921
|
+
const error = validateField(field.name, value, field);
|
|
1922
|
+
if (error) {
|
|
1923
|
+
newErrors[field.name] = error;
|
|
1924
|
+
hasErrors = true;
|
|
1925
|
+
}
|
|
1926
|
+
});
|
|
1927
|
+
if (hasErrors) {
|
|
1928
|
+
setErrors(newErrors);
|
|
1929
|
+
return;
|
|
1930
|
+
}
|
|
1931
|
+
setErrors({});
|
|
1932
|
+
setIsOpen(false);
|
|
1933
|
+
config.onSubmitPersonalization?.(values);
|
|
1934
|
+
}, "submitValues");
|
|
1594
1935
|
const validateField = /* @__PURE__ */ __name((name, value, fieldConfig) => {
|
|
1595
1936
|
if (!fieldConfig) return null;
|
|
1596
1937
|
if (fieldConfig.required && !value.trim()) {
|
|
@@ -1629,25 +1970,11 @@ var KenobiLib = (() => {
|
|
|
1629
1970
|
if (isPending) return;
|
|
1630
1971
|
const formData = new FormData(e3.target);
|
|
1631
1972
|
const values = {};
|
|
1632
|
-
const newErrors = {};
|
|
1633
|
-
let hasErrors = false;
|
|
1634
1973
|
formData.forEach((value, key) => {
|
|
1635
1974
|
const strValue = value.toString();
|
|
1636
1975
|
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
1976
|
});
|
|
1644
|
-
|
|
1645
|
-
setErrors(newErrors);
|
|
1646
|
-
return;
|
|
1647
|
-
}
|
|
1648
|
-
setErrors({});
|
|
1649
|
-
setIsOpen(false);
|
|
1650
|
-
config.onSubmitPersonalization?.(values);
|
|
1977
|
+
submitValues(values);
|
|
1651
1978
|
}, "handleSubmit");
|
|
1652
1979
|
const handleInput = /* @__PURE__ */ __name((e3) => {
|
|
1653
1980
|
const target = e3.target;
|
|
@@ -1666,10 +1993,15 @@ var KenobiLib = (() => {
|
|
|
1666
1993
|
});
|
|
1667
1994
|
}
|
|
1668
1995
|
}, "handleInput");
|
|
1996
|
+
const handleDeanonymizedSubmit = /* @__PURE__ */ __name(() => {
|
|
1997
|
+
if (isPending || !isDeanonymized) return;
|
|
1998
|
+
submitValues(buildDeanonymizedValues());
|
|
1999
|
+
}, "handleDeanonymizedSubmit");
|
|
1669
2000
|
const togglePopover = /* @__PURE__ */ __name((e3) => {
|
|
1670
2001
|
e3.stopPropagation();
|
|
2002
|
+
if (isDeanonymized) return;
|
|
1671
2003
|
if (isPending || isSuccess) return;
|
|
1672
|
-
const opening = !
|
|
2004
|
+
const opening = !isPopoverOpen;
|
|
1673
2005
|
setIsOpen(opening);
|
|
1674
2006
|
if (opening && config.enableClickSheen) {
|
|
1675
2007
|
setSheenActive(true);
|
|
@@ -1679,7 +2011,7 @@ var KenobiLib = (() => {
|
|
|
1679
2011
|
y2(() => {
|
|
1680
2012
|
if (!timerEnabled) return;
|
|
1681
2013
|
if (hasTimerCompletedRef.current) return;
|
|
1682
|
-
const shouldRun = config.isVisible && mode === "card" && config.status === "resting" && !
|
|
2014
|
+
const shouldRun = config.isVisible && mode === "card" && config.status === "resting" && !isPopoverOpen && !isHovering;
|
|
1683
2015
|
if (!shouldRun) {
|
|
1684
2016
|
if (timerRafRef.current !== null) {
|
|
1685
2017
|
cancelAnimationFrame(timerRafRef.current);
|
|
@@ -1723,7 +2055,7 @@ var KenobiLib = (() => {
|
|
|
1723
2055
|
config.onDismiss,
|
|
1724
2056
|
config.status,
|
|
1725
2057
|
isHovering,
|
|
1726
|
-
|
|
2058
|
+
isPopoverOpen,
|
|
1727
2059
|
mode,
|
|
1728
2060
|
setIsOpen,
|
|
1729
2061
|
timerDuration,
|
|
@@ -1742,6 +2074,7 @@ var KenobiLib = (() => {
|
|
|
1742
2074
|
const isContainerVisible = !!config.isVisible && mode === "card" && !isDismissed;
|
|
1743
2075
|
const isLauncherVisible = !!config.isVisible && mode === "launcher" && !isDismissed;
|
|
1744
2076
|
const isAnythingVisible = isContainerVisible || isLauncherVisible;
|
|
2077
|
+
const showLauncherHint = !!config.showKeyboardHints && isLauncherVisible;
|
|
1745
2078
|
return /* @__PURE__ */ u3(k, { children: [
|
|
1746
2079
|
/* @__PURE__ */ u3(
|
|
1747
2080
|
"div",
|
|
@@ -1755,12 +2088,12 @@ var KenobiLib = (() => {
|
|
|
1755
2088
|
"div",
|
|
1756
2089
|
{
|
|
1757
2090
|
ref: containerRef,
|
|
1758
|
-
class: `container theme-${config.theme || "glass"} pos-${config.position || "top-center"}${
|
|
2091
|
+
class: `container theme-${config.theme || "glass"} pos-${config.position || "top-center"}${isPopoverOpen ? " popover-open" : ""}`,
|
|
1759
2092
|
style: {
|
|
1760
2093
|
...getThemeStyles(config.customTheme),
|
|
1761
2094
|
pointerEvents: isContainerVisible ? "auto" : "none"
|
|
1762
2095
|
},
|
|
1763
|
-
onClick: () => !
|
|
2096
|
+
onClick: () => !isPopoverOpen && !isPending && !isSuccess && isPopoverEnabled && setIsOpen(true),
|
|
1764
2097
|
onMouseEnter: () => setIsHovering(true),
|
|
1765
2098
|
onMouseLeave: () => setIsHovering(false),
|
|
1766
2099
|
children: [
|
|
@@ -1785,7 +2118,7 @@ var KenobiLib = (() => {
|
|
|
1785
2118
|
/* @__PURE__ */ u3("div", { class: "content-wrapper", children: /* @__PURE__ */ u3("div", { class: "text-content", children: /* @__PURE__ */ u3("div", { class: "text-row", children: [
|
|
1786
2119
|
/* @__PURE__ */ u3("div", { children: [
|
|
1787
2120
|
/* @__PURE__ */ u3("div", { class: "title", children: titleText }),
|
|
1788
|
-
/* @__PURE__ */ u3("div", { class: "subtitle", children: subtitleText })
|
|
2121
|
+
isDeanonymized ? /* @__PURE__ */ u3("div", { class: "subtitle-chip", children: renderDeanonymizedChip("card") }) : /* @__PURE__ */ u3("div", { class: "subtitle-text", children: subtitleText })
|
|
1789
2122
|
] }),
|
|
1790
2123
|
isPending ? /* @__PURE__ */ u3("span", { class: "status-text", children: [
|
|
1791
2124
|
/* @__PURE__ */ u3(LoaderIcon, {}),
|
|
@@ -1794,9 +2127,9 @@ var KenobiLib = (() => {
|
|
|
1794
2127
|
] }) : /* @__PURE__ */ u3(
|
|
1795
2128
|
"button",
|
|
1796
2129
|
{
|
|
1797
|
-
class: `btn btn-trigger ${showAsSuccess ? "success" : ""}${
|
|
2130
|
+
class: `btn btn-trigger ${showAsSuccess ? "success" : ""}${isPopoverOpen || isExitingToLauncher ? " hidden" : ""}`,
|
|
1798
2131
|
disabled: showAsSuccess,
|
|
1799
|
-
onClick: togglePopover,
|
|
2132
|
+
onClick: isDeanonymized ? handleDeanonymizedSubmit : togglePopover,
|
|
1800
2133
|
children: showAsSuccess ? /* @__PURE__ */ u3(k, { children: [
|
|
1801
2134
|
/* @__PURE__ */ u3(CheckIcon, {}),
|
|
1802
2135
|
" ",
|
|
@@ -1814,10 +2147,10 @@ var KenobiLib = (() => {
|
|
|
1814
2147
|
}
|
|
1815
2148
|
}
|
|
1816
2149
|
) }) }),
|
|
1817
|
-
/* @__PURE__ */ u3(
|
|
2150
|
+
!isDeanonymized && /* @__PURE__ */ u3(
|
|
1818
2151
|
"div",
|
|
1819
2152
|
{
|
|
1820
|
-
class: `popover ${
|
|
2153
|
+
class: `popover ${isPopoverOpen ? "open" : ""}`,
|
|
1821
2154
|
onClick: (e3) => e3.stopPropagation(),
|
|
1822
2155
|
children: [
|
|
1823
2156
|
/* @__PURE__ */ u3("form", { onSubmit: handleSubmit, ref: formRef, children: [
|
|
@@ -1884,7 +2217,7 @@ var KenobiLib = (() => {
|
|
|
1884
2217
|
config.showKeyboardHints && config.enableFocusMode && /* @__PURE__ */ u3(
|
|
1885
2218
|
"div",
|
|
1886
2219
|
{
|
|
1887
|
-
class: `kbd-hint ${!
|
|
2220
|
+
class: `kbd-hint ${!isPopoverOpen && !isPending && !isSuccess ? "visible" : ""}`,
|
|
1888
2221
|
children: [
|
|
1889
2222
|
/* @__PURE__ */ u3("div", { class: "kbd-group", children: /* @__PURE__ */ u3("div", { class: "kbd", children: "Esc" }) }),
|
|
1890
2223
|
/* @__PURE__ */ u3("span", { class: "kbd-text", children: "to dismiss" })
|
|
@@ -1908,7 +2241,7 @@ var KenobiLib = (() => {
|
|
|
1908
2241
|
e3.stopPropagation();
|
|
1909
2242
|
setIsDismissed(false);
|
|
1910
2243
|
setMode("card");
|
|
1911
|
-
setIsOpen(
|
|
2244
|
+
setIsOpen(isPopoverEnabled);
|
|
1912
2245
|
},
|
|
1913
2246
|
role: "button",
|
|
1914
2247
|
tabIndex: 0,
|
|
@@ -1938,23 +2271,56 @@ var KenobiLib = (() => {
|
|
|
1938
2271
|
}
|
|
1939
2272
|
),
|
|
1940
2273
|
config.showLauncherLogo !== false && /* @__PURE__ */ u3("div", { class: "launcher-logo", children: /* @__PURE__ */ u3(LogoIcon, {}) }),
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
2274
|
+
/* @__PURE__ */ u3("div", { class: "launcher-label", children: [
|
|
2275
|
+
/* @__PURE__ */ u3("span", { children: (() => {
|
|
2276
|
+
const forMatch = launcherLabelText.match(/^(For\s+)(.+)$/i);
|
|
2277
|
+
if (forMatch) {
|
|
2278
|
+
return /* @__PURE__ */ u3(k, { children: [
|
|
2279
|
+
forMatch[1],
|
|
2280
|
+
/* @__PURE__ */ u3("span", { class: "launcher-domain", children: forMatch[2] })
|
|
2281
|
+
] });
|
|
2282
|
+
}
|
|
2283
|
+
return launcherLabelText;
|
|
2284
|
+
})() }),
|
|
2285
|
+
isDeanonymized && renderDeanonymizedChip("launcher")
|
|
2286
|
+
] }),
|
|
2287
|
+
/* @__PURE__ */ u3("div", { class: "launcher-actions", children: [
|
|
2288
|
+
config.enableUndoToggle && hasHadSuccess && /* @__PURE__ */ u3(
|
|
2289
|
+
"button",
|
|
2290
|
+
{
|
|
2291
|
+
class: "btn-toggle-personalization",
|
|
2292
|
+
"aria-label": config.isPersonalized ? "Show original" : "Show personalized",
|
|
2293
|
+
onClick: (e3) => {
|
|
2294
|
+
e3.stopPropagation();
|
|
2295
|
+
config.onTogglePersonalization?.();
|
|
2296
|
+
},
|
|
2297
|
+
children: [
|
|
2298
|
+
/* @__PURE__ */ u3(ArrowPathIcon, {}),
|
|
2299
|
+
/* @__PURE__ */ u3("span", { class: "toggle-tooltip", children: config.isPersonalized ? "Show original" : "Show personalized" })
|
|
2300
|
+
]
|
|
2301
|
+
}
|
|
2302
|
+
),
|
|
2303
|
+
config.launcherAction && config.launcherAction.status !== "idle" && hasHadSuccess && /* @__PURE__ */ u3(
|
|
2304
|
+
"button",
|
|
2305
|
+
{
|
|
2306
|
+
class: `btn-toggle-personalization${config.launcherAction.status === "loading" ? " loading" : ""}`,
|
|
2307
|
+
"aria-label": config.launcherAction.tooltip || "Action",
|
|
2308
|
+
onClick: (e3) => {
|
|
2309
|
+
e3.stopPropagation();
|
|
2310
|
+
config.launcherAction?.onClick?.();
|
|
2311
|
+
},
|
|
2312
|
+
disabled: config.launcherAction.status === "loading",
|
|
2313
|
+
children: [
|
|
2314
|
+
config.launcherAction.status === "loading" ? /* @__PURE__ */ u3(LoaderIcon, {}) : /* @__PURE__ */ u3(ArrowRightIcon, {}),
|
|
2315
|
+
config.launcherAction.tooltip && /* @__PURE__ */ u3("span", { class: "toggle-tooltip", children: config.launcherAction.tooltip })
|
|
2316
|
+
]
|
|
2317
|
+
}
|
|
2318
|
+
)
|
|
2319
|
+
] }),
|
|
2320
|
+
showLauncherHint && /* @__PURE__ */ u3("div", { class: "kbd-hint visible launcher-hint", "aria-hidden": "true", children: [
|
|
2321
|
+
launcherHint.keys.length > 0 && /* @__PURE__ */ u3("div", { class: "kbd-group", children: launcherHint.keys.map((key, index) => /* @__PURE__ */ u3("div", { class: "kbd", children: key }, index)) }),
|
|
2322
|
+
/* @__PURE__ */ u3("span", { class: "kbd-text", children: launcherHint.label })
|
|
2323
|
+
] })
|
|
1958
2324
|
]
|
|
1959
2325
|
}
|
|
1960
2326
|
)
|
|
@@ -1968,6 +2334,33 @@ var KenobiLib = (() => {
|
|
|
1968
2334
|
__publicField(this, "isOpen", false);
|
|
1969
2335
|
__publicField(this, "skipFocus", false);
|
|
1970
2336
|
__publicField(this, "mountTarget", null);
|
|
2337
|
+
__publicField(this, "deanonymizedCompany", null);
|
|
2338
|
+
__publicField(this, "deanonymizationStatus", "idle");
|
|
2339
|
+
__publicField(this, "deanonymizationCleanup", null);
|
|
2340
|
+
__publicField(this, "hasStartedDeanonymization", false);
|
|
2341
|
+
__publicField(this, "clearDeanonymizedCompany", /* @__PURE__ */ __name(() => {
|
|
2342
|
+
const previousCompany = this.deanonymizedCompany;
|
|
2343
|
+
const shouldResetStatus = this.config.status === "success" || this.config.isPersonalized;
|
|
2344
|
+
if (this.config.isPersonalized) {
|
|
2345
|
+
this.config.onTogglePersonalization?.();
|
|
2346
|
+
}
|
|
2347
|
+
this.deanonymizedCompany = null;
|
|
2348
|
+
this.deanonymizationStatus = "failed";
|
|
2349
|
+
if (previousCompany) {
|
|
2350
|
+
dispatchCueCardEvent("deanonymization:not-you", {
|
|
2351
|
+
company: previousCompany
|
|
2352
|
+
});
|
|
2353
|
+
}
|
|
2354
|
+
if (shouldResetStatus) {
|
|
2355
|
+
this.config = {
|
|
2356
|
+
...this.config,
|
|
2357
|
+
status: "resting",
|
|
2358
|
+
progressPct: 0,
|
|
2359
|
+
isPersonalized: false
|
|
2360
|
+
};
|
|
2361
|
+
}
|
|
2362
|
+
this.render();
|
|
2363
|
+
}, "clearDeanonymizedCompany"));
|
|
1971
2364
|
this.config = {
|
|
1972
2365
|
position: "top-center",
|
|
1973
2366
|
direction: "top-to-bottom",
|
|
@@ -1990,6 +2383,9 @@ var KenobiLib = (() => {
|
|
|
1990
2383
|
...config
|
|
1991
2384
|
};
|
|
1992
2385
|
this.mountTarget = config.mountNode ?? null;
|
|
2386
|
+
if (this.isDeanonymizationEnabled()) {
|
|
2387
|
+
this.deanonymizationStatus = "pending";
|
|
2388
|
+
}
|
|
1993
2389
|
this.host = document.createElement("div");
|
|
1994
2390
|
this.host.id = "kenobi-cue-card-root";
|
|
1995
2391
|
this.applyHostStyles();
|
|
@@ -2038,20 +2434,95 @@ var KenobiLib = (() => {
|
|
|
2038
2434
|
resolvedTarget.appendChild(this.host);
|
|
2039
2435
|
}
|
|
2040
2436
|
this.applyHostStyles();
|
|
2437
|
+
this.startDeanonymization();
|
|
2041
2438
|
this.render();
|
|
2042
2439
|
}
|
|
2043
2440
|
unmount() {
|
|
2044
2441
|
G(null, this.shadow.lastElementChild);
|
|
2045
2442
|
this.host.remove();
|
|
2443
|
+
this.deanonymizationCleanup?.();
|
|
2444
|
+
this.deanonymizationCleanup = null;
|
|
2046
2445
|
}
|
|
2047
2446
|
update(newState) {
|
|
2048
2447
|
if (newState.status === "starting" && this.config.status !== "starting") {
|
|
2049
2448
|
this.isOpen = false;
|
|
2050
2449
|
}
|
|
2450
|
+
const wasDeanonymizationEnabled = this.isDeanonymizationEnabled();
|
|
2051
2451
|
this.config = { ...this.config, ...newState };
|
|
2452
|
+
const isDeanonymizationEnabled = this.isDeanonymizationEnabled();
|
|
2453
|
+
if (isDeanonymizationEnabled && !wasDeanonymizationEnabled) {
|
|
2454
|
+
this.deanonymizationStatus = "pending";
|
|
2455
|
+
this.startDeanonymization();
|
|
2456
|
+
}
|
|
2457
|
+
if (!isDeanonymizationEnabled && wasDeanonymizationEnabled) {
|
|
2458
|
+
this.deanonymizedCompany = null;
|
|
2459
|
+
this.deanonymizationStatus = "idle";
|
|
2460
|
+
this.deanonymizationCleanup?.();
|
|
2461
|
+
this.deanonymizationCleanup = null;
|
|
2462
|
+
this.hasStartedDeanonymization = false;
|
|
2463
|
+
}
|
|
2052
2464
|
this.applyHostStyles();
|
|
2053
2465
|
this.render();
|
|
2054
2466
|
}
|
|
2467
|
+
isDeanonymizationEnabled() {
|
|
2468
|
+
return this.config.deanonymization?.provider === "Kenobi";
|
|
2469
|
+
}
|
|
2470
|
+
startDeanonymization() {
|
|
2471
|
+
if (!this.isDeanonymizationEnabled()) return;
|
|
2472
|
+
if (this.hasStartedDeanonymization) return;
|
|
2473
|
+
if (this.deanonymizationStatus !== "pending") return;
|
|
2474
|
+
this.hasStartedDeanonymization = true;
|
|
2475
|
+
if (typeof window === "undefined") {
|
|
2476
|
+
this.deanonymizationStatus = "failed";
|
|
2477
|
+
this.render();
|
|
2478
|
+
return;
|
|
2479
|
+
}
|
|
2480
|
+
const cachedIdentity = window.__kenobiIdentityResolution;
|
|
2481
|
+
if (cachedIdentity) {
|
|
2482
|
+
this.handleDeanonymizationResult(cachedIdentity);
|
|
2483
|
+
return;
|
|
2484
|
+
}
|
|
2485
|
+
const handleEvent = /* @__PURE__ */ __name((event) => {
|
|
2486
|
+
const detail = event.detail;
|
|
2487
|
+
this.handleDeanonymizationResult(detail);
|
|
2488
|
+
}, "handleEvent");
|
|
2489
|
+
window.addEventListener(IDENTITY_RESOLVED_EVENT, handleEvent);
|
|
2490
|
+
ensureKenobiSnitcherLoaded(this.config.deanonymization);
|
|
2491
|
+
const timeoutMs = this.config.deanonymization?.timeoutMs ?? DEFAULT_DEANON_TIMEOUT_MS;
|
|
2492
|
+
const timeoutId = window.setTimeout(() => {
|
|
2493
|
+
window.removeEventListener(IDENTITY_RESOLVED_EVENT, handleEvent);
|
|
2494
|
+
this.handleDeanonymizationResult(null);
|
|
2495
|
+
}, timeoutMs);
|
|
2496
|
+
this.deanonymizationCleanup = () => {
|
|
2497
|
+
window.removeEventListener(IDENTITY_RESOLVED_EVENT, handleEvent);
|
|
2498
|
+
window.clearTimeout(timeoutId);
|
|
2499
|
+
};
|
|
2500
|
+
}
|
|
2501
|
+
handleDeanonymizationResult(detail) {
|
|
2502
|
+
if (this.deanonymizationStatus !== "pending") return;
|
|
2503
|
+
this.deanonymizationCleanup?.();
|
|
2504
|
+
this.deanonymizationCleanup = null;
|
|
2505
|
+
const company = resolveDeanonymizedCompany(detail);
|
|
2506
|
+
this.deanonymizedCompany = company;
|
|
2507
|
+
this.deanonymizationStatus = company ? "resolved" : "failed";
|
|
2508
|
+
if (company) {
|
|
2509
|
+
dispatchCueCardEvent("deanonymization:success", {
|
|
2510
|
+
company,
|
|
2511
|
+
detail
|
|
2512
|
+
});
|
|
2513
|
+
} else {
|
|
2514
|
+
dispatchCueCardEvent("deanonymization:fail", {
|
|
2515
|
+
detail
|
|
2516
|
+
});
|
|
2517
|
+
}
|
|
2518
|
+
this.render();
|
|
2519
|
+
}
|
|
2520
|
+
getRenderConfig() {
|
|
2521
|
+
if (this.deanonymizationStatus === "pending") {
|
|
2522
|
+
return { ...this.config, isVisible: false };
|
|
2523
|
+
}
|
|
2524
|
+
return this.config;
|
|
2525
|
+
}
|
|
2055
2526
|
setTheme(theme) {
|
|
2056
2527
|
this.update({ theme });
|
|
2057
2528
|
}
|
|
@@ -2068,9 +2539,11 @@ var KenobiLib = (() => {
|
|
|
2068
2539
|
/* @__PURE__ */ u3(
|
|
2069
2540
|
CueCardContent,
|
|
2070
2541
|
{
|
|
2071
|
-
config: this.
|
|
2542
|
+
config: this.getRenderConfig(),
|
|
2072
2543
|
isOpen: this.isOpen,
|
|
2073
2544
|
skipFocus: skipFocusOnce,
|
|
2545
|
+
deanonymizedCompany: this.deanonymizedCompany,
|
|
2546
|
+
onClearDeanonymizedCompany: this.clearDeanonymizedCompany,
|
|
2074
2547
|
setIsOpen: (val) => {
|
|
2075
2548
|
this.isOpen = val;
|
|
2076
2549
|
this.config.onOpenChange?.(val);
|
|
@@ -2492,6 +2965,8 @@ var KenobiLib = (() => {
|
|
|
2492
2965
|
};
|
|
2493
2966
|
__name(_TransitionOrchestrator, "TransitionOrchestrator");
|
|
2494
2967
|
var TransitionOrchestrator = _TransitionOrchestrator;
|
|
2968
|
+
var IDENTITY_RESOLVED_EVENT2 = "kenobi:identity-resolved";
|
|
2969
|
+
var DEFAULT_DEANON_TIMEOUT_MS2 = 1600;
|
|
2495
2970
|
var isCueCardConfigResponse = /* @__PURE__ */ __name((value) => {
|
|
2496
2971
|
if (typeof value !== "object" || value === null) return false;
|
|
2497
2972
|
const candidate = value;
|
|
@@ -2528,6 +3003,10 @@ var KenobiLib = (() => {
|
|
|
2528
3003
|
__publicField(this, "visitorKey", null);
|
|
2529
3004
|
__publicField(this, "orchestrator");
|
|
2530
3005
|
__publicField(this, "cueCardInstance", null);
|
|
3006
|
+
__publicField(this, "preparedPersonalization", null);
|
|
3007
|
+
__publicField(this, "isPreparingPersonalization", false);
|
|
3008
|
+
__publicField(this, "preparePersonalizationPromise", null);
|
|
3009
|
+
__publicField(this, "deanonymizationPrefetchCleanup", null);
|
|
2531
3010
|
//
|
|
2532
3011
|
__publicField(this, "currentPath");
|
|
2533
3012
|
__publicField(this, "currentUrl");
|
|
@@ -3227,6 +3706,8 @@ var KenobiLib = (() => {
|
|
|
3227
3706
|
}
|
|
3228
3707
|
this.log("debug", "Active template found, mounting CueCard...");
|
|
3229
3708
|
const serverConfig = configResponse.config;
|
|
3709
|
+
const deanonymizationConfig = serverConfig?.deanonymization;
|
|
3710
|
+
const shouldWaitForDeanonymization = !!deanonymizationConfig?.provider;
|
|
3230
3711
|
this.cueCardInstance = new CueCard({
|
|
3231
3712
|
theme: serverConfig?.theme ?? "light",
|
|
3232
3713
|
position: serverConfig?.position ?? "top-center",
|
|
@@ -3241,7 +3722,7 @@ var KenobiLib = (() => {
|
|
|
3241
3722
|
errorMessage: "Company name or domain is required"
|
|
3242
3723
|
}
|
|
3243
3724
|
],
|
|
3244
|
-
isVisible:
|
|
3725
|
+
isVisible: !shouldWaitForDeanonymization,
|
|
3245
3726
|
enableFocusMode: serverConfig?.enableFocusMode ?? false,
|
|
3246
3727
|
showWatermark: serverConfig?.showWatermark ?? false,
|
|
3247
3728
|
showKeyboardHints: serverConfig?.showKeyboardHints ?? true,
|
|
@@ -3249,6 +3730,7 @@ var KenobiLib = (() => {
|
|
|
3249
3730
|
customTheme: serverConfig?.customTheme,
|
|
3250
3731
|
textOverrides: serverConfig?.textOverrides,
|
|
3251
3732
|
enableUndoToggle: serverConfig?.enableUndoToggle ?? false,
|
|
3733
|
+
deanonymization: deanonymizationConfig,
|
|
3252
3734
|
isPersonalized: this.isPersonalized,
|
|
3253
3735
|
onDismiss: /* @__PURE__ */ __name(() => {
|
|
3254
3736
|
this.log("debug", "CueCard dismissed by user");
|
|
@@ -3277,8 +3759,220 @@ var KenobiLib = (() => {
|
|
|
3277
3759
|
}, "onTogglePersonalization")
|
|
3278
3760
|
});
|
|
3279
3761
|
this.cueCardInstance.mount();
|
|
3762
|
+
if (shouldWaitForDeanonymization) {
|
|
3763
|
+
this.setupDeanonymizationPrefetch(
|
|
3764
|
+
deanonymizationConfig,
|
|
3765
|
+
serverConfig?.fields
|
|
3766
|
+
);
|
|
3767
|
+
}
|
|
3280
3768
|
this.log("debug", "CueCard mounted successfully");
|
|
3281
3769
|
}, "initCueCard"));
|
|
3770
|
+
__publicField(this, "isSameInput", /* @__PURE__ */ __name((a3, b) => {
|
|
3771
|
+
const aKeys = Object.keys(a3).sort();
|
|
3772
|
+
const bKeys = Object.keys(b).sort();
|
|
3773
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
3774
|
+
for (let i3 = 0; i3 < aKeys.length; i3 += 1) {
|
|
3775
|
+
const key = aKeys[i3];
|
|
3776
|
+
if (key !== bKeys[i3]) return false;
|
|
3777
|
+
if ((a3[key] ?? "") !== (b[key] ?? "")) return false;
|
|
3778
|
+
}
|
|
3779
|
+
return true;
|
|
3780
|
+
}, "isSameInput"));
|
|
3781
|
+
__publicField(this, "buildInputFromFields", /* @__PURE__ */ __name((fields, companyName, companyDomain) => {
|
|
3782
|
+
const fallback = companyDomain || companyName;
|
|
3783
|
+
if (!fallback) return null;
|
|
3784
|
+
const input = {};
|
|
3785
|
+
fields.forEach((field) => {
|
|
3786
|
+
const key = field.name;
|
|
3787
|
+
const lowerKey = key.toLowerCase();
|
|
3788
|
+
if (lowerKey.includes("domain")) {
|
|
3789
|
+
input[key] = companyDomain || fallback;
|
|
3790
|
+
return;
|
|
3791
|
+
}
|
|
3792
|
+
if (lowerKey.includes("company")) {
|
|
3793
|
+
input[key] = companyName || fallback;
|
|
3794
|
+
return;
|
|
3795
|
+
}
|
|
3796
|
+
input[key] = fallback;
|
|
3797
|
+
});
|
|
3798
|
+
return input;
|
|
3799
|
+
}, "buildInputFromFields"));
|
|
3800
|
+
__publicField(this, "buildDeanonymizedInput", /* @__PURE__ */ __name((detail, fields) => {
|
|
3801
|
+
const name = detail.company?.name || detail.domain || "";
|
|
3802
|
+
const domain = detail.company?.domain || detail.domain || "";
|
|
3803
|
+
if (!fields || fields.length === 0) {
|
|
3804
|
+
if (!name && !domain) return null;
|
|
3805
|
+
return {
|
|
3806
|
+
companyName: name || domain,
|
|
3807
|
+
companyDomain: domain || name
|
|
3808
|
+
};
|
|
3809
|
+
}
|
|
3810
|
+
return this.buildInputFromFields(fields, name, domain);
|
|
3811
|
+
}, "buildDeanonymizedInput"));
|
|
3812
|
+
__publicField(this, "requestPersonalization", /* @__PURE__ */ __name(async (input, options) => {
|
|
3813
|
+
const payload = {
|
|
3814
|
+
publicKey: this.config.publicKey,
|
|
3815
|
+
input,
|
|
3816
|
+
pagePath: this.currentPath
|
|
3817
|
+
};
|
|
3818
|
+
if (options?.notifySlack === false) {
|
|
3819
|
+
payload.notifySlack = false;
|
|
3820
|
+
}
|
|
3821
|
+
if (options?.notifyOnly) {
|
|
3822
|
+
payload.notifyOnly = true;
|
|
3823
|
+
}
|
|
3824
|
+
if (options?.predictionSource) {
|
|
3825
|
+
payload.predictionSource = options.predictionSource;
|
|
3826
|
+
}
|
|
3827
|
+
if (options?.prefetchedTransformations) {
|
|
3828
|
+
payload.prefetchedTransformations = options.prefetchedTransformations;
|
|
3829
|
+
}
|
|
3830
|
+
if (options?.prefetchedMetadata) {
|
|
3831
|
+
payload.prefetchedMetadata = options.prefetchedMetadata;
|
|
3832
|
+
}
|
|
3833
|
+
const response = await fetch(`${this.config.apiHost}/v1/personalize`, {
|
|
3834
|
+
method: "POST",
|
|
3835
|
+
headers: {
|
|
3836
|
+
"Content-Type": "application/json"
|
|
3837
|
+
},
|
|
3838
|
+
body: JSON.stringify(payload)
|
|
3839
|
+
});
|
|
3840
|
+
if (!response.ok) {
|
|
3841
|
+
const errorBody = await response.json().catch(() => ({}));
|
|
3842
|
+
throw new Error(errorBody.error || `API error: ${response.status}`);
|
|
3843
|
+
}
|
|
3844
|
+
const result = await response.json();
|
|
3845
|
+
this.log("debug", "Personalization API response:", result);
|
|
3846
|
+
return result;
|
|
3847
|
+
}, "requestPersonalization"));
|
|
3848
|
+
__publicField(this, "preparePersonalization", /* @__PURE__ */ __name(async (input, options) => {
|
|
3849
|
+
if (!this.config.publicKey) {
|
|
3850
|
+
this.log("error", "Cannot prepare personalization: publicKey not configured");
|
|
3851
|
+
return null;
|
|
3852
|
+
}
|
|
3853
|
+
if (this.preparedPersonalization?.input && this.isSameInput(this.preparedPersonalization.input, input)) {
|
|
3854
|
+
if (options?.source && !this.preparedPersonalization.source) {
|
|
3855
|
+
this.preparedPersonalization = {
|
|
3856
|
+
...this.preparedPersonalization,
|
|
3857
|
+
source: options.source
|
|
3858
|
+
};
|
|
3859
|
+
}
|
|
3860
|
+
return this.preparedPersonalization.result;
|
|
3861
|
+
}
|
|
3862
|
+
if (this.preparePersonalizationPromise) {
|
|
3863
|
+
return this.preparePersonalizationPromise;
|
|
3864
|
+
}
|
|
3865
|
+
this.isPreparingPersonalization = true;
|
|
3866
|
+
this.preparePersonalizationPromise = (async () => {
|
|
3867
|
+
try {
|
|
3868
|
+
const result = await this.requestPersonalization(input, {
|
|
3869
|
+
notifySlack: false,
|
|
3870
|
+
predictionSource: options?.source
|
|
3871
|
+
});
|
|
3872
|
+
this.preparedPersonalization = { input, result, source: options?.source };
|
|
3873
|
+
this.dispatchKenobiEvent("personalization:ready", {
|
|
3874
|
+
input,
|
|
3875
|
+
pagePath: this.currentPath,
|
|
3876
|
+
transformationsCount: result.transformations?.length ?? 0,
|
|
3877
|
+
metadata: result.metadata,
|
|
3878
|
+
source: options?.source
|
|
3879
|
+
});
|
|
3880
|
+
return result;
|
|
3881
|
+
} catch (error) {
|
|
3882
|
+
this.log("error", "Personalization prefetch failed:", error);
|
|
3883
|
+
return null;
|
|
3884
|
+
} finally {
|
|
3885
|
+
this.isPreparingPersonalization = false;
|
|
3886
|
+
this.preparePersonalizationPromise = null;
|
|
3887
|
+
}
|
|
3888
|
+
})();
|
|
3889
|
+
return this.preparePersonalizationPromise;
|
|
3890
|
+
}, "preparePersonalization"));
|
|
3891
|
+
__publicField(this, "notifyPreparedPersonalization", /* @__PURE__ */ __name(async (prepared) => {
|
|
3892
|
+
if (!prepared.result.transformations || !prepared.result.metadata) {
|
|
3893
|
+
this.log(
|
|
3894
|
+
"warn",
|
|
3895
|
+
"Prepared personalization missing transformations or metadata for notify"
|
|
3896
|
+
);
|
|
3897
|
+
return;
|
|
3898
|
+
}
|
|
3899
|
+
try {
|
|
3900
|
+
await this.requestPersonalization(prepared.input, {
|
|
3901
|
+
notifySlack: true,
|
|
3902
|
+
notifyOnly: true,
|
|
3903
|
+
predictionSource: prepared.source,
|
|
3904
|
+
prefetchedTransformations: prepared.result.transformations,
|
|
3905
|
+
prefetchedMetadata: prepared.result.metadata
|
|
3906
|
+
});
|
|
3907
|
+
} catch (error) {
|
|
3908
|
+
this.log(
|
|
3909
|
+
"warn",
|
|
3910
|
+
"Failed to send Slack notification for prepared personalization:",
|
|
3911
|
+
error
|
|
3912
|
+
);
|
|
3913
|
+
}
|
|
3914
|
+
}, "notifyPreparedPersonalization"));
|
|
3915
|
+
__publicField(this, "setupDeanonymizationPrefetch", /* @__PURE__ */ __name((config, fields) => {
|
|
3916
|
+
if (!this.cueCardInstance) return;
|
|
3917
|
+
if (typeof window === "undefined") {
|
|
3918
|
+
this.cueCardInstance.update({ isVisible: true });
|
|
3919
|
+
return;
|
|
3920
|
+
}
|
|
3921
|
+
if (this.deanonymizationPrefetchCleanup) return;
|
|
3922
|
+
let resolved = false;
|
|
3923
|
+
let hasIdentity = false;
|
|
3924
|
+
let shouldDisableDeanonymization = false;
|
|
3925
|
+
const finish = /* @__PURE__ */ __name(() => {
|
|
3926
|
+
if (resolved) return;
|
|
3927
|
+
resolved = true;
|
|
3928
|
+
if (shouldDisableDeanonymization) {
|
|
3929
|
+
this.cueCardInstance?.update({
|
|
3930
|
+
deanonymization: void 0,
|
|
3931
|
+
isVisible: true
|
|
3932
|
+
});
|
|
3933
|
+
} else {
|
|
3934
|
+
this.cueCardInstance?.update({ isVisible: true });
|
|
3935
|
+
}
|
|
3936
|
+
this.deanonymizationPrefetchCleanup?.();
|
|
3937
|
+
this.deanonymizationPrefetchCleanup = null;
|
|
3938
|
+
}, "finish");
|
|
3939
|
+
const handleIdentity = /* @__PURE__ */ __name(async (event) => {
|
|
3940
|
+
if (resolved) return;
|
|
3941
|
+
const detail = event.detail;
|
|
3942
|
+
hasIdentity = true;
|
|
3943
|
+
if (detail?.type !== "business") {
|
|
3944
|
+
finish();
|
|
3945
|
+
return;
|
|
3946
|
+
}
|
|
3947
|
+
const input = this.buildDeanonymizedInput(detail, fields);
|
|
3948
|
+
if (!input) {
|
|
3949
|
+
finish();
|
|
3950
|
+
return;
|
|
3951
|
+
}
|
|
3952
|
+
const prepared = await this.preparePersonalization(input, {
|
|
3953
|
+
source: "deanonymized"
|
|
3954
|
+
});
|
|
3955
|
+
if (!prepared) {
|
|
3956
|
+
shouldDisableDeanonymization = true;
|
|
3957
|
+
}
|
|
3958
|
+
finish();
|
|
3959
|
+
}, "handleIdentity");
|
|
3960
|
+
const cachedIdentity = window.__kenobiIdentityResolution;
|
|
3961
|
+
if (cachedIdentity) {
|
|
3962
|
+
void handleIdentity({ detail: cachedIdentity });
|
|
3963
|
+
}
|
|
3964
|
+
window.addEventListener(IDENTITY_RESOLVED_EVENT2, handleIdentity);
|
|
3965
|
+
const timeoutMs = config?.timeoutMs ?? DEFAULT_DEANON_TIMEOUT_MS2;
|
|
3966
|
+
const timeoutId = window.setTimeout(() => {
|
|
3967
|
+
if (!hasIdentity) {
|
|
3968
|
+
finish();
|
|
3969
|
+
}
|
|
3970
|
+
}, timeoutMs + 50);
|
|
3971
|
+
this.deanonymizationPrefetchCleanup = () => {
|
|
3972
|
+
window.removeEventListener(IDENTITY_RESOLVED_EVENT2, handleIdentity);
|
|
3973
|
+
window.clearTimeout(timeoutId);
|
|
3974
|
+
};
|
|
3975
|
+
}, "setupDeanonymizationPrefetch"));
|
|
3282
3976
|
/**
|
|
3283
3977
|
* Syncs CueCard visibility based on the current path.
|
|
3284
3978
|
* Checks with the server if an active template exists for the new path.
|
|
@@ -3319,46 +4013,36 @@ var KenobiLib = (() => {
|
|
|
3319
4013
|
__publicField(this, "personalize", /* @__PURE__ */ __name(async (input) => {
|
|
3320
4014
|
if (!this.config.publicKey) {
|
|
3321
4015
|
this.log("error", "Cannot personalize: publicKey not configured");
|
|
3322
|
-
return;
|
|
4016
|
+
return null;
|
|
3323
4017
|
}
|
|
3324
4018
|
const startTime = /* @__PURE__ */ new Date();
|
|
3325
4019
|
this.log("debug", "Starting personalization with input:", input);
|
|
4020
|
+
const prepared = this.preparedPersonalization?.input && this.isSameInput(this.preparedPersonalization.input, input) ? this.preparedPersonalization : null;
|
|
4021
|
+
const isDeanonymizedInput = prepared?.source === "deanonymized";
|
|
3326
4022
|
this.dispatchKenobiEvent("personalization:start", {
|
|
3327
4023
|
input,
|
|
3328
|
-
pagePath: this.currentPath
|
|
4024
|
+
pagePath: this.currentPath,
|
|
4025
|
+
deanonymized: isDeanonymizedInput
|
|
3329
4026
|
});
|
|
3330
|
-
if (this.cueCardInstance) {
|
|
3331
|
-
this.cueCardInstance.update({ status: "starting", progressPct: 10 });
|
|
3332
|
-
}
|
|
3333
4027
|
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
4028
|
if (this.cueCardInstance) {
|
|
3346
|
-
this.cueCardInstance.update({
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
throw new Error(errorBody.error || `API error: ${response.status}`);
|
|
4029
|
+
this.cueCardInstance.update({
|
|
4030
|
+
status: "starting",
|
|
4031
|
+
progressPct: prepared ? 80 : 10
|
|
4032
|
+
});
|
|
3351
4033
|
}
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
if (this.cueCardInstance) {
|
|
3355
|
-
this.cueCardInstance.update({ progressPct: 80 });
|
|
4034
|
+
if (prepared) {
|
|
4035
|
+
void this.notifyPreparedPersonalization(prepared);
|
|
3356
4036
|
}
|
|
4037
|
+
const result = prepared ? prepared.result : await this.requestPersonalization(input);
|
|
3357
4038
|
if (result.transformations && Array.isArray(result.transformations)) {
|
|
3358
4039
|
await this.applyTransformations(result.transformations, {
|
|
3359
4040
|
shouldConsolidate: true
|
|
3360
4041
|
});
|
|
3361
4042
|
}
|
|
4043
|
+
if (prepared) {
|
|
4044
|
+
this.preparedPersonalization = null;
|
|
4045
|
+
}
|
|
3362
4046
|
if (this.cueCardInstance) {
|
|
3363
4047
|
this.cueCardInstance.update({ status: "success", progressPct: 100 });
|
|
3364
4048
|
}
|
|
@@ -3373,8 +4057,11 @@ var KenobiLib = (() => {
|
|
|
3373
4057
|
pagePath: this.currentPath,
|
|
3374
4058
|
durationMs: duration,
|
|
3375
4059
|
transformationsCount: result.transformations?.length ?? 0,
|
|
3376
|
-
metadata: result.metadata
|
|
4060
|
+
metadata: result.metadata,
|
|
4061
|
+
source: prepared ? "prefetch" : "api",
|
|
4062
|
+
deanonymized: isDeanonymizedInput
|
|
3377
4063
|
});
|
|
4064
|
+
return result;
|
|
3378
4065
|
} catch (error) {
|
|
3379
4066
|
this.log("error", "Personalization failed:", error);
|
|
3380
4067
|
if (this.cueCardInstance) {
|
|
@@ -3383,9 +4070,11 @@ var KenobiLib = (() => {
|
|
|
3383
4070
|
this.dispatchKenobiEvent("personalization:error", {
|
|
3384
4071
|
input,
|
|
3385
4072
|
pagePath: this.currentPath,
|
|
3386
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4073
|
+
error: error instanceof Error ? error.message : String(error),
|
|
4074
|
+
deanonymized: isDeanonymizedInput
|
|
3387
4075
|
});
|
|
3388
4076
|
}
|
|
4077
|
+
return null;
|
|
3389
4078
|
}, "personalize"));
|
|
3390
4079
|
/**
|
|
3391
4080
|
* Returns the CueCard instance if one was auto-mounted.
|