@patternfly/chatbot 6.4.0-prerelease.17 → 6.4.0-prerelease.19

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 (56) hide show
  1. package/dist/cjs/DeepThinking/DeepThinking.d.ts +18 -0
  2. package/dist/cjs/DeepThinking/DeepThinking.js +18 -0
  3. package/dist/cjs/DeepThinking/DeepThinking.test.d.ts +1 -0
  4. package/dist/cjs/DeepThinking/DeepThinking.test.js +48 -0
  5. package/dist/cjs/DeepThinking/index.d.ts +2 -0
  6. package/dist/cjs/DeepThinking/index.js +23 -0
  7. package/dist/cjs/FilePreview/FilePreview.d.ts +26 -0
  8. package/dist/cjs/FilePreview/FilePreview.js +26 -0
  9. package/dist/cjs/FilePreview/FilePreview.test.d.ts +1 -0
  10. package/dist/cjs/FilePreview/FilePreview.test.js +97 -0
  11. package/dist/cjs/FilePreview/index.d.ts +2 -0
  12. package/dist/cjs/FilePreview/index.js +23 -0
  13. package/dist/cjs/Message/Message.d.ts +3 -0
  14. package/dist/cjs/Message/Message.js +3 -2
  15. package/dist/cjs/Message/Message.test.js +11 -0
  16. package/dist/cjs/index.d.ts +4 -0
  17. package/dist/cjs/index.js +7 -1
  18. package/dist/css/main.css +49 -0
  19. package/dist/css/main.css.map +1 -1
  20. package/dist/dynamic/DeepThinking/package.json +1 -0
  21. package/dist/dynamic/FilePreview/package.json +1 -0
  22. package/dist/esm/DeepThinking/DeepThinking.d.ts +18 -0
  23. package/dist/esm/DeepThinking/DeepThinking.js +14 -0
  24. package/dist/esm/DeepThinking/DeepThinking.test.d.ts +1 -0
  25. package/dist/esm/DeepThinking/DeepThinking.test.js +43 -0
  26. package/dist/esm/DeepThinking/index.d.ts +2 -0
  27. package/dist/esm/DeepThinking/index.js +2 -0
  28. package/dist/esm/FilePreview/FilePreview.d.ts +26 -0
  29. package/dist/esm/FilePreview/FilePreview.js +21 -0
  30. package/dist/esm/FilePreview/FilePreview.test.d.ts +1 -0
  31. package/dist/esm/FilePreview/FilePreview.test.js +92 -0
  32. package/dist/esm/FilePreview/index.d.ts +2 -0
  33. package/dist/esm/FilePreview/index.js +2 -0
  34. package/dist/esm/Message/Message.d.ts +3 -0
  35. package/dist/esm/Message/Message.js +3 -2
  36. package/dist/esm/Message/Message.test.js +11 -0
  37. package/dist/esm/index.d.ts +4 -0
  38. package/dist/esm/index.js +4 -0
  39. package/dist/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +1 -1
  41. package/patternfly-docs/content/extensions/chatbot/examples/Messages/FilePreview.tsx +33 -0
  42. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDeepThinking.tsx +17 -0
  43. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +19 -0
  44. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +1 -0
  45. package/src/DeepThinking/DeepThinking.scss +24 -0
  46. package/src/DeepThinking/DeepThinking.test.tsx +61 -0
  47. package/src/DeepThinking/DeepThinking.tsx +68 -0
  48. package/src/DeepThinking/index.ts +3 -0
  49. package/src/FilePreview/FilePreview.scss +22 -0
  50. package/src/FilePreview/FilePreview.test.tsx +112 -0
  51. package/src/FilePreview/FilePreview.tsx +58 -0
  52. package/src/FilePreview/index.ts +3 -0
  53. package/src/Message/Message.test.tsx +13 -0
  54. package/src/Message/Message.tsx +5 -0
  55. package/src/index.ts +6 -0
  56. package/src/main.scss +2 -0
@@ -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';
@@ -11,6 +11,7 @@ import { UserFeedbackCompleteProps } from './UserFeedback/UserFeedbackComplete';
11
11
  import { TableProps } from '@patternfly/react-table';
12
12
  import { PluggableList } from 'unified';
13
13
  import { ToolResponseProps } from '../ToolResponse';
14
+ import { DeepThinkingProps } from '../DeepThinking';
14
15
  export interface MessageAttachment {
15
16
  /** Name of file attached to the message */
16
17
  name: string;
@@ -148,6 +149,8 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
148
149
  reactMarkdownProps?: Options;
149
150
  /** Props for tool response card */
150
151
  toolResponse?: ToolResponseProps;
152
+ /** Props for deep thinking card */
153
+ deepThinking?: DeepThinkingProps;
151
154
  }
152
155
  export declare const MessageBase: FunctionComponent<MessageProps>;
153
156
  declare const Message: import("react").ForwardRefExoticComponent<Omit<MessageProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -45,8 +45,9 @@ import ErrorMessage from './ErrorMessage/ErrorMessage';
45
45
  import MessageInput from './MessageInput';
46
46
  import { rehypeMoveImagesOutOfParagraphs } from './Plugins/rehypeMoveImagesOutOfParagraphs';
47
47
  import ToolResponse from '../ToolResponse';
