@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.
- package/README.md +71 -57
- package/dist/rai-widget.iife.js +1 -1
- package/dist/rai-widget.js +10796 -148
- package/dist/types/BaseWidget.d.ts +52 -9
- package/dist/types/core/auth.d.ts +10 -2
- package/dist/types/types.d.ts +20 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -10,12 +10,14 @@ Your access credentials stay on your server. Your server exchanges them for a **
|
|
|
10
10
|
|
|
11
11
|
**Step 1 — Create an access key pair** (one-time, from your dashboard):
|
|
12
12
|
|
|
13
|
-
Go to **Community Settings > Integrations > SDK Access** and click **Create SDK Key**. Enter a name and optional allowed origins.
|
|
13
|
+
Go to **Community Settings > Integrations > SDK Access** and click **Create SDK Key**. Enter a name and optional allowed origins (required in production; localhost is auto-allowed in dev).
|
|
14
14
|
|
|
15
15
|
The dashboard will display your `accessId` and `accessKey`. The `accessKey` is shown **once only** — save it securely.
|
|
16
16
|
|
|
17
17
|
Store both values in your server environment variables.
|
|
18
18
|
|
|
19
|
+
> **Rotating or revoking keys:** The same dashboard page lists existing keys and lets you revoke or replace them. Revocation takes effect immediately for token issuance, and forces active sessions to re-auth on their next page load.
|
|
20
|
+
|
|
19
21
|
**Step 2 — Exchange credentials for an embed token on every page load** (Node.js example):
|
|
20
22
|
|
|
21
23
|
```js
|
|
@@ -26,13 +28,22 @@ const response = await fetch('https://YOUR_API_URL/v2/api/widget-access-keys/tok
|
|
|
26
28
|
body: JSON.stringify({
|
|
27
29
|
accessId: process.env.RAI_ACCESS_ID,
|
|
28
30
|
accessKey: process.env.RAI_ACCESS_KEY,
|
|
31
|
+
// userIdentifiers keys MUST be `data-*` prefixed — they match the
|
|
32
|
+
// `dataAttribute` value of each field configured in your widget's
|
|
33
|
+
// User Identifier Fields (e.g. the dashboard stores "data-email",
|
|
34
|
+
// "data-user-id", not bare "email"/"userId").
|
|
35
|
+
userIdentifiers: {
|
|
36
|
+
'data-user-id': [YourUserObject].id,
|
|
37
|
+
'data-email': [YourUserObject].email,
|
|
38
|
+
// ...any other fields configured for this widget
|
|
39
|
+
},
|
|
29
40
|
}),
|
|
30
41
|
})
|
|
31
42
|
const { data } = await response.json()
|
|
32
|
-
// data.embedToken expires in 15 minutes
|
|
43
|
+
// data.embedToken expires in 15 minutes and carries signed identity claims
|
|
33
44
|
```
|
|
34
45
|
|
|
35
|
-
**Step 3 — Embed** (only the short-lived token appears in HTML):
|
|
46
|
+
**Step 3 — Embed** (only the short-lived token appears in HTML — no identity attributes):
|
|
36
47
|
|
|
37
48
|
```html
|
|
38
49
|
<div id="returning-ai-widget-YOUR_WIDGET_ID" style="width:100%;height:600px"></div>
|
|
@@ -40,14 +51,14 @@ const { data } = await response.json()
|
|
|
40
51
|
data-widget-id="YOUR_WIDGET_ID"
|
|
41
52
|
data-widget-type="store"
|
|
42
53
|
data-theme="dark"
|
|
43
|
-
data-email="user@example.com"
|
|
44
54
|
data-embed-token="eyJ..."
|
|
45
|
-
api-url="YOUR_API_URL"
|
|
46
55
|
widget-url="YOUR_WIDGET_URL"
|
|
47
56
|
></script>
|
|
48
57
|
```
|
|
49
58
|
|
|
50
|
-
The SDK
|
|
59
|
+
`api-url` is optional. The SDK resolves the widget server from `domain-key` when provided and uses production by default; pass `api-url` only if you need to override the widget auth server.
|
|
60
|
+
|
|
61
|
+
The server validates the token and extracts identity from its signed claims. If the token is expired, invalid, or its identifiers don't satisfy the widget's configured User Identifier Fields, the widget shows an error screen. Tokens expire after 15 minutes — regenerate on each page render.
|
|
51
62
|
|
|
52
63
|
---
|
|
53
64
|
|
|
@@ -81,6 +92,8 @@ Set the `data-widget-type` attribute to choose which widget to display. The Widg
|
|
|
81
92
|
| `referral-conditions` | Referral widget |
|
|
82
93
|
| `custom` | Custom widget |
|
|
83
94
|
|
|
95
|
+
All examples below use **Access Key Embed** (recommended) — identity is signed into `data-embed-token` server-side per the [Quick Start](#quick-start). Swap `data-embed-token="eyJ..."` for `data-*` identifier attributes if you want [Public Embed](#user-identifier-attributes) instead.
|
|
96
|
+
|
|
84
97
|
### Store widget
|
|
85
98
|
|
|
86
99
|
```html
|
|
@@ -89,8 +102,7 @@ Set the `data-widget-type` attribute to choose which widget to display. The Widg
|
|
|
89
102
|
data-widget-id="YOUR_WIDGET_ID"
|
|
90
103
|
data-widget-type="store"
|
|
91
104
|
data-theme="dark"
|
|
92
|
-
data-
|
|
93
|
-
api-url="YOUR_API_URL"
|
|
105
|
+
data-embed-token="eyJ..."
|
|
94
106
|
widget-url="YOUR_WIDGET_URL"
|
|
95
107
|
></script>
|
|
96
108
|
```
|
|
@@ -103,8 +115,7 @@ Set the `data-widget-type` attribute to choose which widget to display. The Widg
|
|
|
103
115
|
data-widget-id="YOUR_WIDGET_ID"
|
|
104
116
|
data-widget-type="channel"
|
|
105
117
|
data-theme="dark"
|
|
106
|
-
data-
|
|
107
|
-
api-url="YOUR_API_URL"
|
|
118
|
+
data-embed-token="eyJ..."
|
|
108
119
|
widget-url="YOUR_WIDGET_URL"
|
|
109
120
|
></script>
|
|
110
121
|
```
|
|
@@ -119,8 +130,7 @@ Set the `data-widget-type` attribute to choose which widget to display. The Widg
|
|
|
119
130
|
data-widget-id="YOUR_WIDGET_ID"
|
|
120
131
|
data-widget-type="social"
|
|
121
132
|
data-theme="dark"
|
|
122
|
-
data-
|
|
123
|
-
api-url="YOUR_API_URL"
|
|
133
|
+
data-embed-token="eyJ..."
|
|
124
134
|
widget-url="YOUR_WIDGET_URL"
|
|
125
135
|
></script>
|
|
126
136
|
```
|
|
@@ -133,8 +143,7 @@ Set the `data-widget-type` attribute to choose which widget to display. The Widg
|
|
|
133
143
|
data-widget-id="YOUR_WIDGET_ID"
|
|
134
144
|
data-widget-type="milestone"
|
|
135
145
|
data-theme="dark"
|
|
136
|
-
data-
|
|
137
|
-
api-url="YOUR_API_URL"
|
|
146
|
+
data-embed-token="eyJ..."
|
|
138
147
|
widget-url="YOUR_WIDGET_URL"
|
|
139
148
|
></script>
|
|
140
149
|
```
|
|
@@ -147,12 +156,13 @@ Set the `data-widget-type` attribute to choose which widget to display. The Widg
|
|
|
147
156
|
data-widget-id="YOUR_WIDGET_ID"
|
|
148
157
|
data-widget-type="custom"
|
|
149
158
|
data-theme="dark"
|
|
150
|
-
data-
|
|
151
|
-
api-url="YOUR_API_URL"
|
|
159
|
+
data-embed-token="eyJ..."
|
|
152
160
|
widget-url="YOUR_WIDGET_URL"
|
|
153
161
|
></script>
|
|
154
162
|
```
|
|
155
163
|
|
|
164
|
+
> **Custom widgets:** `YOUR_WIDGET_ID` is the base64-encoded `_id` of the CustomWidget record (not the community ID). The custom element variant `<rai-custom-widget widget-id="...">` uses this same base64 value — it's the one widget type where raw ObjectIds are not accepted.
|
|
165
|
+
|
|
156
166
|
---
|
|
157
167
|
|
|
158
168
|
## Attributes
|
|
@@ -170,18 +180,20 @@ All attributes can be provided with or without the `data-` prefix — both work.
|
|
|
170
180
|
|-----------|----------|---------|-------------|
|
|
171
181
|
| `data-widget-id` | **Yes** | — | Your widget ID (from dashboard) |
|
|
172
182
|
| `data-widget-type` | **Yes** | `store` | Widget type (see table above) |
|
|
173
|
-
| `api-url` |
|
|
183
|
+
| `api-url` | No | Production widget server | Optional widget auth server override. Defaults from `domain-key` when provided |
|
|
174
184
|
| `widget-url` | **Yes**\* | — | Widget URL (from dashboard). \*Not required when using `data-bundle-url` |
|
|
175
185
|
| `data-bundle-url` | No | — | URL to the widget IIFE bundle — triggers [bundle mode](#bundle-mode) (non-iframe) |
|
|
176
|
-
| `data-domain-key` |
|
|
186
|
+
| `data-domain-key` | No | `PROD` | Environment key: `SGTR`, `STG`, or `PROD`. Used to resolve default environment URLs when overrides are omitted |
|
|
177
187
|
| `data-theme` | No | `light` | `light` or `dark` |
|
|
178
|
-
| `data-email` |
|
|
179
|
-
| `data-embed-token` | Access Key only | — | Short-lived
|
|
188
|
+
| `data-email` | Public Embed only | — | User's email for identification. **Access Key Embed:** omit — identity is signed into `data-embed-token` |
|
|
189
|
+
| `data-embed-token` | Access Key Embed only | — | Short-lived JWT from your server. Carries signed user identifiers — no `data-*` identifier attributes needed |
|
|
180
190
|
| `data-locale` | No | — | BCP 47 locale tag (e.g. `fr-FR`) |
|
|
181
|
-
| `data-eager` | No | — | Load immediately instead of waiting until visible |
|
|
191
|
+
| `data-eager` | No | — | Load immediately instead of waiting until visible (presence-based boolean) |
|
|
182
192
|
| `data-auto-refresh` | No | `true` | Auto-refresh access token before expiry |
|
|
183
193
|
| `data-debug` | No | `false` | Verbose console logging |
|
|
184
194
|
| `data-custom-data` | No | — | JSON object forwarded to the widget |
|
|
195
|
+
| `data-retry-label` | No | `Retry` | Label text for the retry button on the error screen |
|
|
196
|
+
| `data-v2-api-url` | No | Domain-key default | Optional V2 API override for bundle mode. Safe to omit for standard environments |
|
|
185
197
|
|
|
186
198
|
### Custom element attributes
|
|
187
199
|
|
|
@@ -189,20 +201,22 @@ All attributes can be provided with or without the `data-` prefix — both work.
|
|
|
189
201
|
|-----------|----------|---------|-------------|
|
|
190
202
|
| `community-id` | **Yes**\* | — | Your community ID (raw ObjectId from dashboard). \*Custom widgets use `widget-id` instead |
|
|
191
203
|
| `channel-id` | **Channel only** | — | Channel ID (raw ObjectId) — required for `<rai-channel-widget>` |
|
|
192
|
-
| `api-url` |
|
|
204
|
+
| `api-url` | No | Production widget server | Optional widget auth server override. Defaults from `domain-key` when provided |
|
|
193
205
|
| `widget-url` | **Yes**\* | — | Widget URL (from dashboard). \*Not required when using `bundle-url` |
|
|
194
206
|
| `bundle-url` | No | — | URL to the widget IIFE bundle — triggers [bundle mode](#bundle-mode) (non-iframe) |
|
|
195
|
-
| `domain-key` |
|
|
207
|
+
| `domain-key` | No | `PROD` | Environment key: `SGTR`, `STG`, or `PROD`. Used to resolve default environment URLs when overrides are omitted |
|
|
196
208
|
| `theme` | No | `light` | `light` or `dark` |
|
|
197
|
-
| `data-email` |
|
|
198
|
-
| `embed-token` | Access Key only | — | Short-lived
|
|
209
|
+
| `data-email` | Public Embed only | — | User's email for identification. **Access Key Embed:** omit — identity is signed into `embed-token` |
|
|
210
|
+
| `embed-token` | Access Key Embed only | — | Short-lived JWT from your server. Carries signed user identifiers — no `data-*` identifier attributes needed |
|
|
199
211
|
| `width` | No | `100%` | CSS width |
|
|
200
212
|
| `height` | No | `600px` | CSS height |
|
|
201
213
|
| `locale` | No | — | BCP 47 locale tag (e.g. `fr-FR`) |
|
|
202
|
-
| `eager` | No | — | Load immediately instead of waiting until visible |
|
|
214
|
+
| `eager` | No | — | Load immediately instead of waiting until visible (presence-based boolean) |
|
|
203
215
|
| `auto-refresh` | No | `true` | Auto-refresh access token before expiry |
|
|
204
216
|
| `debug` | No | `false` | Verbose console logging |
|
|
205
217
|
| `custom-data` | No | — | JSON object forwarded to the widget |
|
|
218
|
+
| `retry-label` | No | `Retry` | Label text for the retry button on the error screen |
|
|
219
|
+
| `v2-api-url` | No | Domain-key default | Optional V2 API override for bundle mode. Safe to omit for standard environments |
|
|
206
220
|
|
|
207
221
|
> **`widget-id` vs `community-id`:** The script-tag method uses `data-widget-id` which is a pre-encoded identifier (base64). The custom element method uses raw ObjectIds — `community-id` for most widget types, plus `channel-id` for channel widgets. The SDK handles the encoding internally.
|
|
208
222
|
|
|
@@ -218,21 +232,23 @@ Custom elements don't need a container div — they size themselves using `width
|
|
|
218
232
|
|
|
219
233
|
### User Identifier Attributes
|
|
220
234
|
|
|
221
|
-
Pass
|
|
235
|
+
> **Access Key Embed:** Do **not** put identifiers in HTML. Pass them inside the `userIdentifiers` object when exchanging your access credentials for an embed token (Step 2). Identity is cryptographically signed into the token so it cannot be tampered with from the browser.
|
|
236
|
+
>
|
|
237
|
+
> **Public Embed:** Pass any `data-*` attribute to identify the current user. Which identifiers are available is configured per community in your dashboard.
|
|
222
238
|
|
|
223
239
|
```html
|
|
240
|
+
<!-- Public Embed — identifiers in HTML -->
|
|
224
241
|
<script src="https://unpkg.com/@returningai/widget-sdk/dist/rai-widget.iife.js"
|
|
225
242
|
data-widget-id="YOUR_WIDGET_ID"
|
|
226
243
|
data-widget-type="store"
|
|
227
244
|
data-email="user@example.com"
|
|
228
245
|
data-user-id="12345"
|
|
229
246
|
data-account-id="abc"
|
|
230
|
-
api-url="YOUR_API_URL"
|
|
231
247
|
widget-url="YOUR_WIDGET_URL"
|
|
232
248
|
></script>
|
|
233
249
|
```
|
|
234
250
|
|
|
235
|
-
|
|
251
|
+
In Public Embed mode, any `data-*` attribute not reserved by the SDK is forwarded to the auth API as a user identifier.
|
|
236
252
|
|
|
237
253
|
---
|
|
238
254
|
|
|
@@ -240,7 +256,12 @@ Any `data-*` attribute not reserved by the SDK is forwarded to the auth API as a
|
|
|
240
256
|
|
|
241
257
|
When you set the `bundle-url` attribute, the widget renders directly in the page DOM instead of inside an iframe. This gives full CSS cascade — `html[data-theme]` and Tailwind classes apply to the widget content naturally.
|
|
242
258
|
|
|
243
|
-
`widget-url` is not needed in bundle mode
|
|
259
|
+
- `widget-url` is **not** needed in bundle mode (the widget is loaded directly from `bundle-url`).
|
|
260
|
+
- `api-url` is optional. The SDK resolves the widget auth server from `domain-key` when provided, or defaults to production.
|
|
261
|
+
- `domain-key` is optional. When omitted, the SDK defaults to production (`PROD`).
|
|
262
|
+
- Environment URL variables such as `window.api_url` are optional overrides. Standard `SGTR`, `STG`, and `PROD` environments resolve from `domain-key`.
|
|
263
|
+
|
|
264
|
+
Both examples below use Access Key Embed and target staging. Omit `domain-key` for production.
|
|
244
265
|
|
|
245
266
|
```html
|
|
246
267
|
<!-- Script-tag approach -->
|
|
@@ -249,20 +270,18 @@ When you set the `bundle-url` attribute, the widget renders directly in the page
|
|
|
249
270
|
data-widget-id="YOUR_WIDGET_ID"
|
|
250
271
|
data-widget-type="store"
|
|
251
272
|
data-theme="dark"
|
|
252
|
-
data-
|
|
273
|
+
data-embed-token="eyJ..."
|
|
253
274
|
data-bundle-url="YOUR_BUNDLE_URL"
|
|
254
|
-
data-domain-key="
|
|
255
|
-
api-url="YOUR_API_URL"
|
|
275
|
+
data-domain-key="STG"
|
|
256
276
|
data-eager
|
|
257
277
|
></script>
|
|
258
278
|
|
|
259
279
|
<!-- Custom element approach -->
|
|
260
280
|
<rai-store-widget
|
|
261
281
|
community-id="YOUR_COMMUNITY_ID"
|
|
262
|
-
api-url="YOUR_API_URL"
|
|
263
282
|
bundle-url="YOUR_BUNDLE_URL"
|
|
264
|
-
domain-key="
|
|
265
|
-
|
|
283
|
+
domain-key="STG"
|
|
284
|
+
embed-token="eyJ..."
|
|
266
285
|
theme="dark"
|
|
267
286
|
width="100%"
|
|
268
287
|
height="100vh"
|
|
@@ -288,7 +307,9 @@ The bundle must export a `mount(container, config)` function on its global (e.g.
|
|
|
288
307
|
|
|
289
308
|
## Framework Usage (Custom Elements)
|
|
290
309
|
|
|
291
|
-
When using a frontend framework (React, Vue, Angular), you can use custom HTML element tags instead of the script-tag method. Custom elements use raw
|
|
310
|
+
When using a frontend framework (React, Vue, Angular), you can use custom HTML element tags instead of the script-tag method. Custom elements use raw ObjectIds (`community-id`, `channel-id`) instead of the pre-encoded `data-widget-id` — the SDK handles the encoding internally. (Exception: `<rai-custom-widget>` uses `widget-id` with a base64-encoded value — see the [attributes table](#custom-element-attributes).)
|
|
311
|
+
|
|
312
|
+
All examples below use **Access Key Embed** — pass the short-lived token your server minted into `embed-token`. For [Public Embed](#user-identifier-attributes), replace `embed-token` with `data-*` identifier attributes.
|
|
292
313
|
|
|
293
314
|
### Plain HTML
|
|
294
315
|
|
|
@@ -299,8 +320,7 @@ When using a frontend framework (React, Vue, Angular), you can use custom HTML e
|
|
|
299
320
|
<rai-store-widget
|
|
300
321
|
community-id="YOUR_COMMUNITY_ID"
|
|
301
322
|
theme="dark"
|
|
302
|
-
|
|
303
|
-
api-url="YOUR_API_URL"
|
|
323
|
+
embed-token="eyJ..."
|
|
304
324
|
widget-url="YOUR_WIDGET_URL"
|
|
305
325
|
></rai-store-widget>
|
|
306
326
|
|
|
@@ -309,8 +329,7 @@ When using a frontend framework (React, Vue, Angular), you can use custom HTML e
|
|
|
309
329
|
community-id="YOUR_COMMUNITY_ID"
|
|
310
330
|
channel-id="YOUR_CHANNEL_ID"
|
|
311
331
|
theme="dark"
|
|
312
|
-
|
|
313
|
-
api-url="YOUR_API_URL"
|
|
332
|
+
embed-token="eyJ..."
|
|
314
333
|
widget-url="YOUR_WIDGET_URL"
|
|
315
334
|
></rai-channel-widget>
|
|
316
335
|
```
|
|
@@ -322,26 +341,24 @@ Types are included — no manual JSX declarations needed.
|
|
|
322
341
|
```tsx
|
|
323
342
|
import '@returningai/widget-sdk'
|
|
324
343
|
|
|
325
|
-
export function StoreEmbed({
|
|
344
|
+
export function StoreEmbed({ embedToken }: { embedToken: string }) {
|
|
326
345
|
return (
|
|
327
346
|
<rai-store-widget
|
|
328
347
|
community-id="YOUR_COMMUNITY_ID"
|
|
329
348
|
theme="dark"
|
|
330
|
-
|
|
331
|
-
api-url="YOUR_API_URL"
|
|
349
|
+
embed-token={embedToken}
|
|
332
350
|
widget-url="YOUR_WIDGET_URL"
|
|
333
351
|
/>
|
|
334
352
|
)
|
|
335
353
|
}
|
|
336
354
|
|
|
337
|
-
export function ChannelEmbed({
|
|
355
|
+
export function ChannelEmbed({ embedToken }: { embedToken: string }) {
|
|
338
356
|
return (
|
|
339
357
|
<rai-channel-widget
|
|
340
358
|
community-id="YOUR_COMMUNITY_ID"
|
|
341
359
|
channel-id="YOUR_CHANNEL_ID"
|
|
342
360
|
theme="dark"
|
|
343
|
-
|
|
344
|
-
api-url="YOUR_API_URL"
|
|
361
|
+
embed-token={embedToken}
|
|
345
362
|
widget-url="YOUR_WIDGET_URL"
|
|
346
363
|
/>
|
|
347
364
|
)
|
|
@@ -353,6 +370,7 @@ export function ChannelEmbed({ email }: { email: string }) {
|
|
|
353
370
|
```vue
|
|
354
371
|
<script setup>
|
|
355
372
|
import '@returningai/widget-sdk'
|
|
373
|
+
defineProps({ embedToken: String })
|
|
356
374
|
</script>
|
|
357
375
|
|
|
358
376
|
<template>
|
|
@@ -360,8 +378,7 @@ import '@returningai/widget-sdk'
|
|
|
360
378
|
<rai-store-widget
|
|
361
379
|
community-id="YOUR_COMMUNITY_ID"
|
|
362
380
|
theme="dark"
|
|
363
|
-
:
|
|
364
|
-
api-url="YOUR_API_URL"
|
|
381
|
+
:embed-token="embedToken"
|
|
365
382
|
widget-url="YOUR_WIDGET_URL"
|
|
366
383
|
/>
|
|
367
384
|
|
|
@@ -370,8 +387,7 @@ import '@returningai/widget-sdk'
|
|
|
370
387
|
community-id="YOUR_COMMUNITY_ID"
|
|
371
388
|
channel-id="YOUR_CHANNEL_ID"
|
|
372
389
|
theme="dark"
|
|
373
|
-
:
|
|
374
|
-
api-url="YOUR_API_URL"
|
|
390
|
+
:embed-token="embedToken"
|
|
375
391
|
widget-url="YOUR_WIDGET_URL"
|
|
376
392
|
/>
|
|
377
393
|
</template>
|
|
@@ -392,8 +408,7 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
|
|
|
392
408
|
<rai-store-widget
|
|
393
409
|
community-id="YOUR_COMMUNITY_ID"
|
|
394
410
|
theme="dark"
|
|
395
|
-
[attr.
|
|
396
|
-
api-url="YOUR_API_URL"
|
|
411
|
+
[attr.embed-token]="embedToken"
|
|
397
412
|
widget-url="YOUR_WIDGET_URL"
|
|
398
413
|
></rai-store-widget>
|
|
399
414
|
|
|
@@ -402,8 +417,7 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
|
|
|
402
417
|
community-id="YOUR_COMMUNITY_ID"
|
|
403
418
|
channel-id="YOUR_CHANNEL_ID"
|
|
404
419
|
theme="dark"
|
|
405
|
-
[attr.
|
|
406
|
-
api-url="YOUR_API_URL"
|
|
420
|
+
[attr.embed-token]="embedToken"
|
|
407
421
|
widget-url="YOUR_WIDGET_URL"
|
|
408
422
|
></rai-channel-widget>
|
|
409
423
|
```
|
|
@@ -431,7 +445,7 @@ Listen for widget lifecycle events:
|
|
|
431
445
|
| `rai-authenticated` | `{}` | Auth succeeded, before widget mounts |
|
|
432
446
|
| `rai-ready` | `{}` | `WIDGET_READY` received, loader hidden (iframe mode) |
|
|
433
447
|
| `rai-mounted` | `{}` | Widget bundle mounted successfully (bundle mode) |
|
|
434
|
-
| `rai-error` | `{ message }` | Auth failed after all retries |
|
|
448
|
+
| `rai-error` | `{ message, hint?, status? }` | Auth failed after all retries. `message` is the backend error text (e.g. `"Invalid or expired embed token"`), `hint` is the optional human-readable suggestion, `status` is the HTTP status code of the failing response. |
|
|
435
449
|
| `rai-logout` | `{}` | Widget logged out |
|
|
436
450
|
| `rai-height-change` | `{ height }` | iframe resized (after debounce) |
|
|
437
451
|
|
|
@@ -445,7 +459,7 @@ const widget = document.querySelector('rai-store-widget')
|
|
|
445
459
|
widget.addEventListener('rai-authenticated', () => { /* auth succeeded */ })
|
|
446
460
|
widget.addEventListener('rai-ready', () => { /* widget loaded and visible (iframe mode) */ })
|
|
447
461
|
widget.addEventListener('rai-mounted', () => { /* widget mounted (bundle mode) */ })
|
|
448
|
-
widget.addEventListener('rai-error', (e) => console.error(e.detail.message))
|
|
462
|
+
widget.addEventListener('rai-error', (e) => console.error(e.detail.status, e.detail.message, e.detail.hint))
|
|
449
463
|
widget.addEventListener('rai-logout', () => { /* user logged out */ })
|
|
450
464
|
widget.addEventListener('rai-height-change', (e) => console.log(e.detail.height))
|
|
451
465
|
```
|