@patternfly/chatbot 6.4.0-prerelease.2 → 6.4.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 (186) hide show
  1. package/dist/cjs/Chatbot/Chatbot.js +1 -7
  2. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
  3. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
  4. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +22 -2
  5. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +15 -9
  6. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +40 -2
  7. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
  8. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
  9. package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
  10. package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.js +25 -0
  11. package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
  12. package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +22 -0
  13. package/dist/cjs/ChatbotHeader/index.d.ts +1 -0
  14. package/dist/cjs/ChatbotHeader/index.js +1 -0
  15. package/dist/cjs/DeepThinking/DeepThinking.d.ts +18 -0
  16. package/dist/cjs/DeepThinking/DeepThinking.js +18 -0
  17. package/dist/cjs/DeepThinking/DeepThinking.test.d.ts +1 -0
  18. package/dist/cjs/DeepThinking/DeepThinking.test.js +48 -0
  19. package/dist/cjs/DeepThinking/index.d.ts +2 -0
  20. package/dist/cjs/DeepThinking/index.js +23 -0
  21. package/dist/cjs/FilePreview/FilePreview.d.ts +26 -0
  22. package/dist/cjs/FilePreview/FilePreview.js +26 -0
  23. package/dist/cjs/FilePreview/FilePreview.test.d.ts +1 -0
  24. package/dist/cjs/FilePreview/FilePreview.test.js +97 -0
  25. package/dist/cjs/FilePreview/index.d.ts +2 -0
  26. package/dist/cjs/FilePreview/index.js +23 -0
  27. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +3 -3
  28. package/dist/cjs/Message/LinkMessage/LinkMessage.d.ts +2 -1
  29. package/dist/cjs/Message/LinkMessage/LinkMessage.js +7 -3
  30. package/dist/cjs/Message/ListMessage/ListItemMessage.d.ts +1 -1
  31. package/dist/cjs/Message/ListMessage/ListItemMessage.js +16 -1
  32. package/dist/cjs/Message/Message.d.ts +15 -0
  33. package/dist/cjs/Message/Message.js +129 -32
  34. package/dist/cjs/Message/Message.test.js +71 -0
  35. package/dist/cjs/Message/SuperscriptMessage/SuperscriptMessage.d.ts +3 -0
  36. package/dist/cjs/Message/SuperscriptMessage/SuperscriptMessage.js +5 -0
  37. package/dist/cjs/Message/UserFeedback/UserFeedback.d.ts +15 -1
  38. package/dist/cjs/Message/UserFeedback/UserFeedback.js +4 -4
  39. package/dist/cjs/Message/UserFeedback/UserFeedback.test.js +44 -0
  40. package/dist/cjs/MessageBar/MessageBar.js +19 -4
  41. package/dist/cjs/MessageBox/JumpButton.d.ts +5 -0
  42. package/dist/cjs/MessageBox/JumpButton.js +1 -1
  43. package/dist/cjs/MessageBox/JumpButton.test.js +4 -4
  44. package/dist/cjs/MessageBox/MessageBox.d.ts +9 -0
  45. package/dist/cjs/MessageBox/MessageBox.js +2 -2
  46. package/dist/cjs/MessageBox/MessageBox.test.js +2 -2
  47. package/dist/cjs/SourcesCard/SourcesCard.d.ts +13 -1
  48. package/dist/cjs/SourcesCard/SourcesCard.js +6 -6
  49. package/dist/cjs/SourcesCard/SourcesCard.test.js +49 -0
  50. package/dist/cjs/ToolResponse/ToolResponse.d.ts +30 -0
  51. package/dist/cjs/ToolResponse/ToolResponse.js +18 -0
  52. package/dist/cjs/ToolResponse/ToolResponse.test.d.ts +1 -0
  53. package/dist/cjs/ToolResponse/ToolResponse.test.js +60 -0
  54. package/dist/cjs/ToolResponse/index.d.ts +2 -0
  55. package/dist/cjs/ToolResponse/index.js +23 -0
  56. package/dist/cjs/index.d.ts +6 -0
  57. package/dist/cjs/index.js +10 -1
  58. package/dist/css/main.css +273 -17
  59. package/dist/css/main.css.map +1 -1
  60. package/dist/dynamic/DeepThinking/package.json +1 -0
  61. package/dist/dynamic/FilePreview/package.json +1 -0
  62. package/dist/dynamic/ToolResponse/package.json +1 -0
  63. package/dist/esm/Chatbot/Chatbot.js +1 -7
  64. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
  65. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
  66. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +22 -2
  67. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +17 -11
  68. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +41 -3
  69. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
  70. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
  71. package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
  72. package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.js +22 -0
  73. package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
  74. package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +20 -0
  75. package/dist/esm/ChatbotHeader/index.d.ts +1 -0
  76. package/dist/esm/ChatbotHeader/index.js +1 -0
  77. package/dist/esm/DeepThinking/DeepThinking.d.ts +18 -0
  78. package/dist/esm/DeepThinking/DeepThinking.js +14 -0
  79. package/dist/esm/DeepThinking/DeepThinking.test.d.ts +1 -0
  80. package/dist/esm/DeepThinking/DeepThinking.test.js +43 -0
  81. package/dist/esm/DeepThinking/index.d.ts +2 -0
  82. package/dist/esm/DeepThinking/index.js +2 -0
  83. package/dist/esm/FilePreview/FilePreview.d.ts +26 -0
  84. package/dist/esm/FilePreview/FilePreview.js +21 -0
  85. package/dist/esm/FilePreview/FilePreview.test.d.ts +1 -0
  86. package/dist/esm/FilePreview/FilePreview.test.js +92 -0
  87. package/dist/esm/FilePreview/index.d.ts +2 -0
  88. package/dist/esm/FilePreview/index.js +2 -0
  89. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +5 -5
  90. package/dist/esm/Message/LinkMessage/LinkMessage.d.ts +2 -1
  91. package/dist/esm/Message/LinkMessage/LinkMessage.js +7 -3
  92. package/dist/esm/Message/ListMessage/ListItemMessage.d.ts +1 -1
  93. package/dist/esm/Message/ListMessage/ListItemMessage.js +16 -1
  94. package/dist/esm/Message/Message.d.ts +15 -0
  95. package/dist/esm/Message/Message.js +129 -32
  96. package/dist/esm/Message/Message.test.js +71 -0
  97. package/dist/esm/Message/SuperscriptMessage/SuperscriptMessage.d.ts +3 -0
  98. package/dist/esm/Message/SuperscriptMessage/SuperscriptMessage.js +3 -0
  99. package/dist/esm/Message/UserFeedback/UserFeedback.d.ts +15 -1
  100. package/dist/esm/Message/UserFeedback/UserFeedback.js +4 -4
  101. package/dist/esm/Message/UserFeedback/UserFeedback.test.js +45 -1
  102. package/dist/esm/MessageBar/MessageBar.js +19 -4
  103. package/dist/esm/MessageBox/JumpButton.d.ts +5 -0
  104. package/dist/esm/MessageBox/JumpButton.js +1 -1
  105. package/dist/esm/MessageBox/JumpButton.test.js +4 -4
  106. package/dist/esm/MessageBox/MessageBox.d.ts +9 -0
  107. package/dist/esm/MessageBox/MessageBox.js +2 -2
  108. package/dist/esm/MessageBox/MessageBox.test.js +2 -2
  109. package/dist/esm/SourcesCard/SourcesCard.d.ts +13 -1
  110. package/dist/esm/SourcesCard/SourcesCard.js +6 -6
  111. package/dist/esm/SourcesCard/SourcesCard.test.js +50 -1
  112. package/dist/esm/ToolResponse/ToolResponse.d.ts +30 -0
  113. package/dist/esm/ToolResponse/ToolResponse.js +14 -0
  114. package/dist/esm/ToolResponse/ToolResponse.test.d.ts +1 -0
  115. package/dist/esm/ToolResponse/ToolResponse.test.js +55 -0
  116. package/dist/esm/ToolResponse/index.d.ts +2 -0
  117. package/dist/esm/ToolResponse/index.js +2 -0
  118. package/dist/esm/index.d.ts +6 -0
  119. package/dist/esm/index.js +6 -0
  120. package/dist/tsconfig.tsbuildinfo +1 -1
  121. package/package.json +7 -6
  122. package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +101 -3
  123. package/patternfly-docs/content/extensions/chatbot/examples/Messages/FilePreview.tsx +33 -0
  124. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDeepThinking.tsx +17 -0
  125. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx +111 -85
  126. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithSources.tsx +70 -0
  127. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolResponse.tsx +135 -0
  128. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +28 -4
  129. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +107 -2
  130. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx +616 -3
  131. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotConversationEditing.tsx +202 -0
  132. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderBasic.tsx +17 -3
  133. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawer.tsx +36 -5
  134. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithPin.tsx +12 -2
  135. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +22 -3
  136. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +1 -1
  137. package/patternfly-docs/patternfly-docs.config.js +1 -1
  138. package/src/Chatbot/Chatbot.scss +9 -2
  139. package/src/Chatbot/Chatbot.tsx +18 -31
  140. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.tsx +5 -1
  141. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +28 -10
  142. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +132 -3
  143. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +80 -33
  144. package/src/ChatbotHeader/ChatbotHeaderMenu.test.tsx +1 -1
  145. package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +2 -2
  146. package/src/ChatbotHeader/ChatbotHeaderNewChatButton.test.tsx +25 -0
  147. package/src/ChatbotHeader/ChatbotHeaderNewChatButton.tsx +64 -0
  148. package/src/ChatbotHeader/index.ts +1 -0
  149. package/src/ChatbotModal/ChatbotModal.scss +1 -1
  150. package/src/DeepThinking/DeepThinking.scss +24 -0
  151. package/src/DeepThinking/DeepThinking.test.tsx +61 -0
  152. package/src/DeepThinking/DeepThinking.tsx +68 -0
  153. package/src/DeepThinking/index.ts +3 -0
  154. package/src/FileDetails/__snapshots__/FileDetails.test.tsx.snap +6 -9
  155. package/src/FileDetailsLabel/__snapshots__/FileDetailsLabel.test.tsx.snap +6 -9
  156. package/src/FilePreview/FilePreview.scss +22 -0
  157. package/src/FilePreview/FilePreview.test.tsx +112 -0
  158. package/src/FilePreview/FilePreview.tsx +58 -0
  159. package/src/FilePreview/index.ts +3 -0
  160. package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +2 -1
  161. package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +6 -5
  162. package/src/Message/LinkMessage/LinkMessage.tsx +6 -2
  163. package/src/Message/ListMessage/ListItemMessage.tsx +5 -1
  164. package/src/Message/ListMessage/ListMessage.scss +17 -0
  165. package/src/Message/Message.scss +44 -0
  166. package/src/Message/Message.test.tsx +90 -0
  167. package/src/Message/Message.tsx +171 -46
  168. package/src/Message/SuperscriptMessage/SuperscriptMessage.scss +8 -0
  169. package/src/Message/SuperscriptMessage/SuperscriptMessage.tsx +13 -0
  170. package/src/Message/TextMessage/TextMessage.scss +46 -5
  171. package/src/Message/UserFeedback/UserFeedback.test.tsx +107 -0
  172. package/src/Message/UserFeedback/UserFeedback.tsx +41 -6
  173. package/src/MessageBar/MessageBar.tsx +23 -3
  174. package/src/MessageBox/JumpButton.test.tsx +4 -4
  175. package/src/MessageBox/JumpButton.tsx +20 -4
  176. package/src/MessageBox/MessageBox.test.tsx +2 -2
  177. package/src/MessageBox/MessageBox.tsx +22 -1
  178. package/src/SourcesCard/SourcesCard.scss +17 -0
  179. package/src/SourcesCard/SourcesCard.test.tsx +93 -0
  180. package/src/SourcesCard/SourcesCard.tsx +116 -80
  181. package/src/ToolResponse/ToolResponse.scss +36 -0
  182. package/src/ToolResponse/ToolResponse.test.tsx +78 -0
  183. package/src/ToolResponse/ToolResponse.tsx +95 -0
  184. package/src/ToolResponse/index.ts +3 -0
  185. package/src/index.ts +9 -0
  186. package/src/main.scss +3 -0
