@patternfly/chatbot 6.5.0-prerelease.2 → 6.5.0-prerelease.20

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 (152) hide show
  1. package/dist/cjs/AttachMenu/AttachMenu.d.ts +8 -2
  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/ChatbotHeader/ChatbotHeaderMenu.js +29 -2
  7. package/dist/cjs/CodeModal/CodeModal.d.ts +2 -0
  8. package/dist/cjs/CodeModal/CodeModal.js +53 -8
  9. package/dist/cjs/FileDetailsLabel/FileDetailsLabel.d.ts +2 -1
  10. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.d.ts +3 -1
  11. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +2 -2
  12. package/dist/cjs/Message/Message.d.ts +7 -1
  13. package/dist/cjs/Message/Message.js +11 -8
  14. package/dist/cjs/Message/Message.test.js +36 -0
  15. package/dist/cjs/Message/MessageLoading.d.ts +2 -1
  16. package/dist/cjs/Message/MessageLoading.js +1 -1
  17. package/dist/cjs/Message/TableMessage/TableMessage.d.ts +4 -1
  18. package/dist/cjs/Message/TableMessage/TableMessage.js +2 -2
  19. package/dist/cjs/Message/TextMessage/TextMessage.d.ts +4 -1
  20. package/dist/cjs/Message/TextMessage/TextMessage.js +2 -2
  21. package/dist/cjs/MessageBar/AttachButton.d.ts +2 -0
  22. package/dist/cjs/MessageBar/AttachButton.js +2 -2
  23. package/dist/cjs/MessageBar/AttachButton.test.js +4 -0
  24. package/dist/cjs/MessageBar/MessageBar.d.ts +16 -6
  25. package/dist/cjs/MessageBar/MessageBar.js +6 -5
  26. package/dist/cjs/MessageBar/MessageBar.test.js +62 -0
  27. package/dist/cjs/Onboarding/Onboarding.d.ts +36 -0
  28. package/dist/cjs/Onboarding/Onboarding.js +37 -0
  29. package/dist/cjs/Onboarding/Onboarding.test.d.ts +1 -0
  30. package/dist/cjs/Onboarding/Onboarding.test.js +80 -0
  31. package/dist/cjs/Onboarding/index.d.ts +2 -0
  32. package/dist/cjs/Onboarding/index.js +23 -0
  33. package/dist/cjs/ResponseActions/ResponseActions.d.ts +3 -0
  34. package/dist/cjs/ResponseActions/ResponseActions.js +28 -7
  35. package/dist/cjs/ResponseActions/ResponseActions.test.js +67 -12
  36. package/dist/cjs/__mocks__/monaco-editor.d.ts +11 -0
  37. package/dist/cjs/__mocks__/monaco-editor.js +18 -0
  38. package/dist/cjs/__mocks__/rehype-highlight.d.ts +2 -0
  39. package/dist/cjs/__mocks__/rehype-highlight.js +4 -0
  40. package/dist/cjs/index.d.ts +2 -0
  41. package/dist/cjs/index.js +4 -1
  42. package/dist/css/main.css +219 -21
  43. package/dist/css/main.css.map +1 -1
  44. package/dist/dynamic/Onboarding/package.json +1 -0
  45. package/dist/esm/AttachMenu/AttachMenu.d.ts +8 -2
  46. package/dist/esm/AttachMenu/AttachMenu.js +2 -2
  47. package/dist/esm/ChatbotFooter/ChatbotFooter.d.ts +5 -2
  48. package/dist/esm/ChatbotFooter/ChatbotFooter.js +2 -2
  49. package/dist/esm/ChatbotFooter/ChatbotFooter.test.js +5 -1
  50. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +30 -3
  51. package/dist/esm/CodeModal/CodeModal.d.ts +2 -0
  52. package/dist/esm/CodeModal/CodeModal.js +54 -9
  53. package/dist/esm/FileDetailsLabel/FileDetailsLabel.d.ts +2 -1
  54. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.d.ts +3 -1
  55. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +2 -2
  56. package/dist/esm/Message/Message.d.ts +7 -1
  57. package/dist/esm/Message/Message.js +11 -8
  58. package/dist/esm/Message/Message.test.js +36 -0
  59. package/dist/esm/Message/MessageLoading.d.ts +2 -1
  60. package/dist/esm/Message/MessageLoading.js +1 -1
  61. package/dist/esm/Message/TableMessage/TableMessage.d.ts +4 -1
  62. package/dist/esm/Message/TableMessage/TableMessage.js +2 -2
  63. package/dist/esm/Message/TextMessage/TextMessage.d.ts +4 -1
  64. package/dist/esm/Message/TextMessage/TextMessage.js +2 -2
  65. package/dist/esm/MessageBar/AttachButton.d.ts +2 -0
  66. package/dist/esm/MessageBar/AttachButton.js +2 -2
  67. package/dist/esm/MessageBar/AttachButton.test.js +4 -0
  68. package/dist/esm/MessageBar/MessageBar.d.ts +16 -6
  69. package/dist/esm/MessageBar/MessageBar.js +6 -5
  70. package/dist/esm/MessageBar/MessageBar.test.js +62 -0
  71. package/dist/esm/Onboarding/Onboarding.d.ts +36 -0
  72. package/dist/esm/Onboarding/Onboarding.js +30 -0
  73. package/dist/esm/Onboarding/Onboarding.test.d.ts +1 -0
  74. package/dist/esm/Onboarding/Onboarding.test.js +75 -0
  75. package/dist/esm/Onboarding/index.d.ts +2 -0
  76. package/dist/esm/Onboarding/index.js +2 -0
  77. package/dist/esm/ResponseActions/ResponseActions.d.ts +3 -0
  78. package/dist/esm/ResponseActions/ResponseActions.js +28 -7
  79. package/dist/esm/ResponseActions/ResponseActions.test.js +67 -12
  80. package/dist/esm/__mocks__/monaco-editor.d.ts +11 -0
  81. package/dist/esm/__mocks__/monaco-editor.js +18 -0
  82. package/dist/esm/__mocks__/rehype-highlight.d.ts +2 -0
  83. package/dist/esm/__mocks__/rehype-highlight.js +2 -0
  84. package/dist/esm/index.d.ts +2 -0
  85. package/dist/esm/index.js +2 -0
  86. package/dist/tsconfig.tsbuildinfo +1 -1
  87. package/package.json +14 -2
  88. package/patternfly-docs/content/extensions/chatbot/chatbot.md +57 -0
  89. package/patternfly-docs/content/extensions/chatbot/design-guidelines.md +12 -12
  90. package/patternfly-docs/content/extensions/chatbot/examples/Analytics/Analytics.md +1 -1
  91. package/patternfly-docs/content/extensions/chatbot/examples/Customizing Messages/Customizing Messages.md +1 -1
  92. package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +1 -0
  93. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithPersistedActions.tsx +22 -0
  94. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithQuickResponses.tsx +11 -0
  95. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +18 -4
  96. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +1 -0
  97. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx +3 -1
  98. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotMessageBarIndicatorThinking.tsx +15 -0
  99. package/patternfly-docs/content/extensions/chatbot/examples/UI/CompactOnboarding.tsx +141 -0
  100. package/patternfly-docs/content/extensions/chatbot/examples/UI/Onboarding.tsx +151 -0
  101. package/patternfly-docs/content/extensions/chatbot/examples/UI/RH-Hat-Image.svg +9 -0
  102. package/patternfly-docs/content/extensions/chatbot/examples/UI/Settings.tsx +1 -1
  103. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +55 -27
  104. package/patternfly-docs/content/extensions/chatbot/examples/demos/AttachmentDemos.md +18 -18
  105. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +29 -21
  106. package/patternfly-docs/content/extensions/chatbot/examples/demos/WhiteEmbeddedChatbot.tsx +451 -0
  107. package/patternfly-docs/patternfly-docs.config.js +2 -1
  108. package/patternfly-docs/patternfly-docs.source.js +1 -1
  109. package/src/AttachMenu/AttachMenu.tsx +26 -11
  110. package/src/Chatbot/Chatbot.scss +23 -1
  111. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +25 -0
  112. package/src/ChatbotFooter/ChatbotFooter.scss +21 -0
  113. package/src/ChatbotFooter/ChatbotFooter.test.tsx +10 -1
  114. package/src/ChatbotFooter/ChatbotFooter.tsx +10 -3
  115. package/src/ChatbotHeader/ChatbotHeader.scss +19 -0
  116. package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +56 -14
  117. package/src/ChatbotModal/ChatbotModal.scss +3 -0
  118. package/src/CodeModal/CodeModal.tsx +72 -23
  119. package/src/DeepThinking/DeepThinking.scss +1 -1
  120. package/src/FileDetailsLabel/FileDetailsLabel.tsx +2 -2
  121. package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +12 -0
  122. package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +4 -1
  123. package/src/Message/Message.scss +11 -7
  124. package/src/Message/Message.test.tsx +41 -0
  125. package/src/Message/Message.tsx +28 -13
  126. package/src/Message/MessageLoading.scss +7 -0
  127. package/src/Message/MessageLoading.tsx +2 -2
  128. package/src/Message/TableMessage/TableMessage.scss +6 -1
  129. package/src/Message/TableMessage/TableMessage.tsx +6 -2
  130. package/src/Message/TextMessage/TextMessage.scss +10 -0
  131. package/src/Message/TextMessage/TextMessage.tsx +11 -2
  132. package/src/Message/UserFeedback/UserFeedback.scss +2 -1
  133. package/src/MessageBar/AttachButton.test.tsx +4 -0
  134. package/src/MessageBar/AttachButton.tsx +4 -1
  135. package/src/MessageBar/MessageBar.scss +40 -3
  136. package/src/MessageBar/MessageBar.test.tsx +102 -1
  137. package/src/MessageBar/MessageBar.tsx +44 -11
  138. package/src/Onboarding/Onboarding.scss +101 -0
  139. package/src/Onboarding/Onboarding.test.tsx +148 -0
  140. package/src/Onboarding/Onboarding.tsx +126 -0
  141. package/src/Onboarding/index.ts +3 -0
  142. package/src/ResponseActions/ResponseActions.scss +1 -1
  143. package/src/ResponseActions/ResponseActions.test.tsx +111 -12
  144. package/src/ResponseActions/ResponseActions.tsx +38 -10
  145. package/src/ToolCall/ToolCall.scss +1 -1
  146. package/src/ToolResponse/ToolResponse.scss +3 -3
  147. package/src/__mocks__/monaco-editor.ts +19 -0
  148. package/src/__mocks__/rehype-highlight.ts +3 -0
  149. package/src/index.ts +3 -0
  150. package/src/main.scss +1 -0
  151. package/tsconfig.json +1 -1
  152. package/patternfly-docs/content/extensions/chatbot/about-chatbot.md +0 -44
