@yext/chat-ui-react 0.11.3 → 0.12.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.
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var version = "0.11.3";
3
+ var version = "0.12.0";
4
4
 
5
5
  exports.version = version;
6
6
  //# sourceMappingURL=package.json.js.map
@@ -58,4 +58,17 @@ export interface ChatPanelProps extends Omit<MessageBubbleProps, "customCssClass
58
58
  * @param props - {@link ChatPanelProps}
59
59
  */
60
60
  export declare function ChatPanel(props: ChatPanelProps): React.JSX.Element;
61
+ export declare function getStateLocalStorageKey(hostname: string, conversationId: string): string;
62
+ /**
63
+ * Maintains the panel state of the session.
64
+ */
65
+ export interface PanelState {
66
+ /** The scroll position of the panel. */
67
+ scrollPosition?: number;
68
+ }
69
+ /**
70
+ * Loads the {@link PanelState} from local storage.
71
+ */
72
+ export declare const loadSessionState: (conversationId: string) => PanelState;
73
+ export declare const saveSessionState: (conversationId: string, state: PanelState) => void;
61
74
  //# sourceMappingURL=ChatPanel.d.ts.map
@@ -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;;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"}
1
+ {"version":3,"file":"ChatPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/ChatPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,SAAS,EAOV,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;AAiBD;;;;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,qBA6L9C;AAID,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACrB,MAAM,CAER;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,wCAAwC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,mBAAoB,MAAM,KAAG,UAsBzD,CAAC;AAEF,eAAO,MAAM,gBAAgB,mBAAoB,MAAM,SAAS,UAAU,SASzE,CAAC"}
@@ -40,6 +40,7 @@ function ChatPanel(props) {
40
40
  const messages = chatHeadlessReact.useChatState((state) => state.conversation.messages);
41
41
  const loading = chatHeadlessReact.useChatState((state) => state.conversation.isLoading);
42
42
  const suggestedReplies = chatHeadlessReact.useChatState((state) => state.conversation.notes?.suggestedReplies);
43
+ const conversationId = chatHeadlessReact.useChatState((state) => state.conversation.conversationId);
43
44
  const cssClasses = useComposedCssClasses.useComposedCssClasses(builtInCssClasses, customCssClasses);
44
45
  const reportAnalyticsEvent = useReportAnalyticsEvent.useReportAnalyticsEvent();
45
46
  useFetchInitialMessage.useFetchInitialMessage(handleError, stream);
@@ -66,23 +67,38 @@ function ChatPanel(props) {
66
67
  }, [messages, suggestedReplies, messageSuggestions]);
67
68
  const messagesRef = React.useRef([]);
68
69
  const messagesContainer = React.useRef(null);
70
+ // State to help detect initial messages rendering
71
+ const [initialMessagesLength] = React.useState(messages.length);
72
+ const savedPanelState = React.useMemo(() => {
73
+ if (!conversationId) {
74
+ return {};
75
+ }
76
+ return loadSessionState(conversationId);
77
+ }, [conversationId]);
69
78
  // Handle scrolling when messages change
70
79
  React.useEffect(() => {
71
- let scrollTop = 0;
72
- messagesRef.current = messagesRef.current.slice(0, messages.length);
73
- // Sums up scroll heights of all messages except the last one
74
- if (messagesRef?.current.length > 1) {
75
- scrollTop = messagesRef.current
76
- .slice(0, -1)
77
- .map((elem, _) => elem?.scrollHeight ?? 0)
78
- .reduce((total, height) => total + height);
80
+ const isInitialRender = messages.length === initialMessagesLength;
81
+ let scrollPos = 0;
82
+ if (isInitialRender && savedPanelState.scrollPosition !== undefined) {
83
+ // memorized position
84
+ scrollPos = savedPanelState?.scrollPosition;
85
+ }
86
+ else {
87
+ messagesRef.current = messagesRef.current.slice(0, messages.length);
88
+ // Sums up scroll heights of all messages except the last one
89
+ if (messagesRef?.current.length > 1) {
90
+ // position of the top of the last message
91
+ scrollPos = messagesRef.current
92
+ .slice(0, -1)
93
+ .map((elem, _) => elem?.scrollHeight ?? 0)
94
+ .reduce((total, height) => total + height);
95
+ }
79
96
  }
80
- // Scroll to the top of the last message
81
97
  messagesContainer.current?.scroll({
82
- top: scrollTop,
98
+ top: scrollPos,
83
99
  behavior: "smooth",
84
100
  });
85
- }, [messages]);
101
+ }, [messages, initialMessagesLength, savedPanelState.scrollPosition]);
86
102
  const setMessagesRef = React.useCallback((index) => {
87
103
  if (!messagesRef?.current)
88
104
  return null;
@@ -92,11 +108,26 @@ function ChatPanel(props) {
92
108
  container: cssClasses.footer,
93
109
  link: "cursor-pointer hover:underline text-blue-600",
94
110
  }), [cssClasses]);