@@ -12,34 +12,40 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import { useRef, Fragment } from 'react';
14
14
  // Import PatternFly components
15
- import { Button, Drawer, DrawerPanelContent, DrawerContent, DrawerPanelBody, DrawerHead, DrawerActions, DrawerCloseButton, DrawerContentBody, SearchInput, Menu, MenuList, MenuGroup, MenuItem, MenuContent, Title, Icon } from '@patternfly/react-core';
16
- import { OutlinedClockIcon, OutlinedCommentAltIcon } from '@patternfly/react-icons';
15
+ import { Button, Drawer, DrawerPanelContent, DrawerContent, DrawerPanelBody, DrawerHead, DrawerActions, DrawerCloseButton, DrawerContentBody, SearchInput, Title, Icon, MenuList, MenuGroup, MenuItem, Menu, MenuContent } from '@patternfly/react-core';
16
+ import { OutlinedClockIcon, OutlinedCommentAltIcon, PenToSquareIcon } from '@patternfly/react-icons';
17
17
  import { ChatbotDisplayMode } from '../Chatbot/Chatbot';
18
18
  import ConversationHistoryDropdown from './ChatbotConversationHistoryDropdown';
19
19
  import LoadingState from './LoadingState';
20
20
  import HistoryEmptyState from './EmptyState';
