@clivly/chat-widget 0.5.0 → 0.7.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.
@@ -340,6 +340,13 @@ const WIDGET_STYLES = `
340
340
  }
341
341
  `;
342
342
  const DEFAULT_STORAGE = typeof window === "undefined" ? void 0 : window.localStorage;
343
+ function sessionDisplayName(session) {
344
+ return session.contact?.name ?? "You";
345
+ }
346
+ function sessionSummaryText(session, fallback) {
347
+ if (!session) return fallback;
348
+ return session.contact ? `${session.contact.name} • ${session.contact.email}` : "Verified visitor";
349
+ }
343
350
  function createLocalMessage(message, delivery = "sent") {
344
351
  return {
345
352
  ...message,
@@ -537,16 +544,18 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
537
544
  setError(null);
538
545
  setIsConnecting(true);
539
546
  try {
547
+ const existingVisitorToken = storage?.getItem(createStorageKey(widgetId)) ?? null;
540
548
  const nextSession = await getSession({
541
549
  visitor,
542
- visitorToken: storage?.getItem(createStorageKey(widgetId)) ?? null,
550
+ visitorToken: existingVisitorToken,
543
551
  widgetId
544
552
  });
545
553
  storage?.setItem(createStorageKey(widgetId), nextSession.visitorToken);
546
554
  setSession(nextSession);
547
555
  setMessages(sortMessages(nextSession.messages.map((message) => createLocalMessage(message))));
548
556
  } catch (sessionError) {
549
- setError((sessionError instanceof Error ? sessionError : /* @__PURE__ */ new Error("Failed to start the conversation.")).message);
557
+ const resolved = sessionError instanceof Error ? sessionError : /* @__PURE__ */ new Error("Failed to start the conversation.");
558
+ setError(resolved.message);
550
559
  } finally {
551
560
  setIsConnecting(false);
552
561
  }
@@ -561,7 +570,7 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
561
570
  if (!body) return;
562
571
  const clientMessageId = generateId();
563
572
  const optimisticMessage = {
564
- author: session.contact.name,
573
+ author: sessionDisplayName(session),
565
574
  body,
566
575
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
567
576
  id: clientMessageId,
@@ -584,7 +593,7 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
584
593
  };
585
594
  const greeting = session?.widget.config.greeting ?? "Tell us a little about yourself and we’ll pick up the conversation from there.";
586
595
  const panelTitle = session?.widget.name ?? "Start a conversation";
587
- const sessionSummary = session ? `${session.contact.name} • ${session.contact.email}` : greeting;
596
+ const sessionSummary = sessionSummaryText(session, greeting);
588
597
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
589
598
  className: `clivly-chat-widget ${className ?? ""}`.trim(),
590
599
  "data-clivly-theme": resolvedTheme,
@@ -1,6 +1,5 @@
1
1
  import { Root } from "react-dom/client";
2
2
  import { CSSProperties } from "react";
3
-
4
3
  //#region src/theme.d.ts
5
4
  /**
6
5
  * Theme resolution for the widget.
@@ -41,7 +40,7 @@ interface WidgetMessage {
41
40
  senderType: WidgetSenderType;
42
41
  }
43
42
  interface WidgetSessionPayload {
44
- contact: WidgetContact;
43
+ contact: WidgetContact | null;
45
44
  conversation: WidgetConversation;
46
45
  expiresAt: string;
47
46
  messages: WidgetMessage[];
@@ -1,6 +1,5 @@
1
1
  import { Root } from "react-dom/client";
2
2
  import { CSSProperties } from "react";
3
-
4
3
  //#region src/theme.d.ts
5
4
  /**
6
5
  * Theme resolution for the widget.
@@ -41,7 +40,7 @@ interface WidgetMessage {
41
40
  senderType: WidgetSenderType;
42
41
  }
43
42
  interface WidgetSessionPayload {
44
- contact: WidgetContact;
43
+ contact: WidgetContact | null;
45
44
  conversation: WidgetConversation;
46
45
  expiresAt: string;
47
46
  messages: WidgetMessage[];
@@ -339,6 +339,13 @@ const WIDGET_STYLES = `
339
339
  }
340
340
  `;
341
341
  const DEFAULT_STORAGE = typeof window === "undefined" ? void 0 : window.localStorage;
342
+ function sessionDisplayName(session) {
343
+ return session.contact?.name ?? "You";
344
+ }
345
+ function sessionSummaryText(session, fallback) {
346
+ if (!session) return fallback;
347
+ return session.contact ? `${session.contact.name} • ${session.contact.email}` : "Verified visitor";
348
+ }
342
349
  function createLocalMessage(message, delivery = "sent") {
343
350
  return {
344
351
  ...message,
@@ -536,16 +543,18 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
536
543
  setError(null);
537
544
  setIsConnecting(true);
538
545
  try {
546
+ const existingVisitorToken = storage?.getItem(createStorageKey(widgetId)) ?? null;
539
547
  const nextSession = await getSession({
540
548
  visitor,
541
- visitorToken: storage?.getItem(createStorageKey(widgetId)) ?? null,
549
+ visitorToken: existingVisitorToken,
542
550
  widgetId
543
551
  });
544
552
  storage?.setItem(createStorageKey(widgetId), nextSession.visitorToken);
545
553
  setSession(nextSession);
546
554
  setMessages(sortMessages(nextSession.messages.map((message) => createLocalMessage(message))));
547
555
  } catch (sessionError) {
548
- setError((sessionError instanceof Error ? sessionError : /* @__PURE__ */ new Error("Failed to start the conversation.")).message);
556
+ const resolved = sessionError instanceof Error ? sessionError : /* @__PURE__ */ new Error("Failed to start the conversation.");
557
+ setError(resolved.message);
549
558
  } finally {
550
559
  setIsConnecting(false);
551
560
  }
