@returningai/widget-sdk 1.2.16 → 1.4.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,4 @@
1
- import type { WidgetConfig } from './types';
1
+ import type { 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
  protected shadow: ShadowRoot;
@@ -10,27 +10,70 @@ export declare abstract class BaseWidget extends HTMLElement {
10
10
  private cleanupListener?;
11
11
  private intersectionObserver?;
12
12
  private themeObserver?;
13
+ private lottieInstances;
13
14
  constructor();
14
15
  protected abstract buildWidgetUrl(config: WidgetConfig): string;
15
16
  connectedCallback(): void;
16
17
  disconnectedCallback(): void;
17
18
  private emit;
19
+ /**
20
+ * Apply widget-defined CSS colors before first paint so the loader uses
21
+ * the community's actual theme — not generic light/dark — from frame 1.
22
+ *
23
+ * Priority:
24
+ * 1. Cached themePalette (synchronous localStorage read)
25
+ * 2. HTML attribute hints (`bg`, `text`, `accent`)
26
+ * 3. Generic light/dark fallback (--rai-* vars set in connectedCallback)
27
+ *
28
+ * After the API response arrives, fetchAndRenderLoader() re-applies the
29
+ * fresh palette via applyPaletteFromState(). On every load except the
30
+ * absolute first-ever, the cached palette is already correct.
31
+ */
32
+ private applyFirstPaintColors;
33
+ private applyFont;
34
+ private applyPalette;
18
35
  private renderShell;
19
36
  /**
20
- * Fetches the community's loading animation config from the error-settings
21
- * API (which now also returns loadingAnimation) and renders the appropriate
22
- * loader. Falls back to the default bar loader if the API fails or if no
23
- * custom animation is configured.
37
+ * Loads the community loading animation + theme palette from cache or API
38
+ * and renders the animation above the "Loading ..." text. The text is
39
+ * already painted by renderShell so this method only ADDS the animation;
40
+ * users see two states at most: text-only → text + animation.
24
41
  *
25
- * This runs in parallel with auth — the API call is fire-and-forget and
26
- * the loader is rendered as soon as the response arrives. The result is
27
- * also cached by fetchErrorSettings so init() doesn't re-fetch.
42
+ * Stale-while-revalidate:
43
+ * - Cache hit → apply palette & render animation synchronously, fire
44
+ * background refresh.
45
+ * - Cache miss → text remains visible; await network; apply palette
46
+ * + render animation when response arrives.
28
47
  */
29
48
  private fetchAndRenderLoader;
30
- private renderLottieLoader;
49
+ /**
50
+ * Append the loading animation above the text. Removes any previous
51
+ * animation first so this is safe to call repeatedly (e.g. after a
52
+ * background refresh changes the configured loader).
53
+ */
54
+ private renderLoaderAnimation;
55
+ private renderLottieInto;
56
+ private clearLottieInstances;
31
57
  private createDefaultLoader;
32
58
  private createPresetLoader;
33
59
  private hideLoader;
60
+ /**
61
+ * Bundle mode: keep the SDK loader visible until React has actually
62
+ * painted into `container`, eliminating the brief bg-color gap that
63
+ * happens when the loader is removed before the React app's first frame.
64
+ *
65
+ * Strategy:
66
+ * 1. MutationObserver fires when React commits any DOM mutation into
67
+ * the container — synchronous inside mount(), but the callback runs
68
+ * as a microtask, so it observes the first child addition.
69
+ * 2. requestAnimationFrame waits one paint cycle so the React content
70
+ * is actually visible before the SDK loader fades out.
71
+ * 3. 2s fallback covers silent React mount errors so the loader doesn't
72
+ * hang forever.
73
+ *
74
+ * Calls hideLoader() (with its 300ms fade-out) so the transition is smooth.
75
+ */
76
+ private deferLoaderRemovalUntilReactPaints;
34
77
  private showError;
35
78
  private renderCustomError;
36
79
  private init;
@@ -4,7 +4,15 @@ export declare function authenticateViaProxy(config: WidgetConfig, state: Widget
4
4
  export declare function refreshAccessToken(config: WidgetConfig, state: WidgetState, onRefreshScheduled?: () => void, sendToken?: () => void): Promise<boolean>;
5
5
  export declare function getValidToken(config: WidgetConfig, state: WidgetState, onRefreshScheduled?: () => void): Promise<string>;
6
6
  export declare function logout(config: WidgetConfig, state: WidgetState): Promise<void>;
7
- export declare function validateEmbedToken(config: WidgetConfig): Promise<boolean>;
8
- export declare function fetchErrorSettings(config: WidgetConfig, state: WidgetState): Promise<typeof state.errorSettings>;
7
+ export declare function applyErrorSettingsToState(state: WidgetState, data: Record<string, unknown>): void;
8
+ /**
9
+ * Fetches widget error settings + community loading animation.
10
+ *
11
+ * Stale-while-revalidate: serves from cache instantly when present (no TTL).
12
+ * Pass { skipCache: true } to force a network fetch (used for background refresh).
13
+ */
14
+ export declare function fetchErrorSettings(config: WidgetConfig, state: WidgetState, opts?: {
15
+ skipCache?: boolean;
16
+ }): Promise<typeof state.errorSettings>;
9
17
  declare function clearState(state: WidgetState): void;
10
18
  export { clearState };
@@ -11,6 +11,7 @@ export interface WidgetConfig {
11
11
  widgetId: string;
12
12
  widgetType: 'store' | 'channel' | 'milestone' | 'social' | 'currency-view' | 'referral-conditions' | 'custom';
13
13
  theme: 'light' | 'dark';
14
+ themeExplicit: boolean;
14
15
  container: string;
15
16
  width: string;
16
17
  height: string;
@@ -30,7 +31,14 @@ export interface WidgetConfig {
30
31
  bundleUrl?: string;
31
32
  embedToken?: string;
32
33
  v2ApiUrl?: string;
33
- domainKey?: string;
34
+ domainKey: string;
35
+ loadingText: string;
36
+ firstPaintColors?: {
37
+ bg?: string;
38
+ text?: string;
39
+ accent?: string;
40
+ };
41
+ firstPaintFont?: string;
34
42
  }
35
43
  export interface WidgetState {
36
44
  accessToken: string | null;
@@ -49,6 +57,11 @@ export interface WidgetState {
49
57
  modalColor?: string;
50
58
  backgroundImage?: string;
51
59
  } | null;
60
+ lastAuthError: {
61
+ status: number;
62
+ error?: string;
63
+ hint?: string;
64
+ } | null;
52
65
  loadingAnimation: {
53
66
  type?: string;
54
67
  preset?: string;
@@ -68,6 +81,12 @@ export interface WidgetState {
68
81
  };
69
82
  };
70
83
  } | null;
84
+ themePalette: {
85
+ light?: Record<string, string>;
86
+ dark?: Record<string, string>;
87
+ } | null;
88
+ font: string | null;
89
+ defaultColorSchema: 'light' | 'dark' | null;
71
90
  }
72
91
  export interface TokenData {
73
92
  accessToken: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@returningai/widget-sdk",
3
- "version": "1.2.16",
3
+ "version": "1.4.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,5 +26,8 @@
26
26
  "terser": "^5.46.0",
27
27
  "typescript": "^5.3.3",
28
28
  "vite": "^5.1.0"
29
+ },
30
+ "dependencies": {
31
+ "lottie-web": "^5.13.0"
29
32
  }
30
33
  }