@clivly/chat-widget 0.15.0 → 0.17.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.
@@ -1,6 +1,24 @@
1
1
  import { Root } from "react-dom/client";
2
2
  import { CSSProperties } from "react";
3
- //#region src/theme.d.ts
3
+ /**
4
+ * Where the widget sits on the host page, and what its launcher looks like.
5
+ *
6
+ * Until 0.16 the widget rendered in normal flow wherever it was mounted — the
7
+ * script tag inserted it directly after itself, so most embeds showed a
8
+ * full-width-label pill at the end of the page rather than a floating button.
9
+ * Floating in a corner is now the default; `"inline"` keeps the old behaviour
10
+ * for a host that positions the widget itself.
11
+ */
12
+ type ChatWidgetPlacement = "bottom-left" | "bottom-right" | "inline";
13
+ /**
14
+ * - `"auto"` (default): the labelled pill on wide screens, a 48px icon-only
15
+ * button below 48rem, where a pill covers the host's own controls.
16
+ * - `"pill"`: always the labelled pill.
17
+ * - `"icon"`: always the icon-only button.
18
+ *
19
+ * The label stays the button's accessible name in every variant.
20
+ */
21
+ type ChatWidgetLauncher = "auto" | "icon" | "pill";
4
22
  /**
5
23
  * Theme resolution for the widget.
6
24
  *
@@ -11,8 +29,6 @@ import { CSSProperties } from "react";
11
29
  * does, and why it is a plain DOM module rather than a stylesheet.
12
30
  */
13
31
  type ChatWidgetTheme = "auto" | "dark" | "light";
14
- //#endregion
15
- //#region src/types.d.ts
16
32
  type WidgetSenderType = "visitor" | "operator" | "system";