21
21
  export const ChatbotConversationHistoryNav = (_a) => {
22
- var { onDrawerToggle, isDrawerOpen, setIsDrawerOpen, activeItemId, onSelectActiveItem, conversations, newChatButtonText = 'New chat', drawerContent, onNewChat, newChatButtonProps, searchInputPlaceholder = 'Search previous conversations...', searchInputAriaLabel = 'Filter menu items', handleTextInputChange, displayMode, reverseButtonOrder = false, drawerActionsTestId = 'chatbot-nav-drawer-actions', menuProps, drawerPanelContentProps, drawerContentProps, drawerContentBodyProps, drawerHeadProps, drawerActionsProps, drawerCloseButtonProps, drawerPanelBodyProps, isLoading, loadingState, errorState, emptyState, noResultsState, isCompact, title = 'Chat history' } = _a, props = __rest(_a, ["onDrawerToggle", "isDrawerOpen", "setIsDrawerOpen", "activeItemId", "onSelectActiveItem", "conversations", "newChatButtonText", "drawerContent", "onNewChat", "newChatButtonProps", "searchInputPlaceholder", "searchInputAriaLabel", "handleTextInputChange", "displayMode", "reverseButtonOrder", "drawerActionsTestId", "menuProps", "drawerPanelContentProps", "drawerContentProps", "drawerContentBodyProps", "drawerHeadProps", "drawerActionsProps", "drawerCloseButtonProps", "drawerPanelBodyProps", "isLoading", "loadingState", "errorState", "emptyState", "noResultsState", "isCompact", "title"]);
22
+ var { onDrawerToggle, isDrawerOpen, setIsDrawerOpen, activeItemId, onSelectActiveItem, conversations, menuListProps, newChatButtonText = 'New chat', drawerContent, onNewChat, newChatButtonProps, searchInputPlaceholder = 'Search previous conversations...', searchInputAriaLabel = 'Search previous conversations', searchInputProps, handleTextInputChange, displayMode, reverseButtonOrder = false, drawerActionsTestId = 'chatbot-nav-drawer-actions', drawerPanelContentProps, drawerContentProps, drawerContentBodyProps, drawerHeadProps, drawerActionsProps, drawerCloseButtonProps, drawerPanelBodyProps, isLoading, loadingState, errorState, emptyState, noResultsState, isCompact, title = 'Chat history', navTitleProps, navTitleIcon = _jsx(OutlinedClockIcon, {}), searchInputScreenReaderText, menuProps, menuGroupProps, menuContentProps } = _a, props = __rest(_a, ["onDrawerToggle", "isDrawerOpen", "setIsDrawerOpen", "activeItemId", "onSelectActiveItem", "conversations", "menuListProps", "newChatButtonText", "drawerContent", "onNewChat", "newChatButtonProps", "searchInputPlaceholder", "searchInputAriaLabel", "searchInputProps", "handleTextInputChange", "displayMode", "reverseButtonOrder", "drawerActionsTestId", "drawerPanelContentProps", "drawerContentProps", "drawerContentBodyProps", "drawerHeadProps", "drawerActionsProps", "drawerCloseButtonProps", "drawerPanelBodyProps", "isLoading", "loadingState", "errorState", "emptyState", "noResultsState", "isCompact", "title", "navTitleProps", "navTitleIcon", "searchInputScreenReaderText", "menuProps", "menuGroupProps", "menuContentProps"]);
23
23
  const drawerRef = useRef(null);
24
24
  const onExpand = () => {
25
25
  drawerRef.current && drawerRef.current.focus();
26
26
  };
27
+ const isConversation = (item) => item && typeof item === 'object' && 'id' in item && 'text' in item;
27
28
  const getNavItem = (conversation) => {
28
29
  var _a;
29
30
  return (_jsx(MenuItem, Object.assign({ className: `pf-chatbot__menu-item ${activeItemId && activeItemId === conversation.id ? 'pf-chatbot__menu-item--active' : ''}`, itemId: conversation.id }, (conversation.noIcon ? {} : { icon: (_a = conversation.icon) !== null && _a !== void 0 ? _a : _jsx(OutlinedCommentAltIcon, {}) }), (conversation.menuItems
30
31
  ? {
31
32
  actions: (_jsx(ConversationHistoryDropdown, { menuClassName: conversation.menuClassName, onSelect: conversation.onSelect, menuItems: conversation.menuItems, label: conversation.label }))
32
33
  }
33
- : {}), conversation.additionalProps, { children: conversation.text }), conversation.id));
34
+ : {}), conversation.additionalProps, { children: conversation.text })));
34
35
  };