48
+ import DeepThinking from '../DeepThinking';
48
49
  export const MessageBase = (_a) => {
49
- var { role, content, extraContent, name, avatar, timestamp, isLoading, actions, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [], linkProps, error, isEditable, editPlaceholder = 'Edit prompt message...', updateWord = 'Update', cancelWord = 'Cancel', onEditUpdate, onEditCancel, inputRef, editFormProps, isCompact, isMarkdownDisabled, reactMarkdownProps, toolResponse } = _a, props = __rest(_a, ["role", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins", "linkProps", "error", "isEditable", "editPlaceholder", "updateWord", "cancelWord", "onEditUpdate", "onEditCancel", "inputRef", "editFormProps", "isCompact", "isMarkdownDisabled", "reactMarkdownProps", "toolResponse"]);
50
+ var { role, content, extraContent, name, avatar, timestamp, isLoading, actions, sources, botWord = 'AI', loadingWord = 'Loading message', codeBlockProps, quickResponses, quickResponseContainerProps = { numLabels: 5 }, attachments, hasRoundAvatar = true, avatarProps, quickStarts, userFeedbackForm, userFeedbackComplete, isLiveRegion = true, innerRef, tableProps, openLinkInNewTab = true, additionalRehypePlugins = [], linkProps, error, isEditable, editPlaceholder = 'Edit prompt message...', updateWord = 'Update', cancelWord = 'Cancel', onEditUpdate, onEditCancel, inputRef, editFormProps, isCompact, isMarkdownDisabled, reactMarkdownProps, toolResponse, deepThinking } = _a, props = __rest(_a, ["role", "content", "extraContent", "name", "avatar", "timestamp", "isLoading", "actions", "sources", "botWord", "loadingWord", "codeBlockProps", "quickResponses", "quickResponseContainerProps", "attachments", "hasRoundAvatar", "avatarProps", "quickStarts", "userFeedbackForm", "userFeedbackComplete", "isLiveRegion", "innerRef", "tableProps", "openLinkInNewTab", "additionalRehypePlugins", "linkProps", "error", "isEditable", "editPlaceholder", "updateWord", "cancelWord", "onEditUpdate", "onEditCancel", "inputRef", "editFormProps", "isCompact", "isMarkdownDisabled", "reactMarkdownProps", "toolResponse", "deepThinking"]);
50
51
  const [messageText, setMessageText] = useState(content);
51
52
  useEffect(() => {
52
53
  setMessageText(content);
@@ -115,7 +116,7 @@ export const MessageBase = (_a) => {
115
116
  }
116
117
  return (_jsxs(_Fragment, { children: [beforeMainContent && _jsx(_Fragment, { children: beforeMainContent }), error ? _jsx(ErrorMessage, Object.assign({}, error)) : handleMarkdown()] }));
117
118
  };
118
- return (_jsxs("section", Object.assign({ "aria-label": `Message from ${role} - ${dateString}`, className: `pf-chatbot__message pf-chatbot__message--${role}`, "aria-live": isLiveRegion ? 'polite' : undefined, "aria-atomic": isLiveRegion ? false : undefined, ref: innerRef }, props, { children: [_jsx(Avatar, Object.assign({ className: `pf-chatbot__message-avatar ${hasRoundAvatar ? 'pf-chatbot__message-avatar--round' : ''} ${avatarClassName ? avatarClassName : ''}`, src: avatar, alt: "" }, avatarProps)), _jsxs("div", { className: "pf-chatbot__message-contents", children: [_jsxs("div", { className: "pf-chatbot__message-meta", children: [name && (_jsx("span", { className: "pf-chatbot__message-name", children: _jsx(Truncate, { content: name }) })), role === 'bot' && (_jsx(Label, { variant: "outline", isCompact: true, children: botWord })), _jsx(Timestamp, { date: date, children: timestamp })] }), _jsxs("div", { className: "pf-chatbot__message-response", children: [_jsxs("div", { className: "pf-chatbot__message-and-actions", children: [renderMessage(), afterMainContent && _jsx(_Fragment, { children: afterMainContent }), toolResponse && _jsx(ToolResponse, Object.assign({}, toolResponse)), !isLoading && sources && _jsx(SourcesCard, Object.assign({}, sources, { isCompact: isCompact })), quickStarts && quickStarts.quickStart && (_jsx(QuickStartTile, { quickStart: quickStarts.quickStart, onSelectQuickStart: quickStarts.onSelectQuickStart, minuteWord: quickStarts.minuteWord, minuteWordPlural: quickStarts.minuteWordPlural, prerequisiteWord: quickStarts.prerequisiteWord, prerequisiteWordPlural: quickStarts.prerequisiteWordPlural, quickStartButtonAriaLabel: quickStarts.quickStartButtonAriaLabel, isCompact: isCompact })), !isLoading && !isEditable && actions && _jsx(ResponseActions, { actions: actions }), userFeedbackForm && _jsx(UserFeedback, Object.assign({}, userFeedbackForm, { timestamp: dateString, isCompact: isCompact })), userFeedbackComplete && (_jsx(UserFeedbackComplete, Object.assign({}, userFeedbackComplete, { timestamp: dateString, isCompact: isCompact }))), !isLoading && quickResponses && (_jsx(QuickResponse, { quickResponses: quickResponses, quickResponseContainerProps: quickResponseContainerProps, isCompact: isCompact }))] }), attachments && (_jsx("div", { className: "pf-chatbot__message-attachments-container", children: attachments.map((attachment) => {
119
+ return (_jsxs("section", Object.assign({ "aria-label": `Message from ${role} - ${dateString}`, className: `pf-chatbot__message pf-chatbot__message--${role}`, "aria-live": isLiveRegion ? 'polite' : undefined, "aria-atomic": isLiveRegion ? false : undefined, ref: innerRef }, props, { children: [_jsx(Avatar, Object.assign({ className: `pf-chatbot__message-avatar ${hasRoundAvatar ? 'pf-chatbot__message-avatar--round' : ''} ${avatarClassName ? avatarClassName : ''}`, src: avatar, alt: "" }, avatarProps)), _jsxs("div", { className: "pf-chatbot__message-contents", children: [_jsxs("div", { className: "pf-chatbot__message-meta", children: [name && (_jsx("span", { className: "pf-chatbot__message-name", children: _jsx(Truncate, { content: name }) })), role === 'bot' && (_jsx(Label, { variant: "outline", isCompact: true, children: botWord })), _jsx(Timestamp, { date: date, children: timestamp })] }), _jsxs("div", { className: "pf-chatbot__message-response", children: [_jsxs("div", { className: "pf-chatbot__message-and-actions", children: [renderMessage(), afterMainContent && _jsx(_Fragment, { children: afterMainContent }), toolResponse && _jsx(ToolResponse, Object.assign({}, toolResponse)), deepThinking && _jsx(DeepThinking, Object.assign({}, deepThinking)), !isLoading && sources && _jsx(SourcesCard, Object.assign({}, sources, { isCompact: isCompact })), quickStarts && quickStarts.quickStart && (_jsx(QuickStartTile, { quickStart: quickStarts.quickStart, onSelectQuickStart: quickStarts.onSelectQuickStart, minuteWord: quickStarts.minuteWord, minuteWordPlural: quickStarts.minuteWordPlural, prerequisiteWord: quickStarts.prerequisiteWord, prerequisiteWordPlural: quickStarts.prerequisiteWordPlural, quickStartButtonAriaLabel: quickStarts.quickStartButtonAriaLabel, isCompact: isCompact })), !isLoading && !isEditable && actions && _jsx(ResponseActions, { actions: actions }), userFeedbackForm && _jsx(UserFeedback, Object.assign({}, userFeedbackForm, { timestamp: dateString, isCompact: isCompact })), userFeedbackComplete && (_jsx(UserFeedbackComplete, Object.assign({}, userFeedbackComplete, { timestamp: dateString, isCompact: isCompact }))), !isLoading && quickResponses && (_jsx(QuickResponse, { quickResponses: quickResponses, quickResponseContainerProps: quickResponseContainerProps, isCompact: isCompact }))] }), attachments && (_jsx("div", { className: "pf-chatbot__message-attachments-container", children: attachments.map((attachment) => {
119
120
  var _a;
120
121
  return (_jsx("div", { className: "pf-chatbot__message-attachment", children: _jsx(FileDetailsLabel, { fileName: attachment.name, fileId: attachment.id, onClose: attachment.onClose, onClick: attachment.onClick, isLoading: attachment.isLoading, closeButtonAriaLabel: attachment.closeButtonAriaLabel, languageTestId: attachment.languageTestId, spinnerTestId: attachment.spinnerTestId }) }, (_a = attachment.id) !== null && _a !== void 0 ? _a : attachment.name));
121
122
  }) })), !isLoading && endContent && _jsx(_Fragment, { children: endContent })] })] })] })));
@@ -138,6 +138,11 @@ const EMPTY_TABLE = `
138
138
  `;
139
139
  const IMAGE = `![Multi-colored wavy lines on a black background](https://cdn.dribbble.com/userupload/10651749/file/original-8a07b8e39d9e8bf002358c66fce1223e.gif)`;
140
140
  const INLINE_IMAGE = `inline text ![Multi-colored wavy lines on a black background](https://cdn.dribbble.com/userupload/10651749/file/original-8a07b8e39d9e8bf002358c66fce1223e.gif)`;
141
+ const DEEP_THINKING = {
142
+ toggleContent: 'Show thinking',
143
+ subheading: 'Thought for 3 seconds',
144
+ body: "Here's why I said this."
145
+ };
141
146
  const ERROR = {
142
147
  title: 'Could not load chat',
143
148
  children: 'Wait a few minutes and check your network settings. If the issue persists: ',
@@ -759,4 +764,10 @@ describe('Message', () => {
759
764
  // code block isn't rendering
760
765
  expect(screen.queryByRole('button', { name: 'Copy code' })).toBeFalsy();
761
766
  });
767
+ it('should render deep thinking section correctly', () => {
768
+ render(_jsx(Message, { avatar: "./img", role: "user", name: "User", content: "", deepThinking: DEEP_THINKING }));
769
+ expect(screen.getByRole('button', { name: /Show thinking/i })).toBeTruthy();
770
+ expect(screen.getByText('Thought for 3 seconds')).toBeTruthy();
771
+ expect(screen.getByText("Here's why I said this.")).toBeTruthy();
772
+ });
762
773
  });
@@ -26,12 +26,16 @@ export { default as CodeModal } from './CodeModal';
26
26
  export * from './CodeModal';
27
27
  export { default as Compare } from './Compare';
28
28
  export * from './Compare';
29
+ export { default as DeepThinking } from './DeepThinking';
30
+ export * from './DeepThinking';
29
31
  export { default as FileDetails } from './FileDetails';
30
32
  export * from './FileDetails';
31
33
  export { default as FileDetailsLabel } from './FileDetailsLabel';
32
34
  export * from './FileDetailsLabel';
33
35
  export { default as FileDropZone } from './FileDropZone';
34
36
  export * from './FileDropZone';
37
+ export { default as FilePreview } from './FilePreview';
38
+ export * from './FilePreview';
35
39
  export { default as LoadingMessage } from './LoadingMessage';
36
40
  export * from './LoadingMessage';
37
41
  export { default as Message } from './Message';
package/dist/esm/index.js CHANGED
@@ -27,12 +27,16 @@ export { default as CodeModal } from './CodeModal';
27
27
  export * from './CodeModal';
28
28
  export { default as Compare } from './Compare';
29
29
  export * from './Compare';
30
+ export { default as DeepThinking } from './DeepThinking';
31
+ export * from './DeepThinking';
30
32
  export { default as FileDetails } from './FileDetails';
31
33
  export * from './FileDetails';
32
34
  export { default as FileDetailsLabel } from './FileDetailsLabel';
33
35
  export * from './FileDetailsLabel';
34
36
  export { default as FileDropZone } from './FileDropZone';
35
37
  export * from './FileDropZone';
38
+ export { default as FilePreview } from './FilePreview';
39
+ export * from './FilePreview';
36
40
  export { default as LoadingMessage } from './LoadingMessage';
37
41
  export * from './LoadingMessage';
38
42
  export { default as Message } from './Message';
@@ -1 +1 @@
1
- {"root":["../src/index.ts","../src/AttachMenu/AttachMenu.tsx","../src/AttachMenu/index.ts","../src/AttachmentEdit/AttachmentEdit.test.tsx","../src/AttachmentEdit/AttachmentEdit.tsx","../src/AttachmentEdit/index.ts","../src/Chatbot/Chatbot.test.tsx","../src/Chatbot/Chatbot.tsx","../src/Chatbot/index.ts","../src/ChatbotAlert/ChatbotAlert.test.tsx","../src/ChatbotAlert/ChatbotAlert.tsx","../src/ChatbotAlert/index.ts","../src/ChatbotContent/ChatbotContent.test.tsx","../src/ChatbotContent/ChatbotContent.tsx","../src/ChatbotContent/index.ts","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.test.tsx","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.tsx","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx","../src/ChatbotConversationHistoryNav/EmptyState.tsx","../src/ChatbotConversationHistoryNav/LoadingState.tsx","../src/ChatbotConversationHistoryNav/index.ts","../src/ChatbotFooter/ChatbotFooter.test.tsx","../src/ChatbotFooter/ChatbotFooter.tsx","../src/ChatbotFooter/ChatbotFooternote.test.tsx","../src/ChatbotFooter/ChatbotFootnote.tsx","../src/ChatbotFooter/index.ts","../src/ChatbotHeader/ChatbotHeader.test.tsx","../src/ChatbotHeader/ChatbotHeader.tsx","../src/ChatbotHeader/ChatbotHeaderActions.test.tsx","../src/ChatbotHeader/ChatbotHeaderActions.tsx","../src/ChatbotHeader/ChatbotHeaderCloseButton.test.tsx","../src/ChatbotHeader/ChatbotHeaderCloseButton.tsx","../src/ChatbotHeader/ChatbotHeaderMain.test.tsx","../src/ChatbotHeader/ChatbotHeaderMain.tsx","../src/ChatbotHeader/ChatbotHeaderMenu.test.tsx","../src/ChatbotHeader/ChatbotHeaderMenu.tsx","../src/ChatbotHeader/ChatbotHeaderNewChatButton.test.tsx","../src/ChatbotHeader/ChatbotHeaderNewChatButton.tsx","../src/ChatbotHeader/ChatbotHeaderOptionsDropdown.test.tsx","../src/ChatbotHeader/ChatbotHeaderOptionsDropdown.tsx","../src/ChatbotHeader/ChatbotHeaderSelectorDropdown.test.tsx","../src/ChatbotHeader/ChatbotHeaderSelectorDropdown.tsx","../src/ChatbotHeader/ChatbotHeaderTitle.test.tsx","../src/ChatbotHeader/ChatbotHeaderTitle.tsx","../src/ChatbotHeader/index.ts","../src/ChatbotModal/ChatbotModal.test.tsx","../src/ChatbotModal/ChatbotModal.tsx","../src/ChatbotModal/index.ts","../src/ChatbotPopover/ChatbotPopover.tsx","../src/ChatbotPopover/index.ts","../src/ChatbotToggle/ChatbotToggle.test.tsx","../src/ChatbotToggle/ChatbotToggle.tsx","../src/ChatbotToggle/index.ts","../src/ChatbotWelcomePrompt/ChatbotWelcomePrompt.test.tsx","../src/ChatbotWelcomePrompt/ChatbotWelcomePrompt.tsx","../src/ChatbotWelcomePrompt/index.ts","../src/CodeModal/CodeModal.test.tsx","../src/CodeModal/CodeModal.tsx","../src/CodeModal/index.ts","../src/Compare/Compare.test.tsx","../src/Compare/Compare.tsx","../src/Compare/index.ts","../src/FileDetails/FileDetails.test.tsx","../src/FileDetails/FileDetails.tsx","../src/FileDetails/index.ts","../src/FileDetailsLabel/FileDetailsLabel.test.tsx","../src/FileDetailsLabel/FileDetailsLabel.tsx","../src/FileDetailsLabel/index.ts","../src/FileDropZone/FileDropZone.test.tsx","../src/FileDropZone/FileDropZone.tsx","../src/FileDropZone/index.ts","../src/LoadingMessage/LoadingMessage.test.tsx","../src/LoadingMessage/LoadingMessage.tsx","../src/LoadingMessage/index.ts","../src/Message/Message.test.tsx","../src/Message/Message.tsx","../src/Message/MessageInput.tsx","../src/Message/MessageLoading.tsx","../src/Message/index.ts","../src/Message/CodeBlockMessage/CodeBlockMessage.tsx","../src/Message/ErrorMessage/ErrorMessage.tsx","../src/Message/ImageMessage/ImageMessage.tsx","../src/Message/LinkMessage/LinkMessage.tsx","../src/Message/ListMessage/ListItemMessage.tsx","../src/Message/ListMessage/OrderedListMessage.tsx","../src/Message/ListMessage/UnorderedListMessage.tsx","../src/Message/Plugins/index.ts","../src/Message/Plugins/rehypeCodeBlockToggle.ts","../src/Message/Plugins/rehypeMoveImagesOutOfParagraphs.ts","../src/Message/QuickResponse/QuickResponse.tsx","../src/Message/QuickStarts/FallbackImg.tsx","../src/Message/QuickStarts/QuickStartTile.tsx","../src/Message/QuickStarts/QuickStartTileDescription.test.tsx","../src/Message/QuickStarts/QuickStartTileDescription.tsx","../src/Message/QuickStarts/QuickStartTileHeader.tsx","../src/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.ts","../src/Message/QuickStarts/monitor-sampleapp-quickstart.ts","../src/Message/QuickStarts/types.ts","../src/Message/TableMessage/TableMessage.tsx","../src/Message/TableMessage/TbodyMessage.tsx","../src/Message/TableMessage/TdMessage.tsx","../src/Message/TableMessage/ThMessage.tsx","../src/Message/TableMessage/TheadMessage.tsx","../src/Message/TableMessage/TrMessage.tsx","../src/Message/TextMessage/TextMessage.tsx","../src/Message/UserFeedback/CloseButton.tsx","../src/Message/UserFeedback/UserFeedback.test.tsx","../src/Message/UserFeedback/UserFeedback.tsx","../src/Message/UserFeedback/UserFeedbackComplete.test.tsx","../src/Message/UserFeedback/UserFeedbackComplete.tsx","../src/MessageBar/AttachButton.test.tsx","../src/MessageBar/AttachButton.tsx","../src/MessageBar/MessageBar.test.tsx","../src/MessageBar/MessageBar.tsx","../src/MessageBar/MicrophoneButton.tsx","../src/MessageBar/SendButton.test.tsx","../src/MessageBar/SendButton.tsx","../src/MessageBar/StopButton.test.tsx","../src/MessageBar/StopButton.tsx","../src/MessageBar/index.ts","../src/MessageBox/JumpButton.test.tsx","../src/MessageBox/JumpButton.tsx","../src/MessageBox/MessageBox.test.tsx","../src/MessageBox/MessageBox.tsx","../src/MessageBox/index.ts","../src/MessageDivider/MessageDivider.test.tsx","../src/MessageDivider/MessageDivider.tsx","../src/MessageDivider/index.ts","../src/PreviewAttachment/PreviewAttachment.test.tsx","../src/PreviewAttachment/PreviewAttachment.tsx","../src/PreviewAttachment/index.ts","../src/ResponseActions/ResponseActionButton.test.tsx","../src/ResponseActions/ResponseActionButton.tsx","../src/ResponseActions/ResponseActions.test.tsx","../src/ResponseActions/ResponseActions.tsx","../src/ResponseActions/index.ts","../src/Settings/SettingsForm.test.tsx","../src/Settings/SettingsForm.tsx","../src/Settings/index.ts","../src/SourceDetailsMenuItem/SourceDetailsMenuItem.tsx","../src/SourceDetailsMenuItem/index.ts","../src/SourcesCard/SourcesCard.test.tsx","../src/SourcesCard/SourcesCard.tsx","../src/SourcesCard/index.ts","../src/TermsOfUse/TermsOfUse.test.tsx","../src/TermsOfUse/TermsOfUse.tsx","../src/TermsOfUse/index.ts","../src/ToolResponse/ToolResponse.test.tsx","../src/ToolResponse/ToolResponse.tsx","../src/ToolResponse/index.ts","../src/__mocks__/rehype-external-links.ts","../src/__mocks__/rehype-sanitize.ts","../src/__mocks__/rehype-unwrap-images.tsx","../src/tracking/console_tracking_provider.ts","../src/tracking/index.ts","../src/tracking/posthog_tracking_provider.ts","../src/tracking/segment_tracking_provider.ts","../src/tracking/trackingProviderProxy.ts","../src/tracking/tracking_api.ts","../src/tracking/tracking_registry.ts","../src/tracking/tracking_spi.ts","../src/tracking/umami_tracking_provider.ts"],"version":"5.6.3"}
1
+ {"root":["../src/index.ts","../src/AttachMenu/AttachMenu.tsx","../src/AttachMenu/index.ts","../src/AttachmentEdit/AttachmentEdit.test.tsx","../src/AttachmentEdit/AttachmentEdit.tsx","../src/AttachmentEdit/index.ts","../src/Chatbot/Chatbot.test.tsx","../src/Chatbot/Chatbot.tsx","../src/Chatbot/index.ts","../src/ChatbotAlert/ChatbotAlert.test.tsx","../src/ChatbotAlert/ChatbotAlert.tsx","../src/ChatbotAlert/index.ts","../src/ChatbotContent/ChatbotContent.test.tsx","../src/ChatbotContent/ChatbotContent.tsx","../src/ChatbotContent/index.ts","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.test.tsx","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.tsx","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx","../src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx","../src/ChatbotConversationHistoryNav/EmptyState.tsx","../src/ChatbotConversationHistoryNav/LoadingState.tsx","../src/ChatbotConversationHistoryNav/index.ts","../src/ChatbotFooter/ChatbotFooter.test.tsx","../src/ChatbotFooter/ChatbotFooter.tsx","../src/ChatbotFooter/ChatbotFooternote.test.tsx","../src/ChatbotFooter/ChatbotFootnote.tsx","../src/ChatbotFooter/index.ts","../src/ChatbotHeader/ChatbotHeader.test.tsx","../src/ChatbotHeader/ChatbotHeader.tsx","../src/ChatbotHeader/ChatbotHeaderActions.test.tsx","../src/ChatbotHeader/ChatbotHeaderActions.tsx","../src/ChatbotHeader/ChatbotHeaderCloseButton.test.tsx","../src/ChatbotHeader/ChatbotHeaderCloseButton.tsx","../src/ChatbotHeader/ChatbotHeaderMain.test.tsx","../src/ChatbotHeader/ChatbotHeaderMain.tsx","../src/ChatbotHeader/ChatbotHeaderMenu.test.tsx","../src/ChatbotHeader/ChatbotHeaderMenu.tsx","../src/ChatbotHeader/ChatbotHeaderNewChatButton.test.tsx","../src/ChatbotHeader/ChatbotHeaderNewChatButton.tsx","../src/ChatbotHeader/ChatbotHeaderOptionsDropdown.test.tsx","../src/ChatbotHeader/ChatbotHeaderOptionsDropdown.tsx","../src/ChatbotHeader/ChatbotHeaderSelectorDropdown.test.tsx","../src/ChatbotHeader/ChatbotHeaderSelectorDropdown.tsx","../src/ChatbotHeader/ChatbotHeaderTitle.test.tsx","../src/ChatbotHeader/ChatbotHeaderTitle.tsx","../src/ChatbotHeader/index.ts","../src/ChatbotModal/ChatbotModal.test.tsx","../src/ChatbotModal/ChatbotModal.tsx","../src/ChatbotModal/index.ts","../src/ChatbotPopover/ChatbotPopover.tsx","../src/ChatbotPopover/index.ts","../src/ChatbotToggle/ChatbotToggle.test.tsx","../src/ChatbotToggle/ChatbotToggle.tsx","../src/ChatbotToggle/index.ts","../src/ChatbotWelcomePrompt/ChatbotWelcomePrompt.test.tsx","../src/ChatbotWelcomePrompt/ChatbotWelcomePrompt.tsx","../src/ChatbotWelcomePrompt/index.ts","../src/CodeModal/CodeModal.test.tsx","../src/CodeModal/CodeModal.tsx","../src/CodeModal/index.ts","../src/Compare/Compare.test.tsx","../src/Compare/Compare.tsx","../src/Compare/index.ts","../src/DeepThinking/DeepThinking.test.tsx","../src/DeepThinking/DeepThinking.tsx","../src/DeepThinking/index.ts","../src/FileDetails/FileDetails.test.tsx","../src/FileDetails/FileDetails.tsx","../src/FileDetails/index.ts","../src/FileDetailsLabel/FileDetailsLabel.test.tsx","../src/FileDetailsLabel/FileDetailsLabel.tsx","../src/FileDetailsLabel/index.ts","../src/FileDropZone/FileDropZone.test.tsx","../src/FileDropZone/FileDropZone.tsx","../src/FileDropZone/index.ts","../src/FilePreview/FilePreview.test.tsx","../src/FilePreview/FilePreview.tsx","../src/FilePreview/index.ts","../src/LoadingMessage/LoadingMessage.test.tsx","../src/LoadingMessage/LoadingMessage.tsx","../src/LoadingMessage/index.ts","../src/Message/Message.test.tsx","../src/Message/Message.tsx","../src/Message/MessageInput.tsx","../src/Message/MessageLoading.tsx","../src/Message/index.ts","../src/Message/CodeBlockMessage/CodeBlockMessage.tsx","../src/Message/ErrorMessage/ErrorMessage.tsx","../src/Message/ImageMessage/ImageMessage.tsx","../src/Message/LinkMessage/LinkMessage.tsx","../src/Message/ListMessage/ListItemMessage.tsx","../src/Message/ListMessage/OrderedListMessage.tsx","../src/Message/ListMessage/UnorderedListMessage.tsx","../src/Message/Plugins/index.ts","../src/Message/Plugins/rehypeCodeBlockToggle.ts","../src/Message/Plugins/rehypeMoveImagesOutOfParagraphs.ts","../src/Message/QuickResponse/QuickResponse.tsx","../src/Message/QuickStarts/FallbackImg.tsx","../src/Message/QuickStarts/QuickStartTile.tsx","../src/Message/QuickStarts/QuickStartTileDescription.test.tsx","../src/Message/QuickStarts/QuickStartTileDescription.tsx","../src/Message/QuickStarts/QuickStartTileHeader.tsx","../src/Message/QuickStarts/monitor-sampleapp-quickstart-with-image.ts","../src/Message/QuickStarts/monitor-sampleapp-quickstart.ts","../src/Message/QuickStarts/types.ts","../src/Message/TableMessage/TableMessage.tsx","../src/Message/TableMessage/TbodyMessage.tsx","../src/Message/TableMessage/TdMessage.tsx","../src/Message/TableMessage/ThMessage.tsx","../src/Message/TableMessage/TheadMessage.tsx","../src/Message/TableMessage/TrMessage.tsx","../src/Message/TextMessage/TextMessage.tsx","../src/Message/UserFeedback/CloseButton.tsx","../src/Message/UserFeedback/UserFeedback.test.tsx","../src/Message/UserFeedback/UserFeedback.tsx","../src/Message/UserFeedback/UserFeedbackComplete.test.tsx","../src/Message/UserFeedback/UserFeedbackComplete.tsx","../src/MessageBar/AttachButton.test.tsx","../src/MessageBar/AttachButton.tsx","../src/MessageBar/MessageBar.test.tsx","../src/MessageBar/MessageBar.tsx","../src/MessageBar/MicrophoneButton.tsx","../src/MessageBar/SendButton.test.tsx","../src/MessageBar/SendButton.tsx","../src/MessageBar/StopButton.test.tsx","../src/MessageBar/StopButton.tsx","../src/MessageBar/index.ts","../src/MessageBox/JumpButton.test.tsx","../src/MessageBox/JumpButton.tsx","../src/MessageBox/MessageBox.test.tsx","../src/MessageBox/MessageBox.tsx","../src/MessageBox/index.ts","../src/MessageDivider/MessageDivider.test.tsx","../src/MessageDivider/MessageDivider.tsx","../src/MessageDivider/index.ts","../src/PreviewAttachment/PreviewAttachment.test.tsx","../src/PreviewAttachment/PreviewAttachment.tsx","../src/PreviewAttachment/index.ts","../src/ResponseActions/ResponseActionButton.test.tsx","../src/ResponseActions/ResponseActionButton.tsx","../src/ResponseActions/ResponseActions.test.tsx","../src/ResponseActions/ResponseActions.tsx","../src/ResponseActions/index.ts","../src/Settings/SettingsForm.test.tsx","../src/Settings/SettingsForm.tsx","../src/Settings/index.ts","../src/SourceDetailsMenuItem/SourceDetailsMenuItem.tsx","../src/SourceDetailsMenuItem/index.ts","../src/SourcesCard/SourcesCard.test.tsx","../src/SourcesCard/SourcesCard.tsx","../src/SourcesCard/index.ts","../src/TermsOfUse/TermsOfUse.test.tsx","../src/TermsOfUse/TermsOfUse.tsx","../src/TermsOfUse/index.ts","../src/ToolResponse/ToolResponse.test.tsx","../src/ToolResponse/ToolResponse.tsx","../src/ToolResponse/index.ts","../src/__mocks__/rehype-external-links.ts","../src/__mocks__/rehype-sanitize.ts","../src/__mocks__/rehype-unwrap-images.tsx","../src/tracking/console_tracking_provider.ts","../src/tracking/index.ts","../src/tracking/posthog_tracking_provider.ts","../src/tracking/segment_tracking_provider.ts","../src/tracking/trackingProviderProxy.ts","../src/tracking/tracking_api.ts","../src/tracking/tracking_registry.ts","../src/tracking/tracking_spi.ts","../src/tracking/umami_tracking_provider.ts"],"version":"5.6.3"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/chatbot",
3
- "version": "6.4.0-prerelease.17",
3
+ "version": "6.4.0-prerelease.19",
4
4
  "description": "This library provides React components based on PatternFly 6 that can be used to build chatbots.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -0,0 +1,33 @@
1
+ import { useState, FunctionComponent, MouseEvent as ReactMouseEvent } from 'react';
2
+ import { Button, Checkbox } from '@patternfly/react-core';
3
+ import FilePreview from '@patternfly/chatbot/dist/dynamic/FilePreview';
4
+
5
+ export const AttachmentEditModalExample: FunctionComponent = () => {
6
+ const [isModalOpen, setIsModalOpen] = useState(false);
7
+ const [isCompact, setIsCompact] = useState(false);
8
+
9
+ const handleModalToggle = (_event: ReactMouseEvent | MouseEvent | KeyboardEvent) => {
10
+ setIsModalOpen(!isModalOpen);
11
+ };
12
+
13
+ return (
14
+ <>
15
+ <Checkbox
16
+ label="Show compact version"
17
+ isChecked={isCompact}
18
+ onChange={() => setIsCompact(!isCompact)}
19
+ id="modal-compact-no-preview"
20
+ name="modal-compact-no-preview"
21
+ ></Checkbox>
22
+ <Button onClick={handleModalToggle}>Launch file preview modal</Button>
23
+ <FilePreview
24
+ isModalOpen={isModalOpen}
25
+ handleModalToggle={handleModalToggle}
26
+ fileName="compressed-file.zip"
27
+ isCompact={isCompact}
28
+ >
29
+ Preview unavailable
30
+ </FilePreview>
31
+ </>
32
+ );
33
+ };
@@ -0,0 +1,17 @@
1
+ import { FunctionComponent } from 'react';
2
+ import Message from '@patternfly/chatbot/dist/dynamic/Message';
3
+ import patternflyAvatar from './patternfly_avatar.jpg';
4
+
5
+ export const MessageWithDeepThinkingExample: FunctionComponent = () => (
6
+ <Message
7
+ name="Bot"
8
+ role="bot"
9
+ avatar={patternflyAvatar}
10
+ content="This example has a body description that's within the recommended limit of 2 lines."
11
+ deepThinking={{
12
+ toggleContent: 'Show thinking',
13
+ subheading: 'Thought for 3 seconds',
14
+ body: "Here's why I said this."
15
+ }}
16
+ />
17
+ );
@@ -47,6 +47,7 @@ import { monitorSampleAppQuickStart } from '@patternfly/chatbot/src/Message/Quic
47
47
  import userAvatar from './user_avatar.svg';
48
48
  import squareImg from './PF-social-color-square.svg';
49
49
  import { CSSProperties, useState, Fragment, FunctionComponent, MouseEvent as ReactMouseEvent, KeyboardEvent as ReactKeyboardEvent, Ref, isValidElement, cloneElement, Children, ReactNode, useRef, useEffect } from 'react';
50
+ import FilePreview from '@patternfly/chatbot/dist/dynamic/FilePreview';
50
51
 
51
52
  The `content` prop of the `<Message>` component is passed to a `<Markdown>` component (from [react-markdown](https://remarkjs.github.io/react-markdown/)), which is configured to translate plain text strings into PatternFly [`<Content>` components](/components/content) and code blocks into PatternFly [`<CodeBlock>` components.](/components/code-block)
52
53
 
@@ -186,6 +187,16 @@ If you are using [model context protocol (MCP)](https://www.redhat.com/en/blog/m
186
187
 
187
188
  ```
188
189
 
190
+ ### Messages with deep thinking
191
+
192
+ You can share details about the "thought process" behind an LLM's response, also known as deep thinking. To display a customizable, expandable card with these details, pass `deepThinking` to `<Message>` and provide a subheading (optional) and content body.
193
+
194
+ Because this is an evolving area, this card content is currently fully customizable.
195
+
196
+ ```js file="./MessageWithDeepThinking.tsx"
197
+
198
+ ```
199
+
189
200
  ### Messages with quick start tiles
190
201
 
191
202
  [Quick start](/extensions/quick-starts/) tiles can be added to messages via the `quickStarts` prop. Users can initiate the quick start from a link within the message tile.
@@ -263,6 +274,14 @@ To allow users to edit an attached file, load a new code editor within the ChatB
263
274
 
264
275
  ```
265
276
 
277
+ ### File preview
278
+
279
+ If the contents of an attachment cannot be previewed, load a file preview modal with a view of the file name and an unavailable message. When users close the modal, return to the main ChatBot window.
280
+
281
+ ```js file="./FilePreview.tsx"
282
+
283
+ ```
284
+
266
285
  ### Failed attachment error
267
286
 
268
287
  When an attachment upload fails, a [danger alert](/components/alert) is displayed to provide details about the reason for failure.
@@ -87,6 +87,7 @@ import patternflyAvatar from '../Messages/patternfly_avatar.jpg';
87
87
  import termsAndConditionsHeader from './PF-TermsAndConditionsHeader.svg';
88
88
  import { CloseIcon, SearchIcon, OutlinedCommentsIcon } from '@patternfly/react-icons';
89
89
  import { FunctionComponent, FormEvent, useState, useRef, MouseEvent, isValidElement, cloneElement, Children, ReactNode, Ref, MouseEvent as ReactMouseEvent, CSSProperties, useEffect} from 'react';
90
+ import FilePreview from '@patternfly/chatbot/dist/dynamic/FilePreview';
90
91
 
91
92
  ## Structure
92
93
 
@@ -0,0 +1,24 @@
1
+ .pf-chatbot__deep-thinking {
2
+ --pf-v6-c-card--BorderColor: var(--pf-t--global--border--color--control--read-only);
3
+ overflow: unset;
4
+ }
5
+
6
+ .pf-chatbot__deep-thinking-expandable-section {
7
+ --pf-v6-c-expandable-section--Gap: var(--pf-t--global--spacer--xs);
8
+ }
9
+
10
+ .pf-chatbot__deep-thinking-section {
11
+ display: flex;
12
+ flex-direction: column;
13
+ gap: var(--pf-t--global--spacer--xs);
14
+ }
15
+
16
+ .pf-chatbot__deep-thinking-subheading {
17
+ font-size: var(--pf-t--global--font--size--body--sm);
18
+ font-weight: var(--pf-t--global--font--weight--body--default);
19
+ color: var(--pf-t--global--text--color--subtle);
20
+ }
21
+
22
+ .pf-chatbot__deep-thinking-body {
23
+ color: var(--pf-t--global--text--color--subtle);
24
+ }
@@ -0,0 +1,61 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import '@testing-library/jest-dom';
3
+ import DeepThinking from './DeepThinking';
4
+
5
+ describe('DeepThinking', () => {
6
+ const defaultProps = {
7
+ toggleContent: 'Show thinking'
8
+ };
9
+
10
+ it('should render with required props only', () => {
11
+ render(<DeepThinking {...defaultProps} />);
12
+ expect(screen.getByText('Show thinking')).toBeTruthy();
13
+ });
14
+
15
+ it('should render subheading when provided', () => {
16
+ const subheading = 'Thought for 3 seconds';
17
+ render(<DeepThinking {...defaultProps} subheading={subheading} />);
18
+ expect(screen.getByText(subheading)).toBeTruthy();
19
+ });
20
+
21
+ it('should render body content when provided', () => {
22
+ const body = "Here's why I think that";
23
+ render(<DeepThinking {...defaultProps} body={body} />);
24
+ expect(screen.getByText(body)).toBeTruthy();
25
+ });
26
+
27
+ it('should render with complex content including React elements', () => {
28
+ const body = (
29
+ <div>
30
+ <p>Complex body content</p>
31
+ <ul>
32
+ <li>Item 1</li>
33
+ <li>Item 2</li>
34
+ </ul>
35
+ </div>
36
+ );
37
+
38
+ render(<DeepThinking {...defaultProps} body={body} />);
39
+ expect(screen.getByText('Complex body content')).toBeTruthy();
40
+ expect(screen.getByText('Item 1')).toBeTruthy();
41
+ expect(screen.getByText('Item 2')).toBeTruthy();
42
+ });
43
+
44
+ it('should apply custom className from cardProps', () => {
45
+ const { container } = render(
46
+ <DeepThinking {...defaultProps} cardProps={{ className: 'custom-tool-response-class' }} />
47
+ );
48
+ expect(container.querySelector('.custom-tool-response-class')).toBeTruthy();
49
+ });
50
+
51
+ it('should pass through expandableSectionProps', () => {
52
+ render(<DeepThinking {...defaultProps} expandableSectionProps={{ className: 'custom-expandable-class' }} />);
53
+ expect(document.querySelector('.custom-expandable-class')).toBeTruthy();
54
+ });
55
+
56
+ it('should not render subheading span when subheading is not provided', () => {
57
+ const { container } = render(<DeepThinking {...defaultProps} />);
58
+ const subheadingContainer = container.querySelector('.pf-chatbot__tool-response-subheading');
59
+ expect(subheadingContainer).toBeFalsy();
60
+ });
61
+ });