@ensembleapp/client-sdk 0.0.5 → 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.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 useCallback2, useEffect as useEffect3, useMemo, useRef as useRef2, useState as useState3 } from "react";
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 useEffect2,
9262
+ useCallback as useCallback3,
9263
+ useEffect as useEffect3,
9001
9264
  useRef,
9002
- useState as useState2
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] = useState2(false);
9024
- const [isSupported, setIsSupported] = useState2(false);
9025
- const [countdown, setCountdown] = useState2(0);
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] = useState2(false);
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 = useCallback(() => {
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 = useCallback(() => {
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 = useCallback(() => {
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 = useCallback(() => {
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 = useCallback((message) => {
9324
+ const handleRecognitionError = useCallback3((message) => {
9062
9325
  console.error("Speech recognition error:", message);
9063
9326
  onError?.(message);
9064
9327
  }, [onError]);
9065
- const resetSilenceTimer = useCallback(() => {
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 = useCallback((text3) => {
9333
+ const dispatchInterim = useCallback3((text3) => {
9071
9334
  if (text3) {
9072
9335
  onInterim?.(text3);
9073
9336
  }
9074
9337
  }, [onInterim]);
9075
- const dispatchFinal = useCallback((text3) => {
9338
+ const dispatchFinal = useCallback3((text3) => {
9076
9339
  if (text3) {
9077
9340
  onFinal?.(text3);
9078
9341
  }
9079
9342
  }, [onFinal]);
9080
- const flushFinalText = useCallback(() => {
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 = useCallback(() => {
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 = useCallback(() => {
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 = useCallback(() => {
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 = useCallback((recognition) => {
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 = useCallback(() => {
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 = useCallback(() => {
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
- useEffect2(() => {
9480
+ useEffect3(() => {
9218
9481
  if (disabled && isListening) {
9219
9482
  stopListening();
9220
9483
  }
9221
9484
  }, [disabled, isListening, stopListening]);
9222
- useEffect2(() => {
9485
+ useEffect3(() => {
9223
9486
  setIsSupported(typeof window !== "undefined" && !!getSpeechRecognitionCtor());
9224
9487
  }, []);
9225
- useEffect2(() => {
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__ */ jsxs(
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__ */ jsx(Mic, { className: "chat-widget__mic-icon" }) : /* @__PURE__ */ jsx(MicOff, { className: "chat-widget__mic-icon" }),
9252
- finalDelay > 0 && isListening && countdownActive && /* @__PURE__ */ jsx("span", { className: "chat-widget__mic-bar", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
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 jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
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__ */ jsx2(MarkdownComponent, { remarkPlugins: [remarkGfm], children: children.replace(/\n\n/gi, "\n\n \n\n") });
9531
+ return /* @__PURE__ */ jsx3(MarkdownComponent, { remarkPlugins: [remarkGfm], children: children.replace(/\n\n/gi, "\n\n \n\n") });
9269
9532
  };
9270
- var classNames = {
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] = useState3("");
9370
- const [isMicActive, setIsMicActive] = useState3(false);
9371
- const [isSpeechPending, setIsSpeechPending] = useState3(false);
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
- useEffect3(() => {
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
- useEffect3(() => {
9705
+ useEffect4(() => {
9425
9706
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
9426
9707
  }, [messages, status]);
9427
- useEffect3(() => {
9708
+ useEffect4(() => {
9428
9709
  const timer = setTimeout(() => {
9429
9710
  textareaRef.current?.focus();
9430
9711
  }, 150);
9431
9712
  return () => clearTimeout(timer);
9432
9713
  }, []);
9433
- useEffect3(() => {
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 = useCallback2((raw) => {
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 = useCallback2((text3) => {
9743
+ const handleSpeechInterim = useCallback4((text3) => {
9463
9744
  setInput(text3);
9464
9745
  }, [setInput]);
9465
- const handleSpeechFinal = useCallback2((text3) => {
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
- useEffect3(() => {
9755
+ useEffect4(() => {
9475
9756
  if (!speechEnabled) {
9476
9757
  setIsMicActive(false);
9477
9758
  }
9478
9759
  }, [speechEnabled]);
9479
- const renderOutput = useCallback2(
9760
+ const renderOutput = useCallback4(
9480
9761
  (messageId, content) => content.map((entry, index) => {
9481
9762
  if (typeof entry === "string") {
9482
- return /* @__PURE__ */ jsx2("div", { className: "chat-widget__markdown", children: /* @__PURE__ */ jsx2(FormattedMarkdown, { children: entry }) }, `${messageId}-text-${index}`);
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__ */ jsxs2("span", { children: [
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__ */ jsx2("div", { className: "chat-widget__widget", children: widgetDef.render(entry) }, `${messageId}-widget-${index}`);
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
- useEffect3(() => {
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__ */ jsxs2(
9794
+ return /* @__PURE__ */ jsxs3(
9514
9795
  "div",
9515
9796
  {
9516
- className: cn(classNames.container, className),
9797
+ className: cn(classNames2.container, className),
9517
9798
  style: themeVariables,
9518
9799
  "data-chat-widget": "",
9519
9800
  children: [
9520
- title && /* @__PURE__ */ jsx2("div", { className: classNames.header, children: /* @__PURE__ */ jsx2("h3", { className: classNames.headerTitle, children: title }) }),
9521
- /* @__PURE__ */ jsxs2("div", { className: classNames.messagesContainer, children: [
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__ */ jsxs2("div", { className: classNames.messageWrapper, children: [
9524
- /* @__PURE__ */ jsx2(
9804
+ return /* @__PURE__ */ jsxs3("div", { className: classNames2.messageWrapper, children: [
9805
+ /* @__PURE__ */ jsx3(
9525
9806
  "div",
9526
9807
  {
9527
9808
  className: cn(
9528
- classNames.messageRow,
9529
- message.role === "user" ? classNames.userMessageRow : classNames.assistantMessageRow
9809
+ classNames2.messageRow,
9810
+ message.role === "user" ? classNames2.userMessageRow : classNames2.assistantMessageRow
9530
9811
  ),
9531
- children: message.content.length > 0 && /* @__PURE__ */ jsx2(
9812
+ children: message.content.length > 0 && /* @__PURE__ */ jsx3(
9532
9813
  "div",
9533
9814
  {
9534
9815
  className: cn(
9535
- classNames.messageBubble,
9536
- message.role === "user" ? classNames.userMessage : classNames.assistantMessage
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__ */ jsx2("div", { className: classNames.thoughtsContainer, children: /* @__PURE__ */ jsxs2("details", { className: "chat-widget__details", children: [
9544
- /* @__PURE__ */ jsxs2("summary", { className: classNames.thoughtsSummary, children: [
9545
- /* @__PURE__ */ jsx2("span", { className: classNames.thoughtsIconContainer, children: /* @__PURE__ */ jsx2(ChevronRight, { className: classNames.thoughtsIcon }) }),
9546
- /* @__PURE__ */ jsx2("span", { children: "Thoughts" })
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__ */ jsx2("div", { className: classNames.thoughtsContent, children: /* @__PURE__ */ jsx2("pre", { className: classNames.thoughtsText, children: renderOutput(`${message.id}-thoughts`, message.thoughts) }) })
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__ */ jsx2("div", { className: classNames.loadingContainer, children: /* @__PURE__ */ jsx2("div", { className: classNames.loadingBubble, children: /* @__PURE__ */ jsxs2("div", { className: classNames.loadingDots, children: [
9553
- /* @__PURE__ */ jsx2("div", { className: classNames.loadingDot }),
9554
- /* @__PURE__ */ jsx2("div", { className: classNames.loadingDot, "data-delay": "1" }),
9555
- /* @__PURE__ */ jsx2("div", { className: classNames.loadingDot, "data-delay": "2" })
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__ */ jsx2("div", { ref: messagesEndRef })
9849
+ /* @__PURE__ */ jsx3("div", { ref: messagesEndRef })
9558
9850
  ] }),
9559
- /* @__PURE__ */ jsx2("div", { className: classNames.inputContainer, children: /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, className: classNames.inputForm, children: [
9560
- /* @__PURE__ */ jsx2(
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: classNames.textarea
9862
+ className: classNames2.textarea
9571
9863
  }
9572
9864
  ),
9573
- /* @__PURE__ */ jsx2("div", { className: classNames.toolbar, children: speechEnabled && /* @__PURE__ */ jsx2(
9865
+ /* @__PURE__ */ jsx3("div", { className: classNames2.toolbar, children: speechEnabled && /* @__PURE__ */ jsx3(
9574
9866
  SpeechToTextButton,
9575
9867
  {
9576
- className: classNames.micButton,
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__ */ jsx2(
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: classNames.submitButton,
9594
- children: status === "streaming" ? /* @__PURE__ */ jsx2(StopCircle, { className: classNames.sendIcon }) : /* @__PURE__ */ jsx2(Send, { className: classNames.sendIcon })
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 useEffect4, useMemo as useMemo2, useState as useState4 } from "react";
9609
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
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] = useState4(anchor?.initiallyOpen ?? false);
9612
- const [hasOpened, setHasOpened] = useState4(anchor?.initiallyOpen ?? false);
9903
+ const [isOpen, setIsOpen] = useState6(anchor?.initiallyOpen ?? false);
9904
+ const [hasOpened, setHasOpened] = useState6(anchor?.initiallyOpen ?? false);
9613
9905
  const openResolved = props.openOverride ?? isOpen;
9614
- useEffect4(() => {
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__ */ jsxs3("div", { style: themeStyle, children: [
9667
- /* @__PURE__ */ jsx3("div", { className: cn("chat-popup__anchor", anchorPositionClass), children: anchor?.render ? anchor.render({ isOpen: openResolved, toggle: handleToggle }) : !openResolved && /* @__PURE__ */ jsxs3(
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__ */ jsx3(MessageSquare, { className: "chat-popup__anchor-icon" }),
9677
- /* @__PURE__ */ jsx3("span", { children: anchor?.label ?? "Chat" })
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__ */ jsx3(
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__ */ jsxs3("div", { className: "chat-popup__panel-inner", style: popupStyle, children: [
9690
- showClose && /* @__PURE__ */ jsx3(
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__ */ jsx3(
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__ */ jsx3(X, { className: "chat-popup__close-icon" })
9996
+ children: /* @__PURE__ */ jsx4(X, { className: "chat-popup__close-icon" })
9705
9997
  }
9706
9998
  )
9707
9999
  }
9708
10000
  ),
9709
- hasOpened && /* @__PURE__ */ jsx3(ChatWidget, { ...props })
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 jsx4 } from "react/jsx-runtime";
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__ */ jsx4(ChatWidget, { ...currentProps }));
10018
+ root2.render(/* @__PURE__ */ jsx5(ChatWidget, { ...currentProps }));
9727
10019
  };
9728
10020
  render();
9729
10021
  const mergeStyles = (nextStyles) => ({
@@ -9764,7 +10056,7 @@ var createWidget = ({
9764
10056
  });
9765
10057
 
9766
10058
  // lib/widgets/default-widgets.tsx
9767
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
10059
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
9768
10060
  var defaultChatWidgets = [
9769
10061
  createWidget({
9770
10062
  widgetType: "person-card",
@@ -9773,7 +10065,7 @@ var defaultChatWidgets = [
9773
10065
  profileUri: zod_default.string().optional(),
9774
10066
  details: zod_default.record(zod_default.any()).optional()
9775
10067
  }).describe("showing a person card with name, photo and additional details"),
9776
- render: (widget) => /* @__PURE__ */ jsx5(
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__ */ jsxs4("div", { style: { display: "flex", alignItems: "flex-start", gap: "0.75rem" }, children: [
9790
- widget.profileUri && /* @__PURE__ */ jsx5(
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__ */ jsxs4("div", { style: { flex: 1, minWidth: 0 }, children: [
9806
- /* @__PURE__ */ jsx5("div", { style: { fontWeight: 600, fontSize: "1rem", color: "#111827", marginBottom: "0.25rem" }, children: widget.name }),
9807
- widget.details ? /* @__PURE__ */ jsx5("div", { style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: Object.entries(widget.details).map(([key, value]) => /* @__PURE__ */ jsxs4("div", { style: { display: "flex", gap: "0.5rem", fontSize: "0.875rem" }, children: [
9808
- /* @__PURE__ */ jsxs4("span", { style: { color: "#6b7280", fontWeight: 500, minWidth: "fit-content" }, children: [
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__ */ jsx5("span", { style: { color: "#374151" }, children: String(value) })
10104
+ /* @__PURE__ */ jsx6("span", { style: { color: "#374151" }, children: String(value) })
9813
10105
  ] }, key)) }) : null
9814
10106
  ] })
9815
10107
  ] })
@@ -9822,7 +10114,7 @@ var defaultChatWidgets = [
9822
10114
  uri: zod_default.string().url(),
9823
10115
  text: zod_default.string().optional()
9824
10116
  }).describe("rendering a clickable link"),
9825
- render: (widget) => /* @__PURE__ */ jsx5(
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