@patternfly/chatbot 6.4.0-prerelease.2 → 6.4.0-prerelease.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Chatbot/Chatbot.js +1 -7
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +22 -2
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +15 -9
- package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +40 -2
- package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
- package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.js +25 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
- package/dist/cjs/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +22 -0
- package/dist/cjs/ChatbotHeader/index.d.ts +1 -0
- package/dist/cjs/ChatbotHeader/index.js +1 -0
- package/dist/cjs/DeepThinking/DeepThinking.d.ts +18 -0
- package/dist/cjs/DeepThinking/DeepThinking.js +18 -0
- package/dist/cjs/DeepThinking/DeepThinking.test.d.ts +1 -0
- package/dist/cjs/DeepThinking/DeepThinking.test.js +48 -0
- package/dist/cjs/DeepThinking/index.d.ts +2 -0
- package/dist/cjs/DeepThinking/index.js +23 -0
- package/dist/cjs/FileDetails/FileDetails.d.ts +22 -3
- package/dist/cjs/FileDetails/FileDetails.js +27 -912
- package/dist/cjs/FileDetails/FileDetails.test.js +16 -0
- package/dist/cjs/FileDetailsLabel/FileDetailsLabel.d.ts +8 -2
- package/dist/cjs/FileDetailsLabel/FileDetailsLabel.js +14 -2
- package/dist/cjs/FileDetailsLabel/FileDetailsLabel.test.js +19 -1
- package/dist/cjs/FilePreview/FilePreview.d.ts +26 -0
- package/dist/cjs/FilePreview/FilePreview.js +26 -0
- package/dist/cjs/FilePreview/FilePreview.test.d.ts +1 -0
- package/dist/cjs/FilePreview/FilePreview.test.js +97 -0
- package/dist/cjs/FilePreview/index.d.ts +2 -0
- package/dist/cjs/FilePreview/index.js +23 -0
- package/dist/cjs/ImagePreview/ImagePreview.d.ts +53 -0
- package/dist/cjs/ImagePreview/ImagePreview.js +47 -0
- package/dist/cjs/ImagePreview/ImagePreview.test.d.ts +1 -0
- package/dist/cjs/ImagePreview/ImagePreview.test.js +225 -0
- package/dist/cjs/ImagePreview/index.d.ts +2 -0
- package/dist/cjs/ImagePreview/index.js +23 -0
- package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +3 -3
- package/dist/cjs/Message/LinkMessage/LinkMessage.d.ts +2 -1
- package/dist/cjs/Message/LinkMessage/LinkMessage.js +7 -3
- package/dist/cjs/Message/ListMessage/ListItemMessage.d.ts +1 -1
- package/dist/cjs/Message/ListMessage/ListItemMessage.js +16 -1
- package/dist/cjs/Message/Message.d.ts +15 -0
- package/dist/cjs/Message/Message.js +129 -32
- package/dist/cjs/Message/Message.test.js +71 -0
- package/dist/cjs/Message/SuperscriptMessage/SuperscriptMessage.d.ts +3 -0
- package/dist/cjs/Message/SuperscriptMessage/SuperscriptMessage.js +5 -0
- package/dist/cjs/Message/UserFeedback/UserFeedback.d.ts +15 -1
- package/dist/cjs/Message/UserFeedback/UserFeedback.js +4 -4
- package/dist/cjs/Message/UserFeedback/UserFeedback.test.js +44 -0
- package/dist/cjs/MessageBar/MessageBar.js +19 -4
- package/dist/cjs/MessageBox/JumpButton.d.ts +5 -0
- package/dist/cjs/MessageBox/JumpButton.js +1 -1
- package/dist/cjs/MessageBox/JumpButton.test.js +4 -4
- package/dist/cjs/MessageBox/MessageBox.d.ts +9 -0
- package/dist/cjs/MessageBox/MessageBox.js +2 -2
- package/dist/cjs/MessageBox/MessageBox.test.js +2 -2
- package/dist/cjs/SourcesCard/SourcesCard.d.ts +13 -1
- package/dist/cjs/SourcesCard/SourcesCard.js +6 -6
- package/dist/cjs/SourcesCard/SourcesCard.test.js +49 -0
- package/dist/cjs/ToolResponse/ToolResponse.d.ts +30 -0
- package/dist/cjs/ToolResponse/ToolResponse.js +18 -0
- package/dist/cjs/ToolResponse/ToolResponse.test.d.ts +1 -0
- package/dist/cjs/ToolResponse/ToolResponse.test.js +60 -0
- package/dist/cjs/ToolResponse/index.d.ts +2 -0
- package/dist/cjs/ToolResponse/index.js +23 -0
- package/dist/cjs/index.d.ts +8 -0
- package/dist/cjs/index.js +13 -1
- package/dist/css/main.css +339 -27
- package/dist/css/main.css.map +1 -1
- package/dist/dynamic/DeepThinking/package.json +1 -0
- package/dist/dynamic/FilePreview/package.json +1 -0
- package/dist/dynamic/ImagePreview/package.json +1 -0
- package/dist/dynamic/ToolResponse/package.json +1 -0
- package/dist/esm/Chatbot/Chatbot.js +1 -7
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.d.ts +2 -0
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.js +2 -2
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +22 -2
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +17 -11
- package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +41 -3
- package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +1 -1
- package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.test.js +1 -1
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.d.ts +18 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.js +22 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.d.ts +1 -0
- package/dist/esm/ChatbotHeader/ChatbotHeaderNewChatButton.test.js +20 -0
- package/dist/esm/ChatbotHeader/index.d.ts +1 -0
- package/dist/esm/ChatbotHeader/index.js +1 -0
- package/dist/esm/DeepThinking/DeepThinking.d.ts +18 -0
- package/dist/esm/DeepThinking/DeepThinking.js +14 -0
- package/dist/esm/DeepThinking/DeepThinking.test.d.ts +1 -0
- package/dist/esm/DeepThinking/DeepThinking.test.js +43 -0
- package/dist/esm/DeepThinking/index.d.ts +2 -0
- package/dist/esm/DeepThinking/index.js +2 -0
- package/dist/esm/FileDetails/FileDetails.d.ts +22 -3
- package/dist/esm/FileDetails/FileDetails.js +27 -912
- package/dist/esm/FileDetails/FileDetails.test.js +16 -0
- package/dist/esm/FileDetailsLabel/FileDetailsLabel.d.ts +8 -2
- package/dist/esm/FileDetailsLabel/FileDetailsLabel.js +14 -2
- package/dist/esm/FileDetailsLabel/FileDetailsLabel.test.js +19 -1
- package/dist/esm/FilePreview/FilePreview.d.ts +26 -0
- package/dist/esm/FilePreview/FilePreview.js +21 -0
- package/dist/esm/FilePreview/FilePreview.test.d.ts +1 -0
- package/dist/esm/FilePreview/FilePreview.test.js +92 -0
- package/dist/esm/FilePreview/index.d.ts +2 -0
- package/dist/esm/FilePreview/index.js +2 -0
- package/dist/esm/ImagePreview/ImagePreview.d.ts +53 -0
- package/dist/esm/ImagePreview/ImagePreview.js +42 -0
- package/dist/esm/ImagePreview/ImagePreview.test.d.ts +1 -0
- package/dist/esm/ImagePreview/ImagePreview.test.js +220 -0
- package/dist/esm/ImagePreview/index.d.ts +2 -0
- package/dist/esm/ImagePreview/index.js +2 -0
- package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +5 -5
- package/dist/esm/Message/LinkMessage/LinkMessage.d.ts +2 -1
- package/dist/esm/Message/LinkMessage/LinkMessage.js +7 -3
- package/dist/esm/Message/ListMessage/ListItemMessage.d.ts +1 -1
- package/dist/esm/Message/ListMessage/ListItemMessage.js +16 -1
- package/dist/esm/Message/Message.d.ts +15 -0
- package/dist/esm/Message/Message.js +129 -32
- package/dist/esm/Message/Message.test.js +71 -0
- package/dist/esm/Message/SuperscriptMessage/SuperscriptMessage.d.ts +3 -0
- package/dist/esm/Message/SuperscriptMessage/SuperscriptMessage.js +3 -0
- package/dist/esm/Message/UserFeedback/UserFeedback.d.ts +15 -1
- package/dist/esm/Message/UserFeedback/UserFeedback.js +4 -4
- package/dist/esm/Message/UserFeedback/UserFeedback.test.js +45 -1
- package/dist/esm/MessageBar/MessageBar.js +19 -4
- package/dist/esm/MessageBox/JumpButton.d.ts +5 -0
- package/dist/esm/MessageBox/JumpButton.js +1 -1
- package/dist/esm/MessageBox/JumpButton.test.js +4 -4
- package/dist/esm/MessageBox/MessageBox.d.ts +9 -0
- package/dist/esm/MessageBox/MessageBox.js +2 -2
- package/dist/esm/MessageBox/MessageBox.test.js +2 -2
- package/dist/esm/SourcesCard/SourcesCard.d.ts +13 -1
- package/dist/esm/SourcesCard/SourcesCard.js +6 -6
- package/dist/esm/SourcesCard/SourcesCard.test.js +50 -1
- package/dist/esm/ToolResponse/ToolResponse.d.ts +30 -0
- package/dist/esm/ToolResponse/ToolResponse.js +14 -0
- package/dist/esm/ToolResponse/ToolResponse.test.d.ts +1 -0
- package/dist/esm/ToolResponse/ToolResponse.test.js +55 -0
- package/dist/esm/ToolResponse/index.d.ts +2 -0
- package/dist/esm/ToolResponse/index.js +2 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.js +8 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/AttachmentEdit.tsx +1 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +101 -3
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/FilePreview.tsx +33 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/ImagePreview.tsx +53 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDeepThinking.tsx +17 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx +111 -85
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithSources.tsx +70 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolResponse.tsx +135 -0
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +38 -4
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/PreviewAttachment.tsx +1 -1
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +107 -2
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx +616 -3
- package/patternfly-docs/content/extensions/chatbot/examples/Messages/file-preview.svg +9 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotConversationEditing.tsx +202 -0
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderBasic.tsx +17 -3
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawer.tsx +36 -5
- package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithPin.tsx +12 -2
- package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +22 -3
- package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +1 -1
- package/patternfly-docs/patternfly-docs.config.js +1 -1
- package/src/Chatbot/Chatbot.scss +9 -2
- package/src/Chatbot/Chatbot.tsx +18 -31
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryDropdown.tsx +5 -1
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +16 -10
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +132 -3
- package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +80 -33
- package/src/ChatbotHeader/ChatbotHeaderMenu.test.tsx +1 -1
- package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +2 -2
- package/src/ChatbotHeader/ChatbotHeaderNewChatButton.test.tsx +25 -0
- package/src/ChatbotHeader/ChatbotHeaderNewChatButton.tsx +64 -0
- package/src/ChatbotHeader/index.ts +1 -0
- package/src/ChatbotModal/ChatbotModal.scss +1 -1
- package/src/DeepThinking/DeepThinking.scss +24 -0
- package/src/DeepThinking/DeepThinking.test.tsx +61 -0
- package/src/DeepThinking/DeepThinking.tsx +68 -0
- package/src/DeepThinking/index.ts +3 -0
- package/src/FileDetails/FileDetails.scss +10 -0
- package/src/FileDetails/FileDetails.test.tsx +16 -0
- package/src/FileDetails/FileDetails.tsx +89 -32
- package/src/FileDetails/__snapshots__/FileDetails.test.tsx.snap +20 -14
- package/src/FileDetailsLabel/FileDetailsLabel.test.tsx +21 -1
- package/src/FileDetailsLabel/FileDetailsLabel.tsx +16 -3
- package/src/FileDetailsLabel/__snapshots__/FileDetailsLabel.test.tsx.snap +20 -14
- package/src/FilePreview/FilePreview.scss +22 -0
- package/src/FilePreview/FilePreview.test.tsx +112 -0
- package/src/FilePreview/FilePreview.tsx +58 -0
- package/src/FilePreview/index.ts +3 -0
- package/src/ImagePreview/ImagePreview.scss +61 -0
- package/src/ImagePreview/ImagePreview.test.tsx +253 -0
- package/src/ImagePreview/ImagePreview.tsx +200 -0
- package/src/ImagePreview/index.ts +3 -0
- package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +2 -1
- package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +6 -5
- package/src/Message/LinkMessage/LinkMessage.tsx +6 -2
- package/src/Message/ListMessage/ListItemMessage.tsx +5 -1
- package/src/Message/ListMessage/ListMessage.scss +17 -0
- package/src/Message/Message.scss +44 -0
- package/src/Message/Message.test.tsx +90 -0
- package/src/Message/Message.tsx +171 -46
- package/src/Message/SuperscriptMessage/SuperscriptMessage.scss +8 -0
- package/src/Message/SuperscriptMessage/SuperscriptMessage.tsx +13 -0
- package/src/Message/TextMessage/TextMessage.scss +46 -5
- package/src/Message/UserFeedback/UserFeedback.test.tsx +107 -0
- package/src/Message/UserFeedback/UserFeedback.tsx +41 -6
- package/src/MessageBar/MessageBar.tsx +23 -3
- package/src/MessageBox/JumpButton.test.tsx +4 -4
- package/src/MessageBox/JumpButton.tsx +20 -4
- package/src/MessageBox/MessageBox.scss +0 -12
- package/src/MessageBox/MessageBox.test.tsx +2 -2
- package/src/MessageBox/MessageBox.tsx +23 -2
- package/src/SourcesCard/SourcesCard.scss +17 -0
- package/src/SourcesCard/SourcesCard.test.tsx +93 -0
- package/src/SourcesCard/SourcesCard.tsx +116 -80
- package/src/ToolResponse/ToolResponse.scss +36 -0
- package/src/ToolResponse/ToolResponse.test.tsx +78 -0
- package/src/ToolResponse/ToolResponse.tsx +95 -0
- package/src/ToolResponse/index.ts +3 -0
- package/src/index.ts +12 -0
- package/src/main.scss +16 -0
|
@@ -7,6 +7,7 @@ import { monitorSampleAppQuickStart } from './QuickStarts/monitor-sampleapp-quic
|
|
|
7
7
|
import { monitorSampleAppQuickStartWithImage } from './QuickStarts/monitor-sampleapp-quickstart-with-image';
|
|
8
8
|
import rehypeExternalLinks from '../__mocks__/rehype-external-links';
|
|
9
9
|
import { AlertActionLink } from '@patternfly/react-core';
|
|
10
|
+
import { DeepThinkingProps } from '../DeepThinking';
|
|
10
11
|
|
|
11
12
|
const ALL_ACTIONS = [
|
|
12
13
|
{ label: /Good response/i },
|
|
@@ -141,10 +142,30 @@ const EMPTY_TABLE = `
|
|
|
141
142
|
|
|
142
143
|
`;
|
|
143
144
|
|
|
145
|
+
const FOOTNOTE = `This is some text with a footnote[^1] and here's a longer one.[^bignote]
|
|
146
|
+
|
|
147
|
+
You can also reference the same footnote multiple times[^1].
|
|
148
|
+
|
|
149
|
+
[^1]: This is the full footnote text. You can click the arrow to go back up.
|
|
150
|
+
|
|
151
|
+
[^bignote]: Here's one with multiple paragraphs and **formatting**.
|
|
152
|
+
|
|
153
|
+
Indent paragraphs to include them in the footnote.
|
|
154
|
+
|
|
155
|
+
Add as many paragraphs as you like. You can include *italic text*, **bold text**, and even \`code\`.
|
|
156
|
+
|
|
157
|
+
> You can even include blockquotes in footnotes!`;
|
|
158
|
+
|
|
144
159
|
const IMAGE = ``;
|
|
145
160
|
|
|
146
161
|
const INLINE_IMAGE = `inline text `;
|
|
147
162
|
|
|
163
|
+
const DEEP_THINKING: DeepThinkingProps = {
|
|
164
|
+
toggleContent: 'Show thinking',
|
|
165
|
+
subheading: 'Thought for 3 seconds',
|
|
166
|
+
body: "Here's why I said this."
|
|
167
|
+
};
|
|
168
|
+
|
|
148
169
|
const ERROR = {
|
|
149
170
|
title: 'Could not load chat',
|
|
150
171
|
children: 'Wait a few minutes and check your network settings. If the issue persists: ',
|
|
@@ -675,6 +696,28 @@ describe('Message', () => {
|
|
|
675
696
|
);
|
|
676
697
|
expect(screen.getAllByRole('img')[1]).toHaveAttribute('src', 'test.png');
|
|
677
698
|
});
|
|
699
|
+
it('should handle tool response correctly', async () => {
|
|
700
|
+
render(
|
|
701
|
+
<Message
|
|
702
|
+
avatar="./img"
|
|
703
|
+
role="user"
|
|
704
|
+
name="User"
|
|
705
|
+
content="Hi"
|
|
706
|
+
toolResponse={{
|
|
707
|
+
toggleContent: 'Tool response: Name',
|
|
708
|
+
subheading: 'Thought for 3 seconds',
|
|
709
|
+
body: 'Lorem ipsum dolor sit amet',
|
|
710
|
+
cardTitle: 'Card title',
|
|
711
|
+
cardBody: 'Card body'
|
|
712
|
+
}}
|
|
713
|
+
/>
|
|
714
|
+
);
|
|
715
|
+
expect(screen.getByRole('button', { name: /Tool response: Name/i })).toBeTruthy();
|
|
716
|
+
expect(screen.getByText('Thought for 3 seconds')).toBeTruthy();
|
|
717
|
+
expect(screen.getByText('Lorem ipsum dolor sit amet')).toBeTruthy();
|
|
718
|
+
expect(screen.getByText('Card title')).toBeTruthy();
|
|
719
|
+
expect(screen.getByText('Card body')).toBeTruthy();
|
|
720
|
+
});
|
|
678
721
|
it('should handle block quote correctly', () => {
|
|
679
722
|
render(<Message avatar="./img" role="user" name="User" content={BLOCK_QUOTES} />);
|
|
680
723
|
expect(screen.getByText(/Blockquotes can also be nested.../)).toBeTruthy();
|
|
@@ -740,6 +783,28 @@ describe('Message', () => {
|
|
|
740
783
|
render(<Message avatar="./img" role="user" name="User" content={TABLE} tableProps={{ 'aria-label': 'Test' }} />);
|
|
741
784
|
expect(screen.getByRole('grid', { name: /Test/i })).toBeTruthy();
|
|
742
785
|
});
|
|
786
|
+
it('should render footnote correctly', () => {
|
|
787
|
+
render(<Message avatar="./img" role="user" name="User" content={FOOTNOTE} />);
|
|
788
|
+
expect(screen.getByText(/This is some text with a footnote/i)).toBeTruthy();
|
|
789
|
+
expect(screen.getByText(/and here's a longer one./i)).toBeTruthy();
|
|
790
|
+
expect(screen.getByText(/You can also reference the same footnote multiple times./i)).toBeTruthy();
|
|
791
|
+
expect(screen.getByRole('heading', { name: /Footnotes/i })).toBeTruthy();
|
|
792
|
+
expect(screen.getByText(/This is the full footnote text. You can click the arrow to go back up./i)).toBeTruthy();
|
|
793
|
+
expect(screen.getByText(/Here's one with multiple paragraphs and/i)).toBeTruthy();
|
|
794
|
+
expect(screen.getByText(/formatting/i)).toBeTruthy();
|
|
795
|
+
expect(screen.getByText(/Indent paragraphs to include them in the footnote./i)).toBeTruthy();
|
|
796
|
+
expect(screen.getByText(/Add as many paragraphs as you like. You can include/i)).toBeTruthy();
|
|
797
|
+
expect(screen.getByText(/italic text/i)).toBeTruthy();
|
|
798
|
+
expect(screen.getByText(/bold text/i)).toBeTruthy();
|
|
799
|
+
expect(screen.getByText(/, and even/i)).toBeTruthy();
|
|
800
|
+
expect(screen.getByText(/code/i)).toBeTruthy();
|
|
801
|
+
expect(screen.getByText(/You can even include blockquotes in footnotes!/i)).toBeTruthy();
|
|
802
|
+
expect(screen.getAllByRole('link', { name: '1' })).toHaveLength(2);
|
|
803
|
+
expect(screen.getAllByRole('link', { name: '2' })).toBeTruthy();
|
|
804
|
+
expect(screen.getByRole('link', { name: 'Back to reference 1' })).toBeTruthy();
|
|
805
|
+
expect(screen.getByRole('link', { name: 'Back to reference 1-2' })).toBeTruthy();
|
|
806
|
+
expect(screen.getByRole('link', { name: /Back to reference 2/i })).toBeTruthy();
|
|
807
|
+
});
|
|
743
808
|
it('should render beforeMainContent with main content', () => {
|
|
744
809
|
const mainContent = 'Main message content';
|
|
745
810
|
const beforeMainContentText = 'Before main content';
|
|
@@ -962,4 +1027,29 @@ describe('Message', () => {
|
|
|
962
1027
|
const form = container.querySelector('form');
|
|
963
1028
|
expect(form).toHaveClass('test');
|
|
964
1029
|
});
|
|
1030
|
+
it('should be able to disable markdown parsing', () => {
|
|
1031
|
+
render(<Message avatar="./img" role="user" name="User" content={CODE_MESSAGE} isMarkdownDisabled />);
|
|
1032
|
+
// this is looking for markdown syntax that is ordinarily stripped
|
|
1033
|
+
expect(screen.getByText(/~~~yaml/i)).toBeTruthy();
|
|
1034
|
+
});
|
|
1035
|
+
it('should be able to pass props to react-markdown, such as disabling tags', () => {
|
|
1036
|
+
render(
|
|
1037
|
+
<Message
|
|
1038
|
+
avatar="./img"
|
|
1039
|
+
role="user"
|
|
1040
|
+
name="User"
|
|
1041
|
+
content={CODE_MESSAGE}
|
|
1042
|
+
reactMarkdownProps={{ disallowedElements: ['code'] }}
|
|
1043
|
+
/>
|
|
1044
|
+
);
|
|
1045
|
+
expect(screen.getByText('Here is some YAML code:')).toBeTruthy();
|
|
1046
|
+
// code block isn't rendering
|
|
1047
|
+
expect(screen.queryByRole('button', { name: 'Copy code' })).toBeFalsy();
|
|
1048
|
+
});
|
|
1049
|
+
it('should render deep thinking section correctly', () => {
|
|
1050
|
+
render(<Message avatar="./img" role="user" name="User" content="" deepThinking={DEEP_THINKING} />);
|
|
1051
|
+
expect(screen.getByRole('button', { name: /Show thinking/i })).toBeTruthy();
|
|
1052
|
+
expect(screen.getByText('Thought for 3 seconds')).toBeTruthy();
|
|
1053
|
+
expect(screen.getByText("Here's why I said this.")).toBeTruthy();
|
|
1054
|
+
});
|
|
965
1055
|
});
|
package/src/Message/Message.tsx
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// ============================================================================
|
|
4
4
|
import { forwardRef, ReactNode, useEffect, useState } from 'react';
|
|
5
5
|
import type { FunctionComponent, HTMLProps, MouseEvent as ReactMouseEvent, Ref } from 'react';
|
|
6
|
-
import Markdown from 'react-markdown';
|
|
6
|
+
import Markdown, { Options } from 'react-markdown';
|
|
7
7
|
import remarkGfm from 'remark-gfm';
|
|
8
8
|
import {
|
|
9
9
|
AlertProps,
|
|
@@ -49,6 +49,9 @@ import LinkMessage from './LinkMessage/LinkMessage';
|
|
|
49
49
|
import ErrorMessage from './ErrorMessage/ErrorMessage';
|
|
50
50
|
import MessageInput from './MessageInput';
|
|
51
51
|
import { rehypeMoveImagesOutOfParagraphs } from './Plugins/rehypeMoveImagesOutOfParagraphs';
|
|
52
|
+
import ToolResponse, { ToolResponseProps } from '../ToolResponse';
|
|
53
|
+
import DeepThinking, { DeepThinkingProps } from '../DeepThinking';
|
|
54
|
+
import SuperscriptMessage from './SuperscriptMessage/SuperscriptMessage';
|
|
52
55
|
|
|
53
56
|
export interface MessageAttachment {
|
|
54
57
|
/** Name of file attached to the message */
|
|
@@ -161,6 +164,8 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
|
|
|
161
164
|
tableProps?: Required<Pick<TableProps, 'aria-label'>> & TableProps;
|
|
162
165
|
/** Additional rehype plugins passed from the consumer */
|
|
163
166
|
additionalRehypePlugins?: PluggableList;
|
|
167
|
+
/** Additional remark plugins passed from the consumer */
|
|
168
|
+
additionalRemarkPlugins?: PluggableList;
|
|
164
169
|
/** Whether to open links in message in new tab. */
|
|
165
170
|
openLinkInNewTab?: boolean;
|
|
166
171
|
/** Optional inline error message that can be displayed in the message */
|
|
@@ -185,6 +190,16 @@ export interface MessageProps extends Omit<HTMLProps<HTMLDivElement>, 'role'> {
|
|
|
185
190
|
editFormProps?: FormProps;
|
|
186
191
|
/** Sets message to compact styling. */
|
|
187
192
|
isCompact?: boolean;
|
|
193
|
+
/** Disables markdown parsing for message, allowing only text input */
|
|
194
|
+
isMarkdownDisabled?: boolean;
|
|
195
|
+
/** Allows passing additional props down to markdown parser react-markdown, such as allowedElements and disallowedElements. See https://github.com/remarkjs/react-markdown?tab=readme-ov-file#options for options */
|
|
196
|
+
reactMarkdownProps?: Options;
|
|
197
|
+
/** Props for tool response card */
|
|
198
|
+
toolResponse?: ToolResponseProps;
|
|
199
|
+
/** Props for deep thinking card */
|
|
200
|
+
deepThinking?: DeepThinkingProps;
|
|
201
|
+
/** Allows passing additional props down to remark-gfm. See https://github.com/remarkjs/remark-gfm?tab=readme-ov-file#options for options */
|
|
202
|
+
remarkGfmProps?: Options;
|
|
188
203
|
}
|
|
189
204
|
|
|
190
205
|
export const MessageBase: FunctionComponent<MessageProps> = ({
|
|
@@ -213,6 +228,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
|
|
|
213
228
|
tableProps,
|
|
214
229
|
openLinkInNewTab = true,
|
|
215
230
|
additionalRehypePlugins = [],
|
|
231
|
+
additionalRemarkPlugins = [],
|
|
216
232
|
linkProps,
|
|
217
233
|
error,
|
|
218
234
|
isEditable,
|
|
@@ -224,6 +240,11 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
|
|
|
224
240
|
inputRef,
|
|
225
241
|
editFormProps,
|
|
226
242
|
isCompact,
|
|
243
|
+
isMarkdownDisabled,
|
|
244
|
+
reactMarkdownProps,
|
|
245
|
+
toolResponse,
|
|
246
|
+
deepThinking,
|
|
247
|
+
remarkGfmProps,
|
|
227
248
|
...props
|
|
228
249
|
}: MessageProps) => {
|
|
229
250
|
const [messageText, setMessageText] = useState(content);
|
|
@@ -250,6 +271,152 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
|
|
|
250
271
|
const date = new Date();
|
|
251
272
|
const dateString = timestamp ?? `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`;
|
|
252
273
|
|
|
274
|
+
const handleMarkdown = () => {
|
|
275
|
+
if (isMarkdownDisabled) {
|
|
276
|
+
return (
|
|
277
|
+
<TextMessage component={ContentVariants.p} {...props}>
|
|
278
|
+
{messageText}
|
|
279
|
+
</TextMessage>
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
return (
|
|
283
|
+
<Markdown
|
|
284
|
+
components={{
|
|
285
|
+
section: (props) => {
|
|
286
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
287
|
+
const { node, ...rest } = props;
|
|
288
|
+
return <section {...rest} className={`pf-chatbot__message-text ${rest?.className}`} />;
|
|
289
|
+
},
|
|
290
|
+
p: (props) => {
|
|
291
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
292
|
+
const { node, ...rest } = props;
|
|
293
|
+
return <TextMessage component={ContentVariants.p} {...rest} />;
|
|
294
|
+
},
|
|
295
|
+
code: ({ children, ...props }) => {
|
|
296
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
297
|
+
const { node, ...codeProps } = props;
|
|
298
|
+
return (
|
|
299
|
+
<CodeBlockMessage {...codeProps} {...codeBlockProps}>
|
|
300
|
+
{children}
|
|
301
|
+
</CodeBlockMessage>
|
|
302
|
+
);
|
|
303
|
+
},
|
|
304
|
+
h1: (props) => {
|
|
305
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
306
|
+
const { node, ...rest } = props;
|
|
307
|
+
return <TextMessage component={ContentVariants.h1} {...rest} />;
|
|
308
|
+
},
|
|
309
|
+
h2: (props) => {
|
|
310
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
311
|
+
const { node, ...rest } = props;
|
|
312
|
+
return <TextMessage component={ContentVariants.h2} {...rest} />;
|
|
313
|
+
},
|
|
314
|
+
h3: (props) => {
|
|
315
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
316
|
+
const { node, ...rest } = props;
|
|
317
|
+
return <TextMessage component={ContentVariants.h3} {...rest} />;
|
|
318
|
+
},
|
|
319
|
+
h4: (props) => {
|
|
320
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
321
|
+
const { node, ...rest } = props;
|
|
322
|
+
return <TextMessage component={ContentVariants.h4} {...rest} />;
|
|
323
|
+
},
|
|
324
|
+
h5: (props) => {
|
|
325
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
326
|
+
const { node, ...rest } = props;
|
|
327
|
+
return <TextMessage component={ContentVariants.h5} {...rest} />;
|
|
328
|
+
},
|
|
329
|
+
h6: (props) => {
|
|
330
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
331
|
+
const { node, ...rest } = props;
|
|
332
|
+
return <TextMessage component={ContentVariants.h6} {...rest} />;
|
|
333
|
+
},
|
|
334
|
+
blockquote: (props) => {
|
|
335
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
336
|
+
const { node, ...rest } = props;
|
|
337
|
+
return <TextMessage component={ContentVariants.blockquote} {...rest} />;
|
|
338
|
+
},
|
|
339
|
+
ul: (props) => {
|
|
340
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
341
|
+
const { node, ...rest } = props;
|
|
342
|
+
return <UnorderedListMessage {...rest} />;
|
|
343
|
+
},
|
|
344
|
+
ol: (props) => {
|
|
345
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
346
|
+
const { node, ...rest } = props;
|
|
347
|
+
return <OrderedListMessage {...rest} />;
|
|
348
|
+
},
|
|
349
|
+
li: (props) => {
|
|
350
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
351
|
+
const { node, ...rest } = props;
|
|
352
|
+
return <ListItemMessage {...rest} />;
|
|
353
|
+
},
|
|
354
|
+
// table requires node attribute for calculating headers for mobile breakpoint
|
|
355
|
+
table: (props) => <TableMessage {...props} {...tableProps} />,
|
|
356
|
+
tbody: (props) => {
|
|
357
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
358
|
+
const { node, ...rest } = props;
|
|
359
|
+
return <TbodyMessage {...rest} />;
|
|
360
|
+
},
|
|
361
|
+
thead: (props) => {
|
|
362
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
363
|
+
const { node, ...rest } = props;
|
|
364
|
+
return <TheadMessage {...rest} />;
|
|
365
|
+
},
|
|
366
|
+
tr: (props) => {
|
|
367
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
368
|
+
const { node, ...rest } = props;
|
|
369
|
+
return <TrMessage {...rest} />;
|
|
370
|
+
},
|
|
371
|
+
td: (props) => {
|
|
372
|
+
// Conflicts with Td type
|
|
373
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
374
|
+
const { node, width, ...rest } = props;
|
|
375
|
+
return <TdMessage {...rest} />;
|
|
376
|
+
},
|
|
377
|
+
th: (props) => {
|
|
378
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
379
|
+
const { node, ...rest } = props;
|
|
380
|
+
return <ThMessage {...rest} />;
|
|
381
|
+
},
|
|
382
|
+
img: (props) => {
|
|
383
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
384
|
+
const { node, ...rest } = props;
|
|
385
|
+
return <ImageMessage {...rest} />;
|
|
386
|
+
},
|
|
387
|
+
a: (props) => {
|
|
388
|
+
// node is just the details of the document structure - not needed
|
|
389
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
390
|
+
const { node, ...rest } = props;
|
|
391
|
+
return (
|
|
392
|
+
// some a types conflict with ButtonProps, but it's ok because we are using an a tag
|
|
393
|
+
// there are too many to handle manually
|
|
394
|
+
<LinkMessage {...(rest as any)} {...linkProps}>
|
|
395
|
+
{props.children}
|
|
396
|
+
</LinkMessage>
|
|
397
|
+
);
|
|
398
|
+
},
|
|
399
|
+
// used for footnotes
|
|
400
|
+
sup: (props) => {
|
|
401
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
402
|
+
const { node, ...rest } = props;
|
|
403
|
+
return <SuperscriptMessage {...rest} />;
|
|
404
|
+
}
|
|
405
|
+
}}
|
|
406
|
+
remarkPlugins={[[remarkGfm, { ...remarkGfmProps }], ...additionalRemarkPlugins]}
|
|
407
|
+
rehypePlugins={rehypePlugins}
|
|
408
|
+
{...reactMarkdownProps}
|
|
409
|
+
remarkRehypeOptions={{
|
|
410
|
+
// removes sr-only class from footnote labels applied by default
|
|
411
|
+
footnoteLabelProperties: { className: [''] },
|
|
412
|
+
...reactMarkdownProps?.remarkRehypeOptions
|
|
413
|
+
}}
|
|
414
|
+
>
|
|
415
|
+
{messageText}
|
|
416
|
+
</Markdown>
|
|
417
|
+
);
|
|
418
|
+
};
|
|
419
|
+
|
|
253
420
|
const renderMessage = () => {
|
|
254
421
|
if (isLoading) {
|
|
255
422
|
return <MessageLoading loadingWord={loadingWord} />;
|
|
@@ -277,51 +444,7 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
|
|
|
277
444
|
return (
|
|
278
445
|
<>
|
|
279
446
|
{beforeMainContent && <>{beforeMainContent}</>}
|
|
280
|
-
{error ? (
|
|
281
|
-
<ErrorMessage {...error} />
|
|
282
|
-
) : (
|
|
283
|
-
<Markdown
|
|
284
|
-
components={{
|
|
285
|
-
p: (props) => <TextMessage component={ContentVariants.p} {...props} />,
|
|
286
|
-
code: ({ children, ...props }) => (
|
|
287
|
-
<CodeBlockMessage {...props} {...codeBlockProps}>
|
|
288
|
-
{children}
|
|
289
|
-
</CodeBlockMessage>
|
|
290
|
-
),
|
|
291
|
-
h1: (props) => <TextMessage component={ContentVariants.h1} {...props} />,
|
|
292
|
-
h2: (props) => <TextMessage component={ContentVariants.h2} {...props} />,
|
|
293
|
-
h3: (props) => <TextMessage component={ContentVariants.h3} {...props} />,
|
|
294
|
-
h4: (props) => <TextMessage component={ContentVariants.h4} {...props} />,
|
|
295
|
-
h5: (props) => <TextMessage component={ContentVariants.h5} {...props} />,
|
|
296
|
-
h6: (props) => <TextMessage component={ContentVariants.h6} {...props} />,
|
|
297
|
-
blockquote: (props) => <TextMessage component={ContentVariants.blockquote} {...props} />,
|
|
298
|
-
ul: (props) => <UnorderedListMessage {...props} />,
|
|
299
|
-
ol: (props) => <OrderedListMessage {...props} />,
|
|
300
|
-
li: (props) => <ListItemMessage {...props} />,
|
|
301
|
-
table: (props) => <TableMessage {...props} {...tableProps} />,
|
|
302
|
-
tbody: (props) => <TbodyMessage {...props} />,
|
|
303
|
-
thead: (props) => <TheadMessage {...props} />,
|
|
304
|
-
tr: (props) => <TrMessage {...props} />,
|
|
305
|
-
td: (props) => {
|
|
306
|
-
// Conflicts with Td type
|
|
307
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
308
|
-
const { width, ...rest } = props;
|
|
309
|
-
return <TdMessage {...rest} />;
|
|
310
|
-
},
|
|
311
|
-
th: (props) => <ThMessage {...props} />,
|
|
312
|
-
img: (props) => <ImageMessage {...props} />,
|
|
313
|
-
a: (props) => (
|
|
314
|
-
<LinkMessage href={props.href} rel={props.rel} target={props.target} {...linkProps}>
|
|
315
|
-
{props.children}
|
|
316
|
-
</LinkMessage>
|
|
317
|
-
)
|
|
318
|
-
}}
|
|
319
|
-
remarkPlugins={[remarkGfm]}
|
|
320
|
-
rehypePlugins={rehypePlugins}
|
|
321
|
-
>
|
|
322
|
-
{messageText}
|
|
323
|
-
</Markdown>
|
|
324
|
-
)}
|
|
447
|
+
{error ? <ErrorMessage {...error} /> : handleMarkdown()}
|
|
325
448
|
</>
|
|
326
449
|
);
|
|
327
450
|
};
|
|
@@ -360,6 +483,8 @@ export const MessageBase: FunctionComponent<MessageProps> = ({
|
|
|
360
483
|
<div className="pf-chatbot__message-and-actions">
|
|
361
484
|
{renderMessage()}
|
|
362
485
|
{afterMainContent && <>{afterMainContent}</>}
|
|
486
|
+
{toolResponse && <ToolResponse {...toolResponse} />}
|
|
487
|
+
{deepThinking && <DeepThinking {...deepThinking} />}
|
|
363
488
|
{!isLoading && sources && <SourcesCard {...sources} isCompact={isCompact} />}
|
|
364
489
|
{quickStarts && quickStarts.quickStart && (
|
|
365
490
|
<QuickStartTile
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Chatbot Main - Message - Content - Superscript (like for footnotes)
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import { ExtraProps } from 'react-markdown';
|
|
6
|
+
|
|
7
|
+
const SuperscriptMessage = ({ children }: JSX.IntrinsicElements['sup'] & ExtraProps) => (
|
|
8
|
+
<span className="pf-chatbot__message-superscript">
|
|
9
|
+
<sup>{children}</sup>
|
|
10
|
+
</span>
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
export default SuperscriptMessage;
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
width: fit-content;
|
|
18
18
|
padding: var(--pf-t--global--spacer--sm) 0 var(--pf-t--global--spacer--sm) 0;
|
|
19
19
|
border-radius: var(--pf-t--global--border--radius--small);
|
|
20
|
+
--pf-chatbot-message-text-font-size: var(--pf-t--global--font--size--md);
|
|
20
21
|
|
|
21
22
|
.pf-v6-c-button.pf-m-link {
|
|
22
|
-
font-size: var(--pf-
|
|
23
|
+
font-size: var(--pf-chatbot-message-text-font-size);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
.pf-v6-c-content,
|
|
@@ -27,15 +28,49 @@
|
|
|
27
28
|
.pf-v6-c-content--blockquote,
|
|
28
29
|
p,
|
|
29
30
|
a {
|
|
30
|
-
--pf-v6-c-content--FontSize: var(--pf-
|
|
31
|
+
--pf-v6-c-content--FontSize: var(--pf-chatbot-message-text-font-size);
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
code {
|
|
34
35
|
background-color: var(--pf-t--global--background--color--tertiary--default);
|
|
35
|
-
font-size: var(--pf-
|
|
36
|
+
font-size: var(--pf-chatbot-message-text-inline-code-font-size);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Hide message text that contains sr-only content
|
|
40
|
+
// https://css-tricks.com/inclusively-hidden/
|
|
41
|
+
&:has(.sr-only) {
|
|
42
|
+
clip: rect(0 0 0 0);
|
|
43
|
+
clip-path: inset(50%);
|
|
44
|
+
height: 1px;
|
|
45
|
+
overflow: hidden;
|
|
46
|
+
position: absolute;
|
|
47
|
+
white-space: nowrap;
|
|
48
|
+
width: 1px;
|
|
36
49
|
}
|
|
37
50
|
}
|
|
38
51
|
|
|
52
|
+
// ============================================================================
|
|
53
|
+
// Footnote spacing styles
|
|
54
|
+
// ============================================================================
|
|
55
|
+
|
|
56
|
+
// Add spacing to paragraphs in multi-paragraph footnotes
|
|
57
|
+
// Only target p tags that are direct children of message-text spans (not inside blockquotes, etc.)
|
|
58
|
+
li[id*='user-content-fn-']:has(> span > .pf-chatbot__message-text + .pf-chatbot__message-text)
|
|
59
|
+
> span
|
|
60
|
+
> .pf-chatbot__message-text
|
|
61
|
+
> p {
|
|
62
|
+
margin-block-end: var(--pf-t--global--spacer--md);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Handle user message footnotes which may have extra span wrappers
|
|
66
|
+
li[id*='user-content-fn-']:has(> span > span > .pf-chatbot__message-text + .pf-chatbot__message-text)
|
|
67
|
+
> span
|
|
68
|
+
> span
|
|
69
|
+
> .pf-chatbot__message-text
|
|
70
|
+
> p {
|
|
71
|
+
margin-block-end: var(--pf-t--global--spacer--md);
|
|
72
|
+
}
|
|
73
|
+
|
|
39
74
|
.pf-chatbot__message--user {
|
|
40
75
|
.pf-chatbot__message-text {
|
|
41
76
|
background-color: var(--pf-t--global--color--brand--default);
|
|
@@ -54,6 +89,11 @@
|
|
|
54
89
|
color: var(--pf-t--global--text--color--on-brand--default);
|
|
55
90
|
}
|
|
56
91
|
}
|
|
92
|
+
|
|
93
|
+
.pf-chatbot__message-text > .pf-chatbot__message-text {
|
|
94
|
+
background-color: initial;
|
|
95
|
+
padding: initial;
|
|
96
|
+
}
|
|
57
97
|
}
|
|
58
98
|
|
|
59
99
|
// ============================================================================
|
|
@@ -62,8 +102,9 @@
|
|
|
62
102
|
.pf-chatbot.pf-m-compact {
|
|
63
103
|
// Need to inline shorter text
|
|
64
104
|
.pf-chatbot__message-text {
|
|
105
|
+
--pf-chatbot-message-text-font-size: var(--pf-t--global--font--size--sm);
|
|
65
106
|
.pf-v6-c-button.pf-m-link {
|
|
66
|
-
font-size: var(--pf-
|
|
107
|
+
font-size: var(--pf-chatbot-message-text-font-size);
|
|
67
108
|
}
|
|
68
109
|
|
|
69
110
|
.pf-v6-c-content,
|
|
@@ -71,7 +112,7 @@
|
|
|
71
112
|
.pf-v6-c-content--blockquote,
|
|
72
113
|
p,
|
|
73
114
|
a {
|
|
74
|
-
--pf-v6-c-content--FontSize: var(--pf-
|
|
115
|
+
--pf-v6-c-content--FontSize: var(--pf-chatbot-message-text-font-size);
|
|
75
116
|
}
|
|
76
117
|
|
|
77
118
|
.pf-v6-c-content--blockquote {
|
|
@@ -245,4 +245,111 @@ describe('UserFeedback', () => {
|
|
|
245
245
|
);
|
|
246
246
|
expect(screen.getByTestId('card')).toHaveClass('pf-m-compact');
|
|
247
247
|
});
|
|
248
|
+
it('should pass buttonProps to submit button', () => {
|
|
249
|
+
render(
|
|
250
|
+
<UserFeedback
|
|
251
|
+
timestamp="12/12/12"
|
|
252
|
+
onClose={jest.fn}
|
|
253
|
+
onSubmit={jest.fn}
|
|
254
|
+
quickResponses={MOCK_RESPONSES}
|
|
255
|
+
submitButtonProps={{ variant: 'secondary', isDisabled: true }}
|
|
256
|
+
/>
|
|
257
|
+
);
|
|
258
|
+
const submitButton = screen.getByRole('button', { name: /Submit/i });
|
|
259
|
+
expect(submitButton).toHaveClass('pf-v6-c-button pf-m-secondary');
|
|
260
|
+
expect(submitButton).toBeDisabled();
|
|
261
|
+
});
|
|
262
|
+
it('should pass cardHeaderProps to card header', () => {
|
|
263
|
+
render(
|
|
264
|
+
<UserFeedback
|
|
265
|
+
timestamp="12/12/12"
|
|
266
|
+
onClose={jest.fn}
|
|
267
|
+
onSubmit={jest.fn}
|
|
268
|
+
quickResponses={MOCK_RESPONSES}
|
|
269
|
+
cardHeaderProps={{ 'data-testid': 'card-header', className: 'custom-header' } as any}
|
|
270
|
+
/>
|
|
271
|
+
);
|
|
272
|
+
const cardHeader = screen.getByTestId('card-header');
|
|
273
|
+
expect(cardHeader).toHaveClass('custom-header');
|
|
274
|
+
});
|
|
275
|
+
it('should pass cardBodyProps to card body', () => {
|
|
276
|
+
render(
|
|
277
|
+
<UserFeedback
|
|
278
|
+
timestamp="12/12/12"
|
|
279
|
+
onClose={jest.fn}
|
|
280
|
+
onSubmit={jest.fn}
|
|
281
|
+
quickResponses={MOCK_RESPONSES}
|
|
282
|
+
cardBodyProps={{ 'data-testid': 'card-body', className: 'custom-body' } as any}
|
|
283
|
+
/>
|
|
284
|
+
);
|
|
285
|
+
const cardBody = screen.getByTestId('card-body');
|
|
286
|
+
expect(cardBody).toHaveClass('custom-body');
|
|
287
|
+
});
|
|
288
|
+
it('should pass headingLevelProps to title heading', () => {
|
|
289
|
+
render(
|
|
290
|
+
<UserFeedback
|
|
291
|
+
timestamp="12/12/12"
|
|
292
|
+
onClose={jest.fn}
|
|
293
|
+
onSubmit={jest.fn}
|
|
294
|
+
quickResponses={MOCK_RESPONSES}
|
|
295
|
+
headingLevelProps={{ className: 'custom-heading', id: 'feedback-title' }}
|
|
296
|
+
/>
|
|
297
|
+
);
|
|
298
|
+
const heading = screen.getByRole('heading', { level: 1, name: /Why did you choose this rating?/i });
|
|
299
|
+
expect(heading).toHaveClass('custom-heading');
|
|
300
|
+
expect(heading).toHaveAttribute('id', 'feedback-title');
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('should pass formProps to form', () => {
|
|
304
|
+
render(
|
|
305
|
+
<UserFeedback
|
|
306
|
+
timestamp="12/12/12"
|
|
307
|
+
onClose={jest.fn}
|
|
308
|
+
onSubmit={jest.fn}
|
|
309
|
+
quickResponses={MOCK_RESPONSES}
|
|
310
|
+
formProps={{ 'data-testid': 'feedback-form', className: 'custom-form' } as any}
|
|
311
|
+
/>
|
|
312
|
+
);
|
|
313
|
+
const form = screen.getByTestId('feedback-form');
|
|
314
|
+
expect(form).toHaveClass('custom-form');
|
|
315
|
+
});
|
|
316
|
+
it('should pass textAreaProps to text area when hasTextArea is true', () => {
|
|
317
|
+
render(
|
|
318
|
+
<UserFeedback
|
|
319
|
+
timestamp="12/12/12"
|
|
320
|
+
onClose={jest.fn}
|
|
321
|
+
onSubmit={jest.fn}
|
|
322
|
+
quickResponses={MOCK_RESPONSES}
|
|
323
|
+
hasTextArea
|
|
324
|
+
textAreaProps={{ 'data-testid': 'custom-textarea', rows: 5 } as any}
|
|
325
|
+
/>
|
|
326
|
+
);
|
|
327
|
+
const textArea = screen.getByTestId('custom-textarea');
|
|
328
|
+
expect(textArea).toHaveAttribute('rows', '5');
|
|
329
|
+
expect(textArea).toHaveAttribute('data-testid', 'custom-textarea');
|
|
330
|
+
});
|
|
331
|
+
it('should pass actionGroupProps to action group', () => {
|
|
332
|
+
render(
|
|
333
|
+
<UserFeedback
|
|
334
|
+
timestamp="12/12/12"
|
|
335
|
+
onClose={jest.fn}
|
|
336
|
+
onSubmit={jest.fn}
|
|
337
|
+
quickResponses={MOCK_RESPONSES}
|
|
338
|
+
actionGroupProps={{ 'data-testid': 'action-group', className: 'custom-actions' } as any}
|
|
339
|
+
/>
|
|
340
|
+
);
|
|
341
|
+
const actionGroup = screen.getByTestId('action-group');
|
|
342
|
+
expect(actionGroup).toHaveClass('custom-actions');
|
|
343
|
+
});
|
|
344
|
+
it('should render children', () => {
|
|
345
|
+
render(
|
|
346
|
+
<UserFeedback timestamp="12/12/12" onClose={jest.fn} onSubmit={jest.fn} quickResponses={MOCK_RESPONSES}>
|
|
347
|
+
<div data-testid="custom-content">Custom feedback content</div>
|
|
348
|
+
<p>Additional paragraph</p>
|
|
349
|
+
</UserFeedback>
|
|
350
|
+
);
|
|
351
|
+
expect(screen.getByTestId('custom-content')).toBeInTheDocument();
|
|
352
|
+
expect(screen.getByText('Custom feedback content')).toBeInTheDocument();
|
|
353
|
+
expect(screen.getByText('Additional paragraph')).toBeInTheDocument();
|
|
354
|
+
});
|
|
248
355
|
});
|