35
- const buildMenu = () => {
36
+ const buildConversations = () => {
36
37
  if (Array.isArray(conversations)) {
37
- // Render for array of MenuItemObject
38
- return (_jsx(MenuList, { children: conversations.map((conversation) => (_jsx(Fragment, { children: getNavItem(conversation) }, conversation.id))) }));
38
+ return (_jsx(MenuList, Object.assign({}, menuListProps, { children: conversations.map((conversation) => {
39
+ if (isConversation(conversation)) {
40
+ return _jsx(Fragment, { children: getNavItem(conversation) }, conversation.id);
41
+ }
42
+ else {
43
+ return conversation;
44
+ }
45
+ }) })));
39
46
  }
40
47
  else {
41
- // Render for object with NavItemObject arrays as values
42
- return (_jsx(_Fragment, { children: Object.keys(conversations).map((navGroup) => (_jsx(MenuGroup, { className: "pf-chatbot__menu-item-header", label: navGroup, children: _jsx(MenuList, { children: conversations[navGroup].map((conversation) => (_jsx(Fragment, { children: getNavItem(conversation) }, conversation.id))) }) }, navGroup))) }));
48
+ return (_jsx(_Fragment, { children: Object.keys(conversations).map((navGroup) => (_jsx(MenuGroup, Object.assign({ className: "pf-chatbot__menu-item-header", label: navGroup, labelHeadingLevel: "h3" }, menuGroupProps === null || menuGroupProps === void 0 ? void 0 : menuGroupProps[navGroup], { children: _jsx(MenuList, Object.assign({}, menuListProps === null || menuListProps === void 0 ? void 0 : menuListProps[navGroup], { children: conversations[navGroup].map((conversation) => (_jsx(Fragment, { children: getNavItem(conversation) }, conversation.id))) })) }), navGroup))) }));
43
49
  }
44
50
  };
45
51
  // Menu Content
@@ -55,11 +61,11 @@ export const ChatbotConversationHistoryNav = (_a) => {
55
61
  if (noResultsState) {
56
62
  return _jsx(HistoryEmptyState, Object.assign({}, noResultsState));
57
63
  }
58
- return (_jsx(Menu, Object.assign({ isPlain: true, onSelect: onSelectActiveItem, activeItemId: activeItemId }, menuProps, { children: _jsx(MenuContent, { children: buildMenu() }) })));
64
+ return (_jsx(Menu, Object.assign({ isPlain: true, onSelect: onSelectActiveItem, activeItemId: activeItemId }, menuProps, { children: _jsx(MenuContent, Object.assign({}, menuContentProps, { children: buildConversations() })) })));
59
65
  };
60
66
  const renderDrawerContent = () => (_jsx(_Fragment, { children: _jsx(DrawerPanelBody, Object.assign({}, drawerPanelBodyProps, { children: renderMenuContent() })) }));
61
67
  const renderPanelContent = () => {
62
- const drawer = (_jsxs(_Fragment, { children: [_jsx(DrawerHead, Object.assign({}, drawerHeadProps, { children: _jsxs(DrawerActions, Object.assign({ "data-testid": drawerActionsTestId, className: reverseButtonOrder ? 'pf-v6-c-drawer__actions--reversed' : '' }, drawerActionsProps, { children: [_jsx(DrawerCloseButton, Object.assign({ onClick: onDrawerToggle }, drawerCloseButtonProps)), onNewChat && (_jsx(Button, Object.assign({ size: isCompact ? 'sm' : undefined, onClick: onNewChat }, newChatButtonProps, { children: newChatButtonText })))] })) })), _jsxs("div", { className: "pf-chatbot__title-container", children: [_jsxs(Title, { headingLevel: "h3", children: [_jsx(Icon, { size: "lg", className: "pf-chatbot__title-icon", children: _jsx(OutlinedClockIcon, {}) }), title] }), !isLoading && handleTextInputChange && (_jsx("div", { className: "pf-chatbot__input", children: _jsx(SearchInput, { "aria-label": searchInputAriaLabel, onChange: (_event, value) => handleTextInputChange(value), placeholder: searchInputPlaceholder }) }))] }), isLoading ? _jsx(LoadingState, Object.assign({}, loadingState)) : renderDrawerContent()] }));
68
+ const drawer = (_jsxs(_Fragment, { children: [_jsx(DrawerHead, Object.assign({}, drawerHeadProps, { children: _jsxs(DrawerActions, Object.assign({ "data-testid": drawerActionsTestId, className: reverseButtonOrder ? 'pf-v6-c-drawer__actions--reversed' : '' }, drawerActionsProps, { children: [_jsx(DrawerCloseButton, Object.assign({ onClick: onDrawerToggle }, drawerCloseButtonProps)), onNewChat && (_jsx(Button, Object.assign({ size: isCompact ? 'sm' : undefined, onClick: onNewChat, icon: _jsx(PenToSquareIcon, {}) }, newChatButtonProps, { children: newChatButtonText })))] })) })), _jsxs("div", { className: "pf-chatbot__heading-container", children: [_jsxs("div", { className: "pf-chatbot__title-container", children: [_jsx(Icon, { size: "lg", className: "pf-chatbot__title-icon", children: navTitleIcon }), _jsx(Title, Object.assign({ className: "pf-chatbot__title", headingLevel: "h2" }, navTitleProps, { children: title }))] }), !isLoading && handleTextInputChange && (_jsxs("div", { className: "pf-chatbot__input", children: [_jsx(SearchInput, Object.assign({ "aria-label": searchInputAriaLabel, onChange: (_event, value) => handleTextInputChange(value), placeholder: searchInputPlaceholder }, searchInputProps)), searchInputScreenReaderText && (_jsx("div", { className: "pf-chatbot__filter-announcement", children: searchInputScreenReaderText }))] }))] }), isLoading ? _jsx(LoadingState, Object.assign({}, loadingState)) : renderDrawerContent()] }));
63
69
  return (_jsx(DrawerPanelContent, Object.assign({ "aria-live": "polite", focusTrap: { enabled: true }, defaultSize: "384px" }, drawerPanelContentProps, { children: drawer })));
64
70
  };
65
71
  // An onKeyDown property must be passed to the Drawer component to handle closing
@@ -13,7 +13,7 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
13
13
  import { ChatbotDisplayMode } from '../Chatbot/Chatbot';
14
14
  import ChatbotConversationHistoryNav from './ChatbotConversationHistoryNav';
15
15
  import { EmptyStateStatus, Spinner } from '@patternfly/react-core';
16
- import { OutlinedCommentsIcon, SearchIcon } from '@patternfly/react-icons';
16
+ import { BellIcon, OutlinedCommentsIcon, SearchIcon } from '@patternfly/react-icons';
17
17
  const ERROR = {
18
18
  bodyText: (_jsxs(_Fragment, { children: ["To try again, check your connection and reload this page. If the issue persists,", ' ', _jsx("a", { href: "", children: "contact the support team" }), "."] })),
19
19
  buttonText: 'Reload',
@@ -147,7 +147,7 @@ describe('ChatbotConversationHistoryNav', () => {
147
147
  })).toBeTruthy();
148
148
  expect(screen.getByRole('button', { name: /Close drawer panel/i })).toBeTruthy();
149
149
  expect(screen.getByRole('button', { name: /Loading... Reload/i })).toBeTruthy();
150
- expect(screen.getByRole('textbox', { name: /Filter menu items/i })).toBeTruthy();
150
+ expect(screen.getByRole('textbox', { name: /Search previous conversations/i })).toBeTruthy();
151
151
  expect(screen.getByRole('heading', { name: /Could not load chat history/i })).toBeTruthy();
152
152
  });
153
153
  it('should accept errorState without button', () => {
@@ -157,7 +157,7 @@ describe('ChatbotConversationHistoryNav', () => {
157
157
  })).toBeTruthy();
158
158
  expect(screen.getByRole('button', { name: /Close drawer panel/i })).toBeTruthy();
159
159
  expect(screen.queryByRole('button', { name: /Loading... Reload/i })).toBeFalsy();
160
- expect(screen.getByRole('textbox', { name: /Filter menu items/i })).toBeTruthy();
160
+ expect(screen.getByRole('textbox', { name: /Search previous conversations/i })).toBeTruthy();
161
161
  expect(screen.getByRole('heading', { name: /Could not load chat history/i })).toBeTruthy();
162
162
  });
