@aiden-voice/widget 0.9.1 → 0.10.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 +11 -4
- package/dist/components/MessageList.d.ts +10 -1
- package/dist/config.d.ts +5 -1
- package/dist/controller.d.ts +4 -1
- package/dist/i18n/messages.d.ts +1 -0
- package/dist/types.d.ts +25 -1
- package/dist/version.d.ts +1 -1
- package/dist/widget.iife.js +7 -7
- package/dist/widget.js +554 -484
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -134,16 +134,19 @@ throws synchronously, at call time, if you pass both or neither.
|
|
|
134
134
|
| `getSessionToken` | `sessionToken` mode only: a function returning a fresh session token (or a promise of one) from your backend, called when the current one has run out or is refused. Without it an expired session ends the chat until the page is reloaded. Ignored, with a warning, with `publishableKey` or when not a function. | none |
|
|
135
135
|
| `language` | Language of the widget's own text, as a BCP 47 tag (`'fr'`, `'pt-BR'`, `'zh-CN'`). Without it the widget follows the page's `<html lang>`, then English. See [Language](#language). | the page's language, else `'en'` |
|
|
136
136
|
| `messages` | Replaces individual built-in strings in the active language, e.g. `{ newConversation: 'Start over' }`. See [Language](#language). | none |
|
|
137
|
-
| `contentLanguage` | The language of the conversation's content (replies, the visitor's messages, and your `greeting`, `title`, `name` and image text), as a BCP 47 tag, so screen readers read it with the right voice. Separate from `language`, which only sets the widget's own text; `language` counts only for a page with no `<html lang>`. See [Language](#language). | the page's `<html lang>`, else `language`, else unknown |
|
|
137
|
+
| `contentLanguage` | The language of the conversation's content (replies, the visitor's messages, and your `greeting`, `notice`, `title`, `subtitle`, `name` and image text), as a BCP 47 tag, so screen readers read it with the right voice. Separate from `language`, which only sets the widget's own text; `language` counts only for a page with no `<html lang>`. See [Language](#language). | the page's `<html lang>`, else `language`, else unknown |
|
|
138
138
|
| `position` | Launcher/panel corner: `'bottom-right'` or `'bottom-left'`. | `'bottom-right'` |
|
|
139
139
|
| `color` | Primary accent color (any valid CSS color). Overrides the color configured in whoo-aiden; omit it to use that one. | whoo-aiden's, else `'#4f46e5'` |
|
|
140
140
|
| `inkColor` | Body text color (chat title and replies). Darkened automatically if needed to stay readable. Overrides the color configured in whoo-aiden; omit it to use that one. | whoo-aiden's, else `'#111111'` |
|
|
141
141
|
| `accentColor` | Link color in replies. Darkened automatically if needed to stay readable. Overrides the color configured in whoo-aiden; omit it to use that one. | whoo-aiden's, else `'#0000ee'` |
|
|
142
142
|
| `name` | Agent name for the panel header and the dialog's screen-reader label ("Chat with {name}"). Overrides the name configured in whoo-aiden; omit it to use that one. | whoo-aiden's, else `'Aiden'` |
|
|
143
143
|
| `title` | Full panel title, used for the header heading and the dialog's screen-reader label. Replaces the whole "Chat with {name}" string (e.g. `'Ask our concierge'`), with surrounding whitespace trimmed; the agent's messages are still labelled with its name. A blank value is ignored. | `'Chat with {name}'` |
|
|
144
|
+
| `subtitle` | A second, smaller line under the panel title (e.g. your property's name). Not part of the dialog's screen-reader name, which stays the title. Blank values are ignored. | none |
|
|
144
145
|
| `greeting` | Welcome text shown in the panel before the first message. | none |
|
|
145
|
-
| `
|
|
146
|
+
| `greetingStyle` | How `greeting` is shown: `'bubble'`, as the agent's first message, or `'centered'`, as plain text centered under `emptyStateImageUrl`, the two together in the middle of the empty panel. Either way it goes away once the visitor writes. | `'bubble'` |
|
|
147
|
+
| `notice` | A notice, such as a disclaimer or terms of use, pinned at the top of the conversation (or under the message field, with `noticePlacement`). Unlike `greeting` it stays after the visitor writes, and comes back after "New conversation". Screen readers read it with the panel's title when the panel opens, until the visitor sends a first message. Supports `**bold**`, `_italic_`, `[links](https://...)` and `- ` lists; raw HTML shows as text. Blank values are ignored. See [Notice](#notice). | none |
|
|
146
148
|
| `requireNoticeAgreement` | Ask the visitor to agree to `notice` before chatting: an "I agree" button (the `agreeToNotice` message) replaces the message field until they do. Remembered for the tab session, and asked again if the notice text changes. Ignored, with a console warning, without a `notice`. See [Notice](#notice). | `false` |
|
|
149
|
+
| `noticePlacement` | Where `notice` is shown: `'top'`, above the conversation, or `'footer'`, as small print under the message field. See [Notice](#notice). | `'top'` |
|
|
147
150
|
| `launcherIconUrl` | Image shown on the launcher bubble instead of the default chat icon. `https:` or `data:image/` only. Until it loads, and permanently if it fails, the default icon shows. Alias of `theme.launcher.iconUrl`. | none (default icon) |
|
|
148
151
|
| `theme` | Colors, font and launcher icons. See [Theming](#theming). | defaults |
|
|
149
152
|
| `layout` | Launcher position and size, and panel size. See [Layout](#layout). | defaults |
|
|
@@ -172,6 +175,7 @@ init({
|
|
|
172
175
|
```
|
|
173
176
|
|
|
174
177
|
- **Where it shows:** above the conversation (below `emptyStateImageUrl`, above `greeting`), outlined rather than in a chat bubble, since it isn't something the agent said. It never leaves the transcript. The panel opens scrolled to its first line until the visitor writes.
|
|
178
|
+
- **As a footer (`noticePlacement: 'footer'`):** small centered print under the message field (or under "I agree"), always in view. It takes at most a quarter of the panel; a longer notice scrolls inside it, and it is then reachable with Tab so keyboard users can scroll it. Keep a footer notice to a sentence or two.
|
|
175
179
|
- **Screen readers:** the panel is described by the notice, so it's read with the title when the panel opens, until the visitor sends a first message (after that it would repeat on every open). It stays reachable as the first item of the conversation.
|
|
176
180
|
- **It isn't sent to the agent** and isn't saved with the conversation.
|
|
177
181
|
- **Agreement (`requireNoticeAgreement: true`):** until the visitor agrees, an "I agree" button takes the message field's place, and nothing can be sent. When the panel opens, focus is on the button, which the notice describes, so screen readers read the title, "I agree, button" and the notice; after agreeing, focus moves to the message field. The agreement lasts for the tab session (like the conversation), survives "New conversation", and is asked for again if you change the notice text. Change the label with `messages: { agreeToNotice: '...' }`; if you do, make the notice text match it.
|
|
@@ -210,6 +214,7 @@ window.whooAidenWidget.init({
|
|
|
210
214
|
| `conversation` | Conversation | message list region name |
|
|
211
215
|
| `you` | You | screen-reader speaker label on the visitor's messages |
|
|
212
216
|
| `message` | Message | message box label |
|
|
217
|
+
| `messagePlaceholder` | Type a message… | message box placeholder (a hint; `message` stays its label) |
|
|
213
218
|
| `send` | Send | composer button |
|
|
214
219
|
| `lookingItUp` | Looking that up for you… | slow-reply notice |
|
|
215
220
|
| `goodResponse` | Good response | thumbs-up name |
|
|
@@ -277,13 +282,13 @@ init({
|
|
|
277
282
|
| `border` | Dividers | `#e5e5e5` |
|
|
278
283
|
| `headerHover` | Header control hover fill | `#f3f4f6` |
|
|
279
284
|
| `assistantBubble` | Reply bubble background | `#f0f0f0` |
|
|
280
|
-
| `muted` | Secondary text on replies | `#4b5563` |
|
|
285
|
+
| `muted` | Secondary text on replies and on the panel (`subtitle`, the footer notice, the message box placeholder) | `#4b5563` |
|
|
281
286
|
| `typingDots` | "Waiting for a reply" dots | `#6b7280` |
|
|
282
287
|
| `errorBackground`, `errorText` | Error banner | `#fee2e2`, `#991b1b` |
|
|
283
288
|
| `inputBorder` | Input and form borders | `#6b7280` |
|
|
284
289
|
| `focusRing` | Dark tone of the keyboard focus outline | `#111827` |
|
|
285
290
|
|
|
286
|
-
If you override a surface (`panel`, `assistantBubble`, ...), also override the roles drawn on it: the defaults are made for the default surfaces, and an override of one is never adjusted to fit another. The roles drawn on each surface are `panel`: `primaryText`, `text`, `focusRing`, `border`, `inputBorder`; `headerHover`: `primaryText`; `assistantBubble`: `ink`, `link`, `muted`, `typingDots`, `text`; `errorBackground`: `errorText`. (The example above leaves `inputBorder`, `typingDots` and the error colors at their defaults, which already read well on it.)
|
|
291
|
+
If you override a surface (`panel`, `assistantBubble`, ...), also override the roles drawn on it: the defaults are made for the default surfaces, and an override of one is never adjusted to fit another. The roles drawn on each surface are `panel`: `primaryText`, `ink`, `link`, `muted`, `text`, `focusRing`, `border`, `inputBorder`; `headerHover`: `primaryText`; `assistantBubble`: `ink`, `link`, `muted`, `typingDots`, `text`; `errorBackground`: `errorText`. (The example above leaves `inputBorder`, `typingDots` and the error colors at their defaults, which already read well on it.)
|
|
287
292
|
|
|
288
293
|
**Fonts.** `theme.fonts.family` takes a CSS font-family stack. The widget never loads fonts, so the font must already be available: a system font, or one your page loads (a Google Fonts `<link>`, or your own `@font-face`). A stack that is over 200 characters or contains `url(`, `@`, `;`, `{`, `}` or `\` is ignored with a warning.
|
|
289
294
|
|
|
@@ -301,6 +306,7 @@ init({
|
|
|
301
306
|
offset: { x: 24, y: 96 }, // distance from the chosen corner (default 20, 20)
|
|
302
307
|
launcherSize: 64, // launcher diameter, 24-120 (default 56)
|
|
303
308
|
panel: { width: 420, height: 640 }, // preferred panel size (default 360×480, minimum 280×320)
|
|
309
|
+
cornerRadius: 20, // panel, message box, Send and "I agree", 0-32 (default 12 panel, 6 controls)
|
|
304
310
|
},
|
|
305
311
|
})
|
|
306
312
|
```
|
|
@@ -308,6 +314,7 @@ init({
|
|
|
308
314
|
- The launcher can't be moved off-screen, and not so far from its corner that the chat panel loses its room: an offset that doesn't leave space for the launcher and a minimum-size panel is held back (a warning is logged if that applies when the page loads). A smaller offset than the 20px default is always honored.
|
|
309
315
|
- A `launcherSize` outside 24-120 is clamped (the 24px floor is WCAG 2.2's minimum target size).
|
|
310
316
|
- The panel is always placed above the launcher, whatever its size or offset, and is capped to the viewport. `panel` is a preferred size: it can never run past the screen, and on very small screens (a viewport 400px wide or less, or 420px tall or less) it fills the viewport as before. A `panel.width` or `panel.height` below 280×320 is raised to that minimum, with a warning.
|
|
317
|
+
- `cornerRadius` rounds the panel, the message box and the Send and "I agree" buttons alike; about 20 or more turns the message box and Send into pills. It's clamped to 32, past which a short panel's corners eat into the header and message box. Without it, the panel keeps 12px corners and the controls 6px.
|
|
311
318
|
- A value that isn't a non-negative number is ignored with a warning and the default is used.
|
|
312
319
|
- On a phone, while the on-screen keyboard is open, the panel moves and shrinks to stay above it, so the message box is never hidden. While the panel fills the screen, the page behind it doesn't scroll (the widget sets `overflow: hidden` on `<html>` and restores your value on close).
|
|
313
320
|
- Your page needs `<meta name="viewport" content="width=device-width, initial-scale=1">` for the phone layout to apply; without it phones render the page, widget included, at desktop width and shrink it.
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { FeedbackCategory, Message, MessageFeedbackState } from '../controller';
|
|
2
2
|
import { WidgetMessages } from '../i18n/messages';
|
|
3
3
|
export declare const NOTICE_ID = "whoo-widget-notice";
|
|
4
|
+
export declare function Notice({ notice, placement, text, contentLanguage, languageTag, }: {
|
|
5
|
+
notice: string;
|
|
6
|
+
placement?: 'top' | 'footer';
|
|
7
|
+
text: WidgetMessages;
|
|
8
|
+
contentLanguage?: string;
|
|
9
|
+
languageTag?: string;
|
|
10
|
+
}): import('preact').JSX.Element;
|
|
4
11
|
type DraftChangeHandler = (messageId: string, correction: string, category: '' | FeedbackCategory) => void;
|
|
5
12
|
type SubmitHandler = (messageId: string, correction: string, category: '' | FeedbackCategory) => void;
|
|
6
|
-
export declare function MessageList({ messages, messageFeedback, announcement, emptyStateImage, notice, agentName, showFeedback, isStreaming, isSlowResponse, onThumbsUp, onThumbsDown, onDraftChange, onSubmitDetailed, onCancelFeedback, text, contentLanguage, languageTag, announcementIsContent, }: {
|
|
13
|
+
export declare function MessageList({ messages, messageFeedback, announcement, emptyStateImage, centerEmptyState, centeredGreeting, notice, agentName, showFeedback, isStreaming, isSlowResponse, onThumbsUp, onThumbsDown, onDraftChange, onSubmitDetailed, onCancelFeedback, text, contentLanguage, languageTag, announcementIsContent, }: {
|
|
7
14
|
messages: Message[];
|
|
8
15
|
messageFeedback: Record<string, MessageFeedbackState>;
|
|
9
16
|
announcement: string | null;
|
|
@@ -11,6 +18,8 @@ export declare function MessageList({ messages, messageFeedback, announcement, e
|
|
|
11
18
|
url: string;
|
|
12
19
|
alt: string;
|
|
13
20
|
};
|
|
21
|
+
centerEmptyState?: boolean;
|
|
22
|
+
centeredGreeting?: string;
|
|
14
23
|
notice?: string;
|
|
15
24
|
agentName?: string;
|
|
16
25
|
showFeedback?: boolean;
|
package/dist/config.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WidgetMessages } from './i18n/messages';
|
|
2
2
|
import { ThemeColorOverrides } from './themeRoles';
|
|
3
|
-
import { LauncherIcon, LauncherOpenIcon, WidgetConfig } from './types';
|
|
3
|
+
import { GreetingStyle, LauncherIcon, LauncherOpenIcon, NoticePlacement, WidgetConfig } from './types';
|
|
4
4
|
export declare const DEFAULT_API_BASE_URL = "https://api.aidenvoice.com";
|
|
5
5
|
export declare const DEFAULT_Z_INDEX = 2147483000;
|
|
6
6
|
export declare function resolveZIndex(zIndex: unknown): number;
|
|
@@ -10,6 +10,8 @@ export declare function isBlankText(text: string): boolean;
|
|
|
10
10
|
export declare function validateConfig(config: WidgetConfig): void;
|
|
11
11
|
export declare function normalizeGetSessionToken(config: WidgetConfig): (() => string | Promise<string>) | undefined;
|
|
12
12
|
export declare function normalizeMessages(value: unknown): Partial<WidgetMessages>;
|
|
13
|
+
export declare function normalizeGreetingStyle(value: unknown): GreetingStyle;
|
|
14
|
+
export declare function normalizeNoticePlacement(value: unknown): NoticePlacement;
|
|
13
15
|
export declare function safeFontFamily(value: unknown): string | undefined;
|
|
14
16
|
export interface NormalizedTheme {
|
|
15
17
|
colors: ThemeColorOverrides;
|
|
@@ -33,11 +35,13 @@ export declare const LAUNCHER_SIZE_MIN = 24;
|
|
|
33
35
|
export declare const LAUNCHER_SIZE_MAX = 120;
|
|
34
36
|
export declare const PANEL_MIN_WIDTH = 280;
|
|
35
37
|
export declare const PANEL_MIN_HEIGHT = 320;
|
|
38
|
+
export declare const CORNER_RADIUS_MAX = 32;
|
|
36
39
|
export interface NormalizedLayout {
|
|
37
40
|
offsetX: number;
|
|
38
41
|
offsetY: number;
|
|
39
42
|
launcherSize: number;
|
|
40
43
|
panelWidth: number;
|
|
41
44
|
panelHeight: number;
|
|
45
|
+
cornerRadius?: number;
|
|
42
46
|
}
|
|
43
47
|
export declare function normalizeLayout(layout: unknown): NormalizedLayout;
|
package/dist/controller.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NormalizedTheme } from './config';
|
|
2
2
|
import { SupportedLanguage } from './i18n';
|
|
3
3
|
import { WidgetMessages } from './i18n/messages';
|
|
4
|
-
import { WidgetConfig } from './types';
|
|
4
|
+
import { GreetingStyle, NoticePlacement, WidgetConfig } from './types';
|
|
5
5
|
export declare const SLOW_RESPONSE_DELAY_MS = 8000;
|
|
6
6
|
export declare const BRANDING_LOOKUP_WAIT_MS = 3000;
|
|
7
7
|
export declare const TOKEN_RENEWAL_MARGIN_MS = 60000;
|
|
@@ -58,6 +58,9 @@ export declare class WidgetController {
|
|
|
58
58
|
readonly emptyStateImageAlt: string;
|
|
59
59
|
readonly notice: string;
|
|
60
60
|
readonly requireNoticeAgreement: boolean;
|
|
61
|
+
readonly noticePlacement: NoticePlacement;
|
|
62
|
+
readonly subtitle: string;
|
|
63
|
+
readonly greetingStyle: GreetingStyle;
|
|
61
64
|
readonly showFeedback: boolean;
|
|
62
65
|
readonly text: WidgetMessages;
|
|
63
66
|
readonly language: SupportedLanguage;
|
package/dist/i18n/messages.d.ts
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export interface WidgetTheme {
|
|
|
28
28
|
headerHover?: string;
|
|
29
29
|
/** Reply bubble background. */
|
|
30
30
|
assistantBubble?: string;
|
|
31
|
-
/** Secondary text on the reply bubble. */
|
|
31
|
+
/** Secondary text on the reply bubble and the panel (subtitle, footer notice, placeholder). */
|
|
32
32
|
muted?: string;
|
|
33
33
|
/** Waiting-for-reply indicator. */
|
|
34
34
|
typingDots?: string;
|
|
@@ -69,7 +69,15 @@ export interface WidgetLayout {
|
|
|
69
69
|
width?: number;
|
|
70
70
|
height?: number;
|
|
71
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Corner radius in px, 0-32, of the panel, the message field and the Send
|
|
74
|
+
* and "I agree" buttons. Half the field's height or more rounds the field
|
|
75
|
+
* and Send into pills. Default: 12 on the panel and 6 on the controls.
|
|
76
|
+
*/
|
|
77
|
+
cornerRadius?: number;
|
|
72
78
|
}
|
|
79
|
+
export type GreetingStyle = 'bubble' | 'centered';
|
|
80
|
+
export type NoticePlacement = 'top' | 'footer';
|
|
73
81
|
export interface WidgetConfig {
|
|
74
82
|
publishableKey?: string;
|
|
75
83
|
sessionToken?: string;
|
|
@@ -121,7 +129,18 @@ export interface WidgetConfig {
|
|
|
121
129
|
accentColor?: string;
|
|
122
130
|
name?: string;
|
|
123
131
|
title?: string;
|
|
132
|
+
/**
|
|
133
|
+
* A second, smaller line under the panel title (e.g. the property's name).
|
|
134
|
+
* Shown as given, trimmed; blank or non-string values are ignored.
|
|
135
|
+
*/
|
|
136
|
+
subtitle?: string;
|
|
124
137
|
greeting?: string;
|
|
138
|
+
/**
|
|
139
|
+
* How `greeting` is shown: 'bubble' (the default) as the agent's first
|
|
140
|
+
* message, or 'centered' as plain text centered under
|
|
141
|
+
* `emptyStateImageUrl`, the two centered together in the empty panel.
|
|
142
|
+
*/
|
|
143
|
+
greetingStyle?: GreetingStyle;
|
|
125
144
|
/**
|
|
126
145
|
* A notice (e.g. a disclaimer or terms of use) pinned at the top of the
|
|
127
146
|
* conversation. Unlike `greeting` it stays after the visitor sends a
|
|
@@ -130,6 +149,11 @@ export interface WidgetConfig {
|
|
|
130
149
|
* values are ignored.
|
|
131
150
|
*/
|
|
132
151
|
notice?: string;
|
|
152
|
+
/**
|
|
153
|
+
* Where `notice` is shown: 'top' (the default) pinned above the
|
|
154
|
+
* conversation, or 'footer' as small print under the message field.
|
|
155
|
+
*/
|
|
156
|
+
noticePlacement?: NoticePlacement;
|
|
133
157
|
/**
|
|
134
158
|
* Require the visitor to agree to `notice` before chatting: the panel shows
|
|
135
159
|
* an "I agree" button (the `agreeToNotice` message) in place of the message
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const WIDGET_VERSION = "0.
|
|
1
|
+
export declare const WIDGET_VERSION = "0.10.0";
|