@@ -1,10 +1,10 @@
1
1
  import type { FunctionComponent } from 'react';
2
- import { DropdownProps, DropdownToggleProps, PopperOptions } from '@patternfly/react-core';
2
+ import { DropdownProps, DropdownToggleProps, PopperOptions, MenuSearchInputProps, SearchInputProps, MenuSearchProps } from '@patternfly/react-core';
3
3
  export interface AttachMenuProps extends DropdownProps {
4
4
  /** Items in menu */
5
5
  filteredItems: React.ReactNode;
6
6
  /** A callback for when the input value changes. */
7
- handleTextInputChange: (value: string) => void;
7
+ handleTextInputChange?: (value: string) => void;
8
8
  /** Flag to indicate if menu is opened. */
9
9
  isOpen: boolean;
10
10
  /** Additional properties to pass to the Popper */
@@ -21,6 +21,12 @@ export interface AttachMenuProps extends DropdownProps {
21
21
  searchInputAriaLabel?: string;
22
22
  /** Toggle to be rendered */
23
23
  toggle: DropdownToggleProps | ((toggleRef: React.RefObject<any>) => React.ReactNode);
24
+ /** Additional props passed to MenuSearch component */
25
+ menuSearchProps?: Omit<MenuSearchProps, 'ref'>;
26
+ /** Additional props passed to MenuSearchInput component */
27
+ menuSearchInputProps?: Omit<MenuSearchInputProps, 'ref'>;
28
+ /** Additional props passed to SearchInput component */
29
+ searchInputProps?: SearchInputProps;
24
30
  }
25
31
  export declare const AttachMenu: FunctionComponent<AttachMenuProps>;
26
32
  export default AttachMenu;
@@ -16,8 +16,8 @@ const jsx_runtime_1 = require("react/jsx-runtime");
16
16
  // Import PatternFly components
17
17
  const react_core_1 = require("@patternfly/react-core");
18
18
  const AttachMenu = (_a) => {
19
- var { className, filteredItems, handleTextInputChange, isOpen, popperProps = undefined, onOpenChange, onOpenChangeKeys, onSelect, searchInputPlaceholder, searchInputAriaLabel = 'Filter menu items', toggle } = _a, props = __rest(_a, ["className", "filteredItems", "handleTextInputChange", "isOpen", "popperProps", "onOpenChange", "onOpenChangeKeys", "onSelect", "searchInputPlaceholder", "searchInputAriaLabel", "toggle"]);
20
- return ((0, jsx_runtime_1.jsxs)(react_core_1.Dropdown, Object.assign({ className: `pf-chatbot__menu ${className !== null && className !== void 0 ? className : ''}`, isOpen: isOpen, onOpenChange: (isOpen) => onOpenChange(isOpen), onOpenChangeKeys: onOpenChangeKeys !== null && onOpenChangeKeys !== void 0 ? onOpenChangeKeys : ['Esc'], toggle: toggle, popperProps: popperProps, onSelect: onSelect }, props, { children: [(0, jsx_runtime_1.jsx)(react_core_1.MenuSearch, { children: (0, jsx_runtime_1.jsx)(react_core_1.MenuSearchInput, { children: (0, jsx_runtime_1.jsx)(react_core_1.SearchInput, { "aria-label": searchInputAriaLabel, onChange: (_event, value) => handleTextInputChange(value), placeholder: searchInputPlaceholder }) }) }), filteredItems] })));
19
+ var { className, filteredItems, handleTextInputChange, isOpen, popperProps = undefined, onOpenChange, onOpenChangeKeys, onSelect, searchInputPlaceholder, searchInputAriaLabel = 'Filter menu items', toggle, menuSearchProps, menuSearchInputProps, searchInputProps } = _a, props = __rest(_a, ["className", "filteredItems", "handleTextInputChange", "isOpen", "popperProps", "onOpenChange", "onOpenChangeKeys", "onSelect", "searchInputPlaceholder", "searchInputAriaLabel", "toggle", "menuSearchProps", "menuSearchInputProps", "searchInputProps"]);
20
+ return ((0, jsx_runtime_1.jsxs)(react_core_1.Dropdown, Object.assign({ className: `pf-chatbot__menu ${className !== null && className !== void 0 ? className : ''}`, isOpen: isOpen, onOpenChange: (isOpen) => onOpenChange(isOpen), onOpenChangeKeys: onOpenChangeKeys !== null && onOpenChangeKeys !== void 0 ? onOpenChangeKeys : ['Esc'], toggle: toggle, popperProps: popperProps, onSelect: onSelect }, props, { children: [handleTextInputChange && ((0, jsx_runtime_1.jsx)(react_core_1.MenuSearch, Object.assign({}, menuSearchProps, { children: (0, jsx_runtime_1.jsx)(react_core_1.MenuSearchInput, Object.assign({}, menuSearchInputProps, { children: (0, jsx_runtime_1.jsx)(react_core_1.SearchInput, Object.assign({ "aria-label": searchInputAriaLabel, onChange: (_event, value) => handleTextInputChange(value), placeholder: searchInputPlaceholder }, searchInputProps)) })) }))), filteredItems] })));
21
21
  };
22
22
  exports.AttachMenu = AttachMenu;
23
23
  exports.default = exports.AttachMenu;
@@ -1,10 +1,13 @@
1
1
  import type { HTMLProps, FunctionComponent } from 'react';
2
2
  export interface ChatbotFooterProps extends HTMLProps<HTMLDivElement> {
3
- /** Children for the Footer that supports MessageBar and FootNote components*/
3
+ /** Children for the footer - supports MessageBar and FootNote components*/
4
4
  children?: React.ReactNode;
5
- /** Custom classname for the Footer component */
5
+ /** Custom classname for the footer component */
6
6
  className?: string;
7
+ /** Sets footer to compact styling. */
7
8
  isCompact?: boolean;
9
+ /** Sets background color to primary */
10
+ isPrimary?: boolean;
8
11
  }
9
12
  export declare const ChatbotFooter: FunctionComponent<ChatbotFooterProps>;
10
13
  export default ChatbotFooter;
@@ -15,8 +15,8 @@ exports.ChatbotFooter = void 0;
15
15
  const jsx_runtime_1 = require("react/jsx-runtime");
16
16
  const react_core_1 = require("@patternfly/react-core");
17
17
  const ChatbotFooter = (_a) => {
18
- var { children, className, isCompact } = _a, props = __rest(_a, ["children", "className", "isCompact"]);
19
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: `pf-chatbot__footer ${isCompact ? 'pf-m-compact' : ''} ${className !== null && className !== void 0 ? className : ''}` }, props, { children: [(0, jsx_runtime_1.jsx)(react_core_1.Divider, {}), (0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__footer-container", children: children })] })));
18
+ var { children, className, isCompact, isPrimary } = _a, props = __rest(_a, ["children", "className", "isCompact", "isPrimary"]);
19
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: `pf-chatbot__footer ${isCompact ? 'pf-m-compact' : ''} ${isPrimary ? 'pf-m-primary' : ''} ${className !== null && className !== void 0 ? className : ''}` }, props, { children: [(0, jsx_runtime_1.jsx)(react_core_1.Divider, {}), (0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__footer-container", children: children })] })));
20
20
  };
21
21
  exports.ChatbotFooter = ChatbotFooter;
22
22
  exports.default = exports.ChatbotFooter;
@@ -17,7 +17,11 @@ describe('ChatbotFooter', () => {
17
17
  expect(container.querySelector('.custom-class')).toBeTruthy();
18
18
  });
19
19
  it('should handle isCompact', () => {
20
- (0, react_1.render)((0, jsx_runtime_1.jsx)(ChatbotFooter_1.default, { className: "custom-class", isCompact: true, "data-testid": "footer", children: "Chatbot Content" }));
20
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(ChatbotFooter_1.default, { isCompact: true, "data-testid": "footer", children: "Chatbot Content" }));
21
21
  expect(react_1.screen.getByTestId('footer')).toHaveClass('pf-m-compact');
22
22
  });
23
+ it('should handle isPrimary', () => {
24
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(ChatbotFooter_1.default, { isPrimary: true, "data-testid": "footer", children: "Chatbot Content" }));
25
+ expect(react_1.screen.getByTestId('footer')).toHaveClass('pf-m-primary');
26
+ });
23
27
  });
@@ -21,8 +21,35 @@ const react_core_1 = require("@patternfly/react-core");
21
21
  const bars_icon_1 = __importDefault(require("@patternfly/react-icons/dist/esm/icons/bars-icon"));
22
22
  const ChatbotHeaderMenuBase = (_a) => {
23
23
  var { className, onMenuToggle, tooltipProps, menuAriaLabel = 'Chat history menu', innerRef, tooltipContent = 'Chat history menu', isCompact } = _a, props = __rest(_a, ["className", "onMenuToggle", "tooltipProps", "menuAriaLabel", "innerRef", "tooltipContent", "isCompact"]);
24
- return ((0, jsx_runtime_1.jsx)("div", { className: `pf-chatbot__menu ${className}`, children: (0, jsx_runtime_1.jsx)(react_core_1.Tooltip, Object.assign({ content: tooltipContent, position: "bottom",
24
+ const [isDrawerAnimating, setIsDrawerAnimating] = (0, react_1.useState)(false);
25
+ // I'd like to use a prop here later if this works
26
+ const drawerState = props['aria-expanded'];
27
+ const isDrawerOpen = drawerState === true;
28
+ const prevDrawerStateRef = (0, react_1.useRef)(isDrawerOpen);
29
+ const buttonRef = (0, react_1.useRef)(null);
30
+ (0, react_1.useEffect)(() => {
31
+ if (drawerState !== undefined) {
32
+ const wasDrawerOpen = prevDrawerStateRef.current === true;
33
+ const isDrawerClosing = wasDrawerOpen && !isDrawerOpen;
34
+ setIsDrawerAnimating(true);
35
+ const timeout = setTimeout(() => {
36
+ setIsDrawerAnimating(false);
37
+ if (isDrawerClosing) {
38
+ requestAnimationFrame(() => {
39
+ var _a;
40
+ (_a = buttonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
41
+ });
42
+ }
43
+ }, 350);
44
+ prevDrawerStateRef.current = isDrawerOpen;
45
+ return () => clearTimeout(timeout);
46
+ }
47
+ }, [drawerState, isDrawerOpen]);
48
+ const button = (0, react_1.useMemo)(() => ((0, jsx_runtime_1.jsx)(react_core_1.Button, Object.assign({ className: `pf-chatbot__button--toggle-menu ${isCompact ? 'pf-m-compact' : ''}`, variant: "plain", onClick: onMenuToggle, "aria-label": menuAriaLabel, ref: innerRef !== null && innerRef !== void 0 ? innerRef : buttonRef, icon: (0, jsx_runtime_1.jsx)(react_core_1.Icon, { size: isCompact ? 'lg' : 'xl', isInline: true, children: (0, jsx_runtime_1.jsx)(bars_icon_1.default, {}) }), size: isCompact ? 'sm' : undefined }, props))),
49
+ // eslint-disable-next-line react-hooks/exhaustive-deps
50
+ [isCompact, menuAriaLabel, onMenuToggle, innerRef, buttonRef]);
51
+ return ((0, jsx_runtime_1.jsx)("div", { className: `pf-chatbot__menu ${className}`, children: isDrawerAnimating ? (button) : ((0, jsx_runtime_1.jsx)(react_core_1.Tooltip, Object.assign({ content: tooltipContent, position: "bottom",
25
52
  // prevents VO announcements of both aria label and tooltip
26
- aria: "none" }, tooltipProps, { children: (0, jsx_runtime_1.jsx)(react_core_1.Button, Object.assign({ className: `pf-chatbot__button--toggle-menu ${isCompact ? 'pf-m-compact' : ''}`, variant: "plain", onClick: onMenuToggle, "aria-label": menuAriaLabel, ref: innerRef, icon: (0, jsx_runtime_1.jsx)(react_core_1.Icon, { size: isCompact ? 'lg' : 'xl', isInline: true, children: (0, jsx_runtime_1.jsx)(bars_icon_1.default, {}) }), size: isCompact ? 'sm' : undefined }, props)) })) }));
53
+ aria: "none" }, tooltipProps, { children: button }))) }));
27
54
  };
28
55
  exports.ChatbotHeaderMenu = (0, react_1.forwardRef)((props, ref) => ((0, jsx_runtime_1.jsx)(ChatbotHeaderMenuBase, Object.assign({ innerRef: ref }, props))));
@@ -37,6 +37,8 @@ export interface CodeModalProps {
37
37
  modalBodyClassName?: string;
38
38
  /** Class applied to modal footer */
39
39
  modalFooterClassName?: string;
40
+ /** Aria label applied to spinner when loading Monaco */
41
+ spinnerAriaLabel?: string;
40
42
  }
41
43
  export declare const CodeModal: FunctionComponent<CodeModalProps>;
42
44
  export default CodeModal;
@@ -22,6 +22,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
25
34
  var __rest = (this && this.__rest) || function (s, e) {
26
35
  var t = {};
27
36
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -47,12 +56,39 @@ const react_core_1 = require("@patternfly/react-core");
47
56
  const FileDetails_1 = __importStar(require("../FileDetails"));
48
57
  const Chatbot_1 = require("../Chatbot");
49
58
  const ChatbotModal_1 = __importDefault(require("../ChatbotModal/ChatbotModal"));
59
+ // Try to lazy load - some consumers need to be below a certain bundle size, but can't use the CDN and don't have webpack
60
+ let monacoInstance = null;
61
+ const loadMonaco = () => __awaiter(void 0, void 0, void 0, function* () {
62
+ if (!monacoInstance) {
63
+ const [monaco, { loader }] = yield Promise.all([Promise.resolve().then(() => __importStar(require('monaco-editor'))), Promise.resolve().then(() => __importStar(require('@monaco-editor/react')))]);
64
+ monacoInstance = monaco;
65
+ loader.config({ monaco });
66
+ }
67
+ return monacoInstance;
68
+ });
50
69
  const CodeModal = (_a) => {
51
- var { fileName, code, codeEditorControlClassName: codeEditorClassName, handleModalToggle, isCopyEnabled, isLineNumbersVisible, isModalOpen, isReadOnly, onPrimaryAction, onSecondaryAction, primaryActionBtn, secondaryActionBtn, title, displayMode = Chatbot_1.ChatbotDisplayMode.default, isCompact, modalHeaderClassName, modalBodyClassName, modalFooterClassName } = _a, props = __rest(_a, ["fileName", "code", "codeEditorControlClassName", "handleModalToggle", "isCopyEnabled", "isLineNumbersVisible", "isModalOpen", "isReadOnly", "onPrimaryAction", "onSecondaryAction", "primaryActionBtn", "secondaryActionBtn", "title", "displayMode", "isCompact", "modalHeaderClassName", "modalBodyClassName", "modalFooterClassName"]);
70
+ var { fileName, code, codeEditorControlClassName: codeEditorClassName, handleModalToggle, isCopyEnabled, isLineNumbersVisible, isModalOpen, isReadOnly, onPrimaryAction, onSecondaryAction, primaryActionBtn, secondaryActionBtn, title, displayMode = Chatbot_1.ChatbotDisplayMode.default, isCompact, modalHeaderClassName, modalBodyClassName, modalFooterClassName, spinnerAriaLabel = 'Loading' } = _a, props = __rest(_a, ["fileName", "code", "codeEditorControlClassName", "handleModalToggle", "isCopyEnabled", "isLineNumbersVisible", "isModalOpen", "isReadOnly", "onPrimaryAction", "onSecondaryAction", "primaryActionBtn", "secondaryActionBtn", "title", "displayMode", "isCompact", "modalHeaderClassName", "modalBodyClassName", "modalFooterClassName", "spinnerAriaLabel"]);
52
71
  const [newCode, setNewCode] = (0, react_1.useState)(code);
53
72
  const [editorInstance, setEditorInstance] = (0, react_1.useState)(null);
54
73
  const [isEditorReady, setIsEditorReady] = (0, react_1.useState)(false);
74
+ const [isMonacoLoading, setIsMonacoLoading] = (0, react_1.useState)(false);
75
+ const [isMonacoLoaded, setIsMonacoLoaded] = (0, react_1.useState)(false);
55
76
  const containerRef = (0, react_1.useRef)(null);
77
+ (0, react_1.useEffect)(() => {
78
+ if (isModalOpen && !isMonacoLoaded && !isMonacoLoading) {
79
+ setIsMonacoLoading(true);
80
+ loadMonaco()
81
+ .then(() => {
82
+ setIsMonacoLoaded(true);
83
+ setIsMonacoLoading(false);
84
+ })
85
+ .catch((error) => {
86
+ // eslint-disable-next-line no-console
87
+ console.error('Failed to load Monaco editor:', error);
88
+ setIsMonacoLoading(false);
89
+ });
90
+ }
91
+ }, [isModalOpen, isMonacoLoaded, isMonacoLoading]);
56
92
  (0, react_1.useEffect)(() => {
57
93
  if (!isModalOpen || !isEditorReady || !editorInstance || !containerRef.current) {
58
94
  return;
@@ -102,13 +138,22 @@ const CodeModal = (_a) => {
102
138
  setNewCode(value);
103
139
  }
104
140
  };
105
- const modal = ((0, jsx_runtime_1.jsxs)(ChatbotModal_1.default, { isOpen: isModalOpen, onClose: handleModalToggle, ouiaId: "CodeModal", "aria-labelledby": "code-modal-title", "aria-describedby": "code-modal", className: `pf-chatbot__code-modal ${isCompact ? 'pf-m-compact' : ''} pf-chatbot__code-modal--${displayMode}`, displayMode: displayMode, isCompact: isCompact, children: [(0, jsx_runtime_1.jsx)(react_core_1.ModalHeader, { className: modalHeaderClassName, title: title, labelId: "code-modal-title" }), (0, jsx_runtime_1.jsx)(react_core_1.ModalBody, { className: modalBodyClassName, id: "code-modal-body", children: (0, jsx_runtime_1.jsxs)(react_core_1.Stack, { className: "pf-chatbot__code-modal-body", children: [(0, jsx_runtime_1.jsx)(react_core_1.StackItem, { className: "pf-chatbot__code-modal-file-details", children: (0, jsx_runtime_1.jsx)(FileDetails_1.default, { fileName: fileName }) }), (0, jsx_runtime_1.jsx)("div", { className: "pf-v6-l-stack__item pf-chatbot__code-modal-editor", ref: containerRef, children: (0, jsx_runtime_1.jsx)(react_code_editor_1.CodeEditor, Object.assign({ isDarkTheme: true, isLineNumbersVisible: isLineNumbersVisible, isLanguageLabelVisible: true, isCopyEnabled: isCopyEnabled, isReadOnly: isReadOnly, code: newCode, language: FileDetails_1.extensionToLanguage[path_browserify_1.default.extname(fileName).slice(1)], onEditorDidMount: onEditorDidMount, onCodeChange: onCodeChange, className: codeEditorClassName, isFullHeight: true, options: {
106
- glyphMargin: false,
107
- folding: false,
108
- // prevents Monaco from handling resizing itself
109
- // was causing ResizeObserver issues
110
- automaticLayout: false
111
- } }, props)) })] }) }), (0, jsx_runtime_1.jsxs)(react_core_1.ModalFooter, { className: modalFooterClassName, children: [(0, jsx_runtime_1.jsx)(react_core_1.Button, { isBlock: true, variant: "primary", onClick: handlePrimaryAction, form: "code-modal-form", children: primaryActionBtn }, "code-modal-primary"), (0, jsx_runtime_1.jsx)(react_core_1.Button, { isBlock: true, variant: "link", onClick: handleSecondaryAction, children: secondaryActionBtn }, "code-modal-secondary")] })] }));
141
+ const renderMonacoEditor = () => {
142
+ if (isMonacoLoading) {
143
+ return ((0, jsx_runtime_1.jsx)(react_core_1.Bullseye, { children: (0, jsx_runtime_1.jsx)(react_core_1.Spinner, { "aria-label": spinnerAriaLabel }) }));
144
+ }
145
+ if (isMonacoLoaded) {
146
+ return ((0, jsx_runtime_1.jsx)(react_code_editor_1.CodeEditor, Object.assign({ isDarkTheme: true, isLineNumbersVisible: isLineNumbersVisible, isLanguageLabelVisible: true, isCopyEnabled: isCopyEnabled, isReadOnly: isReadOnly, code: newCode, language: FileDetails_1.extensionToLanguage[path_browserify_1.default.extname(fileName).slice(1)], onEditorDidMount: onEditorDidMount, onCodeChange: onCodeChange, className: codeEditorClassName, isFullHeight: true, options: {
147
+ glyphMargin: false,
148
+ folding: false,
149
+ // prevents Monaco from handling resizing itself
150
+ // was causing ResizeObserver issues
151
+ automaticLayout: false
152
+ } }, props)));
153
+ }
154
+ return null;
155
+ };
156
+ const modal = ((0, jsx_runtime_1.jsxs)(ChatbotModal_1.default, { isOpen: isModalOpen, onClose: handleModalToggle, ouiaId: "CodeModal", "aria-labelledby": "code-modal-title", "aria-describedby": "code-modal", className: `pf-chatbot__code-modal ${isCompact ? 'pf-m-compact' : ''} pf-chatbot__code-modal--${displayMode}`, displayMode: displayMode, isCompact: isCompact, children: [(0, jsx_runtime_1.jsx)(react_core_1.ModalHeader, { className: modalHeaderClassName, title: title, labelId: "code-modal-title" }), (0, jsx_runtime_1.jsx)(react_core_1.ModalBody, { className: modalBodyClassName, id: "code-modal-body", children: (0, jsx_runtime_1.jsxs)(react_core_1.Stack, { className: "pf-chatbot__code-modal-body", children: [(0, jsx_runtime_1.jsx)(react_core_1.StackItem, { className: "pf-chatbot__code-modal-file-details", children: (0, jsx_runtime_1.jsx)(FileDetails_1.default, { fileName: fileName }) }), (0, jsx_runtime_1.jsx)("div", { className: "pf-v6-l-stack__item pf-chatbot__code-modal-editor", ref: containerRef, children: renderMonacoEditor() })] }) }), (0, jsx_runtime_1.jsxs)(react_core_1.ModalFooter, { className: modalFooterClassName, children: [(0, jsx_runtime_1.jsx)(react_core_1.Button, { isBlock: true, variant: "primary", onClick: handlePrimaryAction, form: "code-modal-form", children: primaryActionBtn }, "code-modal-primary"), (0, jsx_runtime_1.jsx)(react_core_1.Button, { isBlock: true, variant: "link", onClick: handleSecondaryAction, children: secondaryActionBtn }, "code-modal-secondary")] })] }));
112
157
  return modal;
113
158
  };
114
159
  exports.CodeModal = CodeModal;
@@ -1,5 +1,6 @@
1
1
  import { PropsWithChildren } from 'react';
2
- export interface FileDetailsLabelProps {
2
+ import { LabelProps } from '@patternfly/react-core';
3
+ export interface FileDetailsLabelProps extends Omit<LabelProps, 'onClose' | 'onClick'> {
3
4
  /** Name of file, including extension */
4
5
  fileName: string;
5
6
  /** Unique id of file */
@@ -18,6 +18,8 @@ export interface CodeBlockMessageProps {
18
18
  collapsedText?: string;
19
19
  /** Custom actions added to header of code block, after any default actions such as the "copy" action. */
20
20
  customActions?: React.ReactNode;
21
+ /** Sets background colors to be appropriate on primary chatbot background */
22
+ isPrimary?: boolean;
21
23
  }
22
- declare const CodeBlockMessage: ({ children, className, "aria-label": ariaLabel, isExpandable, expandableSectionProps, expandableSectionToggleProps, expandedText, collapsedText, customActions, ...props }: CodeBlockMessageProps) => import("react/jsx-runtime").JSX.Element;
24
+ declare const CodeBlockMessage: ({ children, className, "aria-label": ariaLabel, isExpandable, expandableSectionProps, expandableSectionToggleProps, expandedText, collapsedText, customActions, isPrimary, ...props }: CodeBlockMessageProps) => import("react/jsx-runtime").JSX.Element;
23
25
  export default CodeBlockMessage;
@@ -24,7 +24,7 @@ const DEFAULT_EXPANDED_TEXT = 'Show less';
24
24
  const DEFAULT_COLLAPSED_TEXT = 'Show more';
25
25
  const CodeBlockMessage = (_a) => {
26
26
  var _b;
27
- var { children, className, 'aria-label': ariaLabel, isExpandable = false, expandableSectionProps, expandableSectionToggleProps, expandedText = DEFAULT_EXPANDED_TEXT, collapsedText = DEFAULT_COLLAPSED_TEXT, customActions } = _a, props = __rest(_a, ["children", "className", 'aria-label', "isExpandable", "expandableSectionProps", "expandableSectionToggleProps", "expandedText", "collapsedText", "customActions"]);
27
+ var { children, className, 'aria-label': ariaLabel, isExpandable = false, expandableSectionProps, expandableSectionToggleProps, expandedText = DEFAULT_EXPANDED_TEXT, collapsedText = DEFAULT_COLLAPSED_TEXT, customActions, isPrimary } = _a, props = __rest(_a, ["children", "className", 'aria-label', "isExpandable", "expandableSectionProps", "expandableSectionToggleProps", "expandedText", "collapsedText", "customActions", "isPrimary"]);
28
28
  const [copied, setCopied] = (0, react_1.useState)(false);
29
29
  const [isExpanded, setIsExpanded] = (0, react_1.useState)(false);
30
30
  const buttonRef = (0, react_1.useRef)();
@@ -61,7 +61,7 @@ const CodeBlockMessage = (_a) => {
61
61
  }
62
62
  });
63
63
  if (!String(children).includes('\n')) {
64
- return ((0, jsx_runtime_1.jsx)("code", Object.assign({}, props, { className: "pf-chatbot__message-inline-code", children: children })));
64
+ return ((0, jsx_runtime_1.jsx)("code", Object.assign({}, props, { className: `pf-chatbot__message-inline-code ${isPrimary ? 'pf-m-primary' : ''}`, children: children })));
65
65
  }
66
66
  // Setup code block header
67
67
  const actions = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(react_core_1.CodeBlockAction, { className: "pf-chatbot__message-code-block-default-action", children: [language && (0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-code-block-language", children: language }), (0, jsx_runtime_1.jsx)(react_core_1.Button, { ref: buttonRef, "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : 'Copy code', variant: "plain", className: "pf-chatbot__button--copy", onClick: (event) => handleCopy(event, children), children: copied ? (0, jsx_runtime_1.jsx)(check_icon_1.CheckIcon, {}) : (0, jsx_runtime_1.jsx)(copy_icon_1.CopyIcon, {}) }), (0, jsx_runtime_1.jsx)(react_core_1.Tooltip, { id: tooltipID, content: "Copy", position: "top", triggerRef: buttonRef })] }), customActions] }));
@@ -10,6 +10,7 @@ import QuickResponse from './QuickResponse/QuickResponse';
10
10
  import { UserFeedbackProps } from './UserFeedback/UserFeedback';
11
11
  import { UserFeedbackCompleteProps } from './UserFeedback/UserFeedbackComplete';
12
12
  import { TableProps } from '@patternfly/react-table';
13
+ import 'highlight.js/styles/vs2015.css';
13
14
  import { PluggableList } from 'unified';
14
15
  import { ToolResponseProps } from '../ToolResponse';
15
16
  import { DeepThinkingProps } from '../DeepThinking';
@@ -52,7 +53,7 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
52
53
  /** Name of the user */
53
54
  name?: string;
54
55
  /** Avatar src for the user */
55
- avatar: string;
56
+ avatar?: string;
56
57
  /** Timestamp for the message */
57
58
  timestamp?: string;
58
59
  /** Set this to true if message is being loaded */
@@ -63,6 +64,9 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
63
64
  actions?: {
64
65
  [key: string]: ActionProps;
65
66
  };
67
+ /** When true, the selected action will persist even when clicking outside the component.
68
+ * When false (default), clicking outside or clicking another action will deselect the current selection. */
69
+ persistActionSelection?: boolean;
66
70
  /** Sources for message */
67
71
  sources?: SourcesCardProps;
68
72
  /** Label for the English word "AI," used to tag messages with role "bot" */
@@ -144,6 +148,8 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
144
148
  toolCall?: ToolCallProps;
145
149
  /** Whether user messages default to stripping out images in markdown */
146
150
  hasNoImagesInUserMessages?: boolean;
151
+ /** Sets background colors to be appropriate on primary chatbot background */
152
+ isPrimary?: boolean;
147
153
  }
