@patternfly/chatbot 2.2.0-prerelease.23 → 2.2.0-prerelease.25

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 (36) hide show
  1. package/dist/cjs/Message/ImageMessage/ImageMessage.d.ts +4 -0
  2. package/dist/cjs/Message/ImageMessage/ImageMessage.js +25 -0
  3. package/dist/cjs/Message/Message.d.ts +11 -1
  4. package/dist/cjs/Message/Message.js +38 -30
  5. package/dist/cjs/Message/Message.test.js +68 -0
  6. package/dist/cjs/MessageBar/MessageBar.d.ts +4 -4
  7. package/dist/cjs/MessageBar/MessageBar.js +2 -2
  8. package/dist/cjs/MessageBar/MessageBar.test.js +8 -0
  9. package/dist/cjs/__mocks__/rehype-unwrap-images.d.ts +2 -0
  10. package/dist/cjs/__mocks__/rehype-unwrap-images.js +4 -0
  11. package/dist/css/main.css +8 -0
  12. package/dist/css/main.css.map +1 -1
  13. package/dist/esm/Message/ImageMessage/ImageMessage.d.ts +4 -0
  14. package/dist/esm/Message/ImageMessage/ImageMessage.js +20 -0
  15. package/dist/esm/Message/Message.d.ts +11 -1
  16. package/dist/esm/Message/Message.js +38 -30
  17. package/dist/esm/Message/Message.test.js +68 -0
  18. package/dist/esm/MessageBar/MessageBar.d.ts +4 -4
  19. package/dist/esm/MessageBar/MessageBar.js +2 -2
  20. package/dist/esm/MessageBar/MessageBar.test.js +8 -0
  21. package/dist/esm/__mocks__/rehype-unwrap-images.d.ts +2 -0
  22. package/dist/esm/__mocks__/rehype-unwrap-images.js +2 -0
  23. package/dist/tsconfig.tsbuildinfo +1 -1
  24. package/package.json +2 -1
  25. package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +11 -0
  26. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +11 -0
  27. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +11 -0
  28. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx +54 -0
  29. package/src/Message/ImageMessage/ImageMessage.scss +9 -0
  30. package/src/Message/ImageMessage/ImageMessage.tsx +14 -0
  31. package/src/Message/Message.test.tsx +120 -0
  32. package/src/Message/Message.tsx +59 -35
  33. package/src/MessageBar/MessageBar.test.tsx +8 -0
  34. package/src/MessageBar/MessageBar.tsx +6 -5
  35. package/src/__mocks__/rehype-unwrap-images.tsx +3 -0
  36. package/src/main.scss +1 -0
@@ -2,7 +2,7 @@
2
2
  // Chatbot Main - Message
3
3
  // ============================================================================
4
4
 
5
- import React from 'react';
5
+ import React, { ReactNode } from 'react';
6
6
 
7
7
  import Markdown from 'react-markdown';
8
8
  import remarkGfm from 'remark-gfm';
@@ -36,6 +36,8 @@ import TbodyMessage from './TableMessage/TbodyMessage';
36
36
  import TheadMessage from './TableMessage/TheadMessage';
37
37
  import ThMessage from './TableMessage/ThMessage';
38
38
  import { TableProps } from '@patternfly/react-table';
39
+ import ImageMessage from './ImageMessage/ImageMessage';
40
+ import rehypeUnwrapImages from 'rehype-unwrap-images';
39
41
 
