@clivly/chat-widget 0.7.1 → 0.7.2
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 +108 -140
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,155 +1,128 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @clivly/chat-widget
|
|
2
2
|
|
|
3
|
-
Embeddable chat widget
|
|
3
|
+
Embeddable chat widget for Clivly conversations.
|
|
4
4
|
|
|
5
|
-
|
|
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.
|
|
5
|
+
## Install
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
```bash
|
|
8
|
+
npm install @clivly/chat-widget
|
|
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.
|
|
14
21
|
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
For the end-to-end integration flow, start with:
|
|
23
|
+
[Adding the chat widget](https://github.com/amani-joseph/clivly.com/blob/master/docs/guides/adding-the-chat-widget.md).
|
|
17
24
|
|
|
18
25
|
## Entrypoints
|
|
19
26
|
|
|
20
27
|
### `@clivly/chat-widget`
|
|
21
28
|
|
|
22
|
-
Use the package root for
|
|
29
|
+
Use the package root for React components plus browser-safe helpers.
|
|
23
30
|
|
|
24
|
-
|
|
31
|
+
Exports include:
|
|
25
32
|
|
|
26
|
-
-
|
|
33
|
+
- `ChatWidget`
|
|
34
|
+
- `ChatLauncher`
|
|
35
|
+
- `ChatPanel`
|
|
36
|
+
- `ConversationView`
|
|
37
|
+
- `MessageComposer`
|
|
38
|
+
- `PreChatForm`
|
|
27
39
|
- `createSessionFetcher()`
|
|
28
40
|
- `createClivlyTransport()`
|
|
29
|
-
-
|
|
41
|
+
- `createWebSocketTransport()`
|
|
42
|
+
- `createLoopbackTransport()`
|
|
43
|
+
- `mountChatWidget()`
|
|
44
|
+
- `mountChatWidgetScript()`
|
|
45
|
+
- `autoMountChatWidgetScript()`
|
|
30
46
|
|
|
31
47
|
Example:
|
|
32
48
|
|
|
33
49
|
```ts
|
|
34
50
|
import {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
mountChatWidget,
|
|
51
|
+
ChatWidget,
|
|
52
|
+
createSessionFetcher,
|
|
38
53
|
} from "@clivly/chat-widget";
|
|
39
|
-
|
|
40
|
-
const getSession = createSessionFetcher({
|
|
41
|
-
sessionUrl: "/api/clivly/chat/session",
|
|
42
|
-
});
|
|
43
54
|
```
|
|
44
55
|
|
|
45
56
|
### `@clivly/chat-widget/browser`
|
|
46
57
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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.
|
|
58
|
+
Browser entry that auto-mounts at module evaluation time when `document`
|
|
59
|
+
exists. It also exports `mountChatWidget()`, `mountChatWidgetScript()`, and
|
|
60
|
+
`autoMountChatWidgetScript()`.
|
|
57
61
|
|
|
58
62
|
### `@clivly/chat-widget/mount`
|
|
59
63
|
|
|
60
|
-
Use this
|
|
64
|
+
Use this when you want the mounting helpers without the browser entry's
|
|
61
65
|
auto-mount side effect.
|
|
62
66
|
|
|
63
|
-
|
|
67
|
+
### `@clivly/chat-widget/script`
|
|
64
68
|
|
|
65
|
-
|
|
69
|
+
Maps to the generated global bundle at `dist/widget.global.js` for script-tag or
|
|
70
|
+
CDN-style delivery.
|
|
66
71
|
|
|
67
|
-
|
|
68
|
-
- `mountChatWidgetScript()`
|
|
69
|
-
- `autoMountChatWidgetScript()`
|
|
70
|
-
- `MountChatWidgetOptions`
|
|
71
|
-
- `ChatWidgetMount`
|
|
72
|
-
- `ScriptMountResult`
|
|
72
|
+
## React usage
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
```tsx
|
|
75
|
+
import { ChatWidget, createSessionFetcher } from "@clivly/chat-widget";
|
|
76
|
+
|
|
77
|
+
<ChatWidget
|
|
78
|
+
widgetId="support"
|
|
79
|
+
getSession={createSessionFetcher({
|
|
80
|
+
sessionUrl: "/api/clivly/widget/session",
|
|
81
|
+
})}
|
|
82
|
+
/>;
|
|
83
|
+
```
|
|
75
84
|
|
|
76
|
-
|
|
85
|
+
## Script-tag usage
|
|
77
86
|
|
|
78
|
-
|
|
87
|
+
```html
|
|
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
|
+
```
|
|
79
95
|
|
|
80
|
-
|
|
81
|
-
|
|
96
|
+
Supported attributes:
|
|
97
|
+
|
|
98
|
+
| Attribute | Required | Purpose |
|
|
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 |
|
|
82
104
|
|
|
83
105
|
## Theming
|
|
84
106
|
|
|
85
|
-
The widget ships light and dark palettes and follows the host
|
|
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).
|
|
107
|
+
The widget ships light and dark palettes and follows the host by default.
|
|
88
108
|
|
|
89
|
-
|
|
109
|
+
`theme` accepts:
|
|
90
110
|
|
|
91
111
|
| Value | Behaviour |
|
|
92
112
|
| --- | --- |
|
|
93
|
-
| `"auto"`
|
|
94
|
-
| `"light"` / `"dark"` | Pinned
|
|
113
|
+
| `"auto"` | Follows `data-theme` on `<html>`, then `dark` / `light` classes on `<html>`, then `prefers-color-scheme` |
|
|
114
|
+
| `"light"` / `"dark"` | Pinned theme |
|
|
95
115
|
|
|
96
|
-
Set it as a prop
|
|
97
|
-
|
|
98
|
-
`
|
|
116
|
+
Set it as a React prop, a script-tag `data-theme`, or through
|
|
117
|
+
`mountChatWidget()` options. `mountChatWidgetScript()` also returns
|
|
118
|
+
`setTheme(theme)` for hosts with a custom toggle.
|
|
99
119
|
|
|
100
|
-
|
|
101
|
-
|
|
120
|
+
The resolved theme is written to `data-clivly-theme="light|dark"` on the widget
|
|
121
|
+
root.
|
|
102
122
|
|
|
103
|
-
|
|
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`.
|
|
123
|
+
## Session bootstrap
|
|
152
124
|
|
|
125
|
+
The widget expects a bootstrap endpoint that returns a `WidgetSessionPayload`.
|
|
153
126
|
Important fields include:
|
|
154
127
|
|
|
155
128
|
- `token`
|
|
@@ -159,39 +132,21 @@ Important fields include:
|
|
|
159
132
|
- `messages`
|
|
160
133
|
- optional `socketUrl`
|
|
161
134
|
|
|
162
|
-
When `socketUrl` is present, the widget prefers it over reconstructing
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
## Transport behavior
|
|
135
|
+
When `socketUrl` is present, the widget prefers it over reconstructing one from
|
|
136
|
+
`socketUrlTemplate`.
|
|
166
137
|
|
|
167
|
-
|
|
138
|
+
## Transport behaviour
|
|
168
139
|
|
|
169
|
-
|
|
170
|
-
- `createWebSocketTransport()` for explicit socket wiring
|
|
171
|
-
- `createLoopbackTransport()` for local UI/testing flows
|
|
140
|
+
The default browser mount order is:
|
|
172
141
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
1. use a caller-provided `createTransport` when present
|
|
142
|
+
1. use a caller-provided `createTransport`
|
|
176
143
|
2. otherwise prefer `session.socketUrl`
|
|
177
|
-
3. otherwise fall back to `socketUrlTemplate`
|
|
178
|
-
|
|
179
|
-
## Build outputs
|
|
180
|
-
|
|
181
|
-
The package currently produces:
|
|
144
|
+
3. otherwise fall back to `socketUrlTemplate`
|
|
182
145
|
|
|
183
|
-
-
|
|
184
|
-
- `dist/browser.*`
|
|
185
|
-
- `dist/browser-mount.*`
|
|
186
|
-
- `dist/widget.global.js`
|
|
146
|
+
## Host-side session route
|
|
187
147
|
|
|
188
|
-
The
|
|
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:
|
|
148
|
+
The widget talks to your backend, not directly to Clivly. Mount the session
|
|
149
|
+
handler from the SDK on your own origin:
|
|
195
150
|
|
|
196
151
|
```ts
|
|
197
152
|
import { createChatSessionHandler } from "clivly/sdk";
|
|
@@ -201,10 +156,23 @@ export const POST = createChatSessionHandler({
|
|
|
201
156
|
});
|
|
202
157
|
```
|
|
203
158
|
|
|
204
|
-
|
|
205
|
-
|
|
159
|
+
The current scaffolded/default route path is:
|
|
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
|
|
206
177
|
|
|
207
|
-
|
|
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`.
|
|
178
|
+
MIT
|