@@ -560,7 +569,7 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
560
569
  if (!body) return;
561
570
  const clientMessageId = generateId();
562
571
  const optimisticMessage = {
563
- author: session.contact.name,
572
+ author: sessionDisplayName(session),
564
573
  body,
565
574
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
566
575
  id: clientMessageId,
@@ -583,7 +592,7 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
583
592
  };
584
593
  const greeting = session?.widget.config.greeting ?? "Tell us a little about yourself and we’ll pick up the conversation from there.";
585
594
  const panelTitle = session?.widget.name ?? "Start a conversation";
586
- const sessionSummary = session ? `${session.contact.name} • ${session.contact.email}` : greeting;
595
+ const sessionSummary = sessionSummaryText(session, greeting);
587
596
  return /* @__PURE__ */ jsxs("div", {
588
597
  className: `clivly-chat-widget ${className ?? ""}`.trim(),
589
598
  "data-clivly-theme": resolvedTheme,
package/dist/browser.cjs CHANGED
@@ -340,6 +340,13 @@ const WIDGET_STYLES = `
340
340
  }
341
341
  `;
342
342
  const DEFAULT_STORAGE = typeof window === "undefined" ? void 0 : window.localStorage;
343
+ function sessionDisplayName(session) {
344
+ return session.contact?.name ?? "You";
345
+ }
346
+ function sessionSummaryText(session, fallback) {
347
+ if (!session) return fallback;
348
+ return session.contact ? `${session.contact.name} • ${session.contact.email}` : "Verified visitor";
349
+ }
343
350
  function createLocalMessage(message, delivery = "sent") {
344
351
  return {
345
352
  ...message,
@@ -537,16 +544,18 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
537
544
  setError(null);
538
545
  setIsConnecting(true);
539
546
  try {
547
+ const existingVisitorToken = storage?.getItem(createStorageKey(widgetId)) ?? null;
540
548
  const nextSession = await getSession({
541
549
  visitor,
542
- visitorToken: storage?.getItem(createStorageKey(widgetId)) ?? null,
550
+ visitorToken: existingVisitorToken,
543
551
  widgetId
544
552
  });
545
553
  storage?.setItem(createStorageKey(widgetId), nextSession.visitorToken);
546
554
  setSession(nextSession);
547
555
  setMessages(sortMessages(nextSession.messages.map((message) => createLocalMessage(message))));
548
556
  } catch (sessionError) {
549
- setError((sessionError instanceof Error ? sessionError : /* @__PURE__ */ new Error("Failed to start the conversation.")).message);
557
+ const resolved = sessionError instanceof Error ? sessionError : /* @__PURE__ */ new Error("Failed to start the conversation.");
558
+ setError(resolved.message);
550
559
  } finally {
551
560
  setIsConnecting(false);
552
561
  }
@@ -561,7 +570,7 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
561
570
  if (!body) return;
562
571
  const clientMessageId = generateId();
563
572
  const optimisticMessage = {
564
- author: session.contact.name,
573
+ author: sessionDisplayName(session),
565
574
  body,
566
575
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
567
576
  id: clientMessageId,
@@ -584,7 +593,7 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
584
593
  };
585
594
  const greeting = session?.widget.config.greeting ?? "Tell us a little about yourself and we’ll pick up the conversation from there.";
586
595
  const panelTitle = session?.widget.name ?? "Start a conversation";
587
- const sessionSummary = session ? `${session.contact.name} • ${session.contact.email}` : greeting;
596
+ const sessionSummary = sessionSummaryText(session, greeting);
588
597
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
589
598
  className: `clivly-chat-widget ${className ?? ""}`.trim(),
590
599
  "data-clivly-theme": resolvedTheme,
@@ -1,6 +1,5 @@
1
1
  import { Root } from "react-dom/client";
2
2
  import { CSSProperties } from "react";
3
-
4
3
  //#region src/theme.d.ts
5
4
  /**
6
5
  * Theme resolution for the widget.
@@ -41,7 +40,7 @@ interface WidgetMessage {
41
40
  senderType: WidgetSenderType;
42
41
  }
43
42
  interface WidgetSessionPayload {
44
- contact: WidgetContact;
43
+ contact: WidgetContact | null;
45
44
  conversation: WidgetConversation;
46
45
  expiresAt: string;
47
46
  messages: WidgetMessage[];
@@ -1,6 +1,5 @@
1
1
  import { Root } from "react-dom/client";
2
2
  import { CSSProperties } from "react";
3
-
4
3
  //#region src/theme.d.ts
5
4
  /**
6
5
  * Theme resolution for the widget.
@@ -41,7 +40,7 @@ interface WidgetMessage {
41
40
  senderType: WidgetSenderType;
42
41
  }
43
42
  interface WidgetSessionPayload {
44
- contact: WidgetContact;
43
+ contact: WidgetContact | null;
45
44
  conversation: WidgetConversation;
46
45
  expiresAt: string;
47
46
  messages: WidgetMessage[];
package/dist/browser.mjs CHANGED
@@ -339,6 +339,13 @@ const WIDGET_STYLES = `
339
339
  }
340
340
  `;
341
341
  const DEFAULT_STORAGE = typeof window === "undefined" ? void 0 : window.localStorage;
342
+ function sessionDisplayName(session) {
343
+ return session.contact?.name ?? "You";
344
+ }
345
+ function sessionSummaryText(session, fallback) {
346
+ if (!session) return fallback;
347
+ return session.contact ? `${session.contact.name} • ${session.contact.email}` : "Verified visitor";
348
+ }
342
349
  function createLocalMessage(message, delivery = "sent") {
343
350
  return {
344
351
  ...message,
@@ -536,16 +543,18 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
536
543
  setError(null);
537
544
  setIsConnecting(true);
538
545
  try {
546
+ const existingVisitorToken = storage?.getItem(createStorageKey(widgetId)) ?? null;
539
547
  const nextSession = await getSession({
540
548
  visitor,
541
- visitorToken: storage?.getItem(createStorageKey(widgetId)) ?? null,
549
+ visitorToken: existingVisitorToken,
542
550
  widgetId
543
551
  });
544
552
  storage?.setItem(createStorageKey(widgetId), nextSession.visitorToken);
545
553
  setSession(nextSession);
546
554
  setMessages(sortMessages(nextSession.messages.map((message) => createLocalMessage(message))));
547
555
  } catch (sessionError) {
548
- setError((sessionError instanceof Error ? sessionError : /* @__PURE__ */ new Error("Failed to start the conversation.")).message);
556
+ const resolved = sessionError instanceof Error ? sessionError : /* @__PURE__ */ new Error("Failed to start the conversation.");
557
+ setError(resolved.message);
549
558
  } finally {
550
559
  setIsConnecting(false);
551
560
  }
@@ -560,7 +569,7 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
560
569
  if (!body) return;
561
570
  const clientMessageId = generateId();
562
571
  const optimisticMessage = {
563
- author: session.contact.name,
572
+ author: sessionDisplayName(session),
564
573
  body,
565
574
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
566
575
  id: clientMessageId,
@@ -583,7 +592,7 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
583
592
  };
584
593
  const greeting = session?.widget.config.greeting ?? "Tell us a little about yourself and we’ll pick up the conversation from there.";
585
594
  const panelTitle = session?.widget.name ?? "Start a conversation";
586
- const sessionSummary = session ? `${session.contact.name} • ${session.contact.email}` : greeting;
595
+ const sessionSummary = sessionSummaryText(session, greeting);
587
596
  return /* @__PURE__ */ jsxs("div", {
588
597
  className: `clivly-chat-widget ${className ?? ""}`.trim(),
589
598
  "data-clivly-theme": resolvedTheme,
package/dist/index.cjs CHANGED
@@ -340,6 +340,13 @@ const WIDGET_STYLES = `
340
340
  }
341
341
  `;
342
342
  const DEFAULT_STORAGE = typeof window === "undefined" ? void 0 : window.localStorage;
343
+ function sessionDisplayName(session) {
344
+ return session.contact?.name ?? "You";
345
+ }
346
+ function sessionSummaryText(session, fallback) {
347
+ if (!session) return fallback;
348
+ return session.contact ? `${session.contact.name} • ${session.contact.email}` : "Verified visitor";
349
+ }
343
350
  function createLocalMessage(message, delivery = "sent") {
344
351
  return {
345
352
  ...message,
@@ -537,16 +544,18 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
537
544
  setError(null);
538
545
  setIsConnecting(true);
539
546
  try {
547
+ const existingVisitorToken = storage?.getItem(createStorageKey(widgetId)) ?? null;
540
548
  const nextSession = await getSession({
541
549
  visitor,
542
- visitorToken: storage?.getItem(createStorageKey(widgetId)) ?? null,
550
+ visitorToken: existingVisitorToken,
543
551
  widgetId
544
552
  });
545
553
  storage?.setItem(createStorageKey(widgetId), nextSession.visitorToken);
546
554
  setSession(nextSession);
547
555
  setMessages(sortMessages(nextSession.messages.map((message) => createLocalMessage(message))));
548
556
  } catch (sessionError) {
549
- setError((sessionError instanceof Error ? sessionError : /* @__PURE__ */ new Error("Failed to start the conversation.")).message);
557
+ const resolved = sessionError instanceof Error ? sessionError : /* @__PURE__ */ new Error("Failed to start the conversation.");
558
+ setError(resolved.message);
550
559
  } finally {
551
560
  setIsConnecting(false);
552
561
  }
@@ -561,7 +570,7 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
561
570
  if (!body) return;
562
571
  const clientMessageId = generateId();
563
572
  const optimisticMessage = {
564
- author: session.contact.name,
573
+ author: sessionDisplayName(session),
565
574
  body,
566
575
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
567
576
  id: clientMessageId,
@@ -584,7 +593,7 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
584
593
  };
585
594
  const greeting = session?.widget.config.greeting ?? "Tell us a little about yourself and we’ll pick up the conversation from there.";
586
595
  const panelTitle = session?.widget.name ?? "Start a conversation";
587
- const sessionSummary = session ? `${session.contact.name} • ${session.contact.email}` : greeting;
596
+ const sessionSummary = sessionSummaryText(session, greeting);
588
597
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
589
598
  className: `clivly-chat-widget ${className ?? ""}`.trim(),
590
599
  "data-clivly-theme": resolvedTheme,
@@ -820,7 +829,7 @@ function createLoopbackTransport({ operatorName = "Clivly", operatorReply = (bod
820
829
  type: "message.ack",
821
830
  clientMessageId: message.id,
822
831
  message: {
823
- author: session.contact.name,
832
+ author: session.contact?.name ?? "You",
824
833
  body: message.body,
825
834
  createdAt,
826
835
  id: `${message.id}:server`,
package/dist/index.d.cts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { Root } from "react-dom/client";
2
2
  import { CSSProperties, ReactElement } from "react";
3
-
4
3
  //#region src/theme.d.ts
5
4
  /**
6
5
  * Theme resolution for the widget.
@@ -25,10 +24,7 @@ interface ResolveThemeOptions {
25
24
  * document, and guessing dark would flash the wrong palette on hydration for
26
25
  * the majority of pages.
27
26
  */
28
- declare function resolveTheme(theme: ChatWidgetTheme, {
29
- root,
30
- view
31
- }?: ResolveThemeOptions): ResolvedTheme;
27
+ declare function resolveTheme(theme: ChatWidgetTheme, { root, view }?: ResolveThemeOptions): ResolvedTheme;
32
28
  //#endregion
33
29
  //#region src/types.d.ts
34
30
  type WidgetSenderType = "visitor" | "operator" | "system";
@@ -58,7 +54,7 @@ interface WidgetMessage {
58
54
  senderType: WidgetSenderType;
59
55
  }
60
56
  interface WidgetSessionPayload {
61
- contact: WidgetContact;
57
+ contact: WidgetContact | null;
62
58
  conversation: WidgetConversation;
63
59
  expiresAt: string;
64
60
  messages: WidgetMessage[];
@@ -129,21 +125,13 @@ interface CreateWebSocketTransportOptions {
129
125
  getProtocols?: (session: WidgetSessionPayload) => string | string[] | undefined;
130
126
  resolveUrl: (session: WidgetSessionPayload) => string;
131
127
  }
132
- declare function createWebSocketTransport({
133
- createSocket,
134
- getProtocols,
135
- resolveUrl
136
- }: CreateWebSocketTransportOptions): CreateChatTransport;
128
+ declare function createWebSocketTransport({ createSocket, getProtocols, resolveUrl }: CreateWebSocketTransportOptions): CreateChatTransport;
137
129
  interface CreateLoopbackTransportOptions {
138
130
  operatorName?: string;
139
131
  operatorReply?: (body: string) => string | null;
140
132
  replyDelayMs?: number;
141
133
  }
142
- declare function createLoopbackTransport({
143
- operatorName,
144
- operatorReply,
145
- replyDelayMs
146
- }?: CreateLoopbackTransportOptions): CreateChatTransport;
134
+ declare function createLoopbackTransport({ operatorName, operatorReply, replyDelayMs }?: CreateLoopbackTransportOptions): CreateChatTransport;
147
135
  //#endregion
148
136
  //#region src/chat-widget.d.ts
149
137
  interface ChatWidgetProps {
@@ -167,17 +155,7 @@ interface ChatWidgetProps {
167
155
  theme?: ChatWidgetTheme;
168
156
  widgetId: string;
169
157
  }
170
- declare function ChatWidget({
171
- className,
172
- createTransport,
173
- getSession,
174
- initiallyOpen,
175
- launcherLabel,
176
- storage,
177
- style,
178
- theme,
179
- widgetId
180
- }: ChatWidgetProps): ReactElement;
158
+ declare function ChatWidget({ className, createTransport, getSession, initiallyOpen, launcherLabel, storage, style, theme, widgetId }: ChatWidgetProps): ReactElement;
181
159
  declare function ChatLauncher(): null;
182
160
  declare function ChatPanel(): null;
183
161
  declare function MessageComposer(): null;
@@ -228,10 +206,7 @@ interface CreateSessionFetcherOptions {
228
206
  fetchImpl?: typeof fetch;
229
207
  sessionUrl: string;
230
208
  }
231
- declare function createSessionFetcher({
232
- fetchImpl,
233
- sessionUrl
234
- }: CreateSessionFetcherOptions): GetSession;
209
+ declare function createSessionFetcher({ fetchImpl, sessionUrl }: CreateSessionFetcherOptions): GetSession;
235
210
  //#endregion
236
211
  //#region src/index.d.ts
237
212
  type ChatWidgetMount = ChatWidgetMount$1;
package/dist/index.d.mts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { Root } from "react-dom/client";
2
2
  import { CSSProperties, ReactElement } from "react";
3
-
4
3
  //#region src/theme.d.ts
5
4
  /**
6
5
  * Theme resolution for the widget.
@@ -25,10 +24,7 @@ interface ResolveThemeOptions {
25
24
  * document, and guessing dark would flash the wrong palette on hydration for
26
25
  * the majority of pages.
27
26
  */
28
- declare function resolveTheme(theme: ChatWidgetTheme, {
29
- root,
30
- view
31
- }?: ResolveThemeOptions): ResolvedTheme;
27
+ declare function resolveTheme(theme: ChatWidgetTheme, { root, view }?: ResolveThemeOptions): ResolvedTheme;
32
28
  //#endregion
33
29
  //#region src/types.d.ts
34
30
  type WidgetSenderType = "visitor" | "operator" | "system";
@@ -58,7 +54,7 @@ interface WidgetMessage {
58
54
  senderType: WidgetSenderType;
59
55
  }
60
56
  interface WidgetSessionPayload {
61
- contact: WidgetContact;
57
+ contact: WidgetContact | null;
62
58
  conversation: WidgetConversation;
63
59
  expiresAt: string;
64
60
  messages: WidgetMessage[];
@@ -129,21 +125,13 @@ interface CreateWebSocketTransportOptions {
129
125
  getProtocols?: (session: WidgetSessionPayload) => string | string[] | undefined;
130
126
  resolveUrl: (session: WidgetSessionPayload) => string;
131
127
  }
132
- declare function createWebSocketTransport({
133
- createSocket,
134
- getProtocols,
135
- resolveUrl
136
- }: CreateWebSocketTransportOptions): CreateChatTransport;
128
+ declare function createWebSocketTransport({ createSocket, getProtocols, resolveUrl }: CreateWebSocketTransportOptions): CreateChatTransport;
137
129
  interface CreateLoopbackTransportOptions {
138
130
  operatorName?: string;
139
131
  operatorReply?: (body: string) => string | null;
140
132
  replyDelayMs?: number;
141
133
  }
142
- declare function createLoopbackTransport({
143
- operatorName,
144
- operatorReply,
145
- replyDelayMs
146
- }?: CreateLoopbackTransportOptions): CreateChatTransport;
134
+ declare function createLoopbackTransport({ operatorName, operatorReply, replyDelayMs }?: CreateLoopbackTransportOptions): CreateChatTransport;
147
135
  //#endregion
148
136
  //#region src/chat-widget.d.ts
149
137
  interface ChatWidgetProps {
@@ -167,17 +155,7 @@ interface ChatWidgetProps {
167
155
  theme?: ChatWidgetTheme;
168
156
  widgetId: string;
169
157
  }
170
- declare function ChatWidget({
171
- className,
172
- createTransport,
173
- getSession,
174
- initiallyOpen,
175
- launcherLabel,
176
- storage,
177
- style,
178
- theme,
179
- widgetId
180
- }: ChatWidgetProps): ReactElement;
158
+ declare function ChatWidget({ className, createTransport, getSession, initiallyOpen, launcherLabel, storage, style, theme, widgetId }: ChatWidgetProps): ReactElement;
181
159
  declare function ChatLauncher(): null;
182
160
  declare function ChatPanel(): null;
183
161
  declare function MessageComposer(): null;
@@ -228,10 +206,7 @@ interface CreateSessionFetcherOptions {
228
206
  fetchImpl?: typeof fetch;
229
207
  sessionUrl: string;
230
208
  }
231
- declare function createSessionFetcher({
232
- fetchImpl,
233
- sessionUrl
234
- }: CreateSessionFetcherOptions): GetSession;
209
+ declare function createSessionFetcher({ fetchImpl, sessionUrl }: CreateSessionFetcherOptions): GetSession;
235
210
  //#endregion
236
211
  //#region src/index.d.ts
237
212
  type ChatWidgetMount = ChatWidgetMount$1;
package/dist/index.mjs CHANGED
@@ -339,6 +339,13 @@ const WIDGET_STYLES = `
339
339
  }
340
340
  `;
341
341
  const DEFAULT_STORAGE = typeof window === "undefined" ? void 0 : window.localStorage;
342
+ function sessionDisplayName(session) {
343
+ return session.contact?.name ?? "You";
344
+ }
345
+ function sessionSummaryText(session, fallback) {
346
+ if (!session) return fallback;
347
+ return session.contact ? `${session.contact.name} • ${session.contact.email}` : "Verified visitor";
348
+ }
342
349
  function createLocalMessage(message, delivery = "sent") {
343
350
  return {
344
351
  ...message,
@@ -536,16 +543,18 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
536
543
  setError(null);
537
544
  setIsConnecting(true);
538
545
  try {
546
+ const existingVisitorToken = storage?.getItem(createStorageKey(widgetId)) ?? null;
539
547
  const nextSession = await getSession({
540
548
  visitor,
541
- visitorToken: storage?.getItem(createStorageKey(widgetId)) ?? null,
549
+ visitorToken: existingVisitorToken,
542
550
  widgetId
543
551
  });
544
552
  storage?.setItem(createStorageKey(widgetId), nextSession.visitorToken);
545
553
  setSession(nextSession);
546
554
  setMessages(sortMessages(nextSession.messages.map((message) => createLocalMessage(message))));
547
555
  } catch (sessionError) {
548
- setError((sessionError instanceof Error ? sessionError : /* @__PURE__ */ new Error("Failed to start the conversation.")).message);
556
+ const resolved = sessionError instanceof Error ? sessionError : /* @__PURE__ */ new Error("Failed to start the conversation.");
557
+ setError(resolved.message);
549
558
  } finally {
550
559
  setIsConnecting(false);
551
560
  }
@@ -560,7 +569,7 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
560
569
  if (!body) return;
561
570
  const clientMessageId = generateId();
562
571
  const optimisticMessage = {
563
- author: session.contact.name,
572
+ author: sessionDisplayName(session),
564
573
  body,
565
574
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
566
575
  id: clientMessageId,
@@ -583,7 +592,7 @@ function ChatWidget({ className, createTransport, getSession, initiallyOpen = fa
583
592
  };
584
593
  const greeting = session?.widget.config.greeting ?? "Tell us a little about yourself and we’ll pick up the conversation from there.";
585
594
  const panelTitle = session?.widget.name ?? "Start a conversation";
586
- const sessionSummary = session ? `${session.contact.name} • ${session.contact.email}` : greeting;
595
+ const sessionSummary = sessionSummaryText(session, greeting);
587
596
  return /* @__PURE__ */ jsxs("div", {
588
597
  className: `clivly-chat-widget ${className ?? ""}`.trim(),
589
598
  "data-clivly-theme": resolvedTheme,
@@ -819,7 +828,7 @@ function createLoopbackTransport({ operatorName = "Clivly", operatorReply = (bod
819
828
  type: "message.ack",
820
829
  clientMessageId: message.id,
821
830
  message: {
822
- author: session.contact.name,
831
+ author: session.contact?.name ?? "You",
823
832
  body: message.body,
824
833
  createdAt,
825
834
  id: `${message.id}:server`,