kenobi-js 0.1.28 → 0.1.29
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/dist/kenobi.js +274 -14
- package/dist/kenobi.js.map +3 -3
- package/dist/kenobi.min.js +34 -11
- package/package.json +1 -1
package/dist/kenobi.js
CHANGED
|
@@ -1128,9 +1128,9 @@ var KenobiLib = (() => {
|
|
|
1128
1128
|
}
|
|
1129
1129
|
), "LogoIcon");
|
|
1130
1130
|
var STYLES = `
|
|
1131
|
-
: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-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); }
|
|
1132
|
-
.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-kbd-bg: #f1f5f9; --kb-kbd-border: #e2e8f0; --kb-kbd-text: #64748b; --kb-watermark-text: #94a3b8; }
|
|
1133
|
-
.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-kbd-bg: #1e293b; --kb-kbd-border: #334155; --kb-kbd-text: #94a3b8; --kb-watermark-text: #64748b; }
|
|
1131
|
+
: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); }
|
|
1132
|
+
.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; }
|
|
1133
|
+
.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; }
|
|
1134
1134
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
1135
1135
|
#cue-card-root { position: fixed; z-index: 2147483647; pointer-events: none; width: 100%; height: 0; top: 0; left: 0; isolation: isolate; }
|
|
1136
1136
|
.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); }
|
|
@@ -1176,6 +1176,9 @@ var KenobiLib = (() => {
|
|
|
1176
1176
|
.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; }
|
|
1177
1177
|
.form-input::placeholder { color: var(--kb-input-placeholder); }
|
|
1178
1178
|
.form-input:focus { border-color: var(--kb-progress-indicator); }
|
|
1179
|
+
.form-input.error { border-color: var(--kb-error-text); }
|
|
1180
|
+
.form-label.error { color: var(--kb-error-text); }
|
|
1181
|
+
.form-message { color: var(--kb-error-text); font-size: 0.75rem; margin-top: 0.25rem; font-weight: 500; }
|
|
1179
1182
|
.btn-submit { background-color: var(--kb-btn-trigger-bg); color: var(--kb-btn-trigger-text); padding: 0.5rem 1rem; display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; }
|
|
1180
1183
|
.btn-submit:disabled { opacity: 0.7; cursor: not-allowed; }
|
|
1181
1184
|
.kbd-hint { display: flex; align-items: center; gap: 0.5rem; position: absolute; top: calc(100% + 0.5rem); left: 50%; transform: translateX(-50%); opacity: 0; pointer-events: none; transition: opacity 0.2s ease; white-space: nowrap; }
|
|
@@ -1288,6 +1291,7 @@ var KenobiLib = (() => {
|
|
|
1288
1291
|
const timerRafRef = A2(null);
|
|
1289
1292
|
const hasTimerCompletedRef = A2(false);
|
|
1290
1293
|
const [isHovering, setIsHovering] = d2(false);
|
|
1294
|
+
const [errors, setErrors] = d2({});
|
|
1291
1295
|
const [timerProgress, setTimerProgressState] = d2(0);
|
|
1292
1296
|
const timerProgressRef = A2(0);
|
|
1293
1297
|
const timerEnabled = config.enableTimer !== false;
|
|
@@ -1508,17 +1512,81 @@ var KenobiLib = (() => {
|
|
|
1508
1512
|
}
|
|
1509
1513
|
return txt.btnResting || "Show me";
|
|
1510
1514
|
})();
|
|
1515
|
+
const validateField = /* @__PURE__ */ __name((name, value, fieldConfig) => {
|
|
1516
|
+
if (!fieldConfig) return null;
|
|
1517
|
+
if (fieldConfig.required && !value.trim()) {
|
|
1518
|
+
return fieldConfig.errorMessage || `${fieldConfig.label} is required`;
|
|
1519
|
+
}
|
|
1520
|
+
if (!value) return null;
|
|
1521
|
+
if (fieldConfig.type === "email") {
|
|
1522
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1523
|
+
if (!emailRegex.test(value)) {
|
|
1524
|
+
return fieldConfig.errorMessage || "Please enter a valid email address";
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
if (fieldConfig.type === "url") {
|
|
1528
|
+
try {
|
|
1529
|
+
new URL(value);
|
|
1530
|
+
} catch {
|
|
1531
|
+
return fieldConfig.errorMessage || "Please enter a valid URL (e.g., https://example.com)";
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
if (fieldConfig.minLength && value.length < fieldConfig.minLength) {
|
|
1535
|
+
return fieldConfig.errorMessage || `Must be at least ${fieldConfig.minLength} characters`;
|
|
1536
|
+
}
|
|
1537
|
+
if (fieldConfig.maxLength && value.length > fieldConfig.maxLength) {
|
|
1538
|
+
return fieldConfig.errorMessage || `Must be at most ${fieldConfig.maxLength} characters`;
|
|
1539
|
+
}
|
|
1540
|
+
if (fieldConfig.pattern) {
|
|
1541
|
+
const regex = new RegExp(fieldConfig.pattern);
|
|
1542
|
+
if (!regex.test(value)) {
|
|
1543
|
+
return fieldConfig.errorMessage || "Invalid format";
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
return null;
|
|
1547
|
+
}, "validateField");
|
|
1511
1548
|
const handleSubmit = /* @__PURE__ */ __name((e3) => {
|
|
1512
1549
|
e3.preventDefault();
|
|
1513
1550
|
if (isPending) return;
|
|
1514
1551
|
const formData = new FormData(e3.target);
|
|
1515
1552
|
const values = {};
|
|
1553
|
+
const newErrors = {};
|
|
1554
|
+
let hasErrors = false;
|
|
1516
1555
|
formData.forEach((value, key) => {
|
|
1517
|
-
|
|
1556
|
+
const strValue = value.toString();
|
|
1557
|
+
values[key] = strValue;
|
|
1558
|
+
const fieldConfig = config.fields.find((f4) => f4.name === key);
|
|
1559
|
+
const error = validateField(key, strValue, fieldConfig);
|
|
1560
|
+
if (error) {
|
|
1561
|
+
newErrors[key] = error;
|
|
1562
|
+
hasErrors = true;
|
|
1563
|
+
}
|
|
1518
1564
|
});
|
|
1565
|
+
if (hasErrors) {
|
|
1566
|
+
setErrors(newErrors);
|
|
1567
|
+
return;
|
|
1568
|
+
}
|
|
1569
|
+
setErrors({});
|
|
1519
1570
|
setIsOpen(false);
|
|
1520
1571
|
config.onSubmitPersonalization?.(values);
|
|
1521
1572
|
}, "handleSubmit");
|
|
1573
|
+
const handleInput = /* @__PURE__ */ __name((e3) => {
|
|
1574
|
+
const target = e3.target;
|
|
1575
|
+
const name = target.name;
|
|
1576
|
+
if (errors[name]) {
|
|
1577
|
+
const fieldConfig = config.fields.find((f4) => f4.name === name);
|
|
1578
|
+
const error = validateField(name, target.value, fieldConfig);
|
|
1579
|
+
setErrors((prev) => {
|
|
1580
|
+
const next = { ...prev };
|
|
1581
|
+
if (error) {
|
|
1582
|
+
next[name] = error;
|
|
1583
|
+
} else {
|
|
1584
|
+
delete next[name];
|
|
1585
|
+
}
|
|
1586
|
+
return next;
|
|
1587
|
+
});
|
|
1588
|
+
}
|
|
1589
|
+
}, "handleInput");
|
|
1522
1590
|
const togglePopover = /* @__PURE__ */ __name((e3) => {
|
|
1523
1591
|
e3.stopPropagation();
|
|
1524
1592
|
if (isPending || isSuccess) return;
|
|
@@ -1659,17 +1727,24 @@ var KenobiLib = (() => {
|
|
|
1659
1727
|
children: [
|
|
1660
1728
|
/* @__PURE__ */ u3("form", { onSubmit: handleSubmit, ref: formRef, children: [
|
|
1661
1729
|
config.fields.map((field, idx) => /* @__PURE__ */ u3("div", { class: "form-group", children: [
|
|
1662
|
-
/* @__PURE__ */ u3(
|
|
1730
|
+
/* @__PURE__ */ u3(
|
|
1731
|
+
"label",
|
|
1732
|
+
{
|
|
1733
|
+
class: `form-label ${errors[field.name] ? "error" : ""}`,
|
|
1734
|
+
children: field.label
|
|
1735
|
+
}
|
|
1736
|
+
),
|
|
1663
1737
|
/* @__PURE__ */ u3("div", { class: "input-row", children: [
|
|
1664
1738
|
/* @__PURE__ */ u3(
|
|
1665
1739
|
"input",
|
|
1666
1740
|
{
|
|
1667
1741
|
ref: idx === 0 ? firstInputRef : void 0,
|
|
1668
|
-
class:
|
|
1742
|
+
class: `form-input ${errors[field.name] ? "error" : ""}`,
|
|
1669
1743
|
name: field.name,
|
|
1670
1744
|
type: field.type || "text",
|
|
1671
1745
|
placeholder: field.placeholder,
|
|
1672
|
-
required: field.required
|
|
1746
|
+
required: field.required,
|
|
1747
|
+
onInput: handleInput
|
|
1673
1748
|
}
|
|
1674
1749
|
),
|
|
1675
1750
|
config.fields.length === 1 && /* @__PURE__ */ u3(
|
|
@@ -1681,7 +1756,8 @@ var KenobiLib = (() => {
|
|
|
1681
1756
|
children: isPending ? /* @__PURE__ */ u3(LoaderIcon, {}) : /* @__PURE__ */ u3(ArrowRightIcon, {})
|
|
1682
1757
|
}
|
|
1683
1758
|
)
|
|
1684
|
-
] })
|
|
1759
|
+
] }),
|
|
1760
|
+
errors[field.name] && /* @__PURE__ */ u3("div", { class: "form-message", children: errors[field.name] })
|
|
1685
1761
|
] }, field.name)),
|
|
1686
1762
|
config.fields.length > 1 && /* @__PURE__ */ u3(
|
|
1687
1763
|
"button",
|
|
@@ -1844,6 +1920,10 @@ var KenobiLib = (() => {
|
|
|
1844
1920
|
setTheme(theme) {
|
|
1845
1921
|
this.update({ theme });
|
|
1846
1922
|
}
|
|
1923
|
+
openForm() {
|
|
1924
|
+
this.isOpen = true;
|
|
1925
|
+
this.render();
|
|
1926
|
+
}
|
|
1847
1927
|
render() {
|
|
1848
1928
|
const mountPoint = this.shadow.lastElementChild;
|
|
1849
1929
|
G(
|
|
@@ -1875,7 +1955,9 @@ var KenobiLib = (() => {
|
|
|
1875
1955
|
durationMs: 300,
|
|
1876
1956
|
delayMs: 0,
|
|
1877
1957
|
easing: "ease",
|
|
1878
|
-
animateSize: true
|
|
1958
|
+
animateSize: true,
|
|
1959
|
+
overflow: "hidden"
|
|
1960
|
+
// Default to hidden for clean size animations; use "visible" for gradient text
|
|
1879
1961
|
};
|
|
1880
1962
|
var createNormalizedTransitionConfig = /* @__PURE__ */ __name((config) => ({
|
|
1881
1963
|
enabled: config?.enabled ?? DEFAULT_TRANSITION_CONFIG.enabled,
|
|
@@ -1883,6 +1965,7 @@ var KenobiLib = (() => {
|
|
|
1883
1965
|
delayMs: config?.delayMs ?? DEFAULT_TRANSITION_CONFIG.delayMs,
|
|
1884
1966
|
easing: config?.easing ?? DEFAULT_TRANSITION_CONFIG.easing,
|
|
1885
1967
|
animateSize: config?.animateSize ?? DEFAULT_TRANSITION_CONFIG.animateSize,
|
|
1968
|
+
overflow: config?.overflow ?? DEFAULT_TRANSITION_CONFIG.overflow,
|
|
1886
1969
|
textAnimation: config?.textAnimation,
|
|
1887
1970
|
enter: config?.enter,
|
|
1888
1971
|
exit: config?.exit
|
|
@@ -1893,6 +1976,7 @@ var KenobiLib = (() => {
|
|
|
1893
1976
|
delayMs: override?.delayMs ?? base.delayMs,
|
|
1894
1977
|
easing: override?.easing ?? base.easing,
|
|
1895
1978
|
animateSize: override?.animateSize ?? base.animateSize,
|
|
1979
|
+
overflow: override?.overflow ?? base.overflow,
|
|
1896
1980
|
textAnimation: override?.textAnimation ?? base.textAnimation,
|
|
1897
1981
|
enter: override?.enter ?? base.enter,
|
|
1898
1982
|
exit: override?.exit ?? base.exit
|
|
@@ -1905,6 +1989,7 @@ var KenobiLib = (() => {
|
|
|
1905
1989
|
return false;
|
|
1906
1990
|
}, "isAnimatableElement");
|
|
1907
1991
|
var isEasing = /* @__PURE__ */ __name((value) => typeof value === "string", "isEasing");
|
|
1992
|
+
var isTransitionOverflow = /* @__PURE__ */ __name((value) => value === "hidden" || value === "visible" || value === "clip", "isTransitionOverflow");
|
|
1908
1993
|
var isAnimationSplitTarget = /* @__PURE__ */ __name((value) => value === "line" || value === "word" || value === "character", "isAnimationSplitTarget");
|
|
1909
1994
|
var isKeyframeDefinition = /* @__PURE__ */ __name((value) => {
|
|
1910
1995
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -1934,11 +2019,12 @@ var KenobiLib = (() => {
|
|
|
1934
2019
|
delayMs,
|
|
1935
2020
|
easing,
|
|
1936
2021
|
animateSize,
|
|
2022
|
+
overflow,
|
|
1937
2023
|
textAnimation,
|
|
1938
2024
|
enter,
|
|
1939
2025
|
exit
|
|
1940
2026
|
} = candidate;
|
|
1941
|
-
return (enabled === void 0 || typeof enabled === "boolean") && (durationMs === void 0 || typeof durationMs === "number") && (delayMs === void 0 || typeof delayMs === "number") && (easing === void 0 || isEasing(easing)) && (animateSize === void 0 || typeof animateSize === "boolean") && (textAnimation === void 0 || isTextAnimationConfig(textAnimation)) && (enter === void 0 || isAnimationSettings(enter)) && (exit === void 0 || isAnimationSettings(exit));
|
|
2027
|
+
return (enabled === void 0 || typeof enabled === "boolean") && (durationMs === void 0 || typeof durationMs === "number") && (delayMs === void 0 || typeof delayMs === "number") && (easing === void 0 || isEasing(easing)) && (animateSize === void 0 || typeof animateSize === "boolean") && (overflow === void 0 || isTransitionOverflow(overflow)) && (textAnimation === void 0 || isTextAnimationConfig(textAnimation)) && (enter === void 0 || isAnimationSettings(enter)) && (exit === void 0 || isAnimationSettings(exit));
|
|
1942
2028
|
}, "isTransitionConfig");
|
|
1943
2029
|
var _TransitionOrchestrator = class _TransitionOrchestrator {
|
|
1944
2030
|
constructor() {
|
|
@@ -1959,7 +2045,7 @@ var KenobiLib = (() => {
|
|
|
1959
2045
|
__publicField(this, "replaceWithTransition", /* @__PURE__ */ __name(async (oldElement, newMarkup, config) => {
|
|
1960
2046
|
const wrapper = document.createElement("div");
|
|
1961
2047
|
wrapper.style.position = "relative";
|
|
1962
|
-
wrapper.style.overflow =
|
|
2048
|
+
wrapper.style.overflow = config.overflow;
|
|
1963
2049
|
const oldRect = oldElement.getBoundingClientRect();
|
|
1964
2050
|
const oldStyle = window.getComputedStyle(oldElement);
|
|
1965
2051
|
wrapper.style.display = oldStyle.display;
|
|
@@ -2147,17 +2233,70 @@ var KenobiLib = (() => {
|
|
|
2147
2233
|
if (text.trim().length === 0) {
|
|
2148
2234
|
return currentDelay;
|
|
2149
2235
|
}
|
|
2236
|
+
if (config.by === "character") {
|
|
2237
|
+
const words = text.split(/(\s+)/);
|
|
2238
|
+
const fragment2 = document.createDocumentFragment();
|
|
2239
|
+
let delay2 = currentDelay;
|
|
2240
|
+
words.forEach((word) => {
|
|
2241
|
+
if (word.length === 0) return;
|
|
2242
|
+
if (word.trim().length === 0) {
|
|
2243
|
+
fragment2.appendChild(document.createTextNode(word));
|
|
2244
|
+
return;
|
|
2245
|
+
}
|
|
2246
|
+
const wordWrapper = document.createElement("span");
|
|
2247
|
+
wordWrapper.style.display = "inline-block";
|
|
2248
|
+
wordWrapper.style.whiteSpace = "nowrap";
|
|
2249
|
+
if (isBackgroundClippedToText2) {
|
|
2250
|
+
wordWrapper.style.setProperty("background", "inherit");
|
|
2251
|
+
wordWrapper.style.setProperty("-webkit-background-clip", "text");
|
|
2252
|
+
wordWrapper.style.setProperty("background-clip", "text");
|
|
2253
|
+
wordWrapper.style.setProperty("color", "transparent");
|
|
2254
|
+
}
|
|
2255
|
+
const chars = word.split("");
|
|
2256
|
+
chars.forEach((char) => {
|
|
2257
|
+
const span = document.createElement("span");
|
|
2258
|
+
span.textContent = char;
|
|
2259
|
+
span.style.display = "inline-block";
|
|
2260
|
+
span.style.opacity = "0";
|
|
2261
|
+
if (isBackgroundClippedToText2) {
|
|
2262
|
+
span.style.setProperty("background", "inherit");
|
|
2263
|
+
span.style.setProperty("-webkit-background-clip", "text");
|
|
2264
|
+
span.style.setProperty("background-clip", "text");
|
|
2265
|
+
span.style.setProperty("color", "transparent");
|
|
2266
|
+
span.style.paddingBottom = "0.1em";
|
|
2267
|
+
span.style.marginBottom = "-0.1em";
|
|
2268
|
+
}
|
|
2269
|
+
const keyframes = this.resolveKeyframes(config.keyframes);
|
|
2270
|
+
const duration = config.durationMs ?? transitionConfig.durationMs ?? 300;
|
|
2271
|
+
const easing = transitionConfig.easing ?? "ease";
|
|
2272
|
+
const animation = span.animate(keyframes, {
|
|
2273
|
+
duration,
|
|
2274
|
+
easing,
|
|
2275
|
+
delay: delay2,
|
|
2276
|
+
fill: "forwards"
|
|
2277
|
+
});
|
|
2278
|
+
animation.addEventListener("finish", () => {
|
|
2279
|
+
animation.commitStyles();
|
|
2280
|
+
animation.cancel();
|
|
2281
|
+
});
|
|
2282
|
+
wordWrapper.appendChild(span);
|
|
2283
|
+
delay2 += config.staggerMs ?? 50;
|
|
2284
|
+
});
|
|
2285
|
+
fragment2.appendChild(wordWrapper);
|
|
2286
|
+
});
|
|
2287
|
+
node.parentNode?.replaceChild(fragment2, node);
|
|
2288
|
+
return delay2;
|
|
2289
|
+
}
|
|
2150
2290
|
let segments;
|
|
2151
2291
|
switch (config.by) {
|
|
2152
|
-
case "character":
|
|
2153
|
-
segments = text.split("");
|
|
2154
|
-
break;
|
|
2155
2292
|
case "word":
|
|
2156
2293
|
segments = text.split(/(\s+)/);
|
|
2157
2294
|
break;
|
|
2158
2295
|
case "line":
|
|
2159
2296
|
segments = text.split("\n");
|
|
2160
2297
|
break;
|
|
2298
|
+
default:
|
|
2299
|
+
segments = text.split("");
|
|
2161
2300
|
}
|
|
2162
2301
|
const fragment = document.createDocumentFragment();
|
|
2163
2302
|
let delay = currentDelay;
|
|
@@ -2244,6 +2383,7 @@ var KenobiLib = (() => {
|
|
|
2244
2383
|
__publicField(this, "changeStack", /* @__PURE__ */ new Map());
|
|
2245
2384
|
__publicField(this, "visitorKey", null);
|
|
2246
2385
|
__publicField(this, "orchestrator");
|
|
2386
|
+
__publicField(this, "cueCardInstance", null);
|
|
2247
2387
|
//
|
|
2248
2388
|
__publicField(this, "currentPath");
|
|
2249
2389
|
__publicField(this, "currentUrl");
|
|
@@ -2831,6 +2971,122 @@ var KenobiLib = (() => {
|
|
|
2831
2971
|
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
2832
2972
|
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
2833
2973
|
}, "setInputValue"));
|
|
2974
|
+
/*
|
|
2975
|
+
----
|
|
2976
|
+
-- CUE CARD AUTO-MOUNT & PERSONALIZATION
|
|
2977
|
+
----
|
|
2978
|
+
*/
|
|
2979
|
+
/**
|
|
2980
|
+
* Initializes and mounts a CueCard with default configuration.
|
|
2981
|
+
* Called automatically when publishableKey is provided.
|
|
2982
|
+
*
|
|
2983
|
+
* Default config matches the template editor settings.
|
|
2984
|
+
* Future: This config will be fetched per-org from the database.
|
|
2985
|
+
*/
|
|
2986
|
+
__publicField(this, "initCueCard", /* @__PURE__ */ __name(() => {
|
|
2987
|
+
if (this.cueCardInstance) {
|
|
2988
|
+
this.log("warn", "CueCard already initialized, skipping...");
|
|
2989
|
+
return;
|
|
2990
|
+
}
|
|
2991
|
+
this.cueCardInstance = new CueCard({
|
|
2992
|
+
theme: "light",
|
|
2993
|
+
position: "top-center",
|
|
2994
|
+
fields: [
|
|
2995
|
+
{
|
|
2996
|
+
name: "companyDomain",
|
|
2997
|
+
label: "Company Name or Domain",
|
|
2998
|
+
placeholder: "example.com",
|
|
2999
|
+
required: true,
|
|
3000
|
+
minLength: 3,
|
|
3001
|
+
errorMessage: "Company name or domain is required"
|
|
3002
|
+
}
|
|
3003
|
+
],
|
|
3004
|
+
hasPersonalization: true,
|
|
3005
|
+
isVisible: true,
|
|
3006
|
+
enableFocusMode: true,
|
|
3007
|
+
showKeyboardHints: true,
|
|
3008
|
+
focusBlurIntensity: "8px",
|
|
3009
|
+
focusDelayMs: 2e3,
|
|
3010
|
+
enableLauncher: true,
|
|
3011
|
+
onSubmitPersonalization: /* @__PURE__ */ __name((values) => {
|
|
3012
|
+
this.log("debug", "CueCard submitted:", values);
|
|
3013
|
+
void this.personalize(values);
|
|
3014
|
+
}, "onSubmitPersonalization"),
|
|
3015
|
+
onOpenChange: /* @__PURE__ */ __name((isOpen) => {
|
|
3016
|
+
this.log("debug", "CueCard open state changed:", isOpen);
|
|
3017
|
+
}, "onOpenChange")
|
|
3018
|
+
});
|
|
3019
|
+
this.cueCardInstance.mount();
|
|
3020
|
+
this.log("debug", "CueCard mounted successfully");
|
|
3021
|
+
}, "initCueCard"));
|
|
3022
|
+
/**
|
|
3023
|
+
* Triggers personalization by calling the API with the provided input.
|
|
3024
|
+
* Updates CueCard status during the flow and applies transformations.
|
|
3025
|
+
*
|
|
3026
|
+
* @param input - User-provided fields (e.g., { companyDomain: "acme.com" })
|
|
3027
|
+
*/
|
|
3028
|
+
__publicField(this, "personalize", /* @__PURE__ */ __name(async (input) => {
|
|
3029
|
+
if (!this.config.publishableKey) {
|
|
3030
|
+
this.log("error", "Cannot personalize: publishableKey not configured");
|
|
3031
|
+
return;
|
|
3032
|
+
}
|
|
3033
|
+
const startTime = /* @__PURE__ */ new Date();
|
|
3034
|
+
this.log("debug", "Starting personalization with input:", input);
|
|
3035
|
+
if (this.cueCardInstance) {
|
|
3036
|
+
this.cueCardInstance.update({ status: "starting", progressPct: 10 });
|
|
3037
|
+
}
|
|
3038
|
+
try {
|
|
3039
|
+
const response = await fetch(`${this.config.apiHost}/v1/personalize`, {
|
|
3040
|
+
method: "POST",
|
|
3041
|
+
headers: {
|
|
3042
|
+
"Content-Type": "application/json"
|
|
3043
|
+
},
|
|
3044
|
+
body: JSON.stringify({
|
|
3045
|
+
publishableKey: this.config.publishableKey,
|
|
3046
|
+
input,
|
|
3047
|
+
pagePath: this.currentPath
|
|
3048
|
+
})
|
|
3049
|
+
});
|
|
3050
|
+
if (this.cueCardInstance) {
|
|
3051
|
+
this.cueCardInstance.update({ progressPct: 50 });
|
|
3052
|
+
}
|
|
3053
|
+
if (!response.ok) {
|
|
3054
|
+
const errorBody = await response.json().catch(() => ({}));
|
|
3055
|
+
throw new Error(errorBody.error || `API error: ${response.status}`);
|
|
3056
|
+
}
|
|
3057
|
+
const result = await response.json();
|
|
3058
|
+
this.log("debug", "Personalization API response:", result);
|
|
3059
|
+
if (this.cueCardInstance) {
|
|
3060
|
+
this.cueCardInstance.update({ progressPct: 80 });
|
|
3061
|
+
}
|
|
3062
|
+
if (result.transformations && Array.isArray(result.transformations)) {
|
|
3063
|
+
await this.applyTransformations(result.transformations, {
|
|
3064
|
+
shouldConsolidate: true
|
|
3065
|
+
});
|
|
3066
|
+
}
|
|
3067
|
+
if (this.cueCardInstance) {
|
|
3068
|
+
this.cueCardInstance.update({ status: "success", progressPct: 100 });
|
|
3069
|
+
}
|
|
3070
|
+
const endTime = /* @__PURE__ */ new Date();
|
|
3071
|
+
const duration = this.getDurationInMilliseconds(startTime, endTime);
|
|
3072
|
+
this.log(
|
|
3073
|
+
"debug",
|
|
3074
|
+
`Personalization complete, took ${this.formatThousands(duration)} ms`
|
|
3075
|
+
);
|
|
3076
|
+
} catch (error) {
|
|
3077
|
+
this.log("error", "Personalization failed:", error);
|
|
3078
|
+
if (this.cueCardInstance) {
|
|
3079
|
+
this.cueCardInstance.update({ status: "error", progressPct: 0 });
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
}, "personalize"));
|
|
3083
|
+
/**
|
|
3084
|
+
* Returns the CueCard instance if one was auto-mounted.
|
|
3085
|
+
* Useful for external control of the CueCard state.
|
|
3086
|
+
*/
|
|
3087
|
+
__publicField(this, "getCueCard", /* @__PURE__ */ __name(() => {
|
|
3088
|
+
return this.cueCardInstance;
|
|
3089
|
+
}, "getCueCard"));
|
|
2834
3090
|
this.config = {
|
|
2835
3091
|
apiHost: "https://kenobi.ai/api",
|
|
2836
3092
|
debug: false,
|
|
@@ -2858,6 +3114,10 @@ var KenobiLib = (() => {
|
|
|
2858
3114
|
this.log("debug", "Auto-transform is requested... Starting...");
|
|
2859
3115
|
void this.startAutoTransform();
|
|
2860
3116
|
}
|
|
3117
|
+
if (this.config.publishableKey) {
|
|
3118
|
+
this.log("debug", "PublishableKey provided, auto-mounting CueCard...");
|
|
3119
|
+
this.initCueCard();
|
|
3120
|
+
}
|
|
2861
3121
|
}
|
|
2862
3122
|
};
|
|
2863
3123
|
__name(_Kenobi, "Kenobi");
|