@patternfly/chatbot 6.5.0-prerelease.3 → 6.5.0-prerelease.5

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 (63) hide show
  1. package/dist/cjs/AttachMenu/AttachMenu.d.ts +7 -1
  2. package/dist/cjs/AttachMenu/AttachMenu.js +2 -2
  3. package/dist/cjs/ChatbotFooter/ChatbotFooter.d.ts +5 -2
  4. package/dist/cjs/ChatbotFooter/ChatbotFooter.js +2 -2
  5. package/dist/cjs/ChatbotFooter/ChatbotFooter.test.js +5 -1
  6. package/dist/cjs/FileDetailsLabel/FileDetailsLabel.d.ts +2 -1
  7. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.d.ts +3 -1
  8. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +2 -2
  9. package/dist/cjs/Message/Message.d.ts +2 -0
  10. package/dist/cjs/Message/Message.js +6 -6
  11. package/dist/cjs/Message/Message.test.js +32 -0
  12. package/dist/cjs/Message/MessageLoading.d.ts +2 -1
  13. package/dist/cjs/Message/MessageLoading.js +1 -1
  14. package/dist/cjs/Message/TableMessage/TableMessage.d.ts +4 -1
  15. package/dist/cjs/Message/TableMessage/TableMessage.js +2 -2
  16. package/dist/cjs/Message/TextMessage/TextMessage.d.ts +4 -1
  17. package/dist/cjs/Message/TextMessage/TextMessage.js +2 -2
  18. package/dist/cjs/MessageBar/MessageBar.d.ts +9 -1
  19. package/dist/cjs/MessageBar/MessageBar.js +3 -3
  20. package/dist/cjs/MessageBar/MessageBar.test.js +37 -0
  21. package/dist/css/main.css +27 -0
  22. package/dist/css/main.css.map +1 -1
  23. package/dist/esm/AttachMenu/AttachMenu.d.ts +7 -1
  24. package/dist/esm/AttachMenu/AttachMenu.js +2 -2
  25. package/dist/esm/ChatbotFooter/ChatbotFooter.d.ts +5 -2
  26. package/dist/esm/ChatbotFooter/ChatbotFooter.js +2 -2
  27. package/dist/esm/ChatbotFooter/ChatbotFooter.test.js +5 -1
  28. package/dist/esm/FileDetailsLabel/FileDetailsLabel.d.ts +2 -1
  29. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.d.ts +3 -1
  30. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +2 -2
  31. package/dist/esm/Message/Message.d.ts +2 -0
  32. package/dist/esm/Message/Message.js +6 -6
  33. package/dist/esm/Message/Message.test.js +32 -0
  34. package/dist/esm/Message/MessageLoading.d.ts +2 -1
  35. package/dist/esm/Message/MessageLoading.js +1 -1
  36. package/dist/esm/Message/TableMessage/TableMessage.d.ts +4 -1
  37. package/dist/esm/Message/TableMessage/TableMessage.js +2 -2
  38. package/dist/esm/Message/TextMessage/TextMessage.d.ts +4 -1
  39. package/dist/esm/Message/TextMessage/TextMessage.js +2 -2
  40. package/dist/esm/MessageBar/MessageBar.d.ts +9 -1
  41. package/dist/esm/MessageBar/MessageBar.js +3 -3
  42. package/dist/esm/MessageBar/MessageBar.test.js +37 -0
  43. package/package.json +1 -1
  44. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +12 -4
  45. package/patternfly-docs/content/extensions/chatbot/examples/demos/WhiteEmbeddedChatbot.tsx +451 -0
  46. package/src/AttachMenu/AttachMenu.tsx +16 -3
  47. package/src/ChatbotFooter/ChatbotFooter.scss +4 -0
  48. package/src/ChatbotFooter/ChatbotFooter.test.tsx +10 -1
  49. package/src/ChatbotFooter/ChatbotFooter.tsx +10 -3
  50. package/src/FileDetailsLabel/FileDetailsLabel.tsx +2 -2
  51. package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +4 -0
  52. package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +4 -1
  53. package/src/Message/Message.test.tsx +37 -0
  54. package/src/Message/Message.tsx +8 -4
  55. package/src/Message/MessageLoading.scss +4 -0
  56. package/src/Message/MessageLoading.tsx +2 -2
  57. package/src/Message/TableMessage/TableMessage.scss +4 -0
  58. package/src/Message/TableMessage/TableMessage.tsx +6 -2
  59. package/src/Message/TextMessage/TextMessage.scss +6 -0
  60. package/src/Message/TextMessage/TextMessage.tsx +11 -2
  61. package/src/MessageBar/MessageBar.scss +4 -0
  62. package/src/MessageBar/MessageBar.test.tsx +62 -1
  63. package/src/MessageBar/MessageBar.tsx +24 -2
