@clivly/chat-widget 0.14.1 → 0.16.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 CHANGED
@@ -211,6 +211,45 @@ createChatSessionHandler({
211
211
  Use both together for a signed-in user: `defaultVisitor` removes the form,
212
212
  `resolveUser` is what makes it trustworthy.
213
213
 
214
+ ## Placement and launcher
215
+
216
+ The widget floats in the bottom-right corner of the viewport, clear of the
217
+ device's safe-area insets. Below 48rem the launcher is a 48px icon-only
218
+ button, so it does not cover the host page's pagination or form controls; on
219
+ wider screens it is a pill with an icon and your `launcherLabel`. The label is
220
+ the button's accessible name either way, and `aria-expanded` reports whether
221
+ the panel is open.
222
+
223
+ | React prop | Script attribute | Values | Default |
224
+ | --- | --- | --- | --- |
225
+ | `placement` | `data-placement` | `"bottom-right"`, `"bottom-left"`, `"inline"` | `"bottom-right"` |
226
+ | `launcher` | `data-launcher` | `"auto"`, `"pill"`, `"icon"` | `"auto"` |
227
+
228
+ - `"inline"` renders the widget in normal flow, for a host that positions it
229
+ itself. This was the only behaviour before 0.16.
230
+ - `"auto"` switches between the pill and the icon at 48rem; `"pill"` and
231
+ `"icon"` pin one shape at every width.
232
+ - A floating widget stacks at `--clivly-chat-z-index` (default `2147483000`).
233
+ Lower it to sit beneath your own dialogs:
234
+
235
+ ```tsx
236
+ <ChatWidget
237
+ style={{ "--clivly-chat-z-index": 40 } as React.CSSProperties}
238
+ /* … */
239
+ />
240
+ ```
241
+
242
+ ```html
243
+ <script
244
+ src="https://api.clivly.com/widget.js"
245
+ data-widget-id="support"
246
+ data-session-url="/api/clivly/widget/session"
247
+ data-placement="bottom-left"
248
+ data-launcher="icon"
249
+ defer
250
+ ></script>
251
+ ```
252
+
214
253
  ## Theming
215
254
 
216
255
  The widget ships light and dark palettes and follows the host app by default.
@@ -289,6 +328,7 @@ Important fields include:
289
328
  - `contact`
290
329
  - `messages`
291
330
  - optional `socketUrl`
331
+ - optional `support` (see [Support assistant](#support-assistant))
292
332
 
293
333
  When `socketUrl` is present, the widget prefers it over reconstructing the
294
334
  socket URL from a client-side template.
@@ -326,6 +366,26 @@ shows a short note that the team has been
326
366
  notified, and that the reply will also go to the visitor's email when one is
327
367
  known. A failed send doesn't start the clock, because nobody was notified about it.
328
368
 
369
+ ## Support assistant
370
+
371
+ When the widget has guided support turned on in Clivly (**Settings → Chat
372
+ widget → Support**), the session payload carries `support` — the mode, the
373
+ conversation's state, and the topics to offer (ids and labels only; answers stay
374
+ on the server). The widget then:
375
+
376
+ - shows the server-written greeting, and every automated or AI message, with an
377
+ **Automated** / **AI assistant** badge (`message.automation` says which);
378
+ - offers the topics as buttons under the transcript while `support.state` is
379
+ `"automated"`, alongside the message box, and hides them after a handoff or a
380
+ teammate's reply (`support.state` server event);
381
+ - shows *The AI assistant is looking for an answer…* while an
382
+ `assistant.status` event says `thinking`.
383
+
384
+ A topic click is sent as `{ type: "topic.select", id, topicId }`. A **custom
385
+ transport** opts in with the optional `ChatTransportConnection.selectTopic()`;
386
+ without it, a click is sent as the topic's label in an ordinary message. A
387
+ payload without `support` renders exactly as before.
388
+
329
389
  ## Build outputs
330
390
 
331
391
  The package currently produces:
@@ -373,7 +433,7 @@ unreachable Clivly into a JSON `502` instead of a thrown `fetch`.
373
433
  | --- | --- | --- |
374
434
  | Widget mounts but every session is `403` | The origin is not in the widget record's allowlist. It is **exact-match**: `https://example.com` does not cover `https://www.example.com` | Add every embedding origin, with scheme, under **Settings → Chat widget** |
375
435
  | A brand-new widget refuses everything | An empty origin list permits nothing | Add at least one origin |
376
- | `503 widget_not_configured` | The Clivly server has no `CLIVLY_WIDGET_TOKEN_SECRET` | Only relevant when self-hosting — set it, or set `CLIVLY_MASTER_KEY` |
436
+ | `503 widget_not_configured` | The Clivly server cannot sign widget sessions | A Clivly-side configuration problem, not something in your app — contact Clivly support |
377
437
  | Session request returns an opaque `400` | The route was hand-written and omits `origin` from the **body**, or rejects `visitorToken: null` | Use `createChatSessionHandler` from `clivly/sdk` |
378
438
  | `404` on the session request | `sessionUrl` does not match where you mounted the route | `clivly add widget` writes `/api/clivly/widget/session` — match it, or set `sessionUrl` to your path |
379
439
  | Bundle throws on `node:fs` / `node:child_process` | Something imported the `clivly` package root | Import the handler from `clivly/sdk` |