@helpai/elements 1.8.0 → 1.9.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 +34 -12
- package/configurator.mjs +1 -1
- package/docs/README.md +183 -0
- package/docs/analytics.md +551 -0
- package/docs/api-reference.md +622 -0
- package/docs/browser-support.md +302 -0
- package/docs/configuration.md +1001 -0
- package/docs/events-and-hooks.md +483 -0
- package/docs/faq.md +435 -0
- package/docs/frameworks.md +640 -0
- package/docs/installation.md +626 -0
- package/docs/options.md +323 -0
- package/docs/quickstart.md +229 -0
- package/docs/recipes.md +725 -0
- package/docs/security-privacy.md +575 -0
- package/docs/theming.md +570 -0
- package/docs/troubleshooting.md +523 -0
- package/elements-web-component.esm.js +39 -39
- package/elements-web-component.esm.js.map +4 -4
- package/elements.cjs.js +39 -39
- package/elements.cjs.js.map +4 -4
- package/elements.esm.js +39 -39
- package/elements.esm.js.map +4 -4
- package/elements.js +39 -39
- package/elements.js.map +4 -4
- package/index.d.ts +84 -3
- package/index.mjs +13 -13
- package/jsx-react.d.ts +15 -0
- package/jsx-svelte.d.ts +14 -0
- package/jsx-vue.d.ts +14 -0
- package/llms-full.txt +7862 -0
- package/llms.txt +36 -0
- package/loader.js +3 -3
- package/loader.min.js +1 -1
- package/package.json +36 -1
- package/react.d.ts +3552 -0
- package/react.mjs +62 -0
- package/schema.d.ts +56 -0
- package/schema.json +24 -2
- package/schema.mjs +1 -1
- package/web-component.d.ts +1561 -17
- package/web-component.mjs +14 -14
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
# API reference
|
|
2
|
+
|
|
3
|
+
Compact lookup for the SDK's exported functions, types, and events.
|
|
4
|
+
For explanations + examples, see the [Configuration](./configuration.md)
|
|
5
|
+
and [Events & hooks](./events-and-hooks.md) guides.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Exports
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import {
|
|
13
|
+
// Functions
|
|
14
|
+
init, // Mount (or re-config) a widget
|
|
15
|
+
mount, // Mount a new widget (non-idempotent)
|
|
16
|
+
destroy, // Unmount one or all widgets
|
|
17
|
+
hook, // Register a global lifecycle hook
|
|
18
|
+
getInstance, // Look up a live instance
|
|
19
|
+
getAllInstances, // Get every live instance
|
|
20
|
+
|
|
21
|
+
// Constants
|
|
22
|
+
version, // Semver string
|
|
23
|
+
brand, // { id, displayName, cssPrefix, cdnUrl, ... }
|
|
24
|
+
HOOK_WILDCARD, // "*" — wildcard for hook() arguments
|
|
25
|
+
|
|
26
|
+
// Types
|
|
27
|
+
type ChatWidgetOptions,
|
|
28
|
+
type ChatWidgetInstance,
|
|
29
|
+
type ResolvedOptions,
|
|
30
|
+
type EventMap,
|
|
31
|
+
type EventName,
|
|
32
|
+
type HookListener,
|
|
33
|
+
type LogEntry,
|
|
34
|
+
type LogLevel,
|
|
35
|
+
} from '@helpai/elements';
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Web component sub-entry (auto-registers the custom element):
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import '@helpai/elements/web-component';
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
React kit (React 18+; everything above plus the component and the hook, so import it all from this one path):
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import {
|
|
48
|
+
HelpAI, // <HelpAI {...options} /> mounts the widget, re-configures it on prop changes, removes it on unmount
|
|
49
|
+
useHelpAI, // useHelpAI(widgetId?) → { state, ask, open, close, reset }, re-rendering on state changes
|
|
50
|
+
type HelpAIProps,
|
|
51
|
+
type HelpAIControls,
|
|
52
|
+
} from '@helpai/elements/react';
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
See [Frameworks → React](./frameworks.md#react).
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Functions
|
|
60
|
+
|
|
61
|
+
### `init(opts): ChatWidgetInstance`
|
|
62
|
+
|
|
63
|
+
Mount a widget (or re-config an existing one).
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
function init(opts: ChatWidgetOptions & { target?: HTMLElement }): ChatWidgetInstance;
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Idempotent — if an instance with the same `widgetId` exists, its
|
|
70
|
+
options are merged (via `update`) and the existing handle is
|
|
71
|
+
returned.
|
|
72
|
+
|
|
73
|
+
### `mount(opts): ChatWidgetInstance`
|
|
74
|
+
|
|
75
|
+
Force a fresh mount. If an instance exists at the same `widgetId`,
|
|
76
|
+
it's destroyed first.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
function mount(opts: ChatWidgetOptions & { target?: HTMLElement }): ChatWidgetInstance;
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Prefer `init()` — safer for SPA route changes.
|
|
83
|
+
|
|
84
|
+
### `destroy(widgetId?)`
|
|
85
|
+
|
|
86
|
+
Unmount one or all widgets.
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
function destroy(widgetId?: string): void;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- With `widgetId` — destroys that one.
|
|
93
|
+
- Without — destroys every widget on the page.
|
|
94
|
+
|
|
95
|
+
### `hook(widgetId, event, listener): () => void`
|
|
96
|
+
|
|
97
|
+
Register a global lifecycle hook. Fires for any widget matching
|
|
98
|
+
`widgetId` + `event`. Wildcards (`"*"`) match anything.
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
function hook(widgetId: string, event: string, listener: HookListener): () => void;
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Returns an unsubscribe function.
|
|
105
|
+
|
|
106
|
+
### `getInstance(widgetId?): ChatWidgetInstance | null`
|
|
107
|
+
|
|
108
|
+
Look up a live instance by id.
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
function getInstance(widgetId?: string): ChatWidgetInstance | null;
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`widgetId` defaults to `"default"`. Returns `null` if nothing is
|
|
115
|
+
mounted.
|
|
116
|
+
|
|
117
|
+
### `getAllInstances(): ChatWidgetInstance[]`
|
|
118
|
+
|
|
119
|
+
Returns every live widget instance on the page.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## `ChatWidgetInstance`
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
interface ChatWidgetInstance {
|
|
127
|
+
readonly widgetId: string;
|
|
128
|
+
|
|
129
|
+
// Panel control
|
|
130
|
+
open(target?: OpenTarget): void; // with a target: that tab, or one Help article / News post in it
|
|
131
|
+
close(): void;
|
|
132
|
+
expand(): void; // toggle normal ↔ expanded
|
|
133
|
+
openForm(id: string): void;
|
|
134
|
+
ask(text: string, options?: { send?: boolean }): void; // open the chat with `text` in the composer ({ send: true } sends it)
|
|
135
|
+
|
|
136
|
+
// State
|
|
137
|
+
readonly state: WidgetState; // { open, ready, unread, conversationId? }, live
|
|
138
|
+
readonly ready: Promise<void>; // resolves once connected
|
|
139
|
+
|
|
140
|
+
// Lifecycle
|
|
141
|
+
reset(): void; // start over as a new anonymous visitor (on logout)
|
|
142
|
+
destroy(): void;
|
|
143
|
+
|
|
144
|
+
// Events
|
|
145
|
+
on<E extends EventName>(name: E, fn: (payload: EventMap[E]) => void): () => void; // returns unsubscribe fn
|
|
146
|
+
|
|
147
|
+
// Re-config
|
|
148
|
+
update(patch: Partial<ChatWidgetOptions>): void;
|
|
149
|
+
|
|
150
|
+
// Host-asserted context (informational, not auth; re-handshakes, same visitor/conversation)
|
|
151
|
+
setUserContext(ctx: Partial<NonNullable<ChatWidgetOptions['userContext']>>): void; // merges into the current user context
|
|
152
|
+
clearUserContext(): void;
|
|
153
|
+
setPageContext(ctx: Partial<NonNullable<ChatWidgetOptions['pageContext']>>): void; // merges into the current page context
|
|
154
|
+
clearPageContext(): void;
|
|
155
|
+
|
|
156
|
+
// Runtime diagnostics (module-global across widget instances)
|
|
157
|
+
setDebug(level: LogLevel | boolean | number | string): void;
|
|
158
|
+
readonly debugLevel: () => LogLevel;
|
|
159
|
+
onLog(sink: ((entry: LogEntry) => void) | null): void;
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## `ChatWidgetOptions`
|
|
166
|
+
|
|
167
|
+
The generated, schema-backed field reference is
|
|
168
|
+
[`docs/api/configuration.md`](./options.md); it is authoritative.
|
|
169
|
+
The public input keeps embed identity, context, endpoint overrides, storage,
|
|
170
|
+
and callbacks at the top level. Serializable widget settings use focused
|
|
171
|
+
nested sections. `mount()` and `init()` require `aiAgentDeploymentId`; the
|
|
172
|
+
deployment `publicKey` remains optional for intentional guest mode.
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
init({
|
|
176
|
+
publicKey: 'agent_pk_...',
|
|
177
|
+
aiAgentDeploymentId: '01900000-0000-7000-8000-000000000000',
|
|
178
|
+
presentation: {
|
|
179
|
+
mode: 'inline',
|
|
180
|
+
position: 'bottom-right',
|
|
181
|
+
iframe: false,
|
|
182
|
+
size: { width: '420px', height: '640px' },
|
|
183
|
+
},
|
|
184
|
+
behavior: {
|
|
185
|
+
startMinimized: false,
|
|
186
|
+
responseMode: 'streaming',
|
|
187
|
+
disableMessageFeedback: false,
|
|
188
|
+
autoSendSuggestions: false,
|
|
189
|
+
popOutUrl: 'https://chat.example.com',
|
|
190
|
+
},
|
|
191
|
+
theme: 'auto',
|
|
192
|
+
launcher: { variant: 'pill', label: 'Ask AI' },
|
|
193
|
+
header: { actions: ['theme', 'textSize', 'popOut', 'history', 'close'] },
|
|
194
|
+
composer: {
|
|
195
|
+
sendButton: { shape: 'circle', icon: 'arrowUp', variant: 'filled' },
|
|
196
|
+
attachments: { maxCount: 3, accept: 'image/*,application/pdf' },
|
|
197
|
+
},
|
|
198
|
+
feedback: { sound: { enabled: true }, haptics: { enabled: true } },
|
|
199
|
+
i18n: { locale: 'en', availableLocales: ['en', 'fr'] },
|
|
200
|
+
footer: {
|
|
201
|
+
composerDisclaimer: 'AI can make mistakes.',
|
|
202
|
+
poweredBy: { text: 'Powered by Help AI', href: 'https://help.ai' },
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The complete type also exposes `features`, `forms`, `modules`, and `tracking`.
|
|
208
|
+
See [Configuration](./configuration.md) for behavior and examples.
|
|
209
|
+
|
|
210
|
+
### `ActionName`
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
type ActionName = 'clear' | 'expand' | 'fullscreen' | 'popOut' | 'sound' | 'history' | 'language' | 'theme' | 'textSize' | 'close';
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### `FeedbackEvent`
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
type FeedbackEvent = 'messageReceived' | 'messageSent' | 'error' | 'voiceStart' | 'voiceStop';
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### `StringsOverride`
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
type LocaleStrings = Partial<Record<StringKey, string>>;
|
|
226
|
+
|
|
227
|
+
type StringsOverride =
|
|
228
|
+
| LocaleStrings // flat (applies to active locale)
|
|
229
|
+
| Partial<Record<string, LocaleStrings>>; // nested (per-locale)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
`StringKey` includes: `attach`, `composerPlaceholder`, `send`, `stop`,
|
|
233
|
+
`close`, `fullscreen`, `expand`, `history`, `language`, `theme`,
|
|
234
|
+
`themeAuto`, `themeLight`, `themeDark`, ... (full list in
|
|
235
|
+
`src/i18n/strings.ts`).
|
|
236
|
+
|
|
237
|
+
### Storage adapter
|
|
238
|
+
|
|
239
|
+
All adapter methods are synchronous.
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
type StorageAdapter = NonNullable<ChatWidgetOptions['storage']>;
|
|
243
|
+
|
|
244
|
+
interface StorageAdapterShape {
|
|
245
|
+
get(key: string): string | null;
|
|
246
|
+
set(key: string, value: string): void;
|
|
247
|
+
remove(key: string): void;
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### `open(target?)`
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
interface OpenTarget {
|
|
255
|
+
to: 'home' | 'chats' | 'help' | 'news';
|
|
256
|
+
id?: string; // a Help article or News post (its content id)
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Opens the panel; with a target it also shows that tab at its root, or the article / post in it. Back from the post
|
|
261
|
+
lands on the tab's list. A tab the widget doesn't have (or an unknown target) just opens the panel, with a `warn` log.
|
|
262
|
+
A target sent before the widget has connected waits until the deployment's tabs are known. For a site's own buttons:
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
document.querySelector('#whats-new')?.addEventListener('click', () => chat.open({ to: 'news' }));
|
|
266
|
+
document.querySelector('#help')?.addEventListener('click', () => chat.open({ to: 'help' }));
|
|
267
|
+
chat.open({ to: 'news', id: '019a0b6c-7e2a-7000-9d3e-4a5b6c7d8e01' }); // one post
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### `ask(text, options?)`
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
ask(text: string, options?: { send?: boolean }): void;
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Opens the chat with `text` in the composer, focused, for the visitor to edit and send — the way a suggestion chip
|
|
277
|
+
does by default. With `{ send: true }` it goes out right away as the visitor's message in their current conversation
|
|
278
|
+
instead. Use it for a site's own "Ask about pricing" buttons:
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
document.querySelector('#ask-pricing')?.addEventListener('click', () => chat.ask('How much does the Pro plan cost?'));
|
|
282
|
+
document.querySelector('#ask-now')?.addEventListener('click', () => chat.ask('Talk me through the Pro plan', { send: true }));
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
The text waits until the chat can take it, so a button works whenever it's clicked: before the widget has connected
|
|
286
|
+
or while a pre-chat form is waiting for an answer; a send also waits for a reply still arriving. A newer `ask`
|
|
287
|
+
replaces one that is still waiting. Text is trimmed; an empty string is ignored with a `warn` log. If a send is
|
|
288
|
+
refused (for example the visitor is filling an inline form), the text is left in the composer for the visitor to send.
|
|
289
|
+
|
|
290
|
+
A send speaks for the visitor, so call it from something the visitor did (a click), not on page load.
|
|
291
|
+
|
|
292
|
+
Without script, mark any element on the page with `data-helpai-ask`; a click asks the default widget. An empty
|
|
293
|
+
value asks the element's own text, and `data-helpai-send` on the same element sends it instead of filling the composer:
|
|
294
|
+
|
|
295
|
+
```html
|
|
296
|
+
<button data-helpai-ask="How do I book a session?">Book a session</button> <button data-helpai-ask data-helpai-send>Do you offer gift cards?</button>
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
### `state` and `ready`
|
|
302
|
+
|
|
303
|
+
```ts
|
|
304
|
+
interface WidgetState {
|
|
305
|
+
open: boolean; // the panel is showing (always true for inline / page / standalone)
|
|
306
|
+
ready: boolean; // connected: commands act at once
|
|
307
|
+
unread: number; // conversations with replies the visitor hasn't read
|
|
308
|
+
conversationId?: string; // the visitor's current conversation
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
`chat.state` is the widget's state right now; the `state` event delivers every change and `unread` fires when the
|
|
313
|
+
count changes. `chat.ready` resolves once the widget has connected, so code that needs the widget can `await` it
|
|
314
|
+
instead of listening for `handshake`. The unread count is known once the widget has been opened in the page load (a
|
|
315
|
+
closed widget makes no request beyond its handshake) and stays live from then on.
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
await chat.ready;
|
|
319
|
+
const badge = document.querySelector('#help-badge');
|
|
320
|
+
function showUnread(count: number) {
|
|
321
|
+
badge.textContent = String(count);
|
|
322
|
+
badge.hidden = count === 0;
|
|
323
|
+
}
|
|
324
|
+
showUnread(chat.state.unread);
|
|
325
|
+
chat.on('unread', showUnread);
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### `reset()`
|
|
329
|
+
|
|
330
|
+
Starts over as a new anonymous visitor. Call it when your user logs out on a shared computer: it forgets the stored
|
|
331
|
+
visitor, their current conversation (draft and queued messages included), preferences and the user context set with
|
|
332
|
+
`setUserContext`, then reconnects as a first visit. Listeners added with `on()` stay, and the handle keeps working.
|
|
333
|
+
On `<web-ai-chat>`, also remove a `user-context` attribute you set.
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Events
|
|
338
|
+
|
|
339
|
+
### `EventMap`
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
interface EventMap {
|
|
343
|
+
open: void;
|
|
344
|
+
close: void;
|
|
345
|
+
message: { role: string; text: string };
|
|
346
|
+
error: unknown;
|
|
347
|
+
expand: boolean; // new state
|
|
348
|
+
fullscreen: boolean; // new state
|
|
349
|
+
handshake: HandshakeResponse; // backend's bootstrap response
|
|
350
|
+
localeChange: string; // new BCP-47 tag
|
|
351
|
+
state: WidgetState; // open / ready / unread / conversation changed
|
|
352
|
+
unread: number; // the unread conversation count changed
|
|
353
|
+
// … and more: see `EventMap` in the package types
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
type EventName = keyof EventMap;
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### `HookListener`
|
|
360
|
+
|
|
361
|
+
Unified signature for global hooks:
|
|
362
|
+
|
|
363
|
+
```ts
|
|
364
|
+
type HookListener = (instance: ChatWidgetInstance, event: EventName, data: unknown) => void;
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
Within a handler, narrow `data` by event name:
|
|
368
|
+
|
|
369
|
+
```ts
|
|
370
|
+
hook('*', '*', (inst, event, data) => {
|
|
371
|
+
switch (event) {
|
|
372
|
+
case 'message': {
|
|
373
|
+
const m = data as EventMap['message'];
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
case 'expand':
|
|
377
|
+
case 'fullscreen': {
|
|
378
|
+
const flag = data as boolean;
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## Auto-boot via script tag
|
|
388
|
+
|
|
389
|
+
The auto-boot parser exposes the documented flat `data-*` subset.
|
|
390
|
+
|
|
391
|
+
```html
|
|
392
|
+
<script
|
|
393
|
+
src="https://cdn.help.ai/sdk/js/elements/latest/elements.js"
|
|
394
|
+
data-public-key="agent_pk_..."
|
|
395
|
+
data-ai-agent-deployment-id="01900000-0000-7000-8000-000000000000"
|
|
396
|
+
data-mode="floating"
|
|
397
|
+
data-theme="auto"
|
|
398
|
+
data-position="bottom-right"
|
|
399
|
+
data-launcher-variant="pill"
|
|
400
|
+
data-launcher-label="Ask us"
|
|
401
|
+
data-launcher-icon="spark"
|
|
402
|
+
data-response-mode="streaming"
|
|
403
|
+
data-features-disable-file-upload="true"
|
|
404
|
+
data-features-voice="local"
|
|
405
|
+
data-user-id="user_42"
|
|
406
|
+
data-user-name="Jane Doe"
|
|
407
|
+
data-page-area="support"
|
|
408
|
+
defer
|
|
409
|
+
></script>
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Full attribute list: [Installation § script data attributes](./installation.md#attributes).
|
|
413
|
+
|
|
414
|
+
`data-no-autoboot` — loads the bundle but doesn't auto-mount. For
|
|
415
|
+
deferred init via JS.
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## Global `window.HelpAI` API
|
|
420
|
+
|
|
421
|
+
After the IIFE boots:
|
|
422
|
+
|
|
423
|
+
```ts
|
|
424
|
+
// Direct methods
|
|
425
|
+
window.HelpAI.init(opts)
|
|
426
|
+
window.HelpAI.mount(opts)
|
|
427
|
+
window.HelpAI.destroy(widgetId?)
|
|
428
|
+
window.HelpAI.getInstance(widgetId?)
|
|
429
|
+
window.HelpAI.getAllInstances()
|
|
430
|
+
window.HelpAI.hook(widgetId, event, fn)
|
|
431
|
+
|
|
432
|
+
// Shortcuts for the default widget
|
|
433
|
+
window.HelpAI.open() // or .open({ to: 'news', id? })
|
|
434
|
+
window.HelpAI.ask(text, { send }) // send defaults to false: fill the composer
|
|
435
|
+
await window.HelpAI.ready() // the default widget, once connected (also when it mounts later)
|
|
436
|
+
window.HelpAI.reset() // a new anonymous visitor (on logout)
|
|
437
|
+
window.HelpAI.close()
|
|
438
|
+
window.HelpAI.expand()
|
|
439
|
+
window.HelpAI.on(event, fn)
|
|
440
|
+
window.HelpAI.update(patch)
|
|
441
|
+
|
|
442
|
+
// Metadata
|
|
443
|
+
window.HelpAI.version // semver string
|
|
444
|
+
window.HelpAI.brand // { id, displayName, cssPrefix, cdnUrl, ... }
|
|
445
|
+
|
|
446
|
+
// Callable dispatch (for queued calls)
|
|
447
|
+
window.HelpAI('init', opts)
|
|
448
|
+
window.HelpAI('open')
|
|
449
|
+
window.HelpAI('open', { to: 'help' })
|
|
450
|
+
window.HelpAI('ask', 'How do I book?') // or ('ask', 'How do I book?', { send: true })
|
|
451
|
+
window.HelpAI('ready', (chat) => chat.on('unread', showUnread)) // queue-able before the bundle loads
|
|
452
|
+
window.HelpAI('reset')
|
|
453
|
+
window.HelpAI('hook', '*', 'message', fn)
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
## Pre-boot queues
|
|
459
|
+
|
|
460
|
+
Used with the async loader snippet — write calls before the bundle
|
|
461
|
+
arrives:
|
|
462
|
+
|
|
463
|
+
```html
|
|
464
|
+
<script>
|
|
465
|
+
// Command queue
|
|
466
|
+
window.HelpAI =
|
|
467
|
+
window.HelpAI ||
|
|
468
|
+
function () {
|
|
469
|
+
(window.HelpAI.q = window.HelpAI.q || []).push(arguments);
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
// Hook queue — array of [widgetId, event, fn] tuples or { widgetId, event, listener } objects
|
|
473
|
+
window.HelpAIHooks = window.HelpAIHooks || [];
|
|
474
|
+
</script>
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
The IIFE drains both on boot.
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## Web component
|
|
482
|
+
|
|
483
|
+
Custom element tag name: `<web-ai-chat>`.
|
|
484
|
+
|
|
485
|
+
The Web Component exposes the same curated parser fields without the
|
|
486
|
+
script dataset's outer `data-` prefix:
|
|
487
|
+
|
|
488
|
+
```html
|
|
489
|
+
<web-ai-chat
|
|
490
|
+
public-key="agent_pk_..."
|
|
491
|
+
ai-agent-deployment-id="..."
|
|
492
|
+
mode="inline"
|
|
493
|
+
theme="auto"
|
|
494
|
+
position="bottom-right"
|
|
495
|
+
launcher-variant="pill"
|
|
496
|
+
launcher-label="Ask us"
|
|
497
|
+
launcher-icon="chat"
|
|
498
|
+
actions="theme,history,close"
|
|
499
|
+
height="500px"
|
|
500
|
+
></web-ai-chat>
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
Changing a reactive attribute re-resolves the live widget. `iframe`
|
|
504
|
+
and `start-minimized` are mount-time-only.
|
|
505
|
+
|
|
506
|
+
The element has the instance's commands, state and events, so a page drives it directly:
|
|
507
|
+
|
|
508
|
+
```js
|
|
509
|
+
const chat = document.querySelector('web-ai-chat');
|
|
510
|
+
chat.open(); // or chat.open({ to: 'help' })
|
|
511
|
+
chat.ask('How do I book a session?');
|
|
512
|
+
chat.close();
|
|
513
|
+
chat.expand();
|
|
514
|
+
chat.openForm('lead');
|
|
515
|
+
await chat.ready;
|
|
516
|
+
chat.on('unread', (count) => console.log(count, chat.state));
|
|
517
|
+
chat.reset(); // on logout
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
`on()` subscriptions end when the element leaves the page. Importing `@helpai/elements/web-component` types
|
|
521
|
+
`document.querySelector('web-ai-chat')` as `WebAiChatElement` in TypeScript; the
|
|
522
|
+
[JSX typings](#jsx-typings) do the same for React, Vue and Svelte markup.
|
|
523
|
+
|
|
524
|
+
### No-script triggers
|
|
525
|
+
|
|
526
|
+
Mark any element on the page and a click drives the default widget, with no script. A link keeps working without the
|
|
527
|
+
widget; with it, the click opens the widget instead of following the link.
|
|
528
|
+
|
|
529
|
+
| Attribute | Click does |
|
|
530
|
+
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
|
|
531
|
+
| `data-helpai-open` | Opens the panel; a value opens a tab (`home`, `chats`, `help`, `news`) or one article or post (`help/<id>`) |
|
|
532
|
+
| `data-helpai-ask="<text>"` | Opens the chat with the text in the composer (empty value: the element's own text); add `data-helpai-send` to send it |
|
|
533
|
+
| `data-helpai-form="<form id>"` | Opens a form that has a `manual` trigger |
|
|
534
|
+
| `data-helpai-close` | Closes the panel |
|
|
535
|
+
|
|
536
|
+
```html
|
|
537
|
+
<a href="/help" data-helpai-open="help">Help</a>
|
|
538
|
+
<a href="/support/billing" data-helpai-open="help/019a0b6c-7e2a-7000-9d3e-4a5b6c7d8e01">Billing questions</a>
|
|
539
|
+
<button data-helpai-ask>Which plan fits a team of 10?</button>
|
|
540
|
+
<button data-helpai-form="book-demo">Book a demo</button>
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
### Deep links
|
|
544
|
+
|
|
545
|
+
A page address can open the default widget on arrival — for support emails, docs and QR codes. Either parameter can
|
|
546
|
+
sit in the query or the hash. The widget acts once and drops its parameters from the address (the page's own
|
|
547
|
+
parameters and anchors stay), so a reload or a copied link doesn't repeat it. A linked question only fills the
|
|
548
|
+
composer; it is never sent for the visitor.
|
|
549
|
+
|
|
550
|
+
| Address | Opens |
|
|
551
|
+
| -------------------------------------- | ---------------------------------------------------------- |
|
|
552
|
+
| `?helpai=open` | The panel |
|
|
553
|
+
| `?helpai=help/<article id>` | Help at that article (any target `data-helpai-open` takes) |
|
|
554
|
+
| `#helpai-ask=Can+I+export+invoices%3F` | The chat with the question in the composer |
|
|
555
|
+
|
|
556
|
+
### JSX typings
|
|
557
|
+
|
|
558
|
+
Types-only subpaths register `<web-ai-chat>` with its attributes in each framework's JSX, so attributes autocomplete,
|
|
559
|
+
`ai-agent-deployment-id` is required, and a ref or `bind:this` is the typed element:
|
|
560
|
+
|
|
561
|
+
```ts
|
|
562
|
+
import type {} from '@helpai/elements/jsx/react'; // React 19
|
|
563
|
+
import type {} from '@helpai/elements/jsx/svelte'; // Svelte 5, e.g. in src/app.d.ts
|
|
564
|
+
import type {} from '@helpai/elements/jsx/vue'; // Vue 3 (also set compilerOptions.isCustomElement for the tag)
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
---
|
|
568
|
+
|
|
569
|
+
## Brand constants
|
|
570
|
+
|
|
571
|
+
`window.HelpAI.brand` (or `import { brand } from '@helpai/elements'`):
|
|
572
|
+
|
|
573
|
+
```ts
|
|
574
|
+
interface Brand {
|
|
575
|
+
id: string; // e.g. "help-ai"
|
|
576
|
+
name: string; // NPM package name, e.g. "@helpai/elements"
|
|
577
|
+
global: string; // window global, e.g. "HelpAI"
|
|
578
|
+
cssPrefix: string; // "helpai" — used for all CSS classes + custom properties
|
|
579
|
+
displayName: string; // "Help AI" — user-visible brand name
|
|
580
|
+
cdnUrl: string; // "https://cdn.help.ai/sdk/js/elements/latest/elements.js"
|
|
581
|
+
defaultBaseUrl: string; // "https://help.ai" — main origin; modules at /api/agent + /api/data
|
|
582
|
+
defaultTheme: {
|
|
583
|
+
accent: string;
|
|
584
|
+
accentText: string;
|
|
585
|
+
radius: string;
|
|
586
|
+
fontFamily: string;
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
Read-only. Useful for:
|
|
592
|
+
|
|
593
|
+
- "Open in full Help AI dashboard" links.
|
|
594
|
+
- "Download the mobile app" banners.
|
|
595
|
+
- Dynamic theme fallbacks.
|
|
596
|
+
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
## Versioning
|
|
600
|
+
|
|
601
|
+
Semver. `version` export matches the NPM package.
|
|
602
|
+
|
|
603
|
+
- **Patch** (1.2.0 → 1.2.1): bug fixes, perf, docs. Auto-upgrade safe.
|
|
604
|
+
- **Minor** (1.2.0 → 1.3.0): new options, new events, backward-compatible. Auto-upgrade safe.
|
|
605
|
+
- **Major** (1.x.x → 2.0.0): breaking changes. Review the changelog.
|
|
606
|
+
|
|
607
|
+
Pin a specific version with the CDN URL:
|
|
608
|
+
|
|
609
|
+
```html
|
|
610
|
+
<script src="https://cdn.help.ai/v1.2.0/elements.js" defer></script>
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
Or use `/v1/` for the latest 1.x.x (auto-patches, no major breaks).
|
|
614
|
+
|
|
615
|
+
---
|
|
616
|
+
|
|
617
|
+
## See also
|
|
618
|
+
|
|
619
|
+
- [Configuration](./configuration.md) — options with examples + context.
|
|
620
|
+
- [Events & hooks](./events-and-hooks.md) — event handling deep-dive.
|
|
621
|
+
- [Recipes](./recipes.md) — copy-paste scenarios.
|
|
622
|
+
- [Troubleshooting](./troubleshooting.md) — when things go wrong.
|