163
163
  it('should show loading state over error state if both are supplied', () => {
@@ -193,4 +193,42 @@ describe('ChatbotConversationHistoryNav', () => {
193
193
  const iconElement = container.querySelector('.pf-chatbot__title-icon');
194
194
  expect(iconElement).toBeInTheDocument();
195
195
  });
196
+ it('Passes menuProps to Menu', () => {
197
+ var _a;
198
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), conversations: initialConversations, menuProps: { className: 'test' } }));
199
+ expect((_a = screen.getByRole('menu').parentElement) === null || _a === void 0 ? void 0 : _a.parentElement).toHaveClass('test');
200
+ });
201
+ it('Passes menuContentProps to MenuContent', () => {
202
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), conversations: initialConversations, menuContentProps: { className: 'test' } }));
203
+ expect(screen.getByRole('menu').parentElement).toHaveClass('test');
204
+ });
205
+ it('Passes menuListProps to MenuList when conversations is an array', () => {
206
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), conversations: initialConversations, menuListProps: { className: 'test' } }));
207
+ expect(screen.getByRole('menu')).toHaveClass('test');
208
+ });
209
+ it('Passes menuListProps to MenuList when conversations is an object', () => {
210
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), conversations: { Today: initialConversations }, menuListProps: { Today: { className: 'test' } } }));
211
+ expect(screen.getByRole('menu')).toHaveClass('test');
212
+ });
213
+ it('Passes menuGroupProps to MenuGroup when conversations is an object', () => {
214
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), conversations: { Today: initialConversations }, menuGroupProps: { Today: { className: 'test' } } }));
215
+ expect(screen.getByRole('menu').parentElement).toHaveClass('test');
216
+ });
217
+ it('Passes additionalProps to MenuItem', () => {
218
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), conversations: [{ id: '1', text: 'ChatBot documentation', additionalProps: { className: 'test' } }] }));
219
+ expect(screen.getByRole('menuitem')).toHaveClass('test');
220
+ });
221
+ it('should be able to spread search input props when searchInputProps is passed', () => {
222
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), conversations: initialConversations, handleTextInputChange: jest.fn(), searchInputProps: { value: 'I am a sample search' } }));
223
+ expect(screen.getByRole('dialog', { name: /Chat history I am a sample search/i })).toBeInTheDocument();
224
+ });
225
+ it('overrides nav title heading level when navTitleProps.headingLevel is passed', () => {
226
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), conversations: { Today: initialConversations }, navTitleProps: { headingLevel: 'h1' } }));
227
+ expect(screen.queryByRole('heading', { name: /Chat history/i, level: 2 })).not.toBeInTheDocument();
228
+ expect(screen.getByRole('heading', { name: /Chat history/i, level: 1 })).toBeInTheDocument();
229
+ });
230
+ it('overrides nav title icon when navTitleIcon is passed in', () => {
231
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), conversations: initialConversations, navTitleIcon: _jsx(BellIcon, { "data-testid": "bell" }) }));
232
+ expect(screen.getByTestId('bell')).toBeInTheDocument();
233
+ });
196
234
  });
@@ -14,7 +14,7 @@ import { forwardRef } from 'react';
14
14
  import { Button, Icon, Tooltip } from '@patternfly/react-core';
15
15
  import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';