@@ -189,6 +189,8 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
189
189
  toolCall?: ToolCallProps;
190
190
  /** Whether user messages default to stripping out images in markdown */
191
191
  hasNoImagesInUserMessages?: boolean;
192
+ /** Sets background colors to be appropriate on primary chatbot background */
193
+ isPrimary?: boolean;
192
194
  }
193
195
 
194
196
  export const MessageBase: FunctionComponent<MessageProps> = ({
@@ -236,6 +238,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
236
238
  remarkGfmProps,
237
239
  toolCall,
238
240
  hasNoImagesInUserMessages = true,
241
+ isPrimary,
239
242
  ...props
240
243
  }: MessageProps) => {
241
244
  const [messageText, setMessageText] = useState(content);
@@ -286,13 +289,13 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
286
289
  p: (props) => {
287
290
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
288
291
  const { node, ...rest } = props;
289
- return <TextMessage component={ContentVariants.p} {...rest} />;
292
+ return <TextMessage component={ContentVariants.p} {...rest} isPrimary={isPrimary} />;
290
293
  },
291
294
  code: ({ children, ...props }) => {
292
295
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
293
296
  const { node, ...codeProps } = props;
294
297
  return (
295
- <CodeBlockMessage {...codeProps} {...codeBlockProps}>
298
+ <CodeBlockMessage {...codeProps} {...codeBlockProps} isPrimary={isPrimary}>
296
299
  {children}
297
300
  </CodeBlockMessage>
298
301
  );
@@ -348,7 +351,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
348
351
  return <ListItemMessage {...rest} />;
349
352
  },
350
353
  // table requires node attribute for calculating headers for mobile breakpoint
351
- table: (props) => <TableMessage {...props} {...tableProps} />,
354
+ table: (props) => <TableMessage {...props} {...tableProps} isPrimary={isPrimary} />,
352
355
  tbody: (props) => {
353
356
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
354
357
  const { node, ...rest } = props;
@@ -416,7 +419,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
416
419
 
417
420
  const renderMessage = () => {
418
421
  if (isLoading) {
419
- return <MessageLoading loadingWord={loadingWord} />;
422
+ return <MessageLoading loadingWord={loadingWord} isPrimary={isPrimary} />;
420
423
  }
421
424
  if (isEditable) {
422
425
  return (
@@ -522,6 +525,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
522
525
  closeButtonAriaLabel={attachment.closeButtonAriaLabel}
523
526
  languageTestId={attachment.languageTestId}
524
527
  spinnerTestId={attachment.spinnerTestId}
528
+ variant={isPrimary ? 'outline' : undefined}
525
529
  />
526
530
  </div>
527
531
  ))}
@@ -50,4 +50,8 @@
50
50
  background-color: rgba(41, 41, 41, 0.25);
51
51
  }
52
52
  }
53
+
54
+ &.pf-m-primary {
55
+ background-color: var(--pf-t--global--background--color--secondary--default);
56
+ }
53
57
  }
@@ -2,8 +2,8 @@
2
2
  // Chatbot Main - Message - Processing
3
3
  // ============================================================================
4
4
 
