@ensembleapp/client-sdk 0.0.4 → 0.0.7
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/dist/index.d.ts +48 -7
- package/dist/index.js +407 -114
- package/dist/index.js.map +1 -1
- package/dist/widget/widget.global.d.ts +22 -0
- package/dist/widget/widget.global.js +180 -0
- package/dist/widget/widget.global.js.map +1 -0
- package/package.json +15 -5
package/dist/index.js
CHANGED
|
@@ -136,6 +136,90 @@ function useChat({
|
|
|
136
136
|
};
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
// lib/hooks/useFeedback.ts
|
|
140
|
+
import { useCallback, useState as useState2 } from "react";
|
|
141
|
+
function useFeedback({
|
|
142
|
+
api,
|
|
143
|
+
threadId,
|
|
144
|
+
agentId,
|
|
145
|
+
agentExecutionId
|
|
146
|
+
}) {
|
|
147
|
+
const { baseUrl, token } = api;
|
|
148
|
+
const [submittedFeedback, setSubmittedFeedback] = useState2({});
|
|
149
|
+
const [isSubmitting, setIsSubmitting] = useState2(null);
|
|
150
|
+
const [error, setError] = useState2(null);
|
|
151
|
+
const submitFeedback = useCallback(
|
|
152
|
+
async ({ messageId, rating, improvementText }) => {
|
|
153
|
+
setIsSubmitting(messageId);
|
|
154
|
+
setError(null);
|
|
155
|
+
try {
|
|
156
|
+
const response = await fetch(`${baseUrl}/api/feedback`, {
|
|
157
|
+
method: "POST",
|
|
158
|
+
headers: {
|
|
159
|
+
"Content-Type": "application/json",
|
|
160
|
+
Authorization: `Bearer ${token}`
|
|
161
|
+
},
|
|
162
|
+
body: JSON.stringify({
|
|
163
|
+
threadId,
|
|
164
|
+
messageId,
|
|
165
|
+
rating,
|
|
166
|
+
improvementText: improvementText || void 0,
|
|
167
|
+
agentId: agentId || void 0,
|
|
168
|
+
orchestrationId: agentExecutionId || void 0
|
|
169
|
+
})
|
|
170
|
+
});
|
|
171
|
+
if (!response.ok) {
|
|
172
|
+
const errorData = await response.json().catch(() => ({}));
|
|
173
|
+
throw new Error(errorData.error || `Failed to submit feedback: ${response.statusText}`);
|
|
174
|
+
}
|
|
175
|
+
const { data } = await response.json();
|
|
176
|
+
const feedback = {
|
|
177
|
+
id: data.id,
|
|
178
|
+
messageId: data.messageId,
|
|
179
|
+
rating: data.rating,
|
|
180
|
+
improvementText: data.improvementText,
|
|
181
|
+
createdAt: new Date(data.createdAt)
|
|
182
|
+
};
|
|
183
|
+
setSubmittedFeedback((prev) => ({
|
|
184
|
+
...prev,
|
|
185
|
+
[messageId]: {
|
|
186
|
+
rating: feedback.rating,
|
|
187
|
+
comment: feedback.improvementText
|
|
188
|
+
}
|
|
189
|
+
}));
|
|
190
|
+
return feedback;
|
|
191
|
+
} catch (err) {
|
|
192
|
+
const error2 = err instanceof Error ? err : new Error("Unknown error");
|
|
193
|
+
setError(error2);
|
|
194
|
+
console.error("Failed to submit feedback:", error2);
|
|
195
|
+
return null;
|
|
196
|
+
} finally {
|
|
197
|
+
setIsSubmitting(null);
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
[baseUrl, token, threadId, agentId, agentExecutionId]
|
|
201
|
+
);
|
|
202
|
+
const getFeedbackForMessage = useCallback(
|
|
203
|
+
(messageId) => {
|
|
204
|
+
return submittedFeedback[messageId];
|
|
205
|
+
},
|
|
206
|
+
[submittedFeedback]
|
|
207
|
+
);
|
|
208
|
+
const hasFeedback = useCallback(
|
|
209
|
+
(messageId) => {
|
|
210
|
+
return messageId in submittedFeedback;
|
|
211
|
+
},
|
|
212
|
+
[submittedFeedback]
|
|
213
|
+
);
|
|
214
|
+
return {
|
|
215
|
+
submitFeedback,
|
|
216
|
+
getFeedbackForMessage,
|
|
217
|
+
hasFeedback,
|
|
218
|
+
isSubmitting,
|
|
219
|
+
error
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
139
223
|
// #style-inject:#style-inject
|
|
140
224
|
function styleInject(css, { insertAt } = {}) {
|
|
141
225
|
if (!css || typeof document === "undefined") return;
|
|
@@ -163,7 +247,7 @@ styleInject(':root[data-chat-widget],\n[data-chat-widget] {\n --chat-primary: #
|
|
|
163
247
|
|
|
164
248
|
// lib/components/ChatWidget.tsx
|
|
165
249
|
import { ChevronRight, Send, StopCircle } from "lucide-react";
|
|
166
|
-
import { useCallback as
|
|
250
|
+
import { useCallback as useCallback4, useEffect as useEffect4, useMemo, useRef as useRef2, useState as useState5 } from "react";
|
|
167
251
|
import ReactMarkdown from "react-markdown";
|
|
168
252
|
|
|
169
253
|
// ../../node_modules/ccount/index.js
|
|
@@ -7453,7 +7537,7 @@ ZodNaN.create = (params) => {
|
|
|
7453
7537
|
...processCreateParams(params)
|
|
7454
7538
|
});
|
|
7455
7539
|
};
|
|
7456
|
-
var BRAND = Symbol("zod_brand");
|
|
7540
|
+
var BRAND = /* @__PURE__ */ Symbol("zod_brand");
|
|
7457
7541
|
var ZodBranded = class extends ZodType {
|
|
7458
7542
|
_parse(input) {
|
|
7459
7543
|
const { ctx } = this._processInputParams(input);
|
|
@@ -7670,7 +7754,7 @@ var NEVER = INVALID;
|
|
|
7670
7754
|
var zod_default = external_exports;
|
|
7671
7755
|
|
|
7672
7756
|
// ../../node_modules/zod-to-json-schema/dist/esm/Options.js
|
|
7673
|
-
var ignoreOverride = Symbol("Let zodToJsonSchema decide on which parser to use");
|
|
7757
|
+
var ignoreOverride = /* @__PURE__ */ Symbol("Let zodToJsonSchema decide on which parser to use");
|
|
7674
7758
|
var defaultOptions = {
|
|
7675
7759
|
name: void 0,
|
|
7676
7760
|
$refStrategy: "root",
|
|
@@ -8993,15 +9077,194 @@ function cn(...inputs) {
|
|
|
8993
9077
|
return twMerge(clsx(inputs));
|
|
8994
9078
|
}
|
|
8995
9079
|
|
|
9080
|
+
// lib/components/MessageFeedback.css
|
|
9081
|
+
styleInject(".chat-widget__feedback {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n margin-top: 0.35rem;\n}\n.chat-widget__feedback-button {\n border: none;\n background: transparent;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.75rem;\n height: 1.75rem;\n padding: 0;\n color: #9ca3af;\n cursor: pointer;\n border-radius: 0.35rem;\n transition: all 0.15s ease;\n}\n.chat-widget__feedback-button:hover:not(:disabled) {\n background: rgba(0, 0, 0, 0.05);\n color: #6b7280;\n}\n.chat-widget__feedback-button:disabled {\n cursor: default;\n opacity: 0.5;\n}\n.chat-widget__feedback-button--positive.chat-widget__feedback-button--selected {\n color: #22c55e;\n background: rgba(34, 197, 94, 0.1);\n}\n.chat-widget__feedback-button--negative.chat-widget__feedback-button--selected {\n color: #ef4444;\n background: rgba(239, 68, 68, 0.1);\n}\n.chat-widget__feedback-button--comment.chat-widget__feedback-button--selected {\n color: var(--chat-primary, #3b82f6);\n background: rgba(59, 130, 246, 0.1);\n}\n.chat-widget__feedback-button--comment.chat-widget__feedback-button--has-content {\n color: var(--chat-primary, #3b82f6);\n}\n.chat-widget__feedback-icon {\n width: 1rem;\n height: 1rem;\n}\n.chat-widget__feedback-comment-section {\n margin-top: 0.75rem;\n background: var(--chat-background, #ffffff);\n border: 1px solid var(--chat-border, #e5e7eb);\n border-radius: 0.5rem;\n padding: 0.75rem;\n width: 100%;\n max-width: 400px;\n}\n.chat-widget__feedback-comment-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 0.5rem;\n font-size: 0.8125rem;\n font-weight: 600;\n color: var(--chat-assistant-text, #111827);\n}\n.chat-widget__feedback-comment-required {\n font-size: 0.6875rem;\n font-weight: 500;\n color: #ef4444;\n background: rgba(239, 68, 68, 0.1);\n padding: 0.125rem 0.375rem;\n border-radius: 0.25rem;\n}\n.chat-widget__feedback-textarea {\n width: 100%;\n min-height: 120px;\n padding: 0.625rem;\n border: 1px solid var(--chat-border, #e5e7eb);\n border-radius: 0.35rem;\n font-size: 0.875rem;\n font-family: inherit;\n resize: vertical;\n color: var(--chat-input-text, #111827);\n background: var(--chat-input-bg, #ffffff);\n line-height: 1.5;\n}\n.chat-widget__feedback-textarea:focus {\n outline: none;\n border-color: var(--chat-primary, #3b82f6);\n box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);\n}\n.chat-widget__feedback-textarea::-moz-placeholder {\n color: var(--chat-input-placeholder, #6b7280);\n}\n.chat-widget__feedback-textarea::placeholder {\n color: var(--chat-input-placeholder, #6b7280);\n}\n.chat-widget__feedback-actions {\n display: flex;\n justify-content: flex-end;\n gap: 0.5rem;\n margin-top: 0.75rem;\n}\n.chat-widget__feedback-cancel,\n.chat-widget__feedback-submit {\n padding: 0.5rem 1rem;\n font-size: 0.8125rem;\n font-weight: 500;\n border-radius: 0.35rem;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n.chat-widget__feedback-cancel {\n background: transparent;\n border: 1px solid var(--chat-border, #e5e7eb);\n color: #6b7280;\n}\n.chat-widget__feedback-cancel:hover {\n background: rgba(0, 0, 0, 0.05);\n}\n.chat-widget__feedback-submit {\n background: var(--chat-primary, #3b82f6);\n border: none;\n color: var(--chat-primary-text, #ffffff);\n}\n.chat-widget__feedback-submit:hover:not(:disabled) {\n background: var(--chat-primary-hover, #2563eb);\n}\n.chat-widget__feedback-submit:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.chat-widget__feedback-wrapper {\n position: relative;\n}\n");
|
|
9082
|
+
|
|
9083
|
+
// lib/components/MessageFeedback.tsx
|
|
9084
|
+
import { MessageSquare, ThumbsDown, ThumbsUp } from "lucide-react";
|
|
9085
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useState as useState3 } from "react";
|
|
9086
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9087
|
+
var classNames = {
|
|
9088
|
+
wrapper: "chat-widget__feedback-wrapper",
|
|
9089
|
+
container: "chat-widget__feedback",
|
|
9090
|
+
button: "chat-widget__feedback-button",
|
|
9091
|
+
buttonPositive: "chat-widget__feedback-button--positive",
|
|
9092
|
+
buttonNegative: "chat-widget__feedback-button--negative",
|
|
9093
|
+
buttonComment: "chat-widget__feedback-button--comment",
|
|
9094
|
+
buttonSelected: "chat-widget__feedback-button--selected",
|
|
9095
|
+
buttonHasContent: "chat-widget__feedback-button--has-content",
|
|
9096
|
+
icon: "chat-widget__feedback-icon",
|
|
9097
|
+
commentSection: "chat-widget__feedback-comment-section",
|
|
9098
|
+
commentHeader: "chat-widget__feedback-comment-header",
|
|
9099
|
+
commentRequired: "chat-widget__feedback-comment-required",
|
|
9100
|
+
textarea: "chat-widget__feedback-textarea",
|
|
9101
|
+
actions: "chat-widget__feedback-actions",
|
|
9102
|
+
cancelButton: "chat-widget__feedback-cancel",
|
|
9103
|
+
submitButton: "chat-widget__feedback-submit"
|
|
9104
|
+
};
|
|
9105
|
+
var MessageFeedback = ({
|
|
9106
|
+
messageId,
|
|
9107
|
+
existingRating,
|
|
9108
|
+
existingComment,
|
|
9109
|
+
isSubmitting,
|
|
9110
|
+
requireCommentForNegative = false,
|
|
9111
|
+
onSubmit
|
|
9112
|
+
}) => {
|
|
9113
|
+
const [savedRating, setSavedRating] = useState3(existingRating ?? null);
|
|
9114
|
+
const [savedComment, setSavedComment] = useState3(existingComment ?? "");
|
|
9115
|
+
const [pendingRating, setPendingRating] = useState3(null);
|
|
9116
|
+
const [showCommentBox, setShowCommentBox] = useState3(false);
|
|
9117
|
+
const [commentText, setCommentText] = useState3(existingComment ?? "");
|
|
9118
|
+
useEffect2(() => {
|
|
9119
|
+
if (existingRating) {
|
|
9120
|
+
setSavedRating(existingRating);
|
|
9121
|
+
}
|
|
9122
|
+
if (existingComment !== void 0) {
|
|
9123
|
+
setSavedComment(existingComment);
|
|
9124
|
+
setCommentText(existingComment);
|
|
9125
|
+
}
|
|
9126
|
+
}, [existingRating, existingComment]);
|
|
9127
|
+
const handlePositiveClick = useCallback2(() => {
|
|
9128
|
+
setSavedRating("positive");
|
|
9129
|
+
setPendingRating(null);
|
|
9130
|
+
onSubmit(messageId, "positive", commentText.trim() || void 0);
|
|
9131
|
+
}, [messageId, commentText, onSubmit]);
|
|
9132
|
+
const handleNegativeClick = useCallback2(() => {
|
|
9133
|
+
if (requireCommentForNegative) {
|
|
9134
|
+
setPendingRating("negative");
|
|
9135
|
+
setShowCommentBox(true);
|
|
9136
|
+
} else {
|
|
9137
|
+
setSavedRating("negative");
|
|
9138
|
+
setPendingRating(null);
|
|
9139
|
+
onSubmit(messageId, "negative", commentText.trim() || void 0);
|
|
9140
|
+
}
|
|
9141
|
+
}, [messageId, commentText, requireCommentForNegative, onSubmit]);
|
|
9142
|
+
const handleCommentToggle = useCallback2(() => {
|
|
9143
|
+
if (showCommentBox) {
|
|
9144
|
+
setShowCommentBox(false);
|
|
9145
|
+
if (pendingRating === "negative" && requireCommentForNegative) {
|
|
9146
|
+
setPendingRating(null);
|
|
9147
|
+
}
|
|
9148
|
+
setCommentText(savedComment);
|
|
9149
|
+
} else {
|
|
9150
|
+
setShowCommentBox(true);
|
|
9151
|
+
}
|
|
9152
|
+
}, [showCommentBox, pendingRating, requireCommentForNegative, savedComment]);
|
|
9153
|
+
const handleCommentCancel = useCallback2(() => {
|
|
9154
|
+
setShowCommentBox(false);
|
|
9155
|
+
setCommentText(savedComment);
|
|
9156
|
+
if (pendingRating === "negative" && requireCommentForNegative) {
|
|
9157
|
+
setPendingRating(null);
|
|
9158
|
+
}
|
|
9159
|
+
}, [pendingRating, requireCommentForNegative, savedComment]);
|
|
9160
|
+
const handleCommentSubmit = useCallback2(() => {
|
|
9161
|
+
const ratingToSubmit = pendingRating ?? savedRating;
|
|
9162
|
+
if (!ratingToSubmit) {
|
|
9163
|
+
return;
|
|
9164
|
+
}
|
|
9165
|
+
if (ratingToSubmit === "negative" && requireCommentForNegative && !commentText.trim()) {
|
|
9166
|
+
return;
|
|
9167
|
+
}
|
|
9168
|
+
onSubmit(messageId, ratingToSubmit, commentText.trim() || void 0);
|
|
9169
|
+
setSavedRating(ratingToSubmit);
|
|
9170
|
+
setSavedComment(commentText.trim());
|
|
9171
|
+
setPendingRating(null);
|
|
9172
|
+
setShowCommentBox(false);
|
|
9173
|
+
}, [messageId, pendingRating, savedRating, commentText, requireCommentForNegative, onSubmit]);
|
|
9174
|
+
const displayRating = pendingRating ?? savedRating;
|
|
9175
|
+
const isPositiveSelected = displayRating === "positive";
|
|
9176
|
+
const isNegativeSelected = displayRating === "negative";
|
|
9177
|
+
const isCommentRequired = isNegativeSelected && requireCommentForNegative;
|
|
9178
|
+
const canSubmitComment = !isCommentRequired || commentText.trim().length > 0;
|
|
9179
|
+
const hasComment = savedComment.length > 0;
|
|
9180
|
+
return /* @__PURE__ */ jsxs("div", { className: classNames.wrapper, children: [
|
|
9181
|
+
/* @__PURE__ */ jsxs("div", { className: classNames.container, children: [
|
|
9182
|
+
/* @__PURE__ */ jsx(
|
|
9183
|
+
"button",
|
|
9184
|
+
{
|
|
9185
|
+
type: "button",
|
|
9186
|
+
className: `${classNames.button} ${classNames.buttonPositive} ${isPositiveSelected ? classNames.buttonSelected : ""}`,
|
|
9187
|
+
onClick: handlePositiveClick,
|
|
9188
|
+
disabled: isSubmitting,
|
|
9189
|
+
title: "Good response",
|
|
9190
|
+
"aria-label": "Mark as good response",
|
|
9191
|
+
children: /* @__PURE__ */ jsx(ThumbsUp, { className: classNames.icon })
|
|
9192
|
+
}
|
|
9193
|
+
),
|
|
9194
|
+
/* @__PURE__ */ jsx(
|
|
9195
|
+
"button",
|
|
9196
|
+
{
|
|
9197
|
+
type: "button",
|
|
9198
|
+
className: `${classNames.button} ${classNames.buttonNegative} ${isNegativeSelected ? classNames.buttonSelected : ""}`,
|
|
9199
|
+
onClick: handleNegativeClick,
|
|
9200
|
+
disabled: isSubmitting,
|
|
9201
|
+
title: "Could be improved",
|
|
9202
|
+
"aria-label": "Mark as could be improved",
|
|
9203
|
+
children: /* @__PURE__ */ jsx(ThumbsDown, { className: classNames.icon })
|
|
9204
|
+
}
|
|
9205
|
+
),
|
|
9206
|
+
/* @__PURE__ */ jsx(
|
|
9207
|
+
"button",
|
|
9208
|
+
{
|
|
9209
|
+
type: "button",
|
|
9210
|
+
className: `${classNames.button} ${classNames.buttonComment} ${showCommentBox ? classNames.buttonSelected : ""} ${hasComment ? classNames.buttonHasContent : ""}`,
|
|
9211
|
+
onClick: handleCommentToggle,
|
|
9212
|
+
disabled: isSubmitting,
|
|
9213
|
+
title: "Add comment",
|
|
9214
|
+
"aria-label": "Add comment",
|
|
9215
|
+
children: /* @__PURE__ */ jsx(MessageSquare, { className: classNames.icon })
|
|
9216
|
+
}
|
|
9217
|
+
)
|
|
9218
|
+
] }),
|
|
9219
|
+
showCommentBox && /* @__PURE__ */ jsxs("div", { className: classNames.commentSection, children: [
|
|
9220
|
+
/* @__PURE__ */ jsxs("div", { className: classNames.commentHeader, children: [
|
|
9221
|
+
/* @__PURE__ */ jsx("span", { children: "Add a comment" }),
|
|
9222
|
+
isCommentRequired && /* @__PURE__ */ jsx("span", { className: classNames.commentRequired, children: "Required" })
|
|
9223
|
+
] }),
|
|
9224
|
+
/* @__PURE__ */ jsx(
|
|
9225
|
+
"textarea",
|
|
9226
|
+
{
|
|
9227
|
+
className: classNames.textarea,
|
|
9228
|
+
placeholder: isNegativeSelected ? "What could be improved?" : "Share your thoughts...",
|
|
9229
|
+
value: commentText,
|
|
9230
|
+
onChange: (e) => setCommentText(e.target.value),
|
|
9231
|
+
rows: 5
|
|
9232
|
+
}
|
|
9233
|
+
),
|
|
9234
|
+
/* @__PURE__ */ jsxs("div", { className: classNames.actions, children: [
|
|
9235
|
+
/* @__PURE__ */ jsx(
|
|
9236
|
+
"button",
|
|
9237
|
+
{
|
|
9238
|
+
type: "button",
|
|
9239
|
+
className: classNames.cancelButton,
|
|
9240
|
+
onClick: handleCommentCancel,
|
|
9241
|
+
children: "Cancel"
|
|
9242
|
+
}
|
|
9243
|
+
),
|
|
9244
|
+
/* @__PURE__ */ jsx(
|
|
9245
|
+
"button",
|
|
9246
|
+
{
|
|
9247
|
+
type: "button",
|
|
9248
|
+
className: classNames.submitButton,
|
|
9249
|
+
onClick: handleCommentSubmit,
|
|
9250
|
+
disabled: isSubmitting || !canSubmitComment || !displayRating,
|
|
9251
|
+
children: displayRating ? "Save" : "Select Rating First"
|
|
9252
|
+
}
|
|
9253
|
+
)
|
|
9254
|
+
] })
|
|
9255
|
+
] })
|
|
9256
|
+
] });
|
|
9257
|
+
};
|
|
9258
|
+
|
|
8996
9259
|
// lib/components/SpeechToTextButton.tsx
|
|
8997
9260
|
import { Mic, MicOff } from "lucide-react";
|
|
8998
9261
|
import {
|
|
8999
|
-
useCallback,
|
|
9000
|
-
useEffect as
|
|
9262
|
+
useCallback as useCallback3,
|
|
9263
|
+
useEffect as useEffect3,
|
|
9001
9264
|
useRef,
|
|
9002
|
-
useState as
|
|
9265
|
+
useState as useState4
|
|
9003
9266
|
} from "react";
|
|
9004
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9267
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
9005
9268
|
var getSpeechRecognitionCtor = () => {
|
|
9006
9269
|
if (typeof window === "undefined") return null;
|
|
9007
9270
|
const win = window;
|
|
@@ -9020,36 +9283,36 @@ function SpeechToTextButton({
|
|
|
9020
9283
|
disabled,
|
|
9021
9284
|
className
|
|
9022
9285
|
}) {
|
|
9023
|
-
const [isListening, setIsListening] =
|
|
9024
|
-
const [isSupported, setIsSupported] =
|
|
9025
|
-
const [countdown, setCountdown] =
|
|
9286
|
+
const [isListening, setIsListening] = useState4(false);
|
|
9287
|
+
const [isSupported, setIsSupported] = useState4(false);
|
|
9288
|
+
const [countdown, setCountdown] = useState4(0);
|
|
9026
9289
|
const recognitionRef = useRef(null);
|
|
9027
|
-
const [countdownActive, setCountdownActive] =
|
|
9290
|
+
const [countdownActive, setCountdownActive] = useState4(false);
|
|
9028
9291
|
const silenceTimer = useRef(null);
|
|
9029
9292
|
const finalTimer = useRef(null);
|
|
9030
9293
|
const finalTextRef = useRef("");
|
|
9031
9294
|
const countdownFrameRef = useRef(null);
|
|
9032
9295
|
const countdownEndRef = useRef(0);
|
|
9033
9296
|
const recognitionLanguage = language ?? "en-US";
|
|
9034
|
-
const clearSilenceTimer =
|
|
9297
|
+
const clearSilenceTimer = useCallback3(() => {
|
|
9035
9298
|
if (silenceTimer.current) {
|
|
9036
9299
|
clearTimeout(silenceTimer.current);
|
|
9037
9300
|
silenceTimer.current = null;
|
|
9038
9301
|
}
|
|
9039
9302
|
}, []);
|
|
9040
|
-
const clearCountdownFrame =
|
|
9303
|
+
const clearCountdownFrame = useCallback3(() => {
|
|
9041
9304
|
if (countdownFrameRef.current) {
|
|
9042
9305
|
cancelAnimationFrame(countdownFrameRef.current);
|
|
9043
9306
|
countdownFrameRef.current = null;
|
|
9044
9307
|
}
|
|
9045
9308
|
}, []);
|
|
9046
|
-
const clearFinalTimer =
|
|
9309
|
+
const clearFinalTimer = useCallback3(() => {
|
|
9047
9310
|
if (finalTimer.current) {
|
|
9048
9311
|
clearTimeout(finalTimer.current);
|
|
9049
9312
|
finalTimer.current = null;
|
|
9050
9313
|
}
|
|
9051
9314
|
}, []);
|
|
9052
|
-
const stopListening =
|
|
9315
|
+
const stopListening = useCallback3(() => {
|
|
9053
9316
|
clearSilenceTimer();
|
|
9054
9317
|
clearFinalTimer();
|
|
9055
9318
|
clearCountdownFrame();
|
|
@@ -9058,26 +9321,26 @@ function SpeechToTextButton({
|
|
|
9058
9321
|
countdownEndRef.current = 0;
|
|
9059
9322
|
recognitionRef.current?.stop();
|
|
9060
9323
|
}, [clearSilenceTimer, clearFinalTimer, clearCountdownFrame]);
|
|
9061
|
-
const handleRecognitionError =
|
|
9324
|
+
const handleRecognitionError = useCallback3((message) => {
|
|
9062
9325
|
console.error("Speech recognition error:", message);
|
|
9063
9326
|
onError?.(message);
|
|
9064
9327
|
}, [onError]);
|
|
9065
|
-
const resetSilenceTimer =
|
|
9328
|
+
const resetSilenceTimer = useCallback3(() => {
|
|
9066
9329
|
if (!silenceTimeout) return;
|
|
9067
9330
|
clearSilenceTimer();
|
|
9068
9331
|
silenceTimer.current = setTimeout(stopListening, silenceTimeout);
|
|
9069
9332
|
}, [silenceTimeout, clearSilenceTimer, stopListening]);
|
|
9070
|
-
const dispatchInterim =
|
|
9333
|
+
const dispatchInterim = useCallback3((text3) => {
|
|
9071
9334
|
if (text3) {
|
|
9072
9335
|
onInterim?.(text3);
|
|
9073
9336
|
}
|
|
9074
9337
|
}, [onInterim]);
|
|
9075
|
-
const dispatchFinal =
|
|
9338
|
+
const dispatchFinal = useCallback3((text3) => {
|
|
9076
9339
|
if (text3) {
|
|
9077
9340
|
onFinal?.(text3);
|
|
9078
9341
|
}
|
|
9079
9342
|
}, [onFinal]);
|
|
9080
|
-
const flushFinalText =
|
|
9343
|
+
const flushFinalText = useCallback3(() => {
|
|
9081
9344
|
const buffered = finalTextRef.current.trim();
|
|
9082
9345
|
if (buffered) {
|
|
9083
9346
|
dispatchFinal(buffered);
|
|
@@ -9085,7 +9348,7 @@ function SpeechToTextButton({
|
|
|
9085
9348
|
finalTextRef.current = "";
|
|
9086
9349
|
clearFinalTimer();
|
|
9087
9350
|
}, [dispatchFinal, clearFinalTimer]);
|
|
9088
|
-
const updateCountdown =
|
|
9351
|
+
const updateCountdown = useCallback3(() => {
|
|
9089
9352
|
if (!countdownEndRef.current || !finalDelay) {
|
|
9090
9353
|
setCountdown(0);
|
|
9091
9354
|
setCountdownActive(false);
|
|
@@ -9102,7 +9365,7 @@ function SpeechToTextButton({
|
|
|
9102
9365
|
}
|
|
9103
9366
|
countdownFrameRef.current = requestAnimationFrame(updateCountdown);
|
|
9104
9367
|
}, [finalDelay]);
|
|
9105
|
-
const startCountdown =
|
|
9368
|
+
const startCountdown = useCallback3(() => {
|
|
9106
9369
|
if (!finalDelay) {
|
|
9107
9370
|
setCountdown(0);
|
|
9108
9371
|
setCountdownActive(false);
|
|
@@ -9114,7 +9377,7 @@ function SpeechToTextButton({
|
|
|
9114
9377
|
clearCountdownFrame();
|
|
9115
9378
|
countdownFrameRef.current = requestAnimationFrame(updateCountdown);
|
|
9116
9379
|
}, [finalDelay, clearCountdownFrame, updateCountdown]);
|
|
9117
|
-
const scheduleFinalFlush =
|
|
9380
|
+
const scheduleFinalFlush = useCallback3(() => {
|
|
9118
9381
|
clearFinalTimer();
|
|
9119
9382
|
if (!finalDelay) {
|
|
9120
9383
|
flushFinalText();
|
|
@@ -9123,7 +9386,7 @@ function SpeechToTextButton({
|
|
|
9123
9386
|
startCountdown();
|
|
9124
9387
|
finalTimer.current = setTimeout(flushFinalText, finalDelay);
|
|
9125
9388
|
}, [clearFinalTimer, finalDelay, flushFinalText, startCountdown]);
|
|
9126
|
-
const attachRecognitionHandlers =
|
|
9389
|
+
const attachRecognitionHandlers = useCallback3((recognition) => {
|
|
9127
9390
|
recognition.continuous = true;
|
|
9128
9391
|
recognition.interimResults = true;
|
|
9129
9392
|
recognition.lang = recognitionLanguage;
|
|
@@ -9181,7 +9444,7 @@ function SpeechToTextButton({
|
|
|
9181
9444
|
}
|
|
9182
9445
|
};
|
|
9183
9446
|
}, [recognitionLanguage, resetSilenceTimer, startCountdown, dispatchInterim, scheduleFinalFlush, handleRecognitionError, onListeningChange, clearSilenceTimer, flushFinalText, countdownActive]);
|
|
9184
|
-
const ensureRecognition =
|
|
9447
|
+
const ensureRecognition = useCallback3(() => {
|
|
9185
9448
|
if (typeof window === "undefined") {
|
|
9186
9449
|
return null;
|
|
9187
9450
|
}
|
|
@@ -9196,7 +9459,7 @@ function SpeechToTextButton({
|
|
|
9196
9459
|
attachRecognitionHandlers(recognitionRef.current);
|
|
9197
9460
|
return recognitionRef.current;
|
|
9198
9461
|
}, [attachRecognitionHandlers, handleRecognitionError]);
|
|
9199
|
-
const toggleListening =
|
|
9462
|
+
const toggleListening = useCallback3(() => {
|
|
9200
9463
|
if (disabled) {
|
|
9201
9464
|
return;
|
|
9202
9465
|
}
|
|
@@ -9214,15 +9477,15 @@ function SpeechToTextButton({
|
|
|
9214
9477
|
handleRecognitionError("Microphone permission denied or unavailable.");
|
|
9215
9478
|
}
|
|
9216
9479
|
}, [disabled, isListening, stopListening, ensureRecognition, handleRecognitionError]);
|
|
9217
|
-
|
|
9480
|
+
useEffect3(() => {
|
|
9218
9481
|
if (disabled && isListening) {
|
|
9219
9482
|
stopListening();
|
|
9220
9483
|
}
|
|
9221
9484
|
}, [disabled, isListening, stopListening]);
|
|
9222
|
-
|
|
9485
|
+
useEffect3(() => {
|
|
9223
9486
|
setIsSupported(typeof window !== "undefined" && !!getSpeechRecognitionCtor());
|
|
9224
9487
|
}, []);
|
|
9225
|
-
|
|
9488
|
+
useEffect3(() => {
|
|
9226
9489
|
return () => {
|
|
9227
9490
|
clearSilenceTimer();
|
|
9228
9491
|
clearFinalTimer();
|
|
@@ -9234,7 +9497,7 @@ function SpeechToTextButton({
|
|
|
9234
9497
|
if (!isSupported) {
|
|
9235
9498
|
return null;
|
|
9236
9499
|
}
|
|
9237
|
-
return /* @__PURE__ */
|
|
9500
|
+
return /* @__PURE__ */ jsxs2(
|
|
9238
9501
|
"button",
|
|
9239
9502
|
{
|
|
9240
9503
|
type: "button",
|
|
@@ -9248,8 +9511,8 @@ function SpeechToTextButton({
|
|
|
9248
9511
|
"aria-pressed": isListening,
|
|
9249
9512
|
"aria-label": "Toggle microphone",
|
|
9250
9513
|
children: [
|
|
9251
|
-
isListening ? /* @__PURE__ */
|
|
9252
|
-
finalDelay > 0 && isListening && countdownActive && /* @__PURE__ */
|
|
9514
|
+
isListening ? /* @__PURE__ */ jsx2(Mic, { className: "chat-widget__mic-icon" }) : /* @__PURE__ */ jsx2(MicOff, { className: "chat-widget__mic-icon" }),
|
|
9515
|
+
finalDelay > 0 && isListening && countdownActive && /* @__PURE__ */ jsx2("span", { className: "chat-widget__mic-bar", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(
|
|
9253
9516
|
"span",
|
|
9254
9517
|
{
|
|
9255
9518
|
className: "chat-widget__mic-bar-fill",
|
|
@@ -9262,12 +9525,12 @@ function SpeechToTextButton({
|
|
|
9262
9525
|
}
|
|
9263
9526
|
|
|
9264
9527
|
// lib/components/ChatWidget.tsx
|
|
9265
|
-
import { jsx as
|
|
9528
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
9266
9529
|
var FormattedMarkdown = ({ children }) => {
|
|
9267
9530
|
const MarkdownComponent = ReactMarkdown;
|
|
9268
|
-
return /* @__PURE__ */
|
|
9531
|
+
return /* @__PURE__ */ jsx3(MarkdownComponent, { remarkPlugins: [remarkGfm], children: children.replace(/\n\n/gi, "\n\n \n\n") });
|
|
9269
9532
|
};
|
|
9270
|
-
var
|
|
9533
|
+
var classNames2 = {
|
|
9271
9534
|
container: "chat-widget",
|
|
9272
9535
|
header: "chat-widget__header",
|
|
9273
9536
|
headerTitle: "chat-widget__title",
|
|
@@ -9340,7 +9603,8 @@ function ChatWidget({
|
|
|
9340
9603
|
styles: styleProps,
|
|
9341
9604
|
voice,
|
|
9342
9605
|
speechToText,
|
|
9343
|
-
widgets
|
|
9606
|
+
widgets,
|
|
9607
|
+
feedback
|
|
9344
9608
|
}) {
|
|
9345
9609
|
const theme = useMemo(
|
|
9346
9610
|
() => ({ ...defaultTheme, ...styleProps || {} }),
|
|
@@ -9366,9 +9630,9 @@ function ChatWidget({
|
|
|
9366
9630
|
}),
|
|
9367
9631
|
[theme]
|
|
9368
9632
|
);
|
|
9369
|
-
const [input, setInput] =
|
|
9370
|
-
const [isMicActive, setIsMicActive] =
|
|
9371
|
-
const [isSpeechPending, setIsSpeechPending] =
|
|
9633
|
+
const [input, setInput] = useState5("");
|
|
9634
|
+
const [isMicActive, setIsMicActive] = useState5(false);
|
|
9635
|
+
const [isSpeechPending, setIsSpeechPending] = useState5(false);
|
|
9372
9636
|
const messagesEndRef = useRef2(null);
|
|
9373
9637
|
const textareaRef = useRef2(null);
|
|
9374
9638
|
const {
|
|
@@ -9388,6 +9652,23 @@ function ChatWidget({
|
|
|
9388
9652
|
onFinish,
|
|
9389
9653
|
onMessage
|
|
9390
9654
|
});
|
|
9655
|
+
const feedbackEnabled = feedback?.enabled !== false;
|
|
9656
|
+
const {
|
|
9657
|
+
submitFeedback,
|
|
9658
|
+
getFeedbackForMessage,
|
|
9659
|
+
isSubmitting: feedbackSubmitting
|
|
9660
|
+
} = useFeedback({
|
|
9661
|
+
api,
|
|
9662
|
+
threadId,
|
|
9663
|
+
agentId: agentId ?? void 0,
|
|
9664
|
+
agentExecutionId: agentExecutionId ?? void 0
|
|
9665
|
+
});
|
|
9666
|
+
const handleFeedbackSubmit = useCallback4(
|
|
9667
|
+
(messageId, rating, improvementText) => {
|
|
9668
|
+
submitFeedback({ messageId, rating, improvementText });
|
|
9669
|
+
},
|
|
9670
|
+
[submitFeedback]
|
|
9671
|
+
);
|
|
9391
9672
|
const voiceConfig = useMemo(() => {
|
|
9392
9673
|
if (!voice || voice.enabled === false || !voice.url) {
|
|
9393
9674
|
return null;
|
|
@@ -9412,7 +9693,7 @@ function ChatWidget({
|
|
|
9412
9693
|
buildPayload
|
|
9413
9694
|
};
|
|
9414
9695
|
}, [voice]);
|
|
9415
|
-
|
|
9696
|
+
useEffect4(() => {
|
|
9416
9697
|
if (introMessage && messages.length === 0) {
|
|
9417
9698
|
setMessages([{
|
|
9418
9699
|
id: "welcome-message",
|
|
@@ -9421,16 +9702,16 @@ function ChatWidget({
|
|
|
9421
9702
|
}]);
|
|
9422
9703
|
}
|
|
9423
9704
|
}, [introMessage, messages.length, setMessages]);
|
|
9424
|
-
|
|
9705
|
+
useEffect4(() => {
|
|
9425
9706
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
9426
9707
|
}, [messages, status]);
|
|
9427
|
-
|
|
9708
|
+
useEffect4(() => {
|
|
9428
9709
|
const timer = setTimeout(() => {
|
|
9429
9710
|
textareaRef.current?.focus();
|
|
9430
9711
|
}, 150);
|
|
9431
9712
|
return () => clearTimeout(timer);
|
|
9432
9713
|
}, []);
|
|
9433
|
-
|
|
9714
|
+
useEffect4(() => {
|
|
9434
9715
|
if (status === "ready") {
|
|
9435
9716
|
textareaRef.current?.focus();
|
|
9436
9717
|
}
|
|
@@ -9438,7 +9719,7 @@ function ChatWidget({
|
|
|
9438
9719
|
setIsSpeechPending(false);
|
|
9439
9720
|
}
|
|
9440
9721
|
}, [status]);
|
|
9441
|
-
const sendText =
|
|
9722
|
+
const sendText = useCallback4((raw) => {
|
|
9442
9723
|
const text3 = (raw ?? input).trim();
|
|
9443
9724
|
if (!text3 || status !== "ready") return false;
|
|
9444
9725
|
sendMessage({ text: text3 });
|
|
@@ -9459,10 +9740,10 @@ function ChatWidget({
|
|
|
9459
9740
|
}
|
|
9460
9741
|
};
|
|
9461
9742
|
const speechEnabled = speechToText?.enabled !== false;
|
|
9462
|
-
const handleSpeechInterim =
|
|
9743
|
+
const handleSpeechInterim = useCallback4((text3) => {
|
|
9463
9744
|
setInput(text3);
|
|
9464
9745
|
}, [setInput]);
|
|
9465
|
-
const handleSpeechFinal =
|
|
9746
|
+
const handleSpeechFinal = useCallback4((text3) => {
|
|
9466
9747
|
const finalText = text3?.trim();
|
|
9467
9748
|
if (!finalText || isSpeechPending) return;
|
|
9468
9749
|
setInput(finalText);
|
|
@@ -9471,28 +9752,28 @@ function ChatWidget({
|
|
|
9471
9752
|
setIsSpeechPending(true);
|
|
9472
9753
|
}
|
|
9473
9754
|
}, [sendText, setInput, isSpeechPending]);
|
|
9474
|
-
|
|
9755
|
+
useEffect4(() => {
|
|
9475
9756
|
if (!speechEnabled) {
|
|
9476
9757
|
setIsMicActive(false);
|
|
9477
9758
|
}
|
|
9478
9759
|
}, [speechEnabled]);
|
|
9479
|
-
const renderOutput =
|
|
9760
|
+
const renderOutput = useCallback4(
|
|
9480
9761
|
(messageId, content) => content.map((entry, index) => {
|
|
9481
9762
|
if (typeof entry === "string") {
|
|
9482
|
-
return /* @__PURE__ */
|
|
9763
|
+
return /* @__PURE__ */ jsx3("div", { className: "chat-widget__markdown", children: /* @__PURE__ */ jsx3(FormattedMarkdown, { children: entry }) }, `${messageId}-text-${index}`);
|
|
9483
9764
|
}
|
|
9484
9765
|
if (!("widgetType" in entry)) {
|
|
9485
9766
|
return null;
|
|
9486
9767
|
}
|
|
9487
9768
|
const widgetDef = widgets?.find((w) => w.widgetType === entry.widgetType);
|
|
9488
9769
|
if (!widgetDef) {
|
|
9489
|
-
return /* @__PURE__ */
|
|
9770
|
+
return /* @__PURE__ */ jsxs3("span", { children: [
|
|
9490
9771
|
"[Unknown widget: ",
|
|
9491
9772
|
entry.widgetType,
|
|
9492
9773
|
"]"
|
|
9493
9774
|
] }, `${messageId}-unknown-${index}`);
|
|
9494
9775
|
}
|
|
9495
|
-
return /* @__PURE__ */
|
|
9776
|
+
return /* @__PURE__ */ jsx3("div", { className: "chat-widget__widget", children: widgetDef.render(entry) }, `${messageId}-widget-${index}`);
|
|
9496
9777
|
}),
|
|
9497
9778
|
[widgets]
|
|
9498
9779
|
);
|
|
@@ -9500,7 +9781,7 @@ function ChatWidget({
|
|
|
9500
9781
|
threadId: "",
|
|
9501
9782
|
widgets: null
|
|
9502
9783
|
});
|
|
9503
|
-
|
|
9784
|
+
useEffect4(() => {
|
|
9504
9785
|
if (!widgets || widgets.length === 0) return;
|
|
9505
9786
|
const alreadyRegistered = lastRegisteredRef.current.threadId === threadId && lastRegisteredRef.current.widgets === widgets;
|
|
9506
9787
|
if (alreadyRegistered) return;
|
|
@@ -9510,54 +9791,65 @@ function ChatWidget({
|
|
|
9510
9791
|
console.error("Failed to register chat widgets", err);
|
|
9511
9792
|
});
|
|
9512
9793
|
}, [api, threadId, widgets]);
|
|
9513
|
-
return /* @__PURE__ */
|
|
9794
|
+
return /* @__PURE__ */ jsxs3(
|
|
9514
9795
|
"div",
|
|
9515
9796
|
{
|
|
9516
|
-
className: cn(
|
|
9797
|
+
className: cn(classNames2.container, className),
|
|
9517
9798
|
style: themeVariables,
|
|
9518
9799
|
"data-chat-widget": "",
|
|
9519
9800
|
children: [
|
|
9520
|
-
title && /* @__PURE__ */
|
|
9521
|
-
/* @__PURE__ */
|
|
9801
|
+
title && /* @__PURE__ */ jsx3("div", { className: classNames2.header, children: /* @__PURE__ */ jsx3("h3", { className: classNames2.headerTitle, children: title }) }),
|
|
9802
|
+
/* @__PURE__ */ jsxs3("div", { className: classNames2.messagesContainer, children: [
|
|
9522
9803
|
messages.map((message) => {
|
|
9523
|
-
return /* @__PURE__ */
|
|
9524
|
-
/* @__PURE__ */
|
|
9804
|
+
return /* @__PURE__ */ jsxs3("div", { className: classNames2.messageWrapper, children: [
|
|
9805
|
+
/* @__PURE__ */ jsx3(
|
|
9525
9806
|
"div",
|
|
9526
9807
|
{
|
|
9527
9808
|
className: cn(
|
|
9528
|
-
|
|
9529
|
-
message.role === "user" ?
|
|
9809
|
+
classNames2.messageRow,
|
|
9810
|
+
message.role === "user" ? classNames2.userMessageRow : classNames2.assistantMessageRow
|
|
9530
9811
|
),
|
|
9531
|
-
children: message.content.length > 0 && /* @__PURE__ */
|
|
9812
|
+
children: message.content.length > 0 && /* @__PURE__ */ jsx3(
|
|
9532
9813
|
"div",
|
|
9533
9814
|
{
|
|
9534
9815
|
className: cn(
|
|
9535
|
-
|
|
9536
|
-
message.role === "user" ?
|
|
9816
|
+
classNames2.messageBubble,
|
|
9817
|
+
message.role === "user" ? classNames2.userMessage : classNames2.assistantMessage
|
|
9537
9818
|
),
|
|
9538
9819
|
children: renderOutput(`${message.id}-content`, message.content)
|
|
9539
9820
|
}
|
|
9540
9821
|
)
|
|
9541
9822
|
}
|
|
9542
9823
|
),
|
|
9543
|
-
message.role === "assistant" && message.thoughts && message.thoughts.length > 0 && /* @__PURE__ */
|
|
9544
|
-
/* @__PURE__ */
|
|
9545
|
-
/* @__PURE__ */
|
|
9546
|
-
/* @__PURE__ */
|
|
9824
|
+
message.role === "assistant" && message.thoughts && message.thoughts.length > 0 && /* @__PURE__ */ jsx3("div", { className: classNames2.thoughtsContainer, children: /* @__PURE__ */ jsxs3("details", { className: "chat-widget__details", children: [
|
|
9825
|
+
/* @__PURE__ */ jsxs3("summary", { className: classNames2.thoughtsSummary, children: [
|
|
9826
|
+
/* @__PURE__ */ jsx3("span", { className: classNames2.thoughtsIconContainer, children: /* @__PURE__ */ jsx3(ChevronRight, { className: classNames2.thoughtsIcon }) }),
|
|
9827
|
+
/* @__PURE__ */ jsx3("span", { children: "Thoughts" })
|
|
9547
9828
|
] }),
|
|
9548
|
-
/* @__PURE__ */
|
|
9549
|
-
] }) })
|
|
9829
|
+
/* @__PURE__ */ jsx3("div", { className: classNames2.thoughtsContent, children: /* @__PURE__ */ jsx3("pre", { className: classNames2.thoughtsText, children: renderOutput(`${message.id}-thoughts`, message.thoughts) }) })
|
|
9830
|
+
] }) }),
|
|
9831
|
+
feedbackEnabled && message.role === "assistant" && message.id !== "welcome-message" && !(status === "streaming" && message === messages[messages.length - 1]) && /* @__PURE__ */ jsx3(
|
|
9832
|
+
MessageFeedback,
|
|
9833
|
+
{
|
|
9834
|
+
messageId: message.id,
|
|
9835
|
+
existingRating: getFeedbackForMessage(message.id)?.rating,
|
|
9836
|
+
existingComment: getFeedbackForMessage(message.id)?.comment,
|
|
9837
|
+
isSubmitting: feedbackSubmitting === message.id,
|
|
9838
|
+
requireCommentForNegative: feedback?.requireCommentForNegative,
|
|
9839
|
+
onSubmit: handleFeedbackSubmit
|
|
9840
|
+
}
|
|
9841
|
+
)
|
|
9550
9842
|
] }, message.id);
|
|
9551
9843
|
}),
|
|
9552
|
-
status === "streaming" && /* @__PURE__ */
|
|
9553
|
-
/* @__PURE__ */
|
|
9554
|
-
/* @__PURE__ */
|
|
9555
|
-
/* @__PURE__ */
|
|
9844
|
+
status === "streaming" && /* @__PURE__ */ jsx3("div", { className: classNames2.loadingContainer, children: /* @__PURE__ */ jsx3("div", { className: classNames2.loadingBubble, children: /* @__PURE__ */ jsxs3("div", { className: classNames2.loadingDots, children: [
|
|
9845
|
+
/* @__PURE__ */ jsx3("div", { className: classNames2.loadingDot }),
|
|
9846
|
+
/* @__PURE__ */ jsx3("div", { className: classNames2.loadingDot, "data-delay": "1" }),
|
|
9847
|
+
/* @__PURE__ */ jsx3("div", { className: classNames2.loadingDot, "data-delay": "2" })
|
|
9556
9848
|
] }) }) }),
|
|
9557
|
-
/* @__PURE__ */
|
|
9849
|
+
/* @__PURE__ */ jsx3("div", { ref: messagesEndRef })
|
|
9558
9850
|
] }),
|
|
9559
|
-
/* @__PURE__ */
|
|
9560
|
-
/* @__PURE__ */
|
|
9851
|
+
/* @__PURE__ */ jsx3("div", { className: classNames2.inputContainer, children: /* @__PURE__ */ jsxs3("form", { onSubmit: handleSubmit, className: classNames2.inputForm, children: [
|
|
9852
|
+
/* @__PURE__ */ jsx3(
|
|
9561
9853
|
"textarea",
|
|
9562
9854
|
{
|
|
9563
9855
|
ref: textareaRef,
|
|
@@ -9567,13 +9859,13 @@ function ChatWidget({
|
|
|
9567
9859
|
placeholder: inputPlaceholder,
|
|
9568
9860
|
disabled: status !== "ready",
|
|
9569
9861
|
rows: 1,
|
|
9570
|
-
className:
|
|
9862
|
+
className: classNames2.textarea
|
|
9571
9863
|
}
|
|
9572
9864
|
),
|
|
9573
|
-
/* @__PURE__ */
|
|
9865
|
+
/* @__PURE__ */ jsx3("div", { className: classNames2.toolbar, children: speechEnabled && /* @__PURE__ */ jsx3(
|
|
9574
9866
|
SpeechToTextButton,
|
|
9575
9867
|
{
|
|
9576
|
-
className:
|
|
9868
|
+
className: classNames2.micButton,
|
|
9577
9869
|
disabled: status !== "ready",
|
|
9578
9870
|
silenceTimeout: speechToText?.silenceTimeout,
|
|
9579
9871
|
language: speechToText?.language,
|
|
@@ -9584,14 +9876,14 @@ function ChatWidget({
|
|
|
9584
9876
|
onListeningChange: setIsMicActive
|
|
9585
9877
|
}
|
|
9586
9878
|
) }),
|
|
9587
|
-
/* @__PURE__ */
|
|
9879
|
+
/* @__PURE__ */ jsx3(
|
|
9588
9880
|
"button",
|
|
9589
9881
|
{
|
|
9590
9882
|
type: "button",
|
|
9591
9883
|
onClick: status === "streaming" ? stop : handleSendMessage,
|
|
9592
9884
|
disabled: status === "streaming" ? false : !input.trim() || status !== "ready",
|
|
9593
|
-
className:
|
|
9594
|
-
children: status === "streaming" ? /* @__PURE__ */
|
|
9885
|
+
className: classNames2.submitButton,
|
|
9886
|
+
children: status === "streaming" ? /* @__PURE__ */ jsx3(StopCircle, { className: classNames2.sendIcon }) : /* @__PURE__ */ jsx3(Send, { className: classNames2.sendIcon })
|
|
9595
9887
|
}
|
|
9596
9888
|
)
|
|
9597
9889
|
] }) })
|
|
@@ -9604,14 +9896,14 @@ function ChatWidget({
|
|
|
9604
9896
|
styleInject(".chat-popup__anchor {\n position: fixed;\n inset-block-end: 20px;\n inset-inline-end: 20px;\n}\n.chat-popup--start {\n inset-inline-end: auto;\n inset-inline-start: 20px;\n}\n.chat-popup__anchor-button {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.65rem 0.85rem;\n background: var(--chat-primary);\n color: var(--chat-primary-text);\n border: none;\n border-radius: 999px;\n box-shadow: 0 10px 25px rgba(15, 23, 42, 0.2);\n cursor: pointer;\n font-weight: 600;\n z-index: 99999;\n}\n.chat-popup__anchor-button:hover {\n background: var(--chat-primary-hover);\n}\n.chat-popup__anchor-icon {\n width: 1.1rem;\n height: 1.1rem;\n}\n.chat-popup__panel {\n position: fixed;\n inset-block-end: 20px;\n inset-inline-end: 20px;\n z-index: 99998;\n transition: opacity 0.15s ease, visibility 0.15s ease;\n}\n.chat-popup--start.chat-popup__panel {\n inset-inline-end: auto;\n inset-inline-start: 20px;\n}\n.chat-popup__panel--open {\n opacity: 1;\n visibility: visible;\n pointer-events: auto;\n}\n.chat-popup__panel--closed {\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n}\n.chat-popup__panel-inner {\n width: 384px;\n max-width: calc(100vw - 40px);\n height: 500px;\n max-height: calc(100vh - 140px);\n box-shadow: 0 20px 45px rgba(15, 23, 42, 0.12);\n border-radius: 12px;\n overflow: visible;\n background: var(--chat-background);\n border: 1px solid var(--chat-border);\n position: relative;\n}\n.chat-popup__close {\n position: absolute;\n top: 0;\n z-index: 10;\n transform: translate(30%, -40%);\n}\n.chat-popup__close--end {\n inset-inline-end: 0;\n}\n.chat-popup__close--start {\n inset-inline-start: 0;\n}\n.chat-popup__close-button {\n border: none;\n background: var(--chat-primary);\n color: var(--chat-primary-text);\n width: 32px;\n height: 32px;\n border-radius: 999px;\n cursor: pointer;\n display: grid;\n place-items: center;\n box-shadow: 0 10px 25px rgba(15, 23, 42, 0.2);\n}\n.chat-popup__close-button:hover {\n background: var(--chat-primary-hover);\n}\n.chat-popup__close-icon {\n width: 16px;\n height: 16px;\n}\n");
|
|
9605
9897
|
|
|
9606
9898
|
// lib/components/PopupChatWidget.tsx
|
|
9607
|
-
import { MessageSquare, X } from "lucide-react";
|
|
9608
|
-
import { useEffect as
|
|
9609
|
-
import { jsx as
|
|
9899
|
+
import { MessageSquare as MessageSquare2, X } from "lucide-react";
|
|
9900
|
+
import { useEffect as useEffect5, useMemo as useMemo2, useState as useState6 } from "react";
|
|
9901
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
9610
9902
|
function PopupChatWidget({ anchor, ...props }) {
|
|
9611
|
-
const [isOpen, setIsOpen] =
|
|
9612
|
-
const [hasOpened, setHasOpened] =
|
|
9903
|
+
const [isOpen, setIsOpen] = useState6(anchor?.initiallyOpen ?? false);
|
|
9904
|
+
const [hasOpened, setHasOpened] = useState6(anchor?.initiallyOpen ?? false);
|
|
9613
9905
|
const openResolved = props.openOverride ?? isOpen;
|
|
9614
|
-
|
|
9906
|
+
useEffect5(() => {
|
|
9615
9907
|
if (props.openOverride === void 0) return;
|
|
9616
9908
|
setIsOpen(props.openOverride);
|
|
9617
9909
|
if (props.openOverride) {
|
|
@@ -9663,8 +9955,8 @@ function PopupChatWidget({ anchor, ...props }) {
|
|
|
9663
9955
|
maxHeight: size.maxHeight ?? "calc(100vh - 140px)"
|
|
9664
9956
|
};
|
|
9665
9957
|
}, [props.popupSize]);
|
|
9666
|
-
return /* @__PURE__ */
|
|
9667
|
-
/* @__PURE__ */
|
|
9958
|
+
return /* @__PURE__ */ jsxs4("div", { style: themeStyle, children: [
|
|
9959
|
+
/* @__PURE__ */ jsx4("div", { className: cn("chat-popup__anchor", anchorPositionClass), children: anchor?.render ? anchor.render({ isOpen: openResolved, toggle: handleToggle }) : !openResolved && /* @__PURE__ */ jsxs4(
|
|
9668
9960
|
"button",
|
|
9669
9961
|
{
|
|
9670
9962
|
type: "button",
|
|
@@ -9673,12 +9965,12 @@ function PopupChatWidget({ anchor, ...props }) {
|
|
|
9673
9965
|
"aria-expanded": isOpen,
|
|
9674
9966
|
"aria-label": anchor?.label ?? "Open chat",
|
|
9675
9967
|
children: [
|
|
9676
|
-
/* @__PURE__ */
|
|
9677
|
-
/* @__PURE__ */
|
|
9968
|
+
/* @__PURE__ */ jsx4(MessageSquare2, { className: "chat-popup__anchor-icon" }),
|
|
9969
|
+
/* @__PURE__ */ jsx4("span", { children: anchor?.label ?? "Chat" })
|
|
9678
9970
|
]
|
|
9679
9971
|
}
|
|
9680
9972
|
) }),
|
|
9681
|
-
/* @__PURE__ */
|
|
9973
|
+
/* @__PURE__ */ jsx4(
|
|
9682
9974
|
"div",
|
|
9683
9975
|
{
|
|
9684
9976
|
className: cn(
|
|
@@ -9686,27 +9978,27 @@ function PopupChatWidget({ anchor, ...props }) {
|
|
|
9686
9978
|
anchorPositionClass,
|
|
9687
9979
|
openResolved ? "chat-popup__panel--open" : "chat-popup__panel--closed"
|
|
9688
9980
|
),
|
|
9689
|
-
children: /* @__PURE__ */
|
|
9690
|
-
showClose && /* @__PURE__ */
|
|
9981
|
+
children: /* @__PURE__ */ jsxs4("div", { className: "chat-popup__panel-inner", style: popupStyle, children: [
|
|
9982
|
+
showClose && /* @__PURE__ */ jsx4(
|
|
9691
9983
|
"div",
|
|
9692
9984
|
{
|
|
9693
9985
|
className: cn(
|
|
9694
9986
|
"chat-popup__close",
|
|
9695
9987
|
closeConfig?.position === "top-start" ? "chat-popup__close--start" : "chat-popup__close--end"
|
|
9696
9988
|
),
|
|
9697
|
-
children: closeConfig?.render ? closeConfig.render({ toggle: handleToggle }) : /* @__PURE__ */
|
|
9989
|
+
children: closeConfig?.render ? closeConfig.render({ toggle: handleToggle }) : /* @__PURE__ */ jsx4(
|
|
9698
9990
|
"button",
|
|
9699
9991
|
{
|
|
9700
9992
|
type: "button",
|
|
9701
9993
|
className: "chat-popup__close-button",
|
|
9702
9994
|
onClick: handleToggle,
|
|
9703
9995
|
"aria-label": "Close chat",
|
|
9704
|
-
children: /* @__PURE__ */
|
|
9996
|
+
children: /* @__PURE__ */ jsx4(X, { className: "chat-popup__close-icon" })
|
|
9705
9997
|
}
|
|
9706
9998
|
)
|
|
9707
9999
|
}
|
|
9708
10000
|
),
|
|
9709
|
-
hasOpened && /* @__PURE__ */
|
|
10001
|
+
hasOpened && /* @__PURE__ */ jsx4(ChatWidget, { ...props })
|
|
9710
10002
|
] })
|
|
9711
10003
|
}
|
|
9712
10004
|
)
|
|
@@ -9715,7 +10007,7 @@ function PopupChatWidget({ anchor, ...props }) {
|
|
|
9715
10007
|
|
|
9716
10008
|
// lib/createChatWidget.tsx
|
|
9717
10009
|
import { createRoot } from "react-dom/client";
|
|
9718
|
-
import { jsx as
|
|
10010
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
9719
10011
|
var createChatWidget = (target, props) => {
|
|
9720
10012
|
if (!target) {
|
|
9721
10013
|
throw new Error("createChatWidget requires a valid DOM element to mount into.");
|
|
@@ -9723,7 +10015,7 @@ var createChatWidget = (target, props) => {
|
|
|
9723
10015
|
const root2 = createRoot(target);
|
|
9724
10016
|
let currentProps = props;
|
|
9725
10017
|
const render = () => {
|
|
9726
|
-
root2.render(/* @__PURE__ */
|
|
10018
|
+
root2.render(/* @__PURE__ */ jsx5(ChatWidget, { ...currentProps }));
|
|
9727
10019
|
};
|
|
9728
10020
|
render();
|
|
9729
10021
|
const mergeStyles = (nextStyles) => ({
|
|
@@ -9764,16 +10056,16 @@ var createWidget = ({
|
|
|
9764
10056
|
});
|
|
9765
10057
|
|
|
9766
10058
|
// lib/widgets/default-widgets.tsx
|
|
9767
|
-
import { jsx as
|
|
10059
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
9768
10060
|
var defaultChatWidgets = [
|
|
9769
10061
|
createWidget({
|
|
9770
|
-
widgetType: "
|
|
10062
|
+
widgetType: "person-card",
|
|
9771
10063
|
schema: zod_default.object({
|
|
9772
10064
|
name: zod_default.string(),
|
|
9773
10065
|
profileUri: zod_default.string().optional(),
|
|
9774
10066
|
details: zod_default.record(zod_default.any()).optional()
|
|
9775
|
-
}),
|
|
9776
|
-
render: (widget) => /* @__PURE__ */
|
|
10067
|
+
}).describe("showing a person card with name, photo and additional details"),
|
|
10068
|
+
render: (widget) => /* @__PURE__ */ jsx6(
|
|
9777
10069
|
"div",
|
|
9778
10070
|
{
|
|
9779
10071
|
style: {
|
|
@@ -9786,8 +10078,8 @@ var defaultChatWidgets = [
|
|
|
9786
10078
|
borderRadius: "0.5rem",
|
|
9787
10079
|
boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)"
|
|
9788
10080
|
},
|
|
9789
|
-
children: /* @__PURE__ */
|
|
9790
|
-
widget.profileUri && /* @__PURE__ */
|
|
10081
|
+
children: /* @__PURE__ */ jsxs5("div", { style: { display: "flex", alignItems: "flex-start", gap: "0.75rem" }, children: [
|
|
10082
|
+
widget.profileUri && /* @__PURE__ */ jsx6(
|
|
9791
10083
|
"img",
|
|
9792
10084
|
{
|
|
9793
10085
|
src: widget.profileUri,
|
|
@@ -9802,14 +10094,14 @@ var defaultChatWidgets = [
|
|
|
9802
10094
|
loading: "lazy"
|
|
9803
10095
|
}
|
|
9804
10096
|
),
|
|
9805
|
-
/* @__PURE__ */
|
|
9806
|
-
/* @__PURE__ */
|
|
9807
|
-
widget.details ? /* @__PURE__ */
|
|
9808
|
-
/* @__PURE__ */
|
|
10097
|
+
/* @__PURE__ */ jsxs5("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
10098
|
+
/* @__PURE__ */ jsx6("div", { style: { fontWeight: 600, fontSize: "1rem", color: "#111827", marginBottom: "0.25rem" }, children: widget.name }),
|
|
10099
|
+
widget.details ? /* @__PURE__ */ jsx6("div", { style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: Object.entries(widget.details).map(([key, value]) => /* @__PURE__ */ jsxs5("div", { style: { display: "flex", gap: "0.5rem", fontSize: "0.875rem" }, children: [
|
|
10100
|
+
/* @__PURE__ */ jsxs5("span", { style: { color: "#6b7280", fontWeight: 500, minWidth: "fit-content" }, children: [
|
|
9809
10101
|
key,
|
|
9810
10102
|
":"
|
|
9811
10103
|
] }),
|
|
9812
|
-
/* @__PURE__ */
|
|
10104
|
+
/* @__PURE__ */ jsx6("span", { style: { color: "#374151" }, children: String(value) })
|
|
9813
10105
|
] }, key)) }) : null
|
|
9814
10106
|
] })
|
|
9815
10107
|
] })
|
|
@@ -9821,8 +10113,8 @@ var defaultChatWidgets = [
|
|
|
9821
10113
|
schema: zod_default.object({
|
|
9822
10114
|
uri: zod_default.string().url(),
|
|
9823
10115
|
text: zod_default.string().optional()
|
|
9824
|
-
}),
|
|
9825
|
-
render: (widget) => /* @__PURE__ */
|
|
10116
|
+
}).describe("rendering a clickable link"),
|
|
10117
|
+
render: (widget) => /* @__PURE__ */ jsx6(
|
|
9826
10118
|
"a",
|
|
9827
10119
|
{
|
|
9828
10120
|
href: widget.uri,
|
|
@@ -9864,6 +10156,7 @@ export {
|
|
|
9864
10156
|
createWidget,
|
|
9865
10157
|
defaultChatWidgets,
|
|
9866
10158
|
registerChatWidgets,
|
|
9867
|
-
useChat
|
|
10159
|
+
useChat,
|
|
10160
|
+
useFeedback
|
|
9868
10161
|
};
|
|
9869
10162
|
//# sourceMappingURL=index.js.map
|