148
154
  export declare const MessageBase: FunctionComponent<MessageProps>;
149
155
  declare const Message: import("react").ForwardRefExoticComponent<Omit<MessageProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -46,6 +46,9 @@ const ImageMessage_1 = __importDefault(require("./ImageMessage/ImageMessage"));
46
46
  const rehype_unwrap_images_1 = __importDefault(require("rehype-unwrap-images"));
47
47
  const rehype_external_links_1 = __importDefault(require("rehype-external-links"));
48
48
  const rehype_sanitize_1 = __importDefault(require("rehype-sanitize"));
49
+ const rehype_highlight_1 = __importDefault(require("rehype-highlight"));
50
+ // see the full list of styles here: https://highlightjs.org/examples
51
+ require("highlight.js/styles/vs2015.css");
49
52
  const LinkMessage_1 = __importDefault(require("./LinkMessage/LinkMessage"));
50
53
  const ErrorMessage_1 = __importDefault(require("./ErrorMessage/ErrorMessage"));
51
54
  const MessageInput_1 = __importDefault(require("./MessageInput"));
@@ -55,13 +58,13 @@ const DeepThinking_1 = __importDefault(require("../DeepThinking"));
55
58
  const SuperscriptMessage_1 = __importDefault(require("./SuperscriptMessage/SuperscriptMessage"));
