@yext/chat-ui-react 0.1.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 (150) hide show
  1. package/LICENSE +33 -0
  2. package/README.md +44 -0
  3. package/THIRD-PARTY-NOTICES +2106 -0
  4. package/lib/bundle.css +1 -0
  5. package/lib/commonjs/components/ChatHeader.d.ts +51 -0
  6. package/lib/commonjs/components/ChatHeader.d.ts.map +1 -0
  7. package/lib/commonjs/components/ChatHeader.js +42 -0
  8. package/lib/commonjs/components/ChatHeader.js.map +1 -0
  9. package/lib/commonjs/components/ChatInput.d.ts +48 -0
  10. package/lib/commonjs/components/ChatInput.d.ts.map +1 -0
  11. package/lib/commonjs/components/ChatInput.js +50 -0
  12. package/lib/commonjs/components/ChatInput.js.map +1 -0
  13. package/lib/commonjs/components/ChatPanel.d.ts +39 -0
  14. package/lib/commonjs/components/ChatPanel.d.ts.map +1 -0
  15. package/lib/commonjs/components/ChatPanel.js +54 -0
  16. package/lib/commonjs/components/ChatPanel.js.map +1 -0
  17. package/lib/commonjs/components/ChatPopUp.d.ts +42 -0
  18. package/lib/commonjs/components/ChatPopUp.d.ts.map +1 -0
  19. package/lib/commonjs/components/ChatPopUp.js +45 -0
  20. package/lib/commonjs/components/ChatPopUp.js.map +1 -0
  21. package/lib/commonjs/components/LoadingDots.d.ts +9 -0
  22. package/lib/commonjs/components/LoadingDots.d.ts.map +1 -0
  23. package/lib/commonjs/components/LoadingDots.js +15 -0
  24. package/lib/commonjs/components/LoadingDots.js.map +1 -0
  25. package/lib/commonjs/components/Markdown.d.ts +13 -0
  26. package/lib/commonjs/components/Markdown.d.ts.map +1 -0
  27. package/lib/commonjs/components/Markdown.js +32 -0
  28. package/lib/commonjs/components/Markdown.js.map +1 -0
  29. package/lib/commonjs/components/MessageBubble.d.ts +49 -0
  30. package/lib/commonjs/components/MessageBubble.d.ts.map +1 -0
  31. package/lib/commonjs/components/MessageBubble.js +54 -0
  32. package/lib/commonjs/components/MessageBubble.js.map +1 -0
  33. package/lib/commonjs/components/index.d.ts +11 -0
  34. package/lib/commonjs/components/index.d.ts.map +1 -0
  35. package/lib/commonjs/components/index.js +14 -0
  36. package/lib/commonjs/components/index.js.map +1 -0
  37. package/lib/commonjs/hooks/index.d.ts +2 -0
  38. package/lib/commonjs/hooks/index.d.ts.map +1 -0
  39. package/lib/commonjs/hooks/index.js +6 -0
  40. package/lib/commonjs/hooks/index.js.map +1 -0
  41. package/lib/commonjs/hooks/useComposedCssClasses.d.ts +30 -0
  42. package/lib/commonjs/hooks/useComposedCssClasses.d.ts.map +1 -0
  43. package/lib/commonjs/hooks/useComposedCssClasses.js +60 -0
  44. package/lib/commonjs/hooks/useComposedCssClasses.js.map +1 -0
  45. package/lib/commonjs/icons/Arrow.d.ts +3 -0
  46. package/lib/commonjs/icons/Arrow.d.ts.map +1 -0
  47. package/lib/commonjs/icons/Arrow.js +9 -0
  48. package/lib/commonjs/icons/Arrow.js.map +1 -0
  49. package/lib/commonjs/icons/Cross.d.ts +3 -0
  50. package/lib/commonjs/icons/Cross.d.ts.map +1 -0
  51. package/lib/commonjs/icons/Cross.js +9 -0
  52. package/lib/commonjs/icons/Cross.js.map +1 -0
  53. package/lib/commonjs/icons/DualSync.d.ts +3 -0
  54. package/lib/commonjs/icons/DualSync.d.ts.map +1 -0
  55. package/lib/commonjs/icons/DualSync.js +9 -0
  56. package/lib/commonjs/icons/DualSync.js.map +1 -0
  57. package/lib/commonjs/icons/Message.d.ts +3 -0
  58. package/lib/commonjs/icons/Message.d.ts.map +1 -0
  59. package/lib/commonjs/icons/Message.js +9 -0
  60. package/lib/commonjs/icons/Message.js.map +1 -0
  61. package/lib/commonjs/index.d.ts +3 -0
  62. package/lib/commonjs/index.d.ts.map +1 -0
  63. package/lib/commonjs/index.js +19 -0
  64. package/lib/commonjs/index.js.map +1 -0
  65. package/lib/commonjs/utils/defaultHandleError.d.ts +9 -0
  66. package/lib/commonjs/utils/defaultHandleError.d.ts.map +1 -0
  67. package/lib/commonjs/utils/defaultHandleError.js +15 -0
  68. package/lib/commonjs/utils/defaultHandleError.js.map +1 -0
  69. package/lib/esm/components/ChatHeader.d.ts +51 -0
  70. package/lib/esm/components/ChatHeader.d.ts.map +1 -0
  71. package/lib/esm/components/ChatHeader.js +38 -0
  72. package/lib/esm/components/ChatHeader.js.map +1 -0
  73. package/lib/esm/components/ChatInput.d.ts +48 -0
  74. package/lib/esm/components/ChatInput.d.ts.map +1 -0
  75. package/lib/esm/components/ChatInput.js +43 -0
  76. package/lib/esm/components/ChatInput.js.map +1 -0
  77. package/lib/esm/components/ChatPanel.d.ts +39 -0
  78. package/lib/esm/components/ChatPanel.d.ts.map +1 -0
  79. package/lib/esm/components/ChatPanel.js +50 -0
  80. package/lib/esm/components/ChatPanel.js.map +1 -0
  81. package/lib/esm/components/ChatPopUp.d.ts +42 -0
  82. package/lib/esm/components/ChatPopUp.d.ts.map +1 -0
  83. package/lib/esm/components/ChatPopUp.js +41 -0
  84. package/lib/esm/components/ChatPopUp.js.map +1 -0
  85. package/lib/esm/components/LoadingDots.d.ts +9 -0
  86. package/lib/esm/components/LoadingDots.d.ts.map +1 -0
  87. package/lib/esm/components/LoadingDots.js +11 -0
  88. package/lib/esm/components/LoadingDots.js.map +1 -0
  89. package/lib/esm/components/Markdown.d.ts +13 -0
  90. package/lib/esm/components/Markdown.d.ts.map +1 -0
  91. package/lib/esm/components/Markdown.js +25 -0
  92. package/lib/esm/components/Markdown.js.map +1 -0
  93. package/lib/esm/components/MessageBubble.d.ts +49 -0
  94. package/lib/esm/components/MessageBubble.d.ts.map +1 -0
  95. package/lib/esm/components/MessageBubble.js +50 -0
  96. package/lib/esm/components/MessageBubble.js.map +1 -0
  97. package/lib/esm/components/index.d.ts +11 -0
  98. package/lib/esm/components/index.d.ts.map +1 -0
  99. package/lib/esm/components/index.js +6 -0
  100. package/lib/esm/components/index.js.map +1 -0
  101. package/lib/esm/hooks/index.d.ts +2 -0
  102. package/lib/esm/hooks/index.d.ts.map +1 -0
  103. package/lib/esm/hooks/index.js +2 -0
  104. package/lib/esm/hooks/index.js.map +1 -0
  105. package/lib/esm/hooks/useComposedCssClasses.d.ts +30 -0
  106. package/lib/esm/hooks/useComposedCssClasses.d.ts.map +1 -0
  107. package/lib/esm/hooks/useComposedCssClasses.js +56 -0
  108. package/lib/esm/hooks/useComposedCssClasses.js.map +1 -0
  109. package/lib/esm/icons/Arrow.d.ts +3 -0
  110. package/lib/esm/icons/Arrow.d.ts.map +1 -0
  111. package/lib/esm/icons/Arrow.js +5 -0
  112. package/lib/esm/icons/Arrow.js.map +1 -0
  113. package/lib/esm/icons/Cross.d.ts +3 -0
  114. package/lib/esm/icons/Cross.d.ts.map +1 -0
  115. package/lib/esm/icons/Cross.js +5 -0
  116. package/lib/esm/icons/Cross.js.map +1 -0
  117. package/lib/esm/icons/DualSync.d.ts +3 -0
  118. package/lib/esm/icons/DualSync.d.ts.map +1 -0
  119. package/lib/esm/icons/DualSync.js +5 -0
  120. package/lib/esm/icons/DualSync.js.map +1 -0
  121. package/lib/esm/icons/Message.d.ts +3 -0
  122. package/lib/esm/icons/Message.d.ts.map +1 -0
  123. package/lib/esm/icons/Message.js +5 -0
  124. package/lib/esm/icons/Message.js.map +1 -0
  125. package/lib/esm/index.d.ts +266 -0
  126. package/lib/esm/index.d.ts.map +1 -0
  127. package/lib/esm/index.js +3 -0
  128. package/lib/esm/index.js.map +1 -0
  129. package/lib/esm/tsdoc-metadata.json +11 -0
  130. package/lib/esm/utils/defaultHandleError.d.ts +9 -0
  131. package/lib/esm/utils/defaultHandleError.d.ts.map +1 -0
  132. package/lib/esm/utils/defaultHandleError.js +11 -0
  133. package/lib/esm/utils/defaultHandleError.js.map +1 -0
  134. package/package.json +95 -0
  135. package/src/components/ChatHeader.tsx +118 -0
  136. package/src/components/ChatInput.tsx +129 -0
  137. package/src/components/ChatPanel.tsx +108 -0
  138. package/src/components/ChatPopUp.tsx +112 -0
  139. package/src/components/LoadingDots.tsx +22 -0
  140. package/src/components/Markdown.tsx +36 -0
  141. package/src/components/MessageBubble.tsx +125 -0
  142. package/src/components/index.ts +17 -0
  143. package/src/hooks/index.ts +1 -0
  144. package/src/hooks/useComposedCssClasses.ts +62 -0
  145. package/src/icons/Arrow.tsx +8 -0
  146. package/src/icons/Cross.tsx +8 -0
  147. package/src/icons/DualSync.tsx +8 -0
  148. package/src/icons/Message.tsx +10 -0
  149. package/src/index.ts +2 -0
  150. package/src/utils/defaultHandleError.ts +10 -0
