kenobi-js 0.1.41 → 0.1.42

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/browser/dist.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * Kenobi SDK v0.1.40
3
- * (c) 2025 Kenobi.ai
2
+ * Kenobi SDK v0.1.41
3
+ * (c) 2026 Kenobi.ai
4
4
  */
5
5
  "use strict";
6
6
  var KenobiLib = (() => {
@@ -1022,17 +1022,14 @@ var KenobiLib = (() => {
1022
1022
  {
1023
1023
  xmlns: "http://www.w3.org/2000/svg",
1024
1024
  viewBox: "0 0 24 24",
1025
- fill: "currentColor",
1025
+ fill: "none",
1026
+ stroke: "currentColor",
1027
+ "stroke-width": "3",
1028
+ "stroke-linecap": "round",
1029
+ "stroke-linejoin": "round",
1026
1030
  width: "16",
1027
1031
  height: "16",
1028
- children: /* @__PURE__ */ u3(
1029
- "path",
1030
- {
1031
- fillRule: "evenodd",
1032
- d: "M16.72 7.72a.75.75 0 0 1 1.06 0l3.75 3.75a.75.75 0 0 1 0 1.06l-3.75 3.75a.75.75 0 1 1-1.06-1.06l2.47-2.47H3a.75.75 0 0 1 0-1.5h16.19l-2.47-2.47a.75.75 0 0 1 0-1.06Z",
1033
- clipRule: "evenodd"
1034
- }
1035
- )
1032
+ children: /* @__PURE__ */ u3("path", { d: "M5 12h14M12 5l7 7-7 7" })
1036
1033
  }
1037
1034
  ), "ArrowRightIcon");
1038
1035
  var CheckIcon = /* @__PURE__ */ __name(() => /* @__PURE__ */ u3(
@@ -1133,12 +1130,12 @@ var KenobiLib = (() => {
1133
1130
  }
1134
1131
  ), "ArrowPathIcon");
1135
1132
  var STYLES = `
1136
- :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.1); --kb-kbd-border: rgba(255, 255, 255, 0.2); --kb-kbd-text: rgba(255, 255, 255, 0.6); --kb-watermark-text: rgba(255, 255, 255, 0.4); font-family: var(--kb-font-family); }
1133
+ :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); }
1137
1134
  .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; }
1138
1135
  .theme-dark { --kb-bg-container: #0f172a; --kb-border-container: #334155; --kb-shadow-container: 0 25px 50px -12px rgba(0, 0, 0, 0.25); --kb-backdrop-blur: 0px; --kb-text-title: #f1f5f9; --kb-text-subtitle: #94a3b8; --kb-btn-dismiss-bg: #1e293b; --kb-btn-dismiss-border: #334155; --kb-btn-dismiss-text: #cbd5e1; --kb-btn-dismiss-hover-bg: #334155; --kb-btn-dismiss-hover-text: #ffffff; --kb-btn-trigger-bg: #ffffff; --kb-btn-trigger-text: #0f172a; --kb-btn-trigger-hover-bg: #f1f5f9; --kb-progress-track: #1e293b; --kb-progress-indicator: #ffffff; --kb-popover-bg: #0f172a; --kb-popover-border: #334155; --kb-popover-text: #f1f5f9; --kb-input-bg: #0f172a; --kb-input-border: #475569; --kb-input-text: #f1f5f9; --kb-input-placeholder: #94a3b8; --kb-form-label: #e2e8f0; --kb-success-color: #6ee7b7; --kb-error-text: #ef4444; --kb-kbd-bg: #1e293b; --kb-kbd-border: #334155; --kb-kbd-text: #94a3b8; --kb-watermark-text: #64748b; }
1139
1136
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
1140
1137
  #cue-card-root { position: fixed; z-index: 2147483647; pointer-events: none; width: 100%; height: 0; top: 0; left: 0; isolation: isolate; }
1141
- .container { 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: 0.25rem; border-bottom-left-radius: 0.25rem; border-bottom-right-radius: 0.25rem; padding: 1rem; width: auto; min-width: 320px; max-width: 90vw; opacity: 0; z-index: 1; font-family: var(--kb-font-family); }
1138
+ .container { 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: 0.25rem; border-bottom-left-radius: 0.25rem; border-bottom-right-radius: 0.25rem; padding: 1.25rem 1.5rem; width: auto; min-width: 400px; max-width: 90vw; opacity: 0; z-index: 1; font-family: var(--kb-font-family); }
1142
1139
  .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; }
1143
1140
  .backdrop.active { background: rgba(0,0,0,0.1); backdrop-filter: blur(var(--kb-focus-blur)); -webkit-backdrop-filter: blur(var(--kb-focus-blur)); }
1144
1141
  .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); }
@@ -1161,21 +1158,31 @@ var KenobiLib = (() => {
1161
1158
  .title { color: var(--kb-text-title); font-size: 1rem; font-weight: 600; line-height: 1.5; }
1162
1159
  .subtitle { color: var(--kb-text-title); font-size: 0.875rem; line-height: 1.25; opacity: 0.8; }
1163
1160
  .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; }
1164
- .btn-trigger { background-color: var(--kb-btn-trigger-bg); color: var(--kb-btn-trigger-text); min-width: 8rem; gap: 0.5rem; }
1161
+ .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
+ .btn-trigger.hidden { opacity: 0; pointer-events: none; }
1165
1163
  .btn-trigger:not(:disabled):hover { background-color: var(--kb-btn-trigger-hover-bg); }
1166
1164
  .btn-trigger:disabled { opacity: 0.8; cursor: not-allowed; }
1167
1165
  .btn-trigger.success { background-color: transparent; color: var(--kb-success-color); padding-right: 0.75rem; cursor: default; }
1166
+ .status-text { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.875rem; color: var(--kb-text-subtitle); opacity: 0.8; }
1168
1167
  .btn-trigger.success:hover { background-color: transparent; }
1169
1168
  .animate-spin { animation: spin 1s linear infinite; }
1170
1169
  @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
1170
+ @keyframes shine { 0% { background-position: 0% 0%; } 50% { background-position: 100% 100%; } 100% { background-position: 0% 0%; } }
1171
+ @keyframes sheen-flash { 0% { opacity: 0; transform: translateX(-100%) skewX(-15deg); } 50% { opacity: 0.6; } 100% { opacity: 0; transform: translateX(200%) skewX(-15deg); } }
1172
+ .container-sheen { position: absolute; inset: 0; overflow: hidden; pointer-events: none; border-radius: inherit; }
1173
+ .container-sheen::after { content: ''; position: absolute; top: 0; left: 0; width: 50%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent); transform: translateX(-100%) skewX(-15deg); }
1174
+ .container-sheen.active::after { animation: sheen-flash 0.6s ease-out forwards; }
1175
+ .launcher-shine-border { position: absolute; inset: 0; border-radius: inherit; pointer-events: none; background-size: 300% 300%; animation: shine var(--shine-duration, 14s) linear infinite; mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); mask-composite: exclude; -webkit-mask-composite: xor; padding: var(--shine-border-width, 1px); }
1171
1176
  .btn-dismiss { position: absolute; top: -0.5rem; left: -0.5rem; width: 1.5rem; height: 1.5rem; padding: 0; border-radius: 9999px; display: flex; align-items: center; justify-content: center; background-color: var(--kb-btn-dismiss-bg); border: 1px solid var(--kb-btn-dismiss-border); color: var(--kb-btn-dismiss-text); cursor: pointer; transition: all 0.3s ease-out; z-index: 10; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); }
1172
1177
  .btn-dismiss:hover { background-color: var(--kb-btn-dismiss-hover-bg); color: var(--kb-btn-dismiss-hover-text); }
1173
- .progress-clip { position: absolute; inset: 0; border-radius: inherit; overflow: hidden; pointer-events: none; }
1174
- .progress-container { position: absolute; bottom: 0; left: 0; right: 0; height: 0.25rem; background-color: var(--kb-progress-track); overflow: hidden; pointer-events: none; }
1178
+ .progress-clip { position: absolute; inset: 0; border-radius: inherit; border-bottom-left-radius: 0; border-bottom-right-radius: 0; overflow: hidden; pointer-events: none; }
1179
+ .progress-container { position: absolute; bottom: 0; left: 0; right: 0; height: 0.25rem; background-color: var(--kb-progress-track); overflow: hidden; pointer-events: none; border-radius: 0; }
1175
1180
  .progress-bar { height: 100%; background-color: var(--kb-progress-indicator); width: 0%; transition: width 0.3s ease; }
1176
- .popover { position: absolute; top: 100%; left: 0; right: 0; margin-top: 0.375rem; background-color: var(--kb-popover-bg); border: 1px solid var(--kb-popover-border); border-radius: 0.25rem; border-top-left-radius: 0; border-top-right-radius: 0; padding: 1rem; color: var(--kb-popover-text); box-shadow: var(--kb-shadow-container); backdrop-filter: blur(var(--kb-backdrop-blur)); -webkit-backdrop-filter: blur(var(--kb-backdrop-blur)); opacity: 0; transform: translateY(-10px); pointer-events: none; visibility: hidden; transition: all 0.2s ease-out; }
1181
+ .popover { position: absolute; top: 100%; left: 0; right: 0; margin-top: 0.375rem; background-color: var(--kb-popover-bg); border: 1px solid var(--kb-popover-border); border-radius: 0.25rem; border-top-left-radius: 0; border-top-right-radius: 0; padding: 1rem 1.5rem; color: var(--kb-popover-text); box-shadow: var(--kb-shadow-container); backdrop-filter: blur(var(--kb-backdrop-blur)); -webkit-backdrop-filter: blur(var(--kb-backdrop-blur)); opacity: 0; transform: translateY(-10px); pointer-events: none; visibility: hidden; transition: all 0.2s ease-out; }
1177
1182
  .popover.open { opacity: 1; transform: translateY(0); pointer-events: auto; visibility: visible; }
1178
- .form-group { margin-bottom: 1rem; }
1183
+ .container.popover-open { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
1184
+ .container.popover-open .progress-clip { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
1185
+ .form-group { margin-bottom: 0; }
1179
1186
  .form-label { display: block; margin-bottom: 0.5rem; font-size: 0.875rem; color: var(--kb-form-label); font-weight: 500; }
1180
1187
  .input-row { display: flex; gap: 0.5rem; }
1181
1188
  .form-input { flex: 1; background-color: var(--kb-input-bg); border: 1px solid var(--kb-input-border); color: var(--kb-input-text); border-radius: 0.375rem; padding: 0.5rem 0.75rem; font-size: 0.875rem; outline: none; transition: border-color 0.2s; min-height: 44px; }
@@ -1194,6 +1201,9 @@ var KenobiLib = (() => {
1194
1201
  .watermark { text-align: center; font-size: 0.625rem; color: var(--kb-watermark-text); opacity: 0.8; font-weight: 500; letter-spacing: 0.025em; }
1195
1202
  .watermark a { color: inherit; text-decoration: none; cursor: pointer; }
1196
1203
  .watermark a:hover { text-decoration: underline; text-decoration-color: var(--kb-watermark-text); }
1204
+ .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
+ .popover-watermark a { color: inherit; text-decoration: none; cursor: pointer; }
1206
+ .popover-watermark a:hover { text-decoration: underline; opacity: 1; }
1197
1207
  /* Launcher hint positioning */
1198
1208
  .launcher .kbd-hint { position: static; transform: none; opacity: 0.6; transition: opacity 0.2s; }
1199
1209
  .launcher:hover .kbd-hint { opacity: 1; }
@@ -1219,14 +1229,20 @@ var KenobiLib = (() => {
1219
1229
  `;
1220
1230
  var useEnterExitAnimation = /* @__PURE__ */ __name((ref, isVisible, config) => {
1221
1231
  const hasEnteredRef = A2(false);
1232
+ const currentAnimRef = A2(null);
1222
1233
  y2(() => {
1223
1234
  const element = ref.current;
1224
1235
  if (!element) return;
1236
+ if (currentAnimRef.current) {
1237
+ currentAnimRef.current.cancel();
1238
+ currentAnimRef.current = null;
1239
+ }
1225
1240
  const isTopDown = config.direction === "top-to-bottom";
1226
1241
  const initialTransform = isTopDown ? `translateY(-60px)` : `translateX(60px)`;
1227
1242
  const exitTransform = isTopDown ? `translateY(-20px)` : `translateX(20px)`;
1228
1243
  const finalTransform = "translate(0, 0)";
1229
1244
  if (isVisible) {
1245
+ element.style.visibility = "visible";
1230
1246
  hasEnteredRef.current = true;
1231
1247
  const anim = element.animate(
1232
1248
  [
@@ -1240,7 +1256,11 @@ var KenobiLib = (() => {
1240
1256
  fill: "forwards"
1241
1257
  }
1242
1258
  );
1243
- anim.onfinish = () => config.onEntranceComplete?.();
1259
+ currentAnimRef.current = anim;
1260
+ anim.onfinish = () => {
1261
+ currentAnimRef.current = null;
1262
+ config.onEntranceComplete?.();
1263
+ };
1244
1264
  } else {
1245
1265
  if (hasEnteredRef.current) {
1246
1266
  const anim = element.animate(
@@ -1255,10 +1275,16 @@ var KenobiLib = (() => {
1255
1275
  fill: "forwards"
1256
1276
  }
1257
1277
  );
1258
- anim.onfinish = () => config.onExitComplete?.();
1278
+ currentAnimRef.current = anim;
1279
+ anim.onfinish = () => {
1280
+ element.style.visibility = "hidden";
1281
+ currentAnimRef.current = null;
1282
+ config.onExitComplete?.();
1283
+ };
1259
1284
  } else {
1260
1285
  element.style.opacity = "0";
1261
1286
  element.style.transform = exitTransform;
1287
+ element.style.visibility = "hidden";
1262
1288
  }
1263
1289
  }
1264
1290
  }, [isVisible, config.direction]);
@@ -1305,6 +1331,7 @@ var KenobiLib = (() => {
1305
1331
  const [mode, setMode] = d2("card");
1306
1332
  const [isDismissed, setIsDismissed] = d2(false);
1307
1333
  const [hasHadSuccess, setHasHadSuccess] = d2(false);
1334
+ const [isExitingToLauncher, setIsExitingToLauncher] = d2(false);
1308
1335
  const hasEnteredRef = A2(false);
1309
1336
  const isShowingInitialSuccessRef = A2(false);
1310
1337
  const justReopenedRef = A2(false);
@@ -1315,6 +1342,7 @@ var KenobiLib = (() => {
1315
1342
  const timerRafRef = A2(null);
1316
1343
  const hasTimerCompletedRef = A2(false);
1317
1344
  const [isHovering, setIsHovering] = d2(false);
1345
+ const [sheenActive, setSheenActive] = d2(false);
1318
1346
  const [errors, setErrors] = d2({});
1319
1347
  const [timerProgress, setTimerProgressState] = d2(0);
1320
1348
  const timerProgressRef = A2(0);
@@ -1411,6 +1439,9 @@ var KenobiLib = (() => {
1411
1439
  setMode("card");
1412
1440
  }
1413
1441
  }, [isOpen, mode]);
1442
+ const isFirstAppearance = !hasEnteredRef.current;
1443
+ const wasLauncherPreviously = previousModeRef.current === "launcher";
1444
+ const cardEntranceDelay = isFirstAppearance ? config.entranceDelayMs || 0 : wasLauncherPreviously && mode === "card" ? 400 : 0;
1414
1445
  if (!isInline) {
1415
1446
  useEnterExitAnimation(
1416
1447
  containerRef,
@@ -1418,7 +1449,7 @@ var KenobiLib = (() => {
1418
1449
  {
1419
1450
  direction: config.direction || "top-to-bottom",
1420
1451
  position: config.position || "top-center",
1421
- entranceDelayMs: hasEnteredRef.current ? 0 : config.entranceDelayMs || 0,
1452
+ entranceDelayMs: cardEntranceDelay,
1422
1453
  exitDelayMs: 75,
1423
1454
  onEntranceComplete: /* @__PURE__ */ __name(() => {
1424
1455
  config.onEntranceComplete?.();
@@ -1429,13 +1460,14 @@ var KenobiLib = (() => {
1429
1460
  }, "onExitComplete")
1430
1461
  }
1431
1462
  );
1463
+ const launcherEntranceDelay = 400;
1432
1464
  useEnterExitAnimation(
1433
1465
  launcherRef,
1434
1466
  !!config.isVisible && mode === "launcher" && !isDismissed,
1435
1467
  {
1436
1468
  direction: config.direction || "top-to-bottom",
1437
1469
  position: config.position || "top-center",
1438
- entranceDelayMs: 0,
1470
+ entranceDelayMs: launcherEntranceDelay,
1439
1471
  exitDelayMs: 75
1440
1472
  }
1441
1473
  );
@@ -1443,8 +1475,8 @@ var KenobiLib = (() => {
1443
1475
  y2(() => {
1444
1476
  const el = backdropRef.current;
1445
1477
  if (!el) return;
1446
- const isSuccess2 = config.status === "success";
1447
- if (config.enableFocusMode && mode === "card" && config.isVisible && !isSuccess2) {
1478
+ const isShowingSuccessState = config.status === "success" && isShowingInitialSuccessRef.current;
1479
+ if (config.enableFocusMode && mode === "card" && config.isVisible && !isShowingSuccessState) {
1448
1480
  const timer = setTimeout(() => {
1449
1481
  el.classList.add("active");
1450
1482
  }, config.focusDelayMs || 500);
@@ -1463,14 +1495,16 @@ var KenobiLib = (() => {
1463
1495
  if (!config.isVisible) return;
1464
1496
  const handleKey = /* @__PURE__ */ __name((e3) => {
1465
1497
  if (e3.key === "Escape") {
1466
- if (isOpen) {
1467
- setIsOpen(false);
1468
- return;
1469
- }
1470
1498
  if (mode === "card") {
1471
1499
  if (config.enableLauncher) {
1500
+ setIsExitingToLauncher(true);
1472
1501
  setMode("launcher");
1502
+ setTimeout(() => {
1503
+ setIsOpen(false);
1504
+ setIsExitingToLauncher(false);
1505
+ }, 500);
1473
1506
  } else {
1507
+ setIsOpen(false);
1474
1508
  config.onDismiss?.();
1475
1509
  }
1476
1510
  }
@@ -1635,7 +1669,12 @@ var KenobiLib = (() => {
1635
1669
  const togglePopover = /* @__PURE__ */ __name((e3) => {
1636
1670
  e3.stopPropagation();
1637
1671
  if (isPending || isSuccess) return;
1638
- setIsOpen(!isOpen);
1672
+ const opening = !isOpen;
1673
+ setIsOpen(opening);
1674
+ if (opening && config.enableClickSheen) {
1675
+ setSheenActive(true);
1676
+ setTimeout(() => setSheenActive(false), 600);
1677
+ }
1639
1678
  }, "togglePopover");
1640
1679
  y2(() => {
1641
1680
  if (!timerEnabled) return;
@@ -1716,7 +1755,7 @@ var KenobiLib = (() => {
1716
1755
  "div",
1717
1756
  {
1718
1757
  ref: containerRef,
1719
- class: `container theme-${config.theme || "glass"} pos-${config.position || "top-center"}`,
1758
+ class: `container theme-${config.theme || "glass"} pos-${config.position || "top-center"}${isOpen ? " popover-open" : ""}`,
1720
1759
  style: {
1721
1760
  ...getThemeStyles(config.customTheme),
1722
1761
  pointerEvents: isContainerVisible ? "auto" : "none"
@@ -1725,6 +1764,7 @@ var KenobiLib = (() => {
1725
1764
  onMouseEnter: () => setIsHovering(true),
1726
1765
  onMouseLeave: () => setIsHovering(false),
1727
1766
  children: [
1767
+ config.enableClickSheen && /* @__PURE__ */ u3("div", { class: `container-sheen${sheenActive ? " active" : ""}` }),
1728
1768
  /* @__PURE__ */ u3(
1729
1769
  "button",
1730
1770
  {
@@ -1742,32 +1782,29 @@ var KenobiLib = (() => {
1742
1782
  children: /* @__PURE__ */ u3(XMarkIcon, {})
1743
1783
  }
1744
1784
  ),
1745
- /* @__PURE__ */ u3("div", { class: "content-wrapper", children: [
1746
- /* @__PURE__ */ u3("div", { class: "logo", children: /* @__PURE__ */ u3(LogoIcon, {}) }),
1747
- /* @__PURE__ */ u3("div", { class: "text-content", children: /* @__PURE__ */ u3("div", { class: "text-row", children: [
1748
- /* @__PURE__ */ u3("div", { children: [
1749
- /* @__PURE__ */ u3("div", { class: "title", children: titleText }),
1750
- /* @__PURE__ */ u3("div", { class: "subtitle", children: subtitleText })
1751
- ] }),
1752
- /* @__PURE__ */ u3(
1753
- "button",
1754
- {
1755
- class: `btn btn-trigger ${showAsSuccess ? "success" : ""}`,
1756
- disabled: isPending || showAsSuccess,
1757
- onClick: togglePopover,
1758
- children: isPending ? /* @__PURE__ */ u3(k, { children: [
1759
- /* @__PURE__ */ u3(LoaderIcon, {}),
1760
- " ",
1761
- buttonText
1762
- ] }) : showAsSuccess ? /* @__PURE__ */ u3(k, { children: [
1763
- /* @__PURE__ */ u3(CheckIcon, {}),
1764
- " ",
1765
- buttonText
1766
- ] }) : buttonText
1767
- }
1768
- )
1769
- ] }) })
1770
- ] }),
1785
+ /* @__PURE__ */ u3("div", { class: "content-wrapper", children: /* @__PURE__ */ u3("div", { class: "text-content", children: /* @__PURE__ */ u3("div", { class: "text-row", children: [
1786
+ /* @__PURE__ */ u3("div", { children: [
1787
+ /* @__PURE__ */ u3("div", { class: "title", children: titleText }),
1788
+ /* @__PURE__ */ u3("div", { class: "subtitle", children: subtitleText })
1789
+ ] }),
1790
+ isPending ? /* @__PURE__ */ u3("span", { class: "status-text", children: [
1791
+ /* @__PURE__ */ u3(LoaderIcon, {}),
1792
+ " ",
1793
+ buttonText
1794
+ ] }) : /* @__PURE__ */ u3(
1795
+ "button",
1796
+ {
1797
+ class: `btn btn-trigger ${showAsSuccess ? "success" : ""}${isOpen || isExitingToLauncher ? " hidden" : ""}`,
1798
+ disabled: showAsSuccess,
1799
+ onClick: togglePopover,
1800
+ children: showAsSuccess ? /* @__PURE__ */ u3(k, { children: [
1801
+ /* @__PURE__ */ u3(CheckIcon, {}),
1802
+ " ",
1803
+ buttonText
1804
+ ] }) : buttonText
1805
+ }
1806
+ )
1807
+ ] }) }) }),
1771
1808
  /* @__PURE__ */ u3("div", { class: "progress-clip", children: /* @__PURE__ */ u3("div", { class: "progress-container", children: /* @__PURE__ */ u3(
1772
1809
  "div",
1773
1810
  {
@@ -1828,7 +1865,7 @@ var KenobiLib = (() => {
1828
1865
  }
1829
1866
  )
1830
1867
  ] }),
1831
- config.showWatermark && /* @__PURE__ */ u3("div", { class: "watermark", children: [
1868
+ config.showWatermark && /* @__PURE__ */ u3("div", { class: "popover-watermark", children: [
1832
1869
  "Powered by",
1833
1870
  " ",
1834
1871
  /* @__PURE__ */ u3(
@@ -1864,6 +1901,7 @@ var KenobiLib = (() => {
1864
1901
  class: `launcher theme-${config.theme || "glass"} pos-${config.position || "top-center"}`,
1865
1902
  style: {
1866
1903
  ...getThemeStyles(config.customTheme),
1904
+ ...config.launcherStyles,
1867
1905
  pointerEvents: isLauncherVisible ? "auto" : "none"
1868
1906
  },
1869
1907
  onClick: (e3) => {
@@ -1875,6 +1913,17 @@ var KenobiLib = (() => {
1875
1913
  role: "button",
1876
1914
  tabIndex: 0,
1877
1915
  children: [
1916
+ config.launcherShineBorder?.enabled && /* @__PURE__ */ u3(
1917
+ "div",
1918
+ {
1919
+ class: "launcher-shine-border",
1920
+ style: {
1921
+ "--shine-duration": `${config.launcherShineBorder.duration || 14}s`,
1922
+ "--shine-border-width": `${config.launcherShineBorder.borderWidth || 1}px`,
1923
+ backgroundImage: `radial-gradient(transparent, transparent, ${Array.isArray(config.launcherShineBorder.color) ? config.launcherShineBorder.color.join(",") : config.launcherShineBorder.color || "rgba(255,255,255,0.5)"}, transparent, transparent)`
1924
+ }
1925
+ }
1926
+ ),
1878
1927
  /* @__PURE__ */ u3(
1879
1928
  "button",
1880
1929
  {
@@ -1888,8 +1937,8 @@ var KenobiLib = (() => {
1888
1937
  children: /* @__PURE__ */ u3(XMarkIcon, {})
1889
1938
  }
1890
1939
  ),
1891
- /* @__PURE__ */ u3("div", { class: "launcher-logo", children: /* @__PURE__ */ u3(LogoIcon, {}) }),
1892
- config.textOverrides?.launcherLabel || (hasHadSuccess ? "Personalize again" : "Personalize"),
1940
+ config.showLauncherLogo !== false && /* @__PURE__ */ u3("div", { class: "launcher-logo", children: /* @__PURE__ */ u3(LogoIcon, {}) }),
1941
+ hasHadSuccess ? config.textOverrides?.launcherLabelSuccess || config.textOverrides?.launcherLabel || "Personalize again" : config.textOverrides?.launcherLabel || "Personalize",
1893
1942
  config.enableUndoToggle && hasHadSuccess && /* @__PURE__ */ u3(
1894
1943
  "button",
1895
1944
  {
@@ -1954,6 +2003,7 @@ var KenobiLib = (() => {
1954
2003
  applyHostStyles() {
1955
2004
  const isInline = this.config.mountMode === "inline";
1956
2005
  this.host.classList.toggle("kb-inline", isInline);
2006
+ const focusBlur = this.config.focusBlurIntensity ?? "10px";
1957
2007
  if (isInline) {
1958
2008
  this.host.style.cssText = `
1959
2009
  position: relative !important;
@@ -1965,6 +2015,7 @@ var KenobiLib = (() => {
1965
2015
  pointer-events: auto !important;
1966
2016
  isolation: auto !important;
1967
2017
  display: block !important;
2018
+ --kb-focus-blur: ${focusBlur};
1968
2019
  `;
1969
2020
  return;
1970
2021
  }
@@ -1977,6 +2028,7 @@ var KenobiLib = (() => {
1977
2028
  height: 0 !important;
1978
2029
  pointer-events: none !important;
1979
2030
  isolation: isolate !important;
2031
+ --kb-focus-blur: ${focusBlur};
1980
2032
  `;
1981
2033
  }
1982
2034
  mount(target) {
@@ -3200,6 +3252,9 @@ var KenobiLib = (() => {
3200
3252
  isPersonalized: this.isPersonalized,
3201
3253
  onDismiss: /* @__PURE__ */ __name(() => {
3202
3254
  this.log("debug", "CueCard dismissed by user");
3255
+ this.dispatchKenobiEvent("cuecard:dismiss", {
3256
+ pagePath: this.currentPath
3257
+ });
3203
3258
  }, "onDismiss"),
3204
3259
  onSubmitPersonalization: /* @__PURE__ */ __name((values) => {
3205
3260
  this.log("debug", "CueCard submitted:", values);
@@ -3207,10 +3262,18 @@ var KenobiLib = (() => {
3207
3262
  }, "onSubmitPersonalization"),
3208
3263
  onOpenChange: /* @__PURE__ */ __name((isOpen) => {
3209
3264
  this.log("debug", "CueCard open state changed:", isOpen);
3265
+ this.dispatchKenobiEvent("cuecard:openchange", {
3266
+ isOpen,
3267
+ pagePath: this.currentPath
3268
+ });
3210
3269
  }, "onOpenChange"),
3211
3270
  onTogglePersonalization: /* @__PURE__ */ __name(() => {
3212
3271
  this.log("debug", "CueCard toggle personalization");
3213
3272
  void this.toggleTransformations();
3273
+ this.dispatchKenobiEvent("cuecard:toggle", {
3274
+ isPersonalized: this.isPersonalized,
3275
+ pagePath: this.currentPath
3276
+ });
3214
3277
  }, "onTogglePersonalization")
3215
3278
  });
3216
3279
  this.cueCardInstance.mount();
@@ -3230,10 +3293,27 @@ var KenobiLib = (() => {
3230
3293
  }
3231
3294
  void this.initCueCard();
3232
3295
  }, "syncCueCardVisibility"));
3296
+ /**
3297
+ * Dispatches a custom event on window for external listeners.
3298
+ * Events are prefixed with "kenobi:" for namespacing.
3299
+ */
3300
+ __publicField(this, "dispatchKenobiEvent", /* @__PURE__ */ __name((eventName, detail) => {
3301
+ const event = new CustomEvent(`kenobi:${eventName}`, {
3302
+ detail,
3303
+ bubbles: true
3304
+ });
3305
+ window.dispatchEvent(event);
3306
+ this.log("debug", `Dispatched event: kenobi:${eventName}`, detail);
3307
+ }, "dispatchKenobiEvent"));
3233
3308
  /**
3234
3309
  * Triggers personalization by calling the API with the provided input.
3235
3310
  * Updates CueCard status during the flow and applies transformations.
3236
3311
  *
3312
+ * Dispatches events:
3313
+ * - `kenobi:personalization:start` - when personalization begins
3314
+ * - `kenobi:personalization:complete` - when personalization succeeds
3315
+ * - `kenobi:personalization:error` - when personalization fails
3316
+ *
3237
3317
  * @param input - User-provided fields (e.g., { companyDomain: "acme.com" })
3238
3318
  */
3239
3319
  __publicField(this, "personalize", /* @__PURE__ */ __name(async (input) => {
@@ -3243,6 +3323,10 @@ var KenobiLib = (() => {
3243
3323
  }
3244
3324
  const startTime = /* @__PURE__ */ new Date();
3245
3325
  this.log("debug", "Starting personalization with input:", input);
3326
+ this.dispatchKenobiEvent("personalization:start", {
3327
+ input,
3328
+ pagePath: this.currentPath
3329
+ });
3246
3330
  if (this.cueCardInstance) {
3247
3331
  this.cueCardInstance.update({ status: "starting", progressPct: 10 });
3248
3332
  }
@@ -3284,11 +3368,23 @@ var KenobiLib = (() => {
3284
3368
  "debug",
3285
3369
  `Personalization complete, took ${this.formatThousands(duration)} ms`
3286
3370
  );
3371
+ this.dispatchKenobiEvent("personalization:complete", {
3372
+ input,
3373
+ pagePath: this.currentPath,
3374
+ durationMs: duration,
3375
+ transformationsCount: result.transformations?.length ?? 0,
3376
+ metadata: result.metadata
3377
+ });
3287
3378
  } catch (error) {
3288
3379
  this.log("error", "Personalization failed:", error);
3289
3380
  if (this.cueCardInstance) {
3290
3381
  this.cueCardInstance.update({ status: "error", progressPct: 0 });
3291
3382
  }
3383
+ this.dispatchKenobiEvent("personalization:error", {
3384
+ input,
3385
+ pagePath: this.currentPath,
3386
+ error: error instanceof Error ? error.message : String(error)
3387
+ });
3292
3388
  }
3293
3389
  }, "personalize"));
3294
3390
  /**
@@ -3325,7 +3421,7 @@ var KenobiLib = (() => {
3325
3421
  this.log("debug", "Auto-transform is requested... Starting...");
3326
3422
  void this.startAutoTransform();
3327
3423
  }
3328
- if (this.config.publicKey) {
3424
+ if (this.config.publicKey && !this.config.skipCueCardAutoMount) {
3329
3425
  this.log("debug", "Public key provided, checking for active template...");
3330
3426
  void this.initCueCard();
3331
3427
  }