@patternfly/chatbot 6.5.0-prerelease.24 → 6.5.0-prerelease.26
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.
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +9 -1
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +9 -2
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +38 -0
- package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +12 -2
- package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.test.d.ts +1 -0
- package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.test.js +131 -0
- package/dist/css/main.css +11 -0
- package/dist/css/main.css.map +1 -1
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +9 -1
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +10 -3
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +38 -0
- package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +12 -2
- package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.test.d.ts +1 -0
- package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.test.js +126 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithSearchActions.tsx +198 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +12 -2
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +18 -0
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +95 -0
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +51 -15
- package/src/Message/CodeBlockMessage/CodeBlockMessage.test.tsx +171 -0
- package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +12 -3
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
import '@testing-library/jest-dom';
|
|
12
|
+
import { render, screen } from '@testing-library/react';
|
|
13
|
+
import userEvent from '@testing-library/user-event';
|
|
14
|
+
import CodeBlockMessage from './CodeBlockMessage';
|
|
15
|
+
// Mock clipboard API
|
|
16
|
+
Object.assign(navigator, {
|
|
17
|
+
clipboard: {
|
|
18
|
+
writeText: jest.fn()
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
describe('CodeBlockMessage', () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
jest.clearAllMocks();
|
|
24
|
+
});
|
|
25
|
+
it('should render inline code for single-line content', () => {
|
|
26
|
+
render(_jsx(CodeBlockMessage, { className: "language-javascript", children: "const x = 5;" }));
|
|
27
|
+
const code = screen.getByText('const x = 5;');
|
|
28
|
+
expect(code.tagName).toBe('CODE');
|
|
29
|
+
expect(code).toHaveClass('pf-chatbot__message-inline-code');
|
|
30
|
+
});
|
|
31
|
+
it('should render code block for multi-line content', () => {
|
|
32
|
+
const multilineCode = 'const x = 5;\nconst y = 10;';
|
|
33
|
+
const { container } = render(_jsx(CodeBlockMessage, { className: "language-javascript", children: multilineCode }));
|
|
34
|
+
const codeElement = container.querySelector('code');
|
|
35
|
+
expect(codeElement === null || codeElement === void 0 ? void 0 : codeElement.textContent).toBe(multilineCode);
|
|
36
|
+
});
|
|
37
|
+
it('should display language label', () => {
|
|
38
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
39
|
+
render(_jsx(CodeBlockMessage, { className: "language-javascript", children: code }));
|
|
40
|
+
expect(screen.getByText('javascript')).toBeInTheDocument();
|
|
41
|
+
});
|
|
42
|
+
it('should render copy button', () => {
|
|
43
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
44
|
+
render(_jsx(CodeBlockMessage, { children: code }));
|
|
45
|
+
expect(screen.getByRole('button', { name: 'Copy code' })).toBeInTheDocument();
|
|
46
|
+
});
|
|
47
|
+
it('should copy plain string content to clipboard', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
49
|
+
render(_jsx(CodeBlockMessage, { children: code }));
|
|
50
|
+
const copyButton = screen.getByRole('button', { name: 'Copy code' });
|
|
51
|
+
yield userEvent.click(copyButton);
|
|
52
|
+
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(code);
|
|
53
|
+
}));
|
|
54
|
+
it('should extract text content from React elements when copying', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
55
|
+
// Simulate what happens with syntax highlighting - children become React elements
|
|
56
|
+
const { container } = render(_jsxs(CodeBlockMessage, { className: "language-javascript", children: [_jsx("span", { className: "hljs-keyword", children: "const" }), " x = 5;", '\n', _jsx("span", { className: "hljs-keyword", children: "const" }), " y = 10;"] }));
|
|
57
|
+
const copyButton = screen.getByRole('button', { name: 'Copy code' });
|
|
58
|
+
yield userEvent.click(copyButton);
|
|
59
|
+
// Should extract actual text content from DOM, not "[object Object]"
|
|
60
|
+
const codeElement = container.querySelector('code');
|
|
61
|
+
const expectedText = (codeElement === null || codeElement === void 0 ? void 0 : codeElement.textContent) || '';
|
|
62
|
+
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(expectedText);
|
|
63
|
+
expect(expectedText).not.toContain('[object Object]');
|
|
64
|
+
}));
|
|
65
|
+
it('should show check icon after copying', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
67
|
+
render(_jsx(CodeBlockMessage, { children: code }));
|
|
68
|
+
const copyButton = screen.getByRole('button', { name: 'Copy code' });
|
|
69
|
+
yield userEvent.click(copyButton);
|
|
70
|
+
// Check icon should be visible (we can verify by checking if CopyIcon is not present)
|
|
71
|
+
const svgElement = copyButton.querySelector('svg');
|
|
72
|
+
expect(svgElement).toBeInTheDocument();
|
|
73
|
+
}));
|
|
74
|
+
it('should render expandable section when isExpandable is true', () => {
|
|
75
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
76
|
+
render(_jsx(CodeBlockMessage, { isExpandable: true, children: code }));
|
|
77
|
+
expect(screen.getByRole('button', { name: 'Show more' })).toBeInTheDocument();
|
|
78
|
+
});
|
|
79
|
+
it('should toggle expandable section', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
80
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
81
|
+
render(_jsx(CodeBlockMessage, { isExpandable: true, children: code }));
|
|
82
|
+
const toggleButton = screen.getByRole('button', { name: 'Show more' });
|
|
83
|
+
yield userEvent.click(toggleButton);
|
|
84
|
+
expect(screen.getByRole('button', { name: 'Show less' })).toBeInTheDocument();
|
|
85
|
+
}));
|
|
86
|
+
it('should use custom expanded/collapsed text', () => {
|
|
87
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
88
|
+
render(_jsx(CodeBlockMessage, { isExpandable: true, expandedText: "Hide", collapsedText: "Reveal", children: code }));
|
|
89
|
+
expect(screen.getByRole('button', { name: 'Reveal' })).toBeInTheDocument();
|
|
90
|
+
});
|
|
91
|
+
it('should pass through expandableSectionProps', () => {
|
|
92
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
93
|
+
const { container } = render(_jsx(CodeBlockMessage, { isExpandable: true, expandableSectionProps: { className: 'custom-expandable-class' }, children: code }));
|
|
94
|
+
const expandableSection = container.querySelector('.pf-v6-c-expandable-section.custom-expandable-class');
|
|
95
|
+
expect(expandableSection).toBeInTheDocument();
|
|
96
|
+
});
|
|
97
|
+
it('should render custom actions', () => {
|
|
98
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
99
|
+
const customAction = _jsx("button", { "aria-label": "Custom action", children: "Custom" });
|
|
100
|
+
render(_jsx(CodeBlockMessage, { customActions: customAction, children: code }));
|
|
101
|
+
expect(screen.getByRole('button', { name: 'Custom action' })).toBeInTheDocument();
|
|
102
|
+
});
|
|
103
|
+
it('should apply isPrimary class to inline code', () => {
|
|
104
|
+
render(_jsx(CodeBlockMessage, { isPrimary: true, children: "const x = 5;" }));
|
|
105
|
+
const code = screen.getByText('const x = 5;');
|
|
106
|
+
expect(code).toHaveClass('pf-m-primary');
|
|
107
|
+
});
|
|
108
|
+
it('should apply shouldRetainStyles class to code block', () => {
|
|
109
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
110
|
+
const { container } = render(_jsx(CodeBlockMessage, { shouldRetainStyles: true, children: code }));
|
|
111
|
+
const codeBlockDiv = container.querySelector('.pf-chatbot__message-code-block');
|
|
112
|
+
expect(codeBlockDiv).toHaveClass('pf-m-markdown');
|
|
113
|
+
});
|
|
114
|
+
it('should use custom aria-label for copy button', () => {
|
|
115
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
116
|
+
render(_jsx(CodeBlockMessage, { "aria-label": "Copy this code", children: code }));
|
|
117
|
+
expect(screen.getByRole('button', { name: 'Copy this code' })).toBeInTheDocument();
|
|
118
|
+
});
|
|
119
|
+
it('should prioritize data-expanded-text over expandedText prop', () => {
|
|
120
|
+
const code = 'const x = 5;\nconst y = 10;';
|
|
121
|
+
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn());
|
|
122
|
+
render(_jsx(CodeBlockMessage, { isExpandable: true, expandedText: "Custom Expanded", "data-expanded-text": "Data Expanded", children: code }));
|
|
123
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Message:', expect.stringContaining('data-expanded-text or data-collapsed-text will override'));
|
|
124
|
+
consoleErrorSpy.mockRestore();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
@@ -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/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/ImagePreview/ImagePreview.test.tsx","../src/ImagePreview/ImagePreview.tsx","../src/ImagePreview/index.ts","../src/LoadingMessage/LoadingMessage.test.tsx","../src/LoadingMessage/LoadingMessage.tsx","../src/LoadingMessage/index.ts","../src/MarkdownContent/MarkdownContent.test.tsx","../src/MarkdownContent/MarkdownContent.tsx","../src/MarkdownContent/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/SuperscriptMessage/SuperscriptMessage.tsx","../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/Onboarding/Onboarding.test.tsx","../src/Onboarding/Onboarding.tsx","../src/Onboarding/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/SourcesCardBase/SourcesCardBase.test.tsx","../src/SourcesCardBase/SourcesCardBase.tsx","../src/SourcesCardBase/index.ts","../src/TermsOfUse/TermsOfUse.test.tsx","../src/TermsOfUse/TermsOfUse.tsx","../src/TermsOfUse/index.ts","../src/ToolCall/ToolCall.test.tsx","../src/ToolCall/ToolCall.tsx","../src/ToolCall/index.ts","../src/ToolResponse/ToolResponse.test.tsx","../src/ToolResponse/ToolResponse.tsx","../src/ToolResponse/index.ts","../src/__mocks__/monaco-editor.ts","../src/__mocks__/rehype-external-links.ts","../src/__mocks__/rehype-highlight.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/ImagePreview/ImagePreview.test.tsx","../src/ImagePreview/ImagePreview.tsx","../src/ImagePreview/index.ts","../src/LoadingMessage/LoadingMessage.test.tsx","../src/LoadingMessage/LoadingMessage.tsx","../src/LoadingMessage/index.ts","../src/MarkdownContent/MarkdownContent.test.tsx","../src/MarkdownContent/MarkdownContent.tsx","../src/MarkdownContent/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.test.tsx","../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/SuperscriptMessage/SuperscriptMessage.tsx","../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/Onboarding/Onboarding.test.tsx","../src/Onboarding/Onboarding.tsx","../src/Onboarding/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/SourcesCardBase/SourcesCardBase.test.tsx","../src/SourcesCardBase/SourcesCardBase.tsx","../src/SourcesCardBase/index.ts","../src/TermsOfUse/TermsOfUse.test.tsx","../src/TermsOfUse/TermsOfUse.tsx","../src/TermsOfUse/index.ts","../src/ToolCall/ToolCall.test.tsx","../src/ToolCall/ToolCall.tsx","../src/ToolCall/index.ts","../src/ToolResponse/ToolResponse.test.tsx","../src/ToolResponse/ToolResponse.tsx","../src/ToolResponse/index.ts","../src/__mocks__/monaco-editor.ts","../src/__mocks__/rehype-external-links.ts","../src/__mocks__/rehype-highlight.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.5.0-prerelease.
|
|
3
|
+
"version": "6.5.0-prerelease.26",
|
|
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,198 @@
|
|
|
1
|
+
import { FunctionComponent, useState } from 'react';
|
|
2
|
+
import { ChatbotDisplayMode } from '@patternfly/chatbot/dist/dynamic/Chatbot';
|
|
3
|
+
import ChatbotConversationHistoryNav, {
|
|
4
|
+
Conversation
|
|
5
|
+
} from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';
|
|
6
|
+
import {
|
|
7
|
+
Button,
|
|
8
|
+
Checkbox,
|
|
9
|
+
MenuToggle,
|
|
10
|
+
MenuToggleElement,
|
|
11
|
+
Select,
|
|
12
|
+
SelectList,
|
|
13
|
+
SelectOption,
|
|
14
|
+
Tooltip
|
|
15
|
+
} from '@patternfly/react-core';
|
|
16
|
+
import { FilterIcon, SortAmountDownIcon } from '@patternfly/react-icons';
|
|
17
|
+
|
|
18
|
+
const initialConversations: { [key: string]: Conversation[] } = {
|
|
19
|
+
Today: [{ id: '1', text: 'Red Hat products and services' }],
|
|
20
|
+
'This month': [
|
|
21
|
+
{
|
|
22
|
+
id: '2',
|
|
23
|
+
text: 'Enterprise Linux installation and setup'
|
|
24
|
+
},
|
|
25
|
+
{ id: '3', text: 'Troubleshoot system crash' }
|
|
26
|
+
],
|
|
27
|
+
March: [
|
|
28
|
+
{ id: '4', text: 'Ansible security and updates' },
|
|
29
|
+
{ id: '5', text: 'Red Hat certification' },
|
|
30
|
+
{ id: '6', text: 'Lightspeed user documentation' }
|
|
31
|
+
],
|
|
32
|
+
February: [
|
|
33
|
+
{ id: '7', text: 'Crashing pod assistance' },
|
|
34
|
+
{ id: '8', text: 'OpenShift AI pipelines' },
|
|
35
|
+
{ id: '9', text: 'Updating subscription plan' },
|
|
36
|
+
{ id: '10', text: 'Red Hat licensing options' }
|
|
37
|
+
],
|
|
38
|
+
January: [
|
|
39
|
+
{ id: '11', text: 'RHEL system performance' },
|
|
40
|
+
{ id: '12', text: 'Manage user accounts' }
|
|
41
|
+
]
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const ChatbotHeaderTitleDemo: FunctionComponent = () => {
|
|
45
|
+
const [isDrawerOpen, setIsDrawerOpen] = useState(true);
|
|
46
|
+
const [hasDrawerHeadDivider, setHasDrawerHeadDivider] = useState(false);
|
|
47
|
+
const [showSearchActionStart, setShowSearchActionStart] = useState(false);
|
|
48
|
+
const [showSearchActionEnd, setShowSearchActionEnd] = useState(false);
|
|
49
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
50
|
+
const [isSortSelectOpen, setIsSortSelectOpen] = useState(false);
|
|
51
|
+
const [selectedSort, setSelectedSort] = useState<string>('newest');
|
|
52
|
+
const [conversations, setConversations] = useState<Conversation[] | { [key: string]: Conversation[] }>(
|
|
53
|
+
initialConversations
|
|
54
|
+
);
|
|
55
|
+
const displayMode = ChatbotDisplayMode.embedded;
|
|
56
|
+
|
|
57
|
+
const sortLabels: { [key: string]: string } = {
|
|
58
|
+
newest: 'Date (newest first)',
|
|
59
|
+
oldest: 'Date (oldest first)',
|
|
60
|
+
'alphabetical-asc': 'Name (A-Z)',
|
|
61
|
+
'alphabetical-desc': 'Name (Z-A)'
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const onSortSelect = (
|
|
65
|
+
_event: React.MouseEvent<Element, MouseEvent> | undefined,
|
|
66
|
+
value: string | number | undefined
|
|
67
|
+
) => {
|
|
68
|
+
setSelectedSort(value as string);
|
|
69
|
+
setIsSortSelectOpen(false);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const findMatchingItems = (targetValue: string) => {
|
|
73
|
+
const filteredConversations = Object.entries(initialConversations).reduce((acc, [key, items]) => {
|
|
74
|
+
const filteredItems = items.filter((item) => item.text.toLowerCase().includes(targetValue.toLowerCase()));
|
|
75
|
+
if (filteredItems.length > 0) {
|
|
76
|
+
acc[key] = filteredItems;
|
|
77
|
+
}
|
|
78
|
+
return acc;
|
|
79
|
+
}, {});
|
|
80
|
+
|
|
81
|
+
return filteredConversations;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<>
|
|
86
|
+
<Checkbox
|
|
87
|
+
label="Display drawer"
|
|
88
|
+
isChecked={isDrawerOpen}
|
|
89
|
+
onChange={() => setIsDrawerOpen(!isDrawerOpen)}
|
|
90
|
+
id="search-actions-drawer-visible"
|
|
91
|
+
name="drawer-visible"
|
|
92
|
+
/>
|
|
93
|
+
<Checkbox
|
|
94
|
+
label="Show drawer head divider"
|
|
95
|
+
isChecked={hasDrawerHeadDivider}
|
|
96
|
+
onChange={() => setHasDrawerHeadDivider(!hasDrawerHeadDivider)}
|
|
97
|
+
id="search-actions-drawer-head-divider"
|
|
98
|
+
name="drawer-head-divider"
|
|
99
|
+
/>
|
|
100
|
+
<Checkbox
|
|
101
|
+
label="Show search action start"
|
|
102
|
+
isChecked={showSearchActionStart}
|
|
103
|
+
onChange={() => setShowSearchActionStart(!showSearchActionStart)}
|
|
104
|
+
id="search-actions-show-search-action-start"
|
|
105
|
+
name="show-search-action-start"
|
|
106
|
+
/>
|
|
107
|
+
<Checkbox
|
|
108
|
+
label="Show search action end"
|
|
109
|
+
isChecked={showSearchActionEnd}
|
|
110
|
+
onChange={() => setShowSearchActionEnd(!showSearchActionEnd)}
|
|
111
|
+
id="search-actions-show-search-action-end"
|
|
112
|
+
name="show-search-action-end"
|
|
113
|
+
/>
|
|
114
|
+
<Checkbox
|
|
115
|
+
label="Show loading state"
|
|
116
|
+
isChecked={isLoading}
|
|
117
|
+
onChange={() => setIsLoading(!isLoading)}
|
|
118
|
+
id="search-actions-drawer-is-loading"
|
|
119
|
+
name="drawer-is-loading"
|
|
120
|
+
/>
|
|
121
|
+
<ChatbotConversationHistoryNav
|
|
122
|
+
displayMode={displayMode}
|
|
123
|
+
onDrawerToggle={() => setIsDrawerOpen(!isDrawerOpen)}
|
|
124
|
+
isDrawerOpen={isDrawerOpen}
|
|
125
|
+
setIsDrawerOpen={setIsDrawerOpen}
|
|
126
|
+
// eslint-disable-next-line no-console
|
|
127
|
+
onSelectActiveItem={(e, selectedItem) => console.log(`Selected history item with id ${selectedItem}`)}
|
|
128
|
+
conversations={conversations}
|
|
129
|
+
onNewChat={() => {
|
|
130
|
+
setIsDrawerOpen(!isDrawerOpen);
|
|
131
|
+
}}
|
|
132
|
+
handleTextInputChange={(value: string) => {
|
|
133
|
+
if (value === '') {
|
|
134
|
+
setConversations(initialConversations);
|
|
135
|
+
} else {
|
|
136
|
+
const newConversations: { [key: string]: Conversation[] } = findMatchingItems(value);
|
|
137
|
+
setConversations(newConversations);
|
|
138
|
+
}
|
|
139
|
+
}}
|
|
140
|
+
drawerContent={<div>Drawer content</div>}
|
|
141
|
+
hasDrawerHeadDivider={hasDrawerHeadDivider}
|
|
142
|
+
isLoading={isLoading}
|
|
143
|
+
searchActionStart={
|
|
144
|
+
showSearchActionStart ? (
|
|
145
|
+
<Tooltip content="Filter options" aria="none" aria-live="off">
|
|
146
|
+
<Button
|
|
147
|
+
variant="control"
|
|
148
|
+
aria-label="Filter options"
|
|
149
|
+
// eslint-disable-next-line no-console
|
|
150
|
+
onClick={() => console.log('Filter button clicked')}
|
|
151
|
+
icon={<FilterIcon />}
|
|
152
|
+
/>
|
|
153
|
+
</Tooltip>
|
|
154
|
+
) : undefined
|
|
155
|
+
}
|
|
156
|
+
searchActionEnd={
|
|
157
|
+
showSearchActionEnd ? (
|
|
158
|
+
<Select
|
|
159
|
+
id="sort-select"
|
|
160
|
+
isOpen={isSortSelectOpen}
|
|
161
|
+
selected={selectedSort}
|
|
162
|
+
onSelect={onSortSelect}
|
|
163
|
+
shouldFocusToggleOnSelect
|
|
164
|
+
onOpenChange={(isOpen) => setIsSortSelectOpen(isOpen)}
|
|
165
|
+
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
|
|
166
|
+
<Tooltip aria="none" aria-live="off" content={`Sort - ${sortLabels[selectedSort]}`}>
|
|
167
|
+
<MenuToggle
|
|
168
|
+
ref={toggleRef}
|
|
169
|
+
onClick={() => setIsSortSelectOpen(!isSortSelectOpen)}
|
|
170
|
+
isExpanded={isSortSelectOpen}
|
|
171
|
+
variant="plain"
|
|
172
|
+
aria-label={`${sortLabels[selectedSort]}, Sort conversations`}
|
|
173
|
+
icon={
|
|
174
|
+
<SortAmountDownIcon
|
|
175
|
+
style={{
|
|
176
|
+
transform:
|
|
177
|
+
selectedSort === 'oldest' || selectedSort === 'alphabetical-asc' ? 'scaleY(-1)' : 'none'
|
|
178
|
+
}}
|
|
179
|
+
/>
|
|
180
|
+
}
|
|
181
|
+
/>
|
|
182
|
+
</Tooltip>
|
|
183
|
+
)}
|
|
184
|
+
>
|
|
185
|
+
<SelectList>
|
|
186
|
+
{Object.keys(sortLabels).map((currentLabel) => (
|
|
187
|
+
<SelectOption key={currentLabel} value={currentLabel}>
|
|
188
|
+
{sortLabels[currentLabel]}
|
|
189
|
+
</SelectOption>
|
|
190
|
+
))}
|
|
191
|
+
</SelectList>
|
|
192
|
+
</Select>
|
|
193
|
+
) : undefined
|
|
194
|
+
}
|
|
195
|
+
/>
|
|
196
|
+
</>
|
|
197
|
+
);
|
|
198
|
+
};
|
|
@@ -74,7 +74,7 @@ import { BellIcon, CalendarAltIcon, ClipboardIcon, CodeIcon, ThumbtackIcon, Uplo
|
|
|
74
74
|
import { useDropzone } from 'react-dropzone';
|
|
75
75
|
|
|
76
76
|
import ChatbotConversationHistoryNav from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav';
|
|
77
|
-
import { DropdownItem, DropdownList, Checkbox } from '@patternfly/react-core';
|
|
77
|
+
import { Button, DropdownItem, DropdownList, Checkbox, MenuToggle, Select, SelectList, SelectOption } from '@patternfly/react-core';
|
|
78
78
|
|
|
79
79
|
import OutlinedWindowRestoreIcon from '@patternfly/react-icons/dist/esm/icons/outlined-window-restore-icon';
|
|
80
80
|
import ExpandIcon from '@patternfly/react-icons/dist/esm/icons/expand-icon';
|
|
@@ -87,7 +87,7 @@ import userAvatar from '../Messages/user_avatar.svg';
|
|
|
87
87
|
import patternflyAvatar from '../Messages/patternfly_avatar.jpg';
|
|
88
88
|
import termsAndConditionsHeader from './PF-TermsAndConditionsHeader.svg';
|
|
89
89
|
import onboardingHeader from './RH-Hat-Image.svg';
|
|
90
|
-
import { CloseIcon, SearchIcon, OutlinedCommentsIcon } from '@patternfly/react-icons';
|
|
90
|
+
import { CloseIcon, SearchIcon, OutlinedCommentsIcon, FilterIcon, SortAmountDownIcon } from '@patternfly/react-icons';
|
|
91
91
|
import { FunctionComponent, FormEvent, useState, useRef, MouseEvent, isValidElement, cloneElement, Children, ReactNode, Ref, MouseEvent as ReactMouseEvent, CSSProperties, useEffect} from 'react';
|
|
92
92
|
import FilePreview from '@patternfly/chatbot/dist/dynamic/FilePreview';
|
|
93
93
|
|
|
@@ -371,6 +371,16 @@ Both the search input field and "New chat" buttons are optional. The `reverseBut
|
|
|
371
371
|
|
|
372
372
|
```
|
|
373
373
|
|
|
374
|
+
### Drawer with search actions
|
|
375
|
+
|
|
376
|
+
You can customize the search experience within the conversation history drawer via the `searchActionStart` and `searchActionEnd` props, which provide additional search controls before and after the input field. These props are useful for adding filtering, sorting, or other search-related functionality.
|
|
377
|
+
|
|
378
|
+
You can also add a visual divider between the drawer head and the title by setting `hasDrawerHeadDivider` to `true`.
|
|
379
|
+
|
|
380
|
+
```ts file="./ChatbotHeaderDrawerWithSearchActions.tsx"
|
|
381
|
+
|
|
382
|
+
```
|
|
383
|
+
|
|
374
384
|
### Drawer with conversation actions
|
|
375
385
|
|
|
376
386
|
Actions can be added to conversations with `menuItems`. Optionally, you can also add a `className` to the menu via `menuClassName`, change the default aria-label and tooltip content via `label`, or add an `onSelect` callback for when a user selects an item.
|
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
border-radius: var(--pf-t--global--border--radius--medium);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
.pf-chatbot__heading-divider {
|
|
11
|
+
padding-inline-start: var(--pf-t--global--spacer--lg);
|
|
12
|
+
padding-inline-end: var(--pf-t--global--spacer--lg);
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
// Drawer title
|
|
11
16
|
// ----------------------------------------------------------------------------
|
|
12
17
|
.pf-chatbot__heading-container {
|
|
@@ -28,6 +33,19 @@
|
|
|
28
33
|
justify-content: flex-start;
|
|
29
34
|
gap: var(--pf-t--global--spacer--gap--text-to-element--default);
|
|
30
35
|
}
|
|
36
|
+
|
|
37
|
+
// Drawer search and actions
|
|
38
|
+
.pf-chatbot__history-search-actions {
|
|
39
|
+
.pf-v6-c-button.pf-m-control {
|
|
40
|
+
--pf-v6-c-button--m-control--PaddingInlineStart: var(--pf-t--global--spacer--control--horizontal--compact);
|
|
41
|
+
--pf-v6-c-button--m-control--PaddingInlineEnd: var(--pf-t--global--spacer--control--horizontal--compact);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.pf-chatbot__input {
|
|
46
|
+
width: 100%;
|
|
47
|
+
}
|
|
48
|
+
|
|
31
49
|
// Drawer menu
|
|
32
50
|
// ----------------------------------------------------------------------------
|
|
33
51
|
.pf-v6-c-menu {
|
|
@@ -592,6 +592,101 @@ describe('ChatbotConversationHistoryNav', () => {
|
|
|
592
592
|
expect(screen.getByRole('dialog', { name: /Chat history I am a sample search/i })).toBeInTheDocument();
|
|
593
593
|
});
|
|
594
594
|
|
|
595
|
+
it('Does not render search actions by default', () => {
|
|
596
|
+
const handleSearch = jest.fn();
|
|
597
|
+
const groupedConversations: { [key: string]: Conversation[] } = {
|
|
598
|
+
Today: [...initialConversations, { id: '2', text: 'Chatbot extension' }]
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
render(
|
|
602
|
+
<ChatbotConversationHistoryNav
|
|
603
|
+
onDrawerToggle={onDrawerToggle}
|
|
604
|
+
isDrawerOpen={true}
|
|
605
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
606
|
+
setIsDrawerOpen={jest.fn()}
|
|
607
|
+
reverseButtonOrder={false}
|
|
608
|
+
conversations={groupedConversations}
|
|
609
|
+
handleTextInputChange={handleSearch}
|
|
610
|
+
/>
|
|
611
|
+
);
|
|
612
|
+
|
|
613
|
+
const searchInput = screen.getByPlaceholderText(/Search/i);
|
|
614
|
+
|
|
615
|
+
expect(searchInput.parentElement?.previousElementSibling).toBeNull();
|
|
616
|
+
expect(searchInput.parentElement?.nextElementSibling).toBeNull();
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
it('Renders with action at start when searchActionStart is passed', () => {
|
|
620
|
+
const handleSearch = jest.fn();
|
|
621
|
+
const groupedConversations: { [key: string]: Conversation[] } = {
|
|
622
|
+
Today: [...initialConversations, { id: '2', text: 'Chatbot extension' }]
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
render(
|
|
626
|
+
<ChatbotConversationHistoryNav
|
|
627
|
+
onDrawerToggle={onDrawerToggle}
|
|
628
|
+
isDrawerOpen={true}
|
|
629
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
630
|
+
setIsDrawerOpen={jest.fn()}
|
|
631
|
+
reverseButtonOrder={false}
|
|
632
|
+
conversations={groupedConversations}
|
|
633
|
+
handleTextInputChange={handleSearch}
|
|
634
|
+
searchActionStart={<div>Search action start test</div>}
|
|
635
|
+
/>
|
|
636
|
+
);
|
|
637
|
+
|
|
638
|
+
expect(screen.getByText('Search action start test')).toBeVisible();
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
it('Renders with action at end when searchActionEnd is passed', () => {
|
|
642
|
+
const handleSearch = jest.fn();
|
|
643
|
+
const groupedConversations: { [key: string]: Conversation[] } = {
|
|
644
|
+
Today: [...initialConversations, { id: '2', text: 'Chatbot extension' }]
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
render(
|
|
648
|
+
<ChatbotConversationHistoryNav
|
|
649
|
+
onDrawerToggle={onDrawerToggle}
|
|
650
|
+
isDrawerOpen={true}
|
|
651
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
652
|
+
setIsDrawerOpen={jest.fn()}
|
|
653
|
+
reverseButtonOrder={false}
|
|
654
|
+
handleTextInputChange={handleSearch}
|
|
655
|
+
conversations={groupedConversations}
|
|
656
|
+
searchActionEnd={<div>Search action end test</div>}
|
|
657
|
+
/>
|
|
658
|
+
);
|
|
659
|
+
|
|
660
|
+
expect(screen.getByText('Search action end test')).toBeVisible();
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
it('Overrides default search input and actions when searchToolbar is passed', () => {
|
|
664
|
+
const handleSearch = jest.fn();
|
|
665
|
+
const groupedConversations: { [key: string]: Conversation[] } = {
|
|
666
|
+
Today: [...initialConversations, { id: '2', text: 'Chatbot extension' }]
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
render(
|
|
670
|
+
<ChatbotConversationHistoryNav
|
|
671
|
+
onDrawerToggle={onDrawerToggle}
|
|
672
|
+
isDrawerOpen={true}
|
|
673
|
+
displayMode={ChatbotDisplayMode.fullscreen}
|
|
674
|
+
setIsDrawerOpen={jest.fn()}
|
|
675
|
+
reverseButtonOrder={false}
|
|
676
|
+
conversations={groupedConversations}
|
|
677
|
+
handleTextInputChange={handleSearch}
|
|
678
|
+
searchActionStart={<div>Search action start test</div>}
|
|
679
|
+
searchActionEnd={<div>Search action end test</div>}
|
|
680
|
+
searchToolbar={<div>Custom toolbar</div>}
|
|
681
|
+
/>
|
|
682
|
+
);
|
|
683
|
+
|
|
684
|
+
expect(screen.queryByPlaceholderText(/Search/i)).not.toBeInTheDocument();
|
|
685
|
+
expect(screen.queryByText('Search action start test')).not.toBeInTheDocument();
|
|
686
|
+
expect(screen.queryByText('Search action end test')).not.toBeInTheDocument();
|
|
687
|
+
expect(screen.getByText('Custom toolbar')).toBeInTheDocument();
|
|
688
|
+
});
|
|
689
|
+
|
|
595
690
|
it('overrides nav title heading level when navTitleProps.headingLevel is passed', () => {
|
|
596
691
|
render(
|
|
597
692
|
<ChatbotConversationHistoryNav
|