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

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 (153) 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 +21 -3
  13. package/dist/cjs/Message/Message.js +11 -8
  14. package/dist/cjs/Message/Message.test.js +161 -2
  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 +229 -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 +21 -3
  57. package/dist/esm/Message/Message.js +11 -8
  58. package/dist/esm/Message/Message.test.js +161 -2
  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/MessageWithMultipleActionGroups.tsx +61 -0
  94. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithPersistedActions.tsx +22 -0
  95. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithQuickResponses.tsx +11 -0
  96. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +36 -4
  97. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +1 -0
  98. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx +3 -1
  99. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotMessageBarIndicatorThinking.tsx +15 -0
  100. package/patternfly-docs/content/extensions/chatbot/examples/UI/CompactOnboarding.tsx +141 -0
  101. package/patternfly-docs/content/extensions/chatbot/examples/UI/Onboarding.tsx +151 -0
  102. package/patternfly-docs/content/extensions/chatbot/examples/UI/RH-Hat-Image.svg +9 -0
  103. package/patternfly-docs/content/extensions/chatbot/examples/UI/Settings.tsx +1 -1
  104. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +55 -27
  105. package/patternfly-docs/content/extensions/chatbot/examples/demos/AttachmentDemos.md +18 -18
  106. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +29 -21
  107. package/patternfly-docs/content/extensions/chatbot/examples/demos/WhiteEmbeddedChatbot.tsx +451 -0
  108. package/patternfly-docs/patternfly-docs.config.js +2 -1
  109. package/patternfly-docs/patternfly-docs.source.js +1 -1
  110. package/src/AttachMenu/AttachMenu.tsx +26 -11
  111. package/src/Chatbot/Chatbot.scss +23 -1
  112. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +25 -0
  113. package/src/ChatbotFooter/ChatbotFooter.scss +21 -0
  114. package/src/ChatbotFooter/ChatbotFooter.test.tsx +10 -1
  115. package/src/ChatbotFooter/ChatbotFooter.tsx +10 -3
  116. package/src/ChatbotHeader/ChatbotHeader.scss +19 -0
  117. package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +56 -14
  118. package/src/ChatbotModal/ChatbotModal.scss +3 -0
  119. package/src/CodeModal/CodeModal.tsx +72 -23
  120. package/src/DeepThinking/DeepThinking.scss +1 -1
  121. package/src/FileDetailsLabel/FileDetailsLabel.tsx +2 -2
  122. package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +12 -0
  123. package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +4 -1
  124. package/src/Message/Message.scss +11 -7
  125. package/src/Message/Message.test.tsx +239 -2
  126. package/src/Message/Message.tsx +61 -17
  127. package/src/Message/MessageLoading.scss +7 -0
  128. package/src/Message/MessageLoading.tsx +2 -2
  129. package/src/Message/TableMessage/TableMessage.scss +6 -1
  130. package/src/Message/TableMessage/TableMessage.tsx +6 -2
  131. package/src/Message/TextMessage/TextMessage.scss +10 -0
  132. package/src/Message/TextMessage/TextMessage.tsx +11 -2
  133. package/src/Message/UserFeedback/UserFeedback.scss +2 -1
  134. package/src/MessageBar/AttachButton.test.tsx +4 -0
  135. package/src/MessageBar/AttachButton.tsx +4 -1
  136. package/src/MessageBar/MessageBar.scss +40 -3
  137. package/src/MessageBar/MessageBar.test.tsx +102 -1
  138. package/src/MessageBar/MessageBar.tsx +44 -11
  139. package/src/Onboarding/Onboarding.scss +101 -0
  140. package/src/Onboarding/Onboarding.test.tsx +148 -0
  141. package/src/Onboarding/Onboarding.tsx +126 -0
  142. package/src/Onboarding/index.ts +3 -0
  143. package/src/ResponseActions/ResponseActions.scss +12 -1
  144. package/src/ResponseActions/ResponseActions.test.tsx +111 -12
  145. package/src/ResponseActions/ResponseActions.tsx +38 -10
  146. package/src/ToolCall/ToolCall.scss +1 -1
  147. package/src/ToolResponse/ToolResponse.scss +3 -3
  148. package/src/__mocks__/monaco-editor.ts +19 -0
  149. package/src/__mocks__/rehype-highlight.ts +3 -0
  150. package/src/index.ts +3 -0
  151. package/src/main.scss +1 -0
  152. package/tsconfig.json +1 -1
  153. package/patternfly-docs/content/extensions/chatbot/about-chatbot.md +0 -44
@@ -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
  });
@@ -1,6 +1,7 @@
1
1
  import type { FunctionComponent } from 'react';
2
2
  import { Accept, DropEvent, DropzoneOptions, FileError, FileRejection } from 'react-dropzone';
3
- import { ButtonProps, TextAreaProps, TooltipProps } from '@patternfly/react-core';
3
+ import { ButtonProps, MenuSearchInputProps, MenuSearchProps, SearchInputProps, TextAreaProps, TooltipProps } from '@patternfly/react-core';
4
+ import { AttachButtonProps } from './AttachButton';
4
5
  import { ChatbotDisplayMode } from '../Chatbot';