56
59
  const ToolCall_1 = __importDefault(require("../ToolCall"));
57
60
  const MessageBase = (_a) => {
58
- var { role, content, extraContent, name, avatar, timestamp, isLoading, actions, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [], additionalRemarkPlugins = [], linkProps, error, isEditable, editPlaceholder = 'Edit prompt message...', updateWord = 'Update', cancelWord = 'Cancel', onEditUpdate, onEditCancel, inputRef, editFormProps, isCompact, isMarkdownDisabled, reactMarkdownProps, toolResponse, deepThinking, remarkGfmProps, toolCall, hasNoImagesInUserMessages = true } = _a, props = __rest(_a, ["role", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins", "additionalRemarkPlugins", "linkProps", "error", "isEditable", "editPlaceholder", "updateWord", "cancelWord", "onEditUpdate", "onEditCancel", "inputRef", "editFormProps", "isCompact", "isMarkdownDisabled", "reactMarkdownProps", "toolResponse", "deepThinking", "remarkGfmProps", "toolCall", "hasNoImagesInUserMessages"]);
61
+ var { role, content, extraContent, name, avatar, timestamp, isLoading, actions, persistActionSelection, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [], additionalRemarkPlugins = [], linkProps, error, isEditable, editPlaceholder = 'Edit prompt message...', updateWord = 'Update', cancelWord = 'Cancel', onEditUpdate, onEditCancel, inputRef, editFormProps, isCompact, isMarkdownDisabled, reactMarkdownProps, toolResponse, deepThinking, remarkGfmProps, toolCall, hasNoImagesInUserMessages = true, isPrimary } = _a, props = __rest(_a, ["role", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "persistActionSelection", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins", "additionalRemarkPlugins", "linkProps", "error", "isEditable", "editPlaceholder", "updateWord", "cancelWord", "onEditUpdate", "onEditCancel", "inputRef", "editFormProps", "isCompact", "isMarkdownDisabled", "reactMarkdownProps", "toolResponse", "deepThinking", "remarkGfmProps", "toolCall", "hasNoImagesInUserMessages", "isPrimary"]);
59
62
  const [messageText, setMessageText] = (0, react_1.useState)(content);
60
63
  (0, react_1.useEffect)(() => {
61
64
  setMessageText(content);
62
65
  }, [content]);
63
66
  const { beforeMainContent, afterMainContent, endContent } = extraContent || {};
64
- let rehypePlugins = [rehype_unwrap_images_1.default, rehypeMoveImagesOutOfParagraphs_1.rehypeMoveImagesOutOfParagraphs];
67
+ let rehypePlugins = [rehype_unwrap_images_1.default, rehypeMoveImagesOutOfParagraphs_1.rehypeMoveImagesOutOfParagraphs, rehype_highlight_1.default];
65
68
  if (openLinkInNewTab) {
66
69
  rehypePlugins = rehypePlugins.concat([[rehype_external_links_1.default, { target: '_blank' }, rehype_sanitize_1.default]]);
67
70
  }
@@ -94,13 +97,13 @@ const MessageBase = (_a) => {
94
97
  p: (props) => {
95
98
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
96
99
  const { node } = props, rest = __rest(props, ["node"]);
97
- return (0, jsx_runtime_1.jsx)(TextMessage_1.default, Object.assign({ component: react_core_1.ContentVariants.p }, rest));
100
+ return (0, jsx_runtime_1.jsx)(TextMessage_1.default, Object.assign({ component: react_core_1.ContentVariants.p }, rest, { isPrimary: isPrimary }));
98
101
  },
99
102
  code: (_a) => {
100
103
  var { children } = _a, props = __rest(_a, ["children"]);
101
104
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
102
105
  const { node } = props, codeProps = __rest(props, ["node"]);
103
- return ((0, jsx_runtime_1.jsx)(CodeBlockMessage_1.default, Object.assign({}, codeProps, codeBlockProps, { children: children })));
106
+ return ((0, jsx_runtime_1.jsx)(CodeBlockMessage_1.default, Object.assign({}, codeProps, codeBlockProps, { isPrimary: isPrimary, children: children })));
104
107
  },
105
108
  h1: (props) => {
106
109
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -153,7 +156,7 @@ const MessageBase = (_a) => {
153
156
  return (0, jsx_runtime_1.jsx)(ListItemMessage_1.default, Object.assign({}, rest));
154
157
  },
155
158
  // table requires node attribute for calculating headers for mobile breakpoint
156
- table: (props) => (0, jsx_runtime_1.jsx)(TableMessage_1.default, Object.assign({}, props, tableProps)),
159
+ table: (props) => (0, jsx_runtime_1.jsx)(TableMessage_1.default, Object.assign({}, props, tableProps, { isPrimary: isPrimary })),
157
160
  tbody: (props) => {
158
161
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
159
162
  const { node } = props, rest = __rest(props, ["node"]);
@@ -206,7 +209,7 @@ const MessageBase = (_a) => {
206
209
  };
207
210
  const renderMessage = () => {
208
211
  if (isLoading) {
209
- return (0, jsx_runtime_1.jsx)(MessageLoading_1.default, { loadingWord: loadingWord });
212
+ return (0, jsx_runtime_1.jsx)(MessageLoading_1.default, { loadingWord: loadingWord, isPrimary: isPrimary });
210
213
  }
211
214
  if (isEditable) {
212
215
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [beforeMainContent && (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: beforeMainContent }), (0, jsx_runtime_1.jsx)(MessageInput_1.default, Object.assign({ content: messageText, editPlaceholder: editPlaceholder, updateWord: updateWord, cancelWord: cancelWord, onEditUpdate: (event, value) => {
@@ -216,9 +219,9 @@ const MessageBase = (_a) => {
216
219
  }
217
220
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [beforeMainContent && (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: beforeMainContent }), error ? (0, jsx_runtime_1.jsx)(ErrorMessage_1.default, Object.assign({}, error)) : handleMarkdown()] }));
218
221
  };
219
- return ((0, jsx_runtime_1.jsxs)("section", Object.assign({ "aria-label": `Message from ${role} - ${dateString}`, className: `pf-chatbot__message pf-chatbot__message--${role}`, "aria-live": isLiveRegion ? 'polite' : undefined, "aria-atomic": isLiveRegion ? false : undefined, ref: innerRef }, props, { children: [(0, jsx_runtime_1.jsx)(react_core_1.Avatar, Object.assign({ className: `pf-chatbot__message-avatar ${hasRoundAvatar ? 'pf-chatbot__message-avatar--round' : ''} ${avatarClassName ? avatarClassName : ''}`, src: avatar, alt: "" }, avatarProps)), (0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-contents", children: [(0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-meta", children: [name && ((0, jsx_runtime_1.jsx)("span", { className: "pf-chatbot__message-name", children: (0, jsx_runtime_1.jsx)(react_core_1.Truncate, { content: name }) })), role === 'bot' && ((0, jsx_runtime_1.jsx)(react_core_1.Label, { variant: "outline", isCompact: true, children: botWord })), (0, jsx_runtime_1.jsx)(react_core_1.Timestamp, { date: date, children: timestamp })] }), (0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-response", children: [(0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-and-actions", children: [renderMessage(), afterMainContent && (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: afterMainContent }), toolResponse && (0, jsx_runtime_1.jsx)(ToolResponse_1.default, Object.assign({}, toolResponse)), deepThinking && (0, jsx_runtime_1.jsx)(DeepThinking_1.default, Object.assign({}, deepThinking)), toolCall && (0, jsx_runtime_1.jsx)(ToolCall_1.default, Object.assign({}, toolCall)), !isLoading && sources && (0, jsx_runtime_1.jsx)(SourcesCard_1.default, Object.assign({}, sources, { isCompact: isCompact })), quickStarts && quickStarts.quickStart && ((0, jsx_runtime_1.jsx)(QuickStartTile_1.default, { quickStart: quickStarts.quickStart, onSelectQuickStart: quickStarts.onSelectQuickStart, minuteWord: quickStarts.minuteWord, minuteWordPlural: quickStarts.minuteWordPlural, prerequisiteWord: quickStarts.prerequisiteWord, prerequisiteWordPlural: quickStarts.prerequisiteWordPlural, quickStartButtonAriaLabel: quickStarts.quickStartButtonAriaLabel, isCompact: isCompact })), !isLoading && !isEditable && actions && (0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: actions }), userFeedbackForm && (0, jsx_runtime_1.jsx)(UserFeedback_1.default, Object.assign({}, userFeedbackForm, { timestamp: dateString, isCompact: isCompact })), userFeedbackComplete && ((0, jsx_runtime_1.jsx)(UserFeedbackComplete_1.default, Object.assign({}, userFeedbackComplete, { timestamp: dateString, isCompact: isCompact }))), !isLoading && quickResponses && ((0, jsx_runtime_1.jsx)(QuickResponse_1.default, { quickResponses: quickResponses, quickResponseContainerProps: quickResponseContainerProps, isCompact: isCompact }))] }), attachments && ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-attachments-container", children: attachments.map((attachment) => {
222
+ return ((0, jsx_runtime_1.jsxs)("section", Object.assign({ "aria-label": `Message from ${role} - ${dateString}`, className: `pf-chatbot__message pf-chatbot__message--${role}`, "aria-live": isLiveRegion ? 'polite' : undefined, "aria-atomic": isLiveRegion ? false : undefined, ref: innerRef }, props, { children: [avatar && ((0, jsx_runtime_1.jsx)(react_core_1.Avatar, Object.assign({ className: `pf-chatbot__message-avatar ${hasRoundAvatar ? 'pf-chatbot__message-avatar--round' : ''} ${avatarClassName ? avatarClassName : ''}`, src: avatar, alt: "" }, avatarProps))), (0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-contents", children: [(0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-meta", children: [name && ((0, jsx_runtime_1.jsx)("span", { className: "pf-chatbot__message-name", children: (0, jsx_runtime_1.jsx)(react_core_1.Truncate, { content: name }) })), role === 'bot' && ((0, jsx_runtime_1.jsx)(react_core_1.Label, { variant: "outline", isCompact: true, children: botWord })), (0, jsx_runtime_1.jsx)(react_core_1.Timestamp, { date: date, children: timestamp })] }), (0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-response", children: [(0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__message-and-actions", children: [renderMessage(), afterMainContent && (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: afterMainContent }), toolResponse && (0, jsx_runtime_1.jsx)(ToolResponse_1.default, Object.assign({}, toolResponse)), deepThinking && (0, jsx_runtime_1.jsx)(DeepThinking_1.default, Object.assign({}, deepThinking)), toolCall && (0, jsx_runtime_1.jsx)(ToolCall_1.default, Object.assign({}, toolCall)), !isLoading && sources && (0, jsx_runtime_1.jsx)(SourcesCard_1.default, Object.assign({}, sources, { isCompact: isCompact })), quickStarts && quickStarts.quickStart && ((0, jsx_runtime_1.jsx)(QuickStartTile_1.default, { quickStart: quickStarts.quickStart, onSelectQuickStart: quickStarts.onSelectQuickStart, minuteWord: quickStarts.minuteWord, minuteWordPlural: quickStarts.minuteWordPlural, prerequisiteWord: quickStarts.prerequisiteWord, prerequisiteWordPlural: quickStarts.prerequisiteWordPlural, quickStartButtonAriaLabel: quickStarts.quickStartButtonAriaLabel, isCompact: isCompact })), !isLoading && !isEditable && actions && ((0, jsx_runtime_1.jsx)(ResponseActions_1.default, { actions: actions, persistActionSelection: persistActionSelection })), userFeedbackForm && (0, jsx_runtime_1.jsx)(UserFeedback_1.default, Object.assign({}, userFeedbackForm, { timestamp: dateString, isCompact: isCompact })), userFeedbackComplete && ((0, jsx_runtime_1.jsx)(UserFeedbackComplete_1.default, Object.assign({}, userFeedbackComplete, { timestamp: dateString, isCompact: isCompact }))), !isLoading && quickResponses && ((0, jsx_runtime_1.jsx)(QuickResponse_1.default, { quickResponses: quickResponses, quickResponseContainerProps: quickResponseContainerProps, isCompact: isCompact }))] }), attachments && ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-attachments-container", children: attachments.map((attachment) => {
220
223
  var _a;
221
- return ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-attachment", children: (0, jsx_runtime_1.jsx)(FileDetailsLabel_1.default, { fileName: attachment.name, fileId: attachment.id, onClose: attachment.onClose, onClick: attachment.onClick, isLoading: attachment.isLoading, closeButtonAriaLabel: attachment.closeButtonAriaLabel, languageTestId: attachment.languageTestId, spinnerTestId: attachment.spinnerTestId }) }, (_a = attachment.id) !== null && _a !== void 0 ? _a : attachment.name));
224
+ return ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-attachment", children: (0, jsx_runtime_1.jsx)(FileDetailsLabel_1.default, { fileName: attachment.name, fileId: attachment.id, onClose: attachment.onClose, onClick: attachment.onClick, isLoading: attachment.isLoading, closeButtonAriaLabel: attachment.closeButtonAriaLabel, languageTestId: attachment.languageTestId, spinnerTestId: attachment.spinnerTestId, variant: isPrimary ? 'outline' : undefined }) }, (_a = attachment.id) !== null && _a !== void 0 ? _a : attachment.name));
222
225
  }) })), !isLoading && endContent && (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: endContent })] })] })] })));
