@gamaro.io/widget 0.6.0 → 1.0.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/README.md +47 -45
- package/dist/iframe-loader.d.ts +5 -5
- package/dist/index.d.ts +4 -4
- package/dist/loader.d.ts +4 -4
- package/dist/postmessage.d.ts +2 -2
- package/dist/types.d.ts +6 -6
- package/dist/widget.es.js +3096 -1778
- package/dist/widget.umd.js +50 -32
- package/package.json +18 -13
package/README.md
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
[](#typescript)
|
|
6
6
|
[](./LICENSE)
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
Gamaro Widget SDK — embed a conversational conversion agent that grounds every
|
|
9
|
+
response in **your** site's own data (catalogue, inventory, CRM, knowledge base)
|
|
10
|
+
instead of the undifferentiated public training data a generic LLM assistant
|
|
11
|
+
would otherwise draw on.
|
|
11
12
|
|
|
12
13
|
## Table of Contents
|
|
13
14
|
|
|
@@ -71,7 +72,7 @@ the cost of having to bump it manually on every release.
|
|
|
71
72
|
### Programmatic API
|
|
72
73
|
|
|
73
74
|
The minimal integration is one line — every visual and behavioural aspect
|
|
74
|
-
(theme, position, language, open-state, branding) is configured in the **
|
|
75
|
+
(theme, position, language, open-state, branding) is configured in the **Gamaro
|
|
75
76
|
admin portal** for your Agent and resolved server-side from the API key.
|
|
76
77
|
|
|
77
78
|
```typescript
|
|
@@ -93,16 +94,16 @@ widget.destroy();
|
|
|
93
94
|
Two reasons most platforms fail to convert mobile visitors, and two reasons this
|
|
94
95
|
widget does:
|
|
95
96
|
|
|
96
|
-
1. **It
|
|
97
|
-
from your catalogue, your stock, your CRM, your knowledge
|
|
98
|
-
competitors and generic AI assistants don't have.
|
|
97
|
+
1. **It grounds every answer in your own data, not generic AI training data.**
|
|
98
|
+
The agent answers from your catalogue, your stock, your CRM, your knowledge
|
|
99
|
+
base — what your competitors and generic AI assistants don't have.
|
|
99
100
|
2. **It is driven by your thumb, not your keyboard.** The LLM dynamically picks
|
|
100
101
|
the right component at every turn — quick replies, sliders, product cards —
|
|
101
102
|
instead of forcing a form. Visitors qualify their need in a few taps on
|
|
102
103
|
mobile, where 3+ field forms lose 50%+ of users (HubSpot).
|
|
103
104
|
|
|
104
105
|
The widget rendering layer (`QuickReplies`, `PropertyCard`, `ActionButtons`) is
|
|
105
|
-
the runtime that materialises this. Schemas live in the
|
|
106
|
+
the runtime that materialises this. Schemas live in the Gamaro backend
|
|
106
107
|
repository and are out of scope for the SDK consumer.
|
|
107
108
|
|
|
108
109
|
## Configuration
|
|
@@ -125,22 +126,22 @@ context (DOM, identity, environment).
|
|
|
125
126
|
| `userId` | `string` | - | Host-side stable user identifier — must be paired with `userHash`. |
|
|
126
127
|
| `userHash` | `string` | - | HMAC-SHA256 of `email` (or `userId`), signed with the Agent identity secret. See _Identity_. |
|
|
127
128
|
|
|
128
|
-
### 2. Server-resolved (configured in the
|
|
129
|
+
### 2. Server-resolved (configured in the Gamaro admin portal)
|
|
129
130
|
|
|
130
131
|
These are **not** passed by the integration — they are stored in the Agent's
|
|
131
132
|
`widget_config` JSONB row and fetched at bootstrap from the API key. To change
|
|
132
133
|
any of them, edit the Agent in the portal.
|
|
133
134
|
|
|
134
|
-
| Field | Configured in admin | Notes
|
|
135
|
-
| ----------------- | -------------------------- |
|
|
136
|
-
| `theme` | Apparence → palette | Full palette (`primaryColor`, `backgroundColor`, `textColor`, `borderRadius`, `fontFamily`, `colorScheme`).
|
|
137
|
-
| `position` | Apparence → position | `"bottom-right"`, `"bottom-left"`, or `"inline"`.
|
|
138
|
-
| `language` | Apparence → langue | ISO 639-1 (e.g. `fr`, `en`). Falls back to browser language when unset.
|
|
139
|
-
| `showProfile` | Apparence → panneau profil |
|
|
140
|
-
| `open` | Apparence → état initial | Default open state on page load. Host can still call `widget.open()` programmatically.
|
|
141
|
-
| `brand.title` | Branding → titre | Custom header title (falls back to a vertical-specific default).
|
|
142
|
-
| `brand.avatarUrl` | Branding → avatar | Custom avatar URL (must originate from the portal upload — arbitrary URLs are rejected).
|
|
143
|
-
| `vertical` | Agent creation | `real-estate`, `b2b-qualification`, … Bound to the API key.
|
|
135
|
+
| Field | Configured in admin | Notes |
|
|
136
|
+
| ----------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
137
|
+
| `theme` | Apparence → palette | Full palette (`primaryColor`, `backgroundColor`, `textColor`, `borderRadius`, `fontFamily`, `colorScheme`). |
|
|
138
|
+
| `position` | Apparence → position | `"bottom-right"`, `"bottom-left"`, or `"inline"`. |
|
|
139
|
+
| `language` | Apparence → langue | ISO 639-1 (e.g. `fr`, `en`). Falls back to browser language when unset. |
|
|
140
|
+
| `showProfile` | Apparence → panneau profil | Forces the profile panel visible from the start of the conversation. The panel already shows on its own once the visitor's profile has data, regardless of this flag. |
|
|
141
|
+
| `open` | Apparence → état initial | Default open state on page load. Host can still call `widget.open()` programmatically. |
|
|
142
|
+
| `brand.title` | Branding → titre | Custom header title (falls back to a vertical-specific default). |
|
|
143
|
+
| `brand.avatarUrl` | Branding → avatar | Custom avatar URL (must originate from the portal upload — arbitrary URLs are rejected). |
|
|
144
|
+
| `vertical` | Agent creation | `real-estate`, `b2b-qualification`, … Bound to the API key. |
|
|
144
145
|
|
|
145
146
|
### 3. Client overrides (advanced — rarely needed in production)
|
|
146
147
|
|
|
@@ -199,7 +200,7 @@ const widget = createWidget({
|
|
|
199
200
|
});
|
|
200
201
|
```
|
|
201
202
|
|
|
202
|
-
###
|
|
203
|
+
### GamaroWidget Methods
|
|
203
204
|
|
|
204
205
|
| Method | Description |
|
|
205
206
|
| ----------------------------------------------------- | -------------------------------------------------------- |
|
|
@@ -215,15 +216,15 @@ const widget = createWidget({
|
|
|
215
216
|
|
|
216
217
|
### Window API (Script Tag)
|
|
217
218
|
|
|
218
|
-
When using the script tag, the API is available on `window.
|
|
219
|
+
When using the script tag, the API is available on `window.Gamaro`:
|
|
219
220
|
|
|
220
221
|
```javascript
|
|
221
|
-
window.
|
|
222
|
-
window.
|
|
223
|
-
window.
|
|
222
|
+
window.Gamaro.open();
|
|
223
|
+
window.Gamaro.close();
|
|
224
|
+
window.Gamaro.setTheme({ primaryColor: "#10B981" });
|
|
224
225
|
|
|
225
226
|
// Wire your own dark-mode toggle to the widget:
|
|
226
|
-
window.
|
|
227
|
+
window.Gamaro.setColorScheme("dark"); // or "light", or "auto"
|
|
227
228
|
```
|
|
228
229
|
|
|
229
230
|
## Events
|
|
@@ -281,7 +282,7 @@ The package includes full TypeScript support with exported types:
|
|
|
281
282
|
import type {
|
|
282
283
|
WidgetConfig,
|
|
283
284
|
ThemeConfig,
|
|
284
|
-
|
|
285
|
+
GamaroWidget,
|
|
285
286
|
WidgetEventType,
|
|
286
287
|
WidgetProfile,
|
|
287
288
|
WidgetMessage,
|
|
@@ -307,7 +308,7 @@ vertical = creating a new Agent + new key.
|
|
|
307
308
|
### Real-Estate flow
|
|
308
309
|
|
|
309
310
|
When the resolved vertical is `real-estate`, the widget runs in qualification
|
|
310
|
-
mode:
|
|
311
|
+
mode: Gamaro qualifies the buyer through conversation and emits the profile — no
|
|
311
312
|
property data is needed from the integrator (data-dependent tools like
|
|
312
313
|
`searchProperties`, `getCityStats`, `estimateProperty` are automatically
|
|
313
314
|
excluded).
|
|
@@ -381,10 +382,10 @@ createWidget({
|
|
|
381
382
|
"use client";
|
|
382
383
|
|
|
383
384
|
import { useEffect, useRef } from "react";
|
|
384
|
-
import { createWidget, type
|
|
385
|
+
import { createWidget, type GamaroWidget } from "@gamaro.io/widget";
|
|
385
386
|
|
|
386
387
|
export function ContactWidget() {
|
|
387
|
-
const widgetRef = useRef<
|
|
388
|
+
const widgetRef = useRef<GamaroWidget | null>(null);
|
|
388
389
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
389
390
|
|
|
390
391
|
useEffect(() => {
|
|
@@ -448,7 +449,7 @@ attestation, the host `Permissions-Policy`, and your `Content-Security-Policy`.
|
|
|
448
449
|
### Identity verification (HMAC)
|
|
449
450
|
|
|
450
451
|
By default a visitor is anonymous. If your page already knows who the visitor is
|
|
451
|
-
(a logged-in user), you can attest that identity to
|
|
452
|
+
(a logged-in user), you can attest that identity to Gamaro so leads are attached
|
|
452
453
|
to the right account — without trusting a client-supplied email blindly.
|
|
453
454
|
|
|
454
455
|
Pass `email` (or `userId`) **together with** a `userHash`: an HMAC-SHA256 of the
|
|
@@ -507,7 +508,7 @@ conversation still works; the visitor just types the city manually.
|
|
|
507
508
|
Permissions-Policy controls **what the iframe is allowed to do**;
|
|
508
509
|
Content-Security-Policy controls **where scripts / iframes / styles can come
|
|
509
510
|
from**. Both are independent and both are needed in production. The CSP
|
|
510
|
-
directives required for the
|
|
511
|
+
directives required for the Gamaro widget are documented in the Gamaro backend
|
|
511
512
|
repo at `docs/B2B_INTEGRATION.md` § "Content-Security-Policy pour intégrateurs".
|
|
512
513
|
|
|
513
514
|
## E2E Test Selectors (data-testid)
|
|
@@ -516,21 +517,22 @@ For a smoke test that the widget mounted and works on your page, a small core of
|
|
|
516
517
|
`data-testid` selectors is exposed. These are guaranteed not to change without a
|
|
517
518
|
major version bump.
|
|
518
519
|
|
|
519
|
-
| Selector
|
|
520
|
-
|
|
|
521
|
-
| `widget-root`
|
|
522
|
-
| `widget-input`
|
|
523
|
-
| `widget-send`
|
|
524
|
-
| `widget-message`
|
|
525
|
-
| `widget-loading-status`
|
|
526
|
-
| `widget-suggestion`
|
|
527
|
-
| `widget-cta-
|
|
528
|
-
| `widget-
|
|
520
|
+
| Selector | Element | Additional attributes |
|
|
521
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
|
|
522
|
+
| `widget-root` | Chat container (open) | — |
|
|
523
|
+
| `widget-input` | Message input field | — |
|
|
524
|
+
| `widget-send` | Send button | — |
|
|
525
|
+
| `widget-message` | Message bubble | `data-role="user" \| "assistant"` |
|
|
526
|
+
| `widget-loading-status` | Running-tool status label beside the typing dots (e.g. "Recherche de biens…") | — (absent until a tool runs) |
|
|
527
|
+
| `widget-suggestion` | Quick reply chip | `data-index="<N>"` (position) |
|
|
528
|
+
| `widget-cta-summary-continue` | Pre-CTA recap card "Continue" button (#3028) — precedes `widget-cta-button` when the visitor's profile has display config for the active vertical | — (absent otherwise, `widget-cta-button` mounts directly) |
|
|
529
|
+
| `widget-cta-button` | Call-to-action button | `data-objective="<objectiveType>"` |
|
|
530
|
+
| `widget-avatar` | Header avatar | — |
|
|
529
531
|
|
|
530
532
|
> The widget also exposes a large set of vertical-specific selectors
|
|
531
533
|
> (real-estate map, areas-overview, exploration mode, criteria popup, range
|
|
532
|
-
> slider, contact form). They are internal to the
|
|
533
|
-
> SDK consumers — the full contract lives in the
|
|
534
|
+
> slider, contact form). They are internal to the Gamaro UI and out of scope for
|
|
535
|
+
> SDK consumers — the full contract lives in the Gamaro backend repository under
|
|
534
536
|
> `apps/app/src/app/widget/embed/components/`.
|
|
535
537
|
|
|
536
538
|
### Example (Playwright)
|
|
@@ -612,7 +614,7 @@ Lighthouse manually:
|
|
|
612
614
|
analytics pipeline (Google Analytics 4, Sentry, etc.) to track field LCP per
|
|
613
615
|
real visitor — Lighthouse alone only measures synthetic loads.
|
|
614
616
|
|
|
615
|
-
The
|
|
617
|
+
The Gamaro widget itself does not emit web-vitals events (out of scope — the SDK
|
|
616
618
|
should not impose an analytics dependency on the host). Integrators own the
|
|
617
619
|
measurement pipeline for their own page.
|
|
618
620
|
|
|
@@ -656,7 +658,7 @@ Commercial Source-available — see [LICENSE](./LICENSE).
|
|
|
656
658
|
This is **not** an open-source release: the source is published so integrators
|
|
657
659
|
can audit what runs in their visitors' browsers, but fork / redistribution /
|
|
658
660
|
competing-SDK use are prohibited without a written agreement. Production use
|
|
659
|
-
against the
|
|
661
|
+
against the Gamaro backend is governed by the Gamaro Commercial Terms of
|
|
660
662
|
Service.
|
|
661
663
|
|
|
662
664
|
For commercial licensing inquiries: admin@dolard.eu
|
package/dist/iframe-loader.d.ts
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Promotes a skeleton placeholder into an operational iframe with a per-attempt
|
|
5
5
|
* timeout and a configurable backoff between retries. Single responsibility —
|
|
6
|
-
* the host (`
|
|
6
|
+
* the host (`GamaroWidget`) keeps the application FSM, this module owns the
|
|
7
7
|
* mechanics of getting the iframe up.
|
|
8
8
|
*
|
|
9
|
-
* Success criterion: iframe `load` event AND a `
|
|
9
|
+
* Success criterion: iframe `load` event AND a `gamaro:ready` postMessage from
|
|
10
10
|
* the embed React app. The AND is mandatory — a 5xx Next page rendered inside
|
|
11
11
|
* the iframe still fires `load`; relying on that alone would mask deployment
|
|
12
12
|
* failures as silent successes.
|
|
@@ -48,7 +48,7 @@ export interface IframeLoaderOptions {
|
|
|
48
48
|
buildIframe: () => HTMLIFrameElement;
|
|
49
49
|
/** DOM node the iframe will be appended to. */
|
|
50
50
|
container: HTMLElement;
|
|
51
|
-
/** Allowed origins for the `
|
|
51
|
+
/** Allowed origins for the `gamaro:ready` ack (passed to `isValidOrigin`). */
|
|
52
52
|
allowedOrigins: string[];
|
|
53
53
|
/** Per-attempt timeout in ms. Defaults to `IFRAME_LOAD_TIMEOUT_MS`. */
|
|
54
54
|
timeoutMs?: number;
|
|
@@ -69,10 +69,10 @@ export declare class IframeLoadError extends Error {
|
|
|
69
69
|
* success; throws `IframeLoadError` (reason + final attempt count) on final
|
|
70
70
|
* failure, or `DOMException("AbortError")` when `opts.signal` aborts.
|
|
71
71
|
*
|
|
72
|
-
* The `
|
|
72
|
+
* The `gamaro:ready` message is observed via a LOCAL listener that is detached
|
|
73
73
|
* the moment the handshake completes — the caller is expected to attach its
|
|
74
74
|
* own applicative listener AFTER this resolves, and to manually set
|
|
75
75
|
* `isReady = true` + send any post-ready commands, since the embed React app
|
|
76
|
-
* only emits `
|
|
76
|
+
* only emits `gamaro:ready` once on mount.
|
|
77
77
|
*/
|
|
78
78
|
export declare function loadIframeWithRetry(opts: IframeLoaderOptions): Promise<HTMLIFrameElement>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Gamaro Widget SDK
|
|
3
3
|
*
|
|
4
4
|
* Entry point for the widget SDK. Supports both auto-initialization from
|
|
5
5
|
* script tags and programmatic usage.
|
|
@@ -34,14 +34,14 @@
|
|
|
34
34
|
* admin sandbox's live-preview use case (client-wins merge). Partner
|
|
35
35
|
* integrators should configure those fields from the admin portal.
|
|
36
36
|
*/
|
|
37
|
-
import {
|
|
37
|
+
import { GamaroWidget, createWidget } from "./loader";
|
|
38
38
|
import type { WidgetConfig } from "./types";
|
|
39
|
-
export { createWidget,
|
|
39
|
+
export { createWidget, GamaroWidget };
|
|
40
40
|
export { parseScriptAttributes as __parseScriptAttributes };
|
|
41
41
|
export { getCurrentScript as __getCurrentScript };
|
|
42
42
|
export { autoInit as __autoInit };
|
|
43
43
|
export { themeConfigSchema, widgetPositionSchema, widgetConfigSchema, b2bProfileSchema, widgetMessageSchema, applicationConfigResponseSchema, } from "./types";
|
|
44
|
-
export type { WidgetConfig, WidgetPosition, ColorScheme, ThemeConfig, B2BProfile, WidgetProfile, WidgetMessage, WidgetEvent, WidgetEventType, WidgetEventHandler,
|
|
44
|
+
export type { WidgetConfig, WidgetPosition, ColorScheme, ThemeConfig, B2BProfile, WidgetProfile, WidgetMessage, WidgetEvent, WidgetEventType, WidgetEventHandler, GamaroAPI, ApplicationConfigResponse, } from "./types";
|
|
45
45
|
export { fetchApplicationConfig, ConfigFetchError } from "./config";
|
|
46
46
|
/**
|
|
47
47
|
* Parse script tag data attributes to extract widget config (#726).
|
package/dist/loader.d.ts
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* - postMessage communication
|
|
7
7
|
* - Public API exposure
|
|
8
8
|
*/
|
|
9
|
-
import type { WidgetConfig, WidgetEventType, WidgetEventHandler,
|
|
9
|
+
import type { WidgetConfig, WidgetEventType, WidgetEventHandler, GamaroAPI, ColorScheme, ThemeConfig } from "./types";
|
|
10
10
|
export declare function __resetInstanceCounter(): void;
|
|
11
|
-
export declare class
|
|
11
|
+
export declare class GamaroWidget implements GamaroAPI {
|
|
12
12
|
readonly version = "0.1.0";
|
|
13
13
|
/**
|
|
14
14
|
* Original config as passed by the caller — preserved separately from
|
|
@@ -100,7 +100,7 @@ export declare class VersiqWidget implements VersiqAPI {
|
|
|
100
100
|
private init;
|
|
101
101
|
/**
|
|
102
102
|
* Strip any path from `baseUrl` so the resulting string matches the
|
|
103
|
-
* `event.origin` field of a `
|
|
103
|
+
* `event.origin` field of a `gamaro:ready` postMessage (which is always
|
|
104
104
|
* scheme + host + port, no path). Falls back to the raw value if parsing
|
|
105
105
|
* fails so a malformed config does not silently break the loader gate.
|
|
106
106
|
*/
|
|
@@ -143,4 +143,4 @@ export declare class VersiqWidget implements VersiqAPI {
|
|
|
143
143
|
/**
|
|
144
144
|
* Create a new widget instance.
|
|
145
145
|
*/
|
|
146
|
-
export declare function createWidget(config: WidgetConfig):
|
|
146
|
+
export declare function createWidget(config: WidgetConfig): GamaroWidget;
|
package/dist/postmessage.d.ts
CHANGED
|
@@ -15,9 +15,9 @@ import type { WidgetCommand, WidgetEvent } from "./types";
|
|
|
15
15
|
*/
|
|
16
16
|
export declare function isValidOrigin(origin: string, allowedOrigins: string[]): boolean;
|
|
17
17
|
/**
|
|
18
|
-
* Check if an event contains a valid
|
|
18
|
+
* Check if an event contains a valid Gamaro message.
|
|
19
19
|
*/
|
|
20
|
-
export declare function
|
|
20
|
+
export declare function isGamaroMessage(event: MessageEvent): event is MessageEvent<WidgetCommand | WidgetEvent>;
|
|
21
21
|
/**
|
|
22
22
|
* Send a command to the widget iframe.
|
|
23
23
|
*/
|
package/dist/types.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* re-exports them so existing consumers (`apps/marketing`,
|
|
7
7
|
* `apps/app/src/components/portal/sandbox`) keep working unchanged. The only
|
|
8
8
|
* types still defined locally are widget-specific SDK surfaces (B2B profile
|
|
9
|
-
* schemas, `
|
|
9
|
+
* schemas, `GamaroAPI`, `window` augmentation).
|
|
10
10
|
*/
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
import type { ColorScheme, ThemeConfig, WidgetEventHandler, WidgetEventType } from "@gamaro.io/core-types";
|
|
@@ -145,9 +145,9 @@ export declare const b2bProfileSchema: z.ZodObject<{
|
|
|
145
145
|
}, z.core.$strip>;
|
|
146
146
|
export type B2BProfile = z.infer<typeof b2bProfileSchema>;
|
|
147
147
|
/**
|
|
148
|
-
* Public API exposed on window.
|
|
148
|
+
* Public API exposed on window.Gamaro.
|
|
149
149
|
*/
|
|
150
|
-
export interface
|
|
150
|
+
export interface GamaroAPI {
|
|
151
151
|
/** Application ID (available after config resolution) */
|
|
152
152
|
readonly applicationId: string;
|
|
153
153
|
/** Open the widget */
|
|
@@ -161,7 +161,7 @@ export interface VersiqAPI {
|
|
|
161
161
|
/**
|
|
162
162
|
* Update only the color scheme. Sugar over `setTheme({ colorScheme })` so
|
|
163
163
|
* integrators can wire their own dark-mode toggle without rebuilding the
|
|
164
|
-
* full theme object: `window.
|
|
164
|
+
* full theme object: `window.Gamaro.setColorScheme("dark")`.
|
|
165
165
|
*/
|
|
166
166
|
setColorScheme(scheme: ColorScheme): void;
|
|
167
167
|
/** Identify the current user with host-attested HMAC verification */
|
|
@@ -179,7 +179,7 @@ export interface VersiqAPI {
|
|
|
179
179
|
}
|
|
180
180
|
declare global {
|
|
181
181
|
interface Window {
|
|
182
|
-
|
|
183
|
-
|
|
182
|
+
Gamaro?: GamaroAPI;
|
|
183
|
+
GamaroApps?: Map<string, GamaroAPI>;
|
|
184
184
|
}
|
|
185
185
|
}
|