@yext/chat-ui-react 0.10.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/THIRD-PARTY-NOTICES +3 -3
  2. package/lib/bundle.css +1 -1
  3. package/lib/commonjs/package.json.js +1 -1
  4. package/lib/commonjs/src/components/ChatInput.d.ts.map +1 -1
  5. package/lib/commonjs/src/components/ChatInput.js +9 -2
  6. package/lib/commonjs/src/components/ChatInput.js.map +1 -1
  7. package/lib/commonjs/src/components/ChatPanel.d.ts +4 -0
  8. package/lib/commonjs/src/components/ChatPanel.d.ts.map +1 -1
  9. package/lib/commonjs/src/components/ChatPanel.js +7 -7
  10. package/lib/commonjs/src/components/ChatPanel.js.map +1 -1
  11. package/lib/commonjs/src/components/ChatPopUp.d.ts.map +1 -1
  12. package/lib/commonjs/src/components/ChatPopUp.js +19 -8
  13. package/lib/commonjs/src/components/ChatPopUp.js.map +1 -1
  14. package/lib/commonjs/src/components/Markdown.d.ts +3 -1
  15. package/lib/commonjs/src/components/Markdown.d.ts.map +1 -1
  16. package/lib/commonjs/src/components/Markdown.js +3 -2
  17. package/lib/commonjs/src/components/Markdown.js.map +1 -1
  18. package/lib/commonjs/src/components/MessageBubble.d.ts +3 -1
  19. package/lib/commonjs/src/components/MessageBubble.d.ts.map +1 -1
  20. package/lib/commonjs/src/components/MessageBubble.js +3 -3
  21. package/lib/commonjs/src/components/MessageBubble.js.map +1 -1
  22. package/lib/commonjs/src/components/MessageSuggestions.d.ts.map +1 -1
  23. package/lib/commonjs/src/components/MessageSuggestions.js +8 -1
  24. package/lib/commonjs/src/components/MessageSuggestions.js.map +1 -1
  25. package/lib/commonjs/src/hooks/useFetchInitialMessage.d.ts.map +1 -1
  26. package/lib/commonjs/src/hooks/useFetchInitialMessage.js +9 -1
  27. package/lib/commonjs/src/hooks/useFetchInitialMessage.js.map +1 -1
  28. package/lib/commonjs/src/hooks/useSendMessageWithRetries.d.ts.map +1 -1
  29. package/lib/commonjs/src/hooks/useSendMessageWithRetries.js +3 -1
  30. package/lib/commonjs/src/hooks/useSendMessageWithRetries.js.map +1 -1
  31. package/lib/esm/index.d.ts +7 -1
  32. package/lib/esm/package.json.mjs +1 -1
  33. package/lib/esm/src/components/ChatInput.d.ts.map +1 -1
  34. package/lib/esm/src/components/ChatInput.mjs +9 -2
  35. package/lib/esm/src/components/ChatInput.mjs.map +1 -1
  36. package/lib/esm/src/components/ChatPanel.d.ts +4 -0
  37. package/lib/esm/src/components/ChatPanel.d.ts.map +1 -1
  38. package/lib/esm/src/components/ChatPanel.mjs +7 -7
  39. package/lib/esm/src/components/ChatPanel.mjs.map +1 -1
  40. package/lib/esm/src/components/ChatPopUp.d.ts.map +1 -1
  41. package/lib/esm/src/components/ChatPopUp.mjs +19 -8
  42. package/lib/esm/src/components/ChatPopUp.mjs.map +1 -1
  43. package/lib/esm/src/components/Markdown.d.ts +3 -1
  44. package/lib/esm/src/components/Markdown.d.ts.map +1 -1
  45. package/lib/esm/src/components/Markdown.mjs +3 -2
  46. package/lib/esm/src/components/Markdown.mjs.map +1 -1
  47. package/lib/esm/src/components/MessageBubble.d.ts +3 -1
  48. package/lib/esm/src/components/MessageBubble.d.ts.map +1 -1
  49. package/lib/esm/src/components/MessageBubble.mjs +3 -3
  50. package/lib/esm/src/components/MessageBubble.mjs.map +1 -1
  51. package/lib/esm/src/components/MessageSuggestions.d.ts.map +1 -1
  52. package/lib/esm/src/components/MessageSuggestions.mjs +8 -1
  53. package/lib/esm/src/components/MessageSuggestions.mjs.map +1 -1
  54. package/lib/esm/src/hooks/useFetchInitialMessage.d.ts.map +1 -1
  55. package/lib/esm/src/hooks/useFetchInitialMessage.mjs +9 -1
  56. package/lib/esm/src/hooks/useFetchInitialMessage.mjs.map +1 -1
  57. package/lib/esm/src/hooks/useSendMessageWithRetries.d.ts.map +1 -1
  58. package/lib/esm/src/hooks/useSendMessageWithRetries.mjs +3 -1
  59. package/lib/esm/src/hooks/useSendMessageWithRetries.mjs.map +1 -1
  60. package/package.json +3 -3
  61. package/src/components/ChatInput.tsx +16 -7
  62. package/src/components/ChatPanel.tsx +35 -16
  63. package/src/components/ChatPopUp.tsx +27 -8
  64. package/src/components/Markdown.tsx +5 -1
  65. package/src/components/MessageBubble.tsx +5 -1
  66. package/src/components/MessageSuggestions.tsx +12 -5
  67. package/src/hooks/useFetchInitialMessage.ts +11 -3
  68. package/src/hooks/useSendMessageWithRetries.ts +34 -27