223
226
  };
224
227
  exports.MessageBase = MessageBase;
@@ -209,6 +209,10 @@ describe('Message', () => {
209
209
  (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./testImg", role: "bot", name: "Bot", content: "Hi" }));
210
210
  expect(react_2.screen.getByRole('img')).toHaveAttribute('src', './testImg');
211
211
  });
212
+ it('should not render avatar if no avatar prop is passed', () => {
213
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { role: "bot", name: "Bot", content: "Hi" }));
214
+ expect(react_2.screen.queryByRole('img')).not.toBeInTheDocument();
215
+ });
212
216
  it('should render botWord correctly', () => {
213
217
  (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./img", role: "bot", name: "Bot", content: "Hi", botWord: "\u4EBA\u5DE5\u77E5\u80FD" }));
214
218
  expect(react_2.screen.getByText('Bot')).toBeTruthy();
@@ -831,4 +835,36 @@ describe('Message', () => {
831
835
  expect(react_2.screen.getByText('Thought for 3 seconds')).toBeTruthy();
832
836
  expect(react_2.screen.getByText("Here's why I said this.")).toBeTruthy();
833
837
  });
838
+ it('should handle isPrimary correctly for inline code when it is true', () => {
839
+ const { container } = (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./img", role: "user", name: "User", content: INLINE_CODE, isPrimary: true }));
840
+ expect(container.querySelector('.pf-m-primary')).toBeTruthy();
841
+ });
842
+ it('should handle isPrimary correctly for inline code when it is false', () => {
843
+ const { container } = (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./img", role: "user", name: "User", content: INLINE_CODE }));
844
+ expect(container.querySelector('.pf-m-primary')).toBeFalsy();
845
+ });
846
+ it('should handle isPrimary correctly for table when it is true', () => {
847
+ const { container } = (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./img", role: "user", name: "User", content: TABLE, isPrimary: true }));
848
+ expect(container.querySelector('.pf-m-primary')).toBeTruthy();
849
+ });
850
+ it('should handle isPrimary correctly for table when it is false', () => {
851
+ const { container } = (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./img", role: "user", name: "User", content: TABLE }));
852
+ expect(container.querySelector('.pf-m-primary')).toBeFalsy();
853
+ });
854
+ it('should handle isPrimary correctly for loading when it is true', () => {
855
+ const { container } = (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./img", role: "user", name: "User", content: "", isPrimary: true, isLoading: true }));
856
+ expect(container.querySelector('.pf-m-primary')).toBeTruthy();
857
+ });
858
+ it('should handle isPrimary correctly for loading when it is false', () => {
859
+ const { container } = (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./img", role: "user", name: "User", content: "", isLoading: true }));
860
+ expect(container.querySelector('.pf-m-primary')).toBeFalsy();
861
+ });
862
+ it('should handle isPrimary correctly for attachments when it is true', () => {
863
+ const { container } = (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./img", role: "user", name: "User", content: "", isPrimary: true, attachments: [{ name: 'testAttachment' }] }));
864
+ expect(container.querySelector('.pf-m-outline')).toBeTruthy();
865
+ });
866
+ it('should handle isPrimary correctly for attachments when it is false', () => {
867
+ const { container } = (0, react_2.render)((0, jsx_runtime_1.jsx)(Message_1.default, { avatar: "./img", role: "user", name: "User", content: "", attachments: [{ name: 'testAttachment' }] }));
868
+ expect(container.querySelector('.pf-m-outline')).toBeFalsy();
869
+ });
834
870
  });
@@ -1,4 +1,5 @@
1
- declare const MessageLoading: ({ loadingWord }: {
1
+ declare const MessageLoading: ({ loadingWord, isPrimary }: {
2
2
  loadingWord: any;
3
+ isPrimary: any;
3
4
  }) => import("react/jsx-runtime").JSX.Element;
4
5
  export default MessageLoading;
@@ -4,5 +4,5 @@ const jsx_runtime_1 = require("react/jsx-runtime");
4
4
  // ============================================================================
5
5
  // Chatbot Main - Message - Processing
6
6
  // ============================================================================
7
- const MessageLoading = ({ loadingWord }) => ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-loading", children: (0, jsx_runtime_1.jsx)("span", { className: "pf-chatbot__message-loading-dots", children: (0, jsx_runtime_1.jsx)("span", { className: "pf-v6-screen-reader", children: loadingWord }) }) }));
7
+ const MessageLoading = ({ loadingWord, isPrimary }) => ((0, jsx_runtime_1.jsx)("div", { className: `pf-chatbot__message-loading ${isPrimary ? 'pf-m-primary' : ''}`, children: (0, jsx_runtime_1.jsx)("span", { className: "pf-chatbot__message-loading-dots", children: (0, jsx_runtime_1.jsx)("span", { className: "pf-v6-screen-reader", children: loadingWord }) }) }));
8
8
  exports.default = MessageLoading;
@@ -15,5 +15,8 @@ export interface TableNode {
15
15
  tagName: string;
16
16
  type: string;
17
17
  }
18
- declare const TableMessage: ({ children, ...props }: Omit<TableProps, "ref"> & ExtraProps) => import("react/jsx-runtime").JSX.Element;
18
+ export interface TableMessageProps {
19
+ isPrimary?: boolean;
20
+ }
21
+ declare const TableMessage: ({ children, isPrimary, ...props }: Omit<TableProps, "ref"> & ExtraProps & TableMessageProps) => import("react/jsx-runtime").JSX.Element;
19
22
  export default TableMessage;
@@ -19,7 +19,7 @@ const react_1 = require("react");
19
19
  const react_table_1 = require("@patternfly/react-table");
20
20
  const TableMessage = (_a) => {
21
21
  var _b;
22
- var { children } = _a, props = __rest(_a, ["children"]);
22
+ var { children, isPrimary } = _a, props = __rest(_a, ["children", "isPrimary"]);
23
23
  const { className } = props, rest = __rest(props, ["className"]);
24
24
  // This allows us to parse the nested data we get back from the 3rd party Markdown parser
25
25
  // Open to feedback here if there is a better way to do this
@@ -60,6 +60,6 @@ const TableMessage = (_a) => {
60
60
  }
61
61
  return (
62
62
  // gridBreakPoint is so we show mobile-styled-PF table
63
- (0, jsx_runtime_1.jsx)(react_table_1.Table, Object.assign({ "aria-label": props['aria-label'], gridBreakPoint: "grid", className: `pf-chatbot__message-table ${className ? className : ''}` }, rest, { children: modifyChildren(children) })));
63
+ (0, jsx_runtime_1.jsx)(react_table_1.Table, Object.assign({ "aria-label": props['aria-label'], gridBreakPoint: "grid", className: `pf-chatbot__message-table ${isPrimary ? 'pf-m-primary' : ''} ${className ? className : ''}` }, rest, { children: modifyChildren(children) })));
64
64
  };
65
65
  exports.default = TableMessage;
@@ -1,4 +1,7 @@
1
1
  import { ExtraProps } from 'react-markdown';
2
2
  import { ContentProps } from '@patternfly/react-core';
3
- declare const TextMessage: ({ component, children, ...props }: Omit<ContentProps, "ref"> & ExtraProps) => import("react/jsx-runtime").JSX.Element;
3
+ export interface TextMessageProps {
4
+ isPrimary?: boolean;
5
+ }
6
+ declare const TextMessage: ({ component, children, isPrimary, ...props }: Omit<ContentProps, "ref"> & ExtraProps & TextMessageProps) => import("react/jsx-runtime").JSX.Element;
4
7
  export default TextMessage;
@@ -14,7 +14,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
14
14
  const jsx_runtime_1 = require("react/jsx-runtime");
15
15
  const react_core_1 = require("@patternfly/react-core");
16
16
  const TextMessage = (_a) => {
17
- var { component, children } = _a, props = __rest(_a, ["component", "children"]);
18
- return ((0, jsx_runtime_1.jsx)("span", { className: "pf-chatbot__message-text", children: (0, jsx_runtime_1.jsx)(react_core_1.Content, Object.assign({ component: component }, props, { children: children })) }));
17
+ var { component, children, isPrimary } = _a, props = __rest(_a, ["component", "children", "isPrimary"]);
18
+ return ((0, jsx_runtime_1.jsx)("span", { className: `pf-chatbot__message-text ${isPrimary ? 'pf-m-primary' : ''}`, children: (0, jsx_runtime_1.jsx)(react_core_1.Content, Object.assign({ component: component }, props, { children: children })) }));
19
19
  };
20
20
  exports.default = TextMessage;
@@ -41,5 +41,7 @@ export interface AttachButtonProps extends ButtonProps {
41
41
  validator?: <T extends File>(file: T) => FileError | readonly FileError[] | null;
42
42
  /** Additional props passed to react-dropzone */
43
43
  dropzoneProps?: DropzoneOptions;
44
+ /** Icon displayed in attach button */
45
+ icon?: React.ReactNode;
44
46
  }
45
47
  export declare const AttachButton: import("react").ForwardRefExoticComponent<AttachButtonProps & import("react").RefAttributes<any>>;
@@ -19,12 +19,12 @@ const react_core_1 = require("@patternfly/react-core");
19
19
  const react_dropzone_1 = require("react-dropzone");
20
20
  const paperclip_icon_1 = require("@patternfly/react-icons/dist/esm/icons/paperclip-icon");
21
21
  const AttachButtonBase = (_a) => {
22
- var { onAttachAccepted, onClick, isDisabled, className, tooltipProps, innerRef, tooltipContent = 'Attach', inputTestId, isCompact, allowedFileTypes, minSize, maxSize, maxFiles, isAttachmentDisabled, onAttach, onAttachRejected, validator, dropzoneProps } = _a, props = __rest(_a, ["onAttachAccepted", "onClick", "isDisabled", "className", "tooltipProps", "innerRef", "tooltipContent", "inputTestId", "isCompact", "allowedFileTypes", "minSize", "maxSize", "maxFiles", "isAttachmentDisabled", "onAttach", "onAttachRejected", "validator", "dropzoneProps"]);
22
+ var { onAttachAccepted, onClick, isDisabled, className, tooltipProps, innerRef, tooltipContent = 'Attach', inputTestId, isCompact, allowedFileTypes, minSize, maxSize, maxFiles, isAttachmentDisabled, onAttach, onAttachRejected, validator, dropzoneProps, icon = (0, jsx_runtime_1.jsx)(paperclip_icon_1.PaperclipIcon, {}) } = _a, props = __rest(_a, ["onAttachAccepted", "onClick", "isDisabled", "className", "tooltipProps", "innerRef", "tooltipContent", "inputTestId", "isCompact", "allowedFileTypes", "minSize", "maxSize", "maxFiles", "isAttachmentDisabled", "onAttach", "onAttachRejected", "validator", "dropzoneProps", "icon"]);
23
23
  const { open, getInputProps } = (0, react_dropzone_1.useDropzone)(Object.assign({ multiple: true, onDropAccepted: onAttachAccepted, accept: allowedFileTypes, minSize,
24
24
  maxSize,
25
25
  maxFiles, disabled: isAttachmentDisabled, onDrop: onAttach, onDropRejected: onAttachRejected, validator }, dropzoneProps));
26
26
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("input", Object.assign({ "data-testid": inputTestId }, getInputProps(), { hidden: true })), (0, jsx_runtime_1.jsx)(react_core_1.Tooltip, Object.assign({ id: "pf-chatbot__tooltip--attach", content: tooltipContent, position: "top", entryDelay: (tooltipProps === null || tooltipProps === void 0 ? void 0 : tooltipProps.entryDelay) || 0, exitDelay: (tooltipProps === null || tooltipProps === void 0 ? void 0 : tooltipProps.exitDelay) || 0, distance: (tooltipProps === null || tooltipProps === void 0 ? void 0 : tooltipProps.distance) || 8, animationDuration: (tooltipProps === null || tooltipProps === void 0 ? void 0 : tooltipProps.animationDuration) || 0,
27
27
  // prevents VO announcements of both aria label and tooltip
28
- aria: "none" }, tooltipProps, { children: (0, jsx_runtime_1.jsx)(react_core_1.Button, Object.assign({ variant: "plain", ref: innerRef, className: `pf-chatbot__button--attach ${isCompact ? 'pf-m-compact' : ''} ${className !== null && className !== void 0 ? className : ''}`, "aria-label": props['aria-label'] || 'Attach', isDisabled: isDisabled, onClick: onClick !== null && onClick !== void 0 ? onClick : open, icon: (0, jsx_runtime_1.jsx)(react_core_1.Icon, { iconSize: isCompact ? 'lg' : 'xl', isInline: true, children: (0, jsx_runtime_1.jsx)(paperclip_icon_1.PaperclipIcon, {}) }), size: isCompact ? 'sm' : undefined }, props)) }))] }));
28
+ aria: "none" }, tooltipProps, { children: (0, jsx_runtime_1.jsx)(react_core_1.Button, Object.assign({ variant: "plain", ref: innerRef, className: `pf-chatbot__button--attach ${isCompact ? 'pf-m-compact' : ''} ${className !== null && className !== void 0 ? className : ''}`, "aria-label": props['aria-label'] || 'Attach', isDisabled: isDisabled, onClick: onClick !== null && onClick !== void 0 ? onClick : open, icon: (0, jsx_runtime_1.jsx)(react_core_1.Icon, { iconSize: isCompact ? 'lg' : 'xl', isInline: true, children: icon }), size: isCompact ? 'sm' : undefined }, props)) }))] }));
29
29
  };
30
30
  exports.AttachButton = (0, react_1.forwardRef)((props, ref) => ((0, jsx_runtime_1.jsx)(AttachButtonBase, Object.assign({ innerRef: ref }, props))));
@@ -145,4 +145,8 @@ describe('Attach button', () => {
145
145
  expect(validator).toHaveBeenCalledWith(file);
146
146
  expect(onAttachRejected).toHaveBeenCalled();
147
147
  }));
148
+ it('should handle icon prop', () => {
149
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(AttachButton_1.AttachButton, { icon: (0, jsx_runtime_1.jsx)("img", { alt: "", src: "" }) }));
150
+ expect(react_1.screen.getByRole('img')).toBeVisible();
151
+ });
148
152
  });