@returningai/widget-sdk 1.7.0 → 1.7.2
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/CHANGELOG.md +26 -0
- package/README.md +6 -2
- package/dist/rai-banner.iife.js +1 -1
- package/dist/rai-banner.js +40 -30
- package/dist/rai-widget.iife.js +2 -2
- package/dist/rai-widget.js +162 -54
- package/dist/types/BaseWidget.d.ts +1 -0
- package/dist/types/banner/color.d.ts +3 -0
- package/dist/types/banner/render.d.ts +3 -1
- package/dist/types/core/auto-theme-lease.d.ts +5 -0
- package/dist/types/core/bundle-runtime-cache.d.ts +20 -0
- package/package.json +7 -2
package/dist/rai-widget.js
CHANGED
|
@@ -11741,9 +11741,10 @@ function sanitizeBannerHtml(html2) {
|
|
|
11741
11741
|
ALLOW_DATA_ATTR: false
|
|
11742
11742
|
});
|
|
11743
11743
|
}
|
|
11744
|
-
function resolveCssToken(token) {
|
|
11744
|
+
function resolveCssToken(token, preferredScope) {
|
|
11745
11745
|
const normalizedToken = token.startsWith("--") ? token : `--${token}`;
|
|
11746
11746
|
const candidates = [
|
|
11747
|
+
preferredScope,
|
|
11747
11748
|
document.documentElement,
|
|
11748
11749
|
document.body,
|
|
11749
11750
|
...Array.from(
|
|
@@ -11763,32 +11764,33 @@ function resolveCssToken(token) {
|
|
|
11763
11764
|
)
|
|
11764
11765
|
)
|
|
11765
11766
|
].filter(Boolean);
|
|
11767
|
+
const checked = /* @__PURE__ */ new Set();
|
|
11766
11768
|
for (const node of candidates) {
|
|
11769
|
+
if (checked.has(node)) continue;
|
|
11770
|
+
checked.add(node);
|
|
11767
11771
|
const value = getComputedStyle(node).getPropertyValue(normalizedToken).trim();
|
|
11768
11772
|
if (value) return value;
|
|
11769
11773
|
}
|
|
11770
11774
|
for (const node of Array.from(document.querySelectorAll("*"))) {
|
|
11775
|
+
if (checked.has(node)) continue;
|
|
11771
11776
|
const value = getComputedStyle(node).getPropertyValue(normalizedToken).trim();
|
|
11772
11777
|
if (value) return value;
|
|
11773
11778
|
}
|
|
11774
11779
|
return void 0;
|
|
11775
11780
|
}
|
|
11776
|
-
|
|
11781
|
+
function safeColor(v, preferredScope) {
|
|
11777
11782
|
if (!v) return void 0;
|
|
11778
11783
|
const value = v.trim();
|
|
11779
11784
|
if (/^(#|rgb|hsl)/i.test(value)) return value;
|
|
11780
11785
|
if (/^(--)?[a-z0-9-]+$/i.test(value)) {
|
|
11781
|
-
|
|
11782
|
-
return resolved;
|
|
11786
|
+
return resolveCssToken(value, preferredScope);
|
|
11783
11787
|
}
|
|
11784
11788
|
const varMatch = value.match(/^var\((--[a-z0-9-]+)\)$/i);
|
|
11785
11789
|
if (varMatch) {
|
|
11786
|
-
|
|
11787
|
-
const resolved = resolveCssToken(token);
|
|
11788
|
-
return resolved;
|
|
11790
|
+
return resolveCssToken(varMatch[1], preferredScope);
|
|
11789
11791
|
}
|
|
11790
11792
|
return void 0;
|
|
11791
|
-
}
|
|
11793
|
+
}
|
|
11792
11794
|
function el(tag, styles, attrs) {
|
|
11793
11795
|
const node = document.createElement(tag);
|
|
11794
11796
|
Object.assign(node.style, styles);
|
|
@@ -11872,15 +11874,15 @@ function justifyFromTextAlign(align) {
|
|
|
11872
11874
|
if (align === "right") return "flex-end";
|
|
11873
11875
|
return "flex-start";
|
|
11874
11876
|
}
|
|
11875
|
-
function renderBanner(banner, handlers) {
|
|
11877
|
+
function renderBanner(banner, handlers, colorScope) {
|
|
11876
11878
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
11877
11879
|
const placement = banner.placement || {};
|
|
11878
11880
|
const mode = placement.mode || "overlay";
|
|
11879
11881
|
const position = placement.position || "top";
|
|
11880
11882
|
const zIndex = String(placement.zIndex || 2147483e3);
|
|
11881
11883
|
const imageBanner = isImageBanner(banner);
|
|
11882
|
-
const bg = imageBanner ? "transparent" : safeColor((_a = banner.style) == null ? void 0 : _a.backgroundColor) || "#1f2024";
|
|
11883
|
-
const color = safeColor((_b = banner.style) == null ? void 0 : _b.color) || "#ffffff";
|
|
11884
|
+
const bg = imageBanner ? "transparent" : safeColor((_a = banner.style) == null ? void 0 : _a.backgroundColor, colorScope) || "#1f2024";
|
|
11885
|
+
const color = safeColor((_b = banner.style) == null ? void 0 : _b.color, colorScope) || "#ffffff";
|
|
11884
11886
|
const isCard = mode === "overlay" || mode === "popup";
|
|
11885
11887
|
const ctaPosition = getCtaStyleValue(banner, ["position"]) || "center";
|
|
11886
11888
|
const imageHorizontal = imageAlign((_c = banner.image) == null ? void 0 : _c.horizontalAlignment);
|
|
@@ -12021,9 +12023,13 @@ function renderBanner(banner, handlers) {
|
|
|
12021
12023
|
}
|
|
12022
12024
|
if (!imageBanner && ((_n = banner.cta) == null ? void 0 : _n.enabled)) {
|
|
12023
12025
|
const ctaBg = safeColor(
|
|
12024
|
-
getCtaStyleValue(banner, ["backgroundColor", "buttonColor", "aColor"])
|
|
12026
|
+
getCtaStyleValue(banner, ["backgroundColor", "buttonColor", "aColor"]),
|
|
12027
|
+
colorScope
|
|
12025
12028
|
) || "#2f6df6";
|
|
12026
|
-
const ctaColor = safeColor(
|
|
12029
|
+
const ctaColor = safeColor(
|
|
12030
|
+
getCtaStyleValue(banner, ["textColor", "color"]),
|
|
12031
|
+
colorScope
|
|
12032
|
+
) || "#ffffff";
|
|
12027
12033
|
const btn = el("button", {
|
|
12028
12034
|
cursor: "pointer",
|
|
12029
12035
|
border: "none",
|
|
@@ -12498,6 +12504,33 @@ function clearState(state) {
|
|
|
12498
12504
|
state.syncTimer = null;
|
|
12499
12505
|
}
|
|
12500
12506
|
}
|
|
12507
|
+
const AUTO_THEME_LEASE_STATE = "__RAI_AUTO_THEME_LEASE_STATE__";
|
|
12508
|
+
const DISABLE_AUTO_THEME = "__DISABLE_AUTO_THEME__";
|
|
12509
|
+
function acquireAutoThemeDisableLease(target = window) {
|
|
12510
|
+
let state = target[AUTO_THEME_LEASE_STATE];
|
|
12511
|
+
if (!state) {
|
|
12512
|
+
state = {
|
|
12513
|
+
count: 0,
|
|
12514
|
+
previousValue: target[DISABLE_AUTO_THEME]
|
|
12515
|
+
};
|
|
12516
|
+
target[AUTO_THEME_LEASE_STATE] = state;
|
|
12517
|
+
}
|
|
12518
|
+
state.count += 1;
|
|
12519
|
+
target[DISABLE_AUTO_THEME] = true;
|
|
12520
|
+
let released = false;
|
|
12521
|
+
return () => {
|
|
12522
|
+
if (released) return;
|
|
12523
|
+
released = true;
|
|
12524
|
+
state.count = Math.max(0, state.count - 1);
|
|
12525
|
+
if (state.count > 0) return;
|
|
12526
|
+
if (state.previousValue === void 0) {
|
|
12527
|
+
delete target[DISABLE_AUTO_THEME];
|
|
12528
|
+
} else {
|
|
12529
|
+
target[DISABLE_AUTO_THEME] = state.previousValue;
|
|
12530
|
+
}
|
|
12531
|
+
delete target[AUTO_THEME_LEASE_STATE];
|
|
12532
|
+
};
|
|
12533
|
+
}
|
|
12501
12534
|
const BUNDLE_READY_TIMEOUT_MS = 3e4;
|
|
12502
12535
|
function isPromiseLike(value) {
|
|
12503
12536
|
return (typeof value === "object" || typeof value === "function") && value !== null && typeof value.then === "function";
|
|
@@ -12542,6 +12575,80 @@ async function waitForBundleMountReadiness(mountResult, firstPaint, timeoutMs =
|
|
|
12542
12575
|
);
|
|
12543
12576
|
return "deep-ready";
|
|
12544
12577
|
}
|
|
12578
|
+
function isWidgetBundleRuntime(value) {
|
|
12579
|
+
return (typeof value === "object" || typeof value === "function") && value !== null && typeof value.mount === "function";
|
|
12580
|
+
}
|
|
12581
|
+
function normalizeBundleUrl(url, baseUrl) {
|
|
12582
|
+
const normalized = new URL(url, baseUrl);
|
|
12583
|
+
normalized.hash = "";
|
|
12584
|
+
return normalized.href;
|
|
12585
|
+
}
|
|
12586
|
+
function createBundleRuntimeLoader({
|
|
12587
|
+
loadScript,
|
|
12588
|
+
readGlobal,
|
|
12589
|
+
baseUrl
|
|
12590
|
+
}) {
|
|
12591
|
+
const runtimePromises = /* @__PURE__ */ new Map();
|
|
12592
|
+
const globalLoadTails = /* @__PURE__ */ new Map();
|
|
12593
|
+
return async function getBundleRuntime(globalName, bundleUrl) {
|
|
12594
|
+
const normalizedUrl = normalizeBundleUrl(bundleUrl, baseUrl());
|
|
12595
|
+
const cacheKey = `${globalName}:${normalizedUrl}`;
|
|
12596
|
+
const cachedRuntime = runtimePromises.get(cacheKey);
|
|
12597
|
+
if (cachedRuntime) return cachedRuntime;
|
|
12598
|
+
const previousLoad = globalLoadTails.get(globalName) || Promise.resolve();
|
|
12599
|
+
const runtimePromise = previousLoad.then(async () => {
|
|
12600
|
+
await loadScript(normalizedUrl);
|
|
12601
|
+
const runtime = readGlobal(globalName);
|
|
12602
|
+
if (!isWidgetBundleRuntime(runtime)) {
|
|
12603
|
+
throw new Error(
|
|
12604
|
+
`window.${globalName}.mount not found after loading ${normalizedUrl}`
|
|
12605
|
+
);
|
|
12606
|
+
}
|
|
12607
|
+
const mount = runtime.mount;
|
|
12608
|
+
return {
|
|
12609
|
+
mount(container, config) {
|
|
12610
|
+
return mount.call(runtime, container, config);
|
|
12611
|
+
}
|
|
12612
|
+
};
|
|
12613
|
+
});
|
|
12614
|
+
runtimePromises.set(cacheKey, runtimePromise);
|
|
12615
|
+
const loadTail = runtimePromise.then(
|
|
12616
|
+
() => void 0,
|
|
12617
|
+
() => void 0
|
|
12618
|
+
);
|
|
12619
|
+
globalLoadTails.set(globalName, loadTail);
|
|
12620
|
+
void loadTail.then(() => {
|
|
12621
|
+
if (globalLoadTails.get(globalName) === loadTail) {
|
|
12622
|
+
globalLoadTails.delete(globalName);
|
|
12623
|
+
}
|
|
12624
|
+
});
|
|
12625
|
+
try {
|
|
12626
|
+
return await runtimePromise;
|
|
12627
|
+
} catch (error) {
|
|
12628
|
+
if (runtimePromises.get(cacheKey) === runtimePromise) {
|
|
12629
|
+
runtimePromises.delete(cacheKey);
|
|
12630
|
+
}
|
|
12631
|
+
throw error;
|
|
12632
|
+
}
|
|
12633
|
+
};
|
|
12634
|
+
}
|
|
12635
|
+
function appendScript(url) {
|
|
12636
|
+
return new Promise((resolve, reject) => {
|
|
12637
|
+
const script = document.createElement("script");
|
|
12638
|
+
script.src = url;
|
|
12639
|
+
script.onload = () => resolve();
|
|
12640
|
+
script.onerror = () => reject(new Error(`Failed to load ${url}`));
|
|
12641
|
+
document.head.appendChild(script);
|
|
12642
|
+
});
|
|
12643
|
+
}
|
|
12644
|
+
const loadBrowserBundleRuntime = createBundleRuntimeLoader({
|
|
12645
|
+
loadScript: appendScript,
|
|
12646
|
+
readGlobal: (globalName) => window[globalName],
|
|
12647
|
+
baseUrl: () => document.baseURI
|
|
12648
|
+
});
|
|
12649
|
+
function getOrLoadBundleRuntime(globalName, bundleUrl) {
|
|
12650
|
+
return loadBrowserBundleRuntime(globalName, bundleUrl);
|
|
12651
|
+
}
|
|
12545
12652
|
function assertCallbackName(callbackName) {
|
|
12546
12653
|
if (!callbackName || typeof callbackName !== "string") {
|
|
12547
12654
|
throw new TypeError("ReturningAI callback name must be a non-empty string");
|
|
@@ -12860,15 +12967,6 @@ function resolveWidgetServerUrl(domainKey) {
|
|
|
12860
12967
|
function resolveV2ApiUrl(domainKey) {
|
|
12861
12968
|
return DOMAIN_KEY_TO_V2_API_URL[domainKey] || DOMAIN_KEY_TO_V2_API_URL.PROD;
|
|
12862
12969
|
}
|
|
12863
|
-
function loadScript(url) {
|
|
12864
|
-
return new Promise((resolve, reject) => {
|
|
12865
|
-
const s = document.createElement("script");
|
|
12866
|
-
s.src = url;
|
|
12867
|
-
s.onload = () => resolve();
|
|
12868
|
-
s.onerror = () => reject(new Error(`Failed to load ${url}`));
|
|
12869
|
-
document.head.appendChild(s);
|
|
12870
|
-
});
|
|
12871
|
-
}
|
|
12872
12970
|
const loadedFonts = /* @__PURE__ */ new Set();
|
|
12873
12971
|
function ensureGoogleFontLoaded(family) {
|
|
12874
12972
|
if (!family || loadedFonts.has(family)) return;
|
|
@@ -13068,6 +13166,7 @@ class BaseWidget extends HTMLElement {
|
|
|
13068
13166
|
__publicField(this, "lottieInstances", []);
|
|
13069
13167
|
__publicField(this, "callbackRegistry", new WidgetCallbackRegistry());
|
|
13070
13168
|
__publicField(this, "bannerNode", null);
|
|
13169
|
+
__publicField(this, "releaseAutoThemeDisableLease");
|
|
13071
13170
|
this.shadow = this.attachShadow({ mode: "closed" });
|
|
13072
13171
|
}
|
|
13073
13172
|
static get observedAttributes() {
|
|
@@ -13540,24 +13639,28 @@ class BaseWidget extends HTMLElement {
|
|
|
13540
13639
|
if (!banner) return;
|
|
13541
13640
|
if (((_a = banner.placement) == null ? void 0 : _a.mobileBehavior) === "hide" && device === "mobile")
|
|
13542
13641
|
return;
|
|
13543
|
-
const node = renderBanner(
|
|
13544
|
-
|
|
13545
|
-
|
|
13546
|
-
|
|
13547
|
-
|
|
13548
|
-
|
|
13549
|
-
|
|
13550
|
-
|
|
13551
|
-
|
|
13552
|
-
|
|
13642
|
+
const node = renderBanner(
|
|
13643
|
+
banner,
|
|
13644
|
+
{
|
|
13645
|
+
onCtaClick: () => {
|
|
13646
|
+
var _a2, _b2, _c;
|
|
13647
|
+
fireTracking((_a2 = banner.tracking) == null ? void 0 : _a2.clickUrl);
|
|
13648
|
+
this.emit("rai-banner-click", { bannerId: banner.id });
|
|
13649
|
+
const url = (_b2 = banner.cta) == null ? void 0 : _b2.url;
|
|
13650
|
+
if (!url) return;
|
|
13651
|
+
if ((_c = banner.cta) == null ? void 0 : _c.openInNewTab)
|
|
13652
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
13653
|
+
else window.location.href = url;
|
|
13654
|
+
},
|
|
13655
|
+
onDismiss: () => {
|
|
13656
|
+
var _a2;
|
|
13657
|
+
fireTracking((_a2 = banner.tracking) == null ? void 0 : _a2.dismissUrl);
|
|
13658
|
+
this.emit("rai-banner-dismiss", { bannerId: banner.id });
|
|
13659
|
+
this.removeBanner();
|
|
13660
|
+
}
|
|
13553
13661
|
},
|
|
13554
|
-
|
|
13555
|
-
|
|
13556
|
-
fireTracking((_a2 = banner.tracking) == null ? void 0 : _a2.dismissUrl);
|
|
13557
|
-
this.emit("rai-banner-dismiss", { bannerId: banner.id });
|
|
13558
|
-
this.removeBanner();
|
|
13559
|
-
}
|
|
13560
|
-
});
|
|
13662
|
+
this
|
|
13663
|
+
);
|
|
13561
13664
|
this.bannerNode = node;
|
|
13562
13665
|
document.body.appendChild(node);
|
|
13563
13666
|
fireTracking((_b = banner.tracking) == null ? void 0 : _b.impressionUrl);
|
|
@@ -13665,6 +13768,9 @@ class BaseWidget extends HTMLElement {
|
|
|
13665
13768
|
return this.isConnected && initId === this.initGeneration;
|
|
13666
13769
|
}
|
|
13667
13770
|
teardownMountedWidget() {
|
|
13771
|
+
var _a;
|
|
13772
|
+
(_a = this.releaseAutoThemeDisableLease) == null ? void 0 : _a.call(this);
|
|
13773
|
+
this.releaseAutoThemeDisableLease = void 0;
|
|
13668
13774
|
if (this.cleanupListener) {
|
|
13669
13775
|
this.cleanupListener();
|
|
13670
13776
|
this.cleanupListener = void 0;
|
|
@@ -13722,6 +13828,9 @@ class BaseWidget extends HTMLElement {
|
|
|
13722
13828
|
let container = null;
|
|
13723
13829
|
try {
|
|
13724
13830
|
this.teardownMountedWidget();
|
|
13831
|
+
if (this.config.widgetType === "custom") {
|
|
13832
|
+
this.releaseAutoThemeDisableLease = acquireAutoThemeDisableLease();
|
|
13833
|
+
}
|
|
13725
13834
|
const bundleApiUrl = this.config.v2ApiUrl || resolveV2ApiUrl(this.config.domainKey);
|
|
13726
13835
|
const w = window;
|
|
13727
13836
|
if (!w.DomainKey) {
|
|
@@ -13742,16 +13851,11 @@ class BaseWidget extends HTMLElement {
|
|
|
13742
13851
|
window.loadingAnimation = this.state.loadingAnimation;
|
|
13743
13852
|
}
|
|
13744
13853
|
const globalName = WIDGET_GLOBALS[this.config.widgetType];
|
|
13745
|
-
|
|
13746
|
-
|
|
13747
|
-
|
|
13854
|
+
const widgetGlobal = await getOrLoadBundleRuntime(
|
|
13855
|
+
globalName,
|
|
13856
|
+
this.config.bundleUrl
|
|
13857
|
+
);
|
|
13748
13858
|
if (!this.isCurrentInit(initId)) return;
|
|
13749
|
-
const widgetGlobal = window[globalName];
|
|
13750
|
-
if (!(widgetGlobal == null ? void 0 : widgetGlobal.mount)) {
|
|
13751
|
-
throw new Error(
|
|
13752
|
-
`window.${globalName}.mount not found after loading bundle`
|
|
13753
|
-
);
|
|
13754
|
-
}
|
|
13755
13859
|
container = document.createElement("div");
|
|
13756
13860
|
const hideNestedBundleUntilReady = this.config.widgetType === "custom";
|
|
13757
13861
|
container.className = "rai-widget-root";
|
|
@@ -13794,7 +13898,7 @@ class BaseWidget extends HTMLElement {
|
|
|
13794
13898
|
// post. Mirrors the iframe behavior, where `isOpenWidget` is only
|
|
13795
13899
|
// injected by SSR for the explicit `/open-widget` route.
|
|
13796
13900
|
isOpenWidget: !this.state.accessToken,
|
|
13797
|
-
defaultColorSchema: this.config.
|
|
13901
|
+
defaultColorSchema: this.config.widgetType === "custom" && !this.config.themeExplicit ? null : colorMode,
|
|
13798
13902
|
requestHostCallback: async (callbackName, payload) => {
|
|
13799
13903
|
if (this.config.widgetType !== "store" && this.config.widgetType !== "custom") {
|
|
13800
13904
|
throw new Error(
|
|
@@ -13822,6 +13926,8 @@ class BaseWidget extends HTMLElement {
|
|
|
13822
13926
|
return;
|
|
13823
13927
|
}
|
|
13824
13928
|
console.error("[rai-widget] Bundle mount failed:", err);
|
|
13929
|
+
(_a = this.releaseAutoThemeDisableLease) == null ? void 0 : _a.call(this);
|
|
13930
|
+
this.releaseAutoThemeDisableLease = void 0;
|
|
13825
13931
|
this.showError();
|
|
13826
13932
|
}
|
|
13827
13933
|
}
|
|
@@ -13997,17 +14103,19 @@ class CustomWidget extends BaseWidget {
|
|
|
13997
14103
|
const base = config.widgetUrl.endsWith("custom-widget") ? `${config.widgetUrl}/${config.widgetId}` : config.widgetUrl;
|
|
13998
14104
|
try {
|
|
13999
14105
|
const u = new URL(base);
|
|
14000
|
-
u.searchParams.set("
|
|
14106
|
+
u.searchParams.set("auth", "postmessage");
|
|
14107
|
+
if (config.themeExplicit) u.searchParams.set("color", config.theme);
|
|
14001
14108
|
if (config.locale) u.searchParams.set("locale", config.locale);
|
|
14002
14109
|
return u.toString();
|
|
14003
14110
|
} catch {
|
|
14004
|
-
const params = [
|
|
14111
|
+
const params = ["auth=postmessage"];
|
|
14112
|
+
if (config.themeExplicit) params.push(`color=${config.theme}`);
|
|
14005
14113
|
if (config.locale) params.push(`locale=${encodeURIComponent(config.locale)}`);
|
|
14006
|
-
return `${base}?${params.join("&")}
|
|
14114
|
+
return params.length > 0 ? `${base}?${params.join("&")}` : base;
|
|
14007
14115
|
}
|
|
14008
14116
|
}
|
|
14009
14117
|
}
|
|
14010
|
-
console.log(`[rai-widget] v${"1.7.
|
|
14118
|
+
console.log(`[rai-widget] v${"1.7.2"}`);
|
|
14011
14119
|
class StoreWidgetCompat extends StoreWidget {
|
|
14012
14120
|
}
|
|
14013
14121
|
const WIDGET_REGISTRY = [
|
|
@@ -14071,7 +14179,7 @@ function exposePublicApi() {
|
|
|
14071
14179
|
})();
|
|
14072
14180
|
const widget = container == null ? void 0 : container.querySelector(ALL_WIDGET_SELECTOR);
|
|
14073
14181
|
window.ReturningAIWidget = {
|
|
14074
|
-
version: "1.7.
|
|
14182
|
+
version: "1.7.2",
|
|
14075
14183
|
reload: () => (widget == null ? void 0 : widget.reload()) ?? Promise.resolve(),
|
|
14076
14184
|
logout: () => (widget == null ? void 0 : widget.logoutPublic()) ?? Promise.resolve(),
|
|
14077
14185
|
isAuthenticated: () => (widget == null ? void 0 : widget.isAuthenticated()) ?? false,
|
|
@@ -19,6 +19,7 @@ export declare abstract class BaseWidget extends HTMLElement {
|
|
|
19
19
|
private lottieInstances;
|
|
20
20
|
private callbackRegistry;
|
|
21
21
|
private bannerNode;
|
|
22
|
+
private releaseAutoThemeDisableLease?;
|
|
22
23
|
constructor();
|
|
23
24
|
registerCallback(callbackName: typeof STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME, callback: ReturningAIStoreCallbackFieldOptionsCallback): void;
|
|
24
25
|
registerCallback(callbackName: typeof STORE_PURCHASE_SUCCESS_CALLBACK_NAME, callback: ReturningAIStorePurchaseSuccessCallback): void;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Resolve a CSS token from the owning widget before consulting the host page. */
|
|
2
|
+
export declare function resolveCssToken(token: string, preferredScope?: Element): string | undefined;
|
|
3
|
+
export declare function safeColor(v?: string, preferredScope?: Element): string | undefined;
|
|
@@ -7,6 +7,8 @@ export interface BannerHandlers {
|
|
|
7
7
|
* Builds the banner DOM (plain elements + inline styles, so it renders correctly
|
|
8
8
|
* on any host site without external CSS). Honors `placement.mode`:
|
|
9
9
|
* overlay/popup → fixed centered card; inline → in-flow full-width bar.
|
|
10
|
+
* Color tokens resolve from `colorScope` first so a banner uses its owning
|
|
11
|
+
* widget's palette instead of an unrelated host-page or sibling-widget theme.
|
|
10
12
|
* The caller decides where to attach it (body for overlay, target for inline).
|
|
11
13
|
*/
|
|
12
|
-
export declare function renderBanner(banner: EligibleBanner, handlers: BannerHandlers): HTMLElement;
|
|
14
|
+
export declare function renderBanner(banner: EligibleBanner, handlers: BannerHandlers, colorScope?: Element): HTMLElement;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface WidgetBundleRuntime {
|
|
2
|
+
mount(container: HTMLElement, config: unknown): unknown;
|
|
3
|
+
}
|
|
4
|
+
interface BundleRuntimeLoaderOptions {
|
|
5
|
+
loadScript: (url: string) => Promise<void>;
|
|
6
|
+
readGlobal: (globalName: string) => unknown;
|
|
7
|
+
baseUrl: () => string;
|
|
8
|
+
}
|
|
9
|
+
export declare function normalizeBundleUrl(url: string, baseUrl: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Cache widget runtimes by both their window global and normalized bundle URL.
|
|
12
|
+
*
|
|
13
|
+
* Different custom-widget bundles intentionally reuse the same global name, so
|
|
14
|
+
* the current value on window is not enough to identify the requested runtime.
|
|
15
|
+
* Capturing the runtime immediately after its script loads also lets A -> B -> A
|
|
16
|
+
* reuse A without re-evaluating its IIFE.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createBundleRuntimeLoader({ loadScript, readGlobal, baseUrl, }: BundleRuntimeLoaderOptions): (globalName: string, bundleUrl: string) => Promise<WidgetBundleRuntime>;
|
|
19
|
+
export declare function getOrLoadBundleRuntime(globalName: string, bundleUrl: string): Promise<WidgetBundleRuntime>;
|
|
20
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@returningai/widget-sdk",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"description": "Shadow DOM isolated widget SDK for ReturningAI",
|
|
5
5
|
"main": "dist/rai-widget.iife.js",
|
|
6
6
|
"module": "dist/rai-widget.js",
|
|
@@ -26,13 +26,18 @@
|
|
|
26
26
|
"build:all": "npm run build && npm run build:banner",
|
|
27
27
|
"build:all:min": "npm run build:min && npm run build:banner:min",
|
|
28
28
|
"types": "tsc --emitDeclarationOnly --outDir dist/types && cp src/jsx.d.ts dist/types/jsx.d.ts",
|
|
29
|
-
"test": "npm run test:host-callback && npm run test:bundle-readiness && npm run test:jsx-types",
|
|
29
|
+
"test": "npm run test:host-callback && npm run test:bundle-readiness && npm run test:bundle-runtime-cache && npm run test:jsx-types",
|
|
30
30
|
"test:host-callback": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/postmessage-host-callback.test.js",
|
|
31
31
|
"test:bundle-readiness": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/bundle-readiness.test.js",
|
|
32
|
+
"test:bundle-runtime-cache": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/bundle-runtime-cache.test.js",
|
|
32
33
|
"test:jsx-types": "tsc --noEmit --strict --lib ES2020,DOM --skipLibCheck false src/jsx.d.ts",
|
|
34
|
+
"coverage:repowise": "rm -rf coverage && npm run coverage:host-callback && npm run coverage:bundle-readiness && npm run test:jsx-types",
|
|
35
|
+
"coverage:host-callback": "rm -rf test/.tmp && tsc -p test/tsconfig.json && c8 --reporter=lcov --reports-dir=coverage/host-callback --exclude-after-remap --exclude='**/*.test.ts' node test/.tmp/test/postmessage-host-callback.test.js && node scripts/name-lcov-test.mjs coverage/host-callback/lcov.info test/postmessage-host-callback.test.ts",
|
|
36
|
+
"coverage:bundle-readiness": "rm -rf test/.tmp && tsc -p test/tsconfig.json && c8 --reporter=lcov --reports-dir=coverage/bundle-readiness --exclude-after-remap --exclude='**/*.test.ts' node test/.tmp/test/bundle-readiness.test.js && node scripts/name-lcov-test.mjs coverage/bundle-readiness/lcov.info test/bundle-readiness.test.ts",
|
|
33
37
|
"prepublishOnly": "npm run build:all:min && npm run types"
|
|
34
38
|
},
|
|
35
39
|
"devDependencies": {
|
|
40
|
+
"c8": "^11.0.0",
|
|
36
41
|
"terser": "^5.46.0",
|
|
37
42
|
"typescript": "^5.3.3",
|
|
38
43
|
"vite": "^5.1.0"
|