@returningai/widget-sdk 1.6.1 → 1.7.0

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.
@@ -1,4 +1,5 @@
1
- import type { ReturningAIWidgetCallback, WidgetConfig } from "./types";
1
+ import type { ReturningAIStoreCallbackFieldOptionsCallback, ReturningAIStorePurchaseSuccessCallback, ReturningAIWidgetCallback, WidgetConfig } from "./types";
2
+ import { STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME, STORE_PURCHASE_SUCCESS_CALLBACK_NAME } from "./types";
2
3
  export declare function readConfig(el: Element, existingId?: string): WidgetConfig;
3
4
  export declare abstract class BaseWidget extends HTMLElement {
4
5
  static get observedAttributes(): string[];
@@ -19,6 +20,8 @@ export declare abstract class BaseWidget extends HTMLElement {
19
20
  private callbackRegistry;
20
21
  private bannerNode;
21
22
  constructor();
23
+ registerCallback(callbackName: typeof STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME, callback: ReturningAIStoreCallbackFieldOptionsCallback): void;
24
+ registerCallback(callbackName: typeof STORE_PURCHASE_SUCCESS_CALLBACK_NAME, callback: ReturningAIStorePurchaseSuccessCallback): void;
22
25
  registerCallback(callbackName: string, callback: ReturningAIWidgetCallback): void;
23
26
  lockCallbacks(): void;
24
27
  protected abstract buildWidgetUrl(config: WidgetConfig): string;
@@ -52,15 +55,13 @@ export declare abstract class BaseWidget extends HTMLElement {
52
55
  private renderShell;
53
56
  /**
54
57
  * Loads the community loading animation + theme palette from cache or API
55
- * and renders the animation above the "Loading ..." text. The text is
56
- * already painted by renderShell so this method only ADDS the animation;
57
- * users see two states at most: text-only → text + animation.
58
+ * and renders the configured animation above the loading text.
58
59
  *
59
60
  * Stale-while-revalidate:
60
61
  * - Cache hit → apply palette & render animation synchronously, fire
61
62
  * background refresh.
62
- * - Cache miss → text remains visible; await network; apply palette
63
- * + render animation when response arrives.
63
+ * - Cache miss → retain the initial shell; await network; apply palette +
64
+ * render the resolved animation or fallback.
64
65
  */
65
66
  private fetchAndRenderLoader;
66
67
  /**
@@ -75,22 +76,12 @@ export declare abstract class BaseWidget extends HTMLElement {
75
76
  private createPresetLoader;
76
77
  private hideLoader;
77
78
  /**
78
- * Bundle mode: keep the SDK loader visible until React has actually
79
- * painted into `container`, eliminating the brief bg-color gap that
80
- * happens when the loader is removed before the React app's first frame.
81
- *
82
- * Strategy:
83
- * 1. MutationObserver fires when React commits any DOM mutation into
84
- * the container — synchronous inside mount(), but the callback runs
85
- * as a microtask, so it observes the first child addition.
86
- * 2. requestAnimationFrame waits one paint cycle so the React content
87
- * is actually visible before the SDK loader fades out.
88
- * 3. 2s fallback covers silent React mount errors so the loader doesn't
89
- * hang forever.
90
- *
91
- * Calls hideLoader() (with its 300ms fade-out) so the transition is smooth.
79
+ * Resolve after a legacy bundle's first rendered child has reached a paint.
80
+ * This remains the fallback for bundles that do not expose a deep-ready
81
+ * handle from mount(). It intentionally does not hide the loader itself so
82
+ * a stronger nested-MFE readiness signal can take ownership of the handoff.
92
83
  */
93
- private deferLoaderRemovalUntilReactPaints;
84
+ private waitForFirstBundlePaint;
94
85
  private showError;
95
86
  private renderCustomError;
96
87
  private resolveBannerApiUrl;
@@ -0,0 +1,15 @@
1
+ export declare const BUNDLE_READY_TIMEOUT_MS = 30000;
2
+ export interface BundleMountReadyHandle {
3
+ ready: PromiseLike<void>;
4
+ }
5
+ export type BundleMountReadiness = "deep-ready" | "first-paint";
6
+ /**
7
+ * Wait for the strongest readiness signal a bundle provides.
8
+ *
9
+ * Split-bundle loaders may return a promise merely because they dynamically
10
+ * import their app. That promise is not proof that the nested micro-frontend
11
+ * has rendered. A bundle opts into deep readiness by resolving its mount call
12
+ * to an object with a `ready` promise. Legacy bundles keep the first-paint
13
+ * behavior unchanged.
14
+ */
15
+ export declare function waitForBundleMountReadiness(mountResult: unknown, firstPaint: PromiseLike<void>, timeoutMs?: number): Promise<BundleMountReadiness>;
@@ -0,0 +1,3 @@
1
+ import type { ReturningAIWidgetCallbacks, StoreCallbackFieldOptionsResult, StoreHostCallbackPayload } from '../types';
2
+ export declare function isSupportedStoreHostCallback(callbackName: string, payload: StoreHostCallbackPayload | null | undefined): boolean;
3
+ export declare function invokeStoreHostCallback(callbacks: ReturningAIWidgetCallbacks, callbackName: string, payload: StoreHostCallbackPayload): Promise<StoreCallbackFieldOptionsResult | undefined>;
@@ -18,6 +18,6 @@ declare global {
18
18
  }
19
19
  }
20
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';
21
+ export type { ReturningAIStoreCallbackFieldOptionsCallback, ReturningAIStoreHostCallbackActionMessage, ReturningAIStorePurchaseSuccessCallback, ReturningAIWidgetCallback, ReturningAIWidgetCallbackRegistration, ReturningAIWidgetActionMessage, ReturningAIWidgetActionResultMessage, ReturningAIWidgetCallbacks, StoreCallbackFieldOptionsContext, StoreCallbackFieldOptionsField, StoreCallbackFieldOptionsFieldType, StoreCallbackFieldOptionsPayload, StoreCallbackFieldOptionsResult, StoreHostCallbackPayload, StorePurchaseSuccessPayload, } from './types';
22
+ export { STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME, STORE_CALLBACK_FIELD_OPTIONS_SCOPE, STORE_CALLBACK_FIELD_OPTIONS_TIMEOUT_MS, STORE_PURCHASE_SUCCESS_CALLBACK_NAME, STORE_PURCHASE_SUCCESS_SCOPE, } from './types';
23
23
  export type {} from './jsx';
@@ -1,6 +1,8 @@
1
1
  export declare const STORE_CALLBACK_FIELD_OPTIONS_SCOPE: "store.callback_field_options";
2
2
  export declare const STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME: "callbackFieldOptions";
3
3
  export declare const STORE_CALLBACK_FIELD_OPTIONS_TIMEOUT_MS = 15000;
4
+ export declare const STORE_PURCHASE_SUCCESS_SCOPE: "store.purchase_success";
5
+ export declare const STORE_PURCHASE_SUCCESS_CALLBACK_NAME: "storePurchaseSuccess";
4
6
  export type StoreCallbackFieldOptionsFieldType = 'single-select';
5
7
  export interface StoreCallbackFieldOptionsField {
6
8
  id: string;
@@ -21,18 +23,51 @@ export interface StoreCallbackFieldOptionsResult {
21
23
  fieldOptions: Record<string, string[]>;
22
24
  signature?: string;
23
25
  }
26
+ export interface StorePurchaseSuccessPayload {
27
+ scope: typeof STORE_PURCHASE_SUCCESS_SCOPE;
28
+ callbackName: typeof STORE_PURCHASE_SUCCESS_CALLBACK_NAME;
29
+ context: {
30
+ event: 'purchased_store_item';
31
+ orderId: string;
32
+ purchaseHistoryId: string;
33
+ server: {
34
+ id: string;
35
+ name?: string | null;
36
+ };
37
+ product: {
38
+ id: string;
39
+ name?: string | null;
40
+ cost: number;
41
+ };
42
+ customer: {
43
+ customIdentifier: string | null;
44
+ };
45
+ coins: {
46
+ beforePurchase: number;
47
+ cost: number;
48
+ afterPurchase: number;
49
+ };
50
+ userInformation?: Record<string, unknown>;
51
+ customRedemptionOption?: Record<string, unknown> | unknown[];
52
+ purchasedAt: string;
53
+ };
54
+ }
55
+ export type StoreHostCallbackPayload = StoreCallbackFieldOptionsPayload | StorePurchaseSuccessPayload;
24
56
  export type ReturningAIWidgetCallback<TPayload = any, TResult = any> = (payload: TPayload) => Promise<TResult> | TResult;
25
57
  export type ReturningAIStoreCallbackFieldOptionsCallback = (payload: StoreCallbackFieldOptionsPayload) => Promise<StoreCallbackFieldOptionsResult> | StoreCallbackFieldOptionsResult;
58
+ export type ReturningAIStorePurchaseSuccessCallback = (payload: StorePurchaseSuccessPayload) => Promise<unknown> | unknown;
26
59
  export type ReturningAIWidgetCallbacks = {
27
60
  'callbackFieldOptions'?: ReturningAIStoreCallbackFieldOptionsCallback;
61
+ 'storePurchaseSuccess'?: ReturningAIStorePurchaseSuccessCallback;
28
62
  [callbackName: string]: ReturningAIWidgetCallback | undefined;
29
63
  };
30
64
  export interface ReturningAIWidgetCallbackRegistration {
31
65
  registerCallback(callbackName: typeof STORE_CALLBACK_FIELD_OPTIONS_CALLBACK_NAME, callback: ReturningAIStoreCallbackFieldOptionsCallback): void;
66
+ registerCallback(callbackName: typeof STORE_PURCHASE_SUCCESS_CALLBACK_NAME, callback: ReturningAIStorePurchaseSuccessCallback): void;
32
67
  registerCallback(callbackName: string, callback: ReturningAIWidgetCallback): void;
33
68
  lockCallbacks(): void;
34
69
  }
35
- export interface ReturningAIWidgetActionMessage {
70
+ export interface ReturningAIWidgetActionMessage<TPayload extends StoreHostCallbackPayload = StoreCallbackFieldOptionsPayload> {
36
71
  type: 'RETURNINGAI_WIDGET_ACTION';
37
72
  requestId: string;
38
73
  widgetType: 'store';
@@ -41,8 +76,9 @@ export interface ReturningAIWidgetActionMessage {
41
76
  widgetId?: string;
42
77
  callbackName: string;
43
78
  timeoutMs?: number;
44
- payload: StoreCallbackFieldOptionsPayload;
79
+ payload: TPayload;
45
80
  }
81
+ export type ReturningAIStoreHostCallbackActionMessage = ReturningAIWidgetActionMessage<StoreHostCallbackPayload>;
46
82
  export interface ReturningAIWidgetActionResultMessage {
47
83
  type: 'RETURNINGAI_WIDGET_ACTION_RESULT';
48
84
  requestId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@returningai/widget-sdk",
3
- "version": "1.6.1",
3
+ "version": "1.7.0",
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,8 +26,9 @@
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:jsx-types",
29
+ "test": "npm run test:host-callback && npm run test:bundle-readiness && 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
+ "test:bundle-readiness": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/bundle-readiness.test.js",
31
32
  "test:jsx-types": "tsc --noEmit --strict --lib ES2020,DOM --skipLibCheck false src/jsx.d.ts",
32
33
  "prepublishOnly": "npm run build:all:min && npm run types"
33
34
  },