5
6
  export interface MessageBarWithAttachMenuProps {
6
7
  /** Flag to enable whether attach menu is open */
@@ -12,7 +13,7 @@ export interface MessageBarWithAttachMenuProps {
12
13
  /** A callback for when the attachment menu toggle is clicked */
13
14
  onAttachMenuToggleClick: () => void;
14
15
  /** A callback for when the input value in the menu changes. */
15
- onAttachMenuInputChange: (value: string) => void;
16
+ onAttachMenuInputChange?: (value: string) => void;
16
17
  /** Function callback called when user selects item in menu. */
17
18
  onAttachMenuSelect?: (event?: React.MouseEvent<Element, MouseEvent>, value?: string | number) => void;
18
19
  /** Placeholder for search input */
@@ -21,6 +22,12 @@ export interface MessageBarWithAttachMenuProps {
21
22
  onAttachMenuOnOpenChangeKeys?: string[];
22
23
  /** Callback to change the open state of the menu. Triggered by clicking outside of the menu. */
23
24
  onAttachMenuOpenChange?: (isOpen: boolean) => void;
25
+ /** Additional props passed to MenuSearch component in attach menu */
26
+ menuSearchProps?: Omit<MenuSearchProps, 'ref'>;
27
+ /** Additional props passed to MenuSearchInput component in attach menu */
28
+ menuSearchInputProps?: Omit<MenuSearchInputProps, 'ref'>;
29
+ /** Additional props passed to SearchInput component in attach menu */
30
+ searchInputProps?: SearchInputProps;
24
31
  }
25
32
  export interface MessageBarProps extends Omit<TextAreaProps, 'innerRef'> {
26
33
  /** Callback to get the value of input message by user */
@@ -71,11 +78,8 @@ export interface MessageBarProps extends Omit<TextAreaProps, 'innerRef'> {
71
78
  isSendButtonDisabled?: boolean;
72
79
  /** Prop to allow passage of additional props to buttons */
73
80
  buttonProps?: {
74
- attach?: {
75
- tooltipContent?: string;
81
+ attach?: AttachButtonProps & {
76
82
  props?: ButtonProps;
77
- inputTestId?: string;
78
- tooltipProps?: Omit<TooltipProps, 'content'>;
79
83
  };
80
84
  stop?: {
81
85
  tooltipContent?: string;
@@ -105,6 +109,12 @@ export interface MessageBarProps extends Omit<TextAreaProps, 'innerRef'> {
105
109
  isCompact?: boolean;
106
110
  /** Ref applied to message bar textarea, for use with focus or other custom behaviors */
107
111
  innerRef?: React.Ref<HTMLTextAreaElement>;
112
+ /** Sets background color to primary */
113
+ isPrimary?: boolean;
114
+ /** @beta Flag indicating whether the message bar has an AI indicator border. */
115
+ hasAiIndicator?: boolean;
116
+ /** @beta Flag indicating whether the chatbot is thinking in response to a query, adding an animation to the message bar. */
117
+ isThinking?: boolean;
108
118
  }
109
119
  export declare const MessageBarBase: FunctionComponent<MessageBarProps>;
110
120
  declare const MessageBar: import("react").ForwardRefExoticComponent<MessageBarProps & import("react").RefAttributes<HTMLTextAreaElement>>;
@@ -18,6 +18,7 @@ exports.MessageBar = exports.MessageBarBase = void 0;
18
18
  const jsx_runtime_1 = require("react/jsx-runtime");
19
19
  const react_1 = require("react");
20
20
  const react_core_1 = require("@patternfly/react-core");
21
+ const react_styles_1 = require("@patternfly/react-styles");
21
22
  // Import Chatbot components
22
23
  const SendButton_1 = __importDefault(require("./SendButton"));
23
24
  const MicrophoneButton_1 = __importDefault(require("./MicrophoneButton"));
@@ -26,7 +27,7 @@ const AttachMenu_1 = __importDefault(require("../AttachMenu"));
26
27
  const StopButton_1 = __importDefault(require("./StopButton"));
27
28
  const MessageBarBase = (_a) => {
28
29
  var _b;
29
- var { onSendMessage, className, alwayShowSendButton, placeholder = 'Send a message...', hasAttachButton = true, hasMicrophoneButton, listeningText = 'Listening', handleAttach, attachMenuProps, isSendButtonDisabled, handleStopButton, hasStopButton, buttonProps, onChange, displayMode, value, isCompact = false, allowedFileTypes, minSize, maxSize, maxFiles, isAttachmentDisabled, onAttach, onAttachRejected, validator, dropzoneProps, innerRef } = _a, props = __rest(_a, ["onSendMessage", "className", "alwayShowSendButton", "placeholder", "hasAttachButton", "hasMicrophoneButton", "listeningText", "handleAttach", "attachMenuProps", "isSendButtonDisabled", "handleStopButton", "hasStopButton", "buttonProps", "onChange", "displayMode", "value", "isCompact", "allowedFileTypes", "minSize", "maxSize", "maxFiles", "isAttachmentDisabled", "onAttach", "onAttachRejected", "validator", "dropzoneProps", "innerRef"]);
30
+ var { onSendMessage, className, alwayShowSendButton, placeholder = 'Send a message...', hasAttachButton = true, hasMicrophoneButton, listeningText = 'Listening', handleAttach, attachMenuProps, isSendButtonDisabled, handleStopButton, hasStopButton, buttonProps, onChange, displayMode, value, isCompact = false, allowedFileTypes, minSize, maxSize, maxFiles, isAttachmentDisabled, onAttach, onAttachRejected, validator, dropzoneProps, innerRef, isPrimary, hasAiIndicator, isThinking } = _a, props = __rest(_a, ["onSendMessage", "className", "alwayShowSendButton", "placeholder", "hasAttachButton", "hasMicrophoneButton", "listeningText", "handleAttach", "attachMenuProps", "isSendButtonDisabled", "handleStopButton", "hasStopButton", "buttonProps", "onChange", "displayMode", "value", "isCompact", "allowedFileTypes", "minSize", "maxSize", "maxFiles", "isAttachmentDisabled", "onAttach", "onAttachRejected", "validator", "dropzoneProps", "innerRef", "isPrimary", "hasAiIndicator", "isThinking"]);
30
31
  // Text Input
31
32
  // --------------------------------------------------------------------------
32
33
  const [message, setMessage] = (0, react_1.useState)(value !== null && value !== void 0 ? value : '');
@@ -193,11 +194,11 @@ const MessageBarBase = (_a) => {
193
194
  onChange && onChange({}, message);
194
195
  };
195
196
  const renderButtons = () => {
196
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
197
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
197
198
  if (hasStopButton && handleStopButton) {
198
199
  return ((0, jsx_runtime_1.jsx)(StopButton_1.default, Object.assign({ onClick: handleStopButton, tooltipContent: (_a = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.stop) === null || _a === void 0 ? void 0 : _a.tooltipContent, isCompact: isCompact, tooltipProps: (_b = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.stop) === null || _b === void 0 ? void 0 : _b.tooltipProps }, (_c = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.stop) === null || _c === void 0 ? void 0 : _c.props)));
199
200
  }
200
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [attachMenuProps && ((0, jsx_runtime_1.jsx)(AttachButton_1.AttachButton, Object.assign({ ref: attachButtonRef, onClick: handleAttachMenuToggle, isDisabled: isListeningMessage, tooltipContent: (_d = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _d === void 0 ? void 0 : _d.tooltipContent, isCompact: isCompact, tooltipProps: (_e = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _e === void 0 ? void 0 : _e.tooltipProps, allowedFileTypes: allowedFileTypes, minSize: minSize, maxSize: maxSize, maxFiles: maxFiles, isAttachmentDisabled: isAttachmentDisabled, onAttach: onAttach, onAttachRejected: onAttachRejected, validator: validator, dropzoneProps: dropzoneProps }, (_f = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _f === void 0 ? void 0 : _f.props))), !attachMenuProps && hasAttachButton && ((0, jsx_runtime_1.jsx)(AttachButton_1.AttachButton, Object.assign({ onAttachAccepted: handleAttach, isDisabled: isListeningMessage, tooltipContent: (_g = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _g === void 0 ? void 0 : _g.tooltipContent, inputTestId: (_h = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _h === void 0 ? void 0 : _h.inputTestId, isCompact: isCompact, tooltipProps: (_j = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _j === void 0 ? void 0 : _j.tooltipProps, allowedFileTypes: allowedFileTypes, minSize: minSize, maxSize: maxSize, maxFiles: maxFiles, isAttachmentDisabled: isAttachmentDisabled, onAttach: onAttach, onAttachRejected: onAttachRejected, validator: validator, dropzoneProps: dropzoneProps }, (_k = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _k === void 0 ? void 0 : _k.props))), hasMicrophoneButton && ((0, jsx_runtime_1.jsx)(MicrophoneButton_1.default, Object.assign({ isListening: isListeningMessage, onIsListeningChange: setIsListeningMessage, onSpeechRecognition: handleSpeechRecognition, tooltipContent: (_l = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _l === void 0 ? void 0 : _l.tooltipContent, language: (_m = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _m === void 0 ? void 0 : _m.language, isCompact: isCompact, tooltipProps: (_o = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _o === void 0 ? void 0 : _o.tooltipProps }, (_p = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _p === void 0 ? void 0 : _p.props))), (alwayShowSendButton || message) && ((0, jsx_runtime_1.jsx)(SendButton_1.default, Object.assign({ value: message, onClick: () => handleSend(message), isDisabled: isSendButtonDisabled, tooltipContent: (_q = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _q === void 0 ? void 0 : _q.tooltipContent, isCompact: isCompact, tooltipProps: (_r = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _r === void 0 ? void 0 : _r.tooltipProps }, (_s = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _s === void 0 ? void 0 : _s.props)))] }));
201
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [attachMenuProps && ((0, jsx_runtime_1.jsx)(AttachButton_1.AttachButton, Object.assign({ ref: attachButtonRef, onClick: handleAttachMenuToggle, isDisabled: isListeningMessage, tooltipContent: (_d = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _d === void 0 ? void 0 : _d.tooltipContent, isCompact: isCompact, tooltipProps: (_e = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _e === void 0 ? void 0 : _e.tooltipProps, allowedFileTypes: allowedFileTypes, minSize: minSize, maxSize: maxSize, maxFiles: maxFiles, isAttachmentDisabled: isAttachmentDisabled, onAttach: onAttach, onAttachRejected: onAttachRejected, validator: validator, dropzoneProps: dropzoneProps }, buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach))), !attachMenuProps && hasAttachButton && ((0, jsx_runtime_1.jsx)(AttachButton_1.AttachButton, Object.assign({ onAttachAccepted: handleAttach, isDisabled: isListeningMessage, tooltipContent: (_f = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _f === void 0 ? void 0 : _f.tooltipContent, inputTestId: (_g = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _g === void 0 ? void 0 : _g.inputTestId, isCompact: isCompact, tooltipProps: (_h = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _h === void 0 ? void 0 : _h.tooltipProps, allowedFileTypes: allowedFileTypes, minSize: minSize, maxSize: maxSize, maxFiles: maxFiles, isAttachmentDisabled: isAttachmentDisabled, onAttach: onAttach, onAttachRejected: onAttachRejected, validator: validator, dropzoneProps: dropzoneProps }, buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach, (_j = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.attach) === null || _j === void 0 ? void 0 : _j.props))), hasMicrophoneButton && ((0, jsx_runtime_1.jsx)(MicrophoneButton_1.default, Object.assign({ isListening: isListeningMessage, onIsListeningChange: setIsListeningMessage, onSpeechRecognition: handleSpeechRecognition, tooltipContent: (_k = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _k === void 0 ? void 0 : _k.tooltipContent, language: (_l = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _l === void 0 ? void 0 : _l.language, isCompact: isCompact, tooltipProps: (_m = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _m === void 0 ? void 0 : _m.tooltipProps }, (_o = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.microphone) === null || _o === void 0 ? void 0 : _o.props))), (alwayShowSendButton || message) && ((0, jsx_runtime_1.jsx)(SendButton_1.default, Object.assign({ value: message, onClick: () => handleSend(message), isDisabled: isSendButtonDisabled, tooltipContent: (_p = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _p === void 0 ? void 0 : _p.tooltipContent, isCompact: isCompact, tooltipProps: (_q = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _q === void 0 ? void 0 : _q.tooltipProps }, (_r = buttonProps === null || buttonProps === void 0 ? void 0 : buttonProps.send) === null || _r === void 0 ? void 0 : _r.props)))] }));
201
202
  };
202
203
  const messageBarContents = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `pf-chatbot__message-bar-input ${isCompact ? 'pf-m-compact' : ''}`, children: (0, jsx_runtime_1.jsx)(react_core_1.TextArea, Object.assign({ className: "pf-chatbot__message-textarea", value: message, onChange: handleChange, "aria-label": isListeningMessage ? listeningText : placeholder, placeholder: isListeningMessage ? listeningText : placeholder, ref: textareaRef, onKeyDown: handleKeyDown, onCompositionStart: handleCompositionStart, onCompositionEnd: handleCompositionEnd }, props)) }), (0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__message-bar-actions", children: renderButtons() })] }));
203
204
  if (attachMenuProps) {
@@ -206,9 +207,9 @@ const MessageBarBase = (_a) => {
206
207
  (_a = attachButtonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
207
208
  attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.setIsAttachMenuOpen(isAttachMenuOpen);
208
209
  (attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuOpenChange) && (attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuOpenChange(isAttachMenuOpen));
209
- }, onOpenChangeKeys: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuOnOpenChangeKeys, onSelect: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuSelect }, (attachMenuProps && { handleTextInputChange: attachMenuProps.onAttachMenuInputChange }), { popperProps: { direction: 'up', distance: 8 }, searchInputPlaceholder: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.attachMenuInputPlaceholder })));
210
+ }, onOpenChangeKeys: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuOnOpenChangeKeys, onSelect: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.onAttachMenuSelect }, (attachMenuProps && { handleTextInputChange: attachMenuProps.onAttachMenuInputChange }), { popperProps: { direction: 'up', distance: 8 }, searchInputPlaceholder: attachMenuProps === null || attachMenuProps === void 0 ? void 0 : attachMenuProps.attachMenuInputPlaceholder }, attachMenuProps)));
210
211
  }
211
- return (0, jsx_runtime_1.jsx)("div", { className: `pf-chatbot__message-bar ${className !== null && className !== void 0 ? className : ''}`, children: messageBarContents });
212
+ return ((0, jsx_runtime_1.jsx)("div", { className: (0, react_styles_1.css)('pf-chatbot__message-bar', isPrimary && 'pf-m-primary', hasAiIndicator && 'pf-v6-m-ai-indicator', isThinking && 'pf-v6-m-thinking', className), children: messageBarContents }));
212
213
  };
213
214
  exports.MessageBarBase = MessageBarBase;
214
215
  const MessageBar = (0, react_1.forwardRef)((props, ref) => ((0, jsx_runtime_1.jsx)(exports.MessageBarBase, Object.assign({ innerRef: ref }, props))));
@@ -159,6 +159,48 @@ describe('Message bar', () => {
159
159
  yield user_event_1.default.click(attachButton);
160
160
  expect(attachToggleClickSpy).toHaveBeenCalledTimes(1);
161
161
  }));
162
+ it('can pass searchInputProps to search input in AttachMenu', () => {
163
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(MessageBar_1.MessageBar, { onSendMessage: jest.fn, value: "test", attachMenuProps: {
164
+ isAttachMenuOpen: true,
165
+ setIsAttachMenuOpen: jest.fn(),
166
+ onAttachMenuToggleClick: jest.fn(),
167
+ onAttachMenuInputChange: jest.fn(),
168
+ attachMenuItems: ATTACH_MENU_ITEMS,
169
+ searchInputProps: { isDisabled: true }
170
+ } }));
171
+ expect(react_1.screen.getByRole('textbox', { name: /Filter menu items/i })).toBeDisabled();
172
+ });
173
+ it('can pass menuSearchProps to search input in AttachMenu', () => {
174
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(MessageBar_1.MessageBar, { onSendMessage: jest.fn, value: "test", attachMenuProps: {
175
+ isAttachMenuOpen: true,
176
+ setIsAttachMenuOpen: jest.fn(),
177
+ onAttachMenuToggleClick: jest.fn(),
178
+ onAttachMenuInputChange: jest.fn(),
179
+ attachMenuItems: ATTACH_MENU_ITEMS,
180
+ menuSearchProps: { 'data-testid': 'menu-search' }
181
+ } }));
182
+ expect(react_1.screen.getByTestId('menu-search')).toBeTruthy();
183
+ });
184
+ it('can pass menuSearchInputProps to search input in AttachMenu', () => {
185
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(MessageBar_1.MessageBar, { onSendMessage: jest.fn, value: "test", attachMenuProps: {
186
+ isAttachMenuOpen: true,
187
+ setIsAttachMenuOpen: jest.fn(),
188
+ onAttachMenuToggleClick: jest.fn(),
189
+ onAttachMenuInputChange: jest.fn(),
190
+ attachMenuItems: ATTACH_MENU_ITEMS,
191
+ menuSearchInputProps: { 'data-testid': 'menu-search-input' }
192
+ } }));
193
+ expect(react_1.screen.getByTestId('menu-search-input')).toBeTruthy();
194
+ });
195
+ it('can remove input from attach menu', () => __awaiter(void 0, void 0, void 0, function* () {
196
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(MessageBar_1.MessageBar, { onSendMessage: jest.fn, attachMenuProps: {
197
+ isAttachMenuOpen: true,
198
+ setIsAttachMenuOpen: jest.fn(),
199
+ onAttachMenuToggleClick: jest.fn(),
200
+ attachMenuItems: ATTACH_MENU_ITEMS
201
+ } }));
202
+ expect(react_1.screen.queryByRole('textbox', { name: /Filter menu items/i })).not.toBeInTheDocument();
203
+ }));
162
204
  it('can hide attach button', () => {
163
205
  (0, react_1.render)((0, jsx_runtime_1.jsx)(MessageBar_1.MessageBar, { onSendMessage: jest.fn, hasAttachButton: false }));
164
206
  expect(react_1.screen.queryByRole('button', { name: 'Attach' })).toBeFalsy();
@@ -190,6 +232,14 @@ describe('Message bar', () => {
190
232
  (0, react_1.render)((0, jsx_runtime_1.jsx)(MessageBar_1.MessageBar, { onSendMessage: jest.fn, hasAttachButton: true, buttonProps: { attach: { props: { 'aria-label': 'Test' } } } }));
191
233
  yield user_event_1.default.click(react_1.screen.getByRole('button', { name: 'Test' }));
192
234
  }));
235
+ it('can change attach button icon', () => {
236
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(MessageBar_1.MessageBar, { onSendMessage: jest.fn, hasAttachButton: true, buttonProps: {
237
+ attach: {
238
+ icon: (0, jsx_runtime_1.jsx)("img", { alt: "", src: "" })
239
+ }
240
+ } }));
241
+ expect(react_1.screen.getByRole('img')).toBeVisible();
242
+ });
193
243
  // Stop button
194
244
  // --------------------------------------------------------------------------
195
245
  it('can show stop button', () => {
@@ -269,4 +319,16 @@ describe('Message bar', () => {
269
319
  (_a = ref.current) === null || _a === void 0 ? void 0 : _a.focus();
270
320
  expect(document.activeElement).toBe(react_1.screen.getByRole('textbox'));
271
321
  });
322
+ it('should handle isPrimary', () => {
323
+ const { container } = (0, react_1.render)((0, jsx_runtime_1.jsx)(MessageBar_1.MessageBar, { isPrimary: true, onSendMessage: jest.fn }));
324
+ expect(container.querySelector('.pf-m-primary')).toBeTruthy();
325
+ });
326
+ it('Renders with class pf-v6-m-ai-indicator when hasAiIndicator is true', () => {
327
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(MessageBar_1.MessageBar, { onSendMessage: jest.fn, hasAiIndicator: true }));
328
+ expect(react_1.screen.getByRole('textbox').closest('.pf-chatbot__message-bar')).toHaveClass('pf-v6-m-ai-indicator');
329
+ });
330
+ it('Renders with class pf-v6-m-thinking when isThinking is true', () => {
331
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(MessageBar_1.MessageBar, { onSendMessage: jest.fn, isThinking: true }));
332
+ expect(react_1.screen.getByRole('textbox').closest('.pf-chatbot__message-bar')).toHaveClass('pf-v6-m-thinking');
333
+ });
272
334
  });
@@ -0,0 +1,36 @@
1
+ import type { FunctionComponent } from 'react';
2
+ import { ModalProps } from '@patternfly/react-core';
3
+ import { ChatbotDisplayMode } from '../Chatbot';
4
+ export interface OnboardingProps extends ModalProps {
5
+ /** Class applied to modal */
6
+ className?: string;
7
+ /** Action assigned to primary modal button */
8
+ onPrimaryAction?: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void;
9
+ /** Action assigned to secondary modal button */
10
+ onSecondaryAction: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void;
11
+ /** Name of primary modal button */
12
+ primaryActionBtn?: string;
13
+ /** Name of secondary modal button */
14
+ secondaryActionBtn?: string;
15
+ /** Function that handles modal toggle */
16
+ handleModalToggle: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void;
17
+ /** Whether modal is open */
18
+ isModalOpen: boolean;
19
+ /** Title of modal */
20
+ title?: string;
21
+ /** Display mode for the Chatbot parent; this influences the styles applied */
22
+ displayMode?: ChatbotDisplayMode;
23
+ /** Optional image displayed in header */
24
+ headerImage?: string;
25
+ /** Alt text for optional image displayed in header */
26
+ headerImageAltText?: string;
27
+ /** Ref applied to modal */
28
+ innerRef?: React.Ref<HTMLDivElement>;
29
+ /** OuiaID applied to modal */
30
+ ouiaId?: string;
31
+ /** Sets modal to compact styling. */
32
+ isCompact?: boolean;
33
+ }
34
+ export declare const OnboardingBase: FunctionComponent<OnboardingProps>;
35
+ declare const Onboarding: import("react").ForwardRefExoticComponent<Omit<OnboardingProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
36
+ export default Onboarding;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.OnboardingBase = void 0;
18
+ const jsx_runtime_1 = require("react/jsx-runtime");
19
+ const react_1 = require("react");
20
+ const react_core_1 = require("@patternfly/react-core");
21
+ const Chatbot_1 = require("../Chatbot");
22
+ const ChatbotModal_1 = __importDefault(require("../ChatbotModal/ChatbotModal"));
23
+ const OnboardingBase = (_a) => {
24
+ var { handleModalToggle, isModalOpen, onPrimaryAction, onSecondaryAction, primaryActionBtn = 'Continue', secondaryActionBtn = 'Skip', title = 'Onboarding', headerImage, headerImageAltText = '', displayMode = Chatbot_1.ChatbotDisplayMode.default, className, children, innerRef, ouiaId = 'Onboarding', isCompact } = _a, props = __rest(_a, ["handleModalToggle", "isModalOpen", "onPrimaryAction", "onSecondaryAction", "primaryActionBtn", "secondaryActionBtn", "title", "headerImage", "headerImageAltText", "displayMode", "className", "children", "innerRef", "ouiaId", "isCompact"]);
25
+ const handlePrimaryAction = (_event) => {
26
+ handleModalToggle(_event);
27
+ onPrimaryAction && onPrimaryAction(_event);
28
+ };
29
+ const handleSecondaryAction = (_event) => {
30
+ onSecondaryAction(_event);
31
+ };
32
+ const modal = ((0, jsx_runtime_1.jsx)(ChatbotModal_1.default, Object.assign({ isOpen: isModalOpen, ouiaId: ouiaId, "aria-labelledby": "onboarding-title", "aria-describedby": "onboarding-modal", className: `pf-chatbot__onboarding-modal pf-chatbot__onboarding-modal--${displayMode} ${isCompact ? 'pf-m-compact' : ''} ${className ? className : ''}`, displayMode: displayMode, onClose: handleModalToggle }, props, { children: (0, jsx_runtime_1.jsx)("section", { className: `pf-chatbot__onboarding--section`, "aria-label": title, tabIndex: -1, ref: innerRef, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(react_core_1.ModalBody, { className: "pf-chatbot__onboarding--modal-body", children: [!isCompact && headerImage && ((0, jsx_runtime_1.jsx)("div", { className: "pf-chatbot__onboarding--header", children: (0, jsx_runtime_1.jsx)("img", { src: headerImage, className: "pf-chatbot__onboarding--image", alt: headerImageAltText }) })), (0, jsx_runtime_1.jsxs)("div", { className: "pf-chatbot__onboarding--modal-text", children: [(0, jsx_runtime_1.jsx)("h1", { className: "pf-chatbot__onboarding--title", children: title }), (0, jsx_runtime_1.jsx)(react_core_1.Content, { children: children })] })] }), (0, jsx_runtime_1.jsxs)(react_core_1.ModalFooter, { className: "pf-chatbot__onboarding--footer", children: [(0, jsx_runtime_1.jsx)(react_core_1.Button, { isBlock: true, variant: "primary", onClick: handlePrimaryAction, form: "onboarding-form", size: "lg", children: primaryActionBtn }, "onboarding-modal-primary"), (0, jsx_runtime_1.jsx)(react_core_1.Button, { isBlock: true, variant: "secondary", onClick: handleSecondaryAction, size: "lg", children: secondaryActionBtn }, "onboarding-modal-secondary")] })] }) }) })));
33
+ return modal;
34
+ };
35
+ exports.OnboardingBase = OnboardingBase;
36
+ const Onboarding = (0, react_1.forwardRef)((props, ref) => ((0, jsx_runtime_1.jsx)(exports.OnboardingBase, Object.assign({ innerRef: ref }, props))));
37
+ exports.default = Onboarding;
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const jsx_runtime_1 = require("react/jsx-runtime");
16
+ const react_1 = require("@testing-library/react");
17
+ require("@testing-library/jest-dom");
18
+ const user_event_1 = __importDefault(require("@testing-library/user-event"));
19
+ const Onboarding_1 = __importDefault(require("./Onboarding"));
20
+ const handleModalToggle = jest.fn();
21
+ const onPrimaryAction = jest.fn();
22
+ const onSecondaryAction = jest.fn();
23
+ const body = 'Experience personalized assistance and seamless problem-solving, simplifying your journey with Red Hat every step of the way.';
24
+ describe('Onboarding', () => {
25
+ afterEach(() => {
26
+ jest.clearAllMocks();
27
+ });
28
+ it('should render modal correctly', () => {
29
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(Onboarding_1.default, { isModalOpen: true, onSecondaryAction: onSecondaryAction, handleModalToggle: handleModalToggle, ouiaId: "Terms", children: body }));
30
+ expect(react_1.screen.getByRole('heading', { name: /Onboarding/i })).toBeTruthy();
31
+ expect(react_1.screen.getByRole('button', { name: /Continue/i })).toBeTruthy();
32
+ expect(react_1.screen.getByRole('button', { name: /Skip/i })).toBeTruthy();
33
+ expect(react_1.screen.getByText(body)).toBeTruthy();
34
+ expect(react_1.screen.getByRole('dialog')).toHaveClass('pf-chatbot__onboarding-modal');
35
+ expect(react_1.screen.getByRole('dialog')).toHaveClass('pf-chatbot__onboarding-modal--default');
36
+ });
37
+ it('should handle image and altText props', () => {
38
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(Onboarding_1.default, { isModalOpen: true, onSecondaryAction: onSecondaryAction, handleModalToggle: handleModalToggle, headerImage: "./image.png", headerImageAltText: "Test image", children: body }));
39
+ expect(react_1.screen.getByRole('img')).toBeTruthy();
40
+ expect(react_1.screen.getByRole('img')).toHaveAttribute('alt', 'Test image');
41
+ });
42
+ it('should handle className prop', () => {
43
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(Onboarding_1.default, { isModalOpen: true, onSecondaryAction: onSecondaryAction, handleModalToggle: handleModalToggle, className: "test", children: body }));
44
+ expect(react_1.screen.getByRole('dialog')).toHaveClass('pf-chatbot__onboarding-modal');
45
+ expect(react_1.screen.getByRole('dialog')).toHaveClass('pf-chatbot__onboarding-modal--default');
46
+ expect(react_1.screen.getByRole('dialog')).toHaveClass('test');
47
+ });
48
+ it('should handle title prop', () => {
49
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(Onboarding_1.default, { isModalOpen: true, onSecondaryAction: onSecondaryAction, handleModalToggle: handleModalToggle, title: "Updated title", children: body }));
50
+ expect(react_1.screen.getByRole('heading', { name: /Updated title/i })).toBeTruthy();
51
+ expect(react_1.screen.queryByRole('heading', { name: /Onboarding/i })).toBeFalsy();
52
+ });
53
+ it('should handle primary button prop', () => {
54
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(Onboarding_1.default, { isModalOpen: true, onSecondaryAction: onSecondaryAction, handleModalToggle: handleModalToggle, primaryActionBtn: "First", children: body }));
55
+ expect(react_1.screen.getByRole('button', { name: /First/i })).toBeTruthy();
56
+ expect(react_1.screen.queryByRole('button', { name: /Continue/i })).toBeFalsy();
57
+ });
58
+ it('should handle secondary button prop', () => {
59
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(Onboarding_1.default, { isModalOpen: true, onSecondaryAction: onSecondaryAction, handleModalToggle: handleModalToggle, secondaryActionBtn: "Second", children: body }));
60
+ expect(react_1.screen.getByRole('button', { name: /Second/i })).toBeTruthy();
61
+ expect(react_1.screen.queryByRole('button', { name: /Skip/i })).toBeFalsy();
62
+ });
63
+ it('should handle primary button click', () => __awaiter(void 0, void 0, void 0, function* () {
64
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(Onboarding_1.default, { isModalOpen: true, onPrimaryAction: onPrimaryAction, onSecondaryAction: onSecondaryAction, handleModalToggle: handleModalToggle, children: body }));
65
+ yield user_event_1.default.click(react_1.screen.getByRole('button', { name: /Continue/i }));
66
+ expect(onPrimaryAction).toHaveBeenCalledTimes(1);
67
+ expect(handleModalToggle).toHaveBeenCalledTimes(1);
68
+ }));
69
+ it('should handle secondary button click', () => __awaiter(void 0, void 0, void 0, function* () {
70
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(Onboarding_1.default, { isModalOpen: true, onSecondaryAction: onSecondaryAction, handleModalToggle: handleModalToggle, children: body }));
71
+ yield user_event_1.default.click(react_1.screen.getByRole('button', { name: /Skip/i }));
72
+ expect(onSecondaryAction).toHaveBeenCalledTimes(1);
73
+ expect(handleModalToggle).not.toHaveBeenCalled();
74
+ }));
75
+ it('should handle isCompact prop', () => {
76
+ (0, react_1.render)((0, jsx_runtime_1.jsx)(Onboarding_1.default, { isModalOpen: true, onSecondaryAction: onSecondaryAction, handleModalToggle: handleModalToggle, isCompact: true, headerImage: "./image.png", headerImageAltText: "Test image", children: body }));
77
+ expect(react_1.screen.getByRole('dialog')).toHaveClass('pf-m-compact');
78
+ expect(react_1.screen.queryByRole('img')).toBeFalsy();
79
+ });
80
+ });
@@ -0,0 +1,2 @@
1
+ export { default } from './Onboarding';
2
+ export * from './Onboarding';
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.default = void 0;
21
+ var Onboarding_1 = require("./Onboarding");
22
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(Onboarding_1).default; } });
23
+ __exportStar(require("./Onboarding"), exports);
@@ -40,6 +40,9 @@ export interface ResponseActionProps {
40
40
  listen?: ActionProps;
41
41
  edit?: ActionProps;
42
42
  };
