@clivly/chat-widget 0.5.0 → 0.7.1
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 +2 -2
- package/dist/browser-mount.cjs +13 -4
- package/dist/browser-mount.d.cts +1 -2
- package/dist/browser-mount.d.mts +1 -2
- package/dist/browser-mount.mjs +13 -4
- package/dist/browser.cjs +13 -4
- package/dist/browser.d.cts +1 -2
- package/dist/browser.d.mts +1 -2
- package/dist/browser.mjs +13 -4
- package/dist/index.cjs +14 -5
- package/dist/index.d.cts +6 -31
- package/dist/index.d.mts +6 -31
- package/dist/index.mjs +14 -5
- package/dist/widget.global.js +130 -40
- package/package.json +52 -60
package/README.md
CHANGED
|
@@ -190,14 +190,14 @@ The `browser` and `browser-mount` outputs are built as standalone entrypoints.
|
|
|
190
190
|
## Host-side pairing
|
|
191
191
|
|
|
192
192
|
The host-side session handler is the bridge between a backend holding
|
|
193
|
-
`
|
|
193
|
+
`CLIVLY_SECRET_KEY` and the widget's `sessionUrl`. Import it from `clivly/sdk`,
|
|
194
194
|
which is available from the `clivly` package `clivly init` already installs:
|
|
195
195
|
|
|
196
196
|
```ts
|
|
197
197
|
import { createChatSessionHandler } from "clivly/sdk";
|
|
198
198
|
|
|
199
199
|
export const POST = createChatSessionHandler({
|
|
200
|
-
apiKey: process.env.CLIVLY_API_KEY,
|
|
200
|
+
apiKey: process.env.CLIVLY_SECRET_KEY ?? process.env.CLIVLY_API_KEY,
|
|
201
201
|
});
|
|
202
202
|
```
|
|
203
203
|
|
package/dist/browser-mount.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:
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
package/dist/browser-mount.d.cts
CHANGED
|
@@ -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-mount.d.mts
CHANGED
|
@@ -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-mount.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:
|
|
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
|
-
|
|
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
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
|
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
|
|
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,
|
package/dist/browser.d.cts
CHANGED
|
@@ -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.d.mts
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
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
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
831
|
+
author: session.contact?.name ?? "You",
|
|
823
832
|
body: message.body,
|
|
824
833
|
createdAt,
|
|
825
834
|
id: `${message.id}:server`,
|