@yext/chat-ui-react 0.10.0 → 0.10.2

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.
Files changed (66) hide show
  1. package/lib/commonjs/package.json.js +1 -1
  2. package/lib/commonjs/src/components/ChatInput.d.ts.map +1 -1
  3. package/lib/commonjs/src/components/ChatInput.js +9 -2
  4. package/lib/commonjs/src/components/ChatInput.js.map +1 -1
  5. package/lib/commonjs/src/components/ChatPanel.d.ts +4 -0
  6. package/lib/commonjs/src/components/ChatPanel.d.ts.map +1 -1
  7. package/lib/commonjs/src/components/ChatPanel.js +5 -5
  8. package/lib/commonjs/src/components/ChatPanel.js.map +1 -1
  9. package/lib/commonjs/src/components/ChatPopUp.d.ts.map +1 -1
  10. package/lib/commonjs/src/components/ChatPopUp.js +4 -2
  11. package/lib/commonjs/src/components/ChatPopUp.js.map +1 -1
  12. package/lib/commonjs/src/components/Markdown.d.ts +3 -1
  13. package/lib/commonjs/src/components/Markdown.d.ts.map +1 -1
  14. package/lib/commonjs/src/components/Markdown.js +3 -2
  15. package/lib/commonjs/src/components/Markdown.js.map +1 -1
  16. package/lib/commonjs/src/components/MessageBubble.d.ts +3 -1
  17. package/lib/commonjs/src/components/MessageBubble.d.ts.map +1 -1
  18. package/lib/commonjs/src/components/MessageBubble.js +2 -2
  19. package/lib/commonjs/src/components/MessageBubble.js.map +1 -1
  20. package/lib/commonjs/src/components/MessageSuggestions.d.ts.map +1 -1
  21. package/lib/commonjs/src/components/MessageSuggestions.js +8 -1
  22. package/lib/commonjs/src/components/MessageSuggestions.js.map +1 -1
  23. package/lib/commonjs/src/hooks/useFetchInitialMessage.d.ts.map +1 -1
  24. package/lib/commonjs/src/hooks/useFetchInitialMessage.js +9 -1
  25. package/lib/commonjs/src/hooks/useFetchInitialMessage.js.map +1 -1
  26. package/lib/commonjs/src/hooks/useSendMessageWithRetries.d.ts.map +1 -1
  27. package/lib/commonjs/src/hooks/useSendMessageWithRetries.js +3 -1
  28. package/lib/commonjs/src/hooks/useSendMessageWithRetries.js.map +1 -1
  29. package/lib/esm/index.d.ts +7 -1
  30. package/lib/esm/package.json.mjs +1 -1
  31. package/lib/esm/src/components/ChatInput.d.ts.map +1 -1
  32. package/lib/esm/src/components/ChatInput.mjs +9 -2
  33. package/lib/esm/src/components/ChatInput.mjs.map +1 -1
  34. package/lib/esm/src/components/ChatPanel.d.ts +4 -0
  35. package/lib/esm/src/components/ChatPanel.d.ts.map +1 -1
  36. package/lib/esm/src/components/ChatPanel.mjs +5 -5
  37. package/lib/esm/src/components/ChatPanel.mjs.map +1 -1
  38. package/lib/esm/src/components/ChatPopUp.d.ts.map +1 -1
  39. package/lib/esm/src/components/ChatPopUp.mjs +4 -2
  40. package/lib/esm/src/components/ChatPopUp.mjs.map +1 -1
  41. package/lib/esm/src/components/Markdown.d.ts +3 -1
  42. package/lib/esm/src/components/Markdown.d.ts.map +1 -1
  43. package/lib/esm/src/components/Markdown.mjs +3 -2
  44. package/lib/esm/src/components/Markdown.mjs.map +1 -1
  45. package/lib/esm/src/components/MessageBubble.d.ts +3 -1
  46. package/lib/esm/src/components/MessageBubble.d.ts.map +1 -1
  47. package/lib/esm/src/components/MessageBubble.mjs +2 -2
  48. package/lib/esm/src/components/MessageBubble.mjs.map +1 -1
  49. package/lib/esm/src/components/MessageSuggestions.d.ts.map +1 -1
  50. package/lib/esm/src/components/MessageSuggestions.mjs +8 -1
  51. package/lib/esm/src/components/MessageSuggestions.mjs.map +1 -1
  52. package/lib/esm/src/hooks/useFetchInitialMessage.d.ts.map +1 -1
  53. package/lib/esm/src/hooks/useFetchInitialMessage.mjs +9 -1
  54. package/lib/esm/src/hooks/useFetchInitialMessage.mjs.map +1 -1
  55. package/lib/esm/src/hooks/useSendMessageWithRetries.d.ts.map +1 -1
  56. package/lib/esm/src/hooks/useSendMessageWithRetries.mjs +3 -1
  57. package/lib/esm/src/hooks/useSendMessageWithRetries.mjs.map +1 -1
  58. package/package.json +2 -2
  59. package/src/components/ChatInput.tsx +16 -7
  60. package/src/components/ChatPanel.tsx +33 -14
  61. package/src/components/ChatPopUp.tsx +4 -3
  62. package/src/components/Markdown.tsx +5 -1
  63. package/src/components/MessageBubble.tsx +4 -0
  64. package/src/components/MessageSuggestions.tsx +12 -5
  65. package/src/hooks/useFetchInitialMessage.ts +11 -3
  66. package/src/hooks/useSendMessageWithRetries.ts +34 -27