43
+ /** When true, the selected action will persist even when clicking outside the component.
44
+ * When false (default), clicking outside or clicking another action will deselect the current selection. */
45
+ persistActionSelection?: boolean;
43
46
  }
44
47
  export declare const ResponseActions: FunctionComponent<ResponseActionProps>;
45
48
  export default ResponseActions;
@@ -20,10 +20,11 @@ const jsx_runtime_1 = require("react/jsx-runtime");
20
20
  const react_2 = require("react");
21
21
  const react_icons_1 = require("@patternfly/react-icons");
22
22
  const ResponseActionButton_1 = __importDefault(require("./ResponseActionButton"));
23
- const ResponseActions = ({ actions }) => {
23
+ const ResponseActions = ({ actions, persistActionSelection = false }) => {
24
24
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3;
25
25
  const [activeButton, setActiveButton] = (0, react_2.useState)();
26
26
  const [clickStatePersisted, setClickStatePersisted] = (0, react_2.useState)(false);
27
+ const { positive, negative, copy, edit, share, download, listen } = actions, additionalActions = __rest(actions, ["positive", "negative", "copy", "edit", "share", "download", "listen"]);
27
28
  (0, react_2.useEffect)(() => {
28
29
  // Define the order of precedence for checking initial `isClicked`
29
30
  const actionPrecedence = ['positive', 'negative', 'copy', 'edit', 'share', 'download', 'listen'];
@@ -45,11 +46,18 @@ const ResponseActions = ({ actions }) => {
45
46
  // Click state is explicitly controlled by consumer.
46
47
  setClickStatePersisted(true);
47
48
  }
49
+ // If persistActionSelection is true, all selections are persisted
50
+ if (persistActionSelection) {
51
+ setClickStatePersisted(true);
52
+ }
48
53
  setActiveButton(initialActive);
49
- }, [actions]);
50
- const { positive, negative, copy, edit, share, download, listen } = actions, additionalActions = __rest(actions, ["positive", "negative", "copy", "edit", "share", "download", "listen"]);
54
+ }, [actions, persistActionSelection]);
51
55
  const responseActions = (0, react_2.useRef)(null);