5
- const MessageLoading = ({ loadingWord }) => (
6
- <div className="pf-chatbot__message-loading">
5
+ const MessageLoading = ({ loadingWord, isPrimary }) => (
6
+ <div className={`pf-chatbot__message-loading ${isPrimary ? 'pf-m-primary' : ''}`}>
7
7
  <span className="pf-chatbot__message-loading-dots">
8
8
  <span className="pf-v6-screen-reader">{loadingWord}</span>
9
9
  </span>
@@ -8,6 +8,10 @@
8
8
  border-block-start: 0;
9
9
  }
10
10
 
11
+ &.pf-m-primary {
12
+ --pf-v6-c-table--BackgroundColor: var(--pf-t--global--background--color--secondary--default) !important;
13
+ }
14
+
11
15
  tbody {
12
16
  border-radius: var(--pf-t--global--border--radius--small);
13
17
  }
@@ -19,7 +19,11 @@ export interface TableNode {
19
19
  type: string;
20
20
  }
21
21
 
22
- const TableMessage = ({ children, ...props }: Omit<TableProps, 'ref'> & ExtraProps) => {
22
+ export interface TableMessageProps {
23
+ isPrimary?: boolean;
24
+ }
25
+
26
+ const TableMessage = ({ children, isPrimary, ...props }: Omit<TableProps, 'ref'> & ExtraProps & TableMessageProps) => {
23
27
  const { className, ...rest } = props;
24
28
 
25
29
  // This allows us to parse the nested data we get back from the 3rd party Markdown parser
@@ -72,7 +76,7 @@ const TableMessage = ({ children, ...props }: Omit<TableProps, 'ref'> & ExtraPro
72
76
  <Table
73
77
  aria-label={props['aria-label']}
74
78
  gridBreakPoint="grid"
75
- className={`pf-chatbot__message-table ${className ? className : ''}`}
79
+ className={`pf-chatbot__message-table ${isPrimary ? 'pf-m-primary' : ''} ${className ? className : ''}`}
76
80
  {...rest}
77
81
  >
78
82
  {modifyChildren(children)}
@@ -47,6 +47,12 @@
47
47
  white-space: nowrap;
48
48
  width: 1px;
49
49
  }
50
+
51
+ &.pf-m-primary {
52
+ code {
53
+ background-color: var(--pf-t--global--background--color--secondary--default);
54
+ }
55
+ }
50
56
  }
51
57
 
52
58
  // ============================================================================
@@ -5,8 +5,17 @@
5
5
  import { ExtraProps } from 'react-markdown';
6
6
  import { Content, ContentProps } from '@patternfly/react-core';
7
7
 
8
- const TextMessage = ({ component, children, ...props }: Omit<ContentProps, 'ref'> & ExtraProps) => (
9
- <span className="pf-chatbot__message-text">
8
+ export interface TextMessageProps {
9
+ isPrimary?: boolean;
10
+ }
11
+
12
+ const TextMessage = ({
13
+ component,
14
+ children,
15
+ isPrimary,
16
+ ...props
17
+ }: Omit<ContentProps, 'ref'> & ExtraProps & TextMessageProps) => (
18
+ <span className={`pf-chatbot__message-text ${isPrimary ? 'pf-m-primary' : ''}`}>
10
19
  <Content component={component} {...props}>
11
20
  {children}
12
21
  </Content>
@@ -26,6 +26,10 @@
26
26
 
27
27
  overflow: hidden;
28
28
 
29
+ &.pf-m-primary {
30
+ box-shadow: inset 0 0 0 1px var(--pf-t--global--border--color--default);
31
+ }
32
+
29
33
  &:hover {
30
34
  box-shadow: inset 0 0 0 1px var(--pf-t--global--border--color--default);
31
35
  }
@@ -1,5 +1,11 @@
1
1
  import '@testing-library/jest-dom';
2
- import { DropdownGroup, DropdownItem, DropdownList } from '@patternfly/react-core';
2
+ import {
3
+ DropdownGroup,
4
+ DropdownItem,
5
+ DropdownList,
6
+ MenuSearchInputProps,
7
+ MenuSearchProps
8
+ } from '@patternfly/react-core';
3
9
  import { BellIcon, CalendarAltIcon, ClipboardIcon, CodeIcon } from '@patternfly/react-icons';
4
10
  import { render, screen } from '@testing-library/react';
5
11
  import userEvent from '@testing-library/user-event';
@@ -218,6 +224,57 @@ describe('Message bar', () => {
218
224
  await userEvent.click(attachButton);
219
225
  expect(attachToggleClickSpy).toHaveBeenCalledTimes(1);
220
226
  });
227
+ it('can pass searchInputProps to search input in AttachMenu', () => {
228
+ render(
229
+ <MessageBar
230
+ onSendMessage={jest.fn}
231
+ value="test"
232
+ attachMenuProps={{
233
+ isAttachMenuOpen: true,
234
+ setIsAttachMenuOpen: jest.fn(),
235
+ onAttachMenuToggleClick: jest.fn(),
236
+ onAttachMenuInputChange: jest.fn(),
237
+ attachMenuItems: ATTACH_MENU_ITEMS,
238
+ searchInputProps: { isDisabled: true }
239
+ }}
240
+ />
241
+ );
242
+ expect(screen.getByRole('textbox', { name: /Filter menu items/i })).toBeDisabled();
243
+ });
244
+ it('can pass menuSearchProps to search input in AttachMenu', () => {
245
+ render(
246
+ <MessageBar
247
+ onSendMessage={jest.fn}
248
+ value="test"
249
+ attachMenuProps={{
250
+ isAttachMenuOpen: true,
251
+ setIsAttachMenuOpen: jest.fn(),
252
+ onAttachMenuToggleClick: jest.fn(),
253
+ onAttachMenuInputChange: jest.fn(),
254
+ attachMenuItems: ATTACH_MENU_ITEMS,
255
+ menuSearchProps: { 'data-testid': 'menu-search' } as MenuSearchProps
256
+ }}
257
+ />
258
+ );
259
+ expect(screen.getByTestId('menu-search')).toBeTruthy();
260
+ });
261
+ it('can pass menuSearchInputProps to search input in AttachMenu', () => {
262
+ render(
263
+ <MessageBar
264
+ onSendMessage={jest.fn}
265
+ value="test"
266
+ attachMenuProps={{
267
+ isAttachMenuOpen: true,
268
+ setIsAttachMenuOpen: jest.fn(),
269
+ onAttachMenuToggleClick: jest.fn(),
270
+ onAttachMenuInputChange: jest.fn(),
271
+ attachMenuItems: ATTACH_MENU_ITEMS,
272
+ menuSearchInputProps: { 'data-testid': 'menu-search-input' } as MenuSearchInputProps
273
+ }}
274
+ />
275
+ );
276
+ expect(screen.getByTestId('menu-search-input')).toBeTruthy();
277
+ });
221
278
  it('can hide attach button', () => {
222
279
  render(<MessageBar onSendMessage={jest.fn} hasAttachButton={false} />);
223
280
  expect(screen.queryByRole('button', { name: 'Attach' })).toBeFalsy();
@@ -387,4 +444,8 @@ describe('Message bar', () => {
387
444
  ref.current?.focus();
388
445
  expect(document.activeElement).toBe(screen.getByRole('textbox'));
389
446
  });
447
+ it('should handle isPrimary', () => {
448
+ const { container } = render(<MessageBar isPrimary onSendMessage={jest.fn} />);
449
+ expect(container.querySelector('.pf-m-primary')).toBeTruthy();
450
+ });
390
451
  });
@@ -1,7 +1,15 @@
1
1
  import type { ChangeEvent, FunctionComponent, KeyboardEvent as ReactKeyboardEvent, Ref } from 'react';
2
2
  import { forwardRef, useCallback, useEffect, useRef, useState } from 'react';
3
3
  import { Accept, DropEvent, DropzoneOptions, FileError, FileRejection } from 'react-dropzone';
4
- import { ButtonProps, TextArea, TextAreaProps, TooltipProps } from '@patternfly/react-core';
4
+ import {
5
+ ButtonProps,
6
+ MenuSearchInputProps,
7
+ MenuSearchProps,
8
+ SearchInputProps,
9
+ TextArea,
10
+ TextAreaProps,
11
+ TooltipProps
12
+ } from '@patternfly/react-core';
5
13
 
6
14
  // Import Chatbot components
7
15
  import SendButton from './SendButton';
@@ -30,6 +38,12 @@ export interface MessageBarWithAttachMenuProps {
30
38
  onAttachMenuOnOpenChangeKeys?: string[];
31
39
  /** Callback to change the open state of the menu. Triggered by clicking outside of the menu. */
32
40
  onAttachMenuOpenChange?: (isOpen: boolean) => void;
41
+ /** Additional props passed to MenuSearch component in attach menu */
42
+ menuSearchProps?: Omit<MenuSearchProps, 'ref'>;
43
+ /** Additional props passed to MenuSearchInput component in attach menu */
44
+ menuSearchInputProps?: Omit<MenuSearchInputProps, 'ref'>;
45
+ /** Additional props passed to SearchInput component in attach menu */
46
+ searchInputProps?: SearchInputProps;
33
47
  }
34
48
 
35
49
  export interface MessageBarProps extends Omit<TextAreaProps, 'innerRef'> {
@@ -104,6 +118,8 @@ export interface MessageBarProps extends Omit<TextAreaProps, 'innerRef'> {
104
118
  isCompact?: boolean;
105
119
  /** Ref applied to message bar textarea, for use with focus or other custom behaviors */
106
120
  innerRef?: React.Ref<HTMLTextAreaElement>;
121
+ /** Sets background color to primary */
122
+ isPrimary?: boolean;
107
123
  }
108
124
 
109
125
  export const MessageBarBase: FunctionComponent<MessageBarProps> = ({
@@ -134,6 +150,7 @@ export const MessageBarBase: FunctionComponent<MessageBarProps> = ({
134
150
  validator,
135
151
  dropzoneProps,
136
152
  innerRef,
153
+ isPrimary,
137
154
  ...props
138
155
  }: MessageBarProps) => {
139
156
  // Text Input
@@ -449,11 +466,16 @@ export const MessageBarBase: FunctionComponent<MessageBarProps> = ({
449
466
  {...(attachMenuProps && { handleTextInputChange: attachMenuProps.onAttachMenuInputChange })}
450
467
  popperProps={{ direction: 'up', distance: 8 }}
451
468
  searchInputPlaceholder={attachMenuProps?.attachMenuInputPlaceholder}
469
+ {...attachMenuProps}
452
470
  />
453
471
  );
454
472
  }
455
473
 
456
- return <div className={`pf-chatbot__message-bar ${className ?? ''}`}>{messageBarContents}</div>;
474
+ return (
475
+ <div className={`pf-chatbot__message-bar ${isPrimary ? 'pf-m-primary' : ''} ${className ?? ''}`}>
476
+ {messageBarContents}
477
+ </div>
478
+ );
457
479
  };
458
480
 
459
481
  const MessageBar = forwardRef((props: MessageBarProps, ref: Ref<HTMLTextAreaElement>) => (