@@ -0,0 +1,266 @@
1
+ /// <reference types="react" />
2
+
3
+ import { JSX as JSX_2 } from 'react/jsx-runtime';
4
+ import { Message } from '@yext/chat-headless-react';
5
+
6
+ /**
7
+ * A component that renders the header of a chat bot panel,
8
+ * including the title and a button to reset the conversation.
9
+ *
10
+ * @public
11
+ *
12
+ * @param props - {@link ChatHeaderProps}
13
+ */
14
+ export declare function ChatHeader({ title, showRestartButton, restartButtonIcon, showCloseButton, closeButtonIcon, onClose, customCssClasses, }: ChatHeaderProps): JSX_2.Element;
15
+
16
+ /**
17
+ * The CSS class interface for the {@link ChatHeader} component.
18
+ *
19
+ * @public
20
+ */
21
+ export declare interface ChatHeaderCssClasses {
22
+ header?: string;
23
+ title?: string;
24
+ restartButton?: string;
25
+ closeButton?: string;
26
+ }
27
+
28
+ /**
29
+ * The props for the {@link ChatHeader} component.
30
+ *
31
+ * @public
32
+ */
33
+ export declare interface ChatHeaderProps {
34
+ /**
35
+ * The headers's title text, essentially how the chat window identifies itself to the user.
36
+ */
37
+ title: string;
38
+ /**
39
+ * Displays a restart button which allows the user to restart the conversation.
40
+ * Defaults to false.
41
+ */
42
+ showRestartButton?: boolean;
43
+ /**
44
+ * Displays a close button which will invoke {@link ChatHeaderProps.onClose} on click.
45
+ * Default to false.
46
+ */
47
+ showCloseButton?: boolean;
48
+ /** A function which is called when the close button is clicked. */
49
+ onClose?: () => void;
50
+ /** Custom icon for for restart button. */
51
+ restartButtonIcon?: JSX.Element;
52
+ /** Custom icon for for close button. */
53
+ closeButtonIcon?: JSX.Element;
54
+ /** CSS classes for customizing the component styling. */
55
+ customCssClasses?: ChatHeaderCssClasses;
56
+ }
57
+
58
+ /**
59
+ * A component that allows user to input message and send to Chat API.
60
+ * @public
61
+ *
62
+ * @param props - {@link ChatInputProps}
63
+ */
64
+ export declare function ChatInput({ placeholder, stream, inputAutoFocus, handleError, sendButtonIcon, customCssClasses, }: ChatInputProps): JSX_2.Element;
65
+
66
+ /**
67
+ * The CSS class interface for the {@link ChatInput} component.
68
+ *
69
+ * @public
70
+ */
71
+ export declare interface ChatInputCssClasses {
72
+ container?: string;
73
+ textArea?: string;
74
+ sendButton?: string;
75
+ }
76
+
77
+ /**
78
+ * The props for the {@link ChatInput} component.
79
+ *
80
+ * @public
81
+ */
82
+ export declare interface ChatInputProps {
83
+ /**
84
+ * The input's placeholder text when no text has been entered by the user.
85
+ * Defaults to "Type a message...".
86
+ */
87
+ placeholder?: string;
88
+ /**
89
+ * Enable streaming behavior by making a request to Chat Streaming API.
90
+ * Defaults to true.
91
+ */
92
+ stream?: boolean;
93
+ /** Enable auto focus for the input box. Defaults to false. */
94
+ inputAutoFocus?: boolean;
95
+ /**
96
+ * A function which is called when an error occurs from
97
+ * Chat API while processing the user's message.
98
+ * By default, the error is logged to the console.
99
+ */
100
+ handleError?: (e: unknown) => void;
101
+ /** Custom icon for the send button. */
102
+ sendButtonIcon?: JSX.Element;
103
+ /** CSS classes for customizing the component styling. */
104
+ customCssClasses?: ChatInputCssClasses;
105
+ }
106
+
107
+ /**
108
+ * A component that renders a full panel for chat bot interactions. This includes
109
+ * the message bubbles for the conversation, input box with send button, and header
110
+ * (if provided).
111
+ *
112
+ * @public
113
+ *
114
+ * @param props - {@link ChatPanelProps}
115
+ */
116
+ export declare function ChatPanel(props: ChatPanelProps): JSX_2.Element;
117
+
118
+ /**
119
+ * The CSS class interface for the {@link ChatPanel} component.
120
+ *
121
+ * @public
122
+ */
123
+ export declare interface ChatPanelCssClasses {
124
+ container?: string;
125
+ messagesContainer?: string;
126
+ inputContainer?: string;
127
+ inputCssClasses?: ChatInputCssClasses;
128
+ messageBubbleCssClasses?: MessageBubbleCssClasses;
129
+ }
130
+
131
+ /**
132
+ * The props for the {@link ChatPanel} component.
133
+ *
134
+ * @public
135
+ */
136
+ export declare interface ChatPanelProps extends Omit<MessageBubbleProps, "customCssClasses" | "message">, Omit<ChatInputProps, "customCssClasses"> {
137
+ /** A header to render at the top of the panel. */
138
+ header?: JSX.Element;
139
+ /**
140
+ * CSS classes for customizing the component styling.
141
+ */
142
+ customCssClasses?: ChatPanelCssClasses;
143
+ }
144
+
145
+ /**
146
+ * A component that renders a popup button that displays and hides
147
+ * a panel for chat bot interactions.
148
+ *
149
+ * @public
150
+ *
151
+ * @param props - {@link ChatPanelProps}
152
+ */
153
+ export declare function ChatPopUp(props: ChatPopUpProps): JSX_2.Element;
154
+
155
+ /**
156
+ * The CSS class interface for the {@link ChatPopUp} component.
157
+ *
158
+ * @public
159
+ */
160
+ export declare interface ChatPopUpCssClasses {
161
+ container?: string;
162
+ panel?: string;
163
+ panel__display?: string;
164
+ panel__hidden?: string;
165
+ button?: string;
166
+ button__display?: string;
167
+ button__hidden?: string;
168
+ headerCssClasses?: ChatHeaderCssClasses;
169
+ panelCssClasses?: ChatPanelCssClasses;
170
+ }
171
+
172
+ /**
173
+ * The props for the {@link ChatPopUp} component.
174
+ *
175
+ * @public
176
+ */
177
+ export declare interface ChatPopUpProps extends Omit<ChatHeaderProps, "showCloseButton" | "customCssClasses">, Omit<ChatPanelProps, "header" | "customCssClasses"> {
178
+ /** Custom icon for the popup button to open the panel. */
179
+ openPanelButtonIcon?: JSX.Element;
180
+ /**
181
+ * CSS classes for customizing the component styling.
182
+ */
183
+ customCssClasses?: ChatPopUpCssClasses;
184
+ }
185
+
186
+ /**
187
+ * A component that displays the provided message.
188
+ *
189
+ * @public
190
+ *
191
+ * @param props - {@link MessageBubbleProps}
192
+ */
193
+ export declare function MessageBubble({ message, showTimestamp, customCssClasses, formatTimestamp, }: MessageBubbleProps): JSX_2.Element;
194
+
195
+ /**
196
+ * The CSS class interface for the {@link MessageBubble} component.
197
+ *
198
+ * @public
199
+ */
200
+ export declare interface MessageBubbleCssClasses {
201
+ topContainer?: string;
202
+ subContainer?: string;
203
+ subContainer__bot?: string;
204
+ subContainer__user?: string;
205
+ message?: string;
206
+ message__bot?: string;
207
+ message__user?: string;
208
+ timestamp?: string;
209
+ timestamp__bot?: string;
210
+ timestamp__user?: string;
211
+ }
212
+
213
+ /**
214
+ * The props for the {@link MessageBubble} component.
215
+ *
216
+ * @public
217
+ */
218
+ export declare interface MessageBubbleProps {
219
+ /** The message to display. */
220
+ message: Message;
221
+ /**
222
+ * Whether to show the timestamp of the message with the message bubble.
223
+ * Defaults to true.
224
+ */
225
+ showTimestamp?: boolean;
226
+ /**
227
+ * A function which is called to format the message's timestamp given in
228
+ * ISO format (e.g. "2023-05-18T19:33:34.553Z").
229
+ * Defaults to "HH:MM:SS A" (e.g. "7:33:34 PM").
230
+ */
231
+ formatTimestamp?: (timestamp: string) => string;
232
+ /** CSS classes for customizing the component styling. */
233
+ customCssClasses?: MessageBubbleCssClasses;
234
+ }
235
+
236
+ /**
237
+ * useComposedCssClasses merges a component's built-in tailwind classes with custom tailwind classes.
238
+ *
239
+ * @remarks
240
+ * Tailwind classes will be merged without conflict, with custom classes having higher priority
241
+ * than built-in ones.
242
+ *
243
+ * @example
244
+ * Suppose a component has built-in classes of `{ container: 'px-4 text-slate-700' }`.
245
+ *
246
+ * Passing in the custom classes:
247
+ *
248
+ * ```ts
249
+ * { container: 'text-red-200 mb-3' }
250
+ * ```
251
+ *
252
+ * results in the merged classes of:
253
+ *
254
+ * ```ts
255
+ * { container: 'px-4 text-red-200 mb-3' }
256
+ * ```
257
+ *
258
+ * @public
259
+ *
260
+ * @param builtInClasses - The component's built-in tailwind classes
261
+ * @param customClasses - The custom tailwind classes to merge with the built-in ones
262
+ * @returns The composed CSS classes
263
+ */
264
+ export declare function useComposedCssClasses<ClassInterface extends Partial<Record<keyof ClassInterface, string | object>>>(builtInClasses: Readonly<ClassInterface>, customClasses?: Partial<ClassInterface>): ClassInterface;
265
+
266
+ export { }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from "./components";
2
+ export * from "./hooks";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,11 @@
1
+ // This file is read by tools that parse documentation comments conforming to the TSDoc standard.
2
+ // It should be published with your NPM package. It should not be tracked by Git.
3
+ {
4
+ "tsdocVersion": "0.12",
5
+ "toolPackages": [
6
+ {
7
+ "packageName": "@microsoft/api-extractor",
8
+ "packageVersion": "7.35.1"
9
+ }
10
+ ]
11
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Default handler function for API errors.
3
+ *
4
+ * @internal
5
+ *
6
+ * @param e - error returned from api request
7
+ */
8
+ export declare function defaultHandleApiError(e: unknown): void;
9
+ //# sourceMappingURL=defaultHandleError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultHandleError.d.ts","sourceRoot":"","sources":["../../../src/utils/defaultHandleError.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,QAE/C"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Default handler function for API errors.
3
+ *
4
+ * @internal
5
+ *
6
+ * @param e - error returned from api request
7
+ */
8
+ export function defaultHandleApiError(e) {
9
+ console.error(e);
10
+ }
11
+ //# sourceMappingURL=defaultHandleError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultHandleError.js","sourceRoot":"","sources":["../../../src/utils/defaultHandleError.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,CAAU;IAC9C,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,95 @@
1
+ {
2
+ "name": "@yext/chat-ui-react",
3
+ "version": "0.1.0",
4
+ "description": "A library of React Components for powering Yext Chat integrations.",
5
+ "author": "clippy@yext.com",
6
+ "main": "./lib/commonjs/index.js",
7
+ "module": "./lib/esm/index.js",
8
+ "types": "./lib/esm/index.d.ts",
9
+ "sideEffects": false,
10
+ "exports": {
11
+ ".": {
12
+ "import": "./lib/esm/index.js",
13
+ "require": "./lib/commonjs/index.js"
14
+ },
15
+ "./bundle.css": "./lib/bundle.css"
16
+ },
17
+ "license": "BSD-3-Clause",
18
+ "files": [
19
+ "lib",
20
+ "src",
21
+ "THIRD-PARTY-NOTICES",
22
+ "LICENSE"
23
+ ],
24
+ "keywords": [
25
+ "chat",
26
+ "ai",
27
+ "yext",
28
+ "react",
29
+ "components",
30
+ "tailwindcss"
31
+ ],
32
+ "scripts": {
33
+ "lint": "prettier --write . && eslint --fix --max-warnings=0 .",
34
+ "test": "jest --config=jest.config.json",
35
+ "storybook": "storybook dev -p 6006",
36
+ "dev": "tsc --watch -p tsconfig.esm.json",
37
+ "generate-docs": "api-extractor run --local --verbose && api-documenter markdown --input-folder temp --output-folder docs && rm -rf temp",
38
+ "generate-notices": "generate-license-file --input package.json --output ./THIRD-PARTY-NOTICES --overwrite",
39
+ "build:js": "tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json",
40
+ "build:css": "tailwindcss -o ./lib/bundle.css --minify -c tailwind.config.js",
41
+ "build": "rm -rf lib/** && npm run build:js && npm run build:css && npm run generate-docs && npm run generate-notices",
42
+ "build-storybook": "storybook build"
43
+ },
44
+ "devDependencies": {
45
+ "@babel/core": "^7.21.8",
46
+ "@babel/preset-env": "^7.21.5",
47
+ "@babel/preset-react": "^7.18.6",
48
+ "@babel/preset-typescript": "^7.21.5",
49
+ "@microsoft/api-documenter": "^7.22.8",
50
+ "@microsoft/api-extractor": "^7.35.1",
51
+ "@storybook/addon-essentials": "^7.0.18",
52
+ "@storybook/addon-interactions": "^7.0.18",
53
+ "@storybook/addon-links": "^7.0.18",
54
+ "@storybook/blocks": "^7.0.18",
55
+ "@storybook/react": "^7.0.17",
56
+ "@storybook/react-vite": "^7.0.17",
57
+ "@storybook/testing-library": "^0.1.0",
58
+ "@tailwindcss/container-queries": "^0.1.1",
59
+ "@tailwindcss/typography": "^0.5.9",
60
+ "@testing-library/jest-dom": "^5.16.5",
61
+ "@testing-library/react": "^14.0.0",
62
+ "@testing-library/user-event": "^14.4.3",
63
+ "@types/jest": "^29.5.1",
64
+ "@types/react": "^18.2.7",
65
+ "@yext/eslint-config": "^1.0.0",
66
+ "babel-jest": "^29.5.0",
67
+ "eslint": "^8.39.0",
68
+ "eslint-plugin-storybook": "^0.6.12",
69
+ "generate-license-file": "^2.0.0",
70
+ "jest": "^29.5.0",
71
+ "jest-environment-jsdom": "^29.5.0",
72
+ "msw": "^1.2.1",
73
+ "msw-storybook-addon": "^1.8.0",
74
+ "prettier": "^2.8.8",
75
+ "react": "^18.2.0",
76
+ "react-dom": "^18.2.0",
77
+ "storybook": "^7.0.17",
78
+ "tailwindcss": "^3.3.2",
79
+ "typescript": "^5.0.4"
80
+ },
81
+ "peerDependencies": {
82
+ "@yext/chat-headless-react": "^0.3.1",
83
+ "react": "^16.14 || ^17 || ^18",
84
+ "react-dom": "^16.14 || ^17 || || ^18"
85
+ },
86
+ "dependencies": {
87
+ "react-expanding-textarea": "^2.3.6",
88
+ "react-markdown": "^6.0.3",
89
+ "react-textarea-autosize": "^8.4.1",
90
+ "rehype-raw": "^5.0.0",
91
+ "rehype-sanitize": "^4.0.0",
92
+ "remark-gfm": "^1.0.0",
93
+ "tailwind-merge": "^1.12.0"
94
+ }
95
+ }
@@ -0,0 +1,118 @@
1
+ import { useChatActions } from "@yext/chat-headless-react";
2
+ import { DualSyncIcon } from "../icons/DualSync"
3
+ import { useComposedCssClasses } from "../hooks/useComposedCssClasses";
4
+ import { useCallback, useRef, useState } from "react";
5
+ import { twMerge } from "tailwind-merge";
6
+ import { CrossIcon } from "../icons/Cross";
7
+
8
+ /**
9
+ * The CSS class interface for the {@link ChatHeader} component.
10
+ *
11
+ * @public
12
+ */
13
+ export interface ChatHeaderCssClasses {
14
+ header?: string;
15
+ title?: string;
16
+ restartButton?: string;
17
+ closeButton?: string;
18
+ }
19
+
20
+ const builtInCssClasses: Readonly<ChatHeaderCssClasses> = {
21
+ header:
22
+ "w-full px-4 py-3 flex justify-between bg-gradient-to-tr from-blue-600 to-blue-800 rounded-t-3xl",
23
+ title: "text-white text-xl font-medium",
24
+ restartButton: "w-8 text-white stroke-[0.2] ml-auto",
25
+ closeButton: "w-8 text-white hover:scale-110"
26
+ };
27
+
28
+ /**
29
+ * The props for the {@link ChatHeader} component.
30
+ *
31
+ * @public
32
+ */
33
+ export interface ChatHeaderProps {
34
+ /**
35
+ * The headers's title text, essentially how the chat window identifies itself to the user.
36
+ */
37
+ title: string;
38
+ /**
39
+ * Displays a restart button which allows the user to restart the conversation.
40
+ * Defaults to false.
41
+ */
42
+ showRestartButton?: boolean;
43
+ /**
44
+ * Displays a close button which will invoke {@link ChatHeaderProps.onClose} on click.
45
+ * Default to false.
46
+ */
47
+ showCloseButton?: boolean;
48
+ /** A function which is called when the close button is clicked. */
49
+ onClose?: () => void;
50
+ /** Custom icon for for restart button. */
51
+ restartButtonIcon?: JSX.Element;
52
+ /** Custom icon for for close button. */
53
+ closeButtonIcon?: JSX.Element;
54
+ /** CSS classes for customizing the component styling. */
55
+ customCssClasses?: ChatHeaderCssClasses;
56
+ }
57
+
58
+ /**
59
+ * A component that renders the header of a chat bot panel,
60
+ * including the title and a button to reset the conversation.
61
+ *
62
+ * @public
63
+ *
64
+ * @param props - {@link ChatHeaderProps}
65
+ */
66
+ export function ChatHeader({
67
+ title,
68
+ showRestartButton,
69
+ restartButtonIcon = <DualSyncIcon />,
70
+ showCloseButton,
71
+ closeButtonIcon = <CrossIcon />,
72
+ onClose,
73
+ customCssClasses,
74
+ }: ChatHeaderProps) {
75
+ const chat = useChatActions();
76
+
77
+ const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);
78
+
79
+ const [isSpinning, setIsSpinning] = useState(false);
80
+ const restartButtonCssClasses = twMerge(
81
+ cssClasses.restartButton,
82
+ isSpinning ? "animate-[spin_0.3s_linear_infinite]" : "hover:scale-110"
83
+ );
84
+
85
+ const clearTimerRef = useRef<ReturnType<typeof setTimeout>>();
86
+ const onRestart = useCallback(async () => {
87
+ clearTimeout(clearTimerRef.current);
88
+ setIsSpinning(true);
89
+ clearTimerRef.current = setTimeout(() => {
90
+ setIsSpinning(false);
91
+ }, 1000);
92
+ chat.restartConversation();
93
+ }, [chat]);
94
+
95
+ return (
96
+ <div className={cssClasses.header}>
97
+ <h1 className={cssClasses.title}>{title}</h1>
98
+ {showRestartButton && (
99
+ <button
100
+ aria-label="Restart Conversation"
101
+ onClick={onRestart}
102
+ className={restartButtonCssClasses}
103
+ >
104
+ {restartButtonIcon}
105
+ </button>
106
+ )}
107
+ {showCloseButton && (
108
+ <button
109
+ aria-label="Close Chat"
110
+ onClick={onClose}
111
+ className={cssClasses.closeButton}
112
+ >
113
+ {closeButtonIcon}
114
+ </button>
115
+ )}
116
+ </div>
117
+ );
118
+ }
@@ -0,0 +1,129 @@
1
+ import { useCallback, useState } from "react";
2
+ import { useChatActions, useChatState } from "@yext/chat-headless-react";
3
+ import { ArrowIcon } from "../icons/Arrow";
4
+ import { useComposedCssClasses } from "../hooks";
5
+ import Textarea from "react-expanding-textarea";
6
+ import { twMerge } from "tailwind-merge";
7
+ import { defaultHandleApiError } from "../utils/defaultHandleError";
8
+
9
+ /**
10
+ * The CSS class interface for the {@link ChatInput} component.
11
+ *
12
+ * @public
13
+ */
14
+ export interface ChatInputCssClasses {
15
+ container?: string;
16
+ textArea?: string;
17
+ sendButton?: string;
18
+ }
19
+
20
+ const builtInCssClasses: ChatInputCssClasses = {
21
+ container: "w-full h-fit flex flex-row relative @container",
22
+ textArea:
23
+ "w-full p-4 pr-10 border border-slate-300 disabled:bg-slate-50 rounded-3xl resize-none text-[13px] @[480px]:text-base",
24
+ sendButton:
25
+ "rounded-full p-1.5 w-8 stroke-2 text-white bg-blue-600 disabled:bg-slate-100 hover:bg-blue-800 active:scale-90 transition-all absolute right-7 bottom-2.5 @[480px]:bottom-3.5",
26
+ };
27
+
28
+ /**
29
+ * The props for the {@link ChatInput} component.
30
+ *
31
+ * @public
32
+ */
33
+ export interface ChatInputProps {
34
+ /**
35
+ * The input's placeholder text when no text has been entered by the user.
36
+ * Defaults to "Type a message...".
37
+ */
38
+ placeholder?: string;
39
+ /**
40
+ * Enable streaming behavior by making a request to Chat Streaming API.
41
+ * Defaults to true.
42
+ */
43
+ stream?: boolean;
44
+ /** Enable auto focus for the input box. Defaults to false. */
45
+ inputAutoFocus?: boolean;
46
+ /**
47
+ * A function which is called when an error occurs from
48
+ * Chat API while processing the user's message.
49
+ * By default, the error is logged to the console.
50
+ */
51
+ handleError?: (e: unknown) => void;
52
+ /** Custom icon for the send button. */
53
+ sendButtonIcon?: JSX.Element;
54
+ /** CSS classes for customizing the component styling. */
55
+ customCssClasses?: ChatInputCssClasses;
56
+ }
57
+
58
+ /**
59
+ * A component that allows user to input message and send to Chat API.
60
+ * @public
61
+ *
62
+ * @param props - {@link ChatInputProps}
63
+ */
64
+ export function ChatInput({
65
+ placeholder = "Type a message...",
66
+ stream = true,
67
+ inputAutoFocus = false,
68
+ handleError,
69
+ sendButtonIcon = <ArrowIcon />,
70
+ customCssClasses,
71
+ }: ChatInputProps) {
72
+ const chat = useChatActions();
73
+ const [input, setInput] = useState("");
74
+ const canSendMessage = useChatState(
75
+ (state) => state.conversation.canSendMessage
76
+ );
77
+
78
+ const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);
79
+ const sendButtonClassNames = twMerge(
80
+ cssClasses.sendButton,
81
+ input.length === 0 && "opacity-0 invisible"
82
+ );
83
+
84
+ const sendMessage = useCallback(async () => {
85
+ const res = stream
86
+ ? chat.streamNextMessage(input)
87
+ : chat.getNextMessage(input);
88
+ setInput("");
89
+ res.catch((e) => (handleError ? handleError(e) : defaultHandleApiError(e)));
90
+ }, [chat, input, handleError, stream]);
91
+
92
+ const handleKeyDown = useCallback(
93
+ (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
94
+ if (e.key === "Enter") {
95
+ sendMessage();
96
+ }
97
+ },
98
+ [sendMessage]
99
+ );
100
+
101
+ const onInputChange = useCallback(
102
+ (e: React.ChangeEvent<HTMLTextAreaElement>) => {
103
+ setInput(e.target.value);
104
+ },
105
+ []
106
+ );
107
+
108
+ return (
109
+ <div className={cssClasses.container}>
110
+ <Textarea
111
+ autoFocus={inputAutoFocus}
112
+ disabled={!canSendMessage}
113
+ onKeyDown={handleKeyDown}
114
+ value={input}
115
+ onChange={onInputChange}
116
+ className={cssClasses.textArea}
117
+ placeholder={placeholder}
118
+ />
119
+ <button
120
+ aria-label="Send Message"
121
+ disabled={!canSendMessage}
122
+ onClick={sendMessage}
123
+ className={sendButtonClassNames}
124
+ >
125
+ {sendButtonIcon}
126
+ </button>
127
+ </div>
128
+ );
129
+ }