@clivly/chat-widget 0.7.2 → 0.7.3
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 +140 -108
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,128 +1,155 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@clivly/chat-widget`
|
|
2
2
|
|
|
3
|
-
Embeddable chat widget for Clivly conversations.
|
|
3
|
+
Embeddable chat widget package for Clivly conversations.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> **Preview-quality surface.** Install with `npm install @clivly/chat-widget`.
|
|
6
|
+
> The end-to-end path (SDK session handler, `/widget.js` serving, operator
|
|
7
|
+
> inbox) is implemented and covered by integration tests; treat it as
|
|
8
|
+
> design-partner quality while the conversations UX settles.
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Peer dependencies:
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
npm install react react-dom
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
This package is a Tier 2 surface in
|
|
18
|
-
[STABILITY.md](https://github.com/amani-joseph/clivly.com/blob/master/STABILITY.md).
|
|
19
|
-
Stable releases publish on npm's `latest` tag. Use `@next` only when you are
|
|
20
|
-
testing a prerelease build.
|
|
10
|
+
> **New here?** Start with
|
|
11
|
+
> [Adding the chat widget](../../docs/guides/adding-the-chat-widget.md) — the
|
|
12
|
+
> end-to-end integration guide (widget record, session route, embed, operator
|
|
13
|
+
> inbox). This README is the API-level reference for the package's entrypoints.
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
This package currently exposes four stable entrypoints with different intended
|
|
16
|
+
use cases.
|
|
24
17
|
|
|
25
18
|
## Entrypoints
|
|
26
19
|
|
|
27
20
|
### `@clivly/chat-widget`
|
|
28
21
|
|
|
29
|
-
Use the package root for
|
|
22
|
+
Use the package root for app-side integration code.
|
|
30
23
|
|
|
31
|
-
|
|
24
|
+
It exports:
|
|
32
25
|
|
|
33
|
-
-
|
|
34
|
-
- `ChatLauncher`
|
|
35
|
-
- `ChatPanel`
|
|
36
|
-
- `ConversationView`
|
|
37
|
-
- `MessageComposer`
|
|
38
|
-
- `PreChatForm`
|
|
26
|
+
- React widget components
|
|
39
27
|
- `createSessionFetcher()`
|
|
40
28
|
- `createClivlyTransport()`
|
|
41
|
-
-
|
|
42
|
-
- `createLoopbackTransport()`
|
|
43
|
-
- `mountChatWidget()`
|
|
44
|
-
- `mountChatWidgetScript()`
|
|
45
|
-
- `autoMountChatWidgetScript()`
|
|
29
|
+
- side-effect-free mount helpers
|
|
46
30
|
|
|
47
31
|
Example:
|
|
48
32
|
|
|
49
33
|
```ts
|
|
50
34
|
import {
|
|
51
|
-
|
|
52
|
-
|
|
35
|
+
createSessionFetcher,
|
|
36
|
+
createClivlyTransport,
|
|
37
|
+
mountChatWidget,
|
|
53
38
|
} from "@clivly/chat-widget";
|
|
39
|
+
|
|
40
|
+
const getSession = createSessionFetcher({
|
|
41
|
+
sessionUrl: "/api/clivly/chat/session",
|
|
42
|
+
});
|
|
54
43
|
```
|
|
55
44
|
|
|
56
45
|
### `@clivly/chat-widget/browser`
|
|
57
46
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
47
|
+
Use this entry for the browser auto-mount module build.
|
|
48
|
+
|
|
49
|
+
This entry:
|
|
50
|
+
|
|
51
|
+
- exports `mountChatWidget()`
|
|
52
|
+
- exports `mountChatWidgetScript()`
|
|
53
|
+
- exports `autoMountChatWidgetScript()`
|
|
54
|
+
- auto-mounts at module evaluation time when `document` exists
|
|
55
|
+
|
|
56
|
+
This is the module-side equivalent of the script-tag embed behavior.
|
|
61
57
|
|
|
62
58
|
### `@clivly/chat-widget/mount`
|
|
63
59
|
|
|
64
|
-
Use this when you want the
|
|
60
|
+
Use this entry when you want the mount helpers without the browser entry's
|
|
65
61
|
auto-mount side effect.
|
|
66
62
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
Maps to the generated global bundle at `dist/widget.global.js` for script-tag or
|
|
70
|
-
CDN-style delivery.
|
|
63
|
+
This is the safest browser/helper entry for host-controlled mounting.
|
|
71
64
|
|
|
72
|
-
|
|
65
|
+
It exports:
|
|
73
66
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
sessionUrl: "/api/clivly/widget/session",
|
|
81
|
-
})}
|
|
82
|
-
/>;
|
|
83
|
-
```
|
|
67
|
+
- `mountChatWidget()`
|
|
68
|
+
- `mountChatWidgetScript()`
|
|
69
|
+
- `autoMountChatWidgetScript()`
|
|
70
|
+
- `MountChatWidgetOptions`
|
|
71
|
+
- `ChatWidgetMount`
|
|
72
|
+
- `ScriptMountResult`
|
|
84
73
|
|
|
85
|
-
|
|
74
|
+
### `@clivly/chat-widget/script`
|
|
86
75
|
|
|
87
|
-
|
|
88
|
-
<script
|
|
89
|
-
src="https://api.clivly.com/widget.js"
|
|
90
|
-
data-widget-id="support"
|
|
91
|
-
data-session-url="/api/clivly/widget/session"
|
|
92
|
-
defer
|
|
93
|
-
></script>
|
|
94
|
-
```
|
|
76
|
+
This entry maps to the generated global/browser artifact:
|
|
95
77
|
|
|
96
|
-
|
|
78
|
+
- `dist/widget.global.js`
|
|
97
79
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
| `data-widget-id` | yes | Public widget slug from the Clivly dashboard |
|
|
101
|
-
| `data-session-url` | yes | Your backend route that mounts `createChatSessionHandler()` |
|
|
102
|
-
| `data-theme` | no | `auto`, `light`, or `dark` |
|
|
103
|
-
| `data-socket-url-template` | no | Legacy socket override; usually unnecessary |
|
|
80
|
+
Use it for script-tag delivery, CDN-style consumption, or any future server path
|
|
81
|
+
that serves the bundled widget directly.
|
|
104
82
|
|
|
105
83
|
## Theming
|
|
106
84
|
|
|
107
|
-
The widget ships light and dark palettes and follows the host by default.
|
|
85
|
+
The widget ships light and dark palettes and follows the host app by default.
|
|
86
|
+
For integration recipes (Tailwind, next-themes, a custom toggle) see
|
|
87
|
+
[the guide's theming section](../../docs/guides/adding-the-chat-widget.md#theming).
|
|
108
88
|
|
|
109
|
-
`theme`
|
|
89
|
+
### `theme`
|
|
110
90
|
|
|
111
91
|
| Value | Behaviour |
|
|
112
92
|
| --- | --- |
|
|
113
|
-
| `"auto"` | Follows `data-theme` on `<html>`, then `dark
|
|
114
|
-
| `"light"` / `"dark"` | Pinned
|
|
93
|
+
| `"auto"` *(default)* | Follows the host: `data-theme="dark"`/`"light"` on `<html>`, then a `dark`/`light` class on `<html>`, then `prefers-color-scheme`. Re-resolves live. |
|
|
94
|
+
| `"light"` / `"dark"` | Pinned. Host signals are ignored and nothing is observed. |
|
|
115
95
|
|
|
116
|
-
Set it as a
|
|
117
|
-
`mountChatWidget()` options.
|
|
118
|
-
`
|
|
96
|
+
Set it as a prop (`<ChatWidget theme="dark" />`), as `data-theme` on the script
|
|
97
|
+
tag, or as `theme` in `mountChatWidget()` options. An unrecognised
|
|
98
|
+
`data-theme` value falls back to `"auto"` rather than throwing.
|
|
119
99
|
|
|
120
|
-
|
|
121
|
-
|
|
100
|
+
`mountChatWidgetScript()` also returns `setTheme(theme)` for hosts whose toggle
|
|
101
|
+
does not touch `<html>`:
|
|
122
102
|
|
|
123
|
-
|
|
103
|
+
```ts
|
|
104
|
+
const { setTheme } = mountChatWidgetScript(script);
|
|
105
|
+
setTheme("dark"); // pin
|
|
106
|
+
setTheme("auto"); // hand control back to the host
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The resolved theme is applied as `data-clivly-theme="light|dark"` on the widget
|
|
110
|
+
root, together with `color-scheme`, so native scrollbars, autofill, and the
|
|
111
|
+
caret follow the panel.
|
|
112
|
+
|
|
113
|
+
### Palette tokens
|
|
114
|
+
|
|
115
|
+
Every colour reads through a CSS custom property. React hosts can override any
|
|
116
|
+
of them inline — inline declarations beat both palette rules, so no specificity
|
|
117
|
+
work is needed:
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
<ChatWidget style={{ "--clivly-chat-panel": "#0b0f19" }} widgetId="support" />
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
| Token | Light | Dark |
|
|
124
|
+
| --- | --- | --- |
|
|
125
|
+
| `--clivly-chat-accent` | `#185adb` | `#4f8cff` |
|
|
126
|
+
| `--clivly-chat-accent-contrast` | `#ffffff` | `#0b1220` |
|
|
127
|
+
| `--clivly-chat-panel` | `#ffffff` | `#111827` |
|
|
128
|
+
| `--clivly-chat-input` | `transparent` | `#0b1220` |
|
|
129
|
+
| `--clivly-chat-border` | `#d6dde8` | `#2a3546` |
|
|
130
|
+
| `--clivly-chat-text` | `#132238` | `#e8edf5` |
|
|
131
|
+
| `--clivly-chat-muted` | `#60738a` | `#93a2b8` |
|
|
132
|
+
| `--clivly-chat-visitor` | `#ecf3ff` | `#1e3a6b` |
|
|
133
|
+
| `--clivly-chat-operator` | `#f5f7fa` | `#1b2534` |
|
|
134
|
+
| `--clivly-chat-shadow` | `rgba(19, 34, 56, 0.18)` | `rgba(0, 0, 0, 0.5)` |
|
|
135
|
+
| `--clivly-chat-error-bg` | `#fff1f1` | `#2c1618` |
|
|
136
|
+
| `--clivly-chat-error-border` | `#f2c2c2` | `#5c2a2e` |
|
|
137
|
+
| `--clivly-chat-error-text` | `#9f2d2d` | `#ffb4b4` |
|
|
138
|
+
|
|
139
|
+
The widget record's `brandColor` overrides `--clivly-chat-accent` in **both**
|
|
140
|
+
themes — the widget will not silently lighten your brand. If your brand colour
|
|
141
|
+
is very dark it will be low-contrast on the dark panel; pick a lighter accent,
|
|
142
|
+
or override the token per theme in a React host.
|
|
143
|
+
|
|
144
|
+
Deep per-token overrides are not available on the script-tag path: it mounts
|
|
145
|
+
into a Shadow DOM, so host CSS cannot reach the widget's internals. Use
|
|
146
|
+
`brandColor` and the two themes there.
|
|
147
|
+
|
|
148
|
+
## Session bootstrap shape
|
|
149
|
+
|
|
150
|
+
The widget expects a session bootstrap endpoint that returns a
|
|
151
|
+
`WidgetSessionPayload`.
|
|
124
152
|
|
|
125
|
-
The widget expects a bootstrap endpoint that returns a `WidgetSessionPayload`.
|
|
126
153
|
Important fields include:
|
|
127
154
|
|
|
128
155
|
- `token`
|
|
@@ -132,21 +159,39 @@ Important fields include:
|
|
|
132
159
|
- `messages`
|
|
133
160
|
- optional `socketUrl`
|
|
134
161
|
|
|
135
|
-
When `socketUrl` is present, the widget prefers it over reconstructing
|
|
136
|
-
|
|
162
|
+
When `socketUrl` is present, the widget prefers it over reconstructing the
|
|
163
|
+
socket URL from a client-side template.
|
|
164
|
+
|
|
165
|
+
## Transport behavior
|
|
137
166
|
|
|
138
|
-
|
|
167
|
+
The package includes:
|
|
139
168
|
|
|
140
|
-
|
|
169
|
+
- `createClivlyTransport()` for real Clivly backends
|
|
170
|
+
- `createWebSocketTransport()` for explicit socket wiring
|
|
171
|
+
- `createLoopbackTransport()` for local UI/testing flows
|
|
141
172
|
|
|
142
|
-
|
|
173
|
+
The default browser mount behavior is:
|
|
174
|
+
|
|
175
|
+
1. use a caller-provided `createTransport` when present
|
|
143
176
|
2. otherwise prefer `session.socketUrl`
|
|
144
|
-
3. otherwise fall back to `socketUrlTemplate`
|
|
177
|
+
3. otherwise fall back to `socketUrlTemplate` when provided
|
|
178
|
+
|
|
179
|
+
## Build outputs
|
|
180
|
+
|
|
181
|
+
The package currently produces:
|
|
145
182
|
|
|
146
|
-
|
|
183
|
+
- `dist/index.*`
|
|
184
|
+
- `dist/browser.*`
|
|
185
|
+
- `dist/browser-mount.*`
|
|
186
|
+
- `dist/widget.global.js`
|
|
147
187
|
|
|
148
|
-
The
|
|
149
|
-
|
|
188
|
+
The `browser` and `browser-mount` outputs are built as standalone entrypoints.
|
|
189
|
+
|
|
190
|
+
## Host-side pairing
|
|
191
|
+
|
|
192
|
+
The host-side session handler is the bridge between a backend holding
|
|
193
|
+
`CLIVLY_SECRET_KEY` and the widget's `sessionUrl`. Import it from `clivly/sdk`,
|
|
194
|
+
which is available from the `clivly` package `clivly init` already installs:
|
|
150
195
|
|
|
151
196
|
```ts
|
|
152
197
|
import { createChatSessionHandler } from "clivly/sdk";
|
|
@@ -156,23 +201,10 @@ export const POST = createChatSessionHandler({
|
|
|
156
201
|
});
|
|
157
202
|
```
|
|
158
203
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
```text
|
|
162
|
-
/api/clivly/widget/session
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
Use the handler rather than hand-writing the proxy. It forwards `origin`
|
|
166
|
-
correctly, accepts `visitorToken: null` for first-time visitors, and returns a
|
|
167
|
-
clean JSON `502` when Clivly is unreachable.
|
|
168
|
-
|
|
169
|
-
## More docs
|
|
170
|
-
|
|
171
|
-
- End-to-end guide:
|
|
172
|
-
[Adding the chat widget](https://github.com/amani-joseph/clivly.com/blob/master/docs/guides/adding-the-chat-widget.md)
|
|
173
|
-
- Release notes:
|
|
174
|
-
[CHANGELOG.md](https://github.com/amani-joseph/clivly.com/blob/master/CHANGELOG.md)
|
|
175
|
-
|
|
176
|
-
## License
|
|
204
|
+
`@clivly/sdk` exports the same handler if you depend on it directly. Don't import
|
|
205
|
+
from `clivly` (the package root) — that entry is the CLI and is Node-only.
|
|
177
206
|
|
|
178
|
-
|
|
207
|
+
Use the handler rather than hand-writing the proxy: it puts `origin` in the
|
|
208
|
+
request body (the backend requires it there, and only falls back to the `Origin`
|
|
209
|
+
header), accepts `visitorToken: null` for a first-time visitor, and turns an
|
|
210
|
+
unreachable Clivly into a JSON `502` instead of a thrown `fetch`.
|