52
56
  (0, react_2.useEffect)(() => {
57
+ // Only add click outside listener if not persisting selection
58
+ if (persistActionSelection) {
59
+ return;
60
+ }
53
61
  const handleClickOutside = (e) => {
54
62
  if (responseActions.current && !responseActions.current.contains(e.target) && !clickStatePersisted) {
55
63
  setActiveButton(undefined);
@@ -59,13 +67,26 @@ const ResponseActions = ({ actions }) => {
59
67
  return () => {
60
68
  window.removeEventListener('click', handleClickOutside);
61
69
  };
62
- }, [clickStatePersisted]);
70
+ }, [clickStatePersisted, persistActionSelection]);
63
71
  const handleClick = (e, id, onClick) => {
64
- setClickStatePersisted(false);
65
- setActiveButton(id);
72
+ if (persistActionSelection) {
73
+ if (activeButton === id) {
74
+ // Toggle off if clicking the same button
75
+ setActiveButton(undefined);
76
+ }
77
+ else {
78
+ // Set new active button
79
+ setActiveButton(id);
80
+ }
81
+ setClickStatePersisted(true);
82
+ }
83
+ else {
84
+ setClickStatePersisted(false);
85
+ setActiveButton(id);
86
+ }
66
87
  onClick && onClick(e);
67
88
  };
68
- return ((0, jsx_runtime_1.jsxs)("div", { ref: responseActions, className: "pf-chatbot__response-actions", children: [positive && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, positive, { ariaLabel: (_a = positive.ariaLabel) !== null && _a !== void 0 ? _a : 'Good response', clickedAriaLabel: (_b = positive.ariaLabel) !== null && _b !== void 0 ? _b : 'Response recorded', onClick: (e) => handleClick(e, 'positive', positive.onClick), className: positive.className, isDisabled: positive.isDisabled, tooltipContent: (_c = positive.tooltipContent) !== null && _c !== void 0 ? _c : 'Good response', clickedTooltipContent: (_d = positive.clickedTooltipContent) !== null && _d !== void 0 ? _d : 'Response recorded', tooltipProps: positive.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.OutlinedThumbsUpIcon, {}), isClicked: activeButton === 'positive', ref: positive.ref, "aria-expanded": positive['aria-expanded'], "aria-controls": positive['aria-controls'] }))), negative && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, negative, { ariaLabel: (_e = negative.ariaLabel) !== null && _e !== void 0 ? _e : 'Bad response', clickedAriaLabel: (_f = negative.ariaLabel) !== null && _f !== void 0 ? _f : 'Response recorded', onClick: (e) => handleClick(e, 'negative', negative.onClick), className: negative.className, isDisabled: negative.isDisabled, tooltipContent: (_g = negative.tooltipContent) !== null && _g !== void 0 ? _g : 'Bad response', clickedTooltipContent: (_h = negative.clickedTooltipContent) !== null && _h !== void 0 ? _h : 'Response recorded', tooltipProps: negative.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.OutlinedThumbsDownIcon, {}), isClicked: activeButton === 'negative', ref: negative.ref, "aria-expanded": negative['aria-expanded'], "aria-controls": negative['aria-controls'] }))), copy && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, copy, { ariaLabel: (_j = copy.ariaLabel) !== null && _j !== void 0 ? _j : 'Copy', clickedAriaLabel: (_k = copy.ariaLabel) !== null && _k !== void 0 ? _k : 'Copied', onClick: (e) => handleClick(e, 'copy', copy.onClick), className: copy.className, isDisabled: copy.isDisabled, tooltipContent: (_l = copy.tooltipContent) !== null && _l !== void 0 ? _l : 'Copy', clickedTooltipContent: (_m = copy.clickedTooltipContent) !== null && _m !== void 0 ? _m : 'Copied', tooltipProps: copy.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.OutlinedCopyIcon, {}), isClicked: activeButton === 'copy', ref: copy.ref, "aria-expanded": copy['aria-expanded'], "aria-controls": copy['aria-controls'] }))), edit && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, edit, { ariaLabel: (_o = edit.ariaLabel) !== null && _o !== void 0 ? _o : 'Edit', clickedAriaLabel: (_p = edit.ariaLabel) !== null && _p !== void 0 ? _p : 'Editing', onClick: (e) => handleClick(e, 'edit', edit.onClick), className: edit.className, isDisabled: edit.isDisabled, tooltipContent: (_q = edit.tooltipContent) !== null && _q !== void 0 ? _q : 'Edit ', clickedTooltipContent: (_r = edit.clickedTooltipContent) !== null && _r !== void 0 ? _r : 'Editing', tooltipProps: edit.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.PencilAltIcon, {}), isClicked: activeButton === 'edit', ref: edit.ref, "aria-expanded": edit['aria-expanded'], "aria-controls": edit['aria-controls'] }))), share && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, share, { ariaLabel: (_s = share.ariaLabel) !== null && _s !== void 0 ? _s : 'Share', clickedAriaLabel: (_t = share.ariaLabel) !== null && _t !== void 0 ? _t : 'Shared', onClick: (e) => handleClick(e, 'share', share.onClick), className: share.className, isDisabled: share.isDisabled, tooltipContent: (_u = share.tooltipContent) !== null && _u !== void 0 ? _u : 'Share', clickedTooltipContent: (_v = share.clickedTooltipContent) !== null && _v !== void 0 ? _v : 'Shared', tooltipProps: share.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.ExternalLinkAltIcon, {}), isClicked: activeButton === 'share', ref: share.ref, "aria-expanded": share['aria-expanded'], "aria-controls": share['aria-controls'] }))), download && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, download, { ariaLabel: (_w = download.ariaLabel) !== null && _w !== void 0 ? _w : 'Download', clickedAriaLabel: (_x = download.ariaLabel) !== null && _x !== void 0 ? _x : 'Downloaded', onClick: (e) => handleClick(e, 'download', download.onClick), className: download.className, isDisabled: download.isDisabled, tooltipContent: (_y = download.tooltipContent) !== null && _y !== void 0 ? _y : 'Download', clickedTooltipContent: (_z = download.clickedTooltipContent) !== null && _z !== void 0 ? _z : 'Downloaded', tooltipProps: download.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.DownloadIcon, {}), isClicked: activeButton === 'download', ref: download.ref, "aria-expanded": download['aria-expanded'], "aria-controls": download['aria-controls'] }))), listen && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, listen, { ariaLabel: (_0 = listen.ariaLabel) !== null && _0 !== void 0 ? _0 : 'Listen', clickedAriaLabel: (_1 = listen.ariaLabel) !== null && _1 !== void 0 ? _1 : 'Listening', onClick: (e) => handleClick(e, 'listen', listen.onClick), className: listen.className, isDisabled: listen.isDisabled, tooltipContent: (_2 = listen.tooltipContent) !== null && _2 !== void 0 ? _2 : 'Listen', clickedTooltipContent: (_3 = listen.clickedTooltipContent) !== null && _3 !== void 0 ? _3 : 'Listening', tooltipProps: listen.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.VolumeUpIcon, {}), isClicked: activeButton === 'listen', ref: listen.ref, "aria-expanded": listen['aria-expanded'], "aria-controls": listen['aria-controls'] }))), Object.keys(additionalActions).map((action) => {
89
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: responseActions, className: "pf-chatbot__response-actions", children: [positive && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, positive, { ariaLabel: (_a = positive.ariaLabel) !== null && _a !== void 0 ? _a : 'Good response', clickedAriaLabel: (_b = positive.ariaLabel) !== null && _b !== void 0 ? _b : 'Good response recorded', onClick: (e) => handleClick(e, 'positive', positive.onClick), className: positive.className, isDisabled: positive.isDisabled, tooltipContent: (_c = positive.tooltipContent) !== null && _c !== void 0 ? _c : 'Good response', clickedTooltipContent: (_d = positive.clickedTooltipContent) !== null && _d !== void 0 ? _d : 'Good response recorded', tooltipProps: positive.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.OutlinedThumbsUpIcon, {}), isClicked: activeButton === 'positive', ref: positive.ref, "aria-expanded": positive['aria-expanded'], "aria-controls": positive['aria-controls'] }))), negative && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, negative, { ariaLabel: (_e = negative.ariaLabel) !== null && _e !== void 0 ? _e : 'Bad response', clickedAriaLabel: (_f = negative.ariaLabel) !== null && _f !== void 0 ? _f : 'Bad response recorded', onClick: (e) => handleClick(e, 'negative', negative.onClick), className: negative.className, isDisabled: negative.isDisabled, tooltipContent: (_g = negative.tooltipContent) !== null && _g !== void 0 ? _g : 'Bad response', clickedTooltipContent: (_h = negative.clickedTooltipContent) !== null && _h !== void 0 ? _h : 'Bad response recorded', tooltipProps: negative.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.OutlinedThumbsDownIcon, {}), isClicked: activeButton === 'negative', ref: negative.ref, "aria-expanded": negative['aria-expanded'], "aria-controls": negative['aria-controls'] }))), copy && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, copy, { ariaLabel: (_j = copy.ariaLabel) !== null && _j !== void 0 ? _j : 'Copy', clickedAriaLabel: (_k = copy.ariaLabel) !== null && _k !== void 0 ? _k : 'Copied', onClick: (e) => handleClick(e, 'copy', copy.onClick), className: copy.className, isDisabled: copy.isDisabled, tooltipContent: (_l = copy.tooltipContent) !== null && _l !== void 0 ? _l : 'Copy', clickedTooltipContent: (_m = copy.clickedTooltipContent) !== null && _m !== void 0 ? _m : 'Copied', tooltipProps: copy.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.OutlinedCopyIcon, {}), isClicked: activeButton === 'copy', ref: copy.ref, "aria-expanded": copy['aria-expanded'], "aria-controls": copy['aria-controls'] }))), edit && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, edit, { ariaLabel: (_o = edit.ariaLabel) !== null && _o !== void 0 ? _o : 'Edit', clickedAriaLabel: (_p = edit.ariaLabel) !== null && _p !== void 0 ? _p : 'Editing', onClick: (e) => handleClick(e, 'edit', edit.onClick), className: edit.className, isDisabled: edit.isDisabled, tooltipContent: (_q = edit.tooltipContent) !== null && _q !== void 0 ? _q : 'Edit ', clickedTooltipContent: (_r = edit.clickedTooltipContent) !== null && _r !== void 0 ? _r : 'Editing', tooltipProps: edit.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.PencilAltIcon, {}), isClicked: activeButton === 'edit', ref: edit.ref, "aria-expanded": edit['aria-expanded'], "aria-controls": edit['aria-controls'] }))), share && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, share, { ariaLabel: (_s = share.ariaLabel) !== null && _s !== void 0 ? _s : 'Share', clickedAriaLabel: (_t = share.ariaLabel) !== null && _t !== void 0 ? _t : 'Shared', onClick: (e) => handleClick(e, 'share', share.onClick), className: share.className, isDisabled: share.isDisabled, tooltipContent: (_u = share.tooltipContent) !== null && _u !== void 0 ? _u : 'Share', clickedTooltipContent: (_v = share.clickedTooltipContent) !== null && _v !== void 0 ? _v : 'Shared', tooltipProps: share.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.ExternalLinkAltIcon, {}), isClicked: activeButton === 'share', ref: share.ref, "aria-expanded": share['aria-expanded'], "aria-controls": share['aria-controls'] }))), download && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, download, { ariaLabel: (_w = download.ariaLabel) !== null && _w !== void 0 ? _w : 'Download', clickedAriaLabel: (_x = download.ariaLabel) !== null && _x !== void 0 ? _x : 'Downloaded', onClick: (e) => handleClick(e, 'download', download.onClick), className: download.className, isDisabled: download.isDisabled, tooltipContent: (_y = download.tooltipContent) !== null && _y !== void 0 ? _y : 'Download', clickedTooltipContent: (_z = download.clickedTooltipContent) !== null && _z !== void 0 ? _z : 'Downloaded', tooltipProps: download.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.DownloadIcon, {}), isClicked: activeButton === 'download', ref: download.ref, "aria-expanded": download['aria-expanded'], "aria-controls": download['aria-controls'] }))), listen && ((0, jsx_runtime_1.jsx)(ResponseActionButton_1.default, Object.assign({}, listen, { ariaLabel: (_0 = listen.ariaLabel) !== null && _0 !== void 0 ? _0 : 'Listen', clickedAriaLabel: (_1 = listen.ariaLabel) !== null && _1 !== void 0 ? _1 : 'Listening', onClick: (e) => handleClick(e, 'listen', listen.onClick), className: listen.className, isDisabled: listen.isDisabled, tooltipContent: (_2 = listen.tooltipContent) !== null && _2 !== void 0 ? _2 : 'Listen', clickedTooltipContent: (_3 = listen.clickedTooltipContent) !== null && _3 !== void 0 ? _3 : 'Listening', tooltipProps: listen.tooltipProps, icon: (0, jsx_runtime_1.jsx)(react_icons_1.VolumeUpIcon, {}), isClicked: activeButton === 'listen', ref: listen.ref, "aria-expanded": listen['aria-expanded'], "aria-controls": listen['aria-controls'] }))), Object.keys(additionalActions).map((action) => {
69
90
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
70
91
  return ((0, react_1.createElement)(ResponseActionButton_1.default, Object.assign({}, additionalActions[action], { key: action, ariaLabel: (_a = additionalActions[action]) === null || _a === void 0 ? void 0 : _a.ariaLabel, clickedAriaLabel: (_b = additionalActions[action]) === null || _b === void 0 ? void 0 : _b.clickedAriaLabel, onClick: (e) => { var _a; return handleClick(e, action, (_a = additionalActions[action]) === null || _a === void 0 ? void 0 : _a.onClick); }, className: (_c = additionalActions[action]) === null || _c === void 0 ? void 0 : _c.className, isDisabled: (_d = additionalActions[action]) === null || _d === void 0 ? void 0 : _d.isDisabled, tooltipContent: (_e = additionalActions[action]) === null || _e === void 0 ? void 0 : _e.tooltipContent, tooltipProps: (_f = additionalActions[action]) === null || _f === void 0 ? void 0 : _f.tooltipProps, clickedTooltipContent: (_g = additionalActions[action]) === null || _g === void 0 ? void 0 : _g.clickedTooltipContent, icon: (_h = additionalActions[action]) === null || _h === void 0 ? void 0 : _h.icon, isClicked: activeButton === action, ref: (_j = additionalActions[action]) === null || _j === void 0 ? void 0 : _j.ref, "aria-expanded": (_k = additionalActions[action]) === null || _k === void 0 ? void 0 : _k['aria-expanded'], "aria-controls": (_l = additionalActions[action]) === null || _l === void 0 ? void 0 : _l['aria-controls'] })));
71
92
  })] }));