@@ -1 +1 @@
1
- {"version":3,"file":"useFetchInitialMessage.mjs","sources":["../../../../src/hooks/useFetchInitialMessage.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useChatState, useChatActions } from \"@yext/chat-headless-react\";\nimport { useDefaultHandleApiError } from \"../hooks/useDefaultHandleApiError\";\n\n/**\n * Sends a request to Chat API to fetch the initial message when the\n * conversation first start or when the message history is reset.\n *\n * @internal\n *\n * @param handleError - A function which is called when an error occurs while fetching for initial message.\n * By default, the error is logged to the console and an error message is added to state.\n * @param stream - Enable streaming behavior by making a request to Chat Streaming API. Defaults to false.\n * @param customCondition - additional condition for when to fetch initial message\n */\nexport function useFetchInitialMessage(\n handleError?: (e: unknown) => void,\n stream = false,\n customCondition = true,\n) {\n const chat = useChatActions();\n const defaultHandleApiError = useDefaultHandleApiError();\n const messages = useChatState((state) => state.conversation.messages);\n const canSendMessage = useChatState(\n (state) => state.conversation.canSendMessage\n );\n \n useEffect(() => {\n if (messages.length !== 0 || !canSendMessage || !customCondition) {\n return;\n }\n const res = stream ? chat.streamNextMessage() : chat.getNextMessage();\n res.catch((e) => (handleError ? handleError(e) : defaultHandleApiError(e)));\n }, [chat, stream, handleError, defaultHandleApiError, canSendMessage, customCondition, messages.length]);\n}\n"],"names":[],"mappings":";;;;AAIA;;;;;;;;;;AAUG;AACG,SAAU,sBAAsB,CACpC,WAAkC,EAClC,MAAM,GAAG,KAAK,EACd,eAAe,GAAG,IAAI,EAAA;AAEtB,IAAA,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;AAC9B,IAAA,MAAM,qBAAqB,GAAG,wBAAwB,EAAE,CAAC;AACzD,IAAA,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;AACtE,IAAA,MAAM,cAAc,GAAG,YAAY,CACjC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,cAAc,CAC7C,CAAC;IAEF,SAAS,CAAC,MAAK;QACb,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,eAAe,EAAE;YAChE,OAAO;AACR,SAAA;AACD,QAAA,MAAM,GAAG,GAAG,MAAM,GAAG,IAAI,CAAC,iBAAiB,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACtE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9E,KAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,qBAAqB,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC3G;;;;"}
1
+ {"version":3,"file":"useFetchInitialMessage.mjs","sources":["../../../../src/hooks/useFetchInitialMessage.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useChatState, useChatActions } from \"@yext/chat-headless-react\";\nimport { useDefaultHandleApiError } from \"../hooks/useDefaultHandleApiError\";\n\n/**\n * Sends a request to Chat API to fetch the initial message when the\n * conversation first start or when the message history is reset.\n *\n * @internal\n *\n * @param handleError - A function which is called when an error occurs while fetching for initial message.\n * By default, the error is logged to the console and an error message is added to state.\n * @param stream - Enable streaming behavior by making a request to Chat Streaming API. Defaults to false.\n * @param customCondition - additional condition for when to fetch initial message\n */\nexport function useFetchInitialMessage(\n handleError?: (e: unknown) => void,\n stream = false,\n customCondition = true\n) {\n const chat = useChatActions();\n const defaultHandleApiError = useDefaultHandleApiError();\n const messages = useChatState((state) => state.conversation.messages);\n const canSendMessage = useChatState(\n (state) => state.conversation.canSendMessage\n );\n\n useEffect(() => {\n if (messages.length !== 0 || !canSendMessage || !customCondition) {\n return;\n }\n const res = stream ? chat.streamNextMessage() : chat.getNextMessage();\n res.catch((e) => (handleError ? handleError(e) : defaultHandleApiError(e)));\n }, [\n chat,\n stream,\n handleError,\n defaultHandleApiError,\n canSendMessage,\n customCondition,\n messages.length,\n ]);\n}\n"],"names":[],"mappings":";;;;AAIA;;;;;;;;;;AAUG;AACG,SAAU,sBAAsB,CACpC,WAAkC,EAClC,MAAM,GAAG,KAAK,EACd,eAAe,GAAG,IAAI,EAAA;AAEtB,IAAA,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;AAC9B,IAAA,MAAM,qBAAqB,GAAG,wBAAwB,EAAE,CAAC;AACzD,IAAA,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;AACtE,IAAA,MAAM,cAAc,GAAG,YAAY,CACjC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,cAAc,CAC7C,CAAC;IAEF,SAAS,CAAC,MAAK;QACb,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,eAAe,EAAE;YAChE,OAAO;AACR,SAAA;AACD,QAAA,MAAM,GAAG,GAAG,MAAM,GAAG,IAAI,CAAC,iBAAiB,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACtE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9E,KAAC,EAAE;QACD,IAAI;QACJ,MAAM;QACN,WAAW;QACX,qBAAqB;QACrB,cAAc;QACd,eAAe;AACf,QAAA,QAAQ,CAAC,MAAM;AAChB,KAAA,CAAC,CAAC;AACL;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"useSendMessageWithRetries.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useSendMessageWithRetries.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,UAAQ,EACd,UAAU,SAAI,EACd,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,GAC7B,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CA0BlC"}
1
+ {"version":3,"file":"useSendMessageWithRetries.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useSendMessageWithRetries.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,UAAQ,EACd,UAAU,SAAI,EACd,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,GAC7B,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAiClC"}
@@ -23,7 +23,9 @@ function useSendMessageWithRetries(stream = false, maxRetries = 0, onRetry) {
23
23
  let text = input;
24
24
  for (let numRetries = 0; numRetries <= maxRetries; numRetries++) {
25
25
  if (numRetries > 0 && !!err) {
26
- if (err instanceof ApiError && !!err.statusCode && err.statusCode >= 500) {
26
+ if (err instanceof ApiError &&
27
+ !!err.statusCode &&
28
+ err.statusCode >= 500) {
27
29
  onRetry?.(err);
28
30
  // avoid re-adding user message to conversation history on retry
29
31
  text = "";
@@ -1 +1 @@
1
- {"version":3,"file":"useSendMessageWithRetries.mjs","sources":["../../../../src/hooks/useSendMessageWithRetries.ts"],"sourcesContent":["import { ApiError, useChatActions } from \"@yext/chat-headless-react\";\nimport { useCallback } from \"react\";\n\n/**\n * Returns a function that sends a message to the chat API with retries\n * if the API returns a 5xx status code.\n * \n * @remarks\n * The function will throw the error if the maximum number of retries is reached\n * or if the error is not a 5xx status code.\n * \n * @internal\n * \n * @param stream - If true, use streaming API\n * @param maxRetries - Maximum number of retries\n * @param onRetry - Callback to handle error on each retry\n * \n */\nexport function useSendMessageWithRetries(\n stream = false,\n maxRetries = 0,\n onRetry?: (e: unknown) => void\n): (input: string) => Promise<void> {\n const chat = useChatActions()\n return useCallback(async (input: string) => {\n let err: unknown;\n let text = input;\n for (let numRetries = 0; numRetries <= maxRetries; numRetries++) {\n if (numRetries > 0 && !!err) {\n if (err instanceof ApiError && !!err.statusCode && err.statusCode >= 500) {\n onRetry?.(err)\n // avoid re-adding user message to conversation history on retry\n text = \"\";\n } else {\n throw err;\n }\n }\n try {\n await (stream\n ? chat.streamNextMessage(text)\n : chat.getNextMessage(text));\n return;\n } catch (e) {\n err = e;\n }\n }\n throw err\n }, [chat, maxRetries, onRetry, stream])\n}\n"],"names":[],"mappings":";;;AAGA;;;;;;;;;;;;;;AAcG;AACG,SAAU,yBAAyB,CACvC,MAAM,GAAG,KAAK,EACd,UAAU,GAAG,CAAC,EACd,OAA8B,EAAA;AAE9B,IAAA,MAAM,IAAI,GAAG,cAAc,EAAE,CAAA;AAC7B,IAAA,OAAO,WAAW,CAAC,OAAO,KAAa,KAAI;AACzC,QAAA,IAAI,GAAY,CAAC;QACjB,IAAI,IAAI,GAAG,KAAK,CAAC;QACjB,KAAK,IAAI,UAAU,GAAG,CAAC,EAAE,UAAU,IAAI,UAAU,EAAE,UAAU,EAAE,EAAE;AAC/D,YAAA,IAAI,UAAU,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE;AAC3B,gBAAA,IAAI,GAAG,YAAY,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,EAAE;AACxE,oBAAA,OAAO,GAAG,GAAG,CAAC,CAAA;;oBAEd,IAAI,GAAG,EAAE,CAAC;AACX,iBAAA;AAAM,qBAAA;AACL,oBAAA,MAAM,GAAG,CAAC;AACX,iBAAA;AACF,aAAA;YACD,IAAI;AACF,gBAAA,OAAO,MAAM;AACX,sBAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;sBAC5B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC/B,OAAO;AACR,aAAA;AAAC,YAAA,OAAO,CAAC,EAAE;gBACV,GAAG,GAAG,CAAC,CAAC;AACT,aAAA;AACF,SAAA;AACD,QAAA,MAAM,GAAG,CAAA;KACV,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAA;AACzC;;;;"}
1
+ {"version":3,"file":"useSendMessageWithRetries.mjs","sources":["../../../../src/hooks/useSendMessageWithRetries.ts"],"sourcesContent":["import { ApiError, useChatActions } from \"@yext/chat-headless-react\";\nimport { useCallback } from \"react\";\n\n/**\n * Returns a function that sends a message to the chat API with retries\n * if the API returns a 5xx status code.\n *\n * @remarks\n * The function will throw the error if the maximum number of retries is reached\n * or if the error is not a 5xx status code.\n *\n * @internal\n *\n * @param stream - If true, use streaming API\n * @param maxRetries - Maximum number of retries\n * @param onRetry - Callback to handle error on each retry\n *\n */\nexport function useSendMessageWithRetries(\n stream = false,\n maxRetries = 0,\n onRetry?: (e: unknown) => void\n): (input: string) => Promise<void> {\n const chat = useChatActions();\n return useCallback(\n async (input: string) => {\n let err: unknown;\n let text = input;\n for (let numRetries = 0; numRetries <= maxRetries; numRetries++) {\n if (numRetries > 0 && !!err) {\n if (\n err instanceof ApiError &&\n !!err.statusCode &&\n err.statusCode >= 500\n ) {\n onRetry?.(err);\n // avoid re-adding user message to conversation history on retry\n text = \"\";\n } else {\n throw err;\n }\n }\n try {\n await (stream\n ? chat.streamNextMessage(text)\n : chat.getNextMessage(text));\n return;\n } catch (e) {\n err = e;\n }\n }\n throw err;\n },\n [chat, maxRetries, onRetry, stream]\n );\n}\n"],"names":[],"mappings":";;;AAGA;;;;;;;;;;;;;;AAcG;AACG,SAAU,yBAAyB,CACvC,MAAM,GAAG,KAAK,EACd,UAAU,GAAG,CAAC,EACd,OAA8B,EAAA;AAE9B,IAAA,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;AAC9B,IAAA,OAAO,WAAW,CAChB,OAAO,KAAa,KAAI;AACtB,QAAA,IAAI,GAAY,CAAC;QACjB,IAAI,IAAI,GAAG,KAAK,CAAC;QACjB,KAAK,IAAI,UAAU,GAAG,CAAC,EAAE,UAAU,IAAI,UAAU,EAAE,UAAU,EAAE,EAAE;AAC/D,YAAA,IAAI,UAAU,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE;gBAC3B,IACE,GAAG,YAAY,QAAQ;oBACvB,CAAC,CAAC,GAAG,CAAC,UAAU;AAChB,oBAAA,GAAG,CAAC,UAAU,IAAI,GAAG,EACrB;AACA,oBAAA,OAAO,GAAG,GAAG,CAAC,CAAC;;oBAEf,IAAI,GAAG,EAAE,CAAC;AACX,iBAAA;AAAM,qBAAA;AACL,oBAAA,MAAM,GAAG,CAAC;AACX,iBAAA;AACF,aAAA;YACD,IAAI;AACF,gBAAA,OAAO,MAAM;AACX,sBAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC;sBAC5B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC/B,OAAO;AACR,aAAA;AAAC,YAAA,OAAO,CAAC,EAAE;gBACV,GAAG,GAAG,CAAC,CAAC;AACT,aAAA;AACF,SAAA;AACD,QAAA,MAAM,GAAG,CAAC;KACX,EACD,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,CACpC,CAAC;AACJ;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yext/chat-ui-react",
3
- "version": "0.10.0",
3
+ "version": "0.10.2",
4
4
  "description": "A library of React Components for powering Yext Chat integrations.",
5
5
  "author": "clippy@yext.com",
6
6
  "main": "./lib/commonjs/src/index.js",
@@ -91,7 +91,7 @@
91
91
  "typescript": "^5.0.4"
92
92
  },
93
93
  "peerDependencies": {
94
- "@yext/chat-headless-react": "^0.7.0",
94
+ "@yext/chat-headless-react": "^0.8.0",
95
95
  "react": "^16.14 || ^17 || ^18",
96
96
  "react-dom": "^16.14 || ^17 || || ^18"
97
97
  },
@@ -63,7 +63,7 @@ export interface ChatInputProps {
63
63
  * A function which is called when a retryable error occurs from
64
64
  * Chat API while processing the user's message.
65
65
  */
66
- onRetry?: (e: unknown) => void
66
+ onRetry?: (e: unknown) => void;
67
67
  }
68
68
 
69
69
  /**
@@ -92,7 +92,7 @@ export function ChatInput({
92
92
  (state) => state.conversation.canSendMessage
93
93
  );
94
94
  const defaultHandleApiError = useDefaultHandleApiError();
95
- const sendMessageWithRetries = useSendMessageWithRetries(stream, 1, onRetry)
95
+ const sendMessageWithRetries = useSendMessageWithRetries(stream, 1, onRetry);
96
96
  const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);
97
97
 
98
98
  const sendMessage = useCallback(async () => {
@@ -100,18 +100,27 @@ export function ChatInput({
100
100
  sendMessageWithRetries(input)
101
101
  .catch(handleError ?? defaultHandleApiError)
102
102
  .finally(() => {
103
- onSend?.(input)
104
- })
105
- }, [sendMessageWithRetries, input, handleError, defaultHandleApiError, onSend]);
103
+ onSend?.(input);
104
+ });
105
+ }, [
106
+ sendMessageWithRetries,
107
+ input,
108
+ handleError,
109
+ defaultHandleApiError,
110
+ onSend,
111
+ ]);
106
112
 
107
113
  const handleKeyDown = useCallback(
108
114
  (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
109
- if (!e.shiftKey && e.key === "Enter" &&
115
+ if (
116
+ !e.shiftKey &&
117
+ e.key === "Enter" &&
110
118
  // The Japanese Keyboard uses "Enter" key to convert from Hiragana to Kanji.
111
119
  // "isComposing" is a flag that indicates whether the event is part of an ongoing composition session.
112
120
  // Safari does not support `isComposing` with the Japanese IME event,
113
121
  // so we have to additionally check for the keyCode to handle that edge case.
114
- !(e.nativeEvent.isComposing || e.keyCode === 229)) {
122
+ !(e.nativeEvent.isComposing || e.keyCode === 229)
123
+ ) {
115
124
  e.preventDefault();
116
125
  if (canSendMessage && input.trim().length !== 0) {
117
126
  sendMessage();
@@ -75,6 +75,10 @@ export interface ChatPanelProps
75
75
  * can click on instead of typing their own.
76
76
  */
77
77
  messageSuggestions?: string[];
78
+ /** Link target open behavior on click.
79
+ * Defaults to "_blank".
80
+ */
81
+ linkTarget?: string;
78
82
  /** A callback which is called when user clicks a link. */
79
83
  onLinkClick?: (href?: string) => void;
80
84
  /**
@@ -101,9 +105,10 @@ export function ChatPanel(props: ChatPanelProps) {
101
105
  stream,
102
106
  handleError,
103
107
  messageSuggestions,
108
+ linkTarget = "_blank",
104
109
  onLinkClick,
105
- onSend:onSendProp,
106
- onRetry:onRetryProp,
110
+ onSend: onSendProp,
111
+ onRetry: onRetryProp,
107
112
  retryText = "Error occurred. Retrying",
108
113
  } = props;
109
114
  const messages = useChatState((state) => state.conversation.messages);
@@ -116,15 +121,21 @@ export function ChatPanel(props: ChatPanelProps) {
116
121
  useFetchInitialMessage(handleError, stream);
117
122
 
118
123
  const [retry, setRetry] = useState(false);
119
- const onSend = useCallback((message: string) => {
120
- onSendProp?.(message);
121
- setRetry(false)
122
- }, [onSendProp])
124
+ const onSend = useCallback(
125
+ (message: string) => {
126
+ onSendProp?.(message);
127
+ setRetry(false);
128
+ },
129
+ [onSendProp]
130
+ );
123
131
 
124
- const onRetry = useCallback((e: unknown) => {
125
- onRetryProp?.(e);
126
- setRetry(true)
127
- }, [onRetryProp])
132
+ const onRetry = useCallback(
133
+ (e: unknown) => {
134
+ onRetryProp?.(e);
135
+ setRetry(true);
136
+ },
137
+ [onRetryProp]
138
+ );
128
139
 
129
140
  useEffect(() => {
130
141
  reportAnalyticsEvent({
@@ -190,14 +201,21 @@ export function ChatPanel(props: ChatPanelProps) {
190
201
  {...props}
191
202
  customCssClasses={cssClasses.messageBubbleCssClasses}
192
203
  message={message}
204
+ linkTarget={linkTarget}
193
205
  onLinkClick={onLinkClick}
194
206
  />
195
207
  </div>
196
208
  ))}
197
- {loading && <div className="flex">
198
- <LoadingDots />
199
- {retry && <p className="text-slate-500 text-[13px] font-bold">{retryText}</p>}
200
- </div>}
209
+ {loading && (
210
+ <div className="flex">
211
+ <LoadingDots />
212
+ {retry && (
213
+ <p className="text-slate-500 text-[13px] font-bold">
214
+ {retryText}
215
+ </p>
216
+ )}
217
+ </div>
218
+ )}
201
219
  </div>
202
220
  </div>
203
221
  <div className={cssClasses.inputContainer}>
@@ -222,6 +240,7 @@ export function ChatPanel(props: ChatPanelProps) {
222
240
  <Markdown
223
241
  content={footer}
224
242
  linkClickEvent="WEBSITE"
243
+ linkTarget={linkTarget}
225
244
  onLinkClick={onLinkClick}
226
245
  customCssClasses={footerCssClasses}
227
246
  />
@@ -162,12 +162,13 @@ export function ChatPopUp(props: ChatPopUpProps) {
162
162
  // to avoid message requests immediately on load while the popup is still "hidden"
163
163
  const [renderChat, setRenderChat] = useState(false);
164
164
 
165
-
166
165
  // only fetch initial message when ChatPanel is closed on load (otherwise, it will be fetched in ChatPanel)
167
166
  useFetchInitialMessage(
168
167
  showInitialMessagePopUp ? console.error : handleError,
169
168
  false,
170
- (showUnreadNotification || showInitialMessagePopUp) && !renderChat && !openOnLoad,
169
+ (showUnreadNotification || showInitialMessagePopUp) &&
170
+ !renderChat &&
171
+ !openOnLoad
171
172
  );
172
173
 
173
174
  useEffect(() => {
@@ -180,7 +181,7 @@ export function ChatPopUp(props: ChatPopUpProps) {
180
181
  }, [messages.length, openOnLoad, renderChat]);
181
182
 
182
183
  const onClick = useCallback(() => {
183
- setShowChat(prev => !prev);
184
+ setShowChat((prev) => !prev);
184
185
  setRenderChat(true);
185
186
  setshowInitialMessage(false);
186
187
  }, []);
@@ -46,6 +46,8 @@ interface MarkdownProps {
46
46
  * Defaults to 'CHAT_LINK_CLICK'.
47
47
  */
48
48
  linkClickEvent?: "WEBSITE" | "CHAT_LINK_CLICK";
49
+ /** Link target open behavior on click. */
50
+ linkTarget?: string;
49
51
  /** A callback which is called when a link is clicked. */
50
52
  onLinkClick?: (href?: string) => void;
51
53
  }
@@ -64,6 +66,7 @@ export function Markdown({
64
66
  responseId,
65
67
  customCssClasses,
66
68
  linkClickEvent = "CHAT_LINK_CLICK",
69
+ linkTarget,
67
70
  onLinkClick,
68
71
  }: MarkdownProps) {
69
72
  const reportAnalyticsEvent = useReportAnalyticsEvent();
@@ -86,7 +89,7 @@ export function Markdown({
86
89
  <a
87
90
  {...props}
88
91
  onClick={createClickHandlerFn(props.href)}
89
- target="_blank"
92
+ target={linkTarget}
90
93
  rel="noopener noreferrer"
91
94
  className={cssClasses.link}
92
95
  >
@@ -100,6 +103,7 @@ export function Markdown({
100
103
  linkClickEvent,
101
104
  responseId,
102
105
  cssClasses,
106
+ linkTarget,
103
107
  onLinkClick,
104
108
  ]);
105
109
 
@@ -75,6 +75,8 @@ export interface MessageBubbleProps {
75
75
  formatTimestamp?: (timestamp: string) => string;
76
76
  /** CSS classes for customizing the component styling. */
77
77
  customCssClasses?: MessageBubbleCssClasses;
78
+ /** Link target open behavior on click. */
79
+ linkTarget?: string;
78
80
  /** A callback which is called when user clicks a link. */
79
81
  onLinkClick?: (href?: string) => void;
80
82
  }
@@ -92,6 +94,7 @@ export function MessageBubble({
92
94
  showTimestamp = true,
93
95
  customCssClasses,
94
96
  formatTimestamp = defaultFormatTimestamp,
97
+ linkTarget,
95
98
  onLinkClick,
96
99
  }: MessageBubbleProps) {
97
100
  const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);
@@ -141,6 +144,7 @@ export function MessageBubble({
141
144
  content={message.text}
142
145
  responseId={message.responseId}
143
146
  customCssClasses={markdownCssClasses}
147
+ linkTarget={linkTarget}
144
148
  onLinkClick={onLinkClick}
145
149
  />
146
150
  </div>
@@ -36,7 +36,7 @@ export interface MessageSuggestionsProps {
36
36
  /** {@inheritdoc ChatInputProps.onSend} */
37
37
  onSend?: (message: string) => void;
38
38
  /** {@inheritdoc ChatInputProps.onRetry} */
39
- onRetry?: (e: unknown) => void
39
+ onRetry?: (e: unknown) => void;
40
40
  }
41
41
 
42
42
  const defaultClassnames: MessageSuggestionCssClasses = withStylelessCssClasses(
@@ -65,7 +65,7 @@ export const MessageSuggestions: React.FC<MessageSuggestionsProps> = ({
65
65
  const actions = useChatActions();
66
66
  const notes = useChatState((state) => state.conversation.notes);
67
67
  const defaultHandleApiError = useDefaultHandleApiError();
68
- const sendMessageWithRetries = useSendMessageWithRetries(stream, 1, onRetry)
68
+ const sendMessageWithRetries = useSendMessageWithRetries(stream, 1, onRetry);
69
69
  const sendMsg = useCallback(
70
70
  (msg: string) => {
71
71
  const newNotes = {
@@ -76,10 +76,17 @@ export const MessageSuggestions: React.FC<MessageSuggestionsProps> = ({
76
76
  sendMessageWithRetries(msg)
77
77
  .catch(handleError ?? defaultHandleApiError)
78
78
  .finally(() => {
79
- onSend?.(msg)
80
- })
79
+ onSend?.(msg);
80
+ });
81
81
  },
82
- [notes, actions, sendMessageWithRetries, handleError, defaultHandleApiError, onSend]
82
+ [
83
+ notes,
84
+ actions,
85
+ sendMessageWithRetries,
86
+ handleError,
87
+ defaultHandleApiError,
88
+ onSend,
89
+ ]
83
90
  );
84
91
 
85
92
  const classes = useComposedCssClasses(defaultClassnames, customCssClasses);
@@ -16,7 +16,7 @@ import { useDefaultHandleApiError } from "../hooks/useDefaultHandleApiError";
16
16
  export function useFetchInitialMessage(
17
17
  handleError?: (e: unknown) => void,
18
18
  stream = false,
19
- customCondition = true,
19
+ customCondition = true
20
20
  ) {
21
21
  const chat = useChatActions();
22
22
  const defaultHandleApiError = useDefaultHandleApiError();
@@ -24,12 +24,20 @@ export function useFetchInitialMessage(
24
24
  const canSendMessage = useChatState(
25
25
  (state) => state.conversation.canSendMessage
26
26
  );
27
-
27
+
28
28
  useEffect(() => {
29
29
  if (messages.length !== 0 || !canSendMessage || !customCondition) {
30
30
  return;
31
31
  }
32
32
  const res = stream ? chat.streamNextMessage() : chat.getNextMessage();
33
33
  res.catch((e) => (handleError ? handleError(e) : defaultHandleApiError(e)));
34
- }, [chat, stream, handleError, defaultHandleApiError, canSendMessage, customCondition, messages.length]);
34
+ }, [
35
+ chat,
36
+ stream,
37
+ handleError,
38
+ defaultHandleApiError,
39
+ canSendMessage,
40
+ customCondition,
41
+ messages.length,
42
+ ]);
35
43
  }
@@ -4,46 +4,53 @@ import { useCallback } from "react";
4
4
  /**
5
5
  * Returns a function that sends a message to the chat API with retries
6
6
  * if the API returns a 5xx status code.
7
- *
7
+ *
8
8
  * @remarks
9
9
  * The function will throw the error if the maximum number of retries is reached
10
10
  * or if the error is not a 5xx status code.
11
- *
11
+ *
12
12
  * @internal
13
- *
13
+ *
14
14
  * @param stream - If true, use streaming API
15
15
  * @param maxRetries - Maximum number of retries
16
16
  * @param onRetry - Callback to handle error on each retry
17
- *
17
+ *
18
18
  */
19
19
  export function useSendMessageWithRetries(
20
20
  stream = false,
21
21
  maxRetries = 0,
22
22
  onRetry?: (e: unknown) => void
23
23
  ): (input: string) => Promise<void> {
24
- const chat = useChatActions()
25
- return useCallback(async (input: string) => {
26
- let err: unknown;
27
- let text = input;
28
- for (let numRetries = 0; numRetries <= maxRetries; numRetries++) {
29
- if (numRetries > 0 && !!err) {
30
- if (err instanceof ApiError && !!err.statusCode && err.statusCode >= 500) {
31
- onRetry?.(err)
32
- // avoid re-adding user message to conversation history on retry
33
- text = "";
34
- } else {
35
- throw err;
24
+ const chat = useChatActions();
25
+ return useCallback(
26
+ async (input: string) => {
27
+ let err: unknown;
28
+ let text = input;
29
+ for (let numRetries = 0; numRetries <= maxRetries; numRetries++) {
30
+ if (numRetries > 0 && !!err) {
31
+ if (
32
+ err instanceof ApiError &&
33
+ !!err.statusCode &&
34
+ err.statusCode >= 500
35
+ ) {
36
+ onRetry?.(err);
37
+ // avoid re-adding user message to conversation history on retry
38
+ text = "";
39
+ } else {
40
+ throw err;
41
+ }
42
+ }
43
+ try {
44
+ await (stream
45
+ ? chat.streamNextMessage(text)
46
+ : chat.getNextMessage(text));
47
+ return;
48
+ } catch (e) {
49
+ err = e;
36
50
  }
37
51
  }
38
- try {
39
- await (stream
40
- ? chat.streamNextMessage(text)
41
- : chat.getNextMessage(text));
42
- return;
43
- } catch (e) {
44
- err = e;
45
- }
46
- }
47
- throw err
48
- }, [chat, maxRetries, onRetry, stream])
52
+ throw err;
53
+ },
54
+ [chat, maxRetries, onRetry, stream]
55
+ );
49
56
  }