40
42
  export interface MessageAttachment {
41
43
  /** Name of file attached to the message */
@@ -56,6 +58,17 @@ export interface MessageAttachment {
56
58
  spinnerTestId?: string;
57
59
  }
58
60
 
61
+ export interface MessageExtraContent {
62
+ /** Content to display before the main content */
63
+ beforeMainContent?: ReactNode;
64
+
65
+ /** Content to display after the main content */
66
+ afterMainContent?: ReactNode;
67
+
68
+ /** Content to display at the end */
69
+ endContent?: ReactNode;
70
+ }
71
+
59
72
  export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'role'> {
60
73
  /** Unique id for message */
61
74
  id?: string;
@@ -63,6 +76,8 @@ export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'rol
63
76
  role: 'user' | 'bot';
64
77
  /** Message content */
65
78
  content?: string;
79
+ /** Extra Message content */
80
+ extraContent?: MessageExtraContent;
66
81
  /** Name of the user */
67
82
  name?: string;
68
83
  /** Avatar src for the user */
@@ -123,6 +138,7 @@ export interface MessageProps extends Omit<React.HTMLProps<HTMLDivElement>, 'rol
123
138
  export const MessageBase: React.FunctionComponent<MessageProps> = ({
124
139
  role,
125
140
  content,
141
+ extraContent,
126
142
  name,
127
143
  avatar,
128
144
  timestamp,
@@ -145,6 +161,7 @@ export const MessageBase: React.FunctionComponent<MessageProps> = ({
145
161
  tableProps,
146
162
  ...props
147
163
  }: MessageProps) => {
164
+ const { beforeMainContent, afterMainContent, endContent } = extraContent || {};
148
165
  let avatarClassName;
149
166
  if (avatarProps && 'className' in avatarProps) {
150
167
  const { className, ...rest } = avatarProps;
@@ -189,40 +206,46 @@ export const MessageBase: React.FunctionComponent<MessageProps> = ({
189
206
  {isLoading ? (
190
207
  <MessageLoading loadingWord={loadingWord} />
191
208
  ) : (
192
- <Markdown
193
- components={{
194
- p: (props) => <TextMessage component={ContentVariants.p} {...props} />,
195
- code: ({ children, ...props }) => (
196
- <CodeBlockMessage {...props} {...codeBlockProps}>
197
- {children}
198
- </CodeBlockMessage>
199
- ),
200
- h1: (props) => <TextMessage component={ContentVariants.h1} {...props} />,
201
- h2: (props) => <TextMessage component={ContentVariants.h2} {...props} />,
202
- h3: (props) => <TextMessage component={ContentVariants.h3} {...props} />,
203
- h4: (props) => <TextMessage component={ContentVariants.h4} {...props} />,
204
- h5: (props) => <TextMessage component={ContentVariants.h5} {...props} />,
205
- h6: (props) => <TextMessage component={ContentVariants.h6} {...props} />,
206
- blockquote: (props) => <TextMessage component={ContentVariants.blockquote} {...props} />,
207
- ul: (props) => <UnorderedListMessage {...props} />,
208
- ol: (props) => <OrderedListMessage {...props} />,
209
- li: (props) => <ListItemMessage {...props} />,
210
- table: (props) => <TableMessage {...props} {...tableProps} />,
211
- tbody: (props) => <TbodyMessage {...props} />,
212
- thead: (props) => <TheadMessage {...props} />,
213
- tr: (props) => <TrMessage {...props} />,
214
- td: (props) => {
215
- // Conflicts with Td type
216
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
217
- const { width, ...rest } = props;
218
- return <TdMessage {...rest} />;
219
- },
220
- th: (props) => <ThMessage {...props} />
221
- }}
222
- remarkPlugins={[remarkGfm]}
223
- >
224
- {content}
225
- </Markdown>
209
+ <>
210
+ {beforeMainContent && <>{beforeMainContent}</>}
211
+ <Markdown
212
+ components={{
213
+ p: (props) => <TextMessage component={ContentVariants.p} {...props} />,
214
+ code: ({ children, ...props }) => (
215
+ <CodeBlockMessage {...props} {...codeBlockProps}>
216
+ {children}
217
+ </CodeBlockMessage>
218
+ ),
219
+ h1: (props) => <TextMessage component={ContentVariants.h1} {...props} />,
220
+ h2: (props) => <TextMessage component={ContentVariants.h2} {...props} />,
221
+ h3: (props) => <TextMessage component={ContentVariants.h3} {...props} />,
222
+ h4: (props) => <TextMessage component={ContentVariants.h4} {...props} />,
223
+ h5: (props) => <TextMessage component={ContentVariants.h5} {...props} />,
224
+ h6: (props) => <TextMessage component={ContentVariants.h6} {...props} />,
225
+ blockquote: (props) => <TextMessage component={ContentVariants.blockquote} {...props} />,
226
+ ul: (props) => <UnorderedListMessage {...props} />,
227
+ ol: (props) => <OrderedListMessage {...props} />,
228
+ li: (props) => <ListItemMessage {...props} />,
229
+ table: (props) => <TableMessage {...props} {...tableProps} />,
230
+ tbody: (props) => <TbodyMessage {...props} />,
231
+ thead: (props) => <TheadMessage {...props} />,
232
+ tr: (props) => <TrMessage {...props} />,
233
+ td: (props) => {
234
+ // Conflicts with Td type
235
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
236
+ const { width, ...rest } = props;
237
+ return <TdMessage {...rest} />;
238
+ },
239
+ th: (props) => <ThMessage {...props} />,
240
+ img: (props) => <ImageMessage {...props} />
241
+ }}
242
+ remarkPlugins={[remarkGfm]}
243
+ rehypePlugins={[rehypeUnwrapImages]}
244
+ >
245
+ {content}
246
+ </Markdown>
247
+ {afterMainContent && <>{afterMainContent}</>}
248
+ </>
226
249
  )}
227
250
  {!isLoading && sources && <SourcesCard {...sources} />}
228
251
  {quickStarts && quickStarts.quickStart && (
@@ -264,6 +287,7 @@ export const MessageBase: React.FunctionComponent<MessageProps> = ({
264
287
  ))}
265
288
  </div>
266
289
  )}
290
+ {!isLoading && endContent && <>{endContent}</>}
267
291
  </div>
268
292
  </div>
269
293
  </section>
@@ -315,4 +315,12 @@ describe('Message bar', () => {
315
315
  );
316
316
  await userEvent.click(screen.getByRole('button', { name: 'Test' }));
317
317
  });
318
+ it('can be controlled', () => {
319
+ render(<MessageBar onSendMessage={jest.fn} value="test" />);
320
+ expect(screen.getByRole('button', { name: 'Attach button' })).toBeTruthy();
321
+ expect(screen.getByRole('button', { name: 'Send button' })).toBeTruthy();
322
+ expect(screen.queryByRole('button', { name: 'Microphone button' })).toBeFalsy();
323
+ expect(screen.getByRole('textbox', { name: /Send a message.../i })).toBeTruthy();
324
+ expect(screen.getByRole('textbox', { name: /Send a message.../i })).toHaveValue('test');
325
+ });
318
326
  });
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { ButtonProps, DropEvent, TextArea } from '@patternfly/react-core';
2
+ import { ButtonProps, DropEvent, TextArea, TextAreaProps } from '@patternfly/react-core';
3
3
 
4
4
  // Import Chatbot components
5
5
  import SendButton from './SendButton';
@@ -30,9 +30,9 @@ export interface MessageBarWithAttachMenuProps {
30
30
  onAttachMenuOpenChange?: (isOpen: boolean) => void;
31
31
  }
32
32
 
33
- export interface MessageBarProps {
33
+ export interface MessageBarProps extends TextAreaProps {
34
34
  /** Callback to get the value of input message by user */
35
- onSendMessage: (message: string) => void;
35
+ onSendMessage: (message: string | number) => void;
36
36
  /** Class Name for the MessageBar component */
37
37
  className?: string;
38
38
  /** Flag to always to show the send button. By default send button is shown when there is a message in the input field */
@@ -63,7 +63,7 @@ export interface MessageBarProps {
63
63
  };
64
64
  };
65
65
  /** A callback for when the text area value changes. */
66
- onChange?: (event: React.ChangeEvent<HTMLTextAreaElement>, value: string) => void;
66
+ onChange?: (event: React.ChangeEvent<HTMLTextAreaElement>, value: string | number) => void;
67
67
  /** Display mode of chatbot, if you want to message bar to resize when the display mode changes */
68
68
  displayMode?: ChatbotDisplayMode;
69
69
  }
@@ -82,11 +82,12 @@ export const MessageBar: React.FunctionComponent<MessageBarProps> = ({
82
82
  buttonProps,
83
83
  onChange,
84
84
  displayMode,
85
+ value,
85
86
  ...props
86
87
  }: MessageBarProps) => {
87
88
  // Text Input
88
89
  // --------------------------------------------------------------------------
89
- const [message, setMessage] = React.useState<string>('');
90
+ const [message, setMessage] = React.useState<string | number>(value ?? '');
90
91
  const [isListeningMessage, setIsListeningMessage] = React.useState<boolean>(false);
91
92
  const [hasSentMessage, setHasSentMessage] = React.useState(false);
92
93
  const textareaRef = React.useRef<HTMLTextAreaElement>(null);
@@ -0,0 +1,3 @@
1
+ const RehypeUnwrapImages = () => null;
2
+
3
+ export default RehypeUnwrapImages;
package/src/main.scss CHANGED
@@ -16,6 +16,7 @@
16
16
  @import './FileDropZone/FileDropZone';
17
17
  @import './Message/Message';
18
18
  @import './Message/CodeBlockMessage/CodeBlockMessage';
19
+ @import './Message/ImageMessage/ImageMessage';
19
20
  @import './Message/TextMessage/TextMessage';
20
21
  @import './Message/ListMessage/ListMessage';
21
22
  @import './Message/TableMessage/TableMessage';