17
33
  interface WidgetConfig {
18
34
  brandColor?: string | null;
@@ -124,8 +140,6 @@ interface WidgetErrorEvent {
124
140
  type: "error";
125
141
  }
126
142
  type WidgetServerEvent = WidgetAssistantStatusEvent | WidgetConversationSnapshotEvent | WidgetErrorEvent | WidgetMessageAckEvent | WidgetMessageCreatedEvent | WidgetSessionReadyEvent | WidgetSupportStateEvent;
127
- //#endregion
128
- //#region src/transport.d.ts
129
143
  interface ChatTransportHandlers {
130
144
  onClose: () => void;
131
145
  onError: (error: Error) => void;
@@ -152,8 +166,21 @@ interface CreateChatTransportOptions {
152
166
  session: WidgetSessionPayload;
153
167
  }
154
168
  type CreateChatTransport = (options: CreateChatTransportOptions) => ChatTransportConnection;
155
- //#endregion
156
- //#region src/chat-widget.d.ts
169
+ /**
170
+ * Where the widget keeps the visitor token that resumes a conversation.
171
+ *
172
+ * Keyed by widget AND by who the token was issued to. One key per widget used
173
+ * to hand the token to whoever opened the widget next on that browser — after
174
+ * a sign-out, or between two people who don't sign in at all — and the server
175
+ * resumed the previous person's thread for them (chat widget session review
176
+ * 2026-10-28, S1). The server now refuses that resume on its own; this keeps
177
+ * each person's token to themselves so a returning visitor still resumes.
178
+ *
179
+ * The identity part is a short hash of the normalised email, so the address
180
+ * itself isn't written into storage keys. It only partitions storage: the
181
+ * server's identity check is the security boundary, not this.
182
+ */
183
+ type VisitorTokenStorage = Pick<Storage, "getItem" | "setItem"> & Partial<Pick<Storage, "removeItem">>;
157
184
  interface ChatWidgetProps {
158
185
  className?: string;
159
186
  createTransport?: CreateChatTransport;
@@ -177,8 +204,23 @@ interface ChatWidgetProps {
177
204
  defaultVisitor?: Partial<ChatWidgetVisitor>;
178
205
  getSession: GetSession;
179
206
  initiallyOpen?: boolean;
207
+ /** Launcher shape; see {@link ChatWidgetLauncher}. Defaults to `"auto"`. */
208
+ launcher?: ChatWidgetLauncher;
209
+ /** The launcher's visible text, and always its accessible name. */
180
210
  launcherLabel?: string;
181
- storage?: Pick<Storage, "getItem" | "setItem">;
211
+ /**
212
+ * Where the widget sits; see {@link ChatWidgetPlacement}. Defaults to
213
+ * `"bottom-right"`, floating clear of the device's safe-area insets. Stacks
214
+ * at `--clivly-chat-z-index` (default 2147483000) — lower it through
215
+ * `style` to sit beneath the host's own dialogs.
216
+ */
217
+ placement?: ChatWidgetPlacement;
218
+ /**
219
+ * Where the visitor token is kept, per widget and per visitor (see
220
+ * visitor-token-storage.ts). `removeItem` is optional; with it, the
221
+ * pre-0.16 shared token is retired after its first use.
222
+ */
223
+ storage?: VisitorTokenStorage;
182
224
  /**
183
225
  * Inline styles on the widget root. The intended use is overriding palette
184
226
  * tokens — `{ "--clivly-chat-panel": "#0b0f19" }` — which works because
@@ -193,8 +235,6 @@ interface ChatWidgetProps {
193
235
  theme?: ChatWidgetTheme;
194
236
  widgetId: string;
195
237
  }
196
- //#endregion
197
- //#region src/browser-mount.d.ts
198
238
  interface MountChatWidgetOptions$1 extends Omit<ChatWidgetProps, "getSession" | "widgetId"> {
199
239
  container: Element | ShadowRoot;
200
240
  sessionUrl: string;
@@ -219,12 +259,10 @@ interface ScriptMountResult$1 extends ChatWidgetMount$1 {
219
259
  }
220
260
  declare function mountChatWidgetScript$1(script?: HTMLScriptElement): ScriptMountResult$1;
221
261
  declare function autoMountChatWidgetScript$1(script?: HTMLScriptElement | null): ScriptMountResult$1 | null;
222
- //#endregion
223
- //#region src/browser.d.ts
224
262
  export type ChatWidgetMount = ChatWidgetMount$1;
225
263
  export type MountChatWidgetOptions = MountChatWidgetOptions$1;
226
264
  export type ScriptMountResult = ScriptMountResult$1;
227
265
  export declare const mountChatWidget: typeof mountChatWidget$1;
228
266
  export declare const mountChatWidgetScript: typeof mountChatWidgetScript$1;
229
267
  export declare const autoMountChatWidgetScript: typeof autoMountChatWidgetScript$1;
230
- //#endregion
268
+ export {};
@@ -1,6 +1,24 @@
1
1
  import { Root } from "react-dom/client";
2
2
  import { CSSProperties } from "react";
3
- //#region src/theme.d.ts
3
+ /**
4
+ * Where the widget sits on the host page, and what its launcher looks like.
5
+ *
6
+ * Until 0.16 the widget rendered in normal flow wherever it was mounted — the
7
+ * script tag inserted it directly after itself, so most embeds showed a
8
+ * full-width-label pill at the end of the page rather than a floating button.
9
+ * Floating in a corner is now the default; `"inline"` keeps the old behaviour
10
+ * for a host that positions the widget itself.
11
+ */
12
+ type ChatWidgetPlacement = "bottom-left" | "bottom-right" | "inline";
13
+ /**
14
+ * - `"auto"` (default): the labelled pill on wide screens, a 48px icon-only
15
+ * button below 48rem, where a pill covers the host's own controls.
16
+ * - `"pill"`: always the labelled pill.
17
+ * - `"icon"`: always the icon-only button.
18
+ *
19
+ * The label stays the button's accessible name in every variant.
20
+ */
21
+ type ChatWidgetLauncher = "auto" | "icon" | "pill";
4
22
  /**
5
23
  * Theme resolution for the widget.
6
24
  *
@@ -11,8 +29,6 @@ import { CSSProperties } from "react";
11
29
  * does, and why it is a plain DOM module rather than a stylesheet.
12
30
  */
13
31
  type ChatWidgetTheme = "auto" | "dark" | "light";
14
- //#endregion
15
- //#region src/types.d.ts
16
32
  type WidgetSenderType = "visitor" | "operator" | "system";
17
33
  interface WidgetConfig {
18
34
  brandColor?: string | null;
@@ -124,8 +140,6 @@ interface WidgetErrorEvent {
124
140
  type: "error";
125
141
  }
126
142
  type WidgetServerEvent = WidgetAssistantStatusEvent | WidgetConversationSnapshotEvent | WidgetErrorEvent | WidgetMessageAckEvent | WidgetMessageCreatedEvent | WidgetSessionReadyEvent | WidgetSupportStateEvent;
127
- //#endregion
128
- //#region src/transport.d.ts
129
143
  interface ChatTransportHandlers {
130
144
  onClose: () => void;
131
145
  onError: (error: Error) => void;
@@ -152,8 +166,21 @@ interface CreateChatTransportOptions {
152
166
  session: WidgetSessionPayload;
153
167
  }
154
168
  type CreateChatTransport = (options: CreateChatTransportOptions) => ChatTransportConnection;
155
- //#endregion
156
- //#region src/chat-widget.d.ts
169
+ /**
170
+ * Where the widget keeps the visitor token that resumes a conversation.
171
+ *
172
+ * Keyed by widget AND by who the token was issued to. One key per widget used
173
+ * to hand the token to whoever opened the widget next on that browser — after
174
+ * a sign-out, or between two people who don't sign in at all — and the server
175
+ * resumed the previous person's thread for them (chat widget session review
176
+ * 2026-10-28, S1). The server now refuses that resume on its own; this keeps
177
+ * each person's token to themselves so a returning visitor still resumes.
178
+ *
179
+ * The identity part is a short hash of the normalised email, so the address
180
+ * itself isn't written into storage keys. It only partitions storage: the
181
+ * server's identity check is the security boundary, not this.
182
+ */
183
+ type VisitorTokenStorage = Pick<Storage, "getItem" | "setItem"> & Partial<Pick<Storage, "removeItem">>;
157
184
  interface ChatWidgetProps {
158
185
  className?: string;
159
186
  createTransport?: CreateChatTransport;
@@ -177,8 +204,23 @@ interface ChatWidgetProps {
177
204
  defaultVisitor?: Partial<ChatWidgetVisitor>;
178
205
  getSession: GetSession;
179
206
  initiallyOpen?: boolean;
207
+ /** Launcher shape; see {@link ChatWidgetLauncher}. Defaults to `"auto"`. */
208
+ launcher?: ChatWidgetLauncher;
209
+ /** The launcher's visible text, and always its accessible name. */
180
210
  launcherLabel?: string;
181
- storage?: Pick<Storage, "getItem" | "setItem">;
211
+ /**
212
+ * Where the widget sits; see {@link ChatWidgetPlacement}. Defaults to
213
+ * `"bottom-right"`, floating clear of the device's safe-area insets. Stacks
214
+ * at `--clivly-chat-z-index` (default 2147483000) — lower it through
215
+ * `style` to sit beneath the host's own dialogs.
216
+ */
217
+ placement?: ChatWidgetPlacement;
218
+ /**
219
+ * Where the visitor token is kept, per widget and per visitor (see
220
+ * visitor-token-storage.ts). `removeItem` is optional; with it, the
221
+ * pre-0.16 shared token is retired after its first use.
222
+ */
223
+ storage?: VisitorTokenStorage;
182
224
  /**
183
225
  * Inline styles on the widget root. The intended use is overriding palette
184
226
  * tokens — `{ "--clivly-chat-panel": "#0b0f19" }` — which works because
@@ -193,8 +235,6 @@ interface ChatWidgetProps {
193
235
  theme?: ChatWidgetTheme;
194
236
  widgetId: string;
195
237
  }
196
- //#endregion
197
- //#region src/browser-mount.d.ts
198
238
  interface MountChatWidgetOptions$1 extends Omit<ChatWidgetProps, "getSession" | "widgetId"> {
199
239
  container: Element | ShadowRoot;
200
240
  sessionUrl: string;
@@ -219,12 +259,10 @@ interface ScriptMountResult$1 extends ChatWidgetMount$1 {
219
259
  }
220
260
  declare function mountChatWidgetScript$1(script?: HTMLScriptElement): ScriptMountResult$1;
221
261
  declare function autoMountChatWidgetScript$1(script?: HTMLScriptElement | null): ScriptMountResult$1 | null;
222
- //#endregion
223
- //#region src/browser.d.ts
224
262
  export type ChatWidgetMount = ChatWidgetMount$1;
225
263
  export type MountChatWidgetOptions = MountChatWidgetOptions$1;
226
264
  export type ScriptMountResult = ScriptMountResult$1;
227
265
  export declare const mountChatWidget: typeof mountChatWidget$1;
228
266
  export declare const mountChatWidgetScript: typeof mountChatWidgetScript$1;
229
267
  export declare const autoMountChatWidgetScript: typeof autoMountChatWidgetScript$1;
230
- //#endregion
268
+ export {};