111
+ React.useLayoutEffect(() => {
112
+ const curr = messagesContainer.current;
113
+ const onScroll = () => {
114
+ if (!conversationId) {
115
+ return;
116
+ }
117
+ saveSessionState(conversationId, {
118
+ scrollPosition: curr?.scrollTop,
119
+ });
120
+ };
121
+ curr?.addEventListener("scroll", onScroll);
122
+ return () => {
123
+ curr?.removeEventListener("scroll", onScroll);
124
+ };
125
+ }, [messagesContainer, conversationId]);
95
126
  return (React__default.default.createElement("div", { className: "yext-chat w-full h-full" },
96
127
  React__default.default.createElement("div", { className: cssClasses.container },
97
128
  header,
98
129
  React__default.default.createElement("div", { className: cssClasses.messagesScrollContainer },
99
- React__default.default.createElement("div", { ref: messagesContainer, className: cssClasses.messagesContainer },
130
+ React__default.default.createElement("div", { ref: messagesContainer, className: cssClasses.messagesContainer, "aria-label": "Chat Panel Messages Container" },
100
131
  messages.map((message, index) => (React__default.default.createElement("div", { key: index, ref: setMessagesRef(index) },
101
132
  React__default.default.createElement(MessageBubble.MessageBubble, { ...props, customCssClasses: cssClasses.messageBubbleCssClasses, message: message, linkTarget: linkTarget, onLinkClick: onLinkClick })))),
102
133
  loading && (React__default.default.createElement("div", { className: "flex" },
@@ -107,6 +138,41 @@ function ChatPanel(props) {
107
138
  React__default.default.createElement(ChatInput.ChatInput, { ...props, onSend: onSend, onRetry: onRetry, customCssClasses: cssClasses.inputCssClasses })),
108
139
  footer && (React__default.default.createElement(Markdown.Markdown, { content: footer, linkClickEvent: "WEBSITE", linkTarget: linkTarget, onLinkClick: onLinkClick, customCssClasses: footerCssClasses })))));
109
140
  }
141
+ const BASE_STATE_LOCAL_STORAGE_KEY = "yext_chat_panel_state";
142
+ function getStateLocalStorageKey(hostname, conversationId) {
143
+ return `${BASE_STATE_LOCAL_STORAGE_KEY}__${hostname}__${conversationId}`;
144
+ }
145
+ /**
146
+ * Loads the {@link PanelState} from local storage.
147
+ */
148
+ const loadSessionState = (conversationId) => {
149
+ const hostname = window?.location?.hostname;
150
+ if (!localStorage || !hostname) {
151
+ return {};
152
+ }
153
+ const savedState = localStorage.getItem(getStateLocalStorageKey(hostname, conversationId));
154
+ if (savedState) {
155
+ try {
156
+ const parsedState = JSON.parse(savedState);
157
+ return parsedState;
158
+ }
159
+ catch (e) {
160
+ console.warn("Unabled to load saved panel state: error parsing state.");
161
+ localStorage.removeItem(getStateLocalStorageKey(hostname, conversationId));
162
+ }
163
+ }
164
+ return {};
165
+ };
166
+ const saveSessionState = (conversationId, state) => {
167
+ const hostname = window?.location?.hostname;
168
+ if (!localStorage || !hostname) {
169
+ return;
170
+ }
171
+ localStorage.setItem(getStateLocalStorageKey(hostname, conversationId), JSON.stringify(state));
172
+ };
110
173
 
111
174
  exports.ChatPanel = ChatPanel;
175
+ exports.getStateLocalStorageKey = getStateLocalStorageKey;
176
+ exports.loadSessionState = loadSessionState;
177
+ exports.saveSessionState = saveSessionState;
112
178
  //# sourceMappingURL=ChatPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatPanel.js","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":["withStylelessCssClasses","useChatState","useComposedCssClasses","useReportAnalyticsEvent","useFetchInitialMessage","useState","useCallback","useEffect","useMemo","useRef","React","MessageBubble","LoadingDots","MessageSuggestions","ChatInput","Markdown"],"mappings":";;;;;;;;;;;;;;;;;;AA0CA,MAAM,iBAAiB,GAAwBA,+CAAuB,CACpE,OAAO,EACP;AACE,IAAA,SAAS,EAAE,0DAA0D;AACrE,IAAA,uBAAuB,EAAE,uCAAuC;AAChE,IAAA,iBAAiB,EAAE,iEAAiE;AACpF,IAAA,cAAc,EAAE,YAAY;AAC5B,IAAA,uBAAuB,EAAE;AACvB,QAAA,YAAY,EAAE,MAAM;AACrB,KAAA;AACD,IAAA,MAAM,EAAE,gEAAgE;AACzE,CAAA,CACF,CAAC;AAoCF;;;;;;;;AAQG;AACG,SAAU,SAAS,CAAC,KAAqB,EAAA;AAC7C,IAAA,MAAM,EACJ,MAAM,EACN,MAAM,EACN,gBAAgB,EAChB,MAAM,EACN,WAAW,EACX,kBAAkB,EAClB,UAAU,GAAG,QAAQ,EACrB,WAAW,EACX,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,WAAW,EACpB,SAAS,GAAG,0BAA0B,GACvC,GAAG,KAAK,CAAC;AACV,IAAA,MAAM,QAAQ,GAAGC,8BAAY,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;AACtE,IAAA,MAAM,OAAO,GAAGA,8BAAY,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;AACtE,IAAA,MAAM,gBAAgB,GAAGA,8BAAY,CACnC,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,gBAAgB,CACtD,CAAC;IACF,MAAM,UAAU,GAAGC,2CAAqB,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;AAC9E,IAAA,MAAM,oBAAoB,GAAGC,+CAAuB,EAAE,CAAC;AACvD,IAAAC,6CAAsB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAE5C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAGC,cAAQ,CAAC,KAAK,CAAC,CAAC;AAC1C,IAAA,MAAM,MAAM,GAAGC,iBAAW,CACxB,CAAC,OAAe,KAAI;AAClB,QAAA,UAAU,GAAG,OAAO,CAAC,CAAC;QACtB,QAAQ,CAAC,KAAK,CAAC,CAAC;AAClB,KAAC,EACD,CAAC,UAAU,CAAC,CACb,CAAC;AAEF,IAAA,MAAM,OAAO,GAAGA,iBAAW,CACzB,CAAC,CAAU,KAAI;AACb,QAAA,WAAW,GAAG,CAAC,CAAC,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;AACjB,KAAC,EACD,CAAC,WAAW,CAAC,CACd,CAAC;IAEFC,eAAS,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,WAAW,GAAGC,aAAO,CAAC,MAAK;AAC/B,QAAA,IACE,QAAQ,CAAC,MAAM,KAAK,CAAC;AACrB,aAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,EACvD;AACA,YAAA,OAAO,kBAAkB,CAAC;AAC3B,SAAA;AACD,QAAA,OAAO,gBAAgB,CAAC;KACzB,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAErD,IAAA,MAAM,WAAW,GAAGC,YAAM,CAA+B,EAAE,CAAC,CAAC;AAC7D,IAAA,MAAM,iBAAiB,GAAGA,YAAM,CAAiB,IAAI,CAAC,CAAC;;IAGvDF,eAAS,CAAC,MAAK;QACb,IAAI,SAAS,GAAG,CAAC,CAAC;AAClB,QAAA,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;;AAGpE,QAAA,IAAI,WAAW,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;YACnC,SAAS,GAAG,WAAW,CAAC,OAAO;AAC5B,iBAAA,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACZ,iBAAA,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE,YAAY,IAAI,CAAC,CAAC;AACzC,iBAAA,MAAM,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,GAAG,MAAM,CAAC,CAAC;AAC9C,SAAA;;AAGD,QAAA,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC;AAChC,YAAA,GAAG,EAAE,SAAS;AACd,YAAA,QAAQ,EAAE,QAAQ;AACnB,SAAA,CAAC,CAAC;AACL,KAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AAEf,IAAA,MAAM,cAAc,GAAGD,iBAAW,CAAC,CAAC,KAAK,KAAI;QAC3C,IAAI,CAAC,WAAW,EAAE,OAAO;AAAE,YAAA,OAAO,IAAI,CAAC;AACvC,QAAA,OAAO,CAAC,OAAO,MAAM,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC;KAC5D,EAAE,EAAE,CAAC,CAAC;AAEP,IAAA,MAAM,gBAAgB,GAAuBE,aAAO,CAClD,OAAO;QACL,SAAS,EAAE,UAAU,CAAC,MAAM;AAC5B,QAAA,IAAI,EAAE,8CAA8C;AACrD,KAAA,CAAC,EACF,CAAC,UAAU,CAAC,CACb,CAAC;AAEF,IAAA,QACEE,sBAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,yBAAyB,EAAA;AACtC,QAAAA,sBAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,UAAU,CAAC,SAAS,EAAA;YACjC,MAAM;AACP,YAAAA,sBAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,UAAU,CAAC,uBAAuB,EAAA;gBAChDA,sBAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,GAAG,EAAE,iBAAiB,EAAE,SAAS,EAAE,UAAU,CAAC,iBAAiB,EAAA;oBACjE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,MAC3BA,sBAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,cAAc,CAAC,KAAK,CAAC,EAAA;wBACzCA,sBAAC,CAAA,aAAA,CAAAC,2BAAa,EACR,EAAA,GAAA,KAAK,EACT,gBAAgB,EAAE,UAAU,CAAC,uBAAuB,EACpD,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,EAAA,CACxB,CACE,CACP,CAAC;AACD,oBAAA,OAAO,KACND,sBAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,SAAS,EAAC,MAAM,EAAA;AACnB,wBAAAA,sBAAA,CAAA,aAAA,CAACE,uBAAW,EAAG,IAAA,CAAA;AACd,wBAAA,KAAK,KACJF,sBAAG,CAAA,aAAA,CAAA,GAAA,EAAA,EAAA,SAAS,EAAC,sCAAsC,EAChD,EAAA,SAAS,CACR,CACL,CACG,CACP,CACG,CACF;AACN,YAAAA,sBAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,UAAU,CAAC,cAAc,EAAA;AACtC,gBAAA,WAAW,KACVA,sBAAC,CAAA,aAAA,CAAAG,qCAAkB,EACjB,EAAA,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,UAAU,CAAC,wBAAwB,GACrD,CACH;AACD,gBAAAH,sBAAA,CAAA,aAAA,CAACI,mBAAS,EACJ,EAAA,GAAA,KAAK,EACT,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,gBAAgB,EAAE,UAAU,CAAC,eAAe,GAC5C,CACE;AACL,YAAA,MAAM,KACLJ,sBAAC,CAAA,aAAA,CAAAK,iBAAQ,EACP,EAAA,OAAO,EAAE,MAAM,EACf,cAAc,EAAC,SAAS,EACxB,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,gBAAgB,EAClC,CAAA,CACH,CACG,CACF,EACN;AACJ;;;;"}
1
+ {"version":3,"file":"ChatPanel.js","sources":["../../../../src/components/ChatPanel.tsx"],"sourcesContent":["import React, {\n ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useLayoutEffect,\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:\n \"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 conversationId = useChatState(\n (state) => state.conversation.conversationId\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 // State to help detect initial messages rendering\n const [initialMessagesLength] = useState(messages.length);\n\n const savedPanelState = useMemo(() => {\n if (!conversationId) {\n return {};\n }\n return loadSessionState(conversationId);\n }, [conversationId]);\n\n // Handle scrolling when messages change\n useEffect(() => {\n const isInitialRender = messages.length === initialMessagesLength;\n let scrollPos = 0;\n if (isInitialRender && savedPanelState.scrollPosition !== undefined) {\n // memorized position\n scrollPos = savedPanelState?.scrollPosition;\n } else {\n messagesRef.current = messagesRef.current.slice(0, messages.length);\n // Sums up scroll heights of all messages except the last one\n if (messagesRef?.current.length > 1) {\n // position of the top of the last message\n scrollPos = messagesRef.current\n .slice(0, -1)\n .map((elem, _) => elem?.scrollHeight ?? 0)\n .reduce((total, height) => total + height);\n }\n }\n\n messagesContainer.current?.scroll({\n top: scrollPos,\n behavior: \"smooth\",\n });\n }, [messages, initialMessagesLength, savedPanelState.scrollPosition]);\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 useLayoutEffect(() => {\n const curr = messagesContainer.current;\n const onScroll = () => {\n if (!conversationId) {\n return;\n }\n saveSessionState(conversationId, {\n scrollPosition: curr?.scrollTop,\n });\n };\n curr?.addEventListener(\"scroll\", onScroll);\n return () => {\n curr?.removeEventListener(\"scroll\", onScroll);\n };\n }, [messagesContainer, conversationId]);\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\n ref={messagesContainer}\n className={cssClasses.messagesContainer}\n aria-label=\"Chat Panel Messages Container\"\n >\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\nconst BASE_STATE_LOCAL_STORAGE_KEY = \"yext_chat_panel_state\";\n\nexport function getStateLocalStorageKey(\n hostname: string,\n conversationId: string\n): string {\n return `${BASE_STATE_LOCAL_STORAGE_KEY}__${hostname}__${conversationId}`;\n}\n\n/**\n * Maintains the panel state of the session.\n */\nexport interface PanelState {\n /** The scroll position of the panel. */\n scrollPosition?: number;\n}\n\n/**\n * Loads the {@link PanelState} from local storage.\n */\nexport const loadSessionState = (conversationId: string): PanelState => {\n const hostname = window?.location?.hostname;\n if (!localStorage || !hostname) {\n return {};\n }\n const savedState = localStorage.getItem(\n getStateLocalStorageKey(hostname, conversationId)\n );\n\n if (savedState) {\n try {\n const parsedState: PanelState = JSON.parse(savedState);\n return parsedState;\n } catch (e) {\n console.warn(\"Unabled to load saved panel state: error parsing state.\");\n localStorage.removeItem(\n getStateLocalStorageKey(hostname, conversationId)\n );\n }\n }\n\n return {};\n};\n\nexport const saveSessionState = (conversationId: string, state: PanelState) => {\n const hostname = window?.location?.hostname;\n if (!localStorage || !hostname) {\n return;\n }\n localStorage.setItem(\n getStateLocalStorageKey(hostname, conversationId),\n JSON.stringify(state)\n );\n};\n"],"names":["withStylelessCssClasses","useChatState","useComposedCssClasses","useReportAnalyticsEvent","useFetchInitialMessage","useState","useCallback","useEffect","useMemo","useRef","useLayoutEffect","React","MessageBubble","LoadingDots","MessageSuggestions","ChatInput","Markdown"],"mappings":"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"}
@@ -57,6 +57,12 @@ export interface ChatPopUpProps extends Omit<ChatHeaderProps, "showCloseButton"
57
57
  * This prop will override the "showInitialMessagePopUp" prop, if specified.
58
58
  */
59
59
  ctaLabel?: string;
60
+ /**
61
+ * A controlled prop to open or close the panel. If provided, the prop
62
+ * will override the openOnLoad prop and the panel will be controlled
63
+ * by the parent component.
64
+ */
65
+ isOpen?: boolean;
60
66
  }
61
67
  /**
62
68
  * A component that renders a popup button that displays and hides
@@ -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,qBAiL9C"}
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;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,qBAgK9C"}
@@ -50,7 +50,7 @@ const popupLocalStorageKey = "YEXT_CHAT_OPEN_ON_LOAD";
50
50
  * @param props - {@link ChatPanelProps}
51
51
  */
52
52
  function ChatPopUp(props) {
53
- const { openPanelButtonIcon, customCssClasses, showRestartButton = true, onClose: customOnClose, handleError, openOnLoad = false, showInitialMessagePopUp = false, showHeartBeatAnimation = false, showUnreadNotification = false, ctaLabel, title, footer, } = props;
53
+ const { openPanelButtonIcon, customCssClasses, showRestartButton = true, onClose: customOnClose, handleError, openOnLoad = false, showInitialMessagePopUp = false, showHeartBeatAnimation = false, showUnreadNotification = false, ctaLabel, title, footer, isOpen, } = props;
54
54
  const reportAnalyticsEvent = useReportAnalyticsEvent.useReportAnalyticsEvent();
55
55
  React.useEffect(() => {
56
56
  reportAnalyticsEvent({
@@ -60,17 +60,6 @@ function ChatPopUp(props) {
60
60
  const messages = chatHeadlessReact.useChatState((s) => s.conversation.messages);
61
61
  const [numReadMessages, setNumReadMessagesLength] = React.useState(0);
62
62
  const [numUnreadMessages, setNumUnreadMessagesLength] = React.useState(0);
63
- const [showInitialMessage, setshowInitialMessage] = React.useState(
64
- //only show initial message popup (if specified) when CTA label is not provided
65
- !ctaLabel && showInitialMessagePopUp);
66
- const onCloseInitialMessage = React.useCallback(() => {
67
- setshowInitialMessage(false);
68
- }, []);
69
- // control CSS behavior (fade-in/out animation) on open/close state of the panel.
70
- const [showChat, setShowChat] = React.useState(false);
71
- // control the actual DOM rendering of the panel. Start rendering on first open state
72
- // to avoid message requests immediately on load while the popup is still "hidden"
73
- const [renderChat, setRenderChat] = React.useState(false);
74
63
  // Set the initial value of the local storage flag for opening on load only if it doesn't already exist
75
64
  if (window.localStorage.getItem(popupLocalStorageKey) === null) {
76
65
  window.localStorage.setItem(popupLocalStorageKey, openOnLoad ? "true" : "false");
@@ -79,30 +68,22 @@ function ChatPopUp(props) {
79
68
  /* Open panel on load if:
80
69
  - openOnLoad prop is true or there are messages in state (from browser storage), and local storage flag is true */
81
70
  const isOpenOnLoad = (messages.length > 1 && openOnLoadLocalStorage === "true") || openOnLoad;
71
+ const { renderChat, showChat, showInitialMessage, toggleChat, closeChat, closeInitialMessage, } = usePanelState(isOpen, isOpenOnLoad, !ctaLabel && showInitialMessagePopUp);
82
72
  // only fetch initial message when ChatPanel is closed on load (otherwise, it will be fetched in ChatPanel)
83
73
  useFetchInitialMessage.useFetchInitialMessage(showInitialMessagePopUp ? console.error : handleError, false, (showUnreadNotification || showInitialMessagePopUp) &&
84
74
  !renderChat &&
85
75
  !isOpenOnLoad);
86
- React.useEffect(() => {
87
- if (!renderChat && isOpenOnLoad) {
88
- setShowChat(true);
89
- setRenderChat(true);
90
- setshowInitialMessage(false);
91
- }
92
- }, [renderChat, messages.length, isOpenOnLoad]);
93
76
  const onClick = React.useCallback(() => {
94
- setShowChat((prev) => !prev);
95
- setRenderChat(true);
96
- setshowInitialMessage(false);
77
+ toggleChat();
97
78
  window.localStorage.setItem(popupLocalStorageKey, "true");
98
- }, []);
79
+ }, [toggleChat]);
99
80
  const onClose = React.useCallback(() => {
100
- setShowChat(false);
81
+ closeChat();
101
82
  customOnClose?.();
102
83
  // consider all the messages are read while the panel was open
103
84
  setNumReadMessagesLength(messages.length);
104
85
  window.localStorage.setItem(popupLocalStorageKey, "false");
105
- }, [customOnClose, messages.length]);
86
+ }, [closeChat, customOnClose, messages.length]);
106
87
  React.useEffect(() => {
107
88
  // update number of unread messages if there are new messages added while the panel is closed
108
89
  setNumUnreadMessagesLength(messages.length - numReadMessages);
@@ -116,7 +97,7 @@ function ChatPopUp(props) {
116
97
  React__default.default.createElement("div", { className: cssClasses.container },
117
98
  React__default.default.createElement("div", { className: panelCssClasses, "aria-label": "Chat Popup Panel" }, renderChat && (React__default.default.createElement(ChatPanel.ChatPanel, { ...props, customCssClasses: cssClasses.panelCssClasses, header: React__default.default.createElement(ChatHeader.ChatHeader, { title: title, showRestartButton: showRestartButton, showCloseButton: true, onClose: onClose, customCssClasses: cssClasses.headerCssClasses }), footer: footer }))),
118
99
  React__default.default.createElement("div", { className: closedPopupContainerCssClasses, "aria-label": "Chat Closed Popup Container" },
119
- showInitialMessage && (React__default.default.createElement(InitialMessagePopUp.InitialMessagePopUp, { onClose: onCloseInitialMessage, customCssClasses: cssClasses.initialMessagePopUpCssClasses })),
100
+ showInitialMessage && (React__default.default.createElement(InitialMessagePopUp.InitialMessagePopUp, { onClose: closeInitialMessage, customCssClasses: cssClasses.initialMessagePopUpCssClasses })),
120
101
  ctaLabel && (
121
102
  // the div container is needed to islate the expand CSS animation
122
103
  React__default.default.createElement("div", { className: cssClasses.ctaLabelContainer },
@@ -128,6 +109,52 @@ function ChatPopUp(props) {
128
109
  openPanelButtonIcon ?? (React__default.default.createElement(Chat.ChatIcon, { className: cssClasses.buttonIcon })),
129
110
  showUnreadNotification && !!numUnreadMessages && (React__default.default.createElement("div", { "aria-label": "Unread Messages Notification", className: cssClasses.notification }, numUnreadMessages)))))));
130
111
  }
112
+ function usePanelState(isOpen, isOpenOnLoad, initialMessageVisible) {
113
+ // control CSS behavior (fade-in/out animation) on open/close state of the panel.
114
+ const [showChat, setShowChat] = React.useState(false);
115
+ // control the actual DOM rendering of the panel. Start rendering on first open state
116
+ // to avoid message requests immediately on load while the popup is still "hidden"
117
+ const [renderChat, setRenderChat] = React.useState(false);
118
+ const [showInitialMessage, setshowInitialMessage] = React.useState(initialMessageVisible);
119
+ React.useEffect(() => {
120
+ if (isOpen !== undefined) {
121
+ setShowChat(isOpen);
122
+ setRenderChat(isOpen);
123
+ }
124
+ }, [isOpen]);
125
+ React.useEffect(() => {
126
+ if (!renderChat && isOpenOnLoad && isOpen === undefined) {
127
+ setShowChat(true);
128
+ setRenderChat(true);
129
+ setshowInitialMessage(false);
130
+ }
131
+ }, [renderChat, isOpen, isOpenOnLoad]);
132
+ const toggleChat = React.useCallback(() => {
133
+ if (isOpen !== undefined) {
134
+ return;
135
+ }
136
+ setShowChat((prev) => !prev);
137
+ setRenderChat(true);
138
+ setshowInitialMessage(false);
139
+ }, [isOpen]);
140
+ const closeChat = React.useCallback(() => {
141
+ if (isOpen !== undefined) {
142
+ return;
143
+ }
144
+ setShowChat(false);
145
+ }, [isOpen]);
146
+ const closeInitialMessage = React.useCallback(() => {
147
+ setshowInitialMessage(false);
148
+ }, []);
149
+ return {
150
+ showChat,
151
+ renderChat,
152
+ showInitialMessage,
153
+ toggleChat,
154
+ closeChat,
155
+ closeInitialMessage,
156
+ };
157
+ }
131
158
 
132
159
  exports.ChatPopUp = ChatPopUp;
133
160
  //# sourceMappingURL=ChatPopUp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatPopUp.js","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":["withStylelessCssClasses","useReportAnalyticsEvent","useEffect","useChatState","useState","useCallback","useFetchInitialMessage","useComposedCssClasses","twMerge","React","ChatPanel","ChatHeader","InitialMessagePopUp","ChatIcon"],"mappings":"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"}
1
+ {"version":3,"file":"ChatPopUp.js","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 * A controlled prop to open or close the panel. If provided, the prop\n * will override the openOnLoad prop and the panel will be controlled\n * by the parent component.\n */\n isOpen?: boolean;\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 isOpen,\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 // Set the initial value of the local storage flag for opening on load only if it doesn't already exist\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 const {\n renderChat,\n showChat,\n showInitialMessage,\n toggleChat,\n closeChat,\n closeInitialMessage,\n } = usePanelState(isOpen, isOpenOnLoad, !ctaLabel && showInitialMessagePopUp);\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 const onClick = useCallback(() => {\n toggleChat();\n window.localStorage.setItem(popupLocalStorageKey, \"true\");\n }, [toggleChat]);\n\n const onClose = useCallback(() => {\n closeChat();\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 }, [closeChat, 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={closeInitialMessage}\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\nfunction usePanelState(\n isOpen: boolean | undefined,\n isOpenOnLoad: boolean | undefined,\n initialMessageVisible: boolean | undefined\n) {\n // control CSS behavior (fade-in/out animation) on open/close state of the panel.\n const [showChat, setShowChat] = useState(false);\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 const [showInitialMessage, setshowInitialMessage] = useState(\n initialMessageVisible\n );\n\n useEffect(() => {\n if (isOpen !== undefined) {\n setShowChat(isOpen);\n setRenderChat(isOpen);\n }\n }, [isOpen]);\n\n useEffect(() => {\n if (!renderChat && isOpenOnLoad && isOpen === undefined) {\n setShowChat(true);\n setRenderChat(true);\n setshowInitialMessage(false);\n }\n }, [renderChat, isOpen, isOpenOnLoad]);\n\n const toggleChat = useCallback(() => {\n if (isOpen !== undefined) {\n return;\n }\n setShowChat((prev) => !prev);\n setRenderChat(true);\n setshowInitialMessage(false);\n }, [isOpen]);\n\n const closeChat = useCallback(() => {\n if (isOpen !== undefined) {\n return;\n }\n setShowChat(false);\n }, [isOpen]);\n\n const closeInitialMessage = useCallback(() => {\n setshowInitialMessage(false);\n }, []);\n\n return {\n showChat,\n renderChat,\n showInitialMessage,\n toggleChat,\n closeChat,\n closeInitialMessage,\n };\n}\n"],"names":["withStylelessCssClasses","useReportAnalyticsEvent","useEffect","useChatState","useState","useFetchInitialMessage","useCallback","useComposedCssClasses","twMerge","React","ChatPanel","ChatHeader","InitialMessagePopUp","ChatIcon"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../../../src/components/Markdown.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAevC;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,UAAU,aAAa;IACrB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,kBAAkB,CAAC;IACtC;;;OAGG;IACH,cAAc,CAAC,EAAE,SAAS,GAAG,iBAAiB,CAAC;IAC/C,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,WAAW,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,UAAU,EACV,gBAAgB,EAChB,cAAkC,EAClC,UAAU,EACV,WAAW,GACZ,EAAE,aAAa,qBAgDf"}
1
+ {"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../../../src/components/Markdown.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAevC;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,UAAU,aAAa;IACrB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,kBAAkB,CAAC;IACtC;;;OAGG;IACH,cAAc,CAAC,EAAE,SAAS,GAAG,iBAAiB,CAAC;IAC/C,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,WAAW,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,UAAU,EACV,gBAAgB,EAChB,cAAkC,EAClC,UAAU,EACV,WAAW,GACZ,EAAE,aAAa,qBAgDf"}
@@ -1 +1 @@
1
- {"version":3,"file":"Markdown.js","sources":["../../../../src/components/Markdown.tsx"],"sourcesContent":["import ReactMarkdown, { Options } from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport rehypeRaw from \"rehype-raw\";\nimport rehypeSanitize from \"rehype-sanitize\";\nimport React, { useMemo } from \"react\";\nimport { useReportAnalyticsEvent } from \"../hooks/useReportAnalyticsEvent\";\nimport { useComposedCssClasses } from \"../hooks/useComposedCssClasses\";\n\n// The Remark and Rehype plugins to use in conjunction with ReactMarkdown.\nconst unifiedPlugins: { remark?: Options['remarkPlugins']; rehype: Options['rehypePlugins'] } = {\n remark: [\n remarkGfm, //renders Github-Flavored Markdown\n ],\n rehype: [\n rehypeRaw, //to support HTML embedded in markdown\n rehypeSanitize, //to sanitize HTML content\n ],\n};\n\n/**\n * The CSS class interface for the Markdown component.\n *\n * @internal\n */\nexport interface MarkdownCssClasses {\n container?: string;\n link?: string;\n}\n\nconst builtInCssClasses: MarkdownCssClasses = {\n link: \"cursor-pointer\",\n};\n\ninterface MarkdownProps {\n /** Stringified markdown. */\n content: string;\n /** The response ID correlates to the current message. */\n responseId?: string;\n /** CSS classes for customizing the component styling. */\n customCssClasses?: MarkdownCssClasses;\n /**\n * Action to report for analytics event when a link is clicked.\n * Defaults to 'CHAT_LINK_CLICK'.\n */\n linkClickEvent?: \"WEBSITE\" | \"CHAT_LINK_CLICK\";\n /** Link target open behavior on click. */\n linkTarget?: string;\n /** A callback which is called when a link is clicked. */\n onLinkClick?: (href?: string) => void;\n}\n\n/**\n * Renders Github-Flavored Markdown from the Knowledge Graph. This Markdown can include\n * arbitrary HTML. Any HTML will be sanitized according to Rehype's default Schema.\n *\n * @remarks\n * A link click will send a CHAT_LINK_CLICK analytics event\n *\n * @internal\n */\nexport function Markdown({\n content,\n responseId,\n customCssClasses,\n linkClickEvent = \"CHAT_LINK_CLICK\",\n linkTarget,\n onLinkClick,\n}: MarkdownProps) {\n const reportAnalyticsEvent = useReportAnalyticsEvent();\n const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);\n\n const components: Options[\"components\"] = useMemo(() => {\n const createClickHandlerFn = (href?: string) => () => {\n reportAnalyticsEvent({\n action: linkClickEvent,\n destinationUrl: href,\n chat: {\n responseId,\n },\n });\n onLinkClick?.(href);\n };\n return {\n a: ({ node: _, children, ...props }) => {\n return (\n <a\n {...props}\n onClick={createClickHandlerFn(props.href)}\n target={linkTarget}\n rel=\"noopener noreferrer\"\n className={cssClasses.link}\n >\n {children}\n </a>\n );\n },\n };\n }, [\n reportAnalyticsEvent,\n linkClickEvent,\n responseId,\n cssClasses,\n linkTarget,\n onLinkClick,\n ]);\n\n return (\n <ReactMarkdown\n className={cssClasses.container}\n children={content}\n remarkPlugins={unifiedPlugins.remark}\n rehypePlugins={unifiedPlugins.rehype}\n components={components}\n />\n );\n}\n"],"names":["remarkGfm","rehypeRaw","rehypeSanitize","useReportAnalyticsEvent","useComposedCssClasses","useMemo","React","ReactMarkdown"],"mappings":";;;;;;;;;;;;;;;;;;AAQA;AACA,MAAM,cAAc,GAA4E;AAC9F,IAAA,MAAM,EAAE;AACN,QAAAA,0BAAS;AACV,KAAA;AACD,IAAA,MAAM,EAAE;QACNC,0BAAS;AACT,QAAAC,+BAAc;AACf,KAAA;CACF,CAAC;AAYF,MAAM,iBAAiB,GAAuB;AAC5C,IAAA,IAAI,EAAE,gBAAgB;CACvB,CAAC;AAoBF;;;;;;;;AAQG;SACa,QAAQ,CAAC,EACvB,OAAO,EACP,UAAU,EACV,gBAAgB,EAChB,cAAc,GAAG,iBAAiB,EAClC,UAAU,EACV,WAAW,GACG,EAAA;AACd,IAAA,MAAM,oBAAoB,GAAGC,+CAAuB,EAAE,CAAC;IACvD,MAAM,UAAU,GAAGC,2CAAqB,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;AAE9E,IAAA,MAAM,UAAU,GAA0BC,aAAO,CAAC,MAAK;QACrD,MAAM,oBAAoB,GAAG,CAAC,IAAa,KAAK,MAAK;AACnD,YAAA,oBAAoB,CAAC;AACnB,gBAAA,MAAM,EAAE,cAAc;AACtB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,IAAI,EAAE;oBACJ,UAAU;AACX,iBAAA;AACF,aAAA,CAAC,CAAC;AACH,YAAA,WAAW,GAAG,IAAI,CAAC,CAAC;AACtB,SAAC,CAAC;QACF,OAAO;AACL,YAAA,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,KAAI;AACrC,gBAAA,QACEC,sBAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAA,GACM,KAAK,EACT,OAAO,EAAE,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,EACzC,MAAM,EAAE,UAAU,EAClB,GAAG,EAAC,qBAAqB,EACzB,SAAS,EAAE,UAAU,CAAC,IAAI,EAAA,EAEzB,QAAQ,CACP,EACJ;aACH;SACF,CAAC;AACJ,KAAC,EAAE;QACD,oBAAoB;QACpB,cAAc;QACd,UAAU;QACV,UAAU;QACV,UAAU;QACV,WAAW;AACZ,KAAA,CAAC,CAAC;AAEH,IAAA,QACEA,sBAAA,CAAA,aAAA,CAACC,8BAAa,EAAA,EACZ,SAAS,EAAE,UAAU,CAAC,SAAS,EAC/B,QAAQ,EAAE,OAAO,EACjB,aAAa,EAAE,cAAc,CAAC,MAAM,EACpC,aAAa,EAAE,cAAc,CAAC,MAAM,EACpC,UAAU,EAAE,UAAU,EAAA,CACtB,EACF;AACJ;;;;"}
1
+ {"version":3,"file":"Markdown.js","sources":["../../../../src/components/Markdown.tsx"],"sourcesContent":["import ReactMarkdown, {\n PluggableList,\n ReactMarkdownOptions,\n} from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport rehypeRaw from \"rehype-raw\";\nimport rehypeSanitize from \"rehype-sanitize\";\nimport React, { useMemo } from \"react\";\nimport { useReportAnalyticsEvent } from \"../hooks/useReportAnalyticsEvent\";\nimport { useComposedCssClasses } from \"../hooks/useComposedCssClasses\";\n\n// The Remark and Rehype plugins to use in conjunction with ReactMarkdown.\nconst unifiedPlugins: { remark?: PluggableList; rehype: PluggableList } = {\n remark: [\n remarkGfm, //renders Github-Flavored Markdown\n ],\n rehype: [\n rehypeRaw, //to support HTML embedded in markdown\n rehypeSanitize, //to sanitize HTML content\n ],\n};\n\n/**\n * The CSS class interface for the Markdown component.\n *\n * @internal\n */\nexport interface MarkdownCssClasses {\n container?: string;\n link?: string;\n}\n\nconst builtInCssClasses: MarkdownCssClasses = {\n link: \"cursor-pointer\",\n};\n\ninterface MarkdownProps {\n /** Stringified markdown. */\n content: string;\n /** The response ID correlates to the current message. */\n responseId?: string;\n /** CSS classes for customizing the component styling. */\n customCssClasses?: MarkdownCssClasses;\n /**\n * Action to report for analytics event when a link is clicked.\n * Defaults to 'CHAT_LINK_CLICK'.\n */\n linkClickEvent?: \"WEBSITE\" | \"CHAT_LINK_CLICK\";\n /** Link target open behavior on click. */\n linkTarget?: string;\n /** A callback which is called when a link is clicked. */\n onLinkClick?: (href?: string) => void;\n}\n\n/**\n * Renders Github-Flavored Markdown from the Knowledge Graph. This Markdown can include\n * arbitrary HTML. Any HTML will be sanitized according to Rehype's default Schema.\n *\n * @remarks\n * A link click will send a CHAT_LINK_CLICK analytics event\n *\n * @internal\n */\nexport function Markdown({\n content,\n responseId,\n customCssClasses,\n linkClickEvent = \"CHAT_LINK_CLICK\",\n linkTarget,\n onLinkClick,\n}: MarkdownProps) {\n const reportAnalyticsEvent = useReportAnalyticsEvent();\n const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);\n\n const components: ReactMarkdownOptions[\"components\"] = useMemo(() => {\n const createClickHandlerFn = (href?: string) => () => {\n reportAnalyticsEvent({\n action: linkClickEvent,\n destinationUrl: href,\n chat: {\n responseId,\n },\n });\n onLinkClick?.(href);\n };\n return {\n a: ({ node: _, children, ...props }) => {\n return (\n <a\n {...props}\n onClick={createClickHandlerFn(props.href)}\n target={linkTarget}\n rel=\"noopener noreferrer\"\n className={cssClasses.link}\n >\n {children}\n </a>\n );\n },\n };\n }, [\n reportAnalyticsEvent,\n linkClickEvent,\n responseId,\n cssClasses,\n linkTarget,\n onLinkClick,\n ]);\n\n return (\n <ReactMarkdown\n className={cssClasses.container}\n children={content}\n remarkPlugins={unifiedPlugins.remark}\n rehypePlugins={unifiedPlugins.rehype}\n components={components}\n />\n );\n}\n"],"names":["remarkGfm","rehypeRaw","rehypeSanitize","useReportAnalyticsEvent","useComposedCssClasses","useMemo","React","ReactMarkdown"],"mappings":";;;;;;;;;;;;;;;;;;AAWA;AACA,MAAM,cAAc,GAAsD;AACxE,IAAA,MAAM,EAAE;AACN,QAAAA,0BAAS;AACV,KAAA;AACD,IAAA,MAAM,EAAE;QACNC,0BAAS;AACT,QAAAC,+BAAc;AACf,KAAA;CACF,CAAC;AAYF,MAAM,iBAAiB,GAAuB;AAC5C,IAAA,IAAI,EAAE,gBAAgB;CACvB,CAAC;AAoBF;;;;;;;;AAQG;SACa,QAAQ,CAAC,EACvB,OAAO,EACP,UAAU,EACV,gBAAgB,EAChB,cAAc,GAAG,iBAAiB,EAClC,UAAU,EACV,WAAW,GACG,EAAA;AACd,IAAA,MAAM,oBAAoB,GAAGC,+CAAuB,EAAE,CAAC;IACvD,MAAM,UAAU,GAAGC,2CAAqB,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;AAE9E,IAAA,MAAM,UAAU,GAAuCC,aAAO,CAAC,MAAK;QAClE,MAAM,oBAAoB,GAAG,CAAC,IAAa,KAAK,MAAK;AACnD,YAAA,oBAAoB,CAAC;AACnB,gBAAA,MAAM,EAAE,cAAc;AACtB,gBAAA,cAAc,EAAE,IAAI;AACpB,gBAAA,IAAI,EAAE;oBACJ,UAAU;AACX,iBAAA;AACF,aAAA,CAAC,CAAC;AACH,YAAA,WAAW,GAAG,IAAI,CAAC,CAAC;AACtB,SAAC,CAAC;QACF,OAAO;AACL,YAAA,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,KAAI;AACrC,gBAAA,QACEC,sBAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAA,GACM,KAAK,EACT,OAAO,EAAE,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,EACzC,MAAM,EAAE,UAAU,EAClB,GAAG,EAAC,qBAAqB,EACzB,SAAS,EAAE,UAAU,CAAC,IAAI,EAAA,EAEzB,QAAQ,CACP,EACJ;aACH;SACF,CAAC;AACJ,KAAC,EAAE;QACD,oBAAoB;QACpB,cAAc;QACd,UAAU;QACV,UAAU;QACV,UAAU;QACV,WAAW;AACZ,KAAA,CAAC,CAAC;AAEH,IAAA,QACEA,sBAAA,CAAA,aAAA,CAACC,8BAAa,EAAA,EACZ,SAAS,EAAE,UAAU,CAAC,SAAS,EAC/B,QAAQ,EAAE,OAAO,EACjB,aAAa,EAAE,cAAc,CAAC,MAAM,EACpC,aAAa,EAAE,cAAc,CAAC,MAAM,EACpC,UAAU,EAAE,UAAU,EAAA,CACtB,EACF;AACJ;;;;"}
@@ -243,6 +243,12 @@ export declare interface ChatPopUpProps extends Omit<ChatHeaderProps, "showClose
243
243
  * This prop will override the "showInitialMessagePopUp" prop, if specified.
244
244
  */
245
245
  ctaLabel?: string;
246
+ /**
247
+ * A controlled prop to open or close the panel. If provided, the prop
248
+ * will override the openOnLoad prop and the panel will be controlled
249
+ * by the parent component.
250
+ */
251
+ isOpen?: boolean;
246
252
  }
247
253
 
248
254
  /**
@@ -1,4 +1,4 @@
1
- var version = "0.11.3";
1
+ var version = "0.12.0";
2
2
 
3
3
  export { version };
4
4
  //# sourceMappingURL=package.json.mjs.map
@@ -58,4 +58,17 @@ export interface ChatPanelProps extends Omit<MessageBubbleProps, "customCssClass
58
58
  * @param props - {@link ChatPanelProps}
59
59
  */
60
60
  export declare function ChatPanel(props: ChatPanelProps): React.JSX.Element;
61
+ export declare function getStateLocalStorageKey(hostname: string, conversationId: string): string;
62
+ /**
63
+ * Maintains the panel state of the session.
64
+ */
65
+ export interface PanelState {
66
+ /** The scroll position of the panel. */
67
+ scrollPosition?: number;
68
+ }
69
+ /**
70
+ * Loads the {@link PanelState} from local storage.
71
+ */
72
+ export declare const loadSessionState: (conversationId: string) => PanelState;
73
+ export declare const saveSessionState: (conversationId: string, state: PanelState) => void;
61
74
  //# sourceMappingURL=ChatPanel.d.ts.map
@@ -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;;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"}
1
+ {"version":3,"file":"ChatPanel.d.ts","sourceRoot":"","sources":["../../../../src/components/ChatPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,SAAS,EAOV,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;AAiBD;;;;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,qBA6L9C;AAID,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACrB,MAAM,CAER;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,wCAAwC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,mBAAoB,MAAM,KAAG,UAsBzD,CAAC;AAEF,eAAO,MAAM,gBAAgB,mBAAoB,MAAM,SAAS,UAAU,SASzE,CAAC"}