16
16
  const ChatbotHeaderMenuBase = (_a) => {
17
- var { className, onMenuToggle, tooltipProps, menuAriaLabel = 'Toggle menu', innerRef, tooltipContent = 'Menu', isCompact } = _a, props = __rest(_a, ["className", "onMenuToggle", "tooltipProps", "menuAriaLabel", "innerRef", "tooltipContent", "isCompact"]);
17
+ 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"]);
18
18
  return (_jsx("div", { className: `pf-chatbot__menu ${className}`, children: _jsx(Tooltip, Object.assign({ content: tooltipContent, position: "bottom",
19
19
  // prevents VO announcements of both aria label and tooltip
20
20
  aria: "none" }, tooltipProps, { children: _jsx(Button, Object.assign({ className: `pf-chatbot__button--toggle-menu ${isCompact ? 'pf-m-compact' : ''}`, variant: "plain", onClick: onMenuToggle, "aria-label": menuAriaLabel, ref: innerRef, icon: _jsx(Icon, { size: isCompact ? 'lg' : 'xl', isInline: true, children: _jsx(BarsIcon, {}) }), size: isCompact ? 'sm' : undefined }, props)) })) }));
@@ -10,7 +10,7 @@ describe('ChatbotHeaderMenu', () => {
10
10
  it('should call onMenuToggle when ChatbotHeaderMenu button is clicked', () => {
11
11
  const onMenuToggle = jest.fn();
12
12
  render(_jsx(ChatbotHeaderMenu, { className: "custom-header-menu", onMenuToggle: onMenuToggle }));
13
- fireEvent.click(screen.getByRole('button', { name: 'Toggle menu' }));
13
+ fireEvent.click(screen.getByRole('button', { name: 'Chat history menu' }));
14
14
  expect(onMenuToggle).toHaveBeenCalled();
15
15
  });
16
16
  it('should handle isCompact', () => {
@@ -0,0 +1,18 @@
1
+ import { ButtonProps, TooltipProps } from '@patternfly/react-core';
2
+ export interface ChatbotHeaderNewChatButtonProps extends ButtonProps {
3
+ /** Callback function for when button is clicked */
4
+ onClick: () => void;
5
+ /** Custom classname for the header component */
6
+ className?: string;
7
+ /** Props spread to the PF Tooltip component wrapping the display mode dropdown */
8
+ tooltipProps?: TooltipProps;
9
+ /** Aria label for menu */
10
+ menuAriaLabel?: string;
11
+ /** Ref applied to menu */
12
+ innerRef?: React.Ref<HTMLButtonElement>;
13
+ /** Content used in tooltip */
14
+ tooltipContent?: string;
15
+ /** Sets button to compact styling. */
16
+ isCompact?: boolean;
17
+ }
18
+ export declare const ChatbotHeaderNewChatButton: import("react").ForwardRefExoticComponent<ChatbotHeaderNewChatButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,22 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { forwardRef } from 'react';
14
+ import { Button, Icon, Tooltip } from '@patternfly/react-core';
15
+ import { PenToSquareIcon } from '@patternfly/react-icons/dist/esm/icons/pen-to-square-icon';
16
+ const ChatbotHeaderNewChatButtonBase = (_a) => {
17
+ var { className, onClick, tooltipProps, menuAriaLabel = 'New chat', innerRef, tooltipContent = 'New chat', isCompact } = _a, props = __rest(_a, ["className", "onClick", "tooltipProps", "menuAriaLabel", "innerRef", "tooltipContent", "isCompact"]);
18
+ return (_jsx("div", { className: `pf-chatbot__menu${className ? ` ${className}` : ''}`, children: _jsx(Tooltip, Object.assign({ content: tooltipContent, position: "bottom",
19
+ // prevents VO announcements of both aria label and tooltip
20
+ aria: "none" }, tooltipProps, { children: _jsx(Button, Object.assign({ className: `pf-chatbot__button--toggle-menu ${isCompact ? 'pf-m-compact' : ''}`, variant: "plain", onClick: onClick, "aria-label": menuAriaLabel, ref: innerRef, icon: _jsx(Icon, { size: isCompact ? 'lg' : 'xl', isInline: true, children: _jsx(PenToSquareIcon, {}) }), size: isCompact ? 'sm' : undefined }, props)) })) }));
21
+ };
22
+ export const ChatbotHeaderNewChatButton = forwardRef((props, ref) => (_jsx(ChatbotHeaderNewChatButtonBase, Object.assign({ innerRef: ref }, props))));
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { fireEvent, render, screen } from '@testing-library/react';
3
+ import { ChatbotHeaderNewChatButton } from './ChatbotHeaderNewChatButton';
4
+ import '@testing-library/jest-dom';
5
+ describe('ChatbotHeaderNewChatButton', () => {
6
+ it('should render ChatbotHeaderNewChatButton', () => {
7
+ const { container } = render(_jsx(ChatbotHeaderNewChatButton, { className: "custom-header-new-chat-button", onClick: jest.fn() }));
8
+ expect(container.querySelector('.custom-header-new-chat-button')).toBeTruthy();
9
+ });
10
+ it('should call onClick handler when new chat button is pressed', () => {
11
+ const onClick = jest.fn();
12
+ render(_jsx(ChatbotHeaderNewChatButton, { className: "custom-header-new-chat-button", onClick: onClick }));
13
+ fireEvent.click(screen.getByRole('button', { name: 'New chat' }));
14
+ expect(onClick).toHaveBeenCalled();
15
+ });
16
+ it('should render button with isCompact', () => {
17
+ render(_jsx(ChatbotHeaderNewChatButton, { "data-testid": "new-chat-button", onClick: jest.fn(), isCompact: true }));
18
+ expect(screen.getByTestId('new-chat-button')).toHaveClass('pf-m-compact');
19
+ });
20
+ });
@@ -7,3 +7,4 @@ export * from './ChatbotHeaderTitle';
7
7
  export * from './ChatbotHeaderOptionsDropdown';
8
8
  export * from './ChatbotHeaderSelectorDropdown';
9
9
  export * from './ChatbotHeaderCloseButton';
10
+ export * from './ChatbotHeaderNewChatButton';
@@ -7,3 +7,4 @@ export * from './ChatbotHeaderTitle';
7
7
  export * from './ChatbotHeaderOptionsDropdown';
8
8
  export * from './ChatbotHeaderSelectorDropdown';
9
9
  export * from './ChatbotHeaderCloseButton';
10
+ export * from './ChatbotHeaderNewChatButton';
@@ -0,0 +1,18 @@
1
+ import { CardBodyProps, CardProps, ExpandableSectionProps } from '@patternfly/react-core';
2
+ import { type FunctionComponent } from 'react';
3
+ export interface DeepThinkingProps {
4
+ /** Toggle content shown for expandable section */
5
+ toggleContent: React.ReactNode;
6
+ /** Additional props passed to expandable section */
7
+ expandableSectionProps?: Omit<ExpandableSectionProps, 'ref'>;
8
+ /** Subheading rendered inside expandable section */
9
+ subheading?: string;
10
+ /** Body text rendered inside expandable section */
11
+ body?: React.ReactNode | string;
12
+ /** Additional props passed to main card */
13
+ cardProps?: CardProps;
14
+ /** Additional props passed to main card body */
15
+ cardBodyProps?: CardBodyProps;
16
+ }
17
+ export declare const DeepThinking: FunctionComponent<DeepThinkingProps>;
18
+ export default DeepThinking;
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // ============================================================================
3
+ // Deep Thinking
4
+ // ============================================================================
5
+ import { Card, CardBody, ExpandableSection } from '@patternfly/react-core';
6
+ import { useState } from 'react';
7
+ export const DeepThinking = ({ body, cardProps, expandableSectionProps, subheading, toggleContent, cardBodyProps }) => {
8
+ const [isExpanded, setIsExpanded] = useState(true);
9
+ const onToggle = (_event, isExpanded) => {
10
+ setIsExpanded(isExpanded);
11
+ };
12
+ return (_jsx(Card, Object.assign({ isCompact: true, className: "pf-chatbot__deep-thinking" }, cardProps, { children: _jsx(CardBody, Object.assign({}, cardBodyProps, { children: _jsx(ExpandableSection, Object.assign({ toggleContent: toggleContent, onToggle: onToggle, isExpanded: isExpanded, isIndented: true, className: "pf-chatbot__deep-thinking-expandable-section" }, expandableSectionProps, { children: _jsxs("div", { className: "pf-chatbot__deep-thinking-section", children: [subheading && (_jsx("div", { className: "pf-chatbot__deep-thinking-subheading", children: _jsx("span", { children: subheading }) })), body && _jsx("div", { className: "pf-chatbot__deep-thinking-body", children: body })] }) })) })) })));
13
+ };
14
+ export default DeepThinking;
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+ import DeepThinking from './DeepThinking';
5
+ describe('DeepThinking', () => {
6
+ const defaultProps = {
7
+ toggleContent: 'Show thinking'
8
+ };
9
+ it('should render with required props only', () => {
10
+ render(_jsx(DeepThinking, Object.assign({}, defaultProps)));
11
+ expect(screen.getByText('Show thinking')).toBeTruthy();
12
+ });
13
+ it('should render subheading when provided', () => {
14
+ const subheading = 'Thought for 3 seconds';
15
+ render(_jsx(DeepThinking, Object.assign({}, defaultProps, { subheading: subheading })));
16
+ expect(screen.getByText(subheading)).toBeTruthy();
17
+ });
18
+ it('should render body content when provided', () => {
19
+ const body = "Here's why I think that";
20
+ render(_jsx(DeepThinking, Object.assign({}, defaultProps, { body: body })));
21
+ expect(screen.getByText(body)).toBeTruthy();
22
+ });
23
+ it('should render with complex content including React elements', () => {
24
+ const body = (_jsxs("div", { children: [_jsx("p", { children: "Complex body content" }), _jsxs("ul", { children: [_jsx("li", { children: "Item 1" }), _jsx("li", { children: "Item 2" })] })] }));
25
+ render(_jsx(DeepThinking, Object.assign({}, defaultProps, { body: body })));
26
+ expect(screen.getByText('Complex body content')).toBeTruthy();
27
+ expect(screen.getByText('Item 1')).toBeTruthy();
28
+ expect(screen.getByText('Item 2')).toBeTruthy();
29
+ });
30
+ it('should apply custom className from cardProps', () => {
31
+ const { container } = render(_jsx(DeepThinking, Object.assign({}, defaultProps, { cardProps: { className: 'custom-tool-response-class' } })));
32
+ expect(container.querySelector('.custom-tool-response-class')).toBeTruthy();
33
+ });
34
+ it('should pass through expandableSectionProps', () => {
35
+ render(_jsx(DeepThinking, Object.assign({}, defaultProps, { expandableSectionProps: { className: 'custom-expandable-class' } })));
36
+ expect(document.querySelector('.custom-expandable-class')).toBeTruthy();
37
+ });
38
+ it('should not render subheading span when subheading is not provided', () => {
39
+ const { container } = render(_jsx(DeepThinking, Object.assign({}, defaultProps)));
40
+ const subheadingContainer = container.querySelector('.pf-chatbot__tool-response-subheading');
41
+ expect(subheadingContainer).toBeFalsy();
42
+ });
43
+ });
@@ -0,0 +1,2 @@
1
+ export { default } from './DeepThinking';
2
+ export * from './DeepThinking';
@@ -0,0 +1,2 @@
1
+ export { default } from './DeepThinking';
2
+ export * from './DeepThinking';
@@ -0,0 +1,26 @@
1
+ import { ModalBodyProps, ModalHeaderProps } from '@patternfly/react-core';
2
+ import type { FunctionComponent } from 'react';
3
+ import { ChatbotDisplayMode } from '../Chatbot';
4
+ import { ChatbotModalProps } from '../ChatbotModal';
5
+ export interface FilePreviewProps extends ChatbotModalProps {
6
+ /** Class applied to modal */
7
+ className?: string;
8
+ /** Function that handles modal toggle */
9
+ handleModalToggle: (event: React.MouseEvent | MouseEvent | KeyboardEvent) => void;
10
+ /** Whether modal is open */
11
+ isModalOpen: boolean;
12
+ /** Title of modal */
13
+ title?: string;
14
+ /** Display mode for the Chatbot parent; this influences the styles applied */
15
+ displayMode?: ChatbotDisplayMode;
16
+ /** File name */
17
+ fileName: string;
18
+ /** Sets modal to compact styling. */
19
+ isCompact?: boolean;
20
+ /** Additional props passed to modal header */
21
+ modalHeaderProps?: ModalHeaderProps;
22
+ /** Additional props passed to modal body */
23
+ modalBodyProps?: ModalBodyProps;
24
+ }
25
+ declare const FilePreview: FunctionComponent<FilePreviewProps>;
26
+ export default FilePreview;
@@ -0,0 +1,21 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { ModalBody, ModalHeader } from '@patternfly/react-core';
14
+ import { ChatbotDisplayMode } from '../Chatbot';
15
+ import ChatbotModal from '../ChatbotModal';
16
+ import { FileIcon } from '@patternfly/react-icons';
17
+ const FilePreview = (_a) => {
18
+ var { isModalOpen, displayMode = ChatbotDisplayMode.default, children, fileName, isCompact, className, handleModalToggle, title = 'File preview', modalHeaderProps, modalBodyProps } = _a, props = __rest(_a, ["isModalOpen", "displayMode", "children", "fileName", "isCompact", "className", "handleModalToggle", "title", "modalHeaderProps", "modalBodyProps"]);
19
+ return (_jsxs(ChatbotModal, Object.assign({ isOpen: isModalOpen, className: `pf-chatbot__file-preview-modal pf-chatbot__file-preview-modal--${displayMode} ${isCompact ? 'pf-m-compact' : ''} ${className ? className : ''}`, displayMode: displayMode, onClose: handleModalToggle, isCompact: isCompact }, props, { children: [_jsx(ModalHeader, Object.assign({ title: title }, modalHeaderProps)), _jsxs(ModalBody, Object.assign({ className: "pf-chatbot__file-preview-body" }, modalBodyProps, { children: [_jsx(FileIcon, { className: "pf-chatbot__file-preview-icon" }), _jsx("h2", { className: "pf-chatbot__file-preview-name", children: fileName }), children && _jsx("div", { className: "pf-chatbot__file-preview-body", children: children })] }))] })));
20
+ };
21
+ export default FilePreview;
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom';
@@ -0,0 +1,92 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
4
+ import FilePreview from './FilePreview';
5
+ import { ChatbotDisplayMode } from '../Chatbot';
6
+ import { Button } from '@patternfly/react-core';
7
+ describe('FilePreview', () => {
8
+ const defaultProps = {
9
+ isModalOpen: true,
10
+ handleModalToggle: jest.fn(),
11
+ fileName: 'test-file.txt',
12
+ children: 'File content preview'
13
+ };
14
+ beforeEach(() => {
15
+ jest.clearAllMocks();
16
+ });
17
+ it('should render with basic props', () => {
18
+ render(_jsx(FilePreview, Object.assign({}, defaultProps)));
19
+ expect(screen.getByText('File preview')).toBeInTheDocument();
20
+ expect(screen.getByText('test-file.txt')).toBeInTheDocument();
21
+ });
22
+ it('should render with custom title', () => {
23
+ const customTitle = 'Custom file preview title';
24
+ render(_jsx(FilePreview, Object.assign({}, defaultProps, { title: customTitle })));
25
+ expect(screen.getByRole('heading', { name: customTitle })).toBeTruthy();
26
+ });
27
+ it('should handle modal toggle when closed', () => {
28
+ const mockToggle = jest.fn();
29
+ render(_jsx(FilePreview, Object.assign({}, defaultProps, { isModalOpen: false, handleModalToggle: mockToggle })));
30
+ expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
31
+ });
32
+ it('should apply default display mode class', () => {
33
+ render(_jsx(FilePreview, Object.assign({}, defaultProps)));
34
+ const modal = screen.getByRole('dialog');
35
+ expect(modal).toHaveClass('pf-chatbot__file-preview-modal--default');
36
+ });
37
+ it('should apply custom display mode class', () => {
38
+ render(_jsx(FilePreview, Object.assign({}, defaultProps, { displayMode: ChatbotDisplayMode.fullscreen })));
39
+ const modal = screen.getByRole('dialog');
40
+ expect(modal).toHaveClass('pf-chatbot__file-preview-modal--fullscreen');
41
+ });
42
+ it('should apply compact styling when isCompact is true', () => {
43
+ render(_jsx(FilePreview, Object.assign({}, defaultProps, { isCompact: true })));
44
+ const modal = screen.getByRole('dialog');
45
+ expect(modal).toHaveClass('pf-m-compact');
46
+ });
47
+ it('should not apply compact styling when isCompact is false', () => {
48
+ render(_jsx(FilePreview, Object.assign({}, defaultProps, { isCompact: false })));
49
+ const modal = screen.getByRole('dialog');
50
+ expect(modal).not.toHaveClass('pf-m-compact');
51
+ });
52
+ it('should apply custom className', () => {
53
+ const customClass = 'custom-file-preview';
54
+ render(_jsx(FilePreview, Object.assign({}, defaultProps, { className: customClass })));
55
+ const modal = screen.getByRole('dialog');
56
+ expect(modal).toHaveClass(customClass);
57
+ });
58
+ it('should pass through additional props to ChatbotModal', () => {
59
+ render(_jsx(FilePreview, Object.assign({}, defaultProps, { "data-testid": "file-preview-modal" })));
60
+ const modal = screen.getByTestId('file-preview-modal');
61
+ expect(modal).toBeInTheDocument();
62
+ });
63
+ it('should pass modalHeaderProps to ModalHeader', () => {
64
+ const modalHeaderProps = {
65
+ 'data-testid': 'custom-header'
66
+ };
67
+ render(_jsx(FilePreview, Object.assign({}, defaultProps, { modalHeaderProps: modalHeaderProps })));
68
+ const header = screen.getByTestId('custom-header');
69
+ expect(header).toBeInTheDocument();
70
+ });
71
+ it('should pass modalBodyProps to ModalBody', () => {
72
+ const modalBodyProps = {
73
+ 'data-testid': 'custom-body'
74
+ };
75
+ render(_jsx(FilePreview, Object.assign({}, defaultProps, { modalBodyProps: modalBodyProps })));
76
+ const body = screen.getByTestId('custom-body');
77
+ expect(body).toBeInTheDocument();
78
+ });
79
+ it('should pass ouiaId to ChatbotModal', () => {
80
+ const ouiaId = 'file-preview-ouia-id';
81
+ render(_jsx(FilePreview, Object.assign({}, defaultProps, { ouiaId: ouiaId })));
82
+ const modal = screen.getByRole('dialog');
83
+ expect(modal).toHaveAttribute('data-ouia-component-id', ouiaId);
84
+ });
85
+ it('should handle complex children', () => {
86
+ const complexChildren = (_jsxs("div", { children: [_jsx("h3", { children: "File details" }), _jsx("p", { children: "Size: 1.2 MB" }), _jsx(Button, { children: "Download" })] }));
87
+ render(_jsx(FilePreview, Object.assign({}, defaultProps, { children: complexChildren })));
88
+ expect(screen.getByRole('heading', { name: /File details/i })).toBeTruthy();
89
+ expect(screen.getByText('Size: 1.2 MB')).toBeTruthy();
90
+ expect(screen.getByRole('button', { name: /Download/i })).toBeTruthy();
91
+ });
92
+ });
@@ -0,0 +1,2 @@
1
+ export { default } from './FilePreview';
2
+ export * from './FilePreview';
@@ -0,0 +1,2 @@
1
+ export { default } from './FilePreview';
2
+ export * from './FilePreview';
@@ -13,9 +13,9 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
13
13
  // ============================================================================
14
14
  // Chatbot Main - Message - Content - Code Block
15
15
  // ============================================================================
16
- import { useState, useRef, useId, useCallback, useEffect } from 'react';
16
+ import { useState, useRef, useCallback, useEffect } from 'react';
17
17
  // Import PatternFly components
18
- import { CodeBlock, CodeBlockAction, CodeBlockCode, Button, Tooltip, ExpandableSection, ExpandableSectionToggle, ExpandableSectionVariant } from '@patternfly/react-core';
18
+ import { CodeBlock, CodeBlockAction, CodeBlockCode, Button, Tooltip, ExpandableSection, ExpandableSectionToggle, ExpandableSectionVariant, getUniqueId } from '@patternfly/react-core';
19
19
  import { CheckIcon } from '@patternfly/react-icons/dist/esm/icons/check-icon';
20
20
  import { CopyIcon } from '@patternfly/react-icons/dist/esm/icons/copy-icon';
21
21
  const DEFAULT_EXPANDED_TEXT = 'Show less';
@@ -26,9 +26,9 @@ const CodeBlockMessage = (_a) => {
26
26
  const [copied, setCopied] = useState(false);
27
27
  const [isExpanded, setIsExpanded] = useState(false);
28
28
  const buttonRef = useRef();
29
- const tooltipID = useId();
30
- const toggleId = useId();
31
- const contentId = useId();
29
+ const tooltipID = getUniqueId();
30
+ const toggleId = getUniqueId();
31
+ const contentId = getUniqueId();
32
32
  const codeBlockRef = useRef(null);
33
33
  const language = (_b = /language-(\w+)/.exec(className || '')) === null || _b === void 0 ? void 0 : _b[1];
34
34
  // Get custom toggle text from data attributes if available - for use with rehype plugins
@@ -1,3 +1,4 @@
1
1
  import { ButtonProps } from '@patternfly/react-core';
2
- declare const LinkMessage: ({ children, target, href, ...props }: ButtonProps) => import("react/jsx-runtime").JSX.Element;
2
+ import { ExtraProps } from 'react-markdown';
3
+ declare const LinkMessage: ({ children, target, href, id, ...props }: ButtonProps & ExtraProps) => import("react/jsx-runtime").JSX.Element;
3
4
  export default LinkMessage;
@@ -16,10 +16,14 @@ import { jsx as _jsx } from "react/jsx-runtime";
16
16
  import { Button } from '@patternfly/react-core';
17
17
  import { ExternalLinkSquareAltIcon } from '@patternfly/react-icons';
18
18
  const LinkMessage = (_a) => {
19
- var { children, target, href } = _a, props = __rest(_a, ["children", "target", "href"]);
19
+ var { children, target, href, id } = _a, props = __rest(_a, ["children", "target", "href", "id"]);
20
20
  if (target === '_blank') {
21
- return (_jsx(Button, Object.assign({ component: "a", variant: "link", href: href, icon: _jsx(ExternalLinkSquareAltIcon, {}), iconPosition: "end", isInline: true, target: target }, props, { children: children })));
21
+ return (_jsx(Button, Object.assign({ component: "a", variant: "link", href: href, icon: _jsx(ExternalLinkSquareAltIcon, {}), iconPosition: "end", isInline: true, target: target,
22
+ // need to explicitly call this out or id doesn't seem to get passed - required for footnotes
23
+ id: id }, props, { children: children })));
22
24
  }
23
- return (_jsx(Button, Object.assign({ isInline: true, component: "a", href: href, variant: "link" }, props, { children: children })));
25
+ return (
26
+ // need to explicitly call this out or id doesn't seem to get passed - required for footnotes
27
+ _jsx(Button, Object.assign({ isInline: true, component: "a", href: href, variant: "link", id: id }, props, { children: children })));
24
28
  };
25
29
  export default LinkMessage;
@@ -1,3 +1,3 @@
1
1
  import { ExtraProps } from 'react-markdown';
2
- declare const ListItemMessage: ({ children }: JSX.IntrinsicElements["li"] & ExtraProps) => import("react/jsx-runtime").JSX.Element;
2
+ declare const ListItemMessage: ({ children, ...props }: JSX.IntrinsicElements["li"] & ExtraProps) => import("react/jsx-runtime").JSX.Element;
3
3
  export default ListItemMessage;
@@ -1,4 +1,19 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
1
12
  import { jsx as _jsx } from "react/jsx-runtime";
2
13
  import { ListItem } from '@patternfly/react-core';
3
- const ListItemMessage = ({ children }) => _jsx(ListItem, { children: children });
14
+ const ListItemMessage = (_a) => {
15
+ var _b;
16
+ var { children } = _a, props = __rest(_a, ["children"]);
17
+ return (_jsx(ListItem, Object.assign({}, props, { tabIndex: ((_b = props === null || props === void 0 ? void 0 : props.id) === null || _b === void 0 ? void 0 : _b.includes('fn-')) ? -1 : props === null || props === void 0 ? void 0 : props.tabIndex, children: children })));
18
+ };
4
19
  export default ListItemMessage;