@@ -1 +1 @@
1
- {"version":3,"file":"MessageBubble.d.ts","sourceRoot":"","sources":["../../../../src/components/MessageBubble.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,OAAO,EAAiB,MAAM,2BAA2B,CAAC;AAKnE,OAAO,EAAmB,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAE/E;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yBAAyB,CAAC,EAAE,yBAAyB,CAAC;CACvD;AAuBD;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,8BAA8B;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IAChD,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,uBAAuB,CAAC;IAC3C,0DAA0D;IAC1D,WAAW,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,mBAA0B,EAC1B,aAAoB,EACpB,gBAAgB,EAChB,eAAwC,EACxC,WAAW,GACZ,EAAE,kBAAkB,qBA4DpB"}
1
+ {"version":3,"file":"MessageBubble.d.ts","sourceRoot":"","sources":["../../../../src/components/MessageBubble.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,OAAO,EAAiB,MAAM,2BAA2B,CAAC;AAKnE,OAAO,EAAmB,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAE/E;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yBAAyB,CAAC,EAAE,yBAAyB,CAAC;CACvD;AAuBD;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,8BAA8B;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IAChD,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,uBAAuB,CAAC;IAC3C,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,mBAA0B,EAC1B,aAAoB,EACpB,gBAAgB,EAChB,eAAwC,EACxC,UAAU,EACV,WAAW,GACZ,EAAE,kBAAkB,qBA6DpB"}
@@ -23,7 +23,7 @@ const builtInCssClasses = withStylelessCssClasses.withStylelessCssClasses("Messa
23
23
  text: "text-[13px] @[480px]:text-base prose overflow-x-auto",
24
24
  text__bot: "text-slate-900",
25
25
  text__user: "text-white break-words",
26
- timestamp: "w-fit my-0.5 ml-4 @lg:ml-0 text-slate-400 text-[10px] @[480px]:text-[13px] opacity-0 peer-hover:opacity-100 duration-200 whitespace-pre-wrap",
26
+ timestamp: "w-fit ml-4 @lg:ml-0 text-slate-400 text-[10px] @[480px]:text-[13px] opacity-0 peer-hover:opacity-100 duration-200 whitespace-pre-wrap",
27
27
  timestamp__bot: "",
28
28
  timestamp__user: "ml-auto",
29
29
  feedbackButtonsCssClasses: {},
@@ -35,7 +35,7 @@ const builtInCssClasses = withStylelessCssClasses.withStylelessCssClasses("Messa
35
35
  *
36
36
  * @param props - {@link MessageBubbleProps}
37
37
  */
38
- function MessageBubble({ message, showFeedbackButtons = true, showTimestamp = true, customCssClasses, formatTimestamp = defaultFormatTimestamp, onLinkClick, }) {
38
+ function MessageBubble({ message, showFeedbackButtons = true, showTimestamp = true, customCssClasses, formatTimestamp = defaultFormatTimestamp, linkTarget, onLinkClick, }) {
39
39
  const cssClasses = useComposedCssClasses.useComposedCssClasses(builtInCssClasses, customCssClasses);
40
40
  const bubbleCssClasses = tailwindMerge.twMerge(cssClasses.bubble, message.source === chatHeadlessReact.MessageSource.USER
41
41
  ? cssClasses.bubble__user
@@ -56,7 +56,7 @@ function MessageBubble({ message, showFeedbackButtons = true, showTimestamp = tr
56
56
  React__default.default.createElement("div", { className: subContainerCssClasses },
57
57
  React__default.default.createElement("div", { className: bubbleCssClasses },
58
58
  showFeedbackButtons && message.source === chatHeadlessReact.MessageSource.BOT && (React__default.default.createElement(FeedbackButtons.FeedbackButtons, { customCssClasses: cssClasses.feedbackButtonsCssClasses, responseId: message.responseId })),
59
- React__default.default.createElement(Markdown.Markdown, { content: message.text, responseId: message.responseId, customCssClasses: markdownCssClasses, onLinkClick: onLinkClick })),
59
+ React__default.default.createElement(Markdown.Markdown, { content: message.text, responseId: message.responseId, customCssClasses: markdownCssClasses, linkTarget: linkTarget, onLinkClick: onLinkClick })),
60
60
  showTimestamp && (React__default.default.createElement("div", { className: timestampCssClasses }, message.timestamp ? formatTimestamp(message.timestamp) : " ")))));
61
61
  }
62
62
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"MessageBubble.js","sources":["../../../../src/components/MessageBubble.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport { Message, MessageSource } from \"@yext/chat-headless-react\";\nimport { useComposedCssClasses } from \"../hooks\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Markdown, MarkdownCssClasses } from \"./Markdown\";\nimport { withStylelessCssClasses } from \"../utils/withStylelessCssClasses\";\nimport { FeedbackButtons, FeedbackButtonsCssClasses } from \"./FeedbackButtons\";\n\n/**\n * The CSS class interface for the {@link MessageBubble} component.\n *\n * @public\n */\nexport interface MessageBubbleCssClasses {\n topContainer?: string;\n subContainer?: string;\n subContainer__bot?: string;\n subContainer__user?: string;\n bubble?: string;\n bubble__bot?: string;\n bubble__user?: string;\n text?: string;\n text__bot?: string;\n text__user?: string;\n timestamp?: string;\n timestamp__bot?: string;\n timestamp__user?: string;\n feedbackButtonsCssClasses?: FeedbackButtonsCssClasses;\n}\n\nconst builtInCssClasses: MessageBubbleCssClasses =\n withStylelessCssClasses<MessageBubbleCssClasses>(\"MessageBubble\", {\n topContainer: \"w-full animate-fade-in @container\",\n subContainer:\n \"flex flex-col @lg:flex-row @lg:items-center @lg:gap-x-2 @lg:m-1\",\n subContainer__bot: \"\",\n subContainer__user: \"@lg:flex-row-reverse\",\n bubble: \"relative group peer w-fit max-w-[80%] rounded-2xl p-4\",\n bubble__bot: \"bg-gradient-to-tr from-slate-50 to-slate-100\",\n bubble__user:\n \"ml-auto @lg:ml-0 bg-gradient-to-tr from-blue-600 to-blue-700 text-white\",\n text: \"text-[13px] @[480px]:text-base prose overflow-x-auto\",\n text__bot: \"text-slate-900\",\n text__user: \"text-white break-words\",\n timestamp:\n \"w-fit my-0.5 ml-4 @lg:ml-0 text-slate-400 text-[10px] @[480px]:text-[13px] opacity-0 peer-hover:opacity-100 duration-200 whitespace-pre-wrap\",\n timestamp__bot: \"\",\n timestamp__user: \"ml-auto\",\n feedbackButtonsCssClasses: {},\n });\n\n/**\n * The props for the {@link MessageBubble} component.\n *\n * @public\n */\nexport interface MessageBubbleProps {\n /** The message to display. */\n message: Message;\n /**\n * Whether to show the feedback buttons on the message bubble.\n * Defaults to true.\n */\n showFeedbackButtons?: boolean;\n /**\n * Whether to show the timestamp of the message with the message bubble.\n * Defaults to true.\n */\n showTimestamp?: boolean;\n /**\n * A function which is called to format the message's timestamp given in\n * ISO format (e.g. \"2023-05-18T19:33:34.553Z\").\n * Defaults to \"HH:MM A\" (e.g. \"7:33 PM\").\n */\n formatTimestamp?: (timestamp: string) => string;\n /** CSS classes for customizing the component styling. */\n customCssClasses?: MessageBubbleCssClasses;\n /** A callback which is called when user clicks a link. */\n onLinkClick?: (href?: string) => void;\n}\n\n/**\n * A component that displays the provided message.\n *\n * @public\n *\n * @param props - {@link MessageBubbleProps}\n */\nexport function MessageBubble({\n message,\n showFeedbackButtons = true,\n showTimestamp = true,\n customCssClasses,\n formatTimestamp = defaultFormatTimestamp,\n onLinkClick,\n}: MessageBubbleProps) {\n const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);\n const bubbleCssClasses = twMerge(\n cssClasses.bubble,\n message.source === MessageSource.USER\n ? cssClasses.bubble__user\n : cssClasses.bubble__bot\n );\n const textCssClasses = twMerge(\n cssClasses.text,\n message.source === MessageSource.USER\n ? cssClasses.text__user\n : cssClasses.text__bot\n );\n const subContainerCssClasses = twMerge(\n cssClasses.subContainer,\n message.source === MessageSource.USER\n ? cssClasses.subContainer__user\n : cssClasses.subContainer__bot\n );\n const timestampCssClasses = twMerge(\n cssClasses.timestamp,\n message.source === MessageSource.USER\n ? cssClasses.timestamp__user\n : cssClasses.timestamp__bot\n );\n\n const markdownCssClasses: MarkdownCssClasses = useMemo(\n () => ({\n container: textCssClasses,\n }),\n [textCssClasses]\n );\n\n return (\n <div className={cssClasses.topContainer}>\n <div className={subContainerCssClasses}>\n <div className={bubbleCssClasses}>\n {showFeedbackButtons && message.source === MessageSource.BOT && (\n <FeedbackButtons\n customCssClasses={cssClasses.feedbackButtonsCssClasses}\n responseId={message.responseId}\n />\n )}\n <Markdown\n content={message.text}\n responseId={message.responseId}\n customCssClasses={markdownCssClasses}\n onLinkClick={onLinkClick}\n />\n </div>\n {/* fallback on empty space here to perserve the height for timestamp div */}\n {showTimestamp && (\n <div className={timestampCssClasses}>\n {message.timestamp ? formatTimestamp(message.timestamp) : \" \"}\n </div>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Formats message's timestamp from \"2023-05-18T19:33:34.553Z\" to \"7:33 PM\"\n *\n * @param timestamp - the timestamp to convert from\n * @returns formatted timestamp\n */\nfunction defaultFormatTimestamp(timestamp: string): string {\n return new Date(timestamp).toLocaleString(undefined, {\n hour: \"numeric\",\n minute: \"numeric\",\n hour12: true,\n });\n}\n"],"names":["withStylelessCssClasses","useComposedCssClasses","twMerge","MessageSource","useMemo","React","FeedbackButtons","Markdown"],"mappings":"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"}
1
+ {"version":3,"file":"MessageBubble.js","sources":["../../../../src/components/MessageBubble.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport { Message, MessageSource } from \"@yext/chat-headless-react\";\nimport { useComposedCssClasses } from \"../hooks\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Markdown, MarkdownCssClasses } from \"./Markdown\";\nimport { withStylelessCssClasses } from \"../utils/withStylelessCssClasses\";\nimport { FeedbackButtons, FeedbackButtonsCssClasses } from \"./FeedbackButtons\";\n\n/**\n * The CSS class interface for the {@link MessageBubble} component.\n *\n * @public\n */\nexport interface MessageBubbleCssClasses {\n topContainer?: string;\n subContainer?: string;\n subContainer__bot?: string;\n subContainer__user?: string;\n bubble?: string;\n bubble__bot?: string;\n bubble__user?: string;\n text?: string;\n text__bot?: string;\n text__user?: string;\n timestamp?: string;\n timestamp__bot?: string;\n timestamp__user?: string;\n feedbackButtonsCssClasses?: FeedbackButtonsCssClasses;\n}\n\nconst builtInCssClasses: MessageBubbleCssClasses =\n withStylelessCssClasses<MessageBubbleCssClasses>(\"MessageBubble\", {\n topContainer: \"w-full animate-fade-in @container\",\n subContainer:\n \"flex flex-col @lg:flex-row @lg:items-center @lg:gap-x-2 @lg:m-1\",\n subContainer__bot: \"\",\n subContainer__user: \"@lg:flex-row-reverse\",\n bubble: \"relative group peer w-fit max-w-[80%] rounded-2xl p-4\",\n bubble__bot: \"bg-gradient-to-tr from-slate-50 to-slate-100\",\n bubble__user:\n \"ml-auto @lg:ml-0 bg-gradient-to-tr from-blue-600 to-blue-700 text-white\",\n text: \"text-[13px] @[480px]:text-base prose overflow-x-auto\",\n text__bot: \"text-slate-900\",\n text__user: \"text-white break-words\",\n timestamp:\n \"w-fit ml-4 @lg:ml-0 text-slate-400 text-[10px] @[480px]:text-[13px] opacity-0 peer-hover:opacity-100 duration-200 whitespace-pre-wrap\",\n timestamp__bot: \"\",\n timestamp__user: \"ml-auto\",\n feedbackButtonsCssClasses: {},\n });\n\n/**\n * The props for the {@link MessageBubble} component.\n *\n * @public\n */\nexport interface MessageBubbleProps {\n /** The message to display. */\n message: Message;\n /**\n * Whether to show the feedback buttons on the message bubble.\n * Defaults to true.\n */\n showFeedbackButtons?: boolean;\n /**\n * Whether to show the timestamp of the message with the message bubble.\n * Defaults to true.\n */\n showTimestamp?: boolean;\n /**\n * A function which is called to format the message's timestamp given in\n * ISO format (e.g. \"2023-05-18T19:33:34.553Z\").\n * Defaults to \"HH:MM A\" (e.g. \"7:33 PM\").\n */\n formatTimestamp?: (timestamp: string) => string;\n /** CSS classes for customizing the component styling. */\n customCssClasses?: MessageBubbleCssClasses;\n /** Link target open behavior on click. */\n linkTarget?: string;\n /** A callback which is called when user clicks a link. */\n onLinkClick?: (href?: string) => void;\n}\n\n/**\n * A component that displays the provided message.\n *\n * @public\n *\n * @param props - {@link MessageBubbleProps}\n */\nexport function MessageBubble({\n message,\n showFeedbackButtons = true,\n showTimestamp = true,\n customCssClasses,\n formatTimestamp = defaultFormatTimestamp,\n linkTarget,\n onLinkClick,\n}: MessageBubbleProps) {\n const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);\n const bubbleCssClasses = twMerge(\n cssClasses.bubble,\n message.source === MessageSource.USER\n ? cssClasses.bubble__user\n : cssClasses.bubble__bot\n );\n const textCssClasses = twMerge(\n cssClasses.text,\n message.source === MessageSource.USER\n ? cssClasses.text__user\n : cssClasses.text__bot\n );\n const subContainerCssClasses = twMerge(\n cssClasses.subContainer,\n message.source === MessageSource.USER\n ? cssClasses.subContainer__user\n : cssClasses.subContainer__bot\n );\n const timestampCssClasses = twMerge(\n cssClasses.timestamp,\n message.source === MessageSource.USER\n ? cssClasses.timestamp__user\n : cssClasses.timestamp__bot\n );\n\n const markdownCssClasses: MarkdownCssClasses = useMemo(\n () => ({\n container: textCssClasses,\n }),\n [textCssClasses]\n );\n\n return (\n <div className={cssClasses.topContainer}>\n <div className={subContainerCssClasses}>\n <div className={bubbleCssClasses}>\n {showFeedbackButtons && message.source === MessageSource.BOT && (\n <FeedbackButtons\n customCssClasses={cssClasses.feedbackButtonsCssClasses}\n responseId={message.responseId}\n />\n )}\n <Markdown\n content={message.text}\n responseId={message.responseId}\n customCssClasses={markdownCssClasses}\n linkTarget={linkTarget}\n onLinkClick={onLinkClick}\n />\n </div>\n {/* fallback on empty space here to perserve the height for timestamp div */}\n {showTimestamp && (\n <div className={timestampCssClasses}>\n {message.timestamp ? formatTimestamp(message.timestamp) : \" \"}\n </div>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Formats message's timestamp from \"2023-05-18T19:33:34.553Z\" to \"7:33 PM\"\n *\n * @param timestamp - the timestamp to convert from\n * @returns formatted timestamp\n */\nfunction defaultFormatTimestamp(timestamp: string): string {\n return new Date(timestamp).toLocaleString(undefined, {\n hour: \"numeric\",\n minute: \"numeric\",\n hour12: true,\n });\n}\n"],"names":["withStylelessCssClasses","useComposedCssClasses","twMerge","MessageSource","useMemo","React","FeedbackButtons","Markdown"],"mappings":";;;;;;;;;;;;;;AA8BA,MAAM,iBAAiB,GACrBA,+CAAuB,CAA0B,eAAe,EAAE;AAChE,IAAA,YAAY,EAAE,mCAAmC;AACjD,IAAA,YAAY,EACV,iEAAiE;AACnE,IAAA,iBAAiB,EAAE,EAAE;AACrB,IAAA,kBAAkB,EAAE,sBAAsB;AAC1C,IAAA,MAAM,EAAE,uDAAuD;AAC/D,IAAA,WAAW,EAAE,8CAA8C;AAC3D,IAAA,YAAY,EACV,yEAAyE;AAC3E,IAAA,IAAI,EAAE,sDAAsD;AAC5D,IAAA,SAAS,EAAE,gBAAgB;AAC3B,IAAA,UAAU,EAAE,wBAAwB;AACpC,IAAA,SAAS,EACP,uIAAuI;AACzI,IAAA,cAAc,EAAE,EAAE;AAClB,IAAA,eAAe,EAAE,SAAS;AAC1B,IAAA,yBAAyB,EAAE,EAAE;AAC9B,CAAA,CAAC,CAAC;AAkCL;;;;;;AAMG;AACG,SAAU,aAAa,CAAC,EAC5B,OAAO,EACP,mBAAmB,GAAG,IAAI,EAC1B,aAAa,GAAG,IAAI,EACpB,gBAAgB,EAChB,eAAe,GAAG,sBAAsB,EACxC,UAAU,EACV,WAAW,GACQ,EAAA;IACnB,MAAM,UAAU,GAAGC,2CAAqB,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;AAC9E,IAAA,MAAM,gBAAgB,GAAGC,qBAAO,CAC9B,UAAU,CAAC,MAAM,EACjB,OAAO,CAAC,MAAM,KAAKC,+BAAa,CAAC,IAAI;UACjC,UAAU,CAAC,YAAY;AACzB,UAAE,UAAU,CAAC,WAAW,CAC3B,CAAC;AACF,IAAA,MAAM,cAAc,GAAGD,qBAAO,CAC5B,UAAU,CAAC,IAAI,EACf,OAAO,CAAC,MAAM,KAAKC,+BAAa,CAAC,IAAI;UACjC,UAAU,CAAC,UAAU;AACvB,UAAE,UAAU,CAAC,SAAS,CACzB,CAAC;AACF,IAAA,MAAM,sBAAsB,GAAGD,qBAAO,CACpC,UAAU,CAAC,YAAY,EACvB,OAAO,CAAC,MAAM,KAAKC,+BAAa,CAAC,IAAI;UACjC,UAAU,CAAC,kBAAkB;AAC/B,UAAE,UAAU,CAAC,iBAAiB,CACjC,CAAC;AACF,IAAA,MAAM,mBAAmB,GAAGD,qBAAO,CACjC,UAAU,CAAC,SAAS,EACpB,OAAO,CAAC,MAAM,KAAKC,+BAAa,CAAC,IAAI;UACjC,UAAU,CAAC,eAAe;AAC5B,UAAE,UAAU,CAAC,cAAc,CAC9B,CAAC;AAEF,IAAA,MAAM,kBAAkB,GAAuBC,aAAO,CACpD,OAAO;AACL,QAAA,SAAS,EAAE,cAAc;AAC1B,KAAA,CAAC,EACF,CAAC,cAAc,CAAC,CACjB,CAAC;AAEF,IAAA,QACEC,sBAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,UAAU,CAAC,YAAY,EAAA;QACrCA,sBAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,sBAAsB,EAAA;YACpCA,sBAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,gBAAgB,EAAA;gBAC7B,mBAAmB,IAAI,OAAO,CAAC,MAAM,KAAKF,+BAAa,CAAC,GAAG,KAC1DE,sBAAC,CAAA,aAAA,CAAAC,+BAAe,IACd,gBAAgB,EAAE,UAAU,CAAC,yBAAyB,EACtD,UAAU,EAAE,OAAO,CAAC,UAAU,EAAA,CAC9B,CACH;gBACDD,sBAAC,CAAA,aAAA,CAAAE,iBAAQ,EACP,EAAA,OAAO,EAAE,OAAO,CAAC,IAAI,EACrB,UAAU,EAAE,OAAO,CAAC,UAAU,EAC9B,gBAAgB,EAAE,kBAAkB,EACpC,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,EAAA,CACxB,CACE;AAEL,YAAA,aAAa,KACZF,sBAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,mBAAmB,EAChC,EAAA,OAAO,CAAC,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,GAAG,CACzD,CACP,CACG,CACF,EACN;AACJ,CAAC;AAED;;;;;AAKG;AACH,SAAS,sBAAsB,CAAC,SAAiB,EAAA;IAC/C,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,SAAS,EAAE;AACnD,QAAA,IAAI,EAAE,SAAS;AACf,QAAA,MAAM,EAAE,SAAS;AACjB,QAAA,MAAM,EAAE,IAAI;AACb,KAAA,CAAC,CAAC;AACL;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"MessageSuggestions.d.ts","sourceRoot":"","sources":["../../../../src/components/MessageSuggestions.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsB,MAAM,OAAO,CAAC;AAW3C;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,uDAAuD;IACvD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,2BAA2B,CAAC;IAC/C,0CAA0C;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,2CAA2C;IAC3C,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CAC/B;AAWD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA4ChE,CAAC"}
1
+ {"version":3,"file":"MessageSuggestions.d.ts","sourceRoot":"","sources":["../../../../src/components/MessageSuggestions.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsB,MAAM,OAAO,CAAC;AAW3C;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,uDAAuD;IACvD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,2BAA2B,CAAC;IAC/C,0CAA0C;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,2CAA2C;IAC3C,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAChC;AAWD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAmDhE,CAAC"}
@@ -37,7 +37,14 @@ const MessageSuggestions = ({ handleError, suggestions, customCssClasses, stream
37
37
  .finally(() => {
38
38
  onSend?.(msg);
39
39
  });
40
- }, [notes, actions, sendMessageWithRetries, handleError, defaultHandleApiError, onSend]);
40
+ }, [
41
+ notes,
42
+ actions,
43
+ sendMessageWithRetries,
44
+ handleError,
45
+ defaultHandleApiError,
46
+ onSend,
47
+ ]);
41
48
  const classes = useComposedCssClasses.useComposedCssClasses(defaultClassnames, customCssClasses);
42
49
  return (React__default.default.createElement("div", { className: classes.container }, suggestions.map((suggestion, index) => (React__default.default.createElement("button", { key: index, className: classes.suggestion,
43
50
  // eslint-disable-next-line react-perf/jsx-no-new-function-as-prop
@@ -1 +1 @@
1
- {"version":3,"file":"MessageSuggestions.js","sources":["../../../../src/components/MessageSuggestions.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport {\n MessageNotes,\n useChatActions,\n useChatState,\n} from \"@yext/chat-headless-react\";\nimport { useDefaultHandleApiError } from \"../hooks/useDefaultHandleApiError\";\nimport { withStylelessCssClasses } from \"../utils/withStylelessCssClasses\";\nimport { useComposedCssClasses } from \"../hooks\";\nimport { useSendMessageWithRetries } from \"../hooks/useSendMessageWithRetries\";\n\n/**\n * The CSS class interface for the MessageSuggestion component.\n *\n * @public\n */\nexport interface MessageSuggestionCssClasses {\n container?: string;\n suggestion?: string;\n}\n\n/**\n * The props for the MessageSuggestions component.\n *\n * @public\n */\nexport interface MessageSuggestionsProps {\n /** List of clickable message suggestions to render. */\n suggestions: string[];\n /** {@inheritdoc ChatInputProps.handleError} */\n handleError?: (e: unknown) => void;\n /** CSS classes for customizing the component styling. */\n customCssClasses?: MessageSuggestionCssClasses;\n /** {@inheritdoc ChatInputProps.stream} */\n stream?: boolean;\n /** {@inheritdoc ChatInputProps.onSend} */\n onSend?: (message: string) => void;\n /** {@inheritdoc ChatInputProps.onRetry} */\n onRetry?: (e: unknown) => void\n}\n\nconst defaultClassnames: MessageSuggestionCssClasses = withStylelessCssClasses(\n \"Suggestions\",\n {\n container: \"flex gap-2 mb-4 w-full overflow-x-auto flex-wrap\",\n suggestion:\n \"hover:cursor-pointer px-2 py-1 bg-white hover:bg-slate-300 rounded-full text-sm text-blue-700 border border-blue-700 hover:underline\",\n }\n);\n\n/**\n * A component that displays a list of suggested messages\n * to the user, which they can click to send the message to the bot.\n *\n * @internal\n */\nexport const MessageSuggestions: React.FC<MessageSuggestionsProps> = ({\n handleError,\n suggestions,\n customCssClasses,\n stream = false,\n onSend,\n onRetry,\n}) => {\n const actions = useChatActions();\n const notes = useChatState((state) => state.conversation.notes);\n const defaultHandleApiError = useDefaultHandleApiError();\n const sendMessageWithRetries = useSendMessageWithRetries(stream, 1, onRetry)\n const sendMsg = useCallback(\n (msg: string) => {\n const newNotes = {\n ...(notes || {}),\n suggestedReplies: undefined,\n } satisfies MessageNotes;\n actions.setMessageNotes(newNotes);\n sendMessageWithRetries(msg)\n .catch(handleError ?? defaultHandleApiError)\n .finally(() => {\n onSend?.(msg)\n })\n },\n [notes, actions, sendMessageWithRetries, handleError, defaultHandleApiError, onSend]\n );\n\n const classes = useComposedCssClasses(defaultClassnames, customCssClasses);\n\n return (\n <div className={classes.container}>\n {suggestions.map((suggestion, index) => (\n <button\n key={index}\n className={classes.suggestion}\n // eslint-disable-next-line react-perf/jsx-no-new-function-as-prop\n onClick={() => sendMsg(suggestion)}\n >\n {suggestion}\n </button>\n ))}\n </div>\n );\n};\n"],"names":["withStylelessCssClasses","useChatActions","useChatState","useDefaultHandleApiError","useSendMessageWithRetries","useCallback","useComposedCssClasses","React"],"mappings":";;;;;;;;;;;;;AAyCA,MAAM,iBAAiB,GAAgCA,+CAAuB,CAC5E,aAAa,EACb;AACE,IAAA,SAAS,EAAE,kDAAkD;AAC7D,IAAA,UAAU,EACR,sIAAsI;AACzI,CAAA,CACF,CAAC;AAEF;;;;;AAKG;MACU,kBAAkB,GAAsC,CAAC,EACpE,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,MAAM,GAAG,KAAK,EACd,MAAM,EACN,OAAO,GACR,KAAI;AACH,IAAA,MAAM,OAAO,GAAGC,gCAAc,EAAE,CAAC;AACjC,IAAA,MAAM,KAAK,GAAGC,8BAAY,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;AAChE,IAAA,MAAM,qBAAqB,GAAGC,iDAAwB,EAAE,CAAC;IACzD,MAAM,sBAAsB,GAAIC,mDAAyB,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;AAC7E,IAAA,MAAM,OAAO,GAAGC,iBAAW,CACzB,CAAC,GAAW,KAAI;AACd,QAAA,MAAM,QAAQ,GAAG;AACf,YAAA,IAAI,KAAK,IAAI,EAAE,CAAC;AAChB,YAAA,gBAAgB,EAAE,SAAS;SACL,CAAC;AACzB,QAAA,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAClC,sBAAsB,CAAC,GAAG,CAAC;AACxB,aAAA,KAAK,CAAC,WAAW,IAAI,qBAAqB,CAAC;aAC3C,OAAO,CAAC,MAAK;AACZ,YAAA,MAAM,GAAG,GAAG,CAAC,CAAA;AACf,SAAC,CAAC,CAAA;AACN,KAAC,EACD,CAAC,KAAK,EAAE,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,CAAC,CACrF,CAAC;IAEF,MAAM,OAAO,GAAGC,2CAAqB,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;AAE3E,IAAA,QACEC,sBAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,OAAO,CAAC,SAAS,EAAA,EAC9B,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,KAAK,MACjCA,sBACE,CAAA,aAAA,CAAA,QAAA,EAAA,EAAA,GAAG,EAAE,KAAK,EACV,SAAS,EAAE,OAAO,CAAC,UAAU;;AAE7B,QAAA,OAAO,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,EAAA,EAEjC,UAAU,CACJ,CACV,CAAC,CACE,EACN;AACJ;;;;"}
1
+ {"version":3,"file":"MessageSuggestions.js","sources":["../../../../src/components/MessageSuggestions.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport {\n MessageNotes,\n useChatActions,\n useChatState,\n} from \"@yext/chat-headless-react\";\nimport { useDefaultHandleApiError } from \"../hooks/useDefaultHandleApiError\";\nimport { withStylelessCssClasses } from \"../utils/withStylelessCssClasses\";\nimport { useComposedCssClasses } from \"../hooks\";\nimport { useSendMessageWithRetries } from \"../hooks/useSendMessageWithRetries\";\n\n/**\n * The CSS class interface for the MessageSuggestion component.\n *\n * @public\n */\nexport interface MessageSuggestionCssClasses {\n container?: string;\n suggestion?: string;\n}\n\n/**\n * The props for the MessageSuggestions component.\n *\n * @public\n */\nexport interface MessageSuggestionsProps {\n /** List of clickable message suggestions to render. */\n suggestions: string[];\n /** {@inheritdoc ChatInputProps.handleError} */\n handleError?: (e: unknown) => void;\n /** CSS classes for customizing the component styling. */\n customCssClasses?: MessageSuggestionCssClasses;\n /** {@inheritdoc ChatInputProps.stream} */\n stream?: boolean;\n /** {@inheritdoc ChatInputProps.onSend} */\n onSend?: (message: string) => void;\n /** {@inheritdoc ChatInputProps.onRetry} */\n onRetry?: (e: unknown) => void;\n}\n\nconst defaultClassnames: MessageSuggestionCssClasses = withStylelessCssClasses(\n \"Suggestions\",\n {\n container: \"flex gap-2 mb-4 w-full overflow-x-auto flex-wrap\",\n suggestion:\n \"hover:cursor-pointer px-2 py-1 bg-white hover:bg-slate-300 rounded-full text-sm text-blue-700 border border-blue-700 hover:underline\",\n }\n);\n\n/**\n * A component that displays a list of suggested messages\n * to the user, which they can click to send the message to the bot.\n *\n * @internal\n */\nexport const MessageSuggestions: React.FC<MessageSuggestionsProps> = ({\n handleError,\n suggestions,\n customCssClasses,\n stream = false,\n onSend,\n onRetry,\n}) => {\n const actions = useChatActions();\n const notes = useChatState((state) => state.conversation.notes);\n const defaultHandleApiError = useDefaultHandleApiError();\n const sendMessageWithRetries = useSendMessageWithRetries(stream, 1, onRetry);\n const sendMsg = useCallback(\n (msg: string) => {\n const newNotes = {\n ...(notes || {}),\n suggestedReplies: undefined,\n } satisfies MessageNotes;\n actions.setMessageNotes(newNotes);\n sendMessageWithRetries(msg)\n .catch(handleError ?? defaultHandleApiError)\n .finally(() => {\n onSend?.(msg);\n });\n },\n [\n notes,\n actions,\n sendMessageWithRetries,\n handleError,\n defaultHandleApiError,\n onSend,\n ]\n );\n\n const classes = useComposedCssClasses(defaultClassnames, customCssClasses);\n\n return (\n <div className={classes.container}>\n {suggestions.map((suggestion, index) => (\n <button\n key={index}\n className={classes.suggestion}\n // eslint-disable-next-line react-perf/jsx-no-new-function-as-prop\n onClick={() => sendMsg(suggestion)}\n >\n {suggestion}\n </button>\n ))}\n </div>\n );\n};\n"],"names":["withStylelessCssClasses","useChatActions","useChatState","useDefaultHandleApiError","useSendMessageWithRetries","useCallback","useComposedCssClasses","React"],"mappings":";;;;;;;;;;;;;AAyCA,MAAM,iBAAiB,GAAgCA,+CAAuB,CAC5E,aAAa,EACb;AACE,IAAA,SAAS,EAAE,kDAAkD;AAC7D,IAAA,UAAU,EACR,sIAAsI;AACzI,CAAA,CACF,CAAC;AAEF;;;;;AAKG;MACU,kBAAkB,GAAsC,CAAC,EACpE,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,MAAM,GAAG,KAAK,EACd,MAAM,EACN,OAAO,GACR,KAAI;AACH,IAAA,MAAM,OAAO,GAAGC,gCAAc,EAAE,CAAC;AACjC,IAAA,MAAM,KAAK,GAAGC,8BAAY,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;AAChE,IAAA,MAAM,qBAAqB,GAAGC,iDAAwB,EAAE,CAAC;IACzD,MAAM,sBAAsB,GAAGC,mDAAyB,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;AAC7E,IAAA,MAAM,OAAO,GAAGC,iBAAW,CACzB,CAAC,GAAW,KAAI;AACd,QAAA,MAAM,QAAQ,GAAG;AACf,YAAA,IAAI,KAAK,IAAI,EAAE,CAAC;AAChB,YAAA,gBAAgB,EAAE,SAAS;SACL,CAAC;AACzB,QAAA,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAClC,sBAAsB,CAAC,GAAG,CAAC;AACxB,aAAA,KAAK,CAAC,WAAW,IAAI,qBAAqB,CAAC;aAC3C,OAAO,CAAC,MAAK;AACZ,YAAA,MAAM,GAAG,GAAG,CAAC,CAAC;AAChB,SAAC,CAAC,CAAC;AACP,KAAC,EACD;QACE,KAAK;QACL,OAAO;QACP,sBAAsB;QACtB,WAAW;QACX,qBAAqB;QACrB,MAAM;AACP,KAAA,CACF,CAAC;IAEF,MAAM,OAAO,GAAGC,2CAAqB,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;AAE3E,IAAA,QACEC,sBAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,OAAO,CAAC,SAAS,EAAA,EAC9B,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,KAAK,MACjCA,sBACE,CAAA,aAAA,CAAA,QAAA,EAAA,EAAA,GAAG,EAAE,KAAK,EACV,SAAS,EAAE,OAAO,CAAC,UAAU;;AAE7B,QAAA,OAAO,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,EAAA,EAEjC,UAAU,CACJ,CACV,CAAC,CACE,EACN;AACJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"useFetchInitialMessage.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useFetchInitialMessage.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,EAClC,MAAM,UAAQ,EACd,eAAe,UAAO,QAgBvB"}
1
+ {"version":3,"file":"useFetchInitialMessage.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useFetchInitialMessage.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,EAClC,MAAM,UAAQ,EACd,eAAe,UAAO,QAwBvB"}
@@ -26,7 +26,15 @@ function useFetchInitialMessage(handleError, stream = false, customCondition = t
26
26
  }
27
27
  const res = stream ? chat.streamNextMessage() : chat.getNextMessage();
28
28
  res.catch((e) => (handleError ? handleError(e) : defaultHandleApiError(e)));
29
- }, [chat, stream, handleError, defaultHandleApiError, canSendMessage, customCondition, messages.length]);
29
+ }, [
30
+ chat,
31
+ stream,
32
+ handleError,
33
+ defaultHandleApiError,
34
+ canSendMessage,
35
+ customCondition,
36
+ messages.length,
37
+ ]);
30
38
  }
31
39
 
32
40
  exports.useFetchInitialMessage = useFetchInitialMessage;
@@ -1 +1 @@
1
- {"version":3,"file":"useFetchInitialMessage.js","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":["useChatActions","useDefaultHandleApiError","useChatState","useEffect"],"mappings":";;;;;;AAIA;;;;;;;;;;AAUG;AACG,SAAU,sBAAsB,CACpC,WAAkC,EAClC,MAAM,GAAG,KAAK,EACd,eAAe,GAAG,IAAI,EAAA;AAEtB,IAAA,MAAM,IAAI,GAAGA,gCAAc,EAAE,CAAC;AAC9B,IAAA,MAAM,qBAAqB,GAAGC,iDAAwB,EAAE,CAAC;AACzD,IAAA,MAAM,QAAQ,GAAGC,8BAAY,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;AACtE,IAAA,MAAM,cAAc,GAAGA,8BAAY,CACjC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,cAAc,CAC7C,CAAC;IAEFC,eAAS,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.js","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":["useChatActions","useDefaultHandleApiError","useChatState","useEffect"],"mappings":";;;;;;AAIA;;;;;;;;;;AAUG;AACG,SAAU,sBAAsB,CACpC,WAAkC,EAClC,MAAM,GAAG,KAAK,EACd,eAAe,GAAG,IAAI,EAAA;AAEtB,IAAA,MAAM,IAAI,GAAGA,gCAAc,EAAE,CAAC;AAC9B,IAAA,MAAM,qBAAqB,GAAGC,iDAAwB,EAAE,CAAC;AACzD,IAAA,MAAM,QAAQ,GAAGC,8BAAY,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;AACtE,IAAA,MAAM,cAAc,GAAGA,8BAAY,CACjC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,cAAc,CAC7C,CAAC;IAEFC,eAAS,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"}
@@ -25,7 +25,9 @@ function useSendMessageWithRetries(stream = false, maxRetries = 0, onRetry) {
25
25
  let text = input;
26
26
  for (let numRetries = 0; numRetries <= maxRetries; numRetries++) {
27
27
  if (numRetries > 0 && !!err) {
28
- if (err instanceof chatHeadlessReact.ApiError && !!err.statusCode && err.statusCode >= 500) {
28
+ if (err instanceof chatHeadlessReact.ApiError &&
29
+ !!err.statusCode &&
30
+ err.statusCode >= 500) {
29
31
  onRetry?.(err);
30
32
  // avoid re-adding user message to conversation history on retry
31
33
  text = "";
@@ -1 +1 @@
1
- {"version":3,"file":"useSendMessageWithRetries.js","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":["useChatActions","useCallback","ApiError"],"mappings":";;;;;AAGA;;;;;;;;;;;;;;AAcG;AACG,SAAU,yBAAyB,CACvC,MAAM,GAAG,KAAK,EACd,UAAU,GAAG,CAAC,EACd,OAA8B,EAAA;AAE9B,IAAA,MAAM,IAAI,GAAGA,gCAAc,EAAE,CAAA;AAC7B,IAAA,OAAOC,iBAAW,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,YAAYC,0BAAQ,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.js","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":["useChatActions","useCallback","ApiError"],"mappings":";;;;;AAGA;;;;;;;;;;;;;;AAcG;AACG,SAAU,yBAAyB,CACvC,MAAM,GAAG,KAAK,EACd,UAAU,GAAG,CAAC,EACd,OAA8B,EAAA;AAE9B,IAAA,MAAM,IAAI,GAAGA,gCAAc,EAAE,CAAC;AAC9B,IAAA,OAAOC,iBAAW,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,YAAYC,0BAAQ;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;;;;"}
@@ -164,6 +164,10 @@ export declare interface ChatPanelProps extends Omit<MessageBubbleProps, "custom
164
164
  * can click on instead of typing their own.
165
165
  */
166
166
  messageSuggestions?: string[];
167
+ /** Link target open behavior on click.
168
+ * Defaults to "_blank".
169
+ */
170
+ linkTarget?: string;
167
171
  /** A callback which is called when user clicks a link. */
168
172
  onLinkClick?: (href?: string) => void;
169
173
  /**
@@ -275,7 +279,7 @@ export declare interface InitialMessagePopUpCssClasses {
275
279
  *
276
280
  * @param props - {@link MessageBubbleProps}
277
281
  */
278
- export declare function MessageBubble({ message, showFeedbackButtons, showTimestamp, customCssClasses, formatTimestamp, onLinkClick, }: MessageBubbleProps): React_2.JSX.Element;
282
+ export declare function MessageBubble({ message, showFeedbackButtons, showTimestamp, customCssClasses, formatTimestamp, linkTarget, onLinkClick, }: MessageBubbleProps): React_2.JSX.Element;
279
283
 
280
284
  /**
281
285
  * The CSS class interface for the {@link MessageBubble} component.
@@ -325,6 +329,8 @@ export declare interface MessageBubbleProps {
325
329
  formatTimestamp?: (timestamp: string) => string;
326
330
  /** CSS classes for customizing the component styling. */
327
331
  customCssClasses?: MessageBubbleCssClasses;
332
+ /** Link target open behavior on click. */
333
+ linkTarget?: string;
328
334
  /** A callback which is called when user clicks a link. */
329
335
  onLinkClick?: (href?: string) => void;
330
336
  }
@@ -1,4 +1,4 @@
1
- var version = "0.10.1";
1
+ var version = "0.11.0";
2
2
 
3
3
  export { version };
4
4
  //# sourceMappingURL=package.json.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatInput.d.ts","sourceRoot":"","sources":["../../../../src/components/ChatInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AASrD;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAaD;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,uCAAuC;IACvC,cAAc,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IAC7B,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,mBAAmB,CAAC;IACvC,4DAA4D;IAC5D,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CAC/B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,EACxB,WAAiC,EACjC,MAAc,EACd,cAAsB,EACtB,WAAW,EACX,cAA8B,EAC9B,gBAAgB,EAChB,MAAM,EACN,OAAO,GACR,EAAE,cAAc,qBA8DhB"}
1
+ {"version":3,"file":"ChatInput.d.ts","sourceRoot":"","sources":["../../../../src/components/ChatInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AASrD;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAaD;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,uCAAuC;IACvC,cAAc,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IAC7B,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,mBAAmB,CAAC;IACvC,4DAA4D;IAC5D,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,EACxB,WAAiC,EACjC,MAAc,EACd,cAAsB,EACtB,WAAW,EACX,cAA8B,EAC9B,gBAAgB,EAChB,MAAM,EACN,OAAO,GACR,EAAE,cAAc,qBAuEhB"}
@@ -36,9 +36,16 @@ function ChatInput({ placeholder = "Type a message...", stream = false, inputAut
36
36
  .finally(() => {
37
37
  onSend?.(input);
38
38
  });
39
- }, [sendMessageWithRetries, input, handleError, defaultHandleApiError, onSend]);
39
+ }, [
40
+ sendMessageWithRetries,
41
+ input,
42
+ handleError,
43
+ defaultHandleApiError,
44
+ onSend,
45
+ ]);
40
46
  const handleKeyDown = useCallback((e) => {
41
- if (!e.shiftKey && e.key === "Enter" &&
47
+ if (!e.shiftKey &&
48
+ e.key === "Enter" &&
42
49
  // The Japanese Keyboard uses "Enter" key to convert from Hiragana to Kanji.
43
50
  // "isComposing" is a flag that indicates whether the event is part of an ongoing composition session.
44
51
  // Safari does not support `isComposing` with the Japanese IME event,
@@ -1 +1 @@
1
- {"version":3,"file":"ChatInput.mjs","sources":["../../../../src/components/ChatInput.tsx"],"sourcesContent":["import React, { useCallback, useState } from \"react\";\nimport { useChatState } from \"@yext/chat-headless-react\";\nimport { ArrowIcon } from \"../icons/Arrow\";\nimport { useComposedCssClasses } from \"../hooks\";\nimport TextareaAutosize from \"react-textarea-autosize\";\nimport { useDefaultHandleApiError } from \"../hooks/useDefaultHandleApiError\";\nimport { withStylelessCssClasses } from \"../utils/withStylelessCssClasses\";\nimport { useSendMessageWithRetries } from \"../hooks/useSendMessageWithRetries\";\n\n/**\n * The CSS class interface for the {@link ChatInput} component.\n *\n * @public\n */\nexport interface ChatInputCssClasses {\n container?: string;\n textArea?: string;\n sendButton?: string;\n}\n\nconst builtInCssClasses: ChatInputCssClasses = withStylelessCssClasses(\n \"Input\",\n {\n container: \"w-full h-fit flex flex-row relative @container\",\n textArea:\n \"w-full p-4 pr-12 border border-slate-300 rounded-3xl resize-none text-[13px] @[480px]:text-base placeholder:text-[13px] placeholder:@[480px]:text-base text-slate-900\",\n sendButton:\n \"rounded-full p-1.5 w-8 h-8 stroke-2 text-white bg-blue-600 disabled:bg-slate-200 hover:bg-blue-800 active:scale-90 transition-all absolute right-4 bottom-2.5 @[480px]:bottom-3.5\",\n }\n);\n\n/**\n * The props for the {@link ChatInput} component.\n *\n * @public\n */\nexport interface ChatInputProps {\n /**\n * The input's placeholder text when no text has been entered by the user.\n * Defaults to \"Type a message...\".\n */\n placeholder?: string;\n /**\n * Enable streaming behavior by making a request to Chat Streaming API.\n * This feature is experimental, and is subject to change.\n * Defaults to false.\n */\n stream?: boolean;\n /** Enable auto focus for the input box. Defaults to false. */\n inputAutoFocus?: boolean;\n /**\n * A function which is called when an error occurs from Chat API while processing the user's message.\n * By default, the error is logged to the console and an error message is added to state.\n */\n handleError?: (e: unknown) => void;\n /** Custom icon for the send button. */\n sendButtonIcon?: JSX.Element;\n /** CSS classes for customizing the component styling. */\n customCssClasses?: ChatInputCssClasses;\n /** A callback which is called when user sends a message. */\n onSend?: (message: string) => void;\n /**\n * A function which is called when a retryable error occurs from\n * Chat API while processing the user's message.\n */\n onRetry?: (e: unknown) => void\n}\n\n/**\n * A component that allows user to input message and send to Chat API.\n *\n * @remarks\n * Pressing \"Enter\" key will send the current message.\n * To add a newline, press \"Shift\" and \"Enter\".\n *\n * @public\n *\n * @param props - {@link ChatInputProps}\n */\nexport function ChatInput({\n placeholder = \"Type a message...\",\n stream = false,\n inputAutoFocus = false,\n handleError,\n sendButtonIcon = <ArrowIcon />,\n customCssClasses,\n onSend,\n onRetry,\n}: ChatInputProps) {\n const [input, setInput] = useState(\"\");\n const canSendMessage = useChatState(\n (state) => state.conversation.canSendMessage\n );\n const defaultHandleApiError = useDefaultHandleApiError();\n const sendMessageWithRetries = useSendMessageWithRetries(stream, 1, onRetry)\n const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);\n\n const sendMessage = useCallback(async () => {\n setInput(\"\");\n sendMessageWithRetries(input)\n .catch(handleError ?? defaultHandleApiError)\n .finally(() => {\n onSend?.(input)\n })\n }, [sendMessageWithRetries, input, handleError, defaultHandleApiError, onSend]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (!e.shiftKey && e.key === \"Enter\" && \n // The Japanese Keyboard uses \"Enter\" key to convert from Hiragana to Kanji.\n // \"isComposing\" is a flag that indicates whether the event is part of an ongoing composition session.\n // Safari does not support `isComposing` with the Japanese IME event,\n // so we have to additionally check for the keyCode to handle that edge case.\n !(e.nativeEvent.isComposing || e.keyCode === 229)) {\n e.preventDefault();\n if (canSendMessage && input.trim().length !== 0) {\n sendMessage();\n }\n }\n },\n [sendMessage, canSendMessage, input]\n );\n\n const onInputChange = useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setInput(e.target.value);\n },\n []\n );\n\n return (\n <div className={cssClasses.container}>\n <TextareaAutosize\n autoFocus={inputAutoFocus}\n onKeyDown={handleKeyDown}\n value={input}\n onChange={onInputChange}\n className={cssClasses.textArea}\n placeholder={placeholder}\n />\n <button\n aria-label=\"Send Message\"\n disabled={!canSendMessage || input.trim().length === 0}\n onClick={sendMessage}\n className={cssClasses.sendButton}\n >\n {sendButtonIcon}\n </button>\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AAoBA,MAAM,iBAAiB,GAAwB,uBAAuB,CACpE,OAAO,EACP;AACE,IAAA,SAAS,EAAE,gDAAgD;AAC3D,IAAA,QAAQ,EACN,uKAAuK;AACzK,IAAA,UAAU,EACR,mLAAmL;AACtL,CAAA,CACF,CAAC;AAuCF;;;;;;;;;;AAUG;AACa,SAAA,SAAS,CAAC,EACxB,WAAW,GAAG,mBAAmB,EACjC,MAAM,GAAG,KAAK,EACd,cAAc,GAAG,KAAK,EACtB,WAAW,EACX,cAAc,GAAG,KAAC,CAAA,aAAA,CAAA,SAAS,EAAG,IAAA,CAAA,EAC9B,gBAAgB,EAChB,MAAM,EACN,OAAO,GACQ,EAAA;IACf,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;AACvC,IAAA,MAAM,cAAc,GAAG,YAAY,CACjC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,cAAc,CAC7C,CAAC;AACF,IAAA,MAAM,qBAAqB,GAAG,wBAAwB,EAAE,CAAC;IACzD,MAAM,sBAAsB,GAAI,yBAAyB,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;IAC7E,MAAM,UAAU,GAAG,qBAAqB,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;AAE9E,IAAA,MAAM,WAAW,GAAG,WAAW,CAAC,YAAW;QACzC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACb,sBAAsB,CAAC,KAAK,CAAC;AAC1B,aAAA,KAAK,CAAC,WAAW,IAAI,qBAAqB,CAAC;aAC3C,OAAO,CAAC,MAAK;AACZ,YAAA,MAAM,GAAG,KAAK,CAAC,CAAA;AACjB,SAAC,CAAC,CAAA;AACN,KAAC,EAAE,CAAC,sBAAsB,EAAE,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,CAAC,CAAC,CAAC;AAEhF,IAAA,MAAM,aAAa,GAAG,WAAW,CAC/B,CAAC,CAA2C,KAAI;QAC9C,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO;;;;;AAKlC,YAAA,EAAE,CAAC,CAAC,WAAW,CAAC,WAAW,IAAI,CAAC,CAAC,OAAO,KAAK,GAAG,CAAC,EAAE;YACnD,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,IAAI,cAAc,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE;AAC/C,gBAAA,WAAW,EAAE,CAAC;AACf,aAAA;AACF,SAAA;KACF,EACD,CAAC,WAAW,EAAE,cAAc,EAAE,KAAK,CAAC,CACrC,CAAC;AAEF,IAAA,MAAM,aAAa,GAAG,WAAW,CAC/B,CAAC,CAAyC,KAAI;AAC5C,QAAA,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;KAC1B,EACD,EAAE,CACH,CAAC;AAEF,IAAA,QACE,KAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,UAAU,CAAC,SAAS,EAAA;QAClC,KAAC,CAAA,aAAA,CAAA,gBAAgB,EACf,EAAA,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,aAAa,EACxB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,aAAa,EACvB,SAAS,EAAE,UAAU,CAAC,QAAQ,EAC9B,WAAW,EAAE,WAAW,EACxB,CAAA;AACF,QAAA,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAA,YAAA,EACa,cAAc,EACzB,QAAQ,EAAE,CAAC,cAAc,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EACtD,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,UAAU,CAAC,UAAU,EAE/B,EAAA,cAAc,CACR,CACL,EACN;AACJ;;;;"}
1
+ {"version":3,"file":"ChatInput.mjs","sources":["../../../../src/components/ChatInput.tsx"],"sourcesContent":["import React, { useCallback, useState } from \"react\";\nimport { useChatState } from \"@yext/chat-headless-react\";\nimport { ArrowIcon } from \"../icons/Arrow\";\nimport { useComposedCssClasses } from \"../hooks\";\nimport TextareaAutosize from \"react-textarea-autosize\";\nimport { useDefaultHandleApiError } from \"../hooks/useDefaultHandleApiError\";\nimport { withStylelessCssClasses } from \"../utils/withStylelessCssClasses\";\nimport { useSendMessageWithRetries } from \"../hooks/useSendMessageWithRetries\";\n\n/**\n * The CSS class interface for the {@link ChatInput} component.\n *\n * @public\n */\nexport interface ChatInputCssClasses {\n container?: string;\n textArea?: string;\n sendButton?: string;\n}\n\nconst builtInCssClasses: ChatInputCssClasses = withStylelessCssClasses(\n \"Input\",\n {\n container: \"w-full h-fit flex flex-row relative @container\",\n textArea:\n \"w-full p-4 pr-12 border border-slate-300 rounded-3xl resize-none text-[13px] @[480px]:text-base placeholder:text-[13px] placeholder:@[480px]:text-base text-slate-900\",\n sendButton:\n \"rounded-full p-1.5 w-8 h-8 stroke-2 text-white bg-blue-600 disabled:bg-slate-200 hover:bg-blue-800 active:scale-90 transition-all absolute right-4 bottom-2.5 @[480px]:bottom-3.5\",\n }\n);\n\n/**\n * The props for the {@link ChatInput} component.\n *\n * @public\n */\nexport interface ChatInputProps {\n /**\n * The input's placeholder text when no text has been entered by the user.\n * Defaults to \"Type a message...\".\n */\n placeholder?: string;\n /**\n * Enable streaming behavior by making a request to Chat Streaming API.\n * This feature is experimental, and is subject to change.\n * Defaults to false.\n */\n stream?: boolean;\n /** Enable auto focus for the input box. Defaults to false. */\n inputAutoFocus?: boolean;\n /**\n * A function which is called when an error occurs from Chat API while processing the user's message.\n * By default, the error is logged to the console and an error message is added to state.\n */\n handleError?: (e: unknown) => void;\n /** Custom icon for the send button. */\n sendButtonIcon?: JSX.Element;\n /** CSS classes for customizing the component styling. */\n customCssClasses?: ChatInputCssClasses;\n /** A callback which is called when user sends a message. */\n onSend?: (message: string) => void;\n /**\n * A function which is called when a retryable error occurs from\n * Chat API while processing the user's message.\n */\n onRetry?: (e: unknown) => void;\n}\n\n/**\n * A component that allows user to input message and send to Chat API.\n *\n * @remarks\n * Pressing \"Enter\" key will send the current message.\n * To add a newline, press \"Shift\" and \"Enter\".\n *\n * @public\n *\n * @param props - {@link ChatInputProps}\n */\nexport function ChatInput({\n placeholder = \"Type a message...\",\n stream = false,\n inputAutoFocus = false,\n handleError,\n sendButtonIcon = <ArrowIcon />,\n customCssClasses,\n onSend,\n onRetry,\n}: ChatInputProps) {\n const [input, setInput] = useState(\"\");\n const canSendMessage = useChatState(\n (state) => state.conversation.canSendMessage\n );\n const defaultHandleApiError = useDefaultHandleApiError();\n const sendMessageWithRetries = useSendMessageWithRetries(stream, 1, onRetry);\n const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);\n\n const sendMessage = useCallback(async () => {\n setInput(\"\");\n sendMessageWithRetries(input)\n .catch(handleError ?? defaultHandleApiError)\n .finally(() => {\n onSend?.(input);\n });\n }, [\n sendMessageWithRetries,\n input,\n handleError,\n defaultHandleApiError,\n onSend,\n ]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (\n !e.shiftKey &&\n e.key === \"Enter\" &&\n // The Japanese Keyboard uses \"Enter\" key to convert from Hiragana to Kanji.\n // \"isComposing\" is a flag that indicates whether the event is part of an ongoing composition session.\n // Safari does not support `isComposing` with the Japanese IME event,\n // so we have to additionally check for the keyCode to handle that edge case.\n !(e.nativeEvent.isComposing || e.keyCode === 229)\n ) {\n e.preventDefault();\n if (canSendMessage && input.trim().length !== 0) {\n sendMessage();\n }\n }\n },\n [sendMessage, canSendMessage, input]\n );\n\n const onInputChange = useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setInput(e.target.value);\n },\n []\n );\n\n return (\n <div className={cssClasses.container}>\n <TextareaAutosize\n autoFocus={inputAutoFocus}\n onKeyDown={handleKeyDown}\n value={input}\n onChange={onInputChange}\n className={cssClasses.textArea}\n placeholder={placeholder}\n />\n <button\n aria-label=\"Send Message\"\n disabled={!canSendMessage || input.trim().length === 0}\n onClick={sendMessage}\n className={cssClasses.sendButton}\n >\n {sendButtonIcon}\n </button>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -36,6 +36,10 @@ export interface ChatPanelProps extends Omit<MessageBubbleProps, "customCssClass
36
36
  * can click on instead of typing their own.
37
37
  */
38
38
  messageSuggestions?: string[];
39
+ /** Link target open behavior on click.
40
+ * Defaults to "_blank".
41
+ */
42
+ linkTarget?: string;
39
43
  /** A callback which is called when user clicks a link. */
40
44
  onLinkClick?: (href?: string) => void;
41
45
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ChatPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/ChatPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,SAAS,EAMV,MAAM,OAAO,CAAC;AAEf,OAAO,EAEL,uBAAuB,EACvB,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAa,mBAAmB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAM7E,OAAO,EACL,2BAA2B,EAE5B,MAAM,sBAAsB,CAAC;AAG9B;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD,wBAAwB,CAAC,EAAE,2BAA2B,CAAC;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgBD;;;;GAIG;AACH,MAAM,WAAW,cACf,SAAQ,IAAI,CAAC,kBAAkB,EAAE,kBAAkB,GAAG,SAAS,CAAC,EAC9D,IAAI,CAAC,cAAc,EAAE,kBAAkB,CAAC;IAC1C,kDAAkD;IAClD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,gBAAgB,CAAC,EAAE,mBAAmB,CAAC;IACvC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,0DAA0D;IAC1D,WAAW,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,qBAwI9C"}
1
+ {"version":3,"file":"ChatPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/ChatPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,SAAS,EAMV,MAAM,OAAO,CAAC;AAEf,OAAO,EAEL,uBAAuB,EACvB,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAa,mBAAmB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAM7E,OAAO,EACL,2BAA2B,EAE5B,MAAM,sBAAsB,CAAC;AAG9B;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;IAClD,wBAAwB,CAAC,EAAE,2BAA2B,CAAC;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgBD;;;;GAIG;AACH,MAAM,WAAW,cACf,SAAQ,IAAI,CAAC,kBAAkB,EAAE,kBAAkB,GAAG,SAAS,CAAC,EAC9D,IAAI,CAAC,cAAc,EAAE,kBAAkB,CAAC;IAC1C,kDAAkD;IAClD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,gBAAgB,CAAC,EAAE,mBAAmB,CAAC;IACvC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,qBAuJ9C"}
@@ -13,10 +13,10 @@ import { Markdown } from './Markdown.mjs';
13
13
  const builtInCssClasses = withStylelessCssClasses("Panel", {
14
14
  container: "h-full w-full flex flex-col relative shadow-2xl bg-white",
15
15
  messagesScrollContainer: "flex flex-col mt-auto overflow-hidden",
16
- messagesContainer: "flex flex-col gap-y-1 px-4 overflow-auto",
16
+ messagesContainer: "flex flex-col gap-y-1 px-4 overflow-auto [&>*:first-child]:mt-3",
17
17
  inputContainer: "w-full p-4",
18
18
  messageBubbleCssClasses: {
19
- topContainer: "first:mt-4",
19
+ topContainer: "mt-1",
20
20
  },
21
21
  footer: "text-center text-slate-400 rounded-b-3xl px-4 pb-4 text-[12px]",
22
22
  });
@@ -30,7 +30,7 @@ const builtInCssClasses = withStylelessCssClasses("Panel", {
30
30
  * @param props - {@link ChatPanelProps}
31
31
  */
32
32
  function ChatPanel(props) {
33
- const { header, footer, customCssClasses, stream, handleError, messageSuggestions, onLinkClick, onSend: onSendProp, onRetry: onRetryProp, retryText = "Error occurred. Retrying", } = props;
33
+ const { header, footer, customCssClasses, stream, handleError, messageSuggestions, linkTarget = "_blank", onLinkClick, onSend: onSendProp, onRetry: onRetryProp, retryText = "Error occurred. Retrying", } = props;
34
34
  const messages = useChatState((state) => state.conversation.messages);
35
35
  const loading = useChatState((state) => state.conversation.isLoading);
36
36
  const suggestedReplies = useChatState((state) => state.conversation.notes?.suggestedReplies);
@@ -92,14 +92,14 @@ function ChatPanel(props) {
92
92
  React.createElement("div", { className: cssClasses.messagesScrollContainer },
93
93
  React.createElement("div", { ref: messagesContainer, className: cssClasses.messagesContainer },
94
94
  messages.map((message, index) => (React.createElement("div", { key: index, ref: setMessagesRef(index) },
95
- React.createElement(MessageBubble, { ...props, customCssClasses: cssClasses.messageBubbleCssClasses, message: message, onLinkClick: onLinkClick })))),
96
- loading && React.createElement("div", { className: "flex" },
95
+ React.createElement(MessageBubble, { ...props, customCssClasses: cssClasses.messageBubbleCssClasses, message: message, linkTarget: linkTarget, onLinkClick: onLinkClick })))),
96
+ loading && (React.createElement("div", { className: "flex" },
97
97
  React.createElement(LoadingDots, null),
98
- retry && React.createElement("p", { className: "text-slate-500 text-[13px] font-bold" }, retryText)))),
98
+ retry && (React.createElement("p", { className: "text-slate-500 text-[13px] font-bold" }, retryText)))))),
99
99
  React.createElement("div", { className: cssClasses.inputContainer },
100
100
  suggestions && (React.createElement(MessageSuggestions, { stream: stream, onSend: onSend, onRetry: onRetry, handleError: handleError, suggestions: suggestions, customCssClasses: cssClasses.messageSuggestionClasses })),
101
101
  React.createElement(ChatInput, { ...props, onSend: onSend, onRetry: onRetry, customCssClasses: cssClasses.inputCssClasses })),
102
- footer && (React.createElement(Markdown, { content: footer, linkClickEvent: "WEBSITE", onLinkClick: onLinkClick, customCssClasses: footerCssClasses })))));
102
+ footer && (React.createElement(Markdown, { content: footer, linkClickEvent: "WEBSITE", linkTarget: linkTarget, onLinkClick: onLinkClick, customCssClasses: footerCssClasses })))));
103
103
  }
104
104
 
105
105
  export { ChatPanel };
@@ -1 +1 @@
1
- {"version":3,"file":"ChatPanel.mjs","sources":["../../../../src/components/ChatPanel.tsx"],"sourcesContent":["import React, {\n ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useChatState } from \"@yext/chat-headless-react\";\nimport {\n MessageBubble,\n MessageBubbleCssClasses,\n MessageBubbleProps,\n} from \"./MessageBubble\";\nimport { ChatInput, ChatInputCssClasses, ChatInputProps } from \"./ChatInput\";\nimport { LoadingDots } from \"./LoadingDots\";\nimport { useComposedCssClasses } from \"../hooks\";\nimport { withStylelessCssClasses } from \"../utils/withStylelessCssClasses\";\nimport { useReportAnalyticsEvent } from \"../hooks/useReportAnalyticsEvent\";\nimport { useFetchInitialMessage } from \"../hooks/useFetchInitialMessage\";\nimport {\n MessageSuggestionCssClasses,\n MessageSuggestions,\n} from \"./MessageSuggestions\";\nimport { Markdown, MarkdownCssClasses } from \"./Markdown\";\n\n/**\n * The CSS class interface for the {@link ChatPanel} component.\n *\n * @public\n */\nexport interface ChatPanelCssClasses {\n container?: string;\n messagesContainer?: string;\n messagesScrollContainer?: string;\n inputContainer?: string;\n inputCssClasses?: ChatInputCssClasses;\n messageBubbleCssClasses?: MessageBubbleCssClasses;\n messageSuggestionClasses?: MessageSuggestionCssClasses;\n footer?: string;\n}\n\nconst builtInCssClasses: ChatPanelCssClasses = withStylelessCssClasses(\n \"Panel\",\n {\n container: \"h-full w-full flex flex-col relative shadow-2xl bg-white\",\n messagesScrollContainer: \"flex flex-col mt-auto overflow-hidden\",\n messagesContainer: \"flex flex-col gap-y-1 px-4 overflow-auto\",\n inputContainer: \"w-full p-4\",\n messageBubbleCssClasses: {\n topContainer: \"first:mt-4\",\n },\n footer: \"text-center text-slate-400 rounded-b-3xl px-4 pb-4 text-[12px]\",\n }\n);\n\n/**\n * The props for the {@link ChatPanel} component.\n *\n * @public\n */\nexport interface ChatPanelProps\n extends Omit<MessageBubbleProps, \"customCssClasses\" | \"message\">,\n Omit<ChatInputProps, \"customCssClasses\"> {\n /** A header to render at the top of the panel. */\n header?: ReactNode;\n /** A footer markdown string to render at the bottom of the panel. */\n footer?: string;\n /**\n * CSS classes for customizing the component styling.\n */\n customCssClasses?: ChatPanelCssClasses;\n /**\n * A set of pre-written initial messages that the user\n * can click on instead of typing their own.\n */\n messageSuggestions?: string[];\n /** A callback which is called when user clicks a link. */\n onLinkClick?: (href?: string) => void;\n /**\n * Text to display when retrying.\n * Defaults to \"Error occurred. Retrying\".\n */\n retryText?: string;\n}\n\n/**\n * A component that renders a full panel for chat bot interactions. This includes\n * the message bubbles for the conversation, input box with send button, and header\n * (if provided).\n *\n * @public\n *\n * @param props - {@link ChatPanelProps}\n */\nexport function ChatPanel(props: ChatPanelProps) {\n const {\n header,\n footer,\n customCssClasses,\n stream,\n handleError,\n messageSuggestions,\n onLinkClick,\n onSend:onSendProp,\n onRetry:onRetryProp,\n retryText = \"Error occurred. Retrying\",\n } = props;\n const messages = useChatState((state) => state.conversation.messages);\n const loading = useChatState((state) => state.conversation.isLoading);\n const suggestedReplies = useChatState(\n (state) => state.conversation.notes?.suggestedReplies\n );\n const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);\n const reportAnalyticsEvent = useReportAnalyticsEvent();\n useFetchInitialMessage(handleError, stream);\n\n const [retry, setRetry] = useState(false);\n const onSend = useCallback((message: string) => {\n onSendProp?.(message);\n setRetry(false)\n }, [onSendProp])\n\n const onRetry = useCallback((e: unknown) => {\n onRetryProp?.(e);\n setRetry(true)\n }, [onRetryProp])\n\n useEffect(() => {\n reportAnalyticsEvent({\n action: \"CHAT_IMPRESSION\",\n });\n }, [reportAnalyticsEvent]);\n\n const suggestions = useMemo(() => {\n if (\n messages.length === 0 ||\n (messages.length === 1 && messages[0].source === \"BOT\")\n ) {\n return messageSuggestions;\n }\n return suggestedReplies;\n }, [messages, suggestedReplies, messageSuggestions]);\n\n const messagesRef = useRef<Array<HTMLDivElement | null>>([]);\n const messagesContainer = useRef<HTMLDivElement>(null);\n\n // Handle scrolling when messages change\n useEffect(() => {\n let scrollTop = 0;\n messagesRef.current = messagesRef.current.slice(0, messages.length);\n\n // Sums up scroll heights of all messages except the last one\n if (messagesRef?.current.length > 1) {\n scrollTop = messagesRef.current\n .slice(0, -1)\n .map((elem, _) => elem?.scrollHeight ?? 0)\n .reduce((total, height) => total + height);\n }\n\n // Scroll to the top of the last message\n messagesContainer.current?.scroll({\n top: scrollTop,\n behavior: \"smooth\",\n });\n }, [messages]);\n\n const setMessagesRef = useCallback((index) => {\n if (!messagesRef?.current) return null;\n return (message) => (messagesRef.current[index] = message);\n }, []);\n\n const footerCssClasses: MarkdownCssClasses = useMemo(\n () => ({\n container: cssClasses.footer,\n link: \"cursor-pointer hover:underline text-blue-600\",\n }),\n [cssClasses]\n );\n\n return (\n <div className=\"yext-chat w-full h-full\">\n <div className={cssClasses.container}>\n {header}\n <div className={cssClasses.messagesScrollContainer}>\n <div ref={messagesContainer} className={cssClasses.messagesContainer}>\n {messages.map((message, index) => (\n <div key={index} ref={setMessagesRef(index)}>\n <MessageBubble\n {...props}\n customCssClasses={cssClasses.messageBubbleCssClasses}\n message={message}\n onLinkClick={onLinkClick}\n />\n </div>\n ))}\n {loading && <div className=\"flex\">\n <LoadingDots />\n {retry && <p className=\"text-slate-500 text-[13px] font-bold\">{retryText}</p>} \n </div>}\n </div>\n </div>\n <div className={cssClasses.inputContainer}>\n {suggestions && (\n <MessageSuggestions\n stream={stream}\n onSend={onSend}\n onRetry={onRetry}\n handleError={handleError}\n suggestions={suggestions}\n customCssClasses={cssClasses.messageSuggestionClasses}\n />\n )}\n <ChatInput\n {...props}\n onSend={onSend}\n onRetry={onRetry}\n customCssClasses={cssClasses.inputCssClasses}\n />\n </div>\n {footer && (\n <Markdown\n content={footer}\n linkClickEvent=\"WEBSITE\"\n onLinkClick={onLinkClick}\n customCssClasses={footerCssClasses}\n />\n )}\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChatPanel.mjs","sources":["../../../../src/components/ChatPanel.tsx"],"sourcesContent":["import React, {\n ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { useChatState } from \"@yext/chat-headless-react\";\nimport {\n MessageBubble,\n MessageBubbleCssClasses,\n MessageBubbleProps,\n} from \"./MessageBubble\";\nimport { ChatInput, ChatInputCssClasses, ChatInputProps } from \"./ChatInput\";\nimport { LoadingDots } from \"./LoadingDots\";\nimport { useComposedCssClasses } from \"../hooks\";\nimport { withStylelessCssClasses } from \"../utils/withStylelessCssClasses\";\nimport { useReportAnalyticsEvent } from \"../hooks/useReportAnalyticsEvent\";\nimport { useFetchInitialMessage } from \"../hooks/useFetchInitialMessage\";\nimport {\n MessageSuggestionCssClasses,\n MessageSuggestions,\n} from \"./MessageSuggestions\";\nimport { Markdown, MarkdownCssClasses } from \"./Markdown\";\n\n/**\n * The CSS class interface for the {@link ChatPanel} component.\n *\n * @public\n */\nexport interface ChatPanelCssClasses {\n container?: string;\n messagesContainer?: string;\n messagesScrollContainer?: string;\n inputContainer?: string;\n inputCssClasses?: ChatInputCssClasses;\n messageBubbleCssClasses?: MessageBubbleCssClasses;\n messageSuggestionClasses?: MessageSuggestionCssClasses;\n footer?: string;\n}\n\nconst builtInCssClasses: ChatPanelCssClasses = withStylelessCssClasses(\n \"Panel\",\n {\n container: \"h-full w-full flex flex-col relative shadow-2xl bg-white\",\n messagesScrollContainer: \"flex flex-col mt-auto overflow-hidden\",\n messagesContainer: \"flex flex-col gap-y-1 px-4 overflow-auto [&>*:first-child]:mt-3\",\n inputContainer: \"w-full p-4\",\n messageBubbleCssClasses: {\n topContainer: \"mt-1\",\n },\n footer: \"text-center text-slate-400 rounded-b-3xl px-4 pb-4 text-[12px]\",\n }\n);\n\n/**\n * The props for the {@link ChatPanel} component.\n *\n * @public\n */\nexport interface ChatPanelProps\n extends Omit<MessageBubbleProps, \"customCssClasses\" | \"message\">,\n Omit<ChatInputProps, \"customCssClasses\"> {\n /** A header to render at the top of the panel. */\n header?: ReactNode;\n /** A footer markdown string to render at the bottom of the panel. */\n footer?: string;\n /**\n * CSS classes for customizing the component styling.\n */\n customCssClasses?: ChatPanelCssClasses;\n /**\n * A set of pre-written initial messages that the user\n * can click on instead of typing their own.\n */\n messageSuggestions?: string[];\n /** Link target open behavior on click.\n * Defaults to \"_blank\".\n */\n linkTarget?: string;\n /** A callback which is called when user clicks a link. */\n onLinkClick?: (href?: string) => void;\n /**\n * Text to display when retrying.\n * Defaults to \"Error occurred. Retrying\".\n */\n retryText?: string;\n}\n\n/**\n * A component that renders a full panel for chat bot interactions. This includes\n * the message bubbles for the conversation, input box with send button, and header\n * (if provided).\n *\n * @public\n *\n * @param props - {@link ChatPanelProps}\n */\nexport function ChatPanel(props: ChatPanelProps) {\n const {\n header,\n footer,\n customCssClasses,\n stream,\n handleError,\n messageSuggestions,\n linkTarget = \"_blank\",\n onLinkClick,\n onSend: onSendProp,\n onRetry: onRetryProp,\n retryText = \"Error occurred. Retrying\",\n } = props;\n const messages = useChatState((state) => state.conversation.messages);\n const loading = useChatState((state) => state.conversation.isLoading);\n const suggestedReplies = useChatState(\n (state) => state.conversation.notes?.suggestedReplies\n );\n const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);\n const reportAnalyticsEvent = useReportAnalyticsEvent();\n useFetchInitialMessage(handleError, stream);\n\n const [retry, setRetry] = useState(false);\n const onSend = useCallback(\n (message: string) => {\n onSendProp?.(message);\n setRetry(false);\n },\n [onSendProp]\n );\n\n const onRetry = useCallback(\n (e: unknown) => {\n onRetryProp?.(e);\n setRetry(true);\n },\n [onRetryProp]\n );\n\n useEffect(() => {\n reportAnalyticsEvent({\n action: \"CHAT_IMPRESSION\",\n });\n }, [reportAnalyticsEvent]);\n\n const suggestions = useMemo(() => {\n if (\n messages.length === 0 ||\n (messages.length === 1 && messages[0].source === \"BOT\")\n ) {\n return messageSuggestions;\n }\n return suggestedReplies;\n }, [messages, suggestedReplies, messageSuggestions]);\n\n const messagesRef = useRef<Array<HTMLDivElement | null>>([]);\n const messagesContainer = useRef<HTMLDivElement>(null);\n\n // Handle scrolling when messages change\n useEffect(() => {\n let scrollTop = 0;\n messagesRef.current = messagesRef.current.slice(0, messages.length);\n\n // Sums up scroll heights of all messages except the last one\n if (messagesRef?.current.length > 1) {\n scrollTop = messagesRef.current\n .slice(0, -1)\n .map((elem, _) => elem?.scrollHeight ?? 0)\n .reduce((total, height) => total + height);\n }\n\n // Scroll to the top of the last message\n messagesContainer.current?.scroll({\n top: scrollTop,\n behavior: \"smooth\",\n });\n }, [messages]);\n\n const setMessagesRef = useCallback((index) => {\n if (!messagesRef?.current) return null;\n return (message) => (messagesRef.current[index] = message);\n }, []);\n\n const footerCssClasses: MarkdownCssClasses = useMemo(\n () => ({\n container: cssClasses.footer,\n link: \"cursor-pointer hover:underline text-blue-600\",\n }),\n [cssClasses]\n );\n\n return (\n <div className=\"yext-chat w-full h-full\">\n <div className={cssClasses.container}>\n {header}\n <div className={cssClasses.messagesScrollContainer}>\n <div ref={messagesContainer} className={cssClasses.messagesContainer}>\n {messages.map((message, index) => (\n <div key={index} ref={setMessagesRef(index)}>\n <MessageBubble\n {...props}\n customCssClasses={cssClasses.messageBubbleCssClasses}\n message={message}\n linkTarget={linkTarget}\n onLinkClick={onLinkClick}\n />\n </div>\n ))}\n {loading && (\n <div className=\"flex\">\n <LoadingDots />\n {retry && (\n <p className=\"text-slate-500 text-[13px] font-bold\">\n {retryText}\n </p>\n )}\n </div>\n )}\n </div>\n </div>\n <div className={cssClasses.inputContainer}>\n {suggestions && (\n <MessageSuggestions\n stream={stream}\n onSend={onSend}\n onRetry={onRetry}\n handleError={handleError}\n suggestions={suggestions}\n customCssClasses={cssClasses.messageSuggestionClasses}\n />\n )}\n <ChatInput\n {...props}\n onSend={onSend}\n onRetry={onRetry}\n customCssClasses={cssClasses.inputCssClasses}\n />\n </div>\n {footer && (\n <Markdown\n content={footer}\n linkClickEvent=\"WEBSITE\"\n linkTarget={linkTarget}\n onLinkClick={onLinkClick}\n customCssClasses={footerCssClasses}\n />\n )}\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ChatPopUp.d.ts","sourceRoot":"","sources":["../../../../src/components/ChatPopUp.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAa,mBAAmB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EAEL,oBAAoB,EACpB,eAAe,EAChB,MAAM,cAAc,CAAC;AAKtB,OAAO,EAEL,6BAA6B,EAC9B,MAAM,uBAAuB,CAAC;AAI/B;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,6BAA6B,CAAC,EAAE,6BAA6B,CAAC;CAC/D;AAqCD;;;;GAIG;AACH,MAAM,WAAW,cACf,SAAQ,IAAI,CAAC,eAAe,EAAE,iBAAiB,GAAG,kBAAkB,CAAC,EACnE,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,kBAAkB,CAAC;IACrD,0DAA0D;IAC1D,mBAAmB,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IAClC,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,mBAAmB,CAAC;IACvC,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,qBA8J9C"}
1
+ {"version":3,"file":"ChatPopUp.d.ts","sourceRoot":"","sources":["../../../../src/components/ChatPopUp.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAa,mBAAmB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EAEL,oBAAoB,EACpB,eAAe,EAChB,MAAM,cAAc,CAAC;AAKtB,OAAO,EAEL,6BAA6B,EAC9B,MAAM,uBAAuB,CAAC;AAI/B;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,6BAA6B,CAAC,EAAE,6BAA6B,CAAC;CAC/D;AAqCD;;;;GAIG;AACH,MAAM,WAAW,cACf,SAAQ,IAAI,CAAC,eAAe,EAAE,iBAAiB,GAAG,kBAAkB,CAAC,EACnE,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,kBAAkB,CAAC;IACrD,0DAA0D;IAC1D,mBAAmB,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IAClC,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,mBAAmB,CAAC;IACvC,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,qBAiL9C"}
@@ -32,9 +32,9 @@ const builtInCssClasses = withStylelessCssClasses("PopUp", {
32
32
  panelCssClasses: {
33
33
  container: "max-[480px]:rounded-none rounded-3xl",
34
34
  inputContainer: "max-[480px]:rounded-none rounded-b-3xl",
35
- messagesScrollContainer: "rounded-b-3xl",
36
35
  },
37
36
  });
37
+ const popupLocalStorageKey = "YEXT_CHAT_OPEN_ON_LOAD";
38
38
  /**
39
39
  * A component that renders a popup button that displays and hides
40
40
  * a panel for chat bot interactions.
@@ -65,31 +65,42 @@ function ChatPopUp(props) {
65
65
  // control the actual DOM rendering of the panel. Start rendering on first open state
66
66
  // to avoid message requests immediately on load while the popup is still "hidden"
67
67
  const [renderChat, setRenderChat] = useState(false);
68
+ // Set the initial value of the local storage flag for opening on load only if it doesn't already exist
69
+ if (window.localStorage.getItem(popupLocalStorageKey) === null) {
70
+ window.localStorage.setItem(popupLocalStorageKey, openOnLoad ? "true" : "false");
71
+ }
72
+ const openOnLoadLocalStorage = window.localStorage.getItem(popupLocalStorageKey);
73
+ /* Open panel on load if:
74
+ - openOnLoad prop is true or there are messages in state (from browser storage), and local storage flag is true */
75
+ const isOpenOnLoad = (messages.length > 1 && openOnLoadLocalStorage === "true") || openOnLoad;
68
76
  // only fetch initial message when ChatPanel is closed on load (otherwise, it will be fetched in ChatPanel)
69
- useFetchInitialMessage(showInitialMessagePopUp ? console.error : handleError, false, (showUnreadNotification || showInitialMessagePopUp) && !renderChat && !openOnLoad);
77
+ useFetchInitialMessage(showInitialMessagePopUp ? console.error : handleError, false, (showUnreadNotification || showInitialMessagePopUp) &&
78
+ !renderChat &&
79
+ !isOpenOnLoad);
70
80
  useEffect(() => {
71
- // Open panel on load if openOnLoad prop is true or there are messages in state (from browser storage)
72
- if (!renderChat && (openOnLoad || messages.length > 1)) {
81
+ if (!renderChat && isOpenOnLoad) {
73
82
  setShowChat(true);
74
83
  setRenderChat(true);
75
84
  setshowInitialMessage(false);
76
85
  }
77
- }, [messages.length, openOnLoad, renderChat]);
86
+ }, [renderChat, messages.length, isOpenOnLoad]);
78
87
  const onClick = useCallback(() => {
79
- setShowChat(prev => !prev);
88
+ setShowChat((prev) => !prev);
80
89
  setRenderChat(true);
81
90
  setshowInitialMessage(false);
91
+ window.localStorage.setItem(popupLocalStorageKey, "true");
82
92
  }, []);
83
93
  const onClose = useCallback(() => {
84
94
  setShowChat(false);
85
95
  customOnClose?.();
86
96
  // consider all the messages are read while the panel was open
87
97
  setNumReadMessagesLength(messages.length);
88
- }, [customOnClose, messages]);
98
+ window.localStorage.setItem(popupLocalStorageKey, "false");
99
+ }, [customOnClose, messages.length]);
89
100
  useEffect(() => {
90
101
  // update number of unread messages if there are new messages added while the panel is closed
91
102
  setNumUnreadMessagesLength(messages.length - numReadMessages);
92
- }, [messages, numReadMessages]);
103
+ }, [messages.length, numReadMessages]);
93
104
  const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);
94
105
  const panelCssClasses = twMerge(cssClasses.panel, showChat ? cssClasses.panel__display : cssClasses.panel__hidden);
95
106
  const closedPopupContainerCssClasses = twMerge(cssClasses.closedPopupContainer, showChat
@@ -1 +1 @@
1
- {"version":3,"file":"ChatPopUp.mjs","sources":["../../../../src/components/ChatPopUp.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useState } from \"react\";\nimport { ChatIcon } from \"../icons/Chat\";\nimport { ChatPanel, ChatPanelCssClasses, ChatPanelProps } from \"./ChatPanel\";\nimport {\n ChatHeader,\n ChatHeaderCssClasses,\n ChatHeaderProps,\n} from \"./ChatHeader\";\nimport { twMerge } from \"tailwind-merge\";\nimport { useComposedCssClasses } from \"../hooks\";\nimport { withStylelessCssClasses } from \"../utils/withStylelessCssClasses\";\nimport { useReportAnalyticsEvent } from \"../hooks/useReportAnalyticsEvent\";\nimport {\n InitialMessagePopUp,\n InitialMessagePopUpCssClasses,\n} from \"./InitialMessagePopUp\";\nimport { useChatState } from \"@yext/chat-headless-react\";\nimport { useFetchInitialMessage } from \"../hooks/useFetchInitialMessage\";\n\n/**\n * The CSS class interface for the {@link ChatPopUp} component.\n *\n * @public\n */\nexport interface ChatPopUpCssClasses {\n container?: string;\n panel?: string;\n panel__display?: string;\n panel__hidden?: string;\n button?: string;\n buttonIcon?: string;\n ctaLabelContainer?: string;\n ctaLabel?: string;\n notification?: string;\n closedPopupContainer?: string;\n closedPopupContainer__display?: string;\n closedPopupContainer__hidden?: string;\n headerCssClasses?: ChatHeaderCssClasses;\n panelCssClasses?: ChatPanelCssClasses;\n initialMessagePopUpCssClasses?: InitialMessagePopUpCssClasses;\n}\n\nconst fixedPosition = \"fixed bottom-6 right-4 lg:bottom-14 lg:right-10 z-50 \";\nconst builtInCssClasses: ChatPopUpCssClasses = withStylelessCssClasses(\n \"PopUp\",\n {\n container: \"transition-all\",\n panel:\n fixedPosition +\n \"w-80 max-[480px]:right-0 max-[480px]:bottom-0 max-[480px]:w-full max-[480px]:h-full lg:w-96 h-[75vh]\",\n panel__display: \"duration-300 translate-y-0\",\n panel__hidden: \"duration-300 translate-y-[20%] opacity-0 invisible\",\n closedPopupContainer:\n fixedPosition +\n \"flex gap-x-2.5 items-center hover:-translate-y-2 duration-150\",\n closedPopupContainer__display: \"duration-300 transform translate-y-0\",\n closedPopupContainer__hidden:\n \"duration-300 transform translate-y-[20%] opacity-0 invisible\",\n button:\n \"p-2 w-12 h-12 lg:w-16 lg:h-16 flex justify-center items-center text-white shadow-xl rounded-full bg-gradient-to-br from-blue-600 to-blue-700\",\n buttonIcon: \"text-blue-600 w-[28px] h-[28px] lg:w-[40px] lg:h-[40px]\",\n ctaLabelContainer: \"max-w-60 -mr-8 line-clamp-1\",\n ctaLabel:\n \"p-3 pr-8 flex items-center whitespace-nowrap animate-expand-left font-bold rounded-l-full bg-white text-blue-700 h-10 lg:h-14 text-sm lg:text-base\",\n notification:\n \"fixed animate-fade-in bg-red-700 -right-1 top-0 rounded-full w-5 lg:w-6 h-5 lg:h-6 items-center flex justify-center text-sm lg:text-base text-white\",\n headerCssClasses: {\n container: \"max-[480px]:rounded-none rounded-t-3xl\",\n },\n panelCssClasses: {\n container: \"max-[480px]:rounded-none rounded-3xl\",\n inputContainer: \"max-[480px]:rounded-none rounded-b-3xl\",\n messagesScrollContainer: \"rounded-b-3xl\",\n },\n }\n);\n\n/**\n * The props for the {@link ChatPopUp} component.\n *\n * @public\n */\nexport interface ChatPopUpProps\n extends Omit<ChatHeaderProps, \"showCloseButton\" | \"customCssClasses\">,\n Omit<ChatPanelProps, \"header\" | \"customCssClasses\"> {\n /** Custom icon for the popup button to open the panel. */\n openPanelButtonIcon?: JSX.Element;\n /** CSS classes for customizing the component styling. */\n customCssClasses?: ChatPopUpCssClasses;\n /** Whether to show the panel on load. Defaults to false. */\n openOnLoad?: boolean;\n /**\n * Whether to show the initial message popup when the panel is hidden on load.\n * Defaults to false.\n */\n showInitialMessagePopUp?: boolean;\n /**\n * Whether to show a heartbeat animation on the popup button when the panel is hidden.\n * Defaults to false.\n */\n showHeartBeatAnimation?: boolean;\n /**\n * Whether to show notification showing number of unread messages.\n * Defaults to false.\n */\n showUnreadNotification?: boolean;\n /**\n * The \"Call to Action\" label to be displayed next to the popup button.\n * By default, the CTA is not shown.\n * This prop will override the \"showInitialMessagePopUp\" prop, if specified.\n */\n ctaLabel?: string;\n}\n\n/**\n * A component that renders a popup button that displays and hides\n * a panel for chat bot interactions.\n *\n * @public\n *\n * @param props - {@link ChatPanelProps}\n */\nexport function ChatPopUp(props: ChatPopUpProps) {\n const {\n openPanelButtonIcon,\n customCssClasses,\n showRestartButton = true,\n onClose: customOnClose,\n handleError,\n openOnLoad = false,\n showInitialMessagePopUp = false,\n showHeartBeatAnimation = false,\n showUnreadNotification = false,\n ctaLabel,\n title,\n footer,\n } = props;\n\n const reportAnalyticsEvent = useReportAnalyticsEvent();\n useEffect(() => {\n reportAnalyticsEvent({\n action: \"CHAT_IMPRESSION\",\n });\n }, [reportAnalyticsEvent]);\n\n const messages = useChatState((s) => s.conversation.messages);\n const [numReadMessages, setNumReadMessagesLength] = useState<number>(0);\n const [numUnreadMessages, setNumUnreadMessagesLength] = useState<number>(0);\n\n const [showInitialMessage, setshowInitialMessage] = useState(\n //only show initial message popup (if specified) when CTA label is not provided\n !ctaLabel && showInitialMessagePopUp\n );\n const onCloseInitialMessage = useCallback(() => {\n setshowInitialMessage(false);\n }, []);\n\n // control CSS behavior (fade-in/out animation) on open/close state of the panel.\n const [showChat, setShowChat] = useState(false);\n\n // control the actual DOM rendering of the panel. Start rendering on first open state\n // to avoid message requests immediately on load while the popup is still \"hidden\"\n const [renderChat, setRenderChat] = useState(false);\n\n\n // only fetch initial message when ChatPanel is closed on load (otherwise, it will be fetched in ChatPanel)\n useFetchInitialMessage(\n showInitialMessagePopUp ? console.error : handleError,\n false,\n (showUnreadNotification || showInitialMessagePopUp) && !renderChat && !openOnLoad,\n );\n\n useEffect(() => {\n // Open panel on load if openOnLoad prop is true or there are messages in state (from browser storage)\n if (!renderChat && (openOnLoad || messages.length > 1)) {\n setShowChat(true);\n setRenderChat(true);\n setshowInitialMessage(false);\n }\n }, [messages.length, openOnLoad, renderChat]);\n\n const onClick = useCallback(() => {\n setShowChat(prev => !prev);\n setRenderChat(true);\n setshowInitialMessage(false);\n }, []);\n\n const onClose = useCallback(() => {\n setShowChat(false);\n customOnClose?.();\n // consider all the messages are read while the panel was open\n setNumReadMessagesLength(messages.length);\n }, [customOnClose, messages]);\n\n useEffect(() => {\n // update number of unread messages if there are new messages added while the panel is closed\n setNumUnreadMessagesLength(messages.length - numReadMessages);\n }, [messages, numReadMessages]);\n\n const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);\n const panelCssClasses = twMerge(\n cssClasses.panel,\n showChat ? cssClasses.panel__display : cssClasses.panel__hidden\n );\n const closedPopupContainerCssClasses = twMerge(\n cssClasses.closedPopupContainer,\n showChat\n ? cssClasses.closedPopupContainer__hidden\n : cssClasses.closedPopupContainer__display\n );\n\n return (\n <div className=\"yext-chat w-full h-full\">\n <div className={cssClasses.container}>\n <div className={panelCssClasses} aria-label=\"Chat Popup Panel\">\n {renderChat && (\n <ChatPanel\n {...props}\n customCssClasses={cssClasses.panelCssClasses}\n header={\n <ChatHeader\n title={title}\n showRestartButton={showRestartButton}\n showCloseButton={true}\n onClose={onClose}\n customCssClasses={cssClasses.headerCssClasses}\n />\n }\n footer={footer}\n />\n )}\n </div>\n <div\n className={closedPopupContainerCssClasses}\n aria-label=\"Chat Closed Popup Container\"\n >\n {showInitialMessage && (\n <InitialMessagePopUp\n onClose={onCloseInitialMessage}\n customCssClasses={cssClasses.initialMessagePopUpCssClasses}\n />\n )}\n {ctaLabel && (\n // the div container is needed to islate the expand CSS animation\n <div className={cssClasses.ctaLabelContainer}>\n <button\n onClick={onClick}\n aria-label=\"CTA Label\"\n className={cssClasses.ctaLabel}\n >\n {ctaLabel}\n </button>\n </div>\n )}\n <button\n aria-label=\"Chat Popup Button\"\n onClick={onClick}\n className={\n cssClasses.button +\n (showHeartBeatAnimation && !!numUnreadMessages\n ? \" animate-heartbeat\"\n : \"\")\n }\n >\n {openPanelButtonIcon ?? (\n <ChatIcon className={cssClasses.buttonIcon} />\n )}\n {showUnreadNotification && !!numUnreadMessages && (\n <div\n aria-label=\"Unread Messages Notification\"\n className={cssClasses.notification}\n >\n {numUnreadMessages}\n </div>\n )}\n </button>\n </div>\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AA0CA,MAAM,aAAa,GAAG,uDAAuD,CAAC;AAC9E,MAAM,iBAAiB,GAAwB,uBAAuB,CACpE,OAAO,EACP;AACE,IAAA,SAAS,EAAE,gBAAgB;AAC3B,IAAA,KAAK,EACH,aAAa;QACb,sGAAsG;AACxG,IAAA,cAAc,EAAE,4BAA4B;AAC5C,IAAA,aAAa,EAAE,oDAAoD;AACnE,IAAA,oBAAoB,EAClB,aAAa;QACb,+DAA+D;AACjE,IAAA,6BAA6B,EAAE,sCAAsC;AACrE,IAAA,4BAA4B,EAC1B,8DAA8D;AAChE,IAAA,MAAM,EACJ,8IAA8I;AAChJ,IAAA,UAAU,EAAE,yDAAyD;AACrE,IAAA,iBAAiB,EAAE,6BAA6B;AAChD,IAAA,QAAQ,EACN,oJAAoJ;AACtJ,IAAA,YAAY,EACV,qJAAqJ;AACvJ,IAAA,gBAAgB,EAAE;AAChB,QAAA,SAAS,EAAE,wCAAwC;AACpD,KAAA;AACD,IAAA,eAAe,EAAE;AACf,QAAA,SAAS,EAAE,sCAAsC;AACjD,QAAA,cAAc,EAAE,wCAAwC;AACxD,QAAA,uBAAuB,EAAE,eAAe;AACzC,KAAA;AACF,CAAA,CACF,CAAC;AAuCF;;;;;;;AAOG;AACG,SAAU,SAAS,CAAC,KAAqB,EAAA;AAC7C,IAAA,MAAM,EACJ,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,GAAG,IAAI,EACxB,OAAO,EAAE,aAAa,EACtB,WAAW,EACX,UAAU,GAAG,KAAK,EAClB,uBAAuB,GAAG,KAAK,EAC/B,sBAAsB,GAAG,KAAK,EAC9B,sBAAsB,GAAG,KAAK,EAC9B,QAAQ,EACR,KAAK,EACL,MAAM,GACP,GAAG,KAAK,CAAC;AAEV,IAAA,MAAM,oBAAoB,GAAG,uBAAuB,EAAE,CAAC;IACvD,SAAS,CAAC,MAAK;AACb,QAAA,oBAAoB,CAAC;AACnB,YAAA,MAAM,EAAE,iBAAiB;AAC1B,SAAA,CAAC,CAAC;AACL,KAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC;AAE3B,IAAA,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC9D,MAAM,CAAC,eAAe,EAAE,wBAAwB,CAAC,GAAG,QAAQ,CAAS,CAAC,CAAC,CAAC;IACxE,MAAM,CAAC,iBAAiB,EAAE,0BAA0B,CAAC,GAAG,QAAQ,CAAS,CAAC,CAAC,CAAC;AAE5E,IAAA,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAAG,QAAQ;;AAE1D,IAAA,CAAC,QAAQ,IAAI,uBAAuB,CACrC,CAAC;AACF,IAAA,MAAM,qBAAqB,GAAG,WAAW,CAAC,MAAK;QAC7C,qBAAqB,CAAC,KAAK,CAAC,CAAC;KAC9B,EAAE,EAAE,CAAC,CAAC;;IAGP,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;;;IAIhD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;;IAIpD,sBAAsB,CACpB,uBAAuB,GAAG,OAAO,CAAC,KAAK,GAAG,WAAW,EACrD,KAAK,EACL,CAAC,sBAAsB,IAAI,uBAAuB,KAAK,CAAC,UAAU,IAAI,CAAC,UAAU,CAClF,CAAC;IAEF,SAAS,CAAC,MAAK;;AAEb,QAAA,IAAI,CAAC,UAAU,KAAK,UAAU,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE;YACtD,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,aAAa,CAAC,IAAI,CAAC,CAAC;YACpB,qBAAqB,CAAC,KAAK,CAAC,CAAC;AAC9B,SAAA;KACF,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;AAE9C,IAAA,MAAM,OAAO,GAAG,WAAW,CAAC,MAAK;QAC/B,WAAW,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,qBAAqB,CAAC,KAAK,CAAC,CAAC;KAC9B,EAAE,EAAE,CAAC,CAAC;AAEP,IAAA,MAAM,OAAO,GAAG,WAAW,CAAC,MAAK;QAC/B,WAAW,CAAC,KAAK,CAAC,CAAC;QACnB,aAAa,IAAI,CAAC;;AAElB,QAAA,wBAAwB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC5C,KAAC,EAAE,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE9B,SAAS,CAAC,MAAK;;AAEb,QAAA,0BAA0B,CAAC,QAAQ,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC;AAChE,KAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;IAEhC,MAAM,UAAU,GAAG,qBAAqB,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;IAC9E,MAAM,eAAe,GAAG,OAAO,CAC7B,UAAU,CAAC,KAAK,EAChB,QAAQ,GAAG,UAAU,CAAC,cAAc,GAAG,UAAU,CAAC,aAAa,CAChE,CAAC;IACF,MAAM,8BAA8B,GAAG,OAAO,CAC5C,UAAU,CAAC,oBAAoB,EAC/B,QAAQ;UACJ,UAAU,CAAC,4BAA4B;AACzC,UAAE,UAAU,CAAC,6BAA6B,CAC7C,CAAC;AAEF,IAAA,QACE,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,yBAAyB,EAAA;AACtC,QAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,UAAU,CAAC,SAAS,EAAA;YAClC,KAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,eAAe,EAAa,YAAA,EAAA,kBAAkB,IAC3D,UAAU,KACT,KAAA,CAAA,aAAA,CAAC,SAAS,EAAA,EAAA,GACJ,KAAK,EACT,gBAAgB,EAAE,UAAU,CAAC,eAAe,EAC5C,MAAM,EACJ,KAAC,CAAA,aAAA,CAAA,UAAU,EACT,EAAA,KAAK,EAAE,KAAK,EACZ,iBAAiB,EAAE,iBAAiB,EACpC,eAAe,EAAE,IAAI,EACrB,OAAO,EAAE,OAAO,EAChB,gBAAgB,EAAE,UAAU,CAAC,gBAAgB,EAAA,CAC7C,EAEJ,MAAM,EAAE,MAAM,EACd,CAAA,CACH,CACG;AACN,YAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAE,8BAA8B,EAAA,YAAA,EAC9B,6BAA6B,EAAA;AAEvC,gBAAA,kBAAkB,KACjB,KAAC,CAAA,aAAA,CAAA,mBAAmB,IAClB,OAAO,EAAE,qBAAqB,EAC9B,gBAAgB,EAAE,UAAU,CAAC,6BAA6B,GAC1D,CACH;AACA,gBAAA,QAAQ;;AAEP,gBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,UAAU,CAAC,iBAAiB,EAAA;AAC1C,oBAAA,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EACE,OAAO,EAAE,OAAO,EAAA,YAAA,EACL,WAAW,EACtB,SAAS,EAAE,UAAU,CAAC,QAAQ,EAAA,EAE7B,QAAQ,CACF,CACL,CACP;gBACD,KACa,CAAA,aAAA,CAAA,QAAA,EAAA,EAAA,YAAA,EAAA,mBAAmB,EAC9B,OAAO,EAAE,OAAO,EAChB,SAAS,EACP,UAAU,CAAC,MAAM;AACjB,yBAAC,sBAAsB,IAAI,CAAC,CAAC,iBAAiB;AAC5C,8BAAE,oBAAoB;8BACpB,EAAE,CAAC,EAAA;oBAGR,mBAAmB,KAClB,KAAA,CAAA,aAAA,CAAC,QAAQ,EAAA,EAAC,SAAS,EAAE,UAAU,CAAC,UAAU,EAAA,CAAI,CAC/C;oBACA,sBAAsB,IAAI,CAAC,CAAC,iBAAiB,KAC5C,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,YAAA,EACa,8BAA8B,EACzC,SAAS,EAAE,UAAU,CAAC,YAAY,EAEjC,EAAA,iBAAiB,CACd,CACP,CACM,CACL,CACF,CACF,EACN;AACJ;;;;"}
1
+ {"version":3,"file":"ChatPopUp.mjs","sources":["../../../../src/components/ChatPopUp.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useState } from \"react\";\nimport { ChatIcon } from \"../icons/Chat\";\nimport { ChatPanel, ChatPanelCssClasses, ChatPanelProps } from \"./ChatPanel\";\nimport {\n ChatHeader,\n ChatHeaderCssClasses,\n ChatHeaderProps,\n} from \"./ChatHeader\";\nimport { twMerge } from \"tailwind-merge\";\nimport { useComposedCssClasses } from \"../hooks\";\nimport { withStylelessCssClasses } from \"../utils/withStylelessCssClasses\";\nimport { useReportAnalyticsEvent } from \"../hooks/useReportAnalyticsEvent\";\nimport {\n InitialMessagePopUp,\n InitialMessagePopUpCssClasses,\n} from \"./InitialMessagePopUp\";\nimport { useChatState } from \"@yext/chat-headless-react\";\nimport { useFetchInitialMessage } from \"../hooks/useFetchInitialMessage\";\n\n/**\n * The CSS class interface for the {@link ChatPopUp} component.\n *\n * @public\n */\nexport interface ChatPopUpCssClasses {\n container?: string;\n panel?: string;\n panel__display?: string;\n panel__hidden?: string;\n button?: string;\n buttonIcon?: string;\n ctaLabelContainer?: string;\n ctaLabel?: string;\n notification?: string;\n closedPopupContainer?: string;\n closedPopupContainer__display?: string;\n closedPopupContainer__hidden?: string;\n headerCssClasses?: ChatHeaderCssClasses;\n panelCssClasses?: ChatPanelCssClasses;\n initialMessagePopUpCssClasses?: InitialMessagePopUpCssClasses;\n}\n\nconst fixedPosition = \"fixed bottom-6 right-4 lg:bottom-14 lg:right-10 z-50 \";\nconst builtInCssClasses: ChatPopUpCssClasses = withStylelessCssClasses(\n \"PopUp\",\n {\n container: \"transition-all\",\n panel:\n fixedPosition +\n \"w-80 max-[480px]:right-0 max-[480px]:bottom-0 max-[480px]:w-full max-[480px]:h-full lg:w-96 h-[75vh]\",\n panel__display: \"duration-300 translate-y-0\",\n panel__hidden: \"duration-300 translate-y-[20%] opacity-0 invisible\",\n closedPopupContainer:\n fixedPosition +\n \"flex gap-x-2.5 items-center hover:-translate-y-2 duration-150\",\n closedPopupContainer__display: \"duration-300 transform translate-y-0\",\n closedPopupContainer__hidden:\n \"duration-300 transform translate-y-[20%] opacity-0 invisible\",\n button:\n \"p-2 w-12 h-12 lg:w-16 lg:h-16 flex justify-center items-center text-white shadow-xl rounded-full bg-gradient-to-br from-blue-600 to-blue-700\",\n buttonIcon: \"text-blue-600 w-[28px] h-[28px] lg:w-[40px] lg:h-[40px]\",\n ctaLabelContainer: \"max-w-60 -mr-8 line-clamp-1\",\n ctaLabel:\n \"p-3 pr-8 flex items-center whitespace-nowrap animate-expand-left font-bold rounded-l-full bg-white text-blue-700 h-10 lg:h-14 text-sm lg:text-base\",\n notification:\n \"fixed animate-fade-in bg-red-700 -right-1 top-0 rounded-full w-5 lg:w-6 h-5 lg:h-6 items-center flex justify-center text-sm lg:text-base text-white\",\n headerCssClasses: {\n container: \"max-[480px]:rounded-none rounded-t-3xl\",\n },\n panelCssClasses: {\n container: \"max-[480px]:rounded-none rounded-3xl\",\n inputContainer: \"max-[480px]:rounded-none rounded-b-3xl\",\n },\n }\n);\nconst popupLocalStorageKey = \"YEXT_CHAT_OPEN_ON_LOAD\";\n\n/**\n * The props for the {@link ChatPopUp} component.\n *\n * @public\n */\nexport interface ChatPopUpProps\n extends Omit<ChatHeaderProps, \"showCloseButton\" | \"customCssClasses\">,\n Omit<ChatPanelProps, \"header\" | \"customCssClasses\"> {\n /** Custom icon for the popup button to open the panel. */\n openPanelButtonIcon?: JSX.Element;\n /** CSS classes for customizing the component styling. */\n customCssClasses?: ChatPopUpCssClasses;\n /** Whether to show the panel on load. Defaults to false. */\n openOnLoad?: boolean;\n /**\n * Whether to show the initial message popup when the panel is hidden on load.\n * Defaults to false.\n */\n showInitialMessagePopUp?: boolean;\n /**\n * Whether to show a heartbeat animation on the popup button when the panel is hidden.\n * Defaults to false.\n */\n showHeartBeatAnimation?: boolean;\n /**\n * Whether to show notification showing number of unread messages.\n * Defaults to false.\n */\n showUnreadNotification?: boolean;\n /**\n * The \"Call to Action\" label to be displayed next to the popup button.\n * By default, the CTA is not shown.\n * This prop will override the \"showInitialMessagePopUp\" prop, if specified.\n */\n ctaLabel?: string;\n}\n\n/**\n * A component that renders a popup button that displays and hides\n * a panel for chat bot interactions.\n *\n * @public\n *\n * @param props - {@link ChatPanelProps}\n */\nexport function ChatPopUp(props: ChatPopUpProps) {\n const {\n openPanelButtonIcon,\n customCssClasses,\n showRestartButton = true,\n onClose: customOnClose,\n handleError,\n openOnLoad = false,\n showInitialMessagePopUp = false,\n showHeartBeatAnimation = false,\n showUnreadNotification = false,\n ctaLabel,\n title,\n footer,\n } = props;\n\n const reportAnalyticsEvent = useReportAnalyticsEvent();\n useEffect(() => {\n reportAnalyticsEvent({\n action: \"CHAT_IMPRESSION\",\n });\n }, [reportAnalyticsEvent]);\n\n const messages = useChatState((s) => s.conversation.messages);\n const [numReadMessages, setNumReadMessagesLength] = useState<number>(0);\n const [numUnreadMessages, setNumUnreadMessagesLength] = useState<number>(0);\n\n const [showInitialMessage, setshowInitialMessage] = useState(\n //only show initial message popup (if specified) when CTA label is not provided\n !ctaLabel && showInitialMessagePopUp\n );\n\n const onCloseInitialMessage = useCallback(() => {\n setshowInitialMessage(false);\n }, []);\n\n // control CSS behavior (fade-in/out animation) on open/close state of the panel.\n const [showChat, setShowChat] = useState(false);\n\n // control the actual DOM rendering of the panel. Start rendering on first open state\n // to avoid message requests immediately on load while the popup is still \"hidden\"\n const [renderChat, setRenderChat] = useState(false);\n\n // Set the initial value of the local storage flag for opening on load only if it doesn't already exist\n\n if (window.localStorage.getItem(popupLocalStorageKey) === null) {\n window.localStorage.setItem(\n popupLocalStorageKey,\n openOnLoad ? \"true\" : \"false\"\n );\n }\n const openOnLoadLocalStorage =\n window.localStorage.getItem(popupLocalStorageKey);\n\n /* Open panel on load if: \n - openOnLoad prop is true or there are messages in state (from browser storage), and local storage flag is true */\n const isOpenOnLoad =\n (messages.length > 1 && openOnLoadLocalStorage === \"true\") || openOnLoad;\n\n // only fetch initial message when ChatPanel is closed on load (otherwise, it will be fetched in ChatPanel)\n useFetchInitialMessage(\n showInitialMessagePopUp ? console.error : handleError,\n false,\n (showUnreadNotification || showInitialMessagePopUp) &&\n !renderChat &&\n !isOpenOnLoad\n );\n\n useEffect(() => {\n if (!renderChat && isOpenOnLoad) {\n setShowChat(true);\n setRenderChat(true);\n setshowInitialMessage(false);\n }\n }, [renderChat, messages.length, isOpenOnLoad]);\n\n const onClick = useCallback(() => {\n setShowChat((prev) => !prev);\n setRenderChat(true);\n setshowInitialMessage(false);\n window.localStorage.setItem(popupLocalStorageKey, \"true\");\n }, []);\n\n const onClose = useCallback(() => {\n setShowChat(false);\n customOnClose?.();\n // consider all the messages are read while the panel was open\n setNumReadMessagesLength(messages.length);\n window.localStorage.setItem(popupLocalStorageKey, \"false\");\n }, [customOnClose, messages.length]);\n\n useEffect(() => {\n // update number of unread messages if there are new messages added while the panel is closed\n setNumUnreadMessagesLength(messages.length - numReadMessages);\n }, [messages.length, numReadMessages]);\n\n const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);\n const panelCssClasses = twMerge(\n cssClasses.panel,\n showChat ? cssClasses.panel__display : cssClasses.panel__hidden\n );\n const closedPopupContainerCssClasses = twMerge(\n cssClasses.closedPopupContainer,\n showChat\n ? cssClasses.closedPopupContainer__hidden\n : cssClasses.closedPopupContainer__display\n );\n\n return (\n <div className=\"yext-chat w-full h-full\">\n <div className={cssClasses.container}>\n <div className={panelCssClasses} aria-label=\"Chat Popup Panel\">\n {renderChat && (\n <ChatPanel\n {...props}\n customCssClasses={cssClasses.panelCssClasses}\n header={\n <ChatHeader\n title={title}\n showRestartButton={showRestartButton}\n showCloseButton={true}\n onClose={onClose}\n customCssClasses={cssClasses.headerCssClasses}\n />\n }\n footer={footer}\n />\n )}\n </div>\n <div\n className={closedPopupContainerCssClasses}\n aria-label=\"Chat Closed Popup Container\"\n >\n {showInitialMessage && (\n <InitialMessagePopUp\n onClose={onCloseInitialMessage}\n customCssClasses={cssClasses.initialMessagePopUpCssClasses}\n />\n )}\n {ctaLabel && (\n // the div container is needed to islate the expand CSS animation\n <div className={cssClasses.ctaLabelContainer}>\n <button\n onClick={onClick}\n aria-label=\"CTA Label\"\n className={cssClasses.ctaLabel}\n >\n {ctaLabel}\n </button>\n </div>\n )}\n <button\n aria-label=\"Chat Popup Button\"\n onClick={onClick}\n className={\n cssClasses.button +\n (showHeartBeatAnimation && !!numUnreadMessages\n ? \" animate-heartbeat\"\n : \"\")\n }\n >\n {openPanelButtonIcon ?? (\n <ChatIcon className={cssClasses.buttonIcon} />\n )}\n {showUnreadNotification && !!numUnreadMessages && (\n <div\n aria-label=\"Unread Messages Notification\"\n className={cssClasses.notification}\n >\n {numUnreadMessages}\n </div>\n )}\n </button>\n </div>\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}