@returningai/widget-sdk 1.4.3 → 1.5.1
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 +36 -0
- package/README.md +476 -123
- package/dist/rai-widget.iife.js +1 -1
- package/dist/rai-widget.js +123 -6
- package/dist/types/BaseWidget.d.ts +9 -1
- package/dist/types/core/callback-registry.d.ts +15 -0
- package/dist/types/core/postmessage.d.ts +2 -2
- package/dist/types/index.d.ts +11 -7
- package/dist/types/jsx.d.ts +67 -0
- package/dist/types/types.d.ts +56 -0
- package/package.json +5 -2
package/dist/rai-widget.js
CHANGED
|
@@ -10697,6 +10697,9 @@ function clearState(state) {
|
|
|
10697
10697
|
state.syncTimer = null;
|
|
10698
10698
|
}
|
|
10699
10699
|
}
|
|
10700
|
+
const STORE_CALLBACK_FIELD_OPTIONS_SCOPE = "store.callback_field_options";
|
|
10701
|
+
const STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME = "callbackFieldOptions";
|
|
10702
|
+
const STORE_CALLBACK_FIELD_OPTIONS_TIMEOUT_MS = 15e3;
|
|
10700
10703
|
function debounce(fn, wait) {
|
|
10701
10704
|
let timer = null;
|
|
10702
10705
|
return {
|
|
@@ -10733,13 +10736,13 @@ function sendTokenToWidget(config, state, iframe) {
|
|
|
10733
10736
|
} catch {
|
|
10734
10737
|
}
|
|
10735
10738
|
}
|
|
10736
|
-
function setupMessageListener(config, state, _shadow, iframe, onRefreshScheduled, onLogout, hideLoader, emit) {
|
|
10739
|
+
function setupMessageListener(config, state, _shadow, iframe, onRefreshScheduled, onLogout, hideLoader, emit, getCallbacks) {
|
|
10737
10740
|
const heightSetter = debounce((h) => {
|
|
10738
10741
|
iframe.style.height = `${h}px`;
|
|
10739
10742
|
emit == null ? void 0 : emit("rai-height-change", { height: h });
|
|
10740
10743
|
}, config.heightDebounce ?? 100);
|
|
10741
10744
|
const handler = async (event) => {
|
|
10742
|
-
var _a;
|
|
10745
|
+
var _a, _b;
|
|
10743
10746
|
if (event.origin !== config.widgetDomain) return;
|
|
10744
10747
|
if (!event.data || typeof event.data.type !== "string") return;
|
|
10745
10748
|
const { type, containerId, widgetId, payload } = event.data;
|
|
@@ -10785,6 +10788,55 @@ function setupMessageListener(config, state, _shadow, iframe, onRefreshScheduled
|
|
|
10785
10788
|
if (onLogout) await onLogout();
|
|
10786
10789
|
break;
|
|
10787
10790
|
}
|
|
10791
|
+
case "RETURNINGAI_WIDGET_ACTION": {
|
|
10792
|
+
if (event.source !== iframe.contentWindow) break;
|
|
10793
|
+
const message = event.data;
|
|
10794
|
+
if (config.widgetType !== "store" && config.widgetType !== "custom") break;
|
|
10795
|
+
if (message.widgetType !== "store") break;
|
|
10796
|
+
if (message.action !== "store:host-callback") break;
|
|
10797
|
+
if (message.callbackName !== STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME) break;
|
|
10798
|
+
if (((_b = message.payload) == null ? void 0 : _b.scope) !== STORE_CALLBACK_FIELD_OPTIONS_SCOPE) break;
|
|
10799
|
+
if (message.widgetId !== void 0 && message.widgetId !== config.widgetId) break;
|
|
10800
|
+
if (message.containerId !== void 0 && message.containerId !== config.container) break;
|
|
10801
|
+
const respond = (result) => {
|
|
10802
|
+
var _a2;
|
|
10803
|
+
(_a2 = iframe.contentWindow) == null ? void 0 : _a2.postMessage(result, config.widgetDomain);
|
|
10804
|
+
};
|
|
10805
|
+
const callbacks = (getCallbacks == null ? void 0 : getCallbacks()) ?? {};
|
|
10806
|
+
const callback = callbacks[message.callbackName];
|
|
10807
|
+
if (!callback) {
|
|
10808
|
+
respond({
|
|
10809
|
+
type: "RETURNINGAI_WIDGET_ACTION_RESULT",
|
|
10810
|
+
requestId: message.requestId,
|
|
10811
|
+
action: "store:host-callback",
|
|
10812
|
+
ok: false,
|
|
10813
|
+
status: "failed",
|
|
10814
|
+
error: { message: "Host callback is not registered" }
|
|
10815
|
+
});
|
|
10816
|
+
break;
|
|
10817
|
+
}
|
|
10818
|
+
try {
|
|
10819
|
+
const value = await callback(message.payload);
|
|
10820
|
+
respond({
|
|
10821
|
+
type: "RETURNINGAI_WIDGET_ACTION_RESULT",
|
|
10822
|
+
requestId: message.requestId,
|
|
10823
|
+
action: "store:host-callback",
|
|
10824
|
+
ok: true,
|
|
10825
|
+
status: "success",
|
|
10826
|
+
value
|
|
10827
|
+
});
|
|
10828
|
+
} catch {
|
|
10829
|
+
respond({
|
|
10830
|
+
type: "RETURNINGAI_WIDGET_ACTION_RESULT",
|
|
10831
|
+
requestId: message.requestId,
|
|
10832
|
+
action: "store:host-callback",
|
|
10833
|
+
ok: false,
|
|
10834
|
+
status: "failed",
|
|
10835
|
+
error: { message: "Host callback failed" }
|
|
10836
|
+
});
|
|
10837
|
+
}
|
|
10838
|
+
break;
|
|
10839
|
+
}
|
|
10788
10840
|
}
|
|
10789
10841
|
};
|
|
10790
10842
|
window.addEventListener("message", handler);
|
|
@@ -10793,6 +10845,45 @@ function setupMessageListener(config, state, _shadow, iframe, onRefreshScheduled
|
|
|
10793
10845
|
heightSetter.cancel();
|
|
10794
10846
|
};
|
|
10795
10847
|
}
|
|
10848
|
+
function assertCallbackName(callbackName) {
|
|
10849
|
+
if (!callbackName || typeof callbackName !== "string") {
|
|
10850
|
+
throw new TypeError("ReturningAI callback name must be a non-empty string");
|
|
10851
|
+
}
|
|
10852
|
+
}
|
|
10853
|
+
function assertCallback(callback) {
|
|
10854
|
+
if (typeof callback !== "function") {
|
|
10855
|
+
throw new TypeError("ReturningAI callback must be a function");
|
|
10856
|
+
}
|
|
10857
|
+
}
|
|
10858
|
+
class WidgetCallbackRegistry {
|
|
10859
|
+
constructor() {
|
|
10860
|
+
__publicField(this, "registeredCallbacks", {});
|
|
10861
|
+
__publicField(this, "locked", false);
|
|
10862
|
+
}
|
|
10863
|
+
get isLocked() {
|
|
10864
|
+
return this.locked;
|
|
10865
|
+
}
|
|
10866
|
+
registerCallback(callbackName, callback) {
|
|
10867
|
+
if (this.locked) {
|
|
10868
|
+
return;
|
|
10869
|
+
}
|
|
10870
|
+
assertCallbackName(callbackName);
|
|
10871
|
+
assertCallback(callback);
|
|
10872
|
+
this.registeredCallbacks = {
|
|
10873
|
+
...this.registeredCallbacks,
|
|
10874
|
+
[callbackName]: callback
|
|
10875
|
+
};
|
|
10876
|
+
}
|
|
10877
|
+
lock() {
|
|
10878
|
+
if (this.locked) {
|
|
10879
|
+
return;
|
|
10880
|
+
}
|
|
10881
|
+
this.locked = true;
|
|
10882
|
+
}
|
|
10883
|
+
read() {
|
|
10884
|
+
return { ...this.registeredCallbacks };
|
|
10885
|
+
}
|
|
10886
|
+
}
|
|
10796
10887
|
const widgetCSS = ':host{display:block;position:relative;width:100%;height:100%}.rai-loader{position:absolute;top:0;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;width:100%;height:100%;background:var(--background-5, var(--rai-loader-bg, #ffffff));border-radius:8px;z-index:10;transition:opacity .3s ease-out;font-family:var(--rai-loader-font, "Roboto", system-ui, -apple-system, sans-serif)}.rai-loader.fade-out{opacity:0;pointer-events:none}.rai-loader-text{margin:.5rem 0 0;font-size:1.125rem;line-height:1.75rem;font-weight:400;letter-spacing:normal;color:var(--accent-1, var(--rai-accent, #000000));text-align:center}@media (min-width: 768px){.rai-loader-text{font-size:1.5rem;line-height:2rem}}.rai-error{display:none;position:absolute;top:0;left:0;width:100%;height:100%;align-items:center;justify-content:center;flex-direction:column;gap:12px;background:var(--rai-error-bg, #1a1a1a);border-radius:8px;padding:24px;box-sizing:border-box;text-align:center;color:var(--rai-error-text, #9ca3af);font-family:system-ui,-apple-system,sans-serif;z-index:10}.rai-error.visible{display:flex}iframe{display:block;border:none;opacity:0;transition:opacity .3s ease-in}iframe.loaded{opacity:1}.rai-lottie-loader{width:100px;height:100px}.rai-lottie-loader svg{width:100%!important;height:100%!important}.rai-lottie-spinner{width:32px;height:32px;margin:34px auto;border:3px solid var(--rai-text4, #6b7280);border-top-color:var(--rai-accent, #000000);border-radius:50%;animation:rai-spin .7s linear infinite}@keyframes rai-spin{to{transform:rotate(360deg)}}.rai-sdk-loader{position:relative;width:75px;height:100px}.rai-sdk-loader__bar{position:absolute;bottom:0;width:10px;height:50%;background:var(--rai-accent, #000000);transform-origin:center bottom;box-shadow:1px 1px #0003}.rai-sdk-loader__bar:nth-child(1){left:0;transform:scaleY(.2);animation:rai-sdk-barUp1 4s infinite}.rai-sdk-loader__bar:nth-child(2){left:15px;transform:scaleY(.4);animation:rai-sdk-barUp2 4s infinite}.rai-sdk-loader__bar:nth-child(3){left:30px;transform:scaleY(.6);animation:rai-sdk-barUp3 4s infinite}.rai-sdk-loader__bar:nth-child(4){left:45px;transform:scaleY(.8);animation:rai-sdk-barUp4 4s infinite}.rai-sdk-loader__bar:nth-child(5){left:60px;transform:scale(1);animation:rai-sdk-barUp5 4s infinite}.rai-sdk-loader__ball{position:absolute;bottom:10px;left:0;width:10px;height:10px;background:var(--rai-accent, #000000);border-radius:50%;animation:rai-sdk-ball 4s infinite}@keyframes rai-sdk-ball{0%{transform:translate(0)}5%{transform:translate(8px,-14px)}10%{transform:translate(15px,-10px)}17%{transform:translate(23px,-24px)}20%{transform:translate(30px,-20px)}27%{transform:translate(38px,-34px)}30%{transform:translate(45px,-30px)}37%{transform:translate(53px,-44px)}40%{transform:translate(60px,-40px)}50%{transform:translate(60px)}57%{transform:translate(53px,-14px)}60%{transform:translate(45px,-10px)}67%{transform:translate(37px,-24px)}70%{transform:translate(30px,-20px)}77%{transform:translate(22px,-34px)}80%{transform:translate(15px,-30px)}87%{transform:translate(7px,-44px)}90%{transform:translateY(-40px)}to{transform:translate(0)}}@keyframes rai-sdk-barUp1{0%{transform:scaleY(.2)}40%{transform:scaleY(.2)}50%{transform:scale(1)}90%{transform:scale(1)}to{transform:scaleY(.2)}}@keyframes rai-sdk-barUp2{0%{transform:scaleY(.4)}40%{transform:scaleY(.4)}50%{transform:scaleY(.8)}90%{transform:scaleY(.8)}to{transform:scaleY(.4)}}@keyframes rai-sdk-barUp3{0%{transform:scaleY(.6)}to{transform:scaleY(.6)}}@keyframes rai-sdk-barUp4{0%{transform:scaleY(.8)}40%{transform:scaleY(.8)}50%{transform:scaleY(.4)}90%{transform:scaleY(.4)}to{transform:scaleY(.8)}}@keyframes rai-sdk-barUp5{0%{transform:scale(1)}40%{transform:scale(1)}50%{transform:scaleY(.2)}90%{transform:scaleY(.2)}to{transform:scale(1)}}#loading-square{width:75px;aspect-ratio:1;display:flex;color:var(--rai-accent, #000000);background:linear-gradient(currentColor 0 0) right / 51% 100%,linear-gradient(currentColor 0 0) bottom / 100% 51%;background-repeat:no-repeat;animation:l16-0 2s infinite linear .25s}#loading-square>div{width:50%;height:50%;background:currentColor;animation:l16-1 .5s infinite linear}@keyframes l16-0{0%,12.49%{transform:rotate(0)}12.5%,37.49%{transform:rotate(90deg)}37.5%,62.49%{transform:rotate(180deg)}62.5%,87.49%{transform:rotate(270deg)}87.5%,to{transform:rotate(360deg)}}@keyframes l16-1{0%{transform:perspective(80px) rotate3d(-1,-1,0,0)}80%,to{transform:perspective(80px) rotate3d(-1,-1,0,-180deg)}}#loading-circle{width:75px;aspect-ratio:1;display:grid;grid:50%/50%;color:var(--rai-accent, #000000);border-radius:50%;--_g: no-repeat linear-gradient(currentColor 0 0);background:var(--_g),var(--_g),var(--_g);background-size:50.1% 50.1%;animation:l9-0 1.5s infinite steps(1) alternate,l9-0-0 3s infinite steps(1) alternate}#loading-circle>div{background:var(--rai-text4, #6b7280);border-top-left-radius:100px;transform:perspective(150px) rotateY(0) rotateX(0);transform-origin:bottom right;animation:l9-1 1.5s infinite linear alternate}@keyframes l9-0{0%{background-position:0 100%,100% 100%,100% 0}33%{background-position:100% 100%,100% 100%,100% 0}66%{background-position:100% 0,100% 0,100% 0}}@keyframes l9-0-0{0%{transform:scaleX(1) rotate(0)}50%{transform:scaleX(-1) rotate(-90deg)}}@keyframes l9-1{16.5%{transform:perspective(150px) rotateX(-90deg) rotateY(0) rotateX(0);filter:grayscale(.8)}33%{transform:perspective(150px) rotateX(-180deg) rotateY(0) rotateX(0)}66%{transform:perspective(150px) rotateX(-180deg) rotateY(-180deg) rotateX(0)}to{transform:perspective(150px) rotateX(-180deg) rotateY(-180deg) rotateX(-180deg);filter:grayscale(.8)}}.rai-custom-error{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10}.tiptap strong.tw-font-bold,.tiptap b.tw-font-bold{font-weight:700}.tiptap em.tw-font-italic,.tiptap i.tw-font-italic{font-style:italic}.tiptap a.tiptap-rich-text-link{color:#3b82f6;text-decoration:underline;position:relative;display:inline-block;width:fit-content}.tiptap a.tiptap-rich-text-link:hover{color:#3b82f6cc;text-decoration:none}.tiptap a.tiptap-rich-text-link:not([title=""]):before{content:attr(title);position:absolute;top:-2rem;left:50%;transform:translate(-50%);white-space:nowrap;border-radius:.25rem;background-color:#000;padding:.25rem .5rem;color:#fff;opacity:0;transition:opacity .2s;pointer-events:none}.tiptap a.tiptap-rich-text-link:not([title=""]):hover:before{opacity:1}.tiptap p[style*="text-align: left"]{text-align:left}.tiptap p[style*="text-align: center"]{text-align:center}.tiptap p[style*="text-align: right"]{text-align:right}.tiptap p[style*="text-align: justify"]{text-align:justify}.tiptap u{text-decoration:underline}.tiptap.ProseMirror{background-color:transparent;height:fit-content!important;word-wrap:break-word;white-space:pre-wrap;white-space:break-spaces;-webkit-font-variant-ligatures:none;font-variant-ligatures:none;font-feature-settings:"liga" 0;padding:0;width:100%;overflow-y:auto}.tiptap{line-height:1.6;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.tiptap p{margin:.5em 0}.tiptap p:first-child{margin-top:0}.tiptap p:last-child{margin-bottom:0}.tiptap img{max-width:100%;height:auto;display:block}.tiptap p[style*="text-align: left"] img{margin-left:0;margin-right:auto}.tiptap p[style*="text-align: center"] img{margin-left:auto;margin-right:auto}.tiptap p[style*="text-align: right"] img{margin-left:auto;margin-right:0}.rai-retry-btn{padding:8px 20px;border:none;border-radius:6px;background:var(--rai-accent, #000000);color:var(--rai-error-bg, #ffffff);font-size:14px;font-family:system-ui,-apple-system,sans-serif;cursor:pointer}.rai-retry-btn:hover{opacity:.85}';
|
|
10797
10888
|
const DEFINED_ATTRS = /* @__PURE__ */ new Set([
|
|
10798
10889
|
"community-id",
|
|
@@ -11104,11 +11195,18 @@ class BaseWidget extends HTMLElement {
|
|
|
11104
11195
|
__publicField(this, "hasAttemptedInit", false);
|
|
11105
11196
|
__publicField(this, "initGeneration", 0);
|
|
11106
11197
|
__publicField(this, "lottieInstances", []);
|
|
11198
|
+
__publicField(this, "callbackRegistry", new WidgetCallbackRegistry());
|
|
11107
11199
|
this.shadow = this.attachShadow({ mode: "closed" });
|
|
11108
11200
|
}
|
|
11109
11201
|
static get observedAttributes() {
|
|
11110
11202
|
return ["embed-token", "data-embed-token"];
|
|
11111
11203
|
}
|
|
11204
|
+
registerCallback(callbackName, callback) {
|
|
11205
|
+
this.callbackRegistry.registerCallback(callbackName, callback);
|
|
11206
|
+
}
|
|
11207
|
+
lockCallbacks() {
|
|
11208
|
+
this.callbackRegistry.lock();
|
|
11209
|
+
}
|
|
11112
11210
|
connectedCallback() {
|
|
11113
11211
|
this.config = readConfig(this, void 0);
|
|
11114
11212
|
this.identitySignature = identitySignatureForConfig(this.config);
|
|
@@ -11195,6 +11293,13 @@ class BaseWidget extends HTMLElement {
|
|
|
11195
11293
|
})
|
|
11196
11294
|
);
|
|
11197
11295
|
}
|
|
11296
|
+
/**
|
|
11297
|
+
* Reads host callback registrations at call time so framework integrations
|
|
11298
|
+
* can register a callback after the custom element is already mounted.
|
|
11299
|
+
*/
|
|
11300
|
+
readRuntimeCallbacks() {
|
|
11301
|
+
return this.callbackRegistry.read();
|
|
11302
|
+
}
|
|
11198
11303
|
// ── Rendering ─────────────────────────────────────────────────────────
|
|
11199
11304
|
/**
|
|
11200
11305
|
* Apply widget-defined CSS colors before first paint so the loader uses
|
|
@@ -11627,8 +11732,9 @@ class BaseWidget extends HTMLElement {
|
|
|
11627
11732
|
() => this.scheduleRefresh(),
|
|
11628
11733
|
() => this.logoutAndClear(),
|
|
11629
11734
|
() => this.hideLoader(),
|
|
11630
|
-
(type, detail) => this.emit(type, detail)
|
|
11735
|
+
(type, detail) => this.emit(type, detail),
|
|
11631
11736
|
// #1
|
|
11737
|
+
() => this.readRuntimeCallbacks()
|
|
11632
11738
|
);
|
|
11633
11739
|
}
|
|
11634
11740
|
// ── Bundle mode (no-iframe) ──────────────────────────────────────────
|
|
@@ -11698,7 +11804,15 @@ class BaseWidget extends HTMLElement {
|
|
|
11698
11804
|
// post. Mirrors the iframe behavior, where `isOpenWidget` is only
|
|
11699
11805
|
// injected by SSR for the explicit `/open-widget` route.
|
|
11700
11806
|
isOpenWidget: !this.state.accessToken,
|
|
11701
|
-
defaultColorSchema: this.config.theme === "dark" ? "dark" : "light"
|
|
11807
|
+
defaultColorSchema: this.config.theme === "dark" ? "dark" : "light",
|
|
11808
|
+
requestHostCallback: async (callbackName, payload) => {
|
|
11809
|
+
if (this.config.widgetType !== "store" && this.config.widgetType !== "custom" || callbackName !== STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME || payload.scope !== STORE_CALLBACK_FIELD_OPTIONS_SCOPE) {
|
|
11810
|
+
throw new Error("Host callback is only supported for store widgets");
|
|
11811
|
+
}
|
|
11812
|
+
const callback = this.readRuntimeCallbacks()[callbackName];
|
|
11813
|
+
if (!callback) throw new Error("Host callback is not registered");
|
|
11814
|
+
return callback(payload);
|
|
11815
|
+
}
|
|
11702
11816
|
});
|
|
11703
11817
|
this.emit("rai-mounted");
|
|
11704
11818
|
} catch (err) {
|
|
@@ -11886,7 +12000,7 @@ class CustomWidget extends BaseWidget {
|
|
|
11886
12000
|
}
|
|
11887
12001
|
}
|
|
11888
12002
|
}
|
|
11889
|
-
console.log(`[rai-widget] v${"1.
|
|
12003
|
+
console.log(`[rai-widget] v${"1.5.1"}`);
|
|
11890
12004
|
class StoreWidgetCompat extends StoreWidget {
|
|
11891
12005
|
}
|
|
11892
12006
|
const WIDGET_REGISTRY = [
|
|
@@ -11950,7 +12064,7 @@ function exposePublicApi() {
|
|
|
11950
12064
|
})();
|
|
11951
12065
|
const widget = container == null ? void 0 : container.querySelector(ALL_WIDGET_SELECTOR);
|
|
11952
12066
|
window.ReturningAIWidget = {
|
|
11953
|
-
version: "1.
|
|
12067
|
+
version: "1.5.1",
|
|
11954
12068
|
reload: () => (widget == null ? void 0 : widget.reload()) ?? Promise.resolve(),
|
|
11955
12069
|
logout: () => (widget == null ? void 0 : widget.logoutPublic()) ?? Promise.resolve(),
|
|
11956
12070
|
isAuthenticated: () => (widget == null ? void 0 : widget.isAuthenticated()) ?? false,
|
|
@@ -11968,6 +12082,9 @@ export {
|
|
|
11968
12082
|
CustomWidget,
|
|
11969
12083
|
MilestoneWidget,
|
|
11970
12084
|
ReferralWidget,
|
|
12085
|
+
STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME,
|
|
12086
|
+
STORE_CALLBACK_FIELD_OPTIONS_SCOPE,
|
|
12087
|
+
STORE_CALLBACK_FIELD_OPTIONS_TIMEOUT_MS,
|
|
11971
12088
|
SocialWidget,
|
|
11972
12089
|
StoreWidget
|
|
11973
12090
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WidgetConfig } from "./types";
|
|
1
|
+
import type { ReturningAIWidgetCallback, WidgetConfig } from "./types";
|
|
2
2
|
export declare function readConfig(el: Element, existingId?: string): WidgetConfig;
|
|
3
3
|
export declare abstract class BaseWidget extends HTMLElement {
|
|
4
4
|
static get observedAttributes(): string[];
|
|
@@ -16,7 +16,10 @@ export declare abstract class BaseWidget extends HTMLElement {
|
|
|
16
16
|
private hasAttemptedInit;
|
|
17
17
|
private initGeneration;
|
|
18
18
|
private lottieInstances;
|
|
19
|
+
private callbackRegistry;
|
|
19
20
|
constructor();
|
|
21
|
+
registerCallback(callbackName: string, callback: ReturningAIWidgetCallback): void;
|
|
22
|
+
lockCallbacks(): void;
|
|
20
23
|
protected abstract buildWidgetUrl(config: WidgetConfig): string;
|
|
21
24
|
connectedCallback(): void;
|
|
22
25
|
disconnectedCallback(): void;
|
|
@@ -24,6 +27,11 @@ export declare abstract class BaseWidget extends HTMLElement {
|
|
|
24
27
|
private setupIdentityAttributeObserver;
|
|
25
28
|
private handleIdentityConfigChange;
|
|
26
29
|
private emit;
|
|
30
|
+
/**
|
|
31
|
+
* Reads host callback registrations at call time so framework integrations
|
|
32
|
+
* can register a callback after the custom element is already mounted.
|
|
33
|
+
*/
|
|
34
|
+
private readRuntimeCallbacks;
|
|
27
35
|
/**
|
|
28
36
|
* Apply widget-defined CSS colors before first paint so the loader uses
|
|
29
37
|
* the community's actual theme — not generic light/dark — from frame 1.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ReturningAIWidgetCallback, ReturningAIWidgetCallbacks } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Owns callback registration for a single widget element.
|
|
4
|
+
*
|
|
5
|
+
* Callback registration is intentionally per element so pages with multiple
|
|
6
|
+
* widgets can lock each widget's callback behavior independently.
|
|
7
|
+
*/
|
|
8
|
+
export declare class WidgetCallbackRegistry {
|
|
9
|
+
private registeredCallbacks;
|
|
10
|
+
private locked;
|
|
11
|
+
get isLocked(): boolean;
|
|
12
|
+
registerCallback(callbackName: string, callback: ReturningAIWidgetCallback): void;
|
|
13
|
+
lock(): void;
|
|
14
|
+
read(): ReturningAIWidgetCallbacks;
|
|
15
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { WidgetConfig, WidgetState } from '../types';
|
|
1
|
+
import type { ReturningAIWidgetCallbacks, WidgetConfig, WidgetState } from '../types';
|
|
2
2
|
export declare function sendTokenToWidget(config: WidgetConfig, state: WidgetState, iframe: HTMLIFrameElement): void;
|
|
3
|
-
export declare function setupMessageListener(config: WidgetConfig, state: WidgetState, _shadow: ShadowRoot, iframe: HTMLIFrameElement, onRefreshScheduled?: () => void, onLogout?: () => Promise<void>, hideLoader?: () => void, emit?: (type: string, detail?: Record<string, unknown>) => void): () => void;
|
|
3
|
+
export declare function setupMessageListener(config: WidgetConfig, state: WidgetState, _shadow: ShadowRoot, iframe: HTMLIFrameElement, onRefreshScheduled?: () => void, onLogout?: () => Promise<void>, hideLoader?: () => void, emit?: (type: string, detail?: Record<string, unknown>) => void, getCallbacks?: () => ReturningAIWidgetCallbacks): () => void;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -6,14 +6,18 @@ import { CurrencyWidget } from './CurrencyWidget';
|
|
|
6
6
|
import { ReferralWidget } from './ReferralWidget';
|
|
7
7
|
import { CustomWidget } from './CustomWidget';
|
|
8
8
|
declare global {
|
|
9
|
+
interface ReturningAIWidgetGlobal {
|
|
10
|
+
version?: string;
|
|
11
|
+
reload?: () => Promise<void>;
|
|
12
|
+
logout?: () => Promise<void>;
|
|
13
|
+
isAuthenticated?: () => boolean;
|
|
14
|
+
getTokenInfo?: () => object;
|
|
15
|
+
}
|
|
9
16
|
interface Window {
|
|
10
|
-
ReturningAIWidget
|
|
11
|
-
version: string;
|
|
12
|
-
reload: () => Promise<void>;
|
|
13
|
-
logout: () => Promise<void>;
|
|
14
|
-
isAuthenticated: () => boolean;
|
|
15
|
-
getTokenInfo: () => object;
|
|
16
|
-
};
|
|
17
|
+
ReturningAIWidget?: ReturningAIWidgetGlobal;
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
export { StoreWidget, ChannelWidget, MilestoneWidget, SocialWidget, CurrencyWidget, ReferralWidget, CustomWidget };
|
|
21
|
+
export type { ReturningAIStoreCallbackFieldOptionsCallback, ReturningAIWidgetCallback, ReturningAIWidgetCallbackRegistration, ReturningAIWidgetActionMessage, ReturningAIWidgetActionResultMessage, ReturningAIWidgetCallbacks, StoreCallbackFieldOptionsContext, StoreCallbackFieldOptionsField, StoreCallbackFieldOptionsFieldType, StoreCallbackFieldOptionsPayload, StoreCallbackFieldOptionsResult, } from './types';
|
|
22
|
+
export { STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME, STORE_CALLBACK_FIELD_OPTIONS_SCOPE, STORE_CALLBACK_FIELD_OPTIONS_TIMEOUT_MS, } from './types';
|
|
23
|
+
export type {} from './jsx';
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Shared attribute shape for all widget elements
|
|
2
|
+
interface RaiWidgetAttributes {
|
|
3
|
+
'community-id': string
|
|
4
|
+
'channel-id'?: string
|
|
5
|
+
'widget-id'?: string // deprecated — use 'community-id'
|
|
6
|
+
'data-email'?: string
|
|
7
|
+
'widget-type'?: 'store' | 'channel' | 'milestone' | 'social' | 'currency-view' | 'referral-conditions' | 'custom'
|
|
8
|
+
theme?: 'light' | 'dark'
|
|
9
|
+
width?: string
|
|
10
|
+
height?: string
|
|
11
|
+
'api-url'?: string
|
|
12
|
+
'widget-url'?: string
|
|
13
|
+
'bundle-url'?: string
|
|
14
|
+
'domain-key'?: string
|
|
15
|
+
'v2-api-url'?: string
|
|
16
|
+
'embed-token'?: string
|
|
17
|
+
'auth-url'?: string
|
|
18
|
+
'auto-refresh'?: string
|
|
19
|
+
'data-container'?: string
|
|
20
|
+
debug?: string
|
|
21
|
+
class?: string
|
|
22
|
+
style?: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type RaiWidgetElementAttributes = RaiWidgetAttributes & {
|
|
26
|
+
[attributeName: string]: unknown
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface RaiWidgetIntrinsicElements {
|
|
30
|
+
'rai-store-widget': RaiWidgetElementAttributes
|
|
31
|
+
'rai-channel-widget': RaiWidgetElementAttributes
|
|
32
|
+
'rai-milestone-widget': RaiWidgetElementAttributes
|
|
33
|
+
'rai-social-widget': RaiWidgetElementAttributes
|
|
34
|
+
'rai-currency-widget': RaiWidgetElementAttributes
|
|
35
|
+
'rai-referral-widget': RaiWidgetElementAttributes
|
|
36
|
+
'rai-custom-widget': RaiWidgetElementAttributes
|
|
37
|
+
'rai-widget': RaiWidgetElementAttributes // deprecated
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ── React ──────────────────────────────────────────────────────────────────
|
|
41
|
+
declare global {
|
|
42
|
+
namespace React {
|
|
43
|
+
namespace JSX {
|
|
44
|
+
interface IntrinsicElements extends RaiWidgetIntrinsicElements {}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
namespace JSX {
|
|
49
|
+
interface IntrinsicElements extends RaiWidgetIntrinsicElements {}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ── Vue 3 (Volar / vue-tsc) ────────────────────────────────────────────────
|
|
54
|
+
declare module '@vue/runtime-core' {
|
|
55
|
+
interface GlobalComponents {
|
|
56
|
+
RaiStoreWidget: { $props: RaiWidgetAttributes }
|
|
57
|
+
RaiChannelWidget: { $props: RaiWidgetAttributes }
|
|
58
|
+
RaiMilestoneWidget: { $props: RaiWidgetAttributes }
|
|
59
|
+
RaiSocialWidget: { $props: RaiWidgetAttributes }
|
|
60
|
+
RaiCurrencyWidget: { $props: RaiWidgetAttributes }
|
|
61
|
+
RaiReferralWidget: { $props: RaiWidgetAttributes }
|
|
62
|
+
RaiCustomWidget: { $props: RaiWidgetAttributes }
|
|
63
|
+
RaiWidget: { $props: RaiWidgetAttributes } // deprecated
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export {}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,3 +1,59 @@
|
|
|
1
|
+
export declare const STORE_CALLBACK_FIELD_OPTIONS_SCOPE: "store.callback_field_options";
|
|
2
|
+
export declare const STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME: "callbackFieldOptions";
|
|
3
|
+
export declare const STORE_CALLBACK_FIELD_OPTIONS_TIMEOUT_MS = 15000;
|
|
4
|
+
export type StoreCallbackFieldOptionsFieldType = 'single-select';
|
|
5
|
+
export interface StoreCallbackFieldOptionsField {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
type: StoreCallbackFieldOptionsFieldType;
|
|
9
|
+
}
|
|
10
|
+
export interface StoreCallbackFieldOptionsContext {
|
|
11
|
+
productId: string;
|
|
12
|
+
productName?: string;
|
|
13
|
+
fields: StoreCallbackFieldOptionsField[];
|
|
14
|
+
}
|
|
15
|
+
export interface StoreCallbackFieldOptionsPayload {
|
|
16
|
+
scope: typeof STORE_CALLBACK_FIELD_OPTIONS_SCOPE;
|
|
17
|
+
callbackName: typeof STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME;
|
|
18
|
+
context: StoreCallbackFieldOptionsContext;
|
|
19
|
+
}
|
|
20
|
+
export interface StoreCallbackFieldOptionsResult {
|
|
21
|
+
fieldOptions: Record<string, string[]>;
|
|
22
|
+
signature?: string;
|
|
23
|
+
}
|
|
24
|
+
export type ReturningAIWidgetCallback<TPayload = any, TResult = any> = (payload: TPayload) => Promise<TResult> | TResult;
|
|
25
|
+
export type ReturningAIStoreCallbackFieldOptionsCallback = (payload: StoreCallbackFieldOptionsPayload) => Promise<StoreCallbackFieldOptionsResult> | StoreCallbackFieldOptionsResult;
|
|
26
|
+
export type ReturningAIWidgetCallbacks = {
|
|
27
|
+
'callbackFieldOptions'?: ReturningAIStoreCallbackFieldOptionsCallback;
|
|
28
|
+
[callbackName: string]: ReturningAIWidgetCallback | undefined;
|
|
29
|
+
};
|
|
30
|
+
export interface ReturningAIWidgetCallbackRegistration {
|
|
31
|
+
registerCallback(callbackName: typeof STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME, callback: ReturningAIStoreCallbackFieldOptionsCallback): void;
|
|
32
|
+
registerCallback(callbackName: string, callback: ReturningAIWidgetCallback): void;
|
|
33
|
+
lockCallbacks(): void;
|
|
34
|
+
}
|
|
35
|
+
export interface ReturningAIWidgetActionMessage {
|
|
36
|
+
type: 'RETURNINGAI_WIDGET_ACTION';
|
|
37
|
+
requestId: string;
|
|
38
|
+
widgetType: 'store';
|
|
39
|
+
action: 'store:host-callback';
|
|
40
|
+
containerId?: string;
|
|
41
|
+
widgetId?: string;
|
|
42
|
+
callbackName: string;
|
|
43
|
+
timeoutMs?: number;
|
|
44
|
+
payload: StoreCallbackFieldOptionsPayload;
|
|
45
|
+
}
|
|
46
|
+
export interface ReturningAIWidgetActionResultMessage {
|
|
47
|
+
type: 'RETURNINGAI_WIDGET_ACTION_RESULT';
|
|
48
|
+
requestId: string;
|
|
49
|
+
action: 'store:host-callback';
|
|
50
|
+
ok: boolean;
|
|
51
|
+
status: 'success' | 'failed';
|
|
52
|
+
value?: StoreCallbackFieldOptionsResult;
|
|
53
|
+
error?: {
|
|
54
|
+
message: string;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
1
57
|
export interface WidgetConfig {
|
|
2
58
|
/** The community this widget belongs to. Maps to the `community-id` HTML attribute. */
|
|
3
59
|
communityId: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@returningai/widget-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
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",
|
|
@@ -21,7 +21,10 @@
|
|
|
21
21
|
"dev": "vite",
|
|
22
22
|
"build": "vite build",
|
|
23
23
|
"build:min": "vite build --mode production",
|
|
24
|
-
"types": "tsc --emitDeclarationOnly --outDir dist/types",
|
|
24
|
+
"types": "tsc --emitDeclarationOnly --outDir dist/types && cp src/jsx.d.ts dist/types/jsx.d.ts",
|
|
25
|
+
"test": "npm run test:host-callback && npm run test:jsx-types",
|
|
26
|
+
"test:host-callback": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/postmessage-host-callback.test.js",
|
|
27
|
+
"test:jsx-types": "tsc --noEmit --strict --lib ES2020,DOM --skipLibCheck false src/jsx.d.ts",
|
|
25
28
|
"prepublishOnly": "npm run build:min && npm run types"
|
|
26
29
|
},
|
|
27
